🧠 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 execution semantics, not a UI action.
A craft is not “press a button and spawn items”.
It is a multi‑stage decision and execution flow designed to guarantee:
- correct validation
- deterministic outcomes (when desired)
- safe failure and refund paths
- authority‑controlled mutation for multiplayer scenarios
Depending on configuration, execution may be best‑effort or escrow‑based.
Everything in the system exists to protect that pipeline.
🧱 The Single Orchestrator¶
CraftingService¶
There is exactly one authority on crafting truth:
CraftingService
It owns:
- job state
- scheduling
- timing
- lifecycle events
- persistence and offline recovery
Nothing else should:
- create jobs
- mutate job state
- deliver outputs
- refund currency or inputs
If something outside the service attempts to perform these actions directly, the design boundaries of the system have likely been violated.
🔄 The Crafting Pipeline (Start to Finish)¶
Every craft flows through the same conceptual stages:
Preflight
↓
Accept
↓
Schedule
↓
Run / Pause
↓
Deliver
↓
Complete / Fail / Cancel
Each stage has specific extension points and clear responsibilities.
🔍 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
Preflight evaluation order¶
The system evaluates checks in this order:
- Inputs (inventory)
- Currency
- Space (including routing and chance-space policy)
If these checks do not return early, validators are applied to the proposed result.
Extension points used here¶
ICraftingValidatorICraftingLevelSource- Station tag filters
- Output routing (for space checks)
What does NOT belong here¶
- spawning items
- consuming resources
- mutating cooldown state
- creating jobs
Preflight answers possibility, not execution.
✅ Stage 2: Accept (Execution Boundary)¶
Question: “We are committing — do we proceed?”
Accept is the stage where:
- authority is checked
- resources are consumed or reserved
- a
CraftJobmay be created
This is the commit boundary for crafting execution.
Execution modes at accept¶
Accept behaves differently depending on execution mode.
Best‑effort (default)¶
- Inputs and currency are consumed immediately
- Delivery may fail later
- Failures attempt to compensate with refunds where possible
This mode is designed for typical single‑player or non‑critical economies.
Escrow (opt‑in)¶
- Inputs and currency are reserved
- Nothing is consumed until delivery is guaranteed
- Commit is intended to be atomic when adapter invariants are honoured
Escrow mode requires adapters that support reservations/holds.
Extension points here¶
ICraftingAuthorityICraftingModifier(first evaluation pass)
Design rule¶
If something consumes or reserves resources, it belongs here, not in UI or benches.
🗂️ Craft Jobs (The Durable Unit)¶
A CraftJob represents a durable crafting operation.
It records:
- the owner performing the craft
- the recipe
- execution timing
- payment state
- progress and lifecycle state
Jobs are created only through:
CraftingService.Enqueue(...)
Jobs:
- can be queued
- can be paused
- can survive save/load
- can complete offline
You never “fake” a job. You either create one through the service — or not at all.
💾 Persistence (Save / Load Responsibility)¶
Crafting supports persistence through job snapshots:
SaveActiveJobs(...)RestoreJobs(...)
These APIs define:
- what data to persist (active jobs)
- how jobs resume and progress (including offline behaviour)
They do not provide a persistence system.
Crafting defines the job model and lifecycle — your game defines persistence.
🧠 Responsibility Split¶
-
CraftingService
-
Owns job state
- Owns timing and offline progression
-
Owns how jobs resume and complete
-
Your Game
-
Decides when to save
- Decides where to store data (file, cloud, database)
- Provides ID resolution (owner / recipe)
- Ensures identifiers remain stable across sessions
- Calls restore at the correct time in your lifecycle
🧩 Conceptual Flow¶
Game Save:
→ SaveActiveJobs(...)
→ Store snapshot
Game Load:
→ Load snapshot
→ RestoreJobs(...)
⚠️ Design Rule¶
Crafting is responsible for what the data means. Your game is responsible for when and where it is saved.
🔁 Offline Progress Context¶
Offline progression is applied during restore using:
acceptedAtUtcIWallClockProvider
This means:
- Jobs may complete while the game is closed
- Jobs may partially progress
- Jobs may resume
depending on elapsed real-world time and configuration
⏱️ Stage 3: Scheduling & Time¶
Scheduling answers questions such as:
- When can this craft run?
- How many jobs can run in parallel?
- Does a station have available capacity?
Time is abstracted through two providers:
ITimeProvider→ gameplay timeIWallClockProvider→ real UTC time
Why two time sources exist¶
| Time Source | Purpose |
|---|---|
Game time (ITimeProvider) |
Live gameplay ticking |
Wall clock (IWallClockProvider) |
Offline progress calculation |
Design rule¶
Time is data, not a direct call to
UnityEngine.Time.
This abstraction enables deterministic testing and offline completion.
▶️ Stage 4: Run / Pause¶
While running:
- progress events are emitted
- no additional resources are consumed
- modifiers may be re‑evaluated later at delivery
Pausing:
- freezes remaining time
- never re‑consumes inputs
- never re‑debits currency
Job state always lives inside the service.
📦 Stage 5: Delivery (Final Commit)¶
Delivery attempts to produce the final outputs.
Steps:
- Re‑evaluate modifiers
- Resolve output routing
- Attempt to add outputs
- Finalise craft outcome
Delivery semantics¶
Best‑effort¶
- Outputs are attempted
- Delivery failure refunds currency
- Inputs may be refunded depending on service policy and container availability.
Escrow¶
- Outputs are committed atomically
- Delivery either fully succeeds or nothing is applied
If delivery fails:
- currency is refunded or released
- inputs may be refunded or released (mode‑dependent)
- the job ends in
Failed
Extension points used here¶
ICraftingOutputRouterICraftingModifier(delivery pass)
🧠 Validators vs Modifiers¶
Understanding this distinction is critical.
Validators¶
Validators answer:
“Should this craft be allowed?”
They:
- modify
maxCrafts - block crafting with a reason
- never mutate state
Examples:
- cooldowns
- level gates
- progression locks
Modifiers¶
Modifiers answer:
“How does this craft behave?”
They:
- adjust duration
- scale currency cost
- add or alter outputs
- run twice (accept and delivery)
Rule of thumb:
- If it blocks permission, it is a validator.
- If it changes numbers, it is a modifier.
🔌 Adapters (External Systems)¶
Crafting does not talk directly to other gameplay systems.
Instead it integrates through adapters:
ICraftingInventoryAdapterICraftingCurrencyAdapterICraftingInventoryReservationAdapterICraftingCurrencyHoldAdapter
Adapters allow Crafting to remain:
- modular
- testable
- multiplayer‑ready
If you feel tempted to access inventory directly from crafting logic, you are bypassing the system’s safety model.
⚖️ Execution Modes¶
Crafting supports two execution semantics.
Best‑Effort (Default)¶
Designed for most games.
Characteristics:
- immediate resource consumption
- compensating refunds if delivery fails
- simple and fast execution
Escrow (Opt‑In)¶
Designed for multiplayer or economy‑critical systems.
Characteristics:
- resource reservation
- atomic commit guarantees
- strict adapter requirements
Both modes use the same pipeline. Only the transaction guarantees differ.
🧰 Built‑in Component Roles¶
Use this mental map when extending the system.
| Component | Responsibility |
|---|---|
| Workbenches | Provide input and context |
| Validators | Permission rules |
| Modifiers | Behaviour adjustments |
| Routers | Output destination decisions |
| Service | Execution and truth |
If a component crosses these roles, it is probably misplaced.
🚫 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 issue refunds
These boundaries keep the system predictable and safe.
🧠 The One‑Sentence Model¶
Crafting is a job‑based execution pipeline with strict boundaries and explicit execution semantics.
TL;DR¶
- One orchestration service
- Pipeline: preflight → accept → job → delivery
- Validators block, modifiers shape
- Adapters isolate external systems
- Execution semantics are explicit