Skip to content

Commit c74d984

Browse files
committed
Support FileVersion 8.8
1 parent ed41078 commit c74d984

File tree

6 files changed

+797
-37
lines changed

6 files changed

+797
-37
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages = ["src/genieutils"]
77

88
[project]
99
name = "genieutils-py"
10-
version = "0.0.8"
10+
version = "0.0.9"
1111
authors = [
1212
{ name = "SiegeEngineers", email = "[email protected]" },
1313
]

src/genieutils/task.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
FORMAT = '<hhbhhhhhhhhfffbfbbhhbbbhhhhhhll'
88
FORMAT_LENGTH = 67
99

10+
FORMAT_88 = '<hhbhhhhhhhhfffbfbbhhbbbhhhhhhllh'
11+
FORMAT_LENGTH_88 = struct.calcsize(FORMAT_88)
12+
1013

1114
@dataclass(slots=True)
1215
class Task(GenieClass):
@@ -41,9 +44,16 @@ class Task(GenieClass):
4144
resource_deposit_sound_id: int
4245
wwise_resource_gathering_sound_id: int
4346
wwise_resource_deposit_sound_id: int
47+
enabled: int
4448

4549
@classmethod
4650
def from_bytes(cls, content: ByteHandler) -> 'Task':
51+
if content.version >= Version.VER_88:
52+
return cls.from_bytes_88(content)
53+
return cls.from_bytes_84(content)
54+
55+
@classmethod
56+
def from_bytes_84(cls, content: ByteHandler) -> 'Task':
4757
task_type, \
4858
id_, \
4959
is_default, \
@@ -111,9 +121,89 @@ def from_bytes(cls, content: ByteHandler) -> 'Task':
111121
resource_deposit_sound_id=resource_deposit_sound_id,
112122
wwise_resource_gathering_sound_id=wwise_resource_gathering_sound_id,
113123
wwise_resource_deposit_sound_id=wwise_resource_deposit_sound_id,
124+
enabled=-1,
125+
)
126+
127+
@classmethod
128+
def from_bytes_88(cls, content: ByteHandler) -> 'Task':
129+
task_type, \
130+
id_, \
131+
is_default, \
132+
action_type, \
133+
class_id, \
134+
unit_id, \
135+
terrain_id, \
136+
resource_in, \
137+
resource_multiplier, \
138+
resource_out, \
139+
unused_resource, \
140+
work_value_1, \
141+
work_value_2, \
142+
work_range, \
143+
auto_search_targets, \
144+
search_wait_time, \
145+
enable_targeting, \
146+
combat_level_flag, \
147+
gather_type, \
148+
work_flag_2, \
149+
target_diplomacy, \
150+
carry_check, \
151+
pick_for_construction, \
152+
moving_graphic_id, \
153+
proceeding_graphic_id, \
154+
working_graphic_id, \
155+
carrying_graphic_id, \
156+
resource_gathering_sound_id, \
157+
resource_deposit_sound_id, \
158+
wwise_resource_gathering_sound_id, \
159+
wwise_resource_deposit_sound_id, \
160+
enabled = struct.unpack(
161+
FORMAT_88,
162+
content.consume_range(FORMAT_LENGTH_88)
163+
)
164+
165+
return cls(
166+
task_type=task_type,
167+
id=id_,
168+
is_default=is_default,
169+
action_type=action_type,
170+
class_id=class_id,
171+
unit_id=unit_id,
172+
terrain_id=terrain_id,
173+
resource_in=resource_in,
174+
resource_multiplier=resource_multiplier,
175+
resource_out=resource_out,
176+
unused_resource=unused_resource,
177+
work_value_1=work_value_1,
178+
work_value_2=work_value_2,
179+
work_range=work_range,
180+
auto_search_targets=auto_search_targets,
181+
search_wait_time=search_wait_time,
182+
enable_targeting=enable_targeting,
183+
combat_level_flag=combat_level_flag,
184+
gather_type=gather_type,
185+
work_flag_2=work_flag_2,
186+
target_diplomacy=target_diplomacy,
187+
carry_check=carry_check,
188+
pick_for_construction=pick_for_construction,
189+
moving_graphic_id=moving_graphic_id,
190+
proceeding_graphic_id=proceeding_graphic_id,
191+
working_graphic_id=working_graphic_id,
192+
carrying_graphic_id=carrying_graphic_id,
193+
resource_gathering_sound_id=resource_gathering_sound_id,
194+
resource_deposit_sound_id=resource_deposit_sound_id,
195+
wwise_resource_gathering_sound_id=wwise_resource_gathering_sound_id,
196+
wwise_resource_deposit_sound_id=wwise_resource_deposit_sound_id,
197+
enabled=enabled,
114198
)
115199

