Appearance
Deferred command execution guide
Mass Forge rejects unsafe direct entity mutations while Mass is processing. External gameplay, Blueprint callbacks, async handoffs returning to the game thread, and presentation systems can instead submit bounded deferred commands and match completion events by request ID.
All external queues and the Persistent Effect scheduler are executed by one Mass Forge Deferred Command Subsystem. This removes dependence on incidental Unreal subsystem tick order.
Use a direct call only at a lifecycle point where Mass is known to be idle. Use the queued path when timing is uncertain: acceptance returns a positive Request ID, then the coordinator revalidates and publishes exactly one correlated completion unless the world tears down.
Fixed phase order
Every safe coordinator tick runs these phases:
- Entity State Restores — queued complete durable snapshots atomically replace supported attributes, tags, grants, cooldowns, charges, regeneration phase, active Persistent Effects, and one active Ability Lifecycle.
- Attribute Snapshot Restores — queued focused attribute-only snapshots establish saved attribute values.
- Attribute Changes — queued Set/Add/Multiply requests.
- Gameplay Tag Changes — queued raw counted-tag changes.
- Instant Effects — queued atomic attribute and counted-tag transactions.
- Persistent Effects — queued Apply/Remove requests, then deterministic duration/period advancement, due pulses, and expiration.
- Projectile Impacts — completed Mass projectile motion publishes its terminal result and optionally applies impact-driven damage.
- Damage — queued Damage Definition requests and project policy evaluation.
- Death Handling — bounded Mass-entity destruction requested by successful lethal damage, after kill listeners and queued-damage completion events.
- Ability Lifecycles — existing casts/channels advance in stable source-entity order.
- Ability Requests — one FIFO for queued Activate, Grant, Revoke, Cancel, and Interrupt operations. Activation admission can commit costs, effects, cooldowns, and charges; lifecycle control is correlated to the exact captured lifecycle ID.
Advancing existing lifecycles before admitting queued Ability operations ensures a queued cast never consumes the delta time from the frame that accepted it. It also means a lifecycle that naturally ends in phase ten completes before a queued phase-eleven Cancel/Interrupt is evaluated. Directly started lifecycles advance at the next coordinator tick. Channel catch-up remains bounded per active ability and carries earned pulses forward.
Get Deferred Command Phase Order returns these names for Blueprint diagnostics and tools. Category phase order deliberately takes precedence over cross-category submission order. Within each category, requests remain FIFO.
For example, if a Blueprint queues an Ability, Damage, an Instant Effect, a raw Gameplay Tag change, an Attribute Change, an Attribute Snapshot Restore, and finally an Entity State Restore before the next tick, Mass Forge still executes the complete Entity State Restore first, then the focused Attribute Snapshot Restore, raw Attribute Change, raw Gameplay Tag change, Instant Effect, scheduled Persistent Effects, resolved Projectile Impacts, Damage, optional Death Handling, existing Ability Lifecycles, and new Ability Request. This is intentional and covered by automated phase-order tests.
The complete same-boundary pulse, expiration, cancellation, cost, lifecycle, and death precedence rules are defined in the deterministic gameplay ordering contract.
Phase-start snapshot rule
Each phase snapshots how many requests are eligible when that phase begins, capped by its per-frame budget. A completion callback can enqueue more work, but it cannot extend the phase currently being flushed.
- Work queued into the current phase waits for the next safe coordinator tick.
- Work queued into a phase that already ran waits for the next safe tick.
- Work queued into a later phase may execute in the current tick when that later phase begins and has budget.
Calling the coordinator recursively from a completion callback is ignored while a flush is active. This prevents unbounded recursion and preserves the phase-start rule.
Blueprint production pattern
- Call the appropriate Queue node and store its positive
Request Idwhen the receipt reports success. - Treat a queue-full or validation result as an immediate submission failure; no completion event will follow for rejected submission.
- Bind the corresponding completion event on the owning subsystem.
- Match the event's
Request Idto the stored ID. - Branch on the complete execution result. Acceptance means only that the bounded queue owns the request; entities and assets are validated again when it executes.
- Remove UI pending state on every completion outcome, not only success.
Available deferred entry points are:
| Category | Queue node | Completion event |
|---|---|---|
| Entity State Restore | Queue Mass Forge Entity State Restore | On Entity State Restore Completed |
| Attribute Snapshot Restore | Queue Mass Forge Attribute Snapshot Restore | On Attribute Snapshot Restore Request Completed |
| Attribute | Queue Mass Forge Attribute Change | On Attribute Request Completed |
| Gameplay Tag | Queue Add Mass Forge Gameplay Tag / Queue Remove Mass Forge Gameplay Tag | On Gameplay Tag Request Completed |
| Instant Effect | Queue Mass Forge Instant Effect | On Instant Effect Request Completed |
| Persistent Effect | Queue Mass Forge Persistent Effect / Queue Remove Mass Forge Persistent Effect | On Persistent Effect Request Completed |
| Damage | Queue Mass Forge Damage | On Damage Request Completed |
| Ability | Queue Mass Forge Ability Activation, Queue Mass Forge Ability Grant, Queue Mass Forge Ability Revocation, Queue Active Mass Forge Ability Cancellation, or Queue Active Mass Forge Ability Interruption | On Ability Operation Request Completed; activation also emits the compatibility On Ability Request Completed |
Use the dedicated tag queue for one raw counted-tag mutation. Use a tag-only or mixed queued Instant Effect when multiple tag/attribute modifiers must succeed or fail as one entity transaction.
Budgets and back-pressure
Configure limits under Project Settings > Mass Forge > Global Attribute Schemas > Runtime:
| Queue | Per-frame setting | Pending setting |
|---|---|---|
| Entity State Restore | Max Queued Entity State Restores Per Frame | Max Pending Queued Entity State Restores |
| Attribute Snapshot Restore | Max Queued Snapshot Restores Per Frame | Max Pending Queued Snapshot Restores |
| Attribute | Max Queued Changes Per Frame | Max Pending Queued Changes |
| Gameplay Tag | Max Queued Gameplay Tag Changes Per Frame | Max Pending Queued Gameplay Tag Changes |
| Instant Effect | Max Queued Effects Per Frame | Max Pending Queued Effects |
| Persistent Effect | Max Queued Persistent Effect Requests Per Frame | Max Pending Queued Persistent Effect Requests |
| Damage | Max Queued Damage Requests Per Frame | Max Pending Queued Damage Requests |
| Death destruction | Max Death Destructions Per Frame | Max Pending Death Destructions |
| Ability | Max Queued Abilities Per Frame | Max Pending Queued Abilities |
Every setting has a minimum effective value of one. Pending limits provide deterministic back-pressure instead of allowing unbounded memory growth. Per-frame limits prevent a backlog from monopolizing one game frame. Tune them from measured project load rather than raising them blindly.
Completion and failure behavior
- Request IDs are positive and monotonic within their owning world subsystem. They identify a category request; they are not a global ordering number across categories.
- A stale generation-checked entity completes with that operation's explicit invalid-entity or invalid-target result.
- Queued definition assets preserve a soft reference plus their submitted stable ID. An ordinarily unloaded asset is synchronously resolved when its request executes; a missing/unloadable asset, broken redirect, or identity-mutated asset is rejected under the submitted identity.
- Successful application events occur before that request's completion event.
- World teardown discards pending commands and resets counters. Teardown does not broadcast gameplay completion events.
- A queue request is not a multi-request transaction. Separate requests can succeed or fail independently even when submitted together.
Recovery matrix
Submission and execution are separate decisions. A rejected receipt always has request ID 0, owns no queue slot, and produces no later completion. An accepted receipt has a positive ID, and exactly one completion follows unless the owning world tears down first. Blueprint uses the assignable events shown below; C++ has native mirrors for every completion event.
| Queue | Immediate receipt failures | Execution-time failures | Correlation preserved | Required recovery |
|---|---|---|---|---|
| Entity State Restore | Unsupported format, schema mismatch, malformed/duplicate/over-capacity attributes, tags, grants, cooldowns, charges, regeneration, Persistent Effects, or lifecycle state; unset/stale entity when safely inspectable; invalid world; missing/mismatched external lifecycle-target binding; legacy-format active temporal state; or QueueFull. | Stale full generation, changed schema/fragments/definitions, an invalid recreated lifecycle target, format-1/2 active Persistent Effect, format-1/2/3 active lifecycle, or another complete preflight failure. | Request ID, complete entity index/serial, source name, nested attribute result, failed tag/ability/group/target-reference, and restored section counts including active effects and lifecycle. The queue owns a deep copy of the snapshot and optional target binding. | Migrate the nested attribute snapshot; reacquire stale entities; use format 4 for active-lifecycle continuity; resolve an external target key to its recreated full-generation handle; repair payload/archetype failures. Never apply a partial save. |
| Attribute Snapshot Restore | Unsupported binary format, schema-version mismatch, empty payload, unset entity, invalid/duplicate attribute ID, non-finite value, invalid world, or QueueFull. The nested validation result includes received/expected versions and the failing attribute when applicable. | Stale entity generation, schema-version drift, missing schema/fragment, retired/renamed attribute, or other complete restore validation failure. | Request ID, complete entity index/serial, source name, received/expected versions, failed attribute, and applied count. The queue owns a copied snapshot. | Migrate version mismatches before resubmission; reacquire stale entities; repair payload/schema failures. Treat QueueFull as back-pressure. Never apply only part of a failed save. |
| Attribute Change | Invalid world, unset entity, invalid attribute ID, non-finite magnitude, or QueueFull. | Stale entity, missing schema/fragment, retired attribute, invalid calculation, or another explicit attribute result. | Request ID, complete entity index/serial, attribute ID, submitted operation and logical source, old/new values, and clamp state. | Clear pending UI on completion. Reacquire stale entities; repair schema/archetype/ID failures. On QueueFull, defer or shed work and tune limits only from measurements. |
| Gameplay Tag | Invalid world, unset entity, invalid/unregistered tag, invalid count/operation, or QueueFull. | Stale entity, missing fragment, insufficient removal count, count overflow, or no free tag slot. | Request ID, complete entity index/serial, operation, tag, and structured count change. | Reacquire stale entities or correct the reported tag/count/capacity issue. On QueueFull, defer or shed work rather than spinning. |
| Instant Effect | Invalid world, unset entity, invalid/empty effect, or QueueFull. | InvalidEffect for missing/unloadable, redirected-to-incompatible, or stable-ID-mutated definitions; otherwise precise entity, attribute, parameter, or tag failure. | Request ID, source/target entity generations, original Effect ID, logical source ID, and structured application result—even when execution fails before mutation. | Do not retry an invalid definition blindly. Keep the original ID in diagnostics, repair/re-cook the asset or redirect, run Project Health, then submit a new request. |
| Persistent Effect | Invalid world, unset apply target, invalid definition, invalid removal handle, or QueueFull. | Changed/unloadable definition, stale owner, missing fragments/schema, stack/tag/attribute transaction failure, or already-absent exact handle. | Request ID, Apply/Remove operation, complete entity generation, submitted/resolved Effect ID, exact handle, captured effect context, and full apply/removal result. Apply context is retained through pre-mutation failures; removal captures the active context at queue admission when available. | Reacquire stale targets; discard terminal handles; repair the precise asset/archetype/transaction failure. On QueueFull, defer or shed work rather than spinning. |
| Damage | Invalid world, invalid definition, unset target, required source omission, non-finite request, or QueueFull. | InvalidDefinition for missing/unloadable or ID-mutated definitions; InvalidSource/InvalidTarget for stale endpoints; otherwise the full policy, attribute, tag, and transaction diagnostics. | Request ID plus original Damage ID, source, target, requested magnitude, and context. | Re-resolve endpoints or correct the reported definition/policy/attribute/tag. Never reinterpret a failed hit as success. |
| Ability | Invalid world, unset source/entity, invalid Grant/Activate definition, empty Revoke ID, no active lifecycle, blocked Cancel/Interrupt, or QueueFull. | InvalidAbility for missing/unloadable or ID-mutated Grant/Activate definitions; InvalidEntity/InvalidTarget for stale endpoints; NoActiveAbility/LifecycleChanged for safely stale lifecycle control; otherwise exact ownership, cooldown, charge, targeting, requirement, cost, effect, and lifecycle diagnostics. | Request ID, operation, complete source/target handles, original Ability ID, captured lifecycle ID, terminal result, and activation details. Ability check/activation results themselves retain the submitted source and optional target on success or failure. AI tickets retain activation data while tracked. | Replan from the terminal result. Reacquire entities, repair the asset, or inspect the current lifecycle before issuing new control; do not reuse a completed request ID. |
| Death Destruction | Created only by successful lethal damage. Death Handling Queue Full is returned in the killing damage result with death-handling request ID 0. | Entity Already Invalid when another owner already retired the exact generation. | Positive death-handling request ID, complete entity handle, Damage ID, and context. | Fall back to the project's pooling/deactivation cleanup when scheduling is rejected; treat already-invalid completion as safe terminal cleanup. |
QueueFull is a load-shedding signal, not permission to spin. A producer should stop submitting that burst, aggregate replaceable work where gameplay rules allow, spread independent work over later frames, and record queue pressure. Only then should a project raise Max Pending or Per Frame limits and re-profile frame time and memory.
When a world is replaced or shut down, its entity handles and request IDs are permanently invalid. Clear project-owned pending indicators from EndPlay, world-cleanup, or equivalent ownership teardown; never wait for a completion from a destroyed world or carry its ID into a replacement world.
The complete generation-reuse, representation-change, and teardown ownership rules are defined in the entity lifecycle safety contract.
Timing boundary
The coordinator waits whenever the Mass entity manager is processing. It resumes on a later tick when direct access is safe. The Persistent Effect subsystem does not tick independently; the coordinator advances it as the fifth phase. Regeneration remains a Mass processor whose ordering is governed by Mass execution phases rather than this world-subsystem sequence.
Paused and dilated gameplay time, world replacement, and the current durable-save boundary follow the time, travel, and save contract. Network authority and cross-request atomic batches remain separate roadmap items and must not be inferred from queue acceptance.
Automated proof
The automation suite verifies per-queue back-pressure and zero-ID rejection, positive-ID completion correlation, deep snapshot-copy ownership, complete-state/Attribute/tag phase order, counted-tag, Persistent Effect, and unified Ability-operation FIFO/per-frame budgeting, stale source/target generation safety for every queue family, execution-time schema drift, atomic failed restores, exact lifecycle-ID protection, raw-tag-before-Instant-Effect ordering, queued persistent removal before same-boundary pulses, projectile-impact-before-damage ordering, submitted stable-ID preservation when definition identities change, per-frame damage and death-destruction budgeting, callback-enqueued next-tick behavior, same-phase ability conflicts, independent-source requests, coordinator-owned Persistent Effect scheduling, safe stale-destruction completion, teardown discard, and the fixed eleven-phase cross-category order.