367 lines
24 KiB
Markdown
Executable File
367 lines
24 KiB
Markdown
Executable File
# The Last Hearth
|
||
|
||
An original, standalone Luanti survival prototype: gather flint and sticks, make
|
||
tools, build a supported shelter, fuel a hearth, cook forage and boil water.
|
||
It does not depend on Minetest Game (MTG). This is an **environment simulation
|
||
prototype, not a full physics simulator or a launch-ready public service**.
|
||
Original game code and procedural assets are MIT-licensed; the separately
|
||
distributed engine retains its own licenses.
|
||
|
||
## Status and planning
|
||
|
||
**M0 technical gates are complete. M1 implementation/preflight and M2 gameplay /
|
||
verification are complete; their human acceptance gates remain open. M3
|
||
implementation and automated verification are complete; its two-player acceptance
|
||
gate remains open.** M4 ecology, preservation, pottery, metalworking and bounded
|
||
offline process work has passed automated technical verification; its week-long
|
||
group acceptance remains open. M5 is now beginning with an offline-tested private
|
||
staging deployment contract, not a live deployment. See [M0 evidence](docs/m0-verification.md),
|
||
[M1 playtest gate](docs/m1-verification.md), [M2 evidence](docs/m2-verification.md),
|
||
[M3 implementation and verification](docs/m3-verification.md), and [M4 verification](docs/m4-verification.md).
|
||
|
||
The newer living-ecosystem and botanical field-journal/art integration is an
|
||
additional implementation pass, **pending main integrated validation and native
|
||
visual review**. Historical M4 results do not certify this new pass. No version
|
||
or save-schema bump is part of the journal work.
|
||
|
||
### Woodland traveler appearance
|
||
|
||
Use `/character`, or **Character appearance** in the inventory, to choose muted
|
||
woodland clothing, skin, face, hair and details with three equal-mechanics body
|
||
profiles. Four tabs and a rotatable 3D model preview keep changes in a private
|
||
draft: **Save / Apply** persists them; **Cancel** keeps the original. Joining
|
||
restores saved appearance without prompting. Corrupt appearance data is retained
|
||
with a safe-default warning, never a kick. Existing location forms retain priority.
|
||
See [character creator and recovery contract](docs/character-creator.md).
|
||
Focused offline tests do not certify native visuals or client interaction.
|
||
|
||
### Offline species reader
|
||
|
||
Use `/inspect` while pointing at a known plant/tree within six blocks, or
|
||
`/inspect oak` / `/inspect Quercus robur` for an exact catalogue ID or Latin name.
|
||
Field notes include **Inspect target**; `/botany` offers a **Species article**
|
||
selector for each ten-row page. Harvesting and building controls are unchanged.
|
||
|
||
The **Article** tab shows available cached plaintext Wikipedia introductions, labelled
|
||
**Wikipedia excerpt (offline)**, with copyable canonical/revision/history URLs,
|
||
contributor attribution and **CC BY-SA 4.0** licensing. Missing snapshots have
|
||
explicit availability notes, not counterfeit articles; cache expansion is a separate task. **Current
|
||
effects** distinguishes simulated game policy from descriptive natural history.
|
||
This is not a full wiki, embedded browser, or real-world identification/foraging
|
||
guide. Nothing is fetched or automatically opened; inspection writes no world or
|
||
player data. Text is escaped and bounded to 8,000 characters, 4,000 per page.
|
||
See [source coverage, licenses and reader contract](docs/species-references.md).
|
||
Focused isolated tests cover the reader; native visual/client integration remains
|
||
pending. Full-engine tests were not run for this change.
|
||
|
||
The [landscape/content expansion](docs/content-expansion.md) now wires ten
|
||
communities, thirteen tree species, a 100-species botanical catalogue and ordered
|
||
geology into the seasonal ecosystem. Its eight ecological groups are deliberately
|
||
uneven: 13 trees, 14 shrubs, 10 grasses, 22 herbs, 11 ferns/mosses, 10 fungi,
|
||
10 aquatic taxa and 10 lichens. The additions reflect ecological roles, not a
|
||
ten-per-category quota. The trees are oak, birch, pine, willow, alder, beech,
|
||
aspen, rowan, hazel, spruce, crab apple, wild cherry and field maple. All thirteen logs
|
||
fuel hearths for 180 seconds and craft four matching planks; buildings/planks
|
||
are not direct fuel. Copper charges/ingots/picks, copper smelting, coal fuel and
|
||
a three-quartz alternate window recipe are integrated; native validation of the
|
||
latest botanical pass remains pending. New launcher worlds use a broad-relief v7 preset with
|
||
a ±4096 bound; **existing saved mapgen/seed/bounds are not retuned**. Old chunks
|
||
are never regenerated; future unexplored chunks can change and leave seams.
|
||
Focused registration/tooling tests do not certify new-seed safety or engine visuals.
|
||
|
||
**Human acceptance remains open across M1–M4.** The actual M1 course has not been evidenced as
|
||
traversed/repeated by several testers, and there are no measured FPS, frame-time,
|
||
multiplayer, latency or hardware-envelope results. M2 implementation is proceeding
|
||
under the user's explicit direction; this does not waive those gates or claim the
|
||
M2 unfamiliar-tester, M3 two-player cabin, or M4 week-long group gate has passed.
|
||
|
||
- [Roadmap: M0–M6 and M1 acceptance](docs/roadmap.md)
|
||
- [Launch feature checklist: F01–F19](docs/launch-features.md)
|
||
- [M0 decisions, provisional budgets, risks and evidence](docs/m0-decisions.md)
|
||
- [Architecture and save/module contracts](docs/architecture.md)
|
||
|
||
The exact development contract is **Luanti 5.18.0, game 0.5.0-m4, save schema 1**.
|
||
See [release.json](release.json) and [package.json](package.json). Native-first:
|
||
Windows is natively verified on the existing development host. Linux/macOS path
|
||
selection has unit coverage only; native execution is unverified on both. No clean
|
||
machine was tested. A browser client
|
||
is **not promised launch-ready**. There is no committed public launch date.
|
||
|
||
## Run and test locally
|
||
|
||
Requires Node.js 22+ (built-in modules only), a separately installed stock Luanti
|
||
**5.18.0**, and a trusted writable runtime directory. The launcher checks the
|
||
engine's reported version; it does not download the engine or authenticate it.
|
||
On non-Windows systems set `HEARTH_ENGINE` to the absolute executable path. On
|
||
Windows it defaults to the existing Luanti 5.18.0 win64 runtime's bin directory;
|
||
setting `HEARTH_ENGINE` explicitly also works there. A headless-only server binary
|
||
can run checks but cannot provide graphical play.
|
||
|
||
From this repository, using Node on PATH:
|
||
|
||
```text
|
||
node scripts/run.mjs check
|
||
node scripts/run.mjs smoke
|
||
node scripts/run.mjs test
|
||
node scripts/run.mjs test:seeds
|
||
npm test
|
||
node scripts/run.mjs play
|
||
node scripts/run.mjs test:course
|
||
node scripts/run.mjs course
|
||
```
|
||
|
||
- **check:** disposable headless world, game startup and compilation of the Lua
|
||
sources/specs. Compilation alone does not execute the unit assertions.
|
||
- **smoke:** real-engine registry/crafting/terrain/resource/enclosure checks and
|
||
isolated execution of the discovered Lua unit specs. Mocked globals do not
|
||
replace globals in the live game.
|
||
- **test:** check plus smoke; with `HEARTH_LUA` set to an absolute Lua 5.1+/LuaJIT
|
||
executable, also runs the standalone Lua harnesses. No separate Lua is otherwise
|
||
required. Do not rely on historical test counts: record named suites/results.
|
||
- **test:seeds:** fresh real-engine worlds for eight fixed map seeds; checks safe
|
||
arrival surfaces and required starting resources without touching the play world.
|
||
- **M3:** structure removal is refused if it would strand connected construction.
|
||
`/claim share` manages household access and `/claim show` briefly marks boundaries.
|
||
See [M3 rules and remaining gates](docs/m3-verification.md).
|
||
- **npm test:** Node tooling tests only, not the engine suite. The `test:engine`
|
||
package script runs the engine suite; `test:recovery` is a separate, private
|
||
offline recovery exercise described below.
|
||
- **play:** persistent local singleplayer world. Uses normal engine controls.
|
||
The expanded v7 preset applies only at creation. Use a separate empty
|
||
`HEARTH_HOME` to try it without migrating/deleting the current world. See
|
||
[new-world settings and existing-world transitions](docs/content-expansion.md#broad-relief-v7-preset-new-worlds-only).
|
||
- **course:** a fresh disposable summer course; it never opens or changes
|
||
worlds/last_hearth. Wait for arrival, then run `/course` to generate the route
|
||
and receive a temporary kit. The course route covers half-steps, a one-wide
|
||
doorway, water, two controlled falls, gathering, construction and an arena.
|
||
Run `/course report` for checkpoint progress and server-step/Lua-callback
|
||
samples—**not** client FPS. `/spar` opts into a bounded moving sparring opponent;
|
||
`/practice` uses the stationary reference target. PvP remains disabled.
|
||
- **test:course:** native headless enrollment/staging and no-consent preflight.
|
||
It intentionally does not generate terrain, forge a player, or claim traversal.
|
||
|
||
Engine checks require zero exit status **and** a unique per-run success marker.
|
||
Their outer deadline is 90 seconds; standalone Lua invocations are bounded to
|
||
30 seconds. Graphical play has an eight-hour safety bound. Quit normally to save;
|
||
interrupts/deadlines kill the child and are not graceful-save guarantees. Session
|
||
configuration and logs are temporary and removed at session cleanup; retain
|
||
sanitized evidence separately when validating. See [scripts/run.mjs](scripts/run.mjs).
|
||
|
||
## Data locations and isolation
|
||
|
||
`HEARTH_HOME` overrides the runtime root and must be absolute. Without it:
|
||
|
||
| Platform | Default root (literal environment notation) |
|
||
| --- | --- |
|
||
| Windows | %LOCALAPPDATA%/last-hearth-runtime |
|
||
| Linux | $XDG_DATA_HOME/last-hearth-runtime, or $HOME/.local/share/last-hearth-runtime |
|
||
| macOS (runner unverified) | $HOME/Library/Application Support/last-hearth-runtime |
|
||
|
||
The **old Windows runtime and world location remain unchanged**. Within the root,
|
||
the persistent world is under worlds/last_hearth and retained snapshots are under
|
||
backups. Each invocation packages a generated game into a temporary session's
|
||
games directory and sets `LUANTI_GAME_PATH`; it does **not** overwrite the engine
|
||
installation or its games. See [scripts/launcher.mjs](scripts/launcher.mjs).
|
||
|
||
Use a **different absolute `HEARTH_HOME` for staging**, with an explicit
|
||
`HEARTH_ENGINE` when the engine lives outside it. Changing the root does not copy
|
||
or migrate the old world. Production must use a separate external deployment,
|
||
storage and configuration, outside this checkout, packages and webroots. The
|
||
local launcher is not a dedicated-server deployment tool. It binds loopback,
|
||
disables announcements, PvP and creative mode, and keeps mod security enabled.
|
||
|
||
## Package, back up and restore
|
||
|
||
Examples below use absolute Windows destinations; substitute your own trusted
|
||
paths (POSIX absolute paths on Linux/macOS). **Parents must already exist and
|
||
each destination must be new. No command overwrites an existing destination.**
|
||
|
||
```text
|
||
node scripts/run.mjs package C:/HearthArtifacts/game-0.1.0-m0
|
||
node scripts/run.mjs verify C:/HearthArtifacts/game-0.1.0-m0
|
||
node scripts/run.mjs backup C:/HearthPrivate/worlds/last_hearth C:/HearthPrivate/backups/manual-001 --offline
|
||
node scripts/run.mjs restore C:/HearthPrivate/backups/manual-001 C:/HearthPrivate/worlds/restored-001 --offline
|
||
```
|
||
|
||
Without a destination, `package` uses the dist/last_hearth directory, still
|
||
requiring it not to exist. Packaging generates assets and includes release,
|
||
configuration, license, mod and JSON fixture inputs plus an exact SHA-256
|
||
inventory. It is an engine-independent **game directory**, not an engine/client
|
||
bundle or installer; it excludes saves, tooling and the full test suite.
|
||
`verify` verifies a **game package**, not a world backup. Restore verifies a
|
||
backup before and after copying; [scripts/backup.mjs](scripts/backup.mjs) also
|
||
exports `verifyBackup()` for programmatic verification.
|
||
|
||
**Before backup, restore, recovery, or launching an existing managed world, stop
|
||
ALL engines that could access it, including external engines on other machines.**
|
||
`--offline` is the operator's confirmation, not a mechanism that stops them.
|
||
Launcher/world locks and SQLite sidecar checks cannot prove remote idleness.
|
||
Do not delete locks/sidecars merely to bypass a refusal. Clear a stale launcher
|
||
lock only after confirming every relevant process has stopped.
|
||
|
||
The launcher takes a full retained prelaunch snapshot of an existing managed
|
||
world; it has no automatic retention deletion. Backups include private map,
|
||
player, authentication, inventory and mod data: use access-controlled, preferably
|
||
encrypted storage, never a public artifact directory. Permissions remain the
|
||
operator's responsibility; portable file modes do not provision Windows ACLs.
|
||
SHA-256 detects **corruption, not authenticity**; it is not signing or encryption.
|
||
Preserve the original snapshot and restore to a new directory before considering
|
||
any operator-controlled cutover. See [scripts/package.mjs](scripts/package.mjs),
|
||
[scripts/files.mjs](scripts/files.mjs) and [scripts/backup.mjs](scripts/backup.mjs).
|
||
|
||
### Private old-save recovery evidence
|
||
|
||
The `test:recovery` package script runs [scripts/recovery.mjs](scripts/recovery.mjs).
|
||
Stop all engines and other Hearth tooling first. `HEARTH_RECOVERY_SOURCE` selects
|
||
an absolute existing SQLite world; otherwise it selects the legacy Windows world
|
||
under `LOCALAPPDATA`. **`HEARTH_HOME` changes recovery's working/backup root, not
|
||
that default source.** Non-Windows operators normally need an explicit source.
|
||
|
||
Recovery retains an untouched snapshot, verifies byte-exact restores, boots only
|
||
instrumented disposable copies twice, and checks migration/restart behavior.
|
||
Temporary copies omit old worldmods and use synthetic staging coordinates. A
|
||
sanitized report is retained beside, not inside, the immutable snapshot. The
|
||
original world is never launched. The retained successful report records 79 seed
|
||
and 81 restart assertions, two byte-exact restores, two engine shutdowns and an
|
||
unchanged source. It tested an earlier package, not the final export; its source
|
||
had zero claims, so claim-owner/protection coverage uses regression fixtures and
|
||
mocks, not preservation of existing source claims. This is not a real-client
|
||
recovery playtest or public-service disaster recovery certification. See the
|
||
[recovery evidence and qualifications](docs/m0-verification.md#retained-recovery-evidence).
|
||
|
||
## First play and current rules
|
||
|
||
- **I** opens crafting and field notes; `/guide` reopens help.
|
||
- **Ecosystem survey** in the field journal, or `/ecosystem`, observes one small
|
||
loaded habitat patch and reports the actual global active counts for all 23 animal identities. It does not
|
||
grow plants, spawn animals, force-load terrain or change world state.
|
||
- **Botanical guide** in the journal/survey, or `/botany [search]`, browses the
|
||
actual catalogue, ten species per page. Search is literal, escaped and limited
|
||
to 48 characters; it includes common/scientific names, category, habitat,
|
||
seasons and ecological roles. Toxicity flags are game labels, **not real-world
|
||
food-safety advice**; unflagged does not mean edible. Missing catalogue APIs
|
||
display an unavailable message. See the [100-taxon category list and role limits](docs/botany.md).
|
||
- **Fauna guide** in the journal/botanical guide/survey, or `/fauna [search]`,
|
||
browses all 23 animal identities, source URLs and lifecycle status. Field-level
|
||
source-reported ranges, unverified fallback policies and **UNKNOWN** are distinct;
|
||
identity citations do not establish numeric timing. The existing plant article
|
||
reader is unchanged. No runtime network fetch or ecological mutation occurs.
|
||
- Gather flint, sticks, berries and reeds. Make an axe to harvest timber; build
|
||
supported walls/roof and fuel a stone hearth with sticks/logs.
|
||
- Fallen logs are ordinary sideways full cubes. An axe yields **one canonical
|
||
log**, not two sticks gathered by hand. Existing full-block trees/deadwood are
|
||
retained; this journal/process pass does not replace their geometry.
|
||
- Use a cup on water, then use untreated water on a fueled hearth before drinking.
|
||
- **Aux1** (normally E) plus forward sprints; release after exhaustion and recover
|
||
stamina before sprinting again. FOV is unchanged by default; `/comfort fov 75`
|
||
applies a session-only static preference.
|
||
- `/practice` places a stationary target. In local play or privileged staging,
|
||
`/spar` opts into one moving opponent. Strike to begin a round; step back/aside
|
||
to evade or face the attacker and hold right-click with a spear to brace.
|
||
- The controlled route exists only in the disposable launcher-created course
|
||
world. `/course retry` restarts its run. A settings flag alone cannot authorize
|
||
course generation in a survival/production world.
|
||
- `/claim` protects one 25 × 25 area, extending ±24 vertically. `/claim share`
|
||
grants resident (build/use) or storekeeper (storage-only) rights; `/claim unshare`,
|
||
`/claim list`, `/claim show`, and `/claim remove` manage membership and bounds.
|
||
|
||
Death preserves inventory, food, water and wetness; respawn only limits stamina
|
||
and warmth before safe home/fallback arrival. A home must be inside the player's
|
||
own claim and is revalidated at use. Offline player needs pause; hearth fuel and
|
||
queued cooking/boiling use real-time deadlines, while completed output waits for
|
||
collection. Food cooks in six seconds, water boils in four, and fuel cost is
|
||
reserved when a job starts. A craftable bedroll grants a small warmth recovery
|
||
after five uninterrupted sheltered seconds; it does not skip world time.
|
||
M4 adds seasonal crops and preservation; general food spoilage remains disabled.
|
||
PvP is disabled. See the [M2 rules and limits](docs/m2-verification.md) and
|
||
[M4 offline contract](docs/m4-verification.md).
|
||
|
||
### A living landscape, a botanical field journal
|
||
|
||
The [living ecosystem model](docs/ecosystems.md) is an original implementation
|
||
inspired by Dynamic Life's ecological ideas, not copied datapack code or assets.
|
||
Light, shade, moisture and competition shape meadow grass, wildflowers, ferns and
|
||
slow tree succession. Litter, fungi and dung recycle finite nutrients; grazing
|
||
debits finite forage and wildlife links habitat to the food web. Calendar organism
|
||
ages include the full unloaded interval; ecological work remains bounded and
|
||
loaded-only, never replaying an offline backlog. Named trees use species-profile
|
||
calendar endpoints, typically years to decades; conservative fallback thresholds
|
||
are explicitly not researched timings. Fungi do not accelerate tree maturation.
|
||
Claims, placed plants, crops and construction are excluded from autonomous changes;
|
||
existing crop and planted-sapling clocks keep their separate rules. Survey counts
|
||
cover a fixed 5×5×5 patch at your feet, not the whole landscape; unloaded cells are
|
||
explicitly unknown. Wildlife totals describe all currently active animals, not a
|
||
local census or saved population. There is no compulsory ecological quest.
|
||
|
||
Content installs the pure lifecycle namespace before biological factories, and
|
||
publishes wildlife's exact returned fauna catalogue. Human botanical harvest and
|
||
animal frugivory share `botany_ready_at`: after a successful crop debit it rests
|
||
one mean real year (**365.2425 days**), then requires its fruit season, not a
|
||
24-hour refill. One live pollination credit can add only **one** berry to the
|
||
existing two-berry crop; empty or cooling bushes never manufacture fruit. Human
|
||
inventory rejection restores fruit and credit; partial delivery spends both once,
|
||
and reservations precede inventory callbacks to prevent reentrant duplication.
|
||
|
||
All 23 animal identities register fixed, originally authored skeletal B3D assets
|
||
with 100 frames and five clips (idle, locomotion, feeding, flight/swim and rest)
|
||
at 24 fps. Registration/animation contracts are not native visual acceptance.
|
||
Established recruitment is immigration, **not an adult birth**. Every incomplete
|
||
profile disables reproduction by default; pairing, pregnancy, nesting, egg/larval
|
||
development, caste/colony reproduction and delayed implantation remain future
|
||
work. Unknown lives and source longevity averages never imply automatic death.
|
||
No offline meals, dung, births, forced map loading or missed-season replay occur.
|
||
See [calendar evidence and transaction contract](docs/lifecycles.md),
|
||
[fauna behavior and limitations](docs/fauna.md) and [ecosystem policies](docs/ecosystems.md).
|
||
This integration was focused-test-only: no engine launch, world change, version
|
||
bump, wiki-cache edit or claim of complete true-life biology.
|
||
|
||
The [moonlit botanical art direction](docs/art-direction.md) pairs original pixel
|
||
materials with the eom.dev Mocha interface: base `#1e1e2e`, mantle `#181825`, raised
|
||
`#292940`, border `#3c3d56`, pale `#cdd6f4` text and `#a6adc8` annotations. Mauve
|
||
`#cba6f7`, teal `#94e2d5` and yellow `#f9e2af` are restrained navigation, botanical
|
||
and warmth accents. The eight-page guide, botanical browser, recipes, satchel/crafting and location
|
||
forms share controls, dark fields, list colors, tooltips and pressed-sprig dividers.
|
||
HUD needs use labeled percentages and colored tracks on a dark panel rather than
|
||
ASCII bars. The ten-slot hotbar repeats the authored single-slot texture and uses
|
||
the authored selection outline; standard crosshair asset integration belongs to
|
||
the generated-art pass. Client scaling, contrast, long text and artwork still need
|
||
native visual acceptance; automated checks are not a claim of polished gameplay.
|
||
|
||
### Location and privacy
|
||
|
||
Optionally set **both** `HEARTH_LATITUDE` and `HEARTH_LONGITUDE` (−90…90 and
|
||
−180…180). Local worlds can instead use the prompt or `/location`; an unchosen
|
||
local world shows a disclosed neutral equatorial preview. There is no IP lookup
|
||
or external location service. Configured/stored coordinates are private data.
|
||
|
||
Dedicated servers require explicit administrator-selected `hearth_latitude` and
|
||
`hearth_longitude`, even with a stored location. The community location is **not
|
||
chosen**: the user/operator must approve it before M2 climate staging. The M0
|
||
45°N, 0°E synthetic fixture is **not a production location**. The host UTC clock
|
||
drives a synthetic seasonal model and an approximate fixed-orbit sky, not live
|
||
weather. Labels are UTC and local solar time, not civil timezone/DST.
|
||
|
||
`HEARTH_FIXTURE` selects `first-session`, `summer`, or `winter` for isolated local
|
||
or staging work. First-session fixes seed 731104, not the date/location; summer
|
||
and winter fix UTC/weather/45°N, 0°E. Use a separate staging root/world; never
|
||
apply fixtures to valued play data. Production rejects preview/test settings.
|
||
See [tests/fixtures/scenarios.json](tests/fixtures/scenarios.json) and
|
||
[settingtypes.txt](settingtypes.txt).
|
||
|
||
## Known limits, not fixes
|
||
|
||
M1 code now implements smoothed stamina/sprint transitions, collision/course test
|
||
geometry, animated held tools, material feedback and moving sparring. Manual
|
||
feel/collision evaluation, voluntary repeat testing and performance/network
|
||
measurements remain open; see [M1 verification](docs/m1-verification.md). This
|
||
is not a custom engine/client controller; the newer bounded wildlife work is
|
||
documented separately above. Stock Luanti remains the
|
||
M1 baseline unless human measurements reveal a specific blocking engine limitation.
|
||
M2 replaced the old below-world teleport with safe bounded recovery. M3 now provides
|
||
bounded room/vent-aware comfort, a small building palette, refuse-unsafe-removal,
|
||
shared resident/storekeeper roles and protected storage. This is not a full structural
|
||
physics engine or persistent smoke simulation; two-player grief/comfort acceptance
|
||
is still open. Generated art remains procedural prototype art. Public operations,
|
||
moderation, identity and disaster-recovery acceptance remain later gates; no account,
|
||
browser parity or multiplayer-hardening approval is implied.
|