🧠 Crafting System — Mental Model¶
This page explains how to think about Crafting in RevFramework.
It is not an API reference.
It is a conceptual map that helps you decide:
- Where does this behaviour belong?
- Which extension point should I use?
- What should I never touch?
If you understand this page, the API will feel obvious.
🎯 The Core Idea¶
Crafting is a controlled execution pipeline with explicit transaction semantics, not a UI action.
A craft is not “press a button and spawn items”.
It is a multi‑stage decision and execution flow that guarantees: - correct validation - deterministic outcomes (when desired) - safe failure and refund paths - multiplayer‑ready authority gating
Depending on configuration, execution may be best‑effort or escrow‑based.
Everything in the system exists to protect that pipeline.
🧱 The Single Orchestrator¶
CraftingServiceCore¶
There is exactly one authority on truth:
CraftingServiceCore
It owns: - job state - scheduling - timing - lifecycle events - persistence & offline recovery
Nothing else is allowed to: - create jobs - mutate job state - deliver outputs - refund currency or inputs
If something touches those directly, it’s wrong.
🔄 The Crafting Pipeline (Start to Finish)¶
Think of every craft as flowing through these stages:
Preflight
↓
Accept
↓
Schedule
↓
Run / Pause
↓
Deliver
↓
Complete / Fail / Cancel
Each stage has specific extension points and hard rules.
🔍 Stage 1: Preflight (Pure Decision)¶
Question: “Can this craft happen right now?”
Preflight: - never mutates state - never consumes items or currency - is safe to call from UI, tools, and teachables
Order: 1. Inputs (inventory) 2. Currency 3. Space (with routing + chance policy) 4. Validators
Extension points here:¶
ICraftingValidatorICraftingLevelProvider- Station tag filters
- Output routing (for space checks)
What does NOT belong here:¶
- spawning items
- cooldown timers mutating state
- consuming resources
Preflight answers possibility, not execution.
✅ Stage 2: Accept (Execution Boundary)¶
Question: “We are committing — do we proceed?”
Accept is where:
- authority is checked
- payment semantics are applied (consume or reserve)
- a CraftJob is created (if applicable)
This is the commit point for the chosen execution mode.
Execution Modes at Accept¶
Accept behaves differently depending on execution mode:
- Best‑effort (default):
- Inputs and currency are applied immediately
- Failures are compensated where possible
-
Partial application may occur internally, but the system guarantees a sensible outcome
-
Escrow (opt‑in):
- Inputs and currency are reserved (not consumed)
- No partial application is allowed
- Commit happens only if delivery is guaranteed
Extension points here:¶
ICraftingAuthorityICraftingModifier(accept‑time adjustments)
Design rule:¶
If something consumes or reserves resources, it belongs here, not in UI or benches.
🗂️ Craft Jobs (The Durable Unit)¶
A CraftJob is a durable record of intent.
It represents: - what is being crafted - by whom - how long it takes - what has been paid or reserved
Jobs: - can be queued - can be paused - can survive save/load - can complete offline
You never “fake” a job. You either create one properly — or not at all.
⏱️ Stage 3: Scheduling & Time¶
Scheduling answers: - When can this run? - How many can run in parallel? - Does this station have capacity?
Time is abstracted:
- ITimeProvider → game time (scaled/unscaled/fixed)
- IWallClockProvider → real UTC time (offline progress)
Design rule:¶
Time is data, not a call to
Time.time.
This is what makes offline progress and determinism possible.
▶️ Stage 4: Run / Pause¶
While running: - progress events fire - modifiers may be re‑evaluated at delivery time - no resources are consumed again
Pausing: - freezes remaining time - never re‑consumes inputs - never re‑debits currency
This is why job state lives only in the service.
📦 Stage 5: Delivery (Final Commit)¶
Delivery: - re‑evaluates modifiers - resolves output routing - attempts to add outputs - finalises the craft outcome
Delivery Semantics¶
Delivery guarantees depend on execution mode:
- Best‑effort:
- Outputs are attempted
- Failure triggers refunds where possible
-
Some internal steps may have already applied
-
Escrow:
- Outputs are committed atomically
- Delivery either fully succeeds or nothing is applied
- Requires inventory reservations and currency holds
If delivery fails:
- currency is refunded or released
- inputs may be refunded or released (mode‑dependent)
- job ends in Failed
Extension points here:¶
ICraftingOutputRouterICraftingModifier(delivery‑time pass)
🧠 Modifiers vs Validators (This Matters)¶
Validators answer:¶
“Should this craft be allowed?”
- affect
maxCrafts - may block with a reason
- never mutate state
Examples: - cooldowns - level gates - progression locks
Modifiers answer:¶
“How does this craft behave?”
- adjust duration
- scale currency
- add or alter outputs
- run twice (accept + delivery)
If it changes numbers, it’s a modifier.
If it blocks permission, it’s a validator.
🧩 Adapters (External Systems)¶
Crafting never talks directly to: - Inventory internals - Currency internals - Input systems
It uses adapters:
ICraftingInventoryAdapterICraftingCurrencyAdapterICraftingInventoryReservationAdapter(escrow)ICraftingCurrencyHoldAdapter(escrow)
This keeps Crafting: - modular - testable - multiplayer‑ready
If you feel tempted to “just grab the inventory”, stop.
⚖️ Execution Modes (Best‑Effort vs Escrow)¶
Crafting supports two execution semantics:
- Best‑effort (default):
- Designed for single‑player and non‑critical economies
- Matches how most games already work
-
Fast, simple, and forgiving
-
Escrow (opt‑in):
- Designed for multiplayer and economy‑critical games
- Requires inventory reservations and currency holds
- Refuses to run if guarantees cannot be met
Both modes use the same pipeline, jobs, and extension points. Only the execution guarantees differ.
🧰 Built‑in Components (Mental Placement)¶
Use this mental map:
| Thing | Purpose |
|---|---|
| Workbenches | Input & context only |
| Validators | Permission rules |
| Modifiers | Behaviour shaping |
| Routers | Destination decisions |
| Service | Truth & execution |
If a component crosses roles, it’s wrong.
🚫 What Never Belongs Where¶
- Benches should never consume items
- Validators should never spawn outputs
- Modifiers should never check authority
- UI should never mutate job state
- Anything outside the service should never refund
These rules keep the system predictable.
🧠 The One‑Sentence Model¶
Crafting is a job‑based execution pipeline with strict boundaries and explicit execution semantics (best‑effort or escrow).
TL;DR¶
- There is one service
- Everything flows through preflight → accept → job → delivery
- Validators block, modifiers shape
- Adapters isolate external systems
- Execution semantics are explicit, not implied
Once this clicks, Crafting stops feeling complex and starts feeling inevitable.