116200
def to_bytes(self, version: Version) -> bytes:
201+
if version >= Version.VER_88:
202+
return self.to_bytes_88(version)
203+
return self.to_bytes_84(version)
204+
205+
206+
def to_bytes_84(self, version: Version) -> bytes:
117207
return struct.pack(FORMAT,
118208
self.task_type,
119209
self.id,
@@ -147,3 +237,40 @@ def to_bytes(self, version: Version) -> bytes:
147237
self.wwise_resource_gathering_sound_id,
148238
self.wwise_resource_deposit_sound_id,
149239
)
240+
241+
242+
def to_bytes_88(self, version: Version) -> bytes:
243+
return struct.pack(FORMAT_88,
244+
self.task_type,
245+
self.id,
246+
self.is_default,
247+
self.action_type,
248+
self.class_id,
249+
self.unit_id,
250+
self.terrain_id,
251+
self.resource_in,
252+
self.resource_multiplier,
253+
self.resource_out,
254+
self.unused_resource,
255+
self.work_value_1,
256+
self.work_value_2,
257+
self.work_range,
258+
self.auto_search_targets,
259+
self.search_wait_time,
260+
self.enable_targeting,
261+
self.combat_level_flag,
262+
self.gather_type,
263+
self.work_flag_2,
264+
self.target_diplomacy,
265+
self.carry_check,
266+
self.pick_for_construction,
267+
self.moving_graphic_id,
268+
self.proceeding_graphic_id,
269+
self.working_graphic_id,
270+
self.carrying_graphic_id,
271+
self.resource_gathering_sound_id,
272+
self.resource_deposit_sound_id,
273+
self.wwise_resource_gathering_sound_id,
274+
self.wwise_resource_deposit_sound_id,
275+
self.enabled,
276+
)

src/genieutils/tech.py

Lines changed: 148 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,31 @@ def to_bytes(self, version: Version) -> bytes:
2626
])
2727

2828

29+
@dataclass(slots=True)
30+
class ResearchLocation(GenieClass):
31+
location_id: int
32+
research_time: int
33+
button_id: int
34+
hot_key_id: int
35+
36+
@classmethod
37+
def from_bytes(cls, content: ByteHandler) -> 'ResearchLocation':
38+
return cls(
39+
location_id=content.read_int_16(),
40+
research_time=content.read_int_16(),
41+
button_id=content.read_int_8(),
42+
hot_key_id=content.read_int_32(),
43+
)
44+
45+
def to_bytes(self, version: Version) -> bytes:
46+
return b''.join([
47+
self.write_int_16(self.location_id),
48+
self.write_int_16(self.research_time),
49+
self.write_int_8(self.button_id),
50+
self.write_int_32(self.hot_key_id),
51+
])
52+
53+
2954
@dataclass(slots=True)
3055
class Tech(GenieClass):
3156
required_techs: tuple[int, int, int, int, int, int]
@@ -46,31 +71,116 @@ class Tech(GenieClass):
4671
hot_key: int
4772
name: str
4873
repeatable: int
74+
research_locations: list[ResearchLocation]
4975

