mirror of
https://github.com/Steffo99/lihzahrd.git
synced 2024-11-24 09:04:22 +00:00
Use a tilematrix instead of a list of lists
This commit is contained in:
parent
317d5d5190
commit
86ebd39c4e
6 changed files with 78 additions and 12 deletions
2
lihzahrd/errors.py
Normal file
2
lihzahrd/errors.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class InvalidFooterError(Exception):
|
||||||
|
"""This exception is raised if the footer contents do not match the expected data."""
|
|
@ -9,6 +9,7 @@ from .block import Block
|
||||||
from .wall import Wall
|
from .wall import Wall
|
||||||
from .liquid import Liquid
|
from .liquid import Liquid
|
||||||
from .tile import Tile
|
from .tile import Tile
|
||||||
|
from .tilematrix import TileMatrix
|
||||||
|
|
||||||
__all__ = ["LiquidType", "RLEEncoding", "Shape", "Wiring", "BlockType", "FrameImportantData", "WallType", "Block",
|
__all__ = ["LiquidType", "RLEEncoding", "Shape", "Wiring", "BlockType", "FrameImportantData", "WallType", "Block",
|
||||||
"Wall", "Liquid", "Tile"]
|
"Wall", "Liquid", "Tile", "TileMatrix"]
|
||||||
|
|
61
lihzahrd/tiles/tilematrix.py
Normal file
61
lihzahrd/tiles/tilematrix.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import typing
|
||||||
|
from .tile import Tile
|
||||||
|
from ..fileutils import FileReader, Coordinates
|
||||||
|
|
||||||
|
|
||||||
|
class TileMatrix:
|
||||||
|
"""A huge matrix containing the tiles of a whole world."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._tiles: typing.List[typing.List[Tile]] = []
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if len(self._tiles) > 0:
|
||||||
|
return f"<TileMatrix {len(self._tiles)}x{len(self._tiles[0])}>"
|
||||||
|
return f"<TileMatrix 0x0>"
|
||||||
|
|
||||||
|
def __getitem__(self, item: typing.Union[typing.Tuple, Coordinates]):
|
||||||
|
"""Get a tile at specific coordinates.
|
||||||
|
|
||||||
|
(x=0, y=0) returns the top-left tile in the map.
|
||||||
|
|
||||||
|
You can specify a negative coordinate to count tiles respectively from the right or from the bottom:
|
||||||
|
(x=-1, y=-1) returns the bottom-right tile in the map."""
|
||||||
|
if isinstance(item, Coordinates):
|
||||||
|
return self._tiles[item.x][item.y]
|
||||||
|
elif isinstance(item, tuple):
|
||||||
|
return self._tiles[item[0]][item[1]]
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Unsupported type: {item.__class__.__name__}")
|
||||||
|
|
||||||
|
def __setitem__(self, key: typing.Union[typing.Tuple, Coordinates], value: Tile):
|
||||||
|
"""Change a tile at specific coordinates.
|
||||||
|
|
||||||
|
The same properties that apply to __getitem__ are valid for __setitem__."""
|
||||||
|
if not isinstance(value, Tile):
|
||||||
|
raise TypeError(f"Invalid type: {value.__class__.__name__} instead of Tile")
|
||||||
|
if isinstance(key, Coordinates):
|
||||||
|
self._tiles[key.x][key.y] = value
|
||||||
|
elif isinstance(key, tuple):
|
||||||
|
self._tiles[key[0]][key[1]] = value
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Invalid type: {key.__class__.__name__} instead of tuple or Coordinates")
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
"""Return the amount of tiles present in the matrix."""
|
||||||
|
if len(self._tiles) > 0:
|
||||||
|
return len(self._tiles) * len(self._tiles[0])
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def add_column(self, column: typing.List[Tile]):
|
||||||
|
"""Add a new column to the matrix."""
|
||||||
|
if len(self._tiles) > 0 and len(column) != len(self._tiles[0]):
|
||||||
|
raise ValueError("column has a different length than the others in the matrix")
|
||||||
|
self._tiles.append(column)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self) -> Coordinates:
|
||||||
|
"""Return the size of the matrix as a pair of coordinates."""
|
||||||
|
if len(self._tiles) > 0:
|
||||||
|
return Coordinates(len(self._tiles), len(self._tiles[0]))
|
||||||
|
return Coordinates(0, 0)
|
|
@ -37,4 +37,4 @@ class Wiring:
|
||||||
if flags3 is not None:
|
if flags3 is not None:
|
||||||
return cls(red=flags2[1], green=flags2[2], blue=flags2[3], yellow=flags3[5], actuator=flags3[1])
|
return cls(red=flags2[1], green=flags2[2], blue=flags2[3], yellow=flags3[5], actuator=flags3[1])
|
||||||
return cls(red=flags2[1], green=flags2[2], blue=flags2[3])
|
return cls(red=flags2[1], green=flags2[2], blue=flags2[3])
|
||||||
return None
|
return cls()
|
||||||
|
|
|
@ -3,7 +3,8 @@ import typing
|
||||||
|
|
||||||
|
|
||||||
class Timer:
|
class Timer:
|
||||||
def __init__(self, name: str, display: bool = False):
|
"""An object to track and print the time required to perform a section of code."""
|
||||||
|
def __init__(self, name: str, display: bool = True):
|
||||||
self.name: str = name
|
self.name: str = name
|
||||||
self.display: bool = display
|
self.display: bool = display
|
||||||
self._start_time: typing.Optional[float] = None
|
self._start_time: typing.Optional[float] = None
|
||||||
|
|
|
@ -11,6 +11,7 @@ from .tileentities import *
|
||||||
from .pressureplates import *
|
from .pressureplates import *
|
||||||
from .townmanager import *
|
from .townmanager import *
|
||||||
from .timer import Timer
|
from .timer import Timer
|
||||||
|
from .errors import InvalidFooterError
|
||||||
|
|
||||||
|
|
||||||
class World:
|
class World:
|
||||||
|
@ -46,7 +47,7 @@ class World:
|
||||||
anglers_quest: AnglerQuest,
|
anglers_quest: AnglerQuest,
|
||||||
clouds: Clouds,
|
clouds: Clouds,
|
||||||
cultist_delay: int,
|
cultist_delay: int,
|
||||||
tiles: typing.List[typing.List[Tile]],
|
tiles: TileMatrix,
|
||||||
chests: typing.List[Chest],
|
chests: typing.List[Chest],
|
||||||
signs: typing.List[Sign],
|
signs: typing.List[Sign],
|
||||||
npcs: typing.List[NPC],
|
npcs: typing.List[NPC],
|
||||||
|
@ -145,7 +146,7 @@ class World:
|
||||||
self.anglers_quest: AnglerQuest = anglers_quest
|
self.anglers_quest: AnglerQuest = anglers_quest
|
||||||
"""Information about today's Angler's Quest."""
|
"""Information about today's Angler's Quest."""
|
||||||
|
|
||||||
self.tiles: typing.List[typing.List[Tile]] = tiles
|
self.tiles: TileMatrix = tiles
|
||||||
"""A matrix of all the tiles present in the world."""
|
"""A matrix of all the tiles present in the world."""
|
||||||
|
|
||||||
self.chests: typing.List[Chest] = chests
|
self.chests: typing.List[Chest] = chests
|
||||||
|
@ -515,13 +516,13 @@ class World:
|
||||||
unknown_world_header_data = f.read_until(pointers.world_tiles)
|
unknown_world_header_data = f.read_until(pointers.world_tiles)
|
||||||
|
|
||||||
with Timer("World Tiles", display=True):
|
with Timer("World Tiles", display=True):
|
||||||
tiles = []
|
tm = TileMatrix()
|
||||||
while len(tiles) < world_size.x:
|
while tm.size.x < world_size.x:
|
||||||
column = []
|
column = []
|
||||||
while len(column) < world_size.y:
|
while len(column) < world_size.y:
|
||||||
readtiles = cls._read_tile_block(f, tileframeimportant)
|
readtiles = cls._read_tile_block(f, tileframeimportant)
|
||||||
column = [*column, *readtiles]
|
column = [*column, *readtiles]
|
||||||
tiles.append(column)
|
tm.add_column(column)
|
||||||
|
|
||||||
unknown_world_tiles_data = f.read_until(pointers.chests)
|
unknown_world_tiles_data = f.read_until(pointers.chests)
|
||||||
|
|
||||||
|
@ -642,7 +643,7 @@ class World:
|
||||||
time=time, events=events, dungeon_point=dungeon_point, world_evil=world_evil,
|
time=time, events=events, dungeon_point=dungeon_point, world_evil=world_evil,
|
||||||
saved_npcs=saved_npcs, altars_smashed=altars_smashed, is_hardmode=is_hardmode,
|
saved_npcs=saved_npcs, altars_smashed=altars_smashed, is_hardmode=is_hardmode,
|
||||||
shadow_orbs=shadow_orbs, bosses_defeated=bosses_defeated, anglers_quest=anglers_quest,
|
shadow_orbs=shadow_orbs, bosses_defeated=bosses_defeated, anglers_quest=anglers_quest,
|
||||||
clouds=clouds, cultist_delay=cultist_delay, tiles=tiles, chests=chests, signs=signs,
|
clouds=clouds, cultist_delay=cultist_delay, tiles=tm, chests=chests, signs=signs,
|
||||||
npcs=npcs, mobs=mobs, tile_entities=tile_entities,
|
npcs=npcs, mobs=mobs, tile_entities=tile_entities,
|
||||||
weighed_pressure_plates=weighed_pressure_plates, rooms=rooms,
|
weighed_pressure_plates=weighed_pressure_plates, rooms=rooms,
|
||||||
unknown_file_format_data=unknown_file_format_data,
|
unknown_file_format_data=unknown_file_format_data,
|
||||||
|
@ -657,10 +658,10 @@ class World:
|
||||||
|
|
||||||
with Timer("Footer", display=True):
|
with Timer("Footer", display=True):
|
||||||
if not f.bool():
|
if not f.bool():
|
||||||
raise Exception("Invalid footer")
|
raise InvalidFooterError("Invalid footer")
|
||||||
if not f.string() == world.name:
|
if not f.string() == world.name:
|
||||||
raise Exception("Invalid footer")
|
raise InvalidFooterError("Invalid footer")
|
||||||
if not f.int4() == world.id:
|
if not f.int4() == world.id:
|
||||||
raise Exception("Invalid footer")
|
raise InvalidFooterError("Invalid footer")
|
||||||
|
|
||||||
return world
|
return world
|
||||||
|
|
Loading…
Reference in a new issue