wc3maptranslator 3.0.3 → 4.0.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/.codeclimate.yml +0 -1
- package/.eslintignore +0 -1
- package/.github/workflows/codeql-analysis.yml +54 -0
- package/.nycrc +1 -2
- package/.travis.yml +1 -2
- package/CHANGELOG.md +78 -0
- package/LICENSE.md +23 -0
- package/README.md +68 -75
- package/index.js +11 -15
- package/index.ts +12 -30
- package/lib/CommonInterfaces.ts +22 -0
- package/lib/HexBuffer.ts +11 -14
- package/lib/W3Buffer.ts +7 -3
- package/lib/translators/CamerasTranslator.ts +36 -41
- package/lib/translators/DoodadsTranslator.ts +57 -55
- package/lib/translators/ImportsTranslator.ts +29 -31
- package/lib/translators/InfoTranslator.ts +252 -204
- package/lib/translators/{object/ObjectsTranslator.ts → ObjectsTranslator.ts} +84 -82
- package/lib/translators/RegionsTranslator.ts +40 -58
- package/lib/translators/SoundsTranslator.ts +112 -96
- package/lib/translators/StringsTranslator.ts +23 -49
- package/lib/translators/TerrainTranslator.ts +166 -97
- package/lib/translators/UnitsTranslator.ts +98 -97
- package/lib/translators/index.ts +0 -1
- package/package.json +23 -16
- package/test/.mocharc.json +4 -0
- package/test/HexBufferTest.ts +11 -15
- package/test/TranslatorReversion.ts +104 -115
- package/test/W3BufferTest.ts +19 -13
- package/test/data/cameras.json +16 -0
- package/test/data/doodads.json +2730 -0
- package/test/data/imports.json +386 -0
- package/test/data/info.json +250 -0
- package/test/data/obj-abilities.json +4892 -0
- package/test/data/obj-buffs.json +38 -0
- package/test/data/obj-destructables.json +31 -0
- package/test/data/obj-doodads.json +38 -0
- package/test/data/obj-items.json +31 -0
- package/test/data/obj-units.json +40 -0
- package/test/data/obj-upgrades.json +38 -0
- package/test/data/regions.json +206 -0
- package/test/data/sounds.json +50 -0
- package/test/data/strings.json +115 -0
- package/test/data/terrain.json +1 -0
- package/test/data/units.json +452 -0
- package/test/data/war3map.doo +0 -0
- package/test/data/war3map.imp +0 -0
- package/test/data/war3map.j +3442 -0
- package/test/data/war3map.shd +0 -0
- package/test/data/war3map.w3a +0 -0
- package/test/data/war3map.w3b +0 -0
- package/test/data/war3map.w3c +0 -0
- package/test/data/war3map.w3d +0 -0
- package/test/data/war3map.w3e +0 -0
- package/test/data/war3map.w3h +0 -0
- package/test/data/war3map.w3i +0 -0
- package/test/data/war3map.w3q +0 -0
- package/test/data/war3map.w3r +0 -0
- package/test/data/war3map.w3s +0 -0
- package/test/data/war3map.w3t +0 -0
- package/test/data/war3map.w3u +0 -0
- package/test/data/war3map.wts +631 -0
- package/test/data/war3mapUnits.doo +0 -0
- package/examples/index.js +0 -123
- package/examples/index.ts +0 -134
- package/examples/json/cameras.json +0 -16
- package/examples/json/doodads.json +0 -28499
- package/examples/json/imports.json +0 -10
- package/examples/json/info.json +0 -111
- package/examples/json/object-abilities.json +0 -31
- package/examples/json/object-buffs.json +0 -24
- package/examples/json/object-destructables.json +0 -31
- package/examples/json/object-doodads.json +0 -24
- package/examples/json/object-items.json +0 -45
- package/examples/json/object-units.json +0 -45
- package/examples/json/object-upgrades.json +0 -31
- package/examples/json/regions.json +0 -36
- package/examples/json/sounds.json +0 -46
- package/examples/json/strings.json +0 -83
- package/examples/json/terrain.json +0 -46633
- package/examples/json/units.json +0 -332
- package/examples/package.json +0 -17
- package/examples/tsconfig.json +0 -27
- package/examples/war/war3map.doo +0 -0
- package/examples/war/war3map.imp +0 -0
- package/examples/war/war3map.w3a +0 -0
- package/examples/war/war3map.w3b +0 -0
- package/examples/war/war3map.w3c +0 -0
- package/examples/war/war3map.w3d +0 -0
- package/examples/war/war3map.w3e +0 -0
- package/examples/war/war3map.w3h +0 -0
- package/examples/war/war3map.w3i +0 -0
- package/examples/war/war3map.w3q +0 -0
- package/examples/war/war3map.w3r +0 -0
- package/examples/war/war3map.w3s +0 -0
- package/examples/war/war3map.w3t +0 -0
- package/examples/war/war3map.w3u +0 -0
- package/examples/war/war3map.wts +0 -99
- package/lib/translators/index.js +0 -16
- package/test/mocha.opts +0 -4
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { HexBuffer } from '../HexBuffer';
|
|
2
2
|
import { W3Buffer } from '../W3Buffer';
|
|
3
|
+
import { WarResult, JsonResult } from '../CommonInterfaces'
|
|
3
4
|
|
|
4
5
|
interface Terrain {
|
|
5
6
|
tileset: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
customTileset: boolean;
|
|
8
|
+
tilePalette: string[];
|
|
9
|
+
cliffTilePalette: string[];
|
|
9
10
|
map: Map;
|
|
10
|
-
|
|
11
|
+
// "Masks"
|
|
12
|
+
groundHeight: number[],
|
|
13
|
+
waterHeight: number[],
|
|
14
|
+
boundaryFlag: boolean[],
|
|
15
|
+
flags: number[],
|
|
16
|
+
groundTexture: number[],
|
|
17
|
+
groundVariation: number[],
|
|
18
|
+
cliffVariation: number[],
|
|
19
|
+
cliffTexture: number[],
|
|
20
|
+
layerHeight: number[]
|
|
11
21
|
}
|
|
12
22
|
|
|
13
23
|
interface Map {
|
|
@@ -21,83 +31,118 @@ interface Offset {
|
|
|
21
31
|
y: number;
|
|
22
32
|
}
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
function splitLargeArrayIntoWidthArrays(array: any[], width: number) {
|
|
35
|
+
const rows = [];
|
|
36
|
+
for(let i = 0; i < array.length / width; i++) {
|
|
37
|
+
rows.push(array.slice(i * width, (i+1) * width));
|
|
38
|
+
}
|
|
39
|
+
return rows;
|
|
40
|
+
}
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
export abstract class TerrainTranslator {
|
|
30
43
|
|
|
31
|
-
public jsonToWar(terrainJson: Terrain) {
|
|
32
|
-
|
|
44
|
+
public static jsonToWar(terrainJson: Terrain): WarResult {
|
|
45
|
+
const outBufferToWar = new HexBuffer();
|
|
33
46
|
|
|
34
47
|
/*
|
|
35
48
|
* Header
|
|
36
49
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
outBufferToWar.addChars('W3E!'); // file id
|
|
51
|
+
outBufferToWar.addInt(11); // file version
|
|
52
|
+
outBufferToWar.addChar(terrainJson.tileset); // base tileset
|
|
53
|
+
outBufferToWar.addInt(+terrainJson.customTileset); // 1 = using custom tileset, 0 = not
|
|
41
54
|
|
|
42
55
|
/*
|
|
43
56
|
* Tiles
|
|
44
57
|
*/
|
|
45
|
-
|
|
46
|
-
terrainJson.
|
|
47
|
-
|
|
58
|
+
outBufferToWar.addInt(terrainJson.tilePalette.length);
|
|
59
|
+
terrainJson.tilePalette.forEach((tile) => {
|
|
60
|
+
outBufferToWar.addChars(tile);
|
|
48
61
|
});
|
|
49
62
|
|
|
50
63
|
/*
|
|
51
64
|
* Cliffs
|
|
52
65
|
*/
|
|
53
|
-
|
|
54
|
-
terrainJson.
|
|
55
|
-
|
|
66
|
+
outBufferToWar.addInt(terrainJson.cliffTilePalette.length);
|
|
67
|
+
terrainJson.cliffTilePalette.forEach((cliffTile) => {
|
|
68
|
+
outBufferToWar.addChars(cliffTile);
|
|
56
69
|
});
|
|
57
70
|
|
|
58
71
|
/*
|
|
59
72
|
* Map size data
|
|
60
73
|
*/
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
outBufferToWar.addInt(terrainJson.map.width + 1);
|
|
75
|
+
outBufferToWar.addInt(terrainJson.map.height + 1);
|
|
63
76
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
/*
|
|
78
|
+
* Map offset
|
|
79
|
+
*/
|
|
80
|
+
outBufferToWar.addFloat(terrainJson.map.offset.x);
|
|
81
|
+
outBufferToWar.addFloat(terrainJson.map.offset.y);
|
|
67
82
|
|
|
68
83
|
/*
|
|
69
84
|
* Tile points
|
|
70
85
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
// Partition the terrainJson masks into "chunks" (i.e. rows) of (width+1) length,
|
|
87
|
+
// reverse that list of rows (due to vertical flipping), and then write the rows out
|
|
88
|
+
const rows = {
|
|
89
|
+
groundHeight: splitLargeArrayIntoWidthArrays(terrainJson.groundHeight, terrainJson.map.width + 1),
|
|
90
|
+
waterHeight: splitLargeArrayIntoWidthArrays(terrainJson.waterHeight, terrainJson.map.width + 1),
|
|
91
|
+
boundaryFlag: splitLargeArrayIntoWidthArrays(terrainJson.boundaryFlag, terrainJson.map.width + 1),
|
|
92
|
+
flags: splitLargeArrayIntoWidthArrays(terrainJson.flags, terrainJson.map.width + 1),
|
|
93
|
+
groundTexture: splitLargeArrayIntoWidthArrays(terrainJson.groundTexture, terrainJson.map.width + 1),
|
|
94
|
+
groundVariation: splitLargeArrayIntoWidthArrays(terrainJson.groundVariation, terrainJson.map.width + 1),
|
|
95
|
+
cliffVariation: splitLargeArrayIntoWidthArrays(terrainJson.cliffVariation, terrainJson.map.width + 1),
|
|
96
|
+
cliffTexture: splitLargeArrayIntoWidthArrays(terrainJson.cliffTexture, terrainJson.map.width + 1),
|
|
97
|
+
layerHeight: splitLargeArrayIntoWidthArrays(terrainJson.layerHeight, terrainJson.map.width + 1)
|
|
98
|
+
};
|
|
76
99
|
|
|
77
|
-
|
|
100
|
+
rows.groundHeight.reverse();
|
|
101
|
+
rows.waterHeight.reverse();
|
|
102
|
+
rows.boundaryFlag.reverse();
|
|
103
|
+
rows.flags.reverse();
|
|
104
|
+
rows.groundTexture.reverse();
|
|
105
|
+
rows.groundVariation.reverse();
|
|
106
|
+
rows.cliffVariation.reverse();
|
|
107
|
+
rows.cliffTexture.reverse();
|
|
108
|
+
rows.layerHeight.reverse();
|
|
78
109
|
|
|
110
|
+
for(let i = 0; i < rows.groundHeight.length; i++) {
|
|
111
|
+
for(let j = 0; j < rows.groundHeight[i].length; j++) {
|
|
79
112
|
// these bit operations are based off documentation from https://github.com/stijnherfst/HiveWE/wiki/war3map.w3e-Terrain
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
113
|
+
const groundHeight = rows.groundHeight[i][j];
|
|
114
|
+
const waterHeight = rows.waterHeight[i][j];
|
|
115
|
+
const boundaryFlag = rows.boundaryFlag[i][j];
|
|
116
|
+
const flags = rows.flags[i][j];
|
|
117
|
+
const groundTexture = rows.groundTexture[i][j];
|
|
118
|
+
const groundVariation = rows.groundVariation[i][j];
|
|
119
|
+
const cliffVariation = rows.cliffVariation[i][j];
|
|
120
|
+
const cliffTexture = rows.cliffTexture[i][j];
|
|
121
|
+
const layerHeight = rows.layerHeight[i][j];
|
|
122
|
+
|
|
123
|
+
const hasBoundaryFlag = boundaryFlag ? 0x4000 : 0;
|
|
124
|
+
|
|
125
|
+
outBufferToWar.addShort(groundHeight);
|
|
126
|
+
outBufferToWar.addShort(waterHeight | hasBoundaryFlag);
|
|
127
|
+
outBufferToWar.addByte(flags | groundTexture);
|
|
128
|
+
outBufferToWar.addByte(groundVariation | cliffVariation);
|
|
129
|
+
outBufferToWar.addByte(cliffTexture | layerHeight);
|
|
85
130
|
}
|
|
86
131
|
}
|
|
87
132
|
|
|
88
133
|
return {
|
|
89
134
|
errors: [],
|
|
90
|
-
buffer:
|
|
135
|
+
buffer: outBufferToWar.getBuffer()
|
|
91
136
|
};
|
|
92
137
|
}
|
|
93
138
|
|
|
94
|
-
public warToJson(buffer: Buffer) {
|
|
139
|
+
public static warToJson(buffer: Buffer): JsonResult<Terrain> {
|
|
95
140
|
// create buffer
|
|
96
141
|
const result: Terrain = {
|
|
97
142
|
tileset: '',
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
143
|
+
customTileset: false,
|
|
144
|
+
tilePalette: [],
|
|
145
|
+
cliffTilePalette: [],
|
|
101
146
|
map: {
|
|
102
147
|
width: 1,
|
|
103
148
|
height: 1,
|
|
@@ -106,98 +151,122 @@ export class TerrainTranslator {
|
|
|
106
151
|
y: 0
|
|
107
152
|
}
|
|
108
153
|
},
|
|
109
|
-
|
|
154
|
+
groundHeight: [],
|
|
155
|
+
waterHeight: [],
|
|
156
|
+
boundaryFlag: [],
|
|
157
|
+
flags: [],
|
|
158
|
+
groundTexture: [],
|
|
159
|
+
groundVariation: [],
|
|
160
|
+
cliffVariation: [],
|
|
161
|
+
cliffTexture: [],
|
|
162
|
+
layerHeight: []
|
|
110
163
|
};
|
|
111
|
-
|
|
164
|
+
const outBufferToJSON = new W3Buffer(buffer);
|
|
112
165
|
|
|
113
166
|
/**
|
|
114
167
|
* Header
|
|
115
168
|
*/
|
|
116
|
-
const w3eHeader =
|
|
117
|
-
const version =
|
|
118
|
-
const tileset =
|
|
119
|
-
const
|
|
169
|
+
const w3eHeader = outBufferToJSON.readChars(4); // W3E!
|
|
170
|
+
const version = outBufferToJSON.readInt(); // 0B 00 00 00
|
|
171
|
+
const tileset = outBufferToJSON.readChars(1); // tileset
|
|
172
|
+
const customTileset = (outBufferToJSON.readInt() === 1);
|
|
120
173
|
|
|
121
174
|
result.tileset = tileset;
|
|
122
|
-
result.
|
|
175
|
+
result.customTileset = customTileset;
|
|
123
176
|
|
|
124
177
|
/**
|
|
125
178
|
* Tiles
|
|
126
179
|
*/
|
|
127
|
-
const numTilePalettes =
|
|
180
|
+
const numTilePalettes = outBufferToJSON.readInt();
|
|
128
181
|
const tilePalettes = [];
|
|
129
182
|
for (let i = 0; i < numTilePalettes; i++) {
|
|
130
|
-
tilePalettes.push(
|
|
183
|
+
tilePalettes.push(outBufferToJSON.readChars(4));
|
|
131
184
|
}
|
|
132
185
|
|
|
133
|
-
result.
|
|
186
|
+
result.tilePalette = tilePalettes;
|
|
134
187
|
|
|
135
188
|
/**
|
|
136
189
|
* Cliffs
|
|
137
190
|
*/
|
|
138
|
-
const numCliffTilePalettes =
|
|
191
|
+
const numCliffTilePalettes = outBufferToJSON.readInt();
|
|
139
192
|
const cliffPalettes = [];
|
|
140
193
|
for (let i = 0; i < numCliffTilePalettes; i++) {
|
|
141
|
-
const cliffPalette =
|
|
194
|
+
const cliffPalette = outBufferToJSON.readChars(4);
|
|
142
195
|
cliffPalettes.push(cliffPalette);
|
|
143
196
|
}
|
|
144
197
|
|
|
145
|
-
result.
|
|
198
|
+
result.cliffTilePalette = cliffPalettes;
|
|
146
199
|
|
|
147
200
|
/**
|
|
148
201
|
* map dimensions
|
|
149
202
|
*/
|
|
150
|
-
const width =
|
|
151
|
-
const height =
|
|
203
|
+
const width = outBufferToJSON.readInt() - 1;
|
|
204
|
+
const height = outBufferToJSON.readInt() - 1;
|
|
152
205
|
result.map = { width, height, offset: { x: 0, y: 0 } };
|
|
153
206
|
|
|
154
|
-
const offsetX =
|
|
155
|
-
const offsetY =
|
|
207
|
+
const offsetX = outBufferToJSON.readFloat();
|
|
208
|
+
const offsetY = outBufferToJSON.readFloat();
|
|
156
209
|
result.map.offset = { x: offsetX, y: offsetY };
|
|
157
210
|
|
|
158
211
|
/**
|
|
159
212
|
* map tiles
|
|
160
213
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
214
|
+
const arr_groundHeight = [];
|
|
215
|
+
const arr_waterHeight = [];
|
|
216
|
+
const arr_boundaryFlag = [];
|
|
217
|
+
const arr_flags = [];
|
|
218
|
+
const arr_groundTexture = [];
|
|
219
|
+
const arr_groundVariation = [];
|
|
220
|
+
const arr_cliffVariation = [];
|
|
221
|
+
const arr_cliffTexture = [];
|
|
222
|
+
const arr_layerHeight = [];
|
|
223
|
+
|
|
224
|
+
while(!outBufferToJSON.isExhausted()) {
|
|
225
|
+
const groundHeight = outBufferToJSON.readShort();
|
|
226
|
+
const waterHeightAndBoundary = outBufferToJSON.readShort();
|
|
227
|
+
const flagsAndGroundTexture = outBufferToJSON.readByte();
|
|
228
|
+
const groundAndCliffVariation = outBufferToJSON.readByte();
|
|
229
|
+
const cliffTextureAndLayerHeight = outBufferToJSON.readByte();
|
|
230
|
+
|
|
231
|
+
// parse out different bits (based on documentation from https://github.com/stijnherfst/HiveWE/wiki/war3map.w3e-Terrain)
|
|
232
|
+
const waterHeight = waterHeightAndBoundary & 32767;
|
|
233
|
+
const boundaryFlag = (waterHeightAndBoundary & 0x4000) === 0x4000;
|
|
234
|
+
const flags = flagsAndGroundTexture & 240;
|
|
235
|
+
const groundTexture = flagsAndGroundTexture & 15;
|
|
236
|
+
const groundVariation = groundAndCliffVariation & 248;
|
|
237
|
+
const cliffVariation = groundAndCliffVariation & 7;
|
|
238
|
+
const cliffTexture = cliffTextureAndLayerHeight & 240;
|
|
239
|
+
const layerHeight = cliffTextureAndLayerHeight & 15;
|
|
240
|
+
|
|
241
|
+
arr_groundHeight.push(groundHeight);
|
|
242
|
+
arr_waterHeight.push(waterHeight);
|
|
243
|
+
arr_boundaryFlag.push(boundaryFlag);
|
|
244
|
+
arr_flags.push(flags);
|
|
245
|
+
arr_groundTexture.push(groundTexture);
|
|
246
|
+
arr_groundVariation.push(groundVariation);
|
|
247
|
+
arr_cliffVariation.push(cliffVariation);
|
|
248
|
+
arr_cliffTexture.push(cliffTexture);
|
|
249
|
+
arr_layerHeight.push(layerHeight);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function convertArrayOfArraysIntoFlatArray(arr) {
|
|
253
|
+
return arr.reduce((a, b) => {
|
|
254
|
+
return [...a, ...b]
|
|
255
|
+
});
|
|
197
256
|
}
|
|
198
257
|
|
|
199
|
-
//
|
|
200
|
-
//
|
|
258
|
+
// The map was read in "backwards" because wc3 maps have origin (0,0)
|
|
259
|
+
// at the bottom left instead of top left as we desire. Flip the rows
|
|
260
|
+
// vertically to fix this.
|
|
261
|
+
result.groundHeight = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_groundHeight, result.map.width + 1).reverse())
|
|
262
|
+
result.waterHeight = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_waterHeight, result.map.width + 1).reverse())
|
|
263
|
+
result.boundaryFlag = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_boundaryFlag, result.map.width + 1).reverse())
|
|
264
|
+
result.flags = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_flags, result.map.width + 1).reverse())
|
|
265
|
+
result.groundTexture = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_groundTexture, result.map.width + 1).reverse())
|
|
266
|
+
result.groundVariation = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_groundVariation, result.map.width + 1).reverse())
|
|
267
|
+
result.cliffVariation = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_cliffVariation, result.map.width + 1).reverse())
|
|
268
|
+
result.cliffTexture = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_cliffTexture, result.map.width + 1).reverse())
|
|
269
|
+
result.layerHeight = convertArrayOfArraysIntoFlatArray(splitLargeArrayIntoWidthArrays(arr_layerHeight, result.map.width + 1).reverse())
|
|
201
270
|
|
|
202
271
|
return {
|
|
203
272
|
errors: [],
|