Files
last-hearth/docs/species-references.md
T
2026-11-05 09:57:11 -05:00

24 KiB
Executable File

Offline species Wikipedia references

Shipped source coverage

The bundle follows all 100 actual Latin names in the botany catalogue, not their sometimes ambiguous common names. The approved maintenance --refresh run on 2026-11-03 UTC queried all 100 names using ten MediaWiki API batches of ten, with at most two requests in flight, using the absolute installed Node executable and only the hardcoded English Wikipedia API URL.

98 entries contain real English Wikipedia plaintext introductions (78 previous + 20 new). Two entries contain original availability notes, not Wikipedia quotations:

Game ID Exact catalogue Latin name Source status
old_mans_beard Usnea subfloridana Exact species page missing
cup_lichen Cladonia chlorophaea Exact species page missing

For both missing species, the refreshed API explicitly returned missing: true; separate exact-page and REST-summary checks in the previous 80-species maintenance run returned HTTP 404. No genus, species complex, similarly named lichen, invented revision, or synthetic Wikipedia prose was substituted. Consequently 100 actual species article excerpts are blocked by source availability. The original notes make this visible to offline players. Refresh can pick up an article if Wikipedia creates one later. All previous 78 introduction texts and two availability-note texts were preserved exactly (verified by matching SHA-256 over ordered ID/text/kind records before and after refresh); retrieval timestamps were refreshed from actual batch completion times.

Twenty newly cached species references

All twenty new exact catalogue names resolved directly to the same Wikipedia title, without guessed aliases. Each entry contains an actual plaintext introduction, positive page/revision IDs, the API revision timestamp, actual retrieval timestamp, contributor attribution/history, and CC BY-SA 4.0 licensing. Retrieval occurred between 2026-11-03T19:54:51.978Z and 2026-11-03T19:54:52.400Z; per-entry timestamps are retained in the bundle. None of these additions required an availability note or shortening.

Game ID Exact catalogue Latin name / Wikipedia source title Page ID Permanent source revision
crab_apple Malus sylvestris 5958504 1380105044
wild_cherry Prunus avium 28331736 1380998001
field_maple Acer campestre 437923 1366038360
honeysuckle Lonicera periclymenum 811057 1354922261
ivy Hedera helix 5372245 1382798111
gorse Ulex europaeus 2482094 1382611269
broom Cytisus scoparius 510118 1351345770
dandelion Taraxacum officinale 10783290 1371025491
daisy Bellis perennis 1157853 1375045201
red_clover Trifolium pratense 1900302 1371055360
birdsfoot_trefoil Lotus corniculatus 1117322 1379332042
ribwort_plantain Plantago lanceolata 1250244 1377190915
selfheal Prunella vulgaris 12058348 1380124722
knapweed Centaurea nigra 21631605 1366977479
oxeye_daisy Leucanthemum vulgare 567709 1381123379
field_scabious Knautia arvensis 12057909 1371147715
teasel Dipsacus fullonum 4298215 1375022541
cow_parsley Anthriscus sylvestris 2649495 1375096601
garlic_mustard Alliaria petiolata 509457 1375930171
holly_fern Polystichum setiferum 5025872 1296456929

Five catalogue names resolved through Wikipedia's own title redirects in this snapshot:

Catalogue Latin name Recorded source title
Schedonorus pratensis Lolium pratense
Phleum pratense Timothy (grass)
Calluna vulgaris Calluna
Anemone nemorosa Anemonoides nemorosa
Evernia prunastri Oakmoss

These are API-reported redirects, not guessed mappings or search results. The catalogue's current Collybia nuda already matches its current Wikipedia title; the script does not silently replace it with an older Lepista name. Calluna is the article reached by Wikipedia's exact Calluna vulgaris redirect, not a separately selected genus fallback.

Lua/UI data contract

mods/hearth/wiki_articles.lua is a plain Lua module returning a table keyed by botany ID. It has no factory, global assignments, registrations, dependencies, HTTP requests or gameplay side effects. Content initialization loads this table into hearth.wiki_articles and constructs hearth.species_effects after botany and before succession. The interface constructs the injected reader factory and owns its command/field callbacks.

