Commit Graph

60 Commits

Author SHA1 Message Date
George 0799d4d4c9 Fix atmospheric event fidelity from final audit 2026-06-11 18:33:40 +01:00
George d7f8e3ea36 Complete phase 10 dimensional extensions 2026-06-11 18:31:50 +01:00
George d9158bc8e9 Complete phase 9 ambience polish 2026-06-11 18:28:56 +01:00
George 48643b6ef6 Complete phase 8 underground systems 2026-06-11 18:27:33 +01:00
George eaf5db723b Complete phase 7 player feedback loops 2026-06-11 18:25:39 +01:00
George 98f97bfbc4 Complete phase 6 seasonal cycles 2026-06-11 18:18:52 +01:00
George 2304266544 Complete phase 5 ecology systems 2026-06-11 18:17:05 +01:00
George 38ee028651 Complete phase 4 hydrology expansion 2026-06-11 18:11:42 +01:00
George 5331d5b207 Complete phase 3 geological activity 2026-06-11 18:08:56 +01:00
George f8995392eb Complete phase 2 atmospheric events 2026-06-11 18:06:17 +01:00
George 7802e4b603 Complete phase 1 ocean ecosystem 2026-06-11 18:01:13 +01:00
George 54a6be91de Simulate everywhere via ChunkEvent.Load; realistic moon-phase tides; mob currents
World simulation no longer tied to player proximity:
- ChunkEvent.Load listener registers a region for EVERY chunk loaded in ANY
  dimension — player movement, spawn chunks, forceloaded areas, entities
  dragging chunks into memory — all trigger simulation automatically
- Elevation sampled from the loaded chunk itself (4 points within its 16×16 bounds)
  so we never query unloaded chunk heights
- Biome also sampled from the loaded chunk; succession cap and soil/water init
  fire immediately on first load
- Spawn region pre-activation (5×5 grid around origin) on ServerStartedEvent
  covers the always-loaded spawn chunks that never fire ChunkEvent.Load

Realistic tidal system (was: 12 random scans, ±1 block, every 60 s):
- Interval: 200 ticks (~10 s) for visibly smooth waterline movement
- Amplitude: ±2.5 × moon-phase factor — full moon = ±3.5 blocks (spring tide),
  new moon = ±1.5 blocks (neap tide); players will notice the moon matters
- Coverage: 8×8 systematic grid with per-cell jitter = 64 positions per region
  scanning the full intertidal zone (seaLevel ± amplitude + 1), not just one Y slice
- Logic: place water when Y ≤ tideHeight, drain source blocks when Y > tideHeight,
  only on natural base blocks (sand/gravel/stone/sandstone/grass/dirt)

Three-part current physics (applyRiverCurrents every 4 ticks):
1. River: FluidState.getFlow() → player velocity in flowing water (unchanged)
2. Ocean: mid-tide push (tidal current ∝ derivative of tide) applied to players
   in source blocks in coastal regions; direction follows wind angle
3. Mobs: animals/monsters within 48 blocks of a player also pushed by river flow
   (swept downstream, natural behavior for animals crossing rivers)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 18:14:25 +01:00
George fde7264815 Add water physics, river currents, volcanic system with lava & new land
Groundwater aquifer (valley springs):
- Per-region subsurface water table recharges from rainfall + lateral seepage
  from uphill neighbours; valley floors (≥2 higher neighbours) develop springs
- GROUND_SPRING_EMERGES places a permanent water source block at the lowest
  natural terrain point; vanilla fluid physics carries it downhill from there
- Active springs feed riverFlowIntensity for erosion even without rain

River current physics (real player forces):
- Every 4 ticks, players in flowing water receive a velocity push via
  FluidState.getFlow() — the exact direction Minecraft's own rendering uses
- Force scales with fluid level: level 7 (near source) = strong; level 1 = gentle

Hydraulic erosion:
- HYDRAULIC_EROSION fires whenever flow intensity is significant, rain-independent
- Flowing water adjacent to stone/gravel/sand/dirt progressively softens it:
  stone→gravel→sand→air; river valleys widen over time

Volcano lifecycle (DORMANT→BUILDING→ERUPTING→COOLING→FERTILE→DORMANT):
- High-elevation regions (avg surface Y ≥ 85) registered as potentially volcanic
- LAVA_FLOW places source blocks at summit; vanilla physics flows them downhill
- ASH_DEPOSIT covers surrounding terrain with tuff/gravel; kills surface plants;
  ash clouds spread to adjacent regions with air pollution spike
- COBBLESTONE_FORMS solidifies lava: lava+water→cobblestone, lava+air→basalt
  — creates permanent new terrain that did not exist before the eruption
- FERTILE phase: soil fertility +30, contamination −20, rapid pollution decay
- Volcanic ambience: fire crackling during eruption, deep rumble while building

New commands: /lw events (active climate events), /lw volcanoes (lifecycle states)
New ClimateEventType: VOLCANIC_ERUPTION
New WorldEffectTypes: GROUND_SPRING_EMERGES, HYDRAULIC_EROSION, LAVA_FLOW,
  ASH_DEPOSIT, COBBLESTONE_FORMS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 21:23:13 +01:00
George 113741abd6 Add seasons, climate events, river erosion, tides, /lw map, trend tracking, desertification permanence, biome init
New systems (all with real in-world effects):
- Seasonal variation: spring growth surge, summer evaporation, autumn leaf fall, winter die-back — all affect actual VegetationRegionData/WaterRegionData/SoilRegionData each cycle
- Multi-region climate events: drought spreads across dry neighbours; wildfire triggers WILDFIRE + VEGETATION_DIES block effects and air pollution; flood places WATER_POOL_FORMS in downstream regions — all broadcast to players
- River erosion: accumulated runoff intensity triggers RIVER_CARVE world effect — water source blocks placed on natural terrain, channel depth increases over time (actual block changes)
- Tidal simulation: two tidal cycles per Minecraft day; rising/falling tide physically places/removes water source blocks on sand/gravel/stone shoreline at sea level
- Biome-aware initialisation: on first region entry, biome temperature + downfall set realistic soil fertility/moisture and water availability starting values
- Desertification permanence: sustained damage > 65 + health < 20 lowers succession cap by one stage; players notified via chat
- Region trend tracking: last 5 health samples per region; ↑↓→ arrow in compass HUD and /lw atmosphere output
- Seed rain in HUD: shows accumulated seed rain when > 0.5
- /lw map [radius]: ASCII coloured region grid showing succession stages for all nearby loaded regions
- Season enum expanded: temperatureMod, droughtMod, vegGrowthMod fields used by enhanced applySeasonalEffects()
- WorldEffectsModule: queueEffect() public method for external callers (bootstrap hooks, climate events)
- WorldEffectType: RIVER_CARVE type added
- README.md: comprehensive feature list, command reference, pipeline diagram, succession table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 21:01:03 +01:00
George b68390983c Add TOML config, region borders, seed dispersal corridors, wind, and ambient sound
1. TOML config (livingworld-server.toml) — NeoForgeModConfig registers a
   server-side config spec exposing all major tuning constants: pollution
   decay/spread, vegetation growth/dieoff rates, recovery rates, and seed
   dispersal params. EcosystemTuning wires these into the service registry
   (CoreServices.TUNING); PollutionModule, VegetationModule, RecoveryModule
   all read from it so admins can tune without recompiling.

2. Persistence audit — CodecKeys confirmed complete and correct for all 8
   data-bearing modules. The 4-arg RecoveryRegionData constructor (from
   the prior session) correctly preserves maxSuccessionStage on every path.
   No structural issues found.

3. /lw region borders [regionX regionZ] — draws cyan DustParticle lines
   along all 4 edges of the region at surface height (32 samples per edge,
   ~4 blocks apart on the 128-block edge).

4. Pollution spreading — already in place via wind-based air diffusion.
   Extended: applyWaterRunoff now also transports ground pollution
   downstream (15 % of ground pollution × runoff rate) with a small water
   bleed, so contaminated upland regions poison their downhill neighbours.

5. Sound ambience — per-region throttled (≥8 check-intervals between
   plays). Forest (YOUNG_WOODLAND+, health>50): azalea leaves rustling.
   Barren (SPARSE_GRASS-): dry sand step. Heavy pollution (score>50):
   basalt deltas mood. Direct ClientboundSoundPacket per player so other
   nearby players aren't spammed.

6. Seed dispersal & ecological corridors — applySeedDispersal() runs each
   post-sim cycle. Healthy regions (YOUNG_WOODLAND+) stochastically emit
   seeds to all 4 neighbours proportional to vegetationPressure. Pollution
   in the target blocks seeds. Corridor effect: if the target has 2+ healthy
   neighbours, seed strength × corridorBoostMultiplier (default 3.5×).
   When accumulated seed rain ≥ 5.0 the target's succession cap is
   pioneered one stage ahead of what physical conditions alone would allow.
   /lw wind shows current wind angle and spread rate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 20:31:56 +01:00
George 72d94b9f28 Slow pollution decay 4x — BASE_DECAY_RATE 0.008 → 0.002
Air pollution half-life goes from ~48 sim cycles (~2 min at 1x) to
~192 cycles (~8 min). Ground and water pollution persist proportionally
longer. Pollution from furnaces, campfires, and acid rain now lingers
long enough to meaningfully damage regions rather than clearing in seconds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:42:50 +01:00
George 30e680b650 Add VEGETATION_DIES world effect — trees and plants visibly die under bad conditions
WorldEffectType: new VEGETATION_DIES variant.

WorldEffectsModule: emits VEGETATION_DIES whenever soilQuality < 20 OR
pollutionScore > 30, mirroring VegetationModule's bad-conditions gate so
block changes stay in sync with the data-layer die-off. Intensity is the
max of the soil-shortage and pollution-excess fractions.

NeoForgeWorldEffectExecutor.killVegetation():
- Detects tree canopy by comparing MOTION_BLOCKING (includes leaves/logs)
  height vs MOTION_BLOCKING_NO_LEAVES (ground) height.
- When canopy is present: strips all leaf blocks downward from the canopy
  top; at intensity > 0.3 also removes upper trunk log sections, leaving
  bottom two blocks as a visible stump.
- When no canopy: clears surface plants (short grass, fern, tall grass,
  large fern, saplings, dandelion, poppy).

Previously the simulation correctly tracked vegetation pressure dropping
to zero but the Minecraft world remained a full forest, so there was no
visible feedback for degradation. /lw demo degrade now visibly kills the
forest canopy while the succession stage regresses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:32:23 +01:00
George 725ac6b33f Add /lw demo degrade/recover for one-command ecosystem transformation demo
EcoDemoCommand provides two complete condition presets applied in one command:

  /lw demo degrade  — forces stage=MATURE_FOREST with full lush vegetation,
                      then applies dead soil (fertility=5, contamination=8,
                      erosion=8), severe drought (availability=5, risk=90),
                      and clean air. soilQuality collapses to ~0, triggering
                      VegetationModule badConditions and RecoveryModule
                      conditionsMissedForRegression every cycle. Region
                      visibly regresses toward BARREN.

  /lw demo recover  — caps succession at MATURE_FOREST, resets soil to
                      fertility=85/contamination=0/erosion=0, water to
                      availability=85/drought=5, seeds minimal grass.
                      soilQuality immediately hits ~85, unlocking full
                      vegetation succession chain and rapid stage advancement.

Full demo sequence:
  /lw speed 20
  /lw demo degrade        (watch ~30s: MATURE_FOREST → BARREN)
  /lw demo recover
  /lw speed 50            (watch ~30s: BARREN → MATURE_FOREST)
  /lw speed reset

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:27:50 +01:00
George 1727c3a406 Raise speed cap to 100x and increase base growth/recovery rates
- /lw speed now accepts 1-100 (was 1-20)
- Vegetation growth rates 4x faster: grass 0.015→0.06, flowers 0.008→0.03,
  shrubs 0.005→0.02, trees 0.002→0.008. Previously grass alone took ~200
  cycles to unlock shrub growth; now ~50 cycles.
- Recovery base progress 0.5→2.0/cycle, health bonus 0.02→0.05/cycle.
  Each succession stage now advances in ~50 good cycles instead of ~200.

At /lw speed 100 with good soil+water conditions set via /lw set, full
BARREN→MATURE_FOREST succession completes in well under a minute.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:22:05 +01:00
George 66dc2f336a Add /lw speed command for real-time simulation acceleration
/lw speed <1-20>  — run N full sim cycles (module pipeline + all
                    post-sim hooks) per normal tick interval.
/lw speed reset   — return to real-time (1x).

The multiplier is stored on LivingWorldBootstrap and reset to 1 on
server stop. Extra cycles queue all active regions and call the full
post-sim hook chain (pollution spread, seasonal effects, climate,
warming, water runoff, dynamic cap) so ecosystem state advances
coherently rather than just running modules in isolation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:16:26 +01:00
George b17a8990b0 Speed up ecosystem decay and fix succession cap being silently reset
VegetationModule:
- All living tiers now die under bad conditions, not just grass. Rates:
  grass 1.0, flowers 0.5, shrubs 0.25, trees 0.10 per sim cycle (trees
  only die under severe pollution >60 or near-zero soil <10).
- Dead accumulation raised 0.20 → 0.50 per bad cycle.
- Previously only grass died, keeping vegetation pressure artificially
  high and preventing regression even when soil/pollution were terrible.

RecoveryModule:
- DAMAGE_PER_BAD_TICK raised 3.0 → 5.0 so regression fires in ~14 bad
  cycles (~35s) once conditions trip the threshold, down from ~23 cycles.
- DAMAGE_DECAY_RATE lowered 0.05 → 0.03 so damage sticks around during
  oscillating conditions instead of washing away on good ticks.
- Fixed bug: 3-arg RecoveryRegionData constructor (used during damage
  decay) defaulted maxSuccessionStage to MATURE_FOREST, silently
  overwriting any biome or dynamic cap set by setRegionBiomeCap() /
  applyDynamicCapUpdate(). Now uses 4-arg constructor to preserve cap.

Net result: a heavily polluted forest regresses a stage in ~2 minutes
of sustained bad conditions instead of 10-15+ minutes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:07:48 +01:00
George 0f2a265c61 Add /lw set debug commands for ecosystem testing
Adds RegionSetCommand under /lw set with sub-commands to directly mutate
simulation data in the player's current region:

  /lw set soil fertility <0-100>     — soil fertility
  /lw set soil moisture  <0-100>     — soil moisture
  /lw set water availability <0-100> — water availability
  /lw set water drought      <0-100> — drought risk
  /lw set pollution <0-100>          — all pollution layers (proportional)
  /lw set stage <STAGE>              — force succession stage (resets progress)
  /lw set cap   <STAGE>              — force succession ceiling
  /lw set rain  <0.0-1.0>            — override regional rain level

Stage names have tab-completion. Forcing /lw set stage to a higher stage
than the current cap auto-raises the cap. All changes are immediately
persisted via markDirty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 21:50:39 +01:00
George 32e413cc9f Add dynamic region transformation, water runoff physics, and puddle formation
- Dynamic succession cap: desert regions (initially capped at SPARSE_GRASS)
  can now advance to MATURE_FOREST if water and soil conditions improve
  sustainably. applyDynamicCapUpdate() raises the cap each sim cycle;
  maxSuccessionStage is now persisted in the region codec so progress
  survives server restarts.

- Elevation-based water runoff: LivingWorldMod samples average surface
  height once per region on first entry. applyWaterRunoff() uses height
  differences to transfer water availability from high regions to low
  neighbours when it is raining, simulating drainage basin physics —
  valleys collect water, hills drain.

- Water pool formation (WATER_POOL_FORMS): WorldEffectsModule emits the
  new effect when a BARREN/SPARSE_GRASS region has regional rain > 0.3.
  NeoForgeWorldEffectExecutor finds the lowest sampled surface point and
  places water source blocks there; at high intensity the pool widens to
  adjacent blocks. These physical water blocks are then picked up by the
  periodic hasWaterBody() scan and feed back a hydration boost, enabling
  succession.

- Player water management: water bucket placement now invalidates the
  water-body scan cache for that region so player-built pools are detected
  within one player-check cycle. The scan itself is now periodic (every
  ~10 min) rather than one-shot, so natural pools from puddle formation
  are also re-evaluated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 21:41:35 +01:00
George 178d50883e Add global climate layer: carbon cycle, greenhouse warming, /lw climate
GlobalClimateTracker accumulates carbonPpm each sim cycle from total regional
air pollution (emissions) minus total tree-canopy pressure (carbon sink). The
resulting warmingLevel (0–1, representing 0–5°C anomaly) feeds three effects:

- AtmosphereModule subtracts getRainPenalty() (up to -0.15) from every
  region's rain target, creating planet-wide drought as warming rises.
- Bootstrap post-sim pass raises drought risk by warming * 0.02 per cycle,
  giving warming a second, persistent drought pathway.
- Carbon state persists across sessions in living_world/global_climate.dat
  so climate change accumulates over a playthrough.

/lw climate shows: Carbon: 342 ppm (+62 ppm) | Warming: +1.1°C |
  Biodiversity: 73% | Rain penalty: -3%

Deforestation accelerates warming; reforestation reverses it — the mod now
rewards long-term forest stewardship at a planetary scale.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 21:16:14 +01:00
George c82a2afc4f Add seasons, player pollution effects, wildfire, fog, water body boost, /lw atmosphere
Seasons (Step 1)
- Season enum (SPRING/SUMMER/AUTUMN/WINTER) derived from gameTime / 24000 / 8.
- AtmosphereModule applies seasonal rain modifier: spring +10%, summer -15%,
  winter -25%. Cascades naturally through water → soil → succession.
- Bootstrap post-sim pass: spring boosts soil fertility (+0.003/cycle),
  winter draws moisture out of topsoil (-0.002/cycle).

Player pollution effects (Step 2)
- Poll > 40: nausea (MobEffects.CONFUSION in 1.21.1); > 60: slowness; > 80: weakness.
- Duration 100 ticks, refreshed each PLAYER_CHECK_INTERVAL (1 s). Expires
  5 s after the player leaves the polluted region.

Wildfire (Step 3)
- WILDFIRE added to WorldEffectType.
- WorldEffectsModule emits WILDFIRE when droughtRisk > 70 AND thunderLevel > 0.5
  with 1% probability per sim cycle.
- NeoForgeWorldEffectExecutor places fire blocks on surface grass/leaves/logs;
  Minecraft fire spreading takes over from there.

Fog (Step 4)
- When pollutionScore > 40, 1–3 SMOKE particles sent per check interval at
  player eye-level via ServerLevel.sendParticles(player, ...) — per-player only,
  not broadcast to everyone.

Water body passive boost (Step 5)
- On first entry to a region, hasWaterBody() samples 30 surface positions.
  If ≥5 are water, applyWaterBodyBoost() permanently raises purification
  capacity +15, water availability +10, and lowers drought risk -10.

/lw atmosphere command (Step 6)
- Shows: Region (x,z) | Season: Spring | Rain: 72% | Storm: 18%
- Wired via Function<CommandSourceStack, String> atmosphereStatus parameter
  added to LivingWorldCommandRoot.registerDeferred().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:42:41 +01:00
George 61abff52dc Add regional atmosphere: vegetation scrub, ecosystem-driven rain, per-player weather
- New AtmosphereModule (9th in pipeline) derives per-region rain/thunder from
  ecosystem health and pollution score, smoothly interpolating each sim cycle.
- Tree canopy scrubs air pollution: treePressure × 0.003 removed per cycle,
  creating a direct incentive to maintain forests.
- Rain level (0–1) targets ecosystem health / 100 × 0.85; global MC rain adds
  a 0.15 bias so natural weather still matters.
- Thunder level targets pollutionScore / 100 × 0.8; acid rain fires when
  thunder > 0.4 AND pollution > 20, draining soil fertility and water.
- Regional drought: rain < 0.2 raises drought risk proportionally.
- Per-player ClientboundGameEventPacket (RAIN_LEVEL_CHANGE, THUNDER_LEVEL_CHANGE,
  START_RAINING, STOP_RAINING) sent each player-check cycle so each region has
  an independent sky without client-side mixins.
- HUD extended with Rain% and Storm% fields when atmosphere data is present.
- Removed global applyWeatherFeedback() from bootstrap; AtmosphereModule owns
  all rain/drought/acid-rain simulation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:24:04 +01:00
George 67a1e07b82 Add /lw hud debug command to toggle region HUD without compass
/lw hud toggles a persistent per-player flag stored in LivingWorldBootstrap.
When enabled, the action-bar HUD (Eco/Poll/Soil/Wat) is shown every 20 ticks
alongside the existing compass-based trigger. Flag is cleared on server stop.
Requires operator permission level 2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:02:38 +01:00
George c9f927b265 Add mob spawning, HUD, agriculture, acid rain, biome caps, directional wind
Step 1 – Mob spawn feedback: FinalizeSpawnEvent suppresses passive mobs (Animal)
  in regions with ecosystem health < 30 (up to 70% cancellation) and hostile mobs
  (Monster) in regions > 60 health (up to 50% cancellation).

Step 2 – Compass HUD: holding a compass shows a colour-coded action-bar overlay
  with Eco/Poll/Soil/Wat scores for the current region (green/yellow/red banded).

Step 3 – Resource loop closure: logging depletion recovery is already tied to
  vegetation pressure in ResourceDepletionModule; sapling-to-tree growth continues
  to close the loop via the existing vegetation feedback path.

Step 4 – Agriculture: bone meal (PlayerInteractEvent.RightClickBlock) adds +2
  soil fertility; harvesting fully-grown (age=7) crops (BlockEvent.BreakEvent)
  drains -0.5 fertility and adds 0.3 farming depletion.

Step 5 – Acid rain: when raining AND region pollution > 20, rainfall drains soil
  fertility, raises soil contamination, and reduces water availability proportional
  to excess pollution. Implemented in applyWeatherFeedback().

Step 6 – Biome-aware succession: RecoveryRegionData gains a maxSuccessionStage
  cap (default MATURE_FOREST). deriveBiomeCap() samples the biome at the region
  centre on first player entry and calls setRegionBiomeCap(); deserts/badlands →
  SPARSE_GRASS, savannas/mountains/cold → SCRUBLAND, beaches/oceans → GRASSLAND,
  forests/taiga/jungle → MATURE_FOREST, plains/swamp → YOUNG_WOODLAND.

Step 7 – Directional wind: spreadPollutionAcrossRegions() drifts a wind angle by
  ±0.05 rad per sim cycle; each cardinal neighbour's spread rate is multiplied by
  (1 + alignment×0.5) where alignment = cos(windAngle − offsetAngle), creating
  downwind (×1.5) and upwind (×0.5) asymmetry.

All 400 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 19:57:09 +01:00
George 2350c27374 Vary sapling species by succession stage for realistic forest growth
Pioneer species (oak, birch) dominate at YOUNG_WOODLAND (intensity ~0.5).
Spruce and dark oak join at mid intensity. At MATURE_FOREST (intensity ~1.0)
the full mix includes cherry and jungle saplings for a diverse canopy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 19:12:25 +01:00
George 773fb0223f Tune ecosystem sensitivity and add simulation richness (Steps 1-6)
Tuning:
- simulationIntervalTicks: 100→50 (faster sim feedback)
- FURNACE_SCAN_INTERVAL: 100→50 (matches sim interval for pollution equilibrium)
- PollutionModule.BASE_DECAY_RATE: 0.02→0.008 (slower natural decay)
- SoilModule.POLLUTION_CONTAMINATION_THRESHOLD: 30→10, CONTAMINATION_FERTILITY_DRAIN: 0.002→0.005
- VegetationModule.DIEOFF_POLLUTION_THRESHOLD: 60→30
- WorldEffectsModule: lower grass-degrade/pollution-indicator thresholds so effects
  trigger from realistic furnace-driven pollution levels
- NeoForgeWorldEffectExecutor.BLOCK_ATTEMPTS: 8→20

New features:
- Campfire pollution source (0.2 air, 0.05 ground per lit campfire)
- Cross-region air pollution spreading (2% of gradient per sim cycle)
- SimulationManager.queueRegionForUpdate() for priority enqueueing
- LivingWorldBootstrap.notifyPlayerInRegion() boosts priority when player enters region
- Player region tracking in LivingWorldMod: checks every 20 MC ticks, queues update
  on region change
- NeoForgeWorldEffectExecutor: implement SAPLING_GROWTH_BOOSTED (oak sapling placement);
  VEGETATION_SPREADS also places short grass and flowers; GRASS_DEGRADES_TO_DIRT clears
  plants and converts dirt→coarse_dirt at intensity>0.5

All 400 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 18:55:08 +01:00
George 577c14b6ea Lower world effect thresholds to achievable levels; add water pollution to furnaces
The previous thresholds (grass=60, smoke=70) required pollutionScore > 60.
pollutionScore is a weighted average, so even if air pollution caps at 100
the score only reaches 40 from air alone — the thresholds were physically
unreachable from furnace burning.

New thresholds: grass degradation fires at pollutionScore > 15 (soilQuality
gate raised to 75 so it doesn't block — soil defaults to 60), smoke
particles fire at > 10. With 4 furnaces the score reaches ~15 in about
20 real simulation ticks (~2 minutes of play).

Also added acid-rain water pollution (0.1/furnace/scan) — coal burning
emits SO₂ which contributes to the weighted score alongside the existing
air and ground components.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 17:13:57 +01:00
George dfa84a9347 Wire furnace burning to air pollution input
PollutionModule only decayed pollution; no source ever fed it. Every 100
server ticks (one simulation interval), LivingWorldMod now scans each
active region's loaded chunks for lit AbstractFurnaceBlockEntity instances
(covers standard furnace, blast furnace, smoker) using getChunkNow so
unloaded chunks are skipped cheaply.

Per lit furnace per scan: +0.5 air, +0.1 ground pollution. With 4 furnaces
this drives air pollution to an equilibrium of ~55 (decay rate 3.6%/tick),
giving a clearly visible pollution score in /lw region info.

Bootstrap gains getActiveRegions() and handleFurnaceActivity() for the
platform layer to call without needing Minecraft imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 16:57:11 +01:00
George 881f716115 Fix two live simulation bugs: profiler crash + regions never updating
forceUpdateRegion crashed with "no profiling cycle is active" because
runModulesForRegion calls profiler.beginModule() which requires an active
cycle. Wrapped the call in startCycle/endCycle in a try/finally.

Regions showed tick=0 and no module data because SimulationScheduler's
priority queue was never populated for normal rolling updates — only
explicit queueRegion() calls worked. Fixed by auto-enqueueing all active
regions in onMinecraftServerTick() just before each simulation cycle fires.
Auto-enqueueing is placed there (not in runSimulationCycle()) so unit tests
that drive cycles directly are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 16:42:11 +01:00
George 6e6de00f0d Add debug commands, force-update, and weather feedback loop
Track E — commands:
  /lw region info — now shows all 7 module data classes (air/ground/water pollution,
    soil fertility/moisture/contamination, succession stage, depletion levels, etc.)
  /lw region info <x> <z> — inspect any region by block coordinates
  /lw region force-update — runs full module pipeline on current region immediately
  /lw stats — shows last cycle duration, per-module timings, budget overrun flag

Track F — weather feedback:
  Each simulation tick, active overworld regions receive a moisture boost when it
  rains (+0.3 waterAvailability, -0.15 droughtRisk) and a drought increase when
  dry (+0.05 droughtRisk). The rain state is supplied by LivingWorldMod via a
  BooleanSupplier set on ServerStartedEvent and cleared on stop.

400 tests, all passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 16:20:48 +01:00
George 4fd9bb97aa Wire world effect executor — ecosystem simulation now mutates blocks in-game
NeoForgeWorldEffectExecutor translates WorldEffectRequests into actual Minecraft
block operations: GRASS_DEGRADES_TO_DIRT replaces grass with dirt, VEGETATION_SPREADS
spreads grass onto lit dirt, POLLUTION_VISUAL_INDICATOR spawns smoke particles.
SAPLING_GROWTH_SLOWED/BOOSTED are stubs pending mixin hooks.

Block writes are guarded by isLoaded() checks so no chunks are force-loaded.
Intensity scales the number of block candidates attempted per tick (max 8).
MinecraftServer is captured in LivingWorldMod on ServerStartedEvent and cleared
on stop; the executor receives it via Supplier to stay null-safe across restarts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 16:01:57 +01:00
George 6427677db5 Add Volume 2 ecosystem modules, event hooks, and module data persistence
Eight simulation modules (pollution, soil, water, vegetation, resource depletion,
recovery, ecosystem, world effects) form the full ecosystem pipeline. Each module
owns typed RegionData and writes summary metrics back to RegionMetrics.

Player block-break events are wired through BlockBreakInfo across the platform
boundary; the NeoForge adapter translates BreakEvent and routes it to the
bootstrap handler which records mining/logging/farming depletion on the
affected region.

Module state now survives server restarts: FileRegionPersistenceService accepts
per-module codecs (via PropertiesPersistenceWriter/Reader) that serialise every
RegionData instance alongside the region's core state. Bootstrap registers codecs
for all seven data-bearing modules at startup.

395 tests, all passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 15:53:06 +01:00
George ae2a8db3ce Wire Volume 1 server lifecycle 2026-06-07 14:11:10 +01:00
George 96747a37db Add file-backed region persistence 2026-06-07 14:08:44 +01:00
George 69d60f7c13 Add NeoForge platform adapter 2026-06-07 14:06:53 +01:00
George cd5ffea24d Add Minecraft coordinate boundary mapper 2026-06-07 14:04:34 +01:00
George 7045df9a21 Add platform adapter contract 2026-06-07 14:04:27 +01:00
George 482e981c36 Consolidate persistence service contract 2026-06-07 14:03:55 +01:00
George 4f5a067300 Complete persistence metadata foundation 2026-06-07 14:02:50 +01:00
George e23f362b12 Add sustained simulation validation 2026-06-07 13:36:54 +01:00
George 025487dd40 Add direct event bus contract tests 2026-06-07 13:35:16 +01:00
George fbe1ccbbc3 Test and fix scheduler cycle budgets 2026-06-07 13:34:35 +01:00
George f1ceb5e019 Lock lifecycle transition matrix 2026-06-07 13:33:49 +01:00
George a46a945850 Complete region coordinate boundary coverage 2026-06-07 13:33:19 +01:00
George b0815db6c1 Add deterministic test simulation module 2026-06-07 13:32:42 +01:00
George 0ce71b727a Harden simulation profile snapshots 2026-06-07 13:31:39 +01:00