ManagedReferencesRegistry parsing for TypeTrees · UserUnknownFactor/UnityPy@97336ea · GitHub
Skip to content

Commit 97336ea

Browse files
ManagedReferencesRegistry parsing for TypeTrees
BlockStream reader and writer Option to spoof CRC32 for BlockStream Allow EBR parameter for set_raw_data Boosting is difficult to maintain Serialization fixes
1 parent 538b63e commit 97336ea

60 files changed

Lines changed: 2455 additions & 2715 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 1 addition & 1 deletion

‎UnityPy/classes/BuildSettings.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(self, reader):
3232
self.m_AuthToken = reader.read_aligned_string()
3333
self.m_GraphicsAPIs = reader.read_int_array()
3434
"""
35-
self.the_rest = reader.read_the_rest(reader)
35+
self.the_rest = reader.read_the_rest()
3636

3737
def save(self, writer: EndianBinaryWriter = None):
3838
if writer is None:
@@ -66,4 +66,5 @@ def save(self, writer: EndianBinaryWriter = None):
6666
"""
6767

6868
writer.write_bytes(self.the_rest)
69-
self.set_raw_data(writer.bytes)
69+
70+
self.set_raw_data(writer)

‎UnityPy/classes/GameObject.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,4 @@ def save(self, writer: EndianBinaryWriter = None, intern_call=True):
8181
writer.write_u_short(self.m_Tag)
8282
writer.write_boolean(self.m_IsActive)
8383
if not intern_call:
84-
self.set_raw_data(writer.bytes)
84+
self.set_raw_data(writer)

‎UnityPy/classes/Material.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ def save(self, writer: EndianBinaryWriter = None):
9090
writer.write_int(len(self.m_BuildTextureStacks))
9191
for item in self.m_BuildTextureStacks:
9292
item.save(writer)
93-
self.set_raw_data(writer.bytes)
93+
94+
self.set_raw_data(writer)
9495

9596
class BuildTextureStackReference:
9697
def __init__(self, reader: EndianBinaryReader):

‎UnityPy/classes/MonoBehaviour.py‎

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,34 @@ def __init__(self, reader: EndianBinaryReader):
1010
self.name = reader.read_aligned_string()
1111

1212
self._raw_offset = reader.Position
13-
if self.assets_file._enable_type_tree:
13+
if self.assets_file.type_trees_saved and self.assets_file._use_type_trees:
1414
try:
15-
self.read_typetree()
15+
self.read_typetree(all_trees=self.assets_file.get_all_typetrees())
1616
except TypeTreeError as e:
17-
print("Failed to read TypeTree:\n", e)
18-
self.assets_file._enable_type_tree = False
17+
print(f"failed to read TypeTree for {self.name} [path_id={self.path_id}]: {e}")
18+
self.assets_file._use_type_trees = False
19+
self.raw_monobehaviour = self.reader.read_the_rest()
20+
else:
21+
self.raw_monobehaviour = self.reader.read_the_rest()
1922

2023
def save(self, writer: EndianBinaryWriter = None, raw_data: bytes = None):
24+
if raw_data is None:
25+
if not self.raw_monobehaviour:
26+
ValueError("No raw MonoBehaviour data provided")
27+
else:
28+
raw_data = self.raw_monobehaviour
29+
2130
if writer is None:
2231
writer = EndianBinaryWriter(endian=self.reader.endian)
23-
if not raw_data:
24-
ValueError("No raw data given")
25-
32+
2633
super().save(writer)
2734
self.m_Script.save(writer)
2835
writer.write_aligned_string(self.name)
2936
writer.write(raw_data)
30-
31-
self.set_raw_data(writer.bytes)
3237

