diff --git a/res/.gitignore b/res/.gitignore index d6b7ef3..9dc5022 100644 --- a/res/.gitignore +++ b/res/.gitignore @@ -1,2 +1,3 @@ * !.gitignore +!ldtk_repacker.py diff --git a/res/ldtk_repacker.py b/res/ldtk_repacker.py new file mode 100644 index 0000000..d18785e --- /dev/null +++ b/res/ldtk_repacker.py @@ -0,0 +1,86 @@ +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, + 'Water': 2 +} + +# 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"] != "Simple_tiles": + 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 = {} + for layer in level['layerInstances']: + if layer["__identifier"] != "Tiles": + continue + + level_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"]] + + 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() +