Skip to content

Commit 186ecd9

Browse files
committed
Add support for pre-1.0 Tiled JSON formats
While attempting to parse Starbound dungeons in Tiled JSON format, I encountered a number of parse errors. These errors appear to be due to pre-1.0 differences in the Tiled JSON map and tileset formats. As far as I can tell, most Starbound dungeon files were created and/or last edited with Tiled 0.15.2. * Map object `properties` were dictionaries rather than lists, with the key being the property name and the value always a string. * Tileset `tiles` were dictionaries rather than lists, with the key being the tile id (integer cast as a string) and the value being a dictionary containing the remainder of the tile definition. * Some map and tileset properties did not exist, or were optional. This patch introduces minimal changes to the code to allow the Starbound files to be parsed. There may be other legacy quirks, but these are the only ones I've noticed in these files.
1 parent 5635f50 commit 186ecd9

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

pytiled_parser/parsers/json/properties.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def parse(raw_properties: List[RawProperty]) -> Properties:
2727
"""Parse a list of `RawProperty` objects into `Properties`.
2828
2929
Args:
30-
raw_properties: The list of `RawProperty` objects to parse.
30+
raw_properties: The list or dict of `RawProperty` objects to parse. The dict type is supported for parsing legacy Tiled dungeon files.
3131
3232
Returns:
3333
Properties: The parsed `Property` objects.
@@ -36,13 +36,17 @@ def parse(raw_properties: List[RawProperty]) -> Properties:
3636
final: Properties = {}
3737
value: Property
3838

39-
for raw_property in raw_properties:
40-
if raw_property["type"] == "file":
41-
value = Path(cast(str, raw_property["value"]))
42-
elif raw_property["type"] == "color":
43-
value = parse_color(cast(str, raw_property["value"]))
44-
else:
45-
value = raw_property["value"]
46-
final[raw_property["name"]] = value
39+
if isinstance(raw_properties, dict):
40+
for name, value in raw_properties.items():
41+
final[name] = value
42+
else:
43+
for raw_property in raw_properties:
44+
if raw_property["type"] == "file":
45+
value = Path(cast(str, raw_property["value"]))
46+
elif raw_property["type"] == "color":
47+
value = parse_color(cast(str, raw_property["value"]))
48+
else:
49+
value = raw_property["value"]
50+
final[raw_property["name"]] = value
4751

4852
return final

pytiled_parser/parsers/json/tiled_map.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@ def parse(file: Path) -> TiledMap:
112112
# `map` is a built-in function
113113
map_ = TiledMap(
114114
map_file=file,
115-
infinite=raw_tiled_map["infinite"],
115+
infinite=raw_tiled_map.get("infinite", False),
116116
layers=[parse_layer(layer_, parent_dir) for layer_ in raw_tiled_map["layers"]],
117117
map_size=Size(raw_tiled_map["width"], raw_tiled_map["height"]),
118-
next_layer_id=raw_tiled_map["nextlayerid"],
118+
next_layer_id=raw_tiled_map.get("nextlayerid"),
119119
next_object_id=raw_tiled_map["nextobjectid"],
120120
orientation=raw_tiled_map["orientation"],
121121
render_order=raw_tiled_map["renderorder"],
122-
tiled_version=raw_tiled_map["tiledversion"],
122+
tiled_version=raw_tiled_map.get("tiledversion", ""),
123123
tile_size=Size(raw_tiled_map["tilewidth"], raw_tiled_map["tileheight"]),
124124
tilesets=tilesets,
125125
version=version,

pytiled_parser/parsers/json/tileset.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ def parse(
249249
tile_count=raw_tileset["tilecount"],
250250
tile_width=raw_tileset["tilewidth"],
251251
tile_height=raw_tileset["tileheight"],
252-
columns=raw_tileset["columns"],
252+
columns=raw_tileset.get("columns", 1),
253253
spacing=raw_tileset["spacing"],
254254
margin=raw_tileset["margin"],
255255
firstgid=firstgid,
@@ -304,8 +304,18 @@ def parse(
304304

305305
if raw_tileset.get("tiles") is not None:
306306
tiles = {}
307-
for raw_tile in raw_tileset["tiles"]:
308-
tiles[raw_tile["id"]] = _parse_tile(raw_tile, external_path=external_path)
307+
if isinstance(raw_tileset["tiles"], dict):
308+
for raw_tile_id, raw_tile in raw_tileset["tiles"].items():
309+
assert raw_tile.get("id") is None
310+
raw_tile["id"] = int(raw_tile_id)
311+
tiles[raw_tile["id"]] = _parse_tile(
312+
raw_tile, external_path=external_path
313+
)
314+
else:
315+
for raw_tile in raw_tileset["tiles"]:
316+
tiles[raw_tile["id"]] = _parse_tile(
317+
raw_tile, external_path=external_path
318+
)
309319
tileset.tiles = tiles
310320

311321
if raw_tileset.get("wangsets") is not None:

0 commit comments

Comments
 (0)