Skip to content

Commit 96531ff

Browse files
committed
implement Tpk typetree bundle of AssetRipper/Tpk
1 parent 4359169 commit 96531ff

3 files changed

Lines changed: 542 additions & 25 deletions

File tree

UnityPy/files/ObjectReader.py

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from ..enums import ClassIDType
22
from . import SerializedFile
33
from .. import classes
4+
from ..classes.Object import NodeHelper
45
from ..streams import EndianBinaryReader, EndianBinaryWriter
56
from ..helpers import TypeTreeHelper
7+
from ..helpers.Tpk import get_typetree_nodes
68

79

810
class ObjectReader:
@@ -58,10 +60,12 @@ def __init__(self, assets_file, reader: EndianBinaryReader):
5860
self.class_id = reader.read_u_short()
5961
if types:
6062
self.serialized_type = (
61-
x for x in types if x.class_id == self.type_id).__next__()
63+
x for x in types if x.class_id == self.type_id
64+
).__next__()
6265
else:
6366
self.serialized_type = SerializedFile.SerializedType(
64-
reader, self.assets_file)
67+
reader, self.assets_file
68+
)
6569
else:
6670
typ = types[self.type_id]
6771
self.serialized_type = typ
@@ -80,7 +84,9 @@ def __init__(self, assets_file, reader: EndianBinaryReader):
8084
if header.version == 15 or header.version == 16:
8185
self.stripped = reader.read_byte()
8286

83-
def write(self, header, writer: EndianBinaryWriter, data_writer: EndianBinaryWriter):
87+
def write(
88+
self, header, writer: EndianBinaryWriter, data_writer: EndianBinaryWriter
89+
):
8490
if self.assets_file.big_id_enabled:
8591
writer.write_long(self.path_id)
8692
elif header.version < 14:
@@ -150,20 +156,18 @@ def reset(self):
150156
self.reader.Position = self.byte_start
151157

152158
def read(self):
153-
try:
154-
obj = getattr(classes, self.type.name, classes.Object)(self)
155-
except Exception as e:
156-
raise e
157-
# TODO: only specific exceptions here?
158-
except:
159-
# HACK: in case the parsing via the class fails this solution
160-
# uses the type tree to set the variables and then changes the class
161-
obj = classes.Object(self)
162-
obj.__class__ = getattr(classes, self.type.name, classes.Object)
163-
for key, val in obj.__dict__.items():
164-
if " " in key:
165-
obj.__dict__[key.replace(" ", "_")] = val
166-
delattr(obj, key)
159+
cls = getattr(classes, self.type.name, None)
160+
161+
obj = None
162+
if cls:
163+
try:
164+
obj = cls(self)
165+
except Exception as e:
166+
print(e)
167+
if not obj:
168+
typetree = self.read_typetree()
169+
if typetree:
170+
obj = NodeHelper(typetree, self.assets_file)
167171
self._read_until = self.reader.Position
168172
return obj
169173

@@ -189,8 +193,7 @@ def dump_typetree(self, nodes: list = None) -> str:
189193
if nodes:
190194
TypeTreeHelper.read_typetree_str(sb, nodes, self)
191195
elif getattr(self.serialized_type, "nodes", None):
192-
TypeTreeHelper.read_typetree_str(
193-
sb, self.serialized_type.nodes, self)
196+
TypeTreeHelper.read_typetree_str(sb, self.serialized_type.nodes, self)
194197
return "".join(sb)
195198
return ""
196199

@@ -205,18 +208,22 @@ def read_typetree(self, nodes: list = None) -> dict:
205208
if nodes:
206209
tree = TypeTreeHelper.read_typetree(nodes, self)
207210
elif self.serialized_type.nodes:
208-
tree = TypeTreeHelper.read_typetree(
209-
self.serialized_type.nodes, self)
211+
tree = TypeTreeHelper.read_typetree(self.serialized_type.nodes, self)
212+
else:
213+
nodes = get_typetree_nodes(self.class_id, self.version)
214+
if nodes:
215+
tree = TypeTreeHelper.read_typetree(nodes, self)
210216
return tree
211217

212-
def save_typetree(self, tree: dict, nodes: list = None, writer: EndianBinaryWriter = None):
218+
def save_typetree(
219+
self, tree: dict, nodes: list = None, writer: EndianBinaryWriter = None
220+
):
213221
if not writer:
214222
writer = EndianBinaryWriter(endian=self.reader.endian)
215223
if nodes:
216224
TypeTreeHelper.write_typetree(tree, nodes, writer)
217225
elif self.serialized_type.nodes:
218-
TypeTreeHelper.write_typetree(
219-
tree, self.serialized_type.nodes, writer)
226+
TypeTreeHelper.write_typetree(tree, self.serialized_type.nodes, writer)
220227
else:
221228
raise ValueError("There are no TypeTree nodes for this object.")
222229
data = writer.bytes
@@ -234,4 +241,3 @@ def set_raw_data(self, data):
234241
self.data = data
235242
if self.assets_file:
236243
self.assets_file.mark_changed()
237-

0 commit comments

Comments
 (0)