Moved a bit more code out of mapcompile

This commit is contained in:
2025-06-23 16:00:38 -05:00
parent be5e972b32
commit 39ac4b9fb9
5 changed files with 292 additions and 288 deletions

View File

@ -0,0 +1,122 @@
import sys
from constants import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_TILE_COUNT, TILE_WIDTH_HEIGHT
import math
def parseChunkLayerData(layer, mapData, chunkData):
layerData = []
for y in range(CHUNK_HEIGHT):
for x in range(CHUNK_WIDTH):
inputTileIndex = chunkGetTileIndex(x, y, mapData, chunkData)
outputTileIndex = chunkGetOutputTileIndex(x, y)
layerData.append(layer['data'][inputTileIndex])
if len(layerData) != CHUNK_TILE_COUNT:
print(f"Error: Layer data length {len(layerData)} does not match expected chunk tile count {CHUNK_TILE_COUNT}.")
sys.exit(1)
return layerData
def parseChunk(chunkX, chunkY, mapData):
chunkData = { }
chunkData['topLeftTileX'] = chunkX * CHUNK_WIDTH
chunkData['topLeftTileY'] = chunkY * CHUNK_HEIGHT
chunkData['inputTopLeftTileX'] = math.floor(
float(chunkData['topLeftTileX']) / float(mapData['inputLayerWidthInTiles'])
) * mapData['inputLayerWidthInTiles']
chunkData['inputTopLeftTileY'] = math.floor(
float(chunkData['topLeftTileY']) / float(mapData['inputLayerHeightInTiles'])
) * mapData['inputLayerHeightInTiles']
# Get the data for this chunk out of the map data.
chunkData['layers'] = []
for layer in mapData['tileLayers']:
foundChunk = None
if 'chunks' not in layer or not isinstance(layer['chunks'], list):
print(f"Error: Layer '{layer['name']}' does not contain 'chunks' key or it is not a list.")
sys.exit(1)
for chunk in layer['chunks']:
if 'x' not in chunk or 'y' not in chunk:
print(f"Error: Chunk in layer '{layer['name']}' does not contain 'x' or 'y' key.")
sys.exit(1)
# Check if this chunk is within the bounds of the top left tile.
if chunk['x'] != chunkData['inputTopLeftTileX'] or chunk['y'] != chunkData['inputTopLeftTileY']:
continue
foundChunk = chunk
break
if foundChunk is None:
chunkData['layers'].append(None)
continue
# Is layer empty?
layerEmpty = True
for tile in foundChunk['data']:
if tile == 0:
continue
layerEmpty = False
break
if layerEmpty:
chunkData['layers'].append(None)
else:
chunkData['layers'].append(foundChunk)
# Any layers for this chunk?
if all(chunk is None for chunk in chunkData['layers']):
return None
if len(chunkData['layers']) == 0:
return None
# Parse Layer Data
chunkData['layerBase'] = chunkData['layers'][0]
chunkData['layerBaseOverlay'] = None
if len(chunkData['layers']) > 1:
chunkData['layerBaseOverlay'] = chunkData['layers'][1]
chunkData['layerBaseData'] = parseChunkLayerData(chunkData['layerBase'], mapData, chunkData)
if chunkData['layerBaseOverlay'] is not None:
chunkData['layerBaseOverlayData'] = parseChunkLayerData(chunkData['layerBaseOverlay'], mapData, chunkData)
else:
chunkData['layerBaseOverlayData'] = []
# Parse chunk entities.
chunkData['entities'] = []
for ob in 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)
# Is this object within the chunk?
if ob['x'] < chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT:
continue
if ob['x'] >= (chunkData['topLeftTileX'] + CHUNK_WIDTH) * TILE_WIDTH_HEIGHT:
continue
if ob['y'] < chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT:
continue
if ob['y'] >= (chunkData['topLeftTileY'] + CHUNK_HEIGHT) * TILE_WIDTH_HEIGHT:
continue
chunkData['entities'].append(ob)
return chunkData
def chunkGetLocalTileX(absoluteTileX, mapData):
return absoluteTileX % mapData['inputLayerWidthInTiles']
def chunkGetLocalTileY(absoluteTileY, mapData):
return absoluteTileY % mapData['inputLayerHeightInTiles']
def chunkGetTileIndex(localX, localY, mapData, chunkData):
absoluteTileX = chunkData['topLeftTileX'] + localX
absoluteTileY = chunkData['topLeftTileY'] + localY
inputLocalTileX = chunkGetLocalTileX(absoluteTileX, mapData)
inputLocalTileY = chunkGetLocalTileY(absoluteTileY, mapData)
return inputLocalTileY * mapData['inputLayerWidthInTiles'] + inputLocalTileX
def chunkGetOutputTileIndex(localX, localY):
return localY * CHUNK_WIDTH + localX

