Sync from GitHub main #1
@@ -0,0 +1,80 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from player_state import normalize_player_state_packet
|
||||
from server_core import _normalize_action_events
|
||||
|
||||
|
||||
def valid_packet() -> dict:
|
||||
return {
|
||||
"type": "playerState",
|
||||
"playerId": 9999,
|
||||
"characterName": "Sole Survivor",
|
||||
"equippedItems": [
|
||||
{"slot": "rightHand", "formId": "ff"},
|
||||
{"slot": "body", "formId": ""},
|
||||
],
|
||||
"appearance": {
|
||||
"version": 4,
|
||||
"raceFormId": "13746",
|
||||
"height": 1.0,
|
||||
"morphWeight": {"thin": 0.2, "muscular": 0.3, "large": 0.5},
|
||||
"bodyTintColor": {"r": 1, "g": 2, "b": 3, "a": 255},
|
||||
"hairColorFormId": "",
|
||||
"facialHairColorFormId": "",
|
||||
"complexionFormId": "",
|
||||
"isFemale": False,
|
||||
"headParts": ["1a2b"],
|
||||
"morphs": [{"id": "10", "value": 0.5}],
|
||||
"morphRegions": [0.25],
|
||||
"facialBoneMorphs": [
|
||||
{
|
||||
"id": "20",
|
||||
"position": [0.0, 1.0, 2.0],
|
||||
"rotation": [3.0, 4.0, 5.0],
|
||||
"scale": [1.0, 1.0, 1.0],
|
||||
}
|
||||
],
|
||||
"tints": [{"id": 1, "type": 2, "value": 3, "color": "ff00ff00", "swatch": 4}],
|
||||
},
|
||||
"actionEvents": [{"sequence": 7, "type": 3, "eventName": "fireSingle"}],
|
||||
}
|
||||
|
||||
|
||||
def test_player_state_normalizes_only_reliable_fields():
|
||||
clean = normalize_player_state_packet(valid_packet(), _normalize_action_events)
|
||||
assert clean is not None
|
||||
assert clean["type"] == "playerState"
|
||||
assert "playerId" not in clean
|
||||
assert clean["equippedItems"][0]["formId"] == "000000FF"
|
||||
assert clean["appearance"]["raceFormId"] == "00013746"
|
||||
assert clean["appearance"]["headParts"] == ["00001A2B"]
|
||||
assert clean["appearance"]["tints"][0]["color"] == "FF00FF00"
|
||||
assert clean["actionEvents"][0]["sequence"] == 7
|
||||
|
||||
|
||||
def test_empty_player_state_is_rejected():
|
||||
assert normalize_player_state_packet({"type": "playerState"}, _normalize_action_events) is None
|
||||
|
||||
|
||||
def test_invalid_equipment_is_rejected():
|
||||
packet = valid_packet()
|
||||
packet["equippedItems"][0]["formId"] = "not-a-form"
|
||||
assert normalize_player_state_packet(packet, _normalize_action_events) is None
|
||||
|
||||
|
||||
def test_invalid_appearance_numbers_are_rejected():
|
||||
packet = valid_packet()
|
||||
packet["appearance"]["height"] = float("nan")
|
||||
assert normalize_player_state_packet(packet, _normalize_action_events) is None
|
||||
|
||||
|
||||
def test_invalid_action_event_is_rejected_instead_of_silently_dropped():
|
||||
packet = valid_packet()
|
||||
packet["actionEvents"] = [{"sequence": 7, "type": 3, "eventName": "notAllowed"}]
|
||||
assert normalize_player_state_packet(packet, _normalize_action_events) is None
|
||||
|
||||
|
||||
def test_character_name_is_bounded():
|
||||
packet = valid_packet()
|
||||
packet["characterName"] = "x" * 129
|
||||
assert normalize_player_state_packet(packet, _normalize_action_events) is None
|
||||
Reference in New Issue
Block a user