5076
@classmethod
5177
def from_bytes(cls, content: ByteHandler) -> 'Tech':
78+
if content.version >= Version.VER_88:
79+
return cls.from_bytes_88(content)
80+
return cls.from_bytes_84(content)
81+
82+
@classmethod
83+
def from_bytes_84(cls, content: ByteHandler) -> 'Tech':
84+
required_techs = content.read_int_16_array_6()
85+
resource_costs = content.read_class_array_3(ResearchResourceCost)
86+
required_tech_count = content.read_int_16()
87+
civ = content.read_int_16()
88+
full_tech_mode = content.read_int_16()
89+
research_location = content.read_int_16()
90+
language_dll_name = content.read_int_32()
91+
language_dll_description = content.read_int_32()
92+
research_time = content.read_int_16()
93+
effect_id = content.read_int_16()
94+
type = content.read_int_16()
95+
icon_id = content.read_int_16()
96+
button_id = content.read_int_8()
97+
language_dll_help = content.read_int_32()
98+
language_dll_tech_tree = content.read_int_32()
99+
hot_key = content.read_int_32()
100+
name = content.read_debug_string()
101+
repeatable = content.read_int_8()
102+
research_locations = [ResearchLocation(
103+
button_id=button_id,
104+
research_time=research_time,
105+
hot_key_id=hot_key,
106+
location_id=research_location,
107+
)]
52108
return cls(
53-
required_techs=content.read_int_16_array_6(),
54-
resource_costs=content.read_class_array_3(ResearchResourceCost),
55-
required_tech_count=content.read_int_16(),
56-
civ=content.read_int_16(),
57-
full_tech_mode=content.read_int_16(),
58-
research_location=content.read_int_16(),
59-
language_dll_name=content.read_int_32(),
60-
language_dll_description=content.read_int_32(),
61-
research_time=content.read_int_16(),
62-
effect_id=content.read_int_16(),
63-
type=content.read_int_16(),
64-
icon_id=content.read_int_16(),
65-
button_id=content.read_int_8(),
66-
language_dll_help=content.read_int_32(),
67-
language_dll_tech_tree=content.read_int_32(),
68-
hot_key=content.read_int_32(),
69-
name=content.read_debug_string(),
70-
repeatable=content.read_int_8(),
109+
required_techs=required_techs,
110+
resource_costs=resource_costs,
111+
required_tech_count=required_tech_count,
112+
civ=civ,
113+
full_tech_mode=full_tech_mode,
114+
research_location=research_location,
115+
language_dll_name=language_dll_name,
116+
language_dll_description=language_dll_description,
117+
research_time=research_time,
118+
effect_id=effect_id,
119+
type=type,
120+
icon_id=icon_id,
121+
button_id=button_id,
122+
language_dll_help=language_dll_help,
123+
language_dll_tech_tree=language_dll_tech_tree,
124+
hot_key=hot_key,
125+
name=name,
126+
repeatable=repeatable,
127+
research_locations=research_locations,
128+
)
129+
130+
@classmethod
131+
def from_bytes_88(cls, content: ByteHandler) -> 'Tech':
132+
required_techs = content.read_int_16_array_6()
133+
resource_costs = content.read_class_array_3(ResearchResourceCost)
134+
required_tech_count = content.read_int_16()
135+
civ = content.read_int_16()
136+
full_tech_mode = content.read_int_16()
137+
language_dll_name = content.read_int_32()
138+
language_dll_description = content.read_int_32()
139+
effect_id = content.read_int_16()
140+
type = content.read_int_16()
141+
icon_id = content.read_int_16()
142+
language_dll_help = content.read_int_32()
143+
language_dll_tech_tree = content.read_int_32()
144+
name = content.read_debug_string()
145+
repeatable = content.read_int_8()
146+
research_location_count = content.read_int_16()
147+
research_locations = content.read_class_array(ResearchLocation, research_location_count)
148+
research_location = -1
149+
research_time = 0
150+
button_id = 0
151+
hot_key = -1
152+
if len(research_locations):
153+
research_location = research_locations[0].location_id
154+
research_time = research_locations[0].research_time
155+
button_id = research_locations[0].button_id
156+
hot_key = research_locations[0].hot_key_id
157+
return cls(
158+
required_techs=required_techs,
159+
resource_costs=resource_costs,
160+
required_tech_count=required_tech_count,
161+
civ=civ,
162+
full_tech_mode=full_tech_mode,
163+
research_location=research_location,
164+
language_dll_name=language_dll_name,
165+
language_dll_description=language_dll_description,
166+
research_time=research_time,
167+
effect_id=effect_id,
168+
type=type,
169+
icon_id=icon_id,
170+
button_id=button_id,
171+
language_dll_help=language_dll_help,
172+
language_dll_tech_tree=language_dll_tech_tree,
173+
hot_key=hot_key,
174+
name=name,
175+
repeatable=repeatable,
176+
research_locations=research_locations,
71177
)
72178

73179
def to_bytes(self, version: Version) -> bytes:
180+
if version >= Version.VER_88:
181+
return self.to_bytes_88(version)
182+
return self.to_bytes_84(version)
183+
def to_bytes_84(self, version: Version) -> bytes:
74184
return b''.join([
75185
self.write_int_16_array(self.required_techs),
76186
self.write_class_array(self.resource_costs, version),
@@ -91,3 +201,23 @@ def to_bytes(self, version: Version) -> bytes:
91201
self.write_debug_string(self.name),
92202
self.write_int_8(self.repeatable),
93203
])
204+
205+
def to_bytes_88(self, version: Version) -> bytes:
206+
return b''.join([
207+
self.write_int_16_array(self.required_techs),
208+
self.write_class_array(self.resource_costs, version),
209+
self.write_int_16(self.required_tech_count),
210+
self.write_int_16(self.civ),
211+
self.write_int_16(self.full_tech_mode),
212+
self.write_int_32(self.language_dll_name),
213+
self.write_int_32(self.language_dll_description),
214+
self.write_int_16(self.effect_id),
215+
self.write_int_16(self.type),
216+
self.write_int_16(self.icon_id),
217+
self.write_int_32(self.language_dll_help),
218+
self.write_int_32(self.language_dll_tech_tree),
219+
self.write_debug_string(self.name),
220+
self.write_int_8(self.repeatable),
221+
self.write_int_16(len(self.research_locations)),
222+
self.write_class_array(self.research_locations, version),
223+
])

0 commit comments

Comments
 (0)