Reading in game

  • /inspect observes the first pointed node within six blocks of the player's eye, using a bounded ray and get_node_or_nil. Unknown or unloaded first surfaces stop inspection; nothing is emerged, force-loaded, harvested, placed or written. Species-specific seasonal plants, tree stems/stages, logs and leaves resolve through the actual botany.kind() API. Generic unnamed vegetation is not assigned an invented species.
  • /inspect oak or /inspect Quercus robur opens an exact catalogue ID or canonical Latin name. Matching is exact and case-sensitive (surrounding whitespace is allowed), not fuzzy, common-name search or an arbitrary URL. /botany [search] remains the literal-search catalogue browser.
  • Field notes offer Inspect target. The Botanical guide keeps its ten-row pages and adds a Species article dropdown/button for those rows. Selections are bounded numeric indices into the server session's current-page IDs, never submitted IDs or URLs. A HUD hint on known botanical targets advertises /inspect species (replace “species” with an ID, or use bare /inspect for the target). No harvesting or building callbacks are hijacked.
  • The Article tab displays Wikipedia excerpt (offline) for the 98 real introductions. The two missing species use No Wikipedia article cached (offline) and show their original CC0 availability notes, never fake Wikipedia prose or revisions. No HTML, embedded browser or full-article availability is claimed.
  • Current effects comes directly from species_effects.describe(record): SIMULATED and DESCRIPTIVE (not simulated) are separate labels. Reviewed evidence notes and evidence URLs are distinct from snapshot identity provenance. The excerpt may omit the body section supporting an effect; numbers, timings, niche thresholds and budgets remain game policy, not measurements from Wikipedia.
  • Body text is limited to 8,000 Unicode code points, in pages of 4,000. All current introductions fit one page unchanged (maximum 3,417). Any reader-side cap is disclosed. Unnamed read-only, selectable textareas show source title, attribution, license/link, canonical URL, permanent revision URL, contributor history, revision/retrieval timestamps and changes. Links are copyable plain text, never fetched or automatically opened.
  • Closing the reader clears only session navigation. Article/effect reading never changes needs, inventory, node metadata, protection, succession, food permission or persistent state. Submitted article text, source URLs, species IDs and page numbers are ignored; tabs and buttons use validated server-held state. No privileges, credentials, dynamic evaluation or runtime network access are added.

This remains not identification, foraging, food preparation or medical advice. Native Luanti formspec, visual and connected-player integration validation of this reader is pending; isolated tests do not certify those surfaces.

Each Wikipedia entry exports:

Field Type / meaning
table key Stable species ID, e.g. oak, wood_blewit, old_mans_beard
latin Exact catalogue binomial, retained even after a redirect
title Actual resolved English Wikipedia source title; never HTML displaytitle
url Validated canonical HTTPS article URL; copyable full-article link
pageid Positive, finite JavaScript-safe integer identifying the source page
revision Positive, finite safe integer revision ID; must equal API lastrevid
revision_url Permanent source URL using oldid
history_url Article history URL identifying Wikipedia contributors/authorship
revision_timestamp API source revision UTC timestamp
retrieved UTC ISO timestamp captured after the batch response
text Verbatim plaintext introduction prefix, at most 8,000 Unicode code points
kind wikipedia_intro
excerpt true: this is an introduction, not the full article
truncated Whether the introduction itself was shortened to meet the cap
attribution Wikipedia contributors, "<actual title>"
license CC BY-SA 4.0
license_url https://creativecommons.org/licenses/by-sa/4.0/
changes Describes plaintext introduction extraction, body omission and any shortening; no translation

For an unavailable species, kind = 'original_notes', excerpt = false, and truncated = false. text explicitly says it is an original availability note, not a Wikipedia excerpt. pageid, revision, revision_url, and revision_timestamp are nil/absent, not zero, strings, or fake revision numbers. url and history_url retain the exact missing species destination; they are not claims that an article exists. The original availability notes are dedicated to CC0 1.0, with their own attribution, license, license_url and changes fields. Never display them under a Wikipedia-excerpt heading or the Wikipedia license.

Presentation and attribution requirements

  • Display title, latin, text, and an explicit Wikipedia introduction excerpt label for wikipedia_intro. An availability note must get its own distinct label.
  • Display the stored attribution, license/link, retrieval date, permanent revision link, history link and changes notice with the excerpt. The permanent revision and linked page history provide access to the contributing authors; no author usernames or personal information are downloaded into the bundle.
  • Render plain text only. Never interpret HTML, wikitext, Markdown, inline links or article text as executable Lua or formspec syntax. Apply the UI's formspec escaping to every displayed field; byte escaping in the Lua source does not replace presentation-layer escaping.
  • Offer url and revision_url as copyable text. Do not fetch them, prefetch link previews, auto-open a browser, or follow links found in text at runtime.
  • Keep the warning that Wikipedia and game descriptions are not identification, foraging, food preparation or medical advice. Wikipedia can describe toxic species, traditional uses, disputed findings, or processing methods; copying its introduction does not endorse them or enable a game effect.
  • Preserve Wikipedia attribution and CC BY-SA 4.0 when redistributing or adapting Wikipedia excerpts. Share adaptations under the applicable ShareAlike terms and describe modifications. This source-text license is distinct from the game's original code/art licenses. No images, page HTML or full article bodies are copied.

