Files
dusk/tools/mapcompile/mapcompile.py

129 lines
4.1 KiB
Python

import sys, os
import argparse
from datetime import datetime
import math
from helper import floatToFixed248
from inputParser import parseInputFile
from mapParser import parseMap
from chunkParser import parseChunk
from constants import CHUNK_WIDTH, CHUNK_HEIGHT
# Check if the script is run with the correct arguments
parser = argparse.ArgumentParser(description="Generate chunk header files")
parser.add_argument('--output', required=True, help='Dir to output headers')
parser.add_argument('--input', required=True, help='Input JSON file from tiled')
args = parser.parse_args()
# Ensure outdir exists
outputDir = args.output
os.makedirs(outputDir, exist_ok=True)
# Create world directory if it does not exist
worldDir = os.path.join(outputDir, "world")
os.makedirs(worldDir, exist_ok=True)
# Create chunks directory if it does not exist
chunksDir = os.path.join(worldDir, "chunk")
os.makedirs(chunksDir, exist_ok=True)
# Some vars used during printing
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Read the input JSON file
data = parseInputFile(args.input)
mapData = parseMap(data)
# For each output chunk.
worldWidth = 0
worldHeight = 0
chunksDone = set()
for chunkY in range(mapData['mapHeightInRealChunks']):
for chunkX in range(mapData['mapWidthInRealChunks']):
chunkData = parseChunk(chunkX, chunkY, mapData)
if chunkData is None:
continue
# This is a valid chunk.
worldWidth = max(worldWidth, chunkX + 1)
worldHeight = max(worldHeight, chunkY + 1)
chunksDone.add((chunkX, chunkY))
chunkHeaderPath = os.path.join(chunksDir, f"chunk_{chunkX}_{chunkY}.h")
with open(chunkHeaderPath, 'w') as f:
f.write(f"// Generated chunk header for chunk at position ({chunkX}, {chunkY})\n")
f.write(f"// Generated at {now}\n")
f.write("#pragma once\n")
f.write("#include \"world/chunkdata.h\"\n\n")
f.write(f"static const chunkdata_t CHUNK_{chunkX}_{chunkY} = {{\n")
f.write(f" .layerBase = {{\n")
for y in range(CHUNK_HEIGHT):
f.write(f" ")
for x in range(CHUNK_WIDTH):
i = y * CHUNK_WIDTH + x
byte = chunkData['layerBaseData'][i]
f.write(f"0x{byte:02x}, ")
f.write(f"\n")
f.write(" },\n\n")
f.write(" .layerBaseOverlay = {\n")
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 = 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 chunkData['entities']:
f.write(" {\n")
f.write(f" .id = {entity['id']},\n")
f.write(f" .type = {entity['type']},\n")
f.write(f" .x = {floatToFixed248(entity['x'])},\n")
f.write(f" .y = {floatToFixed248(entity['y'])},\n")
if 'dir' in entity:
f.write(f" .dir = {entity['dir']},\n")
f.write(" },\n")
f.write(f" }},\n")
f.write("};\n\n")
# Output header file.
headerPath = os.path.join(worldDir, "world.h")
with open(headerPath, 'w') as f:
f.write(f"// Generated chunks file. Generated at {now}\n\n")
f.write("#pragma once\n")
f.write("#include \"dusk.h\"\n")
# Now, for each chunk, include its header file
for (x, y) in chunksDone:
f.write(f"#include \"world/chunk/chunk_{x}_{y}.h\"\n")
f.write("\n")
f.write(f"#define WORLD_WIDTH {worldWidth}\n")
f.write(f"#define WORLD_HEIGHT {worldHeight}\n")
# Write out other global variables.
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")
f.write("\n")
f.write(f"static const chunkdata_t* WORLD_CHUNKS[] = {{\n")
for i in range(worldHeight):
f.write(" ")
for j in range(worldWidth):
if(j, i) in chunksDone:
f.write(f"&CHUNK_{j}_{i}, ")
else:
f.write("NULL, ")
f.write("\n")
f.write("};\n\n")
print(f"chunks.h generated at: {headerPath}")