Files
Commonwealth-Online-Public/protocol/player-sync.md
T
andrew a0563a6849 Hold proxy in hidden position when no remote
Add a temporary in-cell holding fallback for the single placed proxy actor when no valid same-cell remote player is available. Introduces kProxyHiddenHoldingPosition, ProxyLifecycleState, RemotePlayerSelection, MoveProxyToHoldingPosition and RestoreProxyForRemotePlayer, plus selection/state-tracking and throttled logs. The controller now moves the proxy to the hidden position on disconnect, disappearance, or cell-mismatch and snaps it back when a valid same-cell remote appears. Documentation and dev log updated to describe the lifecycle and rationale (docs/architecture.md, docs/dev-log.md, protocol/player-sync.md).
2026-06-02 13:59:32 +12:00

135 lines
5.1 KiB
Markdown

# Player Sync
Player synchronization is the first major technical goal for Fallout 4 Together.
The current implementation is still a local networking prototype.
## Current Implemented Flow
```text
Fallout 4 Plugin ↔ Local Python Server ↔ Other Clients
Plugin Remote Player State
```
The Fallout 4 plugin currently reads the local player's transform and sends it
to the local Python server. Normal movement sends are throttled separately from
local movement logs: while the player is moving, the plugin targets roughly
10 Hz and skips sends until position or rotation changes meaningfully. The
server assigns a `playerId`, adds `serverTime`, and broadcasts transform packets
to other connected clients.
The Fallout 4 plugin also receives server packets on a background networking
thread. It stores its assigned `playerId`, stores remote transform state by
remote `playerId`, and removes remote state when disconnect packets arrive.
`server/fake_client.py` remains a lightweight test receiver for the same packet
lifecycle.
The plugin's game-thread proxy actor controller can now read a copied snapshot
of this remote-player state and move the single placed test proxy actor
`F4TProxyRemotePlayer01REF` in `F4TTestCell01`. The networking thread still does
not touch Fallout 4 actors or references. If no valid same-cell remote player is
available, the controller moves the placed proxy to a hidden holding position
inside the same test cell instead of leaving it frozen at the last represented
position.
## Current Remote Player State Model
The plugin and fake client store remote players by `playerId`.
Each remote player state entry tracks:
```text
playerId
x
y
z
angleZ
movementType
cellId
worldspaceId
clientTime
serverTime
isMoving
isSprinting
isSneaking
isJumping
weaponDrawn
movementSpeed
lastReceivedLocalTime
```
Required transform packet fields are `type`, `playerId`, `x`, `y`, `z`,
`angleZ`, and `cellId`. `worldspaceId`, `movementType`, `clientTime`, and
`serverTime` are optional; interior test cells may omit `worldspaceId`.
Movement state fields are also optional and default to not moving, not
sprinting, not sneaking, not jumping, weapon holstered, and speed `0.0` when
missing.
This model proves the data shape and lifecycle before spawning remote actors.
For the current visual milestone, the controller represents only one remote
player and chooses the lowest available `playerId` if more than one remote
player exists.
## Implemented
- The plugin sends local player transform packets.
- Normal transform sends are independent from movement logging and are
thresholded to avoid packet-per-frame traffic.
- The plugin receives `welcome` packets and stores its assigned `playerId`.
- The plugin receives broadcast transform packets.
- The plugin ignores transform packets for its own assigned `playerId`.
- The plugin stores remote player state by `playerId`.
- The plugin receives `disconnect` packets and removes remote player state.
- The server assigns incrementing `playerId` values.
- The server sends `welcome` packets.
- The server adds `playerId` and `serverTime` to transform packets.
- The server broadcasts transform packets to other connected clients.
- The fake client stores remote player state by `playerId`.
- The server broadcasts `disconnect` packets.
- The fake client removes disconnected remote players from its state table.
- The plugin moves the single placed test proxy actor from a thread-safe
remote-player snapshot on the game-thread update path.
- Normal proxy movement is smoothed toward the latest received target, while
`cell_change`, `worldspace_change`, and `teleport` transforms snap directly to
avoid slow movement across large discontinuities.
- The game-thread proxy controller holds the single proxy at a hidden in-cell
position when the represented player disconnects, disappears, or leaves the
local test cell, then snaps back to a valid same-cell remote player before
resuming smoothing.
- Transform packets now include basic movement state data for future animation
work, but the proxy actor does not apply animations from that state yet.
## Transform Cadence
Normal local movement currently uses three separate rates:
- Network sends target roughly 10 Hz while the player is moving.
- Sends are skipped until position changes by about 3 game units or rotation
changes by about 0.02 radians.
- Local movement logs stay much slower, around once per second, so
`Fallout4Together.log` remains readable.
`cell_change`, `worldspace_change`, and `teleport` movement types bypass the
normal send interval and are sent immediately. The receiving plugin still stores
remote transform state on the networking thread and moves actors only from the
game-thread proxy controller.
No Fallout 4 remote actor is dynamically spawned yet.
No animation graph sync or animation application is implemented yet.
## Planned Later
- Add one proxy actor per remote player after the single-proxy test is stable.
- Dynamically spawn remote actors only after placed-proxy movement is stable.
## Not Required Yet
- Full animation graph sync
- Combat sync
- Inventory sync
- Quest sync
- Dialogue sync
- Settlement sync
- Accurate physics sync
- Public networking or matchmaking