diff --git a/docs/PORTING.md b/docs/PORTING.md index 98fb28c..9d7fcb4 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -335,6 +335,11 @@ lighting, weather, day length, celestial angle, and celestial phase on the book's right-hand description page. This works for held books and Book Stands without copying mutable Age-generation data onto the item. +Version 0.2.23.0 applies Grid Biome Distribution using two deterministic +Age-seeded biomes in Legacy's diagonal checkerboard layout. Each cell is one +16-by-16-block chunk, and the built-in serializable biome source reconstructs +the same layout whenever the Age reloads. + Version 0.2.14.0 restores the legacy Linking and Descriptive Book artwork for inventory items and gives each book its matching open-book texture when placed on a Book Stand. Return Linking Books created inside another Age also retain and diff --git a/gradle.properties b/gradle.properties index 11d09c4..71620a2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -35,7 +35,7 @@ mod_name=Rivencraft # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=LGPL-3.0-or-later # The mod version. Rivencraft uses the x.y.z.b policy documented in README.md. -mod_version=0.2.22.1 +mod_version=0.2.23.0 immersive_portals_version=6.0.7 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. diff --git a/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java b/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java index 0208825..d14f31a 100644 --- a/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java +++ b/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java @@ -21,7 +21,7 @@ public record AgeDefinition( public static final ResourceLocation RANDOM_VANILLA_PROFILE = ResourceLocation.fromNamespaceAndPath( Rivencraft.MOD_ID, "random_vanilla" ); - public static final int CURRENT_GENERATION_VERSION = 10; + public static final int CURRENT_GENERATION_VERSION = 11; public AgeDefinition { Objects.requireNonNull(id, "id"); diff --git a/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java b/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java index cde5c89..e965e41 100644 --- a/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java +++ b/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java @@ -45,6 +45,7 @@ public final class AgeDimensionService { private static final int SURFACE_SEARCH_RADIUS = 16; private static final int FALLBACK_PLATFORM_Y = 63; private static final int CAVE_SPAWN_SEARCH_Y = 64; + private static final int GRID_BIOME_SCALE = 0; private static final int TILED_BIOME_SCALE = 4; private AgeDimensionService() { @@ -291,12 +292,19 @@ public final class AgeDimensionService { int index = Math.floorMod(Long.hashCode(age.seed() ^ 0x53494E474C454249L), biomes.size()); return new FixedBiomeSource(biomes.get(index)); } - if (age.traits().biomeDistribution() == AgeTraits.BiomeDistribution.TILED && biomes.size() >= 2) { + AgeTraits.BiomeDistribution distribution = age.traits().biomeDistribution(); + if ((distribution == AgeTraits.BiomeDistribution.TILED + || distribution == AgeTraits.BiomeDistribution.GRID) && biomes.size() >= 2) { List> selected = new java.util.ArrayList<>(biomes); - Collections.shuffle(selected, new java.util.Random(age.seed() ^ 0x54494C454442494FL)); + long salt = distribution == AgeTraits.BiomeDistribution.GRID + ? 0x4752494442494F4DL + : 0x54494C454442494FL; + Collections.shuffle(selected, new java.util.Random(age.seed() ^ salt)); return new CheckerboardColumnBiomeSource( HolderSet.direct(List.of(selected.get(0), selected.get(1))), - TILED_BIOME_SCALE + distribution == AgeTraits.BiomeDistribution.GRID + ? GRID_BIOME_SCALE + : TILED_BIOME_SCALE ); } return MultiNoiseBiomeSource.createFromPreset( diff --git a/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java b/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java index 9af0b8b..0c3138d 100644 --- a/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java +++ b/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java @@ -174,6 +174,15 @@ public final class LinkingGameTests { selectedTraits.celestialAngle(), selectedTraits.celestialPhase() ) + : profile.equals(AgeGenerationProfiles.ISLAND) + ? new AgeTraits( + AgeTraits.BiomeDistribution.GRID, + selectedTraits.lighting(), + selectedTraits.weather(), + selectedTraits.celestialPeriod(), + selectedTraits.celestialAngle(), + selectedTraits.celestialPhase() + ) : selectedTraits; AgeDefinition definition = new AgeDefinition( id, @@ -218,6 +227,24 @@ public final class LinkingGameTests { helper.assertTrue(origin.equals(diagonalTile), "Diagonal 256-block Tiled squares must repeat the biome"); } + if (profile.equals(AgeGenerationProfiles.ISLAND)) { + var biomeSource = level.getChunkSource().getGenerator().getBiomeSource(); + helper.assertValueEqual( + biomeSource.possibleBiomes().size(), + 2, + "Grid Biome Distribution must expose exactly two seeded biomes" + ); + var origin = biomeSource.getNoiseBiome(0, 0, 0, null); + var insideOriginChunk = biomeSource.getNoiseBiome(3, 0, 3, null); + var eastChunk = biomeSource.getNoiseBiome(4, 0, 0, null); + var diagonalChunk = biomeSource.getNoiseBiome(4, 0, 4, null); + helper.assertTrue(origin.equals(insideOriginChunk), + "Grid biomes must remain constant inside each 16-block chunk"); + helper.assertFalse(origin.equals(eastChunk), + "Adjacent Grid chunks must alternate biomes"); + helper.assertTrue(origin.equals(diagonalChunk), + "Diagonal Grid chunks must repeat the biome"); + } if (definition.traits().lighting() == AgeTraits.Lighting.DARK) { helper.assertFalse(level.dimensionType().hasSkyLight(), "Dark Lighting Ages must suppress dimension skylight");