Skip to content

Commit

Permalink
Replace fixed-length lists with tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
HSZemi committed Jan 20, 2024
1 parent 8eef1da commit d5ea266
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 52 deletions.
119 changes: 113 additions & 6 deletions src/genieutils/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from abc import ABC
from enum import IntEnum
from typing import TypeVar
from typing import TypeVar, Sequence

from genieutils.datatypes import Int, Float, String

Expand Down Expand Up @@ -45,25 +45,25 @@ def write_string(self, length: int, value: str) -> bytes:
def write_int_8(self, value: int) -> bytes:
return Int.to_bytes(value, length=1, signed=False)

def write_int_8_array(self, value: list[int]) -> bytes:
def write_int_8_array(self, value: Sequence[int]) -> bytes:
return b''.join(self.write_int_8(v) for v in value)

def write_int_16(self, value: int, signed=True) -> bytes:
return Int.to_bytes(value, length=2, signed=signed)

def write_int_16_array(self, value: list[int]) -> bytes:
def write_int_16_array(self, value: Sequence[int]) -> bytes:
return b''.join(self.write_int_16(v) for v in value)

def write_int_32(self, value: int, signed=True) -> bytes:
return Int.to_bytes(value, length=4, signed=signed)

def write_int_32_array(self, value: list[int]) -> bytes:
def write_int_32_array(self, value: Sequence[int]) -> bytes:
return b''.join(self.write_int_32(v) for v in value)

def write_float(self, value: float) -> bytes:
return Float.to_bytes(value)

def write_float_array(self, value: list[float]) -> bytes:
def write_float_array(self, value: Sequence[float]) -> bytes:
return b''.join(self.write_float(v) for v in value)

def write_class(self, value: 'GenieClass') -> bytes:
Expand All @@ -72,7 +72,7 @@ def write_class(self, value: 'GenieClass') -> bytes:
return retval
return b''

def write_class_array(self, value: list['GenieClass']) -> bytes:
def write_class_array(self, value: Sequence['GenieClass']) -> bytes:
retval = b''.join(self.write_class(v) for v in value)
if retval:
return retval
Expand Down Expand Up @@ -117,6 +117,48 @@ def read_int_8_array(self, size: int) -> list[int]:
elements.append(self.read_int_8())
return elements

def read_int_8_array_2(self) -> tuple[int, int]:
element_0 = self.read_int_8()
element_1 = self.read_int_8()
return element_0, element_1

def read_int_8_array_3(self) -> tuple[int, int, int]:
element_0 = self.read_int_8()
element_1 = self.read_int_8()
element_2 = self.read_int_8()
return element_0, element_1, element_2

def read_int_8_array_5(self) -> tuple[int, int, int, int, int]:
element_0 = self.read_int_8()
element_1 = self.read_int_8()
element_2 = self.read_int_8()
element_3 = self.read_int_8()
element_4 = self.read_int_8()
return element_0, element_1, element_2, element_3, element_4

def read_int_8_array_6(self) -> tuple[int, int, int, int, int, int]:
element_0 = self.read_int_8()
element_1 = self.read_int_8()
element_2 = self.read_int_8()
element_3 = self.read_int_8()
element_4 = self.read_int_8()
element_5 = self.read_int_8()
return element_0, element_1, element_2, element_3, element_4, element_5

def read_int_8_array_10(self) -> tuple[int, int, int, int, int, int, int, int, int, int]:
element_0 = self.read_int_8()
element_1 = self.read_int_8()
element_2 = self.read_int_8()
element_3 = self.read_int_8()
element_4 = self.read_int_8()
element_5 = self.read_int_8()
element_6 = self.read_int_8()
element_7 = self.read_int_8()
element_8 = self.read_int_8()
element_9 = self.read_int_8()
return (element_0, element_1, element_2, element_3, element_4, element_5, element_6, element_7, element_8,
element_9)

def read_int_16(self, signed=True) -> int:
return Int.from_bytes(self.consume_range(2), signed=signed)

Expand All @@ -126,6 +168,33 @@ def read_int_16_array(self, size: int) -> list[int]:
elements.append(self.read_int_16())
return elements

def read_int_16_array_2(self) -> tuple[int, int]:
element_0 = self.read_int_16()
element_1 = self.read_int_16()
return element_0, element_1

def read_int_16_array_3(self) -> tuple[int, int, int]:
element_0 = self.read_int_16()
element_1 = self.read_int_16()
element_2 = self.read_int_16()
return element_0, element_1, element_2

