55import java .util .List ;
66
77import com .etheller .warsmash .util .ParseUtils ;
8+ import com .etheller .warsmash .util .War3ID ;
89import com .google .common .io .LittleEndianDataInputStream ;
910import 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 */
1416public 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 () {
0 commit comments