View File

@ -1,20 +0,0 @@
import os
import sys
def parseEntities(layers):
parsed = {
'playerSpawnX': 0,
'playerSpawnY': 0,
}
for ob in layers['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)
parsed['playerSpawnX'] = ob['x']
parsed['playerSpawnY'] = ob['y']
break
return parsed

View File

@ -1,144 +0,0 @@
import sys
from constants import TILE_WIDTH_HEIGHT, CHUNK_WIDTH, CHUNK_HEIGHT
import math
def parseLayers(data):
parsed = {}
# Extract layers
parsed['layers'] = data['layers']
# Object layer
for layer in parsed['layers']:
if layer.get('type') == 'objectgroup':
parsed['objectLayer'] = layer
break
if parsed['objectLayer'] is None:
print(f"Error: Data does not contain an object layer.")
sys.exit(1)
if 'objects' not in parsed['objectLayer'] or not isinstance(parsed['objectLayer']['objects'], list):
print(f"Error: Object layer does not contain 'objects' key or it is not a list.")
sys.exit(1)
# Tile Layers
parsed['tileLayers'] = []
for layer in parsed['layers']:
if layer.get('type') == 'tilelayer':
parsed['tileLayers'].append(layer)
if len(parsed['tileLayers']) == 0:
print(f"Error: Data does not contain any tile layers.")
sys.exit(1)
# First layer
parsed['firstLayer'] = parsed['tileLayers'][0]
if 'width' not in parsed['firstLayer'] or 'height' not in parsed['firstLayer']:
print(f"Error: First layer does not contain 'width' or 'height' key.")
sys.exit(1)
if 'chunks' not in parsed['firstLayer'] or not isinstance(parsed['firstLayer']['chunks'], list):
print(f"Error: First layer does not contain 'chunks' key.")
sys.exit(1)
if len(parsed['firstLayer']['chunks']) == 0:
print(f"Error: First layer does not contain any chunks.")
sys.exit(1)
parsed['firstLayerFirstChunk'] = parsed['firstLayer']['chunks'][0]
# Now determine the input map bounds.
isMinXFound = False
isMaxXFound = False
isMinYFound = False
isMaxYFound = False
parsed['inputMapLowestX'] = 0
parsed['inputMapHighestX'] = 0
parsed['inputMapLowestY'] = 0
parsed['inputMapHighestY'] = 0
parsed['inputLayerWidthInTiles'] = parsed['firstLayerFirstChunk']['width']
parsed['inputLayerHeightInTiles'] = parsed['firstLayerFirstChunk']['height']
for chunk in parsed['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']) != parsed['inputLayerWidthInTiles'] * parsed['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 parsed['inputMapLowestX'] > chunkX or not isMinXFound:
parsed['inputMapLowestX'] = chunkX
isMinXFound = True
if parsed['inputMapHighestX'] < chunkX or not isMaxXFound:
parsed['inputMapHighestX'] = chunkX
isMaxXFound = True
if parsed['inputMapLowestY'] > chunkY or not isMinYFound:
parsed['inputMapLowestY'] = chunkY
isMinYFound = True
if parsed['inputMapHighestY'] < chunkY or not isMaxYFound:
parsed['inputMapHighestY'] = chunkY
isMaxYFound = True
parsed['inputMapHighestX'] += parsed['inputLayerWidthInTiles']
parsed['inputMapHighestY'] += parsed['inputLayerHeightInTiles']
# We now offset all chunks by the lowest X/Y values to make them start at (0, 0).
for layerIndex, layer in enumerate(parsed['tileLayers']):
for chunkIndex, chunk in enumerate(layer['chunks']):
chunk['x'] -= parsed['inputMapLowestX']
chunk['y'] -= parsed['inputMapLowestY']
layer['chunks'][chunkIndex] = chunk
parsed['layers'][layerIndex] = layer
# Same for object layers
for obIndex, ob in enumerate(parsed['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'] -= parsed['inputMapLowestX'] * TILE_WIDTH_HEIGHT
ob['y'] -= parsed['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'])
parsed['objectLayer']['objects'][obIndex] = ob
parsed['mapWidthInTiles'] = parsed['inputMapHighestX'] - parsed['inputMapLowestX']
parsed['mapHeightInTiles'] = parsed['inputMapHighestY'] - parsed['inputMapLowestY']
parsed['mapWidthInRealChunks'] = math.ceil(float(parsed['mapWidthInTiles']) / float(CHUNK_WIDTH))
parsed['mapHeightInRealChunks'] = math.ceil(float(parsed['mapHeightInTiles']) / float(CHUNK_HEIGHT))
if parsed['inputLayerWidthInTiles'] < CHUNK_WIDTH or parsed['inputLayerHeightInTiles'] < CHUNK_HEIGHT:
print(f"Error: Input layer size is smaller than chunk size.")
sys.exit(1)
return parsed

View 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

View File

@ -4,8 +4,8 @@ from datetime import datetime
import math
from helper import floatToFixed248
from inputParser import parseInputFile
from layerParser import parseLayers
from entityParse import parseEntities
from mapParser import parseMap
from chunkParser import chunkGetLocalTileX, chunkGetLocalTileY, chunkGetTileIndex, chunkGetOutputTileIndex, parseChunk
from constants import CHUNK_WIDTH, CHUNK_HEIGHT, TILE_WIDTH_HEIGHT, ENTITY_TYPE_MAP, CHUNK_TILE_COUNT
# Check if the script is run with the correct arguments
@ -31,128 +31,19 @@ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Read the input JSON file
data = parseInputFile(args.input)
layers = parseLayers(data)
entityData = parseEntities(layers)
mapData = parseMap(data)
# For each output chunk.
worldWidth = 0
worldHeight = 0
chunksDone = set()
for chunkY in range(layers['mapHeightInRealChunks']):
for chunkX in range(layers['mapWidthInRealChunks']):
# Top left X/Y based on real chunk size
topLeftTileX = chunkX * CHUNK_WIDTH
topLeftTileY = chunkY * CHUNK_HEIGHT
# Top left coordinates based on input layer size
inputTopLeftTileX = math.floor(float(topLeftTileX) / float(layers['inputLayerWidthInTiles'])) * layers['inputLayerWidthInTiles']
inputTopLeftTileY = math.floor(float(topLeftTileY) / float(layers['inputLayerHeightInTiles'])) * layers['inputLayerHeightInTiles']
# Get the layers for this chunk.
chunkLayers = []
for layer in layers['tileLayers']:
foundChunk = None
if 'chunks' not in layer or not isinstance(layer['chunks'], list):
print(f"Error: Layer '{layer['name']}' does not contain 'chunks' key or it is not a list.")
sys.exit(1)
for chunk in layer['chunks']:
if 'x' not in chunk or 'y' not in chunk:
print(f"Error: Chunk in layer '{layer['name']}' does not contain 'x' or 'y' key.")
sys.exit(1)
# Check if this chunk is within the bounds of the top left tile.
if chunk['x'] != inputTopLeftTileX or chunk['y'] != inputTopLeftTileY:
continue
foundChunk = chunk
break
if foundChunk is None:
chunkLayers.append(None)
continue
# Is layer empty?
layerEmpty = True
for tile in foundChunk['data']:
if tile == 0:
continue
layerEmpty = False
break
if layerEmpty:
chunkLayers.append(None)
else:
chunkLayers.append(foundChunk)
# Now we have a chunkLayers list with the found chunks for each layer.
if all(chunk is None for chunk in chunkLayers) or len(chunkLayers) == 0:
for chunkY in range(mapData['mapHeightInRealChunks']):
for chunkX in range(mapData['mapWidthInRealChunks']):
chunkData = parseChunk(chunkX, chunkY, mapData)
if chunkData is None:
continue
entities = []
for ob in layers['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)
# Is this object within the chunk?
if ob['x'] < topLeftTileX * TILE_WIDTH_HEIGHT:
continue
if ob['x'] >= (topLeftTileX + CHUNK_WIDTH) * TILE_WIDTH_HEIGHT:
continue
if ob['y'] < topLeftTileY * TILE_WIDTH_HEIGHT:
continue
if ob['y'] >= (topLeftTileY + CHUNK_HEIGHT) * TILE_WIDTH_HEIGHT:
continue
entities.append(ob)
# Shorthand functions
def getInputLocalTileX(absoluteTileX):
return absoluteTileX % layers['inputLayerWidthInTiles']
def getInputLocalTileY(absoluteTileY):
return absoluteTileY % layers['inputLayerHeightInTiles']
def getInputTileIndex(localX, localY):
absoluteTileX = topLeftTileX + localX
absoluteTileY = topLeftTileY + localY
inputLocalTileX = getInputLocalTileX(absoluteTileX)
inputLocalTileY = getInputLocalTileY(absoluteTileY)
return inputLocalTileY * layers['inputLayerWidthInTiles'] + inputLocalTileX
def getOutputTileIndex(localX, localY):
return localY * CHUNK_WIDTH + localX
# Determine the layer base.
layerBase = chunkLayers[0]
layerBaseOverlay = None
if len(chunkLayers) > 1:
layerBaseOverlay = chunkLayers[1]
# Determine base layer data.
layerBaseData = []
for y in range(CHUNK_HEIGHT):
for x in range(CHUNK_WIDTH):
inputTileIndex = getInputTileIndex(x, y)
outputTileIndex = getOutputTileIndex(x, y)
layerBaseData.append(layerBase['data'][inputTileIndex])
if len(layerBaseData) != CHUNK_TILE_COUNT:
print(f"Error: Layer base data length {len(layerBaseData)} does not match expected chunk tile count {CHUNK_TILE_COUNT}.")
sys.exit(1)
# Layer base overlay.
layerOverlayData = []
if layerBaseOverlay is not None:
for y in range(CHUNK_HEIGHT):
for x in range(CHUNK_WIDTH):
inputTileIndex = getInputTileIndex(x, y)
outputTileIndex = getOutputTileIndex(x, y)
layerOverlayData.append(layerBaseOverlay['data'][inputTileIndex])
# This is a valid chunk.
worldWidth = max(worldWidth, chunkX + 1)
worldHeight = max(worldHeight, chunkY + 1)
@ -170,27 +61,27 @@ for chunkY in range(layers['mapHeightInRealChunks']):
f.write(f" ")
for x in range(CHUNK_WIDTH):
i = y * CHUNK_WIDTH + x
byte = layerBaseData[i]
byte = chunkData['layerBaseData'][i]
f.write(f"0x{byte:02x}, ")
f.write(f"\n")
f.write(" },\n\n")
f.write(" .layerBaseOverlay = {\n")
if layerBaseOverlay is not None:
if chunkData['layerBaseOverlay'] is not None:
for y in range(CHUNK_HEIGHT):
f.write(f" ")
for x in range(CHUNK_WIDTH):
i = y * CHUNK_WIDTH + x
byte = layerOverlayData[i]
byte = chunkData['layerBaseOverlayData'][i]
f.write(f"0x{byte:02x}, ")
f.write(f"\n")
f.write(" },\n\n")
f.write(f" .entities = {{\n")
for entity in entities:
for entity in chunkData['entities']:
# Entities are center aligned in tiled.
localX = round(entity['x'] - (topLeftTileX * TILE_WIDTH_HEIGHT))
localY = round(entity['y'] - (topLeftTileY * TILE_WIDTH_HEIGHT))
localX = round(entity['x'] - (chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT))
localY = round(entity['y'] - (chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT))
if 'type' in entity and entity['type'] not in ENTITY_TYPE_MAP:
continue
@ -231,7 +122,7 @@ with open(headerPath, 'w') as f:
f.write("NULL, ")
f.write("\n")
f.write("};\n\n")
f.write(f"#define WORLD_PLAYER_SPAWN_X ((fixed248_t){floatToFixed248(entityData['playerSpawnX'])})\n")
f.write(f"#define WORLD_PLAYER_SPAWN_Y ((fixed248_t){floatToFixed248(entityData['playerSpawnY'])})\n")
f.write(f"#define WORLD_PLAYER_SPAWN_X ((fixed248_t){floatToFixed248(mapData['playerSpawnX'])})\n")
f.write(f"#define WORLD_PLAYER_SPAWN_Y ((fixed248_t){floatToFixed248(mapData['playerSpawnY'])})\n")
print(f"chunks.h generated at: {headerPath}")