Skip to content

Deterministic gameplay ordering contract

Mass Forge turns same-frame gameplay into explicit ordered transactions. “Simultaneous” means that two or more operations become eligible for the same safe coordinator tick or the same scheduler boundary; it does not mean they execute concurrently or share one implicit transaction.

World coordinator order

Every safe Mass Forge coordinator tick executes these phases in this exact order:

  1. Entity State Restores — queued complete durable snapshots atomically replace supported attributes, tags, grants, cooldowns, and charges.
  2. Attribute Snapshot Restores — queued focused attribute-only snapshots establish saved attribute values.
  3. Attribute Changes — queued raw Set/Add/Multiply requests.
  4. Gameplay Tag Changes — queued raw counted-tag mutations.
  5. Instant Effects — queued atomic attribute/tag effects.
  6. Persistent Effects — execute queued Apply/Remove requests in FIFO order, then advance durations and periods, execute due pulses, and publish expirations.
  7. Projectile Impacts — completed Mass projectile motion publishes its terminal result and optionally applies impact-driven damage.
  8. Damage — queued Damage Definition transactions and their application/death events.
  9. Death Handling — bounded deferred Mass-entity destruction.
  10. Ability Lifecycles — advance existing casts and channels in stable source-entity order.
  11. Ability Requests — execute queued Activate, Grant, Revoke, Cancel, and Interrupt operations through one FIFO.

Get Deferred Command Phase Order exposes the eleven stable names. Category order takes precedence over cross-category submission order. Complete Entity State Restores run before focused Attribute Snapshot Restores, followed by raw attribute requests and then raw tag requests; all four run before Instant Effects. Each queue is FIFO and snapshots eligible work when its phase begins; each request is an independent transaction. Work queued into the current or an earlier phase waits for the next safe tick, while work queued into a later phase may run when that phase begins in the current tick.

A successful queued snapshot restore commits its complete validated attribute set before publishing any attribute-change event; those events precede its terminal restore completion. A raw attribute change queued for the same coordinator tick observes the restored state and applies afterward. Completion-enqueued restores wait until the next tick. Stale full-generation entity handles, execution-time schema changes, or invalid payloads produce one terminal failure without partial writes or mutation of a replacement generation.

The Persistent Effect subsystem does not tick independently. The coordinator owns its invocation so persistent requests, pulses, and expirations cannot race the Damage or Ability phases through incidental Unreal subsystem registration order. Its request queue snapshots eligible work before scheduler advancement: a queued removal can suppress a same-boundary pulse, while a request enqueued by a request-completion callback waits until the next coordinator tick.

Direct calls and queued calls

Successful direct operations are synchronous and follow caller order. A direct cancellation completed before the coordinator reaches the Persistent Effect phase prevents that instance from pulsing or expiring later. A queued request follows the phase and FIFO rules above, regardless of when another category was submitted.

Callbacks may make a new direct call or enqueue new work, but the callback does not join the transaction that published it. Recursive coordinator ticks are ignored. A callback-created replacement lifecycle or effect keeps its own identity; the outer operation never continues against the replacement by name alone.

Persistent pulse, cancellation, and expiration order

At the Persistent Effect phase, the scheduler first captures all due work without publishing callbacks. It then sorts work by complete target entity handle—index followed by serial number—and by world-unique persistent handle ID. This removes Mass chunk/archetype traversal order from observable gameplay.

The order is:

  1. entities in ascending complete handle order;
  2. instances on one entity in ascending persistent handle order;
  3. earned period numbers on one instance in ascending order;
  4. all eligible period attempts for the phase; then
  5. all pending expirations in the same entity/handle order.

If a finite duration and period land on the same boundary, the final earned pulse runs before Expired. When catch-up is capped, earned periods remain pending and expiration waits until that backlog drains. Once the scheduler has captured an exact-boundary expiration, that expiration owns the terminal reason; trying to remove the same instance from its final-period callback returns Not Found and does not produce a second removal event.

If an earlier period callback synchronously removes a different, later scheduled non-expiring instance, cancellation wins before that later instance becomes observable and its captured pulse is skipped. Manual removal publishes its removal synchronously. Applying an effect that cancels classified effects commits the entire replacement transaction first; direct publication then reports cancelled removals in compact existing-instance order, followed by the new apply event when a new handle is created, the stack disposition, and the optional initial period. Inside an Ability transaction these events instead follow the buffered Ability publication order described below.

Costs, effects, and Ability lifecycle order

An Ability activation validates and commits as one bounded source-plus-one-target transaction. Charge reservation, individual/shared cooldowns, source costs, self effects, target effects, and persistent state are all committed before the first success listener can observe them. Authored cost/effect arrays retain their authored order, but callbacks see the complete committed result rather than intermediate writes.

Successful Ability event publication is:

  1. buffered attribute changes;
  2. buffered counted-tag changes;
  3. buffered persistent removal/apply/stack/initial-period events;
  4. On Ability Activated; then
  5. On Ability Committed with the immutable committed lifecycle snapshot.

A failed commit restores all provisional state and publishes only the detailed Ability failure. A pre-commit cast cancellation ends the lifecycle without paying costs or applying outcomes. A committed channel is never refunded by later cancellation or interruption.

Existing lifecycles advance before new queued Ability requests. Existing lifecycle sources are sorted by complete entity handle. On a channel, pulse numbers execute in ascending order. A pulse callback may cancel or replace the current lifecycle; the lifecycle ID is revalidated after every callback so no later pulse or completion from the old lifecycle leaks through. At the natural duration boundary, every earned pulse allowed by the catch-up budget publishes before the single Completed lifecycle event. Any carried pulse backlog is drained on later safe ticks before completion.

The Ability Requests phase snapshots one shared FIFO workload for Activate, Grant, Revoke, Cancel, and Interrupt. Successful operation-specific events publish before the unified request completion; Activate also publishes its legacy activation-only request completion before the unified completion. Cancel/Interrupt requests capture the exact lifecycle ID at submission. If phase-nine advancement ends that lifecycle, execution returns NoActiveAbility; if a listener or direct call replaces it, execution returns LifecycleChanged and cannot stop the replacement. Requests enqueued by any phase-ten completion callback wait for the next coordinator tick.

Damage and death order

One Mass-target Damage transaction atomically commits Shield, Health, and the optional first-death tag. Its attribute/tag events observe the complete state. The Damage layer then publishes:

  1. On Damage Applied;
  2. On Entity Killed for a first transition to zero Health; then
  3. On Entity Deactivation Requested when that policy is selected.

For queued Damage, those application events occur before On Damage Request Completed. Deferred destruction occurs only in the later Death Handling phase, after the killing request has completed and before existing Ability lifecycles advance. Destruction uses FIFO death-request order and its configured per-frame budget. Consequently, an entity killed and scheduled for destruction by queued Damage cannot commit a later same-tick Ability lifecycle or queued Ability request.

The Keep Entity and project-deactivation policies leave the entity valid. Later phases may therefore interact with it, subject to its committed Health/death tag and ordinary Ability requirements. Mass Forge does not silently cancel unrelated active effects or abilities merely because Health reached zero; author a death tag gate, project callback, or destruction policy when that behavior is required.

What is and is not deterministic

Mass Forge guarantees ordering for its own world-local operations when inputs, entity generations, authored assets, queue contents, frame deltas, and configured budgets are the same. Stable order is not a networking authority model, rollback prediction system, cross-world order, or deterministic floating-point promise across different platforms.

Blueprint listener registration order is not a gameplay priority API. Listeners must read committed state and use request, lifecycle, effect, and death-handling IDs for correlation. Projects needing priority between unrelated external systems should enqueue explicit Mass Forge work or implement one project-owned coordinator instead of relying on delegate binding order.

Automated proof

The automation suite locks the contract by proving:

  • the coordinator exposes all ten phases and executes cross-category work in that order;
  • queues remain FIFO, complete entity-state restores precede focused attribute snapshots and raw attribute/tag changes, raw tag changes precede Instant Effects, and callback-enqueued same-phase work waits for a later tick;
  • persistent request processing and scheduling are coordinator-owned rather than independently ticked;
  • reverse-applied effects on two entities pulse and expire in stable entity-handle order;
  • exact-boundary persistent pulses precede expiration and cannot emit a second cancellation removal;
  • channel pulse sequences and backlogs complete before lifecycle completion;
  • Ability listeners see complete costs and source/target effects, while rollback emits no provisional events;
  • callback cancellation/replacement cannot advance a stale lifecycle; and
  • Damage Applied, Entity Killed, request completion, and deferred destruction retain their published order.

Changing any rule above is a public behavioral change. Update this contract, relevant system guides, automation expectations, changelog, and versioning decision together.

Mass Forge documentation — generated from the shipping Markdown source.