Merge lp:~charlyghislain/widelands/portdock-fix into lp:widelands

Proposed by SirVer
Status: Merged
Merged at revision: 6650
Proposed branch: lp:~charlyghislain/widelands/portdock-fix
Merge into: lp:widelands
Diff against target: 943 lines (+299/-300)
5 files modified
src/economy/portdock.cc (+2/-2)
src/io/bitinbuffer.h (+0/-54)
src/io/bitoutbuffer.h (+0/-56)
src/logic/instances.h (+1/-0)
src/map_io/widelands_map_players_view_data_packet.cc (+296/-188)
To merge this branch: bzr merge lp:~charlyghislain/widelands/portdock-fix
Reviewer Review Type Date Requested Status
SirVer Approve
Review via email: mp+174335@code.launchpad.net
To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote :

While this gets rid of the current problem, this breaks backwards compatibility if I understand the patch correctly. We aim to be able to load games from 3 versions prior to the current version of the game.

While your on it, could you make this a little more future proof by writing uint8 instead using BitInBuffer - I feel it is better to waste some space in the savegame than having huge changes in the save game format each time we touch this code path.

review: Needs Fixing
Revision history for this message
cghislai (charlyghislain) wrote :

Indeed it breaks savegame compatibility.

The other option i had in mind was defining a immovable in the conf files. This would allow a visual representation of the dock, which i guess will be added at some point anyway. And it would not break compatibility i guess. I will consider this option now.

If I continue using the current approach, and if I understand you correctly, I should handle the paquet version mismatch while reading files. I guess this should be done anyway to at least show some error and prevent the crash.

Revision history for this message
SirVer (sirver) wrote :

I do not think that there should ever be an immovable associated with a dock - a dock is everywhere where a port is and they are unseparable, so there is no need for a new immovable.

You are right about the reading part: You check the version number and branch off into code that can handle the current packet version number. There are plenty of examples all over the code for this :). I'll wait with the review for now until I hear back from you.

Btw, it is really impressive how quickly you grab all the code concepts inside of Widelands.

Revision history for this message
cghislai (charlyghislain) wrote :

I included backward compatibility, I was able to load, save, then load back the savegame from the bug report.

Revision history for this message
SirVer (sirver) wrote :

There are test games in the test/ sub directory - you want to test with those as well.

Revision history for this message
cghislai (charlyghislain) wrote :

They loaded without any problem

Revision history for this message
SirVer (sirver) wrote :

Thanks for testing. This already looks much better than the code before. I think it can be merged as is, but if you want to make it super extra specially nice, my suggestion is to do the following:
- move BitInBuffer into this file into an anonymous namespace.
- modify the code so that it is only used for reading old savegames
- add a comment that it should be removed after build 20.

That will make sure that BitInBuffer is never used again - I feel it is more trouble than its worth.

What do you think? If you do not want to do this, I think we can merge right away.

Revision history for this message
cghislai (charlyghislain) wrote :

I implemented your suggestions. Eveything should be ready for cleaning for build20.
I wrote uint8 without really looking for a better way to store data, except in some obvious places. But I dont think there is much space lost. For compressed savegames, du -s gives:

100 build13-test1-2.wgf
104 build13-test1.wgf
172 build15-bigeconomy-2.wgf
184 build15-bigeconomy.wgf
388 Build16-2.wgf
376 Build16.wgf
72 test-win-1-2.wgf
72 test-win-1.wgf

Revision history for this message
SirVer (sirver) wrote :

As mentioned, I am not concerned about space in savegames - zip will care for this nicely, I am more concerned about easier implementations in the future. I think we are ill equipped with bit juggling, so I am really happy to see the BitInBuffer to be unused now.

Comments:
- the code does not compile for me, there seems to be an error in OPEN_INPUT_FILE_NEW_VERSION_SILENT. Shouldn't those macros be functions inside the anon namespace anyways?
int8_t 1 = version; FileRead border_file; char (border_filename)[48]; for (; 1 >= 0; --1) { snprintf(border_filename, sizeof(border_filename), "player/%u" "/view" "/border_%u", plnum, 1); try
{(border_file).Open(fs, border_filename); break;} catch (...) { if (1 == 0) { 1 = -1;} } };

- I suggest removing the indent in the anon namespace - this is quite common to not align.

review: Needs Fixing
Revision history for this message
cghislai (charlyghislain) wrote :

I tried a fix for the OPEN_SILENT macro. The file compiled here without a warning, I hope it will works on your side as well now.
I tested again the compatibility savegames and the buggy one from the bug report, all loaded correctly.
Saving also worked fine

Revision history for this message
SirVer (sirver) wrote :

