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

Proposed by SirVer
Status: Merged
Merged at revision: 7798
Proposed branch: lp:~widelands-dev/widelands/dedicated_out_of_main
Merge into: lp:widelands
Diff against target: 3599 lines (+457/-1848)
25 files modified
src/CMakeLists.txt (+0/-3)
src/io/CMakeLists.txt (+0/-13)
src/io/dedicated_log.cc (+0/-342)
src/io/dedicated_log.h (+0/-90)
src/logic/editor_game_base.cc (+1/-5)
src/logic/game.cc (+56/-108)
src/logic/game.h (+13/-7)
src/logic/game_settings.h (+0/-11)
src/main.cc (+0/-57)
src/map_io/map_building_packet.cc (+1/-2)
src/network/CMakeLists.txt (+0/-1)
src/network/internet_gaming.cc (+21/-22)
src/network/netclient.cc (+47/-163)
src/network/netclient.h (+0/-2)
src/network/nethost.cc (+102/-593)
src/network/nethost.h (+1/-8)
src/network/network_protocol.h (+7/-35)
src/sound/sound_handler.h (+0/-1)
src/ui_fsmenu/launch_mpg.cc (+0/-10)
src/ui_fsmenu/loadgame.cc (+164/-179)
src/ui_fsmenu/mapselect.cc (+39/-113)
src/wlapplication.cc (+2/-77)
src/wlapplication.h (+1/-1)
src/wlapplication_messages.cc (+0/-1)
src/wui/chat_msg_layout.cc (+2/-4)
To merge this branch: bzr merge lp:~widelands-dev/widelands/dedicated_out_of_main
Reviewer Review Type Date Requested Status
Tino Approve
GunChleoc Approve
Review via email: mp+285268@code.launchpad.net

Commit message

Remove --dedicated commandline option and associated code.

Rational: --dedicated allowed people who could host a game to keep a server running that people who could not host could control to play games. This is a great feature, but it came at a price: dedicated required a lot of if () else () in many places, i.e. it was very widespread in the code. One of the most pervasive problems was that dedicated could not spin up a Graphic() instance, therfore g_gr == nullptr and a lot of code did not check for that - since g_gr is never null if the game is run normally. Therefore it was easily broken - I am not sure if it worked in b18, but it has not worked for at least a year.
Another problem was that dedicated is essentially a host instance, i.e. it has to run the full game logic for each game that is played. So it is prohibitively expensive to run it (for example) on the server. So we would have needed a donator to even provide another instance that could be used.

We also have a plan of fixing the hosting problem in a principled way: through the proxy server that is spawned by the metaserver that will forward packets between players. Unfortunately, this is not implemented yet and it will not be for b19.

Description of the change

Requires https://code.launchpad.net/~widelands-dev/widelands/different_replay_names/+merge/285265 to be merged first.

Spend an hour today trying to fix --dedicated. Then decided it was too difficult after I could not follow the various state machines anymore and after it kept crashing. Now I ripped it out. This closes a few bugs related to --dedicated and simplifies the code, but of course the dedicated feature is gone for good.

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

Please have a look at my code review commit - there is a NOCOM question in there.

Also pinging Tino, because some WIN32 includes have been removed.

review: Approve
Revision history for this message
SirVer (sirver) wrote :

// NOCOM why was this deleted? if (!complete) throw wexception("Out of memory");

because it is rather pointless. We allocate memory everywhere and never check for OOM errors. One of the reasons is that if the OS does not have any more memory to give you, it will not give you any memory for creating the error message string or the exception. This will kill your process rather quickly anyways.

Tino, if that compiles for you, could you merge?

Revision history for this message
Tino (tino79) wrote :

Compiles, does work fine. No regressionson windows found.

