OPX//77
opx_infinitycrafting

crafting

Last updated on

A shared crafting service — other modules register benches with recipes, players hand over materials and collect the output when the timer ends.

Workbenches for other modules. No recipes of its own: a module such as gunsmith registers a bench with its recipes. At a bench the player sees what can be made, what each recipe needs and what is already cooking. Ordering takes the materials (and an optional fee) at once; the item is ready after the recipe's time, even across a server restart, and the player comes back to collect it. Use it for "spend items, wait, receive an item".

Sideboth
Requiresinventory, character (hard)
Optionalmenu (the bench screen), progress (the handover bar)
Contractcrafting v1 — server, client
Configconfig/crafting.lua (shared)
Dataopx77_crafting_orders

How a bench works

  • Each character has its own queue per bench, up to the bench's queue orders.
  • Sequential: a new order starts when the previous one is ready.
  • Ordering checks gate, reach, queue space, materials and money, then removes the materials, then takes the fee. If a later step fails, earlier ones are given back.
  • Ready times use the database clock (ready_at): an order keeps cooking while the server is down.
  • Collecting checks the bag can carry the output first. The order is deleted, then the item given; if it cannot be given, the order is put back on the shelf.
  • A bench with a position is reach-checked on the server (its reach plus REACH_SLACK); without one it can be used from anywhere. This covers the gunsmith bench.
  • Refunds and output go to the character, not the connection. The citizen id is pinned and checked again after each yield; materials and the output go to that character's bag (loaded if absent) and the fee comes back through AddMoneyOffline, so a player who left or switched character mid-order loses nothing and pays nobody else. A refund that still fails is logged.
  • A placement carries a token (column token, added to an existing opx77_crafting_orders by OPX.Schema.AddColumns). When a placement answers a failure, the order is looked up by its token before anything is refunded: found, the order stands; absent, everything is refunded; unknown after three tries, nothing is refunded and the log names the token and the amounts to settle by hand.
  • No screen, order or collect from the floor (downed). A refusal names back the bench key only when it could name a bench.
  • Order and collect are audited (crafting.order, crafting.collect).

Bench definition

The table passed to RegisterBench. Lower-case keys.

A bench
crafting.RegisterBench('mymodule:bench', {
  owner = 'mymodule',
  label = 'Ammo bench',
  position = { x = -1520.2, y = 891.4, z = 42.1, bucket = 0 },
  canUse = function(player, recipeKey) return true end,
  recipes = {
    { KEY = 'handgun_rounds', ICON = 'ammo', OUTPUT = 'ammo_handgun', COUNT = 30,
      SECONDS = 120, INPUTS = { scrap_metal = 2 }, PRICE = 40, MONEY = 'EDDIES' },
  },
})
FieldRequiredEffect
owneryesName of the registering module. Used by UnregisterBenches.
labelnoMenu title. Default: the bench key. Max 64 bytes.
positionno{ x, y, z, bucket? }. Turns on the server reach check.
reachnoMetres, above 0 and at most MAX_REACH. Default REACH.
queueno1 to MAX_QUEUE. Default QUEUE.
canUsenofunction(player, recipeKey) → allowed, code?. Called with recipeKey = nil for the bench, then once per recipe. A code shows crafting.<code>. A raise refuses with not_for_you.
recipesyesList of recipes, at most MAX_RECIPES.

Bench and recipe keys: letters, digits, _, -, ., :, up to 64.

Recipe fields

Upper-case keys, as in a config file.

FieldRequiredEffect
KEYyesRecipe key, unique on the bench.
OUTPUTyesItem given. Must be in the inventory catalogue.
COUNTnoUnits given, 1 to MAX_YIELD. Default 1.
SECONDSyesCooking time, MIN_SECONDS to MAX_SECONDS.
INPUTSyes{ item = units }, 1 to MAX_INPUTS items, each in the catalogue.
PRICEnoFee in whole units. Default 0.
MONEYif PRICE > 0Money type the fee is taken from.
LABELnoMenu label. Default: the output's label.
ICONnoA name from OPX.Glyphs.

A recipe that breaks a rule is dropped with a boot warning. A bench left with no recipe is refused.

Configuration

config/crafting.lua sets OPX.Config.MODULES.crafting. Shared. Limits on what a registering module may ask for; recipes live in the consumer's own config.

KeyDefaultEffect
enabledtruefalse switches the module off.
REACH3.0Default bench reach, metres.
MAX_REACH25.0Largest reach a bench may ask for.
QUEUE3Default orders per character per bench.
MAX_QUEUE10Largest queue a bench may ask for.
MIN_SECONDS5Shortest recipe time. Seconds, not ms.
MAX_SECONDS86400Longest recipe time.
MAX_YIELD1000Largest COUNT, and largest units per input.
MAX_INPUTS8Most materials per recipe.
MAX_RECIPES40Most recipes per bench; the rest are dropped.
RATE_LIMIT{ WINDOW_MS = 10000, REQUESTS = 20 }Requests per player per window, across all benches. REQUESTS = 0 turns it off.
HANDOVER_MS1200Length of the progress bar shown when ordering. 0 turns it off.
REFRESH_MS5000How often an open menu asks for a fresh view.

Refusal codes

The toast key is crafting.<code>. A canUse gate may answer its own codes; the registering module must add crafting.<code> to its locales (gunsmith does).

CodeMeaning
no_such_benchNo bench with that key.
no_such_recipeThe bench has no such recipe (or no longer has it).
not_for_youThe canUse gate refused, or raised.
too_farOut of reach, or another bucket.
no_positionThe server cannot read the player's position.
no_characterNo character loaded.
shortNot enough materials.
cannot_payFee could not be paid.
queue_fullThe queue is full. The cap is checked in the same statement that writes the order, so two orders placed at once cannot pass it; a refused order gives back its materials and fee.
no_such_orderNot one of this character's orders.
not_readyStill cooking.
no_roomThe bag cannot carry the output.
too_fastRate limit.
downedThe player is down (Not from the floor.).
unavailableDatabase error.

On this page