-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmesh2info.py
More file actions
executable file
·103 lines (87 loc) · 3.52 KB
/
mesh2info.py
File metadata and controls
executable file
·103 lines (87 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python3
import sys
import os
import struct
import mesh_tag
import mono2tag
import loadtags
import utils
DEBUG = (os.environ.get('DEBUG') == '1')
def main(game_directory, level, plugin_names):
"""
Load Myth game tags and plugins and output header info for a mesh
"""
(game_version, tags, entrypoint_map, data_map, cutscenes) = loadtags.load_tags(game_directory, plugin_names)
try:
if not level or level == 'list':
mono2tag.print_entrypoint_map(entrypoint_map)
else:
for mesh_id in mesh_entries(game_version, level, entrypoint_map, tags, plugin_names):
parse_mesh_tag(game_version, tags, data_map, mesh_id)
except (struct.error, UnicodeDecodeError) as e:
raise ValueError(f"Error processing binary data: {e}")
def mesh_entries(game_version, level, entrypoint_map, tags, plugin_names):
plugin_names = [os.path.basename(p) for p in plugin_names]
if level == 'all':
if game_version == 1:
for level in range(1, 26):
(mesh_id, header_name, entry_name) = parse_level(f'{level:02}', tags)
print(f'mesh={mesh_id} file=[{header_name}] [{entry_name}]')
yield mesh_id
else:
for mesh_id, (entry_name, entry_long_name, archive_list) in entrypoint_map.items():
if not plugin_names or bool(set(plugin_names) & set(archive_list)):
print(f'mesh={mesh_id} archives=[{archive_list}] [{entry_name}] [{entry_long_name}]')
yield mesh_id
else:
(mesh_id, header_name, entry_name) = parse_level(level, tags)
print(f'mesh={mesh_id} file=[{header_name}] [{entry_name}]')
yield mesh_id
def parse_level(level, tags):
ret = None
level_mesh = level[5:] if level.startswith('mesh=') else None
if level_mesh:
if level_mesh in tags['mesh']:
latest = tags['mesh'][level_mesh][-1]
ret = (level_mesh, latest[0], latest[1].name)
else:
for mesh_id, tag_headers in tags['mesh'].items():
latest = tag_headers[-1]
if latest[1].name.startswith(f'{level} '):
ret = (mesh_id, latest[0], latest[1].name)
if ret:
return ret
else:
print("Invalid level")
sys.exit(1)
def parse_mesh_tag(game_version, tags, data_map, mesh_id):
mesh_tag_data = loadtags.get_tag_data(tags, data_map, 'mesh', mesh_id)
mesh_header = mesh_tag.parse_header(mesh_tag_data)
locations = [l for (l, th) in tags['mesh'][mesh_id]]
print('data len', len(mesh_tag_data))
print_header(mesh_header, mesh_id, locations)
# editor_data = mesh_tag.parse_oak_editor_data(mesh_header, mesh_tag_data)
# import json
# print(json.dumps(editor_data, indent=1))
def print_header(mesh_header, mesh_id, locations=None):
for i, (f, val) in enumerate(mesh_header._asdict().items()):
print(f'{f:<42} {utils.val_repr(val)}')
# print(f'[{mesh_id}] {f} {val} {locations}')
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: python3 {sys.argv[0]} <game_directory> [<level> [<plugin_names> ...]]")
sys.exit(1)
game_directory = sys.argv[1]
level = None
plugin_names = []
if len(sys.argv) > 2:
level = sys.argv[2]
if len(sys.argv) > 3:
plugin_names = sys.argv[3:]
try:
main(game_directory, level, plugin_names)
except KeyboardInterrupt:
sys.exit(130)
except BrokenPipeError:
sys.stdout = None
sys.exit(1)