Apply single biome Age distribution
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-22 16:53:41 -04:00
1 parent 98ecc797fd
commit 8f692b181c
5 files changed
+52 -5

No files matched your search

+8
View File
@@ -309,6 +309,14 @@ instead of advancing and correcting their time once per tick. This keeps the
integer day time fixed while preventing the client skybox from visually
bouncing between adjacent celestial positions.
Version 0.2.21.0 begins applying persisted biome-distribution traits. Native
Distribution retains Minecraft's data-pack-aware Overworld climate source.
Single Biome Distribution deterministically selects one registered biome from
the Age seed and uses it throughout compatible noise-based terrain. Flat and
Void profiles retain their profile-specific biome sources. Legacy's scaled,
tiled, and grid layouts require dedicated modern biome sources and remain the
next distribution work.
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
+1 -1
View File
@@ -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.20.2
mod_version=0.2.21.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.
@@ -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 = 7;
public static final int CURRENT_GENERATION_VERSION = 8;
public AgeDefinition {
Objects.requireNonNull(id, "id");
@@ -5,6 +5,7 @@ import dev.galacticraft.dynamicdimensions.api.event.DynamicDimensionLoadCallback
import java.util.Optional;
import java.util.OptionalLong;
import java.util.List;
import java.util.Comparator;
import net.dnorberg.rivencraft.Rivencraft;
import net.dnorberg.rivencraft.compat.ImmersivePortalsChunkLoaders;
import net.minecraft.core.BlockPos;
@@ -20,6 +21,9 @@ import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
import net.minecraft.world.level.biome.MultiNoiseBiomeSourceParameterLists;
import net.minecraft.world.level.chunk.ChunkGenerator;
@@ -263,12 +267,31 @@ public final class AgeDimensionService {
// island. Both use Overworld biomes and dimension environment.
// random_vanilla is retained as a migration alias for existing Ages.
return new NoiseBasedChunkGenerator(
MultiNoiseBiomeSource.createFromPreset(
biomeParameters.getOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD)),
createBiomeSource(server, age, biomeParameters),
noiseSettings.getOrThrow(settingsKey)
);
}
private static BiomeSource createBiomeSource(
MinecraftServer server,
AgeDefinition age,
net.minecraft.core.HolderGetter<net.minecraft.world.level.biome.MultiNoiseBiomeSourceParameterList> biomeParameters
) {
if (age.traits().biomeDistribution() == AgeTraits.BiomeDistribution.SINGLE) {
List<net.minecraft.core.Holder.Reference<Biome>> biomes = server.registryAccess()
.lookupOrThrow(Registries.BIOME)
.listElements()
.sorted(Comparator.comparing(holder -> holder.key().location().toString()))
.toList();
if (!biomes.isEmpty()) {
int index = Math.floorMod(Long.hashCode(age.seed() ^ 0x53494E474C454249L), biomes.size());
return new FixedBiomeSource(biomes.get(index));
}
}
return MultiNoiseBiomeSource.createFromPreset(
biomeParameters.getOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD));
}
private static DimensionType createDimensionType(AgeDefinition age) {
AgeTraits.Lighting lighting = age.traits().lighting();
boolean hasSkyLight = lighting != AgeTraits.Lighting.DARK;
@@ -166,7 +166,16 @@ public final class LinkingGameTests {
Rivencraft.MOD_ID, "gametest/" + profile.getPath() + "_" + id
),
null,
AgeTraits.select(id.getMostSignificantBits())
profile.equals(AgeGenerationProfiles.STANDARD)
? new AgeTraits(
AgeTraits.BiomeDistribution.SINGLE,
AgeTraits.Lighting.NORMAL,
AgeTraits.Weather.NORMAL,
1.0D,
0.0F,
0.0F
)
: AgeTraits.select(id.getMostSignificantBits())
);
var level = AgeDimensionService.ensureLoaded(helper.getLevel().getServer(), definition);
helper.assertTrue(level != null, "The " + profile + " profile must load a runtime dimension");
@@ -176,6 +185,13 @@ public final class LinkingGameTests {
helper.assertTrue(level.dimension().location().equals(definition.dimensionId()),
"The " + profile + " profile must retain its assigned dimension id");
if (profile.equals(AgeGenerationProfiles.STANDARD)) {
helper.assertValueEqual(
level.getChunkSource().getGenerator().getBiomeSource().possibleBiomes().size(),
1,
"Single Biome Distribution must expose exactly one biome"
);
}
if (definition.traits().lighting() == AgeTraits.Lighting.DARK) {
helper.assertFalse(level.dimensionType().hasSkyLight(),
"Dark Lighting Ages must suppress dimension skylight");