Merge lp:~widelands-dev/widelands/log_messages into lp:widelands
- log_messages
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 6727 |
Proposed branch: | lp:~widelands-dev/widelands/log_messages |
Merge into: | lp:widelands |
Diff against target: |
1271 lines (+343/-161) 35 files modified
src/chat.cc (+100/-1) src/chat.h (+1/-6) src/debugconsole.cc (+0/-4) src/gamecontroller.cc (+2/-30) src/log.h (+0/-1) src/logic/game.cc (+3/-1) src/logic/game.h (+4/-1) src/logic/immovable.cc (+1/-0) src/logic/notification.h (+1/-2) src/logic/player.cc (+1/-1) src/logmessage.h (+41/-0) src/network/internet_gaming.cc (+0/-9) src/network/internet_gaming.h (+0/-3) src/network/netclient.cc (+0/-9) src/network/netclient.h (+1/-1) src/network/nethost.cc (+0/-7) src/save_handler.cc (+8/-11) src/ui_basic/panel.h (+1/-1) src/ui_basic/unique_window.cc (+2/-2) src/ui_basic/window.cc (+15/-6) src/ui_basic/window.h (+1/-0) src/wlapplication.cc (+3/-1) src/wui/chatoverlay.cc (+86/-18) src/wui/chatoverlay.h (+3/-0) src/wui/game_main_menu_save_game.cc (+11/-9) src/wui/game_main_menu_save_game.h (+3/-1) src/wui/gamechatpanel.cc (+2/-1) src/wui/interactive_base.cc (+14/-0) src/wui/interactive_base.h (+12/-0) src/wui/interactive_gamebase.cc (+3/-4) src/wui/interactive_gamebase.h (+4/-3) src/wui/interactive_player.cc (+3/-9) src/wui/interactive_player.h (+0/-3) src/wui/interactive_spectator.cc (+9/-11) src/wui/watchwindow.cc (+8/-5) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/log_messages |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
SirVer | Needs Information | ||
Review via email: mp+177712@code.launchpad.net |
Commit message
Description of the change
This is a rework of the use of chat messages to log informationnal messages.
- A new LogMessage struct was created appart of ChatMessage.
- The interactivegamebase is a NoteSender of LogMessage. His log_message() method will send the message to all receivers. The ChatOverlay has also moved in a protected field in this class. This was required so it is initialized before the toolbar box, so that chat messages are displayed below it.
- The ChatOverlay receives ChatMessage as well as LogMessage notes. It keeps the log message in a local vector. It displays both chat and logs mixed and in chronological order. It also uses the new renderer to display them.
- All send_local methods are removed, and it was quite a hack anyway. Several classes do not extend ChatProvider anymore.
Some things to review:
- bug 1206712 can be triggered quite easily using this branch.
- I didn't manage to draw a semi-transparent background below chat messages, it doesn't seem to work as expected?
cghislai (charlyghislain) wrote : | # |
SirVer (sirver) wrote : | # |
Changes sound nice, maybe I can get it some more code reviews tonight before bed and after work.
SirVer (sirver) wrote : | # |
I'll definitely review this this week - I am then all caught up on reviews afaik.
SirVer (sirver) wrote : | # |
Review done. Very little comments - looks very good to me. Makes the code much easier to understand and gets rid of a lot of redundancies. I wondered if it would not be possible to do much of what you've done with composition instead of inheritance though. The multiple inheritance we have all of the place there is really horrible.
One approach could also be boost::signals to install handlers for chat messages and then there are either set or not. What do you think about this?
Feel free to merge when you are happy with this though - I will not review much code in the next two weeks.
cghislai (charlyghislain) wrote : | # |
I completely agree with using composition over inheritance. However, the inheritance you pointed here were not completely related to the log_message thing and it requires more refactoring than expected to change them.
So I think I will open a bug report so that I won't forget to check that later, and that I will merge this as it will allow me to get a bit further with the fh1 branch.
SirVer (sirver) wrote : | # |
perfectly acceptable solution for now. This branch made the code nicer to look at and easier to understand for sure. Thanks for your work as always!
Preview Diff
1 | === modified file 'src/chat.cc' |
2 | --- src/chat.cc 2013-07-26 05:57:03 +0000 |
3 | +++ src/chat.cc 2013-08-21 08:32:15 +0000 |
4 | @@ -23,7 +23,7 @@ |
5 | |
6 | using namespace Widelands; |
7 | |
8 | -std::string ChatMessage::toPrintable() const |
9 | +std::string ChatMessage::toOldRichText() const |
10 | { |
11 | std::string message = "<p font-color=#33ff33 font-size=9>"; |
12 | |
13 | @@ -120,6 +120,105 @@ |
14 | return message + "<br></p>"; |
15 | } |
16 | |
17 | +std::string ChatMessage::toPrintable() const |
18 | +{ |
19 | + std::string message = "<p><font color=33ff33 size=9>"; |
20 | + |
21 | + // Escape richtext characters |
22 | + // The goal of this code is two-fold: |
23 | + // 1. Assuming an honest game host, we want to prevent the ability of |
24 | + // clients to use richtext. |
25 | + // 2. Assuming a malicious host or meta server, we want to reduce the |
26 | + // likelihood that a bug in the richtext renderer can be exploited, |
27 | + // by restricting the set of allowed richtext commands. |
28 | + // Most notably, images are not allowed in richtext at all. |
29 | + // |
30 | + // Note that we do want host and meta server to send some richtext code, |
31 | + // as the ability to send formatted commands is nice for the usability |
32 | + // of meta server and dedicated servers, so we're treading a bit of a |
33 | + // fine line here. |
34 | + std::string sanitized; |
35 | + for (std::string::size_type pos = 0; pos < msg.size(); ++pos) { |
36 | + if (msg[pos] == '<') { |
37 | + if (playern < 0) { |
38 | + static const std::string good1 = "</p><p"; |
39 | + static const std::string good2 = "<br>"; |
40 | + if (!msg.compare(pos, good1.size(), good1)) { |
41 | + std::string::size_type nextclose = msg.find('>', pos + good1.size()); |
42 | + if |
43 | + (nextclose != std::string::npos && |
44 | + (nextclose == pos + good1.size() || msg[pos + good1.size()] == ' ')) |
45 | + { |
46 | + sanitized += good1; |
47 | + pos += good1.size() - 1; |
48 | + continue; |
49 | + } |
50 | + } else if (!msg.compare(pos, good2.size(), good2)) { |
51 | + sanitized += good2; |
52 | + pos += good2.size() - 1; |
53 | + continue; |
54 | + } |
55 | + } |
56 | + |
57 | + sanitized += "<"; |
58 | + } else { |
59 | + sanitized += msg[pos]; |
60 | + } |
61 | + } |
62 | + |
63 | + // time calculation |
64 | + char ts[13]; |
65 | + strftime(ts, sizeof(ts), "[%H:%M] ", localtime(&time)); |
66 | + message += ts; |
67 | + |
68 | + message += "</font><font size=14 face=DejaVuSerif color="; |
69 | + message += color(); |
70 | + |
71 | + if (recipient.size() && sender.size()) { |
72 | + // Personal message handling |
73 | + if (sanitized.compare(0, 3, "/me")) { |
74 | + message += " bold=1>"; |
75 | + message += sender; |
76 | + message += " @ "; |
77 | + message += recipient; |
78 | + message += ":</font><font size=14 face=DejaVuSerif shadow=1 color=eeeeee> "; |
79 | + message += sanitized; |
80 | + } else { |
81 | + message += ">@"; |
82 | + message += recipient; |
83 | + message += " \\> </font><font size=14"; |
84 | + message += " face=DejaVuSerif color="; |
85 | + message += color(); |
86 | + message += " italic=1 shadow=1> "; |
87 | + message += sender; |
88 | + message += sanitized.substr(3); |
89 | + } |
90 | + } else { |
91 | + // Normal messages handling |
92 | + if (not sanitized.compare(0, 3, "/me")) { |
93 | + message += " italic=1>-\\> "; |
94 | + if (sender.size()) |
95 | + message += sender; |
96 | + else |
97 | + message += "***"; |
98 | + message += sanitized.substr(3); |
99 | + } else if (sender.size()) { |
100 | + message += " bold=1>"; |
101 | + message += sender; |
102 | + message += ":</font><font size=14 face=DejaVuSerif shadow=1 color=eeeeee> "; |
103 | + message += sanitized; |
104 | + } else { |
105 | + message += " bold=1>*** "; |
106 | + message += sanitized; |
107 | + } |
108 | + } |
109 | + |
110 | + // return the formated message |
111 | + return message + "</font><br></p>"; |
112 | +} |
113 | + |
114 | + |
115 | + |
116 | std::string ChatMessage::toPlainString() const |
117 | { |
118 | return sender + ": " + msg; |
119 | |
120 | === modified file 'src/chat.h' |
121 | --- src/chat.h 2013-07-26 19:16:51 +0000 |
122 | +++ src/chat.h 2013-08-21 08:32:15 +0000 |
123 | @@ -73,6 +73,7 @@ |
124 | * \return a richtext string that can be displayed to the user. |
125 | */ |
126 | std::string toPrintable() const; |
127 | + std::string toOldRichText() const; |
128 | |
129 | /** |
130 | * \return a plain string containing the sender + message. |
131 | @@ -106,12 +107,6 @@ |
132 | virtual void send(const std::string &) = 0; |
133 | |
134 | /** |
135 | - * Sends the given message to the local player only |
136 | - * This may be used to display useful log messages. |
137 | - */ |
138 | - virtual void send_local(const std::string &) = 0; |
139 | - |
140 | - /** |
141 | * \return a (chronological) list of received chat messages. |
142 | * This list need not be stable or monotonic. In other words, |
143 | * subsequent calls to this functions may return a smaller or |
144 | |
145 | === modified file 'src/debugconsole.cc' |
146 | --- src/debugconsole.cc 2013-07-26 19:16:51 +0000 |
147 | +++ src/debugconsole.cc 2013-08-21 08:32:15 +0000 |
148 | @@ -86,10 +86,6 @@ |
149 | it->second(arg); |
150 | } |
151 | |
152 | - void send_local(const std::string& msg) { |
153 | - send(msg); |
154 | - } |
155 | - |
156 | const std::vector<ChatMessage> & getMessages() const |
157 | { |
158 | return messages; |
159 | |
160 | === modified file 'src/gamecontroller.cc' |
161 | --- src/gamecontroller.cc 2013-08-01 10:51:41 +0000 |
162 | +++ src/gamecontroller.cc 2013-08-21 08:32:15 +0000 |
163 | @@ -19,7 +19,6 @@ |
164 | |
165 | #include "gamecontroller.h" |
166 | |
167 | -#include "chat.h" |
168 | #include "computer_player.h" |
169 | #include "logic/game.h" |
170 | #include "logic/player.h" |
171 | @@ -27,9 +26,8 @@ |
172 | #include "logic/playersmanager.h" |
173 | #include "profile/profile.h" |
174 | #include "wlapplication.h" |
175 | -#include "wui/interactive_player.h" |
176 | |
177 | -struct SinglePlayerGameController : public GameController, public ChatProvider { |
178 | +struct SinglePlayerGameController : public GameController { |
179 | SinglePlayerGameController |
180 | (Widelands::Game &, bool useai, Widelands::Player_Number local); |
181 | ~SinglePlayerGameController(); |
182 | @@ -46,10 +44,6 @@ |
183 | void setPaused(bool paused); |
184 | void report_result(uint8_t player, Widelands::PlayerEndResult result, const std::string & info); |
185 | |
186 | - // Chat provider implementation |
187 | - void send(const std::string & msg); |
188 | - void send_local(const std::string & msg); |
189 | - const std::vector<ChatMessage> & getMessages() const; |
190 | private: |
191 | Widelands::Game & m_game; |
192 | bool m_useai; |
193 | @@ -60,15 +54,13 @@ |
194 | uint32_t m_player_cmdserial; |
195 | Widelands::Player_Number m_local; |
196 | std::vector<Computer_Player *> m_computerplayers; |
197 | - std::vector<ChatMessage> m_chatmessages; |
198 | }; |
199 | |
200 | SinglePlayerGameController::SinglePlayerGameController |
201 | (Widelands::Game & game, |
202 | bool const useai, |
203 | Widelands::Player_Number const local) |
204 | - : ChatProvider(), |
205 | - m_game (game), |
206 | + : m_game (game), |
207 | m_useai (useai), |
208 | m_lastframe (WLApplication::get()->get_time()), |
209 | m_time (m_game.get_gametime()), |
210 | @@ -178,31 +170,11 @@ |
211 | m_game.player_manager()->add_player_end_status(pes); |
212 | } |
213 | |
214 | -void SinglePlayerGameController::send_local(const std::string& msg) |
215 | -{ |
216 | - ChatMessage c; |
217 | - c.msg = msg; |
218 | - c.time = time(0); |
219 | - m_chatmessages.push_back(c); |
220 | - ChatProvider::send(c); |
221 | -} |
222 | - |
223 | -void SinglePlayerGameController::send(const std::string& /* msg */) |
224 | -{ |
225 | - log("SinglePlayerGameController:: Cannot send chat messages in single player game!"); |
226 | -} |
227 | - |
228 | -const std::vector< ChatMessage >& SinglePlayerGameController::getMessages() const |
229 | -{ |
230 | - return m_chatmessages; |
231 | -} |
232 | - |
233 | GameController * GameController::createSinglePlayer |
234 | (Widelands::Game & game, |
235 | bool const cpls, |
236 | Widelands::Player_Number const local) |
237 | { |
238 | SinglePlayerGameController* spgc = new SinglePlayerGameController(game, cpls, local); |
239 | - game.get_ipl()->set_chat_provider(*spgc); |
240 | return spgc; |
241 | } |
242 | |
243 | === modified file 'src/log.h' |
244 | --- src/log.h 2013-07-18 06:31:11 +0000 |
245 | +++ src/log.h 2013-08-21 08:32:15 +0000 |
246 | @@ -53,5 +53,4 @@ |
247 | |
248 | extern bool g_verbose; |
249 | |
250 | - |
251 | #endif |
252 | |
253 | === modified file 'src/logic/game.cc' |
254 | --- src/logic/game.cc 2013-08-13 19:43:52 +0000 |
255 | +++ src/logic/game.cc 2013-08-21 08:32:15 +0000 |
256 | @@ -472,8 +472,10 @@ |
257 | * \note loader_ui can be nullptr, if this is run as dedicated server. |
258 | */ |
259 | bool Game::run |
260 | - (UI::ProgressWindow * loader_ui, Start_Game_Type const start_game_type) |
261 | + (UI::ProgressWindow * loader_ui, Start_Game_Type const start_game_type, |
262 | + bool replay) |
263 | { |
264 | + m_replay = replay; |
265 | postload(); |
266 | |
267 | if (start_game_type != Loaded) { |
268 | |
269 | === modified file 'src/logic/game.h' |
270 | --- src/logic/game.h 2013-08-07 12:32:36 +0000 |
271 | +++ src/logic/game.h 2013-08-21 08:32:15 +0000 |
272 | @@ -105,7 +105,7 @@ |
273 | bool run_splayer_scenario_direct(char const * mapname); |
274 | bool run_load_game (std::string filename); |
275 | enum Start_Game_Type {NewSPScenario, NewNonScenario, Loaded, NewMPScenario}; |
276 | - bool run(UI::ProgressWindow * loader_ui, Start_Game_Type); |
277 | + bool run(UI::ProgressWindow * loader_ui, Start_Game_Type, bool replay = false); |
278 | |
279 | virtual void postload(); |
280 | |
281 | @@ -190,6 +190,8 @@ |
282 | |
283 | const std::string & get_win_condition_displayname() {return m_win_condition_displayname;} |
284 | |
285 | + bool is_replay() const {return m_replay;}; |
286 | + |
287 | private: |
288 | void SyncReset(); |
289 | |
290 | @@ -254,6 +256,7 @@ |
291 | |
292 | /// For save games and statistics generation |
293 | std::string m_win_condition_displayname; |
294 | + bool m_replay; |
295 | }; |
296 | |
297 | inline Coords Game::random_location(Coords location, uint8_t radius) { |
298 | |
299 | === modified file 'src/logic/immovable.cc' |
300 | --- src/logic/immovable.cc 2013-08-07 04:01:58 +0000 |
301 | +++ src/logic/immovable.cc 2013-08-21 08:32:15 +0000 |
302 | @@ -21,6 +21,7 @@ |
303 | |
304 | #include <boost/format.hpp> |
305 | #include <config.h> |
306 | + |
307 | #include <cstdio> |
308 | |
309 | #include "container_iterate.h" |
310 | |
311 | === modified file 'src/logic/notification.h' |
312 | --- src/logic/notification.h 2013-08-10 16:57:13 +0000 |
313 | +++ src/logic/notification.h 2013-08-21 08:32:15 +0000 |
314 | @@ -54,8 +54,7 @@ |
315 | (*m_links.rbegin())->disconnect(*this); |
316 | } |
317 | |
318 | -protected: |
319 | - void send(const T & note) { |
320 | + void send(const T & note) const { |
321 | container_iterate_const(Links, m_links, i) |
322 | (*i.current)->receive(note); |
323 | } |
324 | |
325 | === modified file 'src/logic/player.cc' |
326 | --- src/logic/player.cc 2013-08-17 08:39:21 +0000 |
327 | +++ src/logic/player.cc 2013-08-21 08:32:15 +0000 |
328 | @@ -115,7 +115,7 @@ |
329 | assert(former_buildings && former_buildings->empty()); |
330 | former_buildings->push_back(bi); |
331 | |
332 | - while (true) { |
333 | + for (;;) { |
334 | Widelands::Building_Index oldest_idx = former_buildings->front(); |
335 | const Widelands::Building_Descr * oldest = tribe_descr.get_building_descr(oldest_idx); |
336 | if (!oldest->is_enhanced()) { |
337 | |
338 | === added file 'src/logmessage.h' |
339 | --- src/logmessage.h 1970-01-01 00:00:00 +0000 |
340 | +++ src/logmessage.h 2013-08-21 08:32:15 +0000 |
341 | @@ -0,0 +1,41 @@ |
342 | +/* |
343 | + * Copyright (C) 2008-2011 by the Widelands Development Team |
344 | + * |
345 | + * This program is free software; you can redistribute it and/or |
346 | + * modify it under the terms of the GNU General Public License |
347 | + * as published by the Free Software Foundation; either version 2 |
348 | + * of the License, or (at your option) any later version. |
349 | + * |
350 | + * This program is distributed in the hope that it will be useful, |
351 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
352 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
353 | + * GNU General Public License for more details. |
354 | + * |
355 | + * You should have received a copy of the GNU General Public License |
356 | + * along with this program; if not, write to the Free Software |
357 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
358 | + * |
359 | + */ |
360 | + |
361 | +#ifndef LOGMESSAGE_H |
362 | +#define LOGMESSAGE_H |
363 | + |
364 | +#include <string> |
365 | + |
366 | + |
367 | +/** |
368 | + * Represents one log message. |
369 | + */ |
370 | +struct LogMessage { |
371 | + /** |
372 | + * The (real-)time at which the message was received. |
373 | + */ |
374 | + time_t time; |
375 | + |
376 | + /** |
377 | + * The actual chat message |
378 | + */ |
379 | + std::string msg; |
380 | +}; |
381 | + |
382 | +#endif |
383 | |
384 | === modified file 'src/network/internet_gaming.cc' |
385 | --- src/network/internet_gaming.cc 2013-07-29 18:41:11 +0000 |
386 | +++ src/network/internet_gaming.cc 2013-08-21 08:32:15 +0000 |
387 | @@ -768,15 +768,6 @@ |
388 | s.send(m_sock); |
389 | } |
390 | |
391 | -void InternetGaming::send_local(const std::string& msg) |
392 | -{ |
393 | - ChatMessage c; |
394 | - c.msg = msg; |
395 | - c.time = time(0); |
396 | - messages.push_back(c); |
397 | - ChatProvider::send(c); |
398 | -} |
399 | - |
400 | /** |
401 | * \returns the boolean value of a string received from the metaserver. |
402 | * If conversion fails, it throws a \ref warning |
403 | |
404 | === modified file 'src/network/internet_gaming.h' |
405 | --- src/network/internet_gaming.h 2013-07-26 20:19:36 +0000 |
406 | +++ src/network/internet_gaming.h 2013-08-21 08:32:15 +0000 |
407 | @@ -113,9 +113,6 @@ |
408 | // ChatProvider: sends a message via the metaserver. |
409 | void send(const std::string &); |
410 | |
411 | - // ChatProvider: sends local messages |
412 | - void send_local(const std::string &); |
413 | - |
414 | /// ChatProvider: adds the message to the message list and calls parent. |
415 | void receive(const ChatMessage & msg) {messages.push_back(msg); ChatProvider::send(msg);} |
416 | |
417 | |
418 | === modified file 'src/network/netclient.cc' |
419 | --- src/network/netclient.cc 2013-08-01 10:51:41 +0000 |
420 | +++ src/network/netclient.cc 2013-08-21 08:32:15 +0000 |
421 | @@ -640,15 +640,6 @@ |
422 | s.send(d->sock); |
423 | } |
424 | |
425 | -void NetClient::send_local(const std::string& msg) |
426 | -{ |
427 | - ChatMessage c; |
428 | - c.msg = msg; |
429 | - c.time = time(0); |
430 | - d->chatmessages.push_back(c); |
431 | - ChatProvider::send(c); |
432 | -} |
433 | - |
434 | const std::vector<ChatMessage> & NetClient::getMessages() const |
435 | { |
436 | return d->chatmessages; |
437 | |
438 | === modified file 'src/network/netclient.h' |
439 | --- src/network/netclient.h 2013-08-01 10:51:41 +0000 |
440 | +++ src/network/netclient.h 2013-08-21 08:32:15 +0000 |
441 | @@ -27,6 +27,7 @@ |
442 | |
443 | struct NetClientImpl; |
444 | |
445 | +//FIXME Use composition instead of inheritance |
446 | /** |
447 | * NetClient manages the lifetime of a network game in which this computer |
448 | * participates as a client. |
449 | @@ -94,7 +95,6 @@ |
450 | |
451 | // ChatProvider interface |
452 | void send(const std::string & msg); |
453 | - void send_local(const std::string & msg); |
454 | const std::vector<ChatMessage> & getMessages() const; |
455 | |
456 | private: |
457 | |
458 | === modified file 'src/network/nethost.cc' |
459 | --- src/network/nethost.cc 2013-08-06 10:40:54 +0000 |
460 | +++ src/network/nethost.cc 2013-08-21 08:32:15 +0000 |
461 | @@ -498,13 +498,6 @@ |
462 | h->send(c); |
463 | } |
464 | |
465 | - void send_local(const std::string & msg) { |
466 | - ChatMessage c; |
467 | - c.time = time(0); |
468 | - c.msg = msg; |
469 | - receive(c); |
470 | - } |
471 | - |
472 | const std::vector<ChatMessage> & getMessages() const { |
473 | return messages; |
474 | } |
475 | |
476 | === modified file 'src/save_handler.cc' |
477 | --- src/save_handler.cc 2013-08-01 10:51:41 +0000 |
478 | +++ src/save_handler.cc 2013-08-21 08:32:15 +0000 |
479 | @@ -25,9 +25,10 @@ |
480 | #include "log.h" |
481 | #include "logic/game.h" |
482 | #include "profile/profile.h" |
483 | +#include "upcast.h" |
484 | #include "wexception.h" |
485 | #include "wlapplication.h" |
486 | -#include "wui/interactive_player.h" |
487 | +#include "wui/interactive_base.h" |
488 | |
489 | using Widelands::Game_Saver; |
490 | |
491 | @@ -41,6 +42,9 @@ |
492 | if (!m_allow_saving) { |
493 | return; |
494 | } |
495 | + if (game.is_replay()) { |
496 | + return; |
497 | + } |
498 | |
499 | if (m_save_requested) { |
500 | if (!m_save_filename.empty()) { |
501 | @@ -68,10 +72,7 @@ |
502 | |
503 | // TODO: defer saving to next tick so that this message is shown |
504 | // before the actual save, or put the saving logic in another thread |
505 | - if (game.get_igbase()) { |
506 | - game.get_igbase()->get_chat_provider()->send_local |
507 | - (_("Saving game...")); |
508 | - } |
509 | + game.get_ibase()->log_message(_("Saving game...")); |
510 | |
511 | // save the game |
512 | const std::string complete_filename = create_file_name(get_base_dir(), filename); |
513 | @@ -90,8 +91,7 @@ |
514 | std::string error; |
515 | if (!save_game(game, complete_filename, &error)) { |
516 | log("Autosave: ERROR! - %s\n", error.c_str()); |
517 | - game.get_ipl()->get_chat_provider()->send_local |
518 | - (_("Saving failed!")); |
519 | + game.get_ibase()->log_message(_("Saving failed!")); |
520 | |
521 | // if backup file was created, move it back |
522 | if (backup_filename.length() > 0) { |
523 | @@ -110,10 +110,7 @@ |
524 | } |
525 | |
526 | log("Autosave: save took %d ms\n", m_last_saved_time - realtime); |
527 | - if (game.get_igbase()) { |
528 | - game.get_igbase()->get_chat_provider()->send_local |
529 | - (_("Game saved")); |
530 | - } |
531 | + game.get_ibase()->log_message(_("Game saved")); |
532 | } |
533 | |
534 | /** |
535 | |
536 | === modified file 'src/ui_basic/panel.h' |
537 | --- src/ui_basic/panel.h 2013-08-02 18:36:03 +0000 |
538 | +++ src/ui_basic/panel.h 2013-08-21 08:32:15 +0000 |
539 | @@ -235,7 +235,7 @@ |
540 | std::string ui_fn(); |
541 | |
542 | protected: |
543 | - void die(); |
544 | + virtual void die(); |
545 | bool keyboard_free() {return !(_focus);} |
546 | |
547 | virtual void update_desired_size(); |
548 | |
549 | === modified file 'src/ui_basic/unique_window.cc' |
550 | --- src/ui_basic/unique_window.cc 2013-07-26 20:19:36 +0000 |
551 | +++ src/ui_basic/unique_window.cc 2013-08-21 08:32:15 +0000 |
552 | @@ -42,7 +42,7 @@ |
553 | */ |
554 | void UniqueWindow::Registry::destroy() { |
555 | if (window) { |
556 | - delete window; |
557 | + window->die(); |
558 | } |
559 | } |
560 | |
561 | @@ -51,7 +51,7 @@ |
562 | */ |
563 | void UniqueWindow::Registry::toggle() { |
564 | if (window) { |
565 | - delete window; |
566 | + window->die(); |
567 | } else { |
568 | constr(); |
569 | } |
570 | |
571 | === modified file 'src/ui_basic/window.cc' |
572 | --- src/ui_basic/window.cc 2013-08-01 14:26:47 +0000 |
573 | +++ src/ui_basic/window.cc 2013-08-21 08:32:15 +0000 |
574 | @@ -453,12 +453,7 @@ |
575 | grab_mouse(true); |
576 | } else if (btn == SDL_BUTTON_RIGHT) { |
577 | play_click(); |
578 | - if (is_modal()) |
579 | - end_modal(0); |
580 | - else |
581 | - delete this; // is this 100% safe? |
582 | - // FIXME No, at least provide a flag for making a window unclosable and |
583 | - // FIXME provide a callback. |
584 | + die(); |
585 | } |
586 | |
587 | return true; |
588 | @@ -490,6 +485,20 @@ |
589 | return true; |
590 | } |
591 | |
592 | +/** |
593 | + * Close the window. Overwrite this virtual method if you want |
594 | + * to take some action before the window is destroyed, or to |
595 | + * prevent it |
596 | + */ |
597 | +void Window::die() |
598 | +{ |
599 | + if (is_modal()) { |
600 | + end_modal(0); |
601 | + } else { |
602 | + Panel::die(); |
603 | + } |
604 | +} |
605 | + |
606 | |
607 | void Window::restore() { |
608 | assert(_is_minimal); |
609 | |
610 | === modified file 'src/ui_basic/window.h' |
611 | --- src/ui_basic/window.h 2013-07-26 20:19:36 +0000 |
612 | +++ src/ui_basic/window.h 2013-08-21 08:32:15 +0000 |
613 | @@ -90,6 +90,7 @@ |
614 | bool handle_tooltip(); |
615 | |
616 | protected: |
617 | + virtual void die(); |
618 | virtual void layout(); |
619 | virtual void update_desired_size(); |
620 | |
621 | |
622 | === modified file 'src/wlapplication.cc' |
623 | --- src/wlapplication.cc 2013-08-02 10:45:32 +0000 |
624 | +++ src/wlapplication.cc 2013-08-21 08:32:15 +0000 |
625 | @@ -2226,7 +2226,9 @@ |
626 | game.set_write_replay(false); |
627 | ReplayGameController rgc(game, m_filename); |
628 | |
629 | - game.run(&loaderUI, Widelands::Game::Loaded); |
630 | + game.save_handler().set_allow_saving(false); |
631 | + |
632 | + game.run(&loaderUI, Widelands::Game::Loaded, true); |
633 | } catch (const std::exception & e) { |
634 | log("Fatal Exception: %s\n", e.what()); |
635 | emergency_save(game); |
636 | |
637 | === modified file 'src/wui/chatoverlay.cc' |
638 | --- src/wui/chatoverlay.cc 2013-07-26 20:19:36 +0000 |
639 | +++ src/wui/chatoverlay.cc 2013-08-21 08:32:15 +0000 |
640 | @@ -20,8 +20,9 @@ |
641 | #include "wui/chatoverlay.h" |
642 | |
643 | #include "chat.h" |
644 | +#include "graphic/font_handler1.h" |
645 | #include "graphic/rendertarget.h" |
646 | -#include "graphic/richtext.h" |
647 | +#include "logmessage.h" |
648 | #include "profile/profile.h" |
649 | |
650 | /** |
651 | @@ -30,7 +31,8 @@ |
652 | static const int32_t CHAT_DISPLAY_TIME = 10; |
653 | static const uint32_t MARGIN = 2; |
654 | |
655 | -struct ChatOverlay::Impl : Widelands::NoteReceiver<ChatMessage> { |
656 | +struct ChatOverlay::Impl : Widelands::NoteReceiver<ChatMessage>, |
657 | + Widelands::NoteReceiver<LogMessage> { |
658 | bool transparent; |
659 | ChatProvider * chat; |
660 | bool havemessages; |
661 | @@ -39,12 +41,16 @@ |
662 | time_t oldest; |
663 | |
664 | /// Layouted message list |
665 | - UI::RichText rt; |
666 | + std::string all_text; |
667 | + |
668 | + /// Log messages |
669 | + std::vector<LogMessage> log_messages; |
670 | |
671 | Impl() : transparent(false), chat(0), havemessages(false), oldest(0) {} |
672 | |
673 | void recompute(); |
674 | virtual void receive(const ChatMessage & note); |
675 | + virtual void receive(const LogMessage & note); |
676 | }; |
677 | |
678 | ChatOverlay::ChatOverlay |
679 | @@ -56,8 +62,6 @@ |
680 | m->transparent = s.get_bool("transparent_chat", true); |
681 | |
682 | set_think(true); |
683 | - m->rt.set_width(w - 2 * MARGIN); |
684 | - m->rt.set_background_color(RGBColor(50, 50, 50)); |
685 | } |
686 | |
687 | ChatOverlay::~ChatOverlay() |
688 | @@ -67,10 +71,20 @@ |
689 | void ChatOverlay::setChatProvider(ChatProvider & chat) |
690 | { |
691 | m->chat = &chat; |
692 | - m->connect(chat); |
693 | + Widelands::NoteReceiver<ChatMessage>* cmr |
694 | + = dynamic_cast<Widelands::NoteReceiver<ChatMessage>*>(m.get()); |
695 | + cmr->connect(chat); |
696 | m->recompute(); |
697 | } |
698 | |
699 | +void ChatOverlay::setLogProvider(Widelands::NoteSender<LogMessage>& log_sender) |
700 | +{ |
701 | + Widelands::NoteReceiver<LogMessage>* lmr |
702 | + = dynamic_cast<Widelands::NoteReceiver<LogMessage>*>(m.get()); |
703 | + lmr->connect(log_sender); |
704 | +} |
705 | + |
706 | + |
707 | /** |
708 | * Check for message expiry. |
709 | */ |
710 | @@ -90,6 +104,13 @@ |
711 | recompute(); |
712 | } |
713 | |
714 | +void ChatOverlay::Impl::receive(const LogMessage& note) |
715 | +{ |
716 | + log_messages.push_back(note); |
717 | + recompute(); |
718 | +} |
719 | + |
720 | + |
721 | /** |
722 | * Recompute the chat message display. |
723 | */ |
724 | @@ -99,18 +120,54 @@ |
725 | |
726 | havemessages = false; |
727 | |
728 | - const std::vector<ChatMessage> & msgs = chat->getMessages(); |
729 | - uint32_t idx = msgs.size(); |
730 | + // Parse the chat message list as well as the log message list |
731 | + // and display them in chronological order |
732 | + int32_t chat_idx = chat != nullptr ? chat->getMessages().size() - 1 : -1; |
733 | + int32_t log_idx = log_messages.empty() ? -1 : log_messages.size() - 1; |
734 | + int32_t msg_time = now; |
735 | std::string richtext; |
736 | - while (idx && now - msgs[idx - 1].time <= CHAT_DISPLAY_TIME) { |
737 | - richtext = msgs[idx - 1].toPrintable() + richtext; |
738 | + |
739 | + while ((chat_idx >= 0 || log_idx >= 0) && now - msg_time < CHAT_DISPLAY_TIME) { |
740 | + if |
741 | + (chat_idx < 0 || |
742 | + (log_idx >= 0 && chat->getMessages()[chat_idx].time < log_messages[log_idx].time)) |
743 | + { |
744 | + // Log message is more recent |
745 | + msg_time = log_messages[log_idx].time; |
746 | + // Do some richtext formatting here |
747 | + richtext = "<p><font face=DejaVuSerif size=14 color=dddddd bold=1>" |
748 | + + log_messages[log_idx].msg + "<br></font></p>" + richtext; |
749 | + log_idx--; |
750 | + } else if |
751 | + (log_idx < 0 || |
752 | + (chat_idx >= 0 && chat->getMessages()[chat_idx].time >= log_messages[log_idx].time)) |
753 | + { |
754 | + // Chat message is more recent |
755 | + msg_time = chat->getMessages()[chat_idx].time; |
756 | + richtext = chat->getMessages()[chat_idx].toPrintable() |
757 | + + richtext; |
758 | + chat_idx--; |
759 | + } else { |
760 | + // Shoudn't happen |
761 | + assert(false); |
762 | + } |
763 | havemessages = true; |
764 | - oldest = msgs[idx - 1].time; |
765 | - idx--; |
766 | - } |
767 | - |
768 | - if (havemessages) |
769 | - rt.parse("<rt>" + richtext + "</rt>"); |
770 | + oldest = msg_time; |
771 | + } |
772 | + |
773 | + // Parse log messages to clear old ones |
774 | + while (!log_messages.empty()) { |
775 | + msg_time = log_messages.front().time; |
776 | + if (msg_time < now - CHAT_DISPLAY_TIME) { |
777 | + log_messages.erase(log_messages.begin()); |
778 | + } else { |
779 | + break; |
780 | + } |
781 | + } |
782 | + |
783 | + if (havemessages) { |
784 | + all_text = "<rt>" + richtext + "</rt>"; |
785 | + } |
786 | } |
787 | |
788 | void ChatOverlay::draw(RenderTarget & dst) |
789 | @@ -118,8 +175,19 @@ |
790 | if (!m->havemessages) |
791 | return; |
792 | |
793 | - int32_t height = m->rt.height(); |
794 | + const Image* im = UI::g_fh1->render(m->all_text, get_w()); |
795 | + // Background |
796 | + int32_t height = im->height() > get_h() ? get_h() : im->height(); |
797 | int32_t top = get_h() - height - 2 * MARGIN; |
798 | |
799 | - m->rt.draw(dst, Point(MARGIN, top + MARGIN), !m->transparent); |
800 | + //FIXME: alpha channel not respected |
801 | + if (!m->transparent) { |
802 | + Rect rect(0, top, im->width(), height); |
803 | + dst.fill_rect(rect, RGBAColor(50, 50, 50, 128)); |
804 | + } |
805 | + int32_t topcrop = im->height() - height; |
806 | + Rect cropRect(0, topcrop, im->width(), height); |
807 | + |
808 | + Point pt(0, top); |
809 | + dst.blitrect(pt, im, cropRect); |
810 | } |
811 | |
812 | === modified file 'src/wui/chatoverlay.h' |
813 | --- src/wui/chatoverlay.h 2013-07-21 08:07:18 +0000 |
814 | +++ src/wui/chatoverlay.h 2013-08-21 08:32:15 +0000 |
815 | @@ -20,9 +20,11 @@ |
816 | #ifndef CHATOVERLAY_H |
817 | #define CHATOVERLAY_H |
818 | |
819 | +#include "logic/notification.h" |
820 | #include "ui_basic/panel.h" |
821 | |
822 | struct ChatProvider; |
823 | +struct LogMessage; |
824 | |
825 | /** |
826 | * The overlay that displays all new chat messages for some timeout on the main window. |
827 | @@ -34,6 +36,7 @@ |
828 | ~ChatOverlay(); |
829 | |
830 | void setChatProvider(ChatProvider &); |
831 | + void setLogProvider(Widelands::NoteSender<LogMessage> &); |
832 | virtual void draw(RenderTarget &); |
833 | virtual void think(); |
834 | |
835 | |
836 | === modified file 'src/wui/game_main_menu_save_game.cc' |
837 | --- src/wui/game_main_menu_save_game.cc 2013-08-01 10:51:41 +0000 |
838 | +++ src/wui/game_main_menu_save_game.cc 2013-08-21 08:32:15 +0000 |
839 | @@ -35,7 +35,6 @@ |
840 | #include "profile/profile.h" |
841 | #include "timestring.h" |
842 | #include "wui/interactive_gamebase.h" |
843 | -#include "wui/interactive_player.h" |
844 | |
845 | using boost::format; |
846 | |
847 | @@ -144,11 +143,7 @@ |
848 | } |
849 | |
850 | m_editbox->focus(); |
851 | - if (parent.game().get_ipl() && !parent.game().get_ipl()->is_multiplayer()) { |
852 | - // Pause the game only if we are part of the game |
853 | - // and not in multiplayer |
854 | - parent.game().gameController()->setPaused(true); |
855 | - } |
856 | + pause_game(true); |
857 | } |
858 | |
859 | |
860 | @@ -320,10 +315,8 @@ |
861 | |
862 | void Game_Main_Menu_Save_Game::die() |
863 | { |
864 | + pause_game(false); |
865 | UI::UniqueWindow::die(); |
866 | - if (igbase().game().get_ipl() && !igbase().game().get_ipl()->is_multiplayer()) { |
867 | - igbase().game().gameController()->setPaused(false); |
868 | - } |
869 | } |
870 | |
871 | |
872 | @@ -372,3 +365,12 @@ |
873 | if (g_fs->FileExists(complete_filename)) |
874 | new DeletionMessageBox(*this, complete_filename); |
875 | } |
876 | + |
877 | +void Game_Main_Menu_Save_Game::pause_game(bool paused) |
878 | +{ |
879 | + if (igbase().is_multiplayer()) { |
880 | + return; |
881 | + } |
882 | + igbase().game().gameController()->setPaused(paused); |
883 | +} |
884 | + |
885 | |
886 | === modified file 'src/wui/game_main_menu_save_game.h' |
887 | --- src/wui/game_main_menu_save_game.h 2013-07-26 19:16:51 +0000 |
888 | +++ src/wui/game_main_menu_save_game.h 2013-08-21 08:32:15 +0000 |
889 | @@ -39,9 +39,10 @@ |
890 | |
891 | void fill_list(); |
892 | void select_by_name(std::string name); |
893 | +protected: |
894 | + virtual void die(); |
895 | private: |
896 | Interactive_GameBase & igbase(); |
897 | - void die(); |
898 | void selected (uint32_t); |
899 | void double_clicked(uint32_t); |
900 | void edit_box_changed(); |
901 | @@ -49,6 +50,7 @@ |
902 | void delete_clicked(); |
903 | |
904 | bool save_game(std::string); |
905 | + void pause_game(bool paused); |
906 | |
907 | UI::Listselect<std::string> m_ls; |
908 | UI::EditBox * m_editbox; |
909 | |
910 | === modified file 'src/wui/gamechatpanel.cc' |
911 | --- src/wui/gamechatpanel.cc 2013-07-26 20:19:36 +0000 |
912 | +++ src/wui/gamechatpanel.cc 2013-08-21 08:32:15 +0000 |
913 | @@ -52,7 +52,8 @@ |
914 | |
915 | std::string str = "<rt>"; |
916 | for (uint32_t i = 0; i < msgs.size(); ++i) { |
917 | - str += msgs[i].toPrintable(); |
918 | + // FIXME use toPrintable() when old renderer is kicked out |
919 | + str += msgs[i].toOldRichText(); |
920 | str += '\n'; |
921 | } |
922 | str += "</rt>"; |
923 | |
924 | === modified file 'src/wui/interactive_base.cc' |
925 | --- src/wui/interactive_base.cc 2013-07-26 20:19:36 +0000 |
926 | +++ src/wui/interactive_base.cc 2013-08-21 08:32:15 +0000 |
927 | @@ -93,6 +93,8 @@ |
928 | m_road_buildhelp_overlay_jobid(Overlay_Manager::Job_Id::Null()), |
929 | m_buildroad (0), |
930 | m_road_build_player (0), |
931 | + // Initialize chatoveraly before the toolbar so it is below |
932 | + m_chatOverlay (new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25)), |
933 | m_toolbar (this, 0, 0, UI::Box::Horizontal), |
934 | m_label_speed_shadow |
935 | (this, get_w() - 1, 0, std::string(), UI::Align_TopRight), |
936 | @@ -115,6 +117,8 @@ |
937 | set_dock_windows_to_edges |
938 | (global_s.get_bool("dock_windows_to_edges", false)); |
939 | |
940 | + m_chatOverlay->setLogProvider(m_log_sender); |
941 | + |
942 | // Switch to the new graphics system now, if necessary. |
943 | WLApplication::get()->refresh_graphics(); |
944 | |
945 | @@ -761,6 +765,16 @@ |
946 | return m_buildroad->get_end(); |
947 | } |
948 | |
949 | +void Interactive_Base::log_message(const std::string& message) const |
950 | +{ |
951 | + // Send to linked receivers |
952 | + LogMessage lm; |
953 | + lm.msg = message; |
954 | + lm.time = time(nullptr); |
955 | + m_log_sender.send(lm); |
956 | +} |
957 | + |
958 | + |
959 | |
960 | /* |
961 | =============== |
962 | |
963 | === modified file 'src/wui/interactive_base.h' |
964 | --- src/wui/interactive_base.h 2013-07-26 20:19:36 +0000 |
965 | +++ src/wui/interactive_base.h 2013-08-21 08:32:15 +0000 |
966 | @@ -25,6 +25,9 @@ |
967 | #include "debugconsole.h" |
968 | #include "logic/editor_game_base.h" |
969 | #include "logic/map.h" |
970 | +#include "logic/notification.h" |
971 | +#include "logmessage.h" |
972 | +#include "wui/chatoverlay.h" |
973 | #include "wui/mapview.h" |
974 | #include "wui/overlay_manager.h" |
975 | #include "ui_basic/box.h" |
976 | @@ -111,6 +114,13 @@ |
977 | |
978 | virtual void cleanup_for_load() {}; |
979 | |
980 | + /** |
981 | + * Log a message to be displayed on screen |
982 | + */ |
983 | + void log_message(const std::string& message) const; |
984 | + void log_message(const char* message) const { |
985 | + log_message(std::string(message)); |
986 | + } |
987 | private: |
988 | void roadb_add_overlay (); |
989 | void roadb_remove_overlay(); |
990 | @@ -169,6 +179,7 @@ |
991 | m_toolbar.set_pos |
992 | (Point((get_inner_w() - m_toolbar.get_w()) >> 1, get_inner_h() - 34)); |
993 | } |
994 | + ChatOverlay * m_chatOverlay; |
995 | UI::Box m_toolbar; |
996 | |
997 | |
998 | @@ -181,6 +192,7 @@ |
999 | UI::Textarea m_label_speed; |
1000 | |
1001 | UI::UniqueWindow::Registry m_debugconsole; |
1002 | + Widelands::NoteSender<LogMessage> m_log_sender; |
1003 | }; |
1004 | |
1005 | #define PIC2 g_gr->images().get("pics/but2.png") |
1006 | |
1007 | === modified file 'src/wui/interactive_gamebase.cc' |
1008 | --- src/wui/interactive_gamebase.cc 2013-08-01 10:51:41 +0000 |
1009 | +++ src/wui/interactive_gamebase.cc 2013-08-21 08:32:15 +0000 |
1010 | @@ -25,16 +25,14 @@ |
1011 | #include "logic/ship.h" |
1012 | #include "profile/profile.h" |
1013 | #include "upcast.h" |
1014 | -#include "wui/chatoverlay.h" |
1015 | #include "wui/game_summary.h" |
1016 | |
1017 | Interactive_GameBase::Interactive_GameBase |
1018 | (Widelands::Game & _game, Section & global_s, |
1019 | - PlayerType pt, bool const chatenabled) |
1020 | + PlayerType pt, bool const chatenabled, bool const multiplayer) |
1021 | : |
1022 | Interactive_Base(_game, global_s), |
1023 | m_chatProvider(0), |
1024 | - m_chatOverlay(0), |
1025 | m_building_census_format |
1026 | (global_s.get_string("building_census_format", "%N")), |
1027 | m_building_statistics_format |
1028 | @@ -42,7 +40,8 @@ |
1029 | m_building_tooltip_format |
1030 | (global_s.get_string("building_tooltip_format", "%r")), |
1031 | m_chatenabled(chatenabled), |
1032 | - m_playertype(pt) |
1033 | + m_playertype(pt), |
1034 | + m_multiplayer(multiplayer) |
1035 | {} |
1036 | |
1037 | /// \return a pointer to the running \ref Game instance. |
1038 | |
1039 | === modified file 'src/wui/interactive_gamebase.h' |
1040 | --- src/wui/interactive_gamebase.h 2013-08-01 10:51:41 +0000 |
1041 | +++ src/wui/interactive_gamebase.h 2013-08-21 08:32:15 +0000 |
1042 | @@ -24,7 +24,6 @@ |
1043 | #include "wui/interactive_base.h" |
1044 | #include "logic/game.h" |
1045 | |
1046 | -struct ChatOverlay; |
1047 | struct ChatProvider; |
1048 | |
1049 | enum PlayerType {NONE, OBSERVER, PLAYING, VICTORIOUS, DEFEATED}; |
1050 | @@ -51,7 +50,8 @@ |
1051 | (Widelands::Game &, |
1052 | Section & global_s, |
1053 | PlayerType pt = NONE, |
1054 | - bool chatenabled = false); |
1055 | + bool chatenabled = false, |
1056 | + bool multiplayer = false); |
1057 | Widelands::Game * get_game() const; |
1058 | Widelands::Game & game() const; |
1059 | |
1060 | @@ -78,17 +78,18 @@ |
1061 | void set_playertype(const PlayerType & pt) {m_playertype = pt;} |
1062 | |
1063 | bool try_show_ship_window(); |
1064 | + bool is_multiplayer() {return m_multiplayer;} |
1065 | |
1066 | void show_game_summary(); |
1067 | |
1068 | protected: |
1069 | Game_Main_Menu_Windows m_mainm_windows; |
1070 | ChatProvider * m_chatProvider; |
1071 | - ChatOverlay * m_chatOverlay; |
1072 | std::string m_building_census_format; |
1073 | std::string m_building_statistics_format; |
1074 | std::string m_building_tooltip_format; |
1075 | bool m_chatenabled; |
1076 | + bool m_multiplayer; |
1077 | |
1078 | PlayerType m_playertype; |
1079 | UI::UniqueWindow::Registry m_fieldaction; |
1080 | |
1081 | === modified file 'src/wui/interactive_player.cc' |
1082 | --- src/wui/interactive_player.cc 2013-07-26 20:19:36 +0000 |
1083 | +++ src/wui/interactive_player.cc 2013-08-21 08:32:15 +0000 |
1084 | @@ -46,7 +46,6 @@ |
1085 | #include "ui_basic/unique_window.h" |
1086 | #include "upcast.h" |
1087 | #include "wui/building_statistics_menu.h" |
1088 | -#include "wui/chatoverlay.h" |
1089 | #include "wui/encyclopedia_window.h" |
1090 | #include "wui/fieldaction.h" |
1091 | #include "wui/game_chat_menu.h" |
1092 | @@ -83,10 +82,9 @@ |
1093 | bool const scenario, |
1094 | bool const multiplayer) |
1095 | : |
1096 | - Interactive_GameBase (_game, global_s), |
1097 | + Interactive_GameBase (_game, global_s, NONE, multiplayer, multiplayer), |
1098 | m_auto_roadbuild_mode(global_s.get_bool("auto_roadbuild_mode", true)), |
1099 | m_flag_to_connect(Widelands::Coords::Null()), |
1100 | - m_multiplayer(multiplayer), |
1101 | |
1102 | // Chat is different, as m_chatProvider needs to be checked when toggling |
1103 | // Buildhelp is different as it does not toggle a UniqueWindow |
1104 | @@ -153,10 +151,6 @@ |
1105 | m_toolbar.add(&m_toggle_statistics_menu, UI::Box::AlignLeft); |
1106 | m_toolbar.add(&m_toggle_minimap, UI::Box::AlignLeft); |
1107 | m_toolbar.add(&m_toggle_buildhelp, UI::Box::AlignLeft); |
1108 | - // Limit chat width to half the screen, to limit the damage lamers can do |
1109 | - // by flooding chat messages |
1110 | - m_chatOverlay = |
1111 | - new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25); |
1112 | if (multiplayer) { |
1113 | m_toolbar.add(&m_toggle_chat, UI::Box::AlignLeft); |
1114 | m_toggle_chat.set_visible(false); |
1115 | @@ -284,7 +278,7 @@ |
1116 | m_flag_to_connect = Widelands::Coords::Null(); |
1117 | } |
1118 | } |
1119 | - if (m_multiplayer) { |
1120 | + if (is_multiplayer()) { |
1121 | m_toggle_chat.set_visible(m_chatenabled); |
1122 | m_toggle_chat.set_enabled(m_chatenabled); |
1123 | } |
1124 | @@ -455,7 +449,7 @@ |
1125 | |
1126 | case SDLK_KP_ENTER: |
1127 | case SDLK_RETURN: |
1128 | - if (!m_chatProvider | !m_chatenabled || !m_multiplayer) |
1129 | + if (!m_chatProvider | !m_chatenabled || !is_multiplayer()) |
1130 | break; |
1131 | |
1132 | if (!m_chat.window) |
1133 | |
1134 | === modified file 'src/wui/interactive_player.h' |
1135 | --- src/wui/interactive_player.h 2013-07-26 20:19:36 +0000 |
1136 | +++ src/wui/interactive_player.h 2013-08-21 08:32:15 +0000 |
1137 | @@ -86,15 +86,12 @@ |
1138 | |
1139 | void popup_message(Widelands::Message_Id, const Widelands::Message &); |
1140 | |
1141 | - bool is_multiplayer() {return m_multiplayer;} |
1142 | - |
1143 | private: |
1144 | void cmdSwitchPlayer(const std::vector<std::string> & args); |
1145 | |
1146 | Widelands::Player_Number m_player_number; |
1147 | bool m_auto_roadbuild_mode; |
1148 | Widelands::Coords m_flag_to_connect; |
1149 | - bool m_multiplayer; |
1150 | |
1151 | UI::Button m_toggle_chat; |
1152 | UI::Button m_toggle_options_menu; |
1153 | |
1154 | === modified file 'src/wui/interactive_spectator.cc' |
1155 | --- src/wui/interactive_spectator.cc 2013-07-26 20:19:36 +0000 |
1156 | +++ src/wui/interactive_spectator.cc 2013-08-21 08:32:15 +0000 |
1157 | @@ -28,7 +28,6 @@ |
1158 | #include "ui_basic/textarea.h" |
1159 | #include "ui_basic/unique_window.h" |
1160 | #include "upcast.h" |
1161 | -#include "wui/chatoverlay.h" |
1162 | #include "wui/fieldaction.h" |
1163 | #include "wui/game_chat_menu.h" |
1164 | #include "wui/game_main_menu_save_game.h" |
1165 | @@ -41,7 +40,7 @@ |
1166 | Interactive_Spectator::Interactive_Spectator |
1167 | (Widelands::Game & _game, Section & global_s, bool const multiplayer) |
1168 | : |
1169 | - Interactive_GameBase(_game, global_s, OBSERVER, multiplayer), |
1170 | + Interactive_GameBase(_game, global_s, OBSERVER, multiplayer, multiplayer), |
1171 | |
1172 | #define INIT_BTN(picture, name, tooltip) \ |
1173 | TOOLBAR_BUTTON_COMMON_PARAMETERS(name), \ |
1174 | @@ -69,7 +68,7 @@ |
1175 | m_toggle_minimap.sigclicked.connect(boost::bind(&Interactive_Spectator::toggle_minimap, this)); |
1176 | |
1177 | m_toolbar.set_layout_toplevel(true); |
1178 | - if (!multiplayer) { |
1179 | + if (!is_multiplayer()) { |
1180 | m_toolbar.add(&m_exit, UI::Box::AlignLeft); |
1181 | m_toolbar.add(&m_save, UI::Box::AlignLeft); |
1182 | } else |
1183 | @@ -80,9 +79,7 @@ |
1184 | |
1185 | // TODO : instead of making unneeded buttons invisible after generation, |
1186 | // they should not at all be generated. -> implement more dynamic toolbar UI |
1187 | - if (multiplayer) { |
1188 | - m_chatOverlay = |
1189 | - new ChatOverlay(this, 10, 25, get_w() - 10, get_h() - 25); |
1190 | + if (is_multiplayer()) { |
1191 | m_exit.set_visible(false); |
1192 | m_exit.set_enabled(false); |
1193 | m_save.set_visible(false); |
1194 | @@ -172,28 +169,30 @@ |
1195 | |
1196 | void Interactive_Spectator::exit_btn() |
1197 | { |
1198 | - if (m_chatenabled) // == multiplayer |
1199 | + if (is_multiplayer()) { |
1200 | return; |
1201 | + } |
1202 | end_modal(0); |
1203 | } |
1204 | |
1205 | |
1206 | void Interactive_Spectator::save_btn() |
1207 | { |
1208 | - if (m_chatenabled) // == multiplayer |
1209 | + if (is_multiplayer()) { |
1210 | return; |
1211 | + } |
1212 | if (m_mainm_windows.savegame.window) |
1213 | delete m_mainm_windows.savegame.window; |
1214 | else { |
1215 | - game().gameController()->setDesiredSpeed(0); |
1216 | new Game_Main_Menu_Save_Game(*this, m_mainm_windows.savegame); |
1217 | } |
1218 | } |
1219 | |
1220 | |
1221 | void Interactive_Spectator::toggle_options_menu() { |
1222 | - if (!m_chatenabled) // == !multiplayer |
1223 | + if (!is_multiplayer()) { |
1224 | return; |
1225 | + } |
1226 | if (m_options.window) |
1227 | delete m_options.window; |
1228 | else |
1229 | @@ -259,7 +258,6 @@ |
1230 | |
1231 | case SDLK_s: |
1232 | if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) { |
1233 | - game().gameController()->setDesiredSpeed(0); |
1234 | new Game_Main_Menu_Save_Game(*this, m_mainm_windows.savegame); |
1235 | } else |
1236 | set_display_flag |
1237 | |
1238 | === modified file 'src/wui/watchwindow.cc' |
1239 | --- src/wui/watchwindow.cc 2013-08-02 18:36:03 +0000 |
1240 | +++ src/wui/watchwindow.cc 2013-08-21 08:32:15 +0000 |
1241 | @@ -256,12 +256,14 @@ |
1242 | pos = bob->calc_drawpos(game(), pos); |
1243 | |
1244 | Widelands::Map & map = game().map(); |
1245 | - if (1 < game().get_ipl()->player().vision(map.get_index(bob->get_position(), map.get_width()))) { |
1246 | + // Drop the tracking if it leaves our vision range |
1247 | + Interactive_Player* ipl = game().get_ipl(); |
1248 | + if (ipl && 1 >= ipl->player().vision(map.get_index(bob->get_position(), map.get_width()))) { |
1249 | + // Not in sight |
1250 | + views[cur_index].tracking = 0; |
1251 | + } else { |
1252 | mapview.set_viewpoint |
1253 | (pos - Point(mapview.get_w() / 2, mapview.get_h() / 2), false); |
1254 | - } else { |
1255 | - // stop tracking |
1256 | - views[cur_index].tracking = 0; |
1257 | } |
1258 | } |
1259 | |
1260 | @@ -327,9 +329,10 @@ |
1261 | p = bob->calc_drawpos(g, p); |
1262 | int32_t const dist = |
1263 | MapviewPixelFunctions::calc_pix_distance(map, p, pos); |
1264 | + Interactive_Player* ipl = game().get_ipl(); |
1265 | if |
1266 | ((!closest || closest_dist > dist) |
1267 | - && (1 < game().get_ipl()->player().vision(map.get_index(bob->get_position(), map.get_width())))) |
1268 | + && (!ipl || 1 < ipl->player().vision(map.get_index(bob->get_position(), map.get_width())))) |
1269 | { |
1270 | closest = bob; |
1271 | closest_dist = dist; |
So I've added some code dealing with autosaving , the watch window and replays. Sorry for that, but I felt like rewriting the same things over and over.
The additional changes:
- Add a multiplayer field and getter in interactive gamebase
- Make Panel::die virtual and overwrite in Window to close it and in the save dialog to unpause the game
- Do not rely on interactive player in some place (watch window, save handler)
- Prevent autosaving in replay and prevent autopausing in multiplayer.