123 lines
3.6 KiB
Python
123 lines
3.6 KiB
Python
import sys
|
|
import argparse
|
|
import pprint
|
|
import json
|
|
import struct
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('filename')
|
|
args = parser.parse_args()
|
|
|
|
print("Parsing", args.filename)
|
|
|
|
with open(args.filename, 'r') as f:
|
|
level_pack_data = json.load(f)
|
|
|
|
#pprint.pprint(level_pack_data)
|
|
ENUMIDS_TILETYPE_MAPPING = {
|
|
'Solid': 1,
|
|
'WoodenPlat': 2,
|
|
'Ladder': 3,
|
|
'LSpike': 4,
|
|
'RSpike': 5,
|
|
'USpike': 6,
|
|
'DSpike': 7,
|
|
'EmptyWCrate': 8,
|
|
'LArrowWCrate': 9,
|
|
'RArrowWCrate': 10,
|
|
'UArrowWCrate': 11,
|
|
'DArrowWCrate': 12,
|
|
'BombWCrate': 13,
|
|
'EmptyMCrate': 14,
|
|
'LArrowMCrate': 15,
|
|
'RArrowMCrate': 16,
|
|
'UArrowMCrate': 17,
|
|
'DArrowMCrate': 18,
|
|
'BombMCrate': 19,
|
|
'Boulder': 20,
|
|
'Runner': 21,
|
|
'Player': 22,
|
|
}
|
|
|
|
#ENTID_MAPPING = {
|
|
# 'Player': 1
|
|
#}
|
|
|
|
# First go to tilesets and find Simple_tiles identifier, then find enumTags to identifier which tile type is what tileid
|
|
ids_tiletype_map = {}
|
|
tileset_defs = level_pack_data["defs"]["tilesets"]
|
|
|
|
for ts_def in tileset_defs:
|
|
if ts_def["identifier"] != "Items_spritesheet":
|
|
continue
|
|
for tag in ts_def["enumTags"]:
|
|
ids_tiletype_map[tag["tileIds"][0]] = ENUMIDS_TILETYPE_MAPPING[tag["enumValueId"]]
|
|
|
|
if not ids_tiletype_map:
|
|
print("No tileset definition")
|
|
sys.exit(1)
|
|
|
|
pprint.pprint(ids_tiletype_map)
|
|
|
|
# Number of levels is the length of the levels
|
|
n_levels = len(level_pack_data["levels"])
|
|
print("Number of levels:", n_levels)
|
|
|
|
fileparts = args.filename.split('.')
|
|
if len(fileparts) == 1:
|
|
fileparts.append("lvldat")
|
|
else:
|
|
fileparts[-1] = "lvldata"
|
|
converted_filename = '.'.join(fileparts)
|
|
|
|
# Each level should be packed as: [width, 2 bytes][height, 2 bytes][tile_type,entity,water,padding 1,1,1,1 bytes][tile_type,entity,water,padding 1,1,1,1 bytes]...
|
|
with open(converted_filename, 'wb+') as out_file:
|
|
out_file.write(struct.pack("<I", n_levels))
|
|
# Then loop the levels. Read the layerIndstances
|
|
for level in level_pack_data["levels"]:
|
|
# Search for __identifier for the level layout
|
|
level_name = level["identifier"]
|
|
print("Parsing level", level_name)
|
|
|
|
|
|
level_layout = {}
|
|
entity_layout = {}
|
|
water_layout = {}
|
|
for layer in level['layerInstances']:
|
|
if layer["__identifier"] == "Tiles":
|
|
level_layout = layer
|
|
elif layer["__identifier"] == "Entities":
|
|
entity_layout = layer
|
|
elif layer["__identifier"] == "Water":
|
|
water_layout = layer
|
|
|
|
# Dimensions of each level is obtained via __cWid and __cHei. Get the __gridSize as well
|
|
width = level_layout["__cWid"]
|
|
height = level_layout["__cHei"]
|
|
print(f"Dim.: {width}x{height}")
|
|
# Create a W x H array of tile information
|
|
n_tiles = width * height
|
|
tiles_info = [[0,0,0] for _ in range(n_tiles)]
|
|
# Loop through gridTiles, get "d" as the index to fill the info
|
|
for tile in level_layout["gridTiles"]:
|
|
tiles_info[tile["d"][0]][0] = ids_tiletype_map[tile["t"]]
|
|
|
|
for i, water_level in enumerate(water_layout["intGridCsv"]):
|
|
tiles_info[i][2] = water_level
|
|
|
|
# Subject to change
|
|
for ent in entity_layout["entityInstances"]:
|
|
x,y = ent["__grid"]
|
|
tiles_info[y*width + x][0] = ENUMIDS_TILETYPE_MAPPING[ent["__identifier"]]
|
|
|
|
out_file.write(struct.pack("<32s2H", level_name.encode('utf-8'), width, height))
|
|
for tile in tiles_info:
|
|
out_file.write(struct.pack("<3Bx", *tile))
|
|
|
|
|
|
for y in range(height):
|
|
for x in range(width):
|
|
print(tiles_info[y*width + x], end=" ")
|
|
print()
|
|
|