From 0799d4d4c9d2d54a5213fae090cbcc01fc8c7c32 Mon Sep 17 00:00:00 2001 From: George Date: Thu, 11 Jun 2026 18:33:40 +0100 Subject: [PATCH] Fix atmospheric event fidelity from final audit --- .../java/com/livingworld/LivingWorldMod.java | 46 +++++++++++++++++++ .../bootstrap/LivingWorldBootstrap.java | 5 -- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/livingworld/LivingWorldMod.java b/src/main/java/com/livingworld/LivingWorldMod.java index 3050bf3..bfaca9d 100644 --- a/src/main/java/com/livingworld/LivingWorldMod.java +++ b/src/main/java/com/livingworld/LivingWorldMod.java @@ -136,6 +136,7 @@ public class LivingWorldMod { private boolean migrationCompanionSpawn; /** Stores playerCheckTick when a region last played an ambient sound (per-region throttle). */ private final Map regionSoundLastTick = new HashMap<>(); + private final Map lightningLastTick = new HashMap<>(); public LivingWorldMod(IEventBus eventBus, ModContainer modContainer) { LivingWorldLogger.info(DiagnosticCategory.BOOTSTRAP, "Living World mod starting..."); @@ -253,6 +254,7 @@ public class LivingWorldMod { waterBodyLastScan.clear(); elevationInitialized.clear(); regionSoundLastTick.clear(); + lightningLastTick.clear(); trackedPassiveMobs.clear(); tideTick = 0; lastTideLevel = 0.0; @@ -621,6 +623,18 @@ public class LivingWorldMod { movement.y, movement.z + Math.sin(angle) * 0.025); player.addEffect(new MobEffectInstance( MobEffects.MOVEMENT_SLOWDOWN, 60, 0, true, false)); + for (var mob : ambLevel.getEntitiesOfClass( + net.minecraft.world.entity.LivingEntity.class, + player.getBoundingBox().inflate(32), + entity -> !(entity instanceof ServerPlayer))) { + var mobMovement = mob.getDeltaMovement(); + mob.setDeltaMovement( + mobMovement.x + Math.cos(angle) * 0.018, + mobMovement.y, + mobMovement.z + Math.sin(angle) * 0.018); + mob.addEffect(new MobEffectInstance( + MobEffects.MOVEMENT_SLOWDOWN, 40, 0, true, false)); + } } if (bootstrap.isClimateEventActive( coord, com.livingworld.climate.ClimateEventType.EARTHQUAKE)) { @@ -634,6 +648,14 @@ public class LivingWorldMod { playAmbientSound(player, Holder.direct(SoundEvents.WEATHER_RAIN), 0.08f, 0.75f); } + if (bootstrap.isClimateEventActive( + coord, com.livingworld.climate.ClimateEventType.LIGHTNING_STORM)) { + Integer lastStrike = lightningLastTick.get(coord); + if (lastStrike == null || playerCheckTick - lastStrike >= 8) { + triggerDryLightning(ambLevel, coord); + lightningLastTick.put(coord, playerCheckTick); + } + } } } } @@ -997,6 +1019,30 @@ public class LivingWorldMod { return false; } + private void triggerDryLightning(ServerLevel level, RegionCoordinate coord) { + int baseX = coord.x() * REGION_BLOCKS; + int baseZ = coord.z() * REGION_BLOCKS; + int strikes = 1 + random.nextInt(3); + for (int strike = 0; strike < strikes; strike++) { + for (int attempt = 0; attempt < 20; attempt++) { + int x = baseX + random.nextInt(REGION_BLOCKS); + int z = baseZ + random.nextInt(REGION_BLOCKS); + int y = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z) - 1; + BlockPos surface = new BlockPos(x, y, z); + BlockPos fire = surface.above(); + if (!level.isLoaded(fire) || !level.getBlockState(fire).isAir()) continue; + var state = level.getBlockState(surface); + if (state.is(BlockTags.LOGS) || state.is(BlockTags.LEAVES) + || state.is(net.minecraft.world.level.block.Blocks.GRASS_BLOCK)) { + level.setBlock(fire, + net.minecraft.world.level.block.Blocks.FIRE.defaultBlockState(), + net.minecraft.world.level.block.Block.UPDATE_ALL); + break; + } + } + } + } + /** Step 6: Samples the dominant biome at the region centre and returns a succession ceiling. */ private SuccessionStage deriveBiomeCap(ServerLevel level, RegionCoordinate coord) { int cx = coord.x() * LivingWorldConstants.DEFAULT_REGION_SIZE_CHUNKS * 16 + 64; diff --git a/src/main/java/com/livingworld/bootstrap/LivingWorldBootstrap.java b/src/main/java/com/livingworld/bootstrap/LivingWorldBootstrap.java index 01e7afb..5c78206 100644 --- a/src/main/java/com/livingworld/bootstrap/LivingWorldBootstrap.java +++ b/src/main/java/com/livingworld/bootstrap/LivingWorldBootstrap.java @@ -2419,11 +2419,6 @@ public final class LivingWorldBootstrap { .get(AtmosphereModule.MODULE_ID, AtmosphereRegionData.class).orElse(null); if (atm == null || atm.getThunderLevel() < 0.25) { shouldResolve = true; - break; - } - if (worldEffectsModule != null && windRandom.nextDouble() < 0.45) { - worldEffectsModule.queueEffect(new WorldEffectRequest( - WorldEffectType.WILDFIRE, coord, 0.25)); } } case EARTHQUAKE -> {