Crafting, Durability, and Collections
The lifecycle half of the Item service: blueprints turn ingredients into products, durability wears products out, salvage recycles them, and collections reward completing a set.
Blueprints
A blueprint names its inputs (definitions and quantities), its outputs
(with drop chances), and whether it is static or discoverable. Catalog
role required, body from a file like definitions:
cat > iron_sword_bp.json <<'EOF'
{
"name": "Forge Iron Sword",
"type": "static",
"inputs": [{"match": "definition_id", "value": "FdtUrUxXVxaAxUqNCLZv", "quantity": 3}],
"outputs": [{"definition_id": "jxrfNfxMQYHtquatFgLA", "quantity": 1, "chance": 1.0}]
}
EOF
snug item blueprints create --domain docs4-forge --file iron_sword_bp.jsonEach output rolls its chance independently, and can set
initial_durability_pct to produce pre-worn items.
Crafting
Craft debits the inputs from a source container, rolls the outputs into a target container (both must belong to the same owner), and reports what happened - in one atomic operation:
snug --output json item craft --domain docs4-forge --container cont_XtmDHBhEAZwK \
--blueprint jLaQettEgjCaTBCKbKgb --target-container cont_XtmDHBhEAZwK{
"blueprint_id": "jLaQettEgjCaTBCKbKgb",
"consumed": [{ "definition_id": "FdtUrUxXVxaAxUqNCLZv", "quantity": 3 }],
"produced": [
{
"item_id": "item_GvrxXGGctGsZ",
"definition_id": "jxrfNfxMQYHtquatFgLA",
"quantity": 1,
"durability": { "current": 10.0, "max": 10.0, "broken_behavior": "unusable", ... },
...
}
],
"tier_events": [
{
"collection_id": "snSrXLfCsunXRPupwWpv",
"required": 2,
"bonus_event": "set_complete",
"global_first": true
}
],
"global_first": false
}Omit --blueprint for discovery crafting: the server scans the domain's
blueprints for one whose inputs the source container satisfies and crafts
it. With no satisfiable recipe (verified after the ingots ran out) the call
fails with 400 no_matching_blueprint - the same error a named blueprint
gives when ingredients are short. The top-level global_first flags the
first craft of a discoverable blueprint domain-wide.
Durability
Definitions opt in via default_durability (max, a curve label, a
broken_behavior, optionally downgrade_to). Wear is applied explicitly:
use subtracts the amount you send (default 1) - the curve is stored on
the instance but no time-based decay runs server-side.
snug item use --domain docs4-forge --item item_GvrxXGGctGsZ --amount 4 # 10.0 -> 6.0
snug item use --domain docs4-forge --item item_GvrxXGGctGsZ --amount 6 # 0.0, state "broken"
snug item repair --domain docs4-forge --item item_GvrxXGGctGsZ # back to max, "normal"What happens at zero depends on broken_behavior:
unusable- state flips tobroken; furtherusecalls fail with400 item_unusableuntil repaired.destroy- the item is removed from its container entirely (the response echoes its final state; subsequent reads 404).downgrade- the instance'sdefinition_idis swapped todowngrade_toand durability resets to max, stillnormal.
repair restores --amount durability (omit it to restore to max) and
clears the broken state. Items without durability reject both use and
repair with 400 item has no durability.
Salvage destroys an item and pays out its definition's
salvage_outputs (each with quantity and chance) into the same container -
stackable outputs merge into existing stacks:
snug item salvage --domain docs4-forge --item item_GvrxXGGctGsZ
# granted: 2 Iron Ingots, merged into the existing stackCollections
A collection is a set of member definitions with reward tiers. Ownership is tracked per user, ticked automatically whenever a user receives a member definition - by grant, craft, or transfer:
cat > blacksmith_set.json <<'EOF'
{
"name": "Blacksmith Set",
"members": ["FdtUrUxXVxaAxUqNCLZv", "jxrfNfxMQYHtquatFgLA"],
"tiers": [{"required": 2, "bonus_event": "set_complete"}],
"duplicate_policy": "count"
}
EOF
snug item collections create --domain docs4-forge --file blacksmith_set.json # catalog role
snug --output json item collections progress --domain docs4-forge \
--collection snSrXLfCsunXRPupwWpv --user docs-wave{
"collection_id": "snSrXLfCsunXRPupwWpv",
"user_id": "docs-wave",
"owned": ["FdtUrUxXVxaAxUqNCLZv", "jxrfNfxMQYHtquatFgLA"],
"owned_count": 2,
"total_members": 2,
"completed": true,
"tiers_reached": [2],
"duplicate_counts": { "FdtUrUxXVxaAxUqNCLZv": 1 }
}A tier fires exactly once, at the moment owned_count reaches required -
the craft above returned the set_complete tier event with
"global_first": true because that user was the first in the domain to
complete the set. Receiving a member you already own counts into
duplicate_counts when the policy is count (with ignore, duplicates
are dropped silently). Progress is private: asking for another user's
progress without an admin token fails with 403 insufficient_permissions.