Workers, Residences & Factory Automation
1. Summary
Players can build automated production lines in the world using:
| Piece | Role |
|---|---|
| Craft residence | Ownable building — hosts lodging, devices, storage links, worker roster |
| Craft devices | Placed machines (wood mill, forge, cooking hearth) — run recipes (09) |
| Storage houses | Static chests/warehouses (08) — handoff points between jobs |
| Hired workers | npc_instance with role: worker (19) — one active job each, skills, stamina, pay, lodging |
| Job definitions | Player-authored cycles — harvest → haul → process → store → sell |
Workers loop while active: travel, work, travel, rest when exhausted. They are not free — wages per tick, training fees, food, beds, and tools.
Currency for wages and sales: copper → silver → gold → platinum (08 §8.5).
2. Design principles
| Principle | Meaning |
|---|---|
| Same craft rules | Workers use the same recipes, stations, tools as players (09) |
| Physical logistics | Items move in worker inventory or storage; travel time is real |
| One job per worker | Simple mental model; parallelism = hire more workers |
| Skills matter | Worker skills improve speed, yield, failure rate — trainable |
| Costs everywhere | Wages, training, food, lodging, device fuel — automation is profit, not magic |
| Server authority | Job steps validated on region worker; inventory via central audit |
| Intent-based config | Job YAML / TUI — not hardcoded UI flows |
3. Craft residence
A craft residence is a BuildingInstance (20) — kind: residence | workshop — with linked sub-entities:
craft_residence:
id: residence_b
owner_character_id: ...
region_id: ...
position: { x, y, z }
links:
lodging: lodging_b # beds, pantry
devices: [wood_mill_1, kitchen_1]
storage: [storage_house_a, storage_house_b]
worker_spawn: worker_quarters
permissions: [owner, guild_crafters]
| Sub-system | Purpose |
|---|---|
| Lodging | Beds (1 worker ↔ 1 bed), pantry (food stock), rest area |
| Devices | Craft devices with recipe allow-lists |
| Storage links | Registered chests/warehouses in AOI (may be adjacent buildings) |
| Roster | Hired workers assigned to this residence |
Residences are region-local — all linked storage/devices should be reachable by pathfinding in the same region (cross-region supply chains = later phase).
4. Craft devices
Devices are world-placed items (crafted or installed) that act as stations (09 §7).
craft_device:
id: wood_mill_1
template: wood_processing_mill
residence_id: residence_b
allowed_recipes: [lumber_to_plank, hardwood_to_plank]
fuel: optional # coal, power crystal — per recipe
durability: ...
queue: [] # optional player queue; workers append
Examples: wood mill, forge, cooking hearth, loom, alchemy bench, inscription table.
Worker + device: worker must be adjacent/in range, have inputs in inventory or pull from linked input storage (config), run CraftExecute for craft_time_ticks modified by worker skill.
5. Workers
5.1 Worker entity
Workers are npc_instances (19) with employer_id — same stats, inventory, and death rules as other NPCs; plus job state (13).
worker:
id: worker_ana
name: Ana
employer_character_id: ...
residence_id: residence_b
lodging_bed_id: bed_2
wage_account: employer_bank # deducted per tick
state: working | traveling | resting | idle | dismissed
attributes: # same families as players (`11`)
STR, DEX, STA, VIT, ...
skills:
logging: 12
hauling: 8
carpentry: 5
trading: 3
pools:
stamina: { current, max }
hunger: { current, max }
inventory: WorkerCarrier # limited slots — mass/volume (`08`)
equipment: # job outfit
hands: iron_axe
body: work_tunic
pack: small_backpack
active_job_id: job_lumber_loop
5.2 Hire & dismiss
| Action | Cost |
|---|---|
| Hire | Up-front fee + ongoing wage per N ticks (employer sets; minimum floor per ruleset) |
| Dismiss | Worker leaves; final wage settlement |
Hire from labor broker NPCs in towns or recruit after quests. Worker cap per residence from building tier + CHA (optional).
5.3 Training
Employer pays training fee (coins from bank or residence treasury):
training_session(worker, skill, fee) → skill_xp += f(fee, worker.VIT, teacher_quality)
Training can be passive on-job (slow XP while doing related tasks) or active (paid courses at guild hall — faster). Skilled workers: faster harvest, shorter craft ticks, better yields, fewer failures.
5.4 Wages, effort & silver sink (implemented)
Workers are a deliberate coin sink: harder routes cost more payroll, burn food/water faster, and skilled workers charge more while working faster.
Payroll formula (each wage_interval_ticks)
due_cp = round(
(base_cp + loop_step_cp + travel_cp) * level_wage_mult
).max(1)
| Component | Source |
|---|---|
base_cp |
Employer-set wage.copper_per_interval (hire min from NPC def) |
loop_step_cp |
sum(step_costs) × wage_copper_per_effort — sum, not mean |
travel_cp |
Meters walked this interval × travel_copper_per_m |
level_wage_mult |
1 + (level − 1) × wage_per_level |
Step costing rules (assets/config/server-settings.yaml → workers.step_costs):
| Step kind | Default effort | Notes |
|---|---|---|
harvest_route |
2.2 per node | 20-node route ≈ 44 effort units |
harvest |
2.0 | Single-resource stop |
craft |
1.8 | Per craft stop in the compiled loop |
travel |
0.7 | Flat complexity; meters paid separately |
broker_sell |
0.8 | |
deposit / withdraw / pickup |
~0.45–0.55 | |
rest / wait / idle |
0.15–0.3 | Cheap parking |
Empty companion jobs use idle only.
Pay sources (treasury order)
- Employer bank ledger (automatic paycheck withdraw; works while offline while the region still tracks the character)
- Assigned lodging container contents
- Other employer-owned placed chests within 12 m of lodging (or employer if no lodging)
- Employer carried coins (root + worn bags)
Other player expenses (taxes, shipping fees, shop buys, hire/train fees, property upkeep) use the same bank-then-purse rule via try_spend_copper.
If unpaid → Strike (job loop halted). While striking, pay retries about every 5 s so restocking lodging/chests (or depositing to bank) resumes work without waiting a full interval.
Hunger / thirst
Per-tick drain is multiplied by the current step’s effort rate (hunger_effort_scale / thirst_effort_scale). On lodging rest_if_needed, workers eat/drink one pantry consumable from the assigned bed container only when hunger or thirst is below 65% — stock the bed itself with soup/water (nearby chests are not scanned for meals; that path is wages-only).
Level bonuses (skilled workers)
| Bonus | Formula (capped) | Effect |
|---|---|---|
| Wage | 1 + (L−1)×wage_per_level (default 0.06) |
Higher payroll |
| Harvest speed | duration ÷ 1+(L−1)×0.03 (cap 1.75×) |
Shorter channels |
| Craft speed | same shape | Shorter craft ticks |
| Move speed | × 1+(L−1)×0.02 (cap 1.4×) |
Faster travel |
Worker XP pacing
Cumulative XP → level via xp_base × growth^(L−1) ceilings. Defaults: xp_base: 2000, growth: 1.65, awards 0.35 per harvest/craft/sell, 1.0 per route wrap, soft-capped at xp_max_per_route_loop: 8 so craft-until-exhausted cannot dump a level in one loop. Expect ~80+ gatherer loops to L2 and hundreds to mid levels.
Client UI
Workers dock shows wage base→effective cp (effective_wage_copper previews base + loop effort; live travel meters add at debit time).
If employer cannot pay → worker strikes (idle at lodging) until paid or dismissed.
6. Lodging, food & rest
Workers do not run 24/7.
| Need | Rule |
|---|---|
| Lodging | Each worker assigned one bed in linked lodging |
| Food | Pantry stocks player-crafted food (09, 15); consumed on rest — not NPC stand rations |
| Stamina | Depletes while working/traveling; regen while resting/sleeping |
| Rest trigger | stamina < rest_threshold → complete safe sub-step → travel to lodging |
| Sleep | At lodging: eat (if hungry), sleep N ticks, regen stamina to resume_threshold |
| Resume | Return to job cycle start or configured checkpoint |
Missing bed → worker cannot be set active. Missing food on rest → slower regen, morale debuff, eventual job halt.
7. Job model — one job per worker
7.1 Job definition
A job is a repeating cycle of steps. One active_job per worker.
job_id: job_chop_to_storage_a
worker_id: worker_ana
enabled: true
checkpoint: true # resume mid-cycle after rest
steps:
- step: travel
target: { poi: forest_patch_7 } # harvest node / landmark / coords
- step: harvest
resource: oak_log
tool: iron_axe # must be equipped
until: { inventory_full: true } | { qty: 20 }
- step: travel
target: { storage: storage_house_a }
- step: deposit
storage: storage_house_a
filter: { items: [oak_log] }
deposit_all: true
- step: travel
target: { lodging: lodging_b } # optional: only if stamina low (condition)
- step: rest_if_needed # implicit between cycles
job_id: job_mill_planks
worker_id: worker_ben
steps:
- step: travel
target: { storage: storage_house_a }
- step: withdraw
storage: storage_house_a
items: [{ template: oak_log, qty: 10 }]
- step: travel
target: { device: wood_mill_1 }
- step: craft
device: wood_mill_1
recipe: lumber_to_plank
qty: 10 # or until inputs exhausted
- step: travel
target: { storage: storage_house_b }
- step: deposit
storage: storage_house_b
filter: { items: [hardwood_plank] }
job_id: job_sell_planks
worker_id: worker_cara
steps:
- step: travel
target: { storage: storage_house_b }
- step: withdraw
storage: storage_house_b
items: [{ template: hardwood_plank, qty: 50 }]
- step: travel
target: { broker: market_c_broker }
- step: broker_sell
broker: market_c_broker
items: [{ template: hardwood_plank, qty: all }]
pricing: { mode: market | premium_pct: 5 | fixed_silver: 2 }
currency: silver # proceeds → employer bank (`10`)
7.2 Step types
| Step | Behavior |
|---|---|
travel |
Pathfind to target; time = distance / move_speed; stamina cost |
harvest |
Gather from world node (lumber, ore, herb); skill + tool modify tick time & yield |
withdraw |
Pull items from storage to worker inventory |
deposit |
Push items from worker inventory to storage |
craft |
Run recipe at device; uses worker skill for speed/failure |
enchant |
Run enchant ritual at altar; mana/stamina from worker pools; partial reagent loss on fail (17) |
broker_sell |
List or instant-sell at broker (10); proceeds to employer |
stall_sell |
Optional: player stall instead of broker |
rest_if_needed |
Branch: lodging if stamina/hunger thresholds |
wait |
Rare: wait for input stock (mill blocked until logs arrive) |
harvest_route |
Ordered harvest over specific node ids until carry threshold or nodes exhausted (compiled from route, see §7.3) |
7.3 Harvest loops — route block (implemented)
A high-level route on the job compiles server-side into the travel/harvest/deposit step cycle — this is what the gfx route editor saves:
job_id: route_oak_loop
mode: job_loop
route:
kind: harvest_loop
lodging_container_id: bed-1
outbound_waypoints: [{ x: 12.0, y: 10.0 }]
harvest_nodes: [oak-1, oak-2]
carry_return_ratio: 0.90 # head home when carry ≥ 90%
loop_wait_ticks: 90 # pause at home between loops
steps: [] # compiled from route
Compiled cycle: travel waypoints outbound → harvest_route over the listed nodes → travel waypoints reversed → travel to lodging bed → deposit all → rest_if_needed → wait → repeat.
Runtime reliability rules (harvest route):
- Drop-centric collection — after a harvest channel completes, the worker walks to each scattered loot pile itself and picks it up by drop id. Loot scatters up to ~1.2 m past the fixed harvest stand position, so chasing the drop (not the node) is what keeps collection reliable; far-side scatter can never stall the loop.
- Never abandon mid-collect — carry-full is only checked at node arrival and at pickup time (hard carry cap → head home to deposit); a node in progress is always finished and collected first.
- Path-failure skip — a node or waypoint with no viable path for ~3s is skipped with a
no path …worker error instead of stalling the route; leftover loot at a depleted node is re-collected on a later loop. - Rest rules — stamina only regens while idle, so the loop paces itself: a worker too tired to start a harvest channel rests in place and resumes the same node once recovered (never an
insufficient staminaretry spin);rest_if_neededat the bed tops stamina up to 90% so every loop starts rested; with no active job workers rest in place like any worker. - Carry capacity — route carry thresholds and encumbrance use the shared agent carry snapshot (same source as the sim's pickup/encumbrance gates), so heavy loads (e.g. oak logs) never fake a "full" reading after one node.
7.4 Timing
tick_time(step) =
travel: path_distance / effective_move_speed(worker)
harvest: base_harvest_ticks / (1 + logging_skill × coeff) × qty
craft: recipe.craft_time_ticks / (1 + relevant_skill × coeff)
Travel time is first-class — distant forest + far mill = hire haulers or build closer storage.
7.5 Conditions & branching (Phase 6b+)
- step: withdraw
storage: storage_house_a
items: [{ template: oak_log, qty: 10 }]
on_fail: { wait_ticks: 60, retry: true } # mill idle until supply
8. Example factory line
Player owns residence B with lodging (2 beds), wood mill, links to storage A (near forest) and storage B (near residence).
| Worker | Job cycle |
|---|---|
| Ana | Forest → chop oak_log → deposit storage A → rest → repeat |
| Ben | Withdraw logs from A → mill at residence B → planks to storage B → repeat |
| Cara | Withdraw planks from B → travel to market C → broker sell for silver → bank proceeds to employer → repeat |
[Forest] ──Ana──► [Storage A] ──Ben──► [Mill @ Res B] ──► [Storage B] ──Cara──► [Broker @ Market C]
▲ │
└──────────── rest / food @ lodging B ◄─────────┘
Player stocks lodging pantry, pays wages every N ticks, outfits Ana with axe, maintains mill durability, and monitors profit = broker revenue − wages − training − food − fuel.
9. Outfitting
| Job type | Typical equipment |
|---|---|
| Lumber | axe, hands, backpack |
| Mining | pick, lantern, heavy pack |
| Hauling | large pack, cart (later) |
| Milling / forge | tongs, apron (recipe tool reqs) |
| Trading | light pack, market token |
Missing required tool → step fails / worker idles with error to employer TUI. Tools have durability — employer must repair or replace.
10. Economy integration
| Flow | Handling |
|---|---|
| Wages | Debit employer bank or residence treasury each wage_interval_ticks |
| Training | One-time fee to guild / trainer NPC |
| Broker sales | Proceeds to employer bank (config); physical coins not hauled unless withdraw_coins step |
| Currency | Copper, silver, gold, platinum (08 §8.5) |
| Taxes | Optional region sales tax on broker_sell (10) |
Workers do not need player online — sim runs on region worker while chunk is active (see §12).
11. TUI / agent
flatland residence list
flatland residence link storage residence_b storage_house_a
flatland worker hire --residence residence_b --name Ana --wage 5_copper_per_100_ticks
flatland worker assign-bed worker_ana bed_2
flatland worker equip worker_ana --slot hands iron_axe
flatland worker train worker_ana --skill logging --fee 2_silver
flatland worker job set worker_ana --file jobs/ana_chop.yaml
flatland worker job enable worker_ana
flatland worker status worker_ana # step, stamina, location, errors
flatland factory status residence_b # all workers, storage levels, device queues
Agent JSON: full job state, storage snapshots, P&L estimate.
12. Simulation & region lifecycle
| Case | Behavior |
|---|---|
| Region active (players nearby or policy keeps hot) | Workers tick normally |
| Region cold / unloaded | Workers pause; state frozen; no wages accrue (config) or reduced accrual |
| Employer offline | Workers continue if region active |
Anti-exploit: cap workers per account; audit broker_sell for wash trading; residence must be in valid claimed territory.
13. Phasing
| Phase | Scope |
|---|---|
| 5 | Craft residences (building shell), plot prep, fixture anchors (20) |
| 6a | Hire 1 worker, simple job: harvest → deposit (1 storage) |
| 6b | Multi-step jobs, withdraw/craft/deposit, lodging + rest |
| 6c | Wages per tick, training, skills on job |
| 6d | Broker_sell step, factory dashboard TUI |
| 7 | Multi-worker lines, job conditions, carts, cross-storage wait |
14. Open decisions
Resolved (2026-07-06):
| # | Decision |
|---|---|
| F1 | Guild residences — later phase |
| F2 | Max workers = beds per residence |
| F3 | Worker tips from proceeds boost motivation + efficiency |
| F4 | Player craft priority over worker device queue |
| F5 | Wages continue when region cold/unloaded |
| F6 | Worker insurance — later; respawn via insurance (14 J5) |
| Worker PvP | Die; flee; evil + guards (14) |
Worker motivation (F3)
Optional tip % from broker/stall proceeds into worker pool:
motivation += f(tip_received)
efficiency_multiplier = 1 + motivation_bonus × worker_morale
Higher motivation → faster job steps, fewer idle errors.
15. Settlement workers (NPC towns)
Player-hired workers (§1–§14) and settlement workers share the same job engine (09, 18):
| Player workers | Settlement workers | |
|---|---|---|
| Owner | Player / guild | Authored settlement profile |
| Output | Any recipe player configures | Basic only — short/long sword, shield, leather armor, hardtack |
| Risk | PvP death, evil, wages |
No player-style permadeath; treasury-funded |
| Stock | Employer storage / broker | Shop shelf + food stand — depletes on purchase |
| Design | Player-built residence | World-build settlements/*.yaml (18 §6) |
Settlement job cycles run when the region is loaded; ops can seed initial stock at realm launch. Players compete with — and buy from — these shelves while building superior unique items via skill, quality rolls, and enchants.
16. Cross-references
| Topic | Doc |
|---|---|
| Recipes, devices, stations | 09 §7 |
| Storage chests | 08 §6 |
| Broker sell | 10 §4 |
| Attributes, stamina, skills | 11 |
| Settlement worker pools | 18 §6, 19 §9 |
| NPC definitions & AI | 19 |
| Buildings & schematics | 20 |
| Player housing / residence chests | 08 §6, 20 §9 |
Update 09 for device queue API; 10 for worker broker permissions.