The shipped 98 introductions have a maximum of 3,417 Unicode code points; zero required additional shortening. Extraction omits article bodies and uses MediaWiki's exintro=1 / explaintext=1; whitespace is trimmed only at the ends. Future overlong introductions are cut on a paragraph, sentence, or word boundary without adding invented continuation text, and set truncated = true.

What the real sources support about effects

The actual text is available for in-game reading, not just a source-name label. These examples were reviewed against the cached introductions and their exact source revisions:

Species / cached ID Natural-history observation actually present in the cached introduction Source revision
Quercus robur / oak Near-neutral lowland soils; supports herbivorous insects, acorn-eating birds/mammals and fungi. Supports a qualitative habitat/food-web explanation, not a numeric resource multiplier. Wikipedia revision 1377452916
Alnus glutinosa / alder Wet habitats, association with Frankia alni in poor soils, wildlife food/shelter, and light-demanding pioneer regeneration. The introduction does not quantify a game nutrient budget. Wikipedia revision 1379114226
Trifolium repens / clover Widely introduced and cultivated as a forage crop. This supports a forage description, not human edibility or a quantified nitrogen-fixation rate. Wikipedia revision 1376551191
Sphagnum palustre / sphagnum Strong water absorption and wet-forest habitat. The article's reported absorption capacity is a natural-history statement, not a measured in-game moisture transfer. Wikipedia revision 1241630727
Amanita muscaria / fly_agaric Tree symbioses and poisoning risk. Supports a qualitative mycorrhizal/toxicity explanation; does not establish a safe consumption procedure or specify all permitted game hosts. Wikipedia revision 1380994403
Ceratophyllum demersum / hornwort Submerged, free-floating aquatic growth. Supports the catalogue's qualitative rootless/submerged explanation, not a numerical light or water-depth window. Wikipedia revision 1366317776

Do not claim that all existing botany effects are scientifically verified by these introductions. For example, the cached Pteridium aquilinum introduction does not establish the catalogue's allelopathy descriptor; the cached Peltigera canina introduction does not establish its nitrogen-fixer descriptor. The white-clover introduction likewise does not establish nitrogen-fixation rates. Those claims need separately reviewed species-specific sources or relevant article sections before an effects UI may call them sourced. Historical medicinal uses and preliminary extract studies are not proof of clinical benefit.

Existing game niche thresholds, nutrient caps, timing, protection rules, edibility decisions, host lists and conservation budgets remain game policy, not quotations or measurements from Wikipedia. This bundle neither derives those constants from prose nor changes mechanics. Disabled descriptive effects stay disabled. Reading an article never grants food permission, healing, buffs, poisoning, resource creation, or plant damage. The source observations above provide real evidence for explanatory text while keeping the unverified and numerical parts explicitly separate.

Explicit maintenance script

scripts/wiki-species.mjs uses Node.js 22+ built-ins only. Arguments are deliberately limited to exactly one of:

  • --refresh: read the fixed botany catalogue, require exactly 100 literal rows, query all 100 Latin names, validate complete results, then replace the fixed Lua output. Explicit missing pages become original availability notes. Print exact source counts and batch bounds.
  • --check: parse and validate the generated bundle and its agreement with the current catalogue offline. Print source counts and network requests: 0.
  • --help: print maintenance usage, without reading articles or making requests.

Invoke Node with this script path and one of those flags. There are no URL, title, credential, output-path, retry, concurrency or timeout override arguments. Importing the script does not run maintenance or contact Wikipedia. Tests can inject fetchImpl and now into exported pure/testable helpers; normal maintenance uses built-in fetch. Catalogue parsing is bounded literal-row parsing, never Lua execution.

