parse-tmx 1.8.2 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +306 -1
- package/dist/index.js +305 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,307 @@
|
|
|
1
|
+
interface TMXEditorSettingsParsed extends Record<string, unknown> {
|
|
2
|
+
}
|
|
1
3
|
|
|
2
|
-
|
|
4
|
+
interface TMXFlipsParsed {
|
|
5
|
+
H: boolean;
|
|
6
|
+
V: boolean;
|
|
7
|
+
D: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface TMXImageShared {
|
|
11
|
+
height: number;
|
|
12
|
+
width: number;
|
|
13
|
+
source: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface TMXImageParsed extends TMXImageShared {
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare enum Shape {
|
|
20
|
+
Ellipse = "ellipse",
|
|
21
|
+
Point = "point",
|
|
22
|
+
Polygon = "polygon",
|
|
23
|
+
Rectangle = "rectangle"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type TMXPropertiesParsed = Record<string, unknown>[];
|
|
27
|
+
|
|
28
|
+
interface TMXObjectShared {
|
|
29
|
+
id: number;
|
|
30
|
+
type: string;
|
|
31
|
+
gid: number;
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface TMXObjectParsed extends TMXObjectShared {
|
|
39
|
+
name: string;
|
|
40
|
+
value: string;
|
|
41
|
+
shape: Shape;
|
|
42
|
+
points?: [number, number][];
|
|
43
|
+
text?: string;
|
|
44
|
+
flips?: TMXFlipsParsed;
|
|
45
|
+
properties?: TMXPropertiesParsed;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface TMXLayerShared {
|
|
49
|
+
id: number;
|
|
50
|
+
name: string;
|
|
51
|
+
type: string;
|
|
52
|
+
width: number;
|
|
53
|
+
height: number;
|
|
54
|
+
x?: number;
|
|
55
|
+
y?: number;
|
|
56
|
+
locked?: number;
|
|
57
|
+
opacity?: number;
|
|
58
|
+
visible?: number;
|
|
59
|
+
tintcolor?: string;
|
|
60
|
+
offsetx?: number;
|
|
61
|
+
offsety?: number;
|
|
62
|
+
parallaxx?: number;
|
|
63
|
+
parallaxy?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface TMXLayerParsed extends TMXLayerShared {
|
|
67
|
+
data?: number[];
|
|
68
|
+
image?: TMXImageParsed;
|
|
69
|
+
flips?: TMXFlipsParsed[];
|
|
70
|
+
objects?: TMXObjectParsed[];
|
|
71
|
+
properties?: TMXPropertiesParsed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface TMXGroupLayerShared {
|
|
75
|
+
id: number;
|
|
76
|
+
name: string;
|
|
77
|
+
type: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface TMXGroupLayerParsed extends TMXGroupLayerShared {
|
|
81
|
+
layers: TMXLayerParsed[];
|
|
82
|
+
properties?: TMXPropertiesParsed;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface TMXTileShared {
|
|
86
|
+
id: number;
|
|
87
|
+
gid?: number;
|
|
88
|
+
probability?: number;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface TMXTileParsed extends TMXTileShared {
|
|
92
|
+
id: number;
|
|
93
|
+
type: string;
|
|
94
|
+
animation?: {
|
|
95
|
+
frames: number[];
|
|
96
|
+
};
|
|
97
|
+
objects?: TMXObjectParsed[];
|
|
98
|
+
properties?: TMXPropertiesParsed;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface TMXBaseTilesetShared {
|
|
102
|
+
firstgid: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface TMXEmbeddedTilesetShared extends TMXBaseTilesetShared {
|
|
106
|
+
columns: number;
|
|
107
|
+
name: string;
|
|
108
|
+
spacing?: number;
|
|
109
|
+
margin?: number;
|
|
110
|
+
tilecount: number;
|
|
111
|
+
tilewidth: number;
|
|
112
|
+
tileheight: number;
|
|
113
|
+
imagewidth: number;
|
|
114
|
+
imageheight: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface TMXEmbeddedTilesetParsed extends TMXEmbeddedTilesetShared {
|
|
118
|
+
image: TMXImageParsed;
|
|
119
|
+
tiles: TMXTileParsed[];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface TMXExternalTilesetShared extends TMXBaseTilesetShared {
|
|
123
|
+
source: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface TMXExternalTilesetParsed extends TMXExternalTilesetShared {
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
type TMXTilesetParsed = TMXEmbeddedTilesetParsed | TMXExternalTilesetParsed;
|
|
130
|
+
|
|
131
|
+
declare class TMXMapShared {
|
|
132
|
+
version: number;
|
|
133
|
+
tiledversion: string;
|
|
134
|
+
orientation: string;
|
|
135
|
+
renderorder: string;
|
|
136
|
+
width: number;
|
|
137
|
+
height: number;
|
|
138
|
+
tilewidth: number;
|
|
139
|
+
tileheight: number;
|
|
140
|
+
infinite: number;
|
|
141
|
+
nextlayerid: number;
|
|
142
|
+
nextobjectid: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
declare class TMXMapParsed extends TMXMapShared {
|
|
146
|
+
editorsettings: TMXEditorSettingsParsed;
|
|
147
|
+
tilesets: TMXTilesetParsed[];
|
|
148
|
+
layers: (TMXLayerParsed | TMXGroupLayerParsed)[];
|
|
149
|
+
properties: TMXPropertiesParsed;
|
|
150
|
+
constructor(init?: Partial<TMXMapParsed>);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
interface TMXParsed {
|
|
154
|
+
map: TMXMapParsed;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
declare const parseTmx: (xmlString: string, translateFlips?: boolean) => Promise<TMXParsed>;
|
|
158
|
+
|
|
159
|
+
declare enum Compression {
|
|
160
|
+
Gzip = "gzip",
|
|
161
|
+
Zlib = "zlib"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
declare enum Encoding {
|
|
165
|
+
Base64 = "base64",
|
|
166
|
+
Csv = "csv"
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
declare enum Flipped {
|
|
170
|
+
Diagonally = 536870912,
|
|
171
|
+
Horizontally = 2147483648,
|
|
172
|
+
Vertically = 1073741824
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
declare const isExternalTileset: (tileset: TMXEmbeddedTilesetShared | TMXExternalTilesetShared) => tileset is TMXExternalTilesetShared;
|
|
176
|
+
|
|
177
|
+
declare const parseFlips: (gid: number) => TMXFlipsParsed;
|
|
178
|
+
|
|
179
|
+
interface BaseTMXNode<T> extends Record<string, unknown> {
|
|
180
|
+
$: T;
|
|
181
|
+
}
|
|
182
|
+
type TMXNode<T, TChildNode extends BaseTMXNode<unknown> | undefined = undefined> = BaseTMXNode<T> & {
|
|
183
|
+
$$: TChildNode extends undefined ? undefined : TChildNode[];
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
interface TMXDataNode extends TMXNode<{
|
|
187
|
+
encoding: Encoding;
|
|
188
|
+
compression?: Compression | null;
|
|
189
|
+
}> {
|
|
190
|
+
_: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
interface TMXImageNode extends TMXNode<TMXImageShared> {
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface TMXPropertyNode extends TMXNode<{
|
|
197
|
+
name: string;
|
|
198
|
+
value?: string;
|
|
199
|
+
}> {
|
|
200
|
+
_: string;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
interface TMXPropertiesNode extends TMXNode<Record<string, never>, TMXPropertyNode> {
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
interface TMXObjectNode extends TMXNode<TMXObjectShared, TMXDataNode | TMXPropertiesNode> {
|
|
207
|
+
polygon?: TMXNode<{
|
|
208
|
+
points: string;
|
|
209
|
+
}>[];
|
|
210
|
+
text?: TMXDataNode[];
|
|
211
|
+
properties?: {
|
|
212
|
+
property: TMXPropertyNode[];
|
|
213
|
+
}[];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
interface TMXTileNode extends TMXNode<TMXTileShared, TMXPropertiesNode> {
|
|
217
|
+
animation?: Record<string, TMXNode<number>[]>[];
|
|
218
|
+
objectgroup?: Record<string, TMXObjectNode[]>[];
|
|
219
|
+
properties?: {
|
|
220
|
+
property: TMXPropertyNode[];
|
|
221
|
+
}[];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
interface TMXEmbeddedTilesetNode extends TMXNode<TMXEmbeddedTilesetShared, TMXImageNode | TMXTileNode> {
|
|
225
|
+
tile?: TMXTileNode[];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
interface TMXLayerNode extends TMXNode<TMXLayerShared, TMXEmbeddedTilesetNode | TMXDataNode | TMXPropertiesNode> {
|
|
229
|
+
data?: TMXEmbeddedTilesetNode[] | TMXDataNode[];
|
|
230
|
+
image?: TMXImageNode[];
|
|
231
|
+
object?: TMXObjectNode[];
|
|
232
|
+
properties?: {
|
|
233
|
+
property: TMXPropertyNode[];
|
|
234
|
+
}[];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
interface TMXGroupLayerNode extends TMXNode<TMXGroupLayerShared, TMXLayerNode> {
|
|
238
|
+
properties?: {
|
|
239
|
+
property: TMXPropertyNode[];
|
|
240
|
+
}[];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
declare const parseGroup: (node: TMXGroupLayerNode, expectedCount: number, translateFlips: boolean) => Promise<TMXGroupLayerParsed>;
|
|
244
|
+
|
|
245
|
+
declare const parseLayer: (node: TMXLayerNode) => TMXLayerParsed;
|
|
246
|
+
|
|
247
|
+
declare const parseNode: <TNode extends TMXLayerNode | TMXGroupLayerNode, TParsedNode = TNode extends TMXLayerNode ? TMXLayerParsed : TMXGroupLayerParsed>(node: TMXLayerNode | TMXGroupLayerNode, expectedCount: number, translateFlips: boolean) => Promise<TParsedNode> | TParsedNode;
|
|
248
|
+
|
|
249
|
+
declare const parseObject: (node: TMXObjectNode) => TMXObjectParsed;
|
|
250
|
+
|
|
251
|
+
declare const parseObjectShape: (node: TMXObjectNode) => Shape;
|
|
252
|
+
|
|
253
|
+
declare const parseProperties: (properties?: {
|
|
254
|
+
property: TMXPropertyNode[];
|
|
255
|
+
}[]) => TMXPropertiesParsed | undefined;
|
|
256
|
+
|
|
257
|
+
declare const parseTile: (node: TMXTileNode) => TMXTileParsed;
|
|
258
|
+
|
|
259
|
+
declare const parseTileId: (gid: number) => number;
|
|
260
|
+
|
|
261
|
+
declare const parseTileLayer: (node: TMXLayerNode, expectedCount: number, translateFlips: boolean) => Promise<TMXLayerParsed>;
|
|
262
|
+
|
|
263
|
+
interface TMXExternalTilesetNode extends TMXNode<TMXExternalTilesetShared> {
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
type TMXTilesetNode = TMXEmbeddedTilesetNode | TMXExternalTilesetNode;
|
|
267
|
+
|
|
268
|
+
declare const parseTileset: (node: TMXTilesetNode) => TMXTilesetParsed;
|
|
269
|
+
|
|
270
|
+
declare const unpackTileBytes: (buffer: Buffer, expectedCount: number) => number[];
|
|
271
|
+
|
|
272
|
+
interface TMXExportShared {
|
|
273
|
+
target: string;
|
|
274
|
+
format: string;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
interface TMXExportNode extends TMXNode<TMXExportShared> {
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
interface TMXEditorSettingsNode extends TMXNode<Record<string, never>, TMXExportNode> {
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
interface TMXMapNode extends TMXNode<TMXMapShared, TMXEditorSettingsNode | TMXTilesetNode | TMXGroupLayerNode | TMXPropertiesNode> {
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
interface TMX {
|
|
287
|
+
map: TMXMapNode;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
declare enum TMXNodeType {
|
|
291
|
+
EditorSettings = "editorsettings",
|
|
292
|
+
Export = "export",
|
|
293
|
+
Group = "group",
|
|
294
|
+
Image = "image",
|
|
295
|
+
ImageLayer = "imagelayer",
|
|
296
|
+
Layer = "layer",
|
|
297
|
+
Object = "object",
|
|
298
|
+
Objectgroup = "objectgroup",
|
|
299
|
+
Properties = "properties",
|
|
300
|
+
Property = "property",
|
|
301
|
+
Tileset = "tileset"
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
interface TMXExportParsed extends TMXExportShared {
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export { Compression, Encoding, Flipped, Shape, type TMX, type TMXBaseTilesetShared, type TMXDataNode, type TMXEditorSettingsNode, type TMXEditorSettingsParsed, type TMXEmbeddedTilesetNode, type TMXEmbeddedTilesetParsed, type TMXEmbeddedTilesetShared, type TMXExportNode, type TMXExportParsed, type TMXExportShared, type TMXExternalTilesetNode, type TMXExternalTilesetParsed, type TMXExternalTilesetShared, type TMXFlipsParsed, type TMXGroupLayerNode, type TMXGroupLayerParsed, type TMXGroupLayerShared, type TMXImageNode, type TMXImageParsed, type TMXImageShared, type TMXLayerNode, type TMXLayerParsed, type TMXLayerShared, type TMXMapNode, TMXMapParsed, TMXMapShared, type TMXNode, TMXNodeType, type TMXObjectNode, type TMXObjectParsed, type TMXObjectShared, type TMXParsed, type TMXPropertiesNode, type TMXPropertiesParsed, type TMXPropertyNode, type TMXTileNode, type TMXTileParsed, type TMXTileShared, type TMXTilesetNode, type TMXTilesetParsed, isExternalTileset, parseFlips, parseGroup, parseLayer, parseNode, parseObject, parseObjectShape, parseProperties, parseTile, parseTileId, parseTileLayer, parseTileset, parseTmx, unpackTileBytes };
|
package/dist/index.js
CHANGED
|
@@ -1 +1,306 @@
|
|
|
1
|
+
import { exhaustiveGuard, InvalidOperationError, Operation, parseXmlString } from '@esposter/shared';
|
|
2
|
+
import { gunzip, inflate } from 'node:zlib';
|
|
1
3
|
|
|
4
|
+
var TMXNodeType;
|
|
5
|
+
(function (TMXNodeType) {
|
|
6
|
+
TMXNodeType["EditorSettings"] = "editorsettings";
|
|
7
|
+
TMXNodeType["Export"] = "export";
|
|
8
|
+
TMXNodeType["Group"] = "group";
|
|
9
|
+
TMXNodeType["Image"] = "image";
|
|
10
|
+
TMXNodeType["ImageLayer"] = "imagelayer";
|
|
11
|
+
TMXNodeType["Layer"] = "layer";
|
|
12
|
+
TMXNodeType["Object"] = "object";
|
|
13
|
+
TMXNodeType["Objectgroup"] = "objectgroup";
|
|
14
|
+
TMXNodeType["Properties"] = "properties";
|
|
15
|
+
TMXNodeType["Property"] = "property";
|
|
16
|
+
TMXNodeType["Tileset"] = "tileset";
|
|
17
|
+
})(TMXNodeType || (TMXNodeType = {}));
|
|
18
|
+
|
|
19
|
+
class TMXMapShared {
|
|
20
|
+
version = 0;
|
|
21
|
+
tiledversion = "";
|
|
22
|
+
orientation = "";
|
|
23
|
+
renderorder = "";
|
|
24
|
+
width = 0;
|
|
25
|
+
height = 0;
|
|
26
|
+
tilewidth = 0;
|
|
27
|
+
tileheight = 0;
|
|
28
|
+
infinite = 0;
|
|
29
|
+
nextlayerid = 0;
|
|
30
|
+
nextobjectid = 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class TMXMapParsed extends TMXMapShared {
|
|
34
|
+
editorsettings = {};
|
|
35
|
+
tilesets = [];
|
|
36
|
+
layers = [];
|
|
37
|
+
properties = [];
|
|
38
|
+
constructor(init) {
|
|
39
|
+
super();
|
|
40
|
+
Object.assign(this, init);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const parseGroup = async (node, expectedCount, translateFlips) => {
|
|
45
|
+
const { $, $$ } = node;
|
|
46
|
+
const group = structuredClone($);
|
|
47
|
+
group.type = node["#name"];
|
|
48
|
+
if ($$)
|
|
49
|
+
group.layers = await Promise.all($$.map((l) => parseNode(l, expectedCount, translateFlips)));
|
|
50
|
+
return group;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
var Flipped;
|
|
54
|
+
(function (Flipped) {
|
|
55
|
+
Flipped[Flipped["Diagonally"] = 536870912] = "Diagonally";
|
|
56
|
+
Flipped[Flipped["Horizontally"] = 2147483648] = "Horizontally";
|
|
57
|
+
Flipped[Flipped["Vertically"] = 1073741824] = "Vertically";
|
|
58
|
+
})(Flipped || (Flipped = {}));
|
|
59
|
+
|
|
60
|
+
const parseFlips = (gid) => ({
|
|
61
|
+
H: Boolean(gid & Flipped.Horizontally),
|
|
62
|
+
V: Boolean(gid & Flipped.Vertically),
|
|
63
|
+
D: Boolean(gid & Flipped.Diagonally),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
var Shape;
|
|
67
|
+
(function (Shape) {
|
|
68
|
+
Shape["Ellipse"] = "ellipse";
|
|
69
|
+
Shape["Point"] = "point";
|
|
70
|
+
Shape["Polygon"] = "polygon";
|
|
71
|
+
Shape["Rectangle"] = "rectangle";
|
|
72
|
+
})(Shape || (Shape = {}));
|
|
73
|
+
|
|
74
|
+
const parseObjectShape = (node) => {
|
|
75
|
+
if ("point" in node)
|
|
76
|
+
return Shape.Point;
|
|
77
|
+
else if ("ellipse" in node)
|
|
78
|
+
return Shape.Ellipse;
|
|
79
|
+
else if ("polygon" in node)
|
|
80
|
+
return Shape.Polygon;
|
|
81
|
+
else
|
|
82
|
+
return Shape.Rectangle;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const parseProperties = (properties) => properties
|
|
86
|
+
? properties.map(({ property }) => {
|
|
87
|
+
const { $, _ } = property[0];
|
|
88
|
+
const { name, value } = $;
|
|
89
|
+
return { name, value: value ?? _ };
|
|
90
|
+
})
|
|
91
|
+
: undefined;
|
|
92
|
+
|
|
93
|
+
const parseTileId = (gid) => (gid &= ~Object.values(Flipped).reduce((acc, curr) => acc | curr, 0));
|
|
94
|
+
|
|
95
|
+
const parseObject = (node) => {
|
|
96
|
+
const { $, polygon, text, properties } = node;
|
|
97
|
+
const object = structuredClone($);
|
|
98
|
+
object.shape = parseObjectShape(node);
|
|
99
|
+
if (properties)
|
|
100
|
+
object.properties = parseProperties(properties);
|
|
101
|
+
if (polygon)
|
|
102
|
+
object.points = polygon[0].$.points.split(" ").map((point) => {
|
|
103
|
+
const [x, y] = point.split(",");
|
|
104
|
+
return [parseFloat(x), parseFloat(y)];
|
|
105
|
+
});
|
|
106
|
+
if (text) {
|
|
107
|
+
const textNode = text[0];
|
|
108
|
+
object.text = textNode._;
|
|
109
|
+
object.properties = Object.assign({}, object.properties, textNode.$);
|
|
110
|
+
}
|
|
111
|
+
if (object.gid) {
|
|
112
|
+
object.flips = parseFlips(object.gid);
|
|
113
|
+
object.gid = parseTileId(object.gid);
|
|
114
|
+
}
|
|
115
|
+
return object;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const parseLayer = (node) => {
|
|
119
|
+
const { $, image, object, properties } = node;
|
|
120
|
+
const layer = structuredClone($);
|
|
121
|
+
layer.type = node["#name"];
|
|
122
|
+
layer.visible = 1;
|
|
123
|
+
if (image)
|
|
124
|
+
layer.image = structuredClone(image[0].$);
|
|
125
|
+
if (object)
|
|
126
|
+
layer.objects = object.map((o) => parseObject(o));
|
|
127
|
+
if (properties)
|
|
128
|
+
layer.properties = parseProperties(properties);
|
|
129
|
+
return layer;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
var Compression;
|
|
133
|
+
(function (Compression) {
|
|
134
|
+
Compression["Gzip"] = "gzip";
|
|
135
|
+
Compression["Zlib"] = "zlib";
|
|
136
|
+
})(Compression || (Compression = {}));
|
|
137
|
+
|
|
138
|
+
var Encoding;
|
|
139
|
+
(function (Encoding) {
|
|
140
|
+
Encoding["Base64"] = "base64";
|
|
141
|
+
Encoding["Csv"] = "csv";
|
|
142
|
+
})(Encoding || (Encoding = {}));
|
|
143
|
+
|
|
144
|
+
const unpackTileBytes = (buffer, expectedCount) => {
|
|
145
|
+
const unpackedTiles = [];
|
|
146
|
+
if (buffer.length !== expectedCount)
|
|
147
|
+
throw new Error(`Expected ${expectedCount} bytes of tile data; received ${buffer.length}`);
|
|
148
|
+
for (let i = 0; i < expectedCount; i += 4)
|
|
149
|
+
unpackedTiles.push(buffer.readUInt32LE(i));
|
|
150
|
+
return unpackedTiles;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const isTMXEmbeddedTilesetNode = (node) => "tile" in node;
|
|
154
|
+
const parseTileLayer = async (node, expectedCount, translateFlips) => {
|
|
155
|
+
const { data, properties } = node;
|
|
156
|
+
if (!data)
|
|
157
|
+
throw new Error("TMXLayer data corrupted!");
|
|
158
|
+
const layer = structuredClone(node.$);
|
|
159
|
+
layer.type = node["#name"];
|
|
160
|
+
if (properties)
|
|
161
|
+
layer.properties = parseProperties(properties);
|
|
162
|
+
const nodeData = data[0];
|
|
163
|
+
// Xml Deprecated
|
|
164
|
+
if (isTMXEmbeddedTilesetNode(nodeData))
|
|
165
|
+
layer.data = nodeData.tile?.map(({ $ }) => $.gid ?? 0) ?? [];
|
|
166
|
+
else {
|
|
167
|
+
// Csv, Base64
|
|
168
|
+
const { $, _ } = nodeData;
|
|
169
|
+
const { encoding, compression } = $;
|
|
170
|
+
const layerData = _.trim();
|
|
171
|
+
switch (encoding) {
|
|
172
|
+
case Encoding.Csv:
|
|
173
|
+
layer.data = layerData.split(",").map((d) => parseInt(d));
|
|
174
|
+
break;
|
|
175
|
+
case Encoding.Base64: {
|
|
176
|
+
const buffer = Buffer.from(layerData, encoding);
|
|
177
|
+
switch (compression) {
|
|
178
|
+
case Compression.Gzip:
|
|
179
|
+
case Compression.Zlib:
|
|
180
|
+
{
|
|
181
|
+
const decompress = compression === Compression.Gzip ? gunzip : inflate;
|
|
182
|
+
layer.data = await new Promise((resolve, reject) => {
|
|
183
|
+
decompress(buffer, (err, buf) => {
|
|
184
|
+
if (err)
|
|
185
|
+
reject(err);
|
|
186
|
+
resolve(unpackTileBytes(buf, expectedCount));
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
case null:
|
|
192
|
+
case undefined:
|
|
193
|
+
layer.data = unpackTileBytes(buffer, expectedCount);
|
|
194
|
+
break;
|
|
195
|
+
default:
|
|
196
|
+
exhaustiveGuard(compression);
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
default:
|
|
201
|
+
exhaustiveGuard(encoding);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (translateFlips) {
|
|
205
|
+
layer.flips = [];
|
|
206
|
+
layer.data ??= [];
|
|
207
|
+
for (const gid of layer.data) {
|
|
208
|
+
layer.flips.push(parseFlips(gid));
|
|
209
|
+
layer.data.push(parseTileId(gid));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return layer;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const parseNode = (node, expectedCount, translateFlips) => {
|
|
216
|
+
const tmxNodeType = node["#name"];
|
|
217
|
+
switch (tmxNodeType) {
|
|
218
|
+
case TMXNodeType.Group:
|
|
219
|
+
return parseGroup(node, expectedCount, translateFlips);
|
|
220
|
+
case TMXNodeType.Layer:
|
|
221
|
+
return parseTileLayer(node, expectedCount, translateFlips);
|
|
222
|
+
case TMXNodeType.ImageLayer:
|
|
223
|
+
case TMXNodeType.Objectgroup:
|
|
224
|
+
return parseLayer(node);
|
|
225
|
+
default:
|
|
226
|
+
throw new InvalidOperationError(Operation.Read, parseNode.name, tmxNodeType);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const isExternalTileset = (tileset) => "source" in tileset;
|
|
231
|
+
|
|
232
|
+
const parseTile = (node) => {
|
|
233
|
+
const { $, animation, objectgroup, properties } = node;
|
|
234
|
+
const tile = structuredClone($);
|
|
235
|
+
if (animation)
|
|
236
|
+
tile.animation = {
|
|
237
|
+
frames: animation[0].frame.map(({ $ }) => structuredClone($)),
|
|
238
|
+
};
|
|
239
|
+
if (objectgroup)
|
|
240
|
+
tile.objects = objectgroup[0].object.map((o) => parseObject(o));
|
|
241
|
+
if (properties)
|
|
242
|
+
tile.properties = parseProperties(properties);
|
|
243
|
+
return tile;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const parseTileset = (node) => {
|
|
247
|
+
if (isExternalTileset(node.$))
|
|
248
|
+
return structuredClone(node.$);
|
|
249
|
+
const { $, $$, tile } = node;
|
|
250
|
+
for (const childNode of $$ ?? []) {
|
|
251
|
+
const tmxNodeType = childNode["#name"];
|
|
252
|
+
if (tmxNodeType !== TMXNodeType.Image)
|
|
253
|
+
continue;
|
|
254
|
+
const image = structuredClone(childNode.$);
|
|
255
|
+
const tiles = tile?.map((t) => parseTile(t)) ?? [];
|
|
256
|
+
return { ...$, image, tiles };
|
|
257
|
+
}
|
|
258
|
+
throw new InvalidOperationError(Operation.Read, parseTileset.name, $.name);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// We will try and match phaser's transform when exporting tmx => json tilemaps
|
|
262
|
+
// but also support extra functionality like using external tilesets
|
|
263
|
+
const parseTmx = async (xmlString, translateFlips = false) => {
|
|
264
|
+
const { map: { $, $$ }, } = (await parseXmlString(xmlString));
|
|
265
|
+
const map = new TMXMapParsed(structuredClone($));
|
|
266
|
+
const expectedCount = map.width * map.height * 4;
|
|
267
|
+
await Promise.all($$.map(async (node) => {
|
|
268
|
+
const tmxNodeType = node["#name"];
|
|
269
|
+
switch (tmxNodeType) {
|
|
270
|
+
case TMXNodeType.EditorSettings:
|
|
271
|
+
if (!node.$$)
|
|
272
|
+
break;
|
|
273
|
+
map.editorsettings = { ...node.$$.map((n) => ({ [n["#name"]]: n.$ })) };
|
|
274
|
+
break;
|
|
275
|
+
case TMXNodeType.Group:
|
|
276
|
+
case TMXNodeType.ImageLayer:
|
|
277
|
+
case TMXNodeType.Layer:
|
|
278
|
+
case TMXNodeType.Objectgroup:
|
|
279
|
+
{
|
|
280
|
+
const layer = await parseNode(node, expectedCount, translateFlips);
|
|
281
|
+
map.layers.push(layer);
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
case TMXNodeType.Properties:
|
|
285
|
+
if (!node.$$)
|
|
286
|
+
break;
|
|
287
|
+
map.properties = {
|
|
288
|
+
...node.$$.map(({ $: { name, value } }) => ({ [name]: value })),
|
|
289
|
+
};
|
|
290
|
+
break;
|
|
291
|
+
case TMXNodeType.Tileset:
|
|
292
|
+
map.tilesets.push(parseTileset(node));
|
|
293
|
+
break;
|
|
294
|
+
case TMXNodeType.Export:
|
|
295
|
+
case TMXNodeType.Image:
|
|
296
|
+
case TMXNodeType.Object:
|
|
297
|
+
case TMXNodeType.Property:
|
|
298
|
+
break;
|
|
299
|
+
default:
|
|
300
|
+
exhaustiveGuard(tmxNodeType);
|
|
301
|
+
}
|
|
302
|
+
}));
|
|
303
|
+
return { map };
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
export { Compression, Encoding, Flipped, Shape, TMXMapParsed, TMXMapShared, TMXNodeType, isExternalTileset, parseFlips, parseGroup, parseLayer, parseNode, parseObject, parseObjectShape, parseProperties, parseTile, parseTileId, parseTileLayer, parseTileset, parseTmx, unpackTileBytes };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parse-tmx",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "A parser for tmx",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"export:gen": "ctix build --config ../configuration/.ctirc"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@esposter/shared": "1.
|
|
33
|
+
"@esposter/shared": "1.9.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@esposter/configuration": "1.
|
|
36
|
+
"@esposter/configuration": "1.9.1",
|
|
37
37
|
"@types/node": "^20.12.12"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "39cc371b6c74450fd3b708847d4249a6c3d19deb"
|
|
40
40
|
}
|