Moved a bit more code out of mapcompile
This commit is contained in:
155
tools/mapcompile/mapParser.py
Normal file
155
tools/mapcompile/mapParser.py
Normal file
@ -0,0 +1,155 @@
|
||||
import sys
|
||||
from constants import TILE_WIDTH_HEIGHT, CHUNK_WIDTH, CHUNK_HEIGHT
|
||||
import math
|
||||
|
||||
def parseMap(data):
|
||||
mapData = {
|
||||
'layers': data['layers'],
|
||||
'playerSpawnX': 0,
|
||||
'playerSpawnY': 0,
|
||||
}
|
||||
|
||||
# Object layer
|
||||
for layer in mapData['layers']:
|
||||
if layer.get('type') == 'objectgroup':
|
||||
mapData['objectLayer'] = layer
|
||||
break
|
||||
|
||||
if mapData['objectLayer'] is None:
|
||||
print(f"Error: Data does not contain an object layer.")
|
||||
sys.exit(1)
|
||||
|
||||
if 'objects' not in mapData['objectLayer'] or not isinstance(mapData['objectLayer']['objects'], list):
|
||||
print(f"Error: Object layer does not contain 'objects' key or it is not a list.")
|
||||
sys.exit(1)
|
||||
|
||||
# Tile Layers
|
||||
mapData['tileLayers'] = []
|
||||
for layer in mapData['layers']:
|
||||
if layer.get('type') == 'tilelayer':
|
||||
mapData['tileLayers'].append(layer)
|
||||
|
||||
if len(mapData['tileLayers']) == 0:
|
||||
print(f"Error: Data does not contain any tile layers.")
|
||||
sys.exit(1)
|
||||
|
||||
# First layer
|
||||
mapData['firstLayer'] = mapData['tileLayers'][0]
|
||||
if 'width' not in mapData['firstLayer'] or 'height' not in mapData['firstLayer']:
|
||||
print(f"Error: First layer does not contain 'width' or 'height' key.")
|
||||
sys.exit(1)
|
||||
|
||||
if 'chunks' not in mapData['firstLayer'] or not isinstance(mapData['firstLayer']['chunks'], list):
|
||||
print(f"Error: First layer does not contain 'chunks' key.")
|
||||
sys.exit(1)
|
||||
|
||||
if len(mapData['firstLayer']['chunks']) == 0:
|
||||
print(f"Error: First layer does not contain any chunks.")
|
||||
sys.exit(1)
|
||||
|
||||
mapData['firstLayerFirstChunk'] = mapData['firstLayer']['chunks'][0]
|
||||
|
||||
# Now determine the input map bounds.
|
||||
isMinXFound = False
|
||||
isMaxXFound = False
|
||||
isMinYFound = False
|
||||
isMaxYFound = False
|
||||
mapData['inputMapLowestX'] = 0
|
||||
mapData['inputMapHighestX'] = 0
|
||||
mapData['inputMapLowestY'] = 0
|
||||
mapData['inputMapHighestY'] = 0
|
||||
mapData['inputLayerWidthInTiles'] = mapData['firstLayerFirstChunk']['width']
|
||||
mapData['inputLayerHeightInTiles'] = mapData['firstLayerFirstChunk']['height']
|
||||
|
||||
for chunk in mapData['firstLayer']['chunks']:
|
||||
if 'x' not in chunk or 'y' not in chunk:
|
||||
print(f"Error: Chunk in first layer does not contain 'x' or 'y' key.")
|
||||
sys.exit(1)
|
||||
|
||||
# Check chunk is not empty
|
||||
if 'data' not in chunk or not isinstance(chunk['data'], list):
|
||||
print(f"Error: Chunk in first layer does not contain 'data' key or it is not a list.")
|
||||
sys.exit(1)
|
||||
|
||||
if len(chunk['data']) != mapData['inputLayerWidthInTiles'] * mapData['inputLayerHeightInTiles']:
|
||||
print(f"Error: Chunk in first layer does not contain the expected number of tiles.")
|
||||
sys.exit(1)
|
||||
|
||||
chunkEmpty = True
|
||||
for tile in chunk['data']:
|
||||
if tile == 0:
|
||||
continue
|
||||
chunkEmpty = False
|
||||
break
|
||||
|
||||
if chunkEmpty:
|
||||
print(f"Warning: Chunk at ({chunk['x']}, {chunk['y']}) is empty, skipping.")
|
||||
continue
|
||||
|
||||
chunkX = chunk['x']
|
||||
chunkY = chunk['y']
|
||||
|
||||
if mapData['inputMapLowestX'] > chunkX or not isMinXFound:
|
||||
mapData['inputMapLowestX'] = chunkX
|
||||
isMinXFound = True
|
||||
if mapData['inputMapHighestX'] < chunkX or not isMaxXFound:
|
||||
mapData['inputMapHighestX'] = chunkX
|
||||
isMaxXFound = True
|
||||
|
||||
if mapData['inputMapLowestY'] > chunkY or not isMinYFound:
|
||||
mapData['inputMapLowestY'] = chunkY
|
||||
isMinYFound = True
|
||||
if mapData['inputMapHighestY'] < chunkY or not isMaxYFound:
|
||||
mapData['inputMapHighestY'] = chunkY
|
||||
isMaxYFound = True
|
||||
|
||||
mapData['inputMapHighestX'] += mapData['inputLayerWidthInTiles']
|
||||
mapData['inputMapHighestY'] += mapData['inputLayerHeightInTiles']
|
||||
|
||||
# We now offset all chunks by the lowest X/Y values to make them start at (0, 0).
|
||||
for layerIndex, layer in enumerate(mapData['tileLayers']):
|
||||
for chunkIndex, chunk in enumerate(layer['chunks']):
|
||||
chunk['x'] -= mapData['inputMapLowestX']
|
||||
chunk['y'] -= mapData['inputMapLowestY']
|
||||
layer['chunks'][chunkIndex] = chunk
|
||||
|
||||
mapData['layers'][layerIndex] = layer
|
||||
|
||||
# Same for object layers
|
||||
for obIndex, ob in enumerate(mapData['objectLayer']['objects']):
|
||||
if 'x' not in ob or 'y' not in ob:
|
||||
print(f"Error: Object in object layer does not contain 'x' or 'y' key.")
|
||||
sys.exit(1)
|
||||
|
||||
ob['x'] -= mapData['inputMapLowestX'] * TILE_WIDTH_HEIGHT
|
||||
ob['y'] -= mapData['inputMapLowestY'] * TILE_WIDTH_HEIGHT
|
||||
|
||||
# Objects are bottom aligned in tiled, so we need to adjust the Y coordinate.
|
||||
ob['y'] -= TILE_WIDTH_HEIGHT
|
||||
|
||||
# Round off the coordinates
|
||||
ob['x'] = round(ob['x'])
|
||||
ob['y'] = round(ob['y'])
|
||||
|
||||
mapData['objectLayer']['objects'][obIndex] = ob
|
||||
|
||||
mapData['mapWidthInTiles'] = mapData['inputMapHighestX'] - mapData['inputMapLowestX']
|
||||
mapData['mapHeightInTiles'] = mapData['inputMapHighestY'] - mapData['inputMapLowestY']
|
||||
mapData['mapWidthInRealChunks'] = math.ceil(float(mapData['mapWidthInTiles']) / float(CHUNK_WIDTH))
|
||||
mapData['mapHeightInRealChunks'] = math.ceil(float(mapData['mapHeightInTiles']) / float(CHUNK_HEIGHT))
|
||||
|
||||
if mapData['inputLayerWidthInTiles'] < CHUNK_WIDTH or mapData['inputLayerHeightInTiles'] < CHUNK_HEIGHT:
|
||||
print(f"Error: Input layer size is smaller than chunk size.")
|
||||
sys.exit(1)
|
||||
|
||||
# Extract player spawn point
|
||||
for ob in mapData['objectLayer']['objects']:
|
||||
if 'type' not in ob or ob['type'] != 'player_spawn':
|
||||
continue
|
||||
if 'x' not in ob or 'y' not in ob:
|
||||
print(f"Error: Player spawn object does not contain 'x' or 'y' key.")
|
||||
sys.exit(1)
|
||||
mapData['playerSpawnX'] = ob['x']
|
||||
mapData['playerSpawnY'] = ob['y']
|
||||
|
||||
return mapData
|
Reference in New Issue
Block a user