Skip to content

Commit f6b4ef8

Browse files
committed
fix: use fixed TypeTreeGeneratorAPI and correctly use it to generate nodes, also be more explicit regarding related errors
1 parent 3be629f commit f6b4ef8

File tree

3 files changed

+36
-49
lines changed

3 files changed

+36
-49
lines changed

UnityPy/files/ObjectReader.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,7 @@ def _get_typetree_node(
282282
if not node:
283283
node = get_typetree_node(self.class_id, self.version)
284284
if node.m_Type == "MonoBehaviour":
285-
try:
286-
node = self._try_monobehaviour_node(node)
287-
except Exception:
288-
pass
285+
node = self.generate_monobehaviour_node(node)
289286
if not node:
290287
raise TypeTreeError("There are no TypeTree nodes for this object.")
291288
return node
@@ -297,21 +294,29 @@ def parse_as_object(self, node: Optional[NodeInput] = None, check_read: bool = T
297294
def parse_as_dict(self, node: Optional[NodeInput] = None, check_read: bool = True) -> dict[str, Any]:
298295
return self.read_typetree(nodes=node, wrap=False, check_read=check_read) # type: ignore
299296

300-
def _try_monobehaviour_node(self, base_node: TypeTreeNode) -> TypeTreeNode:
297+
def parse_monobehaviour_head(self, mb_node: Optional[TypeTreeNode] = None) -> MonoBehaviour:
298+
if mb_node is None:
299+
mb_node = get_typetree_node(ClassIDType.MonoBehaviour, self.version)
300+
301+
mb = self.read_typetree(nodes=mb_node, wrap=True, check_read=False)
302+
return cast(MonoBehaviour, mb)
303+
304+
def generate_monobehaviour_node(self, mb_node: Optional[TypeTreeNode] = None) -> TypeTreeNode:
301305
env = self.assets_file.environment
302306
generator = env.typetree_generator
303307
if generator is None:
304-
raise ValueError("No typetree generator set!")
305-
monobehaviour = cast(MonoBehaviour, self.parse_as_object(base_node, check_read=False))
308+
raise ValueError("MonoBehaviour detected, but no typetree_generator set to the environment!")
309+
310+
monobehaviour = self.parse_monobehaviour_head(mb_node)
306311
script = monobehaviour.m_Script.deref_parse_as_object()
307312

308313
if script.m_Namespace != "":
309314
fullname = f"{script.m_Namespace}.{script.m_ClassName}"
310315
else:
311316
fullname = script.m_ClassName
312317

313-
node = generator.get_nodes_up(base_node, script.m_AssemblyName, fullname)
318+
node = generator.get_nodes_up(script.m_AssemblyName, fullname)
314319
if node:
315320
return node
316321
else:
317-
raise ValueError("Failed to get custom MonoBehaviour node!")
322+
raise ValueError(f"Failed to generate MonoBehaviour node for {fullname} of {script.m_AssemblyName}!")

UnityPy/helpers/TypeTreeGenerator.py

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from .TypeTreeNode import TypeTreeNode
55

66
try:
7-
from TypeTreeGeneratorAPI import TypeTreeGenerator as TypeTreeGeneratorBase
7+
from TypeTreeGeneratorAPI import TypeTreeGenerator as TypeTreeGeneratorBase # pyright: ignore[reportAssignmentType]
88
except ImportError:
99

1010
class TypeTreeGeneratorBase:
@@ -45,50 +45,32 @@ def load_local_dll_folder(self, dll_dir: str):
4545
data = f.read()
4646
self.load_dll(data)
4747

48-
def get_nodes_up(self, base_node: TypeTreeNode, assembly: str, fullname: str) -> TypeTreeNode:
49-
root = self.cache.get((assembly, fullname))
50-
if root is not None:
51-
return root
48+
def get_nodes_up(self, assembly: str, fullname: str) -> TypeTreeNode:
49+
key = (assembly, fullname)
50+
if key in self.cache:
51+
return self.cache[key]
5252

5353
if not assembly.endswith(".dll"):
5454
assembly = f"{assembly}.dll"
55+
5556
base_nodes = self.get_nodes(assembly, fullname)
5657

57-
base_root = base_nodes[0]
58-
root = TypeTreeNode(
59-
base_root.m_Level,
60-
base_root.m_Type,
61-
base_root.m_Name,
62-
0,
63-
0,
64-
m_MetaFlag=base_root.m_MetaFlag,
65-
m_Children=base_node.m_Children[:],
58+
node = TypeTreeNode.from_list(
59+
[
60+
TypeTreeNode(
61+
base_node.m_Level,
62+
base_node.m_Type,
63+
base_node.m_Name,
64+
0,
65+
0,
66+
m_MetaFlag=base_node.m_MetaFlag,
67+
)
68+
for base_node in base_nodes
69+
]
6670
)
67-
stack: List[TypeTreeNode] = []
68-
parent = root
69-
prev = root
70-
71-
for base_node in base_nodes[1:]:
72-
node = TypeTreeNode(
73-
base_node.m_Level,
74-
base_node.m_Type,
75-
base_node.m_Name,
76-
0,
77-
0,
78-
m_MetaFlag=base_node.m_MetaFlag,
79-
)
80-
if node.m_Level > prev.m_Level:
81-
stack.append(parent)
82-
parent = prev
83-
elif node.m_Level < prev.m_Level:
84-
while node.m_Level <= parent.m_Level:
85-
parent = stack.pop()
86-
87-
parent.m_Children.append(node)
88-
prev = node
89-
90-
self.cache[(assembly, fullname)] = root
91-
return root
71+
72+
self.cache[key] = node
73+
return node
9274

9375

9476
__all__ = ("TypeTreeGenerator",)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ UnityPy = "UnityPy.cli:main"
5959

6060
[project.optional-dependencies]
6161
# optional dependencies must be lowercase/normalized
62-
ttgen = ["typetreegeneratorapi>=0.0.7"]
62+
ttgen = ["typetreegeneratorapi>=0.0.10"]
6363
full = ["unitypy[ttgen]"]
6464
tests = ["pytest", "pillow", "psutil", "unitypy[full]"]
6565
dev = ["ruff", "unitypy[tests]"]

0 commit comments

Comments
 (0)