Skip to content

Multiplayer

Craftwright is server-authoritative. Clients ask, the server decides: every craft, salvage, cancel, tray collection and tracked recipe is checked and carried out on the server, and the results replicate back. Nothing a client sends can create items.

  1. The player clicks Craft. The menu calls Request Craft on the player’s crafter.
  2. On the client, the crafter runs Check Craft locally. If it fails, the player sees the reason at once, without a round trip.
  3. If it passes, the crafter sends a reliable server RPC and returns Requested.
  4. The server runs every check again: recipe known, uses, station type, interaction range, conditions, queue space and ingredients. If one fails, On Request Failed fires on the server and on the owning client with the reason.
  5. Otherwise the server takes the ingredients and queues the job. The job, the inventories and later the outputs replicate to the clients that should see them.

Salvage requests and tracking go through the server like crafting: Request Salvage checks locally first, like Request Craft, and Request Cancel, Request Collect Tray, Track Recipe and Untrack Recipe are sent to the server, all through server RPCs on the crafter. These functions are for the server only (Blueprint: authority only), and Blueprint calls on clients are ignored: Learn Recipe, Forget Recipe, Notify Inventory Changed, Import Save Data, Cancel Job, Collect Tray, Advance Time, Wake Up, Clear Items.

Server RPCs can only be called on actors the client owns, so the crafter must live on one of them:

Owner Notes
Player Controller Recommended for most games. It lives as long as the player is connected; its queue and learned recipes survive the pawn dying. The example uses it.
Player State Also survives the pawn, and is where Lyra-style games keep player data.
Possessed Pawn Works, but the crafter is destroyed with the pawn, together with its hand-crafting queue and learned recipes.

Whichever you choose, the crafter finds inventories on its owner, the pawn or controller and the player state, and range checks use the pawn’s location. See Inventory sources.

NPC crafters on the server don’t need any of this: on the server, Request Craft runs directly.

Data Replicates to
Crafter: jobs and tray The owning client only
Crafter: known recipes and Crafter Tags The owning client only
Crafter: tracked recipes The owning client only
Station: jobs and tray Everyone
Station: fuel state (seconds left on the burning item, burning or not) Everyone
Built-in inventory: contents Everyone, or only the owning client with Owner Only
On Crafted Server and owning client (a client RPC to the crafter’s owner)
On Bonus Outputs, On Salvaged Server and owning client
On Tracked Recipes Changed Server and owning client
On Request Failed Server and owning client

Jobs and inventory contents replicate as fast arrays, so only changed entries are sent. Items, recipes and books are assets; only references to them are sent.

The built-in inventory replicates its contents to everyone, or only to the owner with Owner Only. Craftwright Player Inventory is the same component with Owner Only on by default; use it for players.

Unreal Engine 5.0 to 5.2 can’t change a property’s replication per component (that needs 5.3), so there Owner Only comes from the class default: Craftwright Player Inventory, or your own subclass with it ticked. Ticking it on a single component takes effect from 5.3. Crafter queues, trays and known recipes go only to their owner on every version.

Station actors, chests and other actors with Craftwright components must replicate (Replicates on) so clients receive their state and can refer to them in requests. The example’s stations, chest and resource nodes all replicate.

The server doesn’t send progress every frame. When a job starts, pauses, resumes or finishes a unit, it sends the job’s progress together with the server’s world time. Between those updates, clients count up from there using the game state’s server time, so Get Unit Progress, Get Job Progress and Get Job Time Remaining move smoothly on clients. Fuel works the same way: Get Fuel Remaining counts down on clients while the station burns.

A paused job (no fuel or power) stops at its last synced progress on clients until the server reports that it works again.

A station’s queue belongs to the station and is shared by all players, but every job remembers the crafter that ordered it:

  • outputs go to that crafter (with Output Mode To Crafter), and refunds always do;
  • only that crafter can cancel the job, and only within the station’s Interaction Range;
  • On Crafted, On Bonus Outputs and On Salvaged fire for that crafter.

When the crafter is gone, for example because the player left, the job keeps running and its outputs wait in the station’s tray for anyone in range to collect. Such a job can also be cancelled by any crafter in range.

Craftwright was tested with a dedicated server and a client, using Unreal’s classic replication system. An automated test in the example map checks, from the client:

  • the owner-only player inventory replicates to its owner;
  • a hand-crafted job replicates to its owner with smooth progress, and its outputs arrive;
  • a request at the forge, using ore from the nearby shared chest, is accepted; the station’s job, progress and fuel replicate to the client, and the ingots arrive in the client’s inventory;
  • a job at the workbench, cancelled from the client, refunds its ingredients.

The Iris replication system has not been tested.