Skip to content

Commit 70fa6f0

Browse files
committed
1 parent 240407d commit 70fa6f0

5 files changed

Lines changed: 156 additions & 42 deletions

File tree

build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ project(":core") {
7676
api "org.apache.commons:commons-compress:1.20"
7777
api "net.nikr:dds:1.0.0"
7878
api files(fileTree(dir:'../jars', includes: ['*.jar']))
79+
80+
testImplementation "org.junit.jupiter:junit-jupiter-api:5.10.2"
81+
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.10.2"
82+
}
83+
84+
test {
85+
useJUnitPlatform()
7986
}
8087
}
8188

core/build.gradle

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22

33
sourceCompatibility = 1.17
44

5-
sourceSets.main.java.srcDirs = [ "src/" ]
6-
5+
sourceSets {
6+
main {
7+
java.srcDirs = [ "src/" ]
8+
}
9+
test {
10+
java.srcDirs = [ "test/" ]
11+
resources.srcDirs = [ "test/resources" ]
12+
}
13+
}
714

815
eclipse.project {
916
name = appName + "-core"

core/src/com/etheller/warsmash/parsers/w3x/w3i/War3MapW3i.java

Lines changed: 115 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import java.util.List;
66

77
import com.etheller.warsmash.util.ParseUtils;
8+
import com.etheller.warsmash.util.War3ID;
89
import com.google.common.io.LittleEndianDataInputStream;
910
import com.google.common.io.LittleEndianDataOutputStream;
1011

1112
/**
1213
* war3map.w3i - the general map information file.
14+
* https://github.com/ChiefOfGxBxL/WC3MapSpecification/blob/master/Info/0-33.md
1315
*/
1416
public class War3MapW3i {
1517
private int version;
@@ -33,7 +35,7 @@ public class War3MapW3i {
3335
private String loadingScreenText;
3436
private String loadingScreenTitle;
3537
private String loadingScreenSubtitle;
36-
private int gameDataSet;
38+
private int gameDataSet = 0;
3739
private String prologueScreenModel;
3840
private String prologueScreenText;
3941
private String prologueScreenTitle;
@@ -42,13 +44,16 @@ public class War3MapW3i {
4244
private final float[] fogHeight = new float[2];
4345
private float fogDensity;
4446
private final short[] fogColor = new short[4];
45-
private int globalWeather;
47+
private War3ID globalWeather;
4648
private String soundEnvironment;
4749
private char lightEnvironmentTileset;
4850
private final short[] waterVertexColor = new short[4];
49-
private final short[] unknown2ProbablyLua = new short[4];
50-
private long supportedModes;
51-
private long gameDataVersion;
51+
private int scriptLanguage = 0; // 0 = JASS, 1 = Lua
52+
private long supportedModes; // 1=SD, 2=HD, 3=SD+HD
53+
private long gameDataVersion = 0; // 0=ROC, 1=TFT
54+
private int forceDefaultCameraZoom;
55+
private int forceMaxCameraZoom;
56+
private int forceMinCameraZoom;
5257
private final List<Player> players = new ArrayList<>();
5358
private final List<Force> forces = new ArrayList<>();
5459
private final List<UpgradeAvailabilityChange> upgradeAvailabilityChanges = new ArrayList<>();
@@ -83,45 +88,78 @@ private void load(final LittleEndianDataInputStream stream) throws IOException {
8388
ParseUtils.readInt32Array(stream, this.playableSize);
8489
this.flags = ParseUtils.readUInt32(stream);
8590
this.tileset = (char) stream.read();
86-
this.campaignBackground = stream.readInt();
8791

88-
if (this.version > 24) {
92+
if (this.version >= 17) {
93+
this.campaignBackground = stream.readInt();
94+
}
95+
96+
if (this.version >= 10 && this.version != 18 && this.version != 19) {
8997
this.loadingScreenModel = ParseUtils.readUntilNull(stream);
9098
}
9199

92-
this.loadingScreenText = ParseUtils.readUntilNull(stream);
93-
this.loadingScreenTitle = ParseUtils.readUntilNull(stream);
94-
this.loadingScreenSubtitle = ParseUtils.readUntilNull(stream);
95-
this.gameDataSet = stream.readInt();
100+
if (this.version >= 10) {
101+
this.loadingScreenText = ParseUtils.readUntilNull(stream);
102+
}
96103

97-
if (this.version > 24) {
104+
if (this.version >= 11) {
105+
this.loadingScreenTitle = ParseUtils.readUntilNull(stream);
106+
this.loadingScreenSubtitle = ParseUtils.readUntilNull(stream);
107+
}
108+
109+
if (this.version >= 17) {
110+
this.gameDataSet = stream.readInt();
111+
}
112+
113+
if (this.version >= 18) {
98114
this.prologueScreenModel = ParseUtils.readUntilNull(stream);
99115
}
100116

101-
this.prologueScreenText = ParseUtils.readUntilNull(stream);
102-
this.prologueScreenTitle = ParseUtils.readUntilNull(stream);
103-
this.prologueScreenSubtitle = ParseUtils.readUntilNull(stream);
117+
if (this.version >= 13) {
118+
this.prologueScreenText = ParseUtils.readUntilNull(stream);
119+
this.prologueScreenTitle = ParseUtils.readUntilNull(stream);
120+
this.prologueScreenSubtitle = ParseUtils.readUntilNull(stream);
121+
}
104122

105-
if (this.version > 24) {
123+
if (this.version >= 19) {
106124
this.useTerrainFog = stream.readInt();
107125
ParseUtils.readFloatArray(stream, this.fogHeight);
108126
this.fogDensity = stream.readFloat();
109127
ParseUtils.readUInt8Array(stream, this.fogColor);
110-
this.globalWeather = stream.readInt(); // TODO probably war3id, right?
128+
}
129+
130+
if (this.version >= 21) {
131+
this.globalWeather = ParseUtils.readWar3ID(stream);
132+
}
133+
134+
if (this.version >= 22) {
111135
this.soundEnvironment = ParseUtils.readUntilNull(stream);
136+
}
137+
138+
if (this.version >= 23) {
112139
this.lightEnvironmentTileset = (char) stream.read();
140+
}
141+
142+
if (this.version >= 25) {
113143
ParseUtils.readUInt8Array(stream, this.waterVertexColor);
114144
}
115145

116-
if (this.version > 27) {
117-
ParseUtils.readUInt8Array(stream, this.unknown2ProbablyLua);
146+
if (this.version >= 28) {
147+
this.scriptLanguage = stream.readInt();
118148
}
119-
if (this.version > 30) {
149+
if (this.version >= 29) {
120150
this.supportedModes = ParseUtils.readUInt32(stream);
151+
}
152+
if (this.version >= 30) {
121153
this.gameDataVersion = ParseUtils.readUInt32(stream);
122154
}
123-
else {
124-
this.gameDataVersion = -1; // indicate to the outside that this was unspecified
155+
156+
if (this.version >= 32) {
157+
this.forceDefaultCameraZoom = stream.readInt();
158+
this.forceMaxCameraZoom = stream.readInt();
159+
}
160+
161+
if (this.version >= 32) {
162+
this.forceMinCameraZoom = stream.readInt();
125163
}
126164

127165
for (int i = 0, l = stream.readInt(); i < l; i++) {
@@ -208,45 +246,82 @@ public void save(final LittleEndianDataOutputStream stream) throws IOException {
208246
ParseUtils.writeInt32Array(stream, this.playableSize);
209247
ParseUtils.writeUInt32(stream, this.flags);
210248
stream.write((byte) this.tileset);
211-
stream.writeInt(this.campaignBackground);
212249

213-
if (this.version > 24) {
250+
if (this.version >= 17) {
251+
stream.writeInt(this.campaignBackground);
252+
}
253+
254+
if (this.version > 10 && this.version != 18 && this.version != 19) {
214255
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenModel);
215256
}
216257

217-
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenText);
218-
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenTitle);
219-
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenSubtitle);
220-
stream.writeInt(this.gameDataSet);
258+
if (this.version >= 10) {
259+
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenText);
260+
}
221261

222-
if (this.version > 24) {
262+
if (this.version >= 11) {
263+
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenTitle);
264+
ParseUtils.writeWithNullTerminator(stream, this.loadingScreenSubtitle);
265+
}
266+
267+
if (this.version >= 17) {
268+
stream.writeInt(this.gameDataSet);
269+
}
270+
271+
if (this.version >= 13 && this.version != 18 && this.version != 19) {
223272
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenModel);
224273
}
225274

226-
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenText);
227-
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenTitle);
228-
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenSubtitle);
275+
if (this.version >= 13) {
276+
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenText);
277+
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenTitle);
278+
ParseUtils.writeWithNullTerminator(stream, this.prologueScreenSubtitle);
279+
}
229280

230-
if (this.version > 24) {
281+
if (this.version > 19) {
231282
stream.writeInt(this.useTerrainFog);
232283
ParseUtils.writeFloatArray(stream, this.fogHeight);
233284
stream.writeFloat(this.fogDensity);
234285
ParseUtils.writeUInt8Array(stream, this.fogColor);
235-
stream.writeInt(this.globalWeather); // TODO War3ID???
286+
}
287+
288+
if (this.version >= 21) {
289+
ParseUtils.writeWar3ID(stream, this.globalWeather);
290+
}
291+
292+
if (this.version >= 22) {
236293
ParseUtils.writeWithNullTerminator(stream, this.soundEnvironment);
294+
}
295+
296+
if (this.version >= 23) {
237297
stream.write((byte) this.lightEnvironmentTileset);
298+
}
299+
300+
if (this.version >= 25) {
238301
ParseUtils.writeUInt8Array(stream, this.waterVertexColor);
239302
}
240303

241-
if (this.version > 27) {
242-
ParseUtils.writeUInt8Array(stream, this.unknown2ProbablyLua);
304+
if (this.version >= 28) {
305+
ParseUtils.writeUInt32(stream, this.scriptLanguage);
243306
}
244307

245-
if (this.version > 30) {
308+
if (this.version >= 29) {
246309
ParseUtils.writeUInt32(stream, this.supportedModes);
310+
}
311+
312+
if (this.version >= 30) {
247313
ParseUtils.writeUInt32(stream, this.gameDataVersion);
248314
}
249315

316+
if (this.version >= 32) {
317+
ParseUtils.writeUInt32(stream, this.forceDefaultCameraZoom);
318+
ParseUtils.writeUInt32(stream, this.forceMaxCameraZoom);
319+
}
320+
321+
if (this.version >= 33) {
322+
ParseUtils.writeUInt32(stream, this.forceMinCameraZoom);
323+
}
324+
250325
ParseUtils.writeUInt32(stream, this.players.size());
251326

252327
for (final Player player : this.players) {
@@ -429,7 +504,7 @@ public short[] getFogColor() {
429504
return this.fogColor;
430505
}
431506

432-
public int getGlobalWeather() {
507+
public War3ID getGlobalWeather() {
433508
return this.globalWeather;
434509
}
435510

@@ -445,8 +520,8 @@ public short[] getWaterVertexColor() {
445520
return this.waterVertexColor;
446521
}
447522

448-
public short[] getUnknown2() {
449-
return this.unknown2ProbablyLua;
523+
public int getScriptLanguage() {
524+
return this.scriptLanguage;
450525
}
451526

452527
public long getSupportedModes() {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.etheller.warsmash.util;
2+
3+
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
4+
import com.google.common.io.LittleEndianDataInputStream;
5+
import org.junit.jupiter.api.Test;
6+
import static org.junit.jupiter.api.Assertions.*;
7+
8+
import java.io.IOException;
9+
10+
class War3MapW3iTest {
11+
12+
@Test
13+
void testWoWReforged() throws IOException {
14+
War3MapW3i mapInfo;
15+
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
16+
getClass().getClassLoader().getResourceAsStream("wowr_w3x/war3map.w3i"))) {
17+
mapInfo = new War3MapW3i(stream);
18+
}
19+
20+
assertEquals(33, mapInfo.getVersion());
21+
assertEquals("TRIGSTR_004", mapInfo.getAuthor());
22+
assertEquals(12, mapInfo.getPlayers().size());
23+
assertEquals(3, mapInfo.getForces().size());
24+
}
25+
}
948 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)