[VERY VERY VERY BAD IDEA]

This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-20 04:24:42 -04:00
1 parent f0e7fea13b
commit 2fa0853e42
892 files changed
+13482 -53554

No files matched your search

@@ -1,5 +1,9 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedChunkGenerator;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeContainerLoot;
import art.arcane.volmlib.util.math.RNG;
import com.mojang.serialization.Codec;
import net.minecraft.SharedConstants;
@@ -66,13 +70,13 @@ public class IrisModdedBlockEntityParityTest {
BlockPos position = new BlockPos(3, 70, 5);
chunk.setBlockState(position, Blocks.CHEST.defaultBlockState(), 0);
IrisModdedChunkGenerator.createDefaultBlockEntity(chunk, position, Blocks.CHEST.defaultBlockState());
NativeModdedChunkGenerator.createDefaultBlockEntity(chunk, position, Blocks.CHEST.defaultBlockState());
BlockEntity blockEntity = chunk.getBlockEntity(position);
assertNotNull(blockEntity);
assertTrue(blockEntity instanceof Container);
Container container = (Container) blockEntity;
ModdedLootApplier.fillContainer(container, List.of(new ItemStack(Items.DIAMOND)), new RNG(17L));
NativeContainerLoot.fillContainer(container, List.of(new ItemStack(Items.DIAMOND)), new RNG(17L), message -> {});
assertEquals(1, countItem(container, Items.DIAMOND));
CompoundTag saved = blockEntity.saveWithoutMetadata(registries);
ChestBlockEntity restored = new ChestBlockEntity(position, Blocks.CHEST.defaultBlockState());
@@ -94,9 +98,9 @@ public class IrisModdedBlockEntityParityTest {
chunk.setBlockState(signPosition, signState, 0);
chunk.setBlockState(spawnerPosition, spawnerState, 0);
chunk.setBlockState(bannerPosition, bannerState, 0);
IrisModdedChunkGenerator.createDefaultBlockEntity(chunk, signPosition, signState);
IrisModdedChunkGenerator.createDefaultBlockEntity(chunk, spawnerPosition, spawnerState);
IrisModdedChunkGenerator.createDefaultBlockEntity(chunk, bannerPosition, bannerState);
NativeModdedChunkGenerator.createDefaultBlockEntity(chunk, signPosition, signState);
NativeModdedChunkGenerator.createDefaultBlockEntity(chunk, spawnerPosition, spawnerState);
NativeModdedChunkGenerator.createDefaultBlockEntity(chunk, bannerPosition, bannerState);
assertTrue(chunk.getBlockEntity(signPosition) instanceof SignBlockEntity);
assertTrue(chunk.getBlockEntity(spawnerPosition) instanceof SpawnerBlockEntity);
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeSpawnTableMerger;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import net.minecraft.util.random.Weighted;
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedHeightmaps;
import net.minecraft.util.Mth;
import net.minecraft.util.SimpleBitStorage;
import org.junit.Test;
@@ -1,6 +1,6 @@
package art.arcane.iris.modded;
import art.arcane.iris.nativegen.NativeStructureLocateResults;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureLocateResults;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
@@ -9,7 +9,7 @@ import art.arcane.iris.generation.runtime.Engine;
import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.mantle.flag.MantleFlag;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import art.arcane.volmlib.nativelib.terrain.NativeBlockPoint;
import net.minecraft.server.Bootstrap;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -40,31 +40,31 @@ public class IrisModdedStructureParityTest {
@Test
public void surfaceBiomeFastPathBeginsAboveTheCaveSwitch() {
assertFalse(IrisModdedBiomeSource.isGuaranteedSurfaceBiome(-2, -256));
assertTrue(IrisModdedBiomeSource.isGuaranteedSurfaceBiome(-1, -256));
assertFalse(IrisModdedBiomeSource.isGuaranteedSurfaceBiome(10, 0));
assertTrue(IrisModdedBiomeSource.isGuaranteedSurfaceBiome(11, 0));
assertFalse(ModdedBiomePolicy.isGuaranteedSurfaceBiome(-2, -256));
assertTrue(ModdedBiomePolicy.isGuaranteedSurfaceBiome(-1, -256));
assertFalse(ModdedBiomePolicy.isGuaranteedSurfaceBiome(10, 0));
assertTrue(ModdedBiomePolicy.isGuaranteedSurfaceBiome(11, 0));
}
@Test
public void visibleCaveBiomeBeginsEightBlocksBelowTheSurface() {
assertFalse(IrisModdedBiomeSource.isUnderground(93, 100));
assertTrue(IrisModdedBiomeSource.isUnderground(92, 100));
assertTrue(IrisModdedBiomeSource.isUnderground(-20, 100));
assertFalse(ModdedBiomePolicy.isUnderground(93, 100));
assertTrue(ModdedBiomePolicy.isUnderground(92, 100));
assertTrue(ModdedBiomePolicy.isUnderground(-20, 100));
}
@Test
public void monumentBiomeCubeUsesSurfaceBiomesAtShiftedSeaLevel() {
assertTrue(IrisModdedBiomeSource.isMonumentSurfaceBiomeQuery(50, 29, -256, 306));
assertFalse(IrisModdedBiomeSource.isMonumentSurfaceBiomeQuery(51, 29, -256, 306));
assertFalse(IrisModdedBiomeSource.isMonumentSurfaceBiomeQuery(50, 28, -256, 306));
assertTrue(ModdedBiomePolicy.isMonumentSurfaceBiomeQuery(50, 29, -256, 306));
assertFalse(ModdedBiomePolicy.isMonumentSurfaceBiomeQuery(51, 29, -256, 306));
assertFalse(ModdedBiomePolicy.isMonumentSurfaceBiomeQuery(50, 28, -256, 306));
}
@Test
public void strongholdRingSearchSamplesOneQuartColumnPerChunk() {
assertEquals(4, IrisModdedBiomeSource.horizontalBiomeSearchQuartStep(0, 112));
assertEquals(1, IrisModdedBiomeSource.horizontalBiomeSearchQuartStep(1, 112));
assertEquals(1, IrisModdedBiomeSource.horizontalBiomeSearchQuartStep(0, 111));
assertEquals(4, ModdedBiomePolicy.horizontalBiomeSearchQuartStep(0, 112));
assertEquals(1, ModdedBiomePolicy.horizontalBiomeSearchQuartStep(1, 112));
assertEquals(1, ModdedBiomePolicy.horizontalBiomeSearchQuartStep(0, 111));
}
@Test
@@ -86,9 +86,9 @@ public class IrisModdedStructureParityTest {
@Test
public void reconciledSpawnUsesOriginAndClampedSurfaceHeight() {
assertEquals(new BlockPos(0, 73, 0), ModdedEngineBootstrap.reconciledSpawnPosition(73, -64, 384));
assertEquals(new BlockPos(0, -63, 0), ModdedEngineBootstrap.reconciledSpawnPosition(-100, -64, 384));
assertEquals(new BlockPos(0, 318, 0), ModdedEngineBootstrap.reconciledSpawnPosition(400, -64, 384));
assertEquals(new NativeBlockPoint(0, 73, 0), ModdedEngineBootstrap.reconciledSpawnPosition(73, -64, 384));
assertEquals(new NativeBlockPoint(0, -63, 0), ModdedEngineBootstrap.reconciledSpawnPosition(-100, -64, 384));
assertEquals(new NativeBlockPoint(0, 318, 0), ModdedEngineBootstrap.reconciledSpawnPosition(400, -64, 384));
}
@Test
@@ -102,7 +102,7 @@ public class IrisModdedStructureParityTest {
^ ((long) blockY * 132897987541L)
^ ((long) blockZ * 42317861L);
assertEquals(expected, IrisModdedBiomeSource.biomeResolutionSeed(worldSeed, blockX, blockY, blockZ));
assertEquals(expected, ModdedBiomePolicy.biomeResolutionSeed(worldSeed, blockX, blockY, blockZ));
}
@Test
@@ -114,19 +114,19 @@ public class IrisModdedStructureParityTest {
assertEquals(
ModdedWorldgenIds.biomeRef("pack", "Upper", "Aurora"),
IrisModdedBiomeSource.customBiomeRef("pack", upper, "Aurora")
ModdedBiomePolicy.customBiomeRef("pack", upper, "Aurora")
);
assertFalse(IrisModdedBiomeSource.customBiomeRef("pack", host, "Aurora")
.equals(IrisModdedBiomeSource.customBiomeRef("pack", upper, "Aurora")));
assertFalse(ModdedBiomePolicy.customBiomeRef("pack", host, "Aurora")
.equals(ModdedBiomePolicy.customBiomeRef("pack", upper, "Aurora")));
}
@Test
public void temporaryNaturalBiomeAnswersAreNotMemoized() {
Engine engine = mock(Engine.class);
when(engine.answersFromNaturalTerrain(12, -8)).thenReturn(true);
assertFalse(IrisModdedBiomeSource.isBiomeCacheable(engine, 12, -8));
assertFalse(ModdedBiomePolicy.isBiomeCacheable(engine, 12, -8));
when(engine.answersFromNaturalTerrain(12, -8)).thenReturn(false);
assertTrue(IrisModdedBiomeSource.isBiomeCacheable(engine, 12, -8));
assertTrue(ModdedBiomePolicy.isBiomeCacheable(engine, 12, -8));
}
@Test
@@ -162,16 +162,16 @@ public class IrisModdedStructureParityTest {
public void structureStateRejectsBiomesOutsideThePackContract() {
Set<String> generated = Set.of("minecraft:deep_ocean", "minecraft:dark_forest");
assertTrue(IrisModdedBiomeSource.isGeneratedBiomeKey("minecraft:deep_ocean", generated));
assertTrue(IrisModdedBiomeSource.isGeneratedBiomeKey("MINECRAFT:DARK_FOREST", generated));
assertFalse(IrisModdedBiomeSource.isGeneratedBiomeKey("minecraft:desert", generated));
assertFalse(IrisModdedBiomeSource.isGeneratedBiomeKey(null, generated));
assertTrue(ModdedBiomePolicy.isGeneratedBiomeKey("minecraft:deep_ocean", generated));
assertTrue(ModdedBiomePolicy.isGeneratedBiomeKey("MINECRAFT:DARK_FOREST", generated));
assertFalse(ModdedBiomePolicy.isGeneratedBiomeKey("minecraft:desert", generated));
assertFalse(ModdedBiomePolicy.isGeneratedBiomeKey(null, generated));
}
@Test
public void structureBiomeContractRejectsAnEmptyConfiguredSet() {
IllegalStateException error = assertThrows(IllegalStateException.class,
() -> IrisModdedBiomeSource.requireConfiguredStructureBiomeKeys(Set.of()));
() -> ModdedBiomePolicy.requireConfiguredStructureBiomeKeys(Set.of()));
assertEquals("Iris has no configured structure biomes", error.getMessage());
}
@@ -180,7 +180,7 @@ public class IrisModdedStructureParityTest {
public void structureBiomeContractPreservesConfiguredKeysDuringBootstrap() {
Set<String> configured = Set.of("minecraft:deep_ocean", "minecraft:dark_forest");
assertSame(configured, IrisModdedBiomeSource.requireConfiguredStructureBiomeKeys(configured));
assertSame(configured, ModdedBiomePolicy.requireConfiguredStructureBiomeKeys(configured));
}
@Test
@@ -1,94 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class MainWorldServiceInstanceRootTest {
@Test
public void universeOptionIsReadInBothArgumentForms() {
assertEquals("worlds", MainWorldService.commandLineOption(
List.of("nogui", "--universe", "worlds"), "universe"));
assertEquals("worlds", MainWorldService.commandLineOption(
List.of("--universe=worlds", "nogui"), "universe"));
assertEquals("survival", MainWorldService.commandLineOption(
List.of("--universe", "worlds", "--world", "survival"), "world"));
}
@Test
public void missingOrValuelessOptionsResolveToNull() {
assertNull(MainWorldService.commandLineOption(List.of("nogui"), "universe"));
assertNull(MainWorldService.commandLineOption(List.of(), "world"));
assertNull(MainWorldService.commandLineOption(List.of("nogui", "--world"), "world"));
}
@Test
public void universeRootDefaultsToTheInstanceRootAndHonorsTheOption() throws IOException {
Path instanceRoot = Files.createTempDirectory("iris-instance");
Path elsewhere = Files.createTempDirectory("iris-elsewhere");
assertEquals(instanceRoot, MainWorldService.universeRoot(instanceRoot, null));
assertEquals(instanceRoot, MainWorldService.universeRoot(instanceRoot, ""));
assertEquals(instanceRoot.resolve("worlds"), MainWorldService.universeRoot(instanceRoot, "worlds"));
assertEquals(elsewhere, MainWorldService.universeRoot(instanceRoot, elsewhere.toString()));
}
@Test
public void worldRootResolvesInsideTheUniverse() throws IOException {
Path universe = Files.createTempDirectory("iris-universe");
Path world = Files.createDirectory(universe.resolve("survival"));
assertEquals(world.toAbsolutePath().normalize(),
MainWorldService.resolveWorldRoot(universe, "survival"));
}
@Test
public void worldRootRefusesToEscapeTheUniverse() throws IOException {
Path universe = Files.createTempDirectory("iris-universe");
Files.createDirectory(universe.resolve("survival"));
IOException escaped = assertThrows(IOException.class,
() -> MainWorldService.resolveWorldRoot(universe, "../survival"));
IOException empty = assertThrows(IOException.class,
() -> MainWorldService.resolveWorldRoot(universe, "."));
assertTrue(escaped.getMessage().contains("Unsafe world name"));
assertTrue(empty.getMessage().contains("Unsafe world name"));
}
@Test
public void worldRootReportsMissingDirectoriesAsTheRecoverableCase() throws IOException {
Path universe = Files.createTempDirectory("iris-universe");
MainWorldService.MissingWorldRootException missingWorld = assertThrows(
MainWorldService.MissingWorldRootException.class,
() -> MainWorldService.resolveWorldRoot(universe, "survival"));
MainWorldService.MissingWorldRootException missingUniverse = assertThrows(
MainWorldService.MissingWorldRootException.class,
() -> MainWorldService.resolveWorldRoot(universe.resolve("absent"), "survival"));
assertTrue(missingWorld.getMessage().contains("world directory does not exist"));
assertEquals(universe.resolve("survival").toAbsolutePath().normalize(), missingWorld.path());
assertTrue(missingUniverse.getMessage().contains("universe directory does not exist"));
assertEquals(universe.resolve("absent"), missingUniverse.path());
}
@Test
public void unsafeWorldNameIsNotTreatedAsAMissingWorldRoot() throws IOException {
Path universe = Files.createTempDirectory("iris-universe");
IOException escaped = assertThrows(IOException.class,
() -> MainWorldService.resolveWorldRoot(universe, "../survival"));
assertFalse(escaped instanceof MainWorldService.MissingWorldRootException);
}
}
@@ -0,0 +1,103 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.terrain.NativeBiomeSourceAccess;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class ModdedBiomePolicyTest {
@Test
public void registryOrderAndHolderIdentitySurviveThePolicyBoundaryAndRefreshOnRepoint() {
BiomeToken ocean = new BiomeToken("minecraft:ocean");
BiomeToken forest = new BiomeToken("minecraft:forest");
List<BiomeToken> entries = new ArrayList<>(List.of(forest, ocean));
AtomicReference<Set<String>> configured = new AtomicReference<>(Set.of(ocean.key(), forest.key()));
ModdedBiomePolicy<BiomeToken, Object> policy = policy(entries, configured);
List<BiomeToken> first = policy.orderedPossibleBiomes();
assertSame(forest, first.getFirst());
assertSame(ocean, first.getLast());
assertEquals(first, new ArrayList<>(policy.possibleBiomes()));
BiomeToken desert = new BiomeToken("minecraft:desert");
entries.clear();
entries.add(desert);
configured.set(Set.of(desert.key()));
assertSame(first, policy.orderedPossibleBiomes());
policy.clearCaches();
assertEquals(1L, policy.packGeneration());
assertEquals(1, policy.orderedPossibleBiomes().size());
assertSame(desert, policy.orderedPossibleBiomes().getFirst());
}
@Test
public void missingRequiredStructureBiomesFailBeforePublishingAPartialSet() {
AtomicReference<Set<String>> configured = new AtomicReference<>(Set.of("example:missing"));
ModdedBiomePolicy<BiomeToken, Object> policy = policy(
new ArrayList<>(List.of(new BiomeToken("minecraft:plains"))), configured);
IllegalStateException failure = assertThrows(IllegalStateException.class, policy::possibleBiomes);
assertTrue(failure.getMessage().contains("example:missing"));
}
private static ModdedBiomePolicy<BiomeToken, Object> policy(List<BiomeToken> entries,
AtomicReference<Set<String>> configured) {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(entries));
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> null, () -> null, engine -> false,
configured::get, engine -> Set.of(), () -> 0L));
return policy;
}
private record BiomeToken(String key) {
}
private record Access(List<BiomeToken> entries) implements NativeBiomeSourceAccess<BiomeToken, Object>,
NativeBiomeSourceAccess.RegistryView<BiomeToken> {
@Override
public RegistryView<BiomeToken> registry() {
return this;
}
@Override
public Set<BiomeToken> serializedBiomes() {
throw new AssertionError("A loaded registry must not use serialized biomes");
}
@Override
public BiomeToken serializedNoise(int x, int y, int z, Object sampler) {
throw new AssertionError("Listing biome holders must not sample terrain");
}
@Override
public String holderKey(BiomeToken holder) {
return holder.key();
}
@Override
public void forEach(Consumer<? super BiomeToken> consumer) {
entries.forEach(consumer);
}
@Override
public BiomeToken lookup(String key) {
for (BiomeToken biome : entries) {
if (biome.key().equals(key)) {
return biome;
}
}
return null;
}
}
}
@@ -1,6 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.iris.spi.PlatformBiome;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeBiomeRegistry;
import art.arcane.volmlib.nativelib.terrain.NativeBiome;
import org.junit.Test;
import java.util.List;
@@ -12,7 +13,7 @@ import static org.junit.Assert.assertTrue;
public class ModdedBiomeWriterCacheTest {
@Test
public void unavailableServerFallsBackToBiomeIdZero() {
ModdedBiomeWriter writer = new ModdedBiomeWriter(() -> null);
ModdedBiomeWriter writer = new ModdedBiomeWriter(new NativeBiomeRegistry(() -> null, "minecraft:plains"));
assertEquals(0, writer.biomeIdFor("minecraft:plains"));
assertEquals(0, writer.biomeIdFor("minecraft:plains"));
@@ -20,10 +21,10 @@ public class ModdedBiomeWriterCacheTest {
@Test
public void unavailableServerYieldsAnEmptyMutableBiomeList() {
ModdedBiomeWriter writer = new ModdedBiomeWriter(() -> null);
ModdedBiomeWriter writer = new ModdedBiomeWriter(new NativeBiomeRegistry(() -> null, "minecraft:plains"));
List<PlatformBiome> first = writer.allBiomes();
List<PlatformBiome> second = writer.allBiomes();
List<NativeBiome> first = writer.allBiomes();
List<NativeBiome> second = writer.allBiomes();
assertTrue(first.isEmpty());
assertNotSame("callers must never share the writer cache instance", first, second);
@@ -19,23 +19,33 @@
package art.arcane.iris.modded;
import net.minecraft.core.Direction;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.StairBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.junit.Test;
import org.junit.BeforeClass;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedBlockBreakHandlerTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void exactMatchingIncludesPropertiesWhileTypeMatchingDoesNot() {
BlockState north = Blocks.OAK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH);
BlockState east = Blocks.OAK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.EAST);
ModdedBlockState north = ModdedBlockState.of(Blocks.OAK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH), null);
ModdedBlockState east = ModdedBlockState.of(Blocks.OAK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.EAST), null);
assertTrue(ModdedBlockBreakHandler.matchesState(north, north, true));
assertFalse(ModdedBlockBreakHandler.matchesState(north, east, true));
assertTrue(ModdedBlockBreakHandler.matchesState(north, east, false));
assertFalse(ModdedBlockBreakHandler.matchesState(north, Blocks.COBBLESTONE.defaultBlockState(), false));
assertFalse(ModdedBlockBreakHandler.matchesState(north, ModdedBlockState.of(Blocks.COBBLESTONE.defaultBlockState(), null), false));
}
}
@@ -1,8 +1,10 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeBlockProperties;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import art.arcane.iris.generation.decoration.DecoratorPlatformHooks;
import art.arcane.iris.generation.decoration.IrisSpeleothems;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
import art.arcane.volmlib.util.hunk.Hunk;
import net.minecraft.SharedConstants;
@@ -35,38 +37,38 @@ public class ModdedBlockResolutionContractTest {
@Test
public void getOrNullReturnsNullForUnknownKey() {
assertNull(ModdedBlockResolution.getOrNull(UNKNOWN));
assertNull(ModdedBlockResolution.getOrNull(UNKNOWN, true));
assertNull(ModdedBlockResolution.BLOCKS.getOrNull(UNKNOWN));
assertNull(ModdedBlockResolution.BLOCKS.getOrNull(UNKNOWN, true));
}
@Test
public void getFallsBackToAirForUnknownKey() {
ModdedBlockState state = ModdedBlockResolution.get(UNKNOWN);
ModdedBlockState state = ModdedBlockResolution.BLOCKS.get(UNKNOWN);
assertNotNull(state);
assertEquals(Blocks.AIR, state.handle().getBlock());
}
@Test
public void getOrNullResolvesKnownKeyWithProperties() {
ModdedBlockState state = ModdedBlockResolution.getOrNull("minecraft:oak_log[axis=x]", true);
ModdedBlockState state = ModdedBlockResolution.BLOCKS.getOrNull("minecraft:oak_log[axis=x]", true);
assertNotNull(state);
assertEquals(Blocks.OAK_LOG, state.handle().getBlock());
}
@Test
public void unknownPropertyFallsBackToDefaultState() {
ModdedBlockState state = ModdedBlockResolution.getOrNull("minecraft:oak_log[not_a_property=x]", true);
ModdedBlockState state = ModdedBlockResolution.BLOCKS.getOrNull("minecraft:oak_log[not_a_property=x]", true);
assertNotNull(state);
assertEquals(Blocks.OAK_LOG, state.handle().getBlock());
}
@Test
public void cactusPlacementRequiresNativeCactusSupport() {
assertTrue(ModdedBlockResolution.canPlaceOnto(Blocks.CACTUS, Blocks.CACTUS));
assertTrue(ModdedBlockResolution.canPlaceOnto(Blocks.CACTUS, Blocks.SAND));
assertTrue(ModdedBlockResolution.canPlaceOnto(Blocks.CACTUS, Blocks.RED_SAND));
assertFalse(ModdedBlockResolution.canPlaceOnto(Blocks.CACTUS, Blocks.STONE));
assertTrue(ModdedBlockResolution.isDecorant(Blocks.CACTUS.defaultBlockState()));
assertTrue(NativeBlockProperties.canPlaceOnto(Blocks.CACTUS, Blocks.CACTUS));
assertTrue(NativeBlockProperties.canPlaceOnto(Blocks.CACTUS, Blocks.SAND));
assertTrue(NativeBlockProperties.canPlaceOnto(Blocks.CACTUS, Blocks.RED_SAND));
assertFalse(NativeBlockProperties.canPlaceOnto(Blocks.CACTUS, Blocks.STONE));
assertTrue(NativeBlockProperties.isDecorant(Blocks.CACTUS.defaultBlockState()));
}
@Test
@@ -74,11 +76,11 @@ public class ModdedBlockResolutionContractTest {
for (Block block : new Block[]{Blocks.SUGAR_CANE, Blocks.GRASS_BLOCK, Blocks.DIRT, Blocks.COARSE_DIRT,
Blocks.PODZOL, Blocks.MYCELIUM, Blocks.ROOTED_DIRT, Blocks.MOSS_BLOCK, Blocks.PALE_MOSS_BLOCK,
Blocks.MUD, Blocks.MUDDY_MANGROVE_ROOTS, Blocks.SAND, Blocks.RED_SAND, Blocks.SUSPICIOUS_SAND}) {
assertTrue(block.toString(), ModdedBlockResolution.canPlaceOnto(Blocks.SUGAR_CANE, block));
assertTrue(block.toString(), NativeBlockProperties.canPlaceOnto(Blocks.SUGAR_CANE, block));
}
for (Block block : new Block[]{Blocks.STONE, Blocks.GRAVEL, Blocks.CLAY, Blocks.DIRT_PATH,
Blocks.FARMLAND, Blocks.AIR, Blocks.WATER}) {
assertFalse(block.toString(), ModdedBlockResolution.canPlaceOnto(Blocks.SUGAR_CANE, block));
assertFalse(block.toString(), NativeBlockProperties.canPlaceOnto(Blocks.SUGAR_CANE, block));
}
}
@@ -87,11 +89,11 @@ public class ModdedBlockResolutionContractTest {
for (Block block : new Block[]{Blocks.SULFUR_SPIKE, Blocks.POINTED_DRIPSTONE}) {
for (SpeleothemThickness thickness : SpeleothemThickness.values()) {
assertEquals(thickness == SpeleothemThickness.TIP,
ModdedBlockResolution.isUpdatable(block.defaultBlockState()
NativeBlockProperties.isUpdatable(block.defaultBlockState()
.setValue(SpeleothemBlock.THICKNESS, thickness)));
}
}
assertFalse(ModdedBlockResolution.isUpdatable(Blocks.STONE.defaultBlockState()));
assertFalse(NativeBlockProperties.isUpdatable(Blocks.STONE.defaultBlockState()));
}
@Test
public void nativeSpikesUseModdedSupportFaces() {
@@ -100,14 +102,14 @@ public class ModdedBlockResolutionContractTest {
try {
for (String material : new String[]{"minecraft:sulfur_spike", "minecraft:pointed_dripstone"}) {
for (boolean upward : new boolean[]{true, false}) {
Hunk<PlatformBlockState> output = Hunk.newArrayHunk(1, 3, 1);
PlatformBlockState spike = ModdedBlockResolution.get(material
Hunk<NativeBlockState> output = Hunk.newArrayHunk(1, 3, 1);
NativeBlockState spike = ModdedBlockResolution.BLOCKS.get(material
+ "[vertical_direction=" + (upward ? "up" : "down") + ",thickness=tip]");
int supportY = upward ? 0 : 2;
output.set(0, 1, 0, spike);
output.set(0, supportY, 0, ModdedBlockResolution.get("minecraft:stone_slab[type=top]"));
output.set(0, supportY, 0, ModdedBlockResolution.BLOCKS.get("minecraft:stone_slab[type=top]"));
assertEquals(upward, IrisSpeleothems.isSupported(spike, output, 0, 0, 1));
output.set(0, supportY, 0, ModdedBlockResolution.get("minecraft:stone_slab[type=bottom]"));
output.set(0, supportY, 0, ModdedBlockResolution.BLOCKS.get("minecraft:stone_slab[type=bottom]"));
assertEquals(!upward, IrisSpeleothems.isSupported(spike, output, 0, 0, 1));
}
}
@@ -32,6 +32,7 @@ import static org.junit.Assert.assertTrue;
*/
public class ModdedClientPackageIsolationTest {
private static final String CLIENT_MINECRAFT = "net/minecraft/client/";
private static final String CLIENT_NATIVE = "art/arcane/volmlib/nativelib/minecraft26_2/client/";
private static final String CLIENT_IRIS = "art/arcane/iris/client/";
private static final List<String> GUARDED_PACKAGES = List.of(
"art/arcane/iris/modded",
@@ -56,6 +57,9 @@ public class ModdedClientPackageIsolationTest {
if (bytecode.contains(CLIENT_MINECRAFT)) {
violations.add(name + " -> " + CLIENT_MINECRAFT);
}
if (bytecode.contains(CLIENT_NATIVE)) {
violations.add(name + " -> " + CLIENT_NATIVE);
}
if (bytecode.contains(CLIENT_IRIS)) {
violations.add(name + " -> " + CLIENT_IRIS);
}
@@ -74,8 +78,8 @@ public class ModdedClientPackageIsolationTest {
*/
@Test
public void scanDetectsClientReferencesInAKnownClientClass() throws IOException, URISyntaxException {
Path visionScreen = classesRoot().resolve("art/arcane/iris/client/IrisVisionScreen.class");
assertTrue("IrisVisionScreen.class missing from " + visionScreen, Files.isRegularFile(visionScreen));
Path visionScreen = classesRoot().resolve("art/arcane/volmlib/nativelib/minecraft26_2/client/NativeClientScreen.class");
assertTrue("NativeClientScreen.class missing from " + visionScreen, Files.isRegularFile(visionScreen));
assertTrue("scan needle no longer matches a known client class",
readAsLatin1(visionScreen).contains(CLIENT_MINECRAFT));
}
@@ -89,7 +93,7 @@ public class ModdedClientPackageIsolationTest {
}
private static Path classesRoot() throws URISyntaxException {
String anchor = "/art/arcane/iris/modded/ModdedMixinFlags.class";
String anchor = "/art/arcane/iris/modded/ModdedMixinAudit.class";
URL located = ModdedClientPackageIsolationTest.class.getResource(anchor);
assertNotNull("compiled main classes are not on the test classpath as files", located);
assertEquals("expected a directory classpath entry, got " + located, "file", located.getProtocol());
@@ -0,0 +1,37 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityLoot;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import org.junit.Test;
import java.util.Set;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ModdedDeathLootTest {
@Test
public void unboundEntityRetainsItsNativeBaseLoot() {
NativeEntityLoot entity = mock(NativeEntityLoot.class);
when(entity.world()).thenReturn(mock(NativeWorld.class));
when(entity.tags()).thenReturn(Set.of("unrelated"));
assertFalse(ModdedDeathLoot.replaceBaseLoot(entity));
}
@Test
public void malformedBindingStillSuppressesNativeBaseLoot() {
NativeEntityLoot entity = mock(NativeEntityLoot.class);
when(entity.world()).thenReturn(mock(NativeWorld.class));
when(entity.tags()).thenReturn(Set.of("iris_loot|invalid"));
assertTrue(ModdedDeathLoot.replaceBaseLoot(entity));
}
@Test
public void entityOutsideServerWorldRetainsNativeBaseLoot() {
NativeEntityLoot entity = mock(NativeEntityLoot.class);
assertFalse(ModdedDeathLoot.replaceBaseLoot(entity));
assertFalse(ModdedDeathLoot.replaceBaseLoot(null));
}
}
@@ -1,12 +1,12 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import art.arcane.iris.modded.api.ModdedBlockData;
import art.arcane.iris.modded.api.ModdedCustomContentRegistry;
import art.arcane.iris.modded.api.ModdedDataProvider;
import art.arcane.iris.modded.api.ModdedDataType;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
import net.minecraft.SharedConstants;
import net.minecraft.resources.Identifier;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.StairBlock;
@@ -23,7 +23,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class ModdedDeferredBlockParityTest {
private static final Identifier BLOCK_ID = Identifier.parse("iris_deferred_test:oak_stairs");
private static final String BLOCK_ID = "iris_deferred_test:oak_stairs";
@BeforeClass
public static void bootstrapMinecraftRegistries() {
@@ -34,7 +34,7 @@ public class ModdedDeferredBlockParityTest {
@Test
public void deferredProviderStateCarriesPlacementMetadataThroughMutation() {
ModdedBlockState resolved = ModdedBlockResolution.getOrNull(
ModdedBlockState resolved = ModdedBlockResolution.BLOCKS.getOrNull(
"iris_deferred_test:oak_stairs[facing=north,half=bottom]");
assertNotNull(resolved);
@@ -42,12 +42,12 @@ public class ModdedDeferredBlockParityTest {
assertEquals("iris_deferred_test:oak_stairs[facing=north,half=bottom]", resolved.deferredPlacementKey());
assertEquals(Blocks.OAK_STAIRS, resolved.handle().getBlock());
PlatformBlockState mutated = resolved.withProperty("facing", "west");
NativeBlockState mutated = resolved.withProperty("facing", "west");
assertTrue(mutated.isCustom());
assertEquals(resolved.deferredPlacementKey(), mutated.deferredPlacementKey());
assertEquals("west", ((ModdedBlockState) mutated).handle().getValue(StairBlock.FACING).getName());
PlatformBlockState base = mutated.placementBaseState();
NativeBlockState base = mutated.placementBaseState();
assertFalse(base.isCustom());
assertEquals(Blocks.OAK_STAIRS, ((ModdedBlockState) base).handle().getBlock());
}
@@ -59,18 +59,18 @@ public class ModdedDeferredBlockParityTest {
}
@Override
public Collection<Identifier> getTypes(ModdedDataType type) {
public Collection<String> getTypes(ModdedDataType type) {
return type == ModdedDataType.BLOCK ? List.of(BLOCK_ID) : List.of();
}
@Override
public boolean isValidProvider(Identifier id, ModdedDataType type) {
public boolean isValidProvider(String id, ModdedDataType type) {
return type == ModdedDataType.BLOCK && BLOCK_ID.equals(id);
}
@Override
public ModdedBlockData getBlockData(Identifier blockId, Map<String, String> state) {
return ModdedBlockData.deferred(Blocks.OAK_STAIRS.defaultBlockState());
public ModdedBlockData getBlockData(String blockId, Map<String, String> state) {
return ModdedBlockData.deferred(ModdedBlockState.of(Blocks.OAK_STAIRS.defaultBlockState(), null));
}
}
}
@@ -1,27 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ModdedDimensionManagerTeleportTest {
@Test
public void blockCoordinatesUseFloorAcrossZeroAndChunkBoundaries() {
assertEquals(0, ModdedTeleportBounds.blockCoordinate(0.99D));
assertEquals(-1, ModdedTeleportBounds.blockCoordinate(-0.01D));
assertEquals(-17, ModdedTeleportBounds.blockCoordinate(-16.01D));
assertEquals(16, ModdedTeleportBounds.blockCoordinate(16D));
}
@Test
public void teleportYReservesSupportFeetAndHeadSpace() {
assertEquals(-63, ModdedTeleportBounds.clampY(-64, 320, -100));
assertEquals(318, ModdedTeleportBounds.clampY(-64, 320, 400));
assertEquals(72, ModdedTeleportBounds.clampY(-64, 320, 72));
}
@Test(expected = IllegalArgumentException.class)
public void teleportYRejectsWorldsWithoutThreeVerticalBlocks() {
ModdedTeleportBounds.clampY(0, 2, 1);
}
}
@@ -18,8 +18,10 @@
package art.arcane.iris.modded;
import art.arcane.iris.platform.bukkit.nms.datapack.DataVersion;
import art.arcane.iris.platform.bukkit.nms.datapack.IDataFixer;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeWorldInspection.Dimension;
import art.arcane.iris.pack.datapack.DataVersion;
import art.arcane.iris.pack.datapack.IDataFixer;
import art.arcane.iris.generation.terrain.IrisDimension;
import art.arcane.iris.generation.terrain.IrisDimensionRuntimeContract;
import art.arcane.iris.generation.terrain.IrisDimensionTypeOptions;
@@ -152,8 +154,8 @@ public class ModdedDimensionTypeParityTest {
.ceiling(TRUE);
IrisDimension dimension = dimension("runtime_contract", IrisEnvironment.CUSTOM,
-128, 384, 384, options);
WorldCheckDimensionContract.DimensionContract expected = WorldCheckDimensionContract.expectedDimensionContract(dimension);
WorldCheckDimensionContract.DimensionContract fallback = new WorldCheckDimensionContract.DimensionContract(
Dimension expected = WorldCheckDimensionContract.expectedDimensionContract(dimension);
Dimension fallback = new Dimension(
-256, 768, 512, 1D, 0F, true, false, false, 0);
assertTrue(WorldCheckDimensionContract.matchesDimensionContract(-128, 512, expected, expected));
@@ -1,6 +1,10 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityBehavior;
import org.junit.Test;
import org.junit.Before;
import art.arcane.volmlib.nativelib.modded.EntityBehaviorTags;
import java.util.HashSet;
import java.util.Set;
@@ -9,27 +13,32 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedEntityAwarenessTest {
@Before
public void configureEntityTags() {
NativeEntityBehavior.bind(new EntityBehaviorTags("iris_non_persistent", "iris_unaware"));
}
@Test
public void unawareConfigurationAddsThePartialAiTag() {
Set<String> tags = new HashSet<>();
ModdedEntityAwareness.configureTags(tags, false);
NativeEntityBehavior.configureAwarenessTags(tags, false);
assertFalse(ModdedEntityAwareness.isAware(tags));
assertFalse(NativeEntityBehavior.isAware(tags));
}
@Test
public void awareConfigurationRemovesThePartialAiTag() {
Set<String> tags = new HashSet<>();
ModdedEntityAwareness.configureTags(tags, false);
NativeEntityBehavior.configureAwarenessTags(tags, false);
ModdedEntityAwareness.configureTags(tags, true);
NativeEntityBehavior.configureAwarenessTags(tags, true);
assertTrue(ModdedEntityAwareness.isAware(tags));
assertTrue(NativeEntityBehavior.isAware(tags));
}
@Test
public void mobsAreAwareWithoutAnIrisTag() {
assertTrue(ModdedEntityAwareness.isAware(Set.of()));
assertTrue(NativeEntityBehavior.isAware(Set.of()));
}
}
@@ -1,6 +1,10 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityBehavior;
import org.junit.Test;
import org.junit.Before;
import art.arcane.volmlib.nativelib.modded.EntityBehaviorTags;
import java.util.HashSet;
import java.util.Set;
@@ -9,31 +13,36 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ModdedEntityPersistenceTest {
@Before
public void configureEntityTags() {
NativeEntityBehavior.bind(new EntityBehaviorTags("iris_non_persistent", "iris_unaware"));
}
@Test
public void generatedNonPersistentEntityIsExcludedFromVanillaSaves() {
Set<String> tags = new HashSet<>();
ModdedEntityPersistence.configureTags(tags, false);
NativeEntityBehavior.configurePersistenceTags(tags, false);
assertFalse(ModdedEntityPersistence.shouldSave(tags, true));
assertFalse(NativeEntityBehavior.shouldSave(tags, true));
}
@Test
public void positivePersistenceRemovesTheSaveExclusion() {
Set<String> tags = new HashSet<>();
ModdedEntityPersistence.configureTags(tags, false);
NativeEntityBehavior.configurePersistenceTags(tags, false);
ModdedEntityPersistence.configureTags(tags, true);
NativeEntityBehavior.configurePersistenceTags(tags, true);
assertTrue(ModdedEntityPersistence.shouldSave(tags, true));
assertTrue(NativeEntityBehavior.shouldSave(tags, true));
}
@Test
public void interceptionNeverOverridesVanillaSaveRejection() {
Set<String> tags = new HashSet<>();
ModdedEntityPersistence.configureTags(tags, true);
NativeEntityBehavior.configurePersistenceTags(tags, true);
assertFalse(ModdedEntityPersistence.shouldSave(tags, false));
assertFalse(NativeEntityBehavior.shouldSave(tags, false));
}
}
@@ -1,5 +1,12 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityRuntime;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedPlatformWorld;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedLoader;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntitySpawns;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.world.entity.IrisEntity;
import art.arcane.volmlib.util.math.RNG;
@@ -46,7 +53,7 @@ public class ModdedEntitySpawnDifficultyTest {
public void sharedPlatformSpawnReturnsFalseForPeacefulHostiles() {
ServerLevel level = mock(ServerLevel.class);
when(level.getDifficulty()).thenReturn(Difficulty.PEACEFUL);
ModdedPlatform platform = new ModdedPlatform(mock(ModdedLoader.class));
ModdedPlatform platform = new ModdedPlatform(mock(NativeModdedLoader.class));
assertFalse(platform.spawnEntity(new ModdedPlatformWorld(level), "minecraft:zombie", 0.5, 80, 0.5));
@@ -63,7 +70,7 @@ public class ModdedEntitySpawnDifficultyTest {
when(chunks.getChunkNow(anyInt(), anyInt())).thenReturn(mock(LevelChunk.class));
IrisEntity configured = new IrisEntity().setType("zombie").setSpawnEffectRiseOutOfGround(false);
assertNull(ModdedEntitySpawner.spawn(mock(Engine.class), configured, level, 0, 80, 0, new RNG(1L)));
assertNull(ModdedEntitySpawner.spawn(mock(Engine.class), configured, new NativeEntityRuntime(level), 0, 80, 0, new RNG(1L)));
verify(level, never()).addFreshEntity(any(Entity.class));
verify(level, never()).enabledFeatures();
@@ -80,7 +87,7 @@ public class ModdedEntitySpawnDifficultyTest {
continue;
}
EntityType<?> type = spy(registered);
assertNull(ModdedEntitySpawner.spawnNative(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL));
assertNull(NativeEntitySpawns.spawn(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL));
verify(type, never()).spawn(level, BlockPos.ZERO, EntitySpawnReason.NATURAL);
rejected++;
}
@@ -98,7 +105,7 @@ public class ModdedEntitySpawnDifficultyTest {
EntityType<?> type = spy(BuiltInRegistries.ENTITY_TYPE.getValue(Identifier.parse("minecraft:" + key)));
doReturn(created).when(type).spawn(level, BlockPos.ZERO, EntitySpawnReason.NATURAL);
assertSame(key, created, ModdedEntitySpawner.spawnNative(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL));
assertSame(key, created, NativeEntitySpawns.spawn(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL));
verify(type).spawn(level, BlockPos.ZERO, EntitySpawnReason.NATURAL);
}
}
@@ -113,7 +120,7 @@ public class ModdedEntitySpawnDifficultyTest {
when(level.getDifficulty()).thenReturn(difficulty);
doReturn(created).when(type).spawn(level, BlockPos.ZERO, EntitySpawnReason.NATURAL);
assertSame(created, ModdedEntitySpawner.spawnNative(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL));
assertSame(created, NativeEntitySpawns.spawn(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL));
verify(type).spawn(level, BlockPos.ZERO, EntitySpawnReason.NATURAL);
}
}
@@ -127,6 +134,6 @@ public class ModdedEntitySpawnDifficultyTest {
doThrow(failure).when(type).spawn(level, BlockPos.ZERO, EntitySpawnReason.NATURAL);
assertSame(failure, assertThrows(IllegalStateException.class,
() -> ModdedEntitySpawner.spawnNative(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL)));
() -> NativeEntitySpawns.spawn(type, level, BlockPos.ZERO, EntitySpawnReason.NATURAL)));
}
}
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityRuntime;
import art.arcane.iris.world.entity.IrisEffect;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Mob;
@@ -22,9 +24,9 @@ public class ModdedEntitySpawnerParityTest {
public void collisionCheckUsesPaperInclusiveIntegerDimensions() {
Set<BlockPos> checked = new HashSet<>();
boolean clear = ModdedEntitySpawner.isAreaClearForSpawn(
10, 64, 20, 0.6F, 1.95F, position -> {
checked.add(position);
boolean clear = NativeEntityRuntime.isAreaClearForSpawn(
10, 64, 20, 0.6F, 1.95F, (x, y, z) -> {
checked.add(new BlockPos(x, y, z));
return true;
});
@@ -35,8 +37,8 @@ public class ModdedEntitySpawnerParityTest {
@Test
public void collisionCheckCoversWideEntityVolumeAndRejectsOneBlockedCell() {
AtomicInteger checked = new AtomicInteger();
boolean fullyClear = ModdedEntitySpawner.isAreaClearForSpawn(
0, 10, 0, 4F, 3.2F, position -> {
boolean fullyClear = NativeEntityRuntime.isAreaClearForSpawn(
0, 10, 0, 4F, 3.2F, (x, y, z) -> {
checked.incrementAndGet();
return true;
});
@@ -46,8 +48,8 @@ public class ModdedEntitySpawnerParityTest {
BlockPos obstruction = new BlockPos(2, 12, -2);
boolean clear = ModdedEntitySpawner.isAreaClearForSpawn(
0, 10, 0, 4F, 3.2F, position -> !position.equals(obstruction));
boolean clear = NativeEntityRuntime.isAreaClearForSpawn(
0, 10, 0, 4F, 3.2F, (x, y, z) -> !new BlockPos(x, y, z).equals(obstruction));
assertFalse(clear);
}
@@ -61,19 +63,19 @@ public class ModdedEntitySpawnerParityTest {
}
}
assertTrue(ModdedEntitySpawner.allNeighborChunksLoaded(5, -2,
assertTrue(NativeEntityRuntime.allNeighborChunksLoaded(5, -2,
(x, z) -> loaded.contains(pack(x, z))));
loaded.remove(pack(4, -3));
assertFalse(ModdedEntitySpawner.allNeighborChunksLoaded(5, -2,
assertFalse(NativeEntityRuntime.allNeighborChunksLoaded(5, -2,
(x, z) -> loaded.contains(pack(x, z))));
}
@Test
public void onlyAiFalseUsesVanillaNoAi() {
assertFalse(ModdedEntitySpawner.shouldDisableAi(true));
assertTrue(ModdedEntitySpawner.shouldDisableAi(false));
assertFalse(NativeEntityRuntime.shouldDisableAi(true));
assertTrue(NativeEntityRuntime.shouldDisableAi(false));
}
@Test
@@ -137,16 +139,16 @@ public class ModdedEntitySpawnerParityTest {
assertEquals(47, expected.size());
for (Map.Entry<String, EntitySpawnReason> entry : expected.entrySet()) {
assertEquals(entry.getKey(), entry.getValue(), ModdedEntitySpawner.reasonFor(entry.getKey()));
assertEquals(entry.getKey(), entry.getValue(), ModdedEntitySpawner.reasonFor(entry.getKey().toLowerCase()));
assertEquals(entry.getKey(), entry.getValue(), NativeEntityRuntime.reasonFor(entry.getKey()));
assertEquals(entry.getKey(), entry.getValue(), NativeEntityRuntime.reasonFor(entry.getKey().toLowerCase()));
}
}
@Test
public void invalidConfiguredSpawnReasonIntentionallyDefaultsToNatural() {
assertEquals(EntitySpawnReason.NATURAL, ModdedEntitySpawner.reasonFor(null));
assertEquals(EntitySpawnReason.NATURAL, ModdedEntitySpawner.reasonFor(""));
assertEquals(EntitySpawnReason.NATURAL, ModdedEntitySpawner.reasonFor("not_a_spawn_reason"));
assertEquals(EntitySpawnReason.NATURAL, NativeEntityRuntime.reasonFor(null));
assertEquals(EntitySpawnReason.NATURAL, NativeEntityRuntime.reasonFor(""));
assertEquals(EntitySpawnReason.NATURAL, NativeEntityRuntime.reasonFor("not_a_spawn_reason"));
}
@Test
@@ -20,7 +20,7 @@ package art.arcane.iris.modded;
import art.arcane.volmlib.util.collection.KSet;
import art.arcane.volmlib.util.json.JSONObject;
import art.arcane.iris.platform.bukkit.nms.datapack.v1217.DataFixerV1217;
import art.arcane.iris.pack.datapack.v1217.DataFixerV1217;
import art.arcane.iris.world.history.GenerationEpochContractFactory;
import art.arcane.iris.world.history.GenerationRegistryContract;
import art.arcane.iris.world.history.GenerationRegistryContractFactory;
@@ -1,11 +1,17 @@
package art.arcane.iris.modded;
import net.minecraft.server.MinecraftServer;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedServer;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedChunkGenerator;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import java.lang.reflect.Field;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.junit.Test;
import org.junit.BeforeClass;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import java.util.List;
@@ -20,67 +26,95 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ModdedGenerationBootstrapBindingTest {
@BeforeClass
public static void bootstrap() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void publishedLevelRequiresCurrentGeneratorIdentity() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel level = mock(ServerLevel.class);
IrisModdedChunkGenerator generator = generator();
NativeModdedServer server = mock(NativeModdedServer.class);
NativeWorld level = world();
ServerChunkCache chunkSource = mock(ServerChunkCache.class);
when(server.getLevel(Level.OVERWORLD)).thenReturn(level);
when(level.dimension()).thenReturn(Level.OVERWORLD);
when(level.getChunkSource()).thenReturn(chunkSource);
when(chunkSource.getGenerator()).thenReturn(generator);
when(server.world("minecraft:overworld")).thenReturn(level);
when(level.name()).thenReturn("minecraft:overworld");
when(((ServerLevel) level.nativeHandle()).getChunkSource()).thenReturn(chunkSource);
ChunkGenerator nativeGenerator = (ChunkGenerator) generator.nativeGenerator();
when(chunkSource.getGenerator()).thenReturn(nativeGenerator);
assertSame(level, generator.requirePublishedLevel(server, Level.OVERWORLD));
assertSame(level, generator.requirePublishedLevel(server, "minecraft:overworld"));
ChunkGenerator otherGenerator = mock(ChunkGenerator.class);
when(chunkSource.getGenerator()).thenReturn(otherGenerator);
IllegalStateException mismatch = assertThrows(IllegalStateException.class,
() -> generator.requirePublishedLevel(server, Level.OVERWORLD));
() -> generator.requirePublishedLevel(server, "minecraft:overworld"));
assertTrue(mismatch.getMessage().contains("does not use Iris generator"));
}
@Test
public void publishedLevelRejectsMissingServerAndWorld() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
IrisModdedChunkGenerator generator = generator();
IllegalStateException missingServer = assertThrows(IllegalStateException.class,
() -> generator.requirePublishedLevel(null, Level.OVERWORLD));
() -> generator.requirePublishedLevel(null, "minecraft:overworld"));
assertTrue(missingServer.getMessage().contains("server is unavailable"));
MinecraftServer server = mock(MinecraftServer.class);
NativeModdedServer server = mock(NativeModdedServer.class);
IllegalStateException missingWorld = assertThrows(IllegalStateException.class,
() -> generator.requirePublishedLevel(server, Level.OVERWORLD));
assertTrue(missingWorld.getMessage().contains("no published ServerLevel"));
() -> generator.requirePublishedLevel(server, "minecraft:overworld"));
assertTrue(missingWorld.getMessage().contains("no published NativeWorld"));
}
@Test
public void staleSnapshotResolvesOnlyCanonicalOverworldOwnedByGenerator() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel overworld = mock(ServerLevel.class);
IrisModdedChunkGenerator generator = generator();
NativeModdedServer server = mock(NativeModdedServer.class);
NativeWorld overworld = world();
ServerChunkCache chunkSource = mock(ServerChunkCache.class);
when(server.getLevel(Level.OVERWORLD)).thenReturn(overworld);
when(overworld.getChunkSource()).thenReturn(chunkSource);
when(chunkSource.getGenerator()).thenReturn(generator);
when(server.overworld()).thenReturn(overworld);
when(((ServerLevel) overworld.nativeHandle()).getChunkSource()).thenReturn(chunkSource);
ChunkGenerator nativeGenerator = (ChunkGenerator) generator.nativeGenerator();
when(chunkSource.getGenerator()).thenReturn(nativeGenerator);
assertSame(overworld, generator.resolveBoundLevel(server, List.of()));
ChunkGenerator otherGenerator = mock(ChunkGenerator.class);
when(chunkSource.getGenerator()).thenReturn(otherGenerator);
assertNull(generator.resolveBoundLevel(server, List.of()));
verify(server, never()).getLevel(Level.NETHER);
verify(server, never()).world("minecraft:the_nether");
}
@Test
public void dynamicLevelStillResolvesFromSnapshotWithoutCanonicalLookup() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel dynamicLevel = mock(ServerLevel.class);
IrisModdedChunkGenerator generator = generator();
NativeModdedServer server = mock(NativeModdedServer.class);
NativeWorld dynamicLevel = world();
ServerChunkCache chunkSource = mock(ServerChunkCache.class);
when(dynamicLevel.getChunkSource()).thenReturn(chunkSource);
when(chunkSource.getGenerator()).thenReturn(generator);
when(((ServerLevel) dynamicLevel.nativeHandle()).getChunkSource()).thenReturn(chunkSource);
ChunkGenerator nativeGenerator = (ChunkGenerator) generator.nativeGenerator();
when(chunkSource.getGenerator()).thenReturn(nativeGenerator);
assertSame(dynamicLevel, generator.resolveBoundLevel(server, List.of(dynamicLevel)));
verify(server, never()).getLevel(Level.OVERWORLD);
verify(server, never()).overworld();
}
private static NativeWorld world() {
NativeWorld world = mock(NativeWorld.class);
when(world.nativeHandle()).thenReturn(mock(ServerLevel.class));
return world;
}
private static IrisModdedChunkGenerator generator() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
NativeModdedChunkGenerator<?, ?, ?> nativeGenerator = mock(NativeModdedChunkGenerator.class, CALLS_REAL_METHODS);
try {
Field field = IrisModdedChunkGenerator.class.getDeclaredField("nativeGenerator");
field.setAccessible(true);
field.set(generator, nativeGenerator);
return generator;
} catch (ReflectiveOperationException failure) {
throw new AssertionError(failure);
}
}
}
@@ -0,0 +1,72 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeFeatureBiomeSource;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.generation.terrain.IrisDimension;
import art.arcane.iris.structure.nativegen.IrisImportedFeatureControl;
import org.junit.Test;
import org.junit.BeforeClass;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ModdedImportedFeatureStageTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void disabledFeaturesRecheckAfterPackRepointAndRuntimeEviction() {
NativeFeatureBiomeSource source = mock(NativeFeatureBiomeSource.class);
when(source.packGeneration()).thenReturn(1L);
IrisImportedFeatureControl control = spy(new IrisImportedFeatureControl());
IrisDimension dimension = new IrisDimension().setImportedFeatures(control);
Engine engine = mock(Engine.class);
when(engine.getDimension()).thenReturn(dimension);
when(engine.getCacheID()).thenReturn(7);
ModdedImportedFeatureStage stage = new ModdedImportedFeatureStage(source);
stage.prepare(engine);
stage.prepare(engine);
verify(control, times(1)).shouldGenerateFeatures();
when(source.packGeneration()).thenReturn(2L);
stage.prepare(engine);
verify(control, times(2)).shouldGenerateFeatures();
stage.evictRuntime(7);
stage.prepare(engine);
verify(control, times(3)).shouldGenerateFeatures();
stage.invalidate();
stage.prepare(engine);
verify(control, times(4)).shouldGenerateFeatures();
verify(source, never()).orderedPossibleBiomes();
assertFalse(stage.active());
}
@Test
public void closingRuntimeDoesNotBuildFeatureTables() {
NativeFeatureBiomeSource source = mock(NativeFeatureBiomeSource.class);
Engine engine = mock(Engine.class);
when(engine.isClosing()).thenReturn(true);
ModdedImportedFeatureStage stage = new ModdedImportedFeatureStage(source);
stage.prepare(engine);
stage.prepareWithoutWaiting(engine);
verify(source, never()).packGeneration();
verify(engine, never()).getDimension();
assertFalse(stage.active());
}
}
@@ -1,71 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class ModdedLevelDataAttachmentTest {
@Test
public void detectsAndInvokesHostLevelDataAttachment() {
ModdedServerLevels.HostLevelDataAttachment attachment =
ModdedServerLevels.HostLevelDataAttachment.detect(
AttachedLevelData.class, RootData.class, DimensionKey.class);
AttachedLevelData levelData = new AttachedLevelData();
RootData rootData = new RootData();
DimensionKey dimensionKey = new DimensionKey();
assertTrue(attachment.supported());
attachment.attach(levelData, rootData, dimensionKey);
assertSame(rootData, levelData.rootData);
assertSame(dimensionKey, levelData.dimensionKey);
}
@Test
public void ignoresLevelDataWithoutAttachmentCapability() {
ModdedServerLevels.HostLevelDataAttachment attachment =
ModdedServerLevels.HostLevelDataAttachment.detect(
StandardLevelData.class, RootData.class, DimensionKey.class);
assertFalse(attachment.supported());
}
@Test
public void propagatesHostAttachmentFailureWithoutReflectionWrapper() {
ModdedServerLevels.HostLevelDataAttachment attachment =
ModdedServerLevels.HostLevelDataAttachment.detect(
FailingLevelData.class, RootData.class, DimensionKey.class);
IllegalStateException failure = assertThrows(IllegalStateException.class,
() -> attachment.attach(new FailingLevelData(), new RootData(), new DimensionKey()));
assertNull(failure.getCause());
}
public static final class AttachedLevelData {
private RootData rootData;
private DimensionKey dimensionKey;
public void attach(RootData rootData, DimensionKey dimensionKey) {
this.rootData = rootData;
this.dimensionKey = dimensionKey;
}
}
public static final class FailingLevelData {
public void attach(RootData rootData, DimensionKey dimensionKey) {
throw new IllegalStateException("attachment failed");
}
}
public static final class StandardLevelData {
}
public static final class RootData {
}
public static final class DimensionKey {
}
}
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeContainerLoot;
import art.arcane.iris.structure.placement.LootResolver;
import art.arcane.iris.world.loot.IrisLootMode;
import art.arcane.volmlib.util.math.RNG;
@@ -112,7 +114,7 @@ public class ModdedLootApplierTest {
@Test
public void nativeKeyIsReturnedWhenTheLiveRegistryContainsIt() {
ResourceKey<LootTable> key = ModdedLootApplier.resolveNativeKey("minecraft:chests/simple_dungeon", candidate -> true);
ResourceKey<LootTable> key = NativeContainerLoot.resolveNativeKey("minecraft:chests/simple_dungeon", candidate -> true);
assertNotNull(key);
assertEquals(Identifier.parse("minecraft:chests/simple_dungeon"), key.identifier());
@@ -120,7 +122,7 @@ public class ModdedLootApplierTest {
@Test
public void nativeKeyIsRejectedWhenTheLiveRegistryDoesNotContainIt() {
ResourceKey<LootTable> key = ModdedLootApplier.resolveNativeKey("minecraft:chests/missing", candidate -> false);
ResourceKey<LootTable> key = NativeContainerLoot.resolveNativeKey("minecraft:chests/missing", candidate -> false);
assertNull(key);
}
@@ -129,7 +131,7 @@ public class ModdedLootApplierTest {
public void malformedNativeKeyIsRejectedBeforeRegistryLookup() {
AtomicBoolean registryConsulted = new AtomicBoolean(false);
ResourceKey<LootTable> key = ModdedLootApplier.resolveNativeKey("not a valid identifier", candidate -> {
ResourceKey<LootTable> key = NativeContainerLoot.resolveNativeKey("not a valid identifier", candidate -> {
registryConsulted.set(true);
return true;
});
@@ -142,7 +144,7 @@ public class ModdedLootApplierTest {
public void nativeOnlyFillMarksTheContainerChanged() {
TrackingContainer container = new TrackingContainer();
ModdedLootApplier.fillContainer(container, List.<ItemStack>of(), new RNG(17L));
NativeContainerLoot.fillContainer(container, List.<ItemStack>of(), new RNG(17L), message -> {});
assertTrue(container.changed);
}
@@ -152,8 +154,8 @@ public class ModdedLootApplierTest {
BlockPos leftPos = new BlockPos(0, 64, 0);
BlockPos rightPos = new BlockPos(1, 64, 0);
assertTrue(ModdedLootApplier.isCanonicalPair(leftPos, rightPos));
assertFalse(ModdedLootApplier.isCanonicalPair(rightPos, leftPos));
assertTrue(NativeContainerLoot.isCanonicalPair(leftPos, rightPos));
assertFalse(NativeContainerLoot.isCanonicalPair(rightPos, leftPos));
}
@Test
@@ -165,8 +167,8 @@ public class ModdedLootApplierTest {
RandomizableContainer empty = containerWithLootTable(null);
RandomizableContainer nativeLoot = containerWithLootTable(key);
assertFalse(ModdedLootApplier.hasNativeLootTable(empty));
assertTrue(ModdedLootApplier.hasNativeLootTable(nativeLoot));
assertFalse(NativeContainerLoot.hasNativeLootTable(empty));
assertTrue(NativeContainerLoot.hasNativeLootTable(nativeLoot));
}
private RandomizableContainer containerWithLootTable(ResourceKey<LootTable> key) {
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedStructureStage;
import com.mojang.serialization.Codec;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
@@ -58,7 +60,7 @@ public class ModdedNativeStructurePoiRegistrationTest {
chunk.setBlockState(ordinaryPosition, Blocks.STONE.defaultBlockState(), 0);
Map<BlockPos, BlockState> visited = new LinkedHashMap<>();
ModdedNativeStructureStage.visitExistingPois(
NativeModdedStructureStage.visitExistingPois(
chunk, (position, state) -> visited.put(position.immutable(), state));
assertEquals(poiState, visited.get(poiPosition));
@@ -92,7 +94,7 @@ public class ModdedNativeStructurePoiRegistrationTest {
Deque<Runnable> serverQueue = new ArrayDeque<>();
AtomicInteger missingRemovals = new AtomicInteger();
ModdedNativeStructureStage.visitExistingPois(chunk,
NativeModdedStructureStage.visitExistingPois(chunk,
(poiPosition, state) -> queuePoiTransition(
serverQueue, section, poiPosition,
Blocks.AIR.defaultBlockState(), state, missingRemovals));
@@ -1,9 +1,11 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedNativeStructureWorldgenAccess;
import art.arcane.iris.structure.placement.IrisStructureTerrain;
import art.arcane.iris.structure.placement.IrisStructureTerrainMode;
import art.arcane.iris.nativegen.NativeStructurePostProcessor;
import art.arcane.iris.nativegen.NativeStructureTerrainIntegrator;
import art.arcane.volmlib.util.structure.StructureTerrainMode;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructurePostProcessor;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureTerrainIntegrator;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -84,7 +86,7 @@ public class ModdedNativeStructureWorldgenAccessTest {
StructureStart start = new StructureStart(structure, generationCenter(), 0, new PiecesContainer(List.of(piece)));
List<NativeStructureTerrainIntegrator.TerrainTarget> targets = List.of(
new NativeStructureTerrainIntegrator.TerrainTarget("minecraft:village_plains", start,
new IrisStructureTerrain().setMode(IrisStructureTerrainMode.FLATTEN)));
new IrisStructureTerrain().setMode(StructureTerrainMode.FLATTEN)));
BoundingBox area = new BoundingBox(generationCenter().getMinBlockX(), -64, generationCenter().getMinBlockZ(),
generationCenter().getMaxBlockX(), 319, generationCenter().getMaxBlockZ());
RecordingDelegate unbounded = new RecordingDelegate();
@@ -1,7 +1,12 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedLoader;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedServer;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedServerAccess;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedServerLevels;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.block.state.BlockState;
@@ -20,7 +25,7 @@ public class ModdedPlatformPathsTest {
private ModdedPlatform platform() {
Path configDir = temporaryFolder.getRoot().toPath();
return new ModdedPlatform(new ModdedLoader() {
return new ModdedPlatform(new NativeModdedLoader() {
@Override
public String platformName() {
return "test";
@@ -37,20 +42,21 @@ public class ModdedPlatformPathsTest {
}
@Override
public MinecraftServer currentServer() {
public NativeModdedServer currentServer() {
return null;
}
@Override
public void invalidateLevelCache(MinecraftServer server) {
public ModdedServerAccess serverAccess() {
return new ModdedServerLevels(server -> {});
}
@Override
public void fireDynamicLevelLoad(MinecraftServer server, ServerLevel level) {
public void fireDynamicLevelLoad(NativeWorld level) {
}
@Override
public void fireDynamicLevelUnload(MinecraftServer server, ServerLevel level) {
public void fireDynamicLevelUnload(NativeWorld level) {
}
@Override
@@ -69,12 +75,12 @@ public class ModdedPlatformPathsTest {
}
@Override
public boolean hasTreeFellerPermission(ServerPlayer player) {
public boolean hasBlockBreakPermission(ServerPlayer player) {
return false;
}
@Override
public boolean canTreeFellerBreak(ServerLevel level, ServerPlayer player, BlockPos position, BlockState state) {
public boolean canBreakBlock(ServerLevel level, ServerPlayer player, BlockPos position, BlockState state) {
return false;
}
});
@@ -1,5 +1,11 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedPlatformWorld;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeProtocolPlayer;
import art.arcane.volmlib.nativelib.terrain.NativeWorld;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityRuntime;
import art.arcane.iris.configuration.IrisSettings;
import art.arcane.iris.pack.loading.IrisData;
import art.arcane.iris.generation.runtime.BiomeEnvironment;
@@ -19,7 +25,7 @@ import net.minecraft.server.Bootstrap;
import net.minecraft.server.level.ServerPlayer;
import org.junit.Test;
import org.junit.BeforeClass;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
import art.arcane.iris.generation.block.B;
import org.mockito.MockedStatic;
@@ -45,7 +51,7 @@ public class ModdedSavedBiomeConsumersTest {
public static void initializeRuntimeTypes() throws Exception {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
PlatformBlockState air = mock(PlatformBlockState.class);
NativeBlockState air = mock(NativeBlockState.class);
try (MockedStatic<B> blocks = mockStatic(B.class)) {
blocks.when(() -> B.getState("AIR")).thenReturn(air);
Class.forName(EngineMantle.class.getName());
@@ -78,10 +84,10 @@ public class ModdedSavedBiomeConsumersTest {
try (MockedStatic<IrisSettings> configured = mockStatic(IrisSettings.class);
MockedStatic<ModdedEntitySpawner> spawns = mockStatic(ModdedEntitySpawner.class)) {
configured.when(IrisSettings::get).thenReturn(settings);
spawns.when(() -> ModdedEntitySpawner.chunksSafe(level, 2, -1)).thenReturn(true);
assertThrows(SavedBiomeUnavailableException.class, () -> manager.initialSpawnChunk(level, 2, -1));
spawns.when(() -> ModdedEntitySpawner.chunksSafe(any(NativeEntityRuntime.class), eq(2), eq(-1))).thenReturn(true);
assertThrows(SavedBiomeUnavailableException.class, () -> manager.initialSpawnChunk(new ModdedPlatformWorld(level), 2, -1));
verify(chunk, never()).raiseFlagUnchecked(eq(ModdedWorldManager.INITIAL_SPAWN_COMPLETION_FLAG), any());
assertTrue(manager.initialSpawnChunk(level, 2, -1));
assertTrue(manager.initialSpawnChunk(new ModdedPlatformWorld(level), 2, -1));
verify(chunk).raiseFlagUnchecked(eq(ModdedWorldManager.INITIAL_SPAWN_COMPLETION_FLAG), any());
} finally {
manager.close();
@@ -105,10 +111,10 @@ public class ModdedSavedBiomeConsumersTest {
IrisSettings settings = new IrisSettings();
settings.getWorld().setEffectSystem(false);
Class<?> stateType = Class.forName(ModdedEngineEffects.class.getName() + "$PlayerState");
Constructor<?> constructor = stateType.getDeclaredConstructor(ServerPlayer.class);
Constructor<?> constructor = stateType.getDeclaredConstructor(NativeProtocolPlayer.class);
constructor.setAccessible(true);
Object state = constructor.newInstance(player);
Method tick = ModdedEngineEffects.class.getDeclaredMethod("tickPlayer", ServerLevel.class, stateType);
Object state = constructor.newInstance(NativeProtocolPlayer.fromHandle(player));
Method tick = ModdedEngineEffects.class.getDeclaredMethod("tickPlayer", NativeWorld.class, stateType);
tick.setAccessible(true);
Field selected = stateType.getDeclaredField("environment");
selected.setAccessible(true);
@@ -116,9 +122,9 @@ public class ModdedSavedBiomeConsumersTest {
try (MockedStatic<IrisSettings> configured = mockStatic(IrisSettings.class)) {
configured.when(IrisSettings::get).thenReturn(settings);
ModdedEngineEffects effects = new ModdedEngineEffects(engine);
tick.invoke(effects, level, state);
tick.invoke(effects, new ModdedPlatformWorld(level), state);
assertNull(selected.get(state));
tick.invoke(effects, level, state);
tick.invoke(effects, new ModdedPlatformWorld(level), state);
assertSame(environment, selected.get(state));
verify(engine, times(2)).getBiomeEnvironment(0, 64, 0);
}
@@ -1,73 +0,0 @@
package art.arcane.iris.modded;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class ModdedServerLevelsTest {
@Test
public void detectsAndInvokesHostLevelPublicationPair() {
ModdedServerLevels.HostLevelPublication publication =
ModdedServerLevels.HostLevelPublication.detect(PublishingServer.class, PublishedLevel.class);
PublishingServer server = new PublishingServer();
PublishedLevel level = new PublishedLevel();
assertTrue(publication.supported());
publication.add(server, level);
assertSame(level, server.added);
publication.remove(server, level);
assertSame(level, server.removed);
}
@Test
public void rejectsPartialHostLevelPublicationCapability() {
ModdedServerLevels.HostLevelPublication publication =
ModdedServerLevels.HostLevelPublication.detect(AddOnlyServer.class, PublishedLevel.class);
assertFalse(publication.supported());
}
@Test
public void propagatesHostPublicationFailureWithoutReflectionWrapper() {
ModdedServerLevels.HostLevelPublication publication =
ModdedServerLevels.HostLevelPublication.detect(FailingServer.class, PublishedLevel.class);
IllegalStateException failure = assertThrows(IllegalStateException.class,
() -> publication.add(new FailingServer(), new PublishedLevel()));
assertNull(failure.getCause());
}
public static final class PublishingServer {
private PublishedLevel added;
private PublishedLevel removed;
public void addLevel(PublishedLevel level) {
added = level;
}
public void removeLevel(PublishedLevel level) {
removed = level;
}
}
public static final class AddOnlyServer {
public void addLevel(PublishedLevel level) {
}
}
public static final class FailingServer {
public void addLevel(PublishedLevel level) {
throw new IllegalStateException("publication failed");
}
public void removeLevel(PublishedLevel level) {
}
}
public static final class PublishedLevel {
}
}
@@ -1,128 +0,0 @@
package art.arcane.iris.modded;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class ModdedStructureHooksTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void objectFeaturesMatchPaperGroups() {
assertEquals("trees", ModdedStructureHooks.classifyFeature(Feature.TREE));
assertEquals("fallen_trees", ModdedStructureHooks.classifyFeature(Feature.FALLEN_TREE));
assertEquals("mushrooms", ModdedStructureHooks.classifyFeature(Feature.HUGE_BROWN_MUSHROOM));
assertEquals("mushrooms", ModdedStructureHooks.classifyFeature(Feature.HUGE_RED_MUSHROOM));
assertNull(ModdedStructureHooks.classifyFeature(Feature.ORE));
}
@Test
public void structureSpanGuardUsesInclusiveBoundingBoxDimensions() {
BoundingBox box = new BoundingBox(-16, -64, 32, 15, 63, 47);
assertTrue(ModdedStructureHooks.isWithinSpan(box, 128));
assertFalse(ModdedStructureHooks.isWithinSpan(box, 127));
assertTrue(ModdedStructureHooks.isWithinSpan(box, 0));
assertTrue(ModdedStructureHooks.isWithinSpan(box, -1));
}
@Test
public void chunkGridSizeCountsEveryChunkPlacementWouldLoad() {
assertEquals(1, ModdedStructureHooks.chunkGridSize(new BoundingBox(0, 0, 0, 15, 15, 15)));
assertEquals(4, ModdedStructureHooks.chunkGridSize(new BoundingBox(0, 0, 0, 16, 15, 16)));
assertEquals(9, ModdedStructureHooks.chunkGridSize(new BoundingBox(-16, 0, -16, 16, 15, 16)));
}
@Test
public void chunkGridSizeSaturatesInsteadOfOverflowing() {
BoundingBox box = new BoundingBox(
Integer.MIN_VALUE / 2, 0, Integer.MIN_VALUE / 2,
Integer.MAX_VALUE / 2, 15, Integer.MAX_VALUE / 2);
assertEquals(Integer.MAX_VALUE, ModdedStructureHooks.chunkGridSize(box));
assertTrue(ModdedStructureHooks.chunkGridSize(box) > ModdedStructureHooks.MAX_PLACEMENT_CHUNKS);
}
@Test
public void structurePlacementReturnsPaperOrderedBounds() {
BoundingBox box = new BoundingBox(-16, -64, 32, 15, 63, 47);
assertArrayEquals(new int[]{-16, -64, 32, 15, 63, 47}, ModdedStructureHooks.bounds(box));
}
@Test
public void platformWorldMaximumHeightIsExclusive() {
assertEquals(320, ModdedPlatformWorld.exclusiveMaxHeight(-64, 384));
assertEquals(384, ModdedPlatformWorld.exclusiveMaxHeight(0, 384));
}
@Test
public void structureRegistryHooksRejectUnavailableServer() {
ModdedStructureHooks hooks = new ModdedStructureHooks(() -> null);
IllegalStateException structureKeys = assertThrows(
IllegalStateException.class, hooks::structureKeys);
IllegalStateException jigsawStructureKeys = assertThrows(
IllegalStateException.class, hooks::jigsawStructureKeys);
IllegalStateException templatePoolKeys = assertThrows(
IllegalStateException.class, hooks::templatePoolKeys);
IllegalStateException jigsawMetadata = assertThrows(
IllegalStateException.class, () -> hooks.jigsawSourceMetadata("minecraft:village"));
IllegalStateException templatePoolSpan = assertThrows(
IllegalStateException.class,
() -> hooks.templatePoolHorizontalSpan("minecraft:village/plains/town_centers"));
IllegalStateException structureSetKeys = assertThrows(
IllegalStateException.class, hooks::structureSetKeys);
IllegalStateException structureBiomeKeys = assertThrows(
IllegalStateException.class, () -> hooks.structureBiomeKeys("minecraft:village"));
assertTrue(structureKeys.getMessage().contains("before the Minecraft server is available"));
assertTrue(jigsawStructureKeys.getMessage().contains("before the Minecraft server is available"));
assertTrue(templatePoolKeys.getMessage().contains("before the Minecraft server is available"));
assertTrue(jigsawMetadata.getMessage().contains("before the Minecraft server is available"));
assertTrue(templatePoolSpan.getMessage().contains("before the Minecraft server is available"));
assertTrue(structureSetKeys.getMessage().contains("before the Minecraft server is available"));
assertTrue(structureBiomeKeys.getMessage().contains("before the Minecraft server is available"));
}
@Test
public void structureReachabilityHooksRejectUnavailableLevel() {
ModdedStructureHooks hooks = new ModdedStructureHooks(() -> null);
IllegalStateException reachable = assertThrows(
IllegalStateException.class, () -> hooks.reachableStructureKeys(null));
IllegalStateException possibleBiomes = assertThrows(
IllegalStateException.class, () -> hooks.possibleBiomeKeys(null));
assertTrue(reachable.getMessage().contains("without a bound modded ServerLevel"));
assertTrue(possibleBiomes.getMessage().contains("without a bound modded ServerLevel"));
}
@Test
public void structureRegistryHooksPreserveServerSupplierFailure() {
IllegalStateException cause = new IllegalStateException("server supplier failed");
ModdedStructureHooks hooks = new ModdedStructureHooks(() -> {
throw cause;
});
IllegalStateException failure = assertThrows(
IllegalStateException.class, hooks::structureKeys);
assertTrue(failure.getMessage().contains("access the Minecraft server"));
assertEquals(cause, failure.getCause());
}
}
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeStructureSetFrequencyOverrides;
import art.arcane.iris.structure.nativegen.IrisImportedStructureControl;
import art.arcane.iris.structure.placement.IrisStructureSetFrequencyOverride;
import art.arcane.volmlib.util.collection.KList;
@@ -55,7 +57,7 @@ public class ModdedStructureSetFrequencyOverridesTest {
.setFrequencyOverrides(overrides);
ChunkGeneratorStructureState returned =
ModdedStructureSetFrequencyOverrides.apply(state, control);
NativeStructureSetFrequencyOverrides.apply(state, control);
assertSame(state, returned);
List<Holder<StructureSet>> scaledSets = state.possibleStructureSets();
@@ -80,7 +82,7 @@ public class ModdedStructureSetFrequencyOverridesTest {
.setFrequencyOverrides(overrides);
List<Holder<StructureSet>> scaled =
ModdedStructureSetFrequencyOverrides.scaleSets(List.of(custom), control);
NativeStructureSetFrequencyOverrides.scaleSets(List.of(custom), control);
assertSame(custom, scaled.getFirst());
}
@@ -98,7 +100,7 @@ public class ModdedStructureSetFrequencyOverridesTest {
IrisImportedStructureControl control = new IrisImportedStructureControl()
.setFrequencyOverrides(overrides);
List<Holder<StructureSet>> scaled = ModdedStructureSetFrequencyOverrides.scaleSets(
List<Holder<StructureSet>> scaled = NativeStructureSetFrequencyOverrides.scaleSets(
List.of(first, second), control);
assertSame(first, scaled.get(0));
@@ -118,7 +120,7 @@ public class ModdedStructureSetFrequencyOverridesTest {
IrisImportedStructureControl control = new IrisImportedStructureControl()
.setFrequencyOverrides(overrides);
List<Holder<StructureSet>> scaled = ModdedStructureSetFrequencyOverrides.scaleSets(
List<Holder<StructureSet>> scaled = NativeStructureSetFrequencyOverrides.scaleSets(
List.of(first, second), control);
assertEquals(31, ((RandomSpreadStructurePlacement)
@@ -140,7 +142,7 @@ public class ModdedStructureSetFrequencyOverridesTest {
.setFrequencyOverrides(overrides);
assertThrows(IllegalStateException.class, () ->
ModdedStructureSetFrequencyOverrides.scaleSets(List.of(custom), control));
NativeStructureSetFrequencyOverrides.scaleSets(List.of(custom), control));
}
private static Holder<StructureSet> structureSet(
@@ -55,7 +55,7 @@ public class ModdedStructureTemplateCacheTest {
@Test
public void requiredCommonMixinConfigRegistersPaletteConcurrencyFix() throws Exception {
InputStream resource = ModdedStructureTemplateCacheTest.class.getClassLoader()
.getResourceAsStream("irisworldgen.entity.mixins.json");
.getResourceAsStream("volmlib.entity.mixins.json");
assertNotNull(resource);
String config;
try (InputStream input = resource) {
@@ -63,7 +63,7 @@ public class ModdedStructureTemplateCacheTest {
}
assertTrue(config.contains("\"StructureTemplatePaletteConcurrencyMixin\""));
assertNotNull(Class.forName(
"art.arcane.iris.modded.mixin.StructureTemplatePaletteConcurrencyMixin",
"art.arcane.volmlib.nativelib.minecraft26_2.modded.mixin.StructureTemplatePaletteConcurrencyMixin",
false,
ModdedStructureTemplateCacheTest.class.getClassLoader()));
}
@@ -1,5 +1,6 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeTileData;
import art.arcane.iris.generation.block.TileData;
import art.arcane.volmlib.util.collection.KMap;
import com.google.gson.Gson;
@@ -53,15 +54,15 @@ public class ModdedTileDataIdentityTest {
ModdedTileData captured = ModdedTileData.capture("minecraft:player_head", snbt);
assertEquals(snbt, captured.snbt());
assertEquals(snbt, captured.getProperties().get(ModdedTileData.NBT_PROPERTY));
assertEquals(snbt, captured.nativeData().snbt());
assertEquals(snbt, captured.getProperties().get(NativeTileData.NBT_PROPERTY));
// The Bukkit-readable map form is still written, and is still array-lossy - which is why the SNBT has to stay.
assertTrue(captured.getProperties().get("profile") instanceof KMap);
KMap<?, ?> profile = (KMap<?, ?>) captured.getProperties().get("profile");
assertTrue(profile.get("id") instanceof List);
CompoundTag payload = captured.payload();
CompoundTag payload = captured.nativeData().payload();
assertNotNull(payload);
Tag profileTag = payload.get("profile");
assertTrue(profileTag instanceof CompoundTag);
@@ -101,7 +102,7 @@ public class ModdedTileDataIdentityTest {
@Test
public void legacyRecordHasNoBlockKey() {
ModdedTileData legacy = new ModdedTileData(new byte[]{0, 1}, new KMap<>(), null, 0);
ModdedTileData legacy = ModdedTileData.wrap(new NativeTileData(new byte[]{0, 1}, new KMap<>(), null, 0));
assertNull(legacy.getMaterialKey());
}
@@ -131,7 +132,7 @@ public class ModdedTileDataIdentityTest {
out.writeUTF(blockKey);
out.writeUTF(GSON.toJson(properties));
}
return new ModdedTileData(bytes.toByteArray(), properties, blockKey, -1);
return ModdedTileData.wrap(new NativeTileData(bytes.toByteArray(), properties, blockKey, -1));
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeTileReader;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import art.arcane.iris.generation.block.TileData;
import art.arcane.volmlib.util.collection.KMap;
import net.minecraft.SharedConstants;
@@ -39,7 +41,8 @@ public class ModdedTileParityTest {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
registries = RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY);
TileData.bindPlatformReader(new ModdedTileReader(() -> null));
NativeTileReader nativeTileReader = new NativeTileReader(() -> null);
TileData.bindPlatformReader(in -> ModdedTileData.wrap(nativeTileReader.read(in)));
TileData.bindPlatformFactory(ModdedTileData::fromProperties);
}
@@ -55,7 +58,7 @@ public class ModdedTileParityTest {
});
SignBlockEntity sign = new SignBlockEntity(BlockPos.ZERO, Blocks.OAK_SIGN.defaultBlockState());
sign.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.payload()));
sign.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.nativeData().payload()));
assertEquals("Iris", sign.getFrontText().getMessage(0, false).getString());
assertEquals("parity", sign.getBackText().getMessage(3, false).getString());
@@ -70,7 +73,7 @@ public class ModdedTileParityTest {
});
SpawnerBlockEntity spawner = new SpawnerBlockEntity(BlockPos.ZERO, Blocks.SPAWNER.defaultBlockState());
spawner.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.payload()));
spawner.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.nativeData().payload()));
CompoundTag saved = spawner.saveWithoutMetadata(registries);
assertTrue(saved.toString().contains("minecraft:zombie"));
@@ -84,7 +87,7 @@ public class ModdedTileParityTest {
});
SpawnerBlockEntity spawner = new SpawnerBlockEntity(BlockPos.ZERO, Blocks.SPAWNER.defaultBlockState());
spawner.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.payload()));
spawner.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.nativeData().payload()));
CompoundTag saved = spawner.saveWithoutMetadata(registries);
assertTrue(saved.toString().contains("minecraft:command_block_minecart"));
@@ -98,7 +101,7 @@ public class ModdedTileParityTest {
});
SpawnerBlockEntity spawner = new SpawnerBlockEntity(BlockPos.ZERO, Blocks.SPAWNER.defaultBlockState());
spawner.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.payload()));
spawner.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.nativeData().payload()));
CompoundTag saved = spawner.saveWithoutMetadata(registries);
assertTrue(saved.toString().contains("minecraft:pig"));
@@ -114,7 +117,7 @@ public class ModdedTileParityTest {
});
ChestBlockEntity chest = new ChestBlockEntity(BlockPos.ZERO, Blocks.CHEST.defaultBlockState());
chest.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.payload()));
chest.loadWithComponents(TagValueInput.create(ProblemReporter.DISCARDING, registries, tile.nativeData().payload()));
RandomizableContainer lootable = chest;
assertNotNull(lootable.getLootTable());
@@ -132,35 +135,35 @@ public class ModdedTileParityTest {
assertEquals(
BuiltInRegistries.BLOCK.getValue(Identifier.parse("minecraft:red_banner")),
tile.adjustBlockState(BuiltInRegistries.BLOCK.getValue(Identifier.parse("minecraft:white_banner")).defaultBlockState()).getBlock());
assertEquals(Blocks.BARREL, tile.adjustBlockState(Blocks.BARREL.defaultBlockState()).getBlock());
tile.nativeData().adjustBlockState(BuiltInRegistries.BLOCK.getValue(Identifier.parse("minecraft:white_banner")).defaultBlockState()).getBlock());
assertEquals(Blocks.BARREL, tile.nativeData().adjustBlockState(Blocks.BARREL.defaultBlockState()).getBlock());
}
@Test
public void paper26_2LegacyBannerFirstOrdinalIsSmallStripes() {
assertEquals(
Identifier.parse("minecraft:small_stripes"),
ModdedTileReader.legacyBannerPatternKey(0));
NativeTileReader.legacyBannerPatternKey(0));
}
@Test
public void paper26_2LegacyBannerMiddleOrdinalIsStripeLeft() {
assertEquals(
Identifier.parse("minecraft:stripe_left"),
ModdedTileReader.legacyBannerPatternKey(21));
NativeTileReader.legacyBannerPatternKey(21));
}
@Test
public void paper26_2LegacyBannerLastOrdinalIsHalfVerticalRight() {
assertEquals(
Identifier.parse("minecraft:half_vertical_right"),
ModdedTileReader.legacyBannerPatternKey(42));
NativeTileReader.legacyBannerPatternKey(42));
}
@Test
public void invalidLegacyBannerOrdinalFallsBackToBase() {
assertEquals(Identifier.parse("minecraft:base"), ModdedTileReader.legacyBannerPatternKey(-1));
assertEquals(Identifier.parse("minecraft:base"), ModdedTileReader.legacyBannerPatternKey(43));
assertEquals(Identifier.parse("minecraft:base"), NativeTileReader.legacyBannerPatternKey(-1));
assertEquals(Identifier.parse("minecraft:base"), NativeTileReader.legacyBannerPatternKey(43));
}
@Test
@@ -173,13 +176,13 @@ public class ModdedTileParityTest {
assertTrue(tile instanceof ModdedTileData);
ChestBlockEntity chest = new ChestBlockEntity(BlockPos.ZERO, Blocks.CHEST.defaultBlockState());
chest.loadWithComponents(TagValueInput.create(
ProblemReporter.DISCARDING, registries, ((ModdedTileData) tile).payload()));
ProblemReporter.DISCARDING, registries, ((ModdedTileData) tile).nativeData().payload()));
assertNotNull(chest.getLootTable());
assertEquals("minecraft:chests/abandoned_mineshaft", chest.getLootTable().identifier().toString());
assertEquals(9124L, chest.getLootTableSeed());
assertTrue(((ModdedTileData) tile).isApplicable(Blocks.CHEST.defaultBlockState(), chest));
assertFalse(((ModdedTileData) tile).isApplicable(
assertTrue(((ModdedTileData) tile).nativeData().isApplicable(Blocks.CHEST.defaultBlockState(), chest));
assertFalse(((ModdedTileData) tile).nativeData().isApplicable(
Blocks.BARREL.defaultBlockState(),
new BarrelBlockEntity(BlockPos.ZERO, Blocks.BARREL.defaultBlockState())));
}
@@ -197,8 +200,8 @@ public class ModdedTileParityTest {
SignBlockEntity sign = new SignBlockEntity(BlockPos.ZERO, Blocks.OAK_SIGN.defaultBlockState());
ChestBlockEntity chest = new ChestBlockEntity(BlockPos.ZERO, Blocks.CHEST.defaultBlockState());
assertTrue(tile.isApplicable(Blocks.OAK_SIGN.defaultBlockState(), sign));
assertFalse(tile.isApplicable(Blocks.CHEST.defaultBlockState(), chest));
assertTrue(tile.nativeData().isApplicable(Blocks.OAK_SIGN.defaultBlockState(), sign));
assertFalse(tile.nativeData().isApplicable(Blocks.CHEST.defaultBlockState(), chest));
}
private static ModdedTileData legacyTile(TileWriter writer) throws Exception {
@@ -1,5 +1,9 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityRuntime;
import art.arcane.iris.world.entity.IrisEntity;
import art.arcane.iris.world.entity.IrisEntitySpawn;
import art.arcane.iris.world.entity.IrisSpawnGroup;
@@ -37,13 +41,13 @@ public class ModdedWaterEntitySpawnTest {
ServerLevel level = mock(ServerLevel.class);
IrisEntity entity = new IrisEntity().setType("tadpole").setSurface(IrisSurface.WATER);
when(level.getBlockState(any(BlockPos.class))).thenReturn(Blocks.WATER.defaultBlockState());
assertTrue(ModdedEntitySpawner.isAreaClearForSpawn(level, entity, 0, 78, 0));
assertTrue(ModdedEntitySpawner.isAreaClearForSpawn(new NativeEntityRuntime(level), entity, 0, 78, 0));
when(level.getBlockState(any(BlockPos.class))).thenReturn(Blocks.SEAGRASS.defaultBlockState());
assertTrue(ModdedEntitySpawner.isAreaClearForSpawn(level, entity, 0, 78, 0));
assertTrue(ModdedEntitySpawner.isAreaClearForSpawn(new NativeEntityRuntime(level), entity, 0, 78, 0));
when(level.getBlockState(any(BlockPos.class))).thenReturn(Blocks.AIR.defaultBlockState());
assertFalse(ModdedEntitySpawner.isAreaClearForSpawn(level, entity, 0, 79, 0));
assertFalse(ModdedEntitySpawner.isAreaClearForSpawn(new NativeEntityRuntime(level), entity, 0, 79, 0));
when(level.getBlockState(any(BlockPos.class))).thenReturn(Blocks.LAVA.defaultBlockState());
assertFalse(ModdedEntitySpawner.isAreaClearForSpawn(level, entity, 0, 78, 0));
assertFalse(ModdedEntitySpawner.isAreaClearForSpawn(new NativeEntityRuntime(level), entity, 0, 78, 0));
}
@Test
@@ -51,38 +55,38 @@ public class ModdedWaterEntitySpawnTest {
ServerLevel level = mock(ServerLevel.class);
IrisEntity entity = new IrisEntity().setType("tadpole").setSurface(IrisSurface.LAVA);
when(level.getBlockState(any(BlockPos.class))).thenReturn(Blocks.LAVA.defaultBlockState());
assertTrue(ModdedEntitySpawner.isAreaClearForSpawn(level, entity, 0, 78, 0));
assertTrue(ModdedEntitySpawner.isAreaClearForSpawn(new NativeEntityRuntime(level), entity, 0, 78, 0));
when(level.getBlockState(any(BlockPos.class))).thenReturn(Blocks.WATER.defaultBlockState());
assertFalse(ModdedEntitySpawner.isAreaClearForSpawn(level, entity, 0, 78, 0));
assertFalse(ModdedEntitySpawner.isAreaClearForSpawn(new NativeEntityRuntime(level), entity, 0, 78, 0));
}
@Test
public void waterloggedSolidBlocksStillObstructWaterSpawns() {
assertTrue(ModdedWorldManager.matchesSurface(IrisSurface.WATER,
Blocks.SEA_PICKLE.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, true)));
ModdedBlockState.of(Blocks.SEA_PICKLE.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, true), null)));
assertFalse(ModdedWorldManager.matchesSurface(IrisSurface.WATER,
Blocks.OAK_FENCE.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, true)));
ModdedBlockState.of(Blocks.OAK_FENCE.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, true), null)));
}
@Test
public void fractionalFluidVolumeIncludesHorizontalEdgesAndCenteredHeight() {
Set<BlockPos> checked = new HashSet<>();
assertTrue(ModdedEntitySpawner.isFluidAreaClearForSpawn(-1, 78, -1, 1.3F, 0.8F, position -> {
checked.add(position);
assertTrue(NativeEntityRuntime.isFluidAreaClearForSpawn(-1, 78, -1, 1.3F, 0.8F, (x, y, z) -> {
checked.add(new BlockPos(x, y, z));
return true;
}));
assertEquals(18, checked.size());
assertTrue(checked.contains(new BlockPos(-2, 79, -2)));
assertTrue(checked.contains(new BlockPos(0, 78, 0)));
assertFalse(ModdedEntitySpawner.isFluidAreaClearForSpawn(-1, 78, -1, 1.3F, 0.8F,
position -> !position.equals(new BlockPos(-2, 79, -2))));
assertFalse(NativeEntityRuntime.isFluidAreaClearForSpawn(-1, 78, -1, 1.3F, 0.8F,
(x, y, z) -> !new BlockPos(x, y, z).equals(new BlockPos(-2, 79, -2))));
}
@Test
public void exactUpperBoundaryDoesNotRequireWaterOutsideTheBody() {
Set<BlockPos> checked = new HashSet<>();
assertTrue(ModdedEntitySpawner.isFluidAreaClearForSpawn(0, 78, 0, 1F, 0.5F, position -> {
checked.add(position);
assertTrue(NativeEntityRuntime.isFluidAreaClearForSpawn(0, 78, 0, 1F, 0.5F, (x, y, z) -> {
checked.add(new BlockPos(x, y, z));
return true;
}));
assertEquals(Set.of(new BlockPos(0, 78, 0)), checked);
@@ -1,5 +1,7 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeStructureInspection;
import net.minecraft.resources.Identifier;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
@@ -126,7 +128,7 @@ public class ModdedWorldCheckTest {
public void smallStructureFootprintIncludesEveryChunk() {
BoundingBox bounds = new BoundingBox(-16, -20, -16, 31, 120, 31);
List<ChunkPos> chunks = WorldCheckStructureAudit.boundedFootprintChunks(bounds, ChunkPos.ZERO, 96);
List<ChunkPos> chunks = NativeStructureInspection.boundedFootprintChunks(bounds, ChunkPos.ZERO, 96);
assertEquals(9, chunks.size());
assertTrue(chunks.contains(new ChunkPos(-1, -1)));
@@ -137,7 +139,7 @@ public class ModdedWorldCheckTest {
public void largeStructureFootprintIsBoundedAndSamplesEdges() {
BoundingBox bounds = new BoundingBox(-512, -64, -512, 511, 300, 511);
List<ChunkPos> chunks = WorldCheckStructureAudit.boundedFootprintChunks(bounds, ChunkPos.ZERO, 20);
List<ChunkPos> chunks = NativeStructureInspection.boundedFootprintChunks(bounds, ChunkPos.ZERO, 20);
assertTrue(chunks.size() <= 20);
assertTrue(chunks.size() >= 16);
@@ -267,6 +269,6 @@ public class ModdedWorldCheckTest {
private static boolean characteristic(String structureLabel, String structureKey, String blockKey) {
return WorldCheckMaterials.isCharacteristicMaterial(structureLabel,
Identifier.parse(structureKey), Identifier.parse(blockKey));
structureKey, blockKey);
}
}
@@ -0,0 +1,61 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeCommandExecutor;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.Bootstrap;
import net.minecraft.server.MinecraftServer;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedServer;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class NativeCommandExecutorTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void dispatchesConsoleSourceWithLeadingSlashRemoved() {
MinecraftServer server = mock(MinecraftServer.class);
Commands commands = mock(Commands.class);
CommandSourceStack source = mock(CommandSourceStack.class);
when(server.getCommands()).thenReturn(commands);
when(server.createCommandSourceStack()).thenReturn(source);
List<Throwable> errors = new ArrayList<>();
assertTrue(NativeCommandExecutor.dispatch(NativeModdedServer.fromHandle(server), "/say terrain", errors::add));
verify(commands).performPrefixedCommand(source, "say terrain");
assertTrue(errors.isEmpty());
}
@Test
public void failedDispatchPreservesFailureForTheCaller() {
MinecraftServer server = mock(MinecraftServer.class);
Commands commands = mock(Commands.class);
CommandSourceStack source = mock(CommandSourceStack.class);
when(server.getCommands()).thenReturn(commands);
when(server.createCommandSourceStack()).thenReturn(source);
IllegalStateException failure = new IllegalStateException("dispatch failed");
doThrow(failure).when(commands).performPrefixedCommand(source, "say terrain");
List<Throwable> errors = new ArrayList<>();
assertFalse(NativeCommandExecutor.dispatch(NativeModdedServer.fromHandle(server), "say terrain", errors::add));
assertEquals(List.of(failure), errors);
}
}
@@ -0,0 +1,83 @@
package art.arcane.iris.modded;
import art.arcane.iris.world.loot.IrisLoot;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeItemContext;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeItemStack;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeItemTranslator;
import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.collection.KMap;
import art.arcane.volmlib.util.math.RNG;
import net.minecraft.SharedConstants;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class NativeItemTranslatorTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
if (!Items.LEATHER_HELMET.builtInRegistryHolder().areComponentsBound()) {
Items.LEATHER_HELMET.builtInRegistryHolder().bindComponents(DataComponentMap.builder()
.set(DataComponents.MAX_STACK_SIZE, 1)
.set(DataComponents.MAX_DAMAGE, 55)
.set(DataComponents.DAMAGE, 0)
.build());
}
}
@Test
public void componentsPreserveAuthoredValuesAndDurability() {
IrisLoot loot = new IrisLoot().setType("leather_helmet").setMinAmount(2).setMaxAmount(2)
.setMinDurability(0.5).setMaxDurability(0.5).setUnbreakable(true)
.setCustomModel(73).setLeatherColor("0x12ab34").setDisplayName("&aExplorer")
.setLore(new KList<>("&bFirst line", "Second line"))
.setCustomNbt(new KMap<String, Object>().qput("marker", "terrain"));
List<String> warnings = new ArrayList<>();
NativeItemContext context = new NativeItemContext(null,
new NativeItemContext.Options("example", (key, message) -> warnings.add(message)));
NativeItemStack result = NativeItemTranslator.stack(new IrisItemRecipe(loot, new RNG(41)), context);
assertNotNull(result);
ItemStack stack = result.stack();
assertTrue(stack.is(Items.LEATHER_HELMET));
assertEquals(2, stack.getCount());
assertEquals((int) Math.round(stack.getMaxDamage() * 0.5), stack.getDamageValue());
assertNotNull(stack.get(DataComponents.UNBREAKABLE));
assertEquals(73F, stack.get(DataComponents.CUSTOM_MODEL_DATA).floats().getFirst(), 0F);
assertEquals(0x12ab34, stack.get(DataComponents.DYED_COLOR).rgb());
assertEquals("§aExplorer", stack.get(DataComponents.CUSTOM_NAME).getString());
assertEquals("§bFirst line", stack.get(DataComponents.LORE).lines().getFirst().getString());
assertEquals("terrain", stack.get(DataComponents.CUSTOM_DATA).copyTag().getString("marker").orElseThrow());
assertTrue(warnings.isEmpty());
}
@Test
public void unknownItemDoesNotConsumeLootRandomness() {
RNG random = new RNG(83);
RNG expected = new RNG(83);
List<String> warnings = new ArrayList<>();
NativeItemContext context = new NativeItemContext(null,
new NativeItemContext.Options("example", (key, message) -> warnings.add(key)));
NativeItemStack result = NativeItemTranslator.stack(new IrisItemRecipe(
new IrisLoot().setType("example:unknown_item").setMinAmount(1).setMaxAmount(64), random), context);
assertNull(result);
assertEquals(expected.nextLong(), random.nextLong());
assertEquals(List.of("item:example:unknown_item"), warnings);
}
}
@@ -0,0 +1,44 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativePayloadProtocol;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.DecoderException;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
public class NativePayloadProtocolTest {
@Test
public void frameRoundTripKeepsItsChannelAndBytes() {
NativePayloadProtocol protocol = new NativePayloadProtocol("terrain:frame", 32);
byte[] frame = new byte[]{1, 4, 9, 16};
RegistryFriendlyByteBuf buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), RegistryAccess.EMPTY);
try {
protocol.codec().encode(buffer, protocol.payload(frame));
NativePayloadProtocol.Payload decoded = protocol.codec().decode(buffer);
assertSame(protocol, decoded.protocol());
assertArrayEquals(frame, decoded.data());
assertEquals("terrain:frame", decoded.type().id().toString());
} finally {
buffer.release();
}
}
@Test
public void decoderEnforcesTheConfiguredFrameLimit() {
NativePayloadProtocol protocol = new NativePayloadProtocol("terrain:frame", 3);
RegistryFriendlyByteBuf buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), RegistryAccess.EMPTY);
try {
buffer.writeByteArray(new byte[]{1, 2, 3, 4});
assertThrows(DecoderException.class, () -> protocol.codec().decode(buffer));
} finally {
buffer.release();
}
}
}
@@ -0,0 +1,54 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeRegistryAccess;
import art.arcane.volmlib.nativelib.terrain.NativeBlockProperty;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class NativeRegistryAccessTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void statePropertiesPreserveTypesDefaultsAndSharedGroups() {
NativeRegistryAccess access = new NativeRegistryAccess(() -> null, message -> {});
Map<String, List<NativeBlockProperty>> properties = access.blockStateProperties();
assertSame(properties.get("minecraft:stone"), properties.get("minecraft:dirt"));
NativeBlockProperty power = properties.get("minecraft:redstone_wire").stream()
.filter(property -> property.name().equals("power")).findFirst().orElseThrow();
assertEquals("integer", power.jsonType());
assertEquals(0, power.defaultValue());
assertEquals(16, power.allowedValues().size());
assertTrue(power.allowedValues().contains(15));
assertNull(power.numericRange());
}
@Test
public void staticRegistriesResolveWithoutAnActiveServerAndDynamicReadsStayEmpty() {
List<String> warnings = new ArrayList<>();
NativeRegistryAccess access = new NativeRegistryAccess(() -> null, warnings::add);
assertEquals("minecraft:diamond_sword", access.item("DIAMOND SWORD").key());
assertEquals("creature", access.entity("minecraft:cow").spawnCategory());
assertNull(access.item("example:unknown"));
assertTrue(access.biomeKeys().isEmpty());
assertTrue(access.structureKeys().isEmpty());
assertTrue(access.enchantmentKeys().isEmpty());
assertEquals(List.of("biome", "structure", "enchantment"), warnings);
}
}
@@ -0,0 +1,51 @@
package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeBlockResolver;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeStateMerger;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeStateRotator;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
import net.minecraft.SharedConstants;
import net.minecraft.core.Direction;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.block.StairBlock;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class NativeStateOperationsTest {
@BeforeClass
public static void bootstrapMinecraftRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void rotationPreservesDeferredPlacementMetadata() {
ModdedBlockState parsed = NativeBlockResolver.strictParse("minecraft:oak_stairs[facing=north]");
ModdedBlockState deferred = ModdedBlockState.deferred(parsed.handle(), parsed.parsedProperties(), "custom:stairs");
NativeBlockState result = NativeStateRotator.rotate(deferred,
(x, y, z) -> new NativeStateRotator.Vector(-z, y, x), failure -> {
throw new AssertionError(failure);
});
assertEquals(Direction.EAST, ((ModdedBlockState) result).handle().getValue(StairBlock.FACING));
assertEquals("custom:stairs", result.deferredPlacementKey());
}
@Test
public void mergeAppliesOnlySpecifiedPropertiesAndRetainsDeferredPlacement() {
ModdedBlockState parsed = NativeBlockResolver.strictParse("minecraft:oak_stairs[facing=west]");
ModdedBlockState deferred = ModdedBlockState.deferred(parsed.handle(), parsed.parsedProperties(), "custom:stairs");
ModdedBlockState update = NativeBlockResolver.strictParse("minecraft:oak_stairs[waterlogged=true]");
NativeBlockState result = new NativeStateMerger(ModdedBlockResolution.BLOCKS).merge(deferred, update);
assertEquals(Direction.WEST, ((ModdedBlockState) result).handle().getValue(StairBlock.FACING));
assertTrue(((ModdedBlockState) result).handle().getValue(StairBlock.WATERLOGGED));
assertEquals("custom:stairs", result.deferredPlacementKey());
}
}
@@ -1,6 +1,6 @@
package art.arcane.iris.modded;
import art.arcane.iris.nativegen.NativeStructureGenerationException;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureGenerationException;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import org.junit.BeforeClass;
@@ -1,6 +1,10 @@
package art.arcane.iris.modded.api;
import net.minecraft.resources.Identifier;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEntityRuntime;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeSpawnedEntity;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Collection;
@@ -11,8 +15,45 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ModdedCustomContentRegistryTest {
@BeforeClass
public static void bootstrapRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void entityProviderReceivesCanonicalKeyAndOriginalWorldAndPosition() {
ModdedDataProvider provider = mock(ModdedDataProvider.class);
NativeEntityRuntime runtime = mock(NativeEntityRuntime.class);
NativeSpawnedEntity entity = mock(NativeSpawnedEntity.class);
NativeEntityRuntime.Position position = new NativeEntityRuntime.Position(2.5, 63.5, -4.5);
NativeEntityRuntime.CustomSpawn canonical = new NativeEntityRuntime.CustomSpawn(runtime, position, "provider_test:mob");
when(provider.modId()).thenReturn("provider_entity_test");
when(provider.isReady()).thenReturn(true);
when(provider.isValidProvider("provider_test:mob", ModdedDataType.ENTITY)).thenReturn(true);
when(provider.spawnMob(canonical)).thenReturn(entity);
ModdedCustomContentRegistry.Discovery discovery = ModdedCustomContentRegistry.discover(List.of(provider));
try {
assertSame(entity, ModdedCustomContentRegistry.spawnMob(
new NativeEntityRuntime.CustomSpawn(runtime, position, " provider_test:mob[variant=a] ")));
verify(provider).spawnMob(canonical);
} finally {
discovery.rollback();
}
}
@Test
public void unclaimedDeferredBlockDoesNotReadTheWorld() {
ModdedCustomContentRegistry.processBlockPlacement(null, "provider_test:unclaimed", () -> {
throw new AssertionError("unclaimed placement read the world");
});
}
@Test
public void publishesProvidersOnlyAfterCompleteDiscoveryAndCanRollBack() {
String modId = "iris_discovery_success";
@@ -65,12 +106,12 @@ public class ModdedCustomContentRegistryTest {
}
@Override
public Collection<Identifier> getTypes(ModdedDataType type) {
public Collection<String> getTypes(ModdedDataType type) {
return List.of();
}
@Override
public boolean isValidProvider(Identifier id, ModdedDataType type) {
public boolean isValidProvider(String id, ModdedDataType type) {
return false;
}
@@ -6,6 +6,7 @@ import art.arcane.iris.world.lifecycle.LifecycleOperationCoordinator;
import art.arcane.iris.pack.PackDownloader;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.CommandNode;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeCommandRegistration;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.Bootstrap;
@@ -27,7 +28,7 @@ public class IrisModdedCommandParityTest {
Bootstrap.bootStrap();
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
IrisModdedCommands.register(dispatcher);
IrisModdedCommands.register(new NativeCommandRegistration(dispatcher));
CommandNode<CommandSourceStack> iris = child(dispatcher.getRoot(), "iris");
CommandNode<CommandSourceStack> language = child(iris, "language");
@@ -183,7 +184,7 @@ public class IrisModdedCommandParityTest {
Bootstrap.bootStrap();
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
IrisModdedCommands.register(dispatcher);
IrisModdedCommands.register(new NativeCommandRegistration(dispatcher));
CommandNode<CommandSourceStack> iris = child(dispatcher.getRoot(), "iris");
assertNotNull("iris", iris.getCommand());
@@ -2,7 +2,7 @@ package art.arcane.iris.modded.command;
import art.arcane.iris.structure.nativegen.IrisNativeStructureDecision;
import art.arcane.iris.structure.nativegen.NativeStructureGenerationStatus;
import art.arcane.iris.nativegen.NativeStructureLocateResults;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureLocateResults;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import org.junit.Test;
@@ -1,6 +1,6 @@
package art.arcane.iris.modded.command;
import net.minecraft.core.BlockPos;
import art.arcane.volmlib.nativelib.terrain.NativeBlockPoint;
import org.junit.Test;
import java.util.List;
@@ -25,29 +25,29 @@ public class ModdedDustRevealerTest {
@Test
public void revealTraversalUsesDiagonalAdjacencyButNotDisconnectedBlocks() {
Set<BlockPos> object = Set.of(
new BlockPos(0, 0, 0),
new BlockPos(1, 1, 1),
new BlockPos(3, 3, 3));
List<BlockPos> hits = ModdedDustRevealer.collect(
new BlockPos(0, 0, 0),
Set<NativeBlockPoint> object = Set.of(
new NativeBlockPoint(0, 0, 0),
new NativeBlockPoint(1, 1, 1),
new NativeBlockPoint(3, 3, 3));
List<NativeBlockPoint> hits = ModdedDustRevealer.collect(
new NativeBlockPoint(0, 0, 0),
"object",
-64,
-64,
320,
new AtomicBoolean(),
(int x, int relativeY, int z) ->
object.contains(new BlockPos(x, relativeY - 64, z))
object.contains(new NativeBlockPoint(x, relativeY - 64, z))
? "object"
: null);
assertEquals(List.of(new BlockPos(0, 0, 0), new BlockPos(1, 1, 1)), hits);
assertEquals(List.of(new NativeBlockPoint(0, 0, 0), new NativeBlockPoint(1, 1, 1)), hits);
}
@Test
public void cancelledRevealDoesNoTraversal() {
List<BlockPos> hits = ModdedDustRevealer.collect(
new BlockPos(0, 0, 0),
List<NativeBlockPoint> hits = ModdedDustRevealer.collect(
new NativeBlockPoint(0, 0, 0),
"object",
-64,
-64,
@@ -6,7 +6,7 @@ import art.arcane.volmlib.util.localization.PluginLanguageService;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeCommandRegistration;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.server.Bootstrap;
@@ -67,13 +67,13 @@ public class ModdedLanguageCommandsTest {
language.when(IrisLanguage::availableLocales).thenReturn(Set.of("de_DE"));
language.when(() -> IrisLanguage.plain(DirectorHelpMessages.BACK)).thenReturn("Back");
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
dispatcher.register(Commands.literal("iris").then(ModdedLanguageCommands.tree()));
new NativeCommandRegistration(dispatcher).register(NativeCommandRegistration.literal("iris").then(ModdedLanguageCommands.tree()));
assertEquals(1, dispatcher.execute("iris language", source));
}
assertEquals(6, rendered.size());
assertEquals(ModdedCommandFeedback.banner("/iris language"), rendered.getFirst());
assertEquals(ModdedCommandFeedback.banner("/iris language").getString(), rendered.getFirst().getString());
assertEquals(new ClickEvent.RunCommand("/iris"), rendered.get(1).getStyle().getClickEvent());
assertEquals("Iris language: en_US", rendered.get(2).getString());
Component locale = rendered.get(3);
@@ -82,7 +82,7 @@ public class ModdedLanguageCommandsTest {
assertEquals(new ClickEvent.RunCommand("/iris language self de_DE"),
locale.getSiblings().getFirst().getStyle().getClickEvent());
assertEquals(new ClickEvent.RunCommand("/iris language self reset"), rendered.get(4).getStyle().getClickEvent());
assertEquals(ModdedCommandFeedback.footer(), rendered.getLast());
assertEquals(ModdedCommandFeedback.footer().getString(), rendered.getLast().getString());
}
private void assertPersonalCompletion(String requested, String selected, String expected) throws Exception {
@@ -114,7 +114,7 @@ public class ModdedLanguageCommandsTest {
try (MockedStatic<IrisLanguage> language = mockStatic(IrisLanguage.class)) {
language.when(IrisLanguage::selections).thenReturn(service);
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
dispatcher.register(Commands.literal("iris").then(ModdedLanguageCommands.tree()));
new NativeCommandRegistration(dispatcher).register(NativeCommandRegistration.literal("iris").then(ModdedLanguageCommands.tree()));
assertEquals(1, dispatcher.execute("iris language self " + requested, source));
assertTrue(rendered.isEmpty());
selection.complete(null);
@@ -0,0 +1,104 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.configuration.IrisSettings;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.modded.ModdedGenPool;
import art.arcane.volmlib.nativelib.terrain.NativePregenRuntime;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ModdedPregenMethodLifecycleTest {
private MockedStatic<IrisSettings> settings;
private NativePregenRuntime runtime;
private ModdedPregenMethod method;
@Before
public void prepare() {
settings = mockStatic(IrisSettings.class);
IrisSettings configured = new IrisSettings();
settings.when(IrisSettings::get).thenReturn(configured);
runtime = mock(NativePregenRuntime.class);
when(runtime.worldIdentity()).thenReturn("example:terrain");
Engine engine = mock(Engine.class);
when(engine.getHeight()).thenReturn(384);
method = new ModdedPregenMethod(new ModdedPregenMethod.Configuration(runtime, engine, true));
}
@After
public void cleanup() {
settings.close();
}
@Test
public void periodicSaveRunsOnlyAfterTheServerExecutesIt() {
method.save();
verify(runtime, never()).save();
ArgumentCaptor<Runnable> queued = ArgumentCaptor.forClass(Runnable.class);
verify(runtime).execute(queued.capture());
when(runtime.isServerThread()).thenReturn(true);
queued.getValue().run();
verify(runtime).save();
}
@Test
public void shutdownCanClaimTheFinalSaveWithoutQueuingWorkToItsOwnThread() {
when(runtime.isServerThread()).thenReturn(true);
assertTrue(method.deferFinalSaveToServerThread());
method.close();
assertTrue(method.hasPendingFinalSave());
verify(runtime, never()).save();
method.completeDeferredFinalSave();
method.completeDeferredFinalSave();
assertFalse(method.hasPendingFinalSave());
verify(runtime, times(1)).save();
verify(runtime, never()).execute(any());
}
@Test
public void asynchronousCallerCannotClaimTheShutdownSave() {
assertFalse(method.deferFinalSaveToServerThread());
assertThrows(IllegalStateException.class, method::completeDeferredFinalSave);
verify(runtime, never()).save();
}
@Test
public void failedFinalSaveStillRestoresTheEmptyServerPauseSetting() {
AtomicInteger pause = new AtomicInteger(60);
when(runtime.supportsPauseWhenEmpty()).thenReturn(true);
when(runtime.pauseWhenEmptySeconds()).thenAnswer(call -> pause.get());
doAnswer(call -> {
pause.set(call.getArgument(0, Integer.class));
return null;
}).when(runtime).pauseWhenEmptySeconds(anyInt());
when(runtime.isServerThread()).thenReturn(true);
IllegalStateException failure = new IllegalStateException("save failed");
doThrow(failure).when(runtime).save();
try (MockedStatic<ModdedGenPool> pool = mockStatic(ModdedGenPool.class)) {
method.init();
assertEquals(0, pause.get());
assertSame(failure, assertThrows(IllegalStateException.class, method::close));
}
assertEquals(60, pause.get());
}
}
@@ -0,0 +1,95 @@
package art.arcane.iris.modded.command;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
import art.arcane.volmlib.nativelib.terrain.NativeBlockPoint;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedPlatformWorld;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeEditWorld;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.server.Bootstrap;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class NativeEditWorldTest {
@BeforeClass
public static void bootstrapRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void repeatedWritesKeepTheOriginalUndoState() {
ServerLevel level = mock(ServerLevel.class);
BlockPos point = new BlockPos(2, 64, 3);
when(level.getBlockState(point)).thenReturn(Blocks.STONE.defaultBlockState(), Blocks.DIRT.defaultBlockState());
NativeEditWorld.EditSession session = new NativeEditWorld(new ModdedPlatformWorld(level))
.editSession(new NativeEditWorld.EditOptions(1, 256, true));
assertEquals(NativeEditWorld.WriteResult.BLOCK, session.set(2, 64, 3, ModdedBlockState.of(Blocks.DIRT.defaultBlockState(), null)));
assertEquals(NativeEditWorld.WriteResult.AIR, session.set(2, 64, 3, ModdedBlockState.of(Blocks.AIR.defaultBlockState(), null)));
assertEquals(1, session.restore(failure -> { throw new AssertionError(failure.error()); }));
verify(level).setBlock(point, Blocks.STONE.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_KNOWN_SHAPE);
}
@Test
public void protectedBedrockAndOutOfRangeWritesNeverEnterUndo() {
ServerLevel level = mock(ServerLevel.class);
when(level.getBlockState(any())).thenReturn(Blocks.BEDROCK.defaultBlockState());
NativeEditWorld.EditSession session = new NativeEditWorld(new ModdedPlatformWorld(level))
.editSession(new NativeEditWorld.EditOptions(1, 256, true));
ModdedBlockState stone = ModdedBlockState.of(Blocks.STONE.defaultBlockState(), null);
assertEquals(NativeEditWorld.WriteResult.SKIPPED, session.set(0, 0, 0, stone));
assertEquals(NativeEditWorld.WriteResult.SKIPPED, session.set(0, 256, 0, stone));
assertEquals(NativeEditWorld.WriteResult.SKIPPED, session.set(0, 64, 0, stone));
assertTrue(session.empty());
verify(level, never()).setBlock(any(), any(), anyInt());
}
@Test
public void captureOmitsOnlyRegularAirAndPreservesCaveAir() {
ServerLevel level = mock(ServerLevel.class);
when(level.getBlockState(any())).thenAnswer(invocation -> {
BlockPos pos = invocation.getArgument(0);
return pos.getX() == 0 ? Blocks.AIR.defaultBlockState() : Blocks.CAVE_AIR.defaultBlockState();
});
NativeEditWorld.CaptureTarget target = mock(NativeEditWorld.CaptureTarget.class);
new NativeEditWorld(new ModdedPlatformWorld(level)).capture(
new NativeEditWorld.Bounds(new NativeBlockPoint(0, 0, 0), new NativeBlockPoint(1, 0, 0)), target);
verify(target).block(1, 0, 0, ModdedBlockState.of(Blocks.CAVE_AIR.defaultBlockState(), null));
verify(target, never()).block(eq(0), anyInt(), anyInt(), any());
}
@Test
public void reopenedDimensionDoesNotAcceptTheOldWorldIdentity() {
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel original = mock(ServerLevel.class);
ServerLevel replacement = mock(ServerLevel.class);
when(original.getServer()).thenReturn(server);
when(original.dimension()).thenReturn(Level.OVERWORLD);
when(server.getLevel(Level.OVERWORLD)).thenReturn(original, replacement);
NativeEditWorld world = new NativeEditWorld(new ModdedPlatformWorld(original));
assertTrue(world.current());
assertFalse(world.current());
assertTrue(world.represents(new ModdedPlatformWorld(original)));
assertFalse(world.represents(new ModdedPlatformWorld(replacement)));
}
}
@@ -0,0 +1,55 @@
package art.arcane.iris.modded.command;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeCommandText;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeItemStack;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeTaggedItems;
import net.minecraft.SharedConstants;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.server.Bootstrap;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.item.Items;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class NativeTaggedItemsTest {
@BeforeClass
public static void bootstrapRegistries() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
if (!Items.BLAZE_ROD.builtInRegistryHolder().areComponentsBound()) {
Items.BLAZE_ROD.builtInRegistryHolder().bindComponents(DataComponentMap.builder()
.set(DataComponents.MAX_STACK_SIZE, 64).build());
}
}
@Test
public void toolRetainsNameLoreFlagsAndHiddenUnbreakableMarker() {
NativeItemStack item = NativeTaggedItems.create(new NativeTaggedItems.Options("minecraft:blaze_rod",
NativeCommandText.literal("Selection"), List.of(NativeCommandText.literal("First corner")),
"selection_tool", true, true));
assertSame(Items.BLAZE_ROD, item.stack().getItem());
assertEquals("Selection", item.stack().get(DataComponents.CUSTOM_NAME).getString());
assertEquals("First corner", item.stack().get(DataComponents.LORE).lines().getFirst().getString());
assertTrue(item.stack().get(DataComponents.CUSTOM_DATA).copyTag().getBooleanOr("selection_tool", false));
assertTrue(item.stack().get(DataComponents.ENCHANTMENT_GLINT_OVERRIDE));
assertTrue(item.stack().has(DataComponents.UNBREAKABLE));
assertTrue(item.stack().get(DataComponents.TOOLTIP_DISPLAY).hiddenComponents().contains(DataComponents.UNBREAKABLE));
}
@Test
public void editingSoundKeysResolveToTheOriginalEvents() {
assertSame(SoundEvents.END_PORTAL_FRAME_FILL, BuiltInRegistries.SOUND_EVENT.getValue(Identifier.parse("minecraft:block.end_portal_frame.fill")));
assertSame(SoundEvents.LODESTONE_COMPASS_LOCK, BuiltInRegistries.SOUND_EVENT.getValue(Identifier.parse("minecraft:item.lodestone_compass.lock")));
assertSame(SoundEvents.AMETHYST_BLOCK_CHIME, BuiltInRegistries.SOUND_EVENT.getValue(Identifier.parse("minecraft:block.amethyst_block.chime")));
}
}
@@ -1,5 +1,7 @@
package art.arcane.iris.modded.service;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedPlatformWorld;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.generation.runtime.EngineMetrics;
import art.arcane.iris.world.IrisWorld;
@@ -49,13 +51,14 @@ public class ModdedChunkUpdateServiceTest {
when(engine.getMetrics()).thenReturn(new EngineMetrics(8));
ServerLevel level = mock(ServerLevel.class);
when(level.getMinY()).thenReturn(-64);
when(level.getMaxY()).thenReturn(320);
when(level.getMaxY()).thenReturn(319);
when(level.getHeight()).thenReturn(384);
BlockPos position = new BlockPos(15, -59, 14);
BlockState falling = Blocks.WATER.defaultBlockState().setValue(LiquidBlock.LEVEL, 8);
when(level.getBlockState(position)).thenReturn(falling);
UpdateRecordingMantleChunk chunk = new UpdateRecordingMantleChunk();
new ModdedChunkUpdateService().runUpdatePass(engine, level, 0, 0, chunk);
new ModdedChunkUpdateService().runUpdatePass(engine, new ModdedPlatformWorld(level), 0, 0, chunk);
assertEquals(8, falling.getValue(LiquidBlock.LEVEL).intValue());
if (falling.getFluidState().hasProperty(FlowingFluid.FALLING)) {
@@ -5,6 +5,7 @@ import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.item.ItemStack;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeItemStack;
import net.minecraft.world.item.Items;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -40,15 +41,15 @@ public class ModdedTreeFellerPresentationTest {
@Test
public void compatibleDropsConsolidateWithoutExceedingStackLimits() {
List<ItemStack> drops = ModdedTreeFellerPresentation.consolidateDrops(List.of(
new ItemStack(Items.OAK_LOG, 48),
new ItemStack(Items.OAK_LOG, 48),
new ItemStack(Items.BIRCH_LOG, 3)
List<NativeItemStack> drops = ModdedTreeFellerPresentation.consolidateDrops(List.of(
NativeItemStack.of(new ItemStack(Items.OAK_LOG, 48)),
NativeItemStack.of(new ItemStack(Items.OAK_LOG, 48)),
NativeItemStack.of(new ItemStack(Items.BIRCH_LOG, 3))
));
assertEquals(3, drops.size());
assertEquals(64, drops.get(0).getCount());
assertEquals(32, drops.get(1).getCount());
assertEquals(3, drops.get(2).getCount());
assertEquals(64, drops.get(0).count());
assertEquals(32, drops.get(1).count());
assertEquals(3, drops.get(2).count());
}
}
@@ -3,6 +3,10 @@ package art.arcane.iris.modded.service;
import art.arcane.iris.world.IrisWorldBoundary;
import art.arcane.iris.world.IrisWorldBoundaryCenter;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.server.level.ServerLevel;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedPlatformWorld;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -17,7 +21,7 @@ public class ModdedWorldBoundaryTest {
worldBorder.setSafeZone(2.5D);
worldBorder.setDamagePerBlock(0.75D);
ModdedStudioHotloadService.applyWorldBoundary(worldBorder, null);
ModdedStudioHotloadService.applyWorldBoundary(world(worldBorder), null);
assertEquals(3.5D, worldBorder.getCenterX(), 0D);
assertEquals(-4.5D, worldBorder.getCenterZ(), 0D);
@@ -37,7 +41,7 @@ public class ModdedWorldBoundaryTest {
.setDamageBuffer(6.5D)
.setDamageAmount(0.4D);
ModdedStudioHotloadService.applyWorldBoundary(worldBorder, boundary);
ModdedStudioHotloadService.applyWorldBoundary(world(worldBorder), boundary);
assertEquals(12.5D, worldBorder.getCenterX(), 0D);
assertEquals(-7.25D, worldBorder.getCenterZ(), 0D);
@@ -46,4 +50,9 @@ public class ModdedWorldBoundaryTest {
assertEquals(6.5D, worldBorder.getSafeZone(), 0D);
assertEquals(0.4D, worldBorder.getDamagePerBlock(), 0D);
}
private static ModdedPlatformWorld world(WorldBorder border) {
ServerLevel level = mock(ServerLevel.class);
when(level.getWorldBorder()).thenReturn(border);
return new ModdedPlatformWorld(level);
}
}
@@ -1,5 +1,17 @@
package art.arcane.iris.nativegen;
import art.arcane.iris.structure.nativegen.IrisStructurePolicy;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureReferenceRepair;
import art.arcane.volmlib.nativelib.terrain.structure.StructureOwnershipRecordView;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureOwnershipFingerprint;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureVerticalPlacer;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureReferenceEnvelope;
import art.arcane.iris.pack.loading.IrisData;
import art.arcane.iris.generation.runtime.IrisEngine;
import art.arcane.iris.generation.runtime.Engine;
@@ -14,7 +26,7 @@ import art.arcane.iris.structure.nativegen.IrisNativeStructure;
import art.arcane.iris.structure.nativegen.IrisNativeStructureDecision;
import art.arcane.iris.structure.placement.IrisStructurePlacement;
import art.arcane.iris.structure.placement.IrisStructureTerrain;
import art.arcane.iris.structure.placement.IrisStructureTerrainMode;
import art.arcane.volmlib.util.structure.StructureTerrainMode;
import art.arcane.iris.structure.nativegen.NativeStructureGenerationStatus;
import art.arcane.volmlib.util.collection.KList;
import com.github.benmanes.caffeine.cache.Cache;
@@ -75,18 +87,16 @@ public class NativeStructureReferenceRepairTest {
NativeStructureVerticalPlacer.alignOceanMonumentToSeaLevel(
generated, 0, 80, -64, 320);
IrisStructureTerrain terrain = new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.FORCE_CARVE)
.setMode(StructureTerrainMode.FORCE_CARVE)
.setHorizontalPadding(24);
StructureStart wrapped = NativeStructureReferenceEnvelope.wrap(
generated,
structure,
0,
terrain);
NativeStructureOwnershipRecord ownership = NativeStructureOwnershipFingerprint.capture(
"minecraft:monument",
wrapped,
plan(origin, NativeStructureReferenceEnvelope.contentBounds(wrapped).minY()),
NativeStructureReferenceEnvelope.referenceBounds(wrapped, structure, terrain));
NativeStructureOwnershipRecord ownership = NativeStructureOwnershipRecord.capture(
NativeStructureOwnershipFingerprint.capture(
"minecraft:monument", wrapped, NativeStructureReferenceEnvelope.referenceBounds(wrapped, structure, terrain)), plan(origin, NativeStructureReferenceEnvelope.contentBounds(wrapped).minY()));
PiecesContainer regeneratedPieces = OceanMonumentStructure.regeneratePiecesAfterLoad(
origin, seed, new PiecesContainer(wrapped.getPieces()));
StructureStart reloaded = new StructureStart(structure, origin, 0, regeneratedPieces);
@@ -128,15 +138,13 @@ public class NativeStructureReferenceRepairTest {
NativeStructureVerticalPlacer.alignOceanMonumentToSeaLevel(
generated, 0, 80, -64, 320);
IrisStructureTerrain terrain = new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.FORCE_CARVE)
.setMode(StructureTerrainMode.FORCE_CARVE)
.setHorizontalPadding(24);
StructureStart start = NativeStructureReferenceEnvelope.wrap(
generated, structure, 0, terrain);
NativeStructureOwnershipRecord ownership = NativeStructureOwnershipFingerprint.capture(
structureKey,
start,
plan(origin, NativeStructureReferenceEnvelope.contentBounds(start).minY()),
NativeStructureReferenceEnvelope.referenceBounds(start, structure, terrain));
NativeStructureOwnershipRecord ownership = NativeStructureOwnershipRecord.capture(
NativeStructureOwnershipFingerprint.capture(
structureKey, start, NativeStructureReferenceEnvelope.referenceBounds(start, structure, terrain)), plan(origin, NativeStructureReferenceEnvelope.contentBounds(start).minY()));
IrisDimension dimension = new IrisDimension();
dimension.getImportedStructures().getDisabled().add(structureKey);
IrisData data = allocateWithoutConstructor(IrisData.class);
@@ -165,7 +173,7 @@ public class NativeStructureReferenceRepairTest {
registry, serverLevel, originChunk, emptyScannedChunk);
ProtoChunk coveredChunk = emptyChunk(coveredTarget);
NativeStructureReferenceRepair.createReferences(
engine, level, structureManager, coveredChunk);
new IrisStructurePolicy(engine), level, structureManager, coveredChunk);
assertSame(start, originChunk.getStartForStructure(structure));
assertTrue(originChunk.getStartForStructure(structure).isValid());
@@ -173,7 +181,7 @@ public class NativeStructureReferenceRepairTest {
ProtoChunk uncoveredChunk = emptyChunk(uncoveredTarget);
NativeStructureReferenceRepair.createReferences(
engine, level, structureManager, uncoveredChunk);
new IrisStructurePolicy(engine), level, structureManager, uncoveredChunk);
assertSame(start, originChunk.getStartForStructure(structure));
assertTrue(originChunk.getStartForStructure(structure).isValid());
@@ -248,9 +256,9 @@ public class NativeStructureReferenceRepairTest {
for (ChunkPos candidate : candidates) {
if (!ownership.covers(candidate.x(), candidate.z())
&& Math.abs(candidate.x() - originX)
<= NativeStructureOwnershipRecord.MAX_REFERENCE_DISTANCE_CHUNKS
<= StructureOwnershipRecordView.MAX_REFERENCE_DISTANCE_CHUNKS
&& Math.abs(candidate.z() - originZ)
<= NativeStructureOwnershipRecord.MAX_REFERENCE_DISTANCE_CHUNKS) {
<= StructureOwnershipRecordView.MAX_REFERENCE_DISTANCE_CHUNKS) {
return candidate;
}
}
@@ -1,7 +1,11 @@
package art.arcane.iris.nativegen;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureTerrainIntegrator;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureSurfaceFitter;
import art.arcane.iris.structure.placement.IrisStructureTerrain;
import art.arcane.iris.structure.placement.IrisStructureTerrainMode;
import art.arcane.volmlib.util.structure.StructureTerrainMode;
import net.minecraft.SharedConstants;
import net.minecraft.core.HolderSet;
import net.minecraft.server.Bootstrap;
@@ -42,7 +46,7 @@ public class NativeStructureVacuumParityTest {
NativeStructureTerrainIntegrator.TerrainTarget target =
new NativeStructureTerrainIntegrator.TerrainTarget(
"test:vacuum", start,
new IrisStructureTerrain().setMode(IrisStructureTerrainMode.VACUUM));
new IrisStructureTerrain().setMode(StructureTerrainMode.VACUUM));
assertTrue(NativeStructureSurfaceFitter.requiresSurfaceTerrain(target));
assertFalse(NativeStructureTerrainIntegrator.clearsLegacyTemplateAir(