|
|
- import DataScanner from "../util/scanner";
-
- export enum TileType {
- WALKABLE,
- OBSTRUCTED,
- CLIFF,
- }
-
- export enum Corner {
- TOP_LEFT,
- TOP_RIGHT,
- BOTTOM_RIGHT,
- BOTTOM_LEFT,
- }
-
- export type TileAltitudes = Record<Corner, number>;
-
- export type Tile = {
- altitude: TileAltitudes;
- ty: TileType;
- };
-
- export type GAT = {
- height: number;
- tiles: Tile[];
- width: number;
- };
-
- export class ParseError extends Error {
- constructor(message: string) {
- super(message);
- }
- }
-
- const HEADER_MAGIC = 0x54415247;
- const HEADER_SIZE_BYTES = 14;
- const SUPPORTED_VERSION = "1.2";
- const TILE_SIZE_BYTES = 20;
- const SCALING_FACTOR = -1 / 5;
-
- const TERRAIN_TYPE_TO_TILE_TYPE: Record<number, TileType> = {
- 0: TileType.WALKABLE,
- 1: TileType.OBSTRUCTED,
- 5: TileType.CLIFF,
- };
-
- export const parseGAT = (data: ArrayBuffer): GAT => {
- const scanner = new DataScanner(data);
-
- const magic = scanner.uint32();
- if (magic !== HEADER_MAGIC) {
- throw new ParseError("invalid magic number");
- }
-
- const version = `${scanner.uint8()}.${scanner.uint8()}`;
- if (version !== SUPPORTED_VERSION) {
- throw new ParseError(`unsupported file version ${version}`);
- }
-
- const width = scanner.uint32();
- const height = scanner.uint32();
-
- const expectedSize = HEADER_SIZE_BYTES + width * height * TILE_SIZE_BYTES;
- if (data.byteLength !== expectedSize) {
- throw new ParseError(`unexpected size of data`);
- }
-
- const tiles = [];
- for (let i = 0; i < width * height; ++i) {
- tiles[i] = parseTile(scanner);
- }
-
- return {
- height,
- tiles,
- width,
- };
- };
-
- const parseTile = (scanner: DataScanner): Tile => {
- const bottomLeft = scanner.float32();
- const bottomRight = scanner.float32();
- const topLeft = scanner.float32();
- const topRight = scanner.float32();
-
- const terrainType = scanner.uint32() & 0xffff;
- if (typeof TERRAIN_TYPE_TO_TILE_TYPE[terrainType] === "undefined") {
- throw new Error(`unknown terrain type 0x${terrainType.toString(16)}`);
- }
-
- return {
- ty: TERRAIN_TYPE_TO_TILE_TYPE[terrainType],
- altitude: {
- [Corner.TOP_LEFT]: topLeft * SCALING_FACTOR,
- [Corner.TOP_RIGHT]: topRight * SCALING_FACTOR,
- [Corner.BOTTOM_RIGHT]: bottomRight * SCALING_FACTOR,
- [Corner.BOTTOM_LEFT]: bottomLeft * SCALING_FACTOR,
- },
- };
- };
|