Complete phase 8 underground systems
This commit is contained in:
@@ -164,6 +164,7 @@ public final class LivingWorldBootstrap {
|
||||
private final Set<RegionCoordinate> farmlandRegions = new HashSet<>();
|
||||
private final Set<RegionCoordinate> exhaustedFarmlandRegions = new HashSet<>();
|
||||
private final Map<RegionCoordinate, Integer> farmingInactiveCycles = new HashMap<>();
|
||||
private int undergroundCycleTick = 0;
|
||||
|
||||
private PlatformAdapter platformAdapter;
|
||||
private Path worldSaveDirectory;
|
||||
@@ -360,6 +361,7 @@ public final class LivingWorldBootstrap {
|
||||
farmlandRegions.clear();
|
||||
exhaustedFarmlandRegions.clear();
|
||||
farmingInactiveCycles.clear();
|
||||
undergroundCycleTick = 0;
|
||||
simSpeedMultiplier = 1;
|
||||
serverReady = false;
|
||||
LivingWorldLogger.info(
|
||||
@@ -533,6 +535,31 @@ public final class LivingWorldBootstrap {
|
||||
applyEcologyExpansion();
|
||||
applyLongCycleEffects();
|
||||
applyPlayerFeedbackLoops();
|
||||
applyUndergroundSystems();
|
||||
}
|
||||
|
||||
private void applyUndergroundSystems() {
|
||||
if (worldEffectsModule == null) return;
|
||||
undergroundCycleTick++;
|
||||
for (Region region : regionManager.getActiveRegions()) {
|
||||
RegionCoordinate coord = region.getCoordinate();
|
||||
double groundwater = groundwaterLevel.getOrDefault(coord, 0.0);
|
||||
if (groundwater > 80.0 && windRandom.nextDouble() < 0.01) {
|
||||
worldEffectsModule.queueEffect(new WorldEffectRequest(
|
||||
WorldEffectType.CAVE_FLOODS, coord,
|
||||
Math.min(1.0, groundwater / 100.0)));
|
||||
}
|
||||
if (volcanoPhase.get(coord) == VolcanoPhase.FERTILE
|
||||
&& windRandom.nextDouble() < 0.01) {
|
||||
worldEffectsModule.queueEffect(new WorldEffectRequest(
|
||||
WorldEffectType.VEIN_SHIFTS, coord, 0.7));
|
||||
}
|
||||
if (geothermalRegions.contains(coord) && groundwater > 60.0
|
||||
&& undergroundCycleTick % 100 == 0) {
|
||||
worldEffectsModule.queueEffect(new WorldEffectRequest(
|
||||
WorldEffectType.STALACTITE_GROWS, coord, 0.6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyLongCycleEffects() {
|
||||
|
||||
@@ -211,4 +211,13 @@ public enum WorldEffectType {
|
||||
|
||||
/** Exhausted farmland fails into coarse dirt and loses its crop. */
|
||||
CROPLAND_EXHAUSTS,
|
||||
|
||||
/** Saturated groundwater enters a natural cave opening. */
|
||||
CAVE_FLOODS,
|
||||
|
||||
/** Volcanic mineralisation buries old ore and exposes a new shallow vein. */
|
||||
VEIN_SHIFTS,
|
||||
|
||||
/** Wet dripstone cave ceilings grow a pointed stalactite segment. */
|
||||
STALACTITE_GROWS,
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
|
||||
/**
|
||||
@@ -176,6 +177,12 @@ public final class NeoForgeWorldEffectExecutor implements WorldEffectConsumer {
|
||||
siltRiver(level, baseX, baseZ, request.intensity());
|
||||
case CROPLAND_EXHAUSTS ->
|
||||
exhaustCropland(level, baseX, baseZ, request.intensity());
|
||||
case CAVE_FLOODS ->
|
||||
floodCave(level, baseX, baseZ, request.intensity());
|
||||
case VEIN_SHIFTS ->
|
||||
shiftMineralVein(level, baseX, baseZ, request.intensity());
|
||||
case STALACTITE_GROWS ->
|
||||
growStalactite(level, baseX, baseZ, request.intensity());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1034,6 +1041,17 @@ public final class NeoForgeWorldEffectExecutor implements WorldEffectConsumer {
|
||||
|| state.is(Blocks.BASALT);
|
||||
}
|
||||
|
||||
private boolean isOre(net.minecraft.world.level.block.state.BlockState state) {
|
||||
return state.is(Blocks.COAL_ORE) || state.is(Blocks.DEEPSLATE_COAL_ORE)
|
||||
|| state.is(Blocks.IRON_ORE) || state.is(Blocks.DEEPSLATE_IRON_ORE)
|
||||
|| state.is(Blocks.COPPER_ORE) || state.is(Blocks.DEEPSLATE_COPPER_ORE)
|
||||
|| state.is(Blocks.GOLD_ORE) || state.is(Blocks.DEEPSLATE_GOLD_ORE)
|
||||
|| state.is(Blocks.REDSTONE_ORE) || state.is(Blocks.DEEPSLATE_REDSTONE_ORE)
|
||||
|| state.is(Blocks.LAPIS_ORE) || state.is(Blocks.DEEPSLATE_LAPIS_ORE)
|
||||
|| state.is(Blocks.DIAMOND_ORE) || state.is(Blocks.DEEPSLATE_DIAMOND_ORE)
|
||||
|| state.is(Blocks.EMERALD_ORE) || state.is(Blocks.DEEPSLATE_EMERALD_ORE);
|
||||
}
|
||||
|
||||
private void cleanExpiredFloodWater(ServerLevel level, ResourceKey<Level> dimensionKey) {
|
||||
List<TimedWater> entries = floodWater.get(dimensionKey);
|
||||
if (entries == null) return;
|
||||
@@ -1307,6 +1325,78 @@ public final class NeoForgeWorldEffectExecutor implements WorldEffectConsumer {
|
||||
}
|
||||
}
|
||||
|
||||
private void floodCave(ServerLevel level, int baseX, int baseZ, double intensity) {
|
||||
for (int attempt = 0; attempt < 10; attempt++) {
|
||||
int x = baseX + random.nextInt(REGION_BLOCKS);
|
||||
int z = baseZ + random.nextInt(REGION_BLOCKS);
|
||||
int surfaceY = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1;
|
||||
for (int depth = 2; depth <= 10; depth++) {
|
||||
BlockPos cave = new BlockPos(x, surfaceY - depth, z);
|
||||
if (!level.isLoaded(cave) || !level.getBlockState(cave).isAir()) continue;
|
||||
if (level.getBlockState(cave.above()).isSolid()) {
|
||||
level.setBlock(cave, Blocks.WATER.defaultBlockState(), Block.UPDATE_ALL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void shiftMineralVein(ServerLevel level, int baseX, int baseZ, double intensity) {
|
||||
int writes = 0;
|
||||
for (int attempt = 0; attempt < 10 && writes < 10; attempt++) {
|
||||
int x = baseX + random.nextInt(REGION_BLOCKS);
|
||||
int z = baseZ + random.nextInt(REGION_BLOCKS);
|
||||
int surfaceY = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1;
|
||||
for (int depth = 5; depth <= 20 && writes < 10; depth++) {
|
||||
BlockPos pos = new BlockPos(x, surfaceY - depth, z);
|
||||
if (!level.isLoaded(pos)) continue;
|
||||
var state = level.getBlockState(pos);
|
||||
if (isOre(state)) {
|
||||
for (Direction direction : Direction.values()) {
|
||||
BlockPos adjacent = pos.relative(direction);
|
||||
if (writes >= 6) break;
|
||||
if (level.getBlockState(adjacent).is(Blocks.STONE)) {
|
||||
level.setBlock(adjacent, random.nextBoolean()
|
||||
? Blocks.TUFF.defaultBlockState()
|
||||
: Blocks.BASALT.defaultBlockState(), Block.UPDATE_ALL);
|
||||
writes++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
int shallowDepth = 5 + random.nextInt(6);
|
||||
BlockPos exposure = new BlockPos(x, surfaceY - shallowDepth, z);
|
||||
if (writes < 10 && level.isLoaded(exposure)
|
||||
&& level.getBlockState(exposure).is(Blocks.STONE)) {
|
||||
level.setBlock(exposure, random.nextInt(4) == 0
|
||||
? Blocks.RAW_GOLD_BLOCK.defaultBlockState()
|
||||
: Blocks.COPPER_ORE.defaultBlockState(), Block.UPDATE_ALL);
|
||||
writes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void growStalactite(ServerLevel level, int baseX, int baseZ, double intensity) {
|
||||
for (int attempt = 0; attempt < 10; attempt++) {
|
||||
int x = baseX + random.nextInt(REGION_BLOCKS);
|
||||
int z = baseZ + random.nextInt(REGION_BLOCKS);
|
||||
int surfaceY = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1;
|
||||
for (int depth = 5; depth <= 30; depth++) {
|
||||
BlockPos air = new BlockPos(x, surfaceY - depth, z);
|
||||
if (!level.isLoaded(air) || !level.getBlockState(air).isAir()) continue;
|
||||
BlockPos ceiling = air.above();
|
||||
if (level.getBlockState(ceiling).is(Blocks.DRIPSTONE_BLOCK)
|
||||
|| level.getBlockState(ceiling).is(Blocks.STONE)) {
|
||||
var dripstone = Blocks.POINTED_DRIPSTONE.defaultBlockState()
|
||||
.setValue(BlockStateProperties.VERTICAL_DIRECTION, Direction.DOWN);
|
||||
level.setBlock(air, dripstone, Block.UPDATE_ALL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BlockPos surfaceAt(ServerLevel level, int x, int z) {
|
||||
int y = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1;
|
||||
if (y < level.getMinBuildHeight()) {
|
||||
|
||||
Reference in New Issue
Block a user