mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-25 03:55:14 +01:00
8c5b837e05
Firstly, the old methods all routed to the CompletableFuture method. However, the CF method could not guarantee that if the caller was off-main that the future would be "completed" on-main. Since the callback methods used the CF one, this meant that the callback methods did not guarantee that the callbacks were to be called on the main thread. Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb) so that the methods with the callback are guaranteed to invoke the callback on the main thread. The CF behavior remains unchanged; it may still appear to complete on main if invoked off-main. Secondly, remove the scheduleOnMain invocation in the async chunk completion. This unnecessarily delays the callback by 1 tick. Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which will load chunks within an area. This method is provided as a helper as keeping all chunks loaded within an area can be complicated to implement for plugins (due to the lacking ticket API), and is already implemented internally anyways. Fourthly, remove the ticket addition that occured with getChunkAt and getChunkAtAsync. The ticket addition may delay the unloading of the chunk unnecessarily. It also fixes a very rare timing bug where the future/callback would be completed after the chunk unloads.
596 lines
32 KiB
Diff
596 lines
32 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
Date: Thu, 20 Jun 2024 09:40:57 -0700
|
|
Subject: [PATCH] Tag Lifecycle Events
|
|
|
|
== AT ==
|
|
public net/minecraft/tags/TagEntry id
|
|
public net/minecraft/tags/TagEntry tag
|
|
public net/minecraft/tags/TagEntry required
|
|
|
|
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 b11346e04bb16c3238f32deb87dbd680e261d4d2..996bac2fab8fb927d184fb62e043454e877727a6 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
|
|
@@ -13,6 +13,8 @@ public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeP
|
|
return (LifecycleEventTypeProviderImpl) LifecycleEventTypeProvider.provider();
|
|
}
|
|
|
|
+ private final PaperTagEventTypeProvider provider = new PaperTagEventTypeProvider();
|
|
+
|
|
@Override
|
|
public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Monitorable<O, E> monitor(final String name, final Class<? extends O> ownerType) {
|
|
return new MonitorableLifecycleEventType<>(name, ownerType);
|
|
@@ -22,4 +24,9 @@ public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeP
|
|
public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) {
|
|
return new PrioritizableLifecycleEventType.Simple<>(name, ownerType);
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public PaperTagEventTypeProvider tagProvider() {
|
|
+ return this.provider;
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PaperTagEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PaperTagEventTypeProvider.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..1cf4a3caa8d630e95eb569eef2cd577bba1a97a9
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PaperTagEventTypeProvider.java
|
|
@@ -0,0 +1,24 @@
|
|
+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.PaperTagListenerManager;
|
|
+import io.papermc.paper.tag.PostFlattenTagRegistrar;
|
|
+import io.papermc.paper.tag.PreFlattenTagRegistrar;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class PaperTagEventTypeProvider implements TagEventTypeProvider {
|
|
+
|
|
+ @Override
|
|
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<T>>> preFlatten(final RegistryKey<T> registryKey) {
|
|
+ return PaperTagListenerManager.INSTANCE.getPreFlattenType(registryKey);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<T>>> postFlatten(final RegistryKey<T> registryKey) {
|
|
+ return PaperTagListenerManager.INSTANCE.getPostFlattenType(registryKey);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/tag/PaperPostFlattenTagRegistrar.java b/src/main/java/io/papermc/paper/tag/PaperPostFlattenTagRegistrar.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..2596586fd7e2546cd18cf6ac36a4eb5cf8d00359
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/tag/PaperPostFlattenTagRegistrar.java
|
|
@@ -0,0 +1,119 @@
|
|
+package io.papermc.paper.tag;
|
|
+
|
|
+import com.google.common.collect.Collections2;
|
|
+import com.google.common.collect.ImmutableMap;
|
|
+import com.google.common.collect.Lists;
|
|
+import io.papermc.paper.adventure.PaperAdventure;
|
|
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import io.papermc.paper.registry.TypedKey;
|
|
+import io.papermc.paper.registry.tag.TagKey;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collection;
|
|
+import java.util.Collections;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import java.util.Optional;
|
|
+import java.util.function.Function;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@SuppressWarnings("BoundedWildcard")
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class PaperPostFlattenTagRegistrar<M, T> implements PaperRegistrar<BootstrapContext>, PostFlattenTagRegistrar<T> {
|
|
+
|
|
+ public final Map<ResourceLocation, List<M>> tags;
|
|
+ private final Function<ResourceLocation, Optional<? extends M>> fromIdConverter;
|
|
+ private final Function<M, ResourceLocation> toIdConverter;
|
|
+ private final RegistryKey<T> registryKey;
|
|
+
|
|
+ public PaperPostFlattenTagRegistrar(
|
|
+ final Map<ResourceLocation, List<M>> tags,
|
|
+ final TagEventConfig<M, T> config
|
|
+ ) {
|
|
+ this.tags = tags;
|
|
+ this.fromIdConverter = config.fromIdConverter();
|
|
+ this.toIdConverter = config.toIdConverter();
|
|
+ this.registryKey = config.apiRegistryKey();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setCurrentContext(final @Nullable BootstrapContext owner) {
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public RegistryKey<T> registryKey() {
|
|
+ return this.registryKey;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Map<TagKey<T>, Collection<TypedKey<T>>> getAllTags() {
|
|
+ final ImmutableMap.Builder<TagKey<T>, Collection<TypedKey<T>>> tags = ImmutableMap.builderWithExpectedSize(this.tags.size());
|
|
+ for (final Map.Entry<ResourceLocation, List<M>> entry : this.tags.entrySet()) {
|
|
+ final TagKey<T> key = TagKey.create(this.registryKey, CraftNamespacedKey.fromMinecraft(entry.getKey()));
|
|
+ tags.put(key, this.convert(entry.getValue()));
|
|
+ }
|
|
+ return tags.build();
|
|
+ }
|
|
+
|
|
+ private List<TypedKey<T>> convert(final List<M> nms) {
|
|
+ return Collections.unmodifiableList(
|
|
+ Lists.transform(nms, m -> this.convert(this.toIdConverter.apply(m)))
|
|
+ );
|
|
+ }
|
|
+
|
|
+ private TypedKey<T> convert(final ResourceLocation location) {
|
|
+ return TypedKey.create(this.registryKey, CraftNamespacedKey.fromMinecraft(location));
|
|
+ }
|
|
+
|
|
+ private M convert(final TypedKey<T> key) {
|
|
+ final Optional<? extends M> optional = this.fromIdConverter.apply(PaperAdventure.asVanilla(key.key()));
|
|
+ if (optional.isEmpty()) {
|
|
+ throw new IllegalArgumentException(key + " doesn't exist");
|
|
+ }
|
|
+ return optional.get();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasTag(final TagKey<T> tagKey) {
|
|
+ return this.tags.containsKey(PaperAdventure.asVanilla(tagKey.key()));
|
|
+ }
|
|
+
|
|
+ private List<M> getNmsTag(final TagKey<T> tagKey, final boolean create) {
|
|
+ final ResourceLocation vanillaKey = PaperAdventure.asVanilla(tagKey.key());
|
|
+ List<M> tag = this.tags.get(vanillaKey);
|
|
+ if (tag == null) {
|
|
+ if (create) {
|
|
+ tag = this.tags.computeIfAbsent(vanillaKey, k -> new ArrayList<>());
|
|
+ } else {
|
|
+ throw new NoSuchElementException("Tag " + tagKey + " is not present");
|
|
+ }
|
|
+ }
|
|
+ return tag;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Collection<TypedKey<T>> getTag(final TagKey<T> tagKey) {
|
|
+ return this.convert(this.getNmsTag(tagKey, false));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void addToTag(final TagKey<T> tagKey, final Collection<TypedKey<T>> values) {
|
|
+ final List<M> nmsTag = new ArrayList<>(this.getNmsTag(tagKey, true));
|
|
+ for (final TypedKey<T> key : values) {
|
|
+ nmsTag.add(this.convert(key));
|
|
+ }
|
|
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), nmsTag);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setTag(final TagKey<T> tagKey, final Collection<TypedKey<T>> values) {
|
|
+ final List<M> newList = List.copyOf(Collections2.transform(values, this::convert));
|
|
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), newList);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/tag/PaperPreFlattenTagRegistrar.java b/src/main/java/io/papermc/paper/tag/PaperPreFlattenTagRegistrar.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..44111b55eaa6d1cc93e2c556b23bb5c97953caac
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/tag/PaperPreFlattenTagRegistrar.java
|
|
@@ -0,0 +1,128 @@
|
|
+package io.papermc.paper.tag;
|
|
+
|
|
+import com.google.common.base.Preconditions;
|
|
+import com.google.common.collect.Collections2;
|
|
+import com.google.common.collect.ImmutableMap;
|
|
+import com.google.common.collect.Lists;
|
|
+import io.papermc.paper.adventure.PaperAdventure;
|
|
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import io.papermc.paper.registry.tag.TagKey;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collection;
|
|
+import java.util.Collections;
|
|
+import java.util.HashMap;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.tags.TagLoader;
|
|
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@SuppressWarnings("BoundedWildcard")
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class PaperPreFlattenTagRegistrar<T> implements PaperRegistrar<BootstrapContext>, PreFlattenTagRegistrar<T> {
|
|
+
|
|
+ public final Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags;
|
|
+ private final RegistryKey<T> registryKey;
|
|
+
|
|
+ private @Nullable BootstrapContext owner;
|
|
+
|
|
+ public PaperPreFlattenTagRegistrar(
|
|
+ final Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags,
|
|
+ final TagEventConfig<?, T> config
|
|
+ ) {
|
|
+ this.tags = new HashMap<>(tags);
|
|
+ this.registryKey = config.apiRegistryKey();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setCurrentContext(final @Nullable BootstrapContext owner) {
|
|
+ this.owner = owner;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public RegistryKey<T> registryKey() {
|
|
+ return this.registryKey;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Map<TagKey<T>, Collection<TagEntry<T>>> getAllTags() {
|
|
+ final ImmutableMap.Builder<TagKey<T>, Collection<io.papermc.paper.tag.TagEntry<T>>> builder = ImmutableMap.builderWithExpectedSize(this.tags.size());
|
|
+ for (final Map.Entry<ResourceLocation, List<TagLoader.EntryWithSource>> entry : this.tags.entrySet()) {
|
|
+ final TagKey<T> key = TagKey.create(this.registryKey, CraftNamespacedKey.fromMinecraft(entry.getKey()));
|
|
+ builder.put(key, convert(entry.getValue()));
|
|
+ }
|
|
+ return builder.build();
|
|
+ }
|
|
+
|
|
+ private static <T> List<io.papermc.paper.tag.TagEntry<T>> convert(final List<TagLoader.EntryWithSource> nmsEntries) {
|
|
+ return Collections.unmodifiableList(Lists.transform(nmsEntries, PaperPreFlattenTagRegistrar::convert));
|
|
+ }
|
|
+
|
|
+ private static <T> io.papermc.paper.tag.TagEntry<T> convert(final TagLoader.EntryWithSource nmsEntry) {
|
|
+ return new TagEntryImpl<>(CraftNamespacedKey.fromMinecraft(nmsEntry.entry().id), nmsEntry.entry().tag, nmsEntry.entry().required);
|
|
+ }
|
|
+
|
|
+ private TagLoader.EntryWithSource convert(final TagEntry<T> entry) {
|
|
+ Preconditions.checkState(this.owner != null, "Owner is not set");
|
|
+ final ResourceLocation vanilla = PaperAdventure.asVanilla(entry.key());
|
|
+ final net.minecraft.tags.TagEntry nmsEntry;
|
|
+ if (entry.isTag()) {
|
|
+ if (entry.isRequired()) {
|
|
+ nmsEntry = net.minecraft.tags.TagEntry.tag(vanilla);
|
|
+ } else {
|
|
+ nmsEntry = net.minecraft.tags.TagEntry.optionalTag(vanilla);
|
|
+ }
|
|
+ } else {
|
|
+ if (entry.isRequired()) {
|
|
+ nmsEntry = net.minecraft.tags.TagEntry.element(vanilla);
|
|
+ } else {
|
|
+ nmsEntry = net.minecraft.tags.TagEntry.optionalElement(vanilla);
|
|
+ }
|
|
+ }
|
|
+ return new TagLoader.EntryWithSource(nmsEntry, this.owner.getPluginMeta().getDisplayName());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasTag(final TagKey<T> tagKey) {
|
|
+ return this.tags.containsKey(PaperAdventure.asVanilla(tagKey.key()));
|
|
+ }
|
|
+
|
|
+ private List<TagLoader.EntryWithSource> getNmsTag(final TagKey<T> tagKey, boolean create) {
|
|
+ final ResourceLocation vanillaKey = PaperAdventure.asVanilla(tagKey.key());
|
|
+ List<TagLoader.EntryWithSource> tag = this.tags.get(vanillaKey);
|
|
+ if (tag == null) {
|
|
+ if (create) {
|
|
+ tag = this.tags.computeIfAbsent(vanillaKey, k -> new ArrayList<>());
|
|
+ } else {
|
|
+ throw new NoSuchElementException("Tag " + tagKey + " is not present");
|
|
+ }
|
|
+ }
|
|
+ return tag;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<TagEntry<T>> getTag(final TagKey<T> tagKey) {
|
|
+ return convert(this.getNmsTag(tagKey, false));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void addToTag(final TagKey<T> tagKey, final Collection<TagEntry<T>> entries) {
|
|
+ final List<TagLoader.EntryWithSource> nmsTag = new ArrayList<>(this.getNmsTag(tagKey, true));
|
|
+ for (final TagEntry<T> tagEntry : entries) {
|
|
+ nmsTag.add(this.convert(tagEntry));
|
|
+ }
|
|
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), nmsTag);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setTag(final TagKey<T> tagKey, final Collection<TagEntry<T>> entries) {
|
|
+ final List<TagLoader.EntryWithSource> newList = List.copyOf(Collections2.transform(entries, this::convert));
|
|
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), newList);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/tag/PaperTagListenerManager.java b/src/main/java/io/papermc/paper/tag/PaperTagListenerManager.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..e1ffb7f1df667dd9f92c00ff94b791feb1f14eed
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/tag/PaperTagListenerManager.java
|
|
@@ -0,0 +1,105 @@
|
|
+package io.papermc.paper.tag;
|
|
+
|
|
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.PrioritizableLifecycleEventType;
|
|
+import io.papermc.paper.registry.PaperRegistries;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import io.papermc.paper.registry.event.RegistryEventMap;
|
|
+import java.util.Collection;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+import net.minecraft.core.Holder;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.tags.TagLoader;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class PaperTagListenerManager {
|
|
+
|
|
+ public static final String PRE_FLATTEN_EVENT_NAME = "pre-flatten";
|
|
+ public static final String POST_FLATTEN_EVENT_NAME = "post-flatten";
|
|
+
|
|
+ public static final PaperTagListenerManager INSTANCE = new PaperTagListenerManager();
|
|
+
|
|
+ public final RegistryEventMap preFlatten = new RegistryEventMap(PRE_FLATTEN_EVENT_NAME);
|
|
+ public final RegistryEventMap postFlatten = new RegistryEventMap(POST_FLATTEN_EVENT_NAME);
|
|
+
|
|
+ private PaperTagListenerManager() {
|
|
+ }
|
|
+
|
|
+ public <A> Map<ResourceLocation, List<TagLoader.EntryWithSource>> firePreFlattenEvent(
|
|
+ final Map<ResourceLocation, List<TagLoader.EntryWithSource>> initial,
|
|
+ final @Nullable TagEventConfig<?, A> config
|
|
+ ) {
|
|
+ if (config == null || config.preFlatten() == null || !config.preFlatten().hasHandlers()) {
|
|
+ return initial;
|
|
+ }
|
|
+ final PaperPreFlattenTagRegistrar<A> registrar = new PaperPreFlattenTagRegistrar<>(initial, config);
|
|
+ LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(
|
|
+ config.preFlatten(),
|
|
+ registrar,
|
|
+ BootstrapContext.class,
|
|
+ config.cause()
|
|
+ );
|
|
+ return Map.copyOf(registrar.tags);
|
|
+ }
|
|
+
|
|
+ public <M, A> Map<ResourceLocation, List<M>> firePostFlattenEvent(
|
|
+ final Map<ResourceLocation, List<M>> initial,
|
|
+ final @Nullable TagEventConfig<M, A> config
|
|
+ ) {
|
|
+ if (config == null || config.postFlatten() == null || !config.postFlatten().hasHandlers()) {
|
|
+ return initial;
|
|
+ }
|
|
+ final PaperPostFlattenTagRegistrar<M, A> registrar = new PaperPostFlattenTagRegistrar<>(initial, config);
|
|
+ LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(
|
|
+ config.postFlatten(),
|
|
+ registrar,
|
|
+ BootstrapContext.class,
|
|
+ config.cause()
|
|
+ );
|
|
+ return Map.copyOf(registrar.tags);
|
|
+ }
|
|
+
|
|
+ public <M, B> @Nullable TagEventConfig<Holder<M>, B> createEventConfig(final Registry<M> registry, final ReloadableRegistrarEvent.Cause cause) {
|
|
+ if (PaperRegistries.getEntry(registry.key()) == null) {
|
|
+ // TODO probably should be able to modify every registry
|
|
+ return null;
|
|
+ }
|
|
+ final RegistryKey<B> registryKey = PaperRegistries.registryFromNms(registry.key());
|
|
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<B>>, ?> preFlatten = null;
|
|
+ if (this.preFlatten.hasHandlers(registryKey)) {
|
|
+ preFlatten = (AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<B>>, ?>) this.preFlatten.<B, ReloadableRegistrarEvent<PreFlattenTagRegistrar<B>>>getEventType(registryKey);
|
|
+ }
|
|
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<B>>, ?> postFlatten = null;
|
|
+ if (this.postFlatten.hasHandlers(registryKey)) {
|
|
+ postFlatten = (AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<B>>, ?>) this.postFlatten.<B, ReloadableRegistrarEvent<PostFlattenTagRegistrar<B>>>getEventType(registryKey);
|
|
+ }
|
|
+ return new TagEventConfig<>(
|
|
+ preFlatten,
|
|
+ postFlatten,
|
|
+ cause,
|
|
+ registry::get,
|
|
+ h -> ((Holder.Reference<M>) h).key().location(),
|
|
+ PaperRegistries.registryFromNms(registry.key())
|
|
+ );
|
|
+ }
|
|
+
|
|
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<T>>> getPreFlattenType(final RegistryKey<T> registryKey) {
|
|
+ return this.preFlatten.getOrCreate(registryKey, (ignored, name) -> {
|
|
+ return new PrioritizableLifecycleEventType.Simple<>(name, BootstrapContext.class);
|
|
+ });
|
|
+ }
|
|
+
|
|
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<T>>> getPostFlattenType(final RegistryKey<T> registryKey) {
|
|
+ return this.postFlatten.getOrCreate(registryKey, (ignored, name) -> {
|
|
+ return new PrioritizableLifecycleEventType.Simple<>(name, BootstrapContext.class);
|
|
+ });
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/tag/TagEventConfig.java b/src/main/java/io/papermc/paper/tag/TagEventConfig.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..d6d4bfc6f45d646afeace422a038c670e10aaf80
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/tag/TagEventConfig.java
|
|
@@ -0,0 +1,23 @@
|
|
+package io.papermc.paper.tag;
|
|
+
|
|
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import java.util.Optional;
|
|
+import java.util.function.Function;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public record TagEventConfig<M, A>(
|
|
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ? extends ReloadableRegistrarEvent<PreFlattenTagRegistrar<A>>, ?> preFlatten,
|
|
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ? extends ReloadableRegistrarEvent<PostFlattenTagRegistrar<A>>, ?> postFlatten,
|
|
+ ReloadableRegistrarEvent.Cause cause,
|
|
+ Function<ResourceLocation, Optional<? extends M>> fromIdConverter,
|
|
+ Function<M, ResourceLocation> toIdConverter,
|
|
+ RegistryKey<A> apiRegistryKey
|
|
+) {
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
|
index fdc88e52235a152dbe3cca273990b4b68f8daaf8..13797035494a1e010e1da529fb46040f8a6e859f 100644
|
|
--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
|
+++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
|
@@ -278,7 +278,7 @@ public class RegistryDataLoader {
|
|
}
|
|
}
|
|
|
|
- TagLoader.loadTagsForRegistry(resourceManager, registry);
|
|
+ TagLoader.loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - tag lifecycle - add cause
|
|
}
|
|
|
|
static <E> void loadContentsFromNetwork(
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index ff6f2dc31bbbaa420323a68282cb1ee3d8b98c0f..e18692ad6bdbc8bc2df605833501b1ad888b8b7d 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -2208,7 +2208,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
return stream.<Pack>map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error // todo: is this needed anymore?
|
|
}, this).thenCompose((immutablelist) -> {
|
|
MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist);
|
|
- List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess());
|
|
+ List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess(), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag lifecycle - add cause
|
|
|
|
return ReloadableServerResources.loadResources(resourcemanager, this.registries, list, this.worldData.enabledFeatures(), this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((datapackresources, throwable) -> {
|
|
if (throwable != null) {
|
|
diff --git a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
|
index b5ca1a0acb16d0cd8dccc854f309d425a48b070d..ea1cbd7a3897ea4a86877a557da264387ef78a38 100644
|
|
--- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
|
+++ b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
|
@@ -70,7 +70,7 @@ public class ReloadableServerRegistries {
|
|
String string = Registries.elementsDirPath(type.registryKey());
|
|
SimpleJsonResourceReloadListener.scanDirectory(resourceManager, string, ops, type.codec(), map);
|
|
map.forEach((id, value) -> io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerWithListeners(writableRegistry, ResourceKey.create(type.registryKey(), id), value, DEFAULT_REGISTRATION_INFO, conversions)); // Paper - register with listeners
|
|
- TagLoader.loadTagsForRegistry(resourceManager, writableRegistry);
|
|
+ TagLoader.loadTagsForRegistry(resourceManager, writableRegistry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag life cycle - reload
|
|
return writableRegistry;
|
|
}, prepareExecutor);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/ServerFunctionLibrary.java b/src/main/java/net/minecraft/server/ServerFunctionLibrary.java
|
|
index 7128f01308b60163afa9355b79cb4129b630663d..fa5d4bfd52eb36e48fc811dbbdc1341204cf171d 100644
|
|
--- a/src/main/java/net/minecraft/server/ServerFunctionLibrary.java
|
|
+++ b/src/main/java/net/minecraft/server/ServerFunctionLibrary.java
|
|
@@ -113,7 +113,7 @@ public class ServerFunctionLibrary implements PreparableReloadListener {
|
|
return null;
|
|
}).join());
|
|
this.functions = builder.build();
|
|
- this.tags = this.tagsLoader.build((Map<ResourceLocation, List<TagLoader.EntryWithSource>>)intermediate.getFirst());
|
|
+ this.tags = this.tagsLoader.build((Map<ResourceLocation, List<TagLoader.EntryWithSource>>)intermediate.getFirst(), null); // Paper - command function tags are not implemented yet
|
|
},
|
|
applyExecutor
|
|
);
|
|
diff --git a/src/main/java/net/minecraft/server/WorldLoader.java b/src/main/java/net/minecraft/server/WorldLoader.java
|
|
index f21ccc50f2d507afe1e0af394321020cb5667e60..fad1cc1be3d1b84acacde8736129b970824f48b8 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldLoader.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldLoader.java
|
|
@@ -37,7 +37,7 @@ public class WorldLoader {
|
|
CloseableResourceManager closeableResourceManager = pair.getSecond();
|
|
LayeredRegistryAccess<RegistryLayer> layeredRegistryAccess = RegistryLayer.createRegistryAccess();
|
|
List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(
|
|
- closeableResourceManager, layeredRegistryAccess.getLayer(RegistryLayer.STATIC)
|
|
+ closeableResourceManager, layeredRegistryAccess.getLayer(RegistryLayer.STATIC), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL // Paper - tag lifecycle - add cause
|
|
);
|
|
RegistryAccess.Frozen frozen = layeredRegistryAccess.getAccessForLoading(RegistryLayer.WORLDGEN);
|
|
List<HolderLookup.RegistryLookup<?>> list2 = TagLoader.buildUpdatedLookups(frozen, list);
|
|
diff --git a/src/main/java/net/minecraft/tags/TagLoader.java b/src/main/java/net/minecraft/tags/TagLoader.java
|
|
index 8d742805f7b44b832b532d4ee6d313c0d7659e1d..a81b2b47b909b3858046d2b152d31b2cfc5d5fe4 100644
|
|
--- a/src/main/java/net/minecraft/tags/TagLoader.java
|
|
+++ b/src/main/java/net/minecraft/tags/TagLoader.java
|
|
@@ -86,7 +86,10 @@ public class TagLoader<T> {
|
|
return list.isEmpty() ? Either.right(List.copyOf(sequencedSet)) : Either.left(list);
|
|
}
|
|
|
|
- public Map<ResourceLocation, List<T>> build(Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags) {
|
|
+ // Paper start - fire tag registrar events
|
|
+ public Map<ResourceLocation, List<T>> build(Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags, @Nullable io.papermc.paper.tag.TagEventConfig<T, ?> eventConfig) {
|
|
+ tags = io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.firePreFlattenEvent(tags, eventConfig);
|
|
+ // Paper end - fire tag registrar event
|
|
final Map<ResourceLocation, List<T>> map = new HashMap<>();
|
|
TagEntry.Lookup<T> lookup = new TagEntry.Lookup<T>() {
|
|
@Nullable
|
|
@@ -114,7 +117,7 @@ public class TagLoader<T> {
|
|
)
|
|
.ifRight(values -> map.put(id, (List<T>)values))
|
|
);
|
|
- return map;
|
|
+ return io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.firePostFlattenEvent(map, eventConfig); // Paper - fire tag registrar events
|
|
}
|
|
|
|
public static <T> void loadTagsFromNetwork(TagNetworkSerialization.NetworkPayload tags, WritableRegistry<T> registry) {
|
|
@@ -122,28 +125,38 @@ public class TagLoader<T> {
|
|
}
|
|
|
|
public static List<Registry.PendingTags<?>> loadTagsForExistingRegistries(ResourceManager resourceManager, RegistryAccess registryManager) {
|
|
+ // Paper start - tag lifecycle - add cause
|
|
+ return loadTagsForExistingRegistries(resourceManager, registryManager, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL);
|
|
+ }
|
|
+ public static List<Registry.PendingTags<?>> loadTagsForExistingRegistries(ResourceManager resourceManager, RegistryAccess registryManager, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause cause) {
|
|
+ // Paper end - tag lifecycle - add cause
|
|
return registryManager.registries()
|
|
- .map(registry -> loadPendingTags(resourceManager, registry.value()))
|
|
+ .map(registry -> loadPendingTags(resourceManager, registry.value(), cause)) // Paper - tag lifecycle - add cause
|
|
.flatMap(Optional::stream)
|
|
.collect(Collectors.toUnmodifiableList());
|
|
}
|
|
|
|
public static <T> void loadTagsForRegistry(ResourceManager resourceManager, WritableRegistry<T> registry) {
|
|
+ // Paper start - tag lifecycle - add registrar event cause
|
|
+ loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL);
|
|
+ }
|
|
+ public static <T> void loadTagsForRegistry(ResourceManager resourceManager, WritableRegistry<T> registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause cause) {
|
|
+ // Paper end - tag lifecycle - add registrar event cause
|
|
ResourceKey<? extends Registry<T>> resourceKey = registry.key();
|
|
TagLoader<Holder<T>> tagLoader = new TagLoader<>(TagLoader.ElementLookup.fromWritableRegistry(registry), Registries.tagsDirPath(resourceKey));
|
|
- tagLoader.build(tagLoader.load(resourceManager)).forEach((id, entries) -> registry.bindTag(TagKey.create(resourceKey, id), (List<Holder<T>>)entries));
|
|
+ tagLoader.build(tagLoader.load(resourceManager), io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.createEventConfig(registry, cause)).forEach((id, entries) -> registry.bindTag(TagKey.create(resourceKey, id), (List<Holder<T>>)entries)); // Paper - tag lifecycle - add registrar event cause
|
|
}
|
|
|
|
private static <T> Map<TagKey<T>, List<Holder<T>>> wrapTags(ResourceKey<? extends Registry<T>> registryRef, Map<ResourceLocation, List<Holder<T>>> tags) {
|
|
return tags.entrySet().stream().collect(Collectors.toUnmodifiableMap(entry -> TagKey.create(registryRef, entry.getKey()), Entry::getValue));
|
|
}
|
|
|
|
- private static <T> Optional<Registry.PendingTags<T>> loadPendingTags(ResourceManager resourceManager, Registry<T> registry) {
|
|
+ private static <T> Optional<Registry.PendingTags<T>> loadPendingTags(ResourceManager resourceManager, Registry<T> registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause cause) { // Paper - add registrar event cause
|
|
ResourceKey<? extends Registry<T>> resourceKey = registry.key();
|
|
TagLoader<Holder<T>> tagLoader = new TagLoader<>(
|
|
(TagLoader.ElementLookup<Holder<T>>)TagLoader.ElementLookup.fromFrozenRegistry(registry), Registries.tagsDirPath(resourceKey)
|
|
);
|
|
- TagLoader.LoadResult<T> loadResult = new TagLoader.LoadResult<>(resourceKey, wrapTags(registry.key(), tagLoader.build(tagLoader.load(resourceManager))));
|
|
+ TagLoader.LoadResult<T> loadResult = new TagLoader.LoadResult<>(resourceKey, wrapTags(registry.key(), tagLoader.build(tagLoader.load(resourceManager), io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.createEventConfig(registry, cause)))); // Paper - add registrar event cause
|
|
return loadResult.tags().isEmpty() ? Optional.empty() : Optional.of(registry.prepareTagReload(loadResult));
|
|
}
|
|
|