Add appearance sync and late-join replay
Adds optional `appearance` snapshots to transform packets, applies supported appearance data to runtime proxies, and has the server replay stored transforms to newly connected clients so late joiners receive current visuals immediately.
This commit is contained in:
@@ -73,6 +73,17 @@ Example after server processing:
|
||||
{ "slot": "body", "formId": "0001F66A" },
|
||||
{ "slot": "headband", "formId": "" }
|
||||
],
|
||||
"appearance": {
|
||||
"version": 1,
|
||||
"raceFormId": "00013746",
|
||||
"height": 1.0,
|
||||
"morphWeight": { "thin": 0.0, "muscular": 0.0, "large": 0.0 },
|
||||
"bodyTintColor": { "r": 255, "g": 220, "b": 190, "a": 255 },
|
||||
"hairColorFormId": "",
|
||||
"facialHairColorFormId": "",
|
||||
"headParts": [],
|
||||
"morphs": []
|
||||
},
|
||||
"serverTime": 1780212128.3011043
|
||||
}
|
||||
```
|
||||
@@ -97,6 +108,7 @@ isJumping Optional movement-state flag; defaults to false when missing.
|
||||
weaponDrawn Optional weapon drawn state; defaults to false when missing.
|
||||
movementSpeed Optional derived movement speed in game units per second; defaults to 0.0 when missing.
|
||||
equippedItems Optional full snapshot of tracked visible apparel slots. Each entry has a string `slot` and hex-string `formId`; an empty `formId` means the slot is intentionally unequipped.
|
||||
appearance Optional versioned player appearance snapshot for runtime proxy visuals.
|
||||
serverTime Timestamp added by the server before broadcast.
|
||||
```
|
||||
|
||||
@@ -143,6 +155,26 @@ empty strings for unequipped tracked slots. Power armor, weapon models,
|
||||
condition, legendary instance data, tint/material overrides, and forms missing
|
||||
from the receiver load order are outside this packet extension.
|
||||
|
||||
Appearance fields are optional and additive. When `appearance` is missing,
|
||||
receivers keep the proxy's existing/default body and face. When present, it is a
|
||||
best-effort snapshot for male-proxy-compatible runtime visuals:
|
||||
|
||||
```text
|
||||
version Appearance payload version. Current value is 1.
|
||||
raceFormId Hex-string race form ID captured for diagnostics/future use; receivers do not switch proxy race yet.
|
||||
height NPC height scalar.
|
||||
morphWeight Body triangle weights: thin, muscular, and large.
|
||||
bodyTintColor Body tint channels r, g, b, a as 0-255 integers.
|
||||
hairColorFormId Hex-string `CLFM` form ID for hair color, or empty when unavailable.
|
||||
facialHairColorFormId Hex-string `CLFM` form ID for facial hair color, or empty when unavailable.
|
||||
headParts Hex-string `HDPT` form IDs for the sender's current head parts.
|
||||
morphs Morph slider values as `{ "id": hex-string, "value": number }` entries.
|
||||
```
|
||||
|
||||
Receivers must treat missing or malformed appearance subfields as non-fatal and
|
||||
apply only the parts they can resolve locally. Gender is intentionally not part
|
||||
of this payload yet; female proxy support can add it later.
|
||||
|
||||
### Disconnect Packet
|
||||
|
||||
Sent by the server to remaining connected clients when a client disconnects.
|
||||
|
||||
@@ -18,6 +18,12 @@ local movement logs: while the player is moving, the plugin targets roughly
|
||||
server assigns a `playerId`, adds `serverTime`, and broadcasts transform packets
|
||||
to other connected clients.
|
||||
|
||||
When a new client connects, the server sends the last stored transform snapshot
|
||||
for each already-connected player to that new client after `welcome`. These
|
||||
snapshots include optional fields such as `equippedItems` and `appearance`, so a
|
||||
late joiner can initialize proxy visuals before the existing players' next idle
|
||||
heartbeat or movement packet.
|
||||
|
||||
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.
|
||||
@@ -64,6 +70,7 @@ weaponDrawn
|
||||
movementSpeed
|
||||
animationGraphSpeed
|
||||
equippedItems
|
||||
appearance
|
||||
lastReceivedLocalTime
|
||||
```
|
||||
|
||||
@@ -79,6 +86,13 @@ tracked visible apparel slots with `{ slot, formId }` entries; empty `formId`
|
||||
values mean that tracked slot is intentionally unequipped. Older clients can
|
||||
omit the field and receivers keep the proxy's existing/default appearance.
|
||||
|
||||
`appearance` is optional and versioned. It carries male-proxy-compatible body
|
||||
and face data such as race form ID for diagnostics/future use, height, body
|
||||
morph weight, body tint color, hair color, facial hair color, head-part form IDs,
|
||||
and morph slider values. Receivers apply supported fields only after proxy 3D is
|
||||
loaded. Gender switching is intentionally omitted until female proxy support is
|
||||
available.
|
||||
|
||||
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
|
||||
@@ -115,6 +129,9 @@ player exists.
|
||||
- Transform packets can include optional `equippedItems` snapshots for visible
|
||||
clothing, armor, hats, and eyewear slots. The game-thread proxy controller
|
||||
applies those snapshots after proxy 3D is loaded.
|
||||
- Transform packets can include optional `appearance` snapshots for best-effort
|
||||
body and face proxy visuals. The game-thread proxy controller applies supported
|
||||
fields after proxy 3D is loaded and defers race/gender switching.
|
||||
- The plugin suppresses transform sends and proxy representation in the
|
||||
`COVault109` solo cell.
|
||||
- The game-thread proxy controller applies confirmed Havok animation graph
|
||||
|
||||
Reference in New Issue
Block a user