@bunnybot merge

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2014-12-06 12:22:35 +0000
3+++ src/CMakeLists.txt 2016-02-07 08:11:43 +0000
4@@ -106,7 +106,6 @@
5 graphic_text
6 graphic_text_layout
7 helper
8- io_dedicated_log
9 io_filesystem
10 logic
11 logic_game_controller
12@@ -130,8 +129,6 @@
13 base_exceptions
14 )
15
16-
17-
18 if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
19 target_link_libraries(widelands_ball_of_mud ${EXECINFO_LIBRARY})
20 endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
21
22=== modified file 'src/io/CMakeLists.txt'
23--- src/io/CMakeLists.txt 2014-11-28 16:40:55 +0000
24+++ src/io/CMakeLists.txt 2016-02-07 08:11:43 +0000
25@@ -44,16 +44,3 @@
26 io_stream
27 third_party_minizip
28 )
29-
30-
31-wl_library(io_dedicated_log
32- SRCS
33- dedicated_log.h
34- dedicated_log.cc
35- DEPENDS
36- base_i18n
37- base_log
38- chat
39- io_fileread
40- io_filesystem
41-)
42
43=== removed file 'src/io/dedicated_log.cc'
44--- src/io/dedicated_log.cc 2014-09-30 05:41:55 +0000
45+++ src/io/dedicated_log.cc 1970-01-01 00:00:00 +0000
46@@ -1,342 +0,0 @@
47-/*
48- * Copyright (C) 2012-2013 by the Widelands Development Team
49- *
50- * This program is free software; you can redistribute it and/or
51- * modify it under the terms of the GNU General Public License
52- * as published by the Free Software Foundation; either version 2
53- * of the License, or (at your option) any later version.
54- *
55- * This program is distributed in the hope that it will be useful,
56- * but WITHOUT ANY WARRANTY; without even the implied warranty of
57- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58- * GNU General Public License for more details.
59- *
60- * You should have received a copy of the GNU General Public License
61- * along with this program; if not, write to the Free Software
62- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
63- *
64- */
65-
66-#include "io/dedicated_log.h"
67-
68-#include <string>
69-
70-#include <boost/format.hpp>
71-
72-#include "base/i18n.h"
73-#include "base/log.h"
74-#include "io/filesystem/layered_filesystem.h"
75-
76-/// The dedicated server logger
77-static DedicatedLog * logger;
78-
79-extern std::ostream & wout;
80-
81-void dedicatedlog(const char * const fmt, ...) {
82- char buffer[2048];
83- va_list va;
84-
85- va_start(va, fmt);
86- vsnprintf(buffer, sizeof(buffer), fmt, va);
87- va_end(va);
88-
89- // Here comes the difference to widelands standard log() ;)
90- DedicatedLog::get()->dlog(buffer);
91-
92- wout << buffer;
93- wout.flush();
94-}
95-
96-/// protected constructor
97-DedicatedLog::DedicatedLog()
98-:
99-m_chat_file_path(""),
100-m_info_file_path(""),
101-m_log_file_path(""),
102-d_name(""),
103-d_motd(""),
104-d_start(""),
105-d_logins(0),
106-d_logouts(0),
107-d_chatmessages(0),
108-root(new RealFSImpl("/"))
109-{
110- char ts[42];
111- time_t currenttime = time(nullptr);
112- strftime(ts, sizeof(ts), "%a %Y/%m/%d, %H:%M:%S", localtime(&currenttime));
113- d_start = ts;
114- d_ip = (boost::format("\\<%s\\>") % _("unknown")).str();
115-}
116-
117-
118-/// \returns the dedicated server logger, if it is not yet initialized, this is done before.
119-DedicatedLog * DedicatedLog::get() {
120- if (logger == nullptr)
121- logger = new DedicatedLog();
122- return logger;
123-}
124-
125-
126-/**
127- * chat(ChatMessage & c)
128- *
129- * Writes the ChatMessage \arg c to the chat log, if initialized.
130- */
131-void DedicatedLog::chat(ChatMessage & c) {
132- if (!m_info_file_path.empty()) {
133- ++d_chatmessages;
134- info_update();
135- }
136-
137- if (m_chat_file_path.empty())
138- return;
139-
140- std::string temp("<tr>");
141- temp += "<td class=\"time\">";
142- char ts[32];
143- strftime(ts, sizeof(ts), "[%Y-%m-%d, %H:%M]", localtime(&c.time));
144- temp += (boost::format("%s</td><td class=\"player%i\">") % ts % c.playern).str();
145- temp += c.sender.empty() ? "SYSTEM" : c.sender;
146- temp += "</td><td class=\"recipient\"> ->" + c.recipient + "</td><td class=\"message\">";
147- temp += c.msg + "</td></tr>\n";
148- m_chat.print_f("%s", temp.c_str());
149- m_chat.write_append(*root, m_chat_file_path.c_str());
150-}
151-
152-/// Add's a spacer to the chat log
153-void DedicatedLog::chat_add_spacer() {
154- if (m_chat_file_path.empty())
155- return;
156-
157- m_chat.print_f("<tr><td class=\"space\"></td><td class=\"space\"></td>");
158- m_chat.print_f("<td class=\"space\"></td><td class=\"space\"></td></tr>\n");
159- m_chat.write_append(*root, m_chat_file_path.c_str());
160-}
161-
162-
163-/// Sets the basic server informations
164-void DedicatedLog::set_server_data(std::string name, std::string motd) {
165- if (!d_name.empty())
166- return;
167- d_name = name;
168- d_motd = motd;
169- info_update();
170-}
171-
172-
173-/// Sets the servers ip informations
174-void DedicatedLog::set_server_ip(std::string ip) {
175- if (d_ip != ip) {
176- d_ip = ip;
177- info_update();
178- }
179-}
180-
181-
182-/// Saves the data of a newly started game
183-void DedicatedLog::game_start(std::vector<std::string> clients, std::string mapname) {
184- GameStatistic * new_game = new GameStatistic;
185- new_game->mapname = mapname;
186- new_game->times.push_back(time(nullptr));
187- new_game->clients = clients;
188- d_games.push_back(*new_game);
189- delete new_game;
190- new_game = nullptr;
191- info_update();
192-}
193-
194-
195-/// Saves the winners of the last started game
196-void DedicatedLog::game_end(std::vector<std::string> winners) {
197- assert(!d_games.empty());
198- d_games.back().winners = winners;
199- d_games.back().times.push_back(time(nullptr));
200- info_update();
201-}
202-
203-
204-/// Updates the server information file with current data
205-void DedicatedLog::info_update() {
206- if (m_info_file_path.empty())
207- return;
208-
209- std::string temp("<table class=\"infohead\">\n");
210- // Basic information
211- temp += "<tr><td class=\"infoname\">Servername</td><td class=\"info\">" + d_name + "</td></tr>\n";
212- temp += "<tr><td class=\"infoname\">Server IP</td><td class=\"info\">" + d_ip + "</td></tr>\n";
213- temp += "<tr><td class=\"infoname\">Server MOTD</td><td class=\"info\">" + d_motd + "</td></tr>\n";
214- temp += "<tr><td class=\"infoname\">Started on</td><td class=\"info\">" + d_start + "</td></tr>\n";
215- temp += "<tr><td class=\"infoname\">Logins</td><td class=\"info\">";
216- temp += std::to_string(d_logins) + "</td></tr>\n";
217- temp += "<tr><td class=\"infoname\">Logouts</td><td class=\"info\">";
218- temp += std::to_string(d_logouts) + "</td></tr>\n";
219- temp += "<tr><td class=\"infoname\">Chat messages</td><td class=\"info\">";
220- temp += std::to_string(d_chatmessages) + "</td></tr>\n";
221- temp += "<tr><td class=\"infoname\">Games started</td><td class=\"info\">";
222- temp += std::to_string(d_games.size()) + "</td></tr>\n";
223- if (!d_games.empty()) {
224- // Games information
225- temp += "</table><br><table class=\"infogames\">\n";
226- temp += "<tr><th>start/end of game</th><th>map name</th><th>client(s)</th><th>winner(s)</th></tr>\n";
227-
228- for (uint16_t i = 0; i < d_games.size(); ++i) {
229- assert(!d_games.at(i).clients.empty() && !d_games.at(i).times.empty());
230- // Start and (if already ended) end time
231- char ts[42];
232- strftime(ts, sizeof(ts), "S: %Y/%m/%d, %H:%M:%S", localtime(&d_games.at(i).times.at(0)));
233- temp += (boost::format("<tr><td>%s") % ts).str();
234- if (d_games.at(i).times.size() > 1) {
235- strftime(ts, sizeof(ts), "E: %Y/%m/%d, %H:%M:%S", localtime(&d_games.at(i).times.at(1)));
236- temp += (boost::format("<br>%s") % ts).str();
237- }
238- // Map name
239- temp += (boost::format("</td><td>%s</td><td>") % d_games.at(i).mapname).str();
240- // Players
241- for (uint16_t j = 0; j < d_games.at(i).clients.size(); ++j) {
242- if (j > 0)
243- temp += ", ";
244- temp += d_games.at(i).clients.at(j);
245- }
246- temp += "</td><td>";
247- // Winners
248- for (uint16_t j = 0; j < d_games.at(i).winners.size(); ++j) {
249- if (j > 0)
250- temp += ", ";
251- temp += d_games.at(i).winners.at(j);
252- }
253- temp += "</td></tr>\n";
254- }
255- }
256- temp += "</table>\n";
257- m_chat.print_f("%s", temp.c_str());
258- m_chat.write(*root, m_info_file_path.c_str());
259-}
260-
261-/// Appends the String \arg msg to the log file
262-void DedicatedLog::dlog(std::string msg) {
263- if (m_log_file_path.empty())
264- return;
265-
266- std::string temp("<tr><td class=\"time\">");
267- char ts[32];
268- time_t * t = new time_t(time(nullptr));
269- strftime(ts, sizeof(ts), "[%Y-%m-%d, %H:%M]", localtime(t));
270- delete t;
271- temp += ts;
272- temp += "</td><td class=\"log\">";
273- temp += msg;
274- temp += "</td></tr>\n";
275- m_chat.print_f("%s", temp.c_str());
276- m_chat.write_append(*root, m_log_file_path.c_str());
277-}
278-
279-
280-/**
281- * set_chat_file_path(std::string path)
282- *
283- * Post initialization - this function can be called more than once, but will only handle the input data
284- * as long as the chat file path is not yet set up correctly.
285- * The function takes care:
286- * - Whether the file at \arg path is writeable - \returns false if not.
287- * - About file cleanup - all following data will be attached, therefore the original file will be removed
288- * - About the initial formating like table headers, etc.
289- *
290- * \returns false, if path is not writeable, in all other cases true
291- */
292-bool DedicatedLog::set_chat_file_path(std::string path) {
293- if (!m_chat_file_path.empty() || path.empty())
294- return true;
295-
296- if (!check_file_writeable(path))
297- return false;
298-
299- // Everything's fine, set the path
300- m_chat_file_path = path;
301-
302- // Initialize the chat file
303- m_chat.print_f("<tr><th>Time</th><th>Sender</th><th>Recipient</th><th>Message</th></tr>");
304- m_chat.write(*root, m_chat_file_path.c_str()); // Not write_append, to make sure the file is cleared
305- return true;
306-}
307-
308-
309-/**
310- * set_info_file_path(std::string path)
311- *
312- * Post initialization - this function can be called more than once, but will only handle the input data
313- * as long as the info file path is not yet set up correctly.
314- * The function takes care:
315- * - Whether the file at \arg path is writeable - \returns false if not.
316- * - About file cleanup - all following data will be attached, therefore the original file will be removed
317- * - About the initial formating like table headers, etc.
318- *
319- * \returns false, if path is not writeable, in all other cases true
320- */
321-bool DedicatedLog::set_info_file_path(std::string path) {
322- if (!m_info_file_path.empty() || path.empty())
323- return true;
324-
325- if (!check_file_writeable(path))
326- return false;
327-
328- // Everything's fine, set the path and write info for the first time;
329- m_info_file_path = path;
330- info_update();
331- return true;
332-}
333-
334-
335-/**
336- * set_log_file_path(std::string path)
337- *
338- * Post initialization - this function can be called more than once, but will only handle the input data
339- * as long as the log file path is not yet set up correctly.
340- * The function takes care:
341- * - Whether the file at \arg path is writeable - \returns false if not.
342- * - About file cleanup - all following data will be attached, therefore the original file will be removed
343- * - About the initial formating like table headers, etc.
344- *
345- * \returns false, if path is not writeable, in all other cases true
346- */
347-bool DedicatedLog::set_log_file_path (std::string path) {
348- if (!m_log_file_path.empty() || path.empty())
349- return true;
350-
351- if (!check_file_writeable(path))
352- return false;
353-
354- // Everything's fine, set the path
355- m_log_file_path = path;
356-
357- // Initialize the log file
358- m_chat.print_f("<tr><th></th><th>Widelands dedicated server log:</th></tr>\n");
359- m_chat.write(*root, m_log_file_path.c_str()); // Not write_append, to make sure the file is cleared
360- return true;
361-}
362-
363-
364-/**
365- * check_file_writeable(std::string & path)
366- *
367- * Checks if a file is writeable to \arg path and if yes and a file of that name is already existing
368- * moves the original file to path + "~".
369- *
370- * \returns false, if path is not writeable or if path is a directory or if the directory the file should be
371- * written to does not exist, in all other cases true.
372- */
373-bool DedicatedLog::check_file_writeable(std::string & path) {
374- bool existing = root->file_exists(path);
375- if (existing && root->is_directory(path))
376- return false;
377- if (root->file_is_writeable(path)) {
378- if (existing) {
379- std::string rnpath(path + '~');
380- if (root->file_is_writeable(rnpath))
381- root->fs_rename(path, rnpath);
382- else
383- log("Note: original file %s could not be backuped\n", path.c_str());
384- }
385- return true;
386- }
387- return false;
388-}
389
390=== removed file 'src/io/dedicated_log.h'
391--- src/io/dedicated_log.h 2014-09-20 09:37:47 +0000
392+++ src/io/dedicated_log.h 1970-01-01 00:00:00 +0000
393@@ -1,90 +0,0 @@
394-/*
395- * Copyright (C) 2012 by the Widelands Development Team
396- *
397- * This program is free software; you can redistribute it and/or
398- * modify it under the terms of the GNU General Public License
399- * as published by the Free Software Foundation; either version 2
400- * of the License, or (at your option) any later version.
401- *
402- * This program is distributed in the hope that it will be useful,
403- * but WITHOUT ANY WARRANTY; without even the implied warranty of
404- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
405- * GNU General Public License for more details.
406- *
407- * You should have received a copy of the GNU General Public License
408- * along with this program; if not, write to the Free Software
409- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
410- *
411- */
412-
413-#ifndef WL_IO_DEDICATED_LOG_H
414-#define WL_IO_DEDICATED_LOG_H
415-
416-#include "base/log.h"
417-#include "chat/chat.h"
418-#include "io/filesystem/disk_filesystem.h"
419-#include "io/filewrite.h"
420-
421-void dedicatedlog(const char *, ...) PRINTF_FORMAT(1, 2);
422-
423-/// This struct writes some statistics and chat data to commandline defined files
424-struct DedicatedLog {
425- // Always call DedicatedLog via get() to have only one instance
426- static DedicatedLog * get();
427-
428- // chat logging functions
429- void chat_add_spacer();
430- void chat(ChatMessage & c);
431-
432- // info logging functions
433- bool write_info_active() {return !m_info_file_path.empty();}
434- void set_server_data(std::string name, std::string motd);
435- void set_server_ip (std::string ip);
436- void client_login() {++d_logins; info_update();} // simple counter
437- void client_logout() {++d_logouts; info_update();} // simple counter
438- void game_start(std::vector<std::string> clients, std::string mapname);
439- void game_end (std::vector<std::string> winners);
440- void info_update(); // updates the info file
441-
442- // normal log logging function
443- void dlog(std::string);
444-
445- // Post initialization - can be called more than once, but only the first call will be handled
446- // The functions do not only set up the output path, but as well take care about file cleanup and
447- // generate the initial formating
448- bool set_chat_file_path(std::string path);
449- bool set_info_file_path(std::string path);
450- bool set_log_file_path (std::string path);
451-
452-protected:
453- /// Constructor is protected by purpose - only one instance of DedicatedLog is allowed
454- /// call DedicatedLog::get() instead.
455- DedicatedLog();
456-
457-private:
458- bool check_file_writeable(std::string & path);
459-
460- std::string m_chat_file_path;
461- std::string m_info_file_path;
462- std::string m_log_file_path;
463-
464- FileWrite m_chat;
465- FileWrite m_info;
466- FileWrite m_path;
467-
468- // statics data
469- struct GameStatistic {
470- std::string mapname;
471- std::vector<std::string> clients;
472- std::vector<std::string> winners;
473- std::vector<time_t> times;
474- };
475- std::string d_name, d_ip, d_motd, d_start;
476- uint32_t d_logins, d_logouts, d_chatmessages;
477- std::vector<GameStatistic> d_games;
478-
479-
480- RealFSImpl * root;
481-};
482-
483-#endif // end of include guard: WL_IO_DEDICATED_LOG_H
484
485=== modified file 'src/logic/editor_game_base.cc'
486--- src/logic/editor_game_base.cc 2016-01-28 05:24:34 +0000
487+++ src/logic/editor_game_base.cc 2016-02-07 08:11:43 +0000
488@@ -83,11 +83,7 @@
489 EditorGameBase::~EditorGameBase() {
490 delete map_;
491 delete player_manager_.release();
492-
493- if (g_gr) { // dedicated does not use the sound_handler
494- assert(this == g_sound_handler.egbase_);
495- g_sound_handler.egbase_ = nullptr;
496- }
497+ g_sound_handler.egbase_ = nullptr;
498 }
499
500 void EditorGameBase::think()
501
502=== modified file 'src/logic/game.cc'
503--- src/logic/game.cc 2016-02-04 14:00:35 +0000
504+++ src/logic/game.cc 2016-02-07 08:11:43 +0000
505@@ -24,6 +24,7 @@
506 #include <memory>
507 #include <string>
508
509+#include <boost/format.hpp>
510 #ifndef _WIN32
511 #include <SDL.h> // for a dirty hack.
512 #include <unistd.h> // for usleep
513@@ -73,10 +74,7 @@
514 //#define SYNC_DEBUG
515
516 Game::SyncWrapper::~SyncWrapper() {
517- if (m_dump) {
518- delete m_dump;
519- m_dump = nullptr;
520-
521+ if (m_dump != nullptr) {
522 if (!m_syncstreamsave)
523 g_fs->fs_unlink(m_dumpfname);
524 }
525@@ -84,7 +82,7 @@
526
527 void Game::SyncWrapper::start_dump(const std::string & fname) {
528 m_dumpfname = fname + ".wss";
529- m_dump = g_fs->open_stream_write(m_dumpfname);
530+ m_dump.reset(g_fs->open_stream_write(m_dumpfname));
531 }
532
533 static const unsigned long long MINIMUM_DISK_SPACE = 256 * 1024 * 1024;
534@@ -98,29 +96,21 @@
535 log("\n");
536 #endif
537
538- if
539- (m_dump &&
540- static_cast<int32_t>(m_counter - m_next_diskspacecheck) >= 0)
541- {
542+ if (m_dump != nullptr && static_cast<int32_t>(m_counter - m_next_diskspacecheck) >= 0) {
543 m_next_diskspacecheck = m_counter + 16 * 1024 * 1024;
544
545 if (g_fs->disk_space() < MINIMUM_DISK_SPACE) {
546 log("Stop writing to syncstream file: disk is getting full.\n");
547- delete m_dump;
548- m_dump = nullptr;
549+ m_dump.reset();
550 }
551 }
552
553- if (m_dump) {
554+ if (m_dump != nullptr) {
555 try {
556 m_dump->data(sync_data, size);
557 } catch (const WException &) {
558- log
559- ("Writing to syncstream file %s failed. Stop synctream dump.\n",
560- m_dumpfname.c_str());
561-
562- delete m_dump;
563- m_dump = nullptr;
564+ log("Writing to syncstream file %s failed. Stop synctream dump.\n", m_dumpfname.c_str());
565+ m_dump.reset();
566 }
567 }
568
569@@ -137,7 +127,6 @@
570 m_writesyncstream (false),
571 m_state (gs_notrunning),
572 m_cmdqueue (*this),
573- m_replaywriter (nullptr),
574 /** TRANSLATORS: Win condition for this game has not been set. */
575 m_win_condition_displayname(_("Not set"))
576 {
577@@ -145,7 +134,6 @@
578
579 Game::~Game()
580 {
581- delete m_replaywriter;
582 }
583
584
585@@ -259,7 +247,7 @@
586
587 set_game_controller(new SinglePlayerGameController(*this, true, 1));
588 try {
589- bool const result = run(&loader_ui, NewSPScenario, script_to_run, false);
590+ bool const result = run(&loader_ui, NewSPScenario, script_to_run, false, "single_player");
591 delete m_ctrl;
592 m_ctrl = nullptr;
593 return result;
594@@ -274,39 +262,34 @@
595 /**
596 * Initialize the game based on the given settings.
597 *
598- * \note loader_ui can be nullptr, if this is run as dedicated server.
599 */
600 void Game::init_newgame
601 (UI::ProgressWindow* loader_ui, const GameSettings& settings)
602 {
603- if (loader_ui) {
604- loader_ui->step(_("Preloading map"));
605- }
606+ assert(loader_ui != nullptr);
607+
608+ loader_ui->step(_("Preloading map"));
609
610 assert(!get_map());
611 set_map(new Map);
612
613 std::unique_ptr<MapLoader> maploader
614 (map().get_correct_loader(settings.mapfilename));
615+ assert(maploader != nullptr);
616 maploader->preload_map(settings.scenario);
617
618- if (loader_ui) {
619- loader_ui->step(_("Loading world"));
620- }
621+ loader_ui->step(_("Loading world"));
622 world();
623
624- if (loader_ui) {
625- loader_ui->step(_("Loading tribes"));
626- }
627+ loader_ui->step(_("Loading tribes"));
628 tribes();
629
630 std::string const background = map().get_background();
631- if (loader_ui) {
632- if (!background.empty()) {
633- loader_ui->set_background(background);
634- }
635- loader_ui->step(_("Creating players"));
636+ if (!background.empty()) {
637+ loader_ui->set_background(background);
638 }
639+ loader_ui->step(_("Creating players"));
640+
641 std::vector<PlayerSettings> shared;
642 std::vector<uint8_t> shared_num;
643 for (uint32_t i = 0; i < settings.players.size(); ++i) {
644@@ -338,8 +321,7 @@
645 ->add_further_starting_position(shared_num.at(n), shared.at(n).initialization_index);
646 }
647
648- if (loader_ui)
649- loader_ui->step(_("Loading map"));
650+ loader_ui->step(_("Loading map"));
651 maploader->load_map_complete(*this,
652 settings.scenario ?
653 Widelands::MapLoader::LoadType::kScenario :
654@@ -364,15 +346,13 @@
655 * At return the game is at the same state like a map loaded with Game::init()
656 * Only difference is, that players are already initialized.
657 * run<Returncode>() takes care about this difference.
658- *
659- * \note loader_ui can be nullptr, if this is run as dedicated server.
660 */
661 void Game::init_savegame
662 (UI::ProgressWindow* loader_ui, const GameSettings& settings)
663 {
664- if (loader_ui) {
665- loader_ui->step(_("Preloading map"));
666- }
667+ assert(loader_ui != nullptr);
668+
669+ loader_ui->step(_("Preloading map"));
670
671 assert(!get_map());
672 set_map(new Map);
673@@ -381,11 +361,9 @@
674 Widelands::GamePreloadPacket gpdp;
675 gl.preload_game(gpdp);
676 m_win_condition_displayname = gpdp.get_win_condition();
677- if (loader_ui) {
678- std::string background(gpdp.get_background());
679- loader_ui->set_background(background);
680- loader_ui->step(_("Loading..."));
681- }
682+ std::string background(gpdp.get_background());
683+ loader_ui->set_background(background);
684+ loader_ui->step(_("Loading..."));
685 gl.load_game(settings.multiplayer);
686 } catch (...) {
687 throw;
688@@ -427,7 +405,7 @@
689
690 set_game_controller(new SinglePlayerGameController(*this, true, player_nr));
691 try {
692- bool const result = run(&loader_ui, Loaded, script_to_run, false);
693+ bool const result = run(&loader_ui, Loaded, script_to_run, false, "single_player");
694 delete m_ctrl;
695 m_ctrl = nullptr;
696 return result;
697@@ -448,12 +426,7 @@
698 void Game::postload()
699 {
700 EditorGameBase::postload();
701-
702- if (g_gr) {
703- assert(get_ibase() != nullptr);
704- get_ibase()->postload();
705- } else
706- log("Note: Widelands runs without graphics, probably in dedicated server mode!\n");
707+ get_ibase()->postload();
708 }
709
710
711@@ -473,13 +446,13 @@
712 * 3. After this has happened, the game graphics are loaded.
713 *
714 * \return true if a game actually took place, false otherwise
715- *
716- * \note loader_ui can be nullptr, if this is run as dedicated server.
717 */
718 bool Game::run
719 (UI::ProgressWindow * loader_ui, StartGameType const start_game_type,
720- const std::string& script_to_run, bool replay)
721+ const std::string& script_to_run, bool replay, const std::string& prefix_for_replays)
722 {
723+ assert(loader_ui != nullptr);
724+
725 m_replay = replay;
726 postload();
727
728@@ -545,16 +518,13 @@
729
730 if (m_writereplay || m_writesyncstream) {
731 // Derive a replay filename from the current time
732- std::string fname(REPLAY_DIR);
733- fname += '/';
734- fname += timestring();
735- fname += REPLAY_SUFFIX;
736-
737+ const std::string fname = (boost::format("%s/%s_%s%s") % REPLAY_DIR % timestring() %
738+ prefix_for_replays % REPLAY_SUFFIX).str();
739 if (m_writereplay) {
740 log("Starting replay writer\n");
741
742 assert(!m_replaywriter);
743- m_replaywriter = new ReplayWriter(*this, fname);
744+ m_replaywriter.reset(new ReplayWriter(*this, fname));
745
746 log("Replay writer has started\n");
747 }
748@@ -565,46 +535,30 @@
749
750 sync_reset();
751
752- if (loader_ui) {
753- load_graphics(*loader_ui);
754+ load_graphics(*loader_ui);
755
756 #ifdef _WIN32
757- // Clear the event queue before starting game because we don't want
758- // to handle events at game start that happened during loading procedure.
759- SDL_Event event;
760- while (SDL_PollEvent(&event));
761-#endif
762-
763- g_sound_handler.change_music("ingame", 1000, 0);
764-
765- m_state = gs_running;
766-
767- get_ibase()->run<UI::Panel::Returncodes>();
768-
769- m_state = gs_ending;
770-
771- g_sound_handler.change_music("menu", 1000, 0);
772-
773- cleanup_objects();
774- delete get_ibase();
775- set_ibase(nullptr);
776-
777- m_state = gs_notrunning;
778- } else {
779- // dedicated server
780- m_state = gs_running;
781- //handle network
782- while (m_state == gs_running) {
783- // TODO(unknown): this should be improved.
784-#ifndef _WIN32
785- if (usleep(100) == -1)
786- break;
787-#else
788- Sleep(1);
789-#endif
790- think();
791- }
792- }
793+ // Clear the event queue before starting game because we don't want
794+ // to handle events at game start that happened during loading procedure.
795+ SDL_Event event;
796+ while (SDL_PollEvent(&event));
797+#endif
798+
799+ g_sound_handler.change_music("ingame", 1000, 0);
800+
801+ m_state = gs_running;
802+
803+ get_ibase()->run<UI::Panel::Returncodes>();
804+
805+ m_state = gs_ending;
806+
807+ g_sound_handler.change_music("menu", 1000, 0);
808+
809+ cleanup_objects();
810+ delete get_ibase();
811+ set_ibase(nullptr);
812+
813+ m_state = gs_notrunning;
814
815 return true;
816 }
817@@ -634,12 +588,6 @@
818 }
819 }
820
821-/// (Only) called by the dedicated server, to end a game once all players left
822-void Game::end_dedicated_game() {
823- assert(!g_gr);
824- m_state = gs_notrunning;
825-}
826-
827 /**
828 * Cleanup for load
829 * \deprecated
830
831=== modified file 'src/logic/game.h'
832--- src/logic/game.h 2016-02-04 14:00:35 +0000
833+++ src/logic/game.h 2016-02-07 08:11:43 +0000
834@@ -20,6 +20,8 @@
835 #ifndef WL_LOGIC_GAME_H
836 #define WL_LOGIC_GAME_H
837
838+#include <memory>
839+
840 #include "base/md5.h"
841 #include "io/streamwrite.h"
842 #include "logic/cmd_queue.h"
843@@ -108,7 +110,12 @@
844 void init_newgame (UI::ProgressWindow* loader_ui, const GameSettings&);
845 void init_savegame(UI::ProgressWindow* loader_ui, const GameSettings&);
846 enum StartGameType {NewSPScenario, NewNonScenario, Loaded, NewMPScenario};
847- bool run(UI::ProgressWindow* loader_ui, StartGameType, const std::string& script_to_run, bool replay);
848+
849+ bool run(UI::ProgressWindow* loader_ui,
850+ StartGameType,
851+ const std::string& script_to_run,
852+ bool replay,
853+ const std::string& prefix_for_replays);
854
855 // Returns the upcasted lua interface.
856 LuaGameInterface& lua() override;
857@@ -127,14 +134,15 @@
858
859 void think() override;
860
861- ReplayWriter * get_replaywriter() {return m_replaywriter;}
862+ ReplayWriter* get_replaywriter() {
863+ return m_replaywriter.get();
864+ }
865
866 /**
867 * \return \c true if the game is completely loaded and running (or paused)
868 * or \c false otherwise.
869 */
870 bool is_loaded() {return m_state == gs_running;}
871- void end_dedicated_game();
872
873 void cleanup_for_load() override;
874
875@@ -217,7 +225,6 @@
876 m_target (target),
877 m_counter (0),
878 m_next_diskspacecheck(0),
879- m_dump (nullptr),
880 m_syncstreamsave(false)
881 {}
882
883@@ -238,7 +245,7 @@
884 StreamWrite & m_target;
885 uint32_t m_counter;
886 uint32_t m_next_diskspacecheck;
887- ::StreamWrite * m_dump;
888+ std::unique_ptr<::StreamWrite> m_dump;
889 std::string m_dumpfname;
890 bool m_syncstreamsave;
891 } m_syncwrapper;
892@@ -263,8 +270,7 @@
893
894 SaveHandler m_savehandler;
895
896- ReplayReader * m_replayreader;
897- ReplayWriter * m_replaywriter;
898+ std::unique_ptr<ReplayWriter> m_replaywriter;
899
900 GeneralStatsVector m_general_stats;
901
902
903=== modified file 'src/logic/game_settings.h'
904--- src/logic/game_settings.h 2016-01-28 05:24:34 +0000
905+++ src/logic/game_settings.h 2016-02-07 08:11:43 +0000
906@@ -67,12 +67,6 @@
907 bool ready; // until now only used as a check for whether user is currently receiving a file or not
908 };
909
910-struct DedicatedMapInfos {
911- std::string path;
912- uint8_t players;
913- bool scenario;
914-};
915-
916 /**
917 * Holds all settings about a game that can be configured before the
918 * game actually starts.
919@@ -130,11 +124,6 @@
920
921 /// Users connected to the game (0-based indices) - only used in multiplayer
922 std::vector<UserSettings> users;
923-
924- /// Only used for dedicated servers so the clients can look through the maps available on the server
925- /// like in their "own" map / saved games selection menu
926- std::vector<DedicatedMapInfos> maps;
927- std::vector<DedicatedMapInfos> saved_games;
928 };
929
930
931
932=== modified file 'src/main.cc'
933--- src/main.cc 2016-01-22 20:02:04 +0000
934+++ src/main.cc 2016-02-07 08:11:43 +0000
935@@ -22,10 +22,6 @@
936 #include <typeinfo>
937
938 #include <SDL_main.h>
939-#ifndef _WIN32
940-#include <fcntl.h>
941-#include <syslog.h>
942-#endif
943 #include <unistd.h>
944
945 #include "base/log.h"
946@@ -45,59 +41,6 @@
947 */
948 int main(int argc, char * argv[])
949 {
950-
951-#ifndef _WIN32
952- // if Widelands is called as dedicated server, Widelands should be forked and started as daemon
953- bool dedicated = false;
954- bool daemon = false;
955-
956- for (int i = 1; i < argc && !(daemon && dedicated); ++i) {
957- std::string opt = argv[i];
958-
959- // At least a size of 8 is needed for --daemon, --dedicated is even longer
960- if (opt.size() < 8)
961- continue;
962-
963- if (opt == "--version") {
964- cout << "Widelands " << build_id() << '(' << build_type() << ')' << "\n";
965- return 0;
966- }
967-
968- std::string::size_type const pos = opt.find('=');
969- if (pos == std::string::npos) { // if no equals sign found
970- if (opt == "--daemon")
971- daemon = true;
972- } else {
973- opt.erase(pos, opt.size() - pos);
974- if (opt == "--dedicated")
975- dedicated = true;
976- }
977- }
978- if (daemon && dedicated) {
979- pid_t pid;
980- if ((pid = fork()) < 0) {
981- perror("fork() failed");
982- exit(2);
983- }
984- if (pid == 0) {
985- setsid();
986-
987- close(STDIN_FILENO);
988- close(STDOUT_FILENO);
989- close(STDERR_FILENO);
990-
991- open("/dev/null", O_RDWR);
992- dup(STDIN_FILENO);
993- dup(STDIN_FILENO);
994- // from now on, it's a daemon
995- openlog("FREELINE", LOG_PID, LOG_DAEMON);
996- } else {
997- log("Child has PID %i.\n", pid);
998- return 0;
999- }
1000- }
1001-#endif
1002-
1003 WLApplication * g_app = nullptr;
1004 try {
1005 g_app = WLApplication::get(argc, const_cast<char const * *>(argv));
1006
1007=== modified file 'src/map_io/map_building_packet.cc'
1008--- src/map_io/map_building_packet.cc 2016-01-29 15:09:06 +0000
1009+++ src/map_io/map_building_packet.cc 2016-02-07 08:11:43 +0000
1010@@ -99,8 +99,7 @@
1011 read_priorities (*building, fr);
1012
1013 // Reference the players tribe if in editor.
1014- if (g_gr) // but not on dedicated servers ;)
1015- ibase.reference_player_tribe(p, &tribe);
1016+ ibase.reference_player_tribe(p, &tribe);
1017 } else
1018 throw GameDataError("player %u does not exist", p);
1019 }
1020
1021=== modified file 'src/network/CMakeLists.txt'
1022--- src/network/CMakeLists.txt 2015-01-31 16:03:59 +0000
1023+++ src/network/CMakeLists.txt 2016-02-07 08:11:43 +0000
1024@@ -32,7 +32,6 @@
1025 chat
1026 game_io
1027 helper
1028- io_dedicated_log
1029 io_fileread
1030 io_filesystem
1031 io_stream
1032
1033=== modified file 'src/network/internet_gaming.cc'
1034--- src/network/internet_gaming.cc 2015-10-25 15:44:36 +0000
1035+++ src/network/internet_gaming.cc 2016-02-07 08:11:43 +0000
1036@@ -26,7 +26,6 @@
1037 #include "base/log.h"
1038 #include "base/macros.h"
1039 #include "base/warning.h"
1040-#include "io/dedicated_log.h"
1041 #include "io/fileread.h"
1042 #include "io/filesystem/layered_filesystem.h"
1043 #include "network/internet_gaming_messages.h"
1044@@ -103,7 +102,7 @@
1045
1046 void InternetGaming::initialize_connection() {
1047 // First of all try to connect to the metaserver
1048- dedicatedlog("InternetGaming: Connecting to the metaserver.\n");
1049+ log("InternetGaming: Connecting to the metaserver.\n");
1050 IPaddress peer;
1051 if (hostent * const he = gethostbyname(m_meta.c_str())) {
1052 peer.host = (reinterpret_cast<in_addr *>(he->h_addr_list[0]))->s_addr;
1053@@ -147,7 +146,7 @@
1054 initialize_connection();
1055
1056 // If we are here, a connection was established and we can send our login package through the socket.
1057- dedicatedlog("InternetGaming: Sending login request.\n");
1058+ log("InternetGaming: Sending login request.\n");
1059 SendPacket s;
1060 s.string(IGPCMD_LOGIN);
1061 s.string(boost::lexical_cast<std::string>(INTERNET_GAMING_PROTOCOL_VERSION));
1062@@ -174,7 +173,7 @@
1063 return false;
1064 }
1065 }
1066- dedicatedlog("InternetGaming: No answer from metaserver!\n");
1067+ log("InternetGaming: No answer from metaserver!\n");
1068 logout("NO_ANSWER");
1069 return false;
1070 }
1071@@ -191,7 +190,7 @@
1072 initialize_connection();
1073
1074 // If we are here, a connection was established and we can send our login package through the socket.
1075- dedicatedlog("InternetGaming: Sending relogin request.\n");
1076+ log("InternetGaming: Sending relogin request.\n");
1077 SendPacket s;
1078 s.string(IGPCMD_RELOGIN);
1079 s.string(boost::lexical_cast<std::string>(INTERNET_GAMING_PROTOCOL_VERSION));
1080@@ -218,7 +217,7 @@
1081 }
1082
1083 if (INTERNET_GAMING_TIMEOUT <= time(nullptr) - secs) {
1084- dedicatedlog("InternetGaming: No answer from metaserver!\n");
1085+ log("InternetGaming: No answer from metaserver!\n");
1086 return false;
1087 }
1088
1089@@ -249,7 +248,7 @@
1090 s.send(m_sock);
1091
1092 const std::string & msg = InternetGamingMessages::get_message(msgcode);
1093- dedicatedlog("InternetGaming: logout(%s)\n", msg.c_str());
1094+ log("InternetGaming: logout(%s)\n", msg.c_str());
1095 format_and_add_chat("", "", true, msg);
1096
1097 reset();
1098@@ -269,7 +268,7 @@
1099 if (!m_deserializer.read(m_sock)) {
1100 set_error();
1101 const std::string & msg = InternetGamingMessages::get_message("CONNECTION_LOST");
1102- dedicatedlog("InternetGaming: Error: %s\n", msg.c_str());
1103+ log("InternetGaming: Error: %s\n", msg.c_str());
1104 format_and_add_chat("", "", true, msg);
1105
1106 // Check how much time passed since the socket broke the last time
1107@@ -331,7 +330,7 @@
1108 if (now > waittimeout) {
1109 set_error();
1110 waittimeout = std::numeric_limits<int32_t>::max();
1111- dedicatedlog("InternetGaming: reached a timeout for an awaited answer of the metaserver!\n");
1112+ log("InternetGaming: reached a timeout for an awaited answer of the metaserver!\n");
1113 if (!relogin()) {
1114 // Do not try to relogin again automatically.
1115 reset();
1116@@ -383,20 +382,20 @@
1117 m_clientname = packet.string();
1118 m_clientrights = packet.string();
1119 m_state = LOBBY;
1120- dedicatedlog("InternetGaming: Client %s logged in.\n", m_clientname.c_str());
1121+ log("InternetGaming: Client %s logged in.\n", m_clientname.c_str());
1122 return;
1123
1124 } else if (cmd == IGPCMD_RELOGIN) {
1125 // Clients request to relogin was granted
1126 m_state = LOBBY;
1127- dedicatedlog("InternetGaming: Client %s relogged in.\n", m_clientname.c_str());
1128+ log("InternetGaming: Client %s relogged in.\n", m_clientname.c_str());
1129 format_and_add_chat("", "", true, _("Successfully reconnected to the metaserver!"));
1130 return;
1131
1132 } else if (cmd == IGPCMD_ERROR) {
1133 std::string errortype = packet.string();
1134 if (errortype != "LOGIN" && errortype != "RELOGIN") {
1135- dedicatedlog("InternetGaming: Strange ERROR in connecting state: %s\n", errortype.c_str());
1136+ log("InternetGaming: Strange ERROR in connecting state: %s\n", errortype.c_str());
1137 throw WLWarning(_("Mixed up"), _("The metaserver sent a strange ERROR during connection"));
1138 }
1139 // Clients login request got rejected
1140@@ -419,7 +418,7 @@
1141 try {
1142 if (cmd == IGPCMD_LOGIN || cmd == IGPCMD_RELOGIN) {
1143 // Login specific commands but not in CONNECTING state...
1144- dedicatedlog
1145+ log
1146 ("InternetGaming: Received %s cmd although client is not in CONNECTING state.\n", cmd.c_str());
1147 std::string temp =
1148 (boost::format
1149@@ -431,7 +430,7 @@
1150 else if (cmd == IGPCMD_TIME) {
1151 // Client received the server time
1152 time_offset = boost::lexical_cast<int>(packet.string()) - time(nullptr);
1153- dedicatedlog
1154+ log
1155 (ngettext
1156 ("InternetGaming: Server time offset is %u second.",
1157 "InternetGaming: Server time offset is %u seconds.", time_offset),
1158@@ -471,7 +470,7 @@
1159
1160 else if (cmd == IGPCMD_GAMES_UPDATE) {
1161 // Client received a note, that the list of games was changed
1162- dedicatedlog("InternetGaming: Game update on metaserver.\n");
1163+ log("InternetGaming: Game update on metaserver.\n");
1164 gameupdateonmetaserver = true;
1165 }
1166
1167@@ -480,7 +479,7 @@
1168 uint8_t number = boost::lexical_cast<int>(packet.string()) & 0xff;
1169 std::vector<InternetGame> old = gamelist;
1170 gamelist.clear();
1171- dedicatedlog("InternetGaming: Received a game list update with %u items.\n", number);
1172+ log("InternetGaming: Received a game list update with %u items.\n", number);
1173 for (uint8_t i = 0; i < number; ++i) {
1174 InternetGame * ing = new InternetGame();
1175 ing->name = packet.string();
1176@@ -513,7 +512,7 @@
1177
1178 else if (cmd == IGPCMD_CLIENTS_UPDATE) {
1179 // Client received a note, that the list of clients was changed
1180- dedicatedlog("InternetGaming: Client update on metaserver.\n");
1181+ log("InternetGaming: Client update on metaserver.\n");
1182 clientupdateonmetaserver = true;
1183 }
1184
1185@@ -522,7 +521,7 @@
1186 uint8_t number = boost::lexical_cast<int>(packet.string()) & 0xff;
1187 std::vector<InternetClient> old = clientlist;
1188 clientlist.clear();
1189- dedicatedlog("InternetGaming: Received a client list update with %u items.\n", number);
1190+ log("InternetGaming: Received a client list update with %u items.\n", number);
1191 for (uint8_t i = 0; i < number; ++i) {
1192 InternetClient * inc = new InternetClient();
1193 inc->name = packet.string();
1194@@ -639,7 +638,7 @@
1195 s.string(gamename);
1196 s.send(m_sock);
1197 m_gamename = gamename;
1198- dedicatedlog("InternetGaming: Client tries to join a game with the name %s\n", m_gamename.c_str());
1199+ log("InternetGaming: Client tries to join a game with the name %s\n", m_gamename.c_str());
1200 m_state = IN_GAME;
1201
1202
1203@@ -660,7 +659,7 @@
1204 s.string(m_gamename);
1205 s.string("1024"); // Used to be maxclients, no longer used.
1206 s.send(m_sock);
1207- dedicatedlog("InternetGaming: Client opened a game with the name %s.\n", m_gamename.c_str());
1208+ log("InternetGaming: Client opened a game with the name %s.\n", m_gamename.c_str());
1209 m_state = IN_GAME;
1210
1211 // From now on we wait for a reply from the metaserver
1212@@ -678,7 +677,7 @@
1213 SendPacket s;
1214 s.string(IGPCMD_GAME_START);
1215 s.send(m_sock);
1216- dedicatedlog("InternetGaming: Client announced the start of the game %s.\n", m_gamename.c_str());
1217+ log("InternetGaming: Client announced the start of the game %s.\n", m_gamename.c_str());
1218
1219 // From now on we wait for a reply from the metaserver
1220 waitcmd = IGPCMD_GAME_START;
1221@@ -700,7 +699,7 @@
1222 m_gameip = "";
1223 m_state = LOBBY;
1224
1225- dedicatedlog("InternetGaming: Client announced the disconnect from the game %s.\n", m_gamename.c_str());
1226+ log("InternetGaming: Client announced the disconnect from the game %s.\n", m_gamename.c_str());
1227 }
1228
1229
1230
1231=== modified file 'src/network/netclient.cc'
1232--- src/network/netclient.cc 2016-02-04 14:00:35 +0000
1233+++ src/network/netclient.cc 2016-02-07 08:11:43 +0000
1234@@ -100,7 +100,7 @@
1235
1236 NetClient::NetClient
1237 (IPaddress * const svaddr, const std::string & playername, bool internet)
1238-: d(new NetClientImpl), m_internet(internet), m_dedicated_access(false), m_dedicated_temp_scenario(false)
1239+: d(new NetClientImpl), m_internet(internet)
1240 {
1241 d->sock = SDLNet_TCP_Open(svaddr);
1242 if (d->sock == nullptr)
1243@@ -157,17 +157,6 @@
1244 d->modal = &lgm;
1245 FullscreenMenuBase::MenuTarget code = lgm.run<FullscreenMenuBase::MenuTarget>();
1246 d->modal = nullptr;
1247- // Only possible if server is dedicated - client pressed "start game" button
1248- if (code == FullscreenMenuBase::MenuTarget::kNormalGame) {
1249- SendPacket subs;
1250- subs.unsigned_8(NETCMD_LAUNCH);
1251- subs.send(d->sock);
1252-
1253- // Reopen the menu - perhaps the start is denied or other problems occur
1254- d->modal = &lgm;
1255- code = lgm.run<FullscreenMenuBase::MenuTarget>();
1256- d->modal = nullptr;
1257- }
1258 if (code == FullscreenMenuBase::MenuTarget::kBack) {
1259 // if this is an internet game, tell the metaserver that client is back in the lobby.
1260 if (m_internet)
1261@@ -190,42 +179,37 @@
1262 tipstext.push_back("multiplayer");
1263 try {
1264 tipstext.push_back(get_players_tribe());
1265- } catch (NoTribe) {}
1266- GameTips tips (*loader_ui, tipstext);
1267+ } catch (NoTribe) {
1268+ }
1269+ GameTips tips(*loader_ui, tipstext);
1270
1271 loader_ui->step(_("Preparing game"));
1272
1273 d->game = &game;
1274 game.set_game_controller(this);
1275 uint8_t const pn = d->settings.playernum + 1;
1276- InteractiveGameBase * igb;
1277+ InteractiveGameBase* igb;
1278 if (pn > 0)
1279- igb =
1280- new InteractivePlayer
1281- (game, g_options.pull_section("global"),
1282- pn, true);
1283+ igb = new InteractivePlayer(game, g_options.pull_section("global"), pn, true);
1284 else
1285- igb =
1286- new InteractiveSpectator
1287- (game, g_options.pull_section("global"), true);
1288+ igb = new InteractiveSpectator(game, g_options.pull_section("global"), true);
1289 game.set_ibase(igb);
1290 igb->set_chat_provider(*this);
1291- if (!d->settings.savegame) // new map
1292+ if (!d->settings.savegame) { // new map
1293 game.init_newgame(loader_ui, d->settings);
1294- else // savegame
1295+ } else { // savegame
1296 game.init_savegame(loader_ui, d->settings);
1297+ }
1298 d->time.reset(game.get_gametime());
1299 d->lasttimestamp = game.get_gametime();
1300 d->lasttimestamp_realtime = SDL_GetTicks();
1301
1302 d->modal = game.get_ibase();
1303- game.run
1304- (loader_ui,
1305- d->settings.savegame ?
1306- Widelands::Game::Loaded
1307- : d->settings.scenario ?
1308- Widelands::Game::NewMPScenario : Widelands::Game::NewNonScenario,
1309- "", false);
1310+ game.run(loader_ui, d->settings.savegame ? Widelands::Game::Loaded : d->settings.scenario ?
1311+ Widelands::Game::NewMPScenario :
1312+ Widelands::Game::NewNonScenario,
1313+ "", false,
1314+ (boost::format("netclient_%d") % static_cast<int>(d->settings.usernum)).str());
1315
1316 // if this is an internet game, tell the metaserver that the game is done.
1317 if (m_internet)
1318@@ -318,38 +302,16 @@
1319 return d->settings;
1320 }
1321
1322-void NetClient::set_scenario(bool scenario)
1323-{
1324- // only accessible, if server is a dedicated server and access is granted
1325- if (!m_dedicated_access)
1326- return;
1327- m_dedicated_temp_scenario = scenario;
1328-}
1329-
1330-bool NetClient::can_change_map()
1331-{
1332- // only true, if server is a dedicated server and access is granted
1333- return m_dedicated_access;
1334-}
1335-
1336-bool NetClient::can_change_player_state(uint8_t const number)
1337-{
1338- if (!m_dedicated_access) // normal case
1339- return false;
1340-
1341- // dedicated server, access granted
1342- if (d->settings.savegame)
1343- return d->settings.players.at(number).state != PlayerSettings::stateClosed;
1344- else if (d->settings.scenario)
1345- return
1346- ((d->settings.players.at(number).state == PlayerSettings::stateOpen
1347- ||
1348- d->settings.players.at(number).state == PlayerSettings::stateHuman)
1349- &&
1350- d->settings .players.at(number).closeable)
1351- ||
1352- d->settings .players.at(number).state == PlayerSettings::stateClosed;
1353- return true;
1354+void NetClient::set_scenario(bool) {
1355+}
1356+
1357+bool NetClient::can_change_map() {
1358+ return false;
1359+}
1360+
1361+bool NetClient::can_change_player_state(uint8_t const)
1362+{
1363+ return false;
1364 }
1365
1366 bool NetClient::can_change_player_tribe(uint8_t number)
1367@@ -359,75 +321,17 @@
1368
1369 bool NetClient::can_change_player_team(uint8_t number)
1370 {
1371- if (!m_dedicated_access) // normal case
1372- return (number == d->settings.playernum) && !d->settings.scenario && !d->settings.savegame;
1373- else { // dedicated server, access granted
1374- if (d->settings.scenario || d->settings.savegame)
1375- return false;
1376- if (number >= d->settings.players.size())
1377- return false;
1378- if (number == d->settings.playernum)
1379- return true;
1380- return
1381- d->settings.players.at(number).state == PlayerSettings::stateComputer;
1382- }
1383+ return (number == d->settings.playernum) && !d->settings.scenario && !d->settings.savegame;
1384 }
1385
1386 bool NetClient::can_change_player_init(uint8_t number)
1387 {
1388- if (!m_dedicated_access) // normal case
1389- return false;
1390- else { // dedicated server, access granted
1391- if (d->settings.scenario || d->settings.savegame)
1392- return false;
1393- return number < d->settings.players.size();
1394- }
1395+ return false;
1396 }
1397
1398 bool NetClient::can_launch()
1399 {
1400- // only true, if server is a dedicated server and access is granted
1401- if (!m_dedicated_access)
1402- return false;
1403- if (d->settings.mapname.empty())
1404- return false;
1405- if (d->settings.players.size() < 1)
1406- return false;
1407- if (d->game)
1408- return false;
1409-
1410- // if there is one client that is currently receiving a file, we can not launch.
1411- for (uint8_t i = 0; i < d->settings.users.size(); ++i) {
1412- if (d->settings.users[i].position == d->settings.users[i].not_connected())
1413- continue;
1414- if (!d->settings.users[i].ready)
1415- return false;
1416- }
1417-
1418- // all players must be connected to a controller (human/ai) or be closed.
1419- for (size_t i = 0; i < d->settings.players.size(); ++i) {
1420- if (d->settings.players.at(i).state == PlayerSettings::stateOpen)
1421- return false;
1422- }
1423- return true;
1424-}
1425-
1426-void NetClient::set_map
1427- (const std::string & name,
1428- const std::string & path,
1429- uint32_t /* players */,
1430- bool savegame)
1431-{
1432- // only accessible, if server is a dedicated server and access is granted
1433- if (!m_dedicated_access)
1434- return;
1435- SendPacket s;
1436- s.unsigned_8(NETCMD_SETTING_MAP);
1437- s.string(name);
1438- s.string(path);
1439- s.unsigned_8(savegame ? 1 : 0);
1440- s.unsigned_8(m_dedicated_temp_scenario ? 1 : 0);
1441- s.send(d->sock);
1442+ return false;
1443 }
1444
1445 void NetClient::set_player_state(uint8_t, PlayerSettings::State)
1446@@ -442,18 +346,16 @@
1447
1448 void NetClient::next_player_state(uint8_t number)
1449 {
1450- // only accessible, if server is a dedicated server and access is granted
1451- if (!m_dedicated_access)
1452- return;
1453- SendPacket s;
1454- s.unsigned_8(NETCMD_SETTING_PLAYER);
1455- s.unsigned_8(number);
1456- s.send(d->sock);
1457+ // client is not allowed to do this
1458+}
1459+
1460+void NetClient::set_map(const std::string&, const std::string&, uint32_t, bool) {
1461+ // client is not allowed to do this
1462 }
1463
1464 void NetClient::set_player_tribe(uint8_t number, const std::string & tribe, bool const random_tribe)
1465 {
1466- if ((number != d->settings.playernum) && !m_dedicated_access)
1467+ if ((number != d->settings.playernum))
1468 return;
1469
1470 SendPacket s;
1471@@ -466,7 +368,7 @@
1472
1473 void NetClient::set_player_team(uint8_t number, Widelands::TeamNumber team)
1474 {
1475- if ((number != d->settings.playernum) && !m_dedicated_access)
1476+ if ((number != d->settings.playernum))
1477 return;
1478
1479 SendPacket s;
1480@@ -483,7 +385,7 @@
1481
1482 void NetClient::set_player_shared(uint8_t number, uint8_t player)
1483 {
1484- if ((number != d->settings.playernum) && !m_dedicated_access)
1485+ if ((number != d->settings.playernum))
1486 return;
1487
1488 SendPacket s;
1489@@ -495,7 +397,7 @@
1490
1491 void NetClient::set_player_init(uint8_t number, uint8_t)
1492 {
1493- if ((number != d->settings.playernum) && !m_dedicated_access)
1494+ if ((number != d->settings.playernum))
1495 return;
1496
1497 // Host will decide what to change, therefore the init is not send, just the request to change
1498@@ -526,12 +428,7 @@
1499 }
1500
1501 void NetClient::next_win_condition() {
1502- // only accessible, if server is a dedicated server and access is granted
1503- if (!m_dedicated_access)
1504- return;
1505- SendPacket s;
1506- s.unsigned_8(NETCMD_WIN_CONDITION);
1507- s.send(d->sock);
1508+ // Clients are not allowed to change this
1509 }
1510
1511 void NetClient::set_player_number(uint8_t const number)
1512@@ -723,23 +620,6 @@
1513 break;
1514 }
1515
1516- case NETCMD_DEDICATED_MAPS: {
1517- DedicatedMapInfos info;
1518- info.path = g_fs->FileSystem::fix_cross_file(packet.string());
1519- info.players = packet.unsigned_8();
1520- info.scenario = packet.unsigned_8() == 1;
1521- d->settings.maps.push_back(info);
1522- break;
1523- }
1524-
1525- case NETCMD_DEDICATED_SAVED_GAMES: {
1526- DedicatedMapInfos info;
1527- info.path = g_fs->FileSystem::fix_cross_file(packet.string());
1528- info.players = packet.unsigned_8();
1529- d->settings.saved_games.push_back(info);
1530- break;
1531- }
1532-
1533 case NETCMD_NEW_FILE_AVAILABLE: {
1534 std::string path = g_fs->FileSystem::fix_cross_file(packet.string());
1535 uint32_t bytes = packet.unsigned_32();
1536@@ -839,7 +719,6 @@
1537 fr.open(*g_fs, file->filename);
1538
1539 std::unique_ptr<char[]> complete(new char[file->bytes]);
1540- if (!complete) throw wexception("Out of memory");
1541
1542 fr.data_complete(complete.get(), file->bytes);
1543 SimpleMD5Checksum md5sum;
1544@@ -952,19 +831,23 @@
1545 d->modal->end_modal<FullscreenMenuBase::MenuTarget>(FullscreenMenuBase::MenuTarget::kOk);
1546 break;
1547 }
1548+
1549 case NETCMD_SETSPEED:
1550 d->realspeed = packet.unsigned_16();
1551 log
1552 ("[Client] speed: %u.%03u\n",
1553 d->realspeed / 1000, d->realspeed % 1000);
1554 break;
1555+
1556 case NETCMD_TIME:
1557 d->time.receive(packet.signed_32());
1558 break;
1559+
1560 case NETCMD_WAIT:
1561 log("[Client]: server is waiting.\n");
1562 d->server_is_waiting = true;
1563 break;
1564+
1565 case NETCMD_PLAYERCOMMAND: {
1566 if (!d->game)
1567 throw DisconnectException("PLAYERCMD_WO_GAME");
1568@@ -977,6 +860,7 @@
1569 d->time.receive(time);
1570 break;
1571 }
1572+
1573 case NETCMD_SYNCREQUEST: {
1574 if (!d->game)
1575 throw DisconnectException("SYNCREQUEST_WO_GAME");
1576@@ -985,6 +869,7 @@
1577 d->game->enqueue_command(new CmdNetCheckSync(time, this));
1578 break;
1579 }
1580+
1581 case NETCMD_CHAT: {
1582 ChatMessage c;
1583 c.time = time(nullptr);
1584@@ -997,6 +882,7 @@
1585 Notifications::publish(c);
1586 break;
1587 }
1588+
1589 case NETCMD_SYSTEM_MESSAGE_CODE: {
1590 ChatMessage c;
1591 c.time = time(nullptr);
1592@@ -1011,10 +897,7 @@
1593 Notifications::publish(c);
1594 break;
1595 }
1596- case NETCMD_DEDICATED_ACCESS: {
1597- m_dedicated_access = true;
1598- break;
1599- }
1600+
1601 case NETCMD_INFO_DESYNC:
1602 log
1603 ("[Client] received NETCMD_INFO_DESYNC. Trying to salvage some "
1604@@ -1022,6 +905,7 @@
1605 if (d->game)
1606 d->game->save_syncstream(true);
1607 break;
1608+
1609 default:
1610 throw ProtocolException(cmd);
1611 }
1612
1613=== modified file 'src/network/netclient.h'
1614--- src/network/netclient.h 2014-09-30 06:25:04 +0000
1615+++ src/network/netclient.h 2016-02-07 08:11:43 +0000
1616@@ -117,8 +117,6 @@
1617
1618 NetClientImpl * d;
1619 bool m_internet;
1620- bool m_dedicated_access;
1621- bool m_dedicated_temp_scenario;
1622 };
1623
1624 #endif // end of include guard: WL_NETWORK_NETCLIENT_H
1625
1626=== modified file 'src/network/nethost.cc'
1627--- src/network/nethost.cc 2016-02-04 14:00:35 +0000
1628+++ src/network/nethost.cc 2016-02-07 08:11:43 +0000
1629@@ -40,7 +40,6 @@
1630 #include "game_io/game_loader.h"
1631 #include "game_io/game_preload_packet.h"
1632 #include "helper.h"
1633-#include "io/dedicated_log.h"
1634 #include "io/fileread.h"
1635 #include "io/filesystem/layered_filesystem.h"
1636 #include "logic/game.h"
1637@@ -310,7 +309,7 @@
1638 struct HostChatProvider : public ChatProvider {
1639 HostChatProvider(NetHost * const _h) : h(_h), kickClient(0) {}
1640
1641- void send(const std::string & msg) override {
1642+ void send(const std::string& msg) override {
1643 ChatMessage c;
1644 c.time = time(nullptr);
1645 c.playern = h->get_local_playerposition();
1646@@ -337,9 +336,9 @@
1647
1648 // Split up in "cmd" "arg1" "arg2"
1649 std::string cmd, arg1, arg2;
1650- std::string temp = c.msg.substr(1); // cut off '/'
1651+ std::string temp = c.msg.substr(1); // cut off '/'
1652 h->split_command_array(temp, cmd, arg1, arg2);
1653- dedicatedlog("%s + \"%s\" + \"%s\"\n", cmd.c_str(), arg1.c_str(), arg2.c_str());
1654+ log("%s + \"%s\" + \"%s\"\n", cmd.c_str(), arg1.c_str(), arg2.c_str());
1655
1656 // let "/me" pass - handled by chat
1657 if (cmd == "me") {
1658@@ -354,32 +353,32 @@
1659
1660 // Help
1661 if (cmd == "help") {
1662- c.msg =
1663- (boost::format("<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s")
1664- % _("Available host commands are:")
1665- /** TRANSLATORS: Available host command */
1666- % _("/help - Shows this help")
1667- /** TRANSLATORS: Available host command */
1668- % _("/announce <msg> - Send a chatmessage as announcement (system chat)")
1669- /** TRANSLATORS: Available host command */
1670- % _("/warn <name> <reason> - Warn the user <name> because of <reason>")
1671- /** TRANSLATORS: Available host command */
1672- % _("/kick <name> <reason> - Kick the user <name> because of <reason>")
1673- /** TRANSLATORS: Available host command */
1674- % _("/forcePause - Force the game to pause.")
1675- /** TRANSLATORS: Available host command */
1676- % _("/endForcedPause - Return game to normal speed.")
1677- ).str();
1678- if (!h->is_dedicated())
1679- c.recipient = h->get_local_playername();
1680+ c.msg = (boost::format("<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s") %
1681+ _("Available host commands are:")
1682+ /** TRANSLATORS: Available host command */
1683+ %
1684+ _("/help - Shows this help")
1685+ /** TRANSLATORS: Available host command */
1686+ %
1687+ _("/announce <msg> - Send a chatmessage as announcement (system chat)")
1688+ /** TRANSLATORS: Available host command */
1689+ %
1690+ _("/warn <name> <reason> - Warn the user <name> because of <reason>")
1691+ /** TRANSLATORS: Available host command */
1692+ %
1693+ _("/kick <name> <reason> - Kick the user <name> because of <reason>")
1694+ /** TRANSLATORS: Available host command */
1695+ %
1696+ _("/forcePause - Force the game to pause.")
1697+ /** TRANSLATORS: Available host command */
1698+ %
1699+ _("/endForcedPause - Return game to normal speed.")).str();
1700 }
1701
1702 // Announce
1703 else if (cmd == "announce") {
1704 if (arg1.empty()) {
1705 c.msg = _("Wrong use, should be: /announce <message>");
1706- if (!h->is_dedicated())
1707- c.recipient = h->get_local_playername();
1708 } else {
1709 if (arg2.size())
1710 arg1 += " " + arg2;
1711@@ -391,22 +390,12 @@
1712 else if (cmd == "warn") {
1713 if (arg1.empty() || arg2.empty()) {
1714 c.msg = _("Wrong use, should be: /warn <name> <reason>");
1715- if (!h->is_dedicated())
1716- c.recipient = h->get_local_playername();
1717 } else {
1718 int32_t num = h->check_client(arg1);
1719- if (num == -2) {
1720- if (!h->is_dedicated()) {
1721- c.recipient = h->get_local_playername();
1722- c.msg = _("Why would you warn yourself?");
1723- } else
1724- c.msg = _("Why would you want to warn the dedicated server?");
1725- } else if (num == -1) {
1726- if (!h->is_dedicated())
1727- c.recipient = h->get_local_playername();
1728+ if (num == -1) {
1729 c.msg = (boost::format(_("The client %s could not be found.")) % arg1).str();
1730 } else {
1731- c.msg = (boost::format("HOST WARNING FOR %s: ") % arg1).str();
1732+ c.msg = (boost::format("HOST WARNING FOR %s: ") % arg1).str();
1733 c.msg += arg2;
1734 }
1735 }
1736@@ -424,22 +413,19 @@
1737 kickReason = "No reason given!";
1738 // Check if client exists
1739 int32_t num = h->check_client(kickUser);
1740- if (num == -2)
1741- if (!h->is_dedicated()) {
1742- c.msg = _("You can not kick yourself!");
1743- } else
1744- c.msg = _("You can not kick the dedicated server");
1745- else if (num == -1)
1746+ if (num == -2) {
1747+ c.msg = _("You can not kick yourself!");
1748+ } else if (num == -1) {
1749 c.msg = (boost::format(_("The client %s could not be found.")) % arg1).str();
1750- else {
1751+ } else {
1752 kickClient = num;
1753- c.msg = (boost::format(_("Are you sure you want to kick %s?")) % arg1).str() + "<br>";
1754- c.msg += (boost::format(_("The stated reason was: %s")) % kickReason).str() + "<br>";
1755+ c.msg =
1756+ (boost::format(_("Are you sure you want to kick %s?")) % arg1).str() + "<br>";
1757+ c.msg +=
1758+ (boost::format(_("The stated reason was: %s")) % kickReason).str() + "<br>";
1759 c.msg += (boost::format(_("If yes, type: /ack_kick %s")) % arg1).str();
1760 }
1761 }
1762- if (!h->is_dedicated())
1763- c.recipient = h->get_local_playername();
1764 }
1765
1766 // Acknowledge kick
1767@@ -455,18 +441,14 @@
1768 } else
1769 c.msg = _("kick acknowledgement cancelled: Wrong name given!");
1770 }
1771- kickUser = "";
1772+ kickUser = "";
1773 kickReason = "";
1774- if (!h->is_dedicated())
1775- c.recipient = h->get_local_playername();
1776 }
1777
1778 // Force Pause
1779 else if (cmd == "forcePause") {
1780 if (h->forced_pause()) {
1781 c.msg = _("Pause was already forced - game should be paused.");
1782- if (!h->is_dedicated())
1783- c.recipient = h->get_local_playername();
1784 } else {
1785 c.msg = "HOST FORCED THE GAME TO PAUSE!";
1786 h->force_pause();
1787@@ -477,8 +459,6 @@
1788 else if (cmd == "endForcedPause") {
1789 if (!h->forced_pause()) {
1790 c.msg = _("There is no forced pause - nothing to end.");
1791- if (!h->is_dedicated())
1792- c.recipient = h->get_local_playername();
1793 } else {
1794 c.msg = "HOST ENDED THE FORCED GAME PAUSE!";
1795 h->end_forced_pause();
1796@@ -488,8 +468,6 @@
1797 // Default
1798 else {
1799 c.msg = _("Invalid command! Type /help for a list of commands.");
1800- if (!h->is_dedicated())
1801- c.recipient = h->get_local_playername();
1802 }
1803 }
1804 h->send(c);
1805@@ -522,7 +500,6 @@
1806 bool syncreport_arrived;
1807 int32_t time; // last time report
1808 uint32_t desiredspeed;
1809- bool dedicated_access;
1810 time_t hung_since;
1811 /// The delta time where the last information about the hung client was sent to the other clients relative
1812 /// to when the last answer of the client was received.
1813@@ -545,9 +522,6 @@
1814 /// order as players. In fact, a client must not be assigned to a player.
1815 std::vector<Client> clients;
1816
1817- /// Set to true, once the dedicated server should start
1818- bool dedicated_start;
1819-
1820 /// The game itself; only non-null while game is running
1821 Widelands::Game * game;
1822
1823@@ -603,7 +577,6 @@
1824 syncreport_time(0),
1825 syncreport_arrived(false)
1826 {
1827- dedicated_start = false;
1828 }
1829 };
1830
1831@@ -611,12 +584,9 @@
1832 :
1833 d(new NetHostImpl(this)),
1834 m_internet(internet),
1835- m_is_dedicated(false),
1836- m_password(""),
1837- m_dedicated_motd(""),
1838 m_forced_pause(false)
1839 {
1840- dedicatedlog("[Host]: starting up.\n");
1841+ log("[Host]: starting up.\n");
1842
1843 if (internet) {
1844 InternetGaming::ref().open_game();
1845@@ -711,79 +681,18 @@
1846 }
1847 }
1848
1849-void NetHost::run(bool const autorun)
1850+void NetHost::run()
1851 {
1852- m_is_dedicated = autorun;
1853 // Fill the list of possible system messages
1854 NetworkGamingMessages::fill_map();
1855- if (m_is_dedicated) {
1856- // Initializing
1857- d->hp.next_win_condition();
1858- // May be the server is password protected?
1859- Section & s = g_options.pull_section("global");
1860- m_password = s.get_string("dedicated_password", "");
1861-
1862- // And we read the message of the day
1863- const std::string dedicated_motd_key =
1864- (boost::format
1865- (_("This is a dedicated server. Send \"@%s help\" to get a full list of available commands."))
1866- % d->localplayername).str();
1867- m_dedicated_motd = s.get_string("dedicated_motd", dedicated_motd_key.c_str());
1868-
1869- // Maybe this is the first run, so we try to setup the DedicatedLog
1870- // empty strings are treated as "do not write this type of log"
1871- DedicatedLog * dl = DedicatedLog::get();
1872- bool needip = false;
1873- if (!dl->set_log_file_path (s.get_string("dedicated_log_file_path", "")))
1874- dedicatedlog("Warning: Could not set dedicated log file path");
1875- if (!dl->set_chat_file_path(s.get_string("dedicated_chat_file_path", "")))
1876- dedicatedlog("Warning: Could not set dedicated chat file path");
1877- if (!dl->write_info_active()) {
1878- if (!dl->set_info_file_path(s.get_string("dedicated_info_file_path", "")))
1879- dedicatedlog("Warning: Could not set dedicated info file path");
1880- else {
1881- needip = true;
1882- dl->set_server_data(InternetGaming::ref().get_local_servername(), m_dedicated_motd);
1883- }
1884- }
1885-
1886- dl->chat_add_spacer();
1887- // Setup by the users
1888- log ("[Dedicated] Entering set up mode, waiting for user interaction!\n");
1889-
1890- while (!d->dedicated_start) {
1891- handle_network();
1892- // TODO(unknown): this should be improved.
1893-#ifndef _WIN32
1894- if (d->clients.empty()) {
1895- if (usleep(100000)) // Sleep for 0.1 seconds - there is not anybody connected anyways.
1896- return;
1897- if (needip && (InternetGaming::ref().ip().size() < 1)) {
1898- dl->set_server_ip(InternetGaming::ref().ip());
1899- needip = false;
1900- }
1901- } else {
1902- if (usleep(200) == -1)
1903- return;
1904- }
1905-#else
1906- if (d->clients.empty())
1907- Sleep(100);
1908- else
1909- Sleep(1);
1910-#endif
1911- }
1912- d->dedicated_start = false;
1913- } else {
1914- FullscreenMenuLaunchMPG lm(&d->hp, this);
1915- lm.set_chat_provider(d->chat);
1916- const FullscreenMenuBase::MenuTarget code = lm.run<FullscreenMenuBase::MenuTarget>();
1917- if (code == FullscreenMenuBase::MenuTarget::kBack) {
1918- // if this is an internet game, tell the metaserver that client is back in the lobby.
1919- if (m_internet)
1920- InternetGaming::ref().set_game_done();
1921- return;
1922- }
1923+ FullscreenMenuLaunchMPG lm(&d->hp, this);
1924+ lm.set_chat_provider(d->chat);
1925+ const FullscreenMenuBase::MenuTarget code = lm.run<FullscreenMenuBase::MenuTarget>();
1926+ if (code == FullscreenMenuBase::MenuTarget::kBack) {
1927+ // if this is an internet game, tell the metaserver that client is back in the lobby.
1928+ if (m_internet)
1929+ InternetGaming::ref().set_game_done();
1930+ return;
1931 }
1932
1933 // if this is an internet game, tell the metaserver that the game started
1934@@ -805,61 +714,41 @@
1935 #endif
1936
1937 try {
1938- // NOTE loader_ui will stay uninitialized, if this is run as dedicated, so all called functions need
1939- // NOTE to check whether the pointer is valid.
1940 std::unique_ptr<UI::ProgressWindow> loader_ui;
1941 GameTips * tips = nullptr;
1942- if (m_is_dedicated) {
1943- log ("[Dedicated] Starting the game...\n");
1944- d->game = &game;
1945- game.set_game_controller(this);
1946-
1947- if (d->settings.savegame) {
1948- // Read and broadcast original win condition
1949- Widelands::GameLoader gl(d->settings.mapfilename, game);
1950- Widelands::GamePreloadPacket gpdp;
1951- gl.preload_game(gpdp);
1952-
1953- set_win_condition_script(gpdp.get_win_condition());
1954- }
1955+ loader_ui.reset(new UI::ProgressWindow("images/loadscreens/progress.png"));
1956+ std::vector<std::string> tipstext;
1957+ tipstext.push_back("general_game");
1958+ tipstext.push_back("multiplayer");
1959+ try {
1960+ tipstext.push_back(d->hp.get_players_tribe());
1961+ } catch (GameSettingsProvider::NoTribe) {
1962+ }
1963+ tips = new GameTips(*loader_ui, tipstext);
1964+
1965+ loader_ui->step(_("Preparing game"));
1966+
1967+ d->game = &game;
1968+ game.set_game_controller(this);
1969+ InteractiveGameBase* igb;
1970+ uint8_t pn = d->settings.playernum + 1;
1971+
1972+ if (d->settings.savegame) {
1973+ // Read and broadcast original win condition
1974+ Widelands::GameLoader gl(d->settings.mapfilename, game);
1975+ Widelands::GamePreloadPacket gpdp;
1976+ gl.preload_game(gpdp);
1977+
1978+ set_win_condition_script(gpdp.get_win_condition());
1979+ }
1980+
1981+ if ((pn > 0) && (pn <= UserSettings::highest_playernum())) {
1982+ igb = new InteractivePlayer(game, g_options.pull_section("global"), pn, true);
1983 } else {
1984- loader_ui.reset(new UI::ProgressWindow ("images/loadscreens/progress.png"));
1985- std::vector<std::string> tipstext;
1986- tipstext.push_back("general_game");
1987- tipstext.push_back("multiplayer");
1988- try {
1989- tipstext.push_back(d->hp.get_players_tribe());
1990- } catch (GameSettingsProvider::NoTribe) {}
1991- tips = new GameTips(*loader_ui, tipstext);
1992-
1993- loader_ui->step(_("Preparing game"));
1994-
1995- d->game = &game;
1996- game.set_game_controller(this);
1997- InteractiveGameBase * igb;
1998- uint8_t pn = d->settings.playernum + 1;
1999-
2000- if (d->settings.savegame) {
2001- // Read and broadcast original win condition
2002- Widelands::GameLoader gl(d->settings.mapfilename, game);
2003- Widelands::GamePreloadPacket gpdp;
2004- gl.preload_game(gpdp);
2005-
2006- set_win_condition_script(gpdp.get_win_condition());
2007- }
2008-
2009- if ((pn > 0) && (pn <= UserSettings::highest_playernum())) {
2010- igb =
2011- new InteractivePlayer
2012- (game, g_options.pull_section("global"),
2013- pn, true);
2014- } else
2015- igb =
2016- new InteractiveSpectator
2017- (game, g_options.pull_section("global"), true);
2018- igb->set_chat_provider(d->chat);
2019- game.set_ibase(igb);
2020+ igb = new InteractiveSpectator(game, g_options.pull_section("global"), true);
2021 }
2022+ igb->set_chat_provider(d->chat);
2023+ game.set_ibase(igb);
2024
2025 if (!d->settings.savegame) // new game
2026 game.init_newgame (loader_ui.get(), d->settings);
2027@@ -879,39 +768,18 @@
2028 // wait mode when there are no clients
2029 check_hung_clients();
2030 init_computer_players();
2031- if (m_is_dedicated) {
2032- // Statistics: new game started
2033- std::vector<std::string> clients;
2034- for (uint32_t i = 0; i < d->settings.users.size(); ++i)
2035- if (d->settings.users.at(i).position != UserSettings::not_connected())
2036- if (d->settings.users.at(i).name != d->localplayername) // all names, but the dedicated server
2037- clients.push_back(d->settings.users.at(i).name);
2038- DedicatedLog::get()->game_start(clients, game.map().get_name().c_str());
2039- }
2040 game.run
2041 (loader_ui.get(),
2042 d->settings.savegame ? Widelands::Game::Loaded : d->settings.scenario ?
2043 Widelands::Game::NewMPScenario : Widelands::Game::NewNonScenario,
2044 "",
2045- false);
2046+ false, "nethost");
2047
2048 delete tips;
2049
2050 // if this is an internet game, tell the metaserver that the game is done.
2051 if (m_internet)
2052 InternetGaming::ref().set_game_done();
2053-
2054- if (m_is_dedicated) {
2055- // Statistics: game ended
2056- std::vector<std::string> winners;
2057- for (uint32_t i = 0; i < d->settings.users.size(); ++i)
2058- // We do *not* only check connected users but all, as normally the players are already
2059- // disconnected once the server reaches this line of code.
2060- if (d->settings.users.at(i).name != d->localplayername) // all names, but the dedicated server
2061- if (d->settings.users.at(i).result == Widelands::PlayerEndResult::PLAYER_WON)
2062- winners.push_back(d->settings.users.at(i).name);
2063- DedicatedLog::get()->game_end(winners);
2064- }
2065 clear_computer_players();
2066 } catch (...) {
2067 WLApplication::emergency_save(game);
2068@@ -963,11 +831,6 @@
2069
2070 for (uint32_t i = 0; i < d->computerplayers.size(); ++i)
2071 d->computerplayers.at(i)->think();
2072- } else if (m_is_dedicated) {
2073- // Take care that every player gets updated during set up time
2074- for (uint8_t i = 0; i < d->settings.players.size(); ++i) {
2075- d->npsb.refresh(i);
2076- }
2077 }
2078 }
2079
2080@@ -997,9 +860,6 @@
2081 if (msg.msg.empty())
2082 return;
2083
2084- if (is_dedicated())
2085- DedicatedLog::get()->chat(msg);
2086-
2087 if (msg.recipient.empty()) {
2088 SendPacket s;
2089 s.unsigned_8(NETCMD_CHAT);
2090@@ -1016,9 +876,6 @@
2091
2092 // Is this a pm for the host player?
2093 if (d->localplayername == msg.recipient) {
2094- // If this is a dedicated server, handle commands
2095- if (m_is_dedicated)
2096- handle_dserver_command(msg.msg, msg.sender);
2097 d->chat.receive(msg);
2098 // Write the SendPacket - will be used below to show that the message
2099 // was received.
2100@@ -1036,7 +893,7 @@
2101 s.unsigned_8(1);
2102 s.string(msg.recipient);
2103 s.send(d->clients.at(clientnum).sock);
2104- dedicatedlog("[Host]: personal chat: from %s to %s\n", msg.sender.c_str(), msg.recipient.c_str());
2105+ log("[Host]: personal chat: from %s to %s\n", msg.sender.c_str(), msg.recipient.c_str());
2106 } else {
2107 std::string fail = "Failed to send message: Recipient \"";
2108 fail += msg.recipient + "\" could not be found!";
2109@@ -1068,8 +925,6 @@
2110 else if (d->localplayername == msg.sender)
2111 d->chat.receive(msg);
2112 else { // host is not the sender -> get sender
2113- if (d->localplayername == msg.recipient && m_is_dedicated)
2114- return; // There will be an immediate answer from the host
2115 uint16_t i = 0;
2116 for (; i < d->settings.users.size(); ++i) {
2117 const UserSettings & user = d->settings.users.at(i);
2118@@ -1085,10 +940,10 @@
2119 s.send(d->clients.at(j).sock);
2120 else
2121 // Better no wexception it would break the whole game
2122- dedicatedlog("WARNING: user was found but no client is connected to it!\n");
2123+ log("WARNING: user was found but no client is connected to it!\n");
2124 } else
2125 // Better no wexception it would break the whole game
2126- dedicatedlog("WARNING: sender could not be found!");
2127+ log("WARNING: sender could not be found!");
2128 }
2129 }
2130 }
2131@@ -1164,217 +1019,6 @@
2132 arg2 = "";
2133 }
2134
2135-
2136-/**
2137- * This function is used to handle commands for the dedicated server
2138- */
2139-void NetHost::handle_dserver_command(std::string cmdarray, std::string sender)
2140-{
2141- assert(m_is_dedicated);
2142-
2143- ChatMessage c;
2144- c.time = time(nullptr);
2145- c.playern = -2;
2146- c.sender = d->localplayername;
2147- c.recipient = sender;
2148-
2149- // Find the client that send the chat message
2150- int32_t num = check_client(sender);
2151- if (num < 0) // host or not found
2152- return;
2153- Client & client = d->clients[num];
2154-
2155- if (cmdarray.size() < 1) {
2156- return;
2157- }
2158-
2159- // Split up in "cmd" "arg1" "arg2"
2160- std::string cmd, arg1, arg2;
2161- split_command_array(cmdarray, cmd, arg1, arg2);
2162-
2163- // help
2164- if (cmd == "help") {
2165- if (d->game)
2166- c.msg =
2167- (boost::format("<br>%s<br>%s<br>%s<br>%s")
2168- % _("Available host commands are:")
2169- /** TRANSLATORS: Available host command */
2170- % _("/help - Shows this help")
2171- /** TRANSLATORS: Available host command */
2172- % _("host $ - Tries to run the host command $")
2173- /** TRANSLATORS: Available host command */
2174- % _("save $ - Saves the current game state as $.wgf")
2175- ).str();
2176- else
2177- c.msg =
2178- (boost::format("<br>%s<br>%s<br>%s")
2179- % _("Available host commands are:")
2180- /** TRANSLATORS: Available host command */
2181- % _("/help - Shows this help")
2182- /** TRANSLATORS: Available host command */
2183- % _("host $ - Tries to run the host command $")
2184- ).str();
2185- if (m_password.size() > 1) {
2186- c.msg += "<br>";
2187- c.msg += _("pwd $ - Sends the password $ to the host");
2188- }
2189- send(c);
2190-
2191- // host
2192- } else if (cmd == "host") {
2193- if (!client.dedicated_access) {
2194- c.msg = _("Access to host commands denied. To gain access, send the password with pwd command.");
2195- send(c);
2196- return;
2197- }
2198- std::string temp = arg1 + " " + arg2;
2199- c.msg = (boost::format(_("%1$s told me to run the command: \"%2$s\"")) % sender % temp).str();
2200- c.recipient = "";
2201- send(c);
2202- d->chat.send(temp);
2203-
2204- } else if (cmd == "save") {
2205- // Check whether saving is allowed at all
2206- Section & s = g_options.pull_section("global");
2207- if (!s.get_bool("dedicated_saving", true)) {
2208- c.msg = _("Sorry! Saving was deactivated on this dedicated server!");
2209- send(c);
2210- } else if (!d->game) {
2211- c.msg = _("Cannot save while there is no game running!");
2212- send(c);
2213- } else {
2214- //try to save the game
2215- std::string savename = "save/" + arg1;
2216- if (!arg2.empty()) { // only add space and arg2, if arg2 has anything to print.
2217- savename += " " + arg2;
2218- }
2219- savename += ".wgf";
2220- std::string * error = new std::string();
2221- SaveHandler & sh = d->game->save_handler();
2222- if (sh.save_game(*d->game, savename, error))
2223- c.msg = _("Game successfully saved!");
2224- else
2225- c.msg =
2226- (boost::format(_("Could not save the game to the file \"%1$s\"! (%2$s)"))
2227- % savename % error)
2228- .str();
2229- send(c);
2230- delete error;
2231- }
2232-
2233- } else if (cmd == "pwd") {
2234- if (m_password.empty()) {
2235- c.msg = _("This server is not password protected!");
2236- send(c);
2237- } else if (arg1 != m_password) {
2238- c.msg = _("The sent password was incorrect!");
2239- send(c);
2240- } else {
2241- // Once the client gained access (s)he might need the knowledge about available maps and saved games
2242- dserver_send_maps_and_saves(client);
2243-
2244- // Send the client the access granted message
2245- SendPacket s;
2246- s.reset();
2247- s.unsigned_8(NETCMD_DEDICATED_ACCESS);
2248- s.send(client.sock);
2249- client.dedicated_access = true;
2250-
2251- c.msg = _("The password was correct, access was granted!");
2252- send(c);
2253- }
2254-
2255- // default
2256- } else {
2257- c.msg = (boost::format(_("Unknown dedicated server command \"%s\"!")) % cmd).str();
2258- send(c);
2259- }
2260-}
2261-
2262-void NetHost::dserver_send_maps_and_saves(Client & client) {
2263- assert (!d->game);
2264-
2265- if (d->settings.maps.empty()) {
2266- // Read in maps
2267- std::vector<std::string> directories;
2268- directories.push_back("maps");
2269- while (!directories.empty()) {
2270- FilenameSet files = g_fs->list_directory(directories.at(directories.size() - 1).c_str());
2271- directories.resize(directories.size() - 1);
2272- Widelands::Map map;
2273- for (const std::string& filename : files) {
2274- std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(filename);
2275- if (ml) {
2276- map.set_filename(filename);
2277- ml->preload_map(true);
2278- DedicatedMapInfos info;
2279- info.path = filename;
2280- info.players = map.get_nrplayers();
2281- info.scenario = map.scenario_types() & Widelands::Map::MP_SCENARIO;
2282- d->settings.maps.push_back(info);
2283- } else {
2284- if
2285- (g_fs->is_directory(filename)
2286- &&
2287- strcmp(FileSystem::fs_filename(filename.c_str()), ".")
2288- &&
2289- strcmp(FileSystem::fs_filename(filename.c_str()), ".."))
2290- {
2291- directories.push_back(filename);
2292- }
2293- }
2294- }
2295- }
2296- }
2297-
2298- if (d->settings.saved_games.empty()) {
2299- // Read in saved games
2300- FilenameSet files = g_fs->list_directory("save");
2301- Widelands::Game game;
2302- Widelands::GamePreloadPacket gpdp;
2303- const FilenameSet & gamefiles = files;
2304- for (const std::string& temp_filenames : gamefiles) {
2305- char const * const name = temp_filenames.c_str();
2306- try {
2307- Widelands::GameLoader gl(name, game);
2308- gl.preload_game(gpdp);
2309-
2310- // If we are here, the saved game is valid
2311- std::unique_ptr<FileSystem> sg_fs(g_fs->make_sub_file_system(name));
2312- Profile prof;
2313- prof.read("map/elemental", nullptr, *sg_fs);
2314- Section & s = prof.get_safe_section("global");
2315-
2316- DedicatedMapInfos info;
2317- info.path = name;
2318- info.players = static_cast<uint8_t>(s.get_safe_int("nr_players"));
2319- d->settings.saved_games.push_back(info);
2320- } catch (const WException &) {}
2321- }
2322- }
2323-
2324- SendPacket s;
2325-
2326- // Send list of maps
2327- for (uint8_t i = 0; i < d->settings.maps.size(); ++i) {
2328- s.reset();
2329- s.unsigned_8(NETCMD_DEDICATED_MAPS);
2330- s.string (d->settings.maps[i].path);
2331- s.unsigned_8(d->settings.maps[i].players);
2332- s.unsigned_8(d->settings.maps[i].scenario ? 1 : 0);
2333- s.send(client.sock);
2334- }
2335-
2336- // Send list of saved games
2337- for (uint8_t i = 0; i < d->settings.saved_games.size(); ++i) {
2338- s.reset();
2339- s.unsigned_8(NETCMD_DEDICATED_SAVED_GAMES);
2340- s.string (d->settings.saved_games[i].path);
2341- s.unsigned_8(d->settings.saved_games[i].players);
2342- s.send(client.sock);
2343- }
2344-}
2345-
2346 void NetHost::send_system_message_code
2347 (const std::string & code, const std::string & a, const std::string & b, const std::string & c)
2348 {
2349@@ -1394,8 +1038,6 @@
2350 msg.playern = UserSettings::none(); // == System message
2351 // c.sender remains empty to indicate a system message
2352 d->chat.receive(msg);
2353- if (m_is_dedicated)
2354- DedicatedLog::get()->chat(msg);
2355 }
2356
2357 int32_t NetHost::get_frametime()
2358@@ -1962,7 +1604,7 @@
2359 bool NetHost::write_map_transfer_info(SendPacket & s, std::string mapfilename) {
2360 // TODO(unknown): not yet able to handle directory type maps / savegames
2361 if (g_fs->is_directory(mapfilename)) {
2362- dedicatedlog("Map/Save is a directory! No way for making it available a.t.m.!\n");
2363+ log("Map/Save is a directory! No way for making it available a.t.m.!\n");
2364 return false;
2365 }
2366
2367@@ -2027,13 +1669,8 @@
2368 assert(client.playernum == UserSettings::not_connected());
2369 assert(client.sock);
2370
2371- // Just for statistics
2372- DedicatedLog::get()->client_login();
2373-
2374 // The client gets its own initial data set.
2375 client.playernum = UserSettings::none();
2376- // only used at password protected dedicated server, but better initialize always
2377- client.dedicated_access = m_is_dedicated ? (m_password.empty()) : false;
2378
2379 if (!d->game) // just in case we allow connection of spectators/players after game start
2380 for (uint32_t i = 0; i < d->settings.users.size(); ++i)
2381@@ -2066,7 +1703,7 @@
2382 d->settings.users.at(client.usernum).name = effective_name;
2383 d->settings.users.at(client.usernum).position = UserSettings::none();
2384
2385- dedicatedlog("[Host]: Client %u: welcome to usernum %u\n", number, client.usernum);
2386+ log("[Host]: Client %u: welcome to usernum %u\n", number, client.usernum);
2387
2388 SendPacket s;
2389 s.unsigned_8(NETCMD_HELLO);
2390@@ -2135,34 +1772,6 @@
2391 }
2392
2393 send_system_message_code("CLIENT_HAS_JOINED_GAME", effective_name);
2394-
2395- // If this is a dedicated server, inform the player
2396- if (m_is_dedicated) {
2397- ChatMessage c;
2398- c.time = time(nullptr);
2399- c.playern = -2;
2400- c.sender = d->localplayername;
2401- // Send the message of the day if exists
2402- c.msg = "<br>" + m_dedicated_motd;
2403- if (m_password.size() > 1) {
2404- c.msg += "<br>";
2405- c.msg +=
2406- (boost::format
2407- (_("This server is password protected. You can send the password with: \"@%s pwd PASSWORD\""))
2408- % d->localplayername)
2409- .str();
2410- } else {
2411- // Once the client gained access it might need the knowledge about available maps and saved games
2412- dserver_send_maps_and_saves(client);
2413-
2414- // If not password protected, give the client access to the settings
2415- s.reset();
2416- s.unsigned_8(NETCMD_DEDICATED_ACCESS);
2417- s.send(client.sock);
2418- }
2419- c.recipient = d->settings.users.at(client.usernum).name;
2420- send(c);
2421- }
2422 }
2423
2424 void NetHost::committed_network_time(int32_t const time)
2425@@ -2194,7 +1803,7 @@
2426 }
2427
2428 client.time = time;
2429- dedicatedlog("[Host]: Client %i: Time %i\n", number, time);
2430+ log("[Host]: Client %i: Time %i\n", number, time);
2431
2432 if (d->waiting) {
2433 log
2434@@ -2253,29 +1862,6 @@
2435 d->settings.users.at(d->clients.at(i).usernum).name,
2436 seconds.c_str());
2437 d->clients.at(i).lastdelta = deltanow;
2438- if (m_is_dedicated) {
2439- seconds = (boost::format("%li") % (300 - deltanow)).str();
2440- send_system_message_code
2441- ("CLIENT_HUNG_AUTOKICK",
2442- d->settings.users.at(d->clients.at(i).usernum).name,
2443- seconds.c_str());
2444- }
2445- }
2446-
2447- // If this is a dedicated server, there is no host that cares about kicking hung players
2448- // This is especially problematic, if the last or all players hung and the dedicated
2449- // server does not automatically restart.
2450- // 5 minutes for all other players to react before the dedicated server takes care
2451- // about the situation itself
2452- if ((d->clients.at(i).hung_since < (time(nullptr) - 300)) && m_is_dedicated) {
2453- disconnect_client(i, "CLIENT_TIMEOUTED");
2454- // Try to save the game
2455- std::string savename = (boost::format("save/client_hung_%i.wmf") % time(nullptr)).str();
2456- std::string * error = new std::string();
2457- SaveHandler & sh = d->game->save_handler();
2458- if (sh.save_game(*d->game, savename, error))
2459- send_system_message_code("GAME_SAVED_AS", savename);
2460- delete error;
2461 }
2462 }
2463 }
2464@@ -2284,7 +1870,7 @@
2465
2466 if (!d->waiting) {
2467 if (nrhung) {
2468- dedicatedlog("[Host]: %i clients hung. Entering wait mode\n", nrhung);
2469+ log("[Host]: %i clients hung. Entering wait mode\n", nrhung);
2470
2471 // Brake and wait
2472 d->waiting = true;
2473@@ -2347,14 +1933,12 @@
2474 // No pause was forced - normal speed calculation
2475 std::vector<uint32_t> speeds;
2476
2477- if (!m_is_dedicated)
2478- speeds.push_back(d->localdesiredspeed);
2479+ speeds.push_back(d->localdesiredspeed);
2480 for (uint32_t i = 0; i < d->clients.size(); ++i) {
2481 if (d->clients.at(i).playernum <= UserSettings::highest_playernum())
2482 speeds.push_back(d->clients.at(i).desiredspeed);
2483 }
2484- if (speeds.empty()) // Possible in dedicated server games with only spectators
2485- return;
2486+ assert(!speeds.empty());
2487
2488 std::sort(speeds.begin(), speeds.end());
2489
2490@@ -2395,7 +1979,7 @@
2491 for (uint32_t i = 0; i < d->clients.size(); ++i)
2492 d->clients.at(i).syncreport_arrived = false;
2493
2494- dedicatedlog("[Host]: Requesting sync reports for time %i\n", d->syncreport_time);
2495+ log("[Host]: Requesting sync reports for time %i\n", d->syncreport_time);
2496
2497 SendPacket s;
2498 s.unsigned_8(NETCMD_SYNCREQUEST);
2499@@ -2425,7 +2009,7 @@
2500 }
2501
2502 d->syncreport_pending = false;
2503- dedicatedlog("[Host]: comparing syncreports for time %i\n", d->syncreport_time);
2504+ log("[Host]: comparing syncreports for time %i\n", d->syncreport_time);
2505
2506 for (uint32_t i = 0; i < d->clients.size(); ++i) {
2507 Client & client = d->clients.at(i);
2508@@ -2474,7 +2058,7 @@
2509
2510 // Check for new connections.
2511 while (d->svsock != nullptr && (sock = SDLNet_TCP_Accept(d->svsock)) != nullptr) {
2512- dedicatedlog("[Host]: Received a connection request\n");
2513+ log("[Host]: Received a connection request\n");
2514
2515 SDLNet_TCP_AddSocket (d->sockset, sock);
2516
2517@@ -2571,7 +2155,7 @@
2518
2519 if (client.playernum == UserSettings::not_connected()) {
2520 if (cmd == NETCMD_METASERVER_PING) {
2521- dedicatedlog("[Host]: Received ping from metaserver.\n");
2522+ log("[Host]: Received ping from metaserver.\n");
2523 // Send PING back
2524 SendPacket s;
2525 s.unsigned_8(NETCMD_METASERVER_PING);
2526@@ -2606,56 +2190,12 @@
2527
2528 switch (cmd) {
2529 case NETCMD_PONG:
2530- dedicatedlog("[Host]: Client %u: got pong\n", i);
2531+ log("[Host]: Client %u: got pong\n", i);
2532 break;
2533
2534 case NETCMD_SETTING_MAP:
2535 if (!d->game) {
2536- // Only valid if the server is dedicated and the client was granted access
2537- if (!client.dedicated_access)
2538- throw DisconnectException("NO_ACCESS_TO_SERVER");
2539-
2540- // We want to skip past the name, so read that but don't do anything with it
2541- r.string();
2542- std::string path = g_fs->FileSystem::fix_cross_file(r.string());
2543- bool savegame = r.unsigned_8() == 1;
2544- bool scenario = r.unsigned_8() == 1;
2545- if (savegame) {
2546- if (g_fs->file_exists(path)) {
2547- // Check if file is a saved game and if yes read out the needed data
2548- try {
2549- Widelands::Game game;
2550- Widelands::GamePreloadPacket gpdp;
2551- Widelands::GameLoader gl(path, game);
2552- gl.preload_game(gpdp);
2553-
2554- // If we are here, it is a saved game file :)
2555- // Read the needed data from file "elemental" of the used map.
2556- std::unique_ptr<FileSystem> sg_fs(g_fs->make_sub_file_system(path.c_str()));
2557- Profile prof;
2558- prof.read("map/elemental", nullptr, *sg_fs);
2559- Section & s = prof.get_safe_section("global");
2560- uint8_t nr_players = s.get_safe_int("nr_players");
2561-
2562- d->settings.scenario = false;
2563- d->hp.set_map(gpdp.get_mapname(), path, nr_players, true);
2564- } catch (const WException &) {}
2565- }
2566- } else {
2567- if (g_fs->file_exists(path)) {
2568- // Check if file is a map and if yes read out the needed data
2569- Widelands::Map map;
2570- i18n::Textdomain td("maps");
2571- std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(path);
2572- if (ml != nullptr) {
2573- // Yes it is a map file :)
2574- map.set_filename(path);
2575- ml->preload_map(true);
2576- d->settings.scenario = scenario;
2577- d->hp.set_map(map.get_name(), path, map.get_nrplayers(), false);
2578- }
2579- }
2580- }
2581+ throw DisconnectException("NO_ACCESS_TO_SERVER");
2582 }
2583 break;
2584
2585@@ -2665,9 +2205,7 @@
2586 if (!d->game) {
2587 uint8_t num = r.unsigned_8();
2588 if (num != client.playernum)
2589- // Only valid if the server is dedicated and the client was granted access
2590- if (!client.dedicated_access)
2591- throw DisconnectException("NO_ACCESS_TO_PLAYER");
2592+ throw DisconnectException("NO_ACCESS_TO_PLAYER");
2593 std::string tribe = r.string();
2594 bool random_tribe = r.unsigned_8() == 1;
2595 set_player_tribe(num, tribe, random_tribe);
2596@@ -2680,9 +2218,7 @@
2597 if (!d->game) {
2598 uint8_t num = r.unsigned_8();
2599 if (num != client.playernum)
2600- // Only valid if the server is dedicated and the client was granted access
2601- if (!client.dedicated_access)
2602- throw DisconnectException("NO_ACCESS_TO_PLAYER");
2603+ throw DisconnectException("NO_ACCESS_TO_PLAYER");
2604 set_player_shared(num, r.unsigned_8());
2605 }
2606 break;
2607@@ -2691,9 +2227,7 @@
2608 if (!d->game) {
2609 uint8_t num = r.unsigned_8();
2610 if (num != client.playernum)
2611- // Only valid if the server is dedicated and the client was granted access
2612- if (!client.dedicated_access)
2613- throw DisconnectException("NO_ACCESS_TO_PLAYER");
2614+ throw DisconnectException("NO_ACCESS_TO_PLAYER");
2615 set_player_team(num, r.unsigned_8());
2616 }
2617 break;
2618@@ -2702,9 +2236,7 @@
2619 if (!d->game) {
2620 uint8_t num = r.unsigned_8();
2621 if (num != client.playernum)
2622- // Only valid if the server is dedicated and the client was granted access
2623- if (!client.dedicated_access)
2624- throw DisconnectException("NO_ACCESS_TO_PLAYER");
2625+ throw DisconnectException("NO_ACCESS_TO_PLAYER");
2626 d->npsb.toggle_init(num);
2627 }
2628 break;
2629@@ -2718,30 +2250,19 @@
2630
2631 case NETCMD_SETTING_PLAYER:
2632 if (!d->game) {
2633- // Only valid if the server is dedicated and the client was granted access
2634- if (!client.dedicated_access)
2635- throw DisconnectException("NO_ACCESS_TO_SERVER");
2636- d->hp.next_player_state(r.unsigned_8());
2637+ throw DisconnectException("NO_ACCESS_TO_SERVER");
2638 }
2639 break;
2640
2641 case NETCMD_WIN_CONDITION:
2642 if (!d->game) {
2643- // Only valid if the server is dedicated and the client was granted access
2644- if (!client.dedicated_access)
2645- throw DisconnectException("NO_ACCESS_TO_SERVER");
2646- d->hp.next_win_condition();
2647+ throw DisconnectException("NO_ACCESS_TO_SERVER");
2648 }
2649 break;
2650
2651 case NETCMD_LAUNCH:
2652 if (!d->game) {
2653- // Only valid if the server is dedicated and the client was granted access
2654- if (!client.dedicated_access)
2655- throw DisconnectException("NO_ACCESS_TO_SERVER");
2656- if (!can_launch())
2657- throw DisconnectException("START_SENT_NOT_READY");
2658- d->dedicated_start = true;
2659+ throw DisconnectException("NO_ACCESS_TO_SERVER");
2660 }
2661 break;
2662
2663@@ -2822,7 +2343,7 @@
2664 uint32_t part = r.unsigned_32();
2665 std::string x = r.string();
2666 if (x != file->md5sum) {
2667- dedicatedlog("[Host]: File transfer checksum missmatch %s != %s\n", x.c_str(), file->md5sum.c_str());
2668+ log("[Host]: File transfer checksum missmatch %s != %s\n", x.c_str(), file->md5sum.c_str());
2669 return; // Surely the file was changed, so we cancel here.
2670 }
2671 if (part >= file->parts.size())
2672@@ -2871,7 +2392,7 @@
2673
2674 void NetHost::disconnect_player_controller(uint8_t const number, const std::string & name)
2675 {
2676- dedicatedlog("[Host]: disconnect_player_controller(%u, %s)\n", number, name.c_str());
2677+ log("[Host]: disconnect_player_controller(%u, %s)\n", number, name.c_str());
2678
2679 for (uint32_t i = 0; i < d->settings.users.size(); ++i) {
2680 if (d->settings.users.at(i).position == number) {
2681@@ -2922,13 +2443,10 @@
2682 s.unsigned_32(client.usernum);
2683 write_setting_user(s, client.usernum);
2684 broadcast(s);
2685-
2686- // Just for statistics
2687- DedicatedLog::get()->client_logout();
2688 } else
2689 send_system_message_code("UNKNOWN_LEFT_GAME", reason, arg);
2690
2691- dedicatedlog("[Host]: disconnect_client(%u, %s, %s)\n", number, reason.c_str(), arg.c_str());
2692+ log("[Host]: disconnect_client(%u, %s, %s)\n", number, reason.c_str(), arg.c_str());
2693
2694 if (client.sock) {
2695 if (sendreason) {
2696@@ -2948,16 +2466,7 @@
2697
2698 if (d->game) {
2699 check_hung_clients();
2700- if (m_is_dedicated) {
2701- // Check whether there is at least one client connected. If not, stop the game.
2702- for (uint32_t i = 0; i < d->clients.size(); ++i)
2703- if (d->clients.at(i).playernum != UserSettings::not_connected())
2704- return;
2705- d->game->end_dedicated_game();
2706- dedicatedlog("[Dedicated] Stopping the running game...\n");
2707- }
2708 }
2709-
2710 }
2711
2712 /**
2713@@ -3004,7 +2513,7 @@
2714 }
2715 }
2716
2717- dedicatedlog
2718+ log
2719 ("NetHost::report_result(%d, %u, %s)\n",
2720 player->player_number(), static_cast<uint8_t>(result), info.c_str());
2721 }
2722
2723=== modified file 'src/network/nethost.h'
2724--- src/network/nethost.h 2014-09-30 06:25:04 +0000
2725+++ src/network/nethost.h 2016-02-07 08:11:43 +0000
2726@@ -40,7 +40,7 @@
2727 NetHost (const std::string & playername, bool internet = false);
2728 virtual ~NetHost ();
2729
2730- void run(bool autostart = false);
2731+ void run();
2732 const std::string & get_local_playername() const;
2733 int16_t get_local_playerposition();
2734
2735@@ -90,8 +90,6 @@
2736 void kick_user(uint32_t, std::string);
2737 void split_command_array
2738 (const std::string & cmdarray, std::string & cmd, std::string & arg1, std::string & arg2);
2739- void handle_dserver_command(std::string, std::string);
2740- void dserver_send_maps_and_saves(Client &);
2741
2742 void report_result(uint8_t player, Widelands::PlayerEndResult result, const std::string & info) override;
2743
2744@@ -107,8 +105,6 @@
2745
2746 bool forced_pause() {return m_forced_pause;}
2747
2748- bool is_dedicated() {return m_is_dedicated;}
2749-
2750 private:
2751 NetTransferFile * file;
2752
2753@@ -159,9 +155,6 @@
2754
2755 NetHostImpl * d;
2756 bool m_internet;
2757- bool m_is_dedicated;
2758- std::string m_password;
2759- std::string m_dedicated_motd;
2760 bool m_forced_pause;
2761 };
2762
2763
2764=== modified file 'src/network/network_protocol.h'
2765--- src/network/network_protocol.h 2014-09-20 09:37:47 +0000
2766+++ src/network/network_protocol.h 2016-02-07 08:11:43 +0000
2767@@ -153,7 +153,6 @@
2768
2769 /**
2770 * During game setup, this command is sent by the host to advise clients of a map change.
2771- * Or by a client on a dedicated server to advise a map change.
2772 *
2773 * Payload is:
2774 * \li string: human readable mapname
2775@@ -183,8 +182,6 @@
2776 * During game setup, this command updates the information associated to
2777 * one player slot.
2778 *
2779- * The client sends this command to toggle the player type. This is only available if the server is
2780- * dedicated and the client was granted access.
2781 * Payload in that case is:
2782 * \li unsigned_8: number of the player
2783 *
2784@@ -216,7 +213,6 @@
2785
2786 /**
2787 * Sent by the host during game setup to indicate that the game starts.
2788- * Alternatively sent by the client to start a dedicated server.
2789 *
2790 * The client must load the map and setup the game. As soon as the game
2791 * is fully loaded, it must behave as if a \ref NETCMD_WAIT command had
2792@@ -369,10 +365,9 @@
2793 NETCMD_FILE_PART = 24,
2794
2795 /**
2796- * Sent by the host (or by the client if access was granted to dedicated server)
2797- * to change the win condition.
2798+ * Sent by the host to change the win condition.
2799 *
2800- * If sent by the host, attached data is:
2801+ * Attached data is:
2802 * \li string: name of the win condition
2803 *
2804 * If sent by the client, no data is attached, as it is only a request to toggle
2805@@ -420,34 +415,11 @@
2806 */
2807 NETCMD_SETTING_CHANGEINIT = 28,
2808
2809- /**
2810- * This is sent by the server to grant access to the settings (as well as to acknowledge the correct
2811- * password if the server is password protected)
2812- */
2813- NETCMD_DEDICATED_ACCESS = 29,
2814-
2815- /**
2816- * This is sent by the dedicated server to inform the client about the available maps on the dedicated
2817- * server. Payload is:
2818- *
2819- * \li string: Path to the map file
2820- * \li unsigned_8: Number of maximum players
2821- * \li bool: Whether this map can be played as multiplayer scenario
2822- */
2823- NETCMD_DEDICATED_MAPS = 30,
2824-
2825- /**
2826- * This is sent by the dedicated server to inform the client about the available saved games on the
2827- * dedicated server. Payload is:
2828- *
2829- * \li string: Path to the map file
2830- * \li unsigned_8: Number of maximum players
2831- */
2832- NETCMD_DEDICATED_SAVED_GAMES = 31,
2833-
2834- /**
2835- * This is sent by the dedicated server to generate a clientsided translated system chat message.
2836- * Payload is:
2837+ // 29 - 31 were commands related to dedicated server. Do not use.
2838+
2839+ /**
2840+ * This is sent by the server to generate a clientsided translated system
2841+ * chat message. Payload is:
2842 *
2843 * \li string: Message code \see NetworkGamingMessages::fill_map()
2844 * \li string: First attached string
2845
2846=== modified file 'src/sound/sound_handler.h'
2847--- src/sound/sound_handler.h 2015-10-18 15:41:10 +0000
2848+++ src/sound/sound_handler.h 2016-02-07 08:11:43 +0000
2849@@ -229,7 +229,6 @@
2850 Widelands::EditorGameBase * egbase_;
2851
2852 /** Only for buffering the command line option --nosound until real initialization is done.
2853- * And disabling sound on dedicated servers
2854 * \see SoundHandler::SoundHandler()
2855 * \see SoundHandler::init()
2856 */
2857
2858=== modified file 'src/ui_fsmenu/launch_mpg.cc'
2859--- src/ui_fsmenu/launch_mpg.cc 2016-02-04 09:10:44 +0000
2860+++ src/ui_fsmenu/launch_mpg.cc 2016-02-07 08:11:43 +0000
2861@@ -433,16 +433,6 @@
2862 UI::WLMessageBox::MBoxType::kOk);
2863 warning.run<UI::Panel::Returncodes>();
2864 }
2865- } else {
2866- if (!settings_ || settings_->settings().saved_games.empty())
2867- throw wexception("A file was selected, that is not available to the client");
2868- // this file is obviously a file from the dedicated server's saved games pool not available locally.
2869- for (uint32_t i = 0; i < settings_->settings().saved_games.size(); ++i)
2870- if (settings_->settings().saved_games.at(i).path == filename) {
2871- settings_->set_map(filename, filename, settings_->settings().saved_games.at(i).players, true);
2872- return;
2873- }
2874- throw wexception("The selected file could not be found in the pool of dedicated saved games.");
2875 }
2876 }
2877
2878
2879=== modified file 'src/ui_fsmenu/loadgame.cc'
2880--- src/ui_fsmenu/loadgame.cc 2016-02-04 09:10:44 +0000
2881+++ src/ui_fsmenu/loadgame.cc 2016-02-07 08:11:43 +0000
2882@@ -435,188 +435,173 @@
2883 games_data_.clear();
2884 table_.clear();
2885
2886-
2887- if (settings_ && !settings_->settings().saved_games.empty()) {
2888+ FilenameSet gamefiles;
2889+
2890+ if (is_replay_) {
2891+ gamefiles = filter(g_fs->list_directory(REPLAY_DIR),
2892+ [](const std::string& fn) {return boost::ends_with(fn, REPLAY_SUFFIX);});
2893+ } else {
2894+ gamefiles = g_fs->list_directory("save");
2895+ }
2896+
2897+ Widelands::GamePreloadPacket gpdp;
2898+
2899+ for (const std::string& gamefilename : gamefiles) {
2900+ if (gamefilename == "save/campvis" || gamefilename == "save\\campvis") {
2901+ continue;
2902+ }
2903+
2904 SavegameData gamedata;
2905- for (uint32_t i = 0; i < settings_->settings().saved_games.size(); ++i) {
2906- gamedata.filename = settings_->settings().saved_games.at(i).path;
2907- games_data_.push_back(gamedata);
2908-
2909- UI::Table<uintptr_t const>::EntryRecord & te =
2910- table_.add(games_data_.size() - 1);
2911- te.set_string(0, FileSystem::filename_without_ext(gamedata.filename.c_str()).c_str());
2912- }
2913- } else { // Normal case
2914- // Fill it with all files we find.
2915-
2916- FilenameSet gamefiles;
2917-
2918- if (is_replay_) {
2919- gamefiles = filter(g_fs->list_directory(REPLAY_DIR),
2920- [](const std::string& fn) {return boost::ends_with(fn, REPLAY_SUFFIX);});
2921- } else {
2922- gamefiles = g_fs->list_directory("save");
2923- }
2924-
2925- Widelands::GamePreloadPacket gpdp;
2926-
2927- for (const std::string& gamefilename : gamefiles) {
2928- if (gamefilename == "save/campvis" || gamefilename == "save\\campvis") {
2929- continue;
2930- }
2931-
2932- SavegameData gamedata;
2933-
2934- std::string savename = gamefilename;
2935- if (is_replay_) savename += WLGF_SUFFIX;
2936-
2937- if (!g_fs->file_exists(savename.c_str())) {
2938- continue;
2939- }
2940-
2941- gamedata.filename = gamefilename;
2942-
2943- try {
2944- Widelands::GameLoader gl(savename.c_str(), game_);
2945- gl.preload_game(gpdp);
2946-
2947- gamedata.gametype = gpdp.get_gametype();
2948-
2949- if (!is_replay_) {
2950- if (settings_->settings().multiplayer) {
2951- if (gamedata.gametype == GameController::GameType::SINGLEPLAYER) {
2952- continue;
2953- }
2954- } else if (gamedata.gametype > GameController::GameType::SINGLEPLAYER) {
2955+
2956+ std::string savename = gamefilename;
2957+ if (is_replay_) savename += WLGF_SUFFIX;
2958+
2959+ if (!g_fs->file_exists(savename.c_str())) {
2960+ continue;
2961+ }
2962+
2963+ gamedata.filename = gamefilename;
2964+
2965+ try {
2966+ Widelands::GameLoader gl(savename.c_str(), game_);
2967+ gl.preload_game(gpdp);
2968+
2969+ gamedata.gametype = gpdp.get_gametype();
2970+
2971+ if (!is_replay_) {
2972+ if (settings_->settings().multiplayer) {
2973+ if (gamedata.gametype == GameController::GameType::SINGLEPLAYER) {
2974 continue;
2975 }
2976- }
2977-
2978- gamedata.mapname = gpdp.get_mapname();
2979- gamedata.gametime = gpdp.get_gametime();
2980- gamedata.nrplayers = gpdp.get_number_of_players();
2981- gamedata.version = gpdp.get_version();
2982-
2983- gamedata.savetimestamp = gpdp.get_savetimestamp();
2984- time_t t;
2985- time(&t);
2986- struct tm * currenttime = localtime(&t);
2987- // We need to put these into variables because of a sideeffect of the localtime function.
2988- int8_t current_year = currenttime->tm_year;
2989- int8_t current_month = currenttime->tm_mon;
2990- int8_t current_day = currenttime->tm_mday;
2991-
2992- struct tm * savedate = localtime(&gamedata.savetimestamp);
2993-
2994- if (gamedata.savetimestamp > 0) {
2995- if (savedate->tm_year == current_year &&
2996- savedate->tm_mon == current_month &&
2997- savedate->tm_mday == current_day) { // Today
2998-
2999- // Adding the 0 padding in a separate statement so translators won't have to deal with it
3000- const std::string minute = (boost::format("%02u") % savedate->tm_min).str();
3001-
3002- /** TRANSLATORS: Display date for choosing a savegame/replay */
3003- /** TRANSLATORS: hour:minute */
3004- gamedata.savedatestring = (boost::format(_("Today, %1%:%2%"))
3005- % savedate->tm_hour % minute).str();
3006- } else if ((savedate->tm_year == current_year &&
3007- savedate->tm_mon == current_month &&
3008- savedate->tm_mday == current_day - 1) ||
3009- (savedate->tm_year == current_year - 1 &&
3010- savedate->tm_mon == 11 && current_month == 0 &&
3011- savedate->tm_mday == 31 && current_day == 1)) { // Yesterday
3012- // Adding the 0 padding in a separate statement so translators won't have to deal with it
3013- const std::string minute = (boost::format("%02u") % savedate->tm_min).str();
3014-
3015- /** TRANSLATORS: Display date for choosing a savegame/replay */
3016- /** TRANSLATORS: hour:minute */
3017- gamedata.savedatestring = (boost::format(_("Yesterday, %1%:%2%"))
3018- % savedate->tm_hour % minute).str();
3019- } else { // Older
3020-
3021- /** TRANSLATORS: Display date for choosing a savegame/replay */
3022- /** TRANSLATORS: month day, year */
3023- gamedata.savedatestring = (boost::format(_("%2% %1%, %3%"))
3024- % savedate->tm_mday
3025- % localize_month(savedate->tm_mon)
3026- % (1900 + savedate->tm_year)).str();
3027- }
3028- }
3029-
3030- {
3031- i18n::Textdomain td("win_conditions");
3032- gamedata.wincondition = _(gpdp.get_win_condition());
3033- }
3034- gamedata.minimap_path = gpdp.get_minimap_path();
3035- games_data_.push_back(gamedata);
3036-
3037- UI::Table<uintptr_t const>::EntryRecord & te =
3038- table_.add(games_data_.size() - 1);
3039- te.set_string(0, gamedata.savedatestring);
3040-
3041- if (is_replay_ || settings_->settings().multiplayer) {
3042- std::string gametypestring;
3043- switch (gamedata.gametype) {
3044- case GameController::GameType::SINGLEPLAYER:
3045- /** TRANSLATORS: "Single Player" entry in the Game Mode table column. */
3046- /** TRANSLATORS: "Keep this to 6 letters maximum. */
3047- /** TRANSLATORS: A tooltip will explain the abbreviation. */
3048- /** TRANSLATORS: Make sure that this translation is consistent with the tooltip. */
3049- gametypestring = _("SP");
3050- break;
3051- case GameController::GameType::NETHOST:
3052- /** TRANSLATORS: "Multiplayer Host" entry in the Game Mode table column. */
3053- /** TRANSLATORS: "Keep this to 2 letters maximum. */
3054- /** TRANSLATORS: A tooltip will explain the abbreviation. */
3055- /** TRANSLATORS: Make sure that this translation is consistent with the tooltip. */
3056- /** TRANSLATORS: %1% is the number of players */
3057- gametypestring = (boost::format(_("H (%1%)"))
3058- % static_cast<unsigned int>(gamedata.nrplayers)).str();
3059- break;
3060- case GameController::GameType::NETCLIENT:
3061- /** TRANSLATORS: "Multiplayer" entry in the Game Mode table column. */
3062- /** TRANSLATORS: "Keep this to 2 letters maximum. */
3063- /** TRANSLATORS: A tooltip will explain the abbreviation. */
3064- /** TRANSLATORS: Make sure that this translation is consistent with the tooltip. */
3065- /** TRANSLATORS: %1% is the number of players */
3066- gametypestring = (boost::format(_("MP (%1%)"))
3067- % static_cast<unsigned int>(gamedata.nrplayers)).str();
3068- break;
3069- case GameController::GameType::REPLAY:
3070- gametypestring = "";
3071- break;
3072- }
3073- te.set_string(1, gametypestring);
3074- te.set_string(2, map_filename(gamedata.filename, gamedata.mapname));
3075- } else {
3076- te.set_string(1, map_filename(gamedata.filename, gamedata.mapname));
3077- }
3078- } catch (const WException & e) {
3079- // we simply skip illegal entries
3080- gamedata.errormessage =
3081- ((boost::format("%s\n\n%s\n\n%s"))
3082- /** TRANSLATORS: Error message introduction for when an old savegame can't be loaded */
3083- % _("This file has the wrong format and can’t be loaded."
3084- " Maybe it was created with an older version of Widelands.")
3085- /** TRANSLATORS: This text is on a separate line with an error message below */
3086- % _("Error message:")
3087- % e.what()).str();
3088-
3089- const std::string fs_filename = FileSystem::filename_without_ext(gamedata.filename.c_str());
3090- gamedata.mapname = fs_filename;
3091- games_data_.push_back(gamedata);
3092-
3093- UI::Table<uintptr_t const>::EntryRecord & te =
3094- table_.add(games_data_.size() - 1);
3095- te.set_string(0, "");
3096- if (is_replay_ || settings_->settings().multiplayer) {
3097- te.set_string(1, "");
3098- /** TRANSLATORS: Prefix for incompatible files in load game screens */
3099- te.set_string(2, (boost::format(_("Incompatible: %s")) % fs_filename).str());
3100- } else {
3101- te.set_string(1, (boost::format(_("Incompatible: %s")) % fs_filename).str());
3102- }
3103+ } else if (gamedata.gametype > GameController::GameType::SINGLEPLAYER) {
3104+ continue;
3105+ }
3106+ }
3107+
3108+ gamedata.mapname = gpdp.get_mapname();
3109+ gamedata.gametime = gpdp.get_gametime();
3110+ gamedata.nrplayers = gpdp.get_number_of_players();
3111+ gamedata.version = gpdp.get_version();
3112+
3113+ gamedata.savetimestamp = gpdp.get_savetimestamp();
3114+ time_t t;
3115+ time(&t);
3116+ struct tm * currenttime = localtime(&t);
3117+ // We need to put these into variables because of a sideeffect of the localtime function.
3118+ int8_t current_year = currenttime->tm_year;
3119+ int8_t current_month = currenttime->tm_mon;
3120+ int8_t current_day = currenttime->tm_mday;
3121+
3122+ struct tm * savedate = localtime(&gamedata.savetimestamp);
3123+
3124+ if (gamedata.savetimestamp > 0) {
3125+ if (savedate->tm_year == current_year &&
3126+ savedate->tm_mon == current_month &&
3127+ savedate->tm_mday == current_day) { // Today
3128+
3129+ // Adding the 0 padding in a separate statement so translators won't have to deal with it
3130+ const std::string minute = (boost::format("%02u") % savedate->tm_min).str();
3131+
3132+ /** TRANSLATORS: Display date for choosing a savegame/replay */
3133+ /** TRANSLATORS: hour:minute */
3134+ gamedata.savedatestring = (boost::format(_("Today, %1%:%2%"))
3135+ % savedate->tm_hour % minute).str();
3136+ } else if ((savedate->tm_year == current_year &&
3137+ savedate->tm_mon == current_month &&
3138+ savedate->tm_mday == current_day - 1) ||
3139+ (savedate->tm_year == current_year - 1 &&
3140+ savedate->tm_mon == 11 && current_month == 0 &&
3141+ savedate->tm_mday == 31 && current_day == 1)) { // Yesterday
3142+ // Adding the 0 padding in a separate statement so translators won't have to deal with it
3143+ const std::string minute = (boost::format("%02u") % savedate->tm_min).str();
3144+
3145+ /** TRANSLATORS: Display date for choosing a savegame/replay */
3146+ /** TRANSLATORS: hour:minute */
3147+ gamedata.savedatestring = (boost::format(_("Yesterday, %1%:%2%"))
3148+ % savedate->tm_hour % minute).str();
3149+ } else { // Older
3150+
3151+ /** TRANSLATORS: Display date for choosing a savegame/replay */
3152+ /** TRANSLATORS: month day, year */
3153+ gamedata.savedatestring = (boost::format(_("%2% %1%, %3%"))
3154+ % savedate->tm_mday
3155+ % localize_month(savedate->tm_mon)
3156+ % (1900 + savedate->tm_year)).str();
3157+ }
3158+ }
3159+
3160+ {
3161+ i18n::Textdomain td("win_conditions");
3162+ gamedata.wincondition = _(gpdp.get_win_condition());
3163+ }
3164+ gamedata.minimap_path = gpdp.get_minimap_path();
3165+ games_data_.push_back(gamedata);
3166+
3167+ UI::Table<uintptr_t const>::EntryRecord & te =
3168+ table_.add(games_data_.size() - 1);
3169+ te.set_string(0, gamedata.savedatestring);
3170+
3171+ if (is_replay_ || settings_->settings().multiplayer) {
3172+ std::string gametypestring;
3173+ switch (gamedata.gametype) {
3174+ case GameController::GameType::SINGLEPLAYER:
3175+ /** TRANSLATORS: "Single Player" entry in the Game Mode table column. */
3176+ /** TRANSLATORS: "Keep this to 6 letters maximum. */
3177+ /** TRANSLATORS: A tooltip will explain the abbreviation. */
3178+ /** TRANSLATORS: Make sure that this translation is consistent with the tooltip. */
3179+ gametypestring = _("SP");
3180+ break;
3181+ case GameController::GameType::NETHOST:
3182+ /** TRANSLATORS: "Multiplayer Host" entry in the Game Mode table column. */
3183+ /** TRANSLATORS: "Keep this to 2 letters maximum. */
3184+ /** TRANSLATORS: A tooltip will explain the abbreviation. */
3185+ /** TRANSLATORS: Make sure that this translation is consistent with the tooltip. */
3186+ /** TRANSLATORS: %1% is the number of players */
3187+ gametypestring = (boost::format(_("H (%1%)"))
3188+ % static_cast<unsigned int>(gamedata.nrplayers)).str();
3189+ break;
3190+ case GameController::GameType::NETCLIENT:
3191+ /** TRANSLATORS: "Multiplayer" entry in the Game Mode table column. */
3192+ /** TRANSLATORS: "Keep this to 2 letters maximum. */
3193+ /** TRANSLATORS: A tooltip will explain the abbreviation. */
3194+ /** TRANSLATORS: Make sure that this translation is consistent with the tooltip. */
3195+ /** TRANSLATORS: %1% is the number of players */
3196+ gametypestring = (boost::format(_("MP (%1%)"))
3197+ % static_cast<unsigned int>(gamedata.nrplayers)).str();
3198+ break;
3199+ case GameController::GameType::REPLAY:
3200+ gametypestring = "";
3201+ break;
3202+ }
3203+ te.set_string(1, gametypestring);
3204+ te.set_string(2, map_filename(gamedata.filename, gamedata.mapname));
3205+ } else {
3206+ te.set_string(1, map_filename(gamedata.filename, gamedata.mapname));
3207+ }
3208+ } catch (const WException & e) {
3209+ // we simply skip illegal entries
3210+ gamedata.errormessage =
3211+ ((boost::format("%s\n\n%s\n\n%s"))
3212+ /** TRANSLATORS: Error message introduction for when an old savegame can't be loaded */
3213+ % _("This file has the wrong format and can’t be loaded."
3214+ " Maybe it was created with an older version of Widelands.")
3215+ /** TRANSLATORS: This text is on a separate line with an error message below */
3216+ % _("Error message:")
3217+ % e.what()).str();
3218+
3219+ const std::string fs_filename = FileSystem::filename_without_ext(gamedata.filename.c_str());
3220+ gamedata.mapname = fs_filename;
3221+ games_data_.push_back(gamedata);
3222+
3223+ UI::Table<uintptr_t const>::EntryRecord & te =
3224+ table_.add(games_data_.size() - 1);
3225+ te.set_string(0, "");
3226+ if (is_replay_ || settings_->settings().multiplayer) {
3227+ te.set_string(1, "");
3228+ /** TRANSLATORS: Prefix for incompatible files in load game screens */
3229+ te.set_string(2, (boost::format(_("Incompatible: %s")) % fs_filename).str());
3230+ } else {
3231+ te.set_string(1, (boost::format(_("Incompatible: %s")) % fs_filename).str());
3232 }
3233 }
3234 }
3235
3236=== modified file 'src/ui_fsmenu/mapselect.cc'
3237--- src/ui_fsmenu/mapselect.cc 2016-01-29 08:37:22 +0000
3238+++ src/ui_fsmenu/mapselect.cc 2016-02-07 08:11:43 +0000
3239@@ -214,9 +214,6 @@
3240 * The search starts in \ref curdir_ ("..../maps") and there is no possibility
3241 * to move further up. If the user moves down into subdirectories, we insert an
3242 * entry to move back up.
3243- *
3244- * \note special case is, if this is a multiplayer game on a dedicated server and
3245- * the client wants to change the map - in that case the maps available on the server are shown.
3246 */
3247 void FullscreenMenuMapSelect::fill_table()
3248 {
3249@@ -231,137 +228,66 @@
3250 display_type = MapData::DisplayType::kMapnamesLocalized;
3251 }
3252
3253- if (settings_->settings().maps.empty()) {
3254- // This is the normal case
3255-
3256- // Fill it with all files we find in all directories.
3257- FilenameSet files = g_fs->list_directory(curdir_);
3258-
3259- //If we are not at the top of the map directory hierarchy (we're not talking
3260- //about the absolute filesystem top!) we manually add ".."
3261- if (curdir_ != basedir_) {
3262- maps_data_.push_back(MapData::create_parent_dir(curdir_));
3263- }
3264-
3265- Widelands::Map map; // MapLoader needs a place to put its preload data
3266-
3267- for (const std::string& mapfilename : files) {
3268- // Add map file (compressed) or map directory (uncompressed)
3269- std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(mapfilename);
3270- if (ml != nullptr) {
3271- try {
3272- map.set_filename(mapfilename);
3273- ml->preload_map(true);
3274-
3275- if (!map.get_width() || !map.get_height()) {
3276- continue;
3277- }
3278-
3279- MapData::MapType maptype;
3280- if (map.scenario_types() & scenario_types_) {
3281- maptype = MapData::MapType::kScenario;
3282- } else if (dynamic_cast<WidelandsMapLoader*>(ml.get())) {
3283- maptype = MapData::MapType::kNormal;
3284- } else {
3285- maptype = MapData::MapType::kSettlers2;
3286- }
3287-
3288- MapData mapdata(map, mapfilename, maptype, display_type);
3289-
3290- has_translated_mapname_ =
3291- has_translated_mapname_ || (mapdata.name != mapdata.localized_name);
3292-
3293- bool has_all_tags = true;
3294- for (std::set<uint32_t>::const_iterator it = req_tags_.begin(); it != req_tags_.end(); ++it)
3295- has_all_tags &= mapdata.tags.count(tags_ordered_[*it]);
3296- if (!has_all_tags) {
3297- continue;
3298- }
3299- maps_data_.push_back(mapdata);
3300- } catch (const std::exception & e) {
3301- log("Mapselect: Skip %s due to preload error: %s\n", mapfilename.c_str(), e.what());
3302- } catch (...) {
3303- log("Mapselect: Skip %s due to unknown exception\n", mapfilename.c_str());
3304- }
3305- } else if (g_fs->is_directory(mapfilename)) {
3306- // Add subdirectory to the list
3307- const char* fs_filename = FileSystem::fs_filename(mapfilename.c_str());
3308- if (!strcmp(fs_filename, ".") || !strcmp(fs_filename, ".."))
3309- continue;
3310- maps_data_.push_back(MapData::create_directory(mapfilename));
3311- }
3312- }
3313- } else {
3314- //client changing maps on dedicated server
3315- for (uint16_t i = 0; i < settings_->settings().maps.size(); ++i) {
3316- Widelands::Map map; // MapLoader needs a place to put its preload data
3317-
3318- const DedicatedMapInfos & dmap = settings_->settings().maps.at(i);
3319- const std::string& mapfilename = dmap.path;
3320- std::unique_ptr<Widelands::MapLoader> ml(map.get_correct_loader(mapfilename));
3321-
3322+ // This is the normal case
3323+
3324+ // Fill it with all files we find in all directories.
3325+ FilenameSet files = g_fs->list_directory(curdir_);
3326+
3327+ //If we are not at the top of the map directory hierarchy (we're not talking
3328+ //about the absolute filesystem top!) we manually add ".."
3329+ if (curdir_ != basedir_) {
3330+ maps_data_.push_back(MapData::create_parent_dir(curdir_));
3331+ }
3332+
3333+ Widelands::Map map; // MapLoader needs a place to put its preload data
3334+
3335+ for (const std::string& mapfilename : files) {
3336+ // Add map file (compressed) or map directory (uncompressed)
3337+ std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(mapfilename);
3338+ if (ml != nullptr) {
3339 try {
3340- if (!ml) {
3341- throw wexception("Mapselect: No MapLoader");
3342- }
3343-
3344 map.set_filename(mapfilename);
3345 ml->preload_map(true);
3346
3347 if (!map.get_width() || !map.get_height()) {
3348- throw wexception("Mapselect: Map has no size");
3349+ continue;
3350 }
3351
3352 MapData::MapType maptype;
3353-
3354 if (map.scenario_types() & scenario_types_) {
3355 maptype = MapData::MapType::kScenario;
3356 } else if (dynamic_cast<WidelandsMapLoader*>(ml.get())) {
3357+ maptype = MapData::MapType::kNormal;
3358+ } else {
3359 maptype = MapData::MapType::kSettlers2;
3360- } else {
3361- maptype = MapData::MapType::kNormal;
3362- }
3363-
3364- if (map.get_nrplayers() != dmap.players ||
3365- (maptype == MapData::MapType::kScenario) != dmap.scenario) {
3366- throw wexception("Mapselect: Number of players or scenario doesn't match");
3367 }
3368
3369 MapData mapdata(map, mapfilename, maptype, display_type);
3370
3371- // Finally write the entry to the list
3372+ has_translated_mapname_ =
3373+ has_translated_mapname_ || (mapdata.name != mapdata.localized_name);
3374+
3375+ bool has_all_tags = true;
3376+ for (std::set<uint32_t>::const_iterator it = req_tags_.begin(); it != req_tags_.end(); ++it)
3377+ has_all_tags &= mapdata.tags.count(tags_ordered_[*it]);
3378+ if (!has_all_tags) {
3379+ continue;
3380+ }
3381 maps_data_.push_back(mapdata);
3382+ } catch (const std::exception & e) {
3383+ log("Mapselect: Skip %s due to preload error: %s\n", mapfilename.c_str(), e.what());
3384 } catch (...) {
3385- log("Mapselect: Skipped reading locale data for file %s - not valid.\n", mapfilename.c_str());
3386-
3387- MapData mapdata;
3388-
3389- // Fill in the data we got from the dedicated server
3390- mapdata.filename = mapfilename;
3391- mapdata.name = mapfilename.substr(5, mapfilename.size() - 1);
3392- mapdata.authors = MapAuthorData(_("Nobody"));
3393- mapdata.description = _("This map file is not present in your filesystem."
3394- " The data shown here was sent by the server.");
3395- mapdata.hint = "";
3396- mapdata.nrplayers = dmap.players;
3397- mapdata.width = 1;
3398- mapdata.height = 0;
3399- mapdata.displaytype = display_type;
3400-
3401- if (dmap.scenario) {
3402- mapdata.maptype = MapData::MapType::kScenario;
3403- mapdata.tags.insert("scenario");
3404- } else if (dynamic_cast<WidelandsMapLoader*>(ml.get())) {
3405- mapdata.maptype = MapData::MapType::kSettlers2;
3406- } else {
3407- mapdata.maptype = MapData::MapType::kNormal;
3408- }
3409-
3410- // Finally write the entry to the list
3411- maps_data_.push_back(mapdata);
3412+ log("Mapselect: Skip %s due to unknown exception\n", mapfilename.c_str());
3413 }
3414+ } else if (g_fs->is_directory(mapfilename)) {
3415+ // Add subdirectory to the list
3416+ const char* fs_filename = FileSystem::fs_filename(mapfilename.c_str());
3417+ if (!strcmp(fs_filename, ".") || !strcmp(fs_filename, ".."))
3418+ continue;
3419+ maps_data_.push_back(MapData::create_directory(mapfilename));
3420 }
3421 }
3422+
3423 table_.fill(maps_data_, display_type);
3424 if (!table_.empty()) {
3425 table_.select(0);
3426
3427=== modified file 'src/wlapplication.cc'
3428--- src/wlapplication.cc 2016-02-06 19:58:38 +0000
3429+++ src/wlapplication.cc 2016-02-07 08:11:43 +0000
3430@@ -57,7 +57,6 @@
3431 #include "graphic/text/font_set.h"
3432 #include "graphic/text_constants.h"
3433 #include "helper.h"
3434-#include "io/dedicated_log.h"
3435 #include "io/filesystem/disk_filesystem.h"
3436 #include "io/filesystem/layered_filesystem.h"
3437 #include "logic/game.h"
3438@@ -391,68 +390,6 @@
3439 emergency_save(game);
3440 throw;
3441 }
3442- } else if (game_type_ == INTERNET) {
3443- Widelands::Game game;
3444- try {
3445- // disable sound completely
3446- g_sound_handler.nosound_ = true;
3447-
3448- // setup some details of the dedicated server
3449- Section & s = g_options.pull_section ("global");
3450- const std::string & meta = s.get_string ("metaserver", INTERNET_GAMING_METASERVER.c_str());
3451- uint32_t port = s.get_natural("metaserverport", INTERNET_GAMING_PORT);
3452- const std::string & name = s.get_string ("nickname", "dedicated");
3453- const std::string & server = s.get_string ("servername", name.c_str());
3454- const bool registered = s.get_bool ("registered", false);
3455- const std::string & pwd = s.get_string ("password", "");
3456- for (;;) { // endless loop
3457- if (!InternetGaming::ref().login(name, pwd, registered, meta, port)) {
3458- dedicatedlog("ERROR: Could not connect to metaserver (reason above)!\n");
3459- return;
3460- }
3461- std::string realservername(server);
3462- bool name_valid = false;
3463- while (!name_valid) {
3464- name_valid = true;
3465- const std::vector<InternetGame> & hosts = InternetGaming::ref().games();
3466- for (uint32_t i = 0; i < hosts.size(); ++i) {
3467- if (hosts.at(i).name == realservername)
3468- name_valid = false;
3469- }
3470- if (!name_valid)
3471- realservername += "*";
3472- }
3473-
3474- InternetGaming::ref().set_local_servername(realservername);
3475-
3476- NetHost netgame(name, true);
3477-
3478- // Load the requested map
3479- Widelands::Map map;
3480- map.set_filename(filename_);
3481- std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(filename_);
3482- if (!ml) {
3483- throw WLWarning
3484- ("Unsupported format",
3485- "Widelands could not load the file \"%s\". The file format seems to be incompatible.",
3486- filename_.c_str());
3487- }
3488- ml->preload_map(true);
3489-
3490- // set the map
3491- netgame.set_map(map.get_name(), map.get_filename(), map.get_nrplayers());
3492-
3493- // run the network game
3494- // -> autostarts when a player sends "/start" as pm to the server.
3495- netgame.run(true);
3496-
3497- InternetGaming::ref().logout();
3498- }
3499- } catch (const std::exception & e) {
3500- log("Fatal exception: %s\n", e.what());
3501- emergency_save(game);
3502- throw;
3503- }
3504 } else {
3505 g_sound_handler.start_music("intro");
3506
3507@@ -749,7 +686,6 @@
3508 s.get_bool("remove_syncstreams");
3509 s.get_bool("sound_at_message");
3510 s.get_bool("transparent_chat");
3511- s.get_bool("dedicated_saving"); // saving via chatcommand on dedicated servers -> nethost.cc
3512 s.get_string("registered");
3513 s.get_string("nickname");
3514 s.get_string("password");
3515@@ -958,17 +894,6 @@
3516 game_type_ = SCENARIO;
3517 commandline_.erase("scenario");
3518 }
3519- if (commandline_.count("dedicated")) {
3520- if (game_type_ != NONE)
3521- throw wexception("dedicated can not be combined with other actions");
3522- filename_ = commandline_["dedicated"];
3523- if (filename_.empty())
3524- throw wexception("empty value of commandline parameter --dedicated");
3525- if (*filename_.rbegin() == '/')
3526- filename_.erase(filename_.size() - 1);
3527- game_type_ = INTERNET;
3528- commandline_.erase("dedicated");
3529- }
3530 if (commandline_.count("script")) {
3531 script_to_run_ = commandline_["script"];
3532 if (script_to_run_.empty())
3533@@ -1297,7 +1222,7 @@
3534
3535 game.set_game_controller(ctrl.get());
3536 game.init_newgame(&loader_ui, sp.settings());
3537- game.run(&loader_ui, Widelands::Game::NewNonScenario, "", false);
3538+ game.run(&loader_ui, Widelands::Game::NewNonScenario, "", false, "single_player");
3539 } catch (const std::exception & e) {
3540 log("Fatal exception: %s\n", e.what());
3541 emergency_save(game);
3542@@ -1412,7 +1337,7 @@
3543
3544 game.save_handler().set_allow_saving(false);
3545
3546- game.run(&loader_ui, Widelands::Game::Loaded, "", true);
3547+ game.run(&loader_ui, Widelands::Game::Loaded, "", true, "replay");
3548 } catch (const std::exception & e) {
3549 log("Fatal Exception: %s\n", e.what());
3550 emergency_save(game);
3551
3552=== modified file 'src/wlapplication.h'
3553--- src/wlapplication.h 2016-01-28 05:24:34 +0000
3554+++ src/wlapplication.h 2016-02-07 08:11:43 +0000
3555@@ -135,7 +135,7 @@
3556 static WLApplication * get(int const argc = 0, char const * * argv = nullptr);
3557 ~WLApplication();
3558
3559- enum GameType {NONE, EDITOR, REPLAY, SCENARIO, LOADGAME, NETWORK, INTERNET};
3560+ enum GameType {NONE, EDITOR, REPLAY, SCENARIO, LOADGAME, NETWORK};
3561
3562 void run();
3563
3564
3565=== modified file 'src/wlapplication_messages.cc'
3566--- src/wlapplication_messages.cc 2015-01-12 15:44:52 +0000
3567+++ src/wlapplication_messages.cc 2016-02-07 08:11:43 +0000
3568@@ -85,7 +85,6 @@
3569 << _(" --loadgame=FILENAME Directly loads the savegame FILENAME.") << endl
3570 << _(" --script=FILENAME Run the given Lua script after initialization.\n"
3571 " Only valid with --scenario, --loadgame, or --editor.") << endl
3572- << _(" --dedicated=FILENAME Starts a dedicated server with FILENAME as map") << endl
3573 /** TRANSLATORS: You may translate true/false, also as on/off or yes/no, but */
3574 /** TRANSLATORS: it HAS TO BE CONSISTENT with the translation in the widelands textdomain */
3575 << _(" --auto_roadbuild_mode=[true|false]\n"
3576
3577=== modified file 'src/wui/chat_msg_layout.cc'
3578--- src/wui/chat_msg_layout.cc 2015-03-17 21:29:04 +0000
3579+++ src/wui/chat_msg_layout.cc 2016-02-07 08:11:43 +0000
3580@@ -58,8 +58,7 @@
3581 //
3582 // Note that we do want host and meta server to send some richtext code,
3583 // as the ability to send formatted commands is nice for the usability
3584- // of meta server and dedicated servers, so we're treading a bit of a
3585- // fine line here.
3586+ // of meta server so we're treading a bit of a fine line here.
3587 std::string sanitized;
3588 for (std::string::size_type pos = 0; pos < chat_message.msg.size(); ++pos) {
3589 if (chat_message.msg[pos] == '<') {
3590@@ -157,8 +156,7 @@
3591 //
3592 // Note that we do want host and meta server to send some richtext code,
3593 // as the ability to send formatted commands is nice for the usability
3594- // of meta server and dedicated servers, so we're treading a bit of a
3595- // fine line here.
3596+ // of meta server so we're treading a bit of a fine line here.
3597 std::string sanitized;
3598 for (std::string::size_type pos = 0; pos < chat_message.msg.size(); ++pos) {
3599 if (chat_message.msg[pos] == '<') {

Subscribers

People subscribed via source and target branches

to status/vote changes: