Files
last-hearth/docs/content-expansion.md
T
2026-11-03 12:41:09 -05:00

28 KiB
Executable File
Raw Blame History

Landscape and ecosystem integration

This integrates the independent terrain factory, diversity policy, and named botanical art into content.lua. No save-schema/version change, engine fork, new simulation scheduler, global API wrapper or runtime mapgen editing is introduced. The precise upstream contracts remain world generation, ecosystems, and original art.

Registration order and API

  1. Construct/install hearth.seasons, then hearth.botany and hearth.diversity before creating succession. Both extend seasonal policy; succession reads hearth.biomes lazily when it needs habitat information.
  2. Register all original nodes, ecological flora, seasonal food patches, resource inputs, tools and recipes through the existing private registration facade.
  3. Call the lazy biome factory with (hearth, api, register_node, construction); assign hearth.biomes = biomes.register(). This is the sole registration of new terrain, full-block species trees, geology, aliases and decorations.
  4. Call diversity.register_nodes(register_node), then botany.register_nodes(register_node), then seasons.register(). Species leaves and full-block tree stages now exist for seasonal copies.
  5. Instantiate wildlife after these registrations.

The entire old mapgen section is removed, including its aliases, two biome definitions, simple floor iron decoration, old weir/tree schematics and seep registration. The biome module retains the canonical temperate/riverbank names, canonical meadow timber and gathering routes, while supplying ten communities, ten tree species and ordered real-host ore registrations. Its aliases are non-forcing and honor existing registrations; nothing clears engine tables. Its instance registration and diversity node registration are idempotent.

The private node helper honors explicit def.tiles. Species logs therefore keep their top/top/side faces; soils keep their authored top and canonical earth sides; full-block trees retain their species faces. Seasonal copies retain base placement, protection, ownership and room-invalidation callbacks. Plantlike silhouettes use their supplied texture rather than a guessed node-name image. All resource craftitems use the existing hearth_item_<name>.png naming convention. The new pick uses hearth_item_copper_pick.png, not a legacy hearth_icon_ tool name. No duplicate ore, wood, leaf or seasonal nodes are intentionally registered.

Resource utilities and process handoff

Resource Content integration Process-owner boundary
Quartz Three hearth:quartz shapelessly craft one existing hearth:window No new furnace/glass process or scientific manufacturing claim
Copper One hearth:copper_ore plus one hearth:charcoal shapelessly craft one hearth:copper_charge A lit hearth processes one charge for 45 real seconds, reserving 30 fuel seconds, yielding one hearth:copper_ingot
Copper ingot Three ingots across the top row and two central sticks craft one hearth:copper_pick Ingot/charge registration alone does not implement smelting
Coal Biome-owned coal seams drop two hearth:coal items Each coal adds 240 real fuel seconds, subject to the same 600-second reserve cap and household authorization
Rock and timber One granite/basalt/limestone/slate/sandstone crafts four matching bricks; two matching rocks → two canonical stones. One oak/birch/pine/willow/alder/beech/aspen/rowan/hazel/spruce log crafts four matching planks; two matching species logs → two canonical logs. One species plank crafts one canonical plank All these conversions are shapeless; each pair uses two separate crafting slots, preserving mass (2:2). No single-log or single-rock canonical conversion; mixed types do not convert together

The original reed/plank window recipe remains available; quartz is an alternate mineral supply route to the same protected building node, not free reeds or a new unsupported window. Clay keeps its existing pottery and charcoal roles.

Exact process and thermal contract

The copper pick recipe is shaped: three hearth:copper_ingot across the top row, one hearth:sticks in the center of each remaining row, empty side cells; output is one pick. Quartz windows are shapeless: three quartz, one existing window. The original window uses two identical rows of plank / reed / plank (four canonical planks and two reeds). Each quartz/copper/coal seam drops two matching items, but each copper charge consumes exactly one ore and one charcoal.

The direct exact-name fuel table accepts sticks 45s, canonical logs 180s, oak/birch/pine/willow/alder/beech/aspen/rowan/hazel/spruce logs 180s each, charcoal 90s, coal 240s. Fuel does not ignite itself. A whole fuel item is refused without consumption if it would exceed 600 seconds. Planks, building nodes, raw ore, quartz and arbitrary tree groups are not fuels. Coal is a geological, nonrenewable supply; its higher heat value is not a renewable conversion loop.

Copper requires 75 seconds available at queue time (45 duration + 30 cost). The existing JOBS/RESULTS allowlists validate its distinct smelt_copper kind, 30 cost and copper-ingot output. Queueing reserves 30 seconds immediately and consumes one charge; the absolute UTC fuel deadline also burns 45 seconds during processing. Coal cannot replace the charcoal ingredient in the charge. Iron's separate charge still takes 60 seconds with 30 reserved.

One canonical log + one clay shapelessly make one charcoal charge; species logs must first convert in matching pairs: two same-species logs in separate crafting slots yield two canonical logs, not a single-log conversion. The charcoal job takes 60 seconds and reserves 30, producing one charcoal worth 90 seconds. There is no planks-to-log recipe and no fuel gain from converting timber to charcoal. No recipe is added by the process/UI integration; it exposes the content owner's actual recipes.

One hearth holds one job or one finished output. Queueing, fuel, ignition and collection retain the same claim/external-protection, household-use and six-block reach checks. Repeated timer/load reconciliation after restart or long absence finishes the paid job only once, even after fuel expires; it never creates an inventory item until authorized empty-handed collection. A full inventory or rejected insertion leaves the one output waiting and blocks replacement jobs.

Field notes and observational survey

The Mocha journal retains its original seven page indices and adds an eighth regional geology/timber page. It describes all ten registered communities: temperate meadow, oak woodland, birch forest, pine taiga, wet forest, floodplain, dry scrub, alpine meadow, rocky peaks and riverbank. Recipe search includes both window routes, copper charge/pick, all ten species planks, canonical log/plank/ stone conversions and all five regional rock bricks. Copper-ingot search also finds its real-time process instructions; ingots are not direct crafting outputs.

The survey reads the actual succession.habitat() result once: support ground, canopy/light/moisture, pollination (supporting plants, not an insect census) and nutrients (bounded reserve out of eight). Missing optional observations are shown as unavailable, not invented zeros. Ground labels are escaped for formspecs. Pine and spruce retain evergreen winter shade; the other eight tree species thin in winter. The API does not expose separate evergreen/deciduous canopy counts, so the survey does not invent them. Global active wildlife totals remain labeled as nonlocal.

Seasonal guidance explains pioneer birch, pine on podzol/alpine turf, wet-soil willow/alluvium and alder, clover/flower pollinator support, spring bluebells, autumn heather, wet sedge/bulrush, shade moss/ferns, rock lichen and nettle's nutrient requirement. Clover adds at most two nutrient units per support across replacement/restart while reserves are low; alder has a nitrogen-fixer habitat profile by itself, not an independent fertilizer process; with botany installed, the shared nitrogen-fixer policy also covers alder and other tagged species, subject to the same finite support budget. Decomposers recycle finite material. Habitat moisture is a bounded substrate/water/canopy estimate, not fully simulated hydrology, watersheds, erosion or flooding. The shared synthetic climate HUD and altitude-based environment remain unchanged. Survey observation never advances succession, spawns wildlife or loads terrain.

Eighty-species botanical field guide

The current catalogue is 80 named species, eight categories of ten each. It is a game catalogue of temperate north-west European organisms, not a real-world identification, toxicity or foraging guide. Category membership is an exclusive gameplay classification (for example, hazel is counted with trees, and sedges/rushes with grasses), not a claim about taxonomic rank. Names below follow the actual hearth.botany.list() records, including their chosen scientific-name synonyms:

Category (10 each) Common name — scientific name
Trees Pedunculate oak — Quercus robur; Silver birch — Betula pendula; Scots pine — Pinus sylvestris; White willow — Salix alba; Common alder — Alnus glutinosa; European beech — Fagus sylvatica; European aspen — Populus tremula; Rowan — Sorbus aucuparia; Common hazel — Corylus avellana; Norway spruce — Picea abies
Shrubs Bilberry — Vaccinium myrtillus; Pleated blackberry — Rubus plicatus; Red raspberry — Rubus idaeus; Black elder — Sambucus nigra; Blackthorn — Prunus spinosa; Common hawthorn — Crataegus monogyna; Dog rose — Rosa canina; European holly — Ilex aquifolium; Common juniper — Juniperus communis; Guelder rose — Viburnum opulus
Grasses, sedges and rushes Greater tussock-sedge — Carex paniculata; Bulrush (great reedmace) — Typha latifolia; Meadow fescue — Schedonorus pratensis; Cock's-foot — Dactylis glomerata; Timothy — Phleum pratense; Sweet vernal-grass — Anthoxanthum odoratum; Yorkshire-fog — Holcus lanatus; Tufted hair-grass — Deschampsia cespitosa; Common reed — Phragmites australis; Soft rush — Juncus effusus
Herbs White clover — Trifolium repens; Common nettle — Urtica dioica; Heather — Calluna vulgaris; English bluebell — Hyacinthoides non-scripta; Yarrow — Achillea millefolium; Common foxglove — Digitalis purpurea; Meadowsweet — Filipendula ulmaria; Wild garlic — Allium ursinum; Cowslip — Primula veris; Wood anemone — Anemone nemorosa
Ferns and mosses Bracken — Pteridium aquilinum; Lady-fern — Athyrium filix-femina; Male-fern — Dryopteris filix-mas; Hart's-tongue fern — Asplenium scolopendrium; Common polypody — Polypodium vulgare; Blunt-leaved bog-moss — Sphagnum palustre; Common haircap — Polytrichum commune; Cypress-leaved plait-moss — Hypnum cupressiforme; Broom fork-moss — Dicranum scoparium; Swan's-neck thyme-moss — Mnium hornum
Fungi Fly agaric — Amanita muscaria; Brown birch bolete — Leccinum scabrum; Bay bolete — Imleria badia; Chanterelle — Cantharellus cibarius; Wood blewit — Collybia nuda; Shaggy inkcap — Coprinus comatus; Turkey tail — Trametes versicolor; Oyster mushroom — Pleurotus ostreatus; Honey fungus — Armillaria mellea; Birch polypore — Fomitopsis betulina
Aquatic plants Common duckweed — Lemna minor; Yellow water-lily — Nuphar lutea; White water-lily — Nymphaea alba; Common water-crowfoot — Ranunculus aquatilis; Water mint — Mentha aquatica; Water forget-me-not — Myosotis scorpioides; Brooklime — Veronica beccabunga; Common water-starwort — Callitriche stagnalis; Rigid hornwort — Ceratophyllum demersum; Broad-leaved pondweed — Potamogeton natans
Lichens Reindeer lichen — Cladonia rangiferina; Oakmoss — Evernia prunastri; Old man's beard — Usnea subfloridana; Map lichen — Rhizocarpon geographicum; Dog lichen — Peltigera canina; Lungwort lichen — Lobaria pulmonaria; Common orange lichen — Xanthoria parietina; Hammered shield lichen — Parmelia sulcata; Mealy pixie-cup — Cladonia chlorophaea; Pebbled pixie-cup — Cladonia pyxidata

How do I browse it? Use /botany [search], or the Botanical guide button in the existing journal or ecosystem survey. The journal remains eight pages; no ninth sidebar pane is added. The browser has ten species rows per page in catalogue order, scrollable readable notes, Previous/Next, search, survey and field-note controls. The ecosystem journal page also lists all eight categories and their real common/scientific names. Missing or empty optional botany APIs produce an unavailable message, not fictional substitute species.

What does search mean? Up to 48 characters of literal text, never Lua patterns. It matches common/scientific names, IDs, category, habitat, seasons and roles. Control characters become spaces; queries and all displayed catalogue text are formspec-escaped. Page inputs are floored/clamped, including NaN and infinities; no match and empty catalogue each retain one navigable page. New search resets to page one; paging preserves the sanitized query.

Which interactions are active? The browser's substrate/light/moisture/pH, host and aquatic-depth ranges are game niche windows, not measured field data. Seasonal flowering supports the pollinator index, not spawned insects; browse supports wildlife, not human food permission. Nursery cover reduces recruit stress conditionally. Nitrogen-fixer policy consumes a finite two-unit support budget while reserves are low. Host-compatible root fungi can accelerate tree establishment while spending existing nutrient reserve. Saprotrophs can advance an existing natural litter/deadwood clock; they do not create a second nutrient payout. These require the appropriate season, habitat, natural origin, protection checks and loaded simulation; a tag is not an unconditional aura. Habitat engineering and resin-bearing labels are descriptive here, not a new hydrology simulator or extraction recipe. Parasitism and allelopathy are explicitly descriptor-only: no damage to player plants and no chemical killing effect.

Does a missing toxic flag mean edible? No. Toxic flags are catalogue labels, not an implemented general poisoning system or real-world safety assessment. Only bilberry, pleated blackberry and red raspberry have the catalogue's seasonal game berry-harvest permission; this does not add food interactions for other named fungi/herbs. Existing generic seasonal forage is a separate system. Never use these notes to identify or eat real organisms.

What does the survey count? It reads the actual habitat API, not an 80-species local census: grass/flower-support cover and combined shrub/fern/aquatic/tree cover, canopy, light and moisture. Optional pH, nursery support, aquatic niche, water depth, pollinator support and nutrients are displayed only when supplied; missing optional fields say unavailable. In the botanical API, nearby water cells (near_water) and aquatic depth (water) are different observations; the legacy API's water cell count is not presented as depth. The pH is a coarse substrate-class estimate, not a soil measurement. No species abundance is invented.

How do fallen logs work now? They remain ordinary full cubes laid sideways, with an axe required and exactly one canonical log as the drop. There is no hand-to-two-sticks harvest. The existing metadata-preserving orientation fix, tree stages and ten-tree botany implementation are retained unchanged by this process/journal pass. Claims and player-placed material remain protected from autonomous succession. Voice work is explicitly deferred.

The copper pick mines cracky=3 in 1.4 seconds, with 70 uses, versus flint's 2.4 seconds and 35 uses. It retains mining maxlevel=1, drop level 1, damage 3 and punch interval 1.2; it adds no tougher-rock capability and no wood capability. It is not a replacement for the separate iron axe progression. The exact new icons are hearth_item_copper_ingot.png, hearth_item_copper_charge.png, and hearth_item_copper_pick.png; ore, quartz and coal icons/nodes are registered by the biome owner only.

Broad-relief v7 preset: new worlds only

terrain.mjs exports pure terrainSettings(newWorld) and isTerrainSetting(line) helpers. run.mjs exports writeWorld() for direct disposable tests; importing it does not invoke its CLI. The launcher checks for existing world metadata before creating the world identity. Either existing world.mt or map_meta.txt suppresses the new preset. This also protects a legacy world without map metadata and an orphan map metadata file. Every play still gets a fresh, exclusive session configuration, but existing worlds get no mapgen, seed, water-level or mapgen-limit overrides, including from an inherited fixture. Saved map metadata is neither parsed nor rewritten.

Game defaults and the launcher agree on v7, water level 1, mapgen limit ±4096, caves, light, decorations, biomes and ores. Dungeons and floatlands are disabled; mountains, ridges and caverns are enabled. The launcher retains seed 731104 for fresh worlds, with explicit fresh-world fixture/seed-test overrides taking precedence. Existing seed and mapgen remain engine-owned.

This applies the source-reviewed recommendation with three deliberate adjustments: terrain-base scale 45 instead of 65, mount-height offset 250 instead of 230, and world bound 4096 instead of 512. Base offset 12 and alternate scale 28 keep gentler accessible terrain among the relief. Hills have 384-node spread, mountains/ridge-water fields 700-node spread and climate fields 256-node spread. Mountain density keeps the −0.6 bias and 180×280×180 spread. Mount-height noise is a density-gradient input, not an absolute peak-height cap. Neither the fixed seed nor these inputs guarantees a low, dry or resource-complete starting location.

The goal is broad hills, grounded massifs, river channels/canyon walls, woodland and alpine transitions—not floating islands or voxel confetti. This is native v7 noise and registered geology, not scientific erosion or watershed simulation. Small native overhangs/disconnected remnants remain possible despite nofloatlands. There is no global per-frame voxel rewriting or custom terrain postprocessor.

Existing worlds and transitions

Use a separate empty runtime root/new world to try the coherent preset. Do not delete the current save or metadata to obtain it. Managed play retains its normal prelaunch full backup and embedded-game identity checks. Existing generated chunks remain untouched; the world bound and mapgen parameters are not expanded in place. New biome/ore/decoration registrations can affect future ungenerated chunks of an old world and create visible seams against old terrain. Existing mapgen noise does not imply old biome registration tables are restored. There is no migration, automatic regeneration, chunk deletion or retrofit of old geology/vegetation. The operator must explicitly decide between a separate fresh world for coherent terrain and accepting new-biome boundaries in unexplored parts of an old world; this integration makes no automatic migration decision for existing saves.

Focused validation and remaining native gates

Botanical process/journal follow-up — 2026-11-03

72 focused standalone checks passed: hearth processes 34, recipe/journal/ survey 38. Both used in-memory snapshots of the actual on-disk modules and required the exact named-check total, final suite marker and empty stderr. The journal fixture loads the actual botanical factory and list() method, checking all 80 common/scientific names across eight ten-row pages and category counts. Coverage includes missing/empty botany APIs, all ten timber recipe/fuel routes, building-fuel rejection, bounded literal/escaped queries, pagination, chat/buttons/exit/session routing, footer/sidebar bounds, honest role/toxic labels, optional survey fields and axe-only fallen-log guidance.

Only the seven requested process/UI/test/documentation files changed in this follow-up. No voice work, full engine run, persistent-world launch or native visual certification was performed. Historical results below remain historical; they do not certify the newer 80-species pass.

Final integrated verification — 2026-11-02

  • Full pinned Luanti 5.18.0 check/smoke passed with 25 isolated Lua suites; the expanded suites cover 466 checks. The final invocation exited zero.
  • Native registration/crafting checks resolved 63 recipes / 47 outputs. Species logs and rocks use distinct matching-pair conversion recipes; no single-input canonical-conversion ambiguity remains.
  • Native media closure checked 807 references, with zero missing files.
  • All eight fixed seeds passed in one complete run without seed retries. Each had exposed water, food, flint, sticks, rushes, side-accessible timber, and dry natural landing patches (412–658 sampled patches per seed). Timber access checks inspect horizontal air beside trunks: a leaf canopy above a trunk does not make it unreachable, while buried logs do not count.
  • Four separated bounded worldgen probes observed four surface biomes and granite/slate/limestone/sandstone strata plus quartz, copper, coal and iron. This is sampled evidence, not proof every biome occurs in every seed.
  • All 59 Node tests passed, including original artwork, geometry, deterministic packaging, terrain presets and saved-world preservation. Final native, seed and Node commands each exited zero with empty stderr.
  • Earlier integration checks exposed ambiguous conversion recipes and an upland-rush generation ordering problem; both were fixed, not waived. Springs now generate before adjacent water-dependent rushes. The original overhead-air timber assertion was replaced with a genuine side-accessibility check.

These are disposable headless worlds. No persistent play world was opened or regenerated. Native appearance, performance, ecological balance and human acceptance remain unverified; noise-based relief is not a geological simulator. Optional complete audio codec regeneration was not configured.

Content tests preserve all previous checks, add register_ore to the mock, reject duplicate nodes/items/decorations, verify ten unique biome registrations and nine ordered ore definitions, check seasonal species order and idempotent registration, resolve every recipe/drop and validate named mineral/species/understory images. Tool capabilities and both window routes are checked. Art counts are checked by manifest roles rather than assuming every inventory image is a craftitem (the copper pick is a tool).

Tooling tests compare game defaults to the pure preset, verify new-world config emission and seed precedence, check repeat config writes are exclusive, and assert byte-for-byte unchanged existing world identity/map metadata. They also cover missing-map-metadata and orphan-metadata opt-outs. These are Node-only disposable fixtures, not a launch of the original play world.

Previously recorded terrain/content integration results: 136 Lua checks passed (content 33, biomes 23, seasons 11, ecology 9, succession 49, diversity 11), with each suite's expected final marker and empty stderr. The content suite also passed all 33 checks with a numeric flattened target and remapped sibling loader. 24 Node tooling tests passed, with zero failures, cancellations or skips and empty stderr. All three changed JavaScript/test modules passed syntax checks. Editor diagnostics and the owned tracked-file whitespace check were clean. No previous content or tooling test was removed.

Resource process/journal follow-up: 54 focused standalone checks passed: hearth processes 29 and recipe/journal/survey 25. Both required their exact named-check count and final suite marker, with empty stderr. Coverage includes every species fuel, coal capacity/refusal, copper duration and reserve boundaries, one-output collection, restart/long-offline idempotency, unauthorized interactions, full/rejecting inventories, invalid metadata and raw-item rejection. UI checks cover all five species/rock routes, both windows, copper crafting/process search, eight-page bounds, seasonal guidance, optional/hostile habitat fields and Mocha. The process fixture's notification closure was corrected to reference its local hearth instance; no production authorization behavior was bypassed. No full engine tests were launched for this follow-up, concurrently or otherwise. These mock tests do not certify new terrain, native rendering or real seed reachability.

Standalone Fengari execution requires named checks and the final suite marker with empty stderr; exit zero alone is insufficient. The content harness resolves siblings through its mock modpath/dofile boundary, not a replacement of live core. The recipe-collision regression keeps all 63 registered recipes / 47 distinct outputs and verifies exact output names/counts, unique shapeless ingredient multisets (including repeated inputs), and shaped layouts, including potential shaped/shapeless overlap. All 25 terrain recipes remain: single logs/rocks produce four species planks/bricks; matching pairs produce two canonical logs/ stones. The native smoke must still exercise every recipe through get_craft_result; standalone signature checks are not a native engine pass. Collision-fix validation passed 84 focused Fengari checks: biomes 24, content 35, and recipe/journal 25, with exact named totals, each suite's actual final marker (content uses 1..35), and empty stderr. In-memory negative probes separately restored the old single-log and single-rock conversions; both were rejected by their regression contracts. No engine was launched and no running player session was changed for this fix. Native isolated runners flatten Lua filenames: sibling lookup must use a directory plus explicit sibling basename, not gsub("content.lua", ...) on a numeric staged filename. Focused registration tests do not generate or certify actual terrain.

No full engine tests were run for this integration. Main must still validate saved preset values in a disposable native world, all seed starts including 731104, safe spawn heights, actual tree anchoring/media, and water/flint/sticks/ timber/forage/reeds/clay reachability. Existing emergence/resource fixtures limited to Y=96 can miss high slopes/peaks; canonical-only soil/log searches can miss species terrain. Adapt native probes and spawn policies rather than declaring these mock passes proof of seed safety or handing out supplies. Finish native process and visual/performance review separately. Historical M4 eight-seed results do not certify the new terrain preset.

Security: no secrets, network calls, dependencies, cryptography or arbitrary Lua execution are added. Bounded declarative registrations retain normal claim and external-protection checks. Existing guarded filesystem paths, exclusive config creation, snapshots and mod security remain in use; saved map metadata is read only for existence and never rewritten by this integration.