arkparser 0.7.0__tar.gz → 0.7.1__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.7.0 → arkparser-0.7.1}/PKG-INFO +10 -1
- {arkparser-0.7.0 → arkparser-0.7.1}/README.md +9 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/types.py +11 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/data_models.py +5 -1
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/export.py +14 -18
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/files/world_save.py +5 -7
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/game_objects/game_object.py +11 -1
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser.egg-info/PKG-INFO +10 -1
- {arkparser-0.7.0 → arkparser-0.7.1}/pyproject.toml +1 -1
- {arkparser-0.7.0 → arkparser-0.7.1}/LICENSE +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/__init__.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/__init__.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/binary_reader.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/exceptions.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/map_config.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/normalization.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/common/version_detection.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/files/__init__.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/files/base.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/files/cloud_inventory.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/files/profile.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/files/tribe.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/game_objects/__init__.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/game_objects/container.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/game_objects/location.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/properties/__init__.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/properties/base.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/properties/byte_property.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/properties/compound.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/properties/primitives.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/properties/registry.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/__init__.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/base.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/colors.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/misc.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/property_list.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/registry.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser/structs/vectors.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser.egg-info/SOURCES.txt +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser.egg-info/dependency_links.txt +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser.egg-info/requires.txt +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/arkparser.egg-info/top_level.txt +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/setup.cfg +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_asa_header_position.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_asa_name_table.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_ase_cluster_drift.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_binary_reader.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_binary_reader_layouts.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_cloud_export.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_cloud_inventory.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_cryopod_export.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_current_stats.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_data_models.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_export.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_game_objects.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_golden_exports.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_lazy_properties.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_profile.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_review_fixes.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_tribe.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_v13_property_layouts.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_version_detection.py +0 -0
- {arkparser-0.7.0 → arkparser-0.7.1}/tests/test_world_save.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arkparser
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
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
|
|
@@ -681,6 +681,15 @@ Schema policy:
|
|
|
681
681
|
|
|
682
682
|
ASA worldsave property layouts differ between **v13** (`TheIsland_WP` and older single-player saves, legacy `AsaSavegameToolkit`-style `dataSize + position + typeRef + byte` body) and **v14+** (current production ASA, marker-based body). Both are parsed by version-aware property readers; `WorldSave.version` is the source of truth.
|
|
683
683
|
|
|
684
|
+
### Parse diagnostics (logging)
|
|
685
|
+
|
|
686
|
+
The parser logs through the standard `logging` module on the `arkparser.*` logger hierarchy. At DEBUG level it reports recoverable parse anomalies, for example ASE objects whose property block terminates early (the run of successfully parsed properties is kept and the remaining bytes are preserved on `GameObject.extra_data`):
|
|
687
|
+
|
|
688
|
+
```python
|
|
689
|
+
import logging
|
|
690
|
+
logging.getLogger("arkparser").setLevel(logging.DEBUG)
|
|
691
|
+
```
|
|
692
|
+
|
|
684
693
|
### Known limitation: ASA cryopod property blocks are partially decoded
|
|
685
694
|
|
|
686
695
|
ASA cryopods (`PrimalItem_WeaponEmptyCryopod_C`, `SoulTrap`, `Vivarium`, `DinoBall`) store the embedded creature snapshot inside the item's `CustomItemDatas.CustomDataBytes.ByteArrays[0]` as a **zlib + custom-RLE compressed `AsaDataStore` blob**. The parser surfaces the snapshot via the simpler `CustomDataStrings` / `CustomDataFloats` accessors, exposing **species, tamed name, level, color regions, and `CurrentStatusValues[0..11]`** on each cryopodded creature.
|
|
@@ -647,6 +647,15 @@ Schema policy:
|
|
|
647
647
|
|
|
648
648
|
ASA worldsave property layouts differ between **v13** (`TheIsland_WP` and older single-player saves, legacy `AsaSavegameToolkit`-style `dataSize + position + typeRef + byte` body) and **v14+** (current production ASA, marker-based body). Both are parsed by version-aware property readers; `WorldSave.version` is the source of truth.
|
|
649
649
|
|
|
650
|
+
### Parse diagnostics (logging)
|
|
651
|
+
|
|
652
|
+
The parser logs through the standard `logging` module on the `arkparser.*` logger hierarchy. At DEBUG level it reports recoverable parse anomalies, for example ASE objects whose property block terminates early (the run of successfully parsed properties is kept and the remaining bytes are preserved on `GameObject.extra_data`):
|
|
653
|
+
|
|
654
|
+
```python
|
|
655
|
+
import logging
|
|
656
|
+
logging.getLogger("arkparser").setLevel(logging.DEBUG)
|
|
657
|
+
```
|
|
658
|
+
|
|
650
659
|
### Known limitation: ASA cryopod property blocks are partially decoded
|
|
651
660
|
|
|
652
661
|
ASA cryopods (`PrimalItem_WeaponEmptyCryopod_C`, `SoulTrap`, `Vivarium`, `DinoBall`) store the embedded creature snapshot inside the item's `CustomItemDatas.CustomDataBytes.ByteArrays[0]` as a **zlib + custom-RLE compressed `AsaDataStore` blob**. The parser surfaces the snapshot via the simpler `CustomDataStrings` / `CustomDataFloats` accessors, exposing **species, tamed name, level, color regions, and `CurrentStatusValues[0..11]`** on each cryopodded creature.
|
|
@@ -21,6 +21,17 @@ from dataclasses import dataclass
|
|
|
21
21
|
# The "None" name is used as a terminator in property lists
|
|
22
22
|
NAME_NONE = "None"
|
|
23
23
|
|
|
24
|
+
# Class-name / blueprint fragments that mark a creature-storage item.
|
|
25
|
+
# Single source of truth for cryopod detection: in-world iteration
|
|
26
|
+
# (WorldSave.iter_cryopod_creatures), inventory filtering (export), and
|
|
27
|
+
# uploaded-item checks (UploadedItem.is_cryopod) all match against this.
|
|
28
|
+
CRYOPOD_CLASS_PATTERNS: tuple[str, ...] = (
|
|
29
|
+
"Cryopod",
|
|
30
|
+
"SoulTrap",
|
|
31
|
+
"Vivarium",
|
|
32
|
+
"DinoBall",
|
|
33
|
+
)
|
|
34
|
+
|
|
24
35
|
|
|
25
36
|
# =============================================================================
|
|
26
37
|
# ArkName (FName)
|
|
@@ -15,10 +15,14 @@ from dataclasses import dataclass, field
|
|
|
15
15
|
|
|
16
16
|
from .common.binary_reader import BinaryReader
|
|
17
17
|
from .common.normalization import normalize_indexed_data, normalize_indexed_list
|
|
18
|
+
from .common.types import CRYOPOD_CLASS_PATTERNS
|
|
18
19
|
from .properties.registry import read_properties
|
|
19
20
|
|
|
20
21
|
logger = logging.getLogger(__name__)
|
|
21
22
|
|
|
23
|
+
# Uploaded items match against lowercased blueprint paths.
|
|
24
|
+
_CRYOPOD_PATTERNS_LOWER: tuple[str, ...] = tuple(p.lower() for p in CRYOPOD_CLASS_PATTERNS)
|
|
25
|
+
|
|
22
26
|
# Trailing UE actor spawn-instance suffix on cryopod class names, e.g.
|
|
23
27
|
# "Raptor_Character_BP_C_2145673735". ARK stores the full instance name in the
|
|
24
28
|
# cryopod CustomDataStrings/SoftClasses blob; the worldsave name-table path
|
|
@@ -820,7 +824,7 @@ class UploadedItem:
|
|
|
820
824
|
def is_cryopod(self) -> bool:
|
|
821
825
|
"""Check if this item is a cryopod (or similar creature storage item)."""
|
|
822
826
|
bp_lower = self.blueprint.lower()
|
|
823
|
-
return any(x in bp_lower for x in
|
|
827
|
+
return any(x in bp_lower for x in _CRYOPOD_PATTERNS_LOWER)
|
|
824
828
|
|
|
825
829
|
@property
|
|
826
830
|
def cryopod_creature(self) -> CryopodCreature | None:
|
|
@@ -44,21 +44,14 @@ from pathlib import Path
|
|
|
44
44
|
from arkparser.common.exceptions import ArkParseError
|
|
45
45
|
from arkparser.common.map_config import MapConfig
|
|
46
46
|
from arkparser.common.normalization import normalize_indexed_data, normalize_indexed_list
|
|
47
|
+
from arkparser.common.types import CRYOPOD_CLASS_PATTERNS
|
|
47
48
|
from arkparser.data_models import CryopodCreature
|
|
48
49
|
from arkparser.files import CloudInventory, Profile, Tribe
|
|
49
50
|
|
|
50
51
|
logger = logging.getLogger(__name__)
|
|
51
52
|
|
|
52
|
-
_CRYOPOD_CLASS_PATTERNS: tuple[str, ...] = (
|
|
53
|
-
"Cryopod",
|
|
54
|
-
"SoulTrap",
|
|
55
|
-
"Vivarium",
|
|
56
|
-
"DinoBall",
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
|
|
60
53
|
def _is_cryopod_class(class_name: str) -> bool:
|
|
61
|
-
return any(p in class_name for p in
|
|
54
|
+
return any(p in class_name for p in CRYOPOD_CLASS_PATTERNS)
|
|
62
55
|
|
|
63
56
|
|
|
64
57
|
def _decode_inventory_cryopod(item_obj: t.Any) -> CryopodCreature | None:
|
|
@@ -152,6 +145,10 @@ _LEGACY_STAT_ORDER: tuple[str, ...] = (
|
|
|
152
145
|
)
|
|
153
146
|
_EXTRA_STAT_ORDER: tuple[str, ...] = ("torp", "water", "temp", "fort")
|
|
154
147
|
_FLAT_STAT_ORDER: tuple[str, ...] = _LEGACY_STAT_ORDER + _EXTRA_STAT_ORDER
|
|
148
|
+
# The order tuples are hand-maintained views of _STAT_NAMES; catch drift at
|
|
149
|
+
# import time before it silently misaligns exported stat JSON.
|
|
150
|
+
assert len(_FLAT_STAT_ORDER) == len(_STAT_NAMES), "stat order tuples out of sync"
|
|
151
|
+
assert set(_FLAT_STAT_ORDER) == set(_STAT_NAMES), "stat order tuples out of sync"
|
|
155
152
|
|
|
156
153
|
|
|
157
154
|
def _prop(obj: t.Any, name: str, default: t.Any = None, index: int | None = None) -> t.Any:
|
|
@@ -2519,8 +2516,7 @@ def _tribe_from_object(
|
|
|
2519
2516
|
tribe_id = _int(_prop(obj, "TribeID")) or _int(_prop(obj, "TribeId"))
|
|
2520
2517
|
owner_id = _int(_prop(obj, "OwnerPlayerDataID")) or _int(_prop(obj, "OwnerPlayerDataId"))
|
|
2521
2518
|
members: list[dict[str, t.Any]] = []
|
|
2522
|
-
i
|
|
2523
|
-
while True:
|
|
2519
|
+
for i in range(_MAX_TRIBE_MEMBERS):
|
|
2524
2520
|
pid = _prop(obj, "MembersPlayerDataID", index=i)
|
|
2525
2521
|
if pid is None:
|
|
2526
2522
|
break
|
|
@@ -2536,15 +2532,14 @@ def _tribe_from_object(
|
|
|
2536
2532
|
"steamid": (profile.unique_id or "") if profile is not None else "",
|
|
2537
2533
|
}
|
|
2538
2534
|
)
|
|
2539
|
-
|
|
2535
|
+
assert len(members) < _MAX_TRIBE_MEMBERS, "tribe member list exceeded bound"
|
|
2540
2536
|
alliances: list[int] = []
|
|
2541
|
-
j
|
|
2542
|
-
while True:
|
|
2537
|
+
for j in range(_MAX_TRIBE_MEMBERS):
|
|
2543
2538
|
val = _prop(obj, "TribeAlliances", index=j)
|
|
2544
2539
|
if val is None:
|
|
2545
2540
|
break
|
|
2546
2541
|
alliances.append(_int(val))
|
|
2547
|
-
|
|
2542
|
+
assert len(alliances) < _MAX_TRIBE_MEMBERS, "tribe alliance list exceeded bound"
|
|
2548
2543
|
c = counts.get(tribe_id, {})
|
|
2549
2544
|
data: dict[str, t.Any] = {
|
|
2550
2545
|
"tribeid": tribe_id,
|
|
@@ -2569,14 +2564,15 @@ def _tribe_object_logs(obj: t.Any) -> list[str]:
|
|
|
2569
2564
|
if isinstance(log_val, list):
|
|
2570
2565
|
return [e for e in log_val if isinstance(e, str) and e.strip()]
|
|
2571
2566
|
out: list[str] = []
|
|
2572
|
-
|
|
2573
|
-
|
|
2567
|
+
entries = 0
|
|
2568
|
+
for k in range(_MAX_TRIBE_MEMBERS):
|
|
2574
2569
|
v = _prop(obj, "TribeLog", index=k)
|
|
2575
2570
|
if v is None:
|
|
2576
2571
|
break
|
|
2572
|
+
entries += 1
|
|
2577
2573
|
if isinstance(v, str) and v.strip():
|
|
2578
2574
|
out.append(v)
|
|
2579
|
-
|
|
2575
|
+
assert entries < _MAX_TRIBE_MEMBERS, "tribe log list exceeded bound"
|
|
2580
2576
|
return out
|
|
2581
2577
|
|
|
2582
2578
|
|
|
@@ -34,6 +34,7 @@ from uuid import UUID
|
|
|
34
34
|
from ..common.binary_reader import BinaryReader, guid_str_le
|
|
35
35
|
from ..common.exceptions import ArkParseError, CorruptDataError
|
|
36
36
|
from ..common.normalization import normalize_indexed_data, normalize_indexed_list
|
|
37
|
+
from ..common.types import CRYOPOD_CLASS_PATTERNS
|
|
37
38
|
from ..data_models import CryopodCreature
|
|
38
39
|
from ..game_objects.container import GameObjectContainer
|
|
39
40
|
from ..game_objects.game_object import MAX_OBJECT_COUNT, GameObject
|
|
@@ -428,13 +429,10 @@ class WorldSave:
|
|
|
428
429
|
"""Return creature nest objects (wyvern, drake, etc.)."""
|
|
429
430
|
return self.container.get_nests()
|
|
430
431
|
|
|
431
|
-
#
|
|
432
|
-
#
|
|
433
|
-
#
|
|
434
|
-
|
|
435
|
-
_CRYOPOD_PATTERNS: t.ClassVar[tuple[str, ...]] = (
|
|
436
|
-
"Cryopod", "SoulTrap", "Vivarium", "DinoBall",
|
|
437
|
-
)
|
|
432
|
+
# Shared with data_models.UploadedItem.is_cryopod (blueprint paths) and
|
|
433
|
+
# the export inventory filter; the in-world version matches against the
|
|
434
|
+
# GameObject's ``class_name`` directly.
|
|
435
|
+
_CRYOPOD_PATTERNS: t.ClassVar[tuple[str, ...]] = CRYOPOD_CLASS_PATTERNS
|
|
438
436
|
|
|
439
437
|
def iter_cryopod_creatures(self) -> t.Iterator[tuple[GameObject, CryopodCreature]]:
|
|
440
438
|
"""Yield ``(item_obj, CryopodCreature)`` for every *filled* cryopod
|
|
@@ -7,6 +7,7 @@ Game objects represent creatures, items, structures, players, and other entities
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import logging
|
|
10
11
|
import re
|
|
11
12
|
import typing as t
|
|
12
13
|
from collections import defaultdict
|
|
@@ -16,6 +17,8 @@ from ..common.exceptions import CorruptDataError
|
|
|
16
17
|
from ..properties.registry import read_properties, read_property
|
|
17
18
|
from .location import LocationData
|
|
18
19
|
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
19
22
|
if t.TYPE_CHECKING:
|
|
20
23
|
from ..common.binary_reader import BinaryReader
|
|
21
24
|
from ..properties.base import Property
|
|
@@ -420,11 +423,18 @@ class GameObject:
|
|
|
420
423
|
if prop is None:
|
|
421
424
|
break
|
|
422
425
|
properties.append(prop)
|
|
423
|
-
except Exception:
|
|
426
|
+
except Exception as exc:
|
|
424
427
|
self.properties = properties
|
|
425
428
|
self._props_loaded = True
|
|
426
429
|
if next_object is None:
|
|
427
430
|
raise
|
|
431
|
+
logger.debug(
|
|
432
|
+
"property parse stopped early for %s after %d properties, "
|
|
433
|
+
"remainder kept as extra_data: %s",
|
|
434
|
+
self.class_name,
|
|
435
|
+
len(properties),
|
|
436
|
+
exc,
|
|
437
|
+
)
|
|
428
438
|
|
|
429
439
|
next_offset = properties_block_offset + next_object.properties_offset
|
|
430
440
|
remaining = next_offset - reader.position
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arkparser
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
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
|
|
@@ -681,6 +681,15 @@ Schema policy:
|
|
|
681
681
|
|
|
682
682
|
ASA worldsave property layouts differ between **v13** (`TheIsland_WP` and older single-player saves, legacy `AsaSavegameToolkit`-style `dataSize + position + typeRef + byte` body) and **v14+** (current production ASA, marker-based body). Both are parsed by version-aware property readers; `WorldSave.version` is the source of truth.
|
|
683
683
|
|
|
684
|
+
### Parse diagnostics (logging)
|
|
685
|
+
|
|
686
|
+
The parser logs through the standard `logging` module on the `arkparser.*` logger hierarchy. At DEBUG level it reports recoverable parse anomalies, for example ASE objects whose property block terminates early (the run of successfully parsed properties is kept and the remaining bytes are preserved on `GameObject.extra_data`):
|
|
687
|
+
|
|
688
|
+
```python
|
|
689
|
+
import logging
|
|
690
|
+
logging.getLogger("arkparser").setLevel(logging.DEBUG)
|
|
691
|
+
```
|
|
692
|
+
|
|
684
693
|
### Known limitation: ASA cryopod property blocks are partially decoded
|
|
685
694
|
|
|
686
695
|
ASA cryopods (`PrimalItem_WeaponEmptyCryopod_C`, `SoulTrap`, `Vivarium`, `DinoBall`) store the embedded creature snapshot inside the item's `CustomItemDatas.CustomDataBytes.ByteArrays[0]` as a **zlib + custom-RLE compressed `AsaDataStore` blob**. The parser surfaces the snapshot via the simpler `CustomDataStrings` / `CustomDataFloats` accessors, exposing **species, tamed name, level, color regions, and `CurrentStatusValues[0..11]`** on each cryopodded creature.
|
|
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
|
|
File without changes
|
|
File without changes
|