Skip to content

Commit b5149f6

Browse files
committed
convert: Refactor AoCProcessor into separate files.
1 parent ce4afe3 commit b5149f6

34 files changed

+1651
-1275
lines changed

openage/convert/processor/conversion/aoc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_subdirectory(ability)
2121
add_subdirectory(auxiliary)
2222
add_subdirectory(civ)
2323
add_subdirectory(effect)
24+
add_subdirectory(main)
2425
add_subdirectory(media)
2526
add_subdirectory(modifier)
2627
add_subdirectory(modpack)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
add_py_modules(
2+
__init__.py
3+
)
4+
5+
add_subdirectory(extract)
6+
add_subdirectory(groups)
7+
add_subdirectory(link)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Routines for the main AoC conversion process.
5+
"""
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_py_modules(
2+
__init__.py
3+
civ.py
4+
connection.py
5+
effect_bundle.py
6+
graphics.py
7+
sound.py
8+
tech.py
9+
terrain.py
10+
unit.py
11+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Extract AoC data from the game dataset and prepares it for conversion.
5+
"""
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Extract civs from the AoC data.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_civ import GenieCivilizationObject
10+
11+
if typing.TYPE_CHECKING:
12+
from ......value_object.read.value_members import ArrayMember
13+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
14+
15+
16+
def extract_genie_civs(
17+
gamespec: ArrayMember,
18+
full_data_set: GenieObjectContainer
19+
) -> None:
20+
"""
21+
Extract civs from the game data.
22+
23+
:param gamespec: Gamedata from empires.dat file.
24+
:type gamespec: class: ...dataformat.value_members.ArrayMember
25+
"""
26+
raw_civs = gamespec[0]["civs"].value
27+
28+
index = 0
29+
for raw_civ in raw_civs:
30+
civ_id = index
31+
32+
civ_members = raw_civ.value
33+
units_member = civ_members.pop("units")
34+
units_member = units_member.get_container("id0")
35+
36+
civ_members.update({"units": units_member})
37+
38+
civ = GenieCivilizationObject(civ_id, full_data_set, members=civ_members)
39+
full_data_set.genie_civs.update({civ.get_id(): civ})
40+
41+
index += 1
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Extract connection objects from the AoC data.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_connection import GenieAgeConnection, \
10+
GenieBuildingConnection, GenieUnitConnection, GenieTechConnection
11+
12+
if typing.TYPE_CHECKING:
13+
from ......value_object.read.value_members import ArrayMember
14+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
15+
16+
17+
def extract_age_connections(gamespec: ArrayMember, full_data_set: GenieObjectContainer) -> None:
18+
"""
19+
Extract age connections from the game data.
20+
21+
:param gamespec: Gamedata from empires.dat file.
22+
:type gamespec: class: ...dataformat.value_members.ArrayMember
23+
"""
24+
raw_connections = gamespec[0]["age_connections"].value
25+
26+
for raw_connection in raw_connections:
27+
age_id = raw_connection["id"].value
28+
connection_members = raw_connection.value
29+
30+
connection = GenieAgeConnection(age_id, full_data_set, members=connection_members)
31+
full_data_set.age_connections.update({connection.get_id(): connection})
32+
33+
34+
@staticmethod
35+
def extract_building_connections(
36+
gamespec: ArrayMember,
37+
full_data_set: GenieObjectContainer
38+
) -> None:
39+
"""
40+
Extract building connections from the game data.
41+
42+
:param gamespec: Gamedata from empires.dat file.
43+
:type gamespec: class: ...dataformat.value_members.ArrayMember
44+
"""
45+
raw_connections = gamespec[0]["building_connections"].value
46+
47+
for raw_connection in raw_connections:
48+
building_id = raw_connection["id"].value
49+
connection_members = raw_connection.value
50+
51+
connection = GenieBuildingConnection(building_id, full_data_set,
52+
members=connection_members)
53+
full_data_set.building_connections.update({connection.get_id(): connection})
54+
55+
56+
@staticmethod
57+
def extract_unit_connections(
58+
gamespec: ArrayMember,
59+
full_data_set: GenieObjectContainer
60+
) -> None:
61+
"""
62+
Extract unit connections from the game data.
63+
64+
:param gamespec: Gamedata from empires.dat file.
65+
:type gamespec: class: ...dataformat.value_members.ArrayMember
66+
"""
67+
raw_connections = gamespec[0]["unit_connections"].value
68+
69+
for raw_connection in raw_connections:
70+
unit_id = raw_connection["id"].value
71+
connection_members = raw_connection.value
72+
73+
connection = GenieUnitConnection(unit_id, full_data_set, members=connection_members)
74+
full_data_set.unit_connections.update({connection.get_id(): connection})
75+
76+
77+
@staticmethod
78+
def extract_tech_connections(
79+
gamespec: ArrayMember,
80+
full_data_set: GenieObjectContainer
81+
) -> None:
82+
"""
83+
Extract tech connections from the game data.
84+
85+
:param gamespec: Gamedata from empires.dat file.
86+
:type gamespec: class: ...dataformat.value_members.ArrayMember
87+
"""
88+
raw_connections = gamespec[0]["tech_connections"].value
89+
90+
for raw_connection in raw_connections:
91+
tech_id = raw_connection["id"].value
92+
connection_members = raw_connection.value
93+
94+
connection = GenieTechConnection(tech_id, full_data_set, members=connection_members)
95+
full_data_set.tech_connections.update({connection.get_id(): connection})
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Extract effect objects from the AoC data.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_effect import GenieEffectObject, GenieEffectBundle
10+
11+
if typing.TYPE_CHECKING:
12+
from ......value_object.read.value_members import ArrayMember
13+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
14+
15+
16+
def extract_genie_effect_bundles(
17+
gamespec: ArrayMember,
18+
full_data_set: GenieObjectContainer
19+
) -> None:
20+
"""
21+
Extract effects and effect bundles from the game data.
22+
23+
:param gamespec: Gamedata from empires.dat file.
24+
:type gamespec: ...dataformat.value_members.ArrayMember
25+
"""
26+
raw_effect_bundles = gamespec[0]["effect_bundles"].value
27+
28+
index_bundle = 0
29+
for raw_effect_bundle in raw_effect_bundles:
30+
bundle_id = index_bundle
31+
32+
# call hierarchy: effect_bundle->effects
33+
raw_effects = raw_effect_bundle["effects"].value
34+
35+
effects = {}
36+
37+
index_effect = 0
38+
for raw_effect in raw_effects:
39+
effect_id = index_effect
40+
effect_members = raw_effect.value
41+
42+
effect = GenieEffectObject(effect_id, bundle_id, full_data_set,
43+
members=effect_members)
44+
45+
effects.update({effect_id: effect})
46+
47+
index_effect += 1
48+
49+
# Pass everything to the bundle
50+
effect_bundle_members = raw_effect_bundle.value
51+
# Remove effects we store them as separate objects
52+
effect_bundle_members.pop("effects")
53+
54+
bundle = GenieEffectBundle(bundle_id, effects, full_data_set,
55+
members=effect_bundle_members)
56+
full_data_set.genie_effect_bundles.update({bundle.get_id(): bundle})
57+
58+
index_bundle += 1
59+
60+
61+
def sanitize_effect_bundles(full_data_set: GenieObjectContainer) -> None:
62+
"""
63+
Remove garbage data from effect bundles.
64+
65+
:param full_data_set: GenieObjectContainer instance that
66+
contains all relevant data for the conversion
67+
process.
68+
:type full_data_set: class: ...dataformat.aoc.genie_object_container.GenieObjectContainer
69+
"""
70+
effect_bundles = full_data_set.genie_effect_bundles
71+
72+
for bundle in effect_bundles.values():
73+
sanitized_effects = {}
74+
75+
effects = bundle.get_effects()
76+
77+
index = 0
78+
for effect in effects:
79+
effect_type = effect["type_id"].value
80+
if effect_type < 0:
81+
# Effect has no type
82+
continue
83+
84+
if effect_type == 3:
85+
if effect["attr_b"].value < 0:
86+
# Upgrade to invalid unit
87+
continue
88+
89+
if effect_type == 102:
90+
if effect["attr_d"].value < 0:
91+
# Tech disable effect with no tech id specified
92+
continue
93+
94+
sanitized_effects.update({index: effect})
95+
index += 1
96+
97+
bundle.effects = sanitized_effects
98+
bundle.sanitized = True
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Extract graphics from the AoC data.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_graphic import GenieGraphic
10+
11+
if typing.TYPE_CHECKING:
12+
from ......value_object.read.value_members import ArrayMember
13+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
14+
15+
16+
def extract_genie_graphics(gamespec: ArrayMember, full_data_set: GenieObjectContainer) -> None:
17+
"""
18+
Extract graphic definitions from the game data.
19+
20+
:param gamespec: Gamedata from empires.dat file.
21+
:type gamespec: class: ...dataformat.value_members.ArrayMember
22+
"""
23+
raw_graphics = gamespec[0]["graphics"].value
24+
25+
for raw_graphic in raw_graphics:
26+
# Can be ignored if there is no filename associated
27+
filename = raw_graphic["filename"].value
28+
if not filename:
29+
continue
30+
31+
graphic_id = raw_graphic["graphic_id"].value
32+
graphic_members = raw_graphic.value
33+
34+
graphic = GenieGraphic(graphic_id, full_data_set, members=graphic_members)
35+
slp_id = raw_graphic["slp_id"].value
36+
if str(slp_id) not in full_data_set.existing_graphics:
37+
graphic.exists = False
38+
39+
full_data_set.genie_graphics.update({graphic.get_id(): graphic})
40+
41+
# Detect subgraphics
42+
for genie_graphic in full_data_set.genie_graphics.values():
43+
genie_graphic.detect_subgraphics()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright 2025-2025 the openage authors. See copying.md for legal info.
2+
3+
"""
4+
Extract sounds from the AoC data.
5+
"""
6+
from __future__ import annotations
7+
import typing
8+
9+
from ......entity_object.conversion.aoc.genie_sound import GenieSound
10+
11+
if typing.TYPE_CHECKING:
12+
from ......value_object.read.value_members import ArrayMember
13+
from ......entity_object.conversion.aoc.genie_object_container import GenieObjectContainer
14+
15+
16+
def extract_genie_sounds(gamespec: ArrayMember, full_data_set: GenieObjectContainer) -> None:
17+
"""
18+
Extract sound definitions from the game data.
19+
20+
:param gamespec: Gamedata from empires.dat file.
21+
:type gamespec: class: ...dataformat.value_members.ArrayMember
22+
"""
23+
raw_sounds = gamespec[0]["sounds"].value
24+
25+
for raw_sound in raw_sounds:
26+
sound_id = raw_sound["sound_id"].value
27+
sound_members = raw_sound.value
28+
29+
sound = GenieSound(sound_id, full_data_set, members=sound_members)
30+
full_data_set.genie_sounds.update({sound.get_id(): sound})

0 commit comments

Comments
 (0)