UNPKG

patchwork-mapconverter

Version:

Executable wrapper for https://github.com/ChiefOfGxBxL/WC3MapTranslator

128 lines (107 loc) 4.34 kB
import { HexBuffer } from '../HexBuffer' import { W3Buffer } from '../W3Buffer' import { type WarResult, type JsonResult } from '../CommonInterfaces' import { type Translator } from './Translator' import { type Region } from '../data/Region' export class RegionsTranslator implements Translator<Region[]> { private static instance: RegionsTranslator private constructor () {} public static getInstance (): RegionsTranslator { if (this.instance == null) { this.instance = new this() } return this.instance } public static jsonToWar (regions: Region[]): WarResult { return this.getInstance().jsonToWar(regions) } public static warToJson (buffer: Buffer): JsonResult<Region[]> { return this.getInstance().warToJson(buffer) } public jsonToWar (regionsJson: Region[]): WarResult { const outBufferToWar = new HexBuffer() /* * Header */ outBufferToWar.addInt(5) // file version outBufferToWar.addInt(regionsJson?.length || 0) // number of regions /* * Body */ regionsJson?.forEach(region => { // Position // Note that the .w3x guide has these coords wrong - the guide swaps bottom and right, but this is incorrect; bottom should be written before right outBufferToWar.addFloat(region.position.left) outBufferToWar.addFloat(region.position.bottom) outBufferToWar.addFloat(region.position.right) outBufferToWar.addFloat(region.position.top) outBufferToWar.addString(region.name) outBufferToWar.addInt(region.id) // Weather effect name - lookup necessary: char[4] if (region.weatherEffect != null) { outBufferToWar.addChars(region.weatherEffect) // Weather effect is optional - defaults to 0000 for "none" } else { // We can't put a string "0000", because ASCII 0's differ from 0x0 bytes outBufferToWar.addByte(0) outBufferToWar.addByte(0) outBufferToWar.addByte(0) outBufferToWar.addByte(0) } // Ambient sound - refer to names defined in .w3s file outBufferToWar.addString(region.ambientSound != null ? region.ambientSound : '') // May be empty string // Color of region used by editor // Careful! The order in .w3r is BB GG RR, whereas the JSON spec order is [RR, GG, BB] outBufferToWar.addByte(region.color[2]) // blue outBufferToWar.addByte(region.color[1]) // green outBufferToWar.addByte(region.color[0]) // red // End of structure - for some reason the .w3r needs this here; // Value is set to 0xff based on observing the .w3r file, but not sure if it could be something else outBufferToWar.addByte(0xff) }) return { errors: [], buffer: outBufferToWar.getBuffer() } } public warToJson (buffer: Buffer): JsonResult<Region[]> { const result: Region[] = [] const outBufferToJSON = new W3Buffer(buffer) const fileVersion = outBufferToJSON.readInt() // File version const numRegions = outBufferToJSON.readInt() // # of regions for (let i = 0; i < numRegions; i++) { const region: Region = { name: '', id: 0, weatherEffect: '', ambientSound: '', color: [0, 0, 0], position: { left: 0, bottom: 0, right: 0, top: 0 } } region.position.left = outBufferToJSON.readFloat() region.position.bottom = outBufferToJSON.readFloat() region.position.right = outBufferToJSON.readFloat() region.position.top = outBufferToJSON.readFloat() region.name = outBufferToJSON.readString() region.id = outBufferToJSON.readInt() region.weatherEffect = outBufferToJSON.readChars(4) region.ambientSound = outBufferToJSON.readString() region.color = [ outBufferToJSON.readByte(), // red outBufferToJSON.readByte(), // green outBufferToJSON.readByte() // blue ] region.color.reverse() // json wants it in RGB, but .w3r file stores it as BB GG RR outBufferToJSON.readByte() // end of region structure result.push(region) } return { errors: [], json: result } } }