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