ts-tiled-converter
Version:
Typescript library to convert tiled map to Studio map
47 lines (37 loc) • 1.91 kB
text/typescript
import { unzipSync } from 'zlib';
import { TiledXMLData, TiledXMLLayer, getXMLProperties } from '../tiledXML/objects';
import type { TileMetaData } from '../types';
export const layerToTiles = (layer: TiledXMLLayer, cache: Map<number, TileMetaData | null>) => {
cache.set(0, null);
const data = decodeLayer(layer);
if (data instanceof Error) return data;
return data.map((v) => {
const tileData = cache.get(v);
if (tileData !== undefined) return tileData;
const newTileData: TileMetaData = {
globalId: v & 0x0fffffff,
transformId: (v >> 28) & 0xf,
};
cache.set(v, newTileData);
return newTileData;
});
};
const decodeLayer = ({ layer }: TiledXMLLayer) => {
const data = layer.find((v): v is TiledXMLData => 'data' in v);
if (!data) return new Error('Failed to find data in layer');
if (!data.data[0] || !('rawData' in data.data[0])) return new Error('Failed to find content in data layer');
const { encoding, compression } = getXMLProperties(data);
if (encoding === 'csv') return decodeCSVLayer(data);
if (encoding !== 'base64') return new Error('Unsupported layer data encoding');
if (compression === 'gzip' || compression === 'zlib') return decodeCompressedLayer(data);
if (compression !== 'zstd') return decodeBuffer(Buffer.from(data.data[0].rawData, 'base64'));
return new Error('Unsupported layer data compression');
};
const decodeCSVLayer = ({ data }: TiledXMLData) => data[0].rawData.split(',').map(Number);
const decodeCompressedLayer = ({ data }: TiledXMLData) => decodeBuffer(unzipSync(Buffer.from(data[0].rawData, 'base64')));
const decodeBuffer = (buffer: Buffer) => {
const dwordLength = Math.floor(buffer.length / 4);
const returnArray = Array<number>(dwordLength);
for (let i = 0; i < dwordLength; i++) returnArray[i] = buffer.readUint32LE(i * 4);
return returnArray;
};