Compiled on my end with small fixes and lgtm. Merged.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/economy/portdock.cc'
2--- src/economy/portdock.cc 2013-07-14 10:38:26 +0000
3+++ src/economy/portdock.cc 2013-07-20 12:41:27 +0000
4@@ -67,10 +67,10 @@
5
6 } // namespace
7
8-Map_Object_Descr portdock_descr("portdock", "Port Dock");
9+Map_Object_Descr g_portdock_descr("portdock", "Port Dock");
10
11 PortDock::PortDock() :
12- PlayerImmovable(portdock_descr),
13+ PlayerImmovable(g_portdock_descr),
14 m_fleet(0),
15 m_warehouse(0),
16 m_need_ship(false),
17
18=== removed file 'src/io/bitinbuffer.h'
19--- src/io/bitinbuffer.h 2012-09-21 21:36:07 +0000
20+++ src/io/bitinbuffer.h 1970-01-01 00:00:00 +0000
21@@ -1,54 +0,0 @@
22-/*
23- * Copyright (C) 2007-2008 by the Widelands Development Team
24- *
25- * This program is free software; you can redistribute it and/or
26- * modify it under the terms of the GNU General Public License
27- * as published by the Free Software Foundation; either version 2
28- * of the License, or (at your option) any later version.
29- *
30- * This program is distributed in the hope that it will be useful,
31- * but WITHOUT ANY WARRANTY; without even the implied warranty of
32- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33- * GNU General Public License for more details.
34- *
35- * You should have received a copy of the GNU General Public License
36- * along with this program; if not, write to the Free Software
37- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
38- *
39- */
40-
41-#ifndef BITINBUFFER_H
42-#define BITINBUFFER_H
43-
44-#include "fileread.h"
45-
46-#include "compile_assert.h"
47-
48-/// Wrapper around FileRead for reading groups of Size bits from a file, where
49-/// Size can be a factor of 8. Call get to read Size bits from the buffer.
50-/// Attempts to read more bits than have been written to the BitOutBuffer when
51-/// the file was created will not fail unless it causes another byte to be read
52-/// from the file.
53-template<uint8_t const Size> struct BitInBuffer {
54- compile_assert(Size == 1 or Size == 2 or Size == 4);
55- BitInBuffer() : buffer(0), mask(0x00) {}
56- void Open(FileSystem & fs, char const * const filename) {
57- fr.Open(fs, filename);
58- }
59- size_t GetSize() const throw () {return fr.GetSize ();}
60- bool EndOfFile() const throw () {return fr.EndOfFile();}
61- size_t GetPos () const throw () {return fr.GetPos ();}
62- uint8_t get() {
63- if (mask == 0x00) {buffer = fr.Unsigned8(); mask = 0xff;}
64- uint8_t const result = buffer >> (8 - Size);
65- buffer <<= Size;
66- mask <<= Size;
67- assert(result < (1 << Size));
68- return result;
69- }
70-private:
71- FileRead fr;
72- uint8_t buffer, mask;
73-};
74-
75-#endif
76
77=== removed file 'src/io/bitoutbuffer.h'
78--- src/io/bitoutbuffer.h 2012-02-15 21:25:34 +0000
79+++ src/io/bitoutbuffer.h 1970-01-01 00:00:00 +0000
80@@ -1,56 +0,0 @@
81-/*
82- * Copyright (C) 2007-2008 by the Widelands Development Team
83- *
84- * This program is free software; you can redistribute it and/or
85- * modify it under the terms of the GNU General Public License
86- * as published by the Free Software Foundation; either version 2
87- * of the License, or (at your option) any later version.
88- *
89- * This program is distributed in the hope that it will be useful,
90- * but WITHOUT ANY WARRANTY; without even the implied warranty of
91- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92- * GNU General Public License for more details.
93- *
94- * You should have received a copy of the GNU General Public License
95- * along with this program; if not, write to the Free Software
96- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
97- *
98- */
99-
100-#ifndef BITOUTBUFFER_H
101-#define BITOUTBUFFER_H
102-
103-#include "filewrite.h"
104-
105-#include "compile_assert.h"
106-
107-/// Wrapper around FileWrite for writing bits to a file. Call put to write a
108-/// bit to the buffer. Call Write to write the buffer to file. Unassigned bits
109-/// in the last byte will be 0.
110-template<uint8_t const Size> struct BitOutBuffer {
111- compile_assert(Size == 1 or Size == 2 or Size == 4);
112- BitOutBuffer() : buffer(0x00), mask(0xff) {}
113- void put(uint8_t const item) {
114- assert(item < (1 << Size));
115- buffer |= item;
116- mask <<= Size;
117- if (mask == 0x00) {
118- fw.Unsigned8(buffer);
119- mask = 0xff;
120- }
121- buffer <<= Size;
122- }
123- void Write(FileSystem & fs, const char * const filename) {
124- if (mask != 0xff) {
125- while (mask <<= Size)
126- buffer <<= Size;
127- fw.Unsigned8(buffer);
128- }
129- fw.Write(fs, filename);
130- }
131-private:
132- FileWrite fw;
133- uint8_t buffer, mask;
134-};
135-
136-#endif
137
138=== modified file 'src/logic/instances.h'
139--- src/logic/instances.h 2013-07-09 05:40:36 +0000
140+++ src/logic/instances.h 2013-07-20 12:41:27 +0000
141@@ -104,6 +104,7 @@
142 * \todo move this to another header??
143 */
144 extern Map_Object_Descr g_flag_descr;
145+extern Map_Object_Descr g_portdock_descr;
146
147 /**
148 * \par Notes on Map_Object
149
150=== modified file 'src/map_io/widelands_map_players_view_data_packet.cc'
151--- src/map_io/widelands_map_players_view_data_packet.cc 2013-07-15 05:18:12 +0000
152+++ src/map_io/widelands_map_players_view_data_packet.cc 2013-07-20 12:41:27 +0000
153@@ -22,8 +22,6 @@
154
155 #include "widelands_map_players_view_data_packet.h"
156
157-#include "io/bitinbuffer.h"
158-#include "io/bitoutbuffer.h"
159 #include "logic/editor_game_base.h"
160 #include "logic/field.h"
161 #include "logic/game_data_error.h"
162@@ -39,6 +37,7 @@
163
164 #include "upcast.h"
165
166+
167 namespace Widelands {
168
169
170@@ -48,19 +47,19 @@
171 #define UNSEEN_TIMES_CURRENT_PACKET_VERSION 1
172 #define UNSEEN_TIMES_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/unseen_times_%u"
173
174-#define NODE_IMMOVABLE_KINDS_CURRENT_PACKET_VERSION 1
175+#define NODE_IMMOVABLE_KINDS_CURRENT_PACKET_VERSION 2
176 #define NODE_IMMOVABLE_KINDS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/node_immovable_kinds_%u"
177
178 #define NODE_IMMOVABLES_CURRENT_PACKET_VERSION 2
179 #define NODE_IMMOVABLES_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/node_immovables_%u"
180
181-#define ROADS_CURRENT_PACKET_VERSION 1
182+#define ROADS_CURRENT_PACKET_VERSION 2
183 #define ROADS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/roads_%u"
184
185-#define TERRAINS_CURRENT_PACKET_VERSION 1
186+#define TERRAINS_CURRENT_PACKET_VERSION 2
187 #define TERRAINS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/terrains_%u"
188
189-#define TRIANGLE_IMMOVABLE_KINDS_CURRENT_PACKET_VERSION 1
190+#define TRIANGLE_IMMOVABLE_KINDS_CURRENT_PACKET_VERSION 2
191 #define TRIANGLE_IMMOVABLE_KINDS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/triangle_immovable_kinds_%u"
192
193 #define TRIANGLE_IMMOVABLES_CURRENT_PACKET_VERSION 2
194@@ -69,10 +68,10 @@
195 #define OWNERS_CURRENT_PACKET_VERSION 0
196 #define OWNERS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/owners_%u"
197
198-#define SURVEYS_CURRENT_PACKET_VERSION 1
199+#define SURVEYS_CURRENT_PACKET_VERSION 2
200 #define SURVEYS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/surveys_%u"
201
202-#define SURVEY_AMOUNTS_CURRENT_PACKET_VERSION 1
203+#define SURVEY_AMOUNTS_CURRENT_PACKET_VERSION 2
204 #define SURVEY_AMOUNTS_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/survey_amounts_%u"
205
206 #define SURVEY_TIMES_CURRENT_PACKET_VERSION 1
207@@ -81,11 +80,12 @@
208 #define VISION_CURRENT_PACKET_VERSION 1
209 #define VISION_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/vision_%u"
210
211-#define BORDER_CURRENT_PACKET_VERSION 0
212+#define BORDER_CURRENT_PACKET_VERSION 1
213 #define BORDER_FILENAME_TEMPLATE DIRNAME_TEMPLATE "/border_%u"
214
215 #define FILENAME_SIZE 48
216
217+
218 // The map is traversed by row and column. In each step we process of one map
219 // field (which is 1 node, 2 triangles and 3 edges that are stored together).
220 // For this processing we need to keep track of 4 nodes:
221@@ -110,16 +110,86 @@
222 Player::Constructionsite_Information csi;
223 };
224
225+namespace {
226+#define OPEN_INPUT_FILE(filetype, file, filename, filename_template, version) \
227+ char (filename)[FILENAME_SIZE]; \
228+ snprintf(filename, sizeof(filename), filename_template, plnum, version); \
229+ filetype file; \
230+ try {(file).Open(fs, filename);} \
231+ catch (const File_error &) { \
232+ throw game_data_error \
233+ ("Map_Players_View_Data_Packet::Read: player %u:Could not open " \
234+ "\"%s\" for reading. This file should exist when \"%s\" exists", \
235+ plnum, filename, unseen_times_filename); \
236+ }
237+
238+// Try to find the file with newest fitting version number
239+#define OPEN_INPUT_FILE_NEW_VERSION(filetype, file, filename, fileversion, filename_template, version) \
240+ uint8_t fileversion = version; \
241+ filetype file; \
242+ char (filename)[FILENAME_SIZE]; \
243+ for (;; --fileversion) { \
244+ snprintf(filename, sizeof(filename), filename_template, plnum, fileversion); \
245+ try {(file).Open(fs, filename); break;} \
246+ catch (...) { \
247+ if (fileversion == 0) \
248+ throw game_data_error \
249+ ("Map_Players_View_Data_Packet::Read: player %u:Could not open " \
250+ "\"%s\" for reading. This file should exist when \"%s\" exists", \
251+ plnum, filename, unseen_times_filename); \
252+ } \
253+ }
254+
255+// Using this macro, if no file exists, fileversion will be set to -1
256+#define OPEN_INPUT_FILE_NEW_VERSION_SILENT(filetype, file, filename, fileversion, file_templ, v) \
257+ int8_t fileversion = v; \
258+ filetype file; \
259+ char (filename)[FILENAME_SIZE]; \
260+ for (; fileversion >= -1; --fileversion) { \
261+ snprintf(filename, sizeof(filename), file_templ, plnum, fileversion); \
262+ try {(file).Open(fs, filename); break;} \
263+ catch (...) { \
264+ } \
265+ }
266+
267+#define CHECK_TRAILING_BYTES(file, filename) \
268+ if (not (file).EndOfFile()) \
269+ throw game_data_error \
270+ ("Map_Players_View_Data_Packet::Read: player %u:" \
271+ "Found %lu trailing bytes in \"%s\"", \
272+ plnum, \
273+ static_cast<long unsigned int>((file).GetSize() - (file).GetPos()), \
274+ filename);
275+
276+// FIXME: Legacy code deprecated since build18
277+template<uint8_t const Size> struct BitInBuffer {
278+ compile_assert(Size == 1 or Size == 2 or Size == 4);
279+ BitInBuffer(FileRead* fr) : buffer(0), mask(0x00) {m_fr = fr;}
280+
281+ uint8_t get() {
282+ if (mask == 0x00) {buffer = m_fr->Unsigned8(); mask = 0xff;}
283+ uint8_t const result = buffer >> (8 - Size);
284+ buffer <<= Size;
285+ mask <<= Size;
286+ assert(result < (1 << Size));
287+ return result;
288+ }
289+private:
290+ FileRead* m_fr;
291+ uint8_t buffer, mask;
292+};
293+}
294+
295 inline static Map_Object_Data read_unseen_immovable
296 (const Editor_Game_Base & egbase,
297- BitInBuffer<2> & immovable_kinds_file,
298+ uint8_t & immovable_kind,
299 FileRead & immovables_file,
300 uint8_t & version
301 )
302 {
303 Map_Object_Data m;
304 try {
305- switch (immovable_kinds_file.get()) {
306+ switch (immovable_kind) {
307 case 0: // The player sees no immovable.
308 m.map_object_descr = 0; break;
309 case 1: // The player sees a tribe or world immovable.
310@@ -139,8 +209,10 @@
311 }
312 }
313 break;
314+ case 4: // The player sees a port dock
315+ m.map_object_descr = &g_portdock_descr; break;
316 default:
317- throw game_data_error("Unknown immovable-kind type %d", immovable_kinds_file.get());
318+ throw game_data_error("Unknown immovable-kind type %d", immovable_kind);
319 break;
320 }
321 } catch (const _wexception & e) {
322@@ -149,43 +221,7 @@
323 return m;
324 }
325
326-#define OPEN_INPUT_FILE(filetype, file, filename, filename_template, version) \
327- char (filename)[FILENAME_SIZE]; \
328- snprintf(filename, sizeof(filename), filename_template, plnum, version); \
329- filetype file; \
330- try {(file).Open(fs, filename);} \
331- catch (const File_error &) { \
332- throw game_data_error \
333- ("Map_Players_View_Data_Packet::Read: player %u:Could not open " \
334- "\"%s\" for reading. This file should exist when \"%s\" exists", \
335- plnum, filename, unseen_times_filename); \
336- }
337-
338-// Try to find the file with newest fitting version number
339-#define OPEN_INPUT_FILE_NEW_VERSION(filetype, file, filename, fileversion, filename_template, version) \
340- uint8_t fileversion = version; \
341- filetype file; \
342- char (filename)[FILENAME_SIZE]; \
343- for (; fileversion > 0; --fileversion) { \
344- snprintf(filename, sizeof(filename), filename_template, plnum, fileversion); \
345- try {(file).Open(fs, filename); break;} \
346- catch (...) { \
347- if (fileversion == 1) \
348- throw game_data_error \
349- ("Map_Players_View_Data_Packet::Read: player %u:Could not open " \
350- "\"%s\" for reading. This file should exist when \"%s\" exists", \
351- plnum, filename, unseen_times_filename); \
352- } \
353- }
354-
355-#define CHECK_TRAILING_BYTES(file, filename) \
356- if (not (file).EndOfFile()) \
357- throw game_data_error \
358- ("Map_Players_View_Data_Packet::Read: player %u:" \
359- "Found %lu trailing bytes in \"%s\"", \
360- plnum, \
361- static_cast<long unsigned int>((file).GetSize() - (file).GetPos()), \
362- filename); \
363+
364
365 void Map_Players_View_Data_Packet::Read
366 (FileSystem & fs,
367@@ -347,9 +383,9 @@
368 }
369
370 // Read the player's knowledge about all fields
371- OPEN_INPUT_FILE
372- (BitInBuffer<2>, node_immovable_kinds_file,
373- node_immovable_kinds_filename,
374+ OPEN_INPUT_FILE_NEW_VERSION
375+ (FileRead, node_immovable_kinds_file,
376+ node_immovable_kinds_filename, node_immovable_kinds_file_version,
377 NODE_IMMOVABLE_KINDS_FILENAME_TEMPLATE,
378 NODE_IMMOVABLE_KINDS_CURRENT_PACKET_VERSION);
379
380@@ -359,17 +395,19 @@
381 NODE_IMMOVABLES_FILENAME_TEMPLATE,
382 NODE_IMMOVABLES_CURRENT_PACKET_VERSION);
383
384- OPEN_INPUT_FILE
385- (BitInBuffer<2>, roads_file, roads_filename,
386+ OPEN_INPUT_FILE_NEW_VERSION
387+ (FileRead, roads_file,
388+ roads_filename, road_file_version,
389 ROADS_FILENAME_TEMPLATE, ROADS_CURRENT_PACKET_VERSION);
390
391- OPEN_INPUT_FILE
392- (BitInBuffer<4>, terrains_file, terrains_filename,
393+ OPEN_INPUT_FILE_NEW_VERSION
394+ (FileRead, terrains_file,
395+ terrains_filename, terrains_file_version,
396 TERRAINS_FILENAME_TEMPLATE, TERRAINS_CURRENT_PACKET_VERSION);
397
398- OPEN_INPUT_FILE
399- (BitInBuffer<2>, triangle_immovable_kinds_file,
400- triangle_immovable_kinds_filename,
401+ OPEN_INPUT_FILE_NEW_VERSION
402+ (FileRead, triangle_immovable_kinds_file,
403+ triangle_immovable_kinds_filename, triangle_immovable_kinds_file_version,
404 TRIANGLE_IMMOVABLE_KINDS_FILENAME_TEMPLATE,
405 TRIANGLE_IMMOVABLE_KINDS_CURRENT_PACKET_VERSION);
406
407@@ -383,12 +421,14 @@
408 (FileRead, owners_file, owners_filename,
409 OWNERS_FILENAME_TEMPLATE, OWNERS_CURRENT_PACKET_VERSION);
410
411- OPEN_INPUT_FILE
412- (BitInBuffer<1>, surveys_file, surveys_filename,
413+ OPEN_INPUT_FILE_NEW_VERSION
414+ (FileRead, surveys_file,
415+ surveys_filename, surveys_file_version,
416 SURVEYS_FILENAME_TEMPLATE, SURVEYS_CURRENT_PACKET_VERSION);
417
418- OPEN_INPUT_FILE
419- (BitInBuffer<4>, survey_amounts_file, survey_amounts_filename,
420+ OPEN_INPUT_FILE_NEW_VERSION
421+ (FileRead, survey_amounts_file,
422+ survey_amounts_filename, survey_amounts_file_version,
423 SURVEY_AMOUNTS_FILENAME_TEMPLATE,
424 SURVEY_AMOUNTS_CURRENT_PACKET_VERSION);
425
426@@ -396,21 +436,20 @@
427 (FileRead, survey_times_file, survey_times_filename,
428 SURVEY_TIMES_FILENAME_TEMPLATE, SURVEY_TIMES_CURRENT_PACKET_VERSION);
429
430- // Load border files
431- char border_filename[FILENAME_SIZE];
432- snprintf
433- (border_filename, sizeof(border_filename),
434- BORDER_FILENAME_TEMPLATE, plnum, BORDER_CURRENT_PACKET_VERSION);
435- BitInBuffer<1> border_file;
436- bool borders = false;
437- try {
438- border_file.Open(fs, border_filename);
439- borders = true;
440- } catch (...) {
441- log
442- ("Map_Players_View_Data_Packet::Read: No border file found, therefore no borders will be drawn "
443- "in unseen areas until they get at least once seen again.\n");
444- }
445+ OPEN_INPUT_FILE_NEW_VERSION_SILENT
446+ (FileRead, border_file,
447+ border_filename, border_file_version,
448+ BORDER_FILENAME_TEMPLATE,
449+ BORDER_CURRENT_PACKET_VERSION);
450+
451+ // FIXME: Legacy code deprecated since build18
452+ BitInBuffer<2> legacy_node_immovable_kinds_bitbuffer(&node_immovable_kinds_file);
453+ BitInBuffer<2> legacy_road_bitbuffer(&roads_file);
454+ BitInBuffer<4> legacy_terrains_bitbuffer(&terrains_file);
455+ BitInBuffer<2> legacy_triangle_immovable_kinds_bitbuffer(&triangle_immovable_kinds_file);
456+ BitInBuffer<1> legacy_surveys_bitbuffer(&surveys_file);
457+ BitInBuffer<4> legacy_surveys_amount_bitbuffer(&survey_amounts_file);
458+ BitInBuffer<1> legacy_border_bitbuffer(&border_file);
459
460 for
461 (FCoords first_in_row(Coords(0, 0), &first_field);
462@@ -456,7 +495,7 @@
463 // his information about the node from file.
464 try {
465 f_player_field.time_node_last_unseen = unseen_times_file.Unsigned32();
466- } catch (const FileRead::File_Boundary_Exceeded &) {
467+ } catch (const FileRead::File_Boundary_Exceeded & e) {
468 throw game_data_error
469 ("Map_Players_View_Data_Packet::Read: player %u: in "
470 "\"%s\":%lu: node (%i, %i): unexpected end of file "
471@@ -468,7 +507,7 @@
472 }
473
474 try {owner = owners_file.Unsigned8();}
475- catch (const FileRead::File_Boundary_Exceeded &) {
476+ catch (const FileRead::File_Boundary_Exceeded & e) {
477 throw game_data_error
478 ("Map_Players_View_Data_Packet::Read: player %u: in "
479 "\"%s\":%lu: node (%i, %i): unexpected end of file "
480@@ -479,7 +518,7 @@
481 (unseen_times_file.GetPos() - 1),
482 f.x, f.y);
483 }
484- if (nr_players < owner)
485+ if (nr_players < owner) {
486 throw game_data_error
487 ("Map_Players_View_Data_Packet::Read: player %u: in "
488 "\"%s\":%lu & 0xf: node (%i, %i): Player thinks that "
489@@ -488,19 +527,33 @@
490 plnum, owners_filename,
491 static_cast<long unsigned int>(owners_file.GetPos() - 1),
492 f.x, f.y, owner, nr_players);
493-
494+ }
495+ uint8_t imm_kind = 0;
496+ if (node_immovable_kinds_file_version < 2) {
497+ imm_kind = legacy_node_immovable_kinds_bitbuffer.get();
498+ } else {
499+ imm_kind = node_immovable_kinds_file.Unsigned8();
500+ }
501 Map_Object_Data mod =
502 read_unseen_immovable
503- (egbase, node_immovable_kinds_file, node_immovables_file, node_immovables_file_version);
504+ (egbase, imm_kind, node_immovables_file, node_immovables_file_version);
505 f_player_field.map_object_descr[TCoords<>::None] = mod.map_object_descr;
506 f_player_field.constructionsite = mod.csi;
507
508 // if there is a border file, read in whether this field had a border the last time it was seen
509- if (borders) {
510- f_player_field.border = (border_file.get() == 1);
511- f_player_field.border_r = (border_file.get() == 1);
512- f_player_field.border_br = (border_file.get() == 1);
513- f_player_field.border_bl = (border_file.get() == 1);
514+ if (border_file_version >= 0) {
515+ if (border_file_version < 1) {
516+ f_player_field.border = (legacy_border_bitbuffer.get() == 1);
517+ f_player_field.border_r = (legacy_border_bitbuffer.get() == 1);
518+ f_player_field.border_br = (legacy_border_bitbuffer.get() == 1);
519+ f_player_field.border_bl = (legacy_border_bitbuffer.get() == 1);
520+ } else {
521+ uint8_t borders = border_file.Unsigned8();
522+ f_player_field.border = borders & 1;
523+ f_player_field.border_r = borders & 2;
524+ f_player_field.border_br = borders & 4;
525+ f_player_field.border_bl = borders & 8;
526+ }
527 }
528
529
530@@ -542,18 +595,27 @@
531 } else if (f_everseen | bl_everseen | br_everseen) {
532 // The player has seen the D triangle but does not see it now.
533 // Load his information about the triangle from file.
534- try {f_player_field.terrains.d = terrains_file.get();}
535- catch (const FileRead::File_Boundary_Exceeded &) {
536- throw game_data_error
537- ("Map_Players_View_Data_Packet::Read: player %u: in "
538- "\"%s\": node (%i, %i) t = D: unexpected end of file "
539- "while reading terrain",
540- plnum, terrains_filename, f.x, f.y);
541+ if (terrains_file_version < 2) {
542+ try {f_player_field.terrains.d = legacy_terrains_bitbuffer.get();}
543+ catch (const FileRead::File_Boundary_Exceeded & e) {
544+ throw game_data_error
545+ ("Map_Players_View_Data_Packet::Read: player %u: in "
546+ "\"%s\": node (%i, %i) t = D: unexpected end of file "
547+ "while reading terrain",
548+ plnum, terrains_filename, f.x, f.y);
549+ }
550+ } else {
551+ f_player_field.terrains.d = terrains_file.Unsigned8();
552+ }
553+ uint8_t im_kind = 0;
554+ if (triangle_immovable_kinds_file_version < 2) {
555+ im_kind = legacy_triangle_immovable_kinds_bitbuffer.get();
556+ } else {
557+ im_kind = triangle_immovable_kinds_file.Unsigned8();
558 }
559 Map_Object_Data mod =
560 read_unseen_immovable
561- (egbase, triangle_immovable_kinds_file, triangle_immovables_file,
562- triangle_immovables_file_version);
563+ (egbase, im_kind, triangle_immovables_file, triangle_immovables_file_version);
564 f_player_field.map_object_descr[TCoords<>::D] = mod.map_object_descr;
565
566 }
567@@ -566,62 +628,86 @@
568 } else if (f_everseen | br_everseen | r_everseen) {
569 // The player has seen the R triangle but does not see it now.
570 // Load his information about the triangle from file.
571- try {f_player_field.terrains.r = terrains_file.get();}
572- catch (const FileRead::File_Boundary_Exceeded &) {
573- throw game_data_error
574- ("Map_Players_View_Data_Packet::Read: player %u: in "
575- "\"%s\": node (%i, %i) t = R: unexpected end of file "
576- "while reading terrain",
577- plnum, terrains_filename, f.x, f.y);
578+ if (terrains_file_version < 2) {
579+ try {f_player_field.terrains.r = legacy_terrains_bitbuffer.get();}
580+ catch (const FileRead::File_Boundary_Exceeded & e) {
581+ throw game_data_error
582+ ("Map_Players_View_Data_Packet::Read: player %u: in "
583+ "\"%s\": node (%i, %i) t = R: unexpected end of file "
584+ "while reading terrain",
585+ plnum, terrains_filename, f.x, f.y);
586+ }
587+ } else {
588+ f_player_field.terrains.r = terrains_file.Unsigned8();
589+ }
590+ uint8_t im_kind = 0;
591+ if (triangle_immovable_kinds_file_version < 2) {
592+ im_kind = legacy_triangle_immovable_kinds_bitbuffer.get();
593+ } else {
594+ im_kind = triangle_immovable_kinds_file.Unsigned8();
595 }
596 Map_Object_Data mod =
597 read_unseen_immovable
598- (egbase, triangle_immovable_kinds_file, triangle_immovables_file,
599- triangle_immovables_file_version);
600+ (egbase, im_kind, triangle_immovables_file, triangle_immovables_file_version);
601 f_player_field.map_object_descr[TCoords<>::R] = mod.map_object_descr;
602 }
603
604 { // edges
605 uint8_t mask = 0;
606- if (f_seen | bl_seen)
607+ if (f_seen | bl_seen) {
608 mask = Road_Mask << Road_SouthWest;
609- else if (f_everseen | bl_everseen)
610+ } else if (f_everseen | bl_everseen) {
611 // The player has seen the SouthWest edge but does not see
612 // it now. Load his information about this edge from file.
613- try {roads = roads_file.get() << Road_SouthWest;}
614- catch (const FileRead::File_Boundary_Exceeded &) {
615- throw game_data_error
616- ("Map_Players_View_Data_Packet::Read: player %u: in "
617- "\"%s\": node (%i, %i): unexpected end of file while "
618- "reading Road_SouthWest",
619- plnum, roads_filename, f.x, f.y);
620+ if (road_file_version < 2) {
621+ try {roads = legacy_road_bitbuffer.get() << Road_SouthWest;}
622+ catch (const FileRead::File_Boundary_Exceeded & e) {
623+ throw game_data_error
624+ ("Map_Players_View_Data_Packet::Read: player %u: in "
625+ "\"%s\": node (%i, %i): unexpected end of file while "
626+ "reading Road_SouthWest",
627+ plnum, roads_filename, f.x, f.y);
628+ }
629+ } else {
630+ roads = roads_file.Unsigned8();
631 }
632- if (f_seen | br_seen)
633+ }
634+ if (f_seen | br_seen) {
635 mask |= Road_Mask << Road_SouthEast;
636- else if (f_everseen | br_everseen)
637+ } else if (f_everseen | br_everseen) {
638 // The player has seen the SouthEast edge but does not see
639 // it now. Load his information about this edge from file.
640- try {roads |= roads_file.get() << Road_SouthEast;}
641- catch (const FileRead::File_Boundary_Exceeded &) {
642- throw game_data_error
643- ("Map_Players_View_Data_Packet::Read: player %u: in "
644- "\"%s\": node (%i, %i): unexpected end of file while "
645- "reading Road_SouthEast",
646- plnum, roads_filename, f.x, f.y);
647+ if (road_file_version < 2) {
648+ try {roads |= legacy_road_bitbuffer.get() << Road_SouthEast;}
649+ catch (const FileRead::File_Boundary_Exceeded & e) {
650+ throw game_data_error
651+ ("Map_Players_View_Data_Packet::Read: player %u: in "
652+ "\"%s\": node (%i, %i): unexpected end of file while "
653+ "reading Road_SouthEast",
654+ plnum, roads_filename, f.x, f.y);
655+ }
656+ } else {
657+ roads |= roads_file.Unsigned8();
658 }
659- if (f_seen | r_seen)
660+ }
661+ if (f_seen | r_seen) {
662 mask |= Road_Mask << Road_East;
663- else if (f_everseen | r_everseen)
664+ } else if (f_everseen | r_everseen) {
665 // The player has seen the East edge but does not see
666 // it now. Load his information about this edge from file.
667- try {roads |= roads_file.get() << Road_East;}
668- catch (const FileRead::File_Boundary_Exceeded &) {
669- throw game_data_error
670- ("Map_Players_View_Data_Packet::Read: player %u: in "
671- "\"%s\": node (%i, %i): unexpected end of file while "
672- "reading Road_East",
673- plnum, roads_filename, f.x, f.y);
674+ if (road_file_version < 2) {
675+ try {roads |= legacy_road_bitbuffer.get() << Road_East;}
676+ catch (const FileRead::File_Boundary_Exceeded & e) {
677+ throw game_data_error
678+ ("Map_Players_View_Data_Packet::Read: player %u: in "
679+ "\"%s\": node (%i, %i): unexpected end of file while "
680+ "reading Road_East",
681+ plnum, roads_filename, f.x, f.y);
682+ }
683+ } else {
684+ roads |= roads_file.Unsigned8();
685 }
686+ }
687 roads |= f.field->get_roads() & mask;
688 }
689
690@@ -631,25 +717,33 @@
691
692 // geologic survey
693 try {
694- if
695- ((f_everseen & bl_everseen & br_everseen)
696- and
697- surveys_file.get())
698- {
699- try {
700- f_player_field.resource_amounts.d =
701- survey_amounts_file.get();
702- } catch (const FileRead::File_Boundary_Exceeded &) {
703- throw game_data_error
704- ("Map_Players_View_Data_Packet::Read: player %u: in "
705- "\"%s\": node (%i, %i) t = D: unexpected end of file "
706- "while reading resource amount of surveyed triangle",
707- plnum, survey_amounts_filename, f.x, f.y);
708+ bool survey = false;
709+ if (surveys_file_version < 2) {
710+ survey = (f_everseen & bl_everseen & br_everseen)
711+ && legacy_surveys_bitbuffer.get();
712+ } else {
713+ survey = (f_everseen & bl_everseen & br_everseen)
714+ && surveys_file.Unsigned8();
715+ }
716+ if (survey) {
717+ if (survey_amounts_file_version < 2) {
718+ try {
719+ f_player_field.resource_amounts.d =
720+ legacy_surveys_amount_bitbuffer.get();
721+ } catch (const FileRead::File_Boundary_Exceeded & e) {
722+ throw game_data_error
723+ ("Map_Players_View_Data_Packet::Read: player %u: in "
724+ "\"%s\": node (%i, %i) t = D: unexpected end of file "
725+ "while reading resource amount of surveyed triangle",
726+ plnum, survey_amounts_filename, f.x, f.y);
727+ }
728+ } else {
729+ f_player_field.resource_amounts.d = survey_amounts_file.Unsigned8();
730 }
731 try {
732 f_player_field.time_triangle_last_surveyed[TCoords<>::D] =
733 survey_times_file.Unsigned32();
734- } catch (const FileRead::File_Boundary_Exceeded &) {
735+ } catch (const FileRead::File_Boundary_Exceeded & e) {
736 throw game_data_error
737 ("Map_Players_View_Data_Packet::Read: player %u: in "
738 "\"%s\":%lu: node (%i, %i) t = D: unexpected end of "
739@@ -660,7 +754,7 @@
740 f.x, f.y);
741 }
742 }
743- } catch (const FileRead::File_Boundary_Exceeded &) {
744+ } catch (const FileRead::File_Boundary_Exceeded & e) {
745 throw game_data_error
746 ("Map_Players_View_Data_Packet::Read: player %u: in \"%s\": "
747 "node (%i, %i) t = D: unexpected end of file while reading "
748@@ -668,25 +762,33 @@
749 plnum, surveys_filename, f.x, f.y);
750 }
751 try {
752- if
753- ((f_everseen & br_everseen & r_everseen)
754- and
755- surveys_file.get())
756- {
757- try {
758- f_player_field.resource_amounts.r =
759- survey_amounts_file.get();
760- } catch (const FileRead::File_Boundary_Exceeded &) {
761- throw game_data_error
762- ("Map_Players_View_Data_Packet::Read: player %u: in "
763- "\"%s\": node (%i, %i) t = R: unexpected end of file "
764- "while reading resource amount of surveyed triangle",
765- plnum, survey_amounts_filename, f.x, f.y);
766+ bool survey = false;
767+ if (surveys_file_version < 2) {
768+ survey = (f_everseen & br_everseen & r_everseen)
769+ && legacy_surveys_bitbuffer.get();
770+ } else {
771+ survey = (f_everseen & br_everseen & r_everseen)
772+ && surveys_file.Unsigned8();
773+ }
774+ if (survey) {
775+ if (survey_amounts_file_version < 2) {
776+ try {
777+ f_player_field.resource_amounts.r =
778+ legacy_surveys_amount_bitbuffer.get();
779+ } catch (const FileRead::File_Boundary_Exceeded & e) {
780+ throw game_data_error
781+ ("Map_Players_View_Data_Packet::Read: player %u: in "
782+ "\"%s\": node (%i, %i) t = R: unexpected end of file "
783+ "while reading resource amount of surveyed triangle",
784+ plnum, survey_amounts_filename, f.x, f.y);
785+ }
786+ } else {
787+ f_player_field.resource_amounts.r = survey_amounts_file.Unsigned8();
788 }
789 try {
790 f_player_field.time_triangle_last_surveyed[TCoords<>::R] =
791 survey_times_file.Unsigned32();
792- } catch (const FileRead::File_Boundary_Exceeded &) {
793+ } catch (const FileRead::File_Boundary_Exceeded & e) {
794 throw game_data_error
795 ("Map_Players_View_Data_Packet::Read: player %u: in "
796 "\"%s\":%lu: node (%i, %i) t = R: unexpected end of "
797@@ -697,7 +799,7 @@
798 f.x, f.y);
799 }
800 }
801- } catch (const FileRead::File_Boundary_Exceeded &) {
802+ } catch (const FileRead::File_Boundary_Exceeded & e) {
803 throw game_data_error
804 ("Map_Players_View_Data_Packet::Read: player %u: in \"%s\": "
805 "node (%i, %i) t = R: unexpected end of file while reading "
806@@ -726,7 +828,7 @@
807
808 inline static void write_unseen_immovable
809 (Map_Object_Data const * map_object_data,
810- BitOutBuffer<2> & immovable_kinds_file, FileWrite & immovables_file)
811+ FileWrite & immovable_kinds_file, FileWrite & immovables_file)
812 {
813 Map_Object_Descr const * const map_object_descr = map_object_data->map_object_descr;
814 const Player::Constructionsite_Information & csi = map_object_data->csi;
815@@ -759,7 +861,8 @@
816 immovables_file.Unsigned32(csi.totaltime);
817 immovables_file.Unsigned32(csi.completedtime);
818 }
819- }
820+ } else if (map_object_descr == &g_portdock_descr)
821+ immovable_kind = 4;
822 else
823 {
824 // We should never get here.. debugging code until assert(false)
825@@ -771,7 +874,7 @@
826 map_object_descr->descname().c_str());
827 assert(false);
828 }
829- immovable_kinds_file.put(immovable_kind);
830+ immovable_kinds_file.Unsigned8(immovable_kind);
831 }
832
833 #define WRITE(file, filename_template, version) \
834@@ -793,18 +896,18 @@
835 iterate_players_existing_const(plnum, nr_players, egbase, player)
836 if (const Player::Field * const player_fields = player->m_fields) {
837 FileWrite unseen_times_file;
838- BitOutBuffer<2> node_immovable_kinds_file;
839+ FileWrite node_immovable_kinds_file;
840 FileWrite node_immovables_file;
841- BitOutBuffer<2> roads_file;
842- BitOutBuffer<4> terrains_file;
843- BitOutBuffer<2> triangle_immovable_kinds_file;
844+ FileWrite roads_file;
845+ FileWrite terrains_file;
846+ FileWrite triangle_immovable_kinds_file;
847 FileWrite triangle_immovables_file;
848 FileWrite owners_file;
849- BitOutBuffer<1> surveys_file;
850- BitOutBuffer<4> survey_amounts_file;
851+ FileWrite surveys_file;
852+ FileWrite survey_amounts_file;
853 FileWrite survey_times_file;
854 FileWrite vision_file;
855- BitOutBuffer<1> border_file;
856+ FileWrite border_file;
857 for
858 (FCoords first_in_row(Coords(0, 0), &first_field);
859 first_in_row.y < mapheight;
860@@ -846,10 +949,12 @@
861 write_unseen_immovable(&mod, node_immovable_kinds_file, node_immovables_file);
862
863 // write whether this field had a border the last time it was seen
864- border_file.put(f_player_field.border ? 1 : 0);
865- border_file.put(f_player_field.border_r ? 1 : 0);
866- border_file.put(f_player_field.border_br ? 1 : 0);
867- border_file.put(f_player_field.border_bl ? 1 : 0);
868+ uint8_t borders = 0;
869+ borders |= f_player_field.border;
870+ borders |= f_player_field.border_r << 1;
871+ borders |= f_player_field.border_br << 2;
872+ borders |= f_player_field.border_bl << 3;
873+ border_file.Unsigned8(borders);
874 }
875
876 // triangles
877@@ -859,7 +964,7 @@
878 (not bl_seen & not br_seen &
879 (f_everseen | bl_everseen | br_everseen))
880 {
881- terrains_file.put(f_player_field.terrains.d);
882+ terrains_file.Unsigned8(f_player_field.terrains.d);
883 Map_Object_Data mod;
884 mod.map_object_descr = f_player_field.map_object_descr[TCoords<>::D];
885 write_unseen_immovable(&mod, triangle_immovable_kinds_file, triangle_immovables_file);
886@@ -870,7 +975,7 @@
887 (not br_seen & not r_seen &
888 (f_everseen | br_everseen | r_everseen))
889 {
890- terrains_file.put(f_player_field.terrains.r);
891+ terrains_file.Unsigned8(f_player_field.terrains.r);
892 Map_Object_Data mod;
893 mod.map_object_descr = f_player_field.map_object_descr[TCoords<>::R];
894 write_unseen_immovable(&mod, triangle_immovable_kinds_file, triangle_immovables_file);
895@@ -878,11 +983,11 @@
896
897 // edges
898 if (not bl_seen & (f_everseen | bl_everseen))
899- roads_file.put(f_player_field.road_sw());
900+ roads_file.Unsigned8(f_player_field.road_sw());
901 if (not br_seen & (f_everseen | br_everseen))
902- roads_file.put(f_player_field.road_se());
903+ roads_file.Unsigned8(f_player_field.road_se());
904 if (not r_seen & (f_everseen | r_everseen))
905- roads_file.put(f_player_field.road_e ());
906+ roads_file.Unsigned8(f_player_field.road_e ());
907 }
908
909 // geologic survey
910@@ -890,10 +995,10 @@
911 const uint32_t time_last_surveyed =
912 f_player_field.time_triangle_last_surveyed[TCoords<>::D];
913 const uint8_t has_info = time_last_surveyed != 0xffffffff;
914- surveys_file.put(has_info);
915+ surveys_file.Unsigned8(has_info);
916 if (has_info) {
917 survey_amounts_file
918- .put(f_player_field.resource_amounts.d);
919+ .Unsigned8(f_player_field.resource_amounts.d);
920 survey_times_file.Unsigned32(time_last_surveyed);
921 }
922 }
923@@ -901,10 +1006,10 @@
924 const uint32_t time_last_surveyed =
925 f_player_field.time_triangle_last_surveyed[TCoords<>::R];
926 const uint8_t has_info = time_last_surveyed != 0xffffffff;
927- surveys_file.put(has_info);
928+ surveys_file.Unsigned8(has_info);
929 if (has_info) {
930 survey_amounts_file
931- .put(f_player_field.resource_amounts.r);
932+ .Unsigned8(f_player_field.resource_amounts.r);
933 survey_times_file.Unsigned32(time_last_surveyed);
934 }
935 }
936@@ -981,4 +1086,7 @@
937 }
938 }
939
940+
941+
942 }
943+

Subscribers

People subscribed via source and target branches

to status/vote changes: