Test player state interest and replay safety
This commit is contained in:
@@ -103,11 +103,28 @@ def wait_for_stat(server: FalloutTogetherServer, key: str, minimum: int, timeout
|
|||||||
raise AssertionError(f"stat {key} did not reach {minimum}")
|
raise AssertionError(f"stat {key} did not reach {minimum}")
|
||||||
|
|
||||||
|
|
||||||
|
def establish_transforms(
|
||||||
|
server: FalloutTogetherServer,
|
||||||
|
sender: socket.socket,
|
||||||
|
receiver: socket.socket,
|
||||||
|
*,
|
||||||
|
same_interest: bool,
|
||||||
|
) -> None:
|
||||||
|
send_packet(sender, transform())
|
||||||
|
receiver_transform = transform(
|
||||||
|
cellId="00000001" if same_interest else "00000002",
|
||||||
|
worldspaceId="0000003C" if same_interest else "00000099",
|
||||||
|
)
|
||||||
|
send_packet(receiver, receiver_transform)
|
||||||
|
wait_for_stat(server, "transformPacketsReceived", 2)
|
||||||
|
|
||||||
|
|
||||||
def test_player_state_relay_uses_server_owned_identity():
|
def test_player_state_relay_uses_server_owned_identity():
|
||||||
server = start_server()
|
server = start_server()
|
||||||
sender, sender_welcome = connect_v2(server)
|
sender, sender_welcome = connect_v2(server)
|
||||||
receiver, _ = connect_v2(server)
|
receiver, _ = connect_v2(server)
|
||||||
try:
|
try:
|
||||||
|
establish_transforms(server, sender, receiver, same_interest=True)
|
||||||
send_packet(sender, player_state())
|
send_packet(sender, player_state())
|
||||||
relayed = recv_until(receiver, "playerState")
|
relayed = recv_until(receiver, "playerState")
|
||||||
assert relayed["playerId"] == sender_welcome["playerId"]
|
assert relayed["playerId"] == sender_welcome["playerId"]
|
||||||
@@ -148,18 +165,61 @@ def test_v2_transform_strips_reliable_player_state_fields():
|
|||||||
server.stop()
|
server.stop()
|
||||||
|
|
||||||
|
|
||||||
def test_new_v2_client_receives_cached_player_state_before_any_transform():
|
def test_out_of_interest_player_state_strips_action_events_but_keeps_durable_state():
|
||||||
|
server = start_server()
|
||||||
|
sender, _ = connect_v2(server)
|
||||||
|
receiver, _ = connect_v2(server)
|
||||||
|
try:
|
||||||
|
establish_transforms(server, sender, receiver, same_interest=False)
|
||||||
|
send_packet(sender, player_state())
|
||||||
|
relayed = recv_until(receiver, "playerState")
|
||||||
|
assert relayed["characterName"] == "Sole Survivor"
|
||||||
|
assert relayed["equippedItems"] == [{"slot": "rightHand", "formId": "000000FF"}]
|
||||||
|
assert "actionEvents" not in relayed
|
||||||
|
finally:
|
||||||
|
sender.close()
|
||||||
|
receiver.close()
|
||||||
|
server.stop()
|
||||||
|
|
||||||
|
|
||||||
|
def test_out_of_interest_action_only_player_state_is_not_relayed():
|
||||||
|
server = start_server()
|
||||||
|
sender, _ = connect_v2(server)
|
||||||
|
receiver, _ = connect_v2(server)
|
||||||
|
try:
|
||||||
|
establish_transforms(server, sender, receiver, same_interest=False)
|
||||||
|
send_packet(
|
||||||
|
sender,
|
||||||
|
{
|
||||||
|
"type": "playerState",
|
||||||
|
"actionEvents": [{"sequence": 4, "type": 3, "eventName": "fireSingle"}],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
wait_for_stat(server, "playerStatePacketsReceived", 1)
|
||||||
|
with pytest.raises(AssertionError):
|
||||||
|
recv_until(receiver, "playerState", timeout=0.2)
|
||||||
|
finally:
|
||||||
|
sender.close()
|
||||||
|
receiver.close()
|
||||||
|
server.stop()
|
||||||
|
|
||||||
|
|
||||||
|
def test_new_v2_client_receives_cached_player_state_without_stale_action_events():
|
||||||
server = start_server()
|
server = start_server()
|
||||||
sender, sender_welcome = connect_v2(server)
|
sender, sender_welcome = connect_v2(server)
|
||||||
receiver = None
|
receiver = None
|
||||||
try:
|
try:
|
||||||
send_packet(sender, player_state(actionEvents=[]))
|
send_packet(sender, transform())
|
||||||
|
wait_for_stat(server, "transformPacketsReceived", 1)
|
||||||
|
send_packet(sender, player_state())
|
||||||
wait_for_stat(server, "playerStatePacketsReceived", 1)
|
wait_for_stat(server, "playerStatePacketsReceived", 1)
|
||||||
|
|
||||||
receiver, _ = connect_v2(server)
|
receiver, _ = connect_v2(server)
|
||||||
cached = recv_until(receiver, "playerState")
|
cached = recv_until(receiver, "playerState")
|
||||||
assert cached["playerId"] == sender_welcome["playerId"]
|
assert cached["playerId"] == sender_welcome["playerId"]
|
||||||
assert cached["characterName"] == "Sole Survivor"
|
assert cached["characterName"] == "Sole Survivor"
|
||||||
|
assert cached["equippedItems"] == [{"slot": "rightHand", "formId": "000000FF"}]
|
||||||
|
assert "actionEvents" not in cached
|
||||||
finally:
|
finally:
|
||||||
sender.close()
|
sender.close()
|
||||||
if receiver is not None:
|
if receiver is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user