Merge lp:~widelands-dev/widelands/lua_mapview_persistence into lp:widelands

Proposed by cghislai
Status: Merged
Merge reported by: SirVer
Merged at revision: not available
Proposed branch: lp:~widelands-dev/widelands/lua_mapview_persistence
Merge into: lp:widelands
Diff against target: 438 lines (+25/-156)
7 files modified
src/game_io/game_interactive_player_data_packet.cc (+0/-114)
src/game_io/game_interactive_player_data_packet.h (+0/-38)
src/game_io/game_loader.cc (+2/-2)
src/game_io/game_saver.cc (+2/-2)
src/scripting/lua_ui.cc (+7/-0)
src/scripting/lua_ui.h (+3/-0)
test/lua/persistence.wmf/scripting/init.lua (+11/-0)
To merge this branch: bzr merge lp:~widelands-dev/widelands/lua_mapview_persistence
Reviewer Review Type Date Requested Status
SirVer Approve
Review via email: mp+177251@code.launchpad.net

Description of the change

This is first attempt to persist the mapview. I thought that census and statistics test failed, but after merging trunk and testing again the test seems to pass now - I have no idea why.

I also tried to reproduce the bug as explained in the report, and could not trigger the crash, even on empire 2.

To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote :

I think this is the wrong approach - the LuaClass does not have any data members, so it should not persist anything at all. The MapView (c++ class) should save its data to save games one day, so that you have the same view and so on when loading.

For the Lua fix here, all clases that can get a handle again on the c++ class on a reaload should overwrite the __persists methods which basically does nothing.

The logic here is: if you have a handle to a Window (e.g. a building window of any building) in a lua variable and the game is saved what should the window persist? It cannot reopen the window again after reload (since there is no open_window(name) method), the reloaded game will not have opened the window too, so the variable would contain crap after reloading. For the MapView this is not true: you can always get a hold on the map view again, because there is always a singular one available.

mmh, I fear this was not very well explained. Do you still get what I mean?

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

I think so. but, then, the fix is already there, as I think mapview saves the state (census/statistics/viewpoint) and they are loaded.

So, in this case, the L_Mapview class shoud override __persits/__unpersist, and make sure the pointer is correct upon loading (or it is not even needed?).

Now for the other window, that would need another data paquet class, which would look for UniqueWindow registries, or buildingwindows serials, or field windows coords, and save positions and so. I am not sure for the scripted windows though.

Revision history for this message
SirVer (sirver) wrote :

>
> So, in this case, the L_Mapview class shoud override __persits/__unpersist,
> and make sure the pointer is correct upon loading (or it is not even needed?).
I think nothing is needed - just two empty functions.

> Now for the other window, that would need another data paquet class, which
> would look for UniqueWindow registries, or buildingwindows serials, or field
> windows coords, and save positions and so.
the unique windows would need special treatment. Building windows would need special treatment. And mission texts would be very difficult to get right. Starting with the unique windows would be a possiblity, but I think all of this is pretty low priority right now.

> I am not sure for the scripted windows though.

Revision history for this message
SirVer (sirver) wrote :

btw, is this ready for review too?

Revision history for this message
cghislai (charlyghislain) wrote :

Yes it is. I just needed to restore the m_panel pointer in the __unpersist method.

Revision history for this message
SirVer (sirver) wrote :

I think this is the very right approach to doing this. I am still in the USA right now, and pretty loaded, so I am still slow to review code. However one thing immediately: game_mapview_player_data_paquet should be game_mapview_player_data_packet. Same for the classes. Why did you change this to Paquet?

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

I revert the renaming interactiveplayer->mapview. I did it because I thought it would make more sense, and I didn't even notice i misspelled 'packet'. And now that I think of it, interactive_player makes more sense. Unfortunately, the diff doesn't show the content differences. The only thing that changed is that it tries to persist interactive_base fields, and only use the interactive_player pointer to persist the player number.

Speaking of which, does game.get_ibase() sometimes return null? Here the check is made, but I remember some place in the code where it assumed the pointed object exists.

Revision history for this message
SirVer (sirver) wrote :

I applied a diff of this to trunk and committed this as a new revision. That means your editing history is gone, but I didn't feel comfortable having this removed and added of the same file in the same commit - I do not trust bzr this far :).