33-
@property
34-
def raw_data(self) -> bytes:
38+
self.set_raw_data(writer)
39+
40+
def get_raw_monobehaviour(self) -> bytes:
3541
"""
3642
Reads the undocumentated data following the default init.
3743
This is usefull for classes that are stored via MonoBehaviours.

‎UnityPy/classes/Object.py‎

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def dump_typetree(self, nodes: list = None) -> str:
4141
def dump_typetree_structure(self) -> str:
4242
return self.reader.dump_typetree_structure()
4343

44-
def read_typetree(self, nodes: list = None, wrap: bool = False) -> dict:
45-
tree = self.reader.read_typetree(nodes)
44+
def read_typetree(self, nodes: list = None, wrap: bool = False, all_trees=None) -> dict:
45+
tree = self.reader.read_typetree(nodes, all_trees=all_trees)
4646
self.type_tree = NodeHelper(tree, self.assets_file)
4747
return self.type_tree if wrap else tree
4848

@@ -54,7 +54,7 @@ def class_to_dict(value):
5454
return {key: class_to_dict(val) for key, val in value.items()}
5555
elif hasattr(value, "__dict__"):
5656
if isinstance(value, PPtr):
57-
return {"m_PathID": value.path_id, "m_FileID": value.file_id}
57+
return {"m_FileID": value.file_id, "m_PathID": value.path_id}
5858
return {
5959
key: class_to_dict(val)
6060
for key, val in value.__dict__.items()
@@ -70,7 +70,7 @@ def class_to_dict(value):
7070
def get_raw_data(self) -> bytes:
7171
return self.reader.get_raw_data()
7272

73-
def set_raw_data(self, data):
73+
def set_raw_data(self, data: bytes):
7474
self.reader.set_raw_data(data)
7575

7676
def save(self, writer: EndianBinaryWriter = None, intern_call=False):
@@ -84,11 +84,6 @@ def save(self, writer: EndianBinaryWriter = None, intern_call=False):
8484
# so we have to use the typetree if it exists
8585
self.save_typetree()
8686

87-
def _save(self, writer):
88-
# the reader is actually an ObjectReader,
89-
# the data value is written back into the asset
90-
self.reader.data = writer.bytes
91-
9287
def __getattr__(self, name):
9388
"""
9489
If item not found in __dict__, read type_tree and check if it is in there.
@@ -124,8 +119,8 @@ class NodeHelper:
124119
def __init__(self, data, assets_file):
125120
if "m_PathID" in data and "m_FileID" in data:
126121
# used to make pointers directly useable
127-
self.path_id = data["m_PathID"]
128122
self.file_id = data["m_FileID"]
123+
self.path_id = data["m_PathID"]
129124
self.index = data.get("m_Index", -2)
130125
self.assets_file = assets_file
131126
self._obj = None
@@ -134,6 +129,7 @@ def __init__(self, data, assets_file):
134129
self.__dict__ = {
135130
key: NodeHelper(val, assets_file) for key, val in data.items()
136131
}
132+
pass
137133

138134
def __new__(cls, data, assets_file):
139135
if isinstance(data, dict):
@@ -154,13 +150,12 @@ def dump(val):
154150
if isinstance(val, NodeHelper)
155151
else [dump(item) for item in val]
156152
if isinstance(val, list)
157-
else {"m_PathID": val.path_id, "m_FileID": val.file_id}
153+
else {"m_FileID": val.file_id, "m_PathID": val.path_id}
158154
if isinstance(val, PPtr)
159155
else [x for x in val]
160156
if isinstance(val, (bytearray, bytes))
161157
else val
162158
)
163-
164159
return {key: dump(val) for key, val in self.__dict__.items()}
165160

166161
def items(self):
@@ -174,13 +169,10 @@ def keys(self):
174169

175170
def save(self, *args, **kwargs):
176171
raise NotImplementedError(
177-
"This is a guessed structure, please create its proper "+
178-
"parser or use the Object's save_typetree(<this NodeHelper>) method."
172+
"This is a helper structure, please create its proper parser"+
173+
" or use Object's save_typetree(<this NodeHelper>) method."
179174
)
180175

181176
def __repr__(self):
182177
name = getattr(self, "m_Name", None)
183-
if name:
184-
return f"<NodeHelper name={name}>"
185-
else:
186-
return "<NodeHelper>"
178+
return f"<NodeHelper name={name}>" if name else "<NodeHelper>"

‎UnityPy/classes/PPtr.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from ..files import ObjectReader
2-
from ..streams import EndianBinaryReader, EndianBinaryWriter
2+
from ..streams import EndianBinaryWriter
33
from ..enums import ClassIDType
44
from ..config import WARNED_NOTFOUND_ONCE
55

6-
6+
# NOTE: don't call this by itself since it may be depreciated
77
def save_ptr(obj, writer: EndianBinaryWriter):
88
if isinstance(obj, PPtr):
99
writer.write_int(obj.file_id)
@@ -109,9 +109,13 @@ def external_name(self):
109109
def __getattr__(self, key):
110110
obj = self.get_obj()
111111
if obj is None:
112+
if key == "read":
113+
return lambda: None
112114
raise AttributeError(f"{self} has no method called \"{key}\"")
113115
return getattr(obj, key)
114116

115117
def __bool__(self):
116118
return True if self.get_obj() else False
117119

120+
def __hash__(self):
121+
return hash((self.file_id, self.path_id))

‎UnityPy/classes/PlayerSettings.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def __init__(self, reader: ObjectReader):
251251
self.virtualTexturingSupportEnabled = reader.read_boolean()
252252
self.uploadClearedTextureDataAfterCreationFromScript = reader.read_boolean()
253253
"""
254-
self.the_rest = reader.read_the_rest(reader)
254+
self.the_rest = reader.read_the_rest()
255255

256256
def save(self, writer: EndianBinaryWriter = None):
257257
if writer is None:
@@ -290,5 +290,5 @@ def save(self, writer: EndianBinaryWriter = None):
290290
writer.align_stream()
291291

292292
writer.write_bytes(self.the_rest)
293-
self.set_raw_data(writer.bytes)
293+
self.set_raw_data(writer)
294294

‎UnityPy/classes/RectTransform.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ def save(self, writer = None):
2020
writer.write_vector2(self.m_SizeDelta)
2121
writer.write_vector2(self.m_Pivot)
2222

23-
self.set_raw_data(writer.bytes)
23+
self.set_raw_data(writer)

‎UnityPy/classes/Shader.py‎

Lines changed: 3 additions & 3 deletions

0 commit comments

Comments
 (0)