Add Pip-Boy state to transform sync

Adds optional `isPipboyOpen` to transform packets, remote player state, proxy animation logging, and fake client/player samples. Updates protocol and architecture docs to describe the new Pip-Boy open/raising/closing state and related movement-state handling.
This commit is contained in:
2026-06-30 16:00:07 +12:00
parent 4b8f5246c4
commit 4ed671464e
18 changed files with 196 additions and 19 deletions
+3 -3
View File
@@ -14,9 +14,9 @@ can send a `discover` packet (see `docs/protocol.md`) and receive a
`discoverResponse` with the game port and current player count.
Transform packets may include optional movement-state fields such as
`isMoving`, `isSprinting`, `isSneaking`, `isJumping`, `isCrouching`, `weaponDrawn`, and
`movementSpeed`. The server preserves these fields automatically because it
broadcasts the original transform packet after adding server-owned fields.
`isMoving`, `isSprinting`, `isSneaking`, `isJumping`, `isCrouching`, `weaponDrawn`,
`isPipboyOpen`, and `movementSpeed`. The server preserves these fields automatically
because it broadcasts the original transform packet after adding server-owned fields.
This is still a local prototype. It does not make Fallout 4 multiplayer
playable yet.
+5 -2
View File
@@ -212,6 +212,7 @@ def update_remote_player_state(packet: dict[str, Any]) -> None:
"isJumping": get_optional_bool(packet, "isJumping"),
"isCrouching": get_optional_bool(packet, "isCrouching"),
"weaponDrawn": get_optional_bool(packet, "weaponDrawn"),
"isPipboyOpen": get_optional_bool(packet, "isPipboyOpen"),
"movementSpeed": get_optional_float(packet, "movementSpeed"),
"actorStateFlags1": get_optional_uint32(packet, "actorStateFlags1"),
"actorStateFlags2": get_optional_uint32(packet, "actorStateFlags2"),
@@ -254,7 +255,8 @@ def print_remote_player(player: dict[str, Any]) -> None:
"Movement State: "
f"moving={player['isMoving']}, sprinting={player['isSprinting']}, "
f"sneaking={player['isSneaking']}, jumping={player['isJumping']}, "
f"crouching={player['isCrouching']}, weaponDrawn={player['weaponDrawn']}, speed={player['movementSpeed']:.1f}"
f"crouching={player['isCrouching']}, weaponDrawn={player['weaponDrawn']}, "
f"pipboyOpen={player['isPipboyOpen']}, speed={player['movementSpeed']:.1f}"
),
f"Actor State: flags1={player['actorStateFlags1']:08X}, flags2={player['actorStateFlags2']:08X}",
f"Equipment: {equipment_text}",
@@ -294,7 +296,8 @@ def print_remote_players() -> None:
f"angleZ={player['angleZ']:.2f}, movementType={player['movementType']}, "
f"moving={player['isMoving']}, sprinting={player['isSprinting']}, "
f"sneaking={player['isSneaking']}, jumping={player['isJumping']}, "
f"crouching={player['isCrouching']}, weaponDrawn={player['weaponDrawn']}, speed={player['movementSpeed']:.1f}, "
f"crouching={player['isCrouching']}, weaponDrawn={player['weaponDrawn']}, "
f"pipboyOpen={player['isPipboyOpen']}, speed={player['movementSpeed']:.1f}, "
f"flags1={player['actorStateFlags1']:08X}, flags2={player['actorStateFlags2']:08X}, "
f"equipment={equipment_text}, "
f"appearance={appearance_text}, "
+1
View File
@@ -577,6 +577,7 @@ class FakePlayerClient:
"isJumping": jumping,
"isCrouching": crouching,
"weaponDrawn": False,
"isPipboyOpen": False,
"movementSpeed": movement_speed,
"appearance": DEFAULT_APPEARANCE,
}