Registry Modification API

== AT ==
public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V
public net.minecraft.resources.RegistryOps lookupProvider
public net.minecraft.resources.RegistryOps$HolderLookupAdapter
This commit is contained in:
Jake Potrebic
2023-02-27 18:28:39 -08:00
parent 463f952cd4
commit a1b891dd88
35 changed files with 1109 additions and 11 deletions

View File

@@ -0,0 +1,29 @@
package io.papermc.paper.registry.event;
import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.NamedRegistryKeySetImpl;
import io.papermc.paper.registry.tag.Tag;
import io.papermc.paper.registry.tag.TagKey;
import net.minecraft.core.HolderSet;
import net.minecraft.resources.RegistryOps;
import org.bukkit.Keyed;
public record RegistryEntryAddEventImpl<T, B extends RegistryBuilder<T>>(
TypedKey<T> key,
B builder,
RegistryKey<T> registryKey,
Conversions conversions
) implements RegistryEntryAddEvent<T, B>, PaperLifecycleEvent {
@Override
public <V extends Keyed> Tag<V> getOrCreateTag(final TagKey<V> tagKey) {
final RegistryOps.RegistryInfo<Object> registryInfo = this.conversions.lookup().lookup(PaperRegistries.registryToNms(tagKey.registryKey())).orElseThrow();
final HolderSet.Named<?> tagSet = registryInfo.getter().getOrThrow(PaperRegistries.toNms(tagKey));
return new NamedRegistryKeySetImpl<>(tagKey, tagSet);
}
}

View File

@@ -0,0 +1,45 @@
package io.papermc.paper.registry.event;
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
import io.papermc.paper.registry.RegistryKey;
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<BootstrapContext, ? extends LifecycleEvent, ?>> eventTypes = new HashMap<>();
private final String name;
public RegistryEventMap(final String name) {
this.name = name;
}
@SuppressWarnings("unchecked")
public <T, E extends LifecycleEvent, ET extends LifecycleEventType<BootstrapContext, E, ?>> ET getOrCreate(final RegistryKey<T> registryKey, final BiFunction<? super RegistryKey<T>, ? super String, ET> eventTypeCreator) {
final ET eventType;
if (this.eventTypes.containsKey(registryKey)) {
eventType = (ET) this.eventTypes.get(registryKey);
} else {
eventType = eventTypeCreator.apply(registryKey, this.name);
this.eventTypes.put(registryKey, eventType);
}
return eventType;
}
@SuppressWarnings("unchecked")
public <T, E extends LifecycleEvent> LifecycleEventType<BootstrapContext, E, ?> getEventType(final RegistryKey<T> registryKey) {
return (LifecycleEventType<BootstrapContext, E, ?>) Objects.requireNonNull(this.eventTypes.get(registryKey), "No hook for " + registryKey);
}
public boolean hasHandlers(final RegistryKey<?> registryKey) {
final AbstractLifecycleEventType<?, ?, ?> type = ((AbstractLifecycleEventType<?, ?, ?>) this.eventTypes.get(registryKey));
return type != null && type.hasHandlers();
}
}

View File

@@ -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 {
public static RegistryEventTypeProviderImpl instance() {
return (RegistryEventTypeProviderImpl) RegistryEventTypeProvider.provider();
}
@Override
public <T, B extends RegistryBuilder<T>> RegistryEntryAddEventType<T, B> registryEntryAdd(final RegistryEventProvider<T, B> type) {
return PaperRegistryListenerManager.INSTANCE.getRegistryValueAddEventType(type);
}
@Override
public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryFreezeEvent<T, B>> registryFreeze(final RegistryEventProvider<T, B> type) {
return PaperRegistryListenerManager.INSTANCE.getRegistryFreezeEventType(type);
}
}

View File

@@ -0,0 +1,27 @@
package io.papermc.paper.registry.event;
import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.util.Conversions;
import io.papermc.paper.registry.set.NamedRegistryKeySetImpl;
import io.papermc.paper.registry.tag.Tag;
import io.papermc.paper.registry.tag.TagKey;
import net.minecraft.core.HolderSet;
import net.minecraft.resources.RegistryOps;
import org.bukkit.Keyed;
public record RegistryFreezeEventImpl<T, B extends RegistryBuilder<T>>(
RegistryKey<T> registryKey,
WritableRegistry<T, B> registry,
Conversions conversions
) implements RegistryFreezeEvent<T, B>, PaperLifecycleEvent {
@Override
public <V extends Keyed> Tag<V> getOrCreateTag(final TagKey<V> tagKey) {
final RegistryOps.RegistryInfo<Object> registryInfo = this.conversions.lookup().lookup(PaperRegistries.registryToNms(tagKey.registryKey())).orElseThrow();
final HolderSet.Named<?> tagSet = registryInfo.getter().getOrThrow(PaperRegistries.toNms(tagKey));
return new NamedRegistryKeySetImpl<>(tagKey, tagSet);
}
}

View File

@@ -0,0 +1,4 @@
@NullMarked
package io.papermc.paper.registry.event;
import org.jspecify.annotations.NullMarked;

View File

@@ -0,0 +1,37 @@
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.RegistryKey;
import io.papermc.paper.registry.event.RegistryEntryAddEvent;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class RegistryEntryAddEventTypeImpl<T, B extends RegistryBuilder<T>> extends PrioritizableLifecycleEventType<BootstrapContext, RegistryEntryAddEvent<T, B>, RegistryEntryAddConfiguration<T>> implements RegistryEntryAddEventType<T, B> {
public RegistryEntryAddEventTypeImpl(final RegistryKey<T> registryKey, final String eventName) {
super(registryKey + " / " + eventName, BootstrapContext.class);
}
@Override
public boolean blocksReloading(final BootstrapContext eventOwner) {
return false; // only runs once
}
@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.filter() == null || config.filter().test(event.key());
}
}

View File

@@ -0,0 +1,42 @@
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.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 java.util.function.Predicate;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.Nullable;
public class RegistryEntryAddHandlerConfiguration<T, B extends RegistryBuilder<T>> extends PrioritizedLifecycleEventHandlerConfigurationImpl<BootstrapContext, RegistryEntryAddEvent<T, B>> implements RegistryEntryAddConfiguration<T> {
private @Nullable Predicate<TypedKey<T>> filter;
public RegistryEntryAddHandlerConfiguration(final LifecycleEventHandler<? super RegistryEntryAddEvent<T, B>> handler, final AbstractLifecycleEventType<BootstrapContext, RegistryEntryAddEvent<T, B>, ?> eventType) {
super(handler, eventType);
}
@Contract(pure = true)
public @Nullable Predicate<TypedKey<T>> filter() {
return this.filter;
}
@Override
public RegistryEntryAddConfiguration<T> filter(final Predicate<TypedKey<T>> filter) {
this.filter = filter;
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();
}
}

View File

@@ -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.PrioritizableLifecycleEventType;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.event.RegistryEvent;
public final class RegistryLifecycleEventType<T, E extends RegistryEvent<T>> extends PrioritizableLifecycleEventType.Simple<BootstrapContext, E> {
public RegistryLifecycleEventType(final RegistryKey<T> registryKey, final String eventName) {
super(registryKey + " / " + eventName, BootstrapContext.class);
}
@Override
public boolean blocksReloading(final BootstrapContext eventOwner) {
return false; // only runs once
}
}

View File

@@ -0,0 +1,4 @@
@NullMarked
package io.papermc.paper.registry.event.type;
import org.jspecify.annotations.NullMarked;