From c20296d1064110ac44de221a29b9d0f418b2059f Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Tue, 29 Sep 2026 00:29:25 -0400 Subject: [PATCH] Modded server registries - Modded platform hands the running server to registry access - Tile reader is built from the running server - Registry test covers startup, reload and shutdown of dynamic registries --- .../iris/modded/ModdedEngineBootstrap.java | 5 +-- .../arcane/iris/modded/ModdedPlatform.java | 14 +----- .../iris/modded/ModdedTileParityTest.java | 2 +- .../iris/modded/NativeRegistryAccessTest.java | 45 +++++++++++++++++-- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedEngineBootstrap.java b/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedEngineBootstrap.java index 517c8da0a..e972e70eb 100644 --- a/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedEngineBootstrap.java +++ b/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedEngineBootstrap.java @@ -391,10 +391,7 @@ public final class ModdedEngineBootstrap { BlockDataMergeSupport.StateMerger previousMerger = BlockDataMergeSupport.bindPlatformMerger(new NativeStateMerger(ModdedBlockResolution.BLOCKS)::merge); rollback.add(() -> BlockDataMergeSupport.restorePlatformMerger(previousMerger)); - NativeTileReader nativeTileReader = new NativeTileReader(() -> { - NativeModdedServer server = boundLoader.currentServer(); - return server == null ? null : server.registryAccess(); - }); + NativeTileReader nativeTileReader = NativeTileReader.forServer(boundLoader::currentServer); TileData.TileReader previousTileReader = TileData.bindPlatformReader(in -> ModdedTileData.wrap(nativeTileReader.read(in))); rollback.add(() -> TileData.restorePlatformReader(previousTileReader)); diff --git a/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedPlatform.java b/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedPlatform.java index ba3f55d9d..2a488b3d5 100644 --- a/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedPlatform.java +++ b/adapters/modded-common/src/main/java/art/arcane/iris/modded/ModdedPlatform.java @@ -38,8 +38,6 @@ import art.arcane.iris.spi.PlatformScheduler; import art.arcane.iris.spi.PlatformStructureHooks; import art.arcane.volmlib.nativelib.terrain.NativeWorld; -import net.minecraft.core.HolderLookup; - import java.io.File; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -64,7 +62,7 @@ public final class ModdedPlatform implements IrisPlatform { this.loader = loader; this.registries = new ModdedRegistries( new NativeRegistryAccess(new NativeRegistryAccess.Configuration( - ModdedPlatform::nativeRegistries, ModdedPlatform::reloadableRegistries, + ModdedEngineBootstrap::currentServer, ModdedRegistries::warnNotReady)), ModdedPlatform::generationRegistry); this.scheduler = new ModdedScheduler(); @@ -72,16 +70,6 @@ public final class ModdedPlatform implements IrisPlatform { this.biomeWriter = new ModdedBiomeWriter(new NativeBiomeRegistry(ModdedEngineBootstrap::currentServer, "minecraft:plains")); } - private static HolderLookup.Provider nativeRegistries() { - NativeModdedServer server = ModdedEngineBootstrap.currentServer(); - return server == null ? null : server.registryAccess(); - } - - private static HolderLookup.Provider reloadableRegistries() { - NativeModdedServer server = ModdedEngineBootstrap.currentServer(); - return server == null ? null : server.reloadableRegistries(); - } - public static void errorSink(Consumer sink) { ERROR_SINK = sink; } diff --git a/adapters/modded-common/src/test/java/art/arcane/iris/modded/ModdedTileParityTest.java b/adapters/modded-common/src/test/java/art/arcane/iris/modded/ModdedTileParityTest.java index 3a948b43a..7fbb2b7ee 100644 --- a/adapters/modded-common/src/test/java/art/arcane/iris/modded/ModdedTileParityTest.java +++ b/adapters/modded-common/src/test/java/art/arcane/iris/modded/ModdedTileParityTest.java @@ -41,7 +41,7 @@ public class ModdedTileParityTest { SharedConstants.tryDetectVersion(); Bootstrap.bootStrap(); registries = RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY); - NativeTileReader nativeTileReader = new NativeTileReader(() -> null); + NativeTileReader nativeTileReader = NativeTileReader.forServer(() -> null); TileData.bindPlatformReader(in -> ModdedTileData.wrap(nativeTileReader.read(in))); TileData.bindPlatformFactory(ModdedTileData::fromProperties); } diff --git a/adapters/modded-common/src/test/java/art/arcane/iris/modded/NativeRegistryAccessTest.java b/adapters/modded-common/src/test/java/art/arcane/iris/modded/NativeRegistryAccessTest.java index 5c9ebd510..af9790899 100644 --- a/adapters/modded-common/src/test/java/art/arcane/iris/modded/NativeRegistryAccessTest.java +++ b/adapters/modded-common/src/test/java/art/arcane/iris/modded/NativeRegistryAccessTest.java @@ -1,20 +1,31 @@ package art.arcane.iris.modded; import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeRegistryAccess; +import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedServer; import art.arcane.volmlib.nativelib.terrain.NativeBlockProperty; import net.minecraft.SharedConstants; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.Bootstrap; +import net.minecraft.server.MinecraftServer; import org.junit.BeforeClass; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class NativeRegistryAccessTest { @BeforeClass @@ -25,7 +36,7 @@ public class NativeRegistryAccessTest { @Test public void statePropertiesPreserveTypesDefaultsAndSharedGroups() { - NativeRegistryAccess access = new NativeRegistryAccess(new NativeRegistryAccess.Configuration(() -> null, () -> null, message -> {})); + NativeRegistryAccess access = new NativeRegistryAccess(new NativeRegistryAccess.Configuration(() -> null, message -> {})); Map> properties = access.blockStateProperties(); assertSame(properties.get("minecraft:stone"), properties.get("minecraft:dirt")); @@ -41,7 +52,7 @@ public class NativeRegistryAccessTest { @Test public void staticRegistriesResolveWithoutAnActiveServerAndDynamicReadsStayEmpty() { List warnings = new ArrayList<>(); - NativeRegistryAccess access = new NativeRegistryAccess(new NativeRegistryAccess.Configuration(() -> null, () -> null, warnings::add)); + NativeRegistryAccess access = new NativeRegistryAccess(new NativeRegistryAccess.Configuration(() -> null, warnings::add)); assertEquals("minecraft:diamond_sword", access.item("DIAMOND SWORD").key()); assertEquals("creature", access.entity("minecraft:cow").spawnCategory()); @@ -49,6 +60,34 @@ public class NativeRegistryAccessTest { assertTrue(access.biomeKeys().isEmpty()); assertTrue(access.structureKeys().isEmpty()); assertTrue(access.enchantmentKeys().isEmpty()); - assertEquals(List.of("biome", "structure", "enchantment"), warnings); + assertTrue(access.lootTableKeys().isEmpty()); + assertEquals(List.of("biome", "structure", "enchantment", "loot table"), warnings); + } + + @Test + public void dynamicRegistriesFollowServerStartupReloadAndShutdown() { + AtomicReference activeServer = new AtomicReference<>(); + List warnings = new ArrayList<>(); + NativeRegistryAccess access = new NativeRegistryAccess(new NativeRegistryAccess.Configuration(activeServer::get, warnings::add)); + assertTrue(access.lootTableKeys().isEmpty()); + + MinecraftServer server = mock(MinecraftServer.class, RETURNS_DEEP_STUBS); + when(server.registryAccess().lookupOrThrow(Registries.BIOME).listElementIds()) + .thenAnswer(invocation -> Stream.of(ResourceKey.create(Registries.BIOME, Identifier.parse("example:biome")))); + when(server.reloadableRegistries().lookup().lookupOrThrow(Registries.LOOT_TABLE).listElementIds()) + .thenAnswer(invocation -> Stream.of(ResourceKey.create(Registries.LOOT_TABLE, Identifier.parse("example:initial")))); + activeServer.set(NativeModdedServer.fromHandle(server)); + + assertEquals(List.of("example:biome"), access.biomeKeys()); + assertEquals(List.of("example:initial"), access.lootTableKeys()); + HolderLookup.Provider reloadedRegistries = mock(HolderLookup.Provider.class, RETURNS_DEEP_STUBS); + when(reloadedRegistries.lookupOrThrow(Registries.LOOT_TABLE).listElementIds()) + .thenAnswer(invocation -> Stream.of(ResourceKey.create(Registries.LOOT_TABLE, Identifier.parse("example:reloaded")))); + when(server.reloadableRegistries().lookup()).thenReturn(reloadedRegistries); + assertEquals(List.of("example:reloaded"), access.lootTableKeys()); + activeServer.set(null); + assertTrue(access.biomeKeys().isEmpty()); + assertTrue(access.lootTableKeys().isEmpty()); + assertEquals(List.of("loot table", "biome", "loot table"), warnings); } }