From ffca39bcca649dbd652e70a0b5d2e9ef3021f168 Mon Sep 17 00:00:00 2001
From: Matyrobbrt
Date: Sat, 9 Nov 2024 14:35:44 +0200
Subject: [PATCH 1/3] Add registry context to `LootTableLoadEvent`
See #1625
---
.../ReloadableServerRegistries.java.patch | 2 +-
.../neoforged/neoforge/event/EventHooks.java | 6 ++--
.../neoforge/event/LootTableLoadEvent.java | 29 +++++++++++++++++--
.../resources/META-INF/accesstransformer.cfg | 1 +
.../neoforge/debug/loot/LootPoolTest.java | 6 ++--
5 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
index ff31d3b5cf..fd59dfd417 100644
--- a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
+++ b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
@@ -11,7 +11,7 @@
+ 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(rl, lootTable, (HolderLookup.Provider) p_336173_.lookupProvider);
+ if (value != null)
+ map.put(rl, value);
+ });
diff --git a/src/main/java/net/neoforged/neoforge/event/EventHooks.java b/src/main/java/net/neoforged/neoforge/event/EventHooks.java
index c5109000f3..1c71958c91 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(ResourceLocation name, LootTable table, HolderLookup.Provider registries) {
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 6c1cff856a..e09f4b9d0c 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,16 +31,36 @@
* 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 registries;
+ }
+
public ResourceLocation getName() {
- return this.name;
+ return name;
+ }
+
+ public ResourceKey getKey() {
+ if (this.key == null) {
+ this.key = ResourceKey.create(Registries.LOOT_TABLE, name);
+ }
+ return this.key;
}
public LootTable getTable() {
diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg
index a9634170b7..67400f327c 100644
--- a/src/main/resources/META-INF/accesstransformer.cfg
+++ b/src/main/resources/META-INF/accesstransformer.cfg
@@ -158,6 +158,7 @@ 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.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 fce7b70d4a..10773f8c91 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());
From 8618c046e03de7468d6611bfbf829f30a6182ebd Mon Sep 17 00:00:00 2001
From: Matyrobbrt
Date: Sat, 9 Nov 2024 15:23:38 +0200
Subject: [PATCH 2/3] Expose HLA and extract correctly
---
.../server/ReloadableServerRegistries.java.patch | 7 +++++--
.../net/neoforged/neoforge/common/CommonHooks.java | 13 +++++++++++++
src/main/resources/META-INF/accesstransformer.cfg | 2 ++
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
index fd59dfd417..8b362eb690 100644
--- a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
+++ b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
@@ -1,7 +1,10 @@
--- a/net/minecraft/server/ReloadableServerRegistries.java
+++ b/net/minecraft/server/ReloadableServerRegistries.java
-@@ -61,8 +_,16 @@
+@@ -59,10 +_,19 @@
+ ) {
+ return CompletableFuture.supplyAsync(
() -> {
++ var provider = net.neoforged.neoforge.common.CommonHooks.extractLookupProvider(p_336173_);
WritableRegistry writableregistry = new MappedRegistry<>(p_335741_.registryKey(), Lifecycle.experimental());
Map map = new HashMap<>();
+ Map> optionalMap = new HashMap<>();
@@ -11,7 +14,7 @@
+ 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, (HolderLookup.Provider) p_336173_.lookupProvider);
++ if (value instanceof LootTable lootTable) value = (T) net.neoforged.neoforge.event.EventHooks.loadLootTable(rl, lootTable, provider);
+ 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 d81c78914c..a25ecbbe6b 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/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg
index 67400f327c..38bf188b44 100644
--- a/src/main/resources/META-INF/accesstransformer.cfg
+++ b/src/main/resources/META-INF/accesstransformer.cfg
@@ -159,6 +159,8 @@ 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
From ff4d83fd8949ee62394a4edeeb693bd2a98158a2 Mon Sep 17 00:00:00 2001
From: Matyrobbrt
Date: Wed, 4 Dec 2024 23:28:07 +0200
Subject: [PATCH 3/3] Reimplement patch
---
.../minecraft/server/ReloadableServerRegistries.java.patch | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/patches/net/minecraft/server/ReloadableServerRegistries.java.patch b/patches/net/minecraft/server/ReloadableServerRegistries.java.patch
index 7fb8e44291..6ef1590a62 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(rl, lootTable, provider);
+ if (value != null)
+ map.put(rl, value);
+ });