This is an automated email from the git hooks/post-receive script.

apo pushed a commit to branch master
in repository springlobby.

commit 6cc765fc8179438b55945763dc3e80ef5a87fb4b
Author: Markus Koschany <a...@debian.org>
Date:   Sat Mar 3 17:07:35 2018 +0100

    New upstream version 0.264+dfsg
---
 CMakeLists.txt                                     |   4 +-
 ChangeLog                                          |   8 +
 VERSION                                            |   2 +-
 buildbot/master.cfg                                |   4 +-
 cmake/compat_flags.cmake                           |  28 +---
 doc/UseDoxygen.cmake                               |   6 +-
 springlobby_config.h                               |   2 +-
 src/CMakeLists.txt                                 |   4 +-
 src/address.cpp                                    | 109 ++++++++++++
 src/address.h                                      |   5 +
 src/autohost.cpp                                   |   2 +-
 src/autohostmanager.cpp                            |  10 ++
 src/autohostmanager.h                              |   3 +
 src/battle.cpp                                     |  12 +-
 src/channel.cpp                                    |   2 +-
 src/downloader/lib/CMakeLists.txt                  |  34 ++--
 src/downloader/lib/src/CMakeLists.txt              |   9 +-
 src/downloader/lib/src/Downloader/CurlWrapper.cpp  |   7 +-
 .../lib/src/Downloader/Rapid/RapidDownloader.cpp   |   3 +-
 src/downloader/lib/src/Downloader/Rapid/Sdp.cpp    |   8 +-
 src/downloader/lib/src/Logger.cpp                  |  90 ++++++----
 src/downloader/lib/src/Logger.h                    |  27 +--
 src/downloader/lib/src/Util.cpp                    |   7 -
 src/downloader/lib/src/Util.h                      |   5 -
 .../lib/src/lsl/lslextract/CMakeLists.txt          |   5 +-
 src/downloader/lib/src/lsl/lslextract/index.html   |   2 +-
 .../lib/src/lsl/lslextract/lslextract.cpp          |   2 +-
 src/downloader/lib/src/lsl/lslunitsync/image.cpp   |   4 +-
 src/downloader/lib/src/lsl/lslutils/logging.h      |  31 ++--
 src/downloader/lib/src/main.cpp                    |   3 +-
 src/downloader/lib/test/CMakeLists.txt             |   2 +
 src/downloader/lib/test/lsl/usync.cpp              |  13 +-
 src/downloader/prdownloader.cpp                    |  13 +-
 src/gui/aboutbox.cpp                               |   7 +-
 src/gui/chatpanel.cpp                              |   2 +-
 src/gui/hosting/battleroomtab.cpp                  | 107 ++++++++----
 src/gui/hosting/battleroomtab.h                    |   1 +
 src/gui/hosting/hostbattledialog.cpp               |  42 +++--
 src/gui/hosting/hostbattledialog.h                 |   4 +-
 src/gui/mainwindow.cpp                             |  15 +-
 src/gui/mapctrl.cpp                                |   3 +-
 src/gui/mapgridctrl.cpp                            |   6 +-
 src/gui/notifications/libnotify.cpp                |   4 +-
 src/gui/options/lobbyoptionstab.cpp                |  16 +-
 src/gui/options/mainoptionstab.cpp                 |   5 +-
 src/gui/options/springoptionstab.cpp               |  17 +-
 src/gui/playback/playbacktab.cpp                   |   4 +
 src/gui/singleplayertab.cpp                        |  50 +++---
 src/gui/singleplayertab.h                          |   4 +-
 src/gui/statusbar.cpp                              |   2 +-
 src/gui/ui.cpp                                     |  57 +++----
 src/gui/ui.h                                       |   2 +-
 src/ibattle.cpp                                    |  86 +++++-----
 src/ibattle.h                                      |   5 +-
 src/log.cpp                                        | 186 +++++++++++----------
 src/log.h                                          |   4 +
 src/socket.cpp                                     | 110 +-----------
 src/springlobbyapp.cpp                             |   6 +-
 src/springlobbyapp.h                               |  13 +-
 src/springsettings/frame.cpp                       |   4 +-
 src/sysinfo.cpp                                    |  12 +-
 src/tasserver.cpp                                  |  29 ++--
 src/tests/CMakeLists.txt                           |   6 +
 src/tests/lobbyid.cpp                              |   9 +
 src/updatehelper.cpp                               |  30 ++++
 src/updatehelper.h                                 |   4 +
 src/utils/conversion.cpp                           |   3 +
 src/utils/platform.cpp                             |   4 +
 src/utils/slpaths.cpp                              |   6 +-
 src/utils/version.cpp                              |  12 +-
 src/utils/version.h                                |   6 +-
 tools/mxe_create_builddir.sh                       |   6 +-
 72 files changed, 765 insertions(+), 590 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 42d276b..7a45199 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 PROJECT(springlobby)
 
 #set minimum cmake version
-cmake_minimum_required(VERSION 2.8.11)
+cmake_minimum_required(VERSION 3.1)
 
 SET(CMAKE_COLOR_MAKEFILE ON)
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} )
@@ -35,6 +35,8 @@ endif()
 
#----------------------------------------------------------------------------------------------------
 SET( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
 
+INCLUDE(compat_flags)
+
 
#----------------------------------------------------------------------------------------------------
 # Load needed Modules
 
#----------------------------------------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 3364dea..fd925ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 ChangeLog of Springlobby
 
+## 0.264
+ - improved the start button in battleroom
+ - log everything into springlobby.log (added downloader + unitsync handling)
+ - cmake 3.1 at least is required to compile springlobby
+ - replace boost:: with std:: in some places
+ - fix crash when re-selecting no map / no game in singleplayer tab
+ - updated buildslave to latest mxe (wxwidgets 3.0.3, etc)
+
 ## 0.263
  - more verbose logging to track down crashes
 
diff --git a/VERSION b/VERSION
index b1b695c..4c42f43 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.263
+0.264
diff --git a/buildbot/master.cfg b/buildbot/master.cfg
index 6a4a043..d10aa17 100644
--- a/buildbot/master.cfg
+++ b/buildbot/master.cfg
@@ -436,8 +436,8 @@ class MXEFactory(BuildFactory):
 
 
 win32buildenv = {
-               'CMAKE': 
'/home/buildbot/slaves/springlobby/mxe/build/mxe/usr/bin/i686-w64-mingw32.static-cmake',
-               'CMAKE_PARAMS': 
'-DCMAKE_STRIP:PATH=/home/buildbot/slaves/springlobby/mxe/build/mxe/usr/bin/i686-w64-mingw32.static-strip'
+               'CMAKE':                           
'/home/buildbot/slaves/springlobby/mxe/build/mxe/usr/bin/i686-w64-mingw32.static.posix-cmake',
+               'CMAKE_PARAMS': 
'-DCMAKE_STRIP:PATH=/home/buildbot/slaves/springlobby/mxe/build/mxe/usr/bin/i686-w64-mingw32.static.posix-strip'
        }
 
 c['builders'].append({'name': 'develop',
diff --git a/cmake/compat_flags.cmake b/cmake/compat_flags.cmake
index 741c19d..8496750 100644
--- a/cmake/compat_flags.cmake
+++ b/cmake/compat_flags.cmake
@@ -1,32 +1,22 @@
+
 include(TestCXXAcceptsFlag)
-execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
-                               OUTPUT_VARIABLE GCC_VERSION)
 
-# try to use compiler flag -std=c++11
+CHECK_CXX_ACCEPTS_FLAG("-std=c++11" ACCEPTSFLAGCXX11)
+CHECK_CXX_ACCEPTS_FLAG("-std=c++17" ACCEPTSFLAGCXX17)
+
 MACRO(AddSTDFlag FLAG)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG} ")
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG} ")
        set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${FLAG} ")
        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAG} ")
        set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} 
${FLAG} ")
-       set(CXX_STD0X_FLAGS "${FLAG}" )
 ENDMACRO(AddSTDFlag FLAG)
 
-# try to use compiler flag -std=c++11
-
-set(CXX_STD0X_FLAGS FALSE)
-set(i 0)
-foreach(f -std=gnu++11 -std=c++11 -std=c++0x)
-       MATH(EXPR i "${i}+1") #cmake has working unset :-|
-       CHECK_CXX_ACCEPTS_FLAG("${f}" ACCEPTSFLAG${i})
-       if(${ACCEPTSFLAG${i}} AND NOT CXX_STD0X_FLAGS)
-               message(STATUS "Using ${f}")
-               AddSTDFlag("${f}")
-               set(CXX_STD0X_FLAGS TRUE)
-       endif()
-endforeach()
-
-if(NOT CXX_STD0X_FLAGS)
+if (ACCEPTSFLAGCXX17)
+       AddSTDFlag("-std=c++17")
+elseif(ACCEPTSFLAGCXX11)
+       AddSTDFlag("-std=c++11")
+else()
        message(FATAL_ERROR "you need a c++11 compatible compiler")
 endif()
 
diff --git a/doc/UseDoxygen.cmake b/doc/UseDoxygen.cmake
index 05760ae..5975962 100644
--- a/doc/UseDoxygen.cmake
+++ b/doc/UseDoxygen.cmake
@@ -109,10 +109,6 @@ if(DOXYGEN_FOUND AND DOXYFILE_IN)
 
        configure_file(${DOXYFILE_IN} Doxyfile ESCAPE_QUOTES IMMEDIATE @ONLY)
 
-       get_target_property(DOC_TARGET doc TYPE)
-       if(NOT DOC_TARGET)
-               add_custom_target(doc)
-       endif()
-               
+       add_custom_target(doc)
        add_dependencies(doc doxygen)
 endif()
diff --git a/springlobby_config.h b/springlobby_config.h
index 69dfa26..6093947 100644
--- a/springlobby_config.h
+++ b/springlobby_config.h
@@ -6,6 +6,6 @@
 #undef VERSION
 
 /* the git tag / commit we build from */
-#define VERSION "0.263"
+#define VERSION "0.264"
 
 #endif /* SPRINGLOBBY_HEADERGUARD_CONFIG_H */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 55e64bd..21c54c1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,5 +1,3 @@
-INCLUDE(compat_flags)
-
 
 # Add Definitions, Compiler-Switches, etc.: -Wall -O2 -g3 ...
 # MSVC compiler (cl.exe) does not accept the same switches as gcc, although 
