Skip to content

🧠 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:

  • ICraftingValidator
  • ICraftingLevelProvider
  • 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:

  • ICraftingAuthority
  • ICraftingModifier (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:

  • ICraftingOutputRouter
  • ICraftingModifier (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:

  • ICraftingInventoryAdapter
  • ICraftingCurrencyAdapter
  • ICraftingInventoryReservationAdapter (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.