mapDeserializer.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import base64
  2. import struct
  3. from typing import Dict
  4. class Tile:
  5. def __init__(self, type_id: int, flags: int = 0, variant: int = 0):
  6. self.type_id = type_id
  7. self.flags = flags
  8. self.variant = variant
  9. def __repr__(self):
  10. return f"Tile {self.type_id}, {self.flags}, {self.variant}"
  11. def __eq__(self, other):
  12. return (
  13. self.type_id == other.type_id
  14. and self.flags == other.flags
  15. and self.variant == other.variant
  16. )
  17. class MapChunk:
  18. def __init__(self, x: int, y: int, chunk_size: int):
  19. self.x = x
  20. self.y = y
  21. self.chunk_size = chunk_size
  22. self.tiles = [[Tile(0) for _ in range(chunk_size)] for _ in range(chunk_size)]
  23. def __repr__(self):
  24. return f"MapChunk ({self.x}, {self.y}) - Size {self.chunk_size}"
  25. def set_tile(self, x: int, y: int, tile: Tile):
  26. self.tiles[y][x] = tile
  27. def get_tile(self, x: int, y: int) -> Tile:
  28. return self.tiles[y][x]
  29. def deserialize_map_chunk(
  30. node: Dict[str, any], tile_map: Dict[int, str], chunk_size: int = 16
  31. ) -> MapChunk:
  32. ind = tuple(map(int, node["ind"].split(",")))
  33. chunk = MapChunk(ind[0], ind[1], chunk_size)
  34. tile_bytes = base64.b64decode(node["tiles"])
  35. version = node.get("version", 1)
  36. idx = 0
  37. for y in range(chunk_size):
  38. for x in range(chunk_size):
  39. if version < 6:
  40. tile_id = struct.unpack_from("<H", tile_bytes, idx)[0] # 2 bytes
  41. idx += 2
  42. else:
  43. tile_id = struct.unpack_from("<I", tile_bytes, idx)[0] # 4 bytes
  44. idx += 4
  45. flags = struct.unpack_from("<B", tile_bytes, idx)[0] # 1 byte
  46. idx += 1
  47. variant = struct.unpack_from("<B", tile_bytes, idx)[0] # 1 byte
  48. idx += 1
  49. # Validação com tile_map
  50. if tile_id not in tile_map:
  51. raise ValueError(f"tile_id {tile_id} not found in tile_map.")
  52. tile = Tile(tile_id, flags, variant)
  53. chunk.set_tile(x, y, tile)
  54. return chunk
  55. def serialize_map_chunk(chunk: MapChunk, version: int = 6) -> Dict[str, any]:
  56. root = {
  57. "ind": f"{chunk.x},{chunk.y}",
  58. "version": version,
  59. "tiles": encode_tiles(chunk),
  60. }
  61. return root
  62. def encode_tiles(chunk: MapChunk) -> str:
  63. tile_bytes = bytearray()
  64. for y in range(chunk.chunk_size):
  65. for x in range(chunk.chunk_size):
  66. tile = chunk.get_tile(x, y)
  67. tile_bytes.extend(struct.pack("<I", tile.type_id)) # 4 bytes para type_id
  68. tile_bytes.append(tile.flags) # 1 byte para flags
  69. tile_bytes.append(tile.variant) # 1 byte para variant
  70. return base64.b64encode(tile_bytes).decode("utf-8")
  71. # Dados de exemplo
  72. tile_map = {1: "Space", 2: "FloorGrass", 0: "FloorDirt", 3: "FloorGrassDark"}
  73. chunk_data = {
  74. "ind": "-1,0",
  75. "tiles": "AQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAA",
  76. "version": 6,
  77. }
  78. # Teste
  79. chunk = deserialize_map_chunk(chunk_data, tile_map)
  80. print(chunk)
  81. serialized_chunk = serialize_map_chunk(chunk)
  82. print(
  83. "Original tiles == Serializado tiles:",
  84. serialized_chunk["tiles"] == chunk_data["tiles"],
  85. )
  86. # Para inspecionar alguns tiles
  87. for y in range(5):
  88. for x in range(5):
  89. tile = chunk.get_tile(x, y)
  90. print(f"Tile em ({x}, {y}): {tile}")