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