Skip to content

Commit 75892bb

Browse files
committed
feat: read preload table to get path id
1 parent 3472646 commit 75892bb

3 files changed

Lines changed: 34 additions & 1 deletion

File tree

UnityPy/environment.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,15 @@ def search(item):
203203

204204
return search(self)
205205

206+
def _build_container_index(self) -> None:
207+
for f in self.cabs.values():
208+
if isinstance(f, SerializedFile):
209+
f.container.parse_preload_table()
210+
206211
@property
207212
def container(self) -> ContainerHelper:
208213
"""Returns a dictionary of all objects in the Environment."""
214+
self._build_container_index()
209215
container = []
210216
for f in self.cabs.values():
211217
if isinstance(f, SerializedFile) and not f.is_dependency:

UnityPy/files/ObjectReader.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ def peek_name(self) -> Union[str, None]:
198198

199199
@property
200200
def container(self):
201+
env = self.assets_file.environment
202+
if env is not None:
203+
env._build_container_index()
201204
return self.assets_file._container.path_dict.get(self.path_id)
202205

203206
@property

UnityPy/helpers/ContainerHelper.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING, Dict, Generator, Iterator, List, Tuple, Union
3+
from typing import TYPE_CHECKING, Dict, Generator, Iterator, List, Optional, Tuple, Union
44

55
from attrs import define
66

@@ -16,13 +16,37 @@ class ContainerHelper:
1616
container: List[Tuple[str, AssetInfo]]
1717
container_dict: Dict[str, PPtr[Object]]
1818
path_dict: Dict[int, str]
19+
_preload_table: Optional[List[PPtr[Object]]] = None
1920

2021
def __init__(self, container: Union[List[Tuple[str, AssetInfo]], AssetBundle]) -> None:
22+
preload_table: Optional[List[PPtr[Object]]] = None
2123
if not isinstance(container, (list)):
24+
preload_table = container.m_PreloadTable
2225
container = container.m_Container
2326
self.container = container
2427
self.container_dict = {key: value.asset for key, value in container}
2528
self.path_dict = {value.asset.path_id: key for key, value in container}
29+
self._preload_table = preload_table
30+
31+
def parse_preload_table(self) -> None:
32+
if self._preload_table is None:
33+
return
34+
35+
for path, info in self.container:
36+
start = info.preloadIndex
37+
size = info.preloadSize
38+
if start < 0 or size <= 0 or start + size > len(self._preload_table):
39+
continue
40+
for pptr in self._preload_table[start : start + size]:
41+
if not pptr:
42+
continue
43+
try:
44+
target = pptr.deref()
45+
except (FileNotFoundError, KeyError):
46+
continue
47+
target.assets_file._container.path_dict.setdefault(pptr.path_id, path)
48+
49+
self._preload_table = None
2650

2751
def items(self) -> Generator[Tuple[str, PPtr[Object]], None, None]:
2852
return ((key, value.asset) for key, value in self.container)

0 commit comments

Comments
 (0)