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> farmlandRegions = new HashSet<>();
|
||||||
private final Set<RegionCoordinate> exhaustedFarmlandRegions = new HashSet<>();
|
private final Set<RegionCoordinate> exhaustedFarmlandRegions = new HashSet<>();
|
||||||
private final Map<RegionCoordinate, Integer> farmingInactiveCycles = new HashMap<>();
|
private final Map<RegionCoordinate, Integer> farmingInactiveCycles = new HashMap<>();
|
||||||
|
private int undergroundCycleTick = 0;
|
||||||
|
|
||||||
private PlatformAdapter platformAdapter;
|
private PlatformAdapter platformAdapter;
|
||||||
private Path worldSaveDirectory;
|
private Path worldSaveDirectory;
|
||||||
@@ -360,6 +361,7 @@ public final class LivingWorldBootstrap {
|
|||||||
farmlandRegions.clear();
|
farmlandRegions.clear();
|
||||||
exhaustedFarmlandRegions.clear();
|
exhaustedFarmlandRegions.clear();
|
||||||
farmingInactiveCycles.clear();
|
farmingInactiveCycles.clear();
|
||||||
|
undergroundCycleTick = 0;
|
||||||
simSpeedMultiplier = 1;
|
simSpeedMultiplier = 1;
|
||||||
serverReady = false;
|
serverReady = false;
|
||||||
LivingWorldLogger.info(
|
LivingWorldLogger.info(
|
||||||
@@ -533,6 +535,31 @@ public final class LivingWorldBootstrap {
|
|||||||
applyEcologyExpansion();
|
applyEcologyExpansion();
|
||||||
applyLongCycleEffects();
|
applyLongCycleEffects();
|
||||||
applyPlayerFeedbackLoops();
|
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() {
|
private void applyLongCycleEffects() {
|
||||||
|
|||||||
@@ -211,4 +211,13 @@ public enum WorldEffectType {
|
|||||||
|
|
||||||
/** Exhausted farmland fails into coarse dirt and loses its crop. */
|
/** Exhausted farmland fails into coarse dirt and loses its crop. */
|
||||||
CROPLAND_EXHAUSTS,
|
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.tags.FluidTags;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,6 +177,12 @@ public final class NeoForgeWorldEffectExecutor implements WorldEffectConsumer {
|
|||||||
siltRiver(level, baseX, baseZ, request.intensity());
|
siltRiver(level, baseX, baseZ, request.intensity());
|
||||||
case CROPLAND_EXHAUSTS ->
|
case CROPLAND_EXHAUSTS ->
|
||||||
exhaustCropland(level, baseX, baseZ, request.intensity());
|
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);
|
|| 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) {
|
private void cleanExpiredFloodWater(ServerLevel level, ResourceKey<Level> dimensionKey) {
|
||||||
List<TimedWater> entries = floodWater.get(dimensionKey);
|
List<TimedWater> entries = floodWater.get(dimensionKey);
|
||||||
if (entries == null) return;
|
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) {
|
private BlockPos surfaceAt(ServerLevel level, int x, int z) {
|
||||||
int y = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1;
|
int y = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1;
|
||||||
if (y < level.getMinBuildHeight()) {
|
if (y < level.getMinBuildHeight()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user