Merge lp:~widelands-dev/widelands/map_compatibility into lp:widelands
- map_compatibility
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | GunChleoc |
Proposed branch: | lp:~widelands-dev/widelands/map_compatibility |
Merge into: | lp:widelands |
Diff against target: |
1151 lines (+574/-196) 10 files modified
src/logic/expedition_bootstrap.cc (+25/-13) src/logic/expedition_bootstrap.h (+3/-2) src/map_io/map_buildingdata_packet.cc (+302/-95) src/map_io/map_buildingdata_packet.h (+4/-0) src/map_io/map_exploration_packet.cc (+15/-1) src/map_io/map_flagdata_packet.cc (+53/-3) src/map_io/map_player_names_and_tribes_packet.cc (+1/-2) src/map_io/map_players_view_packet.cc (+141/-64) src/map_io/map_roaddata_packet.cc (+22/-5) src/map_io/map_scripting_packet.cc (+8/-11) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/map_compatibility |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
SirVer | Needs Information | ||
Review via email: mp+276088@code.launchpad.net |
Commit message
Description of the change
There is a problem with loading older maps, so I put the remaining compatibility code for maps back in.
It was removed in r7558.
Nasenbaer (nasenbaer) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
Hi Nasenbaer,
the history here is that I recently removed all savegame compatibility code. I assumed te same thing that you do, thet maps would not know about buildings, workers etc. Turns out they do, so we get cpmpatibility problems with maps. I think one of he problematic maps was Together We're Strong - load it in he Editor to trigger the problem.
Nasenbaer (nasenbaer) wrote : | # |
Hi GunChleoc,
okay, I see the problem - in this case it's the files below "player" in the map directory. Which aren't loaded when starting a game anyways - that's why the error is triggered in the editor, but not when starting a new game.
Speaking of "Together we're strong" - for some reason I committed the map with the player directory. However I am not sure whether that was on purpose or not. Anyways, as the player directory is not loaded during starting a game, it can clearly be deleted - this will indeed fix the problem in the editor as well.
Anyway this would not fix player created maps from Build18 or before, as these contain the player directory as well. However to those applies the same as to "Together we're strong" - the player directory is not loaded during starting a game.
Long text short sense: I would prefere to handle it the same in the editor - simply do not load the files. And if loading the files is needed for some reason with newer maps - don't load if the map is too old.
What do you think?
GunChleoc (gunchleoc) wrote : | # |
Yes, I would like that - you obviously know a lot more about the map loading code than I do. Would you like to take this on?
TiborB (tiborb95) wrote : | # |
So this fix is to allow editing of old maps? And all what is needed to edit them is to remove some directory from wmf archive? Then I would not reintroduce logic that was removed, but just left it unfixed or put an info in error test saying what should be done to make the map loadable in editor again. I think there is so little peoples to be affected by this that this would be much better workaround.
GunChleoc (gunchleoc) wrote : | # |
I agree - the code control flow is a bit complex though, so I have to find out how to pull this off. I think that this sill probably best done in a fresh branch.
bunnybot (widelandsofficial) wrote : | # |
Hi, I am bunnybot (https:/
I am keeping the source branch lp:~widelands-dev/widelands/map_compatibility mirrored to
https:/
The latest continuous integration build can always be found here:
https:/
Please do not merge without making sure that it passes.
You can give me commands by starting a line with @bunnybot <command>. I understand:
merge: Merges the source branch into the target branch, closing the pull request.
bunnybot (widelandsofficial) wrote : | # |
Travis build 122 has changed state to: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Travis build 122 has changed state to: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Bunnybot encountered an error while working on this merge proposal:
Running 'git push github _widelands_
ssh: Could not resolve hostname github.com: Name or service not known
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
bunnybot (widelandsofficial) wrote : | # |
Bunnybot encountered an error while working on this merge proposal:
<urlopen error [Errno -2] Name or service not known>
bunnybot (widelandsofficial) wrote : | # |
Travis build 122 has changed state to: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Travis build 122 has changed state to: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Bunnybot encountered an error while working on this merge proposal:
<urlopen error [Errno -2] Name or service not known>
bunnybot (widelandsofficial) wrote : | # |
Bunnybot encountered an error while working on this merge proposal:
<urlopen error [Errno -2] Name or service not known>
SirVer (sirver) wrote : | # |
Is there a way I can trigger the bug this is trying to fix in trunk? Together we're strong loaded just fine in the editor for me and so did every other shipped map I tried.
GunChleoc (gunchleoc) wrote : | # |
We have updated Together We're Strong because of the artifacts, so you will need to grab the map from Build 18.
I actually want to take a different approach to this: Rather than putting the compatibility code back in, only load needed packages in the editor. So, this branch is now only sitting here as a reminder.
Preview Diff
1 | === modified file 'src/logic/expedition_bootstrap.cc' |
2 | --- src/logic/expedition_bootstrap.cc 2015-11-11 09:52:55 +0000 |
3 | +++ src/logic/expedition_bootstrap.cc 2015-11-21 10:21:30 +0000 |
4 | @@ -260,22 +260,34 @@ |
5 | } |
6 | } |
7 | |
8 | -void ExpeditionBootstrap::load(Warehouse& warehouse, FileRead& fr, |
9 | - Game& game, MapObjectLoader& mol) |
10 | +constexpr uint16_t kCurrentPacketVersionWarehouse = 6; |
11 | + |
12 | +void ExpeditionBootstrap::load |
13 | + (uint32_t warehouse_packet_version, Warehouse& warehouse, FileRead& fr, |
14 | + Game& game, MapObjectLoader& mol) |
15 | { |
16 | - // Expedition workers |
17 | - const uint8_t num_workers = fr.unsigned_8(); |
18 | - for (uint8_t i = 0; i < num_workers; ++i) { |
19 | - workers_.emplace_back(new ExpeditionWorker(nullptr)); |
20 | - if (fr.unsigned_8() == 1) { |
21 | - Request* worker_request = new Request |
22 | - (warehouse, 0, ExpeditionBootstrap::worker_callback, wwWORKER); |
23 | - workers_.back()->request.reset(worker_request); |
24 | - worker_request->read(fr, game, mol); |
25 | - workers_.back()->worker = nullptr; |
26 | + try { |
27 | + if (warehouse_packet_version >= kCurrentPacketVersionWarehouse) { |
28 | + // Expedition workers |
29 | + const uint8_t num_workers = fr.unsigned_8(); |
30 | + for (uint8_t i = 0; i < num_workers; ++i) { |
31 | + workers_.emplace_back(new ExpeditionWorker(nullptr)); |
32 | + if (fr.unsigned_8() == 1) { |
33 | + Request* worker_request = new Request |
34 | + (warehouse, 0, ExpeditionBootstrap::worker_callback, wwWORKER); |
35 | + workers_.back()->request.reset(worker_request); |
36 | + worker_request->read(fr, game, mol); |
37 | + workers_.back()->worker = nullptr; |
38 | + } else { |
39 | + workers_.back()->worker = &mol.get<Worker>(fr.unsigned_32()); |
40 | + } |
41 | + } |
42 | } else { |
43 | - workers_.back()->worker = &mol.get<Worker>(fr.unsigned_32()); |
44 | + throw UnhandledVersionError("ExpeditionBootstrap", |
45 | + warehouse_packet_version, kCurrentPacketVersionWarehouse); |
46 | } |
47 | + } catch (const WException & e) { |
48 | + throw wexception("expedition bootstrap: %s", e.what()); |
49 | } |
50 | |
51 | // Expedition WaresQueues |
52 | |
53 | === modified file 'src/logic/expedition_bootstrap.h' |
54 | --- src/logic/expedition_bootstrap.h 2015-11-11 09:52:55 +0000 |
55 | +++ src/logic/expedition_bootstrap.h 2015-11-21 10:21:30 +0000 |
56 | @@ -75,8 +75,9 @@ |
57 | |
58 | // Save/Load this into a file. The actual data is stored in the buildingdata |
59 | // packet, and there in the warehouse data packet. |
60 | - void load(Warehouse& warehouse, FileRead& fr, |
61 | - Game& game, MapObjectLoader& mol); |
62 | + void load |
63 | + (uint32_t warehouse_packet_version, Warehouse& warehouse, |
64 | + FileRead& fr, Game& game, MapObjectLoader& mol); |
65 | void save(FileWrite& fw, Game& game, MapObjectSaver& mos); |
66 | |
67 | private: |
68 | |
69 | === modified file 'src/map_io/map_buildingdata_packet.cc' |
70 | --- src/map_io/map_buildingdata_packet.cc 2015-11-11 09:53:54 +0000 |
71 | +++ src/map_io/map_buildingdata_packet.cc 2015-11-21 10:21:30 +0000 |
72 | @@ -52,10 +52,12 @@ |
73 | namespace Widelands { |
74 | |
75 | // Overall package version |
76 | +// Since V3: m_old_buildings vector |
77 | constexpr uint16_t kCurrentPacketVersion = 4; |
78 | |
79 | // Building type package versions |
80 | constexpr uint16_t kCurrentPacketVersionDismantlesite = 1; |
81 | +// Since V3: m_prev_building not written |
82 | constexpr uint16_t kCurrentPacketVersionConstructionsite = 3; |
83 | constexpr uint16_t kCurrentPacketPFBuilding = 1; |
84 | constexpr uint16_t kCurrentPacketVersionWarehouse = 6; |
85 | @@ -77,9 +79,17 @@ |
86 | |
87 | try { |
88 | uint16_t const packet_version = fr.unsigned_16(); |
89 | - if (packet_version == kCurrentPacketVersion) { |
90 | - while (! fr.end_of_file()) { |
91 | + if (1 <= packet_version && packet_version <= kCurrentPacketVersion) { |
92 | + for (;;) { |
93 | + if (2 <= packet_version && fr.end_of_file()) |
94 | + break; |
95 | Serial const serial = fr.unsigned_32(); |
96 | + if (packet_version < 2 && serial == 0xffffffff) { |
97 | + if (!fr.end_of_file()) |
98 | + throw GameDataError |
99 | + ("expected end of file after serial 0xffffffff"); |
100 | + break; |
101 | + } |
102 | try { |
103 | Building & building = mol.get<Building>(serial); |
104 | |
105 | @@ -202,6 +212,10 @@ |
106 | // {ConstructionSite, Warehouse, ProductionSite} |
107 | assert(false); |
108 | } |
109 | + if (packet_version < 3) { |
110 | + read_formerbuildings_v2(building, fr, game, mol); |
111 | + } |
112 | + |
113 | mol.mark_object_as_loaded(building); |
114 | } catch (const WException & e) { |
115 | throw GameDataError("building %u: %s", serial, e.what()); |
116 | @@ -215,6 +229,46 @@ |
117 | } |
118 | } |
119 | |
120 | +void MapBuildingdataPacket::read_formerbuildings_v2 |
121 | + (Building& b, FileRead&, Game&, MapObjectLoader&) |
122 | +{ |
123 | + const TribeDescr & t = b.owner().tribe(); |
124 | + DescriptionIndex b_idx = t.building_index(b.descr().name()); |
125 | + if (is_a(ProductionSite, &b)) { |
126 | + assert(b.m_old_buildings.empty()); |
127 | + b.m_old_buildings.push_back(b_idx); |
128 | + } else if (is_a(Warehouse, &b)) { |
129 | + assert(b.m_old_buildings.empty()); |
130 | + b.m_old_buildings.push_back(b_idx); |
131 | + } else if (is_a(DismantleSite, &b)) { |
132 | + // Former buildings filled with the current one |
133 | + // upon building init. |
134 | + assert(!b.m_old_buildings.empty()); |
135 | + } else if (is_a(ConstructionSite, &b)) { |
136 | + // Not needed for csite. |
137 | + return; |
138 | + } else { |
139 | + assert(false); |
140 | + } |
141 | + |
142 | + // iterate through all buildings to find first predecessor |
143 | + for (;;) { |
144 | + DescriptionIndex former_idx = b.m_old_buildings.front(); |
145 | + const BuildingDescr * oldest = t.get_building_descr(former_idx); |
146 | + if (!oldest->is_enhanced()) { |
147 | + break; |
148 | + } |
149 | + for (DescriptionIndex i = 0; i < t.get_nrbuildings(); ++i) { |
150 | + BuildingDescr const * ob = t.get_building_descr(i); |
151 | + if (ob->enhancement() == former_idx) { |
152 | + b.m_old_buildings.insert(b.m_old_buildings.begin(), i); |
153 | + break; |
154 | + } |
155 | + } |
156 | + } |
157 | +} |
158 | + |
159 | + |
160 | void MapBuildingdataPacket::read_partially_finished_building |
161 | (PartiallyFinishedBuilding & pfb, |
162 | FileRead & fr, |
163 | @@ -285,9 +339,14 @@ |
164 | { |
165 | try { |
166 | uint16_t const packet_version = fr.unsigned_16(); |
167 | - if (packet_version >= kCurrentPacketVersionConstructionsite) { |
168 | + if (packet_version == 1) |
169 | + return read_constructionsite_v1(constructionsite, fr, game, mol); |
170 | + |
171 | + if (packet_version >= 2) { |
172 | read_partially_finished_building(constructionsite, fr, game, mol); |
173 | |
174 | + const TribeDescr & tribe = constructionsite.owner().tribe(); |
175 | + |
176 | for (ConstructionSite::Wares::iterator wares_iter = constructionsite.m_wares.begin(); |
177 | wares_iter != constructionsite.m_wares.end(); |
178 | ++wares_iter) { |
179 | @@ -296,6 +355,13 @@ |
180 | (ConstructionSite::wares_queue_callback, &constructionsite); |
181 | } |
182 | |
183 | + if (packet_version <= 2) { |
184 | + if (fr.unsigned_8()) { |
185 | + DescriptionIndex idx = tribe.safe_building_index(fr.c_string()); |
186 | + constructionsite.m_old_buildings.push_back(idx); |
187 | + } |
188 | + } |
189 | + |
190 | constructionsite.m_fetchfromflag = fr. signed_32(); |
191 | } else { |
192 | throw UnhandledVersionError("MapBuildingdataPacket - Constructionsite", |
193 | @@ -306,6 +372,66 @@ |
194 | } |
195 | } |
196 | |
197 | +void MapBuildingdataPacket::read_constructionsite_v1 |
198 | + (ConstructionSite & constructionsite, |
199 | + FileRead & fr, |
200 | + Game & game, |
201 | + MapObjectLoader & mol) |
202 | +{ |
203 | + const TribeDescr & tribe = constructionsite.owner().tribe(); |
204 | + constructionsite.m_building = |
205 | + tribe.get_building_descr(tribe.safe_building_index(fr.c_string())); |
206 | + if (fr.unsigned_8()) { |
207 | + DescriptionIndex bidx = tribe.safe_building_index(fr.c_string()); |
208 | + constructionsite.m_old_buildings.push_back(bidx); |
209 | + } |
210 | + |
211 | + delete constructionsite.m_builder_request; |
212 | + if (fr.unsigned_8()) { |
213 | + constructionsite.m_builder_request = |
214 | + new Request |
215 | + (constructionsite, |
216 | + 0, |
217 | + ConstructionSite::request_builder_callback, |
218 | + wwWORKER); |
219 | + constructionsite.m_builder_request->read(fr, game, mol); |
220 | + } else |
221 | + constructionsite.m_builder_request = nullptr; |
222 | + |
223 | + if (uint32_t const builder_serial = fr.unsigned_32()) { |
224 | + try { |
225 | + constructionsite.m_builder = &mol.get<Worker>(builder_serial); |
226 | + } catch (const WException & e) { |
227 | + throw GameDataError |
228 | + ("builder (%u): %s", builder_serial, e.what()); |
229 | + } |
230 | + } else |
231 | + constructionsite.m_builder = nullptr; |
232 | + |
233 | + try { |
234 | + uint16_t const size = fr.unsigned_16(); |
235 | + constructionsite.m_wares.resize(size); |
236 | + for (uint16_t i = 0; i < constructionsite.m_wares.size(); ++i) |
237 | + { |
238 | + constructionsite.m_wares[i] = |
239 | + new WaresQueue |
240 | + (constructionsite, INVALID_INDEX, 0); |
241 | + constructionsite.m_wares[i]->set_callback |
242 | + (ConstructionSite::wares_queue_callback, &constructionsite); |
243 | + constructionsite.m_wares[i]->read(fr, game, mol); |
244 | + } |
245 | + } catch (const WException & e) { |
246 | + throw GameDataError("wares: %s", e.what()); |
247 | + } |
248 | + |
249 | + constructionsite.m_fetchfromflag = fr. signed_32(); |
250 | + |
251 | + constructionsite.m_working = fr.unsigned_8 (); |
252 | + constructionsite.m_work_steptime = fr.unsigned_32(); |
253 | + constructionsite.m_work_completed = fr.unsigned_32(); |
254 | + constructionsite.m_work_steps = fr.unsigned_32(); |
255 | +} |
256 | + |
257 | void MapBuildingdataPacket::read_dismantlesite |
258 | (DismantleSite & dms, |
259 | FileRead & fr, |
260 | @@ -336,31 +462,59 @@ |
261 | { |
262 | try { |
263 | uint16_t const packet_version = fr.unsigned_16(); |
264 | - if (packet_version == kCurrentPacketVersionWarehouse) { |
265 | + if (1 <= packet_version && packet_version <= kCurrentPacketVersionWarehouse) { |
266 | Player& player = warehouse.owner(); |
267 | warehouse.init_containers(player); |
268 | const TribeDescr& tribe = player.tribe(); |
269 | |
270 | while (fr.unsigned_8()) { |
271 | - const DescriptionIndex& id = tribe.ware_index(fr.c_string()); |
272 | - uint32_t amount = fr.unsigned_32(); |
273 | - Warehouse::StockPolicy policy = |
274 | - static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
275 | - |
276 | - if (game.tribes().ware_exists(id)) { |
277 | - warehouse.insert_wares(id, amount); |
278 | - warehouse.set_ware_policy(id, policy); |
279 | + DescriptionIndex const id = tribe.ware_index(fr.c_string()); |
280 | + if (packet_version >= 5) { |
281 | + uint32_t amount = fr.unsigned_32(); |
282 | + Warehouse::StockPolicy policy = |
283 | + static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
284 | + |
285 | + if (game.tribes().ware_exists(id)) { |
286 | + warehouse.insert_wares(id, amount); |
287 | + warehouse.set_ware_policy(id, policy); |
288 | + } |
289 | + } else { |
290 | + uint16_t amount = fr.unsigned_16(); |
291 | + |
292 | + if (game.tribes().ware_exists(id)) |
293 | + warehouse.insert_wares(id, amount); |
294 | } |
295 | } |
296 | while (fr.unsigned_8()) { |
297 | - const DescriptionIndex& id = tribe.worker_index(fr.c_string()); |
298 | - uint32_t amount = fr.unsigned_32(); |
299 | - Warehouse::StockPolicy policy = |
300 | - static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
301 | - |
302 | - if (game.tribes().worker_exists(id)) { |
303 | - warehouse.insert_workers(id, amount); |
304 | - warehouse.set_worker_policy(id, policy); |
305 | + DescriptionIndex const id = tribe.worker_index(fr.c_string()); |
306 | + if (packet_version >= 5) { |
307 | + uint32_t amount = fr.unsigned_32(); |
308 | + Warehouse::StockPolicy policy = |
309 | + static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
310 | + |
311 | + if (game.tribes().worker_exists(id)) { |
312 | + warehouse.insert_workers(id, amount); |
313 | + warehouse.set_worker_policy(id, policy); |
314 | + } |
315 | + } else { |
316 | + uint16_t amount = fr.unsigned_16(); |
317 | + |
318 | + if (game.tribes().worker_exists(id)) |
319 | + warehouse.insert_workers(id, amount); |
320 | + } |
321 | + } |
322 | + |
323 | + if (packet_version <= 3) { |
324 | + // eat the obsolete idle request structures |
325 | + uint32_t nrrequests = fr.unsigned_16(); |
326 | + while (nrrequests--) { |
327 | + std::unique_ptr<Request> req |
328 | + (new Request |
329 | + (warehouse, |
330 | + 0, |
331 | + &Warehouse::request_cb, |
332 | + wwWORKER)); |
333 | + req->read(fr, game, mol); |
334 | } |
335 | } |
336 | |
337 | @@ -372,6 +526,13 @@ |
338 | |
339 | try { |
340 | Worker & worker = mol.get<Worker>(worker_serial); |
341 | + if (1 == packet_version) { |
342 | + char const * const name = fr.c_string(); |
343 | + if (name != worker.descr().name()) |
344 | + throw GameDataError |
345 | + ("expected %s but found \"%s\"", |
346 | + worker.descr().name().c_str(), name); |
347 | + } |
348 | const DescriptionIndex& worker_index = tribe.worker_index(worker.descr().name().c_str()); |
349 | if (!warehouse.m_incorporated_workers.count(worker_index)) |
350 | warehouse.m_incorporated_workers[worker_index] = std::vector<Worker *>(); |
351 | @@ -386,86 +547,130 @@ |
352 | |
353 | const std::vector<DescriptionIndex>& worker_types_without_cost = tribe.worker_types_without_cost(); |
354 | |
355 | - for (;;) { |
356 | - char const * const worker_typename = fr.c_string (); |
357 | - if (!*worker_typename) // encountered the terminator ("") |
358 | - break; |
359 | - uint32_t const next_spawn = fr.unsigned_32(); |
360 | - DescriptionIndex const worker_index = |
361 | - tribe.safe_worker_index(worker_typename); |
362 | + if (1 == packet_version) { // a single next_spawn time for "carrier" |
363 | + uint32_t const next_spawn = fr.unsigned_32(); |
364 | + const DescriptionIndex worker_index = tribe.carrier(); |
365 | + |
366 | if (!game.tribes().worker_exists(worker_index)) { |
367 | log |
368 | ("WARNING: %s %u has a next_spawn time for nonexistent " |
369 | "worker type \"%s\" set to %u, ignoring\n", |
370 | warehouse.descr().descname().c_str(), warehouse.serial(), |
371 | - worker_typename, next_spawn); |
372 | - continue; |
373 | - } |
374 | - if (tribe.get_worker_descr(worker_index)->buildcost().size()) { |
375 | + "carrier", next_spawn); |
376 | + } else if |
377 | + (tribe.get_worker_descr(worker_index)->buildcost().size()) |
378 | + { |
379 | log |
380 | ("WARNING: %s %u has a next_spawn time for worker type " |
381 | "\"%s\", that costs something to build, set to %u, " |
382 | "ignoring\n", |
383 | warehouse.descr().descname().c_str(), warehouse.serial(), |
384 | - worker_typename, next_spawn); |
385 | - continue; |
386 | - } |
387 | - for (uint8_t i = 0;; ++i) { |
388 | - assert(i < worker_types_without_cost.size()); |
389 | - if (worker_types_without_cost.at(i) == worker_index) { |
390 | - if |
391 | - (warehouse.m_next_worker_without_cost_spawn[i] != never()) |
392 | - throw GameDataError |
393 | - ( |
394 | - "%s %u has a next_spawn time for worker type " |
395 | - "\"%s\" set to %u, but it was previously set " |
396 | - "to %u\n", |
397 | - warehouse.descr().descname().c_str(), warehouse.serial(), |
398 | - worker_typename, next_spawn, |
399 | - warehouse.m_next_worker_without_cost_spawn[i]); |
400 | - warehouse.m_next_worker_without_cost_spawn[i] = next_spawn; |
401 | + "carrier", next_spawn); |
402 | + } else |
403 | + for (uint8_t i = 0;; ++i) { |
404 | + assert(i < worker_types_without_cost.size()); |
405 | + if (worker_types_without_cost.at(i) == worker_index) { |
406 | + if |
407 | + (warehouse.m_next_worker_without_cost_spawn[i] != never()) |
408 | + { |
409 | + warehouse.molog |
410 | + ("read_warehouse: " |
411 | + "m_next_worker_without_cost_spawn[%u] = %u\n", |
412 | + i, warehouse.m_next_worker_without_cost_spawn[i]); |
413 | + } |
414 | + assert(warehouse.m_next_worker_without_cost_spawn[i] == never()); |
415 | + warehouse.m_next_worker_without_cost_spawn[i] = next_spawn; |
416 | + break; |
417 | + } |
418 | + } |
419 | + } else |
420 | + for (;;) { |
421 | + char const * const worker_typename = fr.c_string (); |
422 | + if (!*worker_typename) // encountered the terminator ("") |
423 | break; |
424 | - } |
425 | - } |
426 | - } |
427 | - // The checks that the warehouse has a next_spawn time for each |
428 | - // worker type that the player is allowed to spawn, is in |
429 | - // Warehouse::load_finish. |
430 | - |
431 | - // Read planned worker data |
432 | - // Consistency checks are in Warehouse::load_finish |
433 | - uint32_t nr_planned_workers = fr.unsigned_32(); |
434 | - while (nr_planned_workers--) { |
435 | - warehouse.m_planned_workers.push_back |
436 | - (Warehouse::PlannedWorkers()); |
437 | - Warehouse::PlannedWorkers & pw = |
438 | - warehouse.m_planned_workers.back(); |
439 | - pw.index = tribe.worker_index(fr.c_string()); |
440 | - pw.amount = fr.unsigned_32(); |
441 | - |
442 | - uint32_t nr_requests = fr.unsigned_32(); |
443 | - while (nr_requests--) { |
444 | - pw.requests.push_back |
445 | - (new Request |
446 | - (warehouse, |
447 | - 0, |
448 | - &Warehouse::request_cb, |
449 | - wwWORKER)); |
450 | - pw.requests.back()->read(fr, game, mol); |
451 | - } |
452 | - } |
453 | - |
454 | - warehouse.m_next_stock_remove_act = fr.unsigned_32(); |
455 | - |
456 | - if (warehouse.descr().get_isport()) { |
457 | - if (Serial portdock = fr.unsigned_32()) { |
458 | - warehouse.m_portdock = &mol.get<PortDock>(portdock); |
459 | - warehouse.m_portdock->set_economy(warehouse.get_economy()); |
460 | - // Expedition specific stuff. This is done in this packet |
461 | - // because the "new style" loader is not supported and |
462 | - // doesn't lend itself to request and other stuff. |
463 | - if (warehouse.m_portdock->expedition_started()) { |
464 | - warehouse.m_portdock->expedition_bootstrap()->load(warehouse, fr, game, mol); |
465 | + uint32_t const next_spawn = fr.unsigned_32(); |
466 | + DescriptionIndex const worker_index = |
467 | + tribe.safe_worker_index(worker_typename); |
468 | + if (!tribe.has_worker(worker_index)) { |
469 | + log |
470 | + ("WARNING: %s %u has a next_spawn time for nonexistent " |
471 | + "worker type \"%s\" set to %u, ignoring\n", |
472 | + warehouse.descr().descname().c_str(), warehouse.serial(), |
473 | + worker_typename, next_spawn); |
474 | + continue; |
475 | + } |
476 | + if (tribe.get_worker_descr(worker_index)->buildcost().size()) { |
477 | + log |
478 | + ("WARNING: %s %u has a next_spawn time for worker type " |
479 | + "\"%s\", that costs something to build, set to %u, " |
480 | + "ignoring\n", |
481 | + warehouse.descr().descname().c_str(), warehouse.serial(), |
482 | + worker_typename, next_spawn); |
483 | + continue; |
484 | + } |
485 | + for (uint8_t i = 0;; ++i) { |
486 | + assert(i < worker_types_without_cost.size()); |
487 | + if (worker_types_without_cost.at(i) == worker_index) { |
488 | + if |
489 | + (warehouse.m_next_worker_without_cost_spawn[i] != never()) |
490 | + throw GameDataError |
491 | + ( |
492 | + "%s %u has a next_spawn time for worker type " |
493 | + "\"%s\" set to %u, but it was previously set " |
494 | + "to %u\n", |
495 | + warehouse.descr().descname().c_str(), warehouse.serial(), |
496 | + worker_typename, next_spawn, |
497 | + warehouse.m_next_worker_without_cost_spawn[i]); |
498 | + warehouse.m_next_worker_without_cost_spawn[i] = |
499 | + next_spawn; |
500 | + break; |
501 | + } |
502 | + } |
503 | + } |
504 | + // The checks that the warehouse has a next_spawn time for each |
505 | + // worker type that the player is allowed to spawn, is in |
506 | + // Warehouse::load_finish. |
507 | + |
508 | + if (packet_version >= 3) { |
509 | + // Read planned worker data |
510 | + // Consistency checks are in Warehouse::load_finish |
511 | + uint32_t nr_planned_workers = fr.unsigned_32(); |
512 | + while (nr_planned_workers--) { |
513 | + warehouse.m_planned_workers.push_back |
514 | + (Warehouse::PlannedWorkers()); |
515 | + Warehouse::PlannedWorkers & pw = |
516 | + warehouse.m_planned_workers.back(); |
517 | + pw.index = tribe.worker_index(fr.c_string()); |
518 | + pw.amount = fr.unsigned_32(); |
519 | + |
520 | + uint32_t nr_requests = fr.unsigned_32(); |
521 | + while (nr_requests--) { |
522 | + pw.requests.push_back |
523 | + (new Request |
524 | + (warehouse, |
525 | + 0, |
526 | + &Warehouse::request_cb, |
527 | + wwWORKER)); |
528 | + pw.requests.back()->read(fr, game, mol); |
529 | + } |
530 | + } |
531 | + } |
532 | + |
533 | + if (packet_version >= 5) |
534 | + warehouse.m_next_stock_remove_act = fr.unsigned_32(); |
535 | + |
536 | + if (packet_version >= 6) { |
537 | + if (warehouse.descr().get_isport()) { |
538 | + if (Serial portdock = fr.unsigned_32()) { |
539 | + warehouse.m_portdock = &mol.get<PortDock>(portdock); |
540 | + warehouse.m_portdock->set_economy(warehouse.get_economy()); |
541 | + // Expedition specific stuff. This is done in this packet |
542 | + // because the "new style" loader is not supported and |
543 | + // doesn't lend itself to request and other stuff. |
544 | + if (warehouse.m_portdock->expedition_started()) { |
545 | + warehouse.m_portdock->expedition_bootstrap()->load |
546 | + (packet_version, warehouse, fr, game, mol); |
547 | + } |
548 | } |
549 | } |
550 | } |
551 | @@ -613,7 +818,7 @@ |
552 | { |
553 | try { |
554 | uint16_t const packet_version = fr.unsigned_16(); |
555 | - if (packet_version == kCurrentPacketVersionProductionsite) { |
556 | + if (1 <= packet_version && packet_version <= kCurrentPacketVersionProductionsite) { |
557 | ProductionSite::WorkingPosition & wp_begin = |
558 | *productionsite.m_working_positions; |
559 | const ProductionSiteDescr & pr_descr = productionsite.descr(); |
560 | @@ -707,7 +912,7 @@ |
561 | |
562 | // skipped programs |
563 | uint32_t const gametime = game.get_gametime(); |
564 | - for (uint8_t i = fr.unsigned_8(); i; --i) { |
565 | + for (uint8_t i = 3 <= packet_version ? fr.unsigned_8() : 0; i; --i) { |
566 | char const * const program_name = fr.c_string(); |
567 | if (pr_descr.programs().count(program_name)) { |
568 | uint32_t const skip_time = fr.unsigned_32(); |
569 | @@ -742,10 +947,12 @@ |
570 | productionsite.m_stack[i].phase = fr. signed_32(); |
571 | productionsite.m_stack[i].flags = fr.unsigned_32(); |
572 | |
573 | - uint32_t serial = fr.unsigned_32(); |
574 | - if (serial) |
575 | - productionsite.m_stack[i].objvar = &mol.get<MapObject>(serial); |
576 | - productionsite.m_stack[i].coord = read_coords_32_allow_null(&fr, game.map().extent()); |
577 | + if (packet_version >= 5) { |
578 | + uint32_t serial = fr.unsigned_32(); |
579 | + if (serial) |
580 | + productionsite.m_stack[i].objvar = &mol.get<MapObject>(serial); |
581 | + productionsite.m_stack[i].coord = read_coords_32_allow_null(&fr, game.map().extent()); |
582 | + } |
583 | } |
584 | productionsite.m_program_timer = fr.unsigned_8(); |
585 | productionsite.m_program_time = fr.signed_32(); |
586 | |
587 | === modified file 'src/map_io/map_buildingdata_packet.h' |
588 | --- src/map_io/map_buildingdata_packet.h 2015-10-18 20:23:10 +0000 |
589 | +++ src/map_io/map_buildingdata_packet.h 2015-11-21 10:21:30 +0000 |
590 | @@ -52,6 +52,8 @@ |
591 | (DismantleSite &, FileRead &, Game &, MapObjectLoader &); |
592 | void read_partially_finished_building |
593 | (PartiallyFinishedBuilding &, FileRead &, Game &, MapObjectLoader &); |
594 | + void read_constructionsite_v1 |
595 | + (ConstructionSite &, FileRead &, Game &, MapObjectLoader &); |
596 | void read_warehouse |
597 | (Warehouse &, FileRead &, Game &, MapObjectLoader &); |
598 | void read_militarysite |
599 | @@ -60,6 +62,8 @@ |
600 | (TrainingSite &, FileRead &, Game &, MapObjectLoader &); |
601 | void read_productionsite |
602 | (ProductionSite &, FileRead &, Game &, MapObjectLoader &); |
603 | + void read_formerbuildings_v2 |
604 | + (Building &, FileRead &, Game &, MapObjectLoader &); |
605 | |
606 | void write_constructionsite |
607 | (const ConstructionSite &, FileWrite &, Game &, MapObjectSaver &); |
608 | |
609 | === modified file 'src/map_io/map_exploration_packet.cc' |
610 | --- src/map_io/map_exploration_packet.cc 2015-10-24 15:42:37 +0000 |
611 | +++ src/map_io/map_exploration_packet.cc 2015-11-21 10:21:30 +0000 |
612 | @@ -58,7 +58,21 @@ |
613 | MapIndex const max_index = map.max_index(); |
614 | try { |
615 | uint16_t const packet_version = fr.unsigned_16(); |
616 | - if (packet_version == kCurrentPacketVersion) { |
617 | + if (packet_version == 1) { |
618 | + for (MapIndex i = 0; i < max_index; ++i) { |
619 | + uint32_t const data = fr.unsigned_16(); |
620 | + for (uint8_t j = 0; j < nr_players; ++j) { |
621 | + bool const see = data & (1 << j); |
622 | + if (Player * const player = egbase.get_player(j + 1)) |
623 | + player->m_fields[i].vision = see ? 1 : 0; |
624 | + else if (see) |
625 | + log |
626 | + ("MapExplorationPacket::read: WARNING: Player %u, " |
627 | + "which does not exist, sees field %u.\n", |
628 | + j + 1, i); |
629 | + } |
630 | + } |
631 | + } else if (packet_version == kCurrentPacketVersion) { |
632 | for (MapIndex i = 0; i < max_index; ++i) { |
633 | uint32_t const data = fr.unsigned_32(); |
634 | for (uint8_t j = 0; j < nr_players; ++j) { |
635 | |
636 | === modified file 'src/map_io/map_flagdata_packet.cc' |
637 | --- src/map_io/map_flagdata_packet.cc 2015-10-24 15:42:37 +0000 |
638 | +++ src/map_io/map_flagdata_packet.cc 2015-11-21 10:21:30 +0000 |
639 | @@ -54,15 +54,42 @@ |
640 | |
641 | try { |
642 | uint16_t const packet_version = fr.unsigned_16(); |
643 | - if (packet_version == kCurrentPacketVersion) { |
644 | + if (1 <= packet_version && packet_version <= kCurrentPacketVersion) { |
645 | const Map & map = egbase.map(); |
646 | - while (! fr.end_of_file()) { |
647 | + Extent const extent = map.extent(); |
648 | + for (;;) { |
649 | + if (2 <= packet_version && fr.end_of_file()) |
650 | + break; |
651 | Serial const serial = fr.unsigned_32(); |
652 | + if (packet_version < 2 && serial == 0xffffffff) { |
653 | + if (!fr.end_of_file()) |
654 | + throw GameDataError |
655 | + ("expected end of file after serial 0xffffffff"); |
656 | + break; |
657 | + } |
658 | try { |
659 | Flag & flag = mol.get<Flag>(serial); |
660 | |
661 | // Owner is already set, nothing to do from PlayerImmovable. |
662 | |
663 | + if (packet_version < 3) { |
664 | + if |
665 | + (upcast |
666 | + (Flag const, |
667 | + mf, |
668 | + map[flag.m_position = read_coords_32(&fr, extent)] |
669 | + .get_immovable())) |
670 | + { |
671 | + if (mf != &flag) |
672 | + throw GameDataError |
673 | + ("wrong flag (%u) at given position (%i, %i)", |
674 | + mf->serial(), |
675 | + flag.m_position.x, flag.m_position.y); |
676 | + } else |
677 | + throw GameDataError |
678 | + ("no flag at given position (%i, %i)", |
679 | + flag.m_position.x, flag.m_position.y); |
680 | + } |
681 | flag.m_animstart = fr.unsigned_16(); |
682 | |
683 | { |
684 | @@ -72,6 +99,26 @@ |
685 | dynamic_cast<Building *> |
686 | (building_position.field->get_immovable()); |
687 | } |
688 | + if (packet_version < 3) { |
689 | + if (uint32_t const building_serial = fr.unsigned_32()) |
690 | + try { |
691 | + const Building & building = |
692 | + mol.get<Building>(building_serial); |
693 | + if (flag.m_building != &building) |
694 | + throw GameDataError |
695 | + ( |
696 | + "has building %u at (%i, %i), which is not " |
697 | + "at the top left node", |
698 | + building_serial, |
699 | + building.get_position().x, |
700 | + building.get_position().y); |
701 | + } catch (const WException & e) { |
702 | + throw GameDataError |
703 | + ("building (%u): %s", building_serial, e.what()); |
704 | + } |
705 | + else |
706 | + flag.m_building = nullptr; |
707 | + } |
708 | |
709 | // Roads are set somewhere else. |
710 | |
711 | @@ -87,7 +134,10 @@ |
712 | flag.m_ware_filled = wares_filled; |
713 | for (uint32_t i = 0; i < wares_filled; ++i) { |
714 | flag.m_wares[i].pending = fr.unsigned_8(); |
715 | - flag.m_wares[i].priority = fr.signed_32(); |
716 | + if (packet_version < 4) |
717 | + flag.m_wares[i].priority = 0; |
718 | + else |
719 | + flag.m_wares[i].priority = fr.signed_32(); |
720 | uint32_t const ware_serial = fr.unsigned_32(); |
721 | try { |
722 | flag.m_wares[i].ware = |
723 | |
724 | === modified file 'src/map_io/map_player_names_and_tribes_packet.cc' |
725 | --- src/map_io/map_player_names_and_tribes_packet.cc 2015-10-24 15:42:37 +0000 |
726 | +++ src/map_io/map_player_names_and_tribes_packet.cc 2015-11-21 10:21:30 +0000 |
727 | @@ -63,8 +63,7 @@ |
728 | try { |
729 | int32_t const packet_version = |
730 | prof.get_safe_section("global").get_int("packet_version"); |
731 | - // Supporting older versions for map loading |
732 | - if (1 <= packet_version && packet_version <= kCurrentPacketVersion) { |
733 | + if (packet_version <= kCurrentPacketVersion) { |
734 | PlayerNumber const nr_players = map->get_nrplayers(); |
735 | iterate_player_numbers(p, nr_players) { |
736 | Section & s = prof.get_safe_section((boost::format("player_%u") |
737 | |
738 | === modified file 'src/map_io/map_players_view_packet.cc' |
739 | --- src/map_io/map_players_view_packet.cc 2015-11-14 13:18:24 +0000 |
740 | +++ src/map_io/map_players_view_packet.cc 2015-11-21 10:21:30 +0000 |
741 | @@ -174,6 +174,29 @@ |
742 | static_cast<long unsigned int>((file).get_size() - (file).get_pos()), \ |
743 | filename); |
744 | |
745 | +// TODO(unknown): Legacy code deprecated since build18 |
746 | +template <uint8_t const Size> struct BitInBuffer { |
747 | + static_assert(Size == 1 || Size == 2 || Size == 4, "Unexpected Size."); |
748 | + BitInBuffer(FileRead* fr) : buffer(0), mask(0x00) { |
749 | + m_fr = fr; |
750 | + } |
751 | + |
752 | + uint8_t get() { |
753 | + if (mask == 0x00) { |
754 | + buffer = m_fr->unsigned_8(); |
755 | + mask = 0xff; |
756 | + } |
757 | + uint8_t const result = buffer >> (8 - Size); |
758 | + buffer <<= Size; |
759 | + mask <<= Size; |
760 | + assert(result < (1 << Size)); |
761 | + return result; |
762 | + } |
763 | + |
764 | +private: |
765 | + FileRead* m_fr; |
766 | + uint8_t buffer, mask; |
767 | +}; |
768 | |
769 | // Errors for the Read* functions. |
770 | struct TribeNonexistent : public FileRead::DataError { |
771 | @@ -511,6 +534,15 @@ |
772 | BORDER_FILENAME_TEMPLATE, |
773 | kCurrentPacketVersionBorder); |
774 | |
775 | + // TODO(unknown): Legacy code deprecated since build18 |
776 | + BitInBuffer<2> legacy_node_immovable_kinds_bitbuffer(&node_immovable_kinds_file); |
777 | + BitInBuffer<2> legacy_road_bitbuffer(&roads_file); |
778 | + BitInBuffer<4> legacy_terrains_bitbuffer(&terrains_file); |
779 | + BitInBuffer<2> legacy_triangle_immovable_kinds_bitbuffer(&triangle_immovable_kinds_file); |
780 | + BitInBuffer<1> legacy_surveys_bitbuffer(&surveys_file); |
781 | + BitInBuffer<4> legacy_surveys_amount_bitbuffer(&survey_amounts_file); |
782 | + BitInBuffer<1> legacy_border_bitbuffer(&border_file); |
783 | + |
784 | for |
785 | (FCoords first_in_row(Coords(0, 0), &first_field); |
786 | first_in_row.y < mapheight; |
787 | @@ -589,12 +621,10 @@ |
788 | f.x, f.y, owner, nr_players); |
789 | } |
790 | uint8_t imm_kind = 0; |
791 | - if (node_immovable_kinds_file_version == kCurrentPacketVersionImmovableKinds) { |
792 | + if (node_immovable_kinds_file_version < kCurrentPacketVersionImmovableKinds) { |
793 | + imm_kind = legacy_node_immovable_kinds_bitbuffer.get(); |
794 | + } else { |
795 | imm_kind = node_immovable_kinds_file.unsigned_8(); |
796 | - } else { |
797 | - throw UnhandledVersionError("MapPlayersViewPacket - Node Immovable kinds", |
798 | - node_immovable_kinds_file_version, |
799 | - kCurrentPacketVersionImmovableKinds); |
800 | } |
801 | MapObjectData mod = |
802 | read_unseen_immovable |
803 | @@ -602,17 +632,24 @@ |
804 | f_player_field.map_object_descr[TCoords<>::None] = mod.map_object_descr; |
805 | f_player_field.constructionsite = mod.csi; |
806 | |
807 | - // Read in whether this field had a border the last time it was seen |
808 | - if (border_file_version == kCurrentPacketVersionBorder) { |
809 | - uint8_t borders = border_file.unsigned_8(); |
810 | - f_player_field.border = borders & 1; |
811 | - f_player_field.border_r = borders & 2; |
812 | - f_player_field.border_br = borders & 4; |
813 | - f_player_field.border_bl = borders & 8; |
814 | - } else { |
815 | - throw UnhandledVersionError("MapPlayersViewPacket - Border file", |
816 | - border_file_version, kCurrentPacketVersionBorder); |
817 | - } |
818 | + // if there is a border file, read in whether this field had a border the last time it was seen |
819 | + if (border_file_version >= 0) { |
820 | + if (border_file_version < 1) { |
821 | + f_player_field.border = (legacy_border_bitbuffer.get() == 1); |
822 | + f_player_field.border_r = (legacy_border_bitbuffer.get() == 1); |
823 | + f_player_field.border_br = (legacy_border_bitbuffer.get() == 1); |
824 | + f_player_field.border_bl = (legacy_border_bitbuffer.get() == 1); |
825 | + } else { |
826 | + uint8_t borders = border_file.unsigned_8(); |
827 | + f_player_field.border = borders & 1; |
828 | + f_player_field.border_r = borders & 2; |
829 | + f_player_field.border_br = borders & 4; |
830 | + f_player_field.border_bl = borders & 8; |
831 | + } |
832 | + } else { |
833 | + throw UnhandledVersionError("MapPlayersViewPacket - Border file", |
834 | + border_file_version, kCurrentPacketVersionBorder); |
835 | + } |
836 | break; |
837 | } |
838 | default: |
839 | @@ -651,19 +688,23 @@ |
840 | } else if (f_everseen | bl_everseen | br_everseen) { |
841 | // The player has seen the D triangle but does not see it now. |
842 | // Load his information about the triangle from file. |
843 | - if (terrains_file_version == kCurrentPacketVersionTerrains) { |
844 | + if (terrains_file_version < kCurrentPacketVersionTerrains) { |
845 | + try {f_player_field.terrains.d = legacy_terrains_bitbuffer.get();} |
846 | + catch (const FileRead::FileBoundaryExceeded &) { |
847 | + throw GameDataError |
848 | + ("MapPlayersViewPacket::read: player %u: in " |
849 | + "\"%s\": node (%i, %i) t = D: unexpected end of file " |
850 | + "while reading terrain", |
851 | + plnum, terrains_filename, f.x, f.y); |
852 | + } |
853 | + } else { |
854 | f_player_field.terrains.d = terrains_file.unsigned_8(); |
855 | - } else { |
856 | - throw UnhandledVersionError("MapPlayersViewPacket - Terrains", |
857 | - terrains_file_version, kCurrentPacketVersionTerrains); |
858 | } |
859 | uint8_t im_kind = 0; |
860 | - if (triangle_immovable_kinds_file_version == kCurrentPacketVersionImmovableKinds) { |
861 | + if (triangle_immovable_kinds_file_version < kCurrentPacketVersionImmovableKinds) { |
862 | + im_kind = legacy_triangle_immovable_kinds_bitbuffer.get(); |
863 | + } else { |
864 | im_kind = triangle_immovable_kinds_file.unsigned_8(); |
865 | - } else { |
866 | - throw UnhandledVersionError("MapPlayersViewPacket - Triangle Immovable kinds", |
867 | - triangle_immovable_kinds_file_version, |
868 | - kCurrentPacketVersionImmovableKinds); |
869 | } |
870 | MapObjectData mod = |
871 | read_unseen_immovable |
872 | @@ -680,19 +721,23 @@ |
873 | } else if (f_everseen | br_everseen | r_everseen) { |
874 | // The player has seen the R triangle but does not see it now. |
875 | // Load his information about the triangle from file. |
876 | - if (terrains_file_version == kCurrentPacketVersionTerrains) { |
877 | + if (terrains_file_version < kCurrentPacketVersionTerrains) { |
878 | + try {f_player_field.terrains.r = legacy_terrains_bitbuffer.get();} |
879 | + catch (const FileRead::FileBoundaryExceeded &) { |
880 | + throw GameDataError |
881 | + ("MapPlayersViewPacket::read: player %u: in " |
882 | + "\"%s\": node (%i, %i) t = R: unexpected end of file " |
883 | + "while reading terrain", |
884 | + plnum, terrains_filename, f.x, f.y); |
885 | + } |
886 | + } else { |
887 | f_player_field.terrains.r = terrains_file.unsigned_8(); |
888 | - } else { |
889 | - throw UnhandledVersionError("MapPlayersViewPacket - Terrains", |
890 | - terrains_file_version, kCurrentPacketVersionTerrains); |
891 | } |
892 | uint8_t im_kind = 0; |
893 | - if (triangle_immovable_kinds_file_version == kCurrentPacketVersionImmovableKinds) { |
894 | + if (triangle_immovable_kinds_file_version < kCurrentPacketVersionImmovableKinds) { |
895 | + im_kind = legacy_triangle_immovable_kinds_bitbuffer.get(); |
896 | + } else { |
897 | im_kind = triangle_immovable_kinds_file.unsigned_8(); |
898 | - } else { |
899 | - throw UnhandledVersionError("MapPlayersViewPacket - Triangle Immovable kinds", |
900 | - triangle_immovable_kinds_file_version, |
901 | - kCurrentPacketVersionImmovableKinds); |
902 | } |
903 | MapObjectData mod = |
904 | read_unseen_immovable |
905 | @@ -707,11 +752,17 @@ |
906 | } else if (f_everseen | bl_everseen) { |
907 | // The player has seen the SouthWest edge but does not see |
908 | // it now. Load his information about this edge from file. |
909 | - if (road_file_version == kCurrentPacketVersionRoads) { |
910 | + if (road_file_version < kCurrentPacketVersionRoads) { |
911 | + try {roads = legacy_road_bitbuffer.get() << RoadType::kSouthWest;} |
912 | + catch (const FileRead::FileBoundaryExceeded &) { |
913 | + throw GameDataError |
914 | + ("MapPlayersViewPacket::read: player %u: in " |
915 | + "\"%s\": node (%i, %i): unexpected end of file while " |
916 | + "reading RoadType::kSouthWest", |
917 | + plnum, roads_filename, f.x, f.y); |
918 | + } |
919 | + } else { |
920 | roads = roads_file.unsigned_8(); |
921 | - } else { |
922 | - throw UnhandledVersionError("MapPlayersViewPacket - Road file", |
923 | - road_file_version, kCurrentPacketVersionRoads); |
924 | } |
925 | } |
926 | if (f_seen | br_seen) { |
927 | @@ -719,11 +770,17 @@ |
928 | } else if (f_everseen | br_everseen) { |
929 | // The player has seen the SouthEast edge but does not see |
930 | // it now. Load his information about this edge from file. |
931 | - if (road_file_version == kCurrentPacketVersionRoads) { |
932 | + if (road_file_version < kCurrentPacketVersionRoads) { |
933 | + try {roads |= legacy_road_bitbuffer.get() << RoadType::kSouthEast;} |
934 | + catch (const FileRead::FileBoundaryExceeded &) { |
935 | + throw GameDataError |
936 | + ("MapPlayersViewPacket::read: player %u: in " |
937 | + "\"%s\": node (%i, %i): unexpected end of file while " |
938 | + "reading RoadType::kSouthEast", |
939 | + plnum, roads_filename, f.x, f.y); |
940 | + } |
941 | + } else { |
942 | roads |= roads_file.unsigned_8(); |
943 | - } else { |
944 | - throw UnhandledVersionError("MapPlayersViewPacket - Road file", |
945 | - road_file_version, kCurrentPacketVersionRoads); |
946 | } |
947 | } |
948 | if (f_seen | r_seen) { |
949 | @@ -731,11 +788,17 @@ |
950 | } else if (f_everseen | r_everseen) { |
951 | // The player has seen the East edge but does not see |
952 | // it now. Load his information about this edge from file. |
953 | - if (road_file_version == kCurrentPacketVersionRoads) { |
954 | + if (road_file_version < kCurrentPacketVersionRoads) { |
955 | + try {roads |= legacy_road_bitbuffer.get() << RoadType::kEast;} |
956 | + catch (const FileRead::FileBoundaryExceeded &) { |
957 | + throw GameDataError |
958 | + ("MapPlayersViewPacket::read: player %u: in " |
959 | + "\"%s\": node (%i, %i): unexpected end of file while " |
960 | + "reading RoadType::kEast", |
961 | + plnum, roads_filename, f.x, f.y); |
962 | + } |
963 | + } else { |
964 | roads |= roads_file.unsigned_8(); |
965 | - } else { |
966 | - throw UnhandledVersionError("MapPlayersViewPacket - Road file", |
967 | - road_file_version, kCurrentPacketVersionRoads); |
968 | } |
969 | } |
970 | roads |= f.field->get_roads() & mask; |
971 | @@ -748,20 +811,27 @@ |
972 | // geologic survey |
973 | try { |
974 | bool survey = false; |
975 | - if (surveys_file_version == kCurrentPacketVersionSurveys) { |
976 | + if (surveys_file_version < kCurrentPacketVersionSurveys) { |
977 | + survey = (f_everseen & bl_everseen & br_everseen) |
978 | + && legacy_surveys_bitbuffer.get(); |
979 | + } else { |
980 | survey = (f_everseen & bl_everseen & br_everseen) |
981 | && surveys_file.unsigned_8(); |
982 | - } else { |
983 | - throw UnhandledVersionError("MapPlayersViewPacket - Surveys file", |
984 | - surveys_file_version, kCurrentPacketVersionSurveys); |
985 | } |
986 | if (survey) { |
987 | - if (survey_amounts_file_version == kCurrentPacketVersionSurveyAmounts) { |
988 | + if (survey_amounts_file_version < kCurrentPacketVersionSurveyAmounts) { |
989 | + try { |
990 | + f_player_field.resource_amounts.d = |
991 | + legacy_surveys_amount_bitbuffer.get(); |
992 | + } catch (const FileRead::FileBoundaryExceeded &) { |
993 | + throw GameDataError |
994 | + ("MapPlayersViewPacket::read: player %u: in " |
995 | + "\"%s\": node (%i, %i) t = D: unexpected end of file " |
996 | + "while reading resource amount of surveyed triangle", |
997 | + plnum, survey_amounts_filename, f.x, f.y); |
998 | + } |
999 | + } else { |
1000 | f_player_field.resource_amounts.d = survey_amounts_file.unsigned_8(); |
1001 | - } else { |
1002 | - throw UnhandledVersionError("MapPlayersViewPacket - Survey amounts", |
1003 | - survey_amounts_file_version, |
1004 | - kCurrentPacketVersionSurveyAmounts); |
1005 | } |
1006 | try { |
1007 | f_player_field.time_triangle_last_surveyed[TCoords<>::D] = |
1008 | @@ -786,20 +856,27 @@ |
1009 | } |
1010 | try { |
1011 | bool survey = false; |
1012 | - if (surveys_file_version == kCurrentPacketVersionSurveys) { |
1013 | + if (surveys_file_version < kCurrentPacketVersionSurveys) { |
1014 | + survey = (f_everseen & br_everseen & r_everseen) |
1015 | + && legacy_surveys_bitbuffer.get(); |
1016 | + } else { |
1017 | survey = (f_everseen & br_everseen & r_everseen) |
1018 | && surveys_file.unsigned_8(); |
1019 | - } else { |
1020 | - throw UnhandledVersionError("MapPlayersViewPacket - Surveys file", |
1021 | - surveys_file_version, kCurrentPacketVersionSurveys); |
1022 | } |
1023 | if (survey) { |
1024 | - if (survey_amounts_file_version == kCurrentPacketVersionSurveyAmounts) { |
1025 | + if (survey_amounts_file_version < kCurrentPacketVersionSurveyAmounts) { |
1026 | + try { |
1027 | + f_player_field.resource_amounts.r = |
1028 | + legacy_surveys_amount_bitbuffer.get(); |
1029 | + } catch (const FileRead::FileBoundaryExceeded &) { |
1030 | + throw GameDataError |
1031 | + ("MapPlayersViewPacket::read: player %u: in " |
1032 | + "\"%s\": node (%i, %i) t = R: unexpected end of file " |
1033 | + "while reading resource amount of surveyed triangle", |
1034 | + plnum, survey_amounts_filename, f.x, f.y); |
1035 | + } |
1036 | + } else { |
1037 | f_player_field.resource_amounts.r = survey_amounts_file.unsigned_8(); |
1038 | - } else { |
1039 | - throw UnhandledVersionError("MapPlayersViewPacket - Survey amounts", |
1040 | - survey_amounts_file_version, |
1041 | - kCurrentPacketVersionSurveyAmounts); |
1042 | } |
1043 | try { |
1044 | f_player_field.time_triangle_last_surveyed[TCoords<>::R] = |
1045 | |
1046 | === modified file 'src/map_io/map_roaddata_packet.cc' |
1047 | --- src/map_io/map_roaddata_packet.cc 2015-10-25 08:06:00 +0000 |
1048 | +++ src/map_io/map_roaddata_packet.cc 2015-11-21 10:21:30 +0000 |
1049 | @@ -55,11 +55,19 @@ |
1050 | |
1051 | try { |
1052 | uint16_t const packet_version = fr.unsigned_16(); |
1053 | - if (packet_version == kCurrentPacketVersion) { |
1054 | + if (1 <= packet_version && packet_version <= kCurrentPacketVersion) { |
1055 | const Map & map = egbase.map(); |
1056 | PlayerNumber const nr_players = map.get_nrplayers(); |
1057 | - while (! fr.end_of_file()) { |
1058 | + for (;;) { |
1059 | + if (2 <= packet_version && fr.end_of_file()) |
1060 | + break; |
1061 | Serial const serial = fr.unsigned_32(); |
1062 | + if (packet_version < 2 && serial == 0xffffffff) { |
1063 | + if (!fr.end_of_file()) |
1064 | + throw GameDataError |
1065 | + ("expected end of file after serial 0xffffffff"); |
1066 | + break; |
1067 | + } |
1068 | try { |
1069 | Game& game = dynamic_cast<Game&>(egbase); |
1070 | Road & road = mol.get<Road>(serial); |
1071 | @@ -72,8 +80,10 @@ |
1072 | Player & plr = egbase.player(player_index); |
1073 | |
1074 | road.set_owner(&plr); |
1075 | - road.m_busyness = fr.unsigned_32(); |
1076 | - road.m_busyness_last_update = fr.unsigned_32(); |
1077 | + if (4 <= packet_version) { |
1078 | + road.m_busyness = fr.unsigned_32(); |
1079 | + road.m_busyness_last_update = fr.unsigned_32(); |
1080 | + } |
1081 | road.m_type = fr.unsigned_32(); |
1082 | { |
1083 | uint32_t const flag_0_serial = fr.unsigned_32(); |
1084 | @@ -122,6 +132,12 @@ |
1085 | uint32_t const count = fr.unsigned_32(); |
1086 | if (!count) |
1087 | throw GameDataError("no carrier slot"); |
1088 | + if (packet_version <= 2 && 1 < count) |
1089 | + throw GameDataError |
1090 | + ( |
1091 | + "expected 1 but found %u carrier slots in road saved " |
1092 | + "with packet version 2 (old)", |
1093 | + count); |
1094 | |
1095 | for (uint32_t i = 0; i < count; ++i) { |
1096 | Carrier * carrier = nullptr; |
1097 | @@ -149,7 +165,8 @@ |
1098 | } else { |
1099 | carrier_request = nullptr; |
1100 | } |
1101 | - uint8_t const carrier_type = fr.unsigned_32(); |
1102 | + uint8_t const carrier_type = |
1103 | + packet_version < 3 ? 1 : fr.unsigned_32(); |
1104 | |
1105 | if |
1106 | (i < road.m_carrier_slots.size() && |
1107 | |
1108 | === modified file 'src/map_io/map_scripting_packet.cc' |
1109 | --- src/map_io/map_scripting_packet.cc 2015-11-01 10:11:56 +0000 |
1110 | +++ src/map_io/map_scripting_packet.cc 2015-11-21 10:21:30 +0000 |
1111 | @@ -37,7 +37,7 @@ |
1112 | namespace Widelands { |
1113 | |
1114 | namespace { |
1115 | -constexpr uint32_t kCurrentPacketVersion = 2; |
1116 | +constexpr uint32_t kCurrentPacketVersion = 1; |
1117 | } // namespace |
1118 | /* |
1119 | * ======================================================================== |
1120 | @@ -57,17 +57,13 @@ |
1121 | FileRead fr; |
1122 | if (g && fr.try_open(fs, "scripting/globals.dump")) |
1123 | { |
1124 | - try { |
1125 | - const uint32_t packet_version = fr.unsigned_32(); |
1126 | - if (packet_version == kCurrentPacketVersion) { |
1127 | - upcast(LuaGameInterface, lgi, &g->lua()); |
1128 | - lgi->read_global_env(fr, mol, fr.unsigned_32()); |
1129 | - } else { |
1130 | - throw UnhandledVersionError("MapScriptingPacket", packet_version, kCurrentPacketVersion); |
1131 | - } |
1132 | - } catch (const WException & e) { |
1133 | - throw GameDataError("scripting: %s", e.what()); |
1134 | + const uint32_t sentinel = fr.unsigned_32(); |
1135 | + const uint32_t packet_version = fr.unsigned_32(); |
1136 | + if (sentinel != 0xDEADBEEF && packet_version != kCurrentPacketVersion) { |
1137 | + throw UnhandledVersionError("MapScriptingPacket", packet_version, kCurrentPacketVersion); |
1138 | } |
1139 | + upcast(LuaGameInterface, lgi, &g->lua()); |
1140 | + lgi->read_global_env(fr, mol, fr.unsigned_32()); |
1141 | } |
1142 | } |
1143 | |
1144 | @@ -94,6 +90,7 @@ |
1145 | // Dump the global environment if this is a game and not in the editor |
1146 | if (upcast(Game, g, &egbase)) { |
1147 | FileWrite fw; |
1148 | + fw.unsigned_32(0xDEADBEEF); // Sentinel, because there was no packet version. |
1149 | fw.unsigned_32(kCurrentPacketVersion); |
1150 | const FileWrite::Pos pos = fw.get_pos(); |
1151 | fw.unsigned_32(0); // N bytes written, follows below |
Hi GunChleoc,
Looking at the changes, I was wondering what kind of problems were faced - I wasn't monitoring the project for roughly 1,5 years, so I am a not that up to date, sorry.
Is there one or more bug reports explaining the problem?
Is this merge request about savegames or about maps? I am asking because a lot of the code handles tribe objects like buildings, workers, wares, etc. However as far as I remember, there was no way to build up an economy in the editor in Build18 (is there now?) - so I wonder whether that code is really needed for loading maps of Build18 or Build17.