Merge lp:~widelands-dev/widelands/bug-1732765-economy-refactoring into lp:widelands
- bug-1732765-economy-refactoring
- Merge into trunk
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 8748 | ||||||||||||||||
Proposed branch: | lp:~widelands-dev/widelands/bug-1732765-economy-refactoring | ||||||||||||||||
Merge into: | lp:widelands | ||||||||||||||||
Diff against target: |
1502 lines (+314/-260) 26 files modified
src/ai/defaultai.cc (+1/-1) src/ai/defaultai.h (+1/-1) src/ai/defaultai_warfare.cc (+2/-2) src/economy/economy.cc (+19/-18) src/economy/economy.h (+13/-3) src/economy/economy_data_packet.cc (+11/-1) src/economy/economy_data_packet.h (+3/-0) src/economy/flag.cc (+14/-8) src/economy/flag.h (+6/-2) src/game_io/game_player_economies_packet.cc (+30/-36) src/io/filesystem/filesystem.cc (+6/-7) src/logic/game.cc (+3/-4) src/logic/map_objects/tribes/ship.cc (+30/-23) src/logic/map_objects/tribes/ship.h (+4/-1) src/logic/player.cc (+45/-35) src/logic/player.h (+8/-14) src/logic/playercommand.cc (+8/-8) src/logic/playercommand.h (+2/-2) src/logic/widelands.h (+1/-0) src/map_io/map_flag_packet.cc (+14/-3) src/scripting/lua_bases.cc (+4/-4) src/scripting/lua_game.cc (+7/-9) src/scripting/lua_map.cc (+4/-4) src/wui/economy_options_window.cc (+57/-50) src/wui/economy_options_window.h (+14/-9) src/wui/stock_menu.cc (+7/-15) |
||||||||||||||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/bug-1732765-economy-refactoring | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Klaus Halfmann | Approve | ||
Review via email: mp+345277@code.launchpad.net |
Commit message
Economies are now mapped to global serials and kept as unique_ptr in the Player objects.
Description of the change
Big redesign of economy tracking, hoping that it will fix some bugs.
NOTE: This will break savegame compatibility, so we should take care to deal with all bugs that have interesting savegames attached before merging this. Implementing compatibility would be very complicated.
We used to have economy numbers per player, now we have 1 global serial number.
TiborB (tiborb95) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
Oops, found a failing test
GunChleoc (gunchleoc) wrote : | # |
Yes, I'd like to have it in Build 20 if possible, especially because it breaks savegame compatibility. It will make it easier to deal with future bugs, because we can expect to get sample savegames for Build 20 down the road.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3497. State: failed. Details: https:/
Appveyor build 3302. State: success. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3506. State: passed. Details: https:/
Appveyor build 3311. State: success. Details: https:/
Klaus Halfmann (klaus-halfmann) wrote : | # |
Some comments:
* This depends or includes https:/
* As Serial is uint32_t so we have 2^32 different Economies, ok
* Please respond tho the inline comments, espcially using unordere_map should bet better.
This was a lot of change to digest, in general the code looks better this way.
Do we have a testcase with a lot of Economies to get an Idea of the Performance change?
I will now check the Attached Bugs, and check the code again how it fixes the issues.
Klaus Halfmann (klaus-halfmann) wrote : | # |
Loading an old save game fails as expected:
UnhandledVersio
Packet Name: MapFlagPacket
Saved Version: 1
Current Version: 2
GunChleoc (gunchleoc) wrote : | # |
* This depends or includes https:/
No, that was a failed attempt at fixing something and will be scrapped once this is merged
* As Serial is uint32_t so we have 2^32 different Economies, ok
I hope that is enough - maybe we need a stress test?
* Do we have a testcase with a lot of Economies to get an Idea of the Performance change?
I don't expect any performance changes really - we access economies from containers in both cases.
GunChleoc (gunchleoc) wrote : | # |
Answers to comments
GunChleoc (gunchleoc) wrote : | # |
We do iterate over the economies a lot, so an unordered_map is not possible. e.g. in the stock menu:
for (const auto& economy : player.economies()) {
Klaus Halfmann (klaus-halfmann) wrote : | # |
Played this now for about 30 Minutes again, did not notice any Problems.
Ran the regression tests: Ran 41 tests in 739.863s,
all fine.
GUn: I will leave it up to you to merge this,
it will for sure break savegames.
Should we do some stress testing with a Mutiplayergame
placing and removing flags and roads like mad?
GunChleoc (gunchleoc) wrote : | # |
I have had 8 AIs battle it out on Ice Wars for 100+ hours and have attached the savegame to the bug. We could run this some more to see if we ever hit the limit
Klaus Halfmann (klaus-halfmann) wrote : | # |
Got a conflcit merging test/maps/
I used the versison from trunk, but actually there was no difference.
Regression tests: Ran 42 tests in 1125.653s
We should get his in soon now, merging can become difficult.
And this is (?) the last savegame breaking change, is it not?
Will testplay this again for my second english
youtube video today.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3574. State: failed. Details: https:/
Appveyor build 3377. State: success. Details: https:/
Klaus Halfmann (klaus-halfmann) wrote : | # |
Any Codechecker around?
I think I fixed it but _some_ compilers still dont like me?
Why is it that differetn with some compilers?
ypopezios (ypopezios) wrote : | # |
> * As Serial is uint32_t so we have 2^32 different Economies, ok
> Should we do some stress testing with a Mutiplayergame
placing and removing flags and roads like mad?
> We could run this some more to see if we ever hit the limit
If by testing the limit you mean the number 2^32, this is probably pointless. Cause that's a huge number, bigger than the number of seconds in a lifetime...
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3575. State: passed. Details: https:/
Appveyor build 3378. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
We still have some crash reports with attached savegames. I'd like those to be sorted out first before merging this branch, because they will become unreproducible once this branch hits trunk.
Klaus Halfmann (klaus-halfmann) wrote : | # |
I tried to load some old savegame (for my youtube channel) but it failed to display
the correct files, loading the other files failed, of course.
I assume some versioncheck was lost during the latest merge?
I will merge trunk again now
Klaus Halfmann (klaus-halfmann) wrote : | # |
Uhm I checked ~/.widelands/save, my save files are there,
where is that code to check the file versions?
GunChleoc (gunchleoc) wrote : | # |
There are 3 packets that have changed version - I have added comments to the diff so that you can find them. Savegames from other branches will be incompatible with this one.
Klaus Halfmann (klaus-halfmann) wrote : | # |
My Bad, was playing Singleplayer/
this was a multiplay game. Looks I will create the next
Youtube video tomorrow, then.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3623. State: failed. Details: https:/
Appveyor build 3422. State: success. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3624. State: errored. Details: https:/
Appveyor build 3423. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
We only have 1 bug left now with a savegame that's needed:
https:/
So, let's have this branch now to give it some more testing exposure.
@bunnybot merge
GunChleoc (gunchleoc) wrote : | # |
Transient failure on Travis
@bunnybot merge force
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3658. State: failed. Details: https:/
Appveyor build 3457. State: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Refusing to merge, since Travis is not green. Use @bunnybot merge force for merging anyways.
Travis build 3658. State: failed. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
@bunnybot merge force
Preview Diff
1 | === modified file 'src/ai/defaultai.cc' |
2 | --- src/ai/defaultai.cc 2018-06-19 08:52:49 +0000 |
3 | +++ src/ai/defaultai.cc 2018-07-11 08:33:43 +0000 |
4 | @@ -6565,7 +6565,7 @@ |
5 | assert(new_target > 1); |
6 | |
7 | game().send_player_command(*new Widelands::CmdSetWareTargetQuantity( |
8 | - gametime, player_number(), player_->get_economy_number(&observer->economy), id, |
9 | + gametime, player_number(), observer->economy.serial(), id, |
10 | new_target)); |
11 | } |
12 | } |
13 | |
14 | === modified file 'src/ai/defaultai.h' |
15 | --- src/ai/defaultai.h 2018-04-16 07:03:12 +0000 |
16 | +++ src/ai/defaultai.h 2018-07-11 08:33:43 +0000 |
17 | @@ -155,7 +155,7 @@ |
18 | // common for defaultai.cc and defaultai_seafaring.cc |
19 | static constexpr uint32_t kExpeditionMinDuration = 60 * 60 * 1000; |
20 | static constexpr uint32_t kExpeditionMaxDuration = 210 * 60 * 1000; |
21 | - static constexpr uint32_t kNoShip = std::numeric_limits<uint32_t>::max(); |
22 | + static constexpr Widelands::Serial kNoShip = Widelands::kInvalidSerial; |
23 | static constexpr int kShipCheckInterval = 5 * 1000; |
24 | |
25 | // used by defaultai_warfare.cc |
26 | |
27 | === modified file 'src/ai/defaultai_warfare.cc' |
28 | --- src/ai/defaultai_warfare.cc 2018-04-09 01:50:48 +0000 |
29 | +++ src/ai/defaultai_warfare.cc 2018-07-11 08:33:43 +0000 |
30 | @@ -85,7 +85,7 @@ |
31 | } |
32 | |
33 | // now we update some of them |
34 | - uint32_t best_target = std::numeric_limits<uint32_t>::max(); |
35 | + Widelands::Serial best_target = Widelands::kInvalidSerial; |
36 | uint8_t best_score = 0; |
37 | uint32_t count = 0; |
38 | // sites that were either conquered or destroyed |
39 | @@ -463,7 +463,7 @@ |
40 | } |
41 | |
42 | // if coordinates hash is not set |
43 | - if (best_target == std::numeric_limits<uint32_t>::max()) { |
44 | + if (best_target == Widelands::kInvalidSerial) { |
45 | return false; |
46 | } |
47 | |
48 | |
49 | === modified file 'src/economy/economy.cc' |
50 | --- src/economy/economy.cc 2018-04-07 16:59:00 +0000 |
51 | +++ src/economy/economy.cc 2018-07-11 08:33:43 +0000 |
52 | @@ -41,15 +41,19 @@ |
53 | |
54 | namespace Widelands { |
55 | |
56 | -Economy::Economy(Player& player) : owner_(player), request_timerid_(0), has_window_(false) { |
57 | +Serial Economy::last_economy_serial_ = 0; |
58 | + |
59 | +Economy::Economy(Player& player) : Economy(player, last_economy_serial_++) { |
60 | +} |
61 | + |
62 | +Economy::Economy(Player& player, Serial init_serial) : serial_(init_serial), owner_(player), request_timerid_(0), has_window_(false) { |
63 | + last_economy_serial_ = std::max(last_economy_serial_, serial_ + 1); |
64 | const TribeDescr& tribe = player.tribe(); |
65 | DescriptionIndex const nr_wares = player.egbase().tribes().nrwares(); |
66 | DescriptionIndex const nr_workers = player.egbase().tribes().nrworkers(); |
67 | wares_.set_nrwares(nr_wares); |
68 | workers_.set_nrwares(nr_workers); |
69 | |
70 | - player.add_economy(*this); |
71 | - |
72 | ware_target_quantities_ = new TargetQuantity[nr_wares]; |
73 | for (DescriptionIndex i = 0; i < nr_wares; ++i) { |
74 | TargetQuantity tq; |
75 | @@ -69,12 +73,11 @@ |
76 | worker_target_quantities_[i] = tq; |
77 | } |
78 | |
79 | - router_ = new Router(boost::bind(&Economy::reset_all_pathfinding_cycles, this)); |
80 | + router_.reset(new Router(boost::bind(&Economy::reset_all_pathfinding_cycles, this))); |
81 | } |
82 | |
83 | Economy::~Economy() { |
84 | - Notifications::publish(NoteEconomy{this, this, NoteEconomy::Action::kDeleted}); |
85 | - owner_.remove_economy(*this); |
86 | + Notifications::publish(NoteEconomy{serial_, serial_, NoteEconomy::Action::kDeleted}); |
87 | |
88 | if (requests_.size()) |
89 | log("Warning: Economy still has requests left on destruction\n"); |
90 | @@ -85,8 +88,6 @@ |
91 | |
92 | delete[] ware_target_quantities_; |
93 | delete[] worker_target_quantities_; |
94 | - |
95 | - delete router_; |
96 | } |
97 | |
98 | /** |
99 | @@ -269,8 +270,9 @@ |
100 | do_remove_flag(flag); |
101 | |
102 | // automatically delete the economy when it becomes empty. |
103 | - if (flags_.empty()) |
104 | - delete this; |
105 | + if (flags_.empty()) { |
106 | + owner_.remove_economy(serial_); |
107 | + } |
108 | } |
109 | |
110 | /** |
111 | @@ -528,7 +530,8 @@ |
112 | // If the options window for e is open, but not the one for this, the user |
113 | // should still have an options window after the merge. |
114 | if (e.has_window() && !has_window()) { |
115 | - Notifications::publish(NoteEconomy{&e, this, NoteEconomy::Action::kMerged}); |
116 | + Notifications::publish( |
117 | + NoteEconomy{e.serial(), serial_, NoteEconomy::Action::kMerged}); |
118 | } |
119 | |
120 | for (std::vector<Flag*>::size_type i = e.get_nrflags() + 1; --i;) { |
121 | @@ -542,9 +545,7 @@ |
122 | |
123 | // Remember that the other economy may not have been connected before the merge |
124 | split_checks_.insert(split_checks_.end(), e.split_checks_.begin(), e.split_checks_.end()); |
125 | - |
126 | - // implicitly delete the economy |
127 | - delete &e; |
128 | + owner_.remove_economy(e.serial()); |
129 | } |
130 | |
131 | /** |
132 | @@ -553,21 +554,21 @@ |
133 | void Economy::split(const std::set<OPtr<Flag>>& flags) { |
134 | assert(!flags.empty()); |
135 | |
136 | - Economy& e = *new Economy(owner_); |
137 | + Economy* e = owner_.create_economy(); |
138 | |
139 | for (const DescriptionIndex& ware_index : owner_.tribe().wares()) { |
140 | - e.ware_target_quantities_[ware_index] = ware_target_quantities_[ware_index]; |
141 | + e->ware_target_quantities_[ware_index] = ware_target_quantities_[ware_index]; |
142 | } |
143 | |
144 | for (const DescriptionIndex& worker_index : owner_.tribe().workers()) { |
145 | - e.worker_target_quantities_[worker_index] = worker_target_quantities_[worker_index]; |
146 | + e->worker_target_quantities_[worker_index] = worker_target_quantities_[worker_index]; |
147 | } |
148 | |
149 | for (const OPtr<Flag>& temp_flag : flags) { |
150 | Flag& flag = *temp_flag.get(owner().egbase()); |
151 | assert(flags_.size() > 1); // We will not be deleted in remove_flag, right? |
152 | remove_flag(flag); |
153 | - e.add_flag(flag); |
154 | + e->add_flag(flag); |
155 | } |
156 | |
157 | // As long as rebalance commands are tied to specific flags, we |
158 | |
159 | === modified file 'src/economy/economy.h' |
160 | --- src/economy/economy.h 2018-04-07 16:59:00 +0000 |
161 | +++ src/economy/economy.h 2018-07-11 08:33:43 +0000 |
162 | @@ -56,8 +56,8 @@ |
163 | // When 2 economies have been merged, this is the economy number that has |
164 | // been removed, while the other one is the number of the resulting economy. |
165 | // For all other messages old_economy == new_economy. |
166 | - Economy* old_economy; |
167 | - Economy* new_economy; |
168 | + Widelands::Serial old_economy; |
169 | + Widelands::Serial new_economy; |
170 | |
171 | enum class Action { kMerged, kDeleted }; |
172 | const Action action; |
173 | @@ -108,8 +108,13 @@ |
174 | }; |
175 | |
176 | explicit Economy(Player&); |
177 | + explicit Economy(Player&, Serial serial); // For saveloading |
178 | ~Economy(); |
179 | |
180 | + Serial serial() const { |
181 | + return serial_; |
182 | + } |
183 | + |
184 | Player& owner() const { |
185 | return owner_; |
186 | } |
187 | @@ -209,6 +214,9 @@ |
188 | start_request_timer(); |
189 | } |
190 | |
191 | +protected: |
192 | + static Serial last_economy_serial_; |
193 | + |
194 | private: |
195 | // This structs is to store distance from supply to request(or), but to allow unambiguous |
196 | // sorting if distances are the same, we use also serial number of provider and type of provider |
197 | @@ -251,6 +259,8 @@ |
198 | /*************/ |
199 | using RequestList = std::vector<Request*>; |
200 | |
201 | + const Serial serial_; |
202 | + |
203 | Player& owner_; |
204 | |
205 | using Flags = std::vector<Flag*>; |
206 | @@ -264,7 +274,7 @@ |
207 | |
208 | TargetQuantity* ware_target_quantities_; |
209 | TargetQuantity* worker_target_quantities_; |
210 | - Router* router_; |
211 | + std::unique_ptr<Router> router_; |
212 | |
213 | using SplitPair = std::pair<OPtr<Flag>, OPtr<Flag>>; |
214 | std::vector<SplitPair> split_checks_; |
215 | |
216 | === modified file 'src/economy/economy_data_packet.cc' |
217 | --- src/economy/economy_data_packet.cc 2018-04-07 16:59:00 +0000 |
218 | +++ src/economy/economy_data_packet.cc 2018-07-11 08:33:43 +0000 |
219 | @@ -27,7 +27,7 @@ |
220 | #include "map_io/map_object_loader.h" |
221 | #include "map_io/map_object_saver.h" |
222 | |
223 | -constexpr uint16_t kCurrentPacketVersion = 3; |
224 | +constexpr uint16_t kCurrentPacketVersion = 4; |
225 | |
226 | namespace Widelands { |
227 | |
228 | @@ -35,6 +35,11 @@ |
229 | try { |
230 | uint16_t const packet_version = fr.unsigned_16(); |
231 | if (packet_version == kCurrentPacketVersion) { |
232 | + const Serial saved_serial = fr.unsigned_32(); |
233 | + if (eco_->serial_ != saved_serial) { |
234 | + throw GameDataError("Representative flag/ship has economy serial %d, but the data packet has %d", eco_->serial_, saved_serial); |
235 | + } |
236 | + assert(Economy::last_economy_serial_ >= eco_->serial_); |
237 | try { |
238 | const TribeDescr& tribe = eco_->owner().tribe(); |
239 | while (Time const last_modified = fr.unsigned_32()) { |
240 | @@ -94,6 +99,11 @@ |
241 | |
242 | void EconomyDataPacket::write(FileWrite& fw) { |
243 | fw.unsigned_16(kCurrentPacketVersion); |
244 | + |
245 | + // We save the serial number for sanity checks |
246 | + fw.unsigned_32(eco_->serial()); |
247 | + |
248 | + // Requests etc. |
249 | const TribeDescr& tribe = eco_->owner().tribe(); |
250 | for (const DescriptionIndex& ware_index : tribe.wares()) { |
251 | const Economy::TargetQuantity& tq = eco_->ware_target_quantities_[ware_index]; |
252 | |
253 | === modified file 'src/economy/economy_data_packet.h' |
254 | --- src/economy/economy_data_packet.h 2018-04-07 16:59:00 +0000 |
255 | +++ src/economy/economy_data_packet.h 2018-07-11 08:33:43 +0000 |
256 | @@ -20,6 +20,8 @@ |
257 | #ifndef WL_ECONOMY_ECONOMY_DATA_PACKET_H |
258 | #define WL_ECONOMY_ECONOMY_DATA_PACKET_H |
259 | |
260 | +#include <cassert> |
261 | + |
262 | class FileRead; |
263 | class FileWrite; |
264 | |
265 | @@ -32,6 +34,7 @@ |
266 | class EconomyDataPacket { |
267 | public: |
268 | explicit EconomyDataPacket(Economy* e) : eco_(e) { |
269 | + assert(eco_); |
270 | } |
271 | |
272 | void read(FileRead&); |
273 | |
274 | === modified file 'src/economy/flag.cc' |
275 | --- src/economy/flag.cc 2018-07-07 09:05:13 +0000 |
276 | +++ src/economy/flag.cc 2018-07-11 08:33:43 +0000 |
277 | @@ -44,7 +44,7 @@ |
278 | } |
279 | |
280 | /** |
281 | - * Create the flag. Initially, it doesn't have any attachments. |
282 | + * A bare flag, used for testing only. |
283 | */ |
284 | Flag::Flag() |
285 | : PlayerImmovable(g_flag_descr), |
286 | @@ -106,7 +106,7 @@ |
287 | /** |
288 | * Create a flag at the given location |
289 | */ |
290 | -Flag::Flag(EditorGameBase& egbase, Player* owning_player, const Coords& coords) |
291 | +Flag::Flag(EditorGameBase& egbase, Player* owning_player, const Coords& coords, Economy* eco) |
292 | : PlayerImmovable(g_flag_descr), |
293 | building_(nullptr), |
294 | ware_capacity_(8), |
295 | @@ -124,17 +124,23 @@ |
296 | upcast(Game, game, &egbase); |
297 | |
298 | if (game) { |
299 | - // we split a road, or a new, standalone flag is created |
300 | - (road ? road->get_economy() : new Economy(*owning_player))->add_flag(*this); |
301 | - |
302 | - if (road) |
303 | - road->presplit(*game, coords); |
304 | + if (eco) { |
305 | + // We're saveloading |
306 | + eco->add_flag(*this); |
307 | + } else { |
308 | + // we split a road, or a new, standalone flag is created |
309 | + (road ? road->get_economy() : owning_player->create_economy())->add_flag(*this); |
310 | + if (road) { |
311 | + road->presplit(*game, coords); |
312 | + } |
313 | + } |
314 | } |
315 | |
316 | init(egbase); |
317 | |
318 | - if (road && game) |
319 | + if (!eco && road && game) { |
320 | road->postsplit(*game, *this); |
321 | + } |
322 | } |
323 | |
324 | void Flag::set_flag_position(Coords coords) { |
325 | |
326 | === modified file 'src/economy/flag.h' |
327 | --- src/economy/flag.h 2018-05-15 04:28:36 +0000 |
328 | +++ src/economy/flag.h 2018-07-11 08:33:43 +0000 |
329 | @@ -74,8 +74,12 @@ |
330 | |
331 | const FlagDescr& descr() const; |
332 | |
333 | - Flag(); /// empty flag for savegame loading |
334 | - Flag(EditorGameBase&, Player* owner, const Coords&); /// create a new flag |
335 | + /// Empty flag, for unit tests only. |
336 | + Flag(); |
337 | + |
338 | + /// Create a new flag. Only specify an economy during saveloading. |
339 | + /// Otherwise, a new economy will be created automatically if needed. |
340 | + Flag(EditorGameBase&, Player* owner, const Coords&, Economy* economy = nullptr); |
341 | ~Flag() override; |
342 | |
343 | void load_finish(EditorGameBase&) override; |
344 | |
345 | === modified file 'src/game_io/game_player_economies_packet.cc' |
346 | --- src/game_io/game_player_economies_packet.cc 2018-04-07 16:59:00 +0000 |
347 | +++ src/game_io/game_player_economies_packet.cc 2018-07-11 08:33:43 +0000 |
348 | @@ -34,7 +34,7 @@ |
349 | namespace Widelands { |
350 | namespace { |
351 | |
352 | -constexpr uint16_t kCurrentPacketVersion = 4; |
353 | +constexpr uint16_t kCurrentPacketVersion = 5; |
354 | |
355 | bool write_expedition_ship_economy(Economy* economy, const Map& map, FileWrite* fw) { |
356 | for (Field const* field = &map[0]; field < &map[map.max_index()]; ++field) { |
357 | @@ -67,31 +67,21 @@ |
358 | FileRead fr; |
359 | fr.open(fs, "binary/player_economies"); |
360 | uint16_t const packet_version = fr.unsigned_16(); |
361 | - if (packet_version == 3 || packet_version == kCurrentPacketVersion) { |
362 | + if (packet_version == kCurrentPacketVersion) { |
363 | iterate_players_existing(p, nr_players, game, player) try { |
364 | - // In packet_version 4 we dump the number of economies a player had at |
365 | - // save time to debug |
366 | - // https://bugs.launchpad.net/widelands/+bug/1654897 which is likely |
367 | - // caused by players having more economies at load than they had at |
368 | - // save. |
369 | - Player::Economies& economies = player->economies_; |
370 | - if (packet_version > 3) { |
371 | - const size_t num_economies = fr.unsigned_16(); |
372 | - if (num_economies != economies.size()) { |
373 | - throw GameDataError("Num economies on save (%" PRIuS |
374 | - ") != Num economies on load (%" PRIuS ")", |
375 | - num_economies, economies.size()); |
376 | - } |
377 | - } |
378 | - |
379 | - for (uint32_t i = 0; i < economies.size(); ++i) { |
380 | + const size_t num_economies = fr.unsigned_32(); |
381 | + for (uint32_t i = 0; i < num_economies; ++i) { |
382 | uint32_t value = fr.unsigned_32(); |
383 | if (value < 0xffffffff) { |
384 | if (upcast(Flag const, flag, map[value].get_immovable())) { |
385 | - assert(flag->get_economy()->owner().player_number() == |
386 | - player->player_number()); |
387 | - EconomyDataPacket d(flag->get_economy()); |
388 | - d.read(fr); |
389 | + try { |
390 | + assert(flag->get_economy()->owner().player_number() == |
391 | + player->player_number()); |
392 | + EconomyDataPacket d(flag->get_economy()); |
393 | + d.read(fr); |
394 | + } catch (const GameDataError& e) { |
395 | + throw GameDataError("error reading economy data for flag at map index %d: %s", value, e.what()); |
396 | + } |
397 | } else { |
398 | throw GameDataError("there is no flag at the specified location"); |
399 | } |
400 | @@ -102,13 +92,17 @@ |
401 | if (upcast(Ship const, ship, bob)) { |
402 | // We are interested only in current player's ships |
403 | if (ship->get_owner() == player) { |
404 | - assert(ship->get_economy()); |
405 | - assert(ship->get_economy()->owner().player_number() == |
406 | - player->player_number()); |
407 | - EconomyDataPacket d(ship->get_economy()); |
408 | - d.read(fr); |
409 | - read_this_economy = true; |
410 | - break; |
411 | + try { |
412 | + assert(ship->get_economy()); |
413 | + assert(ship->get_economy()->owner().player_number() == |
414 | + player->player_number()); |
415 | + EconomyDataPacket d(ship->get_economy()); |
416 | + d.read(fr); |
417 | + read_this_economy = true; |
418 | + break; |
419 | + } catch (const GameDataError& e) { |
420 | + throw GameDataError("error reading economy data for ship %s: %s", ship->get_shipname().c_str(), e.what()); |
421 | + } |
422 | } |
423 | } |
424 | bob = bob->get_next_bob(); |
425 | @@ -140,13 +134,13 @@ |
426 | const Map& map = game.map(); |
427 | PlayerNumber const nr_players = map.get_nrplayers(); |
428 | iterate_players_existing_const(p, nr_players, game, player) { |
429 | - const Player::Economies& economies = player->economies_; |
430 | - fw.unsigned_16(economies.size()); |
431 | - for (Economy* economy : economies) { |
432 | - Flag* arbitrary_flag = economy->get_arbitrary_flag(); |
433 | + const auto& economies = player->economies(); |
434 | + fw.unsigned_32(economies.size()); |
435 | + for (const auto& economy : economies) { |
436 | + Flag* arbitrary_flag = economy.second->get_arbitrary_flag(); |
437 | if (arbitrary_flag != nullptr) { |
438 | fw.unsigned_32(map.get_fcoords(arbitrary_flag->get_position()).field - &map[0]); |
439 | - EconomyDataPacket d(economy); |
440 | + EconomyDataPacket d(economy.second.get()); |
441 | d.write(fw); |
442 | continue; |
443 | } |
444 | @@ -154,8 +148,8 @@ |
445 | // No flag found, let's look for a representative Ship. Expeditions |
446 | // ships are special and have their own economy (which will not have a |
447 | // flag), therefore we have to special case them. |
448 | - if (!write_expedition_ship_economy(economy, map, &fw)) { |
449 | - throw GameDataError("economy without representative"); |
450 | + if (!write_expedition_ship_economy(economy.second.get(), map, &fw)) { |
451 | + throw GameDataError("Player %d: economy %d has no representative", player->player_number(), economy.first); |
452 | } |
453 | } |
454 | } |
455 | |
456 | === modified file 'src/io/filesystem/filesystem.cc' |
457 | --- src/io/filesystem/filesystem.cc 2018-06-06 19:45:06 +0000 |
458 | +++ src/io/filesystem/filesystem.cc 2018-07-11 08:33:43 +0000 |
459 | @@ -200,25 +200,24 @@ |
460 | } |
461 | } |
462 | const std::string illegal_start(as_listitem( |
463 | - /** TRANSLATORS: Tooltip entry for characters in illegal filenames. %s is a list of illegal |
464 | - * characters */ |
465 | + /** TRANSLATORS: Tooltip entry for characters in illegal filenames. |
466 | + * %s is a list of illegal characters */ |
467 | (boost::format(pgettext("illegal_filename_characters", "%s at the start of the filename")) % |
468 | richtext_escape(i18n::localize_list(starting_characters, i18n::ConcatenateWith::OR))) |
469 | .str(), |
470 | UI_FONT_SIZE_MESSAGE)); |
471 | |
472 | const std::string illegal(as_listitem( |
473 | - /** TRANSLATORS: Tooltip entry for characters in illegal filenames. %s is a list of illegal |
474 | - * characters */ |
475 | + /** TRANSLATORS: Tooltip entry for characters in illegal filenames. |
476 | + * %s is a list of illegal characters */ |
477 | (boost::format(pgettext("illegal_filename_characters", "%s anywhere in the filename")) % |
478 | richtext_escape(i18n::localize_list(illegal_filename_characters, i18n::ConcatenateWith::OR))) |
479 | .str(), |
480 | UI_FONT_SIZE_MESSAGE)); |
481 | |
482 | return (boost::format("%s%s%s") % |
483 | - /** TRANSLATORS: Tooltip header for characters in illegal filenames. This is followed by |
484 | - * a list |
485 | - * of bullet points */ |
486 | + /** TRANSLATORS: Tooltip header for characters in illegal filenames. |
487 | + * This is followed by a list of bullet points */ |
488 | pgettext("illegal_filename_characters", "The following characters are not allowed:") % |
489 | illegal_start % illegal) |
490 | .str(); |
491 | |
492 | === modified file 'src/logic/game.cc' |
493 | --- src/logic/game.cc 2018-04-30 15:38:48 +0000 |
494 | +++ src/logic/game.cc 2018-07-11 08:33:43 +0000 |
495 | @@ -911,17 +911,16 @@ |
496 | uint32_t wostock = 0; |
497 | uint32_t wastock = 0; |
498 | |
499 | - for (uint32_t j = 0; j < plr->get_nr_economies(); ++j) { |
500 | - Economy* const eco = plr->get_economy_by_number(j); |
501 | + for (const auto& economy : plr->economies()) { |
502 | const TribeDescr& tribe = plr->tribe(); |
503 | |
504 | for (const DescriptionIndex& ware_index : tribe.wares()) { |
505 | - wastock += eco->stock_ware(ware_index); |
506 | + wastock += economy.second->stock_ware(ware_index); |
507 | } |
508 | |
509 | for (const DescriptionIndex& worker_index : tribe.workers()) { |
510 | if (tribe.get_worker_descr(worker_index)->type() != MapObjectType::CARRIER) { |
511 | - wostock += eco->stock_worker(worker_index); |
512 | + wostock += economy.second->stock_worker(worker_index); |
513 | } |
514 | } |
515 | } |
516 | |
517 | === modified file 'src/logic/map_objects/tribes/ship.cc' |
518 | --- src/logic/map_objects/tribes/ship.cc 2018-04-30 15:38:48 +0000 |
519 | +++ src/logic/map_objects/tribes/ship.cc 2018-07-11 08:33:43 +0000 |
520 | @@ -826,14 +826,14 @@ |
521 | expedition_->scouting_direction = WalkingDir::IDLE; |
522 | expedition_->exploration_start = Coords(0, 0); |
523 | expedition_->island_explore_direction = IslandExploreDirection::kClockwise; |
524 | - expedition_->economy.reset(new Economy(*get_owner())); |
525 | + expedition_->economy = get_owner()->create_economy(); |
526 | |
527 | // We are no longer in any other economy, but instead are an economy of our |
528 | // own. |
529 | fleet_->remove_ship(game, this); |
530 | assert(fleet_ == nullptr); |
531 | |
532 | - set_economy(game, expedition_->economy.get()); |
533 | + set_economy(game, expedition_->economy); |
534 | |
535 | for (int i = items_.size() - 1; i >= 0; --i) { |
536 | WareInstance* ware; |
537 | @@ -943,7 +943,7 @@ |
538 | if (!get_fleet() || !get_fleet()->has_ports()) { |
539 | // We lost our last reachable port, so we reset the expedition's state |
540 | ship_state_ = ShipStates::kExpeditionWaiting; |
541 | - set_economy(game, expedition_->economy.get()); |
542 | + set_economy(game, expedition_->economy); |
543 | |
544 | worker = nullptr; |
545 | for (ShippingItem& item : items_) { |
546 | @@ -957,7 +957,7 @@ |
547 | Notifications::publish(NoteShip(this, NoteShip::Action::kNoPortLeft)); |
548 | return; |
549 | } |
550 | - assert(get_economy() && get_economy() != expedition_->economy.get()); |
551 | + assert(get_economy() && get_economy() != expedition_->economy); |
552 | |
553 | send_signal(game, "cancel_expedition"); |
554 | |
555 | @@ -1096,6 +1096,12 @@ |
556 | heading, rt_description, get_position(), serial_))); |
557 | } |
558 | |
559 | +Ship::Expedition::~Expedition() { |
560 | + if (economy) { |
561 | + economy->owner().remove_economy(economy->serial()); |
562 | + } |
563 | +} |
564 | + |
565 | /* |
566 | ============================== |
567 | |
568 | @@ -1104,7 +1110,7 @@ |
569 | ============================== |
570 | */ |
571 | |
572 | -constexpr uint8_t kCurrentPacketVersion = 6; |
573 | +constexpr uint8_t kCurrentPacketVersion = 7; |
574 | |
575 | const Bob::Task* Ship::Loader::get_task(const std::string& name) { |
576 | if (name == "shipidle" || name == "ship") |
577 | @@ -1115,6 +1121,9 @@ |
578 | void Ship::Loader::load(FileRead& fr) { |
579 | Bob::Loader::load(fr); |
580 | |
581 | + // Economy |
582 | + economy_serial_ = fr.unsigned_32(); |
583 | + |
584 | // The state the ship is in |
585 | ship_state_ = static_cast<ShipStates>(fr.unsigned_8()); |
586 | |
587 | @@ -1175,6 +1184,14 @@ |
588 | |
589 | Ship& ship = get<Ship>(); |
590 | |
591 | + // The economy can sometimes be nullptr (e.g. when there are no ports). |
592 | + if (economy_serial_ != kInvalidSerial) { |
593 | + ship.economy_ = ship.get_owner()->get_economy(economy_serial_); |
594 | + if (!ship.economy_) { |
595 | + ship.economy_ = ship.get_owner()->create_economy(economy_serial_); |
596 | + } |
597 | + } |
598 | + |
599 | // restore the state the ship is in |
600 | ship.ship_state_ = ship_state_; |
601 | |
602 | @@ -1184,8 +1201,7 @@ |
603 | // if the ship is on an expedition, restore the expedition specific data |
604 | if (expedition_) { |
605 | ship.expedition_.swap(expedition_); |
606 | - ship.expedition_->economy.reset(new Economy(*ship.get_owner())); |
607 | - ship.economy_ = ship.expedition_->economy.get(); |
608 | + ship.expedition_->economy = ship.economy_; |
609 | } else |
610 | assert(ship_state_ == ShipStates::kTransport); |
611 | |
612 | @@ -1201,28 +1217,16 @@ |
613 | |
614 | MapObject::Loader* Ship::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) { |
615 | std::unique_ptr<Loader> loader(new Loader); |
616 | - |
617 | try { |
618 | // The header has been peeled away by the caller |
619 | uint8_t const packet_version = fr.unsigned_8(); |
620 | - if (1 <= packet_version && packet_version <= kCurrentPacketVersion) { |
621 | + if (packet_version == kCurrentPacketVersion) { |
622 | try { |
623 | const ShipDescr* descr = nullptr; |
624 | // Removing this will break the test suite |
625 | - if (packet_version < 5) { |
626 | - std::string tribe_name = fr.string(); |
627 | - fr.c_string(); // This used to be the ship's name, which we don't need any more. |
628 | - if (!Widelands::tribe_exists(tribe_name)) { |
629 | - throw GameDataError("Tribe %s does not exist for ship", tribe_name.c_str()); |
630 | - } |
631 | - const DescriptionIndex& tribe_index = egbase.tribes().tribe_index(tribe_name); |
632 | - const TribeDescr& tribe_descr = *egbase.tribes().get_tribe_descr(tribe_index); |
633 | - descr = egbase.tribes().get_ship_descr(tribe_descr.ship()); |
634 | - } else { |
635 | - std::string name = fr.c_string(); |
636 | - const DescriptionIndex& ship_index = egbase.tribes().safe_ship_index(name); |
637 | - descr = egbase.tribes().get_ship_descr(ship_index); |
638 | - } |
639 | + std::string name = fr.c_string(); |
640 | + const DescriptionIndex& ship_index = egbase.tribes().safe_ship_index(name); |
641 | + descr = egbase.tribes().get_ship_descr(ship_index); |
642 | loader->init(egbase, mol, descr->create_object()); |
643 | loader->load(fr); |
644 | } catch (const WException& e) { |
645 | @@ -1245,6 +1249,9 @@ |
646 | |
647 | Bob::save(egbase, mos, fw); |
648 | |
649 | + // The economy can sometimes be nullptr (e.g. when there are no ports). |
650 | + fw.unsigned_32(economy_ != nullptr ? economy_->serial() : kInvalidSerial); |
651 | + |
652 | // state the ship is in |
653 | fw.unsigned_8(static_cast<uint8_t>(ship_state_)); |
654 | |
655 | |
656 | === modified file 'src/logic/map_objects/tribes/ship.h' |
657 | --- src/logic/map_objects/tribes/ship.h 2018-04-29 09:20:29 +0000 |
658 | +++ src/logic/map_objects/tribes/ship.h 2018-07-11 08:33:43 +0000 |
659 | @@ -271,13 +271,15 @@ |
660 | std::string shipname_; |
661 | |
662 | struct Expedition { |
663 | + ~Expedition(); |
664 | + |
665 | std::vector<Coords> seen_port_buildspaces; |
666 | bool swimmable[LAST_DIRECTION]; |
667 | bool island_exploration; |
668 | WalkingDir scouting_direction; |
669 | Coords exploration_start; |
670 | IslandExploreDirection island_explore_direction; |
671 | - std::unique_ptr<Economy> economy; |
672 | + Economy* economy; // Owned by Player |
673 | }; |
674 | std::unique_ptr<Expedition> expedition_; |
675 | |
676 | @@ -295,6 +297,7 @@ |
677 | // Initialize everything to make cppcheck happy. |
678 | uint32_t lastdock_ = 0U; |
679 | uint32_t destination_ = 0U; |
680 | + Serial economy_serial_; |
681 | ShipStates ship_state_ = ShipStates::kTransport; |
682 | std::string shipname_; |
683 | std::unique_ptr<Expedition> expedition_; |
684 | |
685 | === modified file 'src/logic/player.cc' |
686 | --- src/logic/player.cc 2018-04-29 09:20:29 +0000 |
687 | +++ src/logic/player.cc 2018-07-11 08:33:43 +0000 |
688 | @@ -798,37 +798,50 @@ |
689 | /* |
690 | * Economy stuff below |
691 | */ |
692 | -void Player::add_economy(Economy& economy) { |
693 | - if (!has_economy(economy)) |
694 | - economies_.push_back(&economy); |
695 | -} |
696 | - |
697 | -void Player::remove_economy(Economy& economy) { |
698 | - for (std::vector<Economy*>::iterator economy_iter = economies_.begin(); |
699 | - economy_iter != economies_.end(); ++economy_iter) |
700 | - if (*economy_iter == &economy) { |
701 | - economies_.erase(economy_iter); |
702 | - return; |
703 | - } |
704 | -} |
705 | - |
706 | -bool Player::has_economy(Economy& economy) const { |
707 | - for (Economy* temp_economy : economies_) { |
708 | - if (temp_economy == &economy) { |
709 | - return true; |
710 | - } |
711 | +Economy* Player::create_economy() { |
712 | + std::unique_ptr<Economy> eco(new Economy(*this)); |
713 | + const Serial serial = eco->serial(); |
714 | + |
715 | + assert(economies_.count(serial) == 0); |
716 | + economies_.emplace(std::make_pair(serial, std::move(eco))); |
717 | + assert(economies_.at(serial)->serial() == serial); |
718 | + assert(economies_.count(serial) == 1); |
719 | + |
720 | + return get_economy(serial); |
721 | +} |
722 | + |
723 | +Economy* Player::create_economy(Serial serial) { |
724 | + std::unique_ptr<Economy> eco(new Economy(*this, serial)); |
725 | + |
726 | + assert(economies_.count(serial) == 0); |
727 | + economies_.emplace(std::make_pair(serial, std::move(eco))); |
728 | + assert(economies_.at(serial)->serial() == serial); |
729 | + assert(economies_.count(serial) == 1); |
730 | + |
731 | + return get_economy(serial); |
732 | +} |
733 | + |
734 | +void Player::remove_economy(Serial serial) { |
735 | + assert(has_economy(serial)); |
736 | + economies_.erase(economies_.find(serial)); |
737 | + assert(!has_economy(serial)); |
738 | +} |
739 | + |
740 | +const std::map<Serial, std::unique_ptr<Economy>>& Player::economies() const { |
741 | + return economies_; |
742 | +} |
743 | + |
744 | +Economy* Player::get_economy(Widelands::Serial serial) const { |
745 | + if (economies_.count(serial) == 0) { |
746 | + return nullptr; |
747 | } |
748 | - return false; |
749 | -} |
750 | - |
751 | -Player::Economies::size_type Player::get_economy_number(Economy const* const economy) const { |
752 | - Economies::const_iterator const economies_end = economies_.end(), |
753 | - economies_begin = economies_.begin(); |
754 | - for (Economies::const_iterator it = economies_begin; it != economies_end; ++it) |
755 | - if (*it == economy) |
756 | - return it - economies_begin; |
757 | - NEVER_HERE(); |
758 | -} |
759 | + return economies_.at(serial).get(); |
760 | +} |
761 | + |
762 | +bool Player::has_economy(Widelands::Serial serial) const { |
763 | + return economies_.count(serial) != 0; |
764 | +} |
765 | + |
766 | |
767 | /************ Military stuff **********/ |
768 | |
769 | @@ -1156,11 +1169,8 @@ |
770 | // Calculate stocks |
771 | std::vector<uint32_t> stocks(egbase().tribes().nrwares()); |
772 | |
773 | - const uint32_t nrecos = get_nr_economies(); |
774 | - for (uint32_t i = 0; i < nrecos; ++i) { |
775 | - const std::vector<Widelands::Warehouse*>& warehouses = get_economy_by_number(i)->warehouses(); |
776 | - |
777 | - for (Widelands::Warehouse* warehouse : warehouses) { |
778 | + for (const auto& economy : economies()) { |
779 | + for (Widelands::Warehouse* warehouse : economy.second->warehouses()) { |
780 | const Widelands::WareList& wares = warehouse->get_wares(); |
781 | for (size_t id = 0; id < stocks.size(); ++id) { |
782 | stocks[id] += wares.stock(DescriptionIndex(id)); |
783 | |
784 | === modified file 'src/logic/player.h' |
785 | --- src/logic/player.h 2018-04-29 09:20:29 +0000 |
786 | +++ src/logic/player.h 2018-07-11 08:33:43 +0000 |
787 | @@ -25,6 +25,7 @@ |
788 | #include <unordered_map> |
789 | |
790 | #include "base/macros.h" |
791 | +#include "economy/economy.h" |
792 | #include "graphic/color.h" |
793 | #include "graphic/playercolor.h" |
794 | #include "logic/editor_game_base.h" |
795 | @@ -40,7 +41,6 @@ |
796 | class Node; |
797 | namespace Widelands { |
798 | |
799 | -class Economy; |
800 | struct Path; |
801 | struct PlayerImmovable; |
802 | class Soldier; |
803 | @@ -515,18 +515,12 @@ |
804 | void enhance_building(Building*, DescriptionIndex index_of_new_building); |
805 | void dismantle_building(Building*); |
806 | |
807 | - // Economy stuff |
808 | - void add_economy(Economy&); |
809 | - void remove_economy(Economy&); |
810 | - bool has_economy(Economy&) const; |
811 | - using Economies = std::vector<Economy*>; |
812 | - Economies::size_type get_economy_number(Economy const*) const; |
813 | - Economy* get_economy_by_number(Economies::size_type const i) const { |
814 | - return economies_[i]; |
815 | - } |
816 | - uint32_t get_nr_economies() const { |
817 | - return economies_.size(); |
818 | - } |
819 | + Economy* create_economy(); |
820 | + Economy* create_economy(Serial serial); // For saveloading only |
821 | + void remove_economy(Serial serial); |
822 | + const std::map<Serial, std::unique_ptr<Economy>>& economies() const; |
823 | + Economy* get_economy(Widelands::Serial serial) const; |
824 | + bool has_economy(Widelands::Serial serial) const; |
825 | |
826 | uint32_t get_current_produced_statistics(uint8_t); |
827 | |
828 | @@ -644,7 +638,7 @@ |
829 | Field* fields_; |
830 | std::vector<bool> allowed_worker_types_; |
831 | std::vector<bool> allowed_building_types_; |
832 | - Economies economies_; |
833 | + std::map<Serial, std::unique_ptr<Economy>> economies_; |
834 | std::set<Serial> ships_; |
835 | std::string name_; // Player name |
836 | std::string ai_; /**< Name of preferred AI implementation */ |
837 | |
838 | === modified file 'src/logic/playercommand.cc' |
839 | --- src/logic/playercommand.cc 2018-04-07 16:59:00 +0000 |
840 | +++ src/logic/playercommand.cc 2018-07-11 08:33:43 +0000 |
841 | @@ -1229,8 +1229,8 @@ |
842 | |
843 | void CmdSetWareTargetQuantity::execute(Game& game) { |
844 | Player* player = game.get_player(sender()); |
845 | - if (economy() < player->get_nr_economies() && game.tribes().ware_exists(ware_type())) { |
846 | - player->get_economy_by_number(economy())->set_ware_target_quantity( |
847 | + if (player->has_economy(economy()) && game.tribes().ware_exists(ware_type())) { |
848 | + player->get_economy(economy())->set_ware_target_quantity( |
849 | ware_type(), permanent_, duetime()); |
850 | } |
851 | } |
852 | @@ -1280,9 +1280,9 @@ |
853 | void CmdResetWareTargetQuantity::execute(Game& game) { |
854 | Player* player = game.get_player(sender()); |
855 | const TribeDescr& tribe = player->tribe(); |
856 | - if (economy() < player->get_nr_economies() && game.tribes().ware_exists(ware_type())) { |
857 | + if (player->has_economy(economy()) && game.tribes().ware_exists(ware_type())) { |
858 | const int count = tribe.get_ware_descr(ware_type())->default_target_quantity(tribe.name()); |
859 | - player->get_economy_by_number(economy())->set_ware_target_quantity( |
860 | + player->get_economy(economy())->set_ware_target_quantity( |
861 | ware_type(), count, duetime()); |
862 | } |
863 | } |
864 | @@ -1328,8 +1328,8 @@ |
865 | |
866 | void CmdSetWorkerTargetQuantity::execute(Game& game) { |
867 | Player* player = game.get_player(sender()); |
868 | - if (economy() < player->get_nr_economies() && game.tribes().worker_exists(ware_type())) { |
869 | - player->get_economy_by_number(economy())->set_worker_target_quantity( |
870 | + if (player->has_economy(economy()) && game.tribes().worker_exists(ware_type())) { |
871 | + player->get_economy(economy())->set_worker_target_quantity( |
872 | ware_type(), permanent_, duetime()); |
873 | } |
874 | } |
875 | @@ -1379,9 +1379,9 @@ |
876 | void CmdResetWorkerTargetQuantity::execute(Game& game) { |
877 | Player* player = game.get_player(sender()); |
878 | const TribeDescr& tribe = player->tribe(); |
879 | - if (economy() < player->get_nr_economies() && game.tribes().ware_exists(ware_type())) { |
880 | + if (player->has_economy(economy()) && game.tribes().ware_exists(ware_type())) { |
881 | const int count = tribe.get_ware_descr(ware_type())->default_target_quantity(tribe.name()); |
882 | - player->get_economy_by_number(economy())->set_worker_target_quantity( |
883 | + player->get_economy(economy())->set_worker_target_quantity( |
884 | ware_type(), count, duetime()); |
885 | } |
886 | } |
887 | |
888 | === modified file 'src/logic/playercommand.h' |
889 | --- src/logic/playercommand.h 2018-04-07 16:59:00 +0000 |
890 | +++ src/logic/playercommand.h 2018-07-11 08:33:43 +0000 |
891 | @@ -543,7 +543,7 @@ |
892 | void serialize(StreamWrite&) override; |
893 | |
894 | protected: |
895 | - uint32_t economy() const { |
896 | + Serial economy() const { |
897 | return economy_; |
898 | } |
899 | DescriptionIndex ware_type() const { |
900 | @@ -551,7 +551,7 @@ |
901 | } |
902 | |
903 | private: |
904 | - uint32_t economy_; |
905 | + Serial economy_; |
906 | DescriptionIndex ware_type_; |
907 | }; |
908 | |
909 | |
910 | === modified file 'src/logic/widelands.h' |
911 | --- src/logic/widelands.h 2018-04-07 16:59:00 +0000 |
912 | +++ src/logic/widelands.h 2018-07-11 08:33:43 +0000 |
913 | @@ -84,6 +84,7 @@ |
914 | } |
915 | |
916 | using Serial = uint32_t; /// Serial number for MapObject. |
917 | +constexpr Serial kInvalidSerial = std::numeric_limits<uint32_t>::max(); |
918 | |
919 | using Direction = uint8_t; |
920 | |
921 | |
922 | === modified file 'src/map_io/map_flag_packet.cc' |
923 | --- src/map_io/map_flag_packet.cc 2018-04-07 16:59:00 +0000 |
924 | +++ src/map_io/map_flag_packet.cc 2018-07-11 08:33:43 +0000 |
925 | @@ -35,7 +35,7 @@ |
926 | |
927 | namespace Widelands { |
928 | |
929 | -constexpr uint16_t kCurrentPacketVersion = 1; |
930 | +constexpr uint16_t kCurrentPacketVersion = 2; |
931 | |
932 | void MapFlagPacket::read(FileSystem& fs, |
933 | EditorGameBase& egbase, |
934 | @@ -63,6 +63,8 @@ |
935 | throw GameDataError("Invalid player number: %i.", owner); |
936 | } |
937 | |
938 | + const Serial economy_serial = fr.unsigned_32(); |
939 | + |
940 | Serial const serial = fr.unsigned_32(); |
941 | |
942 | try { |
943 | @@ -94,13 +96,21 @@ |
944 | |
945 | // No flag lives on more than one place. |
946 | |
947 | + // Get economy from serial |
948 | + Player* player = egbase.get_player(owner); |
949 | + Economy* economy = player->get_economy(economy_serial); |
950 | + if (!economy) { |
951 | + economy = player->create_economy(economy_serial); |
952 | + } |
953 | + |
954 | // Now, create this Flag. Directly create it, do not call |
955 | // the player class since we recreate the data in another |
956 | // packet. We always create this, no matter what skip is |
957 | // since we have to read the data packets. We delete this |
958 | // object later again, if it is not wanted. |
959 | - mol.register_object<Flag>( |
960 | - serial, *new Flag(dynamic_cast<Game&>(egbase), egbase.get_player(owner), fc)); |
961 | + Flag* flag = new Flag(dynamic_cast<Game&>(egbase), player, fc, economy); |
962 | + mol.register_object<Flag>(serial, *flag); |
963 | + |
964 | } catch (const WException& e) { |
965 | throw GameDataError( |
966 | "%u (at (%i, %i), owned by player %u): %s", serial, fc.x, fc.y, owner, e.what()); |
967 | @@ -133,6 +143,7 @@ |
968 | |
969 | fw.unsigned_8(1); |
970 | fw.unsigned_8(flag->owner().player_number()); |
971 | + fw.unsigned_32(flag->economy().serial()); |
972 | fw.unsigned_32(mos.register_object(*flag)); |
973 | } else // no existence, no owner |
974 | fw.unsigned_8(0); |
975 | |
976 | === modified file 'src/scripting/lua_bases.cc' |
977 | --- src/scripting/lua_bases.cc 2018-07-07 09:06:55 +0000 |
978 | +++ src/scripting/lua_bases.cc 2018-07-11 08:33:43 +0000 |
979 | @@ -875,8 +875,8 @@ |
980 | const DescriptionIndex worker = player.tribe().worker_index(workername); |
981 | |
982 | uint32_t nworkers = 0; |
983 | - for (uint32_t i = 0; i < player.get_nr_economies(); ++i) { |
984 | - nworkers += player.get_economy_by_number(i)->stock_worker(worker); |
985 | + for (const auto& economy : player.economies()) { |
986 | + nworkers += economy.second->stock_worker(worker); |
987 | } |
988 | lua_pushuint32(L, nworkers); |
989 | return 1; |
990 | @@ -901,8 +901,8 @@ |
991 | const DescriptionIndex ware = egbase.tribes().ware_index(warename); |
992 | |
993 | uint32_t nwares = 0; |
994 | - for (uint32_t i = 0; i < player.get_nr_economies(); ++i) { |
995 | - nwares += player.get_economy_by_number(i)->stock_ware(ware); |
996 | + for (const auto& economy : player.economies()) { |
997 | + nwares += economy.second->stock_ware(ware); |
998 | } |
999 | lua_pushuint32(L, nwares); |
1000 | return 1; |
1001 | |
1002 | === modified file 'src/scripting/lua_game.cc' |
1003 | --- src/scripting/lua_game.cc 2018-04-16 07:03:12 +0000 |
1004 | +++ src/scripting/lua_game.cc 2018-07-11 08:33:43 +0000 |
1005 | @@ -174,16 +174,16 @@ |
1006 | */ |
1007 | int LuaPlayer::get_defeated(lua_State* L) { |
1008 | Player& p = get(L, get_egbase(L)); |
1009 | - bool have_warehouses = false; |
1010 | + bool is_defeated = true; |
1011 | |
1012 | - for (uint32_t economy_nr = 0; economy_nr < p.get_nr_economies(); economy_nr++) { |
1013 | - if (!p.get_economy_by_number(economy_nr)->warehouses().empty()) { |
1014 | - have_warehouses = true; |
1015 | + for (const auto& economy : p.economies()) { |
1016 | + if (!economy.second->warehouses().empty()) { |
1017 | + is_defeated = false; |
1018 | break; |
1019 | } |
1020 | } |
1021 | |
1022 | - lua_pushboolean(L, !have_warehouses); |
1023 | + lua_pushboolean(L, is_defeated); |
1024 | return 1; |
1025 | } |
1026 | |
1027 | @@ -812,10 +812,8 @@ |
1028 | break; |
1029 | } |
1030 | } |
1031 | - for (uint32_t j = player.get_nr_economies(); j;) { |
1032 | - Economy& economy = *player.get_economy_by_number(--j); |
1033 | - |
1034 | - for (Warehouse* warehouse : economy.warehouses()) { |
1035 | + for (const auto& economy: player.economies()) { |
1036 | + for (Warehouse* warehouse : economy.second->warehouses()) { |
1037 | warehouse->enable_spawn(game, worker_types_without_cost_index); |
1038 | } |
1039 | } |
1040 | |
1041 | === modified file 'src/scripting/lua_map.cc' |
1042 | --- src/scripting/lua_map.cc 2018-07-07 11:03:56 +0000 |
1043 | +++ src/scripting/lua_map.cc 2018-07-11 08:33:43 +0000 |
1044 | @@ -3568,16 +3568,16 @@ |
1045 | const Widelands::Economy* economy = get(); |
1046 | const Widelands::Player& player = economy->owner(); |
1047 | PERS_UINT32("player", player.player_number()); |
1048 | - PERS_UINT32("economy", player.get_economy_number(economy)); |
1049 | + PERS_UINT32("economy", economy->serial()); |
1050 | } |
1051 | |
1052 | void LuaEconomy::__unpersist(lua_State* L) { |
1053 | Widelands::PlayerNumber player_number; |
1054 | - size_t economy_number; |
1055 | + Widelands::Serial economy_serial; |
1056 | UNPERS_UINT32("player", player_number); |
1057 | - UNPERS_UINT32("economy", economy_number); |
1058 | + UNPERS_UINT32("economy", economy_serial); |
1059 | const Widelands::Player& player = get_egbase(L).player(player_number); |
1060 | - set_economy_pointer(player.get_economy_by_number(economy_number)); |
1061 | + set_economy_pointer(player.get_economy(economy_serial)); |
1062 | } |
1063 | |
1064 | /* RST |
1065 | |
1066 | === modified file 'src/wui/economy_options_window.cc' |
1067 | --- src/wui/economy_options_window.cc 2018-05-13 07:15:39 +0000 |
1068 | +++ src/wui/economy_options_window.cc 2018-07-11 08:33:43 +0000 |
1069 | @@ -36,10 +36,11 @@ |
1070 | Widelands::Economy* economy, |
1071 | bool can_act) |
1072 | : UI::Window(parent, "economy_options", 0, 0, 0, 0, _("Economy options")), |
1073 | - economy_(economy), |
1074 | + serial_(economy->serial()), |
1075 | + player_(&economy->owner()), |
1076 | tabpanel_(this, UI::TabPanelStyle::kWuiDark), |
1077 | - ware_panel_(new EconomyOptionsPanel(&tabpanel_, can_act, Widelands::wwWARE, economy)), |
1078 | - worker_panel_(new EconomyOptionsPanel(&tabpanel_, can_act, Widelands::wwWORKER, economy)) { |
1079 | + ware_panel_(new EconomyOptionsPanel(&tabpanel_, serial_, player_, can_act, Widelands::wwWARE)), |
1080 | + worker_panel_(new EconomyOptionsPanel(&tabpanel_, serial_, player_, can_act, Widelands::wwWORKER)) { |
1081 | set_center_panel(&tabpanel_); |
1082 | |
1083 | tabpanel_.add("wares", g_gr->images().get(pic_tab_wares), ware_panel_, _("Wares")); |
1084 | @@ -50,27 +51,29 @@ |
1085 | } |
1086 | |
1087 | EconomyOptionsWindow::~EconomyOptionsWindow() { |
1088 | - if (economy_ != nullptr) { |
1089 | - economy_->set_has_window(false); |
1090 | + Widelands::Economy* economy = player_->get_economy(serial_); |
1091 | + if (economy != nullptr) { |
1092 | + economy->set_has_window(false); |
1093 | } |
1094 | } |
1095 | |
1096 | void EconomyOptionsWindow::on_economy_note(const Widelands::NoteEconomy& note) { |
1097 | - if (note.old_economy == economy_) { |
1098 | + if (note.old_economy == serial_) { |
1099 | switch (note.action) { |
1100 | - case Widelands::NoteEconomy::Action::kMerged: |
1101 | - economy_ = note.new_economy; |
1102 | + case Widelands::NoteEconomy::Action::kMerged: { |
1103 | + serial_ = note.new_economy; |
1104 | + Widelands::Economy* economy = player_->get_economy(serial_); |
1105 | + if (economy == nullptr) { |
1106 | + die(); |
1107 | + return; |
1108 | + } |
1109 | + economy->set_has_window(true); |
1110 | ware_panel_->set_economy(note.new_economy); |
1111 | worker_panel_->set_economy(note.new_economy); |
1112 | - economy_->set_has_window(true); |
1113 | move_to_top(); |
1114 | - break; |
1115 | + } break; |
1116 | case Widelands::NoteEconomy::Action::kDeleted: |
1117 | // Make sure that the panels stop thinking first. |
1118 | - ware_panel_->die(); |
1119 | - worker_panel_->die(); |
1120 | - economy_->set_has_window(false); |
1121 | - economy_ = nullptr; |
1122 | die(); |
1123 | break; |
1124 | } |
1125 | @@ -80,12 +83,13 @@ |
1126 | EconomyOptionsWindow::TargetWaresDisplay::TargetWaresDisplay(UI::Panel* const parent, |
1127 | int32_t const x, |
1128 | int32_t const y, |
1129 | + Widelands::Serial serial, |
1130 | + Widelands::Player* player, |
1131 | Widelands::WareWorker type, |
1132 | - bool selectable, |
1133 | - Widelands::Economy* economy) |
1134 | - : AbstractWaresDisplay(parent, x, y, economy->owner().tribe(), type, selectable), |
1135 | - economy_(economy) { |
1136 | - const Widelands::TribeDescr& owner_tribe = economy->owner().tribe(); |
1137 | + bool selectable) |
1138 | + : AbstractWaresDisplay(parent, x, y, player->tribe(), type, selectable), |
1139 | + serial_(serial), player_(player) { |
1140 | + const Widelands::TribeDescr& owner_tribe = player->tribe(); |
1141 | if (type == Widelands::wwWORKER) { |
1142 | for (const Widelands::DescriptionIndex& worker_index : owner_tribe.workers()) { |
1143 | const Widelands::WorkerDescr* worker_descr = owner_tribe.get_worker_descr(worker_index); |
1144 | @@ -103,29 +107,36 @@ |
1145 | } |
1146 | } |
1147 | |
1148 | -void EconomyOptionsWindow::TargetWaresDisplay::set_economy(Widelands::Economy* economy) { |
1149 | - economy_ = economy; |
1150 | +void EconomyOptionsWindow::TargetWaresDisplay::set_economy(Widelands::Serial serial) { |
1151 | + serial_ = serial; |
1152 | } |
1153 | |
1154 | std::string |
1155 | EconomyOptionsWindow::TargetWaresDisplay::info_for_ware(Widelands::DescriptionIndex const ware) { |
1156 | + Widelands::Economy* economy = player_->get_economy(serial_); |
1157 | + if (economy == nullptr) { |
1158 | + die(); |
1159 | + return *(new std::string()); |
1160 | + } |
1161 | return boost::lexical_cast<std::string>(get_type() == Widelands::wwWORKER ? |
1162 | - economy_->worker_target_quantity(ware).permanent : |
1163 | - economy_->ware_target_quantity(ware).permanent); |
1164 | + economy->worker_target_quantity(ware).permanent : |
1165 | + economy->ware_target_quantity(ware).permanent); |
1166 | } |
1167 | |
1168 | /** |
1169 | * Wraps the wares/workers display together with some buttons |
1170 | */ |
1171 | EconomyOptionsWindow::EconomyOptionsPanel::EconomyOptionsPanel(UI::Panel* parent, |
1172 | + Widelands::Serial serial, |
1173 | + Widelands::Player* player, |
1174 | bool can_act, |
1175 | - Widelands::WareWorker type, |
1176 | - Widelands::Economy* economy) |
1177 | + Widelands::WareWorker type) |
1178 | : UI::Box(parent, 0, 0, UI::Box::Vertical), |
1179 | + serial_(serial), |
1180 | + player_(player), |
1181 | type_(type), |
1182 | - economy_(economy), |
1183 | can_act_(can_act), |
1184 | - display_(this, 0, 0, type_, can_act_, economy) { |
1185 | + display_(this, 0, 0, serial_, player_, type_, can_act_) { |
1186 | add(&display_, UI::Box::Resizing::kFullSize); |
1187 | |
1188 | if (!can_act_) { |
1189 | @@ -154,37 +165,34 @@ |
1190 | buttons->add(b); |
1191 | } |
1192 | |
1193 | -void EconomyOptionsWindow::EconomyOptionsPanel::set_economy(Widelands::Economy* economy) { |
1194 | - economy_ = economy; |
1195 | - display_.set_economy(economy); |
1196 | +void EconomyOptionsWindow::EconomyOptionsPanel::set_economy(Widelands::Serial serial) { |
1197 | + serial_ = serial; |
1198 | + display_.set_economy(serial); |
1199 | } |
1200 | |
1201 | void EconomyOptionsWindow::EconomyOptionsPanel::change_target(int amount) { |
1202 | - auto& owner = economy_->owner(); |
1203 | - Widelands::Game& game = dynamic_cast<Widelands::Game&>(owner.egbase()); |
1204 | + Widelands::Economy* economy = player_->get_economy(serial_); |
1205 | + if (economy == nullptr) { |
1206 | + die(); |
1207 | + return; |
1208 | + } |
1209 | + Widelands::Game& game = dynamic_cast<Widelands::Game&>(player_->egbase()); |
1210 | const bool is_wares = type_ == Widelands::wwWARE; |
1211 | - const auto& items = is_wares ? owner.tribe().wares() : owner.tribe().workers(); |
1212 | + const auto& items = is_wares ? player_->tribe().wares() : player_->tribe().workers(); |
1213 | for (const Widelands::DescriptionIndex& index : items) { |
1214 | if (display_.ware_selected(index)) { |
1215 | - const Widelands::Economy::TargetQuantity& tq = is_wares ? |
1216 | - economy_->ware_target_quantity(index) : |
1217 | - economy_->worker_target_quantity(index); |
1218 | + const Widelands::Economy::TargetQuantity& tq = |
1219 | + is_wares ? economy->ware_target_quantity(index) : economy->worker_target_quantity(index); |
1220 | // Don't allow negative new amount. |
1221 | if (amount >= 0 || -amount <= static_cast<int>(tq.permanent)) { |
1222 | if (is_wares) { |
1223 | - // TODO(sirver): This is crashy. Nobody guarantees that the |
1224 | - // economy_number_ is still the same when this command finally |
1225 | - // is executed. Player::remove_economy relabels economies on |
1226 | - // deletion. Economies require a unique, never changing id, same |
1227 | - // as map objects. |
1228 | game.send_player_command(*new Widelands::CmdSetWareTargetQuantity( |
1229 | - game.get_gametime(), owner.player_number(), owner.get_economy_number(economy_), |
1230 | + game.get_gametime(), player_->player_number(), serial_, |
1231 | index, tq.permanent + amount)); |
1232 | } else { |
1233 | - // TODO(sirver): Same as above |
1234 | game.send_player_command(*new Widelands::CmdSetWorkerTargetQuantity( |
1235 | - game.get_gametime(), owner.player_number(), owner.get_economy_number(economy_), |
1236 | - index, tq.permanent + amount)); |
1237 | + game.get_gametime(), player_->player_number(), serial_, index, |
1238 | + tq.permanent + amount)); |
1239 | } |
1240 | } |
1241 | } |
1242 | @@ -192,19 +200,18 @@ |
1243 | } |
1244 | |
1245 | void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() { |
1246 | - auto& owner = economy_->owner(); |
1247 | - Widelands::Game& game = dynamic_cast<Widelands::Game&>(owner.egbase()); |
1248 | + Widelands::Game& game = dynamic_cast<Widelands::Game&>(player_->egbase()); |
1249 | const bool is_wares = type_ == Widelands::wwWARE; |
1250 | - const auto& items = is_wares ? owner.tribe().wares() : owner.tribe().workers(); |
1251 | + const auto& items = is_wares ? player_->tribe().wares() : player_->tribe().workers(); |
1252 | for (const Widelands::DescriptionIndex& index : items) { |
1253 | if (display_.ware_selected(index)) { |
1254 | if (is_wares) { |
1255 | game.send_player_command(*new Widelands::CmdResetWareTargetQuantity( |
1256 | - game.get_gametime(), owner.player_number(), owner.get_economy_number(economy_), |
1257 | + game.get_gametime(), player_->player_number(), serial_, |
1258 | index)); |
1259 | } else { |
1260 | game.send_player_command(*new Widelands::CmdResetWorkerTargetQuantity( |
1261 | - game.get_gametime(), owner.player_number(), owner.get_economy_number(economy_), |
1262 | + game.get_gametime(), player_->player_number(), serial_, |
1263 | index)); |
1264 | } |
1265 | } |
1266 | |
1267 | === modified file 'src/wui/economy_options_window.h' |
1268 | --- src/wui/economy_options_window.h 2018-04-07 16:59:00 +0000 |
1269 | +++ src/wui/economy_options_window.h 2018-07-11 08:33:43 +0000 |
1270 | @@ -39,17 +39,19 @@ |
1271 | TargetWaresDisplay(UI::Panel* const parent, |
1272 | int32_t const x, |
1273 | int32_t const y, |
1274 | + Widelands::Serial serial, |
1275 | + Widelands::Player* player, |
1276 | Widelands::WareWorker type, |
1277 | - bool selectable, |
1278 | - Widelands::Economy* economy); |
1279 | + bool selectable); |
1280 | |
1281 | - void set_economy(Widelands::Economy*); |
1282 | + void set_economy(Widelands::Serial serial); |
1283 | |
1284 | protected: |
1285 | std::string info_for_ware(Widelands::DescriptionIndex const ware) override; |
1286 | |
1287 | private: |
1288 | - Widelands::Economy* economy_; |
1289 | + Widelands::Serial serial_; |
1290 | + Widelands::Player* player_; |
1291 | }; |
1292 | |
1293 | /** |
1294 | @@ -57,17 +59,19 @@ |
1295 | */ |
1296 | struct EconomyOptionsPanel : UI::Box { |
1297 | EconomyOptionsPanel(UI::Panel* parent, |
1298 | + Widelands::Serial serial, |
1299 | + Widelands::Player* player, |
1300 | bool can_act, |
1301 | - Widelands::WareWorker type, |
1302 | - Widelands::Economy* economy); |
1303 | + Widelands::WareWorker type); |
1304 | |
1305 | - void set_economy(Widelands::Economy*); |
1306 | + void set_economy(Widelands::Serial serial); |
1307 | void change_target(int amount); |
1308 | void reset_target(); |
1309 | |
1310 | private: |
1311 | + Widelands::Serial serial_; |
1312 | + Widelands::Player* player_; |
1313 | Widelands::WareWorker type_; |
1314 | - Widelands::Economy* economy_; |
1315 | bool can_act_; |
1316 | TargetWaresDisplay display_; |
1317 | }; |
1318 | @@ -75,7 +79,8 @@ |
1319 | /// Actions performed when a NoteEconomyWindow is received. |
1320 | void on_economy_note(const Widelands::NoteEconomy& note); |
1321 | |
1322 | - Widelands::Economy* economy_; |
1323 | + Widelands::Serial serial_; |
1324 | + Widelands::Player* player_; |
1325 | UI::TabPanel tabpanel_; |
1326 | EconomyOptionsPanel* ware_panel_; |
1327 | EconomyOptionsPanel* worker_panel_; |
1328 | |
1329 | === modified file 'src/wui/stock_menu.cc' |
1330 | --- src/wui/stock_menu.cc 2018-04-27 06:11:05 +0000 |
1331 | +++ src/wui/stock_menu.cc 2018-07-11 08:33:43 +0000 |
1332 | @@ -75,11 +75,9 @@ |
1333 | void StockMenu::fill_total_waresdisplay(WaresDisplay* waresdisplay, Widelands::WareWorker type) { |
1334 | waresdisplay->remove_all_warelists(); |
1335 | const Widelands::Player& player = *player_.get_player(); |
1336 | - const uint32_t nrecos = player.get_nr_economies(); |
1337 | - for (uint32_t i = 0; i < nrecos; ++i) |
1338 | - waresdisplay->add_warelist(type == Widelands::wwWARE ? |
1339 | - player.get_economy_by_number(i)->get_wares() : |
1340 | - player.get_economy_by_number(i)->get_workers()); |
1341 | + for (const auto& economy : player.economies()) { |
1342 | + waresdisplay->add_warelist(type == Widelands::wwWARE ? economy.second->get_wares() : economy.second->get_workers()); |
1343 | + } |
1344 | } |
1345 | |
1346 | /** |
1347 | @@ -89,16 +87,10 @@ |
1348 | void StockMenu::fill_warehouse_waresdisplay(WaresDisplay* waresdisplay, |
1349 | Widelands::WareWorker type) { |
1350 | waresdisplay->remove_all_warelists(); |
1351 | - const Widelands::Player& player = *player_.get_player(); |
1352 | - const uint32_t nrecos = player.get_nr_economies(); |
1353 | - for (uint32_t i = 0; i < nrecos; ++i) { |
1354 | - const std::vector<Widelands::Warehouse*>& warehouses = |
1355 | - player.get_economy_by_number(i)->warehouses(); |
1356 | - |
1357 | - for (std::vector<Widelands::Warehouse*>::const_iterator it = warehouses.begin(); |
1358 | - it != warehouses.end(); ++it) { |
1359 | - waresdisplay->add_warelist(type == Widelands::wwWARE ? (*it)->get_wares() : |
1360 | - (*it)->get_workers()); |
1361 | + for (const auto& economy : player_.player().economies()) { |
1362 | + for (const auto* warehouse: economy.second->warehouses()) { |
1363 | + waresdisplay->add_warelist(type == Widelands::wwWARE ? warehouse->get_wares() : |
1364 | + warehouse->get_workers()); |
1365 | } |
1366 | } |
1367 | } |
1368 | |
1369 | === removed file 'test/maps/Aquila.wmf/binary/bob' |
1370 | Binary files test/maps/Aquila.wmf/binary/bob 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/bob 1970-01-01 00:00:00 +0000 differ |
1371 | === removed file 'test/maps/Aquila.wmf/binary/bob_data' |
1372 | Binary files test/maps/Aquila.wmf/binary/bob_data 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/bob_data 1970-01-01 00:00:00 +0000 differ |
1373 | === removed file 'test/maps/Aquila.wmf/binary/building' |
1374 | Binary files test/maps/Aquila.wmf/binary/building 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/building 1970-01-01 00:00:00 +0000 differ |
1375 | === added file 'test/maps/Aquila.wmf/binary/exploration' |
1376 | Binary files test/maps/Aquila.wmf/binary/exploration 1970-01-01 00:00:00 +0000 and test/maps/Aquila.wmf/binary/exploration 2018-07-11 08:33:43 +0000 differ |
1377 | === removed file 'test/maps/Aquila.wmf/binary/exploration' |
1378 | Binary files test/maps/Aquila.wmf/binary/exploration 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/exploration 1970-01-01 00:00:00 +0000 differ |
1379 | === removed file 'test/maps/Aquila.wmf/binary/flag' |
1380 | Binary files test/maps/Aquila.wmf/binary/flag 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/flag 1970-01-01 00:00:00 +0000 differ |
1381 | === modified file 'test/maps/Aquila.wmf/binary/mapobjects' |
1382 | Binary files test/maps/Aquila.wmf/binary/mapobjects 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1383 | === added file 'test/maps/Aquila.wmf/binary/node_ownership' |
1384 | Binary files test/maps/Aquila.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 and test/maps/Aquila.wmf/binary/node_ownership 2018-07-11 08:33:43 +0000 differ |
1385 | === removed file 'test/maps/Aquila.wmf/binary/node_ownership' |
1386 | Binary files test/maps/Aquila.wmf/binary/node_ownership 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 differ |
1387 | === modified file 'test/maps/Aquila.wmf/binary/resource' |
1388 | Binary files test/maps/Aquila.wmf/binary/resource 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/resource 2018-07-11 08:33:43 +0000 differ |
1389 | === removed file 'test/maps/Aquila.wmf/binary/road' |
1390 | Binary files test/maps/Aquila.wmf/binary/road 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/road 1970-01-01 00:00:00 +0000 differ |
1391 | === modified file 'test/maps/Aquila.wmf/binary/terrain' |
1392 | Binary files test/maps/Aquila.wmf/binary/terrain 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
1393 | === removed file 'test/maps/Aquila.wmf/binary/ware' |
1394 | Binary files test/maps/Aquila.wmf/binary/ware 2016-08-13 18:47:51 +0000 and test/maps/Aquila.wmf/binary/ware 1970-01-01 00:00:00 +0000 differ |
1395 | === removed file 'test/maps/expedition.wmf/binary/building' |
1396 | Binary files test/maps/expedition.wmf/binary/building 2013-10-05 07:50:17 +0000 and test/maps/expedition.wmf/binary/building 1970-01-01 00:00:00 +0000 differ |
1397 | === added file 'test/maps/expedition.wmf/binary/exploration' |
1398 | Binary files test/maps/expedition.wmf/binary/exploration 1970-01-01 00:00:00 +0000 and test/maps/expedition.wmf/binary/exploration 2018-07-11 08:33:43 +0000 differ |
1399 | === removed file 'test/maps/expedition.wmf/binary/exploration' |
1400 | Binary files test/maps/expedition.wmf/binary/exploration 2013-10-05 07:50:17 +0000 and test/maps/expedition.wmf/binary/exploration 1970-01-01 00:00:00 +0000 differ |
1401 | === removed file 'test/maps/expedition.wmf/binary/flag' |
1402 | Binary files test/maps/expedition.wmf/binary/flag 2013-10-05 07:50:17 +0000 and test/maps/expedition.wmf/binary/flag 1970-01-01 00:00:00 +0000 differ |
1403 | === modified file 'test/maps/expedition.wmf/binary/mapobjects' |
1404 | Binary files test/maps/expedition.wmf/binary/mapobjects 2013-10-05 07:50:17 +0000 and test/maps/expedition.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1405 | === added file 'test/maps/expedition.wmf/binary/node_ownership' |
1406 | Binary files test/maps/expedition.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 and test/maps/expedition.wmf/binary/node_ownership 2018-07-11 08:33:43 +0000 differ |
1407 | === removed file 'test/maps/expedition.wmf/binary/node_ownership' |
1408 | Binary files test/maps/expedition.wmf/binary/node_ownership 2013-10-05 07:50:17 +0000 and test/maps/expedition.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 differ |
1409 | === modified file 'test/maps/expedition.wmf/binary/resource' |
1410 | Binary files test/maps/expedition.wmf/binary/resource 2015-04-14 19:03:11 +0000 and test/maps/expedition.wmf/binary/resource 2018-07-11 08:33:43 +0000 differ |
1411 | === removed file 'test/maps/expedition.wmf/binary/road' |
1412 | Binary files test/maps/expedition.wmf/binary/road 2013-10-05 07:50:17 +0000 and test/maps/expedition.wmf/binary/road 1970-01-01 00:00:00 +0000 differ |
1413 | === modified file 'test/maps/expedition.wmf/binary/terrain' |
1414 | Binary files test/maps/expedition.wmf/binary/terrain 2015-04-14 19:03:11 +0000 and test/maps/expedition.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
1415 | === removed file 'test/maps/lua_persistence.wmf/binary/bob' |
1416 | Binary files test/maps/lua_persistence.wmf/binary/bob 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/bob 1970-01-01 00:00:00 +0000 differ |
1417 | === removed file 'test/maps/lua_persistence.wmf/binary/building' |
1418 | Binary files test/maps/lua_persistence.wmf/binary/building 2015-04-15 10:06:45 +0000 and test/maps/lua_persistence.wmf/binary/building 1970-01-01 00:00:00 +0000 differ |
1419 | === added file 'test/maps/lua_persistence.wmf/binary/exploration' |
1420 | Binary files test/maps/lua_persistence.wmf/binary/exploration 1970-01-01 00:00:00 +0000 and test/maps/lua_persistence.wmf/binary/exploration 2018-07-11 08:33:43 +0000 differ |
1421 | === removed file 'test/maps/lua_persistence.wmf/binary/exploration' |
1422 | Binary files test/maps/lua_persistence.wmf/binary/exploration 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/exploration 1970-01-01 00:00:00 +0000 differ |
1423 | === removed file 'test/maps/lua_persistence.wmf/binary/flag' |
1424 | Binary files test/maps/lua_persistence.wmf/binary/flag 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/flag 1970-01-01 00:00:00 +0000 differ |
1425 | === modified file 'test/maps/lua_persistence.wmf/binary/mapobjects' |
1426 | Binary files test/maps/lua_persistence.wmf/binary/mapobjects 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1427 | === added file 'test/maps/lua_persistence.wmf/binary/node_ownership' |
1428 | Binary files test/maps/lua_persistence.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 and test/maps/lua_persistence.wmf/binary/node_ownership 2018-07-11 08:33:43 +0000 differ |
1429 | === removed file 'test/maps/lua_persistence.wmf/binary/node_ownership' |
1430 | Binary files test/maps/lua_persistence.wmf/binary/node_ownership 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 differ |
1431 | === modified file 'test/maps/lua_persistence.wmf/binary/resource' |
1432 | Binary files test/maps/lua_persistence.wmf/binary/resource 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/resource 2018-07-11 08:33:43 +0000 differ |
1433 | === removed file 'test/maps/lua_persistence.wmf/binary/road' |
1434 | Binary files test/maps/lua_persistence.wmf/binary/road 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/road 1970-01-01 00:00:00 +0000 differ |
1435 | === modified file 'test/maps/lua_persistence.wmf/binary/terrain' |
1436 | Binary files test/maps/lua_persistence.wmf/binary/terrain 2012-02-15 21:25:34 +0000 and test/maps/lua_persistence.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
1437 | === removed file 'test/maps/lua_testsuite.wmf/binary/bob' |
1438 | Binary files test/maps/lua_testsuite.wmf/binary/bob 2012-02-15 21:25:34 +0000 and test/maps/lua_testsuite.wmf/binary/bob 1970-01-01 00:00:00 +0000 differ |
1439 | === removed file 'test/maps/lua_testsuite.wmf/binary/building' |
1440 | Binary files test/maps/lua_testsuite.wmf/binary/building 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/building 1970-01-01 00:00:00 +0000 differ |
1441 | === added file 'test/maps/lua_testsuite.wmf/binary/exploration' |
1442 | Binary files test/maps/lua_testsuite.wmf/binary/exploration 1970-01-01 00:00:00 +0000 and test/maps/lua_testsuite.wmf/binary/exploration 2018-07-11 08:33:43 +0000 differ |
1443 | === removed file 'test/maps/lua_testsuite.wmf/binary/exploration' |
1444 | Binary files test/maps/lua_testsuite.wmf/binary/exploration 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/exploration 1970-01-01 00:00:00 +0000 differ |
1445 | === removed file 'test/maps/lua_testsuite.wmf/binary/flag' |
1446 | Binary files test/maps/lua_testsuite.wmf/binary/flag 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/flag 1970-01-01 00:00:00 +0000 differ |
1447 | === modified file 'test/maps/lua_testsuite.wmf/binary/mapobjects' |
1448 | Binary files test/maps/lua_testsuite.wmf/binary/mapobjects 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1449 | === added file 'test/maps/lua_testsuite.wmf/binary/node_ownership' |
1450 | Binary files test/maps/lua_testsuite.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 and test/maps/lua_testsuite.wmf/binary/node_ownership 2018-07-11 08:33:43 +0000 differ |
1451 | === removed file 'test/maps/lua_testsuite.wmf/binary/node_ownership' |
1452 | Binary files test/maps/lua_testsuite.wmf/binary/node_ownership 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 differ |
1453 | === modified file 'test/maps/lua_testsuite.wmf/binary/resource' |
1454 | Binary files test/maps/lua_testsuite.wmf/binary/resource 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/resource 2018-07-11 08:33:43 +0000 differ |
1455 | === removed file 'test/maps/lua_testsuite.wmf/binary/road' |
1456 | Binary files test/maps/lua_testsuite.wmf/binary/road 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/road 1970-01-01 00:00:00 +0000 differ |
1457 | === modified file 'test/maps/lua_testsuite.wmf/binary/terrain' |
1458 | Binary files test/maps/lua_testsuite.wmf/binary/terrain 2015-04-14 18:34:40 +0000 and test/maps/lua_testsuite.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
1459 | === removed file 'test/maps/plain.wmf/binary/building' |
1460 | Binary files test/maps/plain.wmf/binary/building 2014-06-20 14:38:48 +0000 and test/maps/plain.wmf/binary/building 1970-01-01 00:00:00 +0000 differ |
1461 | === added file 'test/maps/plain.wmf/binary/exploration' |
1462 | Binary files test/maps/plain.wmf/binary/exploration 1970-01-01 00:00:00 +0000 and test/maps/plain.wmf/binary/exploration 2018-07-11 08:33:43 +0000 differ |
1463 | === removed file 'test/maps/plain.wmf/binary/exploration' |
1464 | Binary files test/maps/plain.wmf/binary/exploration 2014-06-20 14:38:48 +0000 and test/maps/plain.wmf/binary/exploration 1970-01-01 00:00:00 +0000 differ |
1465 | === removed file 'test/maps/plain.wmf/binary/flag' |
1466 | Binary files test/maps/plain.wmf/binary/flag 2014-06-20 14:38:48 +0000 and test/maps/plain.wmf/binary/flag 1970-01-01 00:00:00 +0000 differ |
1467 | === modified file 'test/maps/plain.wmf/binary/mapobjects' |
1468 | Binary files test/maps/plain.wmf/binary/mapobjects 2014-06-20 14:38:48 +0000 and test/maps/plain.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1469 | === added file 'test/maps/plain.wmf/binary/node_ownership' |
1470 | Binary files test/maps/plain.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 and test/maps/plain.wmf/binary/node_ownership 2018-07-11 08:33:43 +0000 differ |
1471 | === removed file 'test/maps/plain.wmf/binary/node_ownership' |
1472 | Binary files test/maps/plain.wmf/binary/node_ownership 2014-06-20 14:38:48 +0000 and test/maps/plain.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 differ |
1473 | === modified file 'test/maps/plain.wmf/binary/resource' |
1474 | Binary files test/maps/plain.wmf/binary/resource 2014-06-22 17:09:42 +0000 and test/maps/plain.wmf/binary/resource 2018-07-11 08:33:43 +0000 differ |
1475 | === removed file 'test/maps/plain.wmf/binary/road' |
1476 | Binary files test/maps/plain.wmf/binary/road 2014-06-20 14:38:48 +0000 and test/maps/plain.wmf/binary/road 1970-01-01 00:00:00 +0000 differ |
1477 | === modified file 'test/maps/plain.wmf/binary/terrain' |
1478 | Binary files test/maps/plain.wmf/binary/terrain 2014-06-22 17:09:42 +0000 and test/maps/plain.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
1479 | === modified file 'test/maps/port_space.wmf/binary/mapobjects' |
1480 | Binary files test/maps/port_space.wmf/binary/mapobjects 2016-02-08 20:44:17 +0000 and test/maps/port_space.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1481 | === modified file 'test/maps/port_space.wmf/binary/terrain' |
1482 | Binary files test/maps/port_space.wmf/binary/terrain 2016-02-08 20:44:17 +0000 and test/maps/port_space.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
1483 | === removed file 'test/maps/ship_transportation.wmf/binary/building' |
1484 | Binary files test/maps/ship_transportation.wmf/binary/building 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/building 1970-01-01 00:00:00 +0000 differ |
1485 | === added file 'test/maps/ship_transportation.wmf/binary/exploration' |
1486 | Binary files test/maps/ship_transportation.wmf/binary/exploration 1970-01-01 00:00:00 +0000 and test/maps/ship_transportation.wmf/binary/exploration 2018-07-11 08:33:43 +0000 differ |
1487 | === removed file 'test/maps/ship_transportation.wmf/binary/exploration' |
1488 | Binary files test/maps/ship_transportation.wmf/binary/exploration 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/exploration 1970-01-01 00:00:00 +0000 differ |
1489 | === removed file 'test/maps/ship_transportation.wmf/binary/flag' |
1490 | Binary files test/maps/ship_transportation.wmf/binary/flag 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/flag 1970-01-01 00:00:00 +0000 differ |
1491 | === modified file 'test/maps/ship_transportation.wmf/binary/mapobjects' |
1492 | Binary files test/maps/ship_transportation.wmf/binary/mapobjects 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/mapobjects 2018-07-11 08:33:43 +0000 differ |
1493 | === added file 'test/maps/ship_transportation.wmf/binary/node_ownership' |
1494 | Binary files test/maps/ship_transportation.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 and test/maps/ship_transportation.wmf/binary/node_ownership 2018-07-11 08:33:43 +0000 differ |
1495 | === removed file 'test/maps/ship_transportation.wmf/binary/node_ownership' |
1496 | Binary files test/maps/ship_transportation.wmf/binary/node_ownership 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/node_ownership 1970-01-01 00:00:00 +0000 differ |
1497 | === modified file 'test/maps/ship_transportation.wmf/binary/resource' |
1498 | Binary files test/maps/ship_transportation.wmf/binary/resource 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/resource 2018-07-11 08:33:43 +0000 differ |
1499 | === removed file 'test/maps/ship_transportation.wmf/binary/road' |
1500 | Binary files test/maps/ship_transportation.wmf/binary/road 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/road 1970-01-01 00:00:00 +0000 differ |
1501 | === modified file 'test/maps/ship_transportation.wmf/binary/terrain' |
1502 | Binary files test/maps/ship_transportation.wmf/binary/terrain 2013-10-31 18:52:52 +0000 and test/maps/ship_transportation.wmf/binary/terrain 2018-07-11 08:33:43 +0000 differ |
Do you want it in Build 20?