This is therefore merged, i.e. it's content is in trunk.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'src/game_io/game_interactive_player_data_packet.cc'
2--- src/game_io/game_interactive_player_data_packet.cc 1970-01-01 00:00:00 +0000
3+++ src/game_io/game_interactive_player_data_packet.cc 2013-08-01 08:24:32 +0000
4@@ -0,0 +1,116 @@
5+/*
6+ * Copyright (C) 2002-2004, 2006-2009 by the Widelands Development Team
7+ *
8+ * This program is free software; you can redistribute it and/or
9+ * modify it under the terms of the GNU General Public License
10+ * as published by the Free Software Foundation; either version 2
11+ * of the License, or (at your option) any later version.
12+ *
13+ * This program is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+ * GNU General Public License for more details.
17+ *
18+ * You should have received a copy of the GNU General Public License
19+ * along with this program; if not, write to the Free Software
20+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21+ *
22+ */
23+
24+#include "game_io/game_interactive_player_data_packet.h"
25+
26+#include "logic/game.h"
27+#include "logic/game_data_error.h"
28+#include "logic/player.h"
29+#include "logic/tribe.h"
30+#include "logic/widelands_fileread.h"
31+#include "logic/widelands_filewrite.h"
32+#include "wui/interactive_player.h"
33+#include "wui/mapview.h"
34+#include "wui/overlay_manager.h"
35+
36+namespace Widelands {
37+
38+#define CURRENT_PACKET_VERSION 2
39+
40+
41+void Game_Interactive_Player_Data_Paquet::Read
42+ (FileSystem & fs, Game & game, Map_Map_Object_Loader *)
43+{
44+ try {
45+ FileRead fr;
46+ fr.Open(fs, "binary/interactive_player");
47+ uint16_t const packet_version = fr.Unsigned16();
48+ if (packet_version == CURRENT_PACKET_VERSION) {
49+ Player_Number player_number =
50+ fr.Player_Number8(game.map().get_nrplayers());
51+ if (not game.get_player(player_number)) {
52+ // This happens if the player, that saved the game, was a spectator
53+ // and the slot for player 1 was not used in the game.
54+ // So now we try to create an InteractivePlayer object for another
55+ // player instead.
56+ const Player_Number max = game.map().get_nrplayers();
57+ for (player_number = 1; player_number <= max; ++player_number)
58+ if (game.get_player(player_number))
59+ break;
60+ if (player_number > max)
61+ throw game_data_error(_("The game has no players!"));
62+ }
63+ int32_t const x = fr.Unsigned16();
64+ int32_t const y = fr.Unsigned16();
65+ uint32_t const display_flags = fr.Unsigned32();
66+
67+ if (Interactive_Base * const ibase = game.get_ibase()) {
68+ ibase->set_viewpoint(Point(x, y), true);
69+
70+ uint32_t const loaded_df =
71+ Interactive_Base::dfShowCensus |
72+ Interactive_Base::dfShowStatistics;
73+ uint32_t const olddf = ibase->get_display_flags();
74+ uint32_t const realdf =
75+ (olddf & ~loaded_df) | (display_flags & loaded_df);
76+ ibase->set_display_flags(realdf);
77+ }
78+ if (Interactive_Player * const ipl = game.get_ipl()) {
79+ ipl->set_player_number(player_number);
80+ }
81+ } else
82+ throw game_data_error
83+ (_("unknown/unhandled version %u"), packet_version);
84+ } catch (const _wexception & e) {
85+ throw game_data_error(_("interactive player: %s"), e.what());
86+ }
87+}
88+
89+/*
90+ * Write Function
91+ */
92+void Game_Interactive_Player_Data_Paquet::Write
93+ (FileSystem & fs, Game & game, Map_Map_Object_Saver * const)
94+{
95+ FileWrite fw;
96+
97+ // Now packet version
98+ fw.Unsigned16(CURRENT_PACKET_VERSION);
99+
100+ Interactive_Base * const ibase = game.get_ibase();
101+ Interactive_Player * const iplayer = game.get_ipl();
102+
103+ // Player number
104+ fw.Unsigned8(iplayer ? iplayer->player_number() : 1);
105+
106+ // Map Position
107+ if (ibase) {
108+ assert(0 <= ibase->get_viewpoint().x);
109+ assert(0 <= ibase->get_viewpoint().y);
110+ }
111+ fw.Unsigned16(ibase ? ibase->get_viewpoint().x : 0);
112+ fw.Unsigned16(ibase ? ibase->get_viewpoint().y : 0);
113+
114+ // Display flags
115+ fw.Unsigned32(ibase ? ibase->get_display_flags() : 0);
116+
117+ fw.Write(fs, "binary/interactive_player");
118+}
119+
120+}
121
122=== removed file 'src/game_io/game_interactive_player_data_packet.cc'
123--- src/game_io/game_interactive_player_data_packet.cc 2013-07-26 20:19:36 +0000
124+++ src/game_io/game_interactive_player_data_packet.cc 1970-01-01 00:00:00 +0000
125@@ -1,114 +0,0 @@
126-/*
127- * Copyright (C) 2002-2004, 2006-2009 by the Widelands Development Team
128- *
129- * This program is free software; you can redistribute it and/or
130- * modify it under the terms of the GNU General Public License
131- * as published by the Free Software Foundation; either version 2
132- * of the License, or (at your option) any later version.
133- *
134- * This program is distributed in the hope that it will be useful,
135- * but WITHOUT ANY WARRANTY; without even the implied warranty of
136- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
137- * GNU General Public License for more details.
138- *
139- * You should have received a copy of the GNU General Public License
140- * along with this program; if not, write to the Free Software
141- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
142- *
143- */
144-
145-#include "game_io/game_interactive_player_data_packet.h"
146-
147-#include "logic/game.h"
148-#include "logic/game_data_error.h"
149-#include "logic/player.h"
150-#include "logic/tribe.h"
151-#include "logic/widelands_fileread.h"
152-#include "logic/widelands_filewrite.h"
153-#include "wui/interactive_player.h"
154-#include "wui/mapview.h"
155-#include "wui/overlay_manager.h"
156-
157-namespace Widelands {
158-
159-#define CURRENT_PACKET_VERSION 2
160-
161-
162-void Game_Interactive_Player_Data_Packet::Read
163- (FileSystem & fs, Game & game, Map_Map_Object_Loader *)
164-{
165- try {
166- FileRead fr;
167- fr.Open(fs, "binary/interactive_player");
168- uint16_t const packet_version = fr.Unsigned16();
169- if (packet_version == CURRENT_PACKET_VERSION) {
170- Player_Number player_number =
171- fr.Player_Number8(game.map().get_nrplayers());
172- if (not game.get_player(player_number)) {
173- // This happens if the player, that saved the game, was a spectator
174- // and the slot for player 1 was not used in the game.
175- // So now we try to create an InteractivePlayer object for another
176- // player instead.
177- const Player_Number max = game.map().get_nrplayers();
178- for (player_number = 1; player_number <= max; ++player_number)
179- if (game.get_player(player_number))
180- break;
181- if (player_number > max)
182- throw game_data_error(_("The game has no players!"));
183- }
184- int32_t const x = fr.Unsigned16();
185- int32_t const y = fr.Unsigned16();
186- uint32_t const display_flags = fr.Unsigned32();
187-
188- if (Interactive_Player * const plr = game.get_ipl()) {
189- plr->set_player_number(player_number);
190-
191- plr->set_viewpoint(Point(x, y), true);
192-
193- uint32_t const loaded_df =
194- Interactive_Base::dfShowCensus |
195- Interactive_Base::dfShowStatistics;
196- uint32_t const olddf = plr->get_display_flags();
197- uint32_t const realdf =
198- (olddf & ~loaded_df) | (display_flags & loaded_df);
199- plr->set_display_flags(realdf);
200- }
201- } else
202- throw game_data_error
203- (_("unknown/unhandled version %u"), packet_version);
204- } catch (const _wexception & e) {
205- throw game_data_error(_("interactive player: %s"), e.what());
206- }
207-}
208-
209-/*
210- * Write Function
211- */
212-void Game_Interactive_Player_Data_Packet::Write
213- (FileSystem & fs, Game & game, Map_Map_Object_Saver * const)
214-{
215- FileWrite fw;
216-
217- // Now packet version
218- fw.Unsigned16(CURRENT_PACKET_VERSION);
219-
220- Interactive_Player * const plr = game.get_ipl();
221-
222- // Player number
223- fw.Unsigned8(plr ? plr->player_number() : 1);
224-
225- // Map Position
226- if (plr) {
227- assert(0 <= plr->get_viewpoint().x);
228- assert(0 <= plr->get_viewpoint().y);
229- }
230- fw.Unsigned16(plr ? plr->get_viewpoint().x : 0);
231- fw.Unsigned16(plr ? plr->get_viewpoint().y : 0);
232-
233- // Display flags
234- fw.Unsigned32(plr ? plr->get_display_flags() : 0);
235-
236- fw.Write(fs, "binary/interactive_player");
237-}
238-
239-}
240
241=== added file 'src/game_io/game_interactive_player_data_packet.h'
242--- src/game_io/game_interactive_player_data_packet.h 1970-01-01 00:00:00 +0000
243+++ src/game_io/game_interactive_player_data_packet.h 2013-08-01 08:24:32 +0000
244@@ -0,0 +1,38 @@
245+/*
246+ * Copyright (C) 2002-2004, 2006-2009 by the Widelands Development Team
247+ *
248+ * This program is free software; you can redistribute it and/or
249+ * modify it under the terms of the GNU General Public License
250+ * as published by the Free Software Foundation; either version 2
251+ * of the License, or (at your option) any later version.
252+ *
253+ * This program is distributed in the hope that it will be useful,
254+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
255+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
256+ * GNU General Public License for more details.
257+ *
258+ * You should have received a copy of the GNU General Public License
259+ * along with this program; if not, write to the Free Software
260+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
261+ *
262+ */
263+
264+#ifndef GAME_INTERACTIVE_PLAYER_DATA_PACKET_H
265+#define GAME_INTERACTIVE_PLAYER_DATA_PACKET_H
266+
267+#include "game_io/game_data_packet.h"
268+
269+namespace Widelands {
270+
271+/*
272+ * Information about the interactive player. Mostly scrollpos,
273+ * player number and so on
274+ */
275+struct Game_Interactive_Player_Data_Paquet : public Game_Data_Packet {
276+ void Read (FileSystem &, Game &, Map_Map_Object_Loader * = 0);
277+ void Write(FileSystem &, Game &, Map_Map_Object_Saver * = 0);
278+};
279+
280+}
281+
282+#endif
283
284=== removed file 'src/game_io/game_interactive_player_data_packet.h'
285--- src/game_io/game_interactive_player_data_packet.h 2013-07-26 20:19:36 +0000
286+++ src/game_io/game_interactive_player_data_packet.h 1970-01-01 00:00:00 +0000
287@@ -1,38 +0,0 @@
288-/*
289- * Copyright (C) 2002-2004, 2006-2009 by the Widelands Development Team
290- *
291- * This program is free software; you can redistribute it and/or
292- * modify it under the terms of the GNU General Public License
293- * as published by the Free Software Foundation; either version 2
294- * of the License, or (at your option) any later version.
295- *
296- * This program is distributed in the hope that it will be useful,
297- * but WITHOUT ANY WARRANTY; without even the implied warranty of
298- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
299- * GNU General Public License for more details.
300- *
301- * You should have received a copy of the GNU General Public License
302- * along with this program; if not, write to the Free Software
303- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
304- *
305- */
306-
307-#ifndef GAME_INTERACTIVE_PLAYER_DATA_PACKET_H
308-#define GAME_INTERACTIVE_PLAYER_DATA_PACKET_H
309-
310-#include "game_io/game_data_packet.h"
311-
312-namespace Widelands {
313-
314-/*
315- * Information about the interactive player. Mostly scrollpos,
316- * player number and so on
317- */
318-struct Game_Interactive_Player_Data_Packet : public Game_Data_Packet {
319- void Read (FileSystem &, Game &, Map_Map_Object_Loader * = 0);
320- void Write(FileSystem &, Game &, Map_Map_Object_Saver * = 0);
321-};
322-
323-}
324-
325-#endif
326
327=== modified file 'src/game_io/game_loader.cc'
328--- src/game_io/game_loader.cc 2013-07-27 15:09:18 +0000
329+++ src/game_io/game_loader.cc 2013-08-01 08:24:32 +0000
330@@ -24,8 +24,8 @@
331
332 #include "game_io/game_cmd_queue_data_packet.h"
333 #include "game_io/game_game_class_data_packet.h"
334+#include "game_io/game_map_data_packet.h"
335 #include "game_io/game_interactive_player_data_packet.h"
336-#include "game_io/game_map_data_packet.h"
337 #include "game_io/game_player_economies_data_packet.h"
338 #include "game_io/game_player_info_data_packet.h"
339 #include "game_io/game_preload_data_packet.h"
340@@ -126,7 +126,7 @@
341 // player.
342 if (!multiplayer) {
343 log("Game: Reading Interactive Player Data ... ");
344- {Game_Interactive_Player_Data_Packet p; p.Read(m_fs, m_game, mol);}
345+ {Game_Interactive_Player_Data_Paquet p; p.Read(m_fs, m_game, mol);}
346 log(" done\n");
347 }
348
349
350=== modified file 'src/game_io/game_saver.cc'
351--- src/game_io/game_saver.cc 2013-07-26 20:19:36 +0000
352+++ src/game_io/game_saver.cc 2013-08-01 08:24:32 +0000
353@@ -21,8 +21,8 @@
354
355 #include "game_io/game_cmd_queue_data_packet.h"
356 #include "game_io/game_game_class_data_packet.h"
357+#include "game_io/game_map_data_packet.h"
358 #include "game_io/game_interactive_player_data_packet.h"
359-#include "game_io/game_map_data_packet.h"
360 #include "game_io/game_player_economies_data_packet.h"
361 #include "game_io/game_player_info_data_packet.h"
362 #include "game_io/game_preload_data_packet.h"
363@@ -70,7 +70,7 @@
364 log(" done\n");
365
366 log("Game: Writing Interactive Player Data ... ");
367- {Game_Interactive_Player_Data_Packet p; p.Write(m_fs, m_game, mos);}
368+ {Game_Interactive_Player_Data_Paquet p; p.Write(m_fs, m_game, mos);}
369 log(" done\n");
370 }
371
372
373=== modified file 'src/scripting/lua_ui.cc'
374--- src/scripting/lua_ui.cc 2013-07-26 20:19:36 +0000
375+++ src/scripting/lua_ui.cc 2013-08-01 08:24:32 +0000
376@@ -25,6 +25,7 @@
377 #include "logic/player.h"
378 #include "scripting/c_utils.h"
379 #include "scripting/lua_map.h"
380+#include "scripting/luna.h"
381 #include "upcast.h"
382 #include "wui/interactive_player.h"
383
384@@ -525,6 +526,12 @@
385 L_Panel(get_egbase(L).get_ibase()) {
386 }
387
388+void L_MapView::__unpersist(lua_State* L)
389+{
390+ Widelands::Game & game = get_game(L);
391+ m_panel = game.get_ibase();
392+}
393+
394
395 /*
396 * Properties
397
398=== modified file 'src/scripting/lua_ui.h'
399--- src/scripting/lua_ui.h 2013-07-26 20:19:36 +0000
400+++ src/scripting/lua_ui.h 2013-08-01 08:24:32 +0000
401@@ -179,6 +179,9 @@
402 L_MapView(lua_State * L);
403 virtual ~L_MapView() {}
404
405+ virtual void __persist(lua_State * L) {}
406+ virtual void __unpersist(lua_State * L);
407+
408 /*
409 * Properties
410 */
411
412=== modified file 'test/lua/persistence.wmf/scripting/init.lua'
413--- test/lua/persistence.wmf/scripting/init.lua 2013-07-19 17:07:41 +0000
414+++ test/lua/persistence.wmf/scripting/init.lua 2013-08-01 08:24:32 +0000
415@@ -51,6 +51,12 @@
416 map:get_field(10,10), map:get_field(10,10), map:get_field(10,11)
417 }
418
419+ mapview = wl.ui.MapView()
420+ mapview.viewpoint_x = 10
421+ mapview.viewpoint_y = 40
422+ mapview.statistics = false
423+ mapview.census = true
424+
425 game:save("lua_persistence")
426 print("Save requested\n");
427
428@@ -121,6 +127,11 @@
429 assert_equal(2, myset.size)
430 assert_true(myset:contains(map:get_field(10,10)))
431 assert_true(myset:contains(map:get_field(10,11)))
432+ mapview = wl.ui.MapView()
433+ assert_equal(mapview.viewpoint_x, 10)
434+ assert_equal(mapview.viewpoint_y, 40)
435+ assert_equal(false, mapview.statistics)
436+ assert_equal(true, mapview.census)
437
438 print("################### ALL TEST PASS!")
439

Subscribers

People subscribed via source and target branches

to status/vote changes: