arkparser 0.1.3__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {arkparser-0.1.3 → arkparser-0.1.4}/PKG-INFO +7 -4
- {arkparser-0.1.3 → arkparser-0.1.4}/README.md +6 -3
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/__init__.py +2 -1
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/export.py +13 -3
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/files/profile.py +50 -3
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser.egg-info/PKG-INFO +7 -4
- {arkparser-0.1.3 → arkparser-0.1.4}/pyproject.toml +1 -1
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_export.py +3 -1
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_profile.py +25 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/LICENSE +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/__init__.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/binary_reader.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/exceptions.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/map_config.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/normalization.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/types.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/common/version_detection.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/data_models.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/files/__init__.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/files/base.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/files/cloud_inventory.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/files/tribe.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/files/world_save.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/game_objects/__init__.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/game_objects/container.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/game_objects/game_object.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/game_objects/location.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/__init__.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/character.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/creature.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/item.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/player.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/stats.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/structure.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/models/tribe.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/properties/__init__.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/properties/base.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/properties/byte_property.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/properties/compound.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/properties/primitives.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/properties/registry.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/__init__.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/base.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/colors.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/misc.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/property_list.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/registry.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser/structs/vectors.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser.egg-info/SOURCES.txt +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser.egg-info/dependency_links.txt +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser.egg-info/requires.txt +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/arkparser.egg-info/top_level.txt +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/setup.cfg +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_binary_reader.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_cloud_inventory.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_data_models.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_game_objects.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_models.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_tribe.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_version_detection.py +0 -0
- {arkparser-0.1.3 → arkparser-0.1.4}/tests/test_world_save.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arkparser
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Pure Python parser for ARK: Survival Evolved and ARK: Survival Ascended save files
|
|
5
5
|
Author: Vertyco
|
|
6
6
|
License-Expression: MIT
|
|
@@ -97,7 +97,7 @@ A pure-Python library for parsing ARK: Survival Evolved (ASE) and ARK: Survival
|
|
|
97
97
|
|
|
98
98
|
## Features
|
|
99
99
|
|
|
100
|
-
- **Player Profiles** (`.arkprofile`): character name, level, stats, engrams
|
|
100
|
+
- **Player Profiles** (`.arkprofile`): platform gamertag, character name, level, stats, engrams
|
|
101
101
|
- **Tribe Data** (`.arktribe`): members, ranks, logs, alliances
|
|
102
102
|
- **Cloud Inventory / Obelisk**: uploaded creatures, items, cryopod contents
|
|
103
103
|
- **World Saves** (`.ark`): full map state, including creatures, structures, items, and players
|
|
@@ -122,7 +122,8 @@ from arkparser import Profile
|
|
|
122
122
|
|
|
123
123
|
profile = Profile.load("path/to/player.arkprofile") # auto-detects ASE/ASA
|
|
124
124
|
|
|
125
|
-
print(profile.player_name) #
|
|
125
|
+
print(profile.player_name) # Platform gamertag / display name
|
|
126
|
+
print(profile.character_name) # In-game character name
|
|
126
127
|
print(profile.level) # 105
|
|
127
128
|
print(profile.tribe_id) # 1729028872
|
|
128
129
|
print(profile.engram_blueprints) # ["EngramEntry_Campfire_C", ...]
|
|
@@ -258,11 +259,13 @@ All file parsers support `load(source)` which accepts `str`, `Path`, or `bytes`
|
|
|
258
259
|
|
|
259
260
|
| Property | Type | Description |
|
|
260
261
|
|---|---|---|
|
|
261
|
-
| `player_name` | `str \| None` |
|
|
262
|
+
| `player_name` | `str \| None` | Platform gamertag / display name |
|
|
263
|
+
| `character_name` | `str \| None` | In-game character name, falling back to `player_name` when absent |
|
|
262
264
|
| `player_id` | `int \| None` | Unique player ID |
|
|
263
265
|
| `unique_id` | `str \| None` | Platform ID (Steam/Xbox numeric ID) |
|
|
264
266
|
| `tribe_id` | `int \| None` | Tribe ID (handles ASE `TribeId` / ASA `TribeID`) |
|
|
265
267
|
| `tribe_name` | `str \| None` | Always `None`; tribe name is not stored in profiles |
|
|
268
|
+
| `is_female` | `bool \| None` | Parsed gender flag (`True` = female, `False` = male, `None` = absent) |
|
|
266
269
|
| `level` | `int` | Current level (`ExtraCharacterLevel + 1`) |
|
|
267
270
|
| `experience` | `float` | Total XP |
|
|
268
271
|
| `total_engram_points` | `int` | Engram points spent |
|
|
@@ -63,7 +63,7 @@ A pure-Python library for parsing ARK: Survival Evolved (ASE) and ARK: Survival
|
|
|
63
63
|
|
|
64
64
|
## Features
|
|
65
65
|
|
|
66
|
-
- **Player Profiles** (`.arkprofile`): character name, level, stats, engrams
|
|
66
|
+
- **Player Profiles** (`.arkprofile`): platform gamertag, character name, level, stats, engrams
|
|
67
67
|
- **Tribe Data** (`.arktribe`): members, ranks, logs, alliances
|
|
68
68
|
- **Cloud Inventory / Obelisk**: uploaded creatures, items, cryopod contents
|
|
69
69
|
- **World Saves** (`.ark`): full map state, including creatures, structures, items, and players
|
|
@@ -88,7 +88,8 @@ from arkparser import Profile
|
|
|
88
88
|
|
|
89
89
|
profile = Profile.load("path/to/player.arkprofile") # auto-detects ASE/ASA
|
|
90
90
|
|
|
91
|
-
print(profile.player_name) #
|
|
91
|
+
print(profile.player_name) # Platform gamertag / display name
|
|
92
|
+
print(profile.character_name) # In-game character name
|
|
92
93
|
print(profile.level) # 105
|
|
93
94
|
print(profile.tribe_id) # 1729028872
|
|
94
95
|
print(profile.engram_blueprints) # ["EngramEntry_Campfire_C", ...]
|
|
@@ -224,11 +225,13 @@ All file parsers support `load(source)` which accepts `str`, `Path`, or `bytes`
|
|
|
224
225
|
|
|
225
226
|
| Property | Type | Description |
|
|
226
227
|
|---|---|---|
|
|
227
|
-
| `player_name` | `str \| None` |
|
|
228
|
+
| `player_name` | `str \| None` | Platform gamertag / display name |
|
|
229
|
+
| `character_name` | `str \| None` | In-game character name, falling back to `player_name` when absent |
|
|
228
230
|
| `player_id` | `int \| None` | Unique player ID |
|
|
229
231
|
| `unique_id` | `str \| None` | Platform ID (Steam/Xbox numeric ID) |
|
|
230
232
|
| `tribe_id` | `int \| None` | Tribe ID (handles ASE `TribeId` / ASA `TribeID`) |
|
|
231
233
|
| `tribe_name` | `str \| None` | Always `None`; tribe name is not stored in profiles |
|
|
234
|
+
| `is_female` | `bool \| None` | Parsed gender flag (`True` = female, `False` = male, `None` = absent) |
|
|
232
235
|
| `level` | `int` | Current level (`ExtraCharacterLevel + 1`) |
|
|
233
236
|
| `experience` | `float` | Total XP |
|
|
234
237
|
| `total_engram_points` | `int` | Engram points spent |
|
|
@@ -16,7 +16,8 @@ Example usage:
|
|
|
16
16
|
>>>
|
|
17
17
|
>>> # Load a player profile
|
|
18
18
|
>>> profile = Profile.load("path/to/profile.arkprofile")
|
|
19
|
-
>>> print(f"
|
|
19
|
+
>>> print(f"Gamertag: {profile.player_name}")
|
|
20
|
+
>>> print(f"Character: {profile.character_name}")
|
|
20
21
|
>>>
|
|
21
22
|
>>> # Load tribe data
|
|
22
23
|
>>> tribe = Tribe.load("path/to/tribe.arktribe")
|
|
@@ -521,13 +521,23 @@ def _export_profile_parser(profile: Profile) -> dict[str, t.Any]:
|
|
|
521
521
|
}
|
|
522
522
|
steam_id = profile.unique_id or ""
|
|
523
523
|
|
|
524
|
+
# The C# reference treats these as two distinct names:
|
|
525
|
+
# Name (ContentPlayer.cs:77) -> platform gamertag (PlayerName field)
|
|
526
|
+
# CharacterName (ContentPlayer.cs:86) -> in-game name (PlayerCharacterName field)
|
|
527
|
+
# Export contract mirrors that split: ``steam`` = gamertag, ``name`` =
|
|
528
|
+
# in-game character name. Falls back to the gamertag if the character
|
|
529
|
+
# config struct is absent (matches the C# `?? Name` fallback).
|
|
530
|
+
gamertag = profile.player_name or ""
|
|
531
|
+
character_name = profile.character_name or gamertag
|
|
532
|
+
is_female = profile.is_female
|
|
533
|
+
|
|
524
534
|
result: dict[str, t.Any] = {
|
|
525
535
|
"playerid": profile.player_id or 0,
|
|
526
|
-
"steam":
|
|
527
|
-
"name":
|
|
536
|
+
"steam": gamertag,
|
|
537
|
+
"name": character_name,
|
|
528
538
|
"tribeid": profile.tribe_id or 0,
|
|
529
539
|
"tribe": profile.tribe_name or "",
|
|
530
|
-
"sex": "",
|
|
540
|
+
"sex": "Female" if is_female is True else "Male",
|
|
531
541
|
"lvl": profile.level,
|
|
532
542
|
"hp": stats["health"],
|
|
533
543
|
"stam": stats["stamina"],
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Player profile parser for .arkprofile files.
|
|
3
3
|
|
|
4
4
|
Profile files contain player character data including:
|
|
5
|
-
-
|
|
5
|
+
- Platform gamertag and character name
|
|
6
6
|
- Level and experience
|
|
7
7
|
- Engrams learned
|
|
8
8
|
- Inventory items (if saved)
|
|
@@ -28,7 +28,8 @@ class Profile(ArkFile):
|
|
|
28
28
|
|
|
29
29
|
Example usage:
|
|
30
30
|
>>> profile = Profile.load("examples/ase/map_save/2533274977850953.arkprofile")
|
|
31
|
-
>>> print(f"
|
|
31
|
+
>>> print(f"Gamertag: {profile.player_name}")
|
|
32
|
+
>>> print(f"Character: {profile.character_name}")
|
|
32
33
|
>>> print(f"Level: {profile.level}")
|
|
33
34
|
"""
|
|
34
35
|
|
|
@@ -70,9 +71,53 @@ class Profile(ArkFile):
|
|
|
70
71
|
|
|
71
72
|
@property
|
|
72
73
|
def player_name(self) -> str | None:
|
|
73
|
-
"""Get the player's
|
|
74
|
+
"""Get the player's platform gamertag (Steam / Xbox / PSN display name).
|
|
75
|
+
|
|
76
|
+
Note: despite the historical name, this is NOT the in-game character
|
|
77
|
+
name. For that, use ``character_name``. The C# reference (ContentPlayer.cs
|
|
78
|
+
line 77) reads this same ``PlayerName`` field into its ``Name`` property.
|
|
79
|
+
"""
|
|
74
80
|
return self._player_data.get("PlayerName")
|
|
75
81
|
|
|
82
|
+
@property
|
|
83
|
+
def character_name(self) -> str | None:
|
|
84
|
+
"""Get the player's in-game character name.
|
|
85
|
+
|
|
86
|
+
Purpose: returns the name the player chose when creating their
|
|
87
|
+
character (e.g. "Alex"), distinct from the platform gamertag (e.g.
|
|
88
|
+
"Itz0Alex") which ``player_name`` returns.
|
|
89
|
+
Preconditions: profile file is loaded; ``_player_data`` is accessible.
|
|
90
|
+
Postconditions: returns ``MyPlayerCharacterConfig.PlayerCharacterName``
|
|
91
|
+
when present, including empty-string values, falling back to
|
|
92
|
+
``player_name`` (gamertag) only when the config field is absent -
|
|
93
|
+
matches the C# reference behavior
|
|
94
|
+
(ContentPlayer.cs line 86: ``CharacterName = playerConfig.GetPropertyValue<string>("PlayerCharacterName") ?? Name;``).
|
|
95
|
+
Side effects: none.
|
|
96
|
+
Failure modes: returns ``None`` only when both the config struct and
|
|
97
|
+
``PlayerName`` are missing.
|
|
98
|
+
"""
|
|
99
|
+
config = self._player_data.get("MyPlayerCharacterConfig")
|
|
100
|
+
if isinstance(config, dict):
|
|
101
|
+
character_name = config.get("PlayerCharacterName")
|
|
102
|
+
if character_name is not None:
|
|
103
|
+
return character_name
|
|
104
|
+
return self.player_name
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def is_female(self) -> bool | None:
|
|
108
|
+
"""Get the player's character gender (True = female, False = male, None = unknown).
|
|
109
|
+
|
|
110
|
+
Same nested location as ``character_name``: read from
|
|
111
|
+
``MyPlayerCharacterConfig.bIsFemale``. Returns None when the config
|
|
112
|
+
struct is absent (treat as gender unknown / default male in display code).
|
|
113
|
+
"""
|
|
114
|
+
config = self._player_data.get("MyPlayerCharacterConfig")
|
|
115
|
+
if isinstance(config, dict):
|
|
116
|
+
value = config.get("bIsFemale")
|
|
117
|
+
if value is not None:
|
|
118
|
+
return bool(value)
|
|
119
|
+
return None
|
|
120
|
+
|
|
76
121
|
@property
|
|
77
122
|
def player_id(self) -> int | None:
|
|
78
123
|
"""Get the player's unique ID."""
|
|
@@ -202,10 +247,12 @@ class Profile(ArkFile):
|
|
|
202
247
|
base_dict.update(
|
|
203
248
|
{
|
|
204
249
|
"player_name": self.player_name,
|
|
250
|
+
"character_name": self.character_name,
|
|
205
251
|
"player_id": self.player_id,
|
|
206
252
|
"unique_id": self.unique_id,
|
|
207
253
|
"tribe_id": self.tribe_id,
|
|
208
254
|
"tribe_name": self.tribe_name,
|
|
255
|
+
"is_female": self.is_female,
|
|
209
256
|
"experience": self.experience,
|
|
210
257
|
"total_engram_points": self.total_engram_points,
|
|
211
258
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arkparser
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Pure Python parser for ARK: Survival Evolved and ARK: Survival Ascended save files
|
|
5
5
|
Author: Vertyco
|
|
6
6
|
License-Expression: MIT
|
|
@@ -97,7 +97,7 @@ A pure-Python library for parsing ARK: Survival Evolved (ASE) and ARK: Survival
|
|
|
97
97
|
|
|
98
98
|
## Features
|
|
99
99
|
|
|
100
|
-
- **Player Profiles** (`.arkprofile`): character name, level, stats, engrams
|
|
100
|
+
- **Player Profiles** (`.arkprofile`): platform gamertag, character name, level, stats, engrams
|
|
101
101
|
- **Tribe Data** (`.arktribe`): members, ranks, logs, alliances
|
|
102
102
|
- **Cloud Inventory / Obelisk**: uploaded creatures, items, cryopod contents
|
|
103
103
|
- **World Saves** (`.ark`): full map state, including creatures, structures, items, and players
|
|
@@ -122,7 +122,8 @@ from arkparser import Profile
|
|
|
122
122
|
|
|
123
123
|
profile = Profile.load("path/to/player.arkprofile") # auto-detects ASE/ASA
|
|
124
124
|
|
|
125
|
-
print(profile.player_name) #
|
|
125
|
+
print(profile.player_name) # Platform gamertag / display name
|
|
126
|
+
print(profile.character_name) # In-game character name
|
|
126
127
|
print(profile.level) # 105
|
|
127
128
|
print(profile.tribe_id) # 1729028872
|
|
128
129
|
print(profile.engram_blueprints) # ["EngramEntry_Campfire_C", ...]
|
|
@@ -258,11 +259,13 @@ All file parsers support `load(source)` which accepts `str`, `Path`, or `bytes`
|
|
|
258
259
|
|
|
259
260
|
| Property | Type | Description |
|
|
260
261
|
|---|---|---|
|
|
261
|
-
| `player_name` | `str \| None` |
|
|
262
|
+
| `player_name` | `str \| None` | Platform gamertag / display name |
|
|
263
|
+
| `character_name` | `str \| None` | In-game character name, falling back to `player_name` when absent |
|
|
262
264
|
| `player_id` | `int \| None` | Unique player ID |
|
|
263
265
|
| `unique_id` | `str \| None` | Platform ID (Steam/Xbox numeric ID) |
|
|
264
266
|
| `tribe_id` | `int \| None` | Tribe ID (handles ASE `TribeId` / ASA `TribeID`) |
|
|
265
267
|
| `tribe_name` | `str \| None` | Always `None`; tribe name is not stored in profiles |
|
|
268
|
+
| `is_female` | `bool \| None` | Parsed gender flag (`True` = female, `False` = male, `None` = absent) |
|
|
266
269
|
| `level` | `int` | Current level (`ExtraCharacterLevel + 1`) |
|
|
267
270
|
| `experience` | `float` | Total XP |
|
|
268
271
|
| `total_engram_points` | `int` | Engram points spent |
|
|
@@ -46,7 +46,9 @@ def test_export_players_uses_profile_parser(ase_profile_path: Path) -> None:
|
|
|
46
46
|
profile = Profile.load(ase_profile_path)
|
|
47
47
|
exported = export_players(type("Holder", (), {"profiles": [profile]})())
|
|
48
48
|
assert exported[0]["playerid"] == profile.player_id
|
|
49
|
-
assert exported[0]["
|
|
49
|
+
assert exported[0]["steam"] == profile.player_name
|
|
50
|
+
assert exported[0]["name"] == profile.character_name
|
|
51
|
+
assert exported[0]["sex"] == ("Female" if profile.is_female else "Male")
|
|
50
52
|
assert exported[0]["tribeid"] == profile.tribe_id
|
|
51
53
|
|
|
52
54
|
|
|
@@ -29,6 +29,17 @@ class TestASEProfile:
|
|
|
29
29
|
assert isinstance(profile.player_name, str)
|
|
30
30
|
assert len(profile.player_name) > 0
|
|
31
31
|
|
|
32
|
+
def test_ase_character_name(self, ase_profile_path: Path) -> None:
|
|
33
|
+
"""ASE profile should expose the in-game character name separately."""
|
|
34
|
+
profile = Profile.load(ase_profile_path)
|
|
35
|
+
assert profile.character_name == "neg"
|
|
36
|
+
assert profile.character_name != profile.player_name
|
|
37
|
+
|
|
38
|
+
def test_ase_is_female(self, ase_profile_path: Path) -> None:
|
|
39
|
+
"""ASE profile should expose the parsed gender flag when present."""
|
|
40
|
+
profile = Profile.load(ase_profile_path)
|
|
41
|
+
assert profile.is_female is True
|
|
42
|
+
|
|
32
43
|
def test_ase_player_id(self, ase_profile_path: Path) -> None:
|
|
33
44
|
"""ASE profile should have a numeric player ID."""
|
|
34
45
|
profile = Profile.load(ase_profile_path)
|
|
@@ -47,6 +58,8 @@ class TestASEProfile:
|
|
|
47
58
|
d = profile.to_dict()
|
|
48
59
|
assert isinstance(d, dict)
|
|
49
60
|
assert "player_name" in d
|
|
61
|
+
assert d["character_name"] == profile.character_name
|
|
62
|
+
assert d["is_female"] is True
|
|
50
63
|
assert "player_id" in d
|
|
51
64
|
|
|
52
65
|
|
|
@@ -70,6 +83,16 @@ class TestASAProfile:
|
|
|
70
83
|
assert isinstance(profile.player_name, str)
|
|
71
84
|
assert len(profile.player_name) > 0
|
|
72
85
|
|
|
86
|
+
def test_asa_character_name_falls_back_to_player_name(self, asa_profile_path: Path) -> None:
|
|
87
|
+
"""ASA profile should fall back to the platform name when character config is absent."""
|
|
88
|
+
profile = Profile.load(asa_profile_path)
|
|
89
|
+
assert profile.character_name == profile.player_name
|
|
90
|
+
|
|
91
|
+
def test_asa_is_female_can_be_unknown(self, asa_profile_path: Path) -> None:
|
|
92
|
+
"""ASA profile should return None when the gender flag is absent."""
|
|
93
|
+
profile = Profile.load(asa_profile_path)
|
|
94
|
+
assert profile.is_female is None
|
|
95
|
+
|
|
73
96
|
def test_asa_player_id(self, asa_profile_path: Path) -> None:
|
|
74
97
|
"""ASA profile should have a numeric player ID."""
|
|
75
98
|
profile = Profile.load(asa_profile_path)
|
|
@@ -88,6 +111,8 @@ class TestASAProfile:
|
|
|
88
111
|
d = profile.to_dict()
|
|
89
112
|
assert isinstance(d, dict)
|
|
90
113
|
assert "player_name" in d
|
|
114
|
+
assert d["character_name"] == profile.character_name
|
|
115
|
+
assert d["is_female"] is None
|
|
91
116
|
assert "player_id" in d
|
|
92
117
|
|
|
93
118
|
def test_asa_engram_blueprints(self, asa_profile_path: Path) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|