Files
Commonwealth-Online-Public/docs/protocol-phase2-extensions.md
T
2026-06-30 16:59:42 +12:00

221 lines
7.5 KiB
Markdown

# F4T Network Protocol - Phase 2 Extensions
## Overview
This document describes the Phase 2 protocol extensions to support actor state flags and action events for TiltedEvolution-style animation synchronization.
---
## Transform Packet Format (Extended)
### JSON Structure
```json
{
"type": "transform",
"playerId": 1,
"x": 1234.5,
"y": 5678.9,
"z": 100.0,
"angleZ": 45.0,
"cellId": "Sanctuary",
"worldspaceId": "Commonwealth",
"movementType": "normal",
"isMoving": true,
"isSprinting": false,
"isSneaking": false,
"isJumping": false,
"weaponDrawn": false,
"movementSpeed": 180.5,
"clientTime": 1717424000.123,
"serverTime": 1717424000.456,
"actorStateFlags1": 0x00000042,
"actorStateFlags2": 0x00000001,
"actionEvents": [
{
"type": 0,
"eventName": "ActorMovementStart",
"animationVariablesFloat": [85.0, 90.5, ...],
"animationVariablesBool": [true, false, ...],
"animationVariablesInt": [1, 0, ...],
"state1": 0x00000042,
"state2": 0x00000001,
"captureTime": 1717424000.456
}
]
}
```
### Field Definitions
#### Phase 1 Fields (Existing)
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | String | YES | Packet type; must be `"transform"` |
| `playerId` | Integer (uint32) | YES | Player ID (from welcome packet) |
| `x`, `y`, `z` | Number (float) | YES | Position in game world |
| `angleZ` | Number (float) | YES | Rotation heading (degrees) |
| `cellId` | String | YES | Cell form ID or name |
| `worldspaceId` | String | NO | Worldspace ID (empty for cells) |
| `movementType` | String | NO | Movement type: `"normal"`, `"cell_change"`, `"worldspace_change"`, `"teleport"` (default: `"normal"`) |
| `isMoving` | Boolean | NO | Local player is moving (default: false) |
| `isSprinting` | Boolean | NO | Local player is sprinting (default: false) |
| `isSneaking` | Boolean | NO | Local player is sneaking (default: false) |
| `isJumping` | Boolean | NO | Local player is jumping (default: false) |
| `weaponDrawn` | Boolean | NO | Local player has weapon drawn (default: false) |
| `movementSpeed` | Number (float) | NO | Movement speed in game units/frame (default: 0.0) |
| `clientTime` | Number (double) | NO | Client-side timestamp (optional) |
| `serverTime` | Number (double) | NO | Server timestamp for diagnostics (optional) |
#### Phase 2 Fields (New - Conditionally Optional)
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `actorStateFlags1` | Integer (uint32) | NO | Actor state flags word 1 (combat, animation state, etc.) (default: 0) |
| `actorStateFlags2` | Integer (uint32) | NO | Actor state flags word 2 (additional flags) (default: 0) |
| `actionEvents` | Array of ActionEvent | NO | Queue of action events (default: empty) |
#### Phase 2 ActionEvent Structure
| Field | Type | Description |
|-------|------|-------------|
| `type` | Integer (uint32) | Action type (enum value from `ActorMediator`) |
| `eventName` | String | Human-readable action name (e.g., `"ActorMovementStart"`) |
| `animationVariablesFloat` | Array of Numbers | Float variable cache snapshot (indices correspond to descriptor table) |
| `animationVariablesBool` | Array of Booleans | Bool variable cache snapshot |
| `animationVariablesInt` | Array of Integers | Int variable cache snapshot |
| `state1` | Integer (uint32) | Actor state flags word 1 at action capture |
| `state2` | Integer (uint32) | Actor state flags word 2 at action capture |
| `captureTime` | Number (double) | Server timestamp when action was captured |
---
## World State Packet
Host-authoritative time and weather sync uses a separate `worldState` packet.
Full field definitions live in [`protocol/world-state.md`](../protocol/world-state.md).
```json
{
"type": "worldState",
"playerId": 1,
"gameHour": 14.25,
"gameDaysPassed": 12.5,
"weatherFormId": "00123456",
"timeSync": true,
"clientTime": 1717424000.123,
"serverTime": 1717424000.456
}
```
---
## Backward Compatibility
**Important:** The protocol is **backward compatible**. Existing clients that don't send Phase 2 fields will continue to work:
- Missing `actorStateFlags1/2` → Defaults to 0 (neutral state)
- Missing `actionEvents` → Defaults to empty array (no discrete actions)
**Action:** Old clients can upgrade incrementally; no immediate protocol version bump required.
---
## Implementation Timeline
### Phase 2.1 (DONE)
- ✅ Extend `RemotePlayerState` struct with actor state flags and action event queue
- ✅ Update `HandleTransformPacket()` to parse new optional fields
- ✅ Add logging for actor state flags
### Phase 2.2 (IN PROGRESS)
- Update server relay (`server/server.py`) to pass through new fields
- Update fake test client (`server/fake_client.py`) to populate new fields
- Create protocol documentation (this file)
### Phase 2.3 (PENDING)
- Add `PerformAction` hook in `main.cpp` to capture action events
- Serialize action events into JSON for transmission
- Test end-to-end action event capture and relay
---
## Actor State Flags Reference
### ActorState.flags1 (Common States)
Bitfield values for `actor→actorState.flags1`:
| Bit | Meaning | Animation Impact |
|-----|---------|-----------------|
| 0 | In combat | Triggers combat locomotion graph |
| 1 | Is sneaking | Triggers sneak locomotion (crouch) |
| 2 | Is attacking | Plays attack animations |
| 3 | Is fleeing | Triggers run/fleeing animations |
| 4 | Is sprinting | Redundant with isSprinting (graph driven) |
| 5 | Force walk | Locks to walk speed |
| 6 | Force run | Forces run speed |
| 7-31 | (various) | Context-dependent |
**Note:** Exact bit meanings should be verified in `RE/H/ActorState.h` in CommonLibF4.
### ActorState.flags2 (Additional States)
Bitfield values for `actor→actorState.flags2`:
| Bit | Meaning | Animation Impact |
|-----|---------|-----------------|
| 0-31 | (to be determined) | (to be determined) |
---
## Action Event Capture (Phase 2.3)
When a local player triggers an action, F4T will:
1. **Hook** `ActorMediator::PerformAction()` or equivalent
2. **Capture** the following:
- Action type (enum)
- Event name (string)
- Animation variable cache snapshot
- Actor state flags (flags1, flags2)
- Timestamp
3. **Queue** the action event in `RemotePlayerState.actionEvents`
4. **Serialize** to JSON `actionEvents` array in next transform packet
5. **Transmit** via relay server to other clients
6. **Replay** on proxy actors (Phase 5.2)
**Example Actions to Capture:**
- Idle animations (start/stop moving)
- Combat idles (stand ready, weapon draw)
- Equipping/unequipping items
- Using objects
- Emotes
- Crafting/trading
---
## Testing Checklist
- [ ] F4T plugin compiles with extended RemotePlayerState
- [ ] Fake client can send packets with actor state flags
- [ ] Relay server passes through new fields without error
- [ ] F4T parses actor state flags from incoming packets
- [ ] Logging shows actor state flags in remote update messages
- [ ] Phase 2.3: PerformAction hook implemented and tested
- [ ] Phase 2.3: Action events captured and serialized
- [ ] Phase 2.3: End-to-end action event relay verified
---
## Future Considerations
- **Action Queue Size:** Limit to prevent excessive bandwidth (recommend: 8-16 pending actions per player)
- **Compression:** Animation variable arrays could be compressed/delta-encoded if bandwidth becomes limiting
- **Animation Variable Descriptors:** Index-based approach (Phase 3) will replace string names
- **Thread Safety:** Ensure RemotePlayerState modifications are thread-safe (already using mutex in Phase 1)