From 17ebc6419d349a5af9dd4bf3b0daa1e884e15e85 Mon Sep 17 00:00:00 2001 From: Matyrobbrt <65940752+Matyrobbrt@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:13:25 +0200 Subject: [PATCH] Add registry context to `LootTableLoadEvent` (#1677) --- .../ReloadableServerRegistries.java.patch | 5 ++-- .../neoforge/common/CommonHooks.java | 13 +++++++++ .../neoforged/neoforge/event/EventHooks.java | 6 +++-- .../neoforge/event/LootTableLoadEvent.java | 27 ++++++++++++++++++- .../resources/META-INF/accesstransformer.cfg | 3 +++ .../neoforge/debug/loot/LootPoolTest.java | 6 ++--- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch index 7fb8e442918..dd58fa5f8d0 100644 --- a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch +++ b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch @@ -1,16 +1,17 @@ --- a/net/minecraft/server/ReloadableServerRegistries.java +++ b/net/minecraft/server/ReloadableServerRegistries.java -@@ -61,7 +_,15 @@ +@@ -61,7 +_,16 @@ () -> { WritableRegistry writableregistry = new MappedRegistry<>(p_335741_.registryKey(), Lifecycle.experimental()); Map map = new HashMap<>(); - SimpleJsonResourceReloadListener.scanDirectory(p_335893_, p_335741_.registryKey(), p_336173_, p_335741_.codec(), map); ++ var provider = net.neoforged.neoforge.common.CommonHooks.extractLookupProvider(p_336173_); + Map> optionalMap = new HashMap<>(); + SimpleJsonResourceReloadListener.scanDirectoryWithOptionalValues(p_335893_, p_335741_.registryKey(), p_336173_, p_335741_.conditionalCodec(), optionalMap); + optionalMap.forEach((rl, optionalEntry) -> { + optionalEntry.ifPresent(entry -> p_335741_.idSetter().accept(entry, rl)); + T value = optionalEntry.orElse(p_335741_.defaultValue()); -+ if (value instanceof LootTable lootTable) value = (T) net.neoforged.neoforge.event.EventHooks.loadLootTable(rl, lootTable); ++ if (value instanceof LootTable lootTable) value = (T) net.neoforged.neoforge.event.EventHooks.loadLootTable(provider, rl, lootTable); + if (value != null) + map.put(rl, value); + }); diff --git a/src/main/java/net/neoforged/neoforge/common/CommonHooks.java b/src/main/java/net/neoforged/neoforge/common/CommonHooks.java index f99ab9d2d11..788d95651a7 100644 --- a/src/main/java/net/neoforged/neoforge/common/CommonHooks.java +++ b/src/main/java/net/neoforged/neoforge/common/CommonHooks.java @@ -65,6 +65,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.network.syncher.EntityDataSerializer; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -1524,6 +1525,18 @@ public static RegistryLookup resolveLookup(ResourceKey ops) { + if (ops.lookupProvider instanceof RegistryOps.HolderLookupAdapter hla) { + return hla.lookupProvider; + } + throw new IllegalArgumentException("Registry ops has lookup provider " + ops.lookupProvider + " which is not a HolderLookupAdapter"); + } + /** * Creates a {@link UseOnContext} for {@link net.minecraft.core.dispenser.DispenseItemBehavior dispense behavior}. * diff --git a/src/main/java/net/neoforged/neoforge/event/EventHooks.java b/src/main/java/net/neoforged/neoforge/event/EventHooks.java index 7529a767d18..31da1af28b6 100644 --- a/src/main/java/net/neoforged/neoforge/event/EventHooks.java +++ b/src/main/java/net/neoforged/neoforge/event/EventHooks.java @@ -26,6 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup.RegistryLookup; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; @@ -688,10 +689,11 @@ public static boolean onProjectileImpact(Projectile projectile, HitResult ray) { * which maps to an empty {@link Optional} in {@link LootDataType#deserialize(ResourceLocation, DynamicOps, Object)} */ @Nullable - public static LootTable loadLootTable(ResourceLocation name, LootTable table) { + @ApiStatus.Internal + public static LootTable loadLootTable(HolderLookup.Provider registries, ResourceLocation name, LootTable table) { if (table == LootTable.EMPTY) // Empty table has a null name, and shouldn't be modified anyway. return null; - LootTableLoadEvent event = new LootTableLoadEvent(name, table); + LootTableLoadEvent event = new LootTableLoadEvent(registries, name, table); if (NeoForge.EVENT_BUS.post(event).isCanceled() || event.getTable() == LootTable.EMPTY) return null; return event.getTable(); diff --git a/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java b/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java index 6c1cff856a8..c2ce46dde98 100644 --- a/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java +++ b/src/main/java/net/neoforged/neoforge/event/LootTableLoadEvent.java @@ -6,12 +6,17 @@ package net.neoforged.neoforge.event; import java.util.Objects; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.storage.loot.LootTable; import net.neoforged.bus.api.Event; import net.neoforged.bus.api.ICancellableEvent; import net.neoforged.fml.LogicalSide; import net.neoforged.neoforge.common.NeoForge; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; /** * Fired when a {@link LootTable} is loaded from JSON. @@ -26,18 +31,38 @@ * only on the {@linkplain LogicalSide#SERVER logical server}.

*/ public class LootTableLoadEvent extends Event implements ICancellableEvent { + private final HolderLookup.Provider registries; private final ResourceLocation name; private LootTable table; - public LootTableLoadEvent(ResourceLocation name, LootTable table) { + @Nullable + private ResourceKey key; + + @ApiStatus.Internal + public LootTableLoadEvent(HolderLookup.Provider registries, ResourceLocation name, LootTable table) { + this.registries = registries; this.name = name; this.table = table; } + /** + * {@return a lookup provider that can be used to access registries} + */ + public HolderLookup.Provider getRegistries() { + return this.registries; + } + public ResourceLocation getName() { return this.name; } + public ResourceKey getKey() { + if (this.key == null) { + this.key = ResourceKey.create(Registries.LOOT_TABLE, name); + } + return this.key; + } + public LootTable getTable() { return this.table; } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 7fc1a010d21..78b501f4e70 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -126,6 +126,9 @@ public net.minecraft.gametest.framework.GameTestHelper testInfo # testInfo public net.minecraft.gametest.framework.GameTestInfo sequences # sequences public net.minecraft.gametest.framework.GameTestSequence (Lnet/minecraft/gametest/framework/GameTestInfo;)V # protected net.minecraft.resources.RegistryOps (Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/resources/RegistryOps$RegistryInfoLookup;)V # constructor +public net.minecraft.resources.RegistryOps lookupProvider +public net.minecraft.resources.RegistryOps$HolderLookupAdapter +public net.minecraft.resources.RegistryOps$HolderLookupAdapter lookupProvider public net.minecraft.resources.ResourceLocation validNamespaceChar(C)Z # validNamespaceChar protected net.minecraft.server.MinecraftServer nextTickTimeNanos # nextTickTimeNanos public net.minecraft.server.MinecraftServer$ReloadableResources diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/loot/LootPoolTest.java b/tests/src/main/java/net/neoforged/neoforge/debug/loot/LootPoolTest.java index a9fddd9cd38..27e918bc6f9 100644 --- a/tests/src/main/java/net/neoforged/neoforge/debug/loot/LootPoolTest.java +++ b/tests/src/main/java/net/neoforged/neoforge/debug/loot/LootPoolTest.java @@ -92,7 +92,7 @@ static void pinkConcreteLootTableCanceled(final DynamicTest test, final Registra event.getLookupProvider())); NeoForge.EVENT_BUS.addListener((final LootTableLoadEvent event) -> { - if (event.getName().equals(lootTableToUse.location())) { + if (event.getKey() == lootTableToUse) { event.setCanceled(true); } }); @@ -131,7 +131,7 @@ static void orangeConcreteLootTableReplaced(final DynamicTest test, final Regist event.getLookupProvider())); NeoForge.EVENT_BUS.addListener((final LootTableLoadEvent event) -> { - if (event.getName().equals(lootTableToUse.location())) { + if (event.getKey() == lootTableToUse) { LootPoolSingletonContainer.Builder entry = LootItem.lootTableItem(Items.BLUE_CONCRETE); LootPool.Builder pool = LootPool.lootPool().setRolls(ConstantValue.exactly(1)).add(entry).when(ExplosionCondition.survivesExplosion()); event.setTable(new LootTable.Builder().withPool(pool).build()); @@ -172,7 +172,7 @@ static void yellowConcreteLootTableAppended(final DynamicTest test, final Regist event.getLookupProvider())); NeoForge.EVENT_BUS.addListener((final LootTableLoadEvent event) -> { - if (event.getName().equals(lootTableToUse.location())) { + if (event.getKey() == lootTableToUse) { LootPoolSingletonContainer.Builder entry = LootItem.lootTableItem(Items.YELLOW_CONCRETE); LootPool.Builder pool = LootPool.lootPool().setRolls(ConstantValue.exactly(1)).add(entry).when(ExplosionCondition.survivesExplosion()); event.getTable().addPool(pool.build());