preprocessor definitions in the -D form will work for both
@@ -161,6 +159,7 @@ ENDIF( OPTION_NOTIFY AND NOT WIN32 )
 
 
 set(springlobbySrc
+       address.cpp
        autohost.cpp
        autohostmanager.cpp
        battlelist.cpp
@@ -301,7 +300,6 @@ set(springlobbySrc
 
 
        downloader/lib/src/lsl/lsl/battle/tdfcontainer.cpp #FIXME
-       downloader/lib/src/lsl/lslutils/conversion.cpp #FIXME
 
        gui/uiutils.cpp
        gui/controls.cpp
diff --git a/src/address.cpp b/src/address.cpp
new file mode 100644
index 0000000..1c80f58
--- /dev/null
+++ b/src/address.cpp
@@ -0,0 +1,109 @@
+/* This file is part of the Springlobby (GPL v2 or later), see COPYING */
+
+#include "address.h"
+
+#ifdef _WIN32
+#include <iphlpapi.h>
+#elif defined(linux)
+#include <sys/ioctl.h>
+#include <net/if.h>
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+bool GetMacType(std::vector<unsigned char>& mac, const unsigned int mactype)
+{
+       IP_ADAPTER_INFO AdapterInfo[16];      // Allocate information for 16 
cards
+       DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
+
+       DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen); // Get info
+       if (dwStatus == ERROR_BUFFER_OVERFLOW) {
+               return false;
+       }
+       if (dwStatus != NO_ERROR)
+               return false; // Check status
+
+       for (size_t i = 0; i < dwBufLen / sizeof(AdapterInfo); i++) {
+               if ((mactype != 0) && (AdapterInfo[i].Type != mactype)) //skip 
not wanted type
+                       continue;
+               if (AdapterInfo[i].AddressLength == 0) {
+                       continue;
+               }
+               mac.resize(AdapterInfo[i].AddressLength);
+               mac.assign(AdapterInfo[i].Address, AdapterInfo[i].Address + 
AdapterInfo[i].AddressLength);
+               for (size_t j = 0; j < mac.size(); j++) {
+                       if (mac[j] != 0) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+
+bool GetMac(std::vector<unsigned char>& mac)
+{
+       if (GetMacType(mac, MIB_IF_TYPE_ETHERNET))
+               return true;
+       if (GetMacType(mac, IF_TYPE_IEEE80211))
+               return true;
+       return (GetMacType(mac, 0));
+}
+
+#elif defined(__APPLE__)
+
+bool GetMac(std::vector<unsigned char>& mac)
+{
+       //FIXME: implement this, 
http://lists.freebsd.org/pipermail/freebsd-hackers/2004-June/007415.html
+       return false;
+}
+
+#else
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netpacket/packet.h>
+#include <ifaddrs.h>
+
+bool GetMac(std::vector<unsigned char>& mac)
+{
+       ifaddrs* ifap = 0;
+       if (getifaddrs(&ifap) == 0) {
+               ifaddrs* iter = ifap;
+               while (iter) {
+                       sockaddr_ll* sal = 
reinterpret_cast<sockaddr_ll*>(iter->ifa_addr);
+                       if (sal->sll_family == AF_PACKET) {
+                               mac.resize(sal->sll_halen);
+                               mac.assign(sal->sll_addr, sal->sll_addr + 
sal->sll_halen);
+                               for (size_t i = 0; i < mac.size(); i++) {
+                                       if (mac[i] != 0) {
+                                               freeifaddrs(ifap);
+                                               return true;
+                                       }
+                               }
+                       }
+                       iter = iter->ifa_next;
+               }
+               freeifaddrs(ifap);
+       }
+       return false;
+}
+
+#endif
+
+std::string MacToString(std::vector<unsigned char>& mac)
+{
+       std::string res;
+       for (size_t i = 0; i < mac.size(); i++) {
+               char buf[3];
+               snprintf(buf, sizeof(buf), "%02X", mac[i]);
+               if (!res.empty())
+                       res += ":";
+               res.append(buf, 2);
+       }
+       return res;
+}
+
diff --git a/src/address.h b/src/address.h
new file mode 100644
index 0000000..207b5b9
--- /dev/null
+++ b/src/address.h
@@ -0,0 +1,5 @@
+#include <string>
+#include <vector>
+
+bool GetMac(std::vector<unsigned char>& mac);
+std::string MacToString(std::vector<unsigned char>& mac);
diff --git a/src/autohost.cpp b/src/autohost.cpp
index 64677e6..54a479c 100644
--- a/src/autohost.cpp
+++ b/src/autohost.cpp
@@ -225,7 +225,7 @@ void AutoHost::OnUserAdded(User& user)
        // do nothing if autohost functionality is disabled
        if (!m_enabled)
                return;
-       m_battle.DoAction(stdprintf("Hi %s, this battle is in %s autohost mode. 
For help say !help", user.GetNick().c_str(), getSpringlobbyVersion().c_str()));
+       m_battle.DoAction(stdprintf("Hi %s, this battle is in %s autohost mode. 
For help say !help", user.GetNick().c_str(), GetSpringlobbyVersion().c_str()));
 }
 
 
diff --git a/src/autohostmanager.cpp b/src/autohostmanager.cpp
index 5ac5bd9..e1e3a5b 100644
--- a/src/autohostmanager.cpp
+++ b/src/autohostmanager.cpp
@@ -87,6 +87,11 @@ void SpringieHandler::Promote()
        // TODO
 }
 
+void SpringieHandler::Ring()
+{
+       Send("!ring");
+}
+
 void SpringieHandler::Start()
 {
        Send("!start");
@@ -139,6 +144,11 @@ void SpadsHandler::Promote()
        Send("!promote");
 }
 
+void SpadsHandler::Ring()
+{
+       Send("!ring");
+}
+
 void SpadsHandler::Start()
 {
        Send("!start");
diff --git a/src/autohostmanager.h b/src/autohostmanager.h
index 342471f..0c5dcde 100644
--- a/src/autohostmanager.h
+++ b/src/autohostmanager.h
@@ -20,6 +20,7 @@ public:
        virtual void AddStartBox(int /*posx*/, int /*posy*/, int /*w*/, int 
/*h*/){};
        virtual void Notify(){};
        virtual void Promote(){};
+       virtual void Ring(){};
        virtual void Start(){};
        void SetBattle(IBattle* battle);
 
@@ -47,6 +48,7 @@ public:
        void AddStartBox(int posx, int posy, int w, int h) override;
        void Notify() override;
        void Promote() override;
+       void Ring() override;
        void Start() override;
 };
 
@@ -63,6 +65,7 @@ public:
        void AddStartBox(int posx, int posy, int w, int h) override;
        void Notify() override;
        void Promote() override;
+       void Ring() override;
        void Start() override;
 };
 
diff --git a/src/battle.cpp b/src/battle.cpp
index ab15f51..4ccc331 100644
--- a/src/battle.cpp
+++ b/src/battle.cpp
@@ -331,13 +331,11 @@ void Battle::RingNotSyncedPlayers()
 
 void Battle::RingNotSyncedAndNotReadyPlayers()
 {
-       for (user_map_t::size_type i = 0; i < GetNumUsers(); i++) {
-               User& u = GetUser(i);
-               UserBattleStatus& bs = u.BattleStatus();
-               if (bs.IsBot())
-                       continue;
-               if ((!bs.sync || !bs.ready) && !bs.spectator)
-                       m_serv.Ring(u.GetNick());
+       if (IsFounderMe()) {
+               RingNotReadyPlayers();
+               RingNotSyncedPlayers();
+       } else {
+               m_autohost_manager->GetAutohostHandler().Ring();
        }
 }
 
diff --git a/src/channel.cpp b/src/channel.cpp
index c47bc89..65ad1d3 100644
--- a/src/channel.cpp
+++ b/src/channel.cpp
@@ -222,7 +222,7 @@ bool Channel::ExecuteSayCommand(const std::string& in)
                return true;
        } else if (param == _T("/sayver")) {
                //!this instance is not replaced with GetAppname for sake of 
help/debug online
-               DoAction("is using SpringLobby v" + getSpringlobbyVersion());
+               DoAction("is using " + GetSpringlobbyAgent());
                return true;
        } else if (subcmd == _T("/userban")) {
                m_banned_users.insert(params);
diff --git a/src/downloader/lib/CMakeLists.txt 
b/src/downloader/lib/CMakeLists.txt
index 112efc5..a897566 100644
--- a/src/downloader/lib/CMakeLists.txt
+++ b/src/downloader/lib/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8.11)
+cmake_minimum_required(VERSION 3.1)
 project(pr-downloader)
 
 
@@ -46,16 +46,8 @@ if(PRD_CLEAR_COMPILER_FLAGS)
        SET(CMAKE_SHARED_LINKER_FLAGS "")
 endif()
 
-include(CheckCXXCompilerFlag)
-CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
-CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
-if(COMPILER_SUPPORTS_CXX11)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
-elseif(COMPILER_SUPPORTS_CXX0X)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
-else()
-        message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 
support. Please use a different C++ compiler.")
-endif()
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 MESSAGE(STATUS "PR-Downloader version: ${PR_DOWNLOADER_VERSION}")
 if   (MINGW)
@@ -113,6 +105,26 @@ else()
        find_package(ZLIB REQUIRED)
 endif()
 
+find_program(CURL_CONFIG_EXECUTABLE NAMES curl-config 
ONLY_CMAKE_FIND_ROOT_PATH)
+if (wxWidgets_CONFIG_EXECUTABLE-NOTFOUND)
+        message(FATAL_ERROR "couldn't find curl-config!")
+else()
+        message(STATUS "found curl-config: ${CURL_CONFIG_EXECUTABLE}")
+endif()
+
+if (PREFER_STATIC_LIBS)
+       set(CURLSTATIC "--static")
+else()
+       set(CURLSTATIC "")
+endif()
+
+execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} "--libs" ${CURLSTATIC}
+        OUTPUT_VARIABLE CURL_LD_FLAGS
+        OUTPUT_STRIP_TRAILING_WHITESPACE )
+message(STATUS "Using CURL_LD_FLAGS: ${CURL_LD_FLAGS}")
+
+
+
 if (PRD_JSONCPP_INTERNAL)
         # use bundled JsonCpp
         set(PRD_JSONCPP_INCLUDE_DIR 
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/jsoncpp/include)
diff --git a/src/downloader/lib/src/CMakeLists.txt 
b/src/downloader/lib/src/CMakeLists.txt
index 29df0a7..54f7cde 100644
--- a/src/downloader/lib/src/CMakeLists.txt
+++ b/src/downloader/lib/src/CMakeLists.txt
@@ -32,7 +32,6 @@ add_library(Downloader STATIC
        FileSystem/HashSHA1.cpp
        FileSystem/IHash.cpp
        Util.cpp
-       Logger.cpp
        Version.cpp
        lib/base64/base64.cpp
        ${archivessrc}
@@ -59,6 +58,7 @@ set(PRDOWNLOADER_LIBS
 
 target_link_libraries(Downloader
        ${CURL_LIBRARIES}
+       ${CURL_LD_FLAGS}
        ${OPENSSL_LIBRARIES}
        ${WIN32LIBS}
        ${PRD_JSONCPP_LIBRARIES}
@@ -82,17 +82,13 @@ set (PRDOWNLOADER "pr-downloader")
 set (PRDOWNLOADER_SHARED ${PRDOWNLOADER}_shared)
 set (PRDOWNLOADER_STATIC ${PRDOWNLOADER}_static)
 
-
-
-
-
-
 OPTION(PRD_SHAREDLIB
        "Enables compilation of the shared lib" ON)
 
 if (PRD_SHAREDLIB)
        add_library(${PRDOWNLOADER_SHARED} SHARED
                pr-downloader.cpp
+               Logger.cpp
        )
        if(PRD_DO_INSTALL AND (PRD_DEVELOP_FILES OR (PRD_CONSOLETOOL AND NOT 
PRD_LINK_STATIC)))
                INSTALL (TARGETS ${PRDOWNLOADER_SHARED}
@@ -132,6 +128,7 @@ if (PRD_CONSOLETOOL)
        add_executable(${PRDOWNLOADER}
                ${PRD_ICON}
                main.cpp
+               Logger.cpp
        )
 
        if (PRD_LINK_STATIC)
diff --git a/src/downloader/lib/src/Downloader/CurlWrapper.cpp 
b/src/downloader/lib/src/Downloader/CurlWrapper.cpp
index e727f2c..981bf13 100644
--- a/src/downloader/lib/src/Downloader/CurlWrapper.cpp
+++ b/src/downloader/lib/src/Downloader/CurlWrapper.cpp
@@ -21,16 +21,17 @@ CurlWrapper::CurlWrapper()
        curl_easy_setopt(handle, CURLOPT_FAILONERROR, true);
        curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
 
-       list = NULL;
+       list = nullptr;
        list = curl_slist_append(list, "Cache-Control: no-cache");
        curl_easy_setopt(handle, CURLOPT_HTTPHEADER, list);
 }
 
 CurlWrapper::~CurlWrapper()
 {
-       curl_easy_cleanup(handle);
-       handle = NULL;
        curl_slist_free_all(list); /* free the list again */
+       curl_easy_cleanup(handle);
+       handle = nullptr;
+       list = nullptr;
 }
 
 std::string CurlWrapper::escapeUrl(const std::string& url)
diff --git a/src/downloader/lib/src/Downloader/Rapid/RapidDownloader.cpp 
b/src/downloader/lib/src/Downloader/Rapid/RapidDownloader.cpp
index 62ac84b..a0fb84b 100644
--- a/src/downloader/lib/src/Downloader/Rapid/RapidDownloader.cpp
+++ b/src/downloader/lib/src/Downloader/Rapid/RapidDownloader.cpp
@@ -83,7 +83,8 @@ bool CRapidDownloader::download_name(IDownload* download, int 
reccounter,
                        continue;
                downloaded.insert(sdp.getMD5());
 
-               LOG_DOWNLOAD(sdp.getName().c_str());
+               LOG_INFO ("[Download] %s", sdp.getName().c_str());
+
                if (!sdp.download(download)) {
                        return false;
                }
diff --git a/src/downloader/lib/src/Downloader/Rapid/Sdp.cpp 
b/src/downloader/lib/src/Downloader/Rapid/Sdp.cpp
index 8108865..5836fbc 100644
--- a/src/downloader/lib/src/Downloader/Rapid/Sdp.cpp
+++ b/src/downloader/lib/src/Downloader/Rapid/Sdp.cpp
@@ -149,13 +149,11 @@ bool CSdp::download(IDownload* dl)
         the filename is read from the sdp-list (created at request start)
         filesize is read from the http-data received (could overlap!)
 */
-static size_t write_streamed_data(const void* tmp, size_t size, size_t nmemb,
+static size_t write_streamed_data(const void* buf, size_t size, size_t nmemb,
                                  CSdp* sdp)
 {
        if (IDownloader::AbortDownloads())
                return -1;
-       char buf[CURL_MAX_WRITE_SIZE];
-       memcpy(&buf, tmp, CURL_MAX_WRITE_SIZE);
        if (!sdp->downloadInitialized) {
                sdp->list_it = sdp->files.begin();
                sdp->downloadInitialized = true;
@@ -163,9 +161,9 @@ static size_t write_streamed_data(const void* tmp, size_t 
size, size_t nmemb,
                sdp->file_name = "";
                sdp->skipped = 0;
        }
-       char* buf_start = (char*)&buf;
+       const char* buf_start = (const char*)buf;
        const char* buf_end = buf_start + size * nmemb;
-       char* buf_pos = buf_start;
+       const char* buf_pos = buf_start;
 
        while (buf_pos < buf_end) {             // all bytes written?
                if (sdp->file_handle == NULL) { // no open file, create one
diff --git a/src/downloader/lib/src/Logger.cpp 
b/src/downloader/lib/src/Logger.cpp
index b70d77e..8553ae3 100644
--- a/src/downloader/lib/src/Logger.cpp
+++ b/src/downloader/lib/src/Logger.cpp
@@ -1,10 +1,54 @@
 /* This file is part of pr-downloader (GPL v2 or later), see the LICENSE file 
*/
 
 #include "Logger.h"
-#include "Util.h"
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <time.h>
+
+// Logging functions in standalone mode
+// prdLogRaw is supposed to flush after printing (mostly to stdout/err
+// for progress bars and such).
+static void prdLogRaw(const char* /*fileName*/, int /*line*/, const char* 
/*funcName*/,
+                    const char* format, va_list args)
+{
+       vprintf(format, args);
+       fflush(stdout);
+}
+
+// Normal logging
+static void prdLogError(const char* fileName, int line, const char* funcName,
+                      const char* format, va_list args)
+{
+       fprintf(stderr, "[Error] %s:%d:%s():", fileName, line, funcName);
+       vfprintf(stderr, format, args);
+       fprintf(stderr, "\n");
+}
+
+static void prdLogWarn(const char* fileName, int line, const char* funcName,
+                      const char* format, va_list args)
+{
+       printf("[Warn] %s:%d:%s():", fileName, line, funcName);
+       vprintf(format, args);
+       printf("\n");
+}
+
+static void prdLogInfo(const char* fileName, int line, const char* funcName,
+                     const char* format, va_list args)
+{
+       printf("[Info] %s:%d:%s():", fileName, line, funcName);
+       vprintf(format, args);
+       printf("\n");
+}
+
+static void prdLogDebug(const char* fileName, int line, const char* funcName,
+                      const char* format, va_list args)
+{
+       printf("[Debug] %s:%d:%s():", fileName, line, funcName);
+       vprintf(format, args);
+       printf("\n");
+}
+
 
 static bool logEnabled = true;
 
@@ -13,7 +57,8 @@ void LOG_DISABLE(bool disableLogging)
        logEnabled = !disableLogging;
 }
 
-void L_LOG(L_LEVEL level, const char* format...)
+extern void L_LOG(const char* fileName, int line, const char* funName,
+           L_LEVEL level, const char* format...)
 {
        if (!logEnabled) {
                return;
@@ -23,46 +68,35 @@ void L_LOG(L_LEVEL level, const char* format...)
        va_start(args, format);
        switch (level) {
                case L_RAW:
-                       vprintf(format, args);
-                       fflush(stdout);
+                       prdLogRaw(fileName, line, funName, format, args);
                        break;
                default:
                case L_ERROR:
-                       fprintf(stderr, "[Error] ");
-                       vfprintf(stderr, format, args);
-                       fprintf(stderr, "\n");
+                       prdLogError(fileName, line, funName, format, args);
+                       break;
+               case L_WARN:
+                       prdLogWarn(fileName, line, funName, format, args);
                        break;
                case L_INFO:
-                       printf("[Info] ");
-                       vprintf(format, args);
-                       printf("\n");
+                       prdLogInfo(fileName, line, funName, format, args);
                        break;
                case L_DEBUG:
-                       printf("[Debug] ");
-                       vprintf(format, args);
-                       printf("\n");
+                       prdLogDebug(fileName, line, funName, format, args);
                        break;
        }
        va_end(args);
 }
 
-void LOG_DOWNLOAD(const char* filename)
-{
-       L_LOG(L_RAW, "[Download] %s\n", filename);
-}
-
-void LOG_PROGRESS(long done, long total, bool forceOutput)
+extern void LOG_PROGRESS(long done, long total, bool forceOutput)
 {
-       static unsigned long lastlogtime = 0;
+       static time_t lastlogtime = 0;
        static float lastPercentage = 0.0f;
 
        if (!logEnabled) {
                return;
        }
 
-       unsigned long now = getTime(); // needs to be here atm to avoid static 
link
-                                      // failure because of circular deps 
between
-                                      // libs
+       const time_t now = time(nullptr);
 
        if (lastlogtime < now) {
                lastlogtime = now;
@@ -81,17 +115,17 @@ void LOG_PROGRESS(long done, long total, bool forceOutput)
                return;
        lastPercentage = percentage;
 
-       L_LOG(L_RAW, "[Progress] %3.0f%% [", percentage * 100.0f);
+       LOG("[Progress] %3.0f%% [", percentage * 100.0f);
        int totaldotz = 30; // how wide you want the progress meter to be
        int dotz = percentage * totaldotz;
        for (int i = 0; i < totaldotz; i++) {
                if (i >= dotz)
-                       printf(" "); // blank
+                       LOG(" "); // blank
                else
-                       printf("="); // full
+                       LOG("="); // full
        }
        // and back to line begin - do not forget the fflush to avoid output 
buffering
        // problems!
-       L_LOG(L_RAW, "] %ld/%ld ", done, total);
-       L_LOG(L_RAW, "\r");
+       LOG("] %ld/%ld ", done, total);
+       LOG("\r");
 }
diff --git a/src/downloader/lib/src/Logger.h b/src/downloader/lib/src/Logger.h
index 0425151..85239d2 100644
--- a/src/downloader/lib/src/Logger.h
+++ b/src/downloader/lib/src/Logger.h
@@ -3,8 +3,6 @@
 #ifndef LOGGER_H
 #define LOGGER_H
 
-#include <stdio.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -15,39 +13,42 @@ enum L_LEVEL {
        L_ERROR = 1,
        L_RAW = 2,
        L_INFO = 3,
-       L_DEBUG = 4
+       L_WARN = 4,
+       L_DEBUG = 5,
 };
 
 /**
        *       plain log output
        */
-void L_LOG(L_LEVEL level, const char* format, ...);
+extern void L_LOG(const char* fileName, int line, const char* funcName,
+           L_LEVEL level, const char* format, ...);
 
 #define LOG(...) \
-       L_LOG(L_RAW, __VA_ARGS__)
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_RAW, __VA_ARGS__)
 
-#define LOG_ERROR(fmt, ...) \
-       L_LOG(L_ERROR, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __FUNCTION__, 
##__VA_ARGS__)
+#define LOG_ERROR(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_ERROR, __VA_ARGS__)
 
 #define LOG_INFO(...) \
-       L_LOG(L_INFO, __VA_ARGS__)
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_INFO, __VA_ARGS__)
+
+#define LOG_WARN(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_WARN, __VA_ARGS__)
 
 #ifndef NDEBUG
-#define LOG_DEBUG(fmt, ...) \
-       L_LOG(L_DEBUG, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __FUNCTION__, 
##__VA_ARGS__);
+#define LOG_DEBUG(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_DEBUG, __VA_ARGS__);
 #else
 #define LOG_DEBUG(fmt, ...)
 #endif
 
-void LOG_DOWNLOAD(const char* filename);
-
 /**
        *       output progress bar
        *       @param done bytes already downloaded
        *       @param total total bytes to download
        *       @param forceOutput force output
        */
-void LOG_PROGRESS(long done, long total, bool forceOutput = false);
+extern void LOG_PROGRESS(long done, long total, bool forceOutput = false);
 
 #ifdef __cplusplus
 }
diff --git a/src/downloader/lib/src/Util.cpp b/src/downloader/lib/src/Util.cpp
index 40a34f3..5025ba1 100644
--- a/src/downloader/lib/src/Util.cpp
+++ b/src/downloader/lib/src/Util.cpp
@@ -4,10 +4,8 @@
 #include "FileSystem/FileSystem.h"
 #include "Logger.h"
 
-#include <stdio.h>
 #include <string.h>
 #include <zlib.h>
-#include <time.h>
 
 std::vector<std::string> tokenizeString(const std::string& str, char c)
 {
@@ -95,11 +93,6 @@ bool urlToPath(const std::string& url, std::string& path)
        return true;
 }
 
-unsigned long getTime()
-{
-       return time(NULL);
-}
-
 #ifdef WIN32
 #include <windows.h>
 std::wstring s2ws(const std::string& s)
diff --git a/src/downloader/lib/src/Util.h b/src/downloader/lib/src/Util.h
index 385a8f9..0a6377e 100644
--- a/src/downloader/lib/src/Util.h
+++ b/src/downloader/lib/src/Util.h
@@ -45,11 +45,6 @@ unsigned int intmin(int x, int y);
 */
 bool urlToPath(const std::string& url, std::string& path);
 
-/**
- *     returns the time
- */
-unsigned long getTime();
-
 /*
         convert std::wstring to std::string
 */
diff --git a/src/downloader/lib/src/lsl/lslextract/CMakeLists.txt 
b/src/downloader/lib/src/lsl/lslextract/CMakeLists.txt
index faf71f0..6ac652e 100644
--- a/src/downloader/lib/src/lsl/lslextract/CMakeLists.txt
+++ b/src/downloader/lib/src/lsl/lslextract/CMakeLists.txt
@@ -8,6 +8,7 @@ add_executable(lslextract
        server/request_parser.cpp
        server/reply.cpp
        server/mime_types.cpp
+       ${pr-downloader_SOURCE_DIR}/src/Logger.cpp
 )
 FIND_PACKAGE(PNG REQUIRED)
 FIND_PACKAGE(X11 REQUIRED)
@@ -24,7 +25,7 @@ TARGET_LINK_LIBRARIES(lslextract
 )
 
 target_include_directories(lslextract
-       PRIVATE ${libSpringLobby_SOURCE_DIR}/src
-       PRIVATE ${LSL_JSONCPP_INCLUDE_DIR}
+       PRIVATE ${pr-downloader_SOURCE_DIR}/src/lsl
+       PRIVATE ${PRD_JSONCPP_INCLUDE_DIR}
 )
 
diff --git a/src/downloader/lib/src/lsl/lslextract/index.html 
b/src/downloader/lib/src/lsl/lslextract/index.html
index ee023f9..7080762 100644
--- a/src/downloader/lib/src/lsl/lslextract/index.html
+++ b/src/downloader/lib/src/lsl/lslextract/index.html
@@ -86,7 +86,7 @@ showResult("/maps");
 lslextract is a tool to extract metadata from spring engine content files
 </p>
 <h2>homepage</h2>
-<a 
href="https://github.com/springlobby/lsl";>https://github.com/springlobby/lsl</a>
+<a 
href="https://github.com/spring/pr-downloader";>https://github.com/spring/pr-downloader</a>
 </div>
 <div>
 <h2>List of local content files</h2>
diff --git a/src/downloader/lib/src/lsl/lslextract/lslextract.cpp 
b/src/downloader/lib/src/lsl/lslextract/lslextract.cpp
index 4fa88d1..78dd29b 100644
--- a/src/downloader/lib/src/lsl/lslextract/lslextract.cpp
+++ b/src/downloader/lib/src/lsl/lslextract/lslextract.cpp
@@ -77,7 +77,7 @@ int main(int argc, char* argv[])
                return 1;
        }
 
-       LSL::Util::config().ConfigurePaths(argv[1], argv[2], "");
+       LSL::Util::config().ConfigurePaths(argv[1], argv[2], "", "");
        LSL::usync().LoadUnitSyncLib(argv[2]);
 
        runServer("localhost", "9200", "");
diff --git a/src/downloader/lib/src/lsl/lslunitsync/image.cpp 
b/src/downloader/lib/src/lsl/lslunitsync/image.cpp
index 7a4940a..085b63b 100644
--- a/src/downloader/lib/src/lsl/lslunitsync/image.cpp
+++ b/src/downloader/lib/src/lsl/lslunitsync/image.cpp
@@ -251,11 +251,11 @@ bool UnitsyncImage::Load(const std::string& path) const
                fclose(f);
        } catch (cimg_library::CImgIOException& c) {
                m_data_ptr->clear();
-               LslError("%s:%d (%s) %s failed: %s", __FILE__, __LINE__, 
__FUNCTION__, path.c_str(), c.what());
+               LslWarning("%s:%d (%s) %s failed: %s", __FILE__, __LINE__, 
__FUNCTION__, path.c_str(), c.what());
                return false;
        } catch (cimg_library::CImgException& c) {
                m_data_ptr->clear();
-               LslError("%s:%d (%s) %s failed: %s", __FILE__, __LINE__, 
__FUNCTION__, path.c_str(), c.what());
+               LslWarning("%s:%d (%s) %s failed: %s", __FILE__, __LINE__, 
__FUNCTION__, path.c_str(), c.what());
                return false;
        }
        return true;
diff --git a/src/downloader/lib/src/lsl/lslutils/logging.h 
b/src/downloader/lib/src/lsl/lslutils/logging.h
index 157e52d..fcbee21 100644
--- a/src/downloader/lib/src/lsl/lslutils/logging.h
+++ b/src/downloader/lib/src/lsl/lslutils/logging.h
@@ -1,27 +1,18 @@
 #ifndef LSL_LOGGING_H
 #define LSL_LOGGING_H
 
-extern void lsllogdebug(const char* format, ...);
-extern void lslloginfo(const char* format, ...);
-extern void lsllogwarning(const char* format, ...);
-extern void lsllogerror(const char* format, ...);
+#include "../../Logger.h"
 
-#define LslDebug(...)                     \
-       do {                              \
-               lsllogdebug(__VA_ARGS__); \
-       } while (0)
-#define LslInfo(...)                     \
-       do {                                \
-               lslloginfo(__VA_ARGS__); \
-       } while (0)
-#define LslWarning(...)                     \
-       do {                                \
-               lsllogwarning(__VA_ARGS__); \
-       } while (0)
-#define LslError(...)                     \
-       do {                              \
-               lsllogerror(__VA_ARGS__); \
-       } while (0)
+#define LslDebug(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_DEBUG, __VA_ARGS__);
 
+#define LslInfo(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_INFO, __VA_ARGS__);
+
+#define LslWarning(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_WARN, __VA_ARGS__);
+
+#define LslError(...) \
+       L_LOG(__FILE__, __LINE__, __FUNCTION__, L_ERROR, __VA_ARGS__);
 
 #endif // LSL_LOGGING_H
diff --git a/src/downloader/lib/src/main.cpp b/src/downloader/lib/src/main.cpp
index cff2d07..dcabe8b 100644
--- a/src/downloader/lib/src/main.cpp
+++ b/src/downloader/lib/src/main.cpp
@@ -10,7 +10,6 @@
 #include <unistd.h>
 #include <string>
 #include <getopt.h>
-#include <stdio.h>
 #include <list>
 
 // TODO: Many of these enums are not implemented.
@@ -198,7 +197,7 @@ int main(int argc, char** argv)
                                break;
                        }
                        case HTTP_SEARCH: {
-                               printf("Not implemented\n");
+                               LOG_ERROR("Not implemented");
                                break;
                        }
                        case HELP: {
diff --git a/src/downloader/lib/test/CMakeLists.txt 
b/src/downloader/lib/test/CMakeLists.txt
index c1165a2..864d236 100644
--- a/src/downloader/lib/test/CMakeLists.txt
+++ b/src/downloader/lib/test/CMakeLists.txt
@@ -13,6 +13,7 @@ Else()
 
        SET(prd_testsrc
                ${CMAKE_CURRENT_SOURCE_DIR}/test.cpp
+               ${pr-downloader_SOURCE_DIR}/src/Logger.cpp
        )
 
        ADD_EXECUTABLE(prd_test WIN32 MACOSX_BUNDLE ${prd_testsrc} )
@@ -40,6 +41,7 @@ if (PRD_ENABLE_LSL)
 SET(basic_testSrc
        ${CMAKE_CURRENT_SOURCE_DIR}/lsl/basic.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/lsl/usync.cpp
+       ${pr-downloader_SOURCE_DIR}/src/Logger.cpp
        )
 
 ADD_EXECUTABLE(libSpringLobby_test WIN32 MACOSX_BUNDLE ${basic_testSrc} )
diff --git a/src/downloader/lib/test/lsl/usync.cpp 
b/src/downloader/lib/test/lsl/usync.cpp
index d96fb3a..771740e 100644
--- a/src/downloader/lib/test/lsl/usync.cpp
+++ b/src/downloader/lib/test/lsl/usync.cpp
@@ -8,15 +8,10 @@
 #include <cmath>
 #include <iostream>
 
-extern void lsllogerror(char const*, ...)
-{
-}
-extern void lsllogdebug(char const*, ...)
-{
-}
-extern void lsllogwarning(char const*, ...)
-{
-}
+extern void lsllogerror(char const*, ...){}
+extern void lsllogdebug(char const*, ...){}
+extern void lsllogwarning(char const*, ...){}
+extern void lslloginfo(char const*, ...){}
 
 void dummySync()
 {
diff --git a/src/downloader/prdownloader.cpp b/src/downloader/prdownloader.cpp
index 62b3ce9..ee4ca49 100644
--- a/src/downloader/prdownloader.cpp
+++ b/src/downloader/prdownloader.cpp
@@ -21,8 +21,8 @@
 #include "log.h"
 
 #include <list>
-#include <boost/thread/mutex.hpp>
 #include <memory>
+#include <mutex>
 #include <wx/log.h>
 #include <lslunitsync/unitsync.h>
 #include <lslutils/thread.h>
@@ -34,7 +34,7 @@ SLCONFIG("/Spring/PortableDownload", false, "true to download 
portable versions
 SLCONFIG("/Spring/RapidMasterUrl", "http://repos.springrts.com/repos.gz";, 
"master url for rapid downloads");
 
 static PrDownloader::DownloadProgress* m_progress = nullptr;
-static boost::mutex dlProgressMutex;
+static std::mutex dlProgressMutex;
 
 class DownloadItem : public LSL::WorkItem
 {
@@ -58,7 +58,7 @@ public:
                wxLogInfo("Starting download of filename: %s, name: %s", 
m_filename.c_str(), m_name.c_str());
 
                {
-                       boost::mutex::scoped_lock lock(dlProgressMutex);
+                       std::lock_guard<std::mutex> lock(dlProgressMutex);
 
                        if (m_progress == nullptr)
                                m_progress = new 
PrDownloader::DownloadProgress();
@@ -186,7 +186,7 @@ private:
 
 void PrDownloader::GetProgress(DownloadProgress& progress)
 {
-       boost::mutex::scoped_lock lock(dlProgressMutex);
+       std::lock_guard<std::mutex> lock(dlProgressMutex);
 
        if (m_progress == nullptr) {
                assert(false);
@@ -227,7 +227,7 @@ int clock_gettime(int dummy, struct timespec *ct)
 
 void updatelistener(int downloaded, int filesize)
 {
-       boost::mutex::scoped_lock lock(dlProgressMutex);
+       std::lock_guard<std::mutex> lock(dlProgressMutex);
 
        if (m_progress == nullptr)
                m_progress = new PrDownloader::DownloadProgress();
@@ -267,6 +267,7 @@ PrDownloader::~PrDownloader()
        GlobalEventManager::Instance()->UnSubscribeAll(this);
 
        if (!!m_dl_thread) {
+               m_dl_thread->Wait();
                delete m_dl_thread;
                m_dl_thread = nullptr;
        }
@@ -370,7 +371,7 @@ void PrDownloader::UpdateApplication(const std::string& 
updateurl)
 bool PrDownloader::DownloadUrl(const std::string& httpurl, std::string& res)
 {
        {
-               boost::mutex::scoped_lock lock(dlProgressMutex);
+               std::lock_guard<std::mutex> lock(dlProgressMutex);
                if (m_progress == nullptr)
                        m_progress = new PrDownloader::DownloadProgress();
                m_progress->name = httpurl;
diff --git a/src/gui/aboutbox.cpp b/src/gui/aboutbox.cpp
index 3d90871..247be57 100644
--- a/src/gui/aboutbox.cpp
+++ b/src/gui/aboutbox.cpp
@@ -13,9 +13,10 @@ slAboutBox::slAboutBox()
 {
        info = new wxAboutDialogInfo();
 
-       info->SetName(TowxString(getSpringlobbyName()));
-       info->SetVersion(TowxString(getSpringlobbyVersion()));
-       info->SetDescription(TowxString(getSpringlobbyName()) + _(" is a 
cross-platform lobby client for the Spring RTS engine"));
+       info->SetName(TowxString(GetSpringlobbyName()));
+       info->SetVersion(TowxString(GetSpringlobbyVersion()));
+       info->SetDescription(TowxString(GetSpringlobbyName())
+         + _(" is a cross-platform lobby client for the Spring RTS engine"));
        //info.SetCopyright(wxEmptyString;
        info->SetWebSite(_T("http://springlobby.info";));
        info->SetLicence(_T("GPL v2 or later"));
diff --git a/src/gui/chatpanel.cpp b/src/gui/chatpanel.cpp
index 5d1b1e1..5d2dd98 100644
--- a/src/gui/chatpanel.cpp
+++ b/src/gui/chatpanel.cpp
@@ -948,7 +948,7 @@ bool ChatPanel::Say(const wxString& message) //FIXME: 
remove all parsing / token
 
                if (line == _T( "/ver" )) {
                        //!this instance is not replaced with GetAppname for 
sake of help/debug online
-                       OutputLine(_("You have SpringLobby v") + 
TowxString(getSpringlobbyVersion()), sett().GetChatColorNormal());
+                       OutputLine(wxString::Format(_("You have %s."), 
GetSpringlobbyAgent()), sett().GetChatColorNormal());
                        return true;
                }
 
diff --git a/src/gui/hosting/battleroomtab.cpp 
b/src/gui/hosting/battleroomtab.cpp
index 36a536c..3532ccc 100644
--- a/src/gui/hosting/battleroomtab.cpp
+++ b/src/gui/hosting/battleroomtab.cpp
@@ -571,6 +571,8 @@ void BattleRoomTab::UpdateUser(User& user, bool 
userJustAdded)
        m_ready_chk->SetValue(bs.ready);
        // Enable or disable widgets' sensitivity as appropriate.
        if (bs.spectator) {
+               m_start_btn->SetLabel(_("Spectate"));
+               m_start_btn->SetToolTip(_("Watch a running match (you are a 
spectator)"));
                m_side_sel->Disable();
                m_ally_sel->Disable();
                m_team_sel->Disable();
@@ -586,6 +588,8 @@ void BattleRoomTab::UpdateUser(User& user, bool 
userJustAdded)
                        OnAutolaunch();
                }
        } else { // we are player
+               m_start_btn->SetLabel(_("Start"));
+               m_start_btn->SetToolTip(_("Start the battle"));
                m_side_sel->Enable();
                m_ally_sel->Enable();
                m_team_sel->Enable();
@@ -625,42 +629,70 @@ void BattleRoomTab::OnPromote(wxCommandEvent& /*unused*/)
        }
 }
 
+/*
+ * Running? Spec? Founder? Action
+ *    0       0      0     DL -> ready -> Ring -> OpponentCheck -> !start
+ *    0       0      1     DL -> ready -> Ring -> OpponentCheck -> StartHB
+ *    0       1      0     DL -> ready -> "Unspec to play"
+ *    0       1      1     DL -> ready -> "Unspec to play"
+ *    1       0      0     DL -> ready -> start
+ *    1       0      1     DL -> ready -> start
+ *    1       1      0     DL -> ready -> start
+ *    1       1      1     DL -> ready -> start
+ */
 void BattleRoomTab::OnStart(wxCommandEvent& /*unused*/)
 {
        slLogDebugFunc("");
        if (m_battle == nullptr)
                return;
 
-       //start manually clicked, force start
-       m_battle->SetAutolaunchGame(true);
-
-       if (m_battle->IsFounderMe()) {
-               m_battle->GetMe().BattleStatus().ready = true;
-               if (!m_battle->IsEveryoneReady()) {
-                       int answer = customMessageBox(SL_MAIN_ICON, _("Some 
Players are not ready yet\nDo you want to force start?"), _("Not ready"), 
wxYES_NO | wxCANCEL);
-                       if (answer == wxNO)
-                               return;
-               }
-
-               m_battle->SaveMapDefaults(); // save map presets
+       if (ui().IsSpringRunning()) {
+               customMessageBoxModal(SL_MAIN_ICON, _("You are already 
playing/spectating."), _("Error"));
+               return;
+       }
 
-               m_battle->StartHostedBattle();
-       } else {
-               if (ui().NeedsDownload(m_battle)) {
-                       wxLogWarning("Cannot start, need to download first!");
-                       return;
-               }
+       if (ui().NeedsDownload(m_battle)) {
+               customMessageBoxModal(SL_MAIN_ICON, _("You must download 
missing content before you"
+                 " can start or wait for the downloads to finish if they had 
been started already."),
+                 _("Error"));
+               return;
+       }
 
-               if (m_battle->GetFounder().Status().in_game) {
-                       if (!ui().IsSpringRunning())
-                               m_battle->StartSpring();
-                       else
-                               customMessageBoxModal(SL_MAIN_ICON, _("Spring 
is already running."), _("Error"));
-               } else {
-                       
m_battle->m_autohost_manager->GetAutohostHandler().Start();
-                       //customMessageBoxNoModal( SL_MAIN_ICON, _("Host is not 
ingame."), _("Error") );
+       //start manually clicked, force start
+       m_battle->SetAutolaunchGame(true);
+       m_ready_chk->SetValue(true); OnImReady();
+
+       // Is remote battle running?
+       if (m_battle->GetFounder().Status().in_game) {
+               m_battle->StartSpring();
+       } else { // No, it is not running.
+               if (m_battle->GetMe().BattleStatus().spectator) {
+                       customMessageBoxModal(SL_MAIN_ICON,
+                         _("No battle is running. You must be a player to 
start"), _("Error"));
+               } else { // I am a player
+                       if (m_battle->IsEveryoneReady()) {
+                               if (m_battle->DoesOpponentExist()) {
+                                       if (m_battle->IsFounderMe()) {
+                                               m_battle->SaveMapDefaults(); // 
save map presets
+                                               m_battle->StartHostedBattle();
+                                       } else {
+                                               
m_battle->m_autohost_manager->GetAutohostHandler().Start();
+                                       }
+                               } else {
+                                       customMessageBoxModal(SL_MAIN_ICON,
+                                         _("A battle with no opponents is no 
battle at all" // ...
+                                           " (Hint: add a bot and try 
again)."), _("Error"));
+                               }
+                       } else {
+                               int answer = customMessageBox(SL_MAIN_ICON,
+                                 _("Some players are not ready, ring them?"),
+                                 _("Not ready"), wxYES | wxCANCEL);
+                               if (answer == wxYES)
+                                       
m_battle->RingNotSyncedAndNotReadyPlayers();
+                       }
                }
        }
+
        //reset to value from gui
        m_battle->SetAutolaunchGame(m_autolaunch_chk->GetValue());
 }
@@ -763,13 +795,18 @@ void BattleRoomTab::OnAutolaunch()
 }
 
 
-void BattleRoomTab::OnImReady(wxCommandEvent& /*unused*/)
+void BattleRoomTab::OnImReady()
 {
        if (!m_battle)
                return;
        m_battle->SetImReady(m_ready_chk->GetValue());
 }
 
+void BattleRoomTab::OnImReady(wxCommandEvent& /*unused*/)
+{
+       OnImReady();
+}
+
 
 void BattleRoomTab::OnLock(wxCommandEvent& /*unused*/)
 {
@@ -839,9 +876,21 @@ void BattleRoomTab::OnImSpec(wxCommandEvent& /*unused*/)
 {
        if (!m_battle)
                return;
-       m_battle->ForceSpectator(m_battle->GetMe(), m_spec_chk->GetValue());
-}
 
+       // Prevent taking same team ID as someone else when un-speccing.
+       if (m_spec_chk->IsChecked()) {
+               m_battle->ForceSpectator(m_battle->GetMe(), true);
+       } else {
+               int team = m_battle->GetFreeTeam(/*excludeme=*/false);
+               m_team_sel->SetSelection(team);
+               UserBattleStatus& myStatus = m_battle->GetMe().BattleStatus();
+               // Due to ForceSpectator working on a local copy, one way to 
implement this is by:
+               int oldteam = myStatus.team;
+               myStatus.team = team;
+               m_battle->ForceSpectator(m_battle->GetMe(), false);
+               myStatus.team = oldteam;
+       }
+}
 
 void BattleRoomTab::OnTeamSel(wxCommandEvent& /*unused*/)
 {
diff --git a/src/gui/hosting/battleroomtab.h b/src/gui/hosting/battleroomtab.h
index cf8871f..a604504 100644
--- a/src/gui/hosting/battleroomtab.h
+++ b/src/gui/hosting/battleroomtab.h
@@ -88,6 +88,7 @@ private:
        {
                OnAutolaunch();
        }
+       void OnImReady();
        void OnImReady(wxCommandEvent& event);
        void OnLock(wxCommandEvent& event);
        void OnAutoHost(wxCommandEvent& event);
diff --git a/src/gui/hosting/hostbattledialog.cpp 
b/src/gui/hosting/hostbattledialog.cpp
index edde619..d2fca9a 100644
--- a/src/gui/hosting/hostbattledialog.cpp
+++ b/src/gui/hosting/hostbattledialog.cpp
@@ -98,22 +98,20 @@ HostBattleDialog::HostBattleDialog(wxWindow* parent)
        m_mod_lbl->Wrap(-1);
        topsizer->Add(m_mod_lbl, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
 
-       wxArrayString m_engine_picChoices;
        wxBoxSizer* mod_choice_button_sizer2 = new wxBoxSizer(wxHORIZONTAL);
-       m_engine_pic = new wxChoice(m_panel, CHOOSE_ENGINE, wxDefaultPosition, 
wxDefaultSize, m_engine_picChoices, 0);
-       m_engine_pic->SetToolTip(_("Select the engine version to play."));
-       mod_choice_button_sizer2->Add(m_engine_pic, 0, wxALL, 5);
+       m_engine_choice = new wxChoice(m_panel, CHOOSE_ENGINE);
+       m_engine_choice->SetToolTip(_("Select the engine version to play."));
+       mod_choice_button_sizer2->Add(m_engine_choice, 0, wxALL, 5);
        topsizer->Add(mod_choice_button_sizer2, 0, wxEXPAND | wxALL, 1);
 
        m_mod_lbl = new wxStaticText(m_panel, wxID_ANY, _("Game"), 
wxDefaultPosition, wxDefaultSize, 0);
        m_mod_lbl->Wrap(-1);
        topsizer->Add(m_mod_lbl, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
 
-       wxArrayString m_mod_picChoices;
        wxBoxSizer* mod_choice_button_sizer = new wxBoxSizer(wxHORIZONTAL);
-       m_mod_pic = new wxChoice(m_panel, wxID_ANY, wxDefaultPosition, 
wxDefaultSize, m_mod_picChoices, 0);
-       m_mod_pic->SetToolTip(_("Select the game to play."));
-       mod_choice_button_sizer->Add(m_mod_pic, 0, wxALL, 5);
+       m_game_choice = new wxChoice(m_panel, wxID_ANY);
+       m_game_choice->SetToolTip(_("Select the game to play."));
+       mod_choice_button_sizer->Add(m_game_choice, 0, wxALL, 5);
 
        wxBitmap mp = charArr2wxBitmap(arrow_refresh_png, 
sizeof(arrow_refresh_png));
        m_refresh_btn = new wxBitmapButton(m_panel, BTN_REFRESH, mp);
@@ -293,39 +291,39 @@ HostBattleDialog::HostBattleDialog(wxWindow* parent)
 
 void HostBattleDialog::ReloadModList()
 {
-       m_mod_pic->Clear();
+       m_game_choice->Clear();
 
        wxArrayString modlist = lslTowxArrayString(LSL::usync().GetGameList());
        wxString last = sett().GetLastHostMod();
 
        size_t nummods = modlist.Count();
        for (size_t i = 0; i < nummods; i++) {
-               m_mod_pic->Insert(modlist[i], i);
+               m_game_choice->Insert(modlist[i], i);
                if (last == modlist[i])
-                       m_mod_pic->SetSelection(i);
+                       m_game_choice->SetSelection(i);
        }
 
-       if (m_mod_pic->GetSelection() == wxNOT_FOUND) {
-               m_mod_pic->SetSelection(0);
+       if (m_game_choice->GetSelection() == wxNOT_FOUND) {
+               m_game_choice->SetSelection(0);
        }
 }
 
 void HostBattleDialog::ReloadEngineList()
 {
-       m_engine_pic->Clear();
+       m_engine_choice->Clear();
        std::map<std::string, LSL::SpringBundle> versions = 
SlPaths::GetSpringVersionList();
        const std::string last = SlPaths::GetCurrentUsedSpringIndex();
        int i = 0;
        for (auto pair : versions) {
-               m_engine_pic->Insert(TowxString(pair.first), i);
+               m_engine_choice->Insert(TowxString(pair.first), i);
                if (last == pair.first) {
-                       m_engine_pic->SetSelection(i);
+                       m_engine_choice->SetSelection(i);
                }
                i++;
        }
 
-       if (m_engine_pic->GetSelection() == wxNOT_FOUND) {
-               m_engine_pic->SetSelection(0);
+       if (m_engine_choice->GetSelection() == wxNOT_FOUND) {
+               m_engine_choice->SetSelection(0);
        }
        //unitsync change needs a refresh of games as well
        ReloadModList();
@@ -334,13 +332,13 @@ void HostBattleDialog::ReloadEngineList()
 
 void HostBattleDialog::OnOk(wxCommandEvent& /*unused*/)
 {
-       if (m_mod_pic->GetSelection() == wxNOT_FOUND) {
+       if (m_game_choice->GetSelection() == wxNOT_FOUND) {
                wxLogWarning(_T( "no game selected" ));
                customMessageBox(SL_MAIN_ICON, _("You have to select a game 
first."), _("No game selected."), wxOK);
                return;
        }
 
-       if (m_engine_pic->GetSelection() == wxNOT_FOUND) {
+       if (m_engine_choice->GetSelection() == wxNOT_FOUND) {
                wxLogWarning(_T( "no engine selected" ));
                customMessageBox(SL_MAIN_ICON, _("You have to select a engine 
version first."), _("No engine selected."), wxOK);
                return;
@@ -349,7 +347,7 @@ void HostBattleDialog::OnOk(wxCommandEvent& /*unused*/)
        if (m_desc_text->GetValue().IsEmpty())
                m_desc_text->SetValue(_T( "(none)" ));
        sett().SetLastHostDescription(m_desc_text->GetValue());
-       sett().SetLastHostMod(m_mod_pic->GetString(m_mod_pic->GetSelection()));
+       
sett().SetLastHostMod(m_game_choice->GetString(m_game_choice->GetSelection()));
        wxString password = m_pwd_text->GetValue();
        password.Replace(_T(" "), wxEmptyString);
        sett().SetLastHostPassword(password);
@@ -439,7 +437,7 @@ void HostBattleDialog::OnUseRelay(wxCommandEvent&)
 
 void HostBattleDialog::OnEngineSelect(wxCommandEvent& /*event*/)
 {
-       
SlPaths::SetUsedSpringIndex(STD_STRING(m_engine_pic->GetString(m_engine_pic->GetSelection())));
+       
SlPaths::SetUsedSpringIndex(STD_STRING(m_engine_choice->GetString(m_engine_choice->GetSelection())));
        LSL::usync().ReloadUnitSyncLib();
        ReloadEngineList();
 }
diff --git a/src/gui/hosting/hostbattledialog.h 
b/src/gui/hosting/hostbattledialog.h
index 4c93985..51621ef 100644
--- a/src/gui/hosting/hostbattledialog.h
+++ b/src/gui/hosting/hostbattledialog.h
@@ -46,8 +46,8 @@ private:
        wxStaticText* m_desc_lbl;
        wxTextCtrl* m_desc_text;
        wxStaticText* m_mod_lbl;
-       wxChoice* m_mod_pic;
-       wxChoice* m_engine_pic;
+       wxChoice* m_engine_choice;
+       wxChoice* m_game_choice;
        wxStaticText* m_pwd_lbl;
        wxTextCtrl* m_pwd_text;
        wxChoice* m_rank_direction;
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index a04a3c9..306b84f 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -117,7 +117,7 @@ EVT_COMMAND(mySHOW_ERROR_MESSAGE, wxEVT_SHOW, 
MainWindow::OnShowErrorMessage)
 END_EVENT_TABLE()
 
 MainWindow::MainWindow()
-    : wxFrame(NULL, -1, TowxString(getSpringlobbyName()))
+    : wxFrame(NULL, -1, TowxString(GetSpringlobbyName()))
     , WindowAttributesPickle(_T("MAINWINDOW"), this, wxSize(720, 576))
     , m_opts_dialog(NULL)
     , m_autojoin_dialog(NULL)
@@ -639,10 +639,10 @@ void MainWindow::OnMenuAutojoinChannels(wxCommandEvent& 
/*unused*/)
 void MainWindow::OnMenuSelectLocale(wxCommandEvent& /*unused*/)
 {
        if (wxGetApp().SelectLanguage()) {
-               customMessageBoxModal(SL_MAIN_ICON,
-                                     _("You need to restart SpringLobby for 
the language change to take effect."),
-                                     _("Restart required"),
-                                     wxICON_EXCLAMATION | wxOK);
+               customMessageBoxModal(SL_MAIN_ICON, wxString::Format(
+                 _("You need to restart %s for the language change to take 
effect."),
+                 GetSpringlobbyName()),
+                 _("Restart required"), wxICON_EXCLAMATION | wxOK);
        }
 }
 
@@ -674,7 +674,8 @@ void MainWindow::OnMenuResetLayout(wxCommandEvent& 
/*event*/)
 {
        cfg().Write(_T( "/ResetLayout" ), true);
        sett().SaveSettings();
-       customMessageBoxModal(SL_MAIN_ICON, _("Please restart SpringLobby 
now"), wxEmptyString);
+       customMessageBoxModal(SL_MAIN_ICON, wxString::Format(
+         _("Please restart %s now"), GetSpringlobbyName()), wxEmptyString);
 }
 
 const wxArrayString& MainWindow::GetTabNames()
@@ -728,7 +729,7 @@ void MainWindow::OnMenuPathInfo(wxCommandEvent& /*event*/)
 void MainWindow::OnMenuDownload(wxCommandEvent& /*event*/)
 {
        wxString lines;
-       if (!ui().AskText(_("Which Archives to download? Put each archive on a 
single line, for example \ngame:ba:stable\nmap:The Rock Final\nengine:spring 
98.0"), _("Download Archives"), lines, true))
+       if (!ui().AskText(_("Which Archives to download? Put each archive on a 
single line, for example") + _T("\ngame:ba:stable\nmap:The Rock 
Final\nengine:spring 104.0"), _("Download Archives"), lines, true))
                return;
        size_t start = 0;
        int pos = 0;
diff --git a/src/gui/mapctrl.cpp b/src/gui/mapctrl.cpp
index 705ffd2..a13156e 100644
--- a/src/gui/mapctrl.cpp
+++ b/src/gui/mapctrl.cpp
@@ -1,5 +1,6 @@
 /* This file is part of the Springlobby (GPL v2 or later), see COPYING */
 
+#include <functional>
 #include <wx/panel.h>
 #include <wx/dcclient.h>
 #include <wx/bitmap.h>
@@ -101,7 +102,7 @@ static inline int ReadInt24(const unsigned char* p)
 
 MapCtrl::MapCtrl(wxWindow* parent, int size, IBattle* battle, bool readonly, 
bool draw_start_types, bool singleplayer)
     : wxPanel(parent, -1, wxDefaultPosition, wxSize(size, size), 
wxSIMPLE_BORDER | wxFULL_REPAINT_ON_RESIZE)
-    , m_async(boost::bind(&MapCtrl::OnGetMapImageAsyncCompleted, this, _1))
+    , m_async(std::bind(&MapCtrl::OnGetMapImageAsyncCompleted, this, 
std::placeholders::_1))
     , m_minimap(0)
     , m_metalmap(0)
     , m_heightmap(0)
diff --git a/src/gui/mapgridctrl.cpp b/src/gui/mapgridctrl.cpp
index 66e28d2..a244635 100644
--- a/src/gui/mapgridctrl.cpp
+++ b/src/gui/mapgridctrl.cpp
@@ -1,5 +1,6 @@
 /* This file is part of the Springlobby (GPL v2 or later), see COPYING */
 
+#include <functional>
 #include <wx/dcbuffer.h>
 #include <wx/geometry.h>
 #include <wx/settings.h>
@@ -46,8 +47,8 @@ const wxEventType MapGridCtrl::LoadingCompletedEvt = 
wxNewEventType();
 
 MapGridCtrl::MapGridCtrl(wxWindow* parent, wxSize size, wxWindowID id)
     : wxPanel(parent, id, wxDefaultPosition, size, wxSIMPLE_BORDER | 
wxFULL_REPAINT_ON_RESIZE)
-    , m_async_image(boost::bind(&MapGridCtrl::OnGetMapImageAsyncCompleted, 
this, _1))
-    , m_async_ex(boost::bind(&MapGridCtrl::OnGetMapExAsyncCompleted, this, _1))
+    , m_async_image(std::bind(&MapGridCtrl::OnGetMapImageAsyncCompleted, this, 
std::placeholders::_1))
+    , m_async_ex(std::bind(&MapGridCtrl::OnGetMapExAsyncCompleted, this, 
std::placeholders::_1))
     , m_async_ops_count(0)
     , m_selection_follows_mouse(sett().GetMapSelectorFollowsMouse())
     , m_size(0, 0)
@@ -366,6 +367,7 @@ void MapGridCtrl::DrawMap(wxDC& dc, MapData& map, int x, 
int y)
                case MapState_NoMinimap:
                        map.priority = 1;
                        UpdateAsyncFetches();
+                       [[fallthrough]];
                // fall through, both when starting fetch and when waiting
                // for it to finish, we want to show temporary image
                case MapState_GetMinimap:
diff --git a/src/gui/notifications/libnotify.cpp 
b/src/gui/notifications/libnotify.cpp
index 06e897d..d7734e9 100644
--- a/src/gui/notifications/libnotify.cpp
+++ b/src/gui/notifications/libnotify.cpp
@@ -26,9 +26,9 @@ void LibnotifyNotification::Show(const wxBitmap& icon, const 
size_t /*pos*/, con
        NotifyNotification* n;
        notify_init("Test");
 #if !defined(NOTIFY_VERSION_MINOR) || (NOTIFY_VERSION_MAJOR == 0 && 
NOTIFY_VERSION_MINOR < 7)
-       n = notify_notification_new(getSpringlobbyName().c_str(), 
data.second.mb_str(), NULL, NULL);
+       n = notify_notification_new(GetSpringlobbyName().c_str(), 
data.second.mb_str(), NULL, NULL);
 #else
-       n = notify_notification_new(getSpringlobbyName().c_str(), 
data.second.mb_str(), NULL);
+       n = notify_notification_new(GetSpringlobbyName().c_str(), 
data.second.mb_str(), NULL);
 #endif
        notify_notification_set_timeout(n, 
sett().GetNotificationPopupDisplayTime() * 1000);
 
diff --git a/src/gui/options/lobbyoptionstab.cpp 
b/src/gui/options/lobbyoptionstab.cpp
index 6ceccd0..2c06370 100644
--- a/src/gui/options/lobbyoptionstab.cpp
+++ b/src/gui/options/lobbyoptionstab.cpp
@@ -24,6 +24,7 @@
 #include "gui/mainwindow.h"
 #include "utils/conversion.h"
 #include "utils/uievents.h"
+#include "utils/version.h"
 #include "gui/notifications/notificationmanager.h"
 #include "utils/globalevents.h"
 
@@ -98,9 +99,9 @@ LobbyOptionsTab::LobbyOptionsTab(wxWindow* parent)
        m_editor_box_sizer->Add(m_editor_loc_sizer, 0, wxEXPAND | wxALL, 2);
        ////////
        wxStaticBoxSizer* m_autojoin_sizer = new wxStaticBoxSizer(wxVERTICAL, 
this, _("Autoconnect"));
-       m_autoconnect_label = new wxStaticText(this,
-                                              -1,
-                                              _("If checked, SpringLobby will 
automatically log on to the last used server"));
+       m_autoconnect_label = new wxStaticText(this, -1, wxString::Format (
+         _("If checked, %s will automatically log on to the last used server"),
+         GetSpringlobbyName()));
        m_autojoin = new wxCheckBox(this, -1, _("Autoconnect on lobby start"), 
wxDefaultPosition, wxDefaultSize, 0);
        m_autojoin->SetValue(cfg().ReadBool(_T( "/Server/Autoconnect")));
        m_autojoin_sizer->Add(m_autoconnect_label, 1, wxEXPAND | wxALL, 5);
@@ -109,9 +110,9 @@ LobbyOptionsTab::LobbyOptionsTab(wxWindow* parent)
        m_main_sizer->Add(m_web_box_sizer, 0, wxEXPAND | wxALL, 5);
        m_main_sizer->Add(m_editor_box_sizer, 0, wxEXPAND | wxALL, 5);
        wxStaticBoxSizer* m_updater_sizer = new wxStaticBoxSizer(wxVERTICAL, 
this, _("Automatic updates"));
-       m_updater_label = new wxStaticText(this,
-                                          -1,
-                                          _("SpringLobby can check at startup 
if a newer version is available and automatically download it for you."));
+       m_updater_label = new wxStaticText(this, -1, wxString::Format(
+         _("%s can check at startup if a newer version is available and 
automatically download it for you."),
+         GetSpringlobbyName()));
        m_updater = new wxCheckBox(this, -1, _("automatically check for 
updates"), wxDefaultPosition, wxDefaultSize, 0);
        m_updater->SetValue(cfg().ReadBool(_T("/General/AutoUpdate")));
        m_updater_sizer->Add(m_updater_label, 1, wxEXPAND | wxALL, 5);
@@ -124,7 +125,8 @@ LobbyOptionsTab::LobbyOptionsTab(wxWindow* parent)
        m_show_tooltips = new wxCheckBox(this, -1, _("Show Tooltips?"), 
wxDefaultPosition, wxDefaultSize, 0);
        m_show_tooltips->SetValue(sett().GetShowTooltips());
 #ifndef __WXMSW__ // on windows this change is immediate
-       m_show_tooltips_label = new wxStaticText(this, -1, _("Requires 
SpringLobby restart to take effect."));
+       m_show_tooltips_label = new wxStaticText(this, -1, wxString::Format(
+         _("Requires %s restart to take effect."), GetSpringlobbyName()));
        m_show_tooltips_sizer->Add(m_show_tooltips_label, 1, wxEXPAND | wxALL, 
5);
 #endif
        m_show_tooltips_sizer->Add(m_show_tooltips, 0, wxEXPAND | wxALL, 5);
diff --git a/src/gui/options/mainoptionstab.cpp 
b/src/gui/options/mainoptionstab.cpp
index 635d86d..abf7347 100644
--- a/src/gui/options/mainoptionstab.cpp
+++ b/src/gui/options/mainoptionstab.cpp
@@ -27,6 +27,7 @@
 #include "gui/uiutils.h"
 #include "gui/controls.h"
 #include "utils/conversion.h"
+#include "utils/version.h"
 #include "log.h"
 #include "utils/globalevents.h"
 
@@ -166,7 +167,9 @@ void MainOptionsTab::SavePerspective(const wxString& 
perspective_name)
 }
 
 OptionsDialog::OptionsDialog(wxWindow* parent)
-    : wxDialog(parent, -1, _("SpringLobby Preferences"), wxDefaultPosition, 
wxSize(1055, 620), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
+    : wxDialog(parent, -1, wxString::Format(_("%s Preferences"), 
GetSpringlobbyName()),
+           wxDefaultPosition, wxSize(1055, 620),
+           wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
     , WindowAttributesPickle(_T("preferences"), this, wxSize(1055, 620))
 {
        SetMinSize(wxSize(1055, 620));
diff --git a/src/gui/options/springoptionstab.cpp 
b/src/gui/options/springoptionstab.cpp
index 9af832e..7f55ec7 100644
--- a/src/gui/options/springoptionstab.cpp
+++ b/src/gui/options/springoptionstab.cpp
@@ -284,11 +284,17 @@ void SpringOptionsTab::OnAddBundle(wxCommandEvent& 
/*event*/)
 
                        if (!bundle.IsValid() || version.IsEmpty()) {
                                failed = true;
-                               failMessage = wxString::Format(_T("%s did not 
find engine and unitsync executables at %s\n\nPlease ensure that both exist and 
that you have appropriate access privileges."), getSpringlobbyName().c_str(), 
bundle.path.c_str());
+                               failMessage = wxString::Format(_T(
+                                 "%s did not find engine and unitsync 
executables at %s\n\n"
+                                 "Please ensure that both exist and that you 
have appropriate access privileges."
+                                 ), GetSpringlobbyName().c_str(), 
bundle.path.c_str());
                        }
                } catch (const LSL::Exceptions::unitsync& e) {
                        failed = true;
-                       failMessage = wxString::Format(_T("%s could not obtain 
the version string from the shared library file %s\n\nPlease provide a valid 
unitsync file."), getSpringlobbyName().c_str(), bundle.unitsync.c_str());
+                       failMessage = wxString::Format(_T(
+                         "%s could not obtain the version string from the 
shared library file %s\n\n"
+                         "Please provide a valid unitsync file."),
+                         GetSpringlobbyName().c_str(), 
bundle.unitsync.c_str());
                }
                if (failed) {
                        customMessageBox(SL_MAIN_ICON, failMessage, 
_("Configuration error"), wxOK);
@@ -388,9 +394,10 @@ void SpringOptionsTab::SwitchUnitsync(const std::string& 
newIndex, const std::st
        SlPaths::SetUsedSpringIndex(newIndex);
        if (!LSL::usync().LoadUnitSyncLib(SlPaths::GetUnitSync(newIndex))) { 
//FIXME: make LoadUnitSyncLib() async (partly done)
                wxLogWarning(_T( "Cannot load UnitSync" ));
-               customMessageBox(SL_MAIN_ICON,
-                                wxString::Format(_T("%s is unable to load your 
UnitSync library into the process.\n\nYou might want to take another look at 
your unitsync setting."), getSpringlobbyName().c_str()),
-                                _("Spring error"), wxOK);
+               customMessageBox(SL_MAIN_ICON, wxString::Format(_T(
+                 "%s is unable to load your UnitSync library into the 
process.\n\n"
+                 "You might want to take another look at your unitsync 
setting."),
+                 GetSpringlobbyName().c_str()), _("Spring error"), wxOK);
                SlPaths::SetUsedSpringIndex(oldIndex);
                DoRestore();
        }
diff --git a/src/gui/playback/playbacktab.cpp b/src/gui/playback/playbacktab.cpp
index f12f204..e6f8843 100644
--- a/src/gui/playback/playbacktab.cpp
+++ b/src/gui/playback/playbacktab.cpp
@@ -344,6 +344,10 @@ void PlaybackTab::Deselected()
 
 void PlaybackTab::ReloadList()
 {
+       if (!LSL::usync().IsLoaded()) {
+               wxLogWarning(_("Unitsync library required"));
+               return;
+       }
        Deselect();
        m_replay_dataview->Clear();
        if (m_replay_loader == nullptr) {
diff --git a/src/gui/singleplayertab.cpp b/src/gui/singleplayertab.cpp
index a5ad439..56f60ff 100644
--- a/src/gui/singleplayertab.cpp
+++ b/src/gui/singleplayertab.cpp
@@ -128,15 +128,15 @@ SinglePlayerTab::SinglePlayerTab(wxWindow* parent, 
MainSinglePlayerTab& msptab)
        m_mod_lbl = new wxStaticText(this, -1, _("Game:"));
        m_ctrl_sizer->Add(m_mod_lbl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
 
-       m_mod_pick = new wxChoice(this, SP_MOD_PICK);
-       m_ctrl_sizer->Add(m_mod_pick, 1, wxALL, 5);
+       m_game_choice = new wxChoice(this, SP_MOD_PICK);
+       m_ctrl_sizer->Add(m_game_choice, 1, wxALL, 5);
 
        m_mod_lbl = new wxStaticText(this, -1, _("Engine:"));
        m_ctrl_sizer->Add(m_mod_lbl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
 
-       m_engine_pick = new wxChoice(this, SP_ENGINE_PICK);
-       m_engine_pick->SetToolTip(_("Select the engine version to play."));
-       m_ctrl_sizer->Add(m_engine_pick, 1, wxALL, 5);
+       m_engine_choice = new wxChoice(this, SP_ENGINE_PICK);
+       m_engine_choice->SetToolTip(_("Select the engine version to play."));
+       m_ctrl_sizer->Add(m_engine_choice, 1, wxALL, 5);
 
        //  m_ctrl_sizer->Add( 0, 0, 1, wxEXPAND, 0 );
 
@@ -203,7 +203,7 @@ void SinglePlayerTab::ReloadMaplist()
        } else {
                
m_map_pick->SetStringSelection(TowxString(m_battle.GetHostMapName()));
                if (m_map_pick->GetStringSelection().IsEmpty()) {
-                       SetMap(m_mod_pick->GetCount() - 1);
+                       SetMap(m_game_choice->GetCount() - 1);
                }
        }
 }
@@ -211,15 +211,15 @@ void SinglePlayerTab::ReloadMaplist()
 
 void SinglePlayerTab::ReloadModlist()
 {
-       m_mod_pick->Clear();
-       m_mod_pick->Append(lslTowxArrayString(LSL::usync().GetGameList()));
-       m_mod_pick->Insert(_("-- Select one --"), m_mod_pick->GetCount());
+       m_game_choice->Clear();
+       m_game_choice->Append(lslTowxArrayString(LSL::usync().GetGameList()));
+       m_game_choice->Insert(_("-- Select one --"), m_game_choice->GetCount());
        if (m_battle.GetHostGameName().empty()) {
-               m_mod_pick->SetSelection(m_mod_pick->GetCount() - 1);
+               m_game_choice->SetSelection(m_game_choice->GetCount() - 1);
        } else {
-               
m_mod_pick->SetStringSelection(TowxString(m_battle.GetHostGameName()));
-               if (m_mod_pick->GetStringSelection().empty()) {
-                       SetMod(m_mod_pick->GetCount() - 1);
+               
m_game_choice->SetStringSelection(TowxString(m_battle.GetHostGameName()));
+               if (m_game_choice->GetStringSelection().empty()) {
+                       SetMod(m_game_choice->GetCount() - 1);
                }
        }
 }
@@ -229,22 +229,22 @@ void SinglePlayerTab::ReloadEngineList()
 {
        SlPaths::ValidatePaths();
 
-       m_engine_pick->Clear();
+       m_engine_choice->Clear();
 
        std::map<std::string, LSL::SpringBundle> versions = 
SlPaths::GetSpringVersionList();
        const std::string last = SlPaths::GetCurrentUsedSpringIndex();
        int i = 0;
 
        for (auto pair : versions) {
-               m_engine_pick->Insert(TowxString(pair.first), i);
+               m_engine_choice->Insert(TowxString(pair.first), i);
                if (last == pair.first) {
-                       m_engine_pick->SetSelection(i);
+                       m_engine_choice->SetSelection(i);
                }
                i++;
        }
 
-       if (m_engine_pick->GetSelection() == wxNOT_FOUND) {
-               m_engine_pick->SetSelection(0);
+       if (m_engine_choice->GetSelection() == wxNOT_FOUND) {
+               m_engine_choice->SetSelection(0);
        }
 
        if (i == 0) {
@@ -299,7 +299,7 @@ void SinglePlayerTab::ResetUsername()
 void SinglePlayerTab::SetMod(unsigned int index)
 {
        //ui().ReloadUnitSync();
-       if (index >= m_mod_pick->GetCount() - 1) {
+       if (index >= m_game_choice->GetCount() - 1) {
                m_battle.SetHostGame("", "");
        } else {
                try {
@@ -312,13 +312,13 @@ void SinglePlayerTab::SetMod(unsigned int index)
        m_minimap->UpdateMinimap();
        m_battle.SendHostInfo(IBattle::HI_Restrictions); // Update restrictions 
in options.
        m_battle.SendHostInfo(IBattle::HI_Game_Changed); // reload mod options
-       m_mod_pick->SetSelection(index);
+       m_game_choice->SetSelection(index);
 }
 
 
 bool SinglePlayerTab::ValidSetup() const
 {
-       if (m_mod_pick->GetSelection() == wxNOT_FOUND) {
+       if (m_game_choice->GetSelection() == wxNOT_FOUND) {
                wxLogWarning(_T("no game selected"));
                customMessageBox(SL_MAIN_ICON, _("You have to select a game 
first."), _("Game setup error"));
                return false;
@@ -352,7 +352,7 @@ void SinglePlayerTab::OnMapSelect(wxCommandEvent& 
/*unused*/)
 
 void SinglePlayerTab::OnModSelect(wxCommandEvent& /*unused*/)
 {
-       const int index = m_mod_pick->GetCurrentSelection();
+       const int index = m_game_choice->GetCurrentSelection();
 
        if (index == wxNOT_FOUND) { return; }
 
@@ -364,13 +364,13 @@ void SinglePlayerTab::OnModSelect(wxCommandEvent& 
/*unused*/)
 
 void SinglePlayerTab::OnEngineSelect(wxCommandEvent& /*event*/)
 {
-       const int index = m_engine_pick->GetSelection();
+       const int index = m_engine_choice->GetSelection();
 
        if (index == wxNOT_FOUND) {
-               wxLogError("Invalid index selected: %d > %d", index, 
m_engine_pick->GetCount());
+               wxLogError("Invalid index selected: %d > %d", index, 
m_engine_choice->GetCount());
                return;
        }
-       const std::string selection = 
STD_STRING(m_engine_pick->GetString(index));
+       const std::string selection = 
STD_STRING(m_engine_choice->GetString(index));
        wxLogMessage("Selected engine version %s", selection.c_str());
 
        SlPaths::SetUsedSpringIndex(selection);
diff --git a/src/gui/singleplayertab.h b/src/gui/singleplayertab.h
index cd4d545..df4aa0e 100644
--- a/src/gui/singleplayertab.h
+++ b/src/gui/singleplayertab.h
@@ -66,8 +66,8 @@ private:
        MapCtrl* m_minimap;
        wxWindow* m_nominimap;
        wxChoice* m_map_pick;
-       wxChoice* m_mod_pick;
-       wxChoice* m_engine_pick;
+       wxChoice* m_engine_choice;
+       wxChoice* m_game_choice;
        wxStaticText* m_map_lbl;
        wxStaticText* m_mod_lbl;
        wxButton* m_select_btn;
diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp
index 76232ea..7d580c8 100644
--- a/src/gui/statusbar.cpp
+++ b/src/gui/statusbar.cpp
@@ -15,7 +15,7 @@ Statusbar::Statusbar(wxWindow* parent)
 {
        int w[3] = {460, -1, 120};
        SetFieldsCount(3, w);
-       PushStatusText(TowxString(getSpringlobbyVersion()), 1);
+       PushStatusText(TowxString(GetSpringlobbyAgent()), 1);
        taskBar = new TaskBar(this);
 }
 
diff --git a/src/gui/ui.cpp b/src/gui/ui.cpp
index d54d202..ac400d1 100644
--- a/src/gui/ui.cpp
+++ b/src/gui/ui.cpp
@@ -48,7 +48,6 @@
 #include "gui/agreementdialog.h"
 #include "updatehelper.h"
 #include "gui/customdialogs.h"
-#include "httpfile.h"
 #include "gui/textentrydialog.h"
 #include "log.h"
 #include "settings.h"
@@ -62,7 +61,6 @@
 
 
 SLCONFIG("/General/AutoUpdate", true, "Determines if springlobby should check 
for updates on startup");
-SLCONFIG("/General/LastUpdateCheck", 0L, "Last time springlobby checked for an 
update");
 SLCONFIG("/GUI/StartTab", (long)MainWindow::PAGE_BATTLELIST, "which tab to 
show on startup");
 SLCONFIG("/Chat/BroadcastEverywhere", true, "setting to spam the server 
messages in all channels");
 SLCONFIG("/Server/Autoconnect", false, "Connect to server on startup");
@@ -238,7 +236,7 @@ void Ui::ConsoleHelp()
                wxLogError(_T("GetActiveChatPanel() failed: couldn't find 
current active panel."));
                return;
        }
-       panel->ClientMessage(_("SpringLobby commands help."));
+       panel->ClientMessage(wxString::Format(_("%s commands help:"), 
GetSpringlobbyName()));
        panel->ClientMessage(wxEmptyString);
        panel->ClientMessage(_("Global commands:"));
        panel->ClientMessage(_("  \"/away\" - Sets your status to away."));
@@ -254,9 +252,11 @@ void Ui::ConsoleHelp()
        panel->ClientMessage(_("  \"/part\" - Leaves current channel."));
        panel->ClientMessage(_("  \"/p\" - Alias to /part."));
        panel->ClientMessage(_("  \"/rename newalias\" - Changes your nickname 
to newalias."));
-       panel->ClientMessage(_("  \"/sayver\" - Says what version of 
SpringLobby you have in chat."));
+       panel->ClientMessage(wxString::Format(
+         _("  \"/sayver\" - Says what version of %s you have in chat."), 
GetSpringlobbyName()));
        panel->ClientMessage(_("  \"/testmd5 text\" - Returns md5-b64 hash of 
given text."));
-       panel->ClientMessage(_("  \"/ver\" - Displays what version of 
SpringLobby you have."));
+       panel->ClientMessage(wxString::Format(
+         _("  \"/ver\" - Displays what version of %s you have."), 
GetSpringlobbyName()));
        panel->ClientMessage(_("  \"/clear\" - Clears all text from current 
chat panel"));
        panel->ClientMessage(wxEmptyString);
        panel->ClientMessage(_("Chat commands:"));
@@ -274,11 +274,10 @@ ChatPanel* Ui::GetChannelChatPanel(const wxString& 
channel)
 
////////////////////////////////////////////////////////////////////////////////////////////
 // EVENTS
 
////////////////////////////////////////////////////////////////////////////////////////////
-
 //! @brief Called when connected to a server
 //!
 //! @todo Display in servertab
-void Ui::OnConnected(IServer& server, const wxString& server_name, const 
wxString& version, bool /*supported*/)
+void Ui::OnConnected(IServer& server, const wxString& server_name, const 
wxString& /*version*/, bool /*supported*/)
 {
        slLogDebugFunc("");
 
@@ -291,14 +290,6 @@ void Ui::OnConnected(IServer& server, const wxString& 
server_name, const wxStrin
        mw().GetBattleListTab().OnConnected();
 
        ReopenServerTab();
-
-       if (version.empty()) {
-               wxLogWarning("default version supplied from server is empty!");
-               return;
-       }
-       std::map<std::string, LSL::SpringBundle> enginebundles = 
SlPaths::GetSpringVersionList();
-       if (!SlPaths::GetCompatibleVersion(STD_STRING(version)).empty())
-               return;
 }
 
 void Ui::OnLoggedIn()
@@ -747,12 +738,7 @@ void Ui::OnInit()
                mw().ShowTab(cfg().ReadLong(_T( "/GUI/StartTab" )));
                //don't ask for updates on first run, that's a bit much for a 
newbie
                if (cfg().ReadBool(_T("/General/AutoUpdate"))) {
-                       const time_t now = time(0);
-                       const size_t lastcheck = 
cfg().ReadLong(_T("/General/LastUpdateCheck"));
-                       if (now - lastcheck > 3600) {
-                               CheckForUpdates(false);
-                               cfg().Write(_T("/General/LastUpdateCheck"), 
(long)now);
-                       }
+                       CheckForUpdates(false);
                }
        }
 }
@@ -794,32 +780,37 @@ void Ui::OnLobbyDownloaded(wxCommandEvent& data)
        mw().Close();
 }
 
-void Ui::CheckForUpdates(bool show)
+void Ui::CheckForUpdates(bool is_interactive)
 {
-       std::string latestversion = GetHttpFile(GetLatestVersionUrl());
-       latestversion = 
STD_STRING(TowxString(latestversion).Trim().Trim(false));
+       std::string latestversion = GetLatestVersion(is_interactive);
 
        if (latestversion.empty()) {
-               if (show) {
-                       customMessageBoxModal(SL_MAIN_ICON, _("There was an 
error checking for the latest version.\nPlease try again later.\nIf the problem 
persists, please use Help->Report Bug to report this bug."), _("Error"));
+               if (is_interactive) {
+                       customMessageBoxModal(SL_MAIN_ICON, _(
+                         "There was an error checking for the latest 
version.\n"
+                         "Please try again later.\n"
+                         "If the problem persists, please use Help->Report Bug 
to report this bug."),
+                         _("Error"));
                }
                return;
        }
        //get current rev w/o AUX_VERSION added
-       const std::string myVersion = getSpringlobbyVersion();
+       const std::string myVersion = GetSpringlobbyVersion();
 
        const wxString msg = _("Your Version: ") + myVersion + _T("\n") + 
_("Latest Version: ") + latestversion;
        if (latestversion == myVersion) {
-               if (show) {
-                       customMessageBoxModal(SL_MAIN_ICON, _("Your SpringLobby 
version is up to date.\n\n") + msg, _("Up to Date"));
+               if (is_interactive) {
+                       customMessageBoxModal(SL_MAIN_ICON, wxString::Format(
+                         _("Your %s version is up to date."), 
GetSpringlobbyName())
+                         + _T("\n\n") + msg, _("Up to Date"));
                }
                return;
        }
 #ifdef __WXMSW__
        const wxString message = wxString::Format(_("Your %s version is not up 
to date.") + _T("\n\n%s\n\n") + _("Would you like to update to the new 
version?"),
-                                                 
TowxString(getSpringlobbyName()).c_str(),
+                                                 
TowxString(GetSpringlobbyName()).c_str(),
                                                  msg.c_str());
-       const wxString heading = _("Update Springlobby?");
+       const wxString heading = wxString::Format(_("Update %s?"), 
GetSpringlobbyName());
        if (!Ask(heading, message))
                return;
        try {
@@ -839,7 +830,9 @@ void Ui::CheckForUpdates(bool show)
 #else
        const wxString motivation = _("Please update to the latest version 
before reporting bugs.");
        const wxString doublenl = _T("\n\n");
-       customMessageBoxModal(SL_MAIN_ICON, _("Your SpringLobby version is not 
up to date.") + doublenl + msg + doublenl + motivation, _("Not up to Date"));
+       customMessageBoxModal(SL_MAIN_ICON,
+         wxString::Format(_("Your %s version is not up to date."), 
GetSpringlobbyName())
+         + doublenl + msg + doublenl + motivation, _("Not up to Date"));
 #endif
 }
 
diff --git a/src/gui/ui.h b/src/gui/ui.h
index a1d2e0a..1e625fb 100644
--- a/src/gui/ui.h
+++ b/src/gui/ui.h
@@ -116,7 +116,7 @@ public:
 
        //! the welcome box, should be called in all code paths directly after 
MainWindow might be shown for the first time
        void FirstRunWelcome();
-       void CheckForUpdates(bool show);
+       void CheckForUpdates(bool is_interactive);
        void EnableDebug(bool enable);
        void OnInvalidFingerprintReceived(const std::string& fingerprint, const 
std::string& expected_fingerprint);
 
diff --git a/src/ibattle.cpp b/src/ibattle.cpp
index 93f9eef..e3e4b00 100644
--- a/src/ibattle.cpp
+++ b/src/ibattle.cpp
@@ -105,16 +105,6 @@ LSL::lslColor IBattle::GetFixColour(int i) const
        return palette[i];
 }
 
-int IBattle::GetPlayerNum(const User& user) const
-{
-       for (user_map_t::size_type i = 0; i < GetNumUsers(); i++) {
-               if (&GetUser(i) == &user)
-                       return i;
-       }
-       ASSERT_EXCEPTION(false, _T("The player is not in this game."));
-       return -1;
-}
-
 class DismissColor
 {
 private:
@@ -306,16 +296,16 @@ void IBattle::OnUserBattleStatusUpdated(User& user, 
UserBattleStatus status)
                UserBattleStatus& loopstatus = loopuser.BattleStatus();
                if (loopstatus.spectator)
                        m_opts.spectators++;
-               if (!loopstatus.IsBot()) {
-                       if (!loopstatus.spectator) {
+               else  {
+                       PlayerJoinedTeam(loopstatus.team);
+                       PlayerJoinedAlly(loopstatus.ally);
+                       if (!loopstatus.IsBot()) {
                                if (loopstatus.ready && loopstatus.spectator)
                                        m_players_ready++;
                                if (loopstatus.sync)
                                        m_players_sync++;
                                if (loopstatus.ready && loopstatus.sync)
                                        m_players_ok++;
-                               PlayerJoinedTeam(loopstatus.team);
-                               PlayerJoinedAlly(loopstatus.ally);
                        }
                }
        }
@@ -404,6 +394,12 @@ bool IBattle::IsEveryoneReady() const
 }
 
 
+bool IBattle::DoesOpponentExist() const
+{
+       return (2 <= m_ally_sizes.size());
+}
+
+
 void IBattle::AddStartRect(unsigned int allyno, unsigned int left, unsigned 
int top, unsigned int right, unsigned int bottom)
 {
        assert(allyno < MAX_TEAMS);
@@ -704,18 +700,22 @@ UserPosition IBattle::GetFreePosition()
 void IBattle::SetHostMap(const std::string& mapname, const std::string& hash)
 {
        assert(hash.empty() || LSL::Util::MakeHashUnsigned(hash) == hash);
-       ASSERT_LOGIC(!mapname.empty(), "Battle with empty map name!");
-       if (mapname != m_host_map.name || hash != m_host_map.hash) {
-               m_map_loaded = false;
-               m_host_map.name = mapname;
-               m_host_map.hash = hash;
+       if (mapname == m_host_map.name || hash == m_host_map.hash) {
+               return;
        }
+       m_map_loaded = mapname.empty();
+       m_host_map.name = mapname;
+       m_host_map.hash = hash;
 }
 
 
 void IBattle::SetLocalMap(const std::string& mapname)
 {
-       ASSERT_LOGIC(!mapname.empty(), "Battle with empty map name!");
+       if (mapname.empty()) {
+               wxLogWarning("Battle with empty map name!");
+               return;
+       }
+
        LSL::UnitsyncMap map = LSL::usync().GetMap(mapname);
        if (map.name != m_local_map.name || map.hash != m_local_map.hash) {
                m_local_map = map;
@@ -729,19 +729,16 @@ void IBattle::SetLocalMap(const std::string& mapname)
 
 const LSL::UnitsyncMap& IBattle::LoadMap()
 {
-       if ((!m_map_loaded) && (!m_host_map.name.empty())) {
-               if (MapExists(true)) { //Check if selected map available for 
engine?
-                       try {
-                               m_local_map = 
LSL::usync().GetMap(m_host_map.name);
-                               
assert(LSL::Util::MakeHashUnsigned(m_local_map.hash) == m_local_map.hash);
-                               bool options_loaded = 
CustomBattleOptions().loadOptions(LSL::Enum::MapOption, m_host_map.name);
-                               //TODO: maybe replace this with "silent" IF 
operator?
-                               ASSERT_EXCEPTION(options_loaded, _T("couldn't 
load the map options"));
-                               m_map_loaded = true;
-                       } catch (...) {
-                       }
-               }
+       if ((m_map_loaded) || (m_host_map.name.empty()) || !MapExists(true))
+               return m_local_map;
+
+       m_local_map = LSL::usync().GetMap(m_host_map.name);
+       assert(LSL::Util::MakeHashUnsigned(m_local_map.hash) == 
m_local_map.hash);
+       const bool options_loaded = 
CustomBattleOptions().loadOptions(LSL::Enum::MapOption, m_host_map.name);
+       if (!options_loaded) {
+               wxLogWarning( _T("couldn't load the map options"));
        }
+       m_map_loaded = true;
        return m_local_map;
 }
 
@@ -764,7 +761,7 @@ void IBattle::SetHostGame(const std::string& gamename, 
const std::string& hash)
        if ((m_host_game.name == gamename) && (m_host_game.hash == hash)) {
                return;
        }
-       m_game_loaded = false;
+       m_game_loaded = gamename.empty();
        m_host_game.name = gamename;
        m_host_game.hash = hash;
 }
@@ -787,20 +784,21 @@ void IBattle::SetLocalGame(const LSL::UnitsyncGame& mod)
 
 const LSL::UnitsyncGame& IBattle::LoadGame()
 {
-       ASSERT_LOGIC(!m_host_game.name.empty(), "m_host_game.name.empty() is 
FALSE");
-       if (m_game_loaded) {
+       if (m_game_loaded || m_host_game.name.empty()) {
                return m_local_game;
        }
        if (!GameExists(true)) {
                wxLogWarning("Game doesn't exist");
                return m_local_game;
        }
-       try {
-               SetLocalGame(LSL::usync().GetGame(m_host_game.name));
-               bool options_loaded = 
CustomBattleOptions().loadOptions(LSL::Enum::ModOption, m_host_game.name);
-               ASSERT_EXCEPTION(options_loaded, _T("couldn't load the game 
options"));
-               m_game_loaded = true;
-       } catch (...) { }
+       SetLocalGame(LSL::usync().GetGame(m_host_game.name));
+       const bool options_loaded = 
CustomBattleOptions().loadOptions(LSL::Enum::ModOption, m_host_game.name);
+
+       if (!options_loaded) {
+               wxLogWarning("couldn't load the game options");
+       }
+
+       m_game_loaded = true;
        return m_local_game;
 }
 
@@ -1061,12 +1059,6 @@ bool IBattle::IsFounder(const User& user) const
                return false;
 }
 
-int IBattle::GetMyPlayerNum() const
-{
-       return GetPlayerNum(GetMe());
-}
-
-
 void IBattle::LoadScriptMMOpts(const std::string& sectionname, const 
LSL::TDF::PDataList& node)
 {
        if (!node.ok())
diff --git a/src/ibattle.h b/src/ibattle.h
index 58e75c5..fd5b019 100644
--- a/src/ibattle.h
+++ b/src/ibattle.h
@@ -226,10 +226,6 @@ public:
        virtual bool IsFounderMe() const;
        virtual bool IsFounder(const User& user) const;
 
-       virtual int GetMyPlayerNum() const;
-
-       virtual int GetPlayerNum(const User& user) const;
-
        virtual void SetHostGame(const std::string& gamename, const 
std::string& hash);
        virtual void SetLocalGame(const LSL::UnitsyncGame& game);
        virtual const LSL::UnitsyncGame& LoadGame();
@@ -245,6 +241,7 @@ public:
        virtual void OnUserRemoved(User& user);
 
        virtual bool IsEveryoneReady() const;
+       virtual bool DoesOpponentExist() const;
 
        virtual void ForceSide(User& user, int side);
        virtual void ForceAlly(User& user, int ally);
diff --git a/src/log.cpp b/src/log.cpp
index 7f35aeb..848851c 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -1,38 +1,62 @@
 /* This file is part of the Springlobby (GPL v2 or later), see COPYING */
 
+#include <cstdio>
+#include <algorithm>
+#include <cstring>
+#include <mutex>
+#include <sys/time.h>
+#include <vector>
+#include <time.h>
+
 #include <wx/log.h>
-#include <boost/thread/mutex.hpp>
 
 #include "log.h"
-#include "utils/conversion.h"
 #include "gui/ui.h"
 #include "gui/mainwindow.h"
-#include "time.h"
-
-#if wxUSE_STD_IOSTREAM
-#include <iostream>
-#endif
+#include "utils/conversion.h"
+#include "downloader/lib/src/Logger.h"
 
 static bool gui = false;
 
+const char* wxLogLevelToString(wxLogLevel level)
+{
+       assert(level < 8); // just in case
+
+       static const char* levelNames[] = {
+         "Fatal",
+         "Error",
+         "Warning",
+         "Message",
+         "Status",
+         "Info",
+         "Debug",
+         "Trace"};
+
+       return levelNames[static_cast<int>(level)];
+}
+
 class myLogger : public wxLog
 {
 public:
        ~myLogger()
        {
-               if (m_logfile != NULL) {
-                       fclose(m_logfile);
-               }
+               for (FILE* lf : m_log_files)
+                       fclose(lf);
        }
        myLogger(bool console, const wxString& logfilepath, bool /*showgui*/)
            : wxLog()
-           , m_console(console)
-           ,
            //          m_gui(showgui),
-           m_logfile(NULL)
        {
+               if (console)
+                       m_log_files.push_back (stdout);
                if (!logfilepath.empty()) {
-                       m_logfile = fopen(C_STRING(logfilepath), "wb+"); // 
even if it returns null, wxLogStderr will switch to stderr logging, so it's fine
+                       // even if it returns null, wxLogStderr will switch to 
stderr logging, so it's fine
+                       // TODO: it will?
+                       FILE* log = fopen(C_STRING(logfilepath), "wb+");
+                       if (nullptr == log)
+                               wxLogError ("Unable to open log file %s for 
writing!", logfilepath);
+                       else
+                               m_log_files.push_back (log);
                }
        }
 
@@ -57,7 +81,7 @@ public:
        // catch and process all log messages
        void DoLogRecord(wxLogLevel loglevel, const wxString& msg, const 
wxLogRecordInfo& info) override
        {
-               boost::mutex::scoped_lock lock(m_mutex);
+               std::lock_guard<std::mutex> lock(m_mutex);
 
                if (gui && (loglevel == wxLOG_Error || loglevel == 
wxLOG_FatalError)) // show user only errors
                {
@@ -66,15 +90,37 @@ public:
                        ui().mw().GetEventHandler()->QueueEvent(event);
                }
 
-
-               const std::string std_msg = stdprintf("%s %s %s:%d %s\n", 
GetTimeString().c_str(), LogLevelToString(loglevel).c_str(), info.filename, 
info.line, (STD_STRING(wxString(msg))).c_str());
-               if (m_console) {
-                       std::cout << std_msg;
-               }
-               if (m_logfile != NULL) {
-                       fwrite(std_msg.c_str(), std_msg.length(), 1, m_logfile);
-                       fflush(m_logfile);
+               // only print the last src_fn_size chars of file name
+               const int src_fn_size = 20;
+               const int src_fn_offset = std::max(0, 
static_cast<int>(std::strlen(info.filename)) - src_fn_size);
+               const char* src_fn = info.filename + src_fn_offset;
+
+               const std::string log_prefix = stdprintf("%s %-7s %20.20s:%-4d",
+                 GetTimeString().c_str(), wxLogLevelToString(loglevel),
+                 src_fn, info.line);
+
+               char delim = ' '; // indicates that this is a new message, 
continuations use '+'
+               // sol=Start-Of-Line, eol=End-Of-Line. We have at least one 
execution of the below loop.
+               // eol should be one past the end character for substring 
length = eol - sol to work
+               for (size_t sol = 0, eol = 0; eol < msg.Len(); sol = ++eol) {
+                       eol = msg.find("\n", sol);
+                       if (wxString::npos == eol) {
+                               eol = msg.Len();
+                               if (sol >= eol) // real end condition
+                                       break;
+                       }
+                       wxString line_msg = msg.Mid(sol, eol-sol);
+
+                       for (FILE* lf : m_log_files) {
+                               fwrite(log_prefix.c_str(), log_prefix.length(), 
1, lf);
+                               fwrite(&delim, 1, 1, lf);
+                               fwrite(line_msg.c_str(), line_msg.length(), 1, 
lf);
+                               fwrite("\n", 1, 1, lf);
+                       }
+                       delim = '+'; // not first line any more
                }
+
+               Flush();
                /*
          if (m_gui) {
                  ChatPanel* p = ui().mw().GetChatTab().AddChatPanel();
@@ -84,35 +130,16 @@ public:
          }*/
        }
 
-       std::string LogLevelToString(wxLogLevel level)
-       {
-               assert(level < 8); // just in case
-
-               const char* levelName[] = {
-                   "Fatal",
-                   "Error",
-                   "Warning",
-                   "Message",
-                   "Status",
-                   "Info",
-                   "Debug",
-                   "Trace"};
-
-               return std::string(levelName[(int)level]);
-       }
-
        void Flush() override
        {
-               if (m_logfile != NULL) {
-                       fflush(m_logfile);
-               }
+               for (FILE* lf : m_log_files)
+                       fflush(lf);
        }
 
 private:
-       bool m_console;
        //      bool m_gui;
-       FILE* m_logfile;
-       boost::mutex m_mutex;
+       std::vector<FILE*> m_log_files;
+       std::mutex m_mutex;
 };
 
 
@@ -177,54 +204,45 @@ void Logger::ShowDebugWindow(bool show)
 */
 }
 
-extern void lsllogerror(const char* format, ...)
+extern void LOG_PROGRESS(long /*done*/, long /*total*/, bool /*forceOutput*/)
 {
-       char buf[1024];
-       va_list args;
-       va_start(args, format);
-       const int len = vsnprintf(buf, 1024, format, args);
-       va_end(args);
-       if (len > 0) {
-               const std::string msg(buf, len);
-               wxLogWarning("Error: FIXME: %s", msg.c_str()); //FIXME: lsl 
throws a lot of errors
-       }
 }
 
-extern void lsllogdebug(const char* format, ...)
+void LOG_DISABLE(bool /*disableLogging*/)
 {
-       char buf[1024];
-       va_list args;
-       va_start(args, format);
-       const int len = vsnprintf(buf, 1024, format, args);
-       va_end(args);
-       if (len > 0) {
-               const std::string msg(buf, len);
-               wxLogDebug("%s", msg.c_str());
-       }
 }
 
-extern void lsllogwarning(const char* format, ...)
+extern void L_LOG(const char* fileName, int line, const char* funcName,
+           L_LEVEL level, const char* format...)
 {
-       char buf[1024];
        va_list args;
        va_start(args, format);
-       const int len = vsnprintf(buf, 1024, format, args);
-       va_end(args);
-       if (len > 0) {
-               const std::string msg(buf, len);
-               wxLogWarning("%s", msg.c_str());
-       }
-}
-
-extern void lslloginfo(const char* format, ...)
-{
        char buf[1024];
-       va_list args;
-       va_start(args, format);
-       const int len = vsnprintf(buf, 1024, format, args);
+       // for some reason wxLogger().LogV() fails on windows, see #826
+       const int res = vsnprintf(buf, sizeof(buf), format, args);
        va_end(args);
-       if (len > 0) {
-               const std::string msg(buf, len);
-               wxLogInfo("%s", msg.c_str());
+
+       wxLogLevel lvl;
+       switch (level) {
+               case L_RAW:
+                       lvl = wxLOG_Debug;
+                       break;
+               default:
+               case L_ERROR:
+                       lvl = wxLOG_Error;
+                       break;
+               case L_WARN:
+                       lvl = wxLOG_Warning;
+                       break;
+               case L_INFO:
+                       lvl = wxLOG_Info;
+                       break;
+               case L_DEBUG:
+                       lvl = wxLOG_Debug;
+                       break;
        }
+
+       assert(res >= 0);
+       const wxLogRecordInfo info(fileName, line, funcName, PRD_LOG_COMPONENT);
+       wxLog::OnLog(lvl, buf, info);
 }
diff --git a/src/log.h b/src/log.h
index 89a8027..a2bc991 100644
--- a/src/log.h
+++ b/src/log.h
@@ -6,6 +6,10 @@
 #include <string>
 #include <wx/log.h>
 
+#define PRD_LOG_COMPONENT "prd"
+
+const char* wxLogLevelToString(wxLogLevel level);
+
 class wxString;
 class wxLogWindow;
 class wxWindow;
diff --git a/src/socket.cpp b/src/socket.cpp
index dfbb281..5a2715d 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -28,15 +28,9 @@ lsl/networking/socket.cpp
 
 #include "socket.h"
 #include "inetclass.h"
+#include "address.h"
 #include "utils/conversion.h"
 
-#ifdef __WXMSW__
-#include <iphlpapi.h>
-#elif defined(linux)
-#include <sys/ioctl.h>
-#include <net/if.h>
-#endif
-
 #ifdef SSL_SUPPORT
 #include <openssl/bio.h>
 #include <openssl/ssl.h>
@@ -44,106 +38,6 @@ lsl/networking/socket.cpp
 #include <openssl/x509.h>
 #endif
 
-#ifdef __WXMSW__
-
-bool GetMacType(std::vector<unsigned char>& mac, const unsigned int mactype)
-{
-       IP_ADAPTER_INFO AdapterInfo[16];      // Allocate information for 16 
cards
-       DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
-
-       DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen); // Get info
-       if (dwStatus == ERROR_BUFFER_OVERFLOW) {
-               wxLogError(wxString::Format("To small buffer size: %d", 
dwStatus));
-               return false;
-       }
-       if (dwStatus != NO_ERROR)
-               return false; // Check status
-
-       for (size_t i = 0; i < dwBufLen / sizeof(AdapterInfo); i++) {
-               if ((mactype != 0) && (AdapterInfo[i].Type != mactype)) //skip 
not wanted type
-                       continue;
-               if (AdapterInfo[i].AddressLength == 0) {
-                       wxLogWarning("Zero Address length for adapter");
-                       continue;
-               }
-               mac.resize(AdapterInfo[i].AddressLength);
-               mac.assign(AdapterInfo[i].Address, AdapterInfo[i].Address + 
AdapterInfo[i].AddressLength);
-               for (size_t j = 0; j < mac.size(); j++) {
-                       if (mac[j] != 0) {
-                               return true;
-                       }
-               }
-       }
-       return false;
-}
-
-
-bool GetMac(std::vector<unsigned char>& mac)
-{
-       if (GetMacType(mac, MIB_IF_TYPE_ETHERNET))
-               return true;
-       if (GetMacType(mac, IF_TYPE_IEEE80211))
-               return true;
-       return (GetMacType(mac, 0));
-}
-
-#elif defined(__APPLE__)
-
-bool GetMac(std::vector<unsigned char>& mac)
-{
-       //FIXME: implement this, 
http://lists.freebsd.org/pipermail/freebsd-hackers/2004-June/007415.html
-       return false;
-}
-
-#else
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <netpacket/packet.h>
-#include <ifaddrs.h>
-
-bool GetMac(std::vector<unsigned char>& mac)
-{
-       ifaddrs* ifap = 0;
-       if (getifaddrs(&ifap) == 0) {
-               ifaddrs* iter = ifap;
-               while (iter) {
-                       sockaddr_ll* sal = 
reinterpret_cast<sockaddr_ll*>(iter->ifa_addr);
-                       if (sal->sll_family == AF_PACKET) {
-                               mac.resize(sal->sll_halen);
-                               mac.assign(sal->sll_addr, sal->sll_addr + 
sal->sll_halen);
-                               for (size_t i = 0; i < mac.size(); i++) {
-                                       if (mac[i] != 0) {
-                                               freeifaddrs(ifap);
-                                               return true;
-                                       }
-                               }
-                       }
-                       iter = iter->ifa_next;
-               }
-               freeifaddrs(ifap);
-       }
-       return false;
-}
-
-#endif
-
-std::string MacToString(std::vector<unsigned char>& mac)
-{
-       std::string res;
-       for (size_t i = 0; i < mac.size(); i++) {
-               char buf[3];
-               snprintf(buf, sizeof(buf), "%02X", mac[i]);
-               if (!res.empty())
-                       res += ":";
-               res.append(buf, 2);
-       }
-       return res;
-}
-
 std::string _GetHandle()
 {
        std::vector<unsigned char> mac;
@@ -252,7 +146,7 @@ void Socket::DoSSLHandshake()
 
 void Socket::StartTLS(const std::string& fingerprint)
 {
-       wxLogMessage("Starting TLS...");
+       wxLogMessage("Starting TLS... %s", fingerprint.c_str());
        m_excepted_fingerprint = fingerprint;
        assert(!m_starttls);
        m_starttls = true;
diff --git a/src/springlobbyapp.cpp b/src/springlobbyapp.cpp
index 4d1a3cc..b892ce6 100644
--- a/src/springlobbyapp.cpp
+++ b/src/springlobbyapp.cpp
@@ -79,7 +79,7 @@ SpringLobbyApp::SpringLobbyApp()
     , m_log_console(true)
     , m_log_window_show(false)
     , m_crash_handle_disable(false)
-    , m_appname(_T("SpringLobby"))
+    , m_appname(GetSpringlobbyName())
 {
 #if wxUSE_UNIX
        /*
@@ -143,7 +143,7 @@ bool SpringLobbyApp::OnInit()
        //initialize all loggers, we'll use the returned pointer to set correct 
parent window later
        wxLogWindow* loggerwin = Logger::InitializeLoggingTargets(0, 
m_log_console, m_log_file_path, m_log_window_show, m_log_verbosity);
 
-       wxLogMessage(_T("SpringLobby %s started"), 
TowxString(getSpringlobbyVersion()).c_str());
+       wxLogMessage(_T("%s started"), 
TowxString(GetSpringlobbyAgent()).c_str());
 
        //this needs to called _before_ mainwindow instance is created
        wxInitAllImageHandlers();
@@ -301,7 +301,7 @@ bool SpringLobbyApp::OnCmdLineParsed(wxCmdLineParser& 
parser)
                        return false; // not a syntax error, but program should 
stop if user asked for command line usage
 
                if (parser.Found(_T("version"))) {
-                       
wxLogMessage(TowxString(getSpringlobbyVersion()).c_str());
+                       
wxLogMessage(TowxString(GetSpringlobbyVersion()).c_str());
                        return false;
                }
                return true;
diff --git a/src/springlobbyapp.h b/src/springlobbyapp.h
index b7ebe9d..3ec5852 100644
--- a/src/springlobbyapp.h
+++ b/src/springlobbyapp.h
@@ -15,20 +15,21 @@ class SpringLobbyApp : public wxApp
 public:
        SpringLobbyApp();
 
-       virtual bool OnInit();
-       virtual int OnExit();
+       bool OnInit() override;
+       int OnExit() override;
 
-       virtual void OnFatalException();
+       void OnFatalException() override;
 
        // System Events
        bool SelectLanguage();
 
-       virtual void OnInitCmdLine(wxCmdLineParser& parser);
-       virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
+       void OnInitCmdLine(wxCmdLineParser& parser) override;
+       bool OnCmdLineParsed(wxCmdLineParser& parser) override;
 
-       void OnQuit(wxCommandEvent& data);
 
 private:
+       void OnQuit(wxCommandEvent& data);
+
        bool quit_called;
 
        wxTranslationHelper* m_translationhelper;
diff --git a/src/springsettings/frame.cpp b/src/springsettings/frame.cpp
index 47da556..d87d6f8 100644
--- a/src/springsettings/frame.cpp
+++ b/src/springsettings/frame.cpp
@@ -276,7 +276,7 @@ void settings_frame::OnMenuChoice(wxCommandEvent& event)
                                detailTab = 0;
                                audioTab = 0;
                                //                              hotkeyTab = 0;
-                               SetTitle(TowxString(getSpringlobbyName()) + 
_("(simple mode)"));
+                               SetTitle(TowxString(GetSpringlobbyName()) + 
_("(simple mode)"));
                                if (!sett().getDisableWarning()) {
                                        customMessageBox(SS_MAIN_ICON, 
expertModeWarning, _("Hint"), wxOK);
                                }
@@ -325,7 +325,7 @@ void settings_frame::switchToExpertMode()
 
        notebook->DeletePage(0);
        simpleTab = 0;
-       SetTitle(TowxString(getSpringlobbyName()) + _("(expert mode)"));
+       SetTitle(TowxString(GetSpringlobbyName()) + _("(expert mode)"));
        /*uiTab->updateControls(UPDATE_ALL);
        detailTab->updateControls(UPDATE_ALL);
        qualityTab->updateControls(UPDATE_ALL);
diff --git a/src/sysinfo.cpp b/src/sysinfo.cpp
index 0e85a12..ab0b1e7 100644
--- a/src/sysinfo.cpp
+++ b/src/sysinfo.cpp
@@ -7,6 +7,7 @@
 #include <wx/log.h>
 #include <wx/filename.h>
 #include <wx/string.h>
+#include "log.h"
 #include "utils/conversion.h"
 #include "utils/slpaths.h"
 #include "utils/version.h"
@@ -58,9 +59,9 @@ std::string GetSpringlobbyInfo()
 {
        static const std::string nl = std::string("\n");
        std::string res;
-       res = getSpringlobbyAgent() + nl;
+       res = GetSpringlobbyAgent() + nl;
        const bool configwriteable = 
wxFileName::IsFileWritable(TowxString(SlPaths::GetConfigPath()));
-       res += stdprintf("SpringLobby config file: %s (%swritable)\n",
+       res += stdprintf("Configuration file: %s (%swritable)\n",
                         SlPaths::GetConfigPath().c_str(),
                         BtS(configwriteable, "", "not ").c_str());
        Paths paths;
@@ -71,7 +72,7 @@ std::string GetSpringlobbyInfo()
                if (path.empty()) {
                        continue;
                }
-               
+
 #if defined(__WIN32__) || defined(_MSC_VER)
                path = Utf8ToLocalEncoding(path.c_str());
 #endif
@@ -112,6 +113,11 @@ std::string GetSpringlobbyInfo()
        res += stdprintf("Portable mode: %s\n", 
BtS(SlPaths::IsPortableMode()).c_str());
 
        res += stdprintf(("Compiled with wxWidgets %d.%d.%d.%d"), 
wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER, wxSUBRELEASE_NUMBER) + nl;
+       res += stdprintf("Global log level: %lu (up to and including %s)\n",
+         wxLog::GetLogLevel(), wxLogLevelToString (wxLog::GetLogLevel()));
+       res += stdprintf("PR-Downloader log level: %lu (up to and including 
%s)\n",
+         wxLog::GetComponentLevel(PRD_LOG_COMPONENT),
+         wxLogLevelToString (wxLog::GetComponentLevel(PRD_LOG_COMPONENT)));
        res += "Started with: \n";
        for (int i = 0; i < wxTheApp->argc; ++i)
                res += STD_STRING(wxTheApp->argv[i]) + std::string(" ");
diff --git a/src/tasserver.cpp b/src/tasserver.cpp
index c57e7aa..7844287 100644
--- a/src/tasserver.cpp
+++ b/src/tasserver.cpp
@@ -381,7 +381,8 @@ void TASServer::Login()
                localaddr = "*";
        m_id_transmission = false;
        SendCmd("LOGIN", stdprintf("%s %s 0 %s %s\t%u\ta m sp cl p",
-                                  GetUserName().c_str(), pass.c_str(), 
localaddr.c_str(), getSpringlobbyAgent().c_str(), m_crc.GetCRC()));
+         GetUserName().c_str(), pass.c_str(), localaddr.c_str(),
+         GetSpringlobbyAgent().c_str(), m_crc.GetCRC()));
        m_id_transmission = true;
 }
 
@@ -431,7 +432,8 @@ void TASServer::Notify()
        if (m_last_ping > PING_TIME) { //Send a PING every 30 seconds
                if (interval > PING_TIME) {
                        m_last_net_packet = 0; //assume local clock is broken 
and we received a packed within time
-                       m_se->OnServerMessage(stdprintf("Springlobby hung or 
stale clock. Got no timer for %d msec", interval));
+                       m_se->OnServerMessage(stdprintf("%s hung or stale 
clock. Got no timer for %d msec",
+                         GetSpringlobbyName().c_str(), interval));
                }
                m_last_ping = 0;
                Ping();
@@ -976,22 +978,25 @@ void TASServer::ParseJson(const std::string& jsonstr)
        }
 
        if (!js.isObject()) {
-               wxLogWarning("Invalid json, object excepted: %s", 
jsonstr.c_str());
+               m_se->OnServerMessage(stdprintf("Invalid json, object excepted: 
%s", jsonstr.c_str()));
                return;
        }
-
-       if (!js["SAID"].isObject()) {
-               wxLogWarning("Invalid json, object excepted: %s", 
jsonstr.c_str());
+       if (js["FAILED"].isObject()) {
+               m_se->OnServerMessage(js["FAILED"]["msg"].asString());
                return;
        }
 
-       Json::Value said = js["SAID"];
-       cfg().Write(wxString::Format("/Channels/%s/lastid", 
said["chanName"].asString()), said["id"].asInt());
-       m_se->OnChannelSaid(said["chanName"].asString(), 
said["userName"].asString(), said["msg"].asString());
+       if (js["SAID"].isObject()) {
+               Json::Value said = js["SAID"];
+               cfg().Write(wxString::Format("/Channels/%s/lastid", 
said["chanName"].asString()), said["id"].asInt());
+               m_se->OnChannelSaid(said["chanName"].asString(), 
said["userName"].asString(), said["msg"].asString());
+               //TODO: store last id for channel
+               //said["time"].asInt64();
+               //said["id"].asUInt64();
+               return;
+       }
 
-       //TODO: store last id for channel
-       //said["time"].asInt64();
-       //said["id"].asUInt64();
+       wxLogWarning("Unknown command received: %s", jsonstr.c_str());
 }
 
 
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 201edce..e9a5031 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -52,6 +52,7 @@ Set(test_src
        "${springlobby_SOURCE_DIR}/src/utils/slconfig.cpp"
        "${springlobby_SOURCE_DIR}/src/utils/slpaths.cpp"
        "${springlobby_SOURCE_DIR}/src/utils/conversion.cpp"
+       "${springlobby_SOURCE_DIR}/src/downloader/lib/src/Logger.cpp"
 )
 
 set(test_libs
@@ -80,12 +81,16 @@ set(test_name lobbyid)
 Set(test_src
        "${CMAKE_CURRENT_SOURCE_DIR}/lobbyid.cpp"
        "${springlobby_SOURCE_DIR}/src/utils/crc.cpp"
+       "${springlobby_SOURCE_DIR}/src/address.cpp"
 )
 
 set(test_libs
        ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
        ${Boost_SYSTEM_LIBRARY}
 )
+if(WIN32)
+       set(test_libs ${test_libs} iphlpapi)
+endif()
 add_springlobby_test(${test_name} "${test_src}" "${test_libs}" "-DTEST")
 
################################################################################
 set(test_name lslconversion)
@@ -113,6 +118,7 @@ Set(test_src
        "${springlobby_SOURCE_DIR}/src/utils/conversion.cpp"
        "${springlobby_SOURCE_DIR}/src/downloader/lib/src/lsl/lslutils/misc.cpp"
        
"${springlobby_SOURCE_DIR}/src/downloader/lib/src/lsl/lslutils/conversion.cpp"
+       "${springlobby_SOURCE_DIR}/src/downloader/lib/src/Logger.cpp"
 )
 
 set(test_libs
diff --git a/src/tests/lobbyid.cpp b/src/tests/lobbyid.cpp
index ee3f74a..055c0bf 100644
--- a/src/tests/lobbyid.cpp
+++ b/src/tests/lobbyid.cpp
@@ -5,6 +5,7 @@
 
 #include <stdio.h>
 #include "utils/crc.h"
+#include "address.h"
 
 BOOST_AUTO_TEST_CASE(lobbyid)
 {
@@ -39,3 +40,11 @@ BOOST_AUTO_TEST_CASE(lobbyid)
        m_crc.UpdateData("The quick brown fox jumps over the lazy dog");
        BOOST_CHECK(m_crc.GetCRC() == 1095738169); // == 414fa339, 
http://rosettacode.org/wiki/CRC-32#C.2B.2B
 }
+
+BOOST_AUTO_TEST_CASE(getmac)
+{
+       std::vector<unsigned char> mac;
+       GetMac(mac);
+       const std::string smac = MacToString(mac);
+       printf("%s\n", smac.c_str());
+}
diff --git a/src/updatehelper.cpp b/src/updatehelper.cpp
index 566ed6d..d439440 100644
--- a/src/updatehelper.cpp
+++ b/src/updatehelper.cpp
@@ -2,10 +2,15 @@
 
 #include "updatehelper.h"
 
+#include "httpfile.h"
 #include "utils/conversion.h"
 #include "utils/slconfig.h"
+#include "utils/version.h"
+#include <time.h>
 
+SLCONFIG("/General/LastUpdateCheck", 0L, "Last time springlobby checked for an 
update");
 SLCONFIG("/General/UpdateChannel", "release", "update channel to use (release 
or develop)");
+#define VERSION_CHECK_INTERVAL 1*60*60
 
 static bool isReleaseChannel()
 {
@@ -28,3 +33,28 @@ std::string GetLatestVersionUrl()
        }
        return 
std::string("http://springlobby.info/temp/builds/develop/current.txt";);
 }
+
+static time_t GetTime()
+{
+       time_t now = time(nullptr);
+       if (static_cast<time_t>(-1) == now) {
+               std::string msg = "time() broke: ";
+               msg += strerror (errno);
+               throw std::runtime_error (msg.c_str());
+       }
+       return now;
+}
+
+std::string GetLatestVersion(bool use_cached)
+{
+       static std::string latest_version = GetSpringlobbyVersion();
+       const time_t now = GetTime();
+       const time_t last_check_time = 
cfg().ReadLong(_T("/General/LastUpdateCheck"));
+
+       if (latest_version.empty() || !use_cached || now > (last_check_time + 
VERSION_CHECK_INTERVAL)) {
+               latest_version = GetHttpFile(GetLatestVersionUrl());
+               latest_version = 
STD_STRING(TowxString(latest_version).Trim().Trim(false));
+               cfg().Write(_T("/General/LastUpdateCheck"), (long)now);
+       }
+       return latest_version;
+}
diff --git a/src/updatehelper.h b/src/updatehelper.h
index b0e823f..2fc838d 100644
--- a/src/updatehelper.h
+++ b/src/updatehelper.h
@@ -7,5 +7,9 @@
 
 std::string GetDownloadUrl(const std::string& version);
 std::string GetLatestVersionUrl();
+// returns current version; if use_cached and check timer has not expired
+//         empty string   ; if download failed
+//         latest version ; otherwise
+std::string GetLatestVersion(bool use_cached = true);
 
 #endif
diff --git a/src/utils/conversion.cpp b/src/utils/conversion.cpp
index fd79d9d..de3a2b5 100644
--- a/src/utils/conversion.cpp
+++ b/src/utils/conversion.cpp
@@ -25,6 +25,9 @@ std::string stdprintf(const char* format, ...)
        va_start(args, format);
        const int count = vsnprintf(buf, 1024, format, args);
        va_end(args);
+       if (count <= 0) {
+               return "";
+       }
        return std::string(buf, std::min(count, 1024));
 }
 
diff --git a/src/utils/platform.cpp b/src/utils/platform.cpp
index d47becf..a5c3191 100644
--- a/src/utils/platform.cpp
+++ b/src/utils/platform.cpp
@@ -162,7 +162,11 @@ static wxString escapeStr(const wxString& str)
        return _T("\"") + str + _T("\"");
 }
 
+#ifdef __WXMSW__
 int RunProcess(const wxString& cmd, const wxArrayString& params, const bool 
async, const bool root)
+#else
+int RunProcess(const wxString& cmd, const wxArrayString& params, const bool 
/*async*/, const bool /*root*/)
+#endif
 {
        wxString paramstring;
        for (wxString param : params) {
diff --git a/src/utils/slpaths.cpp b/src/utils/slpaths.cpp
index 422e9de..f25381b 100644
--- a/src/utils/slpaths.cpp
+++ b/src/utils/slpaths.cpp
@@ -56,12 +56,12 @@ SLCONFIG("/Spring/DownloadDir", 
TowxString(LSL::Util::EnsureDelimiter(GetMyDocum
 
 std::string SlPaths::GetLocalConfigPath()
 {
-       return GetExecutableFolder() + getSpringlobbyName(true) + ".conf";
+       return GetExecutableFolder() + GetSpringlobbyName(true) + ".conf";
 }
 
 std::string SlPaths::GetDefaultConfigPath()
 {
-       return GetConfigfileDir() + getSpringlobbyName(true) + ".conf";
+       return GetConfigfileDir() + GetSpringlobbyName(true) + ".conf";
 }
 
 bool SlPaths::IsPortableMode()
@@ -405,7 +405,7 @@ std::string SlPaths::GetConfigfileDir()
 #ifndef WIN32
        path += ".";
 #endif
-       path += getSpringlobbyName(true);
+       path += GetSpringlobbyName(true);
        return LSL::Util::EnsureDelimiter(path);
 }
 
diff --git a/src/utils/version.cpp b/src/utils/version.cpp
index 79fbf38..9918af6 100644
--- a/src/utils/version.cpp
+++ b/src/utils/version.cpp
@@ -7,25 +7,25 @@
 #include SPRINGLOBBY_CONFIGH
 #include "version.h"
 
-const std::string getSpringlobbyName(bool lowercase)
+const std::string GetSpringlobbyName(bool lowercase)
 {
        if (lowercase)
                return "springlobby";
        return "SpringLobby";
 }
 
-const std::string getSpringlobbyVersion()
+const std::string GetSpringlobbyVersion()
 {
        const static std::string version(VERSION);
        return version;
 }
 
-const std::string getSpringlobbyAgent()
+const std::string GetSpringlobbyAgent()
 {
-       std::string agent = getSpringlobbyName() + " ";
-       agent += getSpringlobbyVersion();
+       std::string agent = GetSpringlobbyName() + " ";
+       agent += GetSpringlobbyVersion();
        agent += " (";
-#if WIN32
+#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || 
defined(__MINGW32__)
        agent += "win";
 #elif __APPLE__
        agent += "osx";
diff --git a/src/utils/version.h b/src/utils/version.h
index 8da3269..ba70f5c 100644
--- a/src/utils/version.h
+++ b/src/utils/version.h
@@ -5,8 +5,8 @@
 
 #include <string>
 
-const std::string getSpringlobbyVersion();
-const std::string getSpringlobbyAgent();
-const std::string getSpringlobbyName(bool lowercase = false);
+const std::string GetSpringlobbyVersion();
+const std::string GetSpringlobbyAgent();
+const std::string GetSpringlobbyName(bool lowercase = false);
 
 #endif
diff --git a/tools/mxe_create_builddir.sh b/tools/mxe_create_builddir.sh
index adf1b6a..84faced 100755
--- a/tools/mxe_create_builddir.sh
+++ b/tools/mxe_create_builddir.sh
@@ -2,7 +2,7 @@
 
 set -e
 
-COMMIT=34451075836cdd23cb03b69ef285cf4a4ac9489f
+COMMIT=0dcf498f9563fd35eff0273e1b56929fdce60383
 
 if [ ! -d mxe ]; then
        git clone https://github.com/mxe/mxe.git
@@ -17,9 +17,9 @@ git reset --hard $COMMIT
 
 (
        echo 'JOBS := 2'
-       echo 'MXE_TARGETS := i686-w64-mingw32.static'
+       echo 'MXE_TARGETS := i686-w64-mingw32.static.posix'
        echo 'LOCAL_PKG_LIST := openssl boost curl wxwidgets'
-       echo '.DEFAULT local-pkg-list:'
+       echo '.DEFAULT_GOAL  := local-pkg-list'
        echo 'local-pkg-list: $(LOCAL_PKG_LIST)'
 ) > settings.mk
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/springlobby.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to