Security and failure behavior

  • Only https://en.wikipedia.org/w/api.php is fetched. Latin names go through a strict binomial allowlist and URLSearchParams, never string-interpolated query syntax. Queries contain only the public catalogue Latin names, not player names or private data. No credentials, API keys, cookies or authorization headers are used. The descriptive LastHearthSpeciesBundle/1.0 user agent identifies this manual offline-bundle use.
  • Scope: at most 100 records in fetcher/serializer/parser helpers, ten titles per batch, two concurrent batches. A complete normal refresh makes ten API requests. No search queries, crawl, pagination, automatic retries, external links, or per-player network activity.
  • HTTP redirect mode is manual. At most two redirects per batch are accepted, only to the same allowlisted HTTPS origin, exact API path and unchanged query. Credentials, non-default ports, fragments, other hosts (including mobile subdomains), other paths and query changes are rejected. Article redirects are API data, not HTTP fetch destinations.
  • Each batch has a 15-second total deadline, including its redirects and response body. The complete run has a 90-second deadline. Failed workers abort the remaining work. Responses are limited to 2 MiB of decoded response bytes, checked against both Content-Length and streamed bytes; JSON MIME and valid UTF-8 are required. TLS validation is left enabled; no certificates or secrets are embedded or bypassed.
  • Reject API errors/warnings, incomplete batches, missing response records, HTML/wikitext in introductions, disambiguation pages, namespace/language mismatches, invented aliases, title/canonical-URL mismatches, and invalid or inconsistent page/revision metadata. Only explicit missing: true for the exact species gets an original note. A timeout, HTTP error or validation failure is not turned into an availability note.
  • Excerpts are associated with the API's current revision metadata, with lastrevid and revisions[0].revid required to agree. MediaWiki's current-page extract service is not an immutable old-revision extractor; a concurrent edit or upstream cache issue remains an upstream consistency limitation. The bundle records the exact metadata and retrieval time returned by that query, rather than claiming an independently verified historical text reconstruction.
  • Every string, including IDs, titles and external text, is serialized into fixed-width decimal UTF-8 byte escapes inside Lua quoted literals. Article text cannot inject Lua quotes, comments, long strings, or code. Offline checking uses a strict generated-data parser, not eval, load or a Lua interpreter.
  • The catalogue path and output path are fixed relative to the script. Existing safePath checks reject symlink/junction components, and O_NOFOLLOW is used where supported. Trusted local parent directories and one maintenance writer are required, as with the project's other file helpers. No CLI path can redirect writes.
  • The existing cache is not opened for writing until every batch and the complete generated-data round trip validate. Network/validation failure leaves its bytes unchanged. The final fixed-file write is not crash-atomic: interruption/disk failure during writing requires restoring the tracked bundle or rerunning a successful refresh. It creates no sidecar or temporary workspace files.

Focused offline verification

tests/species_reader_spec.lua exercises the actual cached bundle, botany and effects APIs with injected read-only mocks. tests/recipe_spec.lua preserves its original 38 checks and adds command, dropdown, navigation, target and forged-field regressions. These are isolated Lua suites, not full-engine tests. The new reader suite follows the existing same-name module discovery convention; no launcher or engine-harness edits are needed.

The focused reader run passed 19 reader/HUD checks, 43 recipe/journal checks (38 original + 5 new) and 38 existing content checks, with exact final totals and empty stderr under Fengari. The content probe additionally verified that sources/effects exist before succession construction. All six owned Lua sources/specs compiled. These results do not replace native LuaJIT/client integration, visual review or the full-engine gates; no full-engine tests were run for this change.

tests/wiki-species.test.mjs runs independently with Node's test runner. It does not launch Luanti or use the full-engine suite.

The verified focused Node run has 21 passing tests, 0 failures, 0 real network requests, and 35 mocked transport requests. Coverage includes URL/query injection, SSRF redirects, redirect limits, timeout/abort cleanup, MIME/UTF-8/size rejection, page/revision validation, source-title redirects, missing-page honesty, Unicode/boundary clipping, malicious-text Lua serialization, exactly ten mocked batches at concurrency two, rejection of 99-row catalogues and 101-record fetch/serialized inputs, all twenty new exact identities, offline CLI checks, and byte-for-byte cache preservation after an HTTP failure. The separate approved --refresh above did use the network; tests and --check do not.

A separate isolated Fengari execution of the actual current botany source compared every runtime list() ID/Latin pair with the maintenance parser: 100/100 exact ordered matches, empty stderr. Runtime group counts were trees 13, shrubs 14, grasses 10, herbs 22, ferns/mosses 11, fungi 10, aquatic 10, lichens 10; no equal-ten-per-category assumption was imposed. No catalogue or source-effects code was modified and no full-engine run was launched. Offline --check verified 100/100 species: 98 introductions, 2 original notes; network requests: 0.

Snapshot assertions intentionally expect 98 Wikipedia excerpts (78 previous + 20 new) + 2 original availability notes. After a successful future refresh, review changed text, source identities, license/attribution, missing-page status and any effects claims; update the snapshot expectations and this document when coverage changes. Never replace a failing source with made-up text merely to make the count reach 100.