arkparser 0.1.0__py3-none-any.whl

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.
Files changed (46) hide show
  1. arkparser/__init__.py +117 -0
  2. arkparser/common/__init__.py +72 -0
  3. arkparser/common/binary_reader.py +402 -0
  4. arkparser/common/exceptions.py +99 -0
  5. arkparser/common/map_config.py +166 -0
  6. arkparser/common/types.py +249 -0
  7. arkparser/common/version_detection.py +195 -0
  8. arkparser/data_models.py +801 -0
  9. arkparser/export.py +485 -0
  10. arkparser/files/__init__.py +25 -0
  11. arkparser/files/base.py +309 -0
  12. arkparser/files/cloud_inventory.py +259 -0
  13. arkparser/files/profile.py +205 -0
  14. arkparser/files/tribe.py +155 -0
  15. arkparser/files/world_save.py +699 -0
  16. arkparser/game_objects/__init__.py +32 -0
  17. arkparser/game_objects/container.py +180 -0
  18. arkparser/game_objects/game_object.py +273 -0
  19. arkparser/game_objects/location.py +87 -0
  20. arkparser/models/__init__.py +29 -0
  21. arkparser/models/character.py +227 -0
  22. arkparser/models/creature.py +642 -0
  23. arkparser/models/item.py +207 -0
  24. arkparser/models/player.py +263 -0
  25. arkparser/models/stats.py +226 -0
  26. arkparser/models/structure.py +176 -0
  27. arkparser/models/tribe.py +291 -0
  28. arkparser/properties/__init__.py +77 -0
  29. arkparser/properties/base.py +329 -0
  30. arkparser/properties/byte_property.py +230 -0
  31. arkparser/properties/compound.py +1125 -0
  32. arkparser/properties/primitives.py +803 -0
  33. arkparser/properties/registry.py +236 -0
  34. arkparser/py.typed +0 -0
  35. arkparser/structs/__init__.py +60 -0
  36. arkparser/structs/base.py +63 -0
  37. arkparser/structs/colors.py +108 -0
  38. arkparser/structs/misc.py +133 -0
  39. arkparser/structs/property_list.py +101 -0
  40. arkparser/structs/registry.py +140 -0
  41. arkparser/structs/vectors.py +221 -0
  42. arkparser-0.1.0.dist-info/METADATA +833 -0
  43. arkparser-0.1.0.dist-info/RECORD +46 -0
  44. arkparser-0.1.0.dist-info/WHEEL +5 -0
  45. arkparser-0.1.0.dist-info/licenses/LICENSE +21 -0
  46. arkparser-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,227 @@
