diff options
author | Jake Potrebic <[email protected]> | 2024-06-09 13:41:42 -0700 |
---|---|---|
committer | Jake Potrebic <[email protected]> | 2024-06-14 14:37:05 -0700 |
commit | 88a7368e9c1f7a537c7a1e63081d373d4e9081e3 (patch) | |
tree | 3416f34a51ec7f597c2fd8143da6111f3bf2f4aa | |
parent | 0ec9d9a4ccd0e9ca9e1e7d355e8cdfc9dfcbffff (diff) | |
download | Paper-88a7368e9c1f7a537c7a1e63081d373d4e9081e3.tar.gz Paper-88a7368e9c1f7a537c7a1e63081d373d4e9081e3.zip |
add custom event handler configuration
4 files changed, 595 insertions, 114 deletions
diff --git a/patches/api/0484-Registry-Modification-API.patch b/patches/api/0484-Registry-Modification-API.patch index 7ae62ac0e9..551acc139e 100644 --- a/patches/api/0484-Registry-Modification-API.patch +++ b/patches/api/0484-Registry-Modification-API.patch @@ -25,10 +25,10 @@ index 0000000000000000000000000000000000000000..6edf300c1d81c1001756141c9efd022b +} diff --git a/src/main/java/io/papermc/paper/registry/RegistryView.java b/src/main/java/io/papermc/paper/registry/RegistryView.java new file mode 100644 -index 0000000000000000000000000000000000000000..bc25a03b5c06473300cc1b6d505780e68e5e82fc +index 0000000000000000000000000000000000000000..bcdb1a21f1af49b86764d78bd1d774a7fb06fb51 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/RegistryView.java -@@ -0,0 +1,20 @@ +@@ -0,0 +1,50 @@ +package io.papermc.paper.registry; + +import net.kyori.adventure.key.Key; @@ -45,9 +45,39 @@ index 0000000000000000000000000000000000000000..bc25a03b5c06473300cc1b6d505780e6 +public interface RegistryView<T> extends Iterable<T> { + -+ @Nullable T get(final @NonNull Key key); ++ /** ++ * Get a registry entry by its key. ++ * ++ * @param key the key ++ * @return the registry entry or null ++ */ ++ @Nullable T get(@NonNull Key key); ++ ++ /** ++ * Get a registry entry by its key. ++ * ++ * @param key the key ++ * @return the registry entry or null ++ */ ++ @Nullable T get(@NonNull TypedKey<T> key); ++ ++ /** ++ * Get a registry entry by its key. ++ * ++ * @param key the key ++ * @return the registry entry ++ * @throws java.util.NoSuchElementException if the entry does not exist ++ */ ++ @NonNull T getOrThrow(@NonNull Key key); + -+ @NonNull T getOrThrow(final @NonNull Key key); ++ /** ++ * Get a registry entry by its key. ++ * ++ * @param key the key ++ * @return the registry entry ++ * @throws java.util.NoSuchElementException if the entry does not exist ++ */ ++ @NonNull T getOrThrow(@NonNull TypedKey<T> key); +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEntryAddEvent.java b/src/main/java/io/papermc/paper/registry/event/RegistryEntryAddEvent.java new file mode 100644 @@ -90,15 +120,14 @@ index 0000000000000000000000000000000000000000..d6722f7b55e260bab4bab5c361f9c0e9 +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEvent.java b/src/main/java/io/papermc/paper/registry/event/RegistryEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..c83dc6ef3cbe5ec40d464ad96387d7c3d04f1458 +index 0000000000000000000000000000000000000000..498c5920926158e86c2aec2bd2129d5e8b8613a3 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEvent.java -@@ -0,0 +1,32 @@ +@@ -0,0 +1,23 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; +import io.papermc.paper.registry.RegistryKey; -+import io.papermc.paper.registry.RegistryView; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.ApiStatus; + @@ -117,21 +146,13 @@ index 0000000000000000000000000000000000000000..c83dc6ef3cbe5ec40d464ad96387d7c3 + * @return the registry key + */ + @NonNull RegistryKey<T> registryKey(); -+ -+ /** -+ * Get a view of the registry which may or may not -+ * be complete based on the event. -+ * -+ * @return a registry view -+ */ -+ @NonNull RegistryView<T> registry(); +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventProvider.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventProvider.java new file mode 100644 -index 0000000000000000000000000000000000000000..793208a46680d7b9e164c14012d2b7c9af55499f +index 0000000000000000000000000000000000000000..72e8de9c0049147b83096f0655d9ed615f08287a --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventProvider.java -@@ -0,0 +1,83 @@ +@@ -0,0 +1,58 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; @@ -141,6 +162,7 @@ index 0000000000000000000000000000000000000000..793208a46680d7b9e164c14012d2b7c9 +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.event.type.RegistryEntryAddEventType; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.ApiStatus; + @@ -169,20 +191,7 @@ index 0000000000000000000000000000000000000000..793208a46680d7b9e164c14012d2b7c9 + * + * @return the addition event type + */ -+ LifecycleEventType.@NonNull Prioritizable<BootstrapContext, RegistryEntryAddEvent<T, B>> entryAdd(); -+ -+ /** -+ * Shortcut for calling {@link #entryAdd()} followed by {@link LifecycleEventType#newHandler(LifecycleEventHandler)}. -+ * <p> -+ * Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventHandlerConfiguration)} -+ * to register a handler for {@link RegistryEntryAddEvent} -+ * -+ * @param handler the event handler for {@link RegistryEntryAddEvent} -+ * @return the configuration for further use -+ */ -+ default @NonNull PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> newEntryAddHandler(final @NonNull LifecycleEventHandler<? super RegistryEntryAddEvent<T, B>> handler) { -+ return this.entryAdd().newHandler(handler); -+ } ++ @NonNull RegistryEntryAddEventType<T, B> entryAdd(); + + /** + * Gets the event type for {@link RegistryFreezeEvent} which is fired just before @@ -196,19 +205,6 @@ index 0000000000000000000000000000000000000000..793208a46680d7b9e164c14012d2b7c9 + LifecycleEventType.@NonNull Prioritizable<BootstrapContext, RegistryFreezeEvent<T, B>> freeze(); + + /** -+ * Shortcut for calling {@link #freeze()} followed by {@link LifecycleEventType#newHandler(LifecycleEventHandler)}. -+ * <p> -+ * Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventHandlerConfiguration)} -+ * to register a handler for {@link RegistryFreezeEvent} -+ * -+ * @param handler the event handler for {@link RegistryFreezeEvent} -+ * @return the configuration for further use -+ */ -+ default @NonNull PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> newFreezeHandler(final @NonNull LifecycleEventHandler<? super RegistryFreezeEvent<T, B>> handler) { -+ return this.freeze().newHandler(handler); -+ } -+ -+ /** + * Gets the registry key associated with this event type provider. + * + * @return the registry key @@ -217,16 +213,17 @@ index 0000000000000000000000000000000000000000..793208a46680d7b9e164c14012d2b7c9 +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventProviderImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventProviderImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..85a9fbc6aa59e95aac57aa6e626a7366222cf80e +index 0000000000000000000000000000000000000000..36080923ff13ff097807c45f0c454492e0d22a61 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventProviderImpl.java -@@ -0,0 +1,29 @@ +@@ -0,0 +1,30 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.event.type.RegistryEntryAddEventType; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.jetbrains.annotations.ApiStatus; @@ -240,7 +237,7 @@ index 0000000000000000000000000000000000000000..85a9fbc6aa59e95aac57aa6e626a7366 + } + + @Override -+ public LifecycleEventType.Prioritizable<BootstrapContext, RegistryEntryAddEvent<T, B>> entryAdd() { ++ public RegistryEntryAddEventType<T, B> entryAdd() { + return RegistryEventTypeProvider.provider().registryAddition(this); + } + @@ -252,15 +249,16 @@ index 0000000000000000000000000000000000000000..85a9fbc6aa59e95aac57aa6e626a7366 +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProvider.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProvider.java new file mode 100644 -index 0000000000000000000000000000000000000000..4e3f041f2c4ee09d806c0528af2f67912525d94c +index 0000000000000000000000000000000000000000..f1ef25f0ce441e2e7f02e63aa06d33acbe7f50b9 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProvider.java -@@ -0,0 +1,23 @@ +@@ -0,0 +1,24 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; +import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.event.type.RegistryEntryAddEventType; +import java.util.Optional; +import java.util.ServiceLoader; +import org.jetbrains.annotations.ApiStatus; @@ -275,7 +273,7 @@ index 0000000000000000000000000000000000000000..4e3f041f2c4ee09d806c0528af2f6791 + return PROVIDER.orElseThrow(() -> new IllegalStateException("Could not find a %s service implementation".formatted(RegistryEventTypeProvider.class.getSimpleName()))); + } + -+ <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryEntryAddEvent<T, B>> registryAddition(RegistryEventProvider<T, B> type); ++ <T, B extends RegistryBuilder<T>> RegistryEntryAddEventType<T, B> registryAddition(RegistryEventProvider<T, B> type); + + <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryFreezeEvent<T, B>> registryPreFreeze(RegistryEventProvider<T, B> type); +} @@ -301,10 +299,10 @@ index 0000000000000000000000000000000000000000..1f89945be2ed68f52a544f41f7a151b8 +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryFreezeEvent.java b/src/main/java/io/papermc/paper/registry/event/RegistryFreezeEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..6d34ab36303337551e6318228fd2b28ec7da75d3 +index 0000000000000000000000000000000000000000..2cf9dbdb031b733ee1f39a93cbe0610a33674dea --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryFreezeEvent.java -@@ -0,0 +1,27 @@ +@@ -0,0 +1,26 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.registry.RegistryBuilder; @@ -329,7 +327,6 @@ index 0000000000000000000000000000000000000000..6d34ab36303337551e6318228fd2b28e + * + * @return a writable registry view + */ -+ @Override + @NonNull WritableRegistry<T, B> registry(); +} diff --git a/src/main/java/io/papermc/paper/registry/event/WritableRegistry.java b/src/main/java/io/papermc/paper/registry/event/WritableRegistry.java @@ -366,6 +363,66 @@ index 0000000000000000000000000000000000000000..7a0356b7da3844e7ec9121656dc059f5 + */ + void register(@NonNull TypedKey<T> key, @NonNull Consumer<? super B> value); +} +diff --git a/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddConfiguration.java b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ca570ae59d661e229abf72e3f2455017cbd96fbc +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddConfiguration.java +@@ -0,0 +1,30 @@ ++package io.papermc.paper.registry.event.type; ++ ++import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration; ++import io.papermc.paper.registry.TypedKey; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.Contract; ++ ++/** ++ * Specific configuration for {@link io.papermc.paper.registry.event.RegistryEntryAddEvent}s. ++ * ++ * @param <T> registry entry type ++ */ ++public interface RegistryEntryAddConfiguration<T> extends PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> { ++ ++ /** ++ * Only call the handler if the value being added matches the specified key. ++ * ++ * @param key the key to match ++ * @return this configuration ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ @NonNull RegistryEntryAddConfiguration<T> onlyFor(TypedKey<T> key); ++ ++ @Override ++ RegistryEntryAddConfiguration<T> priority(int priority); ++ ++ @Override ++ RegistryEntryAddConfiguration<T> monitor(); ++} +diff --git a/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddEventType.java b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddEventType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f4d4ebf6cbed1b4a9955ceb2d0586782181d97e5 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddEventType.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.registry.event.type; ++ ++import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; ++import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.event.RegistryEntryAddEvent; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * Lifecycle event type for {@link RegistryEntryAddEvent}s. ++ * ++ * @param <T> registry entry type ++ * @param <B> registry entry builder type ++ */ ++public interface RegistryEntryAddEventType<T, B extends RegistryBuilder<T>> extends LifecycleEventType<BootstrapContext, RegistryEntryAddEvent<T, B>, RegistryEntryAddConfiguration<T>> { ++} diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java index 88bb3b9ae99fae97ec21972b75ec43cb6b7b22b5..661af93e3f73aaf1eca0be08b73fae62c534ecbe 100644 --- a/src/main/java/org/bukkit/Registry.java diff --git a/patches/server/1053-Registry-Modification-API.patch b/patches/server/1053-Registry-Modification-API.patch index e977bb514e..c94e744138 100644 --- a/patches/server/1053-Registry-Modification-API.patch +++ b/patches/server/1053-Registry-Modification-API.patch @@ -7,6 +7,332 @@ Subject: [PATCH] Registry Modification API public net.minecraft.server.RegistryLayer STATIC_ACCESS public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java +index 6c072e44a8144de6658b4eb818c996f0eac5805b..618e9c5e48062840e623cccc7ace4e5c3c118e78 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java +@@ -59,8 +59,8 @@ public class LifecycleEventRunner { + } + + public <O extends LifecycleEventOwner, E extends PaperLifecycleEvent> void callEvent(final LifecycleEventType<O, ? super E, ?> eventType, final E event, final Predicate<? super O> ownerPredicate) { +- final AbstractLifecycleEventType<O, ? super E, ?, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ? super E, ?, ?>) eventType; +- lifecycleEventType.forEachHandler(registeredHandler -> { ++ final AbstractLifecycleEventType<O, ? super E, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ? super E, ?>) eventType; ++ lifecycleEventType.forEachHandler(event, registeredHandler -> { + try { + if (event instanceof final OwnerAwareLifecycleEvent<?> ownerAwareEvent) { + ownerAwareGenericHelper(ownerAwareEvent, registeredHandler.owner()); +@@ -93,7 +93,7 @@ public class LifecycleEventRunner { + } + + private <O extends LifecycleEventOwner> void removeEventHandlersOwnedBy(final LifecycleEventType<O, ?, ?> eventType, final Plugin possibleOwner) { +- final AbstractLifecycleEventType<O, ?, ?, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ?, ?, ?>) eventType; ++ final AbstractLifecycleEventType<O, ?, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ?, ?>) eventType; + lifecycleEventType.removeMatching(registeredHandler -> registeredHandler.owner().getPluginMeta().getName().equals(possibleOwner.getPluginMeta().getName())); + } + +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java +index f1be5b9a29435bae0afd2bd951bfe88d1669e7eb..d05334016bd01201c755dea04c0cea56b6dfcb50 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java +@@ -21,6 +21,6 @@ public final class PaperLifecycleEventManager<O extends LifecycleEventOwner> imp + @Override + public void registerEventHandler(final LifecycleEventHandlerConfiguration<? super O> handlerConfiguration) { + Preconditions.checkState(this.registrationCheck.getAsBoolean(), "Cannot register lifecycle event handlers"); +- ((AbstractLifecycleEventHandlerConfiguration<? super O, ?, ?>) handlerConfiguration).registerFrom(this.owner); ++ ((AbstractLifecycleEventHandlerConfiguration<? super O, ?>) handlerConfiguration).registerFrom(this.owner); + } + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java +index 6a85a4f581612efff04c1a955493aa2e32476277..fa216e6fd804859293385ed43c53dfca057f317f 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java +@@ -8,19 +8,21 @@ import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.framework.qual.DefaultQualifier; + + @DefaultQualifier(NonNull.class) +-public abstract class AbstractLifecycleEventHandlerConfiguration<O extends LifecycleEventOwner, E extends LifecycleEvent, CI extends AbstractLifecycleEventHandlerConfiguration<O, E, CI>> implements LifecycleEventHandlerConfiguration<O> { ++public abstract class AbstractLifecycleEventHandlerConfiguration<O extends LifecycleEventOwner, E extends LifecycleEvent> implements LifecycleEventHandlerConfiguration<O> { + + private final LifecycleEventHandler<? super E> handler; +- private final AbstractLifecycleEventType<O, E, ?, CI> type; ++ private final AbstractLifecycleEventType<O, E, ?> type; + +- protected AbstractLifecycleEventHandlerConfiguration(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?, CI> type) { ++ protected AbstractLifecycleEventHandlerConfiguration(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?> type) { + this.handler = handler; + this.type = type; + } + +- public abstract CI config(); +- + public final void registerFrom(final O owner) { +- this.type.tryRegister(owner, this.handler, this.config()); ++ this.type.tryRegister(owner, this); ++ } ++ ++ public LifecycleEventHandler<? super E> handler() { ++ return this.handler; + } + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java +index e0699fcd0a098abc5e1206e7c0fa80b96eca7884..ab444d60d72bd692843052df5d7b24fbb5621cf7 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java +@@ -8,19 +8,14 @@ import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.framework.qual.DefaultQualifier; + + @DefaultQualifier(NonNull.class) +-public class MonitorLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventHandlerConfiguration<O, E, MonitorLifecycleEventHandlerConfigurationImpl<O, E>> implements MonitorLifecycleEventHandlerConfiguration<O> { ++public class MonitorLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventHandlerConfiguration<O, E> implements MonitorLifecycleEventHandlerConfiguration<O> { + + private boolean monitor = false; + +- public MonitorLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?, MonitorLifecycleEventHandlerConfigurationImpl<O, E>> eventType) { ++ public MonitorLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?> eventType) { + super(handler, eventType); + } + +- @Override +- public MonitorLifecycleEventHandlerConfigurationImpl<O, E> config() { +- return this; +- } +- + public boolean isMonitor() { + return this.monitor; + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java +index c1d0070fc1594f7a7c29d7dc679da7b347a7140b..ccdad31717bf12b844cbeaf11a49247485ec77f1 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java +@@ -9,22 +9,19 @@ import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.framework.qual.DefaultQualifier; + + @DefaultQualifier(NonNull.class) +-public class PrioritizedLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventHandlerConfiguration<O, E, PrioritizedLifecycleEventHandlerConfigurationImpl<O, E>> implements PrioritizedLifecycleEventHandlerConfiguration<O> { ++public class PrioritizedLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> ++ extends AbstractLifecycleEventHandlerConfiguration<O, E> ++ implements PrioritizedLifecycleEventHandlerConfiguration<O> { + + private static final OptionalInt DEFAULT_PRIORITY = OptionalInt.of(0); + private static final OptionalInt MONITOR_PRIORITY = OptionalInt.empty(); + + private OptionalInt priority = DEFAULT_PRIORITY; + +- public PrioritizedLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?, PrioritizedLifecycleEventHandlerConfigurationImpl<O, E>> eventType) { ++ public PrioritizedLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?> eventType) { + super(handler, eventType); + } + +- @Override +- public PrioritizedLifecycleEventHandlerConfigurationImpl<O, E> config() { +- return this; +- } +- + public OptionalInt priority() { + return this.priority; + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java +index a65fb37f4a729e2fe9fb81af822db626ec7e6d7b..9359a36d26970742da3a7abb0050158cd6c64e8e 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java +@@ -12,7 +12,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.framework.qual.DefaultQualifier; + + @DefaultQualifier(NonNull.class) +-public abstract class AbstractLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent, C extends LifecycleEventHandlerConfiguration<O>, CI extends AbstractLifecycleEventHandlerConfiguration<O, E, CI>> implements LifecycleEventType<O, E, C> { ++public abstract class AbstractLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent, C extends LifecycleEventHandlerConfiguration<O>> implements LifecycleEventType<O, E, C> { + + private final String name; + private final Class<? extends O> ownerType; +@@ -33,18 +33,22 @@ public abstract class AbstractLifecycleEventType<O extends LifecycleEventOwner, + } + } + +- public abstract void forEachHandler(Consumer<? super RegisteredHandler<O, E>> consumer, Predicate<? super RegisteredHandler<O, E>> predicate); ++ public abstract void forEachHandler(E event, Consumer<RegisteredHandler<O, E>> consumer, Predicate<RegisteredHandler<O, E>> predicate); + +- public abstract void removeMatching(Predicate<? super RegisteredHandler<O, E>> predicate); ++ public abstract void removeMatching(Predicate<RegisteredHandler<O, E>> predicate); + +- protected abstract void register(O owner, LifecycleEventHandler<? super E> handler, CI config); ++ protected abstract void register(O owner, AbstractLifecycleEventHandlerConfiguration<O, E> config); + +- public final void tryRegister(final O owner, final LifecycleEventHandler<? super E> handler, final CI config) { ++ public final void tryRegister(final O owner, final AbstractLifecycleEventHandlerConfiguration<O, E> config) { + this.verifyOwner(owner); + LifecycleEventRunner.INSTANCE.checkRegisteredHandler(owner, this); +- this.register(owner, handler, config); ++ this.register(owner, config); + } + +- public record RegisteredHandler<O, E extends LifecycleEvent>(O owner, LifecycleEventHandler<? super E> lifecycleEventHandler) { ++ public record RegisteredHandler<O extends LifecycleEventOwner, E extends LifecycleEvent>(O owner, AbstractLifecycleEventHandlerConfiguration<O, E> config) { ++ ++ public LifecycleEventHandler<? super E> lifecycleEventHandler() { ++ return this.config().handler(); ++ } + } + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java +index 0886edad92b40276f268bd745b31bac359fd28af..af0cb3298d9c737417c6e54b360f8dc50a5caf04 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java +@@ -20,6 +20,6 @@ public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeP + + @Override + public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) { +- return LifecycleEventRunner.INSTANCE.addEventType(new PrioritizableLifecycleEventType<>(name, ownerType)); ++ return LifecycleEventRunner.INSTANCE.addEventType(new PrioritizableLifecycleEventType.Simple<>(name, ownerType)); + } + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java +index 6d92c1d3adf220154dfe7cba3a3f8158356c3e3c..c71912f0050ce0cc6e416948a354c8a66da606a8 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java +@@ -3,6 +3,7 @@ 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 io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration; + import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfiguration; + import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfigurationImpl; + import java.util.ArrayList; +@@ -13,7 +14,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.framework.qual.DefaultQualifier; + + @DefaultQualifier(NonNull.class) +-public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventType<O, E, MonitorLifecycleEventHandlerConfiguration<O>, MonitorLifecycleEventHandlerConfigurationImpl<O, E>> implements LifecycleEventType.Monitorable<O, E> { ++public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventType<O, E, MonitorLifecycleEventHandlerConfiguration<O>> implements LifecycleEventType.Monitorable<O, E> { + + final List<RegisteredHandler<O, E>> handlers = new ArrayList<>(); + int nonMonitorIdx = 0; +@@ -28,9 +29,12 @@ public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E exte + } + + @Override +- protected void register(final O owner, final LifecycleEventHandler<? super E> handler, final MonitorLifecycleEventHandlerConfigurationImpl<O, E> config) { +- final RegisteredHandler<O, E> registeredHandler = new RegisteredHandler<>(owner, handler); +- if (!config.isMonitor()) { ++ protected void register(final O owner, final AbstractLifecycleEventHandlerConfiguration<O, E> config) { ++ if (!(config instanceof final MonitorLifecycleEventHandlerConfigurationImpl<?,?> monitor)) { ++ throw new IllegalArgumentException("Configuration must be a MonitorLifecycleEventHandlerConfiguration"); ++ } ++ final RegisteredHandler<O, E> registeredHandler = new RegisteredHandler<>(owner, config); ++ if (!monitor.isMonitor()) { + this.handlers.add(this.nonMonitorIdx, registeredHandler); + this.nonMonitorIdx++; + } else { +@@ -39,7 +43,7 @@ public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E exte + } + + @Override +- public void forEachHandler(final Consumer<? super RegisteredHandler<O, E>> consumer, final Predicate<? super RegisteredHandler<O, E>> predicate) { ++ public void forEachHandler(final E event, final Consumer<RegisteredHandler<O, E>> consumer, final Predicate<RegisteredHandler<O, E>> predicate) { + for (final RegisteredHandler<O, E> handler : this.handlers) { + if (predicate.test(handler)) { + consumer.accept(handler); +@@ -48,7 +52,7 @@ public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E exte + } + + @Override +- public void removeMatching(final Predicate<? super RegisteredHandler<O, E>> predicate) { ++ public void removeMatching(final Predicate<RegisteredHandler<O, E>> predicate) { + this.handlers.removeIf(predicate); + } + } +diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java +index 6629f7fabf66ce761024268043cc30076ba8a3f1..05830f3edbde181418c33e52f1d4cb431575bdb9 100644 +--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java ++++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java +@@ -3,21 +3,25 @@ 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 io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration; + import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration; + import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfigurationImpl; + import java.util.ArrayList; + import java.util.Comparator; + import java.util.List; +-import java.util.OptionalInt; + import java.util.function.Consumer; + import java.util.function.Predicate; + import org.checkerframework.checker.nullness.qual.NonNull; + import org.checkerframework.framework.qual.DefaultQualifier; + + @DefaultQualifier(NonNull.class) +-public class PrioritizableLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventType<O, E, PrioritizedLifecycleEventHandlerConfiguration<O>, PrioritizedLifecycleEventHandlerConfigurationImpl<O, E>> implements LifecycleEventType.Prioritizable<O, E> { ++public abstract class PrioritizableLifecycleEventType< ++ O extends LifecycleEventOwner, ++ E extends LifecycleEvent, ++ C extends PrioritizedLifecycleEventHandlerConfiguration<O> ++> extends AbstractLifecycleEventType<O, E, C> { + +- private static final Comparator<PrioritizedHandler<?, ?>> COMPARATOR = Comparator.comparing(PrioritizedHandler::priority, (o1, o2) -> { ++ private static final Comparator<RegisteredHandler<?, ?>> COMPARATOR = Comparator.comparing(handler -> ((PrioritizedLifecycleEventHandlerConfigurationImpl<?, ?>) handler.config()).priority(), (o1, o2) -> { + if (o1.equals(o2)) { + return 0; + } else if (o1.isEmpty()) { +@@ -29,36 +33,43 @@ public class PrioritizableLifecycleEventType<O extends LifecycleEventOwner, E ex + } + }); + +- private final List<PrioritizedHandler<O, E>> handlers = new ArrayList<>(); ++ private final List<RegisteredHandler<O, E>> handlers = new ArrayList<>(); + + public PrioritizableLifecycleEventType(final String name, final Class<? extends O> ownerType) { + super(name, ownerType); + } + + @Override +- public PrioritizedLifecycleEventHandlerConfiguration<O> newHandler(final LifecycleEventHandler<? super E> handler) { +- return new PrioritizedLifecycleEventHandlerConfigurationImpl<>(handler, this); +- } +- +- @Override +- protected void register(final O owner, final LifecycleEventHandler<? super E> handler, final PrioritizedLifecycleEventHandlerConfigurationImpl<O, E> config) { +- this.handlers.add(new PrioritizedHandler<>(new RegisteredHandler<>(owner, handler), config.priority())); ++ protected void register(final O owner, final AbstractLifecycleEventHandlerConfiguration<O, E> config) { ++ if (!(config instanceof PrioritizedLifecycleEventHandlerConfigurationImpl<?, ?>)) { ++ throw new IllegalArgumentException("Configuration must be a PrioritizedLifecycleEventHandlerConfiguration"); ++ } ++ this.handlers.add(new RegisteredHandler<>(owner, config)); + this.handlers.sort(COMPARATOR); + } + + @Override +- public void forEachHandler(final Consumer<? super RegisteredHandler<O, E>> consumer, final Predicate<? super RegisteredHandler<O, E>> predicate) { +- for (final PrioritizedHandler<O, E> handler : this.handlers) { +- if (predicate.test(handler.handler())) { +- consumer.accept(handler.handler()); ++ public void forEachHandler(final E event, final Consumer<RegisteredHandler<O, E>> consumer, final Predicate<RegisteredHandler<O, E>> predicate) { ++ for (final RegisteredHandler<O, E> handler : this.handlers) { ++ if (predicate.test(handler)) { ++ consumer.accept(handler); + } + } + } + + @Override +- public void removeMatching(final Predicate<? super RegisteredHandler<O, E>> predicate) { +- this.handlers.removeIf(prioritizedHandler -> predicate.test(prioritizedHandler.handler())); ++ public void removeMatching(final Predicate<RegisteredHandler<O, E>> predicate) { ++ this.handlers.removeIf(predicate); + } + +- private record PrioritizedHandler<O extends LifecycleEventOwner, E extends LifecycleEvent>(RegisteredHandler<O, E> handler, OptionalInt priority) {} ++ public static class Simple<O extends LifecycleEventOwner, E extends LifecycleEvent> extends PrioritizableLifecycleEventType<O, E, PrioritizedLifecycleEventHandlerConfiguration<O>> implements LifecycleEventType.Prioritizable<O, E> { ++ public Simple(final String name, final Class<? extends O> ownerType) { ++ super(name, ownerType); ++ } ++ ++ @Override ++ public PrioritizedLifecycleEventHandlerConfiguration<O> newHandler(final LifecycleEventHandler<? super E> handler) { ++ return new PrioritizedLifecycleEventHandlerConfigurationImpl<>(handler, this); ++ } ++ } + } diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java index e68ac2a9710c9e0ac248ce65b6e0d21fa7033fec..9342f034ef590594db046cd9b0810bd4075d8e6b 100644 --- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java @@ -70,10 +396,10 @@ index 0000000000000000000000000000000000000000..4cf32102a134ebef67d3893cfd24bf0a +} diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java new file mode 100644 -index 0000000000000000000000000000000000000000..44199c18e49514f2d06aed0cee9bcf7330b8acb7 +index 0000000000000000000000000000000000000000..d4c4ca9297ae3e481a5aba516e7d2c1729618d4b --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java -@@ -0,0 +1,169 @@ +@@ -0,0 +1,167 @@ +package io.papermc.paper.registry; + +import com.google.common.base.Preconditions; @@ -84,12 +410,14 @@ index 0000000000000000000000000000000000000000..44199c18e49514f2d06aed0cee9bcf73 +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; +import io.papermc.paper.registry.entry.RegistryEntry; +import io.papermc.paper.registry.entry.RegistryEntryInfo; -+import io.papermc.paper.registry.event.RegistryEntryAddEvent; +import io.papermc.paper.registry.event.RegistryEntryAddEventImpl; +import io.papermc.paper.registry.event.RegistryEventMap; +import io.papermc.paper.registry.event.RegistryEventProvider; +import io.papermc.paper.registry.event.RegistryFreezeEvent; +import io.papermc.paper.registry.event.RegistryFreezeEventImpl; ++import io.papermc.paper.registry.event.type.RegistryEntryAddEventType; ++import io.papermc.paper.registry.event.type.RegistryEntryAddEventTypeImpl; ++import io.papermc.paper.registry.event.type.RegistryLifecycleEventType; +import net.kyori.adventure.key.Key; +import net.minecraft.core.Holder; +import net.minecraft.core.MappedRegistry; @@ -98,7 +426,6 @@ index 0000000000000000000000000000000000000000..44199c18e49514f2d06aed0cee9bcf73 +import net.minecraft.core.WritableRegistry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; -+import org.bukkit.craftbukkit.CraftRegistry; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.intellij.lang.annotations.Subst; + @@ -169,27 +496,24 @@ index 0000000000000000000000000000000000000000..44199c18e49514f2d06aed0cee9bcf73 + return registerMethod.register((WritableRegistry<M>) registry, key, nms, registrationInfo); + } + final RegistryEntry.Modifiable<M, T, B> modifiableEntry = (RegistryEntry.Modifiable<M, T, B>) entry; -+ final CraftRegistry<T, M> craftRegistry = (CraftRegistry<T, M>) PaperRegistryAccess.instance().getRegistry(entry.apiKey()); + @SuppressWarnings("PatternValidation") final TypedKey<T> typedKey = TypedKey.create(entry.apiKey(), Key.key(key.location().getNamespace(), key.location().getPath())); + final B builder = modifiableEntry.fillBuilder(typedKey, nms); -+ return this.registerWithListeners(registry, craftRegistry.view, modifiableEntry, key, nms, builder, registrationInfo, registerMethod); ++ return this.registerWithListeners(registry, modifiableEntry, key, nms, builder, registrationInfo, registerMethod); + } + + public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>> void registerWithListeners( + final Registry<M> registry, -+ final RegistryView<T> registryView, + final RegistryEntry.Modifiable<M, T, B> entry, + final ResourceKey<M> key, + final @Nullable M oldNms, + final B builder, + final RegistrationInfo registrationInfo + ) { -+ this.registerWithListeners(registry, registryView, entry, key, oldNms, builder, registrationInfo, WritableRegistry::register); ++ this.registerWithListeners(registry, entry, key, oldNms, builder, registrationInfo, WritableRegistry::register); + } + + public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>, R> R registerWithListeners( + final Registry<M> registry, -+ final RegistryView<T> registryView, + final RegistryEntry.Modifiable<M, T, B> entry, + final ResourceKey<M> key, + final @Nullable M oldNms, @@ -199,7 +523,7 @@ index 0000000000000000000000000000000000000000..44199c18e49514f2d06aed0cee9bcf73 + ) { + @Subst("namespace:key") final ResourceLocation beingAdded = key.location(); + @SuppressWarnings("PatternValidation") final TypedKey<T> typedKey = TypedKey.create(entry.apiKey(), Key.key(beingAdded.getNamespace(), beingAdded.getPath())); -+ final RegistryEntryAddEventImpl<T, B> event = entry.createAdditionEvent(typedKey, builder, registryView); ++ final RegistryEntryAddEventImpl<T, B> event = entry.createAdditionEvent(typedKey, builder); + LifecycleEventRunner.INSTANCE.callEvent(this.valueAddHooks.getHook(entry.apiKey()), event); + if (oldNms != null) { + ((MappedRegistry<M>) registry).clearIntrusiveHolder(oldNms); @@ -229,26 +553,26 @@ index 0000000000000000000000000000000000000000..44199c18e49514f2d06aed0cee9bcf73 + LifecycleEventRunner.INSTANCE.callEvent(this.freezeHooks.getHook(entry.apiKey()), event); + } + -+ public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryEntryAddEvent<T, B>> getRegistryAdditionEventType(final RegistryEventProvider<T, B> type) { ++ public <T, B extends RegistryBuilder<T>> RegistryEntryAddEventType<T, B> getRegistryAdditionEventType(final RegistryEventProvider<T, B> type) { + if (!(PaperRegistries.getEntry(type.registryKey()) instanceof RegistryEntry.Modifiable)) { + throw new IllegalArgumentException(type.registryKey() + " does not support RegistryAdditionEvent"); + } -+ return this.valueAddHooks.getOrCreate(type); ++ return this.valueAddHooks.getOrCreate(type, RegistryEntryAddEventTypeImpl::new); + } + + public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryFreezeEvent<T, B>> getRegistryPreFreezeEventType(final RegistryEventProvider<T, B> type) { + if (!(PaperRegistries.getEntry(type.registryKey()) instanceof RegistryEntry.Writable)) { + throw new IllegalArgumentException(type.registryKey() + " does not support RegistryPreFreezeEvent"); + } -+ return this.freezeHooks.getOrCreate(type); ++ return this.freezeHooks.getOrCreate(type, RegistryLifecycleEventType::new); + } +} diff --git a/src/main/java/io/papermc/paper/registry/SimpleWritableCraftRegistry.java b/src/main/java/io/papermc/paper/registry/SimpleWritableCraftRegistry.java new file mode 100644 -index 0000000000000000000000000000000000000000..e98ffa7403e90d826e6141bc0b512ca712b5ec39 +index 0000000000000000000000000000000000000000..821a54f4dd4f6bd69e0180dd26c1379973483f5a --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/SimpleWritableCraftRegistry.java -@@ -0,0 +1,39 @@ +@@ -0,0 +1,38 @@ +package io.papermc.paper.registry; + +import io.papermc.paper.registry.entry.RegistryEntry; @@ -264,7 +588,6 @@ index 0000000000000000000000000000000000000000..e98ffa7403e90d826e6141bc0b512ca7 + private final PaperRegistryBuilder.Factory<M, T, ? extends B> builderFactory; + private final BiFunction<? super NamespacedKey, M, T> minecraftToBukkit; + -+ + public SimpleWritableCraftRegistry( + final RegistryEntry.BuilderHolder<M, T, B> entry, + final Class<?> classToPreload, @@ -290,10 +613,10 @@ index 0000000000000000000000000000000000000000..e98ffa7403e90d826e6141bc0b512ca7 +} diff --git a/src/main/java/io/papermc/paper/registry/WritableCraftRegistry.java b/src/main/java/io/papermc/paper/registry/WritableCraftRegistry.java new file mode 100644 -index 0000000000000000000000000000000000000000..7834c37048af7faf14eab42fdeece1a3847f7a78 +index 0000000000000000000000000000000000000000..a7fbb03d8d4ee6b96e4be85e0774e1f3a8f28876 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/WritableCraftRegistry.java -@@ -0,0 +1,70 @@ +@@ -0,0 +1,69 @@ +package io.papermc.paper.registry; + +import com.mojang.serialization.Lifecycle; @@ -340,8 +663,7 @@ index 0000000000000000000000000000000000000000..7834c37048af7faf14eab42fdeece1a3 + value.accept(builder); + if (this.entry instanceof final RegistryEntry.Modifiable<M, T, B> modifiable && PaperRegistryListenerManager.INSTANCE.valueAddHooks.hasHooks(this.entry.apiKey())) { + PaperRegistryListenerManager.INSTANCE.registerWithListeners(this.registry, -+ this.view, -+ modifiable, ++ modifiable, + resourceKey, + null, + builder, @@ -473,7 +795,7 @@ index 0000000000000000000000000000000000000000..df10008f6bde1047c8a13523c0a8fc01 + } +} diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java -index dbf4684633e089e5e6a5c61c214eaa324e9272bb..7437c76f2775c7044a65ceb95bd7cce63dc39770 100644 +index dbf4684633e089e5e6a5c61c214eaa324e9272bb..7d6615bb63d6460560593e8d764d986b3d34c479 100644 --- a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java +++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java @@ -1,7 +1,13 @@ @@ -521,8 +843,8 @@ index dbf4684633e089e5e6a5c61c214eaa324e9272bb..7437c76f2775c7044a65ceb95bd7cce6 + */ + interface Modifiable<M, T, B extends PaperRegistryBuilder<M, T>> extends BuilderHolder<M, T, B> { + -+ default RegistryEntryAddEventImpl<T, B> createAdditionEvent(final TypedKey<T> key, final B initialBuilder, final RegistryView<T> view) { -+ return new RegistryEntryAddEventImpl<>(key, initialBuilder, this.apiKey(), view); ++ default RegistryEntryAddEventImpl<T, B> createAdditionEvent(final TypedKey<T> key, final B initialBuilder) { ++ return new RegistryEntryAddEventImpl<>(key, initialBuilder, this.apiKey()); + } + } + @@ -600,14 +922,16 @@ index 0000000000000000000000000000000000000000..562accce731630327d116afd1c9d559d +} diff --git a/src/main/java/io/papermc/paper/registry/event/PaperRegistryView.java b/src/main/java/io/papermc/paper/registry/event/PaperRegistryView.java new file mode 100644 -index 0000000000000000000000000000000000000000..f005f805112534749c26426c5a78b7d02ac262df +index 0000000000000000000000000000000000000000..e835cb34b5c665715b3bbfa80886407c8591ec86 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/PaperRegistryView.java -@@ -0,0 +1,55 @@ +@@ -0,0 +1,68 @@ +package io.papermc.paper.registry.event; + +import com.google.common.collect.Iterators; +import io.papermc.paper.registry.RegistryView; ++import io.papermc.paper.registry.TypedKey; ++import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.function.BiFunction; @@ -617,6 +941,7 @@ index 0000000000000000000000000000000000000000..f005f805112534749c26426c5a78b7d0 +import net.minecraft.resources.ResourceLocation; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class PaperRegistryView<M, T> implements RegistryView<T> { @@ -630,7 +955,7 @@ index 0000000000000000000000000000000000000000..f005f805112534749c26426c5a78b7d0 + } + + @Override -+ public T get(final Key key) { ++ public @Nullable T get(final Key key) { + final @Nullable M value = this.registry.beforeFrozenView().get(new ResourceLocation(key.namespace(), key.value())); + if (value == null) { + return null; @@ -642,6 +967,11 @@ index 0000000000000000000000000000000000000000..f005f805112534749c26426c5a78b7d0 + } + + @Override ++ public @Nullable T get(final TypedKey<T> key) { ++ return this.get(key.key()); ++ } ++ ++ @Override + public T getOrThrow(final Key key) { + final @Nullable T value = this.get(key); + if (value == null) { @@ -651,6 +981,11 @@ index 0000000000000000000000000000000000000000..f005f805112534749c26426c5a78b7d0 + } + + @Override ++ public T getOrThrow(final TypedKey<T> key) { ++ return this.getOrThrow(key.key()); ++ } ++ ++ @Override + public Iterator<T> iterator() { + return Iterators.transform(this.registry.beforeFrozenView().entrySet().iterator(), input -> this.minecraftToBukkit.apply(CraftNamespacedKey.fromMinecraft(input.getKey()), input.getValue())); + } @@ -690,10 +1025,10 @@ index 0000000000000000000000000000000000000000..5bba6101eb79fa1275621ba2b7a024ac +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEntryAddEventImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryEntryAddEventImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..0d55efaaf2be84001663dbc8618cfd42c39c2d77 +index 0000000000000000000000000000000000000000..45930395bfcf87b0120a1f3e079764003a0cb145 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEntryAddEventImpl.java -@@ -0,0 +1,15 @@ +@@ -0,0 +1,14 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent; @@ -705,16 +1040,15 @@ index 0000000000000000000000000000000000000000..0d55efaaf2be84001663dbc8618cfd42 +public record RegistryEntryAddEventImpl<T, B extends RegistryBuilder<T>>( + TypedKey<T> key, + B builder, -+ RegistryKey<T> registryKey, -+ RegistryView<T> registry ++ RegistryKey<T> registryKey +) implements RegistryEntryAddEvent<T, B>, PaperLifecycleEvent { +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventMap.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventMap.java new file mode 100644 -index 0000000000000000000000000000000000000000..8aaad14e07c651b153b35b9d4225414a8bd97da0 +index 0000000000000000000000000000000000000000..f5ea23173dcbe491742c3dd051c147ef397307a0 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventMap.java -@@ -0,0 +1,43 @@ +@@ -0,0 +1,44 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; @@ -725,10 +1059,11 @@ index 0000000000000000000000000000000000000000..8aaad14e07c651b153b35b9d4225414a +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; ++import java.util.function.BiFunction; + +public final class RegistryEventMap { + -+ private final Map<RegistryKey<?>, LifecycleEventType.Prioritizable<BootstrapContext, ? extends RegistryEvent<?>>> hooks = new HashMap<>(); ++ private final Map<RegistryKey<?>, LifecycleEventType<BootstrapContext, ? extends RegistryEvent<?>, ?>> hooks = new HashMap<>(); + private final String name; + + public RegistryEventMap(final String name) { @@ -736,12 +1071,12 @@ index 0000000000000000000000000000000000000000..8aaad14e07c651b153b35b9d4225414a + } + + @SuppressWarnings("unchecked") -+ public <T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> LifecycleEventType.Prioritizable<BootstrapContext, E> getOrCreate(final RegistryEventProvider<T, B> type) { -+ final RegistryLifecycleEventType<T, B, E> registerHook; ++ public <T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>, ET extends LifecycleEventType<BootstrapContext, E, ?>> ET getOrCreate(final RegistryEventProvider<T, B> type, final BiFunction<? super RegistryEventProvider<T, B>, ? super String, ET> eventTypeCreator) { ++ final ET registerHook; + if (this.hooks.containsKey(type.registryKey())) { -+ registerHook = (RegistryLifecycleEventType<T, B, E>) this.hooks.get(type.registryKey()); ++ registerHook = (ET) this.hooks.get(type.registryKey()); + } else { -+ registerHook = new RegistryLifecycleEventType<>(type, this.name); ++ registerHook = eventTypeCreator.apply(type, this.name); + LifecycleEventRunner.INSTANCE.addEventType(registerHook); + this.hooks.put(type.registryKey(), registerHook); + } @@ -749,8 +1084,8 @@ index 0000000000000000000000000000000000000000..8aaad14e07c651b153b35b9d4225414a + } + + @SuppressWarnings("unchecked") -+ public <T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> LifecycleEventType.Prioritizable<BootstrapContext, E> getHook(final RegistryKey<T> registryKey) { -+ return (RegistryLifecycleEventType<T, B, E>) Objects.requireNonNull(this.hooks.get(registryKey), "No hook for " + registryKey); ++ public <T, E extends RegistryEvent<T>> LifecycleEventType<BootstrapContext, E, ?> getHook(final RegistryKey<T> registryKey) { ++ return (LifecycleEventType<BootstrapContext, E, ?>) Objects.requireNonNull(this.hooks.get(registryKey), "No hook for " + registryKey); + } + + public boolean hasHooks(final RegistryKey<?> registryKey) { @@ -760,16 +1095,17 @@ index 0000000000000000000000000000000000000000..8aaad14e07c651b153b35b9d4225414a +} diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProviderImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProviderImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..22b203a176c5b1c53dae7fb173667b9d90cd384d +index 0000000000000000000000000000000000000000..a4c3f981673c4202d06149996db7997f6670a07c --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProviderImpl.java -@@ -0,0 +1,23 @@ +@@ -0,0 +1,24 @@ +package io.papermc.paper.registry.event; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; +import io.papermc.paper.registry.PaperRegistryListenerManager; +import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.event.type.RegistryEntryAddEventType; + +public class RegistryEventTypeProviderImpl implements RegistryEventTypeProvider { + @@ -778,7 +1114,7 @@ index 0000000000000000000000000000000000000000..22b203a176c5b1c53dae7fb173667b9d + } + + @Override -+ public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryEntryAddEvent<T, B>> registryAddition(final RegistryEventProvider<T, B> type) { ++ public <T, B extends RegistryBuilder<T>> RegistryEntryAddEventType<T, B> registryAddition(final RegistryEventProvider<T, B> type) { + return PaperRegistryListenerManager.INSTANCE.getRegistryAdditionEventType(type); + } + @@ -804,35 +1140,120 @@ index 0000000000000000000000000000000000000000..2db5d33d0b72ec3c9ff1c3042d9246df + WritableRegistry<T, B> registry +) implements RegistryFreezeEvent<T, B>, PaperLifecycleEvent { +} -diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryLifecycleEventType.java b/src/main/java/io/papermc/paper/registry/event/RegistryLifecycleEventType.java +diff --git a/src/main/java/io/papermc/paper/registry/event/package-info.java b/src/main/java/io/papermc/paper/registry/event/package-info.java new file mode 100644 -index 0000000000000000000000000000000000000000..0a896584870b2f6dcbf7436f28741bce522e3de8 +index 0000000000000000000000000000000000000000..14d2d9766b8dee763f220c397aba3ad432d02aaa --- /dev/null -+++ b/src/main/java/io/papermc/paper/registry/event/RegistryLifecycleEventType.java -@@ -0,0 +1,12 @@ ++++ b/src/main/java/io/papermc/paper/registry/event/package-info.java +@@ -0,0 +1,5 @@ ++@DefaultQualifier(NonNull.class) +package io.papermc.paper.registry.event; + ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; +diff --git a/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddEventTypeImpl.java b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddEventTypeImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..32303ea9b3da736cbe26d06e57f5dcc3aa32a99b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddEventTypeImpl.java +@@ -0,0 +1,32 @@ ++package io.papermc.paper.registry.event.type; ++ +import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; +import io.papermc.paper.plugin.lifecycle.event.types.PrioritizableLifecycleEventType; +import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.event.RegistryEntryAddEvent; ++import io.papermc.paper.registry.event.RegistryEventProvider; ++import java.util.function.Consumer; ++import java.util.function.Predicate; + -+public final class RegistryLifecycleEventType<T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> extends PrioritizableLifecycleEventType<BootstrapContext, E> { ++public class RegistryEntryAddEventTypeImpl<T, B extends RegistryBuilder<T>> extends PrioritizableLifecycleEventType<BootstrapContext, RegistryEntryAddEvent<T, B>, RegistryEntryAddConfiguration<T>> implements RegistryEntryAddEventType<T, B> { + -+ RegistryLifecycleEventType(final RegistryEventProvider<T, B> type, final String eventName) { ++ public RegistryEntryAddEventTypeImpl(final RegistryEventProvider<T, B> type, final String eventName) { + super(type.registryKey() + " / " + eventName, BootstrapContext.class); + } ++ ++ @Override ++ public RegistryEntryAddConfiguration<T> newHandler(final LifecycleEventHandler<? super RegistryEntryAddEvent<T, B>> handler) { ++ return new RegistryEntryAddHandlerConfiguration<>(handler, this); ++ } ++ ++ @Override ++ public void forEachHandler(final RegistryEntryAddEvent<T, B> event, final Consumer<RegisteredHandler<BootstrapContext, RegistryEntryAddEvent<T, B>>> consumer, final Predicate<RegisteredHandler<BootstrapContext, RegistryEntryAddEvent<T, B>>> predicate) { ++ super.forEachHandler(event, consumer, predicate.and(handler -> this.matchesTarget(event, handler))); ++ } ++ ++ private boolean matchesTarget(final RegistryEntryAddEvent<T, B> event, final RegisteredHandler<BootstrapContext, RegistryEntryAddEvent<T, B>> handler) { ++ final RegistryEntryAddHandlerConfiguration<T, B> config = (RegistryEntryAddHandlerConfiguration<T, B>) handler.config(); ++ return config.target() == null || event.key().equals(config.target()); ++ } +} -diff --git a/src/main/java/io/papermc/paper/registry/event/package-info.java b/src/main/java/io/papermc/paper/registry/event/package-info.java +diff --git a/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddHandlerConfiguration.java b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddHandlerConfiguration.java new file mode 100644 -index 0000000000000000000000000000000000000000..14d2d9766b8dee763f220c397aba3ad432d02aaa +index 0000000000000000000000000000000000000000..53df2dd1a9e1cef90bd8504c717b1cc6374b6f4e --- /dev/null -+++ b/src/main/java/io/papermc/paper/registry/event/package-info.java -@@ -0,0 +1,5 @@ -+@DefaultQualifier(NonNull.class) -+package io.papermc.paper.registry.event; ++++ b/src/main/java/io/papermc/paper/registry/event/type/RegistryEntryAddHandlerConfiguration.java +@@ -0,0 +1,39 @@ ++package io.papermc.paper.registry.event.type; + -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.framework.qual.DefaultQualifier; ++import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; ++import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfigurationImpl; ++import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType; ++import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.TypedKey; ++import io.papermc.paper.registry.event.RegistryEntryAddEvent; ++import org.checkerframework.checker.nullness.qual.Nullable; ++ ++public class RegistryEntryAddHandlerConfiguration<T, B extends RegistryBuilder<T>> extends PrioritizedLifecycleEventHandlerConfigurationImpl<BootstrapContext, RegistryEntryAddEvent<T, B>> implements RegistryEntryAddConfiguration<T> { ++ ++ private @Nullable TypedKey<T> target; ++ ++ public RegistryEntryAddHandlerConfiguration(final LifecycleEventHandler<? super RegistryEntryAddEvent<T, B>> handler, final AbstractLifecycleEventType<BootstrapContext, RegistryEntryAddEvent<T, B>, ?> eventType) { ++ super(handler, eventType); ++ } ++ ++ public @Nullable TypedKey<T> target() { ++ return this.target; ++ } ++ ++ @Override ++ public RegistryEntryAddConfiguration<T> onlyFor(final TypedKey<T> key) { ++ this.target = key; ++ return this; ++ } ++ ++ @Override ++ public RegistryEntryAddConfiguration<T> priority(final int priority) { ++ return (RegistryEntryAddConfiguration<T>) super.priority(priority); ++ } ++ ++ @Override ++ public RegistryEntryAddConfiguration<T> monitor() { ++ return (RegistryEntryAddConfiguration<T>) super.monitor(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/event/type/RegistryLifecycleEventType.java b/src/main/java/io/papermc/paper/registry/event/type/RegistryLifecycleEventType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..dcc0f6b337840a78d38abdf2eb3f4bbd1676f58f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/event/type/RegistryLifecycleEventType.java +@@ -0,0 +1,14 @@ ++package io.papermc.paper.registry.event.type; ++ ++import io.papermc.paper.plugin.bootstrap.BootstrapContext; ++import io.papermc.paper.plugin.lifecycle.event.types.PrioritizableLifecycleEventType; ++import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.event.RegistryEvent; ++import io.papermc.paper.registry.event.RegistryEventProvider; ++ ++public final class RegistryLifecycleEventType<T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> extends PrioritizableLifecycleEventType.Simple<BootstrapContext, E> { ++ ++ public RegistryLifecycleEventType(final RegistryEventProvider<T, B> type, final String eventName) { ++ super(type.registryKey() + " / " + eventName, BootstrapContext.class); ++ } ++} diff --git a/src/main/java/io/papermc/paper/registry/package-info.java b/src/main/java/io/papermc/paper/registry/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..0b80179ff90e085568d7ceafd9b17511789dc99b diff --git a/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java index 727a833f33..b8d30202dd 100644 --- a/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java @@ -1,5 +1,6 @@ package io.papermc.testplugin; +import io.papermc.paper.registry.keys.GameEventKeys; import org.bukkit.GameEvent; import org.bukkit.Registry; import org.bukkit.event.Listener; @@ -19,6 +20,10 @@ public final class TestPlugin extends JavaPlugin implements Listener { } else { System.out.println("New event: " + newEvent.getKey() + " " + newEvent.getRange()); } + final GameEvent changed = Registry.GAME_EVENT.get(GameEventKeys.BLOCK_OPEN); + System.out.println("changed: " + changed.getRange()); + final GameEvent same = Registry.GAME_EVENT.get(GameEventKeys.CONTAINER_OPEN); + System.out.println("same: " + same.getRange()); } } diff --git a/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java index 38e9f4d184..26da106c6c 100644 --- a/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java @@ -23,11 +23,9 @@ public class TestPluginBootstrap implements PluginBootstrap { // io.papermc.testplugin.brigtests.Registration.registerViaBootstrap(context); final LifecycleEventManager<BootstrapContext> lifecycleManager = context.getLifecycleManager(); - lifecycleManager.registerEventHandler(RegistryEvents.GAME_EVENT.newEntryAddHandler(event -> { - if (event.key().equals(GameEventKeys.BLOCK_OPEN)) { - event.builder().range(event.builder().range() * 2); - } - }).priority(10)); + lifecycleManager.registerEventHandler(RegistryEvents.GAME_EVENT.entryAdd().newHandler(event -> { + event.builder().range(event.builder().range() * 40); + }).priority(10).onlyFor(GameEventKeys.BLOCK_OPEN)); lifecycleManager.registerEventHandler(RegistryEvents.GAME_EVENT.freeze(), event -> { event.registry().register(NEW_EVENT, builder -> { builder.range(2); |