Skip to content

Commit

Permalink
Resolve some Volcanic Island generation issues.
Browse files Browse the repository at this point in the history
- Volcanic Islands now generate in any depth of water
- Fix most "buried" Volcano structures
  • Loading branch information
gniftygnome committed Nov 8, 2024
1 parent baa4cc5 commit 32c4e9c
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 17 deletions.
5 changes: 5 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ sourceSets {
}
}
}

dependencies {
// Biolith for BiomePerimeters in the VolcanoStructure
modImplementation "com.terraformersmc:biolith-fabric:${biolith_version}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.terraformersmc.biolith.api.biomeperimeters.BiomePerimeters;
import com.terraformersmc.terrestria.Terrestria;
import com.terraformersmc.terrestria.init.TerrestriaBiomes;
import com.terraformersmc.terrestria.init.TerrestriaStructures;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.structure.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.intprovider.IntProvider;
import net.minecraft.world.Heightmap;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.biome.source.BiomeCoords;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.biome.source.util.MultiNoiseUtil;
import net.minecraft.world.gen.structure.Structure;
import net.minecraft.world.gen.structure.StructureType;

Expand Down Expand Up @@ -41,11 +47,26 @@ public Optional<StructurePosition> getStructurePosition(Structure.Context contex
int x = context.chunkPos().getCenterX();
int z = context.chunkPos().getCenterZ();
int y = context.chunkGenerator().getHeightInGround(x, z, Heightmap.Type.OCEAN_FLOOR_WG, context.world(), context.noiseConfig());
int seaLevel = context.chunkGenerator().getSeaLevel();
RegistryEntry<Biome> biome = context.chunkGenerator().getBiomeSource().getBiome(BiomeCoords.fromBlock(x),
BiomeCoords.fromBlock(y), BiomeCoords.fromBlock(z), context.noiseConfig().getMultiNoiseSampler());

if (!biome.matchesKey(TerrestriaBiomes.VOLCANIC_ISLAND) &&
!Terrestria.getConfigManager().getGeneralConfig().areOceanVolcanoesEnabled()) {
if (biome.matchesKey(TerrestriaBiomes.VOLCANIC_ISLAND)) {
// Shore volcanoes at the edges and regular volcanoes in the center.
int distance = BiomePerimeters.getOrCreateInstance(
context.dynamicRegistryManager().get(RegistryKeys.BIOME).getOrThrow(TerrestriaBiomes.VOLCANIC_ISLAND), 40)
.getPerimeterDistance(new BiomeAccess(
new BiomeAccessStorage(context.biomeSource(), context.noiseConfig().getMultiNoiseSampler()),
context.seed()), new BlockPos(x, seaLevel, z));

if (this.baseY < seaLevel - 10 && distance >= 20) {
return Optional.empty();
}
if (this.baseY >= seaLevel - 10 && distance < 20) {
return Optional.empty();
}
} else if (!Terrestria.getConfigManager().getGeneralConfig().areOceanVolcanoesEnabled()) {
// No need to consider starting a structure outside Volcanic Island unless sea volcanoes are enabled.
return Optional.empty();
}

Expand All @@ -60,4 +81,12 @@ private void addPieces(StructurePiecesCollector collector, Structure.Context con
public StructureType<?> getType() {
return TerrestriaStructures.VOLCANO_STRUCTURE_TYPE;
}

// Shim class to instantiate a BiomeAccess.Storage from available information.
private record BiomeAccessStorage(BiomeSource biomeSource, MultiNoiseUtil.MultiNoiseSampler noiseSampler) implements BiomeAccess.Storage {
@Override
public RegistryEntry<Biome> getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) {
return biomeSource.getBiome(biomeX, biomeY, biomeZ, noiseSampler);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
import com.terraformersmc.terrestria.biomegen.TerrestriaBiolithGeneration;
import com.terraformersmc.terrestria.surfacebuilders.TerrestriaSurfaceBuilders;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.server.world.ServerWorld;
import org.jetbrains.annotations.Nullable;

public class TerrestriaWorldgen implements ModInitializer {
private static ServerWorld OVERWORLD = null;

@Override
public void onInitialize() {
Expand All @@ -17,5 +21,17 @@ public void onInitialize() {
} else {
Terrestria.LOGGER.warn("Terrestria world generation disabled; Biolith is not present.");
}

// We need access to the Overworld for some surface builders.
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
OVERWORLD = server.getOverworld();
});
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
OVERWORLD = null;
});
}

public static @Nullable ServerWorld getOverworld() {
return OVERWORLD;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import net.minecraft.world.gen.chunk.BlockColumn;

public class CanyonSurfaceBuilder extends BiolithSurfaceBuilder {

private static final OpenSimplexNoise CLIFF_NOISE = new OpenSimplexNoise(346987);

private final BlockState cliffMaterial;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import net.minecraft.world.gen.chunk.BlockColumn;

public class DuneSurfaceBuilder extends BiolithSurfaceBuilder {

private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(3445);

private final BlockState topMaterial;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,68 @@
import com.terraformersmc.biolith.api.biomeperimeters.BiomePerimeters;
import com.terraformersmc.biolith.api.surface.BiolithSurfaceBuilder;
import com.terraformersmc.terraform.noise.OpenSimplexNoise;
import com.terraformersmc.terrestria.TerrestriaWorldgen;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.noise.DoublePerlinNoiseSampler;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.Heightmap;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.gen.chunk.BlockColumn;
import net.minecraft.world.gen.noise.NoiseParametersKeys;

public class OceanIslandSurfaceBuilder extends BiolithSurfaceBuilder {
private static final OpenSimplexNoise ISLAND_NOISE = new OpenSimplexNoise(346987);
private static final int DEEP_DEPTH = 32;
private static final int SHALLOW_DEPTH = 16;
private static final double HEIGHT_FACTOR = 1.1;
private static final int ISLAND_HEIGHT = 12;
private static final double NOISE_SCALE = 9.5d;

private final BlockState topMaterial;
private final BlockState midMaterial;
private final BlockState lowMaterial;
private final BlockState beachMaterial;
private final BlockState underwaterMaterial;
private final boolean deepOcean;

public OceanIslandSurfaceBuilder(BlockState topMaterial, BlockState midMaterial, BlockState lowMaterial, BlockState beachMaterial, BlockState underwaterMaterial, boolean deepOcean) {
public OceanIslandSurfaceBuilder(BlockState topMaterial, BlockState midMaterial, BlockState lowMaterial, BlockState beachMaterial, BlockState underwaterMaterial) {
this.topMaterial = topMaterial;
this.midMaterial = midMaterial;
this.lowMaterial = lowMaterial;
this.beachMaterial = beachMaterial;
this.underwaterMaterial = underwaterMaterial;
this.deepOcean = deepOcean;
}

@Override
public void generate(BiomeAccess biomeAccess, BlockColumn column, Random rand, Chunk chunk, Biome biome, int x, int z, int vHeight, int seaLevel) {
int delta = (int)((deepOcean ? DEEP_DEPTH : SHALLOW_DEPTH) * HEIGHT_FACTOR);
ServerWorld overworld = TerrestriaWorldgen.getOverworld();
if (overworld == null) {
throw new IllegalStateException("Overworld does not exist during Overworld surface generation...");
}
DoublePerlinNoiseSampler surface = overworld.getChunkManager().chunkLoadingManager.noiseConfig
.getOrCreateSampler(NoiseParametersKeys.SURFACE);

// We are going to accept the ocean surface noise and just raise it so we need the ocean surface.
// Find the original top Y value, the desired top Y value, and the delta between them.
// We can't trust the provided vHeight because we need the ocean floor instead of surface.
vHeight = chunk.sampleHeightmap(Heightmap.Type.OCEAN_FLOOR_WG, x & 0xf, z & 0xf);
int top = seaLevel + ISLAND_HEIGHT + (int) (NOISE_SCALE * surface.sample(x, seaLevel, z));
int delta = MathHelper.clamp(top - vHeight, 0, 128);

// Work around noise-adapting structures (like villages)...
if (vHeight >= 60) {
if (vHeight >= seaLevel - 2) {
vHeight = seaLevel - delta;
}

// Delta is how much we are raising the surface. Reduce it as we approach the edge of the island biome.
int borderAdjustment = BiomePerimeters.getOrCreateInstance(biome, 40)
.getPerimeterDistance(biomeAccess, new BlockPos(x, 62, z));
.getPerimeterDistance(biomeAccess, new BlockPos(x, seaLevel, z));
if (borderAdjustment < 32) {
delta = delta * borderAdjustment / 32;
}

int top = vHeight + delta;
top = vHeight + delta;
for (int y = 0; y <= top; y++) {
BlockState originalState = column.getState(y);
if (originalState.isOf(Blocks.STONE) || originalState.isOf(Blocks.WATER) || originalState.isAir()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public static void init() {
TerrestriaBlocks.ANDISOL.getDirt().getDefaultState(),
TerrestriaBlocks.VOLCANIC_ROCK.plain.full.getDefaultState(),
TerrestriaBlocks.BLACK_SAND.getDefaultState(),
Blocks.SAND.getDefaultState(),
true
Blocks.SAND.getDefaultState()
).setBiomeKey(TerrestriaBiomes.VOLCANIC_ISLAND));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
accessWidener v1 named

accessible field net/minecraft/server/world/ServerChunkLoadingManager noiseConfig Lnet/minecraft/world/gen/noise/NoiseConfig;

0 comments on commit 32c4e9c

Please sign in to comment.