def read_int_16_array_4(self) -> tuple[int, int, int, int]:
element_0 = self.read_int_16()
element_1 = self.read_int_16()
element_2 = self.read_int_16()
element_3 = self.read_int_16()
return element_0, element_1, element_2, element_3

def read_int_16_array_6(self) -> tuple[int, int, int, int, int, int]:
element_0 = self.read_int_16()
element_1 = self.read_int_16()
element_2 = self.read_int_16()
element_3 = self.read_int_16()
element_4 = self.read_int_16()
element_5 = self.read_int_16()
return element_0, element_1, element_2, element_3, element_4, element_5

def read_int_32(self, signed=True) -> int:
return Int.from_bytes(self.consume_range(4), signed=signed)

Expand All @@ -135,6 +204,20 @@ def read_int_32_array(self, size: int) -> list[int]:
elements.append(self.read_int_32())
return elements

def read_int_32_array_10(self) -> tuple[int, int, int, int, int, int, int, int, int, int]:
element_0 = self.read_int_32()
element_1 = self.read_int_32()
element_2 = self.read_int_32()
element_3 = self.read_int_32()
element_4 = self.read_int_32()
element_5 = self.read_int_32()
element_6 = self.read_int_32()
element_7 = self.read_int_32()
element_8 = self.read_int_32()
element_9 = self.read_int_32()
return (element_0, element_1, element_2, element_3, element_4, element_5, element_6, element_7, element_8,
element_9)

def read_float(self) -> float:
return Float.from_bytes(self.consume_range(4))

Expand All @@ -144,6 +227,17 @@ def read_float_array(self, size: int) -> list[float]:
elements.append(self.read_float())
return elements

def read_float_array_2(self) -> tuple[float, float]:
element_0 = self.read_float()
element_1 = self.read_float()
return element_0, element_1

def read_float_array_3(self) -> tuple[float, float, float]:
element_0 = self.read_float()
element_1 = self.read_float()
element_2 = self.read_float()
return element_0, element_1, element_2

def read_class(self, class_: type[C]) -> C:
element = class_.from_bytes(self)
return element
Expand All @@ -155,6 +249,19 @@ def read_class_array(self, class_: type[C], size: int) -> list[C]:
elements.append(element)
return elements

def read_class_array_3(self, class_: type[C]) -> tuple[C, C, C]:
element_0 = class_.from_bytes(self)
element_1 = class_.from_bytes(self)
element_2 = class_.from_bytes(self)
return element_0, element_1, element_2

def read_class_array_4(self, class_: type[C]) -> tuple[C, C, C, C]:
element_0 = class_.from_bytes(self)
element_1 = class_.from_bytes(self)
element_2 = class_.from_bytes(self)
element_3 = class_.from_bytes(self)
return element_0, element_1, element_2, element_3

def read_class_array_with_pointers(self, class_: type[C], size: int, pointers: list[int]) -> list[C | None]:
elements = []
for i in range(size):
Expand Down
4 changes: 2 additions & 2 deletions src/genieutils/graphic.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Graphic(GenieClass):
layer: int
player_color: int
transparent_selection: int
coordinates: list[int]
coordinates: tuple[int, int, int, int]
delta_count: int
sound_id: int
wwise_sound_id: int
Expand Down Expand Up @@ -116,7 +116,7 @@ def from_bytes(cls, content: ByteHandler) -> 'Graphic':
layer = content.read_int_8()
player_color = content.read_int_16()
transparent_selection = content.read_int_8()
coordinates = content.read_int_16_array(4)
coordinates = content.read_int_16_array_4()
delta_count = content.read_int_16()
sound_id = content.read_int_16()
wwise_sound_id = content.read_int_32()
Expand Down
8 changes: 4 additions & 4 deletions src/genieutils/tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def to_bytes(self) -> bytes:

@dataclass
class Tech(GenieClass):
required_techs: list[int]
resource_costs: list[ResearchResourceCost]
required_techs: tuple[int, int, int, int, int, int]
resource_costs: tuple[ResearchResourceCost, ResearchResourceCost, ResearchResourceCost]
required_tech_count: int
civ: int
full_tech_mode: int
Expand All @@ -49,8 +49,8 @@ class Tech(GenieClass):
@classmethod
def from_bytes(cls, content: ByteHandler) -> 'Tech':
return cls(
required_techs=content.read_int_16_array(6),
resource_costs=content.read_class_array(ResearchResourceCost, 3),
required_techs=content.read_int_16_array_6(),
resource_costs=content.read_class_array_3(ResearchResourceCost),
required_tech_count=content.read_int_16(),
civ=content.read_int_16(),
full_tech_mode=content.read_int_16(),
Expand Down
24 changes: 12 additions & 12 deletions src/genieutils/techtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
@dataclass
class Common(GenieClass):
slots_used: int
unit_research: list[int]
mode: list[int]
unit_research: tuple[int, int, int, int, int, int, int, int, int, int]
mode: tuple[int, int, int, int, int, int, int, int, int, int]

@classmethod
def from_bytes(cls, content: ByteHandler) -> 'Common':
return cls(
slots_used=content.read_int_32(),
unit_research=content.read_int_32_array(10),
mode=content.read_int_32_array(10),
unit_research=content.read_int_32_array_10(),
mode=content.read_int_32_array_10(),
)

def to_bytes(self) -> bytes:
Expand All @@ -37,8 +37,8 @@ class TechTreeAge(GenieClass):
techs: list[int]
common: Common
num_building_levels: int
buildings_per_zone: list[int]
group_length_per_zone: list[int]
buildings_per_zone: tuple[int, int, int, int, int, int, int, int, int, int]
group_length_per_zone: tuple[int, int, int, int, int, int, int, int, int, int]
max_age_length: int
line_mode: int

Expand All @@ -54,8 +54,8 @@ def from_bytes(cls, content: ByteHandler) -> 'TechTreeAge':
techs = content.read_int_32_array(techs_count)
common = content.read_class(Common)
num_building_levels = content.read_int_8()
buildings_per_zone = content.read_int_8_array(10)
group_length_per_zone = content.read_int_8_array(10)
buildings_per_zone = content.read_int_8_array_10()
group_length_per_zone = content.read_int_8_array_10()
max_age_length = content.read_int_8()
line_mode = content.read_int_32()
return cls(
Expand Down Expand Up @@ -106,8 +106,8 @@ class BuildingConnection(GenieClass):
techs: list[int]
common: Common
location_in_age: int
units_techs_total: list[int]
units_techs_first: list[int]
units_techs_total: tuple[int, int, int, int, int]
units_techs_first: tuple[int, int, int, int, int]
line_mode: int
enabling_research: int

Expand All @@ -123,8 +123,8 @@ def from_bytes(cls, content: ByteHandler) -> 'BuildingConnection':
techs = content.read_int_32_array(techs_count)
common = content.read_class(Common)
location_in_age = content.read_int_8()
units_techs_total = content.read_int_8_array(5)
units_techs_first = content.read_int_8_array(5)
units_techs_total = content.read_int_8_array_5()
units_techs_first = content.read_int_8_array_5()
line_mode = content.read_int_32()
enabling_research = content.read_int_32()
return cls(
Expand Down
12 changes: 6 additions & 6 deletions src/genieutils/terrainblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class Terrain(GenieClass):
blend_priority: int
blend_type: int
overlay_mask_name: str
colors: list[int]
cliff_colors: list[int]
colors: tuple[int, int, int]
cliff_colors: tuple[int, int]
passable_terrain: int
impassable_terrain: int
is_animated: int
Expand All @@ -58,7 +58,7 @@ class Terrain(GenieClass):
drawn: int
frame_data: list[FrameData]
terrain_to_draw: int
terrain_dimensions: list[int]
terrain_dimensions: tuple[int, int]
terrain_unit_masked_density: list[int]
terrain_unit_id: list[int]
terrain_unit_density: list[int]
Expand All @@ -84,8 +84,8 @@ def from_bytes(cls, content: ByteHandler) -> 'Terrain':
blend_priority=content.read_int_32(),
blend_type=content.read_int_32(),
overlay_mask_name=content.read_debug_string(),
colors=content.read_int_8_array(3),
cliff_colors=content.read_int_8_array(2),
colors=content.read_int_8_array_3(),
cliff_colors=content.read_int_8_array_2(),
passable_terrain=content.read_int_8(),
impassable_terrain=content.read_int_8(),
is_animated=content.read_int_8(),
Expand All @@ -100,7 +100,7 @@ def from_bytes(cls, content: ByteHandler) -> 'Terrain':
drawn=content.read_int_8(),
frame_data=content.read_class_array(FrameData, TILE_TYPE_COUNT),
terrain_to_draw=content.read_int_16(),
terrain_dimensions=content.read_int_16_array(2),
terrain_dimensions=content.read_int_16_array_2(),
terrain_unit_masked_density=content.read_int_16_array(TERRAIN_UNITS_SIZE),
terrain_unit_id=content.read_int_16_array(TERRAIN_UNITS_SIZE),
terrain_unit_density=content.read_int_16_array(TERRAIN_UNITS_SIZE),
Expand Down
Loading

0 comments on commit d5ea266

Please sign in to comment.