Public Access
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a287e092f5 |
No files matched your search
+1
-1
@@ -36,7 +36,7 @@ mod_name=Rivencraft
|
|||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# 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
|
mod_license=LGPL-3.0-or-later
|
||||||
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
|
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
|
||||||
mod_version=0.4.19.2
|
mod_version=0.4.20.0
|
||||||
immersive_portals_version=6.0.7
|
immersive_portals_version=6.0.7
|
||||||
terrablender_version=4.1.0.8
|
terrablender_version=4.1.0.8
|
||||||
serene_seasons_version_id=B6nTjh4b
|
serene_seasons_version_id=B6nTjh4b
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.Random;
|
|||||||
import net.dnorberg.rivencraft.Rivencraft;
|
import net.dnorberg.rivencraft.Rivencraft;
|
||||||
import net.dnorberg.rivencraft.compat.ImmersivePortalsChunkLoaders;
|
import net.dnorberg.rivencraft.compat.ImmersivePortalsChunkLoaders;
|
||||||
import net.dnorberg.rivencraft.compat.SereneSeasonsCompatibility;
|
import net.dnorberg.rivencraft.compat.SereneSeasonsCompatibility;
|
||||||
|
import net.dnorberg.rivencraft.compat.TerraBlenderBiomes;
|
||||||
import net.dnorberg.rivencraft.writing.OrderedWriting;
|
import net.dnorberg.rivencraft.writing.OrderedWriting;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.GlobalPos;
|
import net.minecraft.core.GlobalPos;
|
||||||
@@ -337,9 +338,11 @@ public final class AgeDimensionService {
|
|||||||
Registries.NOISE_SETTINGS, profile.noiseSettings());
|
Registries.NOISE_SETTINGS, profile.noiseSettings());
|
||||||
NoiseGeneratorSettings baseSettings = noiseSettings.getOrThrow(settingsKey).value();
|
NoiseGeneratorSettings baseSettings = noiseSettings.getOrThrow(settingsKey).value();
|
||||||
Holder<NoiseGeneratorSettings> settings = Holder.direct(withBiomeMaterialRules(baseSettings));
|
Holder<NoiseGeneratorSettings> settings = Holder.direct(withBiomeMaterialRules(baseSettings));
|
||||||
|
boolean caveTerrain = AgeBiomeSelection.isCave(profile);
|
||||||
return age.generationVersion() < AgeDefinition.CURRENT_GENERATION_VERSION
|
return age.generationVersion() < AgeDefinition.CURRENT_GENERATION_VERSION
|
||||||
? new NoiseBasedChunkGenerator(biomeSource, settings)
|
? new NoiseBasedChunkGenerator(biomeSource, settings)
|
||||||
: new AgeFeatureChunkGenerator(biomeSource, settings, features, age.seed());
|
: new AgeFeatureChunkGenerator(biomeSource, settings, features, age.seed(),
|
||||||
|
caveTerrain, caveTerrain ? TerraBlenderBiomes.nether(server.registryAccess()) : List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NoiseGeneratorSettings withBiomeMaterialRules(NoiseGeneratorSettings base) {
|
private static NoiseGeneratorSettings withBiomeMaterialRules(NoiseGeneratorSettings base) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import net.dnorberg.rivencraft.writing.SymbolCatalog;
|
|||||||
import net.dnorberg.rivencraft.writing.SymbolReference;
|
import net.dnorberg.rivencraft.writing.SymbolReference;
|
||||||
import net.dnorberg.rivencraft.writing.WritingEntry;
|
import net.dnorberg.rivencraft.writing.WritingEntry;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.gametest.framework.GameTest;
|
import net.minecraft.gametest.framework.GameTest;
|
||||||
import net.minecraft.gametest.framework.GameTestHelper;
|
import net.minecraft.gametest.framework.GameTestHelper;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
@@ -460,6 +461,32 @@ public final class FeatureWritingGameTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GameTest(template = "empty", timeoutTicks = 600)
|
||||||
|
public static void netherCaveBiomeUsesNetherRock(GameTestHelper helper) {
|
||||||
|
var player = helper.makeMockServerPlayerInLevel();
|
||||||
|
OrderedWriting writing = new OrderedWriting(List.of(panel(), page("terrain/cave"),
|
||||||
|
page("biome/nether_wastes"), page("biome/single")));
|
||||||
|
var target = AgeDimensionService.resolve(player,
|
||||||
|
new AgeReference(UUID.randomUUID(), "Nether Cave Materials"), writing).orElseThrow();
|
||||||
|
helper.runAfterDelay(1, () -> {
|
||||||
|
var level = helper.getLevel().getServer().getLevel(target.location().dimension());
|
||||||
|
helper.assertTrue(level != null, "The Nether cave Age must load");
|
||||||
|
var chunk = level.getChunk(0, 0);
|
||||||
|
int[] rock = new int[2];
|
||||||
|
chunk.findBlocks(state -> state.is(Blocks.NETHERRACK) || state.is(Blocks.STONE)
|
||||||
|
|| state.is(Blocks.DEEPSLATE) || state.is(Blocks.DIRT)
|
||||||
|
|| state.is(Blocks.GRASS_BLOCK),
|
||||||
|
(pos, state) -> {
|
||||||
|
if (state.is(Blocks.NETHERRACK)) rock[0]++;
|
||||||
|
else rock[1]++;
|
||||||
|
});
|
||||||
|
helper.assertTrue(rock[0] > 0, "Nether cave terrain must contain netherrack");
|
||||||
|
helper.assertValueEqual(rock[1], 0,
|
||||||
|
"Nether cave terrain must not retain stone, deepslate, dirt, or grass");
|
||||||
|
helper.succeed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static void rejects(GameTestHelper helper, OrderedWriting writing, String expected) {
|
private static void rejects(GameTestHelper helper, OrderedWriting writing, String expected) {
|
||||||
try {
|
try {
|
||||||
AgeGenerationPlan.compile(writing, 87L, AgeGenerationProfiles.STANDARD,
|
AgeGenerationPlan.compile(writing, 87L, AgeGenerationProfiles.STANDARD,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import net.dnorberg.rivencraft.book.AgeFeatureSelection;
|
import net.dnorberg.rivencraft.book.AgeFeatureSelection;
|
||||||
import net.dnorberg.rivencraft.book.AgeStructureSelection;
|
import net.dnorberg.rivencraft.book.AgeStructureSelection;
|
||||||
@@ -16,6 +17,7 @@ import net.minecraft.core.Holder;
|
|||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.core.QuartPos;
|
import net.minecraft.core.QuartPos;
|
||||||
|
import net.minecraft.tags.BiomeTags;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
@@ -55,23 +57,54 @@ public final class AgeFeatureChunkGenerator extends NoiseBasedChunkGenerator {
|
|||||||
instance.group(BiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.getBiomeSource()),
|
instance.group(BiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.getBiomeSource()),
|
||||||
NoiseGeneratorSettings.CODEC.fieldOf("settings").forGetter(generator -> generator.settings),
|
NoiseGeneratorSettings.CODEC.fieldOf("settings").forGetter(generator -> generator.settings),
|
||||||
AgeFeatureSelection.Choice.CODEC.listOf().fieldOf("age_features").forGetter(generator -> generator.features),
|
AgeFeatureSelection.Choice.CODEC.listOf().fieldOf("age_features").forGetter(generator -> generator.features),
|
||||||
Codec.LONG.fieldOf("age_seed").forGetter(generator -> generator.ageSeed))
|
Codec.LONG.fieldOf("age_seed").forGetter(generator -> generator.ageSeed),
|
||||||
|
Codec.BOOL.optionalFieldOf("nether_cave_materials", false).forGetter(generator -> generator.netherCaveMaterials),
|
||||||
|
ResourceLocation.CODEC.listOf().optionalFieldOf("nether_biomes", List.of())
|
||||||
|
.forGetter(generator -> generator.netherBiomeIds))
|
||||||
.apply(instance, AgeFeatureChunkGenerator::new));
|
.apply(instance, AgeFeatureChunkGenerator::new));
|
||||||
|
|
||||||
private final Holder<NoiseGeneratorSettings> settings;
|
private final Holder<NoiseGeneratorSettings> settings;
|
||||||
private final List<AgeFeatureSelection.Choice> features;
|
private final List<AgeFeatureSelection.Choice> features;
|
||||||
private final long ageSeed;
|
private final long ageSeed;
|
||||||
|
private final boolean netherCaveMaterials;
|
||||||
|
private final List<ResourceLocation> netherBiomeIds;
|
||||||
|
|
||||||
public AgeFeatureChunkGenerator(BiomeSource biomes, Holder<NoiseGeneratorSettings> settings,
|
public AgeFeatureChunkGenerator(BiomeSource biomes, Holder<NoiseGeneratorSettings> settings,
|
||||||
List<AgeFeatureSelection.Choice> features, long ageSeed) {
|
List<AgeFeatureSelection.Choice> features, long ageSeed,
|
||||||
|
boolean netherCaveMaterials, List<ResourceLocation> netherBiomeIds) {
|
||||||
super(biomes, settings);
|
super(biomes, settings);
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.features = List.copyOf(features);
|
this.features = List.copyOf(features);
|
||||||
this.ageSeed = ageSeed;
|
this.ageSeed = ageSeed;
|
||||||
|
this.netherCaveMaterials = netherCaveMaterials;
|
||||||
|
this.netherBiomeIds = List.copyOf(netherBiomeIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AgeFeatureSelection.Choice> ageFeatures() { return features; }
|
public List<AgeFeatureSelection.Choice> ageFeatures() { return features; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildSurface(WorldGenRegion level, StructureManager structures, RandomState random, ChunkAccess chunk) {
|
||||||
|
super.buildSurface(level, structures, random, chunk);
|
||||||
|
if (!netherCaveMaterials) return;
|
||||||
|
Set<ResourceLocation> netherIds = Set.copyOf(netherBiomeIds);
|
||||||
|
// The Cave noise router starts with stone even in Nether biomes. Surface rules
|
||||||
|
// only touch exposed layers, so convert the base rock (and any Overworld soil)
|
||||||
|
// before carvers, ores, and biome decorations run. Never change adjacent biomes.
|
||||||
|
chunk.findBlocks(AgeFeatureChunkGenerator::isOverworldCaveMaterial, (pos, state) -> {
|
||||||
|
Holder<net.minecraft.world.level.biome.Biome> biome = chunk.getNoiseBiome(
|
||||||
|
QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ()));
|
||||||
|
if (biome.is(BiomeTags.IS_NETHER)
|
||||||
|
|| biome.unwrapKey().map(key -> netherIds.contains(key.location())).orElse(false)) {
|
||||||
|
chunk.setBlockState(pos, Blocks.NETHERRACK.defaultBlockState(), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isOverworldCaveMaterial(net.minecraft.world.level.block.state.BlockState state) {
|
||||||
|
return state.is(Blocks.STONE) || state.is(Blocks.DEEPSLATE) || state.is(Blocks.TUFF)
|
||||||
|
|| state.is(Blocks.DIRT) || state.is(Blocks.GRASS_BLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MapCodec<? extends ChunkGenerator> codec() { return CODEC; }
|
protected MapCodec<? extends ChunkGenerator> codec() { return CODEC; }
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user