Tag Lifecycle Events (#10993)
* wip tags * use generics in tag registrars * comment out varargs methods for now * split up patch * cache loaded service provider * finish renames * use builderWithExpectedSize * finalize
This commit is contained in:
parent
1ba1be7d26
commit
7632de5134
8 changed files with 1037 additions and 72 deletions
|
@ -8,7 +8,7 @@ meant for managing resources across reloads and from points in the
|
|||
PluginBootstrap.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java
|
||||
index 08f2050356acaf74e3210416760e3873c2dafd2c..37dfdcfcbd14947e0550e7528aca68f452e53eb6 100644
|
||||
index 70d5f9802f90605a5120ff2a000a2e9395f0aecc..c319f3bbfabdd39ee571c59d7bfc144c58232abc 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java
|
||||
@@ -1,6 +1,9 @@
|
||||
|
@ -447,23 +447,27 @@ index 0000000000000000000000000000000000000000..92ea0374079a228ccc59c00fcf58abff
|
|||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1588f6943a909bed053a952e650e043c44028c2d
|
||||
index 0000000000000000000000000000000000000000..3b17f056d162dd42cae0d33cbbb22fece82fe525
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java
|
||||
@@ -0,0 +1,18 @@
|
||||
@@ -0,0 +1,22 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
||||
+import java.util.Optional;
|
||||
+import java.util.ServiceLoader;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+@ApiStatus.Internal
|
||||
+interface LifecycleEventTypeProvider {
|
||||
+
|
||||
+ LifecycleEventTypeProvider PROVIDER = ServiceLoader.load(LifecycleEventTypeProvider.class)
|
||||
+ .findFirst()
|
||||
+ .orElseThrow();
|
||||
+ Optional<LifecycleEventTypeProvider> INSTANCE = ServiceLoader.load(LifecycleEventTypeProvider.class)
|
||||
+ .findFirst();
|
||||
+
|
||||
+ static LifecycleEventTypeProvider provider() {
|
||||
+ return INSTANCE.orElseThrow();
|
||||
+ }
|
||||
+
|
||||
+ <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Monitorable<O, E> monitor(String name, Class<? extends O> ownerType);
|
||||
+
|
||||
|
@ -471,7 +475,7 @@ index 0000000000000000000000000000000000000000..1588f6943a909bed053a952e650e043c
|
|||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..304f978e40e1759bb19704cc5cec399500905195
|
||||
index 0000000000000000000000000000000000000000..29476a1a82b3526ac03f21011d297d01462d153e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
@@ -0,0 +1,52 @@
|
||||
|
@ -494,33 +498,33 @@ index 0000000000000000000000000000000000000000..304f978e40e1759bb19704cc5cec3995
|
|||
+
|
||||
+ //<editor-fold desc="helper methods" defaultstate="collapsed">
|
||||
+ @ApiStatus.Internal
|
||||
+ private static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
|
||||
+ static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
|
||||
+ return monitor(name, Plugin.class);
|
||||
+ }
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ private static <E extends LifecycleEvent> LifecycleEventType.Prioritizable<Plugin, E> pluginPrioritized(final String name) {
|
||||
+ static <E extends LifecycleEvent> LifecycleEventType.Prioritizable<Plugin, E> pluginPrioritized(final String name) {
|
||||
+ return prioritized(name, Plugin.class);
|
||||
+ }
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ private static <E extends LifecycleEvent> LifecycleEventType.Monitorable<BootstrapContext, E> bootstrap(final String name) {
|
||||
+ static <E extends LifecycleEvent> LifecycleEventType.Monitorable<BootstrapContext, E> bootstrap(final String name) {
|
||||
+ return monitor(name, BootstrapContext.class);
|
||||
+ }
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ private static <E extends LifecycleEvent> LifecycleEventType.Prioritizable<BootstrapContext, E> bootstrapPrioritized(final String name) {
|
||||
+ static <E extends LifecycleEvent> LifecycleEventType.Prioritizable<BootstrapContext, E> bootstrapPrioritized(final String name) {
|
||||
+ return prioritized(name, BootstrapContext.class);
|
||||
+ }
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ private static <O extends LifecycleEventOwner, E extends LifecycleEvent, O2 extends O> LifecycleEventType.Monitorable<O, E> monitor(final String name, final Class<O2> ownerType) {
|
||||
+ return LifecycleEventTypeProvider.PROVIDER.monitor(name, ownerType);
|
||||
+ static <O extends LifecycleEventOwner, E extends LifecycleEvent, O2 extends O> LifecycleEventType.Monitorable<O, E> monitor(final String name, final Class<O2> ownerType) {
|
||||
+ return LifecycleEventTypeProvider.provider().monitor(name, ownerType);
|
||||
+ }
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ private static <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) {
|
||||
+ return LifecycleEventTypeProvider.PROVIDER.prioritized(name, ownerType);
|
||||
+ static <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) {
|
||||
+ return LifecycleEventTypeProvider.provider().prioritized(name, ownerType);
|
||||
+ }
|
||||
+ //</editor-fold>
|
||||
+
|
||||
|
|
|
@ -1540,7 +1540,7 @@ index 0000000000000000000000000000000000000000..159b691e7a1a7066f3e706e80d75ca8f
|
|||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java b/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e8c1c0f781bfc852af4a0f01452566ae994dc285
|
||||
index 0000000000000000000000000000000000000000..a36a36a46b5d71489e1b3e183d48e6e83721ebdf
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProvider.java
|
||||
@@ -0,0 +1,107 @@
|
||||
|
@ -1587,8 +1587,8 @@ index 0000000000000000000000000000000000000000..e8c1c0f781bfc852af4a0f01452566ae
|
|||
+ .findFirst();
|
||||
+
|
||||
+ static VanillaArgumentProvider provider() {
|
||||
+ return PROVIDER.orElseThrow();
|
||||
+ }
|
||||
+ return PROVIDER.orElseThrow();
|
||||
+ }
|
||||
+
|
||||
+ ArgumentType<EntitySelectorArgumentResolver> entity();
|
||||
+
|
||||
|
@ -1914,7 +1914,7 @@ index 0000000000000000000000000000000000000000..906ce6eff30ebd9ec3010ce03b471418
|
|||
+public interface SelectorArgumentResolver<T> extends ArgumentResolver<T> {
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
index 304f978e40e1759bb19704cc5cec399500905195..1fab48593c567fe05b085ac6e12dc22556cf0b92 100644
|
||||
index 29476a1a82b3526ac03f21011d297d01462d153e..dae4935d8e9f46c52f700927a43a9202dac13df6 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
@@ -1,9 +1,11 @@
|
||||
|
@ -1942,7 +1942,7 @@ index 304f978e40e1759bb19704cc5cec399500905195..1fab48593c567fe05b085ac6e12dc225
|
|||
+
|
||||
//<editor-fold desc="helper methods" defaultstate="collapsed">
|
||||
@ApiStatus.Internal
|
||||
private static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
|
||||
static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
|
||||
diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java
|
||||
index 03d2643d166824458c88a49f20270e93b14f3988..0a26fffe9b1e5080b5639767a03af11006108b4a 100644
|
||||
--- a/src/main/java/org/bukkit/command/Command.java
|
||||
|
@ -2046,7 +2046,7 @@ index 3ec32b46264cfff857b50129b5e0fa5584943ec6..bdfe68b386b5ca2878475e548d3c9a38
|
|||
|
||||
return true;
|
||||
diff --git a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
index b43c3cb5c88eada186d6f81712c244aaa18fb53e..ea26cb90d988d693f26e37229fbdee975c0b11f4 100644
|
||||
index 6465e290c090d82986352d5ab7ba5dc65bd3dc17..c71c122ccc4775d030688f7b8df0b4feb49136f4 100644
|
||||
--- a/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/server/TabCompleteEvent.java
|
||||
@@ -18,6 +18,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
|
|
@ -773,10 +773,10 @@ index 0000000000000000000000000000000000000000..a49d328e95f7fda6567ee6c4f5f1878a
|
|||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/tag/TagKeyImpl.java b/src/main/java/io/papermc/paper/registry/tag/TagKeyImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..11d19e339c7c62f2eb4467277552c27e4e83069c
|
||||
index 0000000000000000000000000000000000000000..5fde17e97eddcd1d01ee39694c9159d0ff2a09e3
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/tag/TagKeyImpl.java
|
||||
@@ -0,0 +1,12 @@
|
||||
@@ -0,0 +1,17 @@
|
||||
+package io.papermc.paper.registry.tag;
|
||||
+
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
|
@ -788,9 +788,14 @@ index 0000000000000000000000000000000000000000..11d19e339c7c62f2eb4467277552c27e
|
|||
+@ApiStatus.Internal
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+record TagKeyImpl<T>(RegistryKey<T> registryKey, Key key) implements TagKey<T> {
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "#" + this.key + " (in " + this.registryKey + ")";
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java
|
||||
index cd1e38debbec745dd13cd895327f544dcf42594d..c0428edee6ecbbd646c0e58da39a7ca476914fd1 100644
|
||||
index 5d21459e9128c515508a2b4b2265d9824e10d9d5..20015393f91af405c99db2635a471fb6ff19e4bf 100644
|
||||
--- a/src/main/java/org/bukkit/Registry.java
|
||||
+++ b/src/main/java/org/bukkit/Registry.java
|
||||
@@ -358,6 +358,27 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
|
||||
|
|
406
patches/api/0489-Tag-Lifecycle-Events.patch
Normal file
406
patches/api/0489-Tag-Lifecycle-Events.patch
Normal file
|
@ -0,0 +1,406 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 20 Jun 2024 09:40:53 -0700
|
||||
Subject: [PATCH] Tag Lifecycle Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java
|
||||
index 3b17f056d162dd42cae0d33cbbb22fece82fe525..a52ab9e09420768d89385c881fb7a4c424e5b8d6 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java
|
||||
@@ -19,4 +19,6 @@ interface LifecycleEventTypeProvider {
|
||||
<O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Monitorable<O, E> monitor(String name, Class<? extends O> ownerType);
|
||||
|
||||
<O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(String name, Class<? extends O> ownerType);
|
||||
+
|
||||
+ TagEventTypeProvider tagProvider();
|
||||
}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
index dae4935d8e9f46c52f700927a43a9202dac13df6..720fe2546015838708ce794c291ca187cf7bca9c 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
|
||||
@@ -24,6 +24,12 @@ public final class LifecycleEvents {
|
||||
*/
|
||||
public static final LifecycleEventType.Prioritizable<LifecycleEventOwner, ReloadableRegistrarEvent<Commands>> COMMANDS = prioritized("commands", LifecycleEventOwner.class);
|
||||
|
||||
+ /**
|
||||
+ * These events are for registering tags to the server's tag system. You can register a handler for these events
|
||||
+ * only in {@link io.papermc.paper.plugin.bootstrap.PluginBootstrap#bootstrap(BootstrapContext)}.
|
||||
+ */
|
||||
+ public static final TagEventTypeProvider TAGS = LifecycleEventTypeProvider.provider().tagProvider();
|
||||
+
|
||||
//<editor-fold desc="helper methods" defaultstate="collapsed">
|
||||
@ApiStatus.Internal
|
||||
static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/TagEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/TagEventTypeProvider.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..61c5f6cc6986193eab596ee55e1a414afcf4fbd1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/TagEventTypeProvider.java
|
||||
@@ -0,0 +1,40 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.tag.PostFlattenTagRegistrar;
|
||||
+import io.papermc.paper.tag.PreFlattenTagRegistrar;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+/**
|
||||
+ * Provides event types for tag registration.
|
||||
+ *
|
||||
+ * @see PreFlattenTagRegistrar
|
||||
+ * @see PostFlattenTagRegistrar
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+@ApiStatus.NonExtendable
|
||||
+public interface TagEventTypeProvider {
|
||||
+
|
||||
+ /**
|
||||
+ * Get a prioritizable, reloadable registrar event for tags before they are flattened.
|
||||
+ *
|
||||
+ * @param registryKey the registry key for the tag type
|
||||
+ * @return the registry event type
|
||||
+ * @param <T> the type of value in the tag
|
||||
+ * @see PreFlattenTagRegistrar
|
||||
+ */
|
||||
+ <T> LifecycleEventType.@NonNull Prioritizable<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<T>>> preFlatten(@NonNull RegistryKey<T> registryKey);
|
||||
+
|
||||
+ /**
|
||||
+ * Get a prioritizable, reloadable registrar event for tags after they are flattened.
|
||||
+ *
|
||||
+ * @param registryKey the registry key for the tag type
|
||||
+ * @return the registry event type
|
||||
+ * @param <T> the type of value in the tag
|
||||
+ * @see PostFlattenTagRegistrar
|
||||
+ */
|
||||
+ <T> LifecycleEventType.@NonNull Prioritizable<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<T>>> postFlatten(@NonNull RegistryKey<T> registryKey);
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/PostFlattenTagRegistrar.java b/src/main/java/io/papermc/paper/tag/PostFlattenTagRegistrar.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..32d79dac18c402c3d95edb642eef1563eddf5e9e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/PostFlattenTagRegistrar.java
|
||||
@@ -0,0 +1,103 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.Registrar;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.registry.TypedKey;
|
||||
+import io.papermc.paper.registry.tag.TagKey;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Map;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.Unmodifiable;
|
||||
+
|
||||
+/**
|
||||
+ * Registrar for tags after they have been flattened. Flattened
|
||||
+ * tags are tags which have any nested tags resolved to the tagged
|
||||
+ * values the nested tags point to. This registrar, being a post-flatten
|
||||
+ * registrar, allows for modification after that flattening has happened, when
|
||||
+ * tags only point to individual entries and not other nested tags.
|
||||
+ * <p>
|
||||
+ * An example of a custom enchant being registered to the vanilla
|
||||
+ * {@code #minecraft:in_enchanting_table} tag.
|
||||
+ * <pre>{@code
|
||||
+ * class YourBootstrapClass implements PluginBootstrap {
|
||||
+ *
|
||||
+ * @Override
|
||||
+ * public void bootstrap(@NotNull BootstrapContext context) {
|
||||
+ * LifecycleEventManager<BootstrapContext> manager = context.getLifecycleManager();
|
||||
+ * manager.registerEventHandler(LifecycleEvents.TAGS.postFlatten(RegistryKey.ENCHANTMENT), event -> {
|
||||
+ * final PostFlattenTagRegistrar<Enchantment> registrar = event.registrar();
|
||||
+ * registrar.addToTag(
|
||||
+ * EnchantmentTagKeys.IN_ENCHANTING_TABLE,
|
||||
+ * Set.of(CUSTOM_ENCHANT)
|
||||
+ * );
|
||||
+ * });
|
||||
+ * }
|
||||
+ * }
|
||||
+ * }</pre>
|
||||
+ *
|
||||
+ * @param <T> the type of value in the tag
|
||||
+ * @see PreFlattenTagRegistrar
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+@ApiStatus.NonExtendable
|
||||
+public interface PostFlattenTagRegistrar<T> extends Registrar {
|
||||
+
|
||||
+ /**
|
||||
+ * Get the registry key for this tag registrar.
|
||||
+ *
|
||||
+ * @return the registry key
|
||||
+ */
|
||||
+ @NonNull RegistryKey<T> registryKey();
|
||||
+
|
||||
+ /**
|
||||
+ * Get a copy of all tags currently held in this registrar.
|
||||
+ *
|
||||
+ * @return an immutable map of all tags
|
||||
+ */
|
||||
+ @Contract(value = "-> new", pure = true)
|
||||
+ @Unmodifiable @NonNull Map<TagKey<T>, Collection<TypedKey<T>>> getAllTags();
|
||||
+
|
||||
+ /**
|
||||
+ * Checks if this registrar has a tag with the given key.
|
||||
+ *
|
||||
+ * @param tagKey the key to check for
|
||||
+ * @return true if the tag exists, false otherwise
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ boolean hasTag(@NonNull TagKey<T> tagKey);
|
||||
+
|
||||
+ /**
|
||||
+ * Get the tag with the given key. Use {@link #hasTag(TagKey)} to check
|
||||
+ * if a tag exists first.
|
||||
+ *
|
||||
+ * @param tagKey the key of the tag to get
|
||||
+ * @return an immutable list of tag entries
|
||||
+ * @throws java.util.NoSuchElementException if the tag does not exist
|
||||
+ * @see #hasTag(TagKey)
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ @Unmodifiable @NonNull Collection<TypedKey<T>> getTag(@NonNull TagKey<T> tagKey);
|
||||
+
|
||||
+ /**
|
||||
+ * Adds values to the given tag. If the tag does not exist, it will be created.
|
||||
+ *
|
||||
+ * @param tagKey the key of the tag to add to
|
||||
+ * @param values the values to add
|
||||
+ * @see #setTag(TagKey, Collection)
|
||||
+ */
|
||||
+ @Contract(mutates = "this")
|
||||
+ void addToTag(@NonNull TagKey<T> tagKey, @NonNull Collection<TypedKey<T>> values);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the values of the given tag. If the tag does not exist, it will be created.
|
||||
+ * If the tag does exist, it will be overwritten.
|
||||
+ *
|
||||
+ * @param tagKey the key of the tag to set
|
||||
+ * @param values the values to set
|
||||
+ * @see #addToTag(TagKey, Collection)
|
||||
+ */
|
||||
+ @Contract(mutates = "this")
|
||||
+ void setTag(@NonNull TagKey<T> tagKey, @NonNull Collection<TypedKey<T>> values);
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/PreFlattenTagRegistrar.java b/src/main/java/io/papermc/paper/tag/PreFlattenTagRegistrar.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..44f7a9d3c2734fb00d11890ece9dc4ce2fafa796
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/PreFlattenTagRegistrar.java
|
||||
@@ -0,0 +1,102 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.Registrar;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.registry.tag.TagKey;
|
||||
+import java.util.Collection;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.Unmodifiable;
|
||||
+
|
||||
+/**
|
||||
+ * Registrar for tags before they are flattened. Flattened
|
||||
+ * tags are tags which have any nested tags resolved to the tagged
|
||||
+ * values the nested tags point to. This registrar, being a pre-flatten
|
||||
+ * registrar, allows for modification before that flattening has happened, when
|
||||
+ * tags both point to individual entries and other nested tags.
|
||||
+ * <p>
|
||||
+ * An example of a tag being created in a pre-flatten registrar:
|
||||
+ * <pre>{@code
|
||||
+ * class YourBootstrapClass implements PluginBootstrap {
|
||||
+ *
|
||||
+ * @Override
|
||||
+ * public void bootstrap(@NotNull BootstrapContext context) {
|
||||
+ * LifecycleEventManager<BootstrapContext> manager = context.getLifecycleManager();
|
||||
+ * manager.registerEventHandler(LifecycleEvents.TAGS.preFlatten(RegistryKey.ITEM), event -> {
|
||||
+ * final PreFlattenTagRegistrar<ItemType> registrar = event.registrar();
|
||||
+ * registrar.setTag(AXE_PICKAXE, Set.of(
|
||||
+ * TagEntry.tagEntry(ItemTypeTagKeys.PICKAXES),
|
||||
+ * TagEntry.tagEntry(ItemTypeTagKeys.AXES)
|
||||
+ * ));
|
||||
+ * });
|
||||
+ * }
|
||||
+ * }
|
||||
+ * }</pre>
|
||||
+ *
|
||||
+ * @param <T> the type of value in the tag
|
||||
+ * @see PostFlattenTagRegistrar
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+@ApiStatus.NonExtendable
|
||||
+public interface PreFlattenTagRegistrar<T> extends Registrar {
|
||||
+
|
||||
+ /**
|
||||
+ * Get the registry key for this tag registrar.
|
||||
+ *
|
||||
+ * @return the registry key
|
||||
+ */
|
||||
+ @NonNull RegistryKey<T> registryKey();
|
||||
+
|
||||
+ /**
|
||||
+ * Get a copy of all tags currently held in this registrar.
|
||||
+ *
|
||||
+ * @return an immutable map of all tags
|
||||
+ */
|
||||
+ @Contract(value = "-> new", pure = true)
|
||||
+ @Unmodifiable @NonNull Map<TagKey<T>, Collection<TagEntry<T>>> getAllTags();
|
||||
+
|
||||
+ /**
|
||||
+ * Checks if this registrar has a tag with the given key.
|
||||
+ *
|
||||
+ * @param tagKey the key to check for
|
||||
+ * @return true if the tag exists, false otherwise
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ boolean hasTag(@NonNull TagKey<T> tagKey);
|
||||
+
|
||||
+ /**
|
||||
+ * Get the tag with the given key. Use {@link #hasTag(TagKey)} to check
|
||||
+ * if a tag exists first.
|
||||
+ *
|
||||
+ * @param tagKey the key of the tag to get
|
||||
+ * @return an immutable list of tag entries
|
||||
+ * @throws java.util.NoSuchElementException if the tag does not exist
|
||||
+ * @see #hasTag(TagKey)
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ @Unmodifiable @NonNull List<TagEntry<T>> getTag(@NonNull TagKey<T> tagKey);
|
||||
+
|
||||
+ /**
|
||||
+ * Adds entries to the given tag. If the tag does not exist, it will be created.
|
||||
+ *
|
||||
+ * @param tagKey the key of the tag to add to
|
||||
+ * @param entries the entries to add
|
||||
+ * @see #setTag(TagKey, Collection)
|
||||
+ */
|
||||
+ @Contract(mutates = "this")
|
||||
+ void addToTag(@NonNull TagKey<T> tagKey, @NonNull Collection<TagEntry<T>> entries);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the entries of the given tag. If the tag does not exist, it will be created.
|
||||
+ * If the tag does exist, it will be overwritten.
|
||||
+ *
|
||||
+ * @param tagKey the key of the tag to set
|
||||
+ * @param entries the entries to set
|
||||
+ * @see #addToTag(TagKey, Collection)
|
||||
+ */
|
||||
+ @Contract(mutates = "this")
|
||||
+ void setTag(@NonNull TagKey<T> tagKey, @NonNull Collection<TagEntry<T>> entries);
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/TagEntry.java b/src/main/java/io/papermc/paper/tag/TagEntry.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..436b701f1231354a78a9e0ab04ffd9097343ecfc
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/TagEntry.java
|
||||
@@ -0,0 +1,89 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import io.papermc.paper.registry.TypedKey;
|
||||
+import io.papermc.paper.registry.tag.TagKey;
|
||||
+import net.kyori.adventure.key.Keyed;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+
|
||||
+/**
|
||||
+ * An entry is a pre-flattened tag. Represents
|
||||
+ * either an individual registry entry or a whole tag.
|
||||
+ *
|
||||
+ * @param <T> the type of value in the tag
|
||||
+ * @see PreFlattenTagRegistrar
|
||||
+ */
|
||||
+@ApiStatus.Experimental
|
||||
+@ApiStatus.NonExtendable
|
||||
+public interface TagEntry<T> extends Keyed {
|
||||
+
|
||||
+ /**
|
||||
+ * Create required tag entry for a single value.
|
||||
+ *
|
||||
+ * @param entryKey the key of the entry
|
||||
+ * @return a new tag entry for a value
|
||||
+ * @param <T> the type of value
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ static <T> @NonNull TagEntry<T> valueEntry(final @NonNull TypedKey<T> entryKey) {
|
||||
+ return valueEntry(entryKey, true);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create tag entry for a single value.
|
||||
+ *
|
||||
+ * @param entryKey the key of the entry
|
||||
+ * @param isRequired if this entry is required (see {@link #isRequired()})
|
||||
+ * @return a new tag entry for a value
|
||||
+ * @param <T> the type of value
|
||||
+ */
|
||||
+ @Contract(value = "_, _ -> new", pure = true)
|
||||
+ static <T> @NonNull TagEntry<T> valueEntry(final @NonNull TypedKey<T> entryKey, final boolean isRequired) {
|
||||
+ return new TagEntryImpl<>(entryKey.key(), false, isRequired);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a required tag entry for a nested tag.
|
||||
+ *
|
||||
+ * @param tagKey they key for the tag
|
||||
+ * @return a new tag entry for a tag
|
||||
+ * @param <T> the type of value
|
||||
+ */
|
||||
+ @Contract(value = "_ -> new", pure = true)
|
||||
+ static <T> @NonNull TagEntry<T> tagEntry(final @NonNull TagKey<T> tagKey) {
|
||||
+ return tagEntry(tagKey, true);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Create a tag entry for a nested tag.
|
||||
+ *
|
||||
+ * @param tagKey they key for the tag
|
||||
+ * @param isRequired if this entry is required (see {@link #isRequired()})
|
||||
+ * @return a new tag entry for a tag
|
||||
+ * @param <T> the type of value
|
||||
+ */
|
||||
+ @Contract(value = "_, _ -> new", pure = true)
|
||||
+ static <T> @NonNull TagEntry<T> tagEntry(final @NonNull TagKey<T> tagKey, final boolean isRequired) {
|
||||
+ return new TagEntryImpl<>(tagKey.key(), true, isRequired);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if this entry represents a tag.
|
||||
+ *
|
||||
+ * @return true if this entry is a tag, false if it is an individual entry
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ boolean isTag();
|
||||
+
|
||||
+ /**
|
||||
+ * Returns if this entry is required. If an entry is required,
|
||||
+ * the value or tag must exist on the server in order for the tag
|
||||
+ * to load correctly. A missing value will prevent the tag holding
|
||||
+ * that missing value from being created.
|
||||
+ *
|
||||
+ * @return true if this entry is required, false if it is optional
|
||||
+ */
|
||||
+ @Contract(pure = true)
|
||||
+ boolean isRequired();
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/TagEntryImpl.java b/src/main/java/io/papermc/paper/tag/TagEntryImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c0ffd2b9f814d92d0d9b370dfa7e352f1241f614
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/TagEntryImpl.java
|
||||
@@ -0,0 +1,8 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import net.kyori.adventure.key.Key;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+
|
||||
+@ApiStatus.Internal
|
||||
+record TagEntryImpl<T>(Key key, boolean isTag, boolean isRequired) implements TagEntry<T> {
|
||||
+}
|
Loading…
Add table
Add a link
Reference in a new issue