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 extends Registry
return null;
}
+ /**
+ * Extracts a {@link HolderLookup.Provider} from the given {@code ops}, if possible.
+ *
+ * @throws IllegalArgumentException if the ops were not created using a {@linkplain HolderLookup.Provider}
+ */
+ public static HolderLookup.Provider extractLookupProvider(RegistryOps> 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());