feat: add physical animal care delivery

This commit is contained in:
Rijad Zuzo
2026-07-31 00:19:41 +02:00
parent 7d410d8193
commit ead75fca68
25 changed files with 1469 additions and 191 deletions
+42 -18
View File
@@ -76,19 +76,37 @@ target selection or deterministic RNG state.
NPCStateRecord v3 adds carried inventory. SimulationStateRecord v2 adds
StorageStateRecord entries; world-schema v1 migrates legacy village food and
wood into the stable `village_pantry` and `village_woodpile` records. Parsed
storage values are canonicalized so save/restore continuation retains
byte-stable checksums. Current parsing rejects empty item IDs, negative or
non-finite amounts, negative or non-finite capacity, and contents above
capacity. Runtime deposit and withdrawal requests also reject empty item IDs
and non-finite amounts without mutating authoritative stock. When the authored
pantry or woodpile is present, current world parsing also requires its
authoritative food or wood amount to match the duplicated village summary;
wood into the stable `village_pantry` and `village_woodpile` records. NPC
inventory IDs and amounts are canonicalized to strings and floats; empty or
colliding normalized IDs, non-numeric values, and negative or non-finite
amounts are rejected.
Parsed storage values are likewise canonicalized so save/restore continuation
retains byte-stable checksums. Current storage parsing rejects empty item IDs,
negative or non-finite amounts, negative or non-finite capacity, and contents
above capacity. Runtime deposit and withdrawal requests also reject empty item
IDs and non-finite amounts without mutating authoritative stock. When the
authored pantry or woodpile is present, current world parsing also requires
its authoritative food or wood amount to match the duplicated village summary;
contradictory saves are rejected instead of silently changing checksum during
restore. World-v1 migration expands a storage's inferred capacity when needed
so valid legacy stock above the current default is preserved rather than
discarded.
The compound NPC `feed_animal` route needs no additional saved phase. An
in-progress record already contains the exact animal `target_id`, matching
animal reservation, carried inventory, task state, and active travel
destination. Insufficient carried food plus a pantry destination is the pickup
leg; the definition cost in inventory plus the animal destination is the
delivery leg. Restore emits only the saved travel request and never repeats
pickup. A compatible pre-delivery v11 feed record may instead have empty
inventory and the claimed animal as its destination; arrival redirects that
same claim through the current pantry waypoint before any withdrawal. If that
older record is already working, its first resumed tick performs the same
reroute and carries its saved work progress back to the goat. Successful
pickup changes the saved destination to the exact animal before publishing
synchronous inventory, event, or village signals, so signal-time saves cannot
encode carried food with a stale pantry destination.
SimulationStateRecord v3 adds ordered `EconomicEventRecord` entries and
`next_event_id`. World schemas v1 and v2 migrate explicitly to an empty event
stream. Event records use stable source/destination/item IDs, reject invalid or
@@ -199,10 +217,12 @@ selection establishes the first real target later.
Current-schema parsing requires unique animal IDs that do not collide with
resource or storage IDs. An animal reservation must belong to an existing NPC
whose active feed task targets that exact animal. Every `animal_fed` event
must name the pantry as its source, an existing animal as its destination,
food as its item, the exact feed action cost, and a valid NPC actor or the
player sentinel. The latest matching feed event tick must agree with the
animal's `last_fed_tick`.
must name an existing animal as its destination, food as its item, the exact
feed action cost, and a valid NPC actor or the player sentinel. New NPC events
name the matching `npc_<id>_inventory`; player events name the pantry. Direct
pantry-sourced NPC facts remain accepted as legacy-compatible v11 history,
while runtime emits matching-inventory sources for new NPC deliveries. The
latest matching feed event tick must agree with the animal's `last_fed_tick`.
The bounded opportunity family accepts at most one open record globally.
Opportunity, trigger-event, and resolution-event IDs are unique and the next
@@ -279,10 +299,12 @@ while the node is loaded or absent.
Animals are not `ResourceNode` instances and are not inserted into the
resource discovery grid. The first bounded slice uses a deterministic linear
loaded-animal query. NPC and player feeding resolve through the same atomic
care operation: reserve or select the exact animal, withdraw one real food
from `village_pantry`, reduce that animal's hunger, and append one exact
`animal_fed` fact. Failed withdrawal changes neither animal nor history.
loaded-animal query. NPC and player feeding resolve through the same exact
animal mutation but pay from their real current source. Player care withdraws
directly from `village_pantry`. NPC care reserves the animal, performs an exact
pantry-to-inventory pickup at the authored storage waypoint, carries that unit
to the same claim, and consumes inventory only at delivery. Failed or partial
pickup changes neither inventory nor animal history.
The first routine consumers alternate Dunja and Zora between stable-ID private
shelters and one shared pasture without drawing RNG. `AnimalRoutineSite`
@@ -299,8 +321,10 @@ Hunger cancels travel before care targeting.
Multiple animal records remain independently authoritative. A schema-v11 save
may contain concurrent feed reservations only when each reserving NPC targets
that exact animal in a valid travel or work state. Restoring Dunja and Zora
preserves both claim pairings and the checksum; completing one feed releases
and mutates only its destination record.
preserves both claim pairings and the checksum. The same existing NPC fields
preserve either pantry or goat travel plus carried food, so a post-pickup
restore continues without another withdrawal or RNG draw. Completing one feed
releases and mutates only its destination record.
The persistent hungry/content presentation derives from authoritative hunger.
The short feed response is transient and is reset rather than serialized or