Concept: Multiplayer
Where each piece runs, and why the bar never claims authority over gameplay.
| Piece | Runs on | Replicates | Notes |
|---|---|---|---|
| Layouts (bindings) | server (store) | owner-only, per-layout delta | UCrimsonSlotBindingComponent; PostReplicatedReceive -> OnLayoutChanged -> bar refresh. |
| Manual pages | server | owner-only | SetManualPage / CyclePage -> Server_SetManualPage. |
| Effective page | server + owning client, locally | no | Same inputs (replicated tags + manual page) both sides; no round trip on a stance change. |
| Slot writes | client requests, server applies | via the store | Validator on the server; the same validator pre-flights on the client. |
| Snapshots / polling / input | owning client only | no | Remote proxies of another player's bars are inert. |
| Execution | owning client -> the provider's own path | per provider | Abilities: ASC prediction. Objects: gameplay event or UCrimsonContextActionPlayerComponent server re-gather. Tags: message subsystem. |
Loose tags do not replicate
Automatic pages read replicated owner tags. Grant stance / vehicle tags with a gameplay effect (or
AddReplicatedLooseGameplayTag); a plain AddLooseGameplayTag on the server flips the page for the server only.Verify with Play As Client
Two clients + a dedicated server: bind on client A, confirm the write on the server log and the slot on A; client B's bars are untouched. Grant a stance effect to A: A's bar flips, B's does not. Refuse a write (locked slot) on A: nothing changes and the server logs a Verbose refusal.
Verified (dedicated server + 2 clients)
Client write -> server accept -> owner-only replication (the other client sees neither the binding nor the controller); key activation through GAS from the bar (charges / recharge agree on both sides); locked-slot writes refused by the server validator and the client pre-flight; layout sets saved / applied over RPC; manual pages via
Server_SetManualPage; layouts, presets and manual pages persist across a full restart per player. Use the Action Bar Dev Tools Replication tab to compare any player's store server-vs-client.Server RPCs only run with authority
Every
Server_*_Implementation (store and bar component) starts with EnsureServerRPCAuthority: if the RPC ever resolves locally on a client (editor scripting forces every RPC local; an actor without an owning connection does too) it logs and does nothing - never mutates client state, never re-dispatches. Consequence for tooling: do not drive client -> server writes from Python; the SlateIM dev tool is the client-side harness.