1
+ """
2
+ Character model class - Player characters in world saves.
3
+
4
+ Wraps GameObject with intuitive attribute access for character data.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import typing as t
10
+ from dataclasses import dataclass, field
11
+
12
+ from .stats import CreatureStats, Location
13
+
14
+
15
+ @dataclass
16
+ class Character:
17
+ """
18
+ A player character in a world save.
19
+
20
+ Wraps a GameObject representing a player character with intuitive property access.
21
+ This differs from Player (profile data) - Character is the in-world entity.
22
+
23
+ Attributes:
24
+ class_name: Blueprint class name.
25
+ player_name: Character name.
26
+ tribe_id: ID of the player's tribe.
27
+ tribe_name: Name of the player's tribe.
28
+ level: Character level.
29
+ location: World position.
30
+
31
+ Example:
32
+ >>> for character in save.characters:
33
+ ... print(f"{character.player_name} - Level {character.level}")
34
+ """
35
+
36
+ _game_object: t.Any = field(default=None, repr=False)
37
+ _status_object: t.Any = field(default=None, repr=False)
38
+
39
+ # Cached values
40
+ _stats: CreatureStats | None = field(default=None, repr=False)
41
+
42
+ @classmethod
43
+ def from_game_object(
44
+ cls,
45
+ game_object: t.Any,
46
+ status_object: t.Any = None,
47
+ ) -> Character:
48
+ """
49
+ Create a Character from a GameObject.
50
+
51
+ Args:
52
+ game_object: The character's main game object.
53
+ status_object: The character's status component (for stats).
54
+
55
+ Returns:
56
+ A Character instance.
57
+ """
58
+ return cls(_game_object=game_object, _status_object=status_object)
59
+
60
+ @property
61
+ def class_name(self) -> str:
62
+ """Blueprint class name."""
63
+ return self._game_object.class_name if self._game_object else ""
64
+
65
+ @property
66
+ def guid(self) -> str:
67
+ """Unique identifier (ASA only)."""
68
+ return self._game_object.guid if self._game_object else ""
69
+
70
+ @property
71
+ def player_id(self) -> int:
72
+ """Unique player ID."""
73
+ if not self._game_object:
74
+ return 0
75
+ val = self._game_object.get_property_value("LinkedPlayerDataID", default=0)
76
+ if not val:
77
+ val = self._game_object.get_property_value("PlayerDataID", default=0)
78
+ return int(val) if val else 0
79
+
80
+ @property
81
+ def player_name(self) -> str:
82
+ """Character name."""
83
+ if not self._game_object:
84
+ return ""
85
+ name = self._game_object.get_property_value("PlayerName", default="")
86
+ if not name:
87
+ name = self._game_object.get_property_value("LinkedPlayerName", default="")
88
+ return name or ""
89
+
90
+ @property
91
+ def steam_name(self) -> str:
92
+ """Steam/platform username."""
93
+ if not self._game_object:
94
+ return ""
95
+ return self._game_object.get_property_value("PlatformProfileName", default="") or ""
96
+
97
+ @property
98
+ def tribe_id(self) -> int:
99
+ """Tribe ID the character belongs to."""
100
+ if not self._game_object:
101
+ return 0
102
+ val = self._game_object.get_property_value("TargetingTeam", default=0)
103
+ if not val:
104
+ val = self._game_object.get_property_value("TribeID", default=0)
105
+ return int(val) if val else 0
106
+
107
+ @property
108
+ def tribe_name(self) -> str:
109
+ """Name of the character's tribe."""
110
+ if not self._game_object:
111
+ return ""
112
+ return self._game_object.get_property_value("TribeName", default="") or ""
113
+
114
+ @property
115
+ def is_female(self) -> bool:
116
+ """True if the character is female."""
117
+ if not self._game_object:
118
+ return False
119
+ return self._game_object.get_property_value("bIsFemale", default=False)
120
+
121
+ @property
122
+ def gender(self) -> str:
123
+ """Gender as string ('Female' or 'Male')."""
124
+ return "Female" if self.is_female else "Male"
125
+
126
+ @property
127
+ def base_level(self) -> int:
128
+ """Base character level."""
129
+ if self._status_object:
130
+ return self._status_object.get_property_value("BaseCharacterLevel", default=1)
131
+ return 1
132
+
133
+ @property
134
+ def extra_level(self) -> int:
135
+ """Extra levels (ascension levels, etc.)."""
136
+ if self._status_object:
137
+ val = self._status_object.get_property_value("ExtraCharacterLevel", default=0)
138
+ return int(val) if val else 0
139
+ return 0
140
+
141
+ @property
142
+ def level(self) -> int:
143
+ """Total character level."""
144
+ return self.base_level + self.extra_level
145
+
146
+ @property
147
+ def experience(self) -> float:
148
+ """Current experience points."""
149
+ if self._status_object:
150
+ val = self._status_object.get_property_value("ExperiencePoints", default=0.0)
151
+ return float(val) if val else 0.0
152
+ return 0.0
153
+
154
+ @property
155
+ def stats(self) -> CreatureStats:
156
+ """
157
+ Character stat points.
158
+
159
+ Uses the same 12-stat system as creatures.
160
+ """
161
+ if self._stats is None:
162
+ points = []
163
+ if self._status_object:
164
+ for i in range(12):
165
+ val = self._status_object.get_property_value("NumberOfLevelUpPointsApplied", index=i, default=0)
166
+ points.append(int(val) if val else 0)
167
+ self._stats = CreatureStats.from_array(points)
168
+ return self._stats
169
+
170
+ @property
171
+ def location(self) -> Location | None:
172
+ """World position and rotation."""
173
+ if self._game_object and self._game_object.location:
174
+ loc = self._game_object.location
175
+ return Location(
176
+ x=loc.x,
177
+ y=loc.y,
178
+ z=loc.z,
179
+ pitch=getattr(loc, "pitch", 0.0),
180
+ yaw=getattr(loc, "yaw", 0.0),
181
+ roll=getattr(loc, "roll", 0.0),
182
+ )
183
+ return None
184
+
185
+ @property
186
+ def is_sleeping(self) -> bool:
187
+ """True if the character is sleeping (logged out)."""
188
+ if not self._game_object:
189
+ return False
190
+ return self._game_object.get_property_value("bIsSleeping", default=False)
191
+
192
+ def get_property(self, name: str, index: int = 0, default: t.Any = None) -> t.Any:
193
+ """
194
+ Get a raw property value from the underlying game object.
195
+
196
+ Args:
197
+ name: Property name.
198
+ index: Array index for repeated properties.
199
+ default: Value to return if not found.
200
+
201
+ Returns:
202
+ The property value.
203
+ """
204
+ if self._game_object:
205
+ return self._game_object.get_property_value(name, default=default, index=index)
206
+ return default
207
+
208
+ def to_dict(self) -> dict[str, t.Any]:
209
+ """Convert to dictionary."""
210
+ result: dict[str, t.Any] = {
211
+ "player_id": self.player_id,
212
+ "player_name": self.player_name,
213
+ "gender": self.gender,
214
+ "level": self.level,
215
+ "experience": self.experience,
216
+ "stats": self.stats.to_dict(),
217
+ "tribe_id": self.tribe_id,
218
+ "tribe_name": self.tribe_name,
219
+ }
220
+ if self.steam_name:
221
+ result["steam_name"] = self.steam_name
222
+ if self.location:
223
+ result["location"] = self.location.to_dict()
224
+ return result
225
+
226
+ def __repr__(self) -> str:
227
+ return f"Character({self.player_name!r}, level={self.level})"