From f5df754260bf89b7d8d755b50594a4221deb52ae Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Mon, 19 Apr 2010 12:03:18 +0000 Subject: [PATCH 01/69] added ghost.qt branch --- ghost/ghost.cpp | 341 +----------------------------------------------- ghost/ghost.h | 5 +- ghost/ghost.pro | 92 +++++++++++++ ghost/main.cpp | 272 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 371 insertions(+), 339 deletions(-) create mode 100644 ghost/ghost.pro create mode 100644 ghost/main.cpp diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 95a1f80..33810e4 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -50,346 +50,13 @@ #define __STORMLIB_SELF__ #include -/* - -#include "ghost.h" -#include "util.h" -#include "crc32.h" -#include "sha1.h" -#include "csvparser.h" -#include "config.h" -#include "language.h" -#include "socket.h" -#include "commandpacket.h" -#include "ghostdb.h" -#include "ghostdbsqlite.h" -#include "ghostdbmysql.h" -#include "bncsutilinterface.h" -#include "warden.h" -#include "bnlsprotocol.h" -#include "bnlsclient.h" -#include "bnetprotocol.h" -#include "bnet.h" -#include "map.h" -#include "packed.h" -#include "savegame.h" -#include "replay.h" -#include "gameslot.h" -#include "gameplayer.h" -#include "gameprotocol.h" -#include "gpsprotocol.h" -#include "game_base.h" -#include "game.h" -#include "game_admin.h" -#include "stats.h" -#include "statsdota.h" -#include "sqlite3.h" - -*/ - -#ifdef WIN32 - #include - #include -#endif - -#include - -#ifndef WIN32 - #include -#endif - -#ifdef __APPLE__ - #include -#endif - -string gCFGFile; -string gLogFile; -uint32_t gLogMethod; -ofstream *gLog = NULL; -CGHost *gGHost = NULL; - -uint32_t GetTime( ) -{ - return GetTicks( ) / 1000; -} - -uint32_t GetTicks( ) -{ -#ifdef WIN32 - // don't use GetTickCount anymore because it's not accurate enough (~16ms resolution) - // don't use QueryPerformanceCounter anymore because it isn't guaranteed to be strictly increasing on some systems and thus requires "smoothing" code - // use timeGetTime instead, which typically has a high resolution (5ms or more) but we request a lower resolution on startup - - return timeGetTime( ); -#elif __APPLE__ - uint64_t current = mach_absolute_time( ); - static mach_timebase_info_data_t info = { 0, 0 }; - // get timebase info - if( info.denom == 0 ) - mach_timebase_info( &info ); - uint64_t elapsednano = current * ( info.numer / info.denom ); - // convert ns to ms - return elapsednano / 1e6; -#else - uint32_t ticks; - struct timespec t; - clock_gettime( CLOCK_MONOTONIC, &t ); - ticks = t.tv_sec * 1000; - ticks += t.tv_nsec / 1000000; - return ticks; -#endif -} - -void SignalCatcher2( int s ) -{ - CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting NOW" ); - - if( gGHost ) - { - if( gGHost->m_Exiting ) - exit( 1 ); - else - gGHost->m_Exiting = true; - } - else - exit( 1 ); -} - -void SignalCatcher( int s ) -{ - // signal( SIGABRT, SignalCatcher2 ); - signal( SIGINT, SignalCatcher2 ); - - CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting nicely" ); - - if( gGHost ) - gGHost->m_ExitingNice = true; - else - exit( 1 ); -} - -void CONSOLE_Print( string message ) -{ - cout << message << endl; - - // logging - - if( !gLogFile.empty( ) ) - { - if( gLogMethod == 1 ) - { - ofstream Log; - Log.open( gLogFile.c_str( ), ios :: app ); - - if( !Log.fail( ) ) - { - time_t Now = time( NULL ); - string Time = asctime( localtime( &Now ) ); - - // erase the newline - - Time.erase( Time.size( ) - 1 ); - Log << "[" << Time << "] " << message << endl; - Log.close( ); - } - } - else if( gLogMethod == 2 ) - { - if( gLog && !gLog->fail( ) ) - { - time_t Now = time( NULL ); - string Time = asctime( localtime( &Now ) ); - - // erase the newline - - Time.erase( Time.size( ) - 1 ); - *gLog << "[" << Time << "] " << message << endl; - gLog->flush( ); - } - } - } -} - -void DEBUG_Print( string message ) -{ - cout << message << endl; -} - -void DEBUG_Print( BYTEARRAY b ) -{ - cout << "{ "; - - for( unsigned int i = 0; i < b.size( ); i++ ) - cout << hex << (int)b[i] << " "; - - cout << "}" << endl; -} - -// -// main -// - -int main( int argc, char **argv ) -{ - gCFGFile = "ghost.cfg"; - - if( argc > 1 && argv[1] ) - gCFGFile = argv[1]; - - // read config file - - CConfig CFG; - CFG.Read( "default.cfg" ); - CFG.Read( gCFGFile ); - gLogFile = CFG.GetString( "bot_log", string( ) ); - gLogMethod = CFG.GetInt( "bot_logmethod", 1 ); - - if( !gLogFile.empty( ) ) - { - if( gLogMethod == 1 ) - { - // log method 1: open, append, and close the log for every message - // this works well on Linux but poorly on Windows, particularly as the log file grows in size - // the log file can be edited/moved/deleted while GHost++ is running - } - else if( gLogMethod == 2 ) - { - // log method 2: open the log on startup, flush the log for every message, close the log on shutdown - // the log file CANNOT be edited/moved/deleted while GHost++ is running - - gLog = new ofstream( ); - gLog->open( gLogFile.c_str( ), ios :: app ); - } - } - - CONSOLE_Print( "[GHOST] starting up" ); - - if( !gLogFile.empty( ) ) - { - if( gLogMethod == 1 ) - CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile + "] will not be locked" ); - else if( gLogMethod == 2 ) - { - if( gLog->fail( ) ) - CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile + "] for appending, logging is disabled" ); - else - CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile + "] is now locked" ); - } - } - else - CONSOLE_Print( "[GHOST] no log file specified, logging is disabled" ); - - // catch SIGABRT and SIGINT - - // signal( SIGABRT, SignalCatcher ); - signal( SIGINT, SignalCatcher ); - -#ifndef WIN32 - // disable SIGPIPE since some systems like OS X don't define MSG_NOSIGNAL - - signal( SIGPIPE, SIG_IGN ); -#endif - -#ifdef WIN32 - // initialize timer resolution - // attempt to set the resolution as low as possible from 1ms to 5ms - - unsigned int TimerResolution = 0; - - for( unsigned int i = 1; i <= 5; i++ ) - { - if( timeBeginPeriod( i ) == TIMERR_NOERROR ) - { - TimerResolution = i; - break; - } - else if( i < 5 ) - CONSOLE_Print( "[GHOST] error setting Windows timer resolution to " + UTIL_ToString( i ) + " milliseconds, trying a higher resolution" ); - else - { - CONSOLE_Print( "[GHOST] error setting Windows timer resolution" ); - return 1; - } - } - - CONSOLE_Print( "[GHOST] using Windows timer with resolution " + UTIL_ToString( TimerResolution ) + " milliseconds" ); -#elif __APPLE__ - // not sure how to get the resolution -#else - // print the timer resolution - - struct timespec Resolution; - - if( clock_getres( CLOCK_MONOTONIC, &Resolution ) == -1 ) - CONSOLE_Print( "[GHOST] error getting monotonic timer resolution" ); - else - CONSOLE_Print( "[GHOST] using monotonic timer with resolution " + UTIL_ToString( (double)( Resolution.tv_nsec / 1000 ), 2 ) + " microseconds" ); -#endif - -#ifdef WIN32 - // initialize winsock - - CONSOLE_Print( "[GHOST] starting winsock" ); - WSADATA wsadata; - - if( WSAStartup( MAKEWORD( 2, 2 ), &wsadata ) != 0 ) - { - CONSOLE_Print( "[GHOST] error starting winsock" ); - return 1; - } - - // increase process priority - - CONSOLE_Print( "[GHOST] setting process priority to \"above normal\"" ); - SetPriorityClass( GetCurrentProcess( ), ABOVE_NORMAL_PRIORITY_CLASS ); -#endif - - // initialize ghost - - gGHost = new CGHost( &CFG ); - - while( 1 ) - { - // block for 50ms on all sockets - if you intend to perform any timed actions more frequently you should change this - // that said it's likely we'll loop more often than this due to there being data waiting on one of the sockets but there aren't any guarantees - - if( gGHost->Update( 50000 ) ) - break; - } - - // shutdown ghost - - CONSOLE_Print( "[GHOST] shutting down" ); - delete gGHost; - gGHost = NULL; - -#ifdef WIN32 - // shutdown winsock - - CONSOLE_Print( "[GHOST] shutting down winsock" ); - WSACleanup( ); - - // shutdown timer - - timeEndPeriod( TimerResolution ); -#endif - - if( gLog ) - { - if( !gLog->fail( ) ) - gLog->close( ); - - delete gLog; - } - - return 0; -} // // CGHost // -CGHost :: CGHost( CConfig *CFG ) +CGHost :: CGHost( CConfig *CFG, string configFile ) + : m_ConfigFile(configFile) { m_UDPSocket = new CUDPSocket( ); m_UDPSocket->SetBroadcastTarget( CFG->GetString( "udp_broadcasttarget", string( ) ) ); @@ -1313,7 +980,7 @@ void CGHost :: ReloadConfigs( ) { CConfig CFG; CFG.Read( "default.cfg" ); - CFG.Read( gCFGFile ); + CFG.Read( m_ConfigFile ); SetConfigs( &CFG ); } diff --git a/ghost/ghost.h b/ghost/ghost.h index 7e84ce3..947deb7 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -133,8 +133,9 @@ class CGHost uint32_t m_ReplayBuildNumber; // config value: replay build number (for saving replays) bool m_TCPNoDelay; // config value: use Nagle's algorithm or not uint32_t m_MatchMakingMethod; // config value: the matchmaking method + string m_ConfigFile; - CGHost( CConfig *CFG ); + CGHost( CConfig *CFG, string configFile ); ~CGHost( ); // processing functions diff --git a/ghost/ghost.pro b/ghost/ghost.pro new file mode 100644 index 0000000..bd41067 --- /dev/null +++ b/ghost/ghost.pro @@ -0,0 +1,92 @@ +# ------------------------------------------------- +# Project created by QtCreator 2010-04-19T13:31:03 +# ------------------------------------------------- +QT += network \ + sql +QT -= gui +TARGET = ghost +CONFIG += console +CONFIG -= app_bundle +TEMPLATE = app +SOURCES += util.cpp \ + statsw3mmd.cpp \ + statsdota.cpp \ + stats.cpp \ + sqlite3.c \ + socket.cpp \ + sha1.cpp \ + savegame.cpp \ + replay.cpp \ + packed.cpp \ + map.cpp \ + language.cpp \ + gpsprotocol.cpp \ + ghostdbsqlite.cpp \ + ghostdbmysql.cpp \ + ghostdb.cpp \ + ghost.cpp \ + gameslot.cpp \ + gameprotocol.cpp \ + gameplayer.cpp \ + game_base.cpp \ + game_admin.cpp \ + game.cpp \ + csvparser.cpp \ + crc32.cpp \ + config.cpp \ + commandpacket.cpp \ + bnlsprotocol.cpp \ + bnlsclient.cpp \ + bnetprotocol.cpp \ + bnet.cpp \ + bncsutilinterface.cpp \ + main.cpp +OTHER_FILES += w3g_format.txt \ + w3g_actions.txt \ + ghost.vcproj +INCLUDEPATH += ../StormLib \ + ../bncsutil/src +LIBS += -L../StormLib/stormlib \ + -L../bncsutil/src/bncsutil \ + -lbncsutil \ + -lStorm \ + -lboost_date_time-mt \ + -lboost_thread-mt \ + -lboost_system-mt \ + -lboost_filesystem-mt +HEADERS += util.h \ + statsw3mmd.h \ + statsdota.h \ + stats.h \ + sqlite3ext.h \ + sqlite3.h \ + socket.h \ + sha1.h \ + savegame.h \ + replay.h \ + packed.h \ + next_combination.h \ + ms_stdint.h \ + map.h \ + language.h \ + includes.h \ + gpsprotocol.h \ + ghostdbsqlite.h \ + ghostdbmysql.h \ + ghostdb.h \ + ghost.h \ + gameslot.h \ + gameprotocol.h \ + gameplayer.h \ + game_base.h \ + game_admin.h \ + game.h \ + csvparser.h \ + crc32.h \ + config.h \ + commandpacket.h \ + bnlsprotocol.h \ + bnlsclient.h \ + bnetprotocol.h \ + bnet.h \ + bncsutilinterface.h diff --git a/ghost/main.cpp b/ghost/main.cpp new file mode 100644 index 0000000..bfb6db4 --- /dev/null +++ b/ghost/main.cpp @@ -0,0 +1,272 @@ +#include +#include +#include + +#include "ghost.h" +#include "util.h" +#include "config.h" + +QTime gBasicTime; + +string gCFGFile; +string gLogFile; +uint32_t gLogMethod; +ofstream *gLog = NULL; +CGHost *gGHost = NULL; + +uint32_t GetTime() +{ + return GetTicks( ) / 1000; +} + +uint32_t GetTicks() +{ + return gBasicTime.msec(); +} + +void SignalCatcher2( int s ) +{ + CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting NOW" ); + + if( gGHost ) + { + if( gGHost->m_Exiting ) + exit( 1 ); + else + gGHost->m_Exiting = true; + } + else + exit( 1 ); +} + +void SignalCatcher( int s ) +{ + // signal( SIGABRT, SignalCatcher2 ); + signal( SIGINT, SignalCatcher2 ); + + CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting nicely" ); + + if( gGHost ) + gGHost->m_ExitingNice = true; + else + exit( 1 ); +} + +void CONSOLE_Print( string message ) +{ + cout << message << endl; + + // logging + + if( !gLogFile.empty( ) ) + { + if( gLogMethod == 1 ) + { + ofstream Log; + Log.open( gLogFile.c_str( ), ios :: app ); + + if( !Log.fail( ) ) + { + time_t Now = time( NULL ); + string Time = asctime( localtime( &Now ) ); + + // erase the newline + + Time.erase( Time.size( ) - 1 ); + Log << "[" << Time << "] " << message << endl; + Log.close( ); + } + } + else if( gLogMethod == 2 ) + { + if( gLog && !gLog->fail( ) ) + { + time_t Now = time( NULL ); + string Time = asctime( localtime( &Now ) ); + + // erase the newline + + Time.erase( Time.size( ) - 1 ); + *gLog << "[" << Time << "] " << message << endl; + gLog->flush( ); + } + } + } +} + +void DEBUG_Print( string message ) +{ + cout << message << endl; +} + +void DEBUG_Print( BYTEARRAY b ) +{ + cout << "{ "; + + for( unsigned int i = 0; i < b.size( ); i++ ) + cout << hex << (int)b[i] << " "; + + cout << "}" << endl; +} + +// +// main +// + +int main( int argc, char **argv ) +{ + QCoreApplication a(argc, argv); + + gCFGFile = "ghost.cfg"; + + if( argc > 1 && argv[1] ) + gCFGFile = argv[1]; + + // read config file + + CConfig CFG; + CFG.Read( "default.cfg" ); + CFG.Read( gCFGFile ); + gLogFile = CFG.GetString( "bot_log", string( ) ); + gLogMethod = CFG.GetInt( "bot_logmethod", 1 ); + + if( !gLogFile.empty( ) ) + { + if( gLogMethod == 1 ) + { + // log method 1: open, append, and close the log for every message + // this works well on Linux but poorly on Windows, particularly as the log file grows in size + // the log file can be edited/moved/deleted while GHost++ is running + } + else if( gLogMethod == 2 ) + { + // log method 2: open the log on startup, flush the log for every message, close the log on shutdown + // the log file CANNOT be edited/moved/deleted while GHost++ is running + + gLog = new ofstream( ); + gLog->open( gLogFile.c_str( ), ios :: app ); + } + } + + CONSOLE_Print( "[GHOST] starting up" ); + + if( !gLogFile.empty( ) ) + { + if( gLogMethod == 1 ) + CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile + "] will not be locked" ); + else if( gLogMethod == 2 ) + { + if( gLog->fail( ) ) + CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile + "] for appending, logging is disabled" ); + else + CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile + "] is now locked" ); + } + } + else + CONSOLE_Print( "[GHOST] no log file specified, logging is disabled" ); + + // catch SIGABRT and SIGINT + + // signal( SIGABRT, SignalCatcher ); + signal( SIGINT, SignalCatcher ); + +#ifndef WIN32 + // disable SIGPIPE since some systems like OS X don't define MSG_NOSIGNAL + + signal( SIGPIPE, SIG_IGN ); +#endif + +#ifdef WIN32 + // initialize timer resolution + // attempt to set the resolution as low as possible from 1ms to 5ms + + unsigned int TimerResolution = 0; + + for( unsigned int i = 1; i <= 5; i++ ) + { + if( timeBeginPeriod( i ) == TIMERR_NOERROR ) + { + TimerResolution = i; + break; + } + else if( i < 5 ) + CONSOLE_Print( "[GHOST] error setting Windows timer resolution to " + UTIL_ToString( i ) + " milliseconds, trying a higher resolution" ); + else + { + CONSOLE_Print( "[GHOST] error setting Windows timer resolution" ); + return 1; + } + } + + CONSOLE_Print( "[GHOST] using Windows timer with resolution " + UTIL_ToString( TimerResolution ) + " milliseconds" ); +#elif __APPLE__ + // not sure how to get the resolution +#else + // print the timer resolution + + struct timespec Resolution; + + if( clock_getres( CLOCK_MONOTONIC, &Resolution ) == -1 ) + CONSOLE_Print( "[GHOST] error getting monotonic timer resolution" ); + else + CONSOLE_Print( "[GHOST] using monotonic timer with resolution " + UTIL_ToString( (double)( Resolution.tv_nsec / 1000 ), 2 ) + " microseconds" ); +#endif + +#ifdef WIN32 + // initialize winsock + + CONSOLE_Print( "[GHOST] starting winsock" ); + WSADATA wsadata; + + if( WSAStartup( MAKEWORD( 2, 2 ), &wsadata ) != 0 ) + { + CONSOLE_Print( "[GHOST] error starting winsock" ); + return 1; + } + + // increase process priority + + CONSOLE_Print( "[GHOST] setting process priority to \"above normal\"" ); + SetPriorityClass( GetCurrentProcess( ), ABOVE_NORMAL_PRIORITY_CLASS ); +#endif + + // initialize ghost + + gGHost = new CGHost( &CFG, gCFGFile ); + + while( 1 ) + { + // block for 50ms on all sockets - if you intend to perform any timed actions more frequently you should change this + // that said it's likely we'll loop more often than this due to there being data waiting on one of the sockets but there aren't any guarantees + + if( gGHost->Update( 50000 ) ) + break; + } + + // shutdown ghost + + CONSOLE_Print( "[GHOST] shutting down" ); + delete gGHost; + gGHost = NULL; + +#ifdef WIN32 + // shutdown winsock + + CONSOLE_Print( "[GHOST] shutting down winsock" ); + WSACleanup( ); + + // shutdown timer + + timeEndPeriod( TimerResolution ); +#endif + + if( gLog ) + { + if( !gLog->fail( ) ) + gLog->close( ); + + delete gLog; + } + + return a.exec(); +} From 84b3aaff012e4cbdd8fece6d8efec269ad196650 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Mon, 19 Apr 2010 13:47:06 +0000 Subject: [PATCH 02/69] not working so far --- ghost/Makefile | 678 ++++++++++++++++++++++++++++---- ghost/bncsutilinterface.cpp | 22 +- ghost/bncsutilinterface.h | 16 +- ghost/bnet.cpp | 198 +++++----- ghost/bnetprotocol.cpp | 106 ++--- ghost/bnlsclient.cpp | 8 +- ghost/config.cpp | 28 +- ghost/csvparser.cpp | 44 +-- ghost/game.cpp | 86 ++--- ghost/game.h | 14 +- ghost/game_admin.cpp | 136 +++---- ghost/game_admin.h | 24 +- ghost/game_base.cpp | 166 ++++---- ghost/game_base.h | 80 ++-- ghost/gameplayer.cpp | 24 +- ghost/gameplayer.h | 34 +- ghost/gameprotocol.cpp | 363 ++++++++--------- ghost/gameprotocol.h | 102 ++--- ghost/ghost.cpp | 98 ++--- ghost/ghost.h | 54 +-- ghost/ghost.pro | 1 - ghost/ghostdb.cpp | 108 +++--- ghost/ghostdb.h | 404 +++++++++---------- ghost/ghostdbmysql.cpp | 316 +++++++-------- ghost/ghostdbsqlite.cpp | 138 +++---- ghost/includes.h | 12 +- ghost/language.cpp | 750 ++++++++++++++++++------------------ ghost/main.cpp | 118 ++---- ghost/map.cpp | 130 +++---- ghost/packed.cpp | 32 +- ghost/replay.cpp | 130 +++---- ghost/replay.h | 35 +- ghost/savegame.cpp | 22 +- ghost/savegame.h | 22 +- ghost/socket.cpp | 68 ++-- ghost/socket.h | 40 +- ghost/statsdota.cpp | 82 ++-- ghost/statsw3mmd.cpp | 74 ++-- ghost/statsw3mmd.h | 20 +- ghost/util.cpp | 447 +++++++++------------ ghost/util.h | 98 ++--- 41 files changed, 2839 insertions(+), 2489 deletions(-) diff --git a/ghost/Makefile b/ghost/Makefile index c3a5d5d..c658838 100644 --- a/ghost/Makefile +++ b/ghost/Makefile @@ -1,84 +1,594 @@ -SHELL = /bin/sh -SYSTEM = $(shell uname) -C++ = g++ -CC = gcc -DFLAGS = -DGHOST_MYSQL -OFLAGS = -O3 -LFLAGS = -L. -L../bncsutil/src/bncsutil/ -L../StormLib/stormlib/ -lbncsutil -lpthread -ldl -lz -lStorm -lmysqlclient_r -lboost_date_time-mt -lboost_thread-mt -lboost_system-mt -lboost_filesystem-mt -CFLAGS = - -ifeq ($(SYSTEM),Darwin) -DFLAGS += -D__APPLE__ -OFLAGS += -flat_namespace -else -LFLAGS += -lrt -endif - -ifeq ($(SYSTEM),FreeBSD) -DFLAGS += -D__FREEBSD__ -endif - -ifeq ($(SYSTEM),SunOS) -DFLAGS += -D__SOLARIS__ -LFLAGS += -lresolv -lsocket -lnsl -endif - -CFLAGS += $(OFLAGS) $(DFLAGS) -I. -I../bncsutil/src/ -I../StormLib/ - -ifeq ($(SYSTEM),Darwin) -CFLAGS += -I../mysql/include/ -endif - -OBJS = bncsutilinterface.o bnet.o bnetprotocol.o bnlsclient.o bnlsprotocol.o commandpacket.o config.o crc32.o csvparser.o game.o game_admin.o game_base.o gameplayer.o gameprotocol.o gameslot.o ghost.o ghostdb.o ghostdbmysql.o ghostdbsqlite.o gpsprotocol.o language.o map.o packed.o replay.o savegame.o sha1.o socket.o stats.o statsdota.o statsw3mmd.o util.o -COBJS = sqlite3.o -PROGS = ./ghost++ - -all: $(OBJS) $(COBJS) $(PROGS) - -./ghost++: $(OBJS) $(COBJS) - $(C++) -o ./ghost++ $(OBJS) $(COBJS) $(LFLAGS) - -clean: - rm -f $(OBJS) $(COBJS) $(PROGS) - -$(OBJS): %.o: %.cpp - $(C++) -o $@ $(CFLAGS) -c $< - -$(COBJS): %.o: %.c - $(CC) -o $@ $(CFLAGS) -c $< - -./ghost++: $(OBJS) $(COBJS) - -all: $(PROGS) - -bncsutilinterface.o: ghost.h includes.h util.h bncsutilinterface.h -bnet.o: ghost.h includes.h util.h config.h language.h socket.h commandpacket.h ghostdb.h bncsutilinterface.h bnlsclient.h bnetprotocol.h bnet.h map.h packed.h savegame.h replay.h gameprotocol.h game_base.h -bnetprotocol.o: ghost.h includes.h util.h bnetprotocol.h -bnlsclient.o: ghost.h includes.h util.h socket.h commandpacket.h bnlsprotocol.h bnlsclient.h -bnlsprotocol.o: ghost.h includes.h util.h bnlsprotocol.h -commandpacket.o: ghost.h includes.h commandpacket.h -config.o: ghost.h includes.h config.h -crc32.o: ghost.h includes.h crc32.h -csvparser.o: csvparser.h -game.o: ghost.h includes.h util.h config.h language.h socket.h ghostdb.h bnet.h map.h packed.h savegame.h gameplayer.h gameprotocol.h game_base.h game.h stats.h statsdota.h statsw3mmd.h -game_admin.o: ghost.h includes.h util.h config.h language.h socket.h ghostdb.h bnet.h map.h packed.h savegame.h replay.h gameplayer.h gameprotocol.h game_base.h game_admin.h -game_base.o: ghost.h includes.h util.h config.h language.h socket.h ghostdb.h bnet.h map.h packed.h savegame.h replay.h gameplayer.h gameprotocol.h game_base.h next_combination.h -gameplayer.o: ghost.h includes.h util.h language.h socket.h commandpacket.h bnet.h map.h gameplayer.h gameprotocol.h gpsprotocol.h game_base.h -gameprotocol.o: ghost.h includes.h util.h crc32.h gameplayer.h gameprotocol.h game_base.h -gameslot.o: ghost.h includes.h gameslot.h -ghost.o: ghost.h includes.h util.h crc32.h sha1.h csvparser.h config.h language.h socket.h ghostdb.h ghostdbsqlite.h ghostdbmysql.h bnet.h map.h packed.h savegame.h gameplayer.h gameprotocol.h gpsprotocol.h game_base.h game.h game_admin.h -ghostdb.o: ghost.h includes.h util.h config.h ghostdb.h -ghostdbmysql.o: ghost.h includes.h util.h config.h ghostdb.h ghostdbmysql.h -ghostdbsqlite.o: ghost.h includes.h util.h config.h ghostdb.h ghostdbsqlite.h -gpsprotocol.o: ghost.h util.h gpsprotocol.h -language.o: ghost.h includes.h config.h language.h -map.o: ghost.h includes.h util.h crc32.h sha1.h config.h map.h -packed.o: ghost.h includes.h util.h crc32.h packed.h -replay.o: ghost.h includes.h util.h packed.h replay.h gameprotocol.h -savegame.o: ghost.h includes.h util.h packed.h savegame.h -sha1.o: sha1.h -socket.o: ghost.h includes.h util.h socket.h -stats.o: ghost.h includes.h stats.h -statsdota.o: ghost.h includes.h util.h ghostdb.h gameplayer.h gameprotocol.h game_base.h stats.h statsdota.h -statsw3mmd.o: ghost.h includes.h util.h ghostdb.h gameprotocol.h game_base.h stats.h statsw3mmd.h -util.o: ghost.h includes.h util.h +############################################################################# +# Makefile for building: ghost +# Generated by qmake (2.01a) (Qt 4.6.2) on: Mon Apr 19 15:36:38 2010 +# Project: ghost.pro +# Template: app +# Command: /usr/bin/qmake -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_SQL_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES) +INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtNetwork -I/usr/include/qt4/QtSql -I/usr/include/qt4 -I../StormLib -I../bncsutil/src -I. +LINK = g++ +LFLAGS = -Wl,-rpath,/usr/lib/qt4 +LIBS = $(SUBLIBS) -L/usr/lib/qt4 -L../StormLib/stormlib -L../bncsutil/src/bncsutil -lbncsutil -lStorm -lboost_date_time-mt -lboost_thread-mt -lboost_system-mt -lboost_filesystem-mt -lQtSql -L/usr/lib/mysql -L/usr/lib/qt4 -lQtNetwork -lQtCore -lgthread-2.0 -lrt -lglib-2.0 -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = util.cpp \ + statsw3mmd.cpp \ + statsdota.cpp \ + stats.cpp \ + sqlite3.c \ + sha1.cpp \ + savegame.cpp \ + replay.cpp \ + packed.cpp \ + map.cpp \ + language.cpp \ + gpsprotocol.cpp \ + ghostdbsqlite.cpp \ + ghostdbmysql.cpp \ + ghostdb.cpp \ + ghost.cpp \ + gameslot.cpp \ + gameprotocol.cpp \ + gameplayer.cpp \ + game_base.cpp \ + game_admin.cpp \ + game.cpp \ + csvparser.cpp \ + crc32.cpp \ + config.cpp \ + commandpacket.cpp \ + bnlsprotocol.cpp \ + bnlsclient.cpp \ + bnetprotocol.cpp \ + bnet.cpp \ + bncsutilinterface.cpp \ + main.cpp moc_ghost.cpp +OBJECTS = util.o \ + statsw3mmd.o \ + statsdota.o \ + stats.o \ + sqlite3.o \ + sha1.o \ + savegame.o \ + replay.o \ + packed.o \ + map.o \ + language.o \ + gpsprotocol.o \ + ghostdbsqlite.o \ + ghostdbmysql.o \ + ghostdb.o \ + ghost.o \ + gameslot.o \ + gameprotocol.o \ + gameplayer.o \ + game_base.o \ + game_admin.o \ + game.o \ + csvparser.o \ + crc32.o \ + config.o \ + commandpacket.o \ + bnlsprotocol.o \ + bnlsclient.o \ + bnetprotocol.o \ + bnet.o \ + bncsutilinterface.o \ + main.o \ + moc_ghost.o +DIST = /usr/share/qt4/mkspecs/common/g++.conf \ + /usr/share/qt4/mkspecs/common/unix.conf \ + /usr/share/qt4/mkspecs/common/linux.conf \ + /usr/share/qt4/mkspecs/qconfig.pri \ + /usr/share/qt4/mkspecs/features/qt_functions.prf \ + /usr/share/qt4/mkspecs/features/qt_config.prf \ + /usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt4/mkspecs/features/default_pre.prf \ + /usr/share/qt4/mkspecs/features/debug.prf \ + /usr/share/qt4/mkspecs/features/default_post.prf \ + /usr/share/qt4/mkspecs/features/warn_on.prf \ + /usr/share/qt4/mkspecs/features/qt.prf \ + /usr/share/qt4/mkspecs/features/unix/thread.prf \ + /usr/share/qt4/mkspecs/features/moc.prf \ + /usr/share/qt4/mkspecs/features/resources.prf \ + /usr/share/qt4/mkspecs/features/uic.prf \ + /usr/share/qt4/mkspecs/features/yacc.prf \ + /usr/share/qt4/mkspecs/features/lex.prf \ + /usr/share/qt4/mkspecs/features/include_source_dir.prf \ + ghost.pro +QMAKE_TARGET = ghost +DESTDIR = +TARGET = ghost + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + +Makefile: ghost.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/g++.conf \ + /usr/share/qt4/mkspecs/common/unix.conf \ + /usr/share/qt4/mkspecs/common/linux.conf \ + /usr/share/qt4/mkspecs/qconfig.pri \ + /usr/share/qt4/mkspecs/features/qt_functions.prf \ + /usr/share/qt4/mkspecs/features/qt_config.prf \ + /usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt4/mkspecs/features/default_pre.prf \ + /usr/share/qt4/mkspecs/features/debug.prf \ + /usr/share/qt4/mkspecs/features/default_post.prf \ + /usr/share/qt4/mkspecs/features/warn_on.prf \ + /usr/share/qt4/mkspecs/features/qt.prf \ + /usr/share/qt4/mkspecs/features/unix/thread.prf \ + /usr/share/qt4/mkspecs/features/moc.prf \ + /usr/share/qt4/mkspecs/features/resources.prf \ + /usr/share/qt4/mkspecs/features/uic.prf \ + /usr/share/qt4/mkspecs/features/yacc.prf \ + /usr/share/qt4/mkspecs/features/lex.prf \ + /usr/share/qt4/mkspecs/features/include_source_dir.prf \ + /usr/lib/qt4/libQtSql.prl \ + /usr/lib/qt4/libQtCore.prl \ + /usr/lib/qt4/libQtNetwork.prl + $(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro +/usr/share/qt4/mkspecs/common/g++.conf: +/usr/share/qt4/mkspecs/common/unix.conf: +/usr/share/qt4/mkspecs/common/linux.conf: +/usr/share/qt4/mkspecs/qconfig.pri: +/usr/share/qt4/mkspecs/features/qt_functions.prf: +/usr/share/qt4/mkspecs/features/qt_config.prf: +/usr/share/qt4/mkspecs/features/exclusive_builds.prf: +/usr/share/qt4/mkspecs/features/default_pre.prf: +/usr/share/qt4/mkspecs/features/debug.prf: +/usr/share/qt4/mkspecs/features/default_post.prf: +/usr/share/qt4/mkspecs/features/warn_on.prf: +/usr/share/qt4/mkspecs/features/qt.prf: +/usr/share/qt4/mkspecs/features/unix/thread.prf: +/usr/share/qt4/mkspecs/features/moc.prf: +/usr/share/qt4/mkspecs/features/resources.prf: +/usr/share/qt4/mkspecs/features/uic.prf: +/usr/share/qt4/mkspecs/features/yacc.prf: +/usr/share/qt4/mkspecs/features/lex.prf: +/usr/share/qt4/mkspecs/features/include_source_dir.prf: +/usr/lib/qt4/libQtSql.prl: +/usr/lib/qt4/libQtCore.prl: +/usr/lib/qt4/libQtNetwork.prl: +qmake: FORCE + @$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro + +dist: + @$(CHK_DIR_EXISTS) .tmp/ghost1.0.0 || $(MKDIR) .tmp/ghost1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/ghost1.0.0/ && $(COPY_FILE) --parents util.h statsw3mmd.h statsdota.h stats.h sqlite3ext.h sqlite3.h socket.h sha1.h savegame.h replay.h packed.h next_combination.h ms_stdint.h map.h language.h includes.h gpsprotocol.h ghostdbsqlite.h ghostdbmysql.h ghostdb.h ghost.h gameslot.h gameprotocol.h gameplayer.h game_base.h game_admin.h game.h csvparser.h crc32.h config.h commandpacket.h bnlsprotocol.h bnlsclient.h bnetprotocol.h bnet.h bncsutilinterface.h .tmp/ghost1.0.0/ && $(COPY_FILE) --parents util.cpp statsw3mmd.cpp statsdota.cpp stats.cpp sqlite3.c sha1.cpp savegame.cpp replay.cpp packed.cpp map.cpp language.cpp gpsprotocol.cpp ghostdbsqlite.cpp ghostdbmysql.cpp ghostdb.cpp ghost.cpp gameslot.cpp gameprotocol.cpp gameplayer.cpp game_base.cpp game_admin.cpp game.cpp csvparser.cpp crc32.cpp config.cpp commandpacket.cpp bnlsprotocol.cpp bnlsclient.cpp bnetprotocol.cpp bnet.cpp bncsutilinterface.cpp main.cpp .tmp/ghost1.0.0/ && (cd `dirname .tmp/ghost1.0.0` && $(TAR) ghost1.0.0.tar ghost1.0.0 && $(COMPRESS) ghost1.0.0.tar) && $(MOVE) `dirname .tmp/ghost1.0.0`/ghost1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/ghost1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: moc_ghost.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc_ghost.cpp +moc_ghost.cpp: includes.h \ + ms_stdint.h \ + ghost.h + /usr/bin/moc $(DEFINES) $(INCPATH) ghost.h -o moc_ghost.cpp + +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean + +####### Compile + +util.o: util.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o util.o util.cpp + +statsw3mmd.o: statsw3mmd.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + ghostdb.h \ + gameprotocol.h \ + gameslot.h \ + game_base.h \ + stats.h \ + statsw3mmd.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o statsw3mmd.o statsw3mmd.cpp + +statsdota.o: statsdota.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + ghostdb.h \ + gameplayer.h \ + gameprotocol.h \ + gameslot.h \ + game_base.h \ + stats.h \ + statsdota.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o statsdota.o statsdota.cpp + +stats.o: stats.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + stats.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o stats.o stats.cpp + +sqlite3.o: sqlite3.c config.h + $(CC) -c $(CFLAGS) $(INCPATH) -o sqlite3.o sqlite3.c + +sha1.o: sha1.cpp sha1.h \ + ms_stdint.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o sha1.o sha1.cpp + +savegame.o: savegame.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + packed.h \ + savegame.h \ + gameslot.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o savegame.o savegame.cpp + +replay.o: replay.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + packed.h \ + replay.h \ + gameslot.h \ + gameprotocol.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o replay.o replay.cpp + +packed.o: packed.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + crc32.h \ + packed.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o packed.o packed.cpp + +map.o: map.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + crc32.h \ + sha1.h \ + config.h \ + map.h \ + gameslot.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o map.o map.cpp + +language.o: language.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + language.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o language.o language.cpp + +gpsprotocol.o: gpsprotocol.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + gpsprotocol.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gpsprotocol.o gpsprotocol.cpp + +ghostdbsqlite.o: ghostdbsqlite.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + ghostdb.h \ + ghostdbsqlite.h \ + sqlite3.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghostdbsqlite.o ghostdbsqlite.cpp + +ghostdbmysql.o: ghostdbmysql.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + ghostdb.h \ + ghostdbmysql.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghostdbmysql.o ghostdbmysql.cpp + +ghostdb.o: ghostdb.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + ghostdb.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghostdb.o ghostdb.cpp + +ghost.o: ghost.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + crc32.h \ + sha1.h \ + csvparser.h \ + config.h \ + language.h \ + socket.h \ + ghostdb.h \ + ghostdbsqlite.h \ + ghostdbmysql.h \ + bnet.h \ + map.h \ + gameslot.h \ + packed.h \ + savegame.h \ + gameplayer.h \ + gameprotocol.h \ + gpsprotocol.h \ + game_base.h \ + game.h \ + game_admin.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghost.o ghost.cpp + +gameslot.o: gameslot.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + gameslot.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gameslot.o gameslot.cpp + +gameprotocol.o: gameprotocol.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + crc32.h \ + gameplayer.h \ + gameprotocol.h \ + gameslot.h \ + game_base.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gameprotocol.o gameprotocol.cpp + +gameplayer.o: gameplayer.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + language.h \ + socket.h \ + commandpacket.h \ + bnet.h \ + map.h \ + gameslot.h \ + gameplayer.h \ + gameprotocol.h \ + gpsprotocol.h \ + game_base.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gameplayer.o gameplayer.cpp + +game_base.o: game_base.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + language.h \ + socket.h \ + ghostdb.h \ + bnet.h \ + map.h \ + gameslot.h \ + packed.h \ + savegame.h \ + replay.h \ + gameplayer.h \ + gameprotocol.h \ + game_base.h \ + next_combination.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o game_base.o game_base.cpp + +game_admin.o: game_admin.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + language.h \ + socket.h \ + ghostdb.h \ + bnet.h \ + map.h \ + gameslot.h \ + packed.h \ + savegame.h \ + replay.h \ + gameplayer.h \ + gameprotocol.h \ + game_base.h \ + game_admin.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o game_admin.o game_admin.cpp + +game.o: game.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + language.h \ + socket.h \ + ghostdb.h \ + bnet.h \ + map.h \ + gameslot.h \ + packed.h \ + savegame.h \ + gameplayer.h \ + gameprotocol.h \ + game_base.h \ + game.h \ + stats.h \ + statsdota.h \ + statsw3mmd.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o game.o game.cpp + +csvparser.o: csvparser.cpp csvparser.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o csvparser.o csvparser.cpp + +crc32.o: crc32.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + crc32.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o crc32.o crc32.cpp + +config.o: config.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + config.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o config.o config.cpp + +commandpacket.o: commandpacket.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + commandpacket.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o commandpacket.o commandpacket.cpp + +bnlsprotocol.o: bnlsprotocol.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + bnlsprotocol.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnlsprotocol.o bnlsprotocol.cpp + +bnlsclient.o: bnlsclient.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + socket.h \ + commandpacket.h \ + bnlsprotocol.h \ + bnlsclient.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnlsclient.o bnlsclient.cpp + +bnetprotocol.o: bnetprotocol.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + bnetprotocol.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnetprotocol.o bnetprotocol.cpp + +bnet.o: bnet.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h \ + language.h \ + socket.h \ + commandpacket.h \ + ghostdb.h \ + bncsutilinterface.h \ + bnlsclient.h \ + bnetprotocol.h \ + bnet.h \ + map.h \ + gameslot.h \ + packed.h \ + savegame.h \ + replay.h \ + gameprotocol.h \ + game_base.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnet.o bnet.cpp + +bncsutilinterface.o: bncsutilinterface.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + bncsutilinterface.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bncsutilinterface.o bncsutilinterface.cpp + +main.o: main.cpp ghost.h \ + includes.h \ + ms_stdint.h \ + util.h \ + config.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp + +moc_ghost.o: moc_ghost.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_ghost.o moc_ghost.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index 637bc8d..a63564c 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -28,7 +28,7 @@ // CBNCSUtilInterface // -CBNCSUtilInterface :: CBNCSUtilInterface( string userName, string userPassword ) +CBNCSUtilInterface :: CBNCSUtilInterface( QString userName, QString userPassword ) { // m_nls = (void *)nls_init( userName.c_str( ), userPassword.c_str( ) ); m_NLS = new NLS( userName, userPassword ); @@ -40,7 +40,7 @@ CBNCSUtilInterface :: ~CBNCSUtilInterface( ) delete (NLS *)m_NLS; } -void CBNCSUtilInterface :: Reset( string userName, string userPassword ) +void CBNCSUtilInterface :: Reset( QString userName, QString userPassword ) { // nls_free( (nls_t *)m_nls ); // m_nls = (void *)nls_init( userName.c_str( ), userPassword.c_str( ) ); @@ -48,17 +48,17 @@ void CBNCSUtilInterface :: Reset( string userName, string userPassword ) m_NLS = new NLS( userName, userPassword ); } -bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, string war3Path, string keyROC, string keyTFT, string valueStringFormula, string mpqFileName, BYTEARRAY clientToken, BYTEARRAY serverToken ) +bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, BYTEARRAY clientToken, BYTEARRAY serverToken ) { // set m_EXEVersion, m_EXEVersionHash, m_EXEInfo, m_InfoROC, m_InfoTFT - string FileWar3EXE = war3Path + "war3.exe"; - string FileStormDLL = war3Path + "Storm.dll"; + QString FileWar3EXE = war3Path + "war3.exe"; + QString FileStormDLL = war3Path + "Storm.dll"; if( !UTIL_FileExists( FileStormDLL ) ) FileStormDLL = war3Path + "storm.dll"; - string FileGameDLL = war3Path + "game.dll"; + QString FileGameDLL = war3Path + "game.dll"; bool ExistsWar3EXE = UTIL_FileExists( FileWar3EXE ); bool ExistsStormDLL = UTIL_FileExists( FileStormDLL ); bool ExistsGameDLL = UTIL_FileExists( FileGameDLL ); @@ -122,13 +122,13 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY salt, BYTE // set m_M1 char buf[20]; - // nls_get_M1( (nls_t *)m_nls, buf, string( serverKey.begin( ), serverKey.end( ) ).c_str( ), string( salt.begin( ), salt.end( ) ).c_str( ) ); - ( (NLS *)m_NLS )->getClientSessionKey( buf, string( salt.begin( ), salt.end( ) ).c_str( ), string( serverKey.begin( ), serverKey.end( ) ).c_str( ) ); + // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).c_str( ), QString( salt.begin( ), salt.end( ) ).c_str( ) ); + ( (NLS *)m_NLS )->getClientSessionKey( buf, QString( salt.begin( ), salt.end( ) ).c_str( ), QString( serverKey.begin( ), serverKey.end( ) ).c_str( ) ); m_M1 = UTIL_CreateByteArray( (unsigned char *)buf, 20 ); return true; } -bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( string userPassword ) +bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( QString userPassword ) { // set m_PvPGNPasswordHash @@ -138,7 +138,7 @@ bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( string userPassword ) return true; } -BYTEARRAY CBNCSUtilInterface :: CreateKeyInfo( string key, uint32_t clientToken, uint32_t serverToken ) +BYTEARRAY CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; BYTEARRAY KeyInfo; diff --git a/ghost/bncsutilinterface.h b/ghost/bncsutilinterface.h index 76b5858..be6753d 100644 --- a/ghost/bncsutilinterface.h +++ b/ghost/bncsutilinterface.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -31,7 +31,7 @@ class CBNCSUtilInterface void *m_NLS; BYTEARRAY m_EXEVersion; // set in HELP_SID_AUTH_CHECK BYTEARRAY m_EXEVersionHash; // set in HELP_SID_AUTH_CHECK - string m_EXEInfo; // set in HELP_SID_AUTH_CHECK + QString m_EXEInfo; // set in HELP_SID_AUTH_CHECK BYTEARRAY m_KeyInfoROC; // set in HELP_SID_AUTH_CHECK BYTEARRAY m_KeyInfoTFT; // set in HELP_SID_AUTH_CHECK BYTEARRAY m_ClientKey; // set in HELP_SID_AUTH_ACCOUNTLOGON @@ -39,12 +39,12 @@ class CBNCSUtilInterface BYTEARRAY m_PvPGNPasswordHash; // set in HELP_PvPGNPasswordHash public: - CBNCSUtilInterface( string userName, string userPassword ); + CBNCSUtilInterface( QString userName, QString userPassword ); ~CBNCSUtilInterface( ); BYTEARRAY GetEXEVersion( ) { return m_EXEVersion; } BYTEARRAY GetEXEVersionHash( ) { return m_EXEVersionHash; } - string GetEXEInfo( ) { return m_EXEInfo; } + QString GetEXEInfo( ) { return m_EXEInfo; } BYTEARRAY GetKeyInfoROC( ) { return m_KeyInfoROC; } BYTEARRAY GetKeyInfoTFT( ) { return m_KeyInfoTFT; } BYTEARRAY GetClientKey( ) { return m_ClientKey; } @@ -54,15 +54,15 @@ class CBNCSUtilInterface void SetEXEVersion( BYTEARRAY &nEXEVersion ) { m_EXEVersion = nEXEVersion; } void SetEXEVersionHash( BYTEARRAY &nEXEVersionHash ) { m_EXEVersionHash = nEXEVersionHash; } - void Reset( string userName, string userPassword ); + void Reset( QString userName, QString userPassword ); - bool HELP_SID_AUTH_CHECK( bool TFT, string war3Path, string keyROC, string keyTFT, string valueStringFormula, string mpqFileName, BYTEARRAY clientToken, BYTEARRAY serverToken ); + bool HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, BYTEARRAY clientToken, BYTEARRAY serverToken ); bool HELP_SID_AUTH_ACCOUNTLOGON( ); bool HELP_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY salt, BYTEARRAY serverKey ); - bool HELP_PvPGNPasswordHash( string userPassword ); + bool HELP_PvPGNPasswordHash( QString userPassword ); private: - BYTEARRAY CreateKeyInfo( string key, uint32_t clientToken, uint32_t serverToken ); + BYTEARRAY CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ); }; #endif diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 21b0855..1c6cc87 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -44,7 +44,7 @@ using namespace boost :: filesystem; // CBNET // -CBNET :: CBNET( CGHost *nGHost, string nServer, string nServerAlias, string nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, uint32_t nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, BYTEARRAY nEXEVersion, BYTEARRAY nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ) +CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, BYTEARRAY nEXEVersion, BYTEARRAY nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ) { // todotodo: append path seperator to Warcraft3Path if needed @@ -57,7 +57,7 @@ CBNET :: CBNET( CGHost *nGHost, string nServer, string nServerAlias, string nBNL m_CallableBanList = m_GHost->m_DB->ThreadedBanList( nServer ); m_Exiting = false; m_Server = nServer; - string LowerServer = m_Server; + QString LowerServer = m_Server; transform( LowerServer.begin( ), LowerServer.end( ), LowerServer.begin( ), (int(*)(int))tolower ); if( !nServerAlias.empty( ) ) @@ -362,7 +362,7 @@ bool CBNET :: Update( void *fd, void *send_fd ) if( DotAPlayerSummary ) { - string Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), + QString Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), UTIL_ToString( DotAPlayerSummary->GetTotalGames( ) ), UTIL_ToString( DotAPlayerSummary->GetTotalWins( ) ), UTIL_ToString( DotAPlayerSummary->GetTotalLosses( ) ), @@ -614,7 +614,7 @@ void CBNET :: ExtractPackets( ) { // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue - string *RecvBuffer = m_Socket->GetBytes( ); + QString *RecvBuffer = m_Socket->GetBytes( ); BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -759,7 +759,7 @@ void CBNET :: ProcessPackets( ) if( m_GHost->m_TFT ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: The Frozen Throne" ); else - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: Reign of Chaos" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: Reign of Chaos" ); m_Socket->PutBytes( m_Protocol->SEND_SID_AUTH_CHECK( m_GHost->m_TFT, m_Protocol->GetClientToken( ), m_BNCSUtil->GetEXEVersion( ), m_BNCSUtil->GetEXEVersionHash( ), m_BNCSUtil->GetKeyInfoROC( ), m_BNCSUtil->GetKeyInfoTFT( ), m_BNCSUtil->GetEXEInfo( ), "GHost" ) ); @@ -875,7 +875,7 @@ void CBNET :: ProcessPackets( ) // try to figure out if the user might be using the wrong logon type since too many people are confused by this - string Server = m_Server; + QString Server = m_Server; transform( Server.begin( ), Server.end( ), Server.begin( ), (int(*)(int))tolower ); if( m_PasswordHashType == "pvpgn" && ( Server == "useast.battle.net" || Server == "uswest.battle.net" || Server == "asia.battle.net" || Server == "europe.battle.net" ) ) @@ -928,8 +928,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { CBNETProtocol :: IncomingChatEvent Event = chatEvent->GetChatEvent( ); bool Whisper = ( Event == CBNETProtocol :: EID_WHISPER ); - string User = chatEvent->GetUser( ); - string Message = chatEvent->GetMessage( ); + QString User = chatEvent->GetUser( ); + QString Message = chatEvent->GetMessage( ); if( Event == CBNETProtocol :: EID_WHISPER || Event == CBNETProtocol :: EID_TALK ) { @@ -952,7 +952,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( Message == "s" || Message == "sc" || Message == "spoof" || Message == "check" || Message == "spoofcheck" ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, User, true ); - else if( Message.find( m_GHost->m_CurrentGame->GetGameName( ) ) != string :: npos ) + else if( Message.find( m_GHost->m_CurrentGame->GetGameName( ) ) != QString :: npos ) { // look for messages like "entered a Warcraft III The Frozen Throne game called XYZ" // we don't look for the English part of the text anymore because we want this to work with multiple languages @@ -962,7 +962,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // the equivalent pvpgn message is: [PvPGN Realm] Your friend abc has entered a Warcraft III Frozen Throne game named "xyz". - vector Tokens = UTIL_Tokenize( Message, ' ' ); + vector Tokens = UTIL_Tokenize( Message, ' ' ); if( Tokens.size( ) >= 3 ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, Tokens[2], false ); @@ -975,17 +975,17 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // handle bot commands if( Message == "?trigger" && ( IsAdmin( User ) || IsRootAdmin( User ) || ( m_PublicCommands && m_OutPackets.size( ) <= 3 ) ) ) - QueueChatCommand( m_GHost->m_Language->CommandTrigger( string( 1, m_CommandTrigger ) ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->CommandTrigger( QString( 1, m_CommandTrigger ) ), User, Whisper ); else if( !Message.empty( ) && Message[0] == m_CommandTrigger ) { // extract the command trigger, the command, and the payload // e.g. "!say hello world" -> command: "say", payload: "hello world" - string Command; - string Payload; - string :: size_type PayloadStart = Message.find( " " ); + QString Command; + QString Payload; + QString :: size_type PayloadStart = Message.find( " " ); - if( PayloadStart != string :: npos ) + if( PayloadStart != QString :: npos ) { Command = Message.substr( 1, PayloadStart - 1 ); Payload = Message.substr( PayloadStart + 1 ); @@ -1014,7 +1014,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsAdmin( Payload ) ) QueueChatCommand( m_GHost->m_Language->UserIsAlreadyAnAdmin( m_Server, Payload ), User, Whisper ); else - m_PairedAdminAdds.push_back( PairedAdminAdd( Whisper ? User : string( ), m_GHost->m_DB->ThreadedAdminAdd( m_Server, Payload ) ) ); + m_PairedAdminAdds.push_back( PairedAdminAdd( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedAdminAdd( m_Server, Payload ) ) ); } else QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); @@ -1030,8 +1030,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the victim and the reason // e.g. "Varlock leaver after dying" -> victim: "Varlock", reason: "leaver after dying" - string Victim; - string Reason; + QString Victim; + QString Reason; stringstream SS; SS << Payload; SS >> Victim; @@ -1039,16 +1039,16 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( !SS.eof( ) ) { getline( SS, Reason ); - string :: size_type Start = Reason.find_first_not_of( " " ); + QString :: size_type Start = Reason.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Reason = Reason.substr( Start ); } if( IsBannedName( Victim ) ) QueueChatCommand( m_GHost->m_Language->UserIsAlreadyBanned( m_Server, Victim ), User, Whisper ); else - m_PairedBanAdds.push_back( PairedBanAdd( Whisper ? User : string( ), m_GHost->m_DB->ThreadedBanAdd( m_Server, Victim, string( ), string( ), User, Reason ) ) ); + m_PairedBanAdds.push_back( PairedBanAdd( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedBanAdd( m_Server, Victim, QString( ), QString( ), User, Reason ) ) ); } // @@ -1060,7 +1060,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Payload.empty( ) || Payload == "off" ) { QueueChatCommand( m_GHost->m_Language->AnnounceMessageDisabled( ), User, Whisper ); - m_GHost->m_CurrentGame->SetAnnounce( 0, string( ) ); + m_GHost->m_CurrentGame->SetAnnounce( 0, QString( ) ); } else { @@ -1068,7 +1068,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // e.g. "30 hello everyone" -> interval: "30", message: "hello everyone" uint32_t Interval; - string Message; + QString Message; stringstream SS; SS << Payload; SS >> Interval; @@ -1082,9 +1082,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { getline( SS, Message ); - string :: size_type Start = Message.find_first_not_of( " " ); + QString :: size_type Start = Message.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Message = Message.substr( Start ); QueueChatCommand( m_GHost->m_Language->AnnounceMessageEnabled( ), User, Whisper ); @@ -1122,7 +1122,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t MaximumGames; uint32_t AutoStartPlayers; - string GameName; + QString GameName; stringstream SS; SS << Payload; SS >> MaximumGames; @@ -1142,9 +1142,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { getline( SS, GameName ); - string :: size_type Start = GameName.find_first_not_of( " " ); + QString :: size_type Start = GameName.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) GameName = GameName.substr( Start ); QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); @@ -1198,7 +1198,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t AutoStartPlayers; double MinimumScore; double MaximumScore; - string GameName; + QString GameName; stringstream SS; SS << Payload; SS >> MaximumGames; @@ -1230,9 +1230,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { getline( SS, GameName ); - string :: size_type Start = GameName.find_first_not_of( " " ); + QString :: size_type Start = GameName.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) GameName = GameName.substr( Start ); QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); @@ -1369,7 +1369,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "countadmins" ) { if( IsRootAdmin( User ) ) - m_PairedAdminCounts.push_back( PairedAdminCount( Whisper ? User : string( ), m_GHost->m_DB->ThreadedAdminCount( m_Server ) ) ); + m_PairedAdminCounts.push_back( PairedAdminCount( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedAdminCount( m_Server ) ) ); else QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); } @@ -1379,7 +1379,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // if( Command == "countbans" ) - m_PairedBanCounts.push_back( PairedBanCount( Whisper ? User : string( ), m_GHost->m_DB->ThreadedBanCount( m_Server ) ) ); + m_PairedBanCounts.push_back( PairedBanCount( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedBanCount( m_Server ) ) ); // // !DBSTATUS @@ -1399,7 +1399,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( !IsAdmin( Payload ) ) QueueChatCommand( m_GHost->m_Language->UserIsNotAnAdmin( m_Server, Payload ), User, Whisper ); else - m_PairedAdminRemoves.push_back( PairedAdminRemove( Whisper ? User : string( ), m_GHost->m_DB->ThreadedAdminRemove( m_Server, Payload ) ) ); + m_PairedAdminRemoves.push_back( PairedAdminRemove( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedAdminRemove( m_Server, Payload ) ) ); } else QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); @@ -1411,7 +1411,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // if( ( Command == "delban" || Command == "unban" ) && !Payload.empty( ) ) - m_PairedBanRemoves.push_back( PairedBanRemove( Whisper ? User : string( ), m_GHost->m_DB->ThreadedBanRemove( Payload ) ) ); + m_PairedBanRemoves.push_back( PairedBanRemove( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedBanRemove( Payload ) ) ); // // !DISABLE @@ -1503,11 +1503,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != string :: npos || Payload.find( "\\" ) != string :: npos ) + if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) QueueChatCommand( m_GHost->m_Language->UnableToLoadReplaysOutside( ), User, Whisper ); else { - string File = m_GHost->m_ReplayPath + Payload + ".w3g"; + QString File = m_GHost->m_ReplayPath + Payload + ".w3g"; if( UTIL_FileExists( File ) ) { @@ -1607,7 +1607,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) while( !SS.eof( ) ) { - string HoldName; + QString HoldName; SS >> HoldName; if( SS.fail( ) ) @@ -1640,12 +1640,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); else { - string FoundMapConfigs; + QString FoundMapConfigs; try { path MapCFGPath( m_GHost->m_MapCFGPath ); - string Pattern = Payload; + QString Pattern = Payload; transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); if( !exists( MapCFGPath ) ) @@ -1661,12 +1661,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) for( directory_iterator i( MapCFGPath ); i != EndIterator; i++ ) { - string FileName = i->filename( ); - string Stem = i->path( ).stem( ); + QString FileName = i->filename( ); + QString Stem = i->path( ).stem( ); transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - if( !is_directory( i->status( ) ) && i->path( ).extension( ) == ".cfg" && FileName.find( Pattern ) != string :: npos ) + if( !is_directory( i->status( ) ) && i->path( ).extension( ) == ".cfg" && FileName.find( Pattern ) != QString :: npos ) { LastMatch = i->path( ); Matches++; @@ -1690,10 +1690,10 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->m_Language->NoMapConfigsFound( ), User, Whisper ); else if( Matches == 1 ) { - string File = LastMatch.filename( ); + QString File = LastMatch.filename( ); QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + File ), User, Whisper ); CConfig MapCFG; - MapCFG.Read( LastMatch.string( ) ); + MapCFG.Read( LastMatch.QString( ) ); m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); } else @@ -1716,12 +1716,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != string :: npos || Payload.find( "\\" ) != string :: npos ) + if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) QueueChatCommand( m_GHost->m_Language->UnableToLoadSaveGamesOutside( ), User, Whisper ); else { - string File = m_GHost->m_SaveGamePath + Payload + ".w3z"; - string FileNoPath = Payload + ".w3z"; + QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; + QString FileNoPath = Payload + ".w3z"; if( UTIL_FileExists( File ) ) { @@ -1751,12 +1751,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); else { - string FoundMaps; + QString FoundMaps; try { path MapPath( m_GHost->m_MapPath ); - string Pattern = Payload; + QString Pattern = Payload; transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); if( !exists( MapPath ) ) @@ -1772,12 +1772,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) for( directory_iterator i( MapPath ); i != EndIterator; i++ ) { - string FileName = i->filename( ); - string Stem = i->path( ).stem( ); + QString FileName = i->filename( ); + QString Stem = i->path( ).stem( ); transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - if( !is_directory( i->status( ) ) && FileName.find( Pattern ) != string :: npos ) + if( !is_directory( i->status( ) ) && FileName.find( Pattern ) != QString :: npos ) { LastMatch = i->path( ); Matches++; @@ -1801,7 +1801,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->m_Language->NoMapsFound( ), User, Whisper ); else if( Matches == 1 ) { - string File = LastMatch.filename( ); + QString File = LastMatch.filename( ); QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( File ), User, Whisper ); // hackhack: create a config file in memory with the required information to load the map @@ -1882,11 +1882,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" - string Owner; - string GameName; - string :: size_type GameNameStart = Payload.find( " " ); + QString Owner; + QString GameName; + QString :: size_type GameNameStart = Payload.find( " " ); - if( GameNameStart != string :: npos ) + if( GameNameStart != QString :: npos ) { Owner = Payload.substr( 0, GameNameStart ); GameName = Payload.substr( GameNameStart + 1 ); @@ -1910,11 +1910,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" - string Owner; - string GameName; - string :: size_type GameNameStart = Payload.find( " " ); + QString Owner; + QString GameName; + QString :: size_type GameNameStart = Payload.find( " " ); - if( GameNameStart != string :: npos ) + if( GameNameStart != QString :: npos ) { Owner = Payload.substr( 0, GameNameStart ); GameName = Payload.substr( GameNameStart + 1 ); @@ -1956,7 +1956,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // e.g. "3 hello everyone" -> game number: "3", message: "hello everyone" uint32_t GameNumber; - string Message; + QString Message; stringstream SS; SS << Payload; SS >> GameNumber; @@ -1970,9 +1970,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { getline( SS, Message ); - string :: size_type Start = Message.find_first_not_of( " " ); + QString :: size_type Start = Message.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Message = Message.substr( Start ); if( GameNumber - 1 < m_GHost->m_Games.size( ) ) @@ -2131,7 +2131,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "stats" ) { - string StatsUser = User; + QString StatsUser = User; if( !Payload.empty( ) ) StatsUser = Payload; @@ -2139,7 +2139,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // check for potential abuse if( !StatsUser.empty( ) && StatsUser.size( ) < 16 && StatsUser[0] != '/' ) - m_PairedGPSChecks.push_back( PairedGPSCheck( Whisper ? User : string( ), m_GHost->m_DB->ThreadedGamePlayerSummaryCheck( StatsUser ) ) ); + m_PairedGPSChecks.push_back( PairedGPSCheck( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedGamePlayerSummaryCheck( StatsUser ) ) ); } // @@ -2148,7 +2148,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "statsdota" ) { - string StatsUser = User; + QString StatsUser = User; if( !Payload.empty( ) ) StatsUser = Payload; @@ -2156,7 +2156,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // check for potential abuse if( !StatsUser.empty( ) && StatsUser.size( ) < 16 && StatsUser[0] != '/' ) - m_PairedDPSChecks.push_back( PairedDPSCheck( Whisper ? User : string( ), m_GHost->m_DB->ThreadedDotAPlayerSummaryCheck( StatsUser ) ) ); + m_PairedDPSChecks.push_back( PairedDPSCheck( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedDotAPlayerSummaryCheck( StatsUser ) ) ); } // @@ -2187,10 +2187,10 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the first word which we hope is the username // this is not necessarily true though since info messages also include channel MOTD's and such - string UserName; - string :: size_type Split = Message.find( " " ); + QString UserName; + QString :: size_type Split = Message.find( " " ); - if( Split != string :: npos ) + if( Split != QString :: npos ) UserName = Message.substr( 0, Split ); else UserName = Message.substr( 0 ); @@ -2201,26 +2201,26 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( m_GHost->m_CurrentGame && m_GHost->m_CurrentGame->GetPlayerFromName( UserName, true ) ) { - if( Message.find( "is away" ) != string :: npos ) + if( Message.find( "is away" ) != QString :: npos ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsAway( UserName ) ); - else if( Message.find( "is unavailable" ) != string :: npos ) + else if( Message.find( "is unavailable" ) != QString :: npos ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsUnavailable( UserName ) ); - else if( Message.find( "is refusing messages" ) != string :: npos ) + else if( Message.find( "is refusing messages" ) != QString :: npos ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsRefusingMessages( UserName ) ); - else if( Message.find( "is using Warcraft III The Frozen Throne in the channel" ) != string :: npos ) + else if( Message.find( "is using Warcraft III The Frozen Throne in the channel" ) != QString :: npos ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsNotInGame( UserName ) ); - else if( Message.find( "is using Warcraft III The Frozen Throne in channel" ) != string :: npos ) + else if( Message.find( "is using Warcraft III The Frozen Throne in channel" ) != QString :: npos ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsNotInGame( UserName ) ); - else if( Message.find( "is using Warcraft III The Frozen Throne in a private channel" ) != string :: npos ) + else if( Message.find( "is using Warcraft III The Frozen Throne in a private channel" ) != QString :: npos ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsInPrivateChannel( UserName ) ); - if( Message.find( "is using Warcraft III The Frozen Throne in game" ) != string :: npos || Message.find( "is using Warcraft III Frozen Throne and is currently in game" ) != string :: npos ) + if( Message.find( "is using Warcraft III The Frozen Throne in game" ) != QString :: npos || Message.find( "is using Warcraft III Frozen Throne and is currently in game" ) != QString :: npos ) { // check both the current game name and the last game name against the /whois response // this is because when the game is rehosted, players who joined recently will be in the previous game according to battle.net // note: if the game is rehosted more than once it is possible (but unlikely) for a false positive because only two game names are checked - if( Message.find( m_GHost->m_CurrentGame->GetGameName( ) ) != string :: npos || Message.find( m_GHost->m_CurrentGame->GetLastGameName( ) ) != string :: npos ) + if( Message.find( m_GHost->m_CurrentGame->GetGameName( ) ) != QString :: npos || Message.find( m_GHost->m_CurrentGame->GetLastGameName( ) ) != QString :: npos ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, UserName, false ); else m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsInAnotherGame( UserName ) ); @@ -2236,7 +2236,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } } -void CBNET :: SendJoinChannel( string channel ) +void CBNET :: SendJoinChannel( QString channel ) { if( m_LoggedIn && m_InChat ) m_Socket->PutBytes( m_Protocol->SEND_SID_JOINCHANNEL( channel ) ); @@ -2260,7 +2260,7 @@ void CBNET :: QueueEnterChat( ) m_OutPackets.push( m_Protocol->SEND_SID_ENTERCHAT( ) ); } -void CBNET :: QueueChatCommand( string chatCommand ) +void CBNET :: QueueChatCommand( QString chatCommand ) { if( chatCommand.empty( ) ) return; @@ -2283,7 +2283,7 @@ void CBNET :: QueueChatCommand( string chatCommand ) } } -void CBNET :: QueueChatCommand( string chatCommand, string user, bool whisper ) +void CBNET :: QueueChatCommand( QString chatCommand, QString user, bool whisper ) { if( chatCommand.empty( ) ) return; @@ -2296,7 +2296,7 @@ void CBNET :: QueueChatCommand( string chatCommand, string user, bool whisper ) QueueChatCommand( chatCommand ); } -void CBNET :: QueueGameCreate( unsigned char state, string gameName, string hostName, CMap *map, CSaveGame *savegame, uint32_t hostCounter ) +void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *savegame, uint32_t hostCounter ) { if( m_LoggedIn && map ) { @@ -2311,12 +2311,12 @@ void CBNET :: QueueGameCreate( unsigned char state, string gameName, string host } } -void CBNET :: QueueGameRefresh( unsigned char state, string gameName, string hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ) +void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ) { if( hostName.empty( ) ) { BYTEARRAY UniqueName = m_Protocol->GetUniqueName( ); - hostName = string( UniqueName.begin( ), UniqueName.end( ) ); + hostName = QString( UniqueName.begin( ), UniqueName.end( ) ); } if( m_LoggedIn && map ) @@ -2408,7 +2408,7 @@ void CBNET :: UnqueuePackets( unsigned char type ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] unqueued " + UTIL_ToString( Unqueued ) + " packets of type " + UTIL_ToString( type ) ); } -void CBNET :: UnqueueChatCommand( string chatCommand ) +void CBNET :: UnqueueChatCommand( QString chatCommand ) { // hackhack: this is ugly code // generate the packet that would be sent for this chat command @@ -2442,11 +2442,11 @@ void CBNET :: UnqueueGameRefreshes( ) UnqueuePackets( CBNETProtocol :: SID_STARTADVEX3 ); } -bool CBNET :: IsAdmin( string name ) +bool CBNET :: IsAdmin( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) + for( vector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) { if( *i == name ) return true; @@ -2455,7 +2455,7 @@ bool CBNET :: IsAdmin( string name ) return false; } -bool CBNET :: IsRootAdmin( string name ) +bool CBNET :: IsRootAdmin( QString name ) { // m_RootAdmin was already transformed to lower case in the constructor @@ -2466,7 +2466,7 @@ bool CBNET :: IsRootAdmin( string name ) // however, it's hardly worth optimizing at this point since the code's already written stringstream SS; - string s; + QString s; SS << m_RootAdmin; while( !SS.eof( ) ) @@ -2480,7 +2480,7 @@ bool CBNET :: IsRootAdmin( string name ) return false; } -CDBBan *CBNET :: IsBannedName( string name ) +CDBBan *CBNET :: IsBannedName( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); @@ -2495,7 +2495,7 @@ CDBBan *CBNET :: IsBannedName( string name ) return NULL; } -CDBBan *CBNET :: IsBannedIP( string ip ) +CDBBan *CBNET :: IsBannedIP( QString ip ) { // todotodo: optimize this - maybe use a map? @@ -2508,23 +2508,23 @@ CDBBan *CBNET :: IsBannedIP( string ip ) return NULL; } -void CBNET :: AddAdmin( string name ) +void CBNET :: AddAdmin( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); m_Admins.push_back( name ); } -void CBNET :: AddBan( string name, string ip, string gamename, string admin, string reason ) +void CBNET :: AddBan( QString name, QString ip, QString gamename, QString admin, QString reason ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); m_Bans.push_back( new CDBBan( m_Server, name, ip, "N/A", gamename, admin, reason ) ); } -void CBNET :: RemoveAdmin( string name ) +void CBNET :: RemoveAdmin( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) + for( vector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) { if( *i == name ) i = m_Admins.erase( i ); @@ -2533,7 +2533,7 @@ void CBNET :: RemoveAdmin( string name ) } } -void CBNET :: RemoveBan( string name ) +void CBNET :: RemoveBan( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 3176405..0b4d9fd 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -60,7 +60,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data ) // 10 bytes -> ??? // 2 bytes -> Port // 4 bytes -> IP - // null term string -> GameName + // null term QString -> GameName // 2 bytes -> ??? // 8 bytes -> HostCounter @@ -83,7 +83,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data ) HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 33, true ) ); return new CIncomingGameHost( IP, UTIL_ByteArrayToUInt16( Port, false ), - string( GameName.begin( ), GameName.end( ) ), + QString( GameName.begin( ), GameName.end( ) ), HostCounter ); } } @@ -99,7 +99,7 @@ bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( BYTEARRAY data ) // 2 bytes -> Header // 2 bytes -> Length - // null terminated string -> UniqueName + // null terminated QString -> UniqueName if( ValidateLength( data ) && data.size( ) >= 5 ) { @@ -121,8 +121,8 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data ) // 4 bytes -> ??? // 4 bytes -> Ping // 12 bytes -> ??? - // null terminated string -> User - // null terminated string -> Message + // null terminated QString -> User + // null terminated QString -> Message if( ValidateLength( data ) && data.size( ) >= 29 ) { @@ -150,8 +150,8 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data ) case CBNETProtocol :: EID_EMOTE: return new CIncomingChatEvent( (CBNETProtocol :: IncomingChatEvent)UTIL_ByteArrayToUInt32( EventID, false ), UTIL_ByteArrayToUInt32( Ping, false ), - string( User.begin( ), User.end( ) ), - string( Message.begin( ), Message.end( ) ) ); + QString( User.begin( ), User.end( ) ), + QString( Message.begin( ), Message.end( ) ) ); } } @@ -236,8 +236,8 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( BYTEARRAY data ) // 4 bytes -> ServerToken // 4 bytes -> ??? // 8 bytes -> MPQFileTime - // null terminated string -> IX86VerFileName - // null terminated string -> ValueStringFormula + // null terminated QString -> IX86VerFileName + // null terminated QString -> ValueStringFormula if( ValidateLength( data ) && data.size( ) >= 25 ) { @@ -260,7 +260,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( BYTEARRAY data ) // 2 bytes -> Header // 2 bytes -> Length // 4 bytes -> KeyState - // null terminated string -> KeyStateDescription + // null terminated QString -> KeyStateDescription if( ValidateLength( data ) && data.size( ) >= 9 ) { @@ -345,11 +345,11 @@ vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRA // 2 bytes -> Length // 1 byte -> Total // for( 1 .. Total ) - // null term string -> Account + // null term QString -> Account // 1 byte -> Status // 1 byte -> Area // 4 bytes -> ??? - // null term string -> Location + // null term QString -> Location vector Friends; @@ -376,10 +376,10 @@ vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRA i += 6; BYTEARRAY Location = UTIL_ExtractCString( data, i ); i += Location.size( ) + 1; - Friends.push_back( new CIncomingFriendList( string( Account.begin( ), Account.end( ) ), + Friends.push_back( new CIncomingFriendList( QString( Account.begin( ), Account.end( ) ), Status, Area, - string( Location.begin( ), Location.end( ) ) ) ); + QString( Location.begin( ), Location.end( ) ) ) ); } } @@ -396,10 +396,10 @@ vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARR // 4 bytes -> ??? // 1 byte -> Total // for( 1 .. Total ) - // null term string -> Name + // null term QString -> Name // 1 byte -> Rank // 1 byte -> Status - // null term string -> Location + // null term QString -> Location vector ClanList; @@ -425,11 +425,11 @@ vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARR unsigned char Status = data[i + 1]; i += 2; - // in the original VB source the location string is read but discarded, so that's what I do here + // in the original VB source the location QString is read but discarded, so that's what I do here BYTEARRAY Location = UTIL_ExtractCString( data, i ); i += Location.size( ) + 1; - ClanList.push_back( new CIncomingClanList( string( Name.begin( ), Name.end( ) ), + ClanList.push_back( new CIncomingClanList( QString( Name.begin( ), Name.end( ) ), Rank, Status ) ); } @@ -445,10 +445,10 @@ CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRA // 2 bytes -> Header // 2 bytes -> Length - // null terminated string -> Name + // null terminated QString -> Name // 1 byte -> Rank // 1 byte -> Status - // null terminated string -> Location + // null terminated QString -> Location if( ValidateLength( data ) && data.size( ) >= 5 ) { @@ -459,10 +459,10 @@ CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRA unsigned char Rank = data[Name.size( ) + 5]; unsigned char Status = data[Name.size( ) + 6]; - // in the original VB source the location string is read but discarded, so that's what I do here + // in the original VB source the location QString is read but discarded, so that's what I do here BYTEARRAY Location = UTIL_ExtractCString( data, Name.size( ) + 7 ); - return new CIncomingClanList( string( Name.begin( ), Name.end( ) ), + return new CIncomingClanList( QString( Name.begin( ), Name.end( ) ), Rank, Status ); } @@ -510,7 +510,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_STOPADV( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_GETADVLISTEX( string gameName ) +BYTEARRAY CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) { unsigned char MapFilter1[] = { 255, 3, 0, 0 }; unsigned char MapFilter2[] = { 255, 3, 0, 0 }; @@ -550,7 +550,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_ENTERCHAT( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_JOINCHANNEL( string channel ) +BYTEARRAY CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) { unsigned char NoCreateJoin[] = { 2, 0, 0, 0 }; unsigned char FirstJoin[] = { 1, 0, 0, 0 }; @@ -573,7 +573,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_JOINCHANNEL( string channel ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_CHATCOMMAND( string command ) +BYTEARRAY CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) { BYTEARRAY packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant @@ -606,7 +606,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_CHECKAD( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, BYTEARRAY mapGameType, BYTEARRAY mapFlags, BYTEARRAY mapWidth, BYTEARRAY mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, BYTEARRAY mapCRC, BYTEARRAY mapSHA1, uint32_t hostCounter ) +BYTEARRAY CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, BYTEARRAY mapGameType, BYTEARRAY mapFlags, BYTEARRAY mapWidth, BYTEARRAY mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, BYTEARRAY mapCRC, BYTEARRAY mapSHA1, uint32_t hostCounter ) { // todotodo: sort out how GameType works, the documentation is horrendous @@ -637,16 +637,16 @@ Observers: (mask 0x00700000) cant be combined unsigned char Unknown[] = { 255, 3, 0, 0 }; unsigned char CustomGame[] = { 0, 0, 0, 0 }; - string HostCounterString = UTIL_ToHexString( hostCounter ); + QString HostCounterString = UTIL_ToHexString( hostCounter ); if( HostCounterString.size( ) < 8 ) HostCounterString.insert( 0, 8 - HostCounterString.size( ), '0' ); - HostCounterString = string( HostCounterString.rbegin( ), HostCounterString.rend( ) ); + HostCounterString = QString( HostCounterString.rbegin( ), HostCounterString.rend( ) ); BYTEARRAY packet; - // make the stat string + // make the stat QString BYTEARRAY StatString; UTIL_AppendByteArrayFast( StatString, mapFlags ); @@ -681,7 +681,7 @@ Observers: (mask 0x00700000) cant be combined packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate UTIL_AppendByteArrayFast( packet, HostCounterString, false ); // Host Counter UTIL_AppendByteArrayFast( packet, StatString ); // Stat String - packet.push_back( 0 ); // Stat String null terminator (the stat string is encoded to remove all even numbers i.e. zeros) + packet.push_back( 0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) AssignLength( packet ); } else @@ -692,7 +692,7 @@ Observers: (mask 0x00700000) cant be combined return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_NOTIFYJOIN( string gameName ) +BYTEARRAY CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) { unsigned char ProductID[] = { 0, 0, 0, 0 }; unsigned char ProductVersion[] = { 14, 0, 0, 0 }; // Warcraft III is 14 @@ -733,7 +733,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_PING( BYTEARRAY pingValue ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_LOGONRESPONSE( BYTEARRAY clientToken, BYTEARRAY serverToken, BYTEARRAY passwordHash, string accountName ) +BYTEARRAY CBNETProtocol :: SEND_SID_LOGONRESPONSE( BYTEARRAY clientToken, BYTEARRAY serverToken, BYTEARRAY passwordHash, QString accountName ) { // todotodo: check that the passed BYTEARRAY sizes are correct (don't know what they should be right now so I can't do this today) @@ -766,7 +766,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, string countryAbbrev, string country ) +BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, QString countryAbbrev, QString country ) { unsigned char ProtocolID[] = { 0, 0, 0, 0 }; unsigned char PlatformID[] = { 54, 56, 88, 73 }; // "IX86" @@ -804,7 +804,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, BYTEARRAY exeVersion, BYTEARRAY exeVersionHash, BYTEARRAY keyInfoROC, BYTEARRAY keyInfoTFT, string exeInfo, string keyOwnerName ) +BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, BYTEARRAY exeVersion, BYTEARRAY exeVersionHash, BYTEARRAY keyInfoROC, BYTEARRAY keyInfoTFT, QString exeInfo, QString keyOwnerName ) { uint32_t NumKeys = 0; @@ -843,7 +843,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( BYTEARRAY clientPublicKey, string accountName ) +BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( BYTEARRAY clientPublicKey, QString accountName ) { BYTEARRAY packet; @@ -974,7 +974,7 @@ bool CBNETProtocol :: ValidateLength( BYTEARRAY &content ) // CIncomingGameHost // -CIncomingGameHost :: CIncomingGameHost( BYTEARRAY &nIP, uint16_t nPort, string nGameName, BYTEARRAY &nHostCounter ) +CIncomingGameHost :: CIncomingGameHost( BYTEARRAY &nIP, uint16_t nPort, QString nGameName, BYTEARRAY &nHostCounter ) { m_IP = nIP; m_Port = nPort; @@ -987,9 +987,9 @@ CIncomingGameHost :: ~CIncomingGameHost( ) } -string CIncomingGameHost :: GetIPString( ) +QString CIncomingGameHost :: GetIPString( ) { - string Result; + QString Result; if( m_IP.size( ) >= 4 ) { @@ -1009,7 +1009,7 @@ string CIncomingGameHost :: GetIPString( ) // CIncomingChatEvent // -CIncomingChatEvent :: CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, uint32_t nPing, string nUser, string nMessage ) +CIncomingChatEvent :: CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, uint32_t nPing, QString nUser, QString nMessage ) { m_ChatEvent = nChatEvent; m_Ping = nPing; @@ -1026,7 +1026,7 @@ CIncomingChatEvent :: ~CIncomingChatEvent( ) // CIncomingFriendList // -CIncomingFriendList :: CIncomingFriendList( string nAccount, unsigned char nStatus, unsigned char nArea, string nLocation ) +CIncomingFriendList :: CIncomingFriendList( QString nAccount, unsigned char nStatus, unsigned char nArea, QString nLocation ) { m_Account = nAccount; m_Status = nStatus; @@ -1039,9 +1039,9 @@ CIncomingFriendList :: ~CIncomingFriendList( ) } -string CIncomingFriendList :: GetDescription( ) +QString CIncomingFriendList :: GetDescription( ) { - string Description; + QString Description; Description += GetAccount( ) + "\n"; Description += ExtractStatus( GetStatus( ) ) + "\n"; Description += ExtractArea( GetArea( ) ) + "\n"; @@ -1049,9 +1049,9 @@ string CIncomingFriendList :: GetDescription( ) return Description; } -string CIncomingFriendList :: ExtractStatus( unsigned char status ) +QString CIncomingFriendList :: ExtractStatus( unsigned char status ) { - string Result; + QString Result; if( status & 1 ) Result += ""; @@ -1068,7 +1068,7 @@ string CIncomingFriendList :: ExtractStatus( unsigned char status ) return Result; } -string CIncomingFriendList :: ExtractArea( unsigned char area ) +QString CIncomingFriendList :: ExtractArea( unsigned char area ) { switch( area ) { @@ -1083,9 +1083,9 @@ string CIncomingFriendList :: ExtractArea( unsigned char area ) return ""; } -string CIncomingFriendList :: ExtractLocation( string location ) +QString CIncomingFriendList :: ExtractLocation( QString location ) { - string Result; + QString Result; if( location.substr( 0, 4 ) == "PX3W" ) Result = location.substr( 4 ); @@ -1100,7 +1100,7 @@ string CIncomingFriendList :: ExtractLocation( string location ) // CIncomingClanList // -CIncomingClanList :: CIncomingClanList( string nName, unsigned char nRank, unsigned char nStatus ) +CIncomingClanList :: CIncomingClanList( QString nName, unsigned char nRank, unsigned char nStatus ) { m_Name = nName; m_Rank = nRank; @@ -1112,7 +1112,7 @@ CIncomingClanList :: ~CIncomingClanList( ) } -string CIncomingClanList :: GetRank( ) +QString CIncomingClanList :: GetRank( ) { switch( m_Rank ) { @@ -1126,7 +1126,7 @@ string CIncomingClanList :: GetRank( ) return "Rank Unknown"; } -string CIncomingClanList :: GetStatus( ) +QString CIncomingClanList :: GetStatus( ) { if( m_Status == 0 ) return "Offline"; @@ -1134,9 +1134,9 @@ string CIncomingClanList :: GetStatus( ) return "Online"; } -string CIncomingClanList :: GetDescription( ) +QString CIncomingClanList :: GetDescription( ) { - string Description; + QString Description; Description += GetName( ) + "\n"; Description += GetStatus( ) + "\n"; Description += GetRank( ) + "\n\n"; diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index bce9bee..d07a05f 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -29,7 +29,7 @@ // CBNLSClient // -CBNLSClient :: CBNLSClient( string nServer, uint16_t nPort, uint32_t nWardenCookie ) +CBNLSClient :: CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCookie ) { m_Socket = new CTCPClient( ); m_Protocol = new CBNLSProtocol( ); @@ -126,7 +126,7 @@ bool CBNLSClient :: Update( void *fd, void *send_fd ) if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && !m_WasConnected ) { CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connecting to server [" + m_Server + "] on port " + UTIL_ToString( m_Port ) ); - m_Socket->Connect( string( ), m_Server, m_Port ); + m_Socket->Connect( QString( ), m_Server, m_Port ); return false; } @@ -135,7 +135,7 @@ bool CBNLSClient :: Update( void *fd, void *send_fd ) void CBNLSClient :: ExtractPackets( ) { - string *RecvBuffer = m_Socket->GetBytes( ); + QString *RecvBuffer = m_Socket->GetBytes( ); BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); while( Bytes.size( ) >= 3 ) diff --git a/ghost/config.cpp b/ghost/config.cpp index 2a1276c..84729e4 100644 --- a/ghost/config.cpp +++ b/ghost/config.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -37,7 +37,7 @@ CConfig :: ~CConfig( ) } -void CConfig :: Read( string file ) +void CConfig :: Read( QString file ) { ifstream in; in.open( file.c_str( ) ); @@ -47,7 +47,7 @@ void CConfig :: Read( string file ) else { CONSOLE_Print( "[CONFIG] loading file [" + file + "]" ); - string Line; + QString Line; while( !in.eof( ) ) { @@ -63,17 +63,17 @@ void CConfig :: Read( string file ) Line.erase( remove( Line.begin( ), Line.end( ), '\r' ), Line.end( ) ); Line.erase( remove( Line.begin( ), Line.end( ), '\n' ), Line.end( ) ); - string :: size_type Split = Line.find( "=" ); + QString :: size_type Split = Line.find( "=" ); - if( Split == string :: npos ) + if( Split == QString :: npos ) continue; - string :: size_type KeyStart = Line.find_first_not_of( " " ); - string :: size_type KeyEnd = Line.find( " ", KeyStart ); - string :: size_type ValueStart = Line.find_first_not_of( " ", Split + 1 ); - string :: size_type ValueEnd = Line.size( ); + QString :: size_type KeyStart = Line.find_first_not_of( " " ); + QString :: size_type KeyEnd = Line.find( " ", KeyStart ); + QString :: size_type ValueStart = Line.find_first_not_of( " ", Split + 1 ); + QString :: size_type ValueEnd = Line.size( ); - if( ValueStart != string :: npos ) + if( ValueStart != QString :: npos ) m_CFG[Line.substr( KeyStart, KeyEnd - KeyStart )] = Line.substr( ValueStart, ValueEnd - ValueStart ); } @@ -81,12 +81,12 @@ void CConfig :: Read( string file ) } } -bool CConfig :: Exists( string key ) +bool CConfig :: Exists( QString key ) { return m_CFG.find( key ) != m_CFG.end( ); } -int CConfig :: GetInt( string key, int x ) +int CConfig :: GetInt( QString key, int x ) { if( m_CFG.find( key ) == m_CFG.end( ) ) return x; @@ -94,7 +94,7 @@ int CConfig :: GetInt( string key, int x ) return atoi( m_CFG[key].c_str( ) ); } -string CConfig :: GetString( string key, string x ) +QString CConfig :: GetString( QString key, QString x ) { if( m_CFG.find( key ) == m_CFG.end( ) ) return x; @@ -102,7 +102,7 @@ string CConfig :: GetString( string key, string x ) return m_CFG[key]; } -void CConfig :: Set( string key, string x ) +void CConfig :: Set( QString key, QString x ) { m_CFG[key] = x; } diff --git a/ghost/csvparser.cpp b/ghost/csvparser.cpp index 47a2be0..c174bff 100644 --- a/ghost/csvparser.cpp +++ b/ghost/csvparser.cpp @@ -7,7 +7,7 @@ modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. +this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the @@ -45,10 +45,10 @@ CSVParser::CSVParser() void CSVParser::SkipSpaces(void) { while (m_nPos < m_sData.length() && m_sData[m_nPos] == ' ') - m_nPos++; + m_nPos++; } -const CSVParser & CSVParser::operator <<(const string & sIn) +const CSVParser & CSVParser::operator <<(const QString & sIn) { this->m_sData = sIn; this->m_nPos = 0; @@ -64,10 +64,10 @@ const CSVParser & CSVParser::operator <<(const char *sIn) CSVParser & CSVParser::operator >>(int & nOut) { - string sTmp = ""; + QString sTmp = ""; SkipSpaces(); while (m_nPos < m_sData.length() && m_sData[m_nPos] != ',') - sTmp += m_sData[m_nPos++]; + sTmp += m_sData[m_nPos++]; m_nPos++; // skip past comma nOut = atoi(sTmp.c_str()); @@ -76,17 +76,17 @@ CSVParser & CSVParser::operator >>(int & nOut) CSVParser & CSVParser::operator >>(double & nOut) { - string sTmp = ""; + QString sTmp = ""; SkipSpaces(); while (m_nPos < m_sData.length() && m_sData[m_nPos] != ',') - sTmp += m_sData[m_nPos++]; + sTmp += m_sData[m_nPos++]; m_nPos++; // skip past comma nOut = atof(sTmp.c_str()); return *this; } -CSVParser & CSVParser::operator >>(string & sOut) +CSVParser & CSVParser::operator >>(QString & sOut) { bool bQuotes = false; sOut = ""; @@ -94,29 +94,29 @@ CSVParser & CSVParser::operator >>(string & sOut) // Jump past first " if necessary if (m_nPos < m_sData.length() && m_sData[m_nPos] == '"') { - bQuotes = true; - m_nPos++; + bQuotes = true; + m_nPos++; } - + while (m_nPos < m_sData.length()) { - if (!bQuotes && m_sData[m_nPos] == ',') - break; - if (bQuotes && m_sData[m_nPos] == '"') { - if (m_nPos + 1 >= m_sData.length() - 1) - break; - if (m_sData[m_nPos+1] == ',') - break; - } - sOut += m_sData[m_nPos++]; + if (!bQuotes && m_sData[m_nPos] == ',') + break; + if (bQuotes && m_sData[m_nPos] == '"') { + if (m_nPos + 1 >= m_sData.length() - 1) + break; + if (m_sData[m_nPos+1] == ',') + break; + } + sOut += m_sData[m_nPos++]; } // Jump past last " if necessary if (bQuotes && m_nPos < m_sData.length() && m_sData[m_nPos] == '"') - m_nPos++; + m_nPos++; // Jump past , if necessary if (m_nPos < m_sData.length() && m_sData[m_nPos] == ',') - m_nPos++; + m_nPos++; return *this; } diff --git a/ghost/game.cpp b/ghost/game.cpp index f0c500e..1635204 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -37,7 +37,7 @@ #include "statsw3mmd.h" #include -#include +#include #include // @@ -66,10 +66,10 @@ class CGamePlayerSortDescByPing // CGame // -CGame :: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nOwnerName, string nCreatorName, string nCreatorServer ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, nOwnerName, nCreatorName, nCreatorServer ) +CGame :: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, nOwnerName, nCreatorName, nCreatorServer ) { m_DBBanLast = NULL; - m_DBGame = new CDBGame( 0, string( ), m_Map->GetMapPath( ), string( ), string( ), string( ), 0 ); + m_DBGame = new CDBGame( 0, QString( ), m_Map->GetMapPath( ), QString( ), QString( ), QString( ), 0 ); if( m_Map->GetMapType( ) == "w3mmd" ) m_Stats = new CStatsW3MMD( this, m_Map->GetMapStatsW3MMDCategory( ) ); @@ -234,7 +234,7 @@ bool CGame :: Update( void *fd, void *send_fd ) if( DotAPlayerSummary ) { - string Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), + QString Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), UTIL_ToString( DotAPlayerSummary->GetTotalGames( ) ), UTIL_ToString( DotAPlayerSummary->GetTotalWins( ) ), UTIL_ToString( DotAPlayerSummary->GetTotalLosses( ) ), @@ -341,15 +341,15 @@ void CGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *action ) } } -bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string payload ) +bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ) { bool HideCommand = CBaseGame :: EventPlayerBotCommand( player, command, payload ); // todotodo: don't be lazy - string User = player->GetName( ); - string Command = command; - string Payload = payload; + QString User = player->GetName( ); + QString Command = command; + QString Payload = payload; bool AdminCheck = false; @@ -406,8 +406,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string // extract the victim and the reason // e.g. "Varlock leaver after dying" -> victim: "Varlock", reason: "leaver after dying" - string Victim; - string Reason; + QString Victim; + QString Reason; stringstream SS; SS << Payload; SS >> Victim; @@ -415,28 +415,28 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string if( !SS.eof( ) ) { getline( SS, Reason ); - string :: size_type Start = Reason.find_first_not_of( " " ); + QString :: size_type Start = Reason.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Reason = Reason.substr( Start ); } if( m_GameLoaded ) { - string VictimLower = Victim; + QString VictimLower = Victim; transform( VictimLower.begin( ), VictimLower.end( ), VictimLower.begin( ), (int(*)(int))tolower ); uint32_t Matches = 0; CDBBan *LastMatch = NULL; - // try to match each player with the passed string (e.g. "Varlock" would be matched with "lock") + // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") // we use the m_DBBans vector for this in case the player already left and thus isn't in the m_Players vector anymore for( vector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) { - string TestName = (*i)->GetName( ); + QString TestName = (*i)->GetName( ); transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); - if( TestName.find( VictimLower ) != string :: npos ) + if( TestName.find( VictimLower ) != QString :: npos ) { Matches++; LastMatch = *i; @@ -481,7 +481,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string if( Payload.empty( ) || Payload == "off" ) { SendAllChat( m_GHost->m_Language->AnnounceMessageDisabled( ) ); - SetAnnounce( 0, string( ) ); + SetAnnounce( 0, QString( ) ); } else { @@ -489,7 +489,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string // e.g. "30 hello everyone" -> interval: "30", message: "hello everyone" uint32_t Interval; - string Message; + QString Message; stringstream SS; SS << Payload; SS >> Interval; @@ -503,9 +503,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string else { getline( SS, Message ); - string :: size_type Start = Message.find_first_not_of( " " ); + QString :: size_type Start = Message.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Message = Message.substr( Start ); SendAllChat( m_GHost->m_Language->AnnounceMessageEnabled( ) ); @@ -616,7 +616,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string if( Command == "checkban" && !Payload.empty( ) && !m_GHost->m_BNETs.empty( ) ) { for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) - m_PairedBanChecks.push_back( PairedBanCheck( User, m_GHost->m_DB->ThreadedBanCheck( (*i)->GetServer( ), Payload, string( ) ) ) ); + m_PairedBanChecks.push_back( PairedBanCheck( User, m_GHost->m_DB->ThreadedBanCheck( (*i)->GetServer( ), Payload, QString( ) ) ) ); } // @@ -786,7 +786,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string // e.g. "1 human" -> slot: "1", race: "human" uint32_t Slot; - string Race; + QString Race; stringstream SS; SS << Payload; SS >> Slot; @@ -800,9 +800,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string else { getline( SS, Race ); - string :: size_type Start = Race.find_first_not_of( " " ); + QString :: size_type Start = Race.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Race = Race.substr( Start ); transform( Race.begin( ), Race.end( ), Race.begin( ), (int(*)(int))tolower ); @@ -989,7 +989,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string if( Command == "from" ) { - string Froms; + QString Froms; for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -1026,9 +1026,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string { if( Payload.size( ) <= m_Slots.size( ) ) { - string HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; + QString HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; - if( Payload.find_first_not_of( HCLChars ) == string :: npos ) + if( Payload.find_first_not_of( HCLChars ) == QString :: npos ) { m_HCLCommandString = Payload; SendAllChat( m_GHost->m_Language->SettingHCL( m_HCLCommandString ) ); @@ -1056,7 +1056,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string while( !SS.eof( ) ) { - string HoldName; + QString HoldName; SS >> HoldName; if( SS.fail( ) ) @@ -1260,7 +1260,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string vector SortedPlayers = m_Players; sort( SortedPlayers.begin( ), SortedPlayers.end( ), CGamePlayerSortDescByPing( ) ); - string Pings; + QString Pings; for( vector :: iterator i = SortedPlayers.begin( ); i != SortedPlayers.end( ); i++ ) { @@ -1331,7 +1331,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string // we need to send the game creation message now because private games are not refreshed - (*i)->QueueGameCreate( m_GameState, m_GameName, string( ), m_Map, NULL, m_HostCounter ); + (*i)->QueueGameCreate( m_GameState, m_GameName, QString( ), m_Map, NULL, m_HostCounter ); if( (*i)->GetPasswordHashType( ) != "pvpgn" ) (*i)->QueueEnterChat( ); @@ -1412,7 +1412,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string // extract the ip and the port // e.g. "1.2.3.4 6112" -> ip: "1.2.3.4", port: "6112" - string IP; + QString IP; uint32_t Port = 6112; stringstream SS; SS << Payload; @@ -1622,11 +1622,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string // extract the name and the message // e.g. "Varlock hello there!" -> name: "Varlock", message: "hello there!" - string Name; - string Message; - string :: size_type MessageStart = Payload.find( " " ); + QString Name; + QString Message; + QString :: size_type MessageStart = Payload.find( " " ); - if( MessageStart != string :: npos ) + if( MessageStart != QString :: npos ) { Name = Payload.substr( 0, MessageStart ); Message = Payload.substr( MessageStart + 1 ); @@ -1669,13 +1669,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string if( Command == "stats" && GetTime( ) - player->GetStatsSentTime( ) >= 5 ) { - string StatsUser = User; + QString StatsUser = User; if( !Payload.empty( ) ) StatsUser = Payload; if( player->GetSpoofed( ) && ( AdminCheck || RootAdminCheck || IsOwner( User ) ) ) - m_PairedGPSChecks.push_back( PairedGPSCheck( string( ), m_GHost->m_DB->ThreadedGamePlayerSummaryCheck( StatsUser ) ) ); + m_PairedGPSChecks.push_back( PairedGPSCheck( QString( ), m_GHost->m_DB->ThreadedGamePlayerSummaryCheck( StatsUser ) ) ); else m_PairedGPSChecks.push_back( PairedGPSCheck( User, m_GHost->m_DB->ThreadedGamePlayerSummaryCheck( StatsUser ) ) ); @@ -1688,13 +1688,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string if( Command == "statsdota" && GetTime( ) - player->GetStatsDotASentTime( ) >= 5 ) { - string StatsUser = User; + QString StatsUser = User; if( !Payload.empty( ) ) StatsUser = Payload; if( player->GetSpoofed( ) && ( AdminCheck || RootAdminCheck || IsOwner( User ) ) ) - m_PairedDPSChecks.push_back( PairedDPSCheck( string( ), m_GHost->m_DB->ThreadedDotAPlayerSummaryCheck( StatsUser ) ) ); + m_PairedDPSChecks.push_back( PairedDPSCheck( QString( ), m_GHost->m_DB->ThreadedDotAPlayerSummaryCheck( StatsUser ) ) ); else m_PairedDPSChecks.push_back( PairedDPSCheck( User, m_GHost->m_DB->ThreadedDotAPlayerSummaryCheck( StatsUser ) ) ); @@ -1745,7 +1745,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string player->SetKickVote( true ); CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] started by player [" + User + "]" ); SendAllChat( m_GHost->m_Language->StartedVoteKick( LastMatch->GetName( ), User, UTIL_ToString( (uint32_t)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); - SendAllChat( m_GHost->m_Language->TypeYesToVote( string( 1, m_GHost->m_CommandTrigger ) ) ); + SendAllChat( m_GHost->m_Language->TypeYesToVote( QString( 1, m_GHost->m_CommandTrigger ) ) ); } } else @@ -1812,7 +1812,7 @@ void CGame :: EventGameStarted( ) // so we create a "potential ban" for each player and only store it in the database if requested to by an admin for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - m_DBBans.push_back( new CDBBan( (*i)->GetJoinedRealm( ), (*i)->GetName( ), (*i)->GetExternalIPString( ), string( ), string( ), string( ), string( ) ) ); + m_DBBans.push_back( new CDBBan( (*i)->GetJoinedRealm( ), (*i)->GetName( ), (*i)->GetExternalIPString( ), QString( ), QString( ), QString( ), QString( ) ) ); } bool CGame :: IsGameDataSaved( ) @@ -1823,5 +1823,5 @@ bool CGame :: IsGameDataSaved( ) void CGame :: SaveGameData( ) { CONSOLE_Print( "[GAME: " + m_GameName + "] saving game data to database" ); - m_CallableGameAdd = m_GHost->m_DB->ThreadedGameAdd( m_GHost->m_BNETs.size( ) == 1 ? m_GHost->m_BNETs[0]->GetServer( ) : string( ), m_DBGame->GetMap( ), m_GameName, m_OwnerName, m_GameTicks / 1000, m_GameState, m_CreatorName, m_CreatorServer ); + m_CallableGameAdd = m_GHost->m_DB->ThreadedGameAdd( m_GHost->m_BNETs.size( ) == 1 ? m_GHost->m_BNETs[0]->GetServer( ) : QString( ), m_DBGame->GetMap( ), m_GameName, m_OwnerName, m_GameTicks / 1000, m_GameState, m_CreatorName, m_CreatorServer ); } diff --git a/ghost/game.h b/ghost/game.h index a3b0904..4d45f17 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -35,10 +35,10 @@ class CCallableGameAdd; class CCallableGamePlayerSummaryCheck; class CCallableDotAPlayerSummaryCheck; -typedef pair PairedBanCheck; -typedef pair PairedBanAdd; -typedef pair PairedGPSCheck; -typedef pair PairedDPSCheck; +typedef pair PairedBanCheck; +typedef pair PairedBanAdd; +typedef pair PairedGPSCheck; +typedef pair PairedDPSCheck; class CGame : public CBaseGame { @@ -55,13 +55,13 @@ class CGame : public CBaseGame vector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress public: - CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nOwnerName, string nCreatorName, string nCreatorServer ); + CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CGame( ); virtual bool Update( void *fd, void *send_fd ); virtual void EventPlayerDeleted( CGamePlayer *player ); virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); - virtual bool EventPlayerBotCommand( CGamePlayer *player, string command, string payload ); + virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); virtual void EventGameStarted( ); virtual bool IsGameDataSaved( ); virtual void SaveGameData( ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 547711e..ea0443f 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -34,7 +34,7 @@ #include "game_base.h" #include "game_admin.h" -#include +#include #include @@ -44,7 +44,7 @@ using namespace boost :: filesystem; // CAdminGame // -CAdminGame :: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nPassword ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, string( ), string( ), string( ) ) +CAdminGame :: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, QString( ), QString( ), QString( ) ) { m_VirtualHostName = "|cFFC04040Admin"; m_MuteLobby = true; @@ -268,7 +268,7 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) return CBaseGame :: Update( fd, send_fd ); } -void CAdminGame :: SendAdminChat( string message ) +void CAdminGame :: SendAdminChat( QString message ) { for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -318,15 +318,15 @@ void CAdminGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoin CBaseGame :: EventPlayerJoined( potential, joinPlayer ); } -bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string payload ) +bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ) { CBaseGame :: EventPlayerBotCommand( player, command, payload ); // todotodo: don't be lazy - string User = player->GetName( ); - string Command = command; - string Payload = payload; + QString User = player->GetName( ); + QString Command = command; + QString Payload = payload; if( player->GetLoggedIn( ) ) { @@ -345,8 +345,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" - string Name; - string Server; + QString Name; + QString Server; stringstream SS; SS << Payload; SS >> Name; @@ -363,7 +363,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s if( !Server.empty( ) ) { - string Servers; + QString Servers; bool FoundServer = false; for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) @@ -417,7 +417,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s uint32_t MaximumGames; uint32_t AutoStartPlayers; - string GameName; + QString GameName; stringstream SS; SS << Payload; SS >> MaximumGames; @@ -437,9 +437,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s else { getline( SS, GameName ); - string :: size_type Start = GameName.find_first_not_of( " " ); + QString :: size_type Start = GameName.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) GameName = GameName.substr( Start ); SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); @@ -488,7 +488,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s uint32_t AutoStartPlayers; double MinimumScore; double MaximumScore; - string GameName; + QString GameName; stringstream SS; SS << Payload; SS >> MaximumGames; @@ -520,9 +520,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s else { getline( SS, GameName ); - string :: size_type Start = GameName.find_first_not_of( " " ); + QString :: size_type Start = GameName.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) GameName = GameName.substr( Start ); SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); @@ -554,8 +554,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" - string Name; - string Server; + QString Name; + QString Server; stringstream SS; SS << Payload; SS >> Name; @@ -572,7 +572,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s if( !Server.empty( ) ) { - string Servers; + QString Servers; bool FoundServer = false; for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) @@ -609,8 +609,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" - string Name; - string Server; + QString Name; + QString Server; stringstream SS; SS << Payload; SS >> Name; @@ -627,7 +627,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s if( !Server.empty( ) ) { - string Servers; + QString Servers; bool FoundServer = false; for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) @@ -662,7 +662,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s if( Command == "countadmins" ) { - string Server = Payload; + QString Server = Payload; if( Server.empty( ) && m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); @@ -677,7 +677,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s if( Command == "countbans" ) { - string Server = Payload; + QString Server = Payload; if( Server.empty( ) && m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); @@ -695,8 +695,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" - string Name; - string Server; + QString Name; + QString Server; stringstream SS; SS << Payload; SS >> Name; @@ -713,7 +713,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s if( !Server.empty( ) ) { - string Servers; + QString Servers; bool FoundServer = false; for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) @@ -822,11 +822,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != string :: npos || Payload.find( "\\" ) != string :: npos ) + if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) SendChat( player, m_GHost->m_Language->UnableToLoadReplaysOutside( ) ); else { - string File = m_GHost->m_ReplayPath + Payload + ".w3g"; + QString File = m_GHost->m_ReplayPath + Payload + ".w3g"; if( UTIL_FileExists( File ) ) { @@ -893,7 +893,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // if( Command == "hostsg" && !Payload.empty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, true, Payload, User, User, string( ), false ); + m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, true, Payload, User, User, QString( ), false ); // // !LOAD (load config file) @@ -905,12 +905,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); else { - string FoundMapConfigs; + QString FoundMapConfigs; try { path MapCFGPath( m_GHost->m_MapCFGPath ); - string Pattern = Payload; + QString Pattern = Payload; transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); if( !exists( MapCFGPath ) ) @@ -926,12 +926,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s for( directory_iterator i( MapCFGPath ); i != EndIterator; i++ ) { - string FileName = i->filename( ); - string Stem = i->path( ).stem( ); + QString FileName = i->filename( ); + QString Stem = i->path( ).stem( ); transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - if( !is_directory( i->status( ) ) && i->path( ).extension( ) == ".cfg" && FileName.find( Pattern ) != string :: npos ) + if( !is_directory( i->status( ) ) && i->path( ).extension( ) == ".cfg" && FileName.find( Pattern ) != QString :: npos ) { LastMatch = i->path( ); Matches++; @@ -955,10 +955,10 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s SendChat( player, m_GHost->m_Language->NoMapConfigsFound( ) ); else if( Matches == 1 ) { - string File = LastMatch.filename( ); + QString File = LastMatch.filename( ); SendChat( player, m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + File ) ); CConfig MapCFG; - MapCFG.Read( LastMatch.string( ) ); + MapCFG.Read( LastMatch.QString( ) ); m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); } else @@ -967,7 +967,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s } catch( const exception &ex ) { - CONSOLE_Print( string( "[ADMINGAME] error listing map configs - caught exception [" ) + ex.what( ) + "]" ); + CONSOLE_Print( QString( "[ADMINGAME] error listing map configs - caught exception [" ) + ex.what( ) + "]" ); SendChat( player, m_GHost->m_Language->ErrorListingMapConfigs( ) ); } } @@ -981,12 +981,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != string :: npos || Payload.find( "\\" ) != string :: npos ) + if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) SendChat( player, m_GHost->m_Language->UnableToLoadSaveGamesOutside( ) ); else { - string File = m_GHost->m_SaveGamePath + Payload + ".w3z"; - string FileNoPath = Payload + ".w3z"; + QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; + QString FileNoPath = Payload + ".w3z"; if( UTIL_FileExists( File ) ) { @@ -1016,12 +1016,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); else { - string FoundMaps; + QString FoundMaps; try { path MapPath( m_GHost->m_MapPath ); - string Pattern = Payload; + QString Pattern = Payload; transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); if( !exists( MapPath ) ) @@ -1037,12 +1037,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s for( directory_iterator i( MapPath ); i != EndIterator; i++ ) { - string FileName = i->filename( ); - string Stem = i->path( ).stem( ); + QString FileName = i->filename( ); + QString Stem = i->path( ).stem( ); transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - if( !is_directory( i->status( ) ) && FileName.find( Pattern ) != string :: npos ) + if( !is_directory( i->status( ) ) && FileName.find( Pattern ) != QString :: npos ) { LastMatch = i->path( ); Matches++; @@ -1066,7 +1066,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s SendChat( player, m_GHost->m_Language->NoMapsFound( ) ); else if( Matches == 1 ) { - string File = LastMatch.filename( ); + QString File = LastMatch.filename( ); SendChat( player, m_GHost->m_Language->LoadingConfigFile( File ) ); // hackhack: create a config file in memory with the required information to load the map @@ -1082,7 +1082,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s } catch( const exception &ex ) { - CONSOLE_Print( string( "[ADMINGAME] error listing maps - caught exception [" ) + ex.what( ) + "]" ); + CONSOLE_Print( QString( "[ADMINGAME] error listing maps - caught exception [" ) + ex.what( ) + "]" ); SendChat( player, m_GHost->m_Language->ErrorListingMaps( ) ); } } @@ -1093,7 +1093,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // if( Command == "priv" && !Payload.empty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, Payload, User, User, string( ), false ); + m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, Payload, User, User, QString( ), false ); // // !PRIVBY (host private game by other player) @@ -1104,15 +1104,15 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" - string Owner; - string GameName; - string :: size_type GameNameStart = Payload.find( " " ); + QString Owner; + QString GameName; + QString :: size_type GameNameStart = Payload.find( " " ); - if( GameNameStart != string :: npos ) + if( GameNameStart != QString :: npos ) { Owner = Payload.substr( 0, GameNameStart ); GameName = Payload.substr( GameNameStart + 1 ); - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, GameName, Owner, User, string( ), false ); + m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, GameName, Owner, User, QString( ), false ); } } @@ -1121,7 +1121,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // if( Command == "pub" && !Payload.empty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, Payload, User, User, string( ), false ); + m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, Payload, User, User, QString( ), false ); // // !PUBBY (host public game by other player) @@ -1132,15 +1132,15 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" - string Owner; - string GameName; - string :: size_type GameNameStart = Payload.find( " " ); + QString Owner; + QString GameName; + QString :: size_type GameNameStart = Payload.find( " " ); - if( GameNameStart != string :: npos ) + if( GameNameStart != QString :: npos ) { Owner = Payload.substr( 0, GameNameStart ); GameName = Payload.substr( GameNameStart + 1 ); - m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, GameName, Owner, User, string( ), false ); + m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, GameName, Owner, User, QString( ), false ); } } @@ -1174,7 +1174,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // e.g. "3 hello everyone" -> game number: "3", message: "hello everyone" uint32_t GameNumber; - string Message; + QString Message; stringstream SS; SS << Payload; SS >> GameNumber; @@ -1188,9 +1188,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s else { getline( SS, Message ); - string :: size_type Start = Message.find_first_not_of( " " ); + QString :: size_type Start = Message.find_first_not_of( " " ); - if( Start != string :: npos ) + if( Start != QString :: npos ) Message = Message.substr( Start ); if( GameNumber - 1 < m_GHost->m_Games.size( ) ) @@ -1243,11 +1243,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, string command, s // extract the name and the message // e.g. "Varlock hello there!" -> name: "Varlock", message: "hello there!" - string Name; - string Message; - string :: size_type MessageStart = Payload.find( " " ); + QString Name; + QString Message; + QString :: size_type MessageStart = Payload.find( " " ); - if( MessageStart != string :: npos ) + if( MessageStart != QString :: npos ) { Name = Payload.substr( 0, MessageStart ); Message = Payload.substr( MessageStart + 1 ); diff --git a/ghost/game_admin.h b/ghost/game_admin.h index f59aa96..04fdf07 100644 --- a/ghost/game_admin.h +++ b/ghost/game_admin.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -32,19 +32,19 @@ class CCallableBanCount; // class CCallableBanAdd; class CCallableBanRemove; -typedef pair PairedAdminCount; -typedef pair PairedAdminAdd; -typedef pair PairedAdminRemove; -typedef pair PairedBanCount; -// typedef pair PairedBanAdd; -typedef pair PairedBanRemove; +typedef pair PairedAdminCount; +typedef pair PairedAdminAdd; +typedef pair PairedAdminRemove; +typedef pair PairedBanCount; +// typedef pair PairedBanAdd; +typedef pair PairedBanRemove; -typedef pair TempBan; +typedef pair TempBan; class CAdminGame : public CBaseGame { protected: - string m_Password; + QString m_Password; vector m_TempBans; vector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress vector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress @@ -54,14 +54,14 @@ class CAdminGame : public CBaseGame vector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress public: - CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nPassword ); + CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ); virtual ~CAdminGame( ); virtual bool Update( void *fd, void *send_fd ); - virtual void SendAdminChat( string message ); + virtual void SendAdminChat( QString message ); virtual void SendWelcomeMessage( CGamePlayer *player ); virtual void EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer ); - virtual bool EventPlayerBotCommand( CGamePlayer *player, string command, string payload ); + virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); }; #endif diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 7e09da6..2bb8580 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -34,7 +34,7 @@ #include "game_base.h" #include -#include +#include #include #include "next_combination.h" @@ -43,7 +43,7 @@ // CBaseGame // -CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nOwnerName, string nCreatorName, string nCreatorServer ) +CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) { m_GHost = nGHost; m_Socket = new CTCPServer( ); @@ -165,7 +165,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 else { CONSOLE_Print( "[GAME: " + m_GameName + "] loading IP blacklist file [" + m_GHost->m_IPBlackListFile + "]" ); - string Line; + QString Line; while( !in.eof( ) ) { @@ -184,7 +184,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 // ignore lines that don't look like IP addresses - if( Line.find_first_not_of( "1234567890." ) != string :: npos ) + if( Line.find_first_not_of( "1234567890." ) != QString :: npos ) continue; m_IPBlackList.insert( Line ); @@ -223,8 +223,8 @@ CBaseGame :: ~CBaseGame( ) char Time[17]; memset( Time, 0, sizeof( char ) * 17 ); strftime( Time, sizeof( char ) * 17, "%Y-%m-%d %H-%M", localtime( &Now ) ); - string MinString = UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ); - string SecString = UTIL_ToString( ( m_GameTicks / 1000 ) % 60 ); + QString MinString = UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ); + QString SecString = UTIL_ToString( ( m_GameTicks / 1000 ) % 60 ); if( MinString.size( ) == 1 ) MinString.insert( 0, "0" ); @@ -233,7 +233,7 @@ CBaseGame :: ~CBaseGame( ) SecString.insert( 0, "0" ); m_Replay->BuildReplay( m_GameName, m_StatString, m_GHost->m_ReplayWar3Version, m_GHost->m_ReplayBuildNumber ); - m_Replay->Save( m_GHost->m_TFT, m_GHost->m_ReplayPath + UTIL_FileSafeName( "GHost++ " + string( Time ) + " " + m_GameName + " (" + MinString + "m" + SecString + "s).w3g" ) ); + m_Replay->Save( m_GHost->m_TFT, m_GHost->m_ReplayPath + UTIL_FileSafeName( "GHost++ " + QString( Time ) + " " + m_GameName + " (" + MinString + "m" + SecString + "s).w3g" ) ); } delete m_Socket; @@ -324,9 +324,9 @@ uint32_t CBaseGame :: GetNumHumanPlayers( ) return NumHumanPlayers; } -string CBaseGame :: GetDescription( ) +QString CBaseGame :: GetDescription( ) { - string Description = m_GameName + " : " + m_OwnerName + " : " + UTIL_ToString( GetNumHumanPlayers( ) ) + "/" + UTIL_ToString( m_GameLoading || m_GameLoaded ? m_StartPlayers : m_Slots.size( ) ); + QString Description = m_GameName + " : " + m_OwnerName + " : " + UTIL_ToString( GetNumHumanPlayers( ) ) + "/" + UTIL_ToString( m_GameLoading || m_GameLoaded ? m_StartPlayers : m_Slots.size( ) ); if( m_GameLoading || m_GameLoaded ) Description += " : " + UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ) + "m"; @@ -336,7 +336,7 @@ string CBaseGame :: GetDescription( ) return Description; } -void CBaseGame :: SetAnnounce( uint32_t interval, string message ) +void CBaseGame :: SetAnnounce( uint32_t interval, QString message ) { m_AnnounceInterval = interval; m_AnnounceMessage = message; @@ -503,7 +503,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted // so rehost it using the current autohost game name - string GameName = m_GHost->m_AutoHostGameName + " #" + UTIL_ToString( m_GHost->m_HostCounter ); + QString GameName = m_GHost->m_AutoHostGameName + " #" + UTIL_ToString( m_GHost->m_HostCounter ); CONSOLE_Print( "[GAME: " + m_GameName + "] automatically trying to rehost as public game [" + GameName + "] due to refresh failure" ); m_LastGameName = m_GameName; m_GameName = GameName; @@ -536,7 +536,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) if( (*i)->GetOutPacketsQueued( ) <= 1 ) { - (*i)->QueueGameRefresh( m_GameState, m_GameName, string( ), m_Map, m_SaveGame, GetTime( ) - m_CreationTime, m_HostCounter ); + (*i)->QueueGameRefresh( m_GameState, m_GameName, QString( ), m_Map, m_SaveGame, GetTime( ) - m_CreationTime, m_HostCounter ); Refreshed = true; } } @@ -811,7 +811,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) if( !m_Lagging ) { - string LaggingString; + QString LaggingString; for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -1094,7 +1094,7 @@ void CBaseGame :: SendAll( BYTEARRAY data ) (*i)->Send( data ); } -void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, string message ) +void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString message ) { // send a private message to one player - it'll be marked [Private] in Warcraft 3 @@ -1126,22 +1126,22 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, string m } } -void CBaseGame :: SendChat( unsigned char fromPID, unsigned char toPID, string message ) +void CBaseGame :: SendChat( unsigned char fromPID, unsigned char toPID, QString message ) { SendChat( fromPID, GetPlayerFromPID( toPID ), message ); } -void CBaseGame :: SendChat( CGamePlayer *player, string message ) +void CBaseGame :: SendChat( CGamePlayer *player, QString message ) { SendChat( GetHostPID( ), player, message ); } -void CBaseGame :: SendChat( unsigned char toPID, string message ) +void CBaseGame :: SendChat( unsigned char toPID, QString message ) { SendChat( GetHostPID( ), toPID, message ); } -void CBaseGame :: SendAllChat( unsigned char fromPID, string message ) +void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) { // send a public message to all players - it'll be marked [All] in Warcraft 3 @@ -1169,12 +1169,12 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, string message ) } } -void CBaseGame :: SendAllChat( string message ) +void CBaseGame :: SendAllChat( QString message ) { SendAllChat( GetHostPID( ), message ); } -void CBaseGame :: SendLocalAdminChat( string message ) +void CBaseGame :: SendLocalAdminChat( QString message ) { if( !m_LocalAdminMessages ) return; @@ -1385,7 +1385,7 @@ void CBaseGame :: SendWelcomeMessage( CGamePlayer *player ) // don't print more than 8 lines uint32_t Count = 0; - string Line; + QString Line; while( !in.eof( ) && Count < 8 ) { @@ -1418,7 +1418,7 @@ void CBaseGame :: SendEndMessage( ) // don't print more than 8 lines uint32_t Count = 0; - string Line; + QString Line; while( !in.eof( ) && Count < 8 ) { @@ -1480,7 +1480,7 @@ void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) if( m_GameLoaded && player->GetLeftCode( ) == PLAYERLEAVE_DISCONNECT && m_AutoSave ) { - string SaveGameName = UTIL_FileSafeName( "GHost++ AutoSave " + m_GameName + " (" + player->GetName( ) + ").w3z" ); + QString SaveGameName = UTIL_FileSafeName( "GHost++ AutoSave " + m_GameName + " (" + player->GetName( ) + ").w3z" ); CONSOLE_Print( "[GAME: " + m_GameName + "] auto saving [" + SaveGameName + "] before player drop, shortened send interval = " + UTIL_ToString( GetTicks( ) - m_LastActionSentTicks ) ); BYTEARRAY CRC; BYTEARRAY Action; @@ -1706,7 +1706,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // note: this is not a replacement for spoof checking since it doesn't verify the player's name and it can be spoofed anyway uint32_t HostCounterID = joinPlayer->GetHostCounter( ) >> 28; - string JoinedRealm; + QString JoinedRealm; // we use an ID value of 0 to denote joining via LAN @@ -2077,12 +2077,12 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // note: the following (commented out) line of code will crash because calling GetUniqueName( ) twice will result in two different return values // and unfortunately iterators are not valid if compared against different containers // this comment shall serve as warning to not make this mistake again since it has now been made twice before in GHost++ - // string( (*i)->GetUniqueName( ).begin( ), (*i)->GetUniqueName( ).end( ) ) + // QString( (*i)->GetUniqueName( ).begin( ), (*i)->GetUniqueName( ).end( ) ) BYTEARRAY UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) - SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( string( UniqueName.begin( ), UniqueName.end( ) ) ) ); + SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( QString( UniqueName.begin( ), UniqueName.end( ) ) ) ); } } @@ -2090,7 +2090,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_CheckMultipleIPUsage ) { - string Others; + QString Others; for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -2356,7 +2356,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // note: this is not a replacement for spoof checking since it doesn't verify the player's name and it can be spoofed anyway uint32_t HostCounterID = joinPlayer->GetHostCounter( ) >> 28; - string JoinedRealm; + QString JoinedRealm; // we use an ID value of 0 to denote joining via LAN @@ -2450,12 +2450,12 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // note: the following (commented out) line of code will crash because calling GetUniqueName( ) twice will result in two different return values // and unfortunately iterators are not valid if compared against different containers // this comment shall serve as warning to not make this mistake again since it has now been made twice before in GHost++ - // string( (*i)->GetUniqueName( ).begin( ), (*i)->GetUniqueName( ).end( ) ) + // QString( (*i)->GetUniqueName( ).begin( ), (*i)->GetUniqueName( ).end( ) ) BYTEARRAY UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) - SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( string( UniqueName.begin( ), UniqueName.end( ) ) ) ); + SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( QString( UniqueName.begin( ), UniqueName.end( ) ) ) ); } } @@ -2500,7 +2500,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( m_GHost->m_CheckMultipleIPUsage ) { - string Others; + QString Others; for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -2690,7 +2690,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) else if( j != LargestBin && (*j).second.size( ) == (*LargestBin).second.size( ) ) Tied = true; - string Players; + QString Players; for( vector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) { @@ -2783,8 +2783,8 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye // calculate timestamp - string MinString = UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ); - string SecString = UTIL_ToString( ( m_GameTicks / 1000 ) % 60 ); + QString MinString = UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ); + QString SecString = UTIL_ToString( ( m_GameTicks / 1000 ) % 60 ); if( MinString.size( ) == 1 ) MinString.insert( 0, "0" ); @@ -2834,20 +2834,20 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye // handle bot commands - string Message = chatPlayer->GetMessage( ); + QString Message = chatPlayer->GetMessage( ); if( Message == "?trigger" ) - SendChat( player, m_GHost->m_Language->CommandTrigger( string( 1, m_GHost->m_CommandTrigger ) ) ); + SendChat( player, m_GHost->m_Language->CommandTrigger( QString( 1, m_GHost->m_CommandTrigger ) ) ); else if( !Message.empty( ) && Message[0] == m_GHost->m_CommandTrigger ) { // extract the command trigger, the command, and the payload // e.g. "!say hello world" -> command: "say", payload: "hello world" - string Command; - string Payload; - string :: size_type PayloadStart = Message.find( " " ); + QString Command; + QString Payload; + QString :: size_type PayloadStart = Message.find( " " ); - if( PayloadStart != string :: npos ) + if( PayloadStart != QString :: npos ) { Command = Message.substr( 1, PayloadStart - 1 ); Payload = Message.substr( PayloadStart + 1 ); @@ -2878,7 +2878,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye } } -bool CBaseGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string payload ) +bool CBaseGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ) { // return true if the command itself should be hidden from other players @@ -3063,7 +3063,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map if( m_GHost->m_AllowDownloads != 0 ) { - string *MapData = m_Map->GetMapData( ); + QString *MapData = m_Map->GetMapData( ); if( !MapData->empty( ) ) { @@ -3159,7 +3159,7 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, uint32_t pong ) } } -void CBaseGame :: EventGameRefreshed( string server ) +void CBaseGame :: EventGameRefreshed( QString server ) { if( m_RefreshRehosted ) { @@ -3176,10 +3176,10 @@ void CBaseGame :: EventGameStarted( ) { CONSOLE_Print( "[GAME: " + m_GameName + "] started loading with " + UTIL_ToString( GetNumHumanPlayers( ) ) + " players" ); - // encode the HCL command string in the slot handicaps + // encode the HCL command QString in the slot handicaps // here's how it works: - // the user inputs a command string to be sent to the map - // it is almost impossible to send a message from the bot to the map so we encode the command string in the slot handicaps + // the user inputs a command QString to be sent to the map + // it is almost impossible to send a message from the bot to the map so we encode the command QString in the slot handicaps // this works because there are only 6 valid handicaps but Warcraft III allows the bot to set up to 256 handicaps // we encode the original (unmodified) handicaps in the new handicaps and use the remaining space to store a short message // only occupied slots deliver their handicaps to the map and we can send one character (from a list) per handicap @@ -3194,9 +3194,9 @@ void CBaseGame :: EventGameStarted( ) { if( m_HCLCommandString.size( ) <= GetSlotsOccupied( ) ) { - string HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; + QString HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; - if( m_HCLCommandString.find_first_not_of( HCLChars ) == string :: npos ) + if( m_HCLCommandString.find_first_not_of( HCLChars ) == QString :: npos ) { unsigned char EncodingMap[256]; unsigned char j = 0; @@ -3213,7 +3213,7 @@ void CBaseGame :: EventGameStarted( ) unsigned char CurrentSlot = 0; - for( string :: iterator si = m_HCLCommandString.begin( ); si != m_HCLCommandString.end( ); si++ ) + for( QString :: iterator si = m_HCLCommandString.begin( ); si != m_HCLCommandString.end( ); si++ ) { while( m_Slots[CurrentSlot].GetSlotStatus( ) != SLOTSTATUS_OCCUPIED ) CurrentSlot++; @@ -3224,13 +3224,13 @@ void CBaseGame :: EventGameStarted( ) } SendAllSlotInfo( ); - CONSOLE_Print( "[GAME: " + m_GameName + "] successfully encoded HCL command string [" + m_HCLCommandString + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] successfully encoded HCL command QString [" + m_HCLCommandString + "]" ); } else - CONSOLE_Print( "[GAME: " + m_GameName + "] encoding HCL command string [" + m_HCLCommandString + "] failed because it contains invalid characters" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] encoding HCL command QString [" + m_HCLCommandString + "] failed because it contains invalid characters" ); } else - CONSOLE_Print( "[GAME: " + m_GameName + "] encoding HCL command string [" + m_HCLCommandString + "] failed because there aren't enough occupied slots" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] encoding HCL command QString [" + m_HCLCommandString + "] failed because there aren't enough occupied slots" ); } // send a final slot info update if necessary @@ -3324,7 +3324,7 @@ void CBaseGame :: EventGameStarted( ) } } - // build a stat string for use when saving the replay + // build a stat QString for use when saving the replay // we have to build this now because the map data is going to be deleted BYTEARRAY StatString; @@ -3338,7 +3338,7 @@ void CBaseGame :: EventGameStarted( ) StatString.push_back( 0 ); UTIL_AppendByteArray( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing StatString = UTIL_EncodeStatString( StatString ); - m_StatString = string( StatString.begin( ), StatString.end( ) ); + m_StatString = QString( StatString.begin( ), StatString.end( ) ); // delete the map data @@ -3409,7 +3409,7 @@ void CBaseGame :: EventGameLoaded( ) // don't print more than 8 lines uint32_t Count = 0; - string Line; + QString Line; while( !in.eof( ) && Count < 8 ) { @@ -3463,7 +3463,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromSID( unsigned char SID ) return NULL; } -CGamePlayer *CBaseGame :: GetPlayerFromName( string name, bool sensitive ) +CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) { if( !sensitive ) transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); @@ -3472,7 +3472,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( string name, bool sensitive ) { if( !(*i)->GetLeftMessageSent( ) ) { - string TestName = (*i)->GetName( ); + QString TestName = (*i)->GetName( ); if( !sensitive ) transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); @@ -3485,22 +3485,22 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( string name, bool sensitive ) return NULL; } -uint32_t CBaseGame :: GetPlayerFromNamePartial( string name, CGamePlayer **player ) +uint32_t CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **player ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); uint32_t Matches = 0; *player = NULL; - // try to match each player with the passed string (e.g. "Varlock" would be matched with "lock") + // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { - string TestName = (*i)->GetName( ); + QString TestName = (*i)->GetName( ); transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); - if( TestName.find( name ) != string :: npos ) + if( TestName.find( name ) != QString :: npos ) { Matches++; *player = *i; @@ -3821,7 +3821,7 @@ void CBaseGame :: OpenSlot( unsigned char SID, bool kick ) } CGameSlot Slot = m_Slots[SID]; - m_Slots[SID] = CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, Slot.GetTeam( ), Slot.GetColour( ), Slot.GetRace( ) ); + m_Slots[SID] = CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, Slot.GetTeam( ), Slot.GetColour( ), Slot.GetRace( ) ); SendAllSlotInfo( ); } } @@ -3843,7 +3843,7 @@ void CBaseGame :: CloseSlot( unsigned char SID, bool kick ) } CGameSlot Slot = m_Slots[SID]; - m_Slots[SID] = CGameSlot( 0, 255, SLOTSTATUS_CLOSED, 0, Slot.GetTeam( ), Slot.GetColour( ), Slot.GetRace( ) ); + m_Slots[SID] = CGameSlot( 0, 255, SLOTSTATUS_CLOSED, 0, Slot.GetTeam( ), Slot.GetColour( ), Slot.GetRace( ) ); SendAllSlotInfo( ); } } @@ -4262,7 +4262,7 @@ void CBaseGame :: BalanceSlots( ) } } -void CBaseGame :: AddToSpoofed( string server, string name, bool sendMessage ) +void CBaseGame :: AddToSpoofed( QString server, QString name, bool sendMessage ) { CGamePlayer *Player = GetPlayerFromName( name, true ); @@ -4276,13 +4276,13 @@ void CBaseGame :: AddToSpoofed( string server, string name, bool sendMessage ) } } -void CBaseGame :: AddToReserved( string name ) +void CBaseGame :: AddToReserved( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); // check that the user is not already reserved - for( vector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) + for( vector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { if( *i == name ) return; @@ -4294,7 +4294,7 @@ void CBaseGame :: AddToReserved( string name ) for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - string NameLower = (*i)->GetName( ); + QString NameLower = (*i)->GetName( ); transform( NameLower.begin( ), NameLower.end( ), NameLower.begin( ), (int(*)(int))tolower ); if( NameLower == name ) @@ -4302,19 +4302,19 @@ void CBaseGame :: AddToReserved( string name ) } } -bool CBaseGame :: IsOwner( string name ) +bool CBaseGame :: IsOwner( QString name ) { - string OwnerLower = m_OwnerName; + QString OwnerLower = m_OwnerName; transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); transform( OwnerLower.begin( ), OwnerLower.end( ), OwnerLower.begin( ), (int(*)(int))tolower ); return name == OwnerLower; } -bool CBaseGame :: IsReserved( string name ) +bool CBaseGame :: IsReserved( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) + for( vector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { if( *i == name ) return true; @@ -4357,7 +4357,7 @@ void CBaseGame :: StartCountDown( bool force ) } else { - // check if the HCL command string is short enough + // check if the HCL command QString is short enough if( m_HCLCommandString.size( ) > GetSlotsOccupied( ) ) { @@ -4367,7 +4367,7 @@ void CBaseGame :: StartCountDown( bool force ) // check if everyone has the map - string StillDownloading; + QString StillDownloading; for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { @@ -4390,7 +4390,7 @@ void CBaseGame :: StartCountDown( bool force ) // check if everyone is spoof checked - string NotSpoofChecked; + QString NotSpoofChecked; if( m_GHost->m_RequireSpoofChecks ) { @@ -4412,7 +4412,7 @@ void CBaseGame :: StartCountDown( bool force ) // check if everyone has been pinged enough (3 times) that the autokicker would have kicked them by now // see function EventPlayerPongToHost for the autokicker code - string NotPinged; + QString NotPinged; for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -4453,7 +4453,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) // check if everyone has the map - string StillDownloading; + QString StillDownloading; for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { @@ -4479,7 +4479,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) // check if everyone is spoof checked - string NotSpoofChecked; + QString NotSpoofChecked; if( requireSpoofChecks ) { @@ -4501,7 +4501,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) // check if everyone has been pinged enough (3 times) that the autokicker would have kicked them by now // see function EventPlayerPongToHost for the autokicker code - string NotPinged; + QString NotPinged; for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -4530,9 +4530,9 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) } } -void CBaseGame :: StopPlayers( string reason ) +void CBaseGame :: StopPlayers( QString reason ) { - // disconnect every player and set their left reason to the passed string + // disconnect every player and set their left reason to the passed QString // we use this function when we want the code in the Update function to run before the destructor (e.g. saving players to the database) // therefore calling this function when m_GameLoading || m_GameLoaded is roughly equivalent to setting m_Exiting = true // the only difference is whether the code in the Update function is executed or not @@ -4545,7 +4545,7 @@ void CBaseGame :: StopPlayers( string reason ) } } -void CBaseGame :: StopLaggers( string reason ) +void CBaseGame :: StopLaggers( QString reason ) { for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -4613,7 +4613,7 @@ void CBaseGame :: DeleteFakePlayer( ) for( unsigned char i = 0; i < m_Slots.size( ); i++ ) { if( m_Slots[i].GetPID( ) == m_FakePlayerPID ) - m_Slots[i] = CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, m_Slots[i].GetTeam( ), m_Slots[i].GetColour( ), m_Slots[i].GetRace( ) ); + m_Slots[i] = CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, m_Slots[i].GetTeam( ), m_Slots[i].GetColour( ), m_Slots[i].GetRace( ) ); } SendAll( m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( m_FakePlayerPID, PLAYERLEAVE_LOBBY ) ); diff --git a/ghost/game_base.h b/ghost/game_base.h index 1868c2f..e5500e0 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -53,9 +53,9 @@ class CBaseGame vector m_Players; // vector of players vector m_ScoreChecks; queue m_Actions; // queue of actions to be sent - vector m_Reserved; // vector of player names with reserved slots (from the !hold command) - set m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed - set m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) + vector m_Reserved; // vector of player names with reserved slots (from the !hold command) + set m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed + set m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) vector m_EnforceSlots; // vector of slots to force players to use (used with saved games) vector m_EnforcePlayers; // vector of pids to force players to use (used with saved games) CMap *m_Map; // map data @@ -68,16 +68,16 @@ class CBaseGame unsigned char m_VirtualHostPID; // virtual host's PID unsigned char m_FakePlayerPID; // the fake player's PID (if present) unsigned char m_GProxyEmptyActions; - string m_GameName; // game name - string m_LastGameName; // last game name (the previous game name before it was rehosted) - string m_VirtualHostName; // virtual host's name - string m_OwnerName; // name of the player who owns this game (should be considered an admin) - string m_CreatorName; // name of the player who created this game - string m_CreatorServer; // battle.net server the player who created this game was on - string m_AnnounceMessage; // a message to be sent every m_AnnounceInterval seconds - string m_StatString; // the stat string when the game started (used when saving replays) - string m_KickVotePlayer; // the player to be kicked with the currently running kick vote - string m_HCLCommandString; // the "HostBot Command Library" command string, used to pass a limited amount of data to specially designed maps + QString m_GameName; // game name + QString m_LastGameName; // last game name (the previous game name before it was rehosted) + QString m_VirtualHostName; // virtual host's name + QString m_OwnerName; // name of the player who owns this game (should be considered an admin) + QString m_CreatorName; // name of the player who created this game + QString m_CreatorServer; // battle.net server the player who created this game was on + QString m_AnnounceMessage; // a message to be sent every m_AnnounceInterval seconds + QString m_StatString; // the stat QString when the game started (used when saving replays) + QString m_KickVotePlayer; // the player to be kicked with the currently running kick vote + QString m_HCLCommandString; // the "HostBot Command Library" command QString, used to pass a limited amount of data to specially designed maps uint32_t m_RandomSeed; // the random seed sent to the Warcraft III clients uint32_t m_HostCounter; // a unique game number uint32_t m_Latency; // the number of ms to wait between sending action packets (we queue any received during this time) @@ -126,7 +126,7 @@ class CBaseGame bool m_LocalAdminMessages; // if local admin messages should be relayed or not public: - CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nOwnerName, string nCreatorName, string nCreatorServer ); + CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CBaseGame( ); virtual vector GetEnforceSlots( ) { return m_EnforceSlots; } @@ -135,12 +135,12 @@ class CBaseGame virtual uint16_t GetHostPort( ) { return m_HostPort; } virtual unsigned char GetGameState( ) { return m_GameState; } virtual unsigned char GetGProxyEmptyActions( ) { return m_GProxyEmptyActions; } - virtual string GetGameName( ) { return m_GameName; } - virtual string GetLastGameName( ) { return m_LastGameName; } - virtual string GetVirtualHostName( ) { return m_VirtualHostName; } - virtual string GetOwnerName( ) { return m_OwnerName; } - virtual string GetCreatorName( ) { return m_CreatorName; } - virtual string GetCreatorServer( ) { return m_CreatorServer; } + virtual QString GetGameName( ) { return m_GameName; } + virtual QString GetLastGameName( ) { return m_LastGameName; } + virtual QString GetVirtualHostName( ) { return m_VirtualHostName; } + virtual QString GetOwnerName( ) { return m_OwnerName; } + virtual QString GetCreatorName( ) { return m_CreatorName; } + virtual QString GetCreatorServer( ) { return m_CreatorServer; } virtual uint32_t GetHostCounter( ) { return m_HostCounter; } virtual uint32_t GetLastLagScreenTime( ) { return m_LastLagScreenTime; } virtual bool GetLocked( ) { return m_Locked; } @@ -164,9 +164,9 @@ class CBaseGame virtual uint32_t GetSlotsOpen( ); virtual uint32_t GetNumPlayers( ); virtual uint32_t GetNumHumanPlayers( ); - virtual string GetDescription( ); + virtual QString GetDescription( ); - virtual void SetAnnounce( uint32_t interval, string message ); + virtual void SetAnnounce( uint32_t interval, QString message ); // processing functions @@ -183,13 +183,13 @@ class CBaseGame // functions to send packets to players - virtual void SendChat( unsigned char fromPID, CGamePlayer *player, string message ); - virtual void SendChat( unsigned char fromPID, unsigned char toPID, string message ); - virtual void SendChat( CGamePlayer *player, string message ); - virtual void SendChat( unsigned char toPID, string message ); - virtual void SendAllChat( unsigned char fromPID, string message ); - virtual void SendAllChat( string message ); - virtual void SendLocalAdminChat( string message ); + virtual void SendChat( unsigned char fromPID, CGamePlayer *player, QString message ); + virtual void SendChat( unsigned char fromPID, unsigned char toPID, QString message ); + virtual void SendChat( CGamePlayer *player, QString message ); + virtual void SendChat( unsigned char toPID, QString message ); + virtual void SendAllChat( unsigned char fromPID, QString message ); + virtual void SendAllChat( QString message ); + virtual void SendLocalAdminChat( QString message ); virtual void SendAllSlotInfo( ); virtual void SendVirtualHostPlayerInfo( CGamePlayer *player ); virtual void SendFakePlayerInfo( CGamePlayer *player ); @@ -213,7 +213,7 @@ class CBaseGame virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); virtual void EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ); virtual void EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlayer *chatPlayer ); - virtual bool EventPlayerBotCommand( CGamePlayer *player, string command, string payload ); + virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); virtual void EventPlayerChangeTeam( CGamePlayer *player, unsigned char team ); virtual void EventPlayerChangeColour( CGamePlayer *player, unsigned char colour ); virtual void EventPlayerChangeRace( CGamePlayer *player, unsigned char race ); @@ -224,7 +224,7 @@ class CBaseGame // these events are called outside of any iterations - virtual void EventGameRefreshed( string server ); + virtual void EventGameRefreshed( QString server ); virtual void EventGameStarted( ); virtual void EventGameLoaded( ); @@ -233,8 +233,8 @@ class CBaseGame virtual unsigned char GetSIDFromPID( unsigned char PID ); virtual CGamePlayer *GetPlayerFromPID( unsigned char PID ); virtual CGamePlayer *GetPlayerFromSID( unsigned char SID ); - virtual CGamePlayer *GetPlayerFromName( string name, bool sensitive ); - virtual uint32_t GetPlayerFromNamePartial( string name, CGamePlayer **player ); + virtual CGamePlayer *GetPlayerFromName( QString name, bool sensitive ); + virtual uint32_t GetPlayerFromNamePartial( QString name, CGamePlayer **player ); virtual CGamePlayer *GetPlayerFromColour( unsigned char colour ); virtual unsigned char GetNewPID( ); virtual unsigned char GetNewColour( ); @@ -253,17 +253,17 @@ class CBaseGame virtual void ShuffleSlots( ); virtual vector BalanceSlotsRecursive( vector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ); virtual void BalanceSlots( ); - virtual void AddToSpoofed( string server, string name, bool sendMessage ); - virtual void AddToReserved( string name ); - virtual bool IsOwner( string name ); - virtual bool IsReserved( string name ); + virtual void AddToSpoofed( QString server, QString name, bool sendMessage ); + virtual void AddToReserved( QString name ); + virtual bool IsOwner( QString name ); + virtual bool IsReserved( QString name ); virtual bool IsDownloading( ); virtual bool IsGameDataSaved( ); virtual void SaveGameData( ); virtual void StartCountDown( bool force ); virtual void StartCountDownAuto( bool requireSpoofChecks ); - virtual void StopPlayers( string reason ); - virtual void StopLaggers( string reason ); + virtual void StopPlayers( QString reason ); + virtual void StopLaggers( QString reason ); virtual void CreateVirtualHost( ); virtual void DeleteVirtualHost( ); virtual void CreateFakePlayer( ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 0a78367..7f3479b 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -68,12 +68,12 @@ BYTEARRAY CPotentialPlayer :: GetExternalIP( ) return UTIL_CreateByteArray( Zeros, 4 ); } -string CPotentialPlayer :: GetExternalIPString( ) +QString CPotentialPlayer :: GetExternalIPString( ) { if( m_Socket ) return m_Socket->GetIPString( ); - return string( ); + return QString( ); } bool CPotentialPlayer :: Update( void *fd ) @@ -101,7 +101,7 @@ void CPotentialPlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue - string *RecvBuffer = m_Socket->GetBytes( ); + QString *RecvBuffer = m_Socket->GetBytes( ); BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -189,7 +189,7 @@ void CPotentialPlayer :: Send( BYTEARRAY data ) // CGamePlayer // -CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, string nJoinedRealm, string nName, BYTEARRAY nInternalIP, bool nReserved ) : CPotentialPlayer( nProtocol, nGame, nSocket ) +CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ) : CPotentialPlayer( nProtocol, nGame, nSocket ) { m_PID = nPID; m_Name = nName; @@ -231,7 +231,7 @@ CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSock m_LastGProxyAckTime = 0; } -CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, string nJoinedRealm, string nName, BYTEARRAY nInternalIP, bool nReserved ) : CPotentialPlayer( potential->m_Protocol, potential->m_Game, potential->GetSocket( ) ) +CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ) : CPotentialPlayer( potential->m_Protocol, potential->m_Game, potential->GetSocket( ) ) { // todotodo: properly copy queued packets to the new player, this just discards them // this isn't a big problem because official Warcraft III clients don't send any packets after the join request until they receive a response @@ -288,17 +288,17 @@ CGamePlayer :: ~CGamePlayer( ) } -string CGamePlayer :: GetNameTerminated( ) +QString CGamePlayer :: GetNameTerminated( ) { // if the player's name contains an unterminated colour code add the colour terminator to the end of their name // this is useful because it allows you to print the player's name in a longer message which doesn't colour all the subsequent text - string LowerName = m_Name; + QString LowerName = m_Name; transform( LowerName.begin( ), LowerName.end( ), LowerName.begin( ), (int(*)(int))tolower ); - string :: size_type Start = LowerName.find( "|c" ); - string :: size_type End = LowerName.find( "|r" ); + QString :: size_type Start = LowerName.find( "|c" ); + QString :: size_type End = LowerName.find( "|r" ); - if( Start != string :: npos && ( End == string :: npos || End < Start ) ) + if( Start != QString :: npos && ( End == QString :: npos || End < Start ) ) return m_Name + "|r"; else return m_Name; @@ -405,7 +405,7 @@ void CGamePlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue - string *RecvBuffer = m_Socket->GetBytes( ); + QString *RecvBuffer = m_Socket->GetBytes( ); BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index 262d948..d6ee8e7 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -45,7 +45,7 @@ class CPotentialPlayer queue m_Packets; bool m_DeleteMe; bool m_Error; - string m_ErrorString; + QString m_ErrorString; CIncomingJoinPlayer *m_IncomingJoinPlayer; public: @@ -54,11 +54,11 @@ class CPotentialPlayer virtual CTCPSocket *GetSocket( ) { return m_Socket; } virtual BYTEARRAY GetExternalIP( ); - virtual string GetExternalIPString( ); + virtual QString GetExternalIPString( ); virtual queue GetPackets( ) { return m_Packets; } virtual bool GetDeleteMe( ) { return m_DeleteMe; } virtual bool GetError( ) { return m_Error; } - virtual string GetErrorString( ) { return m_ErrorString; } + virtual QString GetErrorString( ) { return m_ErrorString; } virtual CIncomingJoinPlayer *GetJoinPlayer( ) { return m_IncomingJoinPlayer; } virtual void SetSocket( CTCPSocket *nSocket ) { m_Socket = nSocket; } @@ -83,13 +83,13 @@ class CGamePlayer : public CPotentialPlayer { private: unsigned char m_PID; - string m_Name; // the player's name + QString m_Name; // the player's name BYTEARRAY m_InternalIP; // the player's internal IP address as reported by the player when connecting vector m_Pings; // store the last few (20) pings received so we can take an average queue m_CheckSums; // the last few checksums the player has sent (for detecting desyncs) - string m_LeftReason; // the reason the player left the game - string m_SpoofedRealm; // the realm the player last spoof checked on - string m_JoinedRealm; // the realm the player joined on (probable, can be spoofed) + QString m_LeftReason; // the reason the player left the game + QString m_SpoofedRealm; // the realm the player last spoof checked on + QString m_JoinedRealm; // the realm the player joined on (probable, can be spoofed) uint32_t m_TotalPacketsSent; uint32_t m_TotalPacketsReceived; uint32_t m_LeftCode; // the code to be sent in W3GS_PLAYERLEAVE_OTHERS for why this player left the game @@ -128,19 +128,19 @@ class CGamePlayer : public CPotentialPlayer uint32_t m_LastGProxyAckTime; public: - CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, string nJoinedRealm, string nName, BYTEARRAY nInternalIP, bool nReserved ); - CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, string nJoinedRealm, string nName, BYTEARRAY nInternalIP, bool nReserved ); + CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ); + CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ); virtual ~CGamePlayer( ); unsigned char GetPID( ) { return m_PID; } - string GetName( ) { return m_Name; } + QString GetName( ) { return m_Name; } BYTEARRAY GetInternalIP( ) { return m_InternalIP; } unsigned int GetNumPings( ) { return m_Pings.size( ); } unsigned int GetNumCheckSums( ) { return m_CheckSums.size( ); } queue *GetCheckSums( ) { return &m_CheckSums; } - string GetLeftReason( ) { return m_LeftReason; } - string GetSpoofedRealm( ) { return m_SpoofedRealm; } - string GetJoinedRealm( ) { return m_JoinedRealm; } + QString GetLeftReason( ) { return m_LeftReason; } + QString GetSpoofedRealm( ) { return m_SpoofedRealm; } + QString GetJoinedRealm( ) { return m_JoinedRealm; } uint32_t GetLeftCode( ) { return m_LeftCode; } uint32_t GetLoginAttempts( ) { return m_LoginAttempts; } uint32_t GetSyncCounter( ) { return m_SyncCounter; } @@ -174,8 +174,8 @@ class CGamePlayer : public CPotentialPlayer bool GetGProxyDisconnectNoticeSent( ) { return m_GProxyDisconnectNoticeSent; } uint32_t GetGProxyReconnectKey( ) { return m_GProxyReconnectKey; } - void SetLeftReason( string nLeftReason ) { m_LeftReason = nLeftReason; } - void SetSpoofedRealm( string nSpoofedRealm ) { m_SpoofedRealm = nSpoofedRealm; } + void SetLeftReason( QString nLeftReason ) { m_LeftReason = nLeftReason; } + void SetSpoofedRealm( QString nSpoofedRealm ) { m_SpoofedRealm = nSpoofedRealm; } void SetLeftCode( uint32_t nLeftCode ) { m_LeftCode = nLeftCode; } void SetLoginAttempts( uint32_t nLoginAttempts ) { m_LoginAttempts = nLoginAttempts; } void SetSyncCounter( uint32_t nSyncCounter ) { m_SyncCounter = nSyncCounter; } @@ -202,7 +202,7 @@ class CGamePlayer : public CPotentialPlayer void SetLeftMessageSent( bool nLeftMessageSent ) { m_LeftMessageSent = nLeftMessageSent; } void SetGProxyDisconnectNoticeSent( bool nGProxyDisconnectNoticeSent ) { m_GProxyDisconnectNoticeSent = nGProxyDisconnectNoticeSent; } - string GetNameTerminated( ); + QString GetNameTerminated( ); uint32_t GetPing( bool LCPing ); void AddLoadInGameData( BYTEARRAY nLoadInGameData ) { m_LoadInGameData.push( nLoadInGameData ); } diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 5f505f2..af638d7 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -25,6 +25,7 @@ #include "gameprotocol.h" #include "game_base.h" +#include // // CGameProtocol // @@ -43,7 +44,7 @@ CGameProtocol :: ~CGameProtocol( ) // RECEIVE FUNCTIONS // /////////////////////// -CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( BYTEARRAY data ) +CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_REQJOIN" ); // DEBUG_Print( data ); @@ -55,27 +56,27 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( BYTEARRAY data ) // 1 byte -> ??? // 2 bytes -> Listen Port // 4 bytes -> Peer Key - // null terminated string -> Name + // null terminated QString -> Name // 4 bytes -> ??? // 2 bytes -> InternalPort (???) // 4 bytes -> InternalIP if( ValidateLength( data ) && data.size( ) >= 20 ) { - uint32_t HostCounter = UTIL_ByteArrayToUInt32( data, false, 4 ); - BYTEARRAY Name = UTIL_ExtractCString( data, 19 ); + uint32_t HostCounter = UTIL_QByteArrayToUInt32( data, false, 4 ); + QByteArray Name = UTIL_ExtractCString( data, 19 ); if( !Name.empty( ) && data.size( ) >= Name.size( ) + 30 ) { - BYTEARRAY InternalIP = BYTEARRAY( data.begin( ) + Name.size( ) + 26, data.begin( ) + Name.size( ) + 30 ); - return new CIncomingJoinPlayer( HostCounter, string( Name.begin( ), Name.end( ) ), InternalIP ); + QByteArray InternalIP = QByteArray( data.begin( ) + Name.size( ) + 26, data.begin( ) + Name.size( ) + 30 ); + return new CIncomingJoinPlayer( HostCounter, QString( Name.begin( ), Name.end( ) ), InternalIP ); } } return NULL; } -uint32_t CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( BYTEARRAY data ) +uint32_t CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_LEAVEGAME" ); // DEBUG_Print( data ); @@ -85,12 +86,12 @@ uint32_t CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( BYTEARRAY data ) // 4 bytes -> Reason if( ValidateLength( data ) && data.size( ) >= 8 ) - return UTIL_ByteArrayToUInt32( data, false, 4 ); + return UTIL_QByteArrayToUInt32( data, false, 4 ); return 0; } -bool CGameProtocol :: RECEIVE_W3GS_GAMELOADED_SELF( BYTEARRAY data ) +bool CGameProtocol :: RECEIVE_W3GS_GAMELOADED_SELF( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_GAMELOADED_SELF" ); // DEBUG_Print( data ); @@ -104,7 +105,7 @@ bool CGameProtocol :: RECEIVE_W3GS_GAMELOADED_SELF( BYTEARRAY data ) return false; } -CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( BYTEARRAY data, unsigned char PID ) +CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, unsigned char PID ) { // DEBUG_Print( "RECEIVED W3GS_OUTGOING_ACTION" ); // DEBUG_Print( data ); @@ -116,15 +117,15 @@ CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( BYTEARRAY data, if( PID != 255 && ValidateLength( data ) && data.size( ) >= 8 ) { - BYTEARRAY CRC = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); - BYTEARRAY Action = BYTEARRAY( data.begin( ) + 8, data.end( ) ); + QByteArray CRC = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Action = QByteArray( data.begin( ) + 8, data.end( ) ); return new CIncomingAction( PID, CRC, Action ); } return NULL; } -uint32_t CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( BYTEARRAY data ) +uint32_t CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_OUTGOING_KEEPALIVE" ); // DEBUG_Print( data ); @@ -135,12 +136,12 @@ uint32_t CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( BYTEARRAY data ) // 4 bytes -> CheckSum??? (used in replays) if( ValidateLength( data ) && data.size( ) == 9 ) - return UTIL_ByteArrayToUInt32( data, false, 5 ); + return UTIL_QByteArrayToUInt32( data, false, 5 ); return 0; } -CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data ) +CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_CHAT_TO_HOST" ); // DEBUG_Print( data ); @@ -153,7 +154,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data // 1 byte -> FromPID // 1 byte -> Flag // if( Flag == 16 ) - // null term string -> Message + // null term QString -> Message // elseif( Flag == 17 ) // 1 byte -> Team // elseif( Flag == 18 ) @@ -164,7 +165,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data // 1 byte -> Handicap // elseif( Flag == 32 ) // 4 bytes -> ExtraFlags - // null term string -> Message + // null term QString -> Message if( ValidateLength( data ) ) { @@ -173,7 +174,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data if( Total > 0 && data.size( ) >= i + Total ) { - BYTEARRAY ToPIDs = BYTEARRAY( data.begin( ) + i, data.begin( ) + i + Total ); + QByteArray ToPIDs = QByteArray( data.begin( ) + i, data.begin( ) + i + Total ); i += Total; unsigned char FromPID = data[i]; unsigned char Flag = data[i + 1]; @@ -183,8 +184,8 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data { // chat message - BYTEARRAY Message = UTIL_ExtractCString( data, i ); - return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, string( Message.begin( ), Message.end( ) ) ); + QByteArray Message = UTIL_ExtractCString( data, i ); + return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString( Message.begin( ), Message.end( ) ) ); } else if( ( Flag >= 17 && Flag <= 20 ) && data.size( ) >= i + 1 ) { @@ -197,9 +198,9 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data { // chat message with extra flags - BYTEARRAY ExtraFlags = BYTEARRAY( data.begin( ) + i, data.begin( ) + i + 4 ); - BYTEARRAY Message = UTIL_ExtractCString( data, i + 4 ); - return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, string( Message.begin( ), Message.end( ) ), ExtraFlags ); + QByteArray ExtraFlags = QByteArray( data.begin( ) + i, data.begin( ) + i + 4 ); + QByteArray Message = UTIL_ExtractCString( data, i + 4 ); + return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString( Message.begin( ), Message.end( ) ), ExtraFlags ); } } } @@ -207,7 +208,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data return NULL; } -bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( BYTEARRAY data, unsigned char war3Version ) +bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char war3Version ) { uint32_t ProductID = 1462982736; // "W3XP" uint32_t Version = war3Version; @@ -223,11 +224,11 @@ bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( BYTEARRAY data, unsigned char war if( ValidateLength( data ) && data.size( ) >= 16 ) { - if( UTIL_ByteArrayToUInt32( data, false, 4 ) == ProductID ) + if( UTIL_QByteArrayToUInt32( data, false, 4 ) == ProductID ) { - if( UTIL_ByteArrayToUInt32( data, false, 8 ) == Version ) + if( UTIL_QByteArrayToUInt32( data, false, 8 ) == Version ) { - if( UTIL_ByteArrayToUInt32( data, false, 12 ) == 0 ) + if( UTIL_QByteArrayToUInt32( data, false, 12 ) == 0 ) return true; } } @@ -236,7 +237,7 @@ bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( BYTEARRAY data, unsigned char war return false; } -CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( BYTEARRAY data, BYTEARRAY mapSize ) +CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray mapSize ) { // DEBUG_Print( "RECEIVED W3GS_MAPSIZE" ); // DEBUG_Print( data ); @@ -248,12 +249,12 @@ CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( BYTEARRAY data, BYTEARR // 4 bytes -> MapSize if( ValidateLength( data ) && data.size( ) >= 13 ) - return new CIncomingMapSize( data[8], UTIL_ByteArrayToUInt32( data, false, 9 ) ); + return new CIncomingMapSize( data[8], UTIL_QByteArrayToUInt32( data, false, 9 ) ); return NULL; } -uint32_t CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( BYTEARRAY data ) +uint32_t CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_MAPPARTOK" ); // DEBUG_Print( data ); @@ -266,12 +267,12 @@ uint32_t CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( BYTEARRAY data ) // 4 bytes -> MapSize if( ValidateLength( data ) && data.size( ) >= 14 ) - return UTIL_ByteArrayToUInt32( data, false, 10 ); + return UTIL_QByteArrayToUInt32( data, false, 10 ); return 0; } -uint32_t CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( BYTEARRAY data ) +uint32_t CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_PONG_TO_HOST" ); // DEBUG_Print( data ); @@ -285,7 +286,7 @@ uint32_t CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( BYTEARRAY data ) // (the subtraction is done elsewhere because the very first pong value seems to be 1 and we want to discard that one) if( ValidateLength( data ) && data.size( ) >= 8 ) - return UTIL_ByteArrayToUInt32( data, false, 4 ); + return UTIL_QByteArrayToUInt32( data, false, 4 ); return 1; } @@ -294,26 +295,26 @@ uint32_t CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( BYTEARRAY data ) // SEND FUNCTIONS // //////////////////// -BYTEARRAY CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) +QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_PING_FROM_HOST ); // W3GS_PING_FROM_HOST packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, GetTicks( ), false ); // ping value + UTIL_AppendQByteArray( packet, GetTicks( ), false ); // ping value AssignLength( packet ); // DEBUG_Print( "SENT W3GS_PING_FROM_HOST" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, BYTEARRAY port, BYTEARRAY externalIP, vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; - BYTEARRAY SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); - BYTEARRAY packet; + QByteArray SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); + QByteArray packet; if( port.size( ) == 2 && externalIP.size( ) == 4 ) { @@ -321,15 +322,15 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, BYTEARRAY packet.push_back( W3GS_SLOTINFOJOIN ); // W3GS_SLOTINFOJOIN packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length - UTIL_AppendByteArrayFast( packet, SlotInfo ); // SlotInfo + UTIL_AppendQByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length + UTIL_AppendQByteArrayFast( packet, SlotInfo ); // SlotInfo packet.push_back( PID ); // PID packet.push_back( 2 ); // AF_INET packet.push_back( 0 ); // AF_INET continued... - UTIL_AppendByteArray( packet, port ); // port - UTIL_AppendByteArrayFast( packet, externalIP ); // external IP - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, port ); // port + UTIL_AppendQByteArrayFast( packet, externalIP ); // external IP + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? AssignLength( packet ); } else @@ -340,26 +341,26 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, BYTEARRAY return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_REJECTJOIN( uint32_t reason ) +QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( uint32_t reason ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_REJECTJOIN ); // W3GS_REJECTJOIN packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, reason, false ); // reason + UTIL_AppendQByteArray( packet, reason, false ); // reason AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REJECTJOIN" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, string name, BYTEARRAY externalIP, BYTEARRAY internalIP ) +QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ) { unsigned char PlayerJoinCounter[] = { 2, 0, 0, 0 }; unsigned char Zeros[] = { 0, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; if( !name.empty( ) && name.size( ) <= 15 && externalIP.size( ) == 4 && internalIP.size( ) == 4 ) { @@ -367,25 +368,25 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, string name, packet.push_back( W3GS_PLAYERINFO ); // W3GS_PLAYERINFO packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, PlayerJoinCounter, 4 ); // player join counter + UTIL_AppendQByteArray( packet, PlayerJoinCounter, 4 ); // player join counter packet.push_back( PID ); // PID - UTIL_AppendByteArrayFast( packet, name ); // player name + UTIL_AppendQByteArrayFast( packet, name ); // player name packet.push_back( 1 ); // ??? packet.push_back( 0 ); // ??? packet.push_back( 2 ); // AF_INET packet.push_back( 0 ); // AF_INET continued... packet.push_back( 0 ); // port packet.push_back( 0 ); // port continued... - UTIL_AppendByteArrayFast( packet, externalIP ); // external IP - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArrayFast( packet, externalIP ); // external IP + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? packet.push_back( 2 ); // AF_INET packet.push_back( 0 ); // AF_INET continued... packet.push_back( 0 ); // port packet.push_back( 0 ); // port continued... - UTIL_AppendByteArrayFast( packet, internalIP ); // internal IP - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArrayFast( packet, internalIP ); // internal IP + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? AssignLength( packet ); } else @@ -396,9 +397,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, string name, return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ) +QByteArray CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ) { - BYTEARRAY packet; + QByteArray packet; if( PID != 255 ) { @@ -407,7 +408,7 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later packet.push_back( PID ); // PID - UTIL_AppendByteArray( packet, leftCode, false ); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) + UTIL_AppendQByteArray( packet, leftCode, false ); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) AssignLength( packet ); } else @@ -418,9 +419,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) +QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) { - BYTEARRAY packet; + QByteArray packet; if( PID != 255 ) { @@ -439,25 +440,25 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_SLOTINFO( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { - BYTEARRAY SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); - BYTEARRAY packet; + QByteArray SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_SLOTINFO ); // W3GS_SLOTINFO packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length - UTIL_AppendByteArrayFast( packet, SlotInfo ); // SlotInfo + UTIL_AppendQByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length + UTIL_AppendQByteArrayFast( packet, SlotInfo ); // SlotInfo AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SLOTINFO" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_COUNTDOWN_START( ) +QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_START( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_COUNTDOWN_START ); // W3GS_COUNTDOWN_START packet.push_back( 0 ); // packet length will be assigned later @@ -468,9 +469,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_COUNTDOWN_START( ) return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) +QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_COUNTDOWN_END ); // W3GS_COUNTDOWN_END packet.push_back( 0 ); // packet length will be assigned later @@ -481,39 +482,39 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_INCOMING_ACTION( queue actions, uint16_t sendInterval ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( queue actions, uint16_t sendInterval ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_INCOMING_ACTION ); // W3GS_INCOMING_ACTION packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, sendInterval, false ); // send interval + UTIL_AppendQByteArray( packet, sendInterval, false ); // send interval // create subpacket if( !actions.empty( ) ) { - BYTEARRAY subpacket; + QByteArray subpacket; while( !actions.empty( ) ) { CIncomingAction *Action = actions.front( ); actions.pop( ); subpacket.push_back( Action->GetPID( ) ); - UTIL_AppendByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendByteArrayFast( subpacket, *Action->GetAction( ) ); + UTIL_AppendQByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendQByteArrayFast( subpacket, *Action->GetAction( ) ); } // calculate crc (we only care about the first 2 bytes though) - BYTEARRAY crc32 = UTIL_CreateByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)string( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false ); + QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)QString( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false ); crc32.resize( 2 ); // finish subpacket - UTIL_AppendByteArrayFast( packet, crc32 ); // crc - UTIL_AppendByteArrayFast( packet, subpacket ); // subpacket + UTIL_AppendQByteArrayFast( packet, crc32 ); // crc + UTIL_AppendQByteArrayFast( packet, subpacket ); // subpacket } AssignLength( packet ); @@ -522,9 +523,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_INCOMING_ACTION( queue a return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, BYTEARRAY toPIDs, unsigned char flag, BYTEARRAY flagExtra, string message ) +QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, QString message ) { - BYTEARRAY packet; + QByteArray packet; if( !toPIDs.empty( ) && !message.empty( ) && message.size( ) < 255 ) { @@ -533,11 +534,11 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, BYTE packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later packet.push_back( toPIDs.size( ) ); // number of receivers - UTIL_AppendByteArrayFast( packet, toPIDs ); // receivers + UTIL_AppendQByteArrayFast( packet, toPIDs ); // receivers packet.push_back( fromPID ); // sender packet.push_back( flag ); // flag - UTIL_AppendByteArrayFast( packet, flagExtra ); // extra flag - UTIL_AppendByteArrayFast( packet, message ); // message + UTIL_AppendQByteArrayFast( packet, flagExtra ); // extra flag + UTIL_AppendQByteArrayFast( packet, message ); // message AssignLength( packet ); } else @@ -548,9 +549,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, BYTE return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_START_LAG( vector players, bool loadInGame ) +QByteArray CGameProtocol :: SEND_W3GS_START_LAG( vector players, bool loadInGame ) { - BYTEARRAY packet; + QByteArray packet; unsigned char NumLaggers = 0; @@ -583,7 +584,7 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_START_LAG( vector players, b if( !(*i)->GetFinishedLoading( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendByteArray( packet, (uint32_t)0, false ); + UTIL_AppendQByteArray( packet, (uint32_t)0, false ); } } else @@ -591,7 +592,7 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_START_LAG( vector players, b if( (*i)->GetLagging( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendByteArray( packet, GetTicks( ) - (*i)->GetStartedLaggingTicks( ), false ); + UTIL_AppendQByteArray( packet, GetTicks( ) - (*i)->GetStartedLaggingTicks( ), false ); } } } @@ -606,9 +607,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_START_LAG( vector players, b return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame ) +QByteArray CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_STOP_LAG ); // W3GS_STOP_LAG packet.push_back( 0 ); // packet length will be assigned later @@ -616,9 +617,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInG packet.push_back( player->GetPID( ) ); if( loadInGame ) - UTIL_AppendByteArray( packet, (uint32_t)0, false ); + UTIL_AppendQByteArray( packet, (uint32_t)0, false ); else - UTIL_AppendByteArray( packet, GetTicks( ) - player->GetStartedLaggingTicks( ), false ); + UTIL_AppendQByteArray( packet, GetTicks( ) - player->GetStartedLaggingTicks( ), false ); AssignLength( packet ); // DEBUG_Print( "SENT W3GS_STOP_LAG" ); @@ -626,33 +627,33 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInG return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ) +QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ) { unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" unsigned char Version[] = { war3Version, 0, 0, 0 }; unsigned char Unknown[] = { 0, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_SEARCHGAME ); // W3GS_SEARCHGAME packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) - UTIL_AppendByteArray( packet, Version, 4 ); // Version - UTIL_AppendByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendQByteArray( packet, Version, 4 ); // Version + UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SEARCHGAME" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, BYTEARRAY mapGameType, BYTEARRAY mapFlags, BYTEARRAY mapWidth, BYTEARRAY mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, BYTEARRAY mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ) +QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ) { unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" @@ -660,20 +661,20 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Versi unsigned char Unknown1[] = { 1, 2, 3, 4 }; unsigned char Unknown2[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.empty( ) && !hostName.empty( ) && !mapPath.empty( ) && mapCRC.size( ) == 4 ) { - // make the stat string + // make the stat QString - BYTEARRAY StatString; - UTIL_AppendByteArrayFast( StatString, mapFlags ); + QByteArray StatString; + UTIL_AppendQByteArrayFast( StatString, mapFlags ); StatString.push_back( 0 ); - UTIL_AppendByteArrayFast( StatString, mapWidth ); - UTIL_AppendByteArrayFast( StatString, mapHeight ); - UTIL_AppendByteArrayFast( StatString, mapCRC ); - UTIL_AppendByteArrayFast( StatString, mapPath ); - UTIL_AppendByteArrayFast( StatString, hostName ); + UTIL_AppendQByteArrayFast( StatString, mapWidth ); + UTIL_AppendQByteArrayFast( StatString, mapHeight ); + UTIL_AppendQByteArrayFast( StatString, mapCRC ); + UTIL_AppendQByteArrayFast( StatString, mapPath ); + UTIL_AppendQByteArrayFast( StatString, hostName ); StatString.push_back( 0 ); StatString = UTIL_EncodeStatString( StatString ); @@ -685,23 +686,23 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Versi packet.push_back( 0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) - UTIL_AppendByteArray( packet, Version, 4 ); // Version - UTIL_AppendByteArray( packet, hostCounter, false ); // Host Counter - UTIL_AppendByteArray( packet, Unknown1, 4 ); // ??? (this varies wildly even between two identical games created one after another) - UTIL_AppendByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendQByteArray( packet, Version, 4 ); // Version + UTIL_AppendQByteArray( packet, hostCounter, false ); // Host Counter + UTIL_AppendQByteArray( packet, Unknown1, 4 ); // ??? (this varies wildly even between two identical games created one after another) + UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name packet.push_back( 0 ); // ??? (maybe game password) - UTIL_AppendByteArrayFast( packet, StatString ); // Stat String - packet.push_back( 0 ); // Stat String null terminator (the stat string is encoded to remove all even numbers i.e. zeros) - UTIL_AppendByteArray( packet, slotsTotal, false ); // Slots Total - UTIL_AppendByteArrayFast( packet, mapGameType ); // Game Type - UTIL_AppendByteArray( packet, Unknown2, 4 ); // ??? - UTIL_AppendByteArray( packet, slotsOpen, false ); // Slots Open - UTIL_AppendByteArray( packet, upTime, false ); // time since creation - UTIL_AppendByteArray( packet, port, false ); // port + UTIL_AppendQByteArrayFast( packet, StatString ); // Stat String + packet.push_back( 0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) + UTIL_AppendQByteArray( packet, slotsTotal, false ); // Slots Total + UTIL_AppendQByteArrayFast( packet, mapGameType ); // Game Type + UTIL_AppendQByteArray( packet, Unknown2, 4 ); // ??? + UTIL_AppendQByteArray( packet, slotsOpen, false ); // Slots Open + UTIL_AppendQByteArray( packet, upTime, false ); // time since creation + UTIL_AppendQByteArray( packet, port, false ); // port AssignLength( packet ); } else @@ -712,71 +713,71 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Versi return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ) +QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ) { unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" unsigned char Version[] = { war3Version, 0, 0, 0 }; unsigned char HostCounter[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_CREATEGAME ); // W3GS_CREATEGAME packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) - UTIL_AppendByteArray( packet, Version, 4 ); // Version - UTIL_AppendByteArray( packet, HostCounter, 4 ); // Host Counter + UTIL_AppendQByteArray( packet, Version, 4 ); // Version + UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_CREATEGAME" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ) { unsigned char HostCounter[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_REFRESHGAME ); // W3GS_REFRESHGAME packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, HostCounter, 4 ); // Host Counter - UTIL_AppendByteArray( packet, players, false ); // Players - UTIL_AppendByteArray( packet, playerSlots, false ); // Player Slots + UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter + UTIL_AppendQByteArray( packet, players, false ); // Players + UTIL_AppendQByteArray( packet, playerSlots, false ); // Player Slots AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REFRESHGAME" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_DECREATEGAME( ) +QByteArray CGameProtocol :: SEND_W3GS_DECREATEGAME( ) { unsigned char HostCounter[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_DECREATEGAME ); // W3GS_DECREATEGAME packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, HostCounter, 4 ); // Host Counter + UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_DECREATEGAME" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_MAPCHECK( string mapPath, BYTEARRAY mapSize, BYTEARRAY mapInfo, BYTEARRAY mapCRC, BYTEARRAY mapSHA1 ) +QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ) { unsigned char Unknown[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; if( !mapPath.empty( ) && mapSize.size( ) == 4 && mapInfo.size( ) == 4 && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 ) { @@ -784,12 +785,12 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_MAPCHECK( string mapPath, BYTEARRAY mapSize packet.push_back( W3GS_MAPCHECK ); // W3GS_MAPCHECK packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, Unknown, 4 ); // ??? - UTIL_AppendByteArrayFast( packet, mapPath ); // map path - UTIL_AppendByteArrayFast( packet, mapSize ); // map size - UTIL_AppendByteArrayFast( packet, mapInfo ); // map info - UTIL_AppendByteArrayFast( packet, mapCRC ); // map crc - UTIL_AppendByteArrayFast( packet, mapSHA1 ); // map sha1 + UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendQByteArrayFast( packet, mapPath ); // map path + UTIL_AppendQByteArrayFast( packet, mapSize ); // map size + UTIL_AppendQByteArrayFast( packet, mapInfo ); // map info + UTIL_AppendQByteArrayFast( packet, mapCRC ); // map crc + UTIL_AppendQByteArrayFast( packet, mapSHA1 ); // map sha1 AssignLength( packet ); } else @@ -800,16 +801,16 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_MAPCHECK( string mapPath, BYTEARRAY mapSize return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) +QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) { unsigned char Unknown[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_STARTDOWNLOAD ); // W3GS_STARTDOWNLOAD packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? packet.push_back( fromPID ); // from PID AssignLength( packet ); // DEBUG_Print( "SENT W3GS_STARTDOWNLOAD" ); @@ -817,11 +818,11 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, string *mapData ) +QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, QString *mapData ) { unsigned char Unknown[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; if( start < mapData->size( ) ) { @@ -831,8 +832,8 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned ch packet.push_back( 0 ); // packet length will be assigned later packet.push_back( toPID ); // to PID packet.push_back( fromPID ); // from PID - UTIL_AppendByteArray( packet, Unknown, 4 ); // ??? - UTIL_AppendByteArray( packet, start, false ); // start position + UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendQByteArray( packet, start, false ); // start position // calculate end position (don't send more than 1442 map bytes in one packet) @@ -843,13 +844,13 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned ch // calculate crc - BYTEARRAY crc32 = UTIL_CreateByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)mapData->c_str( ) + start, End - start ), false ); - UTIL_AppendByteArrayFast( packet, crc32 ); + QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)mapData->c_str( ) + start, End - start ), false ); + UTIL_AppendQByteArrayFast( packet, crc32 ); // map data - BYTEARRAY Data = UTIL_CreateByteArray( (unsigned char *)mapData->c_str( ) + start, End - start ); - UTIL_AppendByteArrayFast( packet, Data ); + QByteArray Data = UTIL_CreateQByteArray( (unsigned char *)mapData->c_str( ) + start, End - start ); + UTIL_AppendQByteArrayFast( packet, Data ); AssignLength( packet ); } else @@ -860,9 +861,9 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned ch return packet; } -BYTEARRAY CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue actions ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue actions ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_INCOMING_ACTION2 ); // W3GS_INCOMING_ACTION2 packet.push_back( 0 ); // packet length will be assigned later @@ -874,26 +875,26 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue if( !actions.empty( ) ) { - BYTEARRAY subpacket; + QByteArray subpacket; while( !actions.empty( ) ) { CIncomingAction *Action = actions.front( ); actions.pop( ); subpacket.push_back( Action->GetPID( ) ); - UTIL_AppendByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendByteArrayFast( subpacket, *Action->GetAction( ) ); + UTIL_AppendQByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendQByteArrayFast( subpacket, *Action->GetAction( ) ); } // calculate crc (we only care about the first 2 bytes though) - BYTEARRAY crc32 = UTIL_CreateByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)string( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false ); + QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)QString( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false ); crc32.resize( 2 ); // finish subpacket - UTIL_AppendByteArrayFast( packet, crc32 ); // crc - UTIL_AppendByteArrayFast( packet, subpacket ); // subpacket + UTIL_AppendQByteArrayFast( packet, crc32 ); // crc + UTIL_AppendQByteArrayFast( packet, subpacket ); // subpacket } AssignLength( packet ); @@ -906,15 +907,15 @@ BYTEARRAY CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue // OTHER FUNCTIONS // ///////////////////// -bool CGameProtocol :: AssignLength( BYTEARRAY &content ) +bool CGameProtocol :: AssignLength( QByteArray &content ) { // insert the actual length of the content array into bytes 3 and 4 (indices 2 and 3) - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -923,18 +924,18 @@ bool CGameProtocol :: AssignLength( BYTEARRAY &content ) return false; } -bool CGameProtocol :: ValidateLength( BYTEARRAY &content ) +bool CGameProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length uint16_t Length; - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) { LengthBytes.push_back( content[2] ); LengthBytes.push_back( content[3] ); - Length = UTIL_ByteArrayToUInt16( LengthBytes, false ); + Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); if( Length == content.size( ) ) return true; @@ -943,15 +944,15 @@ bool CGameProtocol :: ValidateLength( BYTEARRAY &content ) return false; } -BYTEARRAY CGameProtocol :: EncodeSlotInfo( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: EncodeSlotInfo( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { - BYTEARRAY SlotInfo; + QByteArray SlotInfo; SlotInfo.push_back( (unsigned char)slots.size( ) ); // number of slots for( unsigned int i = 0; i < slots.size( ); i++ ) - UTIL_AppendByteArray( SlotInfo, slots[i].GetByteArray( ) ); + UTIL_AppendQByteArray( SlotInfo, slots[i].GetQByteArray( ) ); - UTIL_AppendByteArray( SlotInfo, randomSeed, false ); // random seed + UTIL_AppendQByteArray( SlotInfo, randomSeed, false ); // random seed SlotInfo.push_back( layoutStyle ); // LayoutStyle (0 = melee, 1 = custom forces, 3 = custom forces + fixed player settings) SlotInfo.push_back( playerSlots ); // number of player slots (non observer) return SlotInfo; @@ -961,7 +962,7 @@ BYTEARRAY CGameProtocol :: EncodeSlotInfo( vector &slots, uint32_t ra // CIncomingJoinPlayer // -CIncomingJoinPlayer :: CIncomingJoinPlayer( uint32_t nHostCounter, string nName, BYTEARRAY &nInternalIP ) +CIncomingJoinPlayer :: CIncomingJoinPlayer( uint32_t nHostCounter, QString nName, QByteArray &nInternalIP ) { m_HostCounter = nHostCounter; m_Name = nName; @@ -977,7 +978,7 @@ CIncomingJoinPlayer :: ~CIncomingJoinPlayer( ) // CIncomingAction // -CIncomingAction :: CIncomingAction( unsigned char nPID, BYTEARRAY &nCRC, BYTEARRAY &nAction ) +CIncomingAction :: CIncomingAction( unsigned char nPID, QByteArray &nCRC, QByteArray &nAction ) { m_PID = nPID; m_CRC = nCRC; @@ -993,7 +994,7 @@ CIncomingAction :: ~CIncomingAction( ) // CIncomingChatPlayer // -CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &nToPIDs, unsigned char nFlag, string nMessage ) +CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage ) { m_Type = CTH_MESSAGE; m_FromPID = nFromPID; @@ -1002,7 +1003,7 @@ CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &n m_Message = nMessage; } -CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &nToPIDs, unsigned char nFlag, string nMessage, BYTEARRAY &nExtraFlags ) +CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage, QByteArray &nExtraFlags ) { m_Type = CTH_MESSAGEEXTRA; m_FromPID = nFromPID; @@ -1012,7 +1013,7 @@ CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &n m_ExtraFlags = nExtraFlags; } -CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &nToPIDs, unsigned char nFlag, unsigned char nByte ) +CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ) { if( nFlag == 17 ) m_Type = CTH_TEAMCHANGE; diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index 93ce2cd..1f3421a 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -106,48 +106,48 @@ class CGameProtocol // receive functions - CIncomingJoinPlayer *RECEIVE_W3GS_REQJOIN( BYTEARRAY data ); - uint32_t RECEIVE_W3GS_LEAVEGAME( BYTEARRAY data ); - bool RECEIVE_W3GS_GAMELOADED_SELF( BYTEARRAY data ); - CIncomingAction *RECEIVE_W3GS_OUTGOING_ACTION( BYTEARRAY data, unsigned char PID ); - uint32_t RECEIVE_W3GS_OUTGOING_KEEPALIVE( BYTEARRAY data ); - CIncomingChatPlayer *RECEIVE_W3GS_CHAT_TO_HOST( BYTEARRAY data ); - bool RECEIVE_W3GS_SEARCHGAME( BYTEARRAY data, unsigned char war3Version ); - CIncomingMapSize *RECEIVE_W3GS_MAPSIZE( BYTEARRAY data, BYTEARRAY mapSize ); - uint32_t RECEIVE_W3GS_MAPPARTOK( BYTEARRAY data ); - uint32_t RECEIVE_W3GS_PONG_TO_HOST( BYTEARRAY data ); + CIncomingJoinPlayer *RECEIVE_W3GS_REQJOIN( QByteArray data ); + uint32_t RECEIVE_W3GS_LEAVEGAME( QByteArray data ); + bool RECEIVE_W3GS_GAMELOADED_SELF( QByteArray data ); + CIncomingAction *RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, unsigned char PID ); + uint32_t RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ); + CIncomingChatPlayer *RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data ); + bool RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char war3Version ); + CIncomingMapSize *RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray mapSize ); + uint32_t RECEIVE_W3GS_MAPPARTOK( QByteArray data ); + uint32_t RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ); // send functions - BYTEARRAY SEND_W3GS_PING_FROM_HOST( ); - BYTEARRAY SEND_W3GS_SLOTINFOJOIN( unsigned char PID, BYTEARRAY port, BYTEARRAY externalIP, vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); - BYTEARRAY SEND_W3GS_REJECTJOIN( uint32_t reason ); - BYTEARRAY SEND_W3GS_PLAYERINFO( unsigned char PID, string name, BYTEARRAY externalIP, BYTEARRAY internalIP ); - BYTEARRAY SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ); - BYTEARRAY SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); - BYTEARRAY SEND_W3GS_SLOTINFO( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); - BYTEARRAY SEND_W3GS_COUNTDOWN_START( ); - BYTEARRAY SEND_W3GS_COUNTDOWN_END( ); - BYTEARRAY SEND_W3GS_INCOMING_ACTION( queue actions, uint16_t sendInterval ); - BYTEARRAY SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, BYTEARRAY toPIDs, unsigned char flag, BYTEARRAY flagExtra, string message ); - BYTEARRAY SEND_W3GS_START_LAG( vector players, bool loadInGame = false ); - BYTEARRAY SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); - BYTEARRAY SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); - BYTEARRAY SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, BYTEARRAY mapGameType, BYTEARRAY mapFlags, BYTEARRAY mapWidth, BYTEARRAY mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, BYTEARRAY mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ); - BYTEARRAY SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ); - BYTEARRAY SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ); - BYTEARRAY SEND_W3GS_DECREATEGAME( ); - BYTEARRAY SEND_W3GS_MAPCHECK( string mapPath, BYTEARRAY mapSize, BYTEARRAY mapInfo, BYTEARRAY mapCRC, BYTEARRAY mapSHA1 ); - BYTEARRAY SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); - BYTEARRAY SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, string *mapData ); - BYTEARRAY SEND_W3GS_INCOMING_ACTION2( queue actions ); + QByteArray SEND_W3GS_PING_FROM_HOST( ); + QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_REJECTJOIN( uint32_t reason ); + QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, string name, QByteArray externalIP, QByteArray internalIP ); + QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ); + QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); + QByteArray SEND_W3GS_SLOTINFO( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_COUNTDOWN_START( ); + QByteArray SEND_W3GS_COUNTDOWN_END( ); + QByteArray SEND_W3GS_INCOMING_ACTION( queue actions, uint16_t sendInterval ); + QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, string message ); + QByteArray SEND_W3GS_START_LAG( vector players, bool loadInGame = false ); + QByteArray SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); + QByteArray SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); + QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ); + QByteArray SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ); + QByteArray SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ); + QByteArray SEND_W3GS_DECREATEGAME( ); + QByteArray SEND_W3GS_MAPCHECK( string mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); + QByteArray SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); + QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, string *mapData ); + QByteArray SEND_W3GS_INCOMING_ACTION2( queue actions ); // other functions private: - bool AssignLength( BYTEARRAY &content ); - bool ValidateLength( BYTEARRAY &content ); - BYTEARRAY EncodeSlotInfo( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + bool AssignLength( QByteArray &content ); + bool ValidateLength( QByteArray &content ); + QByteArray EncodeSlotInfo( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); }; // @@ -159,15 +159,15 @@ class CIncomingJoinPlayer private: uint32_t m_HostCounter; string m_Name; - BYTEARRAY m_InternalIP; + QByteArray m_InternalIP; public: - CIncomingJoinPlayer( uint32_t nHostCounter, string nName, BYTEARRAY &nInternalIP ); + CIncomingJoinPlayer( uint32_t nHostCounter, string nName, QByteArray &nInternalIP ); ~CIncomingJoinPlayer( ); uint32_t GetHostCounter( ) { return m_HostCounter; } string GetName( ) { return m_Name; } - BYTEARRAY GetInternalIP( ) { return m_InternalIP; } + QByteArray GetInternalIP( ) { return m_InternalIP; } }; // @@ -178,16 +178,16 @@ class CIncomingAction { private: unsigned char m_PID; - BYTEARRAY m_CRC; - BYTEARRAY m_Action; + QByteArray m_CRC; + QByteArray m_Action; public: - CIncomingAction( unsigned char nPID, BYTEARRAY &nCRC, BYTEARRAY &nAction ); + CIncomingAction( unsigned char nPID, QByteArray &nCRC, QByteArray &nAction ); ~CIncomingAction( ); unsigned char GetPID( ) { return m_PID; } - BYTEARRAY GetCRC( ) { return m_CRC; } - BYTEARRAY *GetAction( ) { return &m_Action; } + QByteArray GetCRC( ) { return m_CRC; } + QByteArray *GetAction( ) { return &m_Action; } uint32_t GetLength( ) { return m_Action.size( ) + 3; } }; @@ -211,25 +211,25 @@ class CIncomingChatPlayer private: ChatToHostType m_Type; unsigned char m_FromPID; - BYTEARRAY m_ToPIDs; + QByteArray m_ToPIDs; unsigned char m_Flag; string m_Message; unsigned char m_Byte; - BYTEARRAY m_ExtraFlags; + QByteArray m_ExtraFlags; public: - CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &nToPIDs, unsigned char nFlag, string nMessage ); - CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &nToPIDs, unsigned char nFlag, string nMessage, BYTEARRAY &nExtraFlags ); - CIncomingChatPlayer( unsigned char nFromPID, BYTEARRAY &nToPIDs, unsigned char nFlag, unsigned char nByte ); + CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, string nMessage ); + CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, string nMessage, QByteArray &nExtraFlags ); + CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ); ~CIncomingChatPlayer( ); ChatToHostType GetType( ) { return m_Type; } unsigned char GetFromPID( ) { return m_FromPID; } - BYTEARRAY GetToPIDs( ) { return m_ToPIDs; } + QByteArray GetToPIDs( ) { return m_ToPIDs; } unsigned char GetFlag( ) { return m_Flag; } string GetMessage( ) { return m_Message; } unsigned char GetByte( ) { return m_Byte; } - BYTEARRAY GetExtraFlags( ) { return m_ExtraFlags; } + QByteArray GetExtraFlags( ) { return m_ExtraFlags; } }; class CIncomingMapSize diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 33810e4..8ab0f57 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -55,11 +55,11 @@ // CGHost // -CGHost :: CGHost( CConfig *CFG, string configFile ) +CGHost :: CGHost( CConfig *CFG, QString configFile ) : m_ConfigFile(configFile) { m_UDPSocket = new CUDPSocket( ); - m_UDPSocket->SetBroadcastTarget( CFG->GetString( "udp_broadcasttarget", string( ) ) ); + m_UDPSocket->SetBroadcastTarget( CFG->GetString( "udp_broadcasttarget", QString( ) ) ); m_UDPSocket->SetDontRoute( CFG->GetInt( "udp_dontroute", 0 ) == 0 ? false : true ); m_ReconnectSocket = NULL; m_GPSProtocol = new CGPSProtocol( ); @@ -67,7 +67,7 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) m_CRC->Initialize( ); m_SHA = new CSHA1( ); m_CurrentGame = NULL; - string DBType = CFG->GetString( "db_type", "sqlite3" ); + QString DBType = CFG->GetString( "db_type", "sqlite3" ); CONSOLE_Print( "[GHOST] opening primary database" ); if( DBType == "mysql" ) @@ -113,7 +113,7 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) { sockaddr_in *pAddress; pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress); - CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + string( inet_ntoa( pAddress->sin_addr ) ) + "]" ); + CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + QString( inet_ntoa( pAddress->sin_addr ) ) + "]" ); m_LocalAddresses.push_back( UTIL_CreateByteArray( (uint32_t)pAddress->sin_addr.s_addr, false ) ); } } @@ -129,7 +129,7 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) CONSOLE_Print( "[GHOST] error finding local IP addresses - failed to get local hostname" ); else { - CONSOLE_Print( "[GHOST] local hostname is [" + string( HostName ) + "]" ); + CONSOLE_Print( "[GHOST] local hostname is [" + QString( HostName ) + "]" ); struct hostent *HostEnt = gethostbyname( HostName ); if( !HostEnt ) @@ -140,7 +140,7 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) { struct in_addr Address; memcpy( &Address, HostEnt->h_addr_list[i], sizeof(struct in_addr) ); - CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + string( inet_ntoa( Address ) ) + "]" ); + CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + QString( inet_ntoa( Address ) ) + "]" ); m_LocalAddresses.push_back( UTIL_CreateByteArray( (uint32_t)Address.s_addr, false ) ); } } @@ -155,8 +155,8 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) m_HostCounter = 1; m_AutoHostMaximumGames = CFG->GetInt( "autohost_maxgames", 0 ); m_AutoHostAutoStartPlayers = CFG->GetInt( "autohost_startplayers", 0 ); - m_AutoHostGameName = CFG->GetString( "autohost_gamename", string( ) ); - m_AutoHostOwner = CFG->GetString( "autohost_owner", string( ) ); + m_AutoHostGameName = CFG->GetString( "autohost_gamename", QString( ) ); + m_AutoHostOwner = CFG->GetString( "autohost_owner", QString( ) ); m_LastAutoHostTime = GetTime( ); m_AutoHostMatchMaking = false; m_AutoHostMinimumScore = 0.0; @@ -176,8 +176,8 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) m_DefaultMap = CFG->GetString( "bot_defaultmap", "map" ); m_AdminGameCreate = CFG->GetInt( "admingame_create", 0 ) == 0 ? false : true; m_AdminGamePort = CFG->GetInt( "admingame_port", 6113 ); - m_AdminGamePassword = CFG->GetString( "admingame_password", string( ) ); - m_AdminGameMap = CFG->GetString( "admingame_map", string( ) ); + m_AdminGamePassword = CFG->GetString( "admingame_password", QString( ) ); + m_AdminGameMap = CFG->GetString( "admingame_map", QString( ) ); m_LANWar3Version = CFG->GetInt( "lan_war3version", 24 ); m_ReplayWar3Version = CFG->GetInt( "replay_war3version", 24 ); m_ReplayBuildNumber = CFG->GetInt( "replay_buildnumber", 6059 ); @@ -188,20 +188,20 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) for( uint32_t i = 1; i < 10; i++ ) { - string Prefix; + QString Prefix; if( i == 1 ) Prefix = "bnet_"; else Prefix = "bnet" + UTIL_ToString( i ) + "_"; - string Server = CFG->GetString( Prefix + "server", string( ) ); - string ServerAlias = CFG->GetString( Prefix + "serveralias", string( ) ); - string CDKeyROC = CFG->GetString( Prefix + "cdkeyroc", string( ) ); - string CDKeyTFT = CFG->GetString( Prefix + "cdkeytft", string( ) ); - string CountryAbbrev = CFG->GetString( Prefix + "countryabbrev", "USA" ); - string Country = CFG->GetString( Prefix + "country", "United States" ); - string Locale = CFG->GetString( Prefix + "locale", "system" ); + QString Server = CFG->GetString( Prefix + "server", QString( ) ); + QString ServerAlias = CFG->GetString( Prefix + "serveralias", QString( ) ); + QString CDKeyROC = CFG->GetString( Prefix + "cdkeyroc", QString( ) ); + QString CDKeyTFT = CFG->GetString( Prefix + "cdkeytft", QString( ) ); + QString CountryAbbrev = CFG->GetString( Prefix + "countryabbrev", "USA" ); + QString Country = CFG->GetString( Prefix + "country", "United States" ); + QString Locale = CFG->GetString( Prefix + "locale", "system" ); uint32_t LocaleID; if( Locale == "system" ) @@ -215,11 +215,11 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) else LocaleID = UTIL_ToUInt32( Locale ); - string UserName = CFG->GetString( Prefix + "username", string( ) ); - string UserPassword = CFG->GetString( Prefix + "password", string( ) ); - string FirstChannel = CFG->GetString( Prefix + "firstchannel", "The Void" ); - string RootAdmin = CFG->GetString( Prefix + "rootadmin", string( ) ); - string BNETCommandTrigger = CFG->GetString( Prefix + "commandtrigger", "!" ); + QString UserName = CFG->GetString( Prefix + "username", QString( ) ); + QString UserPassword = CFG->GetString( Prefix + "password", QString( ) ); + QString FirstChannel = CFG->GetString( Prefix + "firstchannel", "The Void" ); + QString RootAdmin = CFG->GetString( Prefix + "rootadmin", QString( ) ); + QString BNETCommandTrigger = CFG->GetString( Prefix + "commandtrigger", "!" ); if( BNETCommandTrigger.empty( ) ) BNETCommandTrigger = "!"; @@ -227,14 +227,14 @@ CGHost :: CGHost( CConfig *CFG, string configFile ) bool HoldFriends = CFG->GetInt( Prefix + "holdfriends", 1 ) == 0 ? false : true; bool HoldClan = CFG->GetInt( Prefix + "holdclan", 1 ) == 0 ? false : true; bool PublicCommands = CFG->GetInt( Prefix + "publiccommands", 1 ) == 0 ? false : true; - string BNLSServer = CFG->GetString( Prefix + "bnlsserver", string( ) ); + QString BNLSServer = CFG->GetString( Prefix + "bnlsserver", QString( ) ); int BNLSPort = CFG->GetInt( Prefix + "bnlsport", 9367 ); int BNLSWardenCookie = CFG->GetInt( Prefix + "bnlswardencookie", 0 ); unsigned char War3Version = CFG->GetInt( Prefix + "custom_war3version", 24 ); - BYTEARRAY EXEVersion = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversion", string( ) ), 4 ); - BYTEARRAY EXEVersionHash = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversionhash", string( ) ), 4 ); - string PasswordHashType = CFG->GetString( Prefix + "custom_passwordhashtype", string( ) ); - string PVPGNRealmName = CFG->GetString( Prefix + "custom_pvpgnrealmname", "PvPGN Realm" ); + BYTEARRAY EXEVersion = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversion", QString( ) ), 4 ); + BYTEARRAY EXEVersionHash = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversionhash", QString( ) ), 4 ); + QString PasswordHashType = CFG->GetString( Prefix + "custom_passwordhashtype", QString( ) ); + QString PVPGNRealmName = CFG->GetString( Prefix + "custom_pvpgnrealmname", "PvPGN Realm" ); uint32_t MaxMessageLength = CFG->GetInt( Prefix + "custom_maxmessagelength", 200 ); if( Server.empty( ) ) @@ -675,7 +675,7 @@ bool CGHost :: Update( long usecBlock ) } (*i)->DoRecv( &fd ); - string *RecvBuffer = (*i)->GetBytes( ); + QString *RecvBuffer = (*i)->GetBytes( ); BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes @@ -778,7 +778,7 @@ bool CGHost :: Update( long usecBlock ) { if( m_AutoHostMap->GetValid( ) ) { - string GameName = m_AutoHostGameName + " #" + UTIL_ToString( m_HostCounter ); + QString GameName = m_AutoHostGameName + " #" + UTIL_ToString( m_HostCounter ); if( GameName.size( ) <= 31 ) { @@ -923,7 +923,7 @@ void CGHost :: EventBNETConnectTimedOut( CBNET *bnet ) m_CurrentGame->SendAllChat( m_Language->ConnectingToBNETTimedOut( bnet->GetServer( ) ) ); } -void CGHost :: EventBNETWhisper( CBNET *bnet, string user, string message ) +void CGHost :: EventBNETWhisper( CBNET *bnet, QString user, QString message ) { if( m_AdminGame ) { @@ -937,7 +937,7 @@ void CGHost :: EventBNETWhisper( CBNET *bnet, string user, string message ) } } -void CGHost :: EventBNETChat( CBNET *bnet, string user, string message ) +void CGHost :: EventBNETChat( CBNET *bnet, QString user, QString message ) { if( m_AdminGame ) { @@ -951,7 +951,7 @@ void CGHost :: EventBNETChat( CBNET *bnet, string user, string message ) } } -void CGHost :: EventBNETEmote( CBNET *bnet, string user, string message ) +void CGHost :: EventBNETEmote( CBNET *bnet, QString user, QString message ) { if( m_AdminGame ) { @@ -993,20 +993,20 @@ void CGHost :: SetConfigs( CConfig *CFG ) delete m_Language; m_Language = new CLanguage( m_LanguageFile ); m_Warcraft3Path = UTIL_AddPathSeperator( CFG->GetString( "bot_war3path", "C:\\Program Files\\Warcraft III\\" ) ); - m_BindAddress = CFG->GetString( "bot_bindaddress", string( ) ); + m_BindAddress = CFG->GetString( "bot_bindaddress", QString( ) ); m_ReconnectWaitTime = CFG->GetInt( "bot_reconnectwaittime", 3 ); m_MaxGames = CFG->GetInt( "bot_maxgames", 5 ); - string BotCommandTrigger = CFG->GetString( "bot_commandtrigger", "!" ); + QString BotCommandTrigger = CFG->GetString( "bot_commandtrigger", "!" ); if( BotCommandTrigger.empty( ) ) BotCommandTrigger = "!"; m_CommandTrigger = BotCommandTrigger[0]; - m_MapCFGPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mapcfgpath", string( ) ) ); - m_SaveGamePath = UTIL_AddPathSeperator( CFG->GetString( "bot_savegamepath", string( ) ) ); - m_MapPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mappath", string( ) ) ); + m_MapCFGPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mapcfgpath", QString( ) ) ); + m_SaveGamePath = UTIL_AddPathSeperator( CFG->GetString( "bot_savegamepath", QString( ) ) ); + m_MapPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mappath", QString( ) ) ); m_SaveReplays = CFG->GetInt( "bot_savereplays", 0 ) == 0 ? false : true; - m_ReplayPath = UTIL_AddPathSeperator( CFG->GetString( "bot_replaypath", string( ) ) ); + m_ReplayPath = UTIL_AddPathSeperator( CFG->GetString( "bot_replaypath", QString( ) ) ); m_VirtualHostName = CFG->GetString( "bot_virtualhostname", "|cFF4080C0GHost" ); m_HideIPAddresses = CFG->GetInt( "bot_hideipaddresses", 0 ) == 0 ? false : true; m_CheckMultipleIPUsage = CFG->GetInt( "bot_checkmultipleipusage", 1 ) == 0 ? false : true; @@ -1053,7 +1053,7 @@ void CGHost :: SetConfigs( CConfig *CFG ) void CGHost :: ExtractScripts( ) { - string PatchMPQFileName = m_Warcraft3Path + "War3Patch.mpq"; + QString PatchMPQFileName = m_Warcraft3Path + "War3Patch.mpq"; HANDLE PatchMPQ; if( SFileOpenArchive( PatchMPQFileName.c_str( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &PatchMPQ ) ) @@ -1141,10 +1141,10 @@ void CGHost :: LoadIPToCountryData( ) else { unsigned char Percent = 0; - string Line; - string IP1; - string IP2; - string Country; + QString Line; + QString IP1; + QString IP2; + QString Country; CSVParser parser; // get length of file for the progress meter @@ -1188,7 +1188,7 @@ void CGHost :: LoadIPToCountryData( ) } } -void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, string gameName, string ownerName, string creatorName, string creatorServer, bool whisper ) +void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QString gameName, QString ownerName, QString creatorName, QString creatorServer, bool whisper ) { if( !m_Enabled ) { @@ -1248,8 +1248,8 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, st return; } - string MapPath1 = m_SaveGame->GetMapPath( ); - string MapPath2 = map->GetMapPath( ); + QString MapPath1 = m_SaveGame->GetMapPath( ); + QString MapPath2 = map->GetMapPath( ); transform( MapPath1.begin( ), MapPath1.end( ), MapPath1.begin( ), (int(*)(int))tolower ); transform( MapPath2.begin( ), MapPath2.end( ), MapPath2.begin( ), (int(*)(int))tolower ); @@ -1349,9 +1349,9 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, st } if( saveGame ) - (*i)->QueueGameCreate( gameState, gameName, string( ), map, m_SaveGame, m_CurrentGame->GetHostCounter( ) ); + (*i)->QueueGameCreate( gameState, gameName, QString( ), map, m_SaveGame, m_CurrentGame->GetHostCounter( ) ); else - (*i)->QueueGameCreate( gameState, gameName, string( ), map, NULL, m_CurrentGame->GetHostCounter( ) ); + (*i)->QueueGameCreate( gameState, gameName, QString( ), map, NULL, m_CurrentGame->GetHostCounter( ) ); } if( m_AdminGame ) diff --git a/ghost/ghost.h b/ghost/ghost.h index 947deb7..5aedbde 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -22,6 +22,7 @@ #define GHOST_H #include "includes.h" +#include // // CGHost @@ -43,8 +44,9 @@ class CMap; class CSaveGame; class CConfig; -class CGHost +class CGHost : public QObject { + Q_OBJECT public: CUDPSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) CTCPServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects @@ -69,11 +71,11 @@ class CGHost bool m_Exiting; // set to true to force ghost to shutdown next update (used by SignalCatcher) bool m_ExitingNice; // set to true to force ghost to disconnect from all battle.net connections and wait for all games to finish before shutting down bool m_Enabled; // set to false to prevent new games from being created - string m_Version; // GHost++ version string + QString m_Version; // GHost++ version QString uint32_t m_HostCounter; // the current host counter (a unique number to identify a game, incremented each time a game is created) - string m_AutoHostGameName; // the base game name to auto host with - string m_AutoHostOwner; - string m_AutoHostServer; + QString m_AutoHostGameName; // the base game name to auto host with + QString m_AutoHostOwner; + QString m_AutoHostServer; uint32_t m_AutoHostMaximumGames; // maximum number of games to auto host uint32_t m_AutoHostAutoStartPlayers; // when using auto hosting auto start the game when this many players have joined uint32_t m_LastAutoHostTime; // GetTime when the last auto host was attempted @@ -82,22 +84,22 @@ class CGHost double m_AutoHostMaximumScore; bool m_AllGamesFinished; // if all games finished (used when exiting nicely) uint32_t m_AllGamesFinishedTime; // GetTime when all games finished (used when exiting nicely) - string m_LanguageFile; // config value: language file - string m_Warcraft3Path; // config value: Warcraft 3 path + QString m_LanguageFile; // config value: language file + QString m_Warcraft3Path; // config value: Warcraft 3 path bool m_TFT; // config value: TFT enabled or not - string m_BindAddress; // config value: the address to host games on + QString m_BindAddress; // config value: the address to host games on uint16_t m_HostPort; // config value: the port to host games on bool m_Reconnect; // config value: GProxy++ reliable reconnects enabled or not uint16_t m_ReconnectPort; // config value: the port to listen for GProxy++ reliable reconnects on uint32_t m_ReconnectWaitTime; // config value: the maximum number of minutes to wait for a GProxy++ reliable reconnect uint32_t m_MaxGames; // config value: maximum number of games in progress char m_CommandTrigger; // config value: the command trigger inside games - string m_MapCFGPath; // config value: map cfg path - string m_SaveGamePath; // config value: savegame path - string m_MapPath; // config value: map path + QString m_MapCFGPath; // config value: map cfg path + QString m_SaveGamePath; // config value: savegame path + QString m_MapPath; // config value: map path bool m_SaveReplays; // config value: save replays - string m_ReplayPath; // config value: replay path - string m_VirtualHostName; // config value: virtual host name + QString m_ReplayPath; // config value: replay path + QString m_VirtualHostName; // config value: virtual host name bool m_HideIPAddresses; // config value: hide IP addresses from players bool m_CheckMultipleIPUsage; // config value: check for multiple IP address usage uint32_t m_SpoofChecks; // config value: do automatic spoof checks or not @@ -113,29 +115,29 @@ class CGHost bool m_LCPings; // config value: use LC style pings (divide actual pings by two) uint32_t m_AutoKickPing; // config value: auto kick players with ping higher than this uint32_t m_BanMethod; // config value: ban method (ban by name/ip/both) - string m_IPBlackListFile; // config value: IP blacklist file (ipblacklist.txt) + QString m_IPBlackListFile; // config value: IP blacklist file (ipblacklist.txt) uint32_t m_LobbyTimeLimit; // config value: auto close the game lobby after this many minutes without any reserved players uint32_t m_Latency; // config value: the latency (by default) uint32_t m_SyncLimit; // config value: the maximum number of packets a player can fall out of sync before starting the lag screen (by default) bool m_VoteKickAllowed; // config value: if votekicks are allowed or not uint32_t m_VoteKickPercentage; // config value: percentage of players required to vote yes for a votekick to pass - string m_DefaultMap; // config value: default map (map.cfg) - string m_MOTDFile; // config value: motd.txt - string m_GameLoadedFile; // config value: gameloaded.txt - string m_GameOverFile; // config value: gameover.txt + QString m_DefaultMap; // config value: default map (map.cfg) + QString m_MOTDFile; // config value: motd.txt + QString m_GameLoadedFile; // config value: gameloaded.txt + QString m_GameOverFile; // config value: gameover.txt bool m_LocalAdminMessages; // config value: send local admin messages or not bool m_AdminGameCreate; // config value: create the admin game or not uint16_t m_AdminGamePort; // config value: the port to host the admin game on - string m_AdminGamePassword; // config value: the admin game password - string m_AdminGameMap; // config value: the admin game map config to use + QString m_AdminGamePassword; // config value: the admin game password + QString m_AdminGameMap; // config value: the admin game map config to use unsigned char m_LANWar3Version; // config value: LAN warcraft 3 version uint32_t m_ReplayWar3Version; // config value: replay warcraft 3 version (for saving replays) uint32_t m_ReplayBuildNumber; // config value: replay build number (for saving replays) bool m_TCPNoDelay; // config value: use Nagle's algorithm or not uint32_t m_MatchMakingMethod; // config value: the matchmaking method - string m_ConfigFile; + QString m_ConfigFile; - CGHost( CConfig *CFG, string configFile ); + CGHost( CConfig *CFG, QString configFile ); ~CGHost( ); // processing functions @@ -151,9 +153,9 @@ class CGHost void EventBNETGameRefreshed( CBNET *bnet ); void EventBNETGameRefreshFailed( CBNET *bnet ); void EventBNETConnectTimedOut( CBNET *bnet ); - void EventBNETWhisper( CBNET *bnet, string user, string message ); - void EventBNETChat( CBNET *bnet, string user, string message ); - void EventBNETEmote( CBNET *bnet, string user, string message ); + void EventBNETWhisper( CBNET *bnet, QString user, QString message ); + void EventBNETChat( CBNET *bnet, QString user, QString message ); + void EventBNETEmote( CBNET *bnet, QString user, QString message ); void EventGameDeleted( CBaseGame *game ); // other functions @@ -162,7 +164,7 @@ class CGHost void SetConfigs( CConfig *CFG ); void ExtractScripts( ); void LoadIPToCountryData( ); - void CreateGame( CMap *map, unsigned char gameState, bool saveGame, string gameName, string ownerName, string creatorName, string creatorServer, bool whisper ); + void CreateGame( CMap *map, unsigned char gameState, bool saveGame, QString gameName, QString ownerName, QString creatorName, QString creatorServer, bool whisper ); }; #endif diff --git a/ghost/ghost.pro b/ghost/ghost.pro index bd41067..593feb2 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -13,7 +13,6 @@ SOURCES += util.cpp \ statsdota.cpp \ stats.cpp \ sqlite3.c \ - socket.cpp \ sha1.cpp \ savegame.cpp \ replay.cpp \ diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index 43ec7df..68f70c7 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -52,77 +52,77 @@ bool CGHostDB :: Commit( ) return true; } -uint32_t CGHostDB :: AdminCount( string server ) +uint32_t CGHostDB :: AdminCount( QString server ) { return 0; } -bool CGHostDB :: AdminCheck( string server, string user ) +bool CGHostDB :: AdminCheck( QString server, QString user ) { return false; } -bool CGHostDB :: AdminAdd( string server, string user ) +bool CGHostDB :: AdminAdd( QString server, QString user ) { return false; } -bool CGHostDB :: AdminRemove( string server, string user ) +bool CGHostDB :: AdminRemove( QString server, QString user ) { return false; } -vector CGHostDB :: AdminList( string server ) +vector CGHostDB :: AdminList( QString server ) { - return vector( ); + return vector( ); } -uint32_t CGHostDB :: BanCount( string server ) +uint32_t CGHostDB :: BanCount( QString server ) { return 0; } -CDBBan *CGHostDB :: BanCheck( string server, string user, string ip ) +CDBBan *CGHostDB :: BanCheck( QString server, QString user, QString ip ) { return NULL; } -bool CGHostDB :: BanAdd( string server, string user, string ip, string gamename, string admin, string reason ) +bool CGHostDB :: BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { return false; } -bool CGHostDB :: BanRemove( string server, string user ) +bool CGHostDB :: BanRemove( QString server, QString user ) { return false; } -bool CGHostDB :: BanRemove( string user ) +bool CGHostDB :: BanRemove( QString user ) { return false; } -vector CGHostDB :: BanList( string server ) +vector CGHostDB :: BanList( QString server ) { return vector( ); } -uint32_t CGHostDB :: GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) +uint32_t CGHostDB :: GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) { return 0; } -uint32_t CGHostDB :: GamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ) +uint32_t CGHostDB :: GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { return 0; } -uint32_t CGHostDB :: GamePlayerCount( string name ) +uint32_t CGHostDB :: GamePlayerCount( QString name ) { return 0; } -CDBGamePlayerSummary *CGHostDB :: GamePlayerSummaryCheck( string name ) +CDBGamePlayerSummary *CGHostDB :: GamePlayerSummaryCheck( QString name ) { return NULL; } @@ -132,37 +132,37 @@ uint32_t CGHostDB :: DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min return 0; } -uint32_t CGHostDB :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +uint32_t CGHostDB :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) { return 0; } -uint32_t CGHostDB :: DotAPlayerCount( string name ) +uint32_t CGHostDB :: DotAPlayerCount( QString name ) { return 0; } -CDBDotAPlayerSummary *CGHostDB :: DotAPlayerSummaryCheck( string name ) +CDBDotAPlayerSummary *CGHostDB :: DotAPlayerSummaryCheck( QString name ) { return NULL; } -string CGHostDB :: FromCheck( uint32_t ip ) +QString CGHostDB :: FromCheck( uint32_t ip ) { return "??"; } -bool CGHostDB :: FromAdd( uint32_t ip1, uint32_t ip2, string country ) +bool CGHostDB :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) { return false; } -bool CGHostDB :: DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) +bool CGHostDB :: DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) { return false; } -uint32_t CGHostDB :: W3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ) +uint32_t CGHostDB :: W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) { return 0; } @@ -177,7 +177,7 @@ bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, map var_reals ) return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, map var_strings ) +bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, map var_strings ) { return false; } @@ -187,72 +187,72 @@ void CGHostDB :: CreateThread( CBaseCallable *callable ) callable->SetReady( true ); } -CCallableAdminCount *CGHostDB :: ThreadedAdminCount( string server ) +CCallableAdminCount *CGHostDB :: ThreadedAdminCount( QString server ) { return NULL; } -CCallableAdminCheck *CGHostDB :: ThreadedAdminCheck( string server, string user ) +CCallableAdminCheck *CGHostDB :: ThreadedAdminCheck( QString server, QString user ) { return NULL; } -CCallableAdminAdd *CGHostDB :: ThreadedAdminAdd( string server, string user ) +CCallableAdminAdd *CGHostDB :: ThreadedAdminAdd( QString server, QString user ) { return NULL; } -CCallableAdminRemove *CGHostDB :: ThreadedAdminRemove( string server, string user ) +CCallableAdminRemove *CGHostDB :: ThreadedAdminRemove( QString server, QString user ) { return NULL; } -CCallableAdminList *CGHostDB :: ThreadedAdminList( string server ) +CCallableAdminList *CGHostDB :: ThreadedAdminList( QString server ) { return NULL; } -CCallableBanCount *CGHostDB :: ThreadedBanCount( string server ) +CCallableBanCount *CGHostDB :: ThreadedBanCount( QString server ) { return NULL; } -CCallableBanCheck *CGHostDB :: ThreadedBanCheck( string server, string user, string ip ) +CCallableBanCheck *CGHostDB :: ThreadedBanCheck( QString server, QString user, QString ip ) { return NULL; } -CCallableBanAdd *CGHostDB :: ThreadedBanAdd( string server, string user, string ip, string gamename, string admin, string reason ) +CCallableBanAdd *CGHostDB :: ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { return NULL; } -CCallableBanRemove *CGHostDB :: ThreadedBanRemove( string server, string user ) +CCallableBanRemove *CGHostDB :: ThreadedBanRemove( QString server, QString user ) { return NULL; } -CCallableBanRemove *CGHostDB :: ThreadedBanRemove( string user ) +CCallableBanRemove *CGHostDB :: ThreadedBanRemove( QString user ) { return NULL; } -CCallableBanList *CGHostDB :: ThreadedBanList( string server ) +CCallableBanList *CGHostDB :: ThreadedBanList( QString server ) { return NULL; } -CCallableGameAdd *CGHostDB :: ThreadedGameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) +CCallableGameAdd *CGHostDB :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) { return NULL; } -CCallableGamePlayerAdd *CGHostDB :: ThreadedGamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ) +CCallableGamePlayerAdd *CGHostDB :: ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { return NULL; } -CCallableGamePlayerSummaryCheck *CGHostDB :: ThreadedGamePlayerSummaryCheck( string name ) +CCallableGamePlayerSummaryCheck *CGHostDB :: ThreadedGamePlayerSummaryCheck( QString name ) { return NULL; } @@ -262,27 +262,27 @@ CCallableDotAGameAdd *CGHostDB :: ThreadedDotAGameAdd( uint32_t gameid, uint32_t return NULL; } -CCallableDotAPlayerAdd *CGHostDB :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +CCallableDotAPlayerAdd *CGHostDB :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) { return NULL; } -CCallableDotAPlayerSummaryCheck *CGHostDB :: ThreadedDotAPlayerSummaryCheck( string name ) +CCallableDotAPlayerSummaryCheck *CGHostDB :: ThreadedDotAPlayerSummaryCheck( QString name ) { return NULL; } -CCallableDownloadAdd *CGHostDB :: ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) +CCallableDownloadAdd *CGHostDB :: ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) { return NULL; } -CCallableScoreCheck *CGHostDB :: ThreadedScoreCheck( string category, string name, string server ) +CCallableScoreCheck *CGHostDB :: ThreadedScoreCheck( QString category, QString name, QString server ) { return NULL; } -CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ) +CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) { return NULL; } @@ -297,7 +297,7 @@ CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) { return NULL; } @@ -421,7 +421,7 @@ CCallableW3MMDVarAdd :: ~CCallableW3MMDVarAdd( ) // CDBBan // -CDBBan :: CDBBan( string nServer, string nName, string nIP, string nDate, string nGameName, string nAdmin, string nReason ) +CDBBan :: CDBBan( QString nServer, QString nName, QString nIP, QString nDate, QString nGameName, QString nAdmin, QString nReason ) { m_Server = nServer; m_Name = nName; @@ -441,7 +441,7 @@ CDBBan :: ~CDBBan( ) // CDBGame // -CDBGame :: CDBGame( uint32_t nID, string nServer, string nMap, string nDateTime, string nGameName, string nOwnerName, uint32_t nDuration ) +CDBGame :: CDBGame( uint32_t nID, QString nServer, QString nMap, QString nDateTime, QString nGameName, QString nOwnerName, uint32_t nDuration ) { m_ID = nID; m_Server = nServer; @@ -461,7 +461,7 @@ CDBGame :: ~CDBGame( ) // CDBGamePlayer // -CDBGamePlayer :: CDBGamePlayer( uint32_t nID, uint32_t nGameID, string nName, string nIP, uint32_t nSpoofed, string nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, string nLeftReason, uint32_t nTeam, uint32_t nColour ) +CDBGamePlayer :: CDBGamePlayer( uint32_t nID, uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour ) { m_ID = nID; m_GameID = nGameID; @@ -486,7 +486,7 @@ CDBGamePlayer :: ~CDBGamePlayer( ) // CDBGamePlayerSummary // -CDBGamePlayerSummary :: CDBGamePlayerSummary( string nServer, string nName, string nFirstGameDateTime, string nLastGameDateTime, uint32_t nTotalGames, uint32_t nMinLoadingTime, uint32_t nAvgLoadingTime, uint32_t nMaxLoadingTime, uint32_t nMinLeftPercent, uint32_t nAvgLeftPercent, uint32_t nMaxLeftPercent, uint32_t nMinDuration, uint32_t nAvgDuration, uint32_t nMaxDuration ) +CDBGamePlayerSummary :: CDBGamePlayerSummary( QString nServer, QString nName, QString nFirstGameDateTime, QString nLastGameDateTime, uint32_t nTotalGames, uint32_t nMinLoadingTime, uint32_t nAvgLoadingTime, uint32_t nMaxLoadingTime, uint32_t nMinLeftPercent, uint32_t nAvgLeftPercent, uint32_t nMaxLeftPercent, uint32_t nMinDuration, uint32_t nAvgDuration, uint32_t nMaxDuration ) { m_Server = nServer; m_Name = nName; @@ -549,7 +549,7 @@ CDBDotAPlayer :: CDBDotAPlayer( ) m_CourierKills = 0; } -CDBDotAPlayer :: CDBDotAPlayer( uint32_t nID, uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, string nItem1, string nItem2, string nItem3, string nItem4, string nItem5, string nItem6, string nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ) +CDBDotAPlayer :: CDBDotAPlayer( uint32_t nID, uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ) { m_ID = nID; m_GameID = nGameID; @@ -579,15 +579,15 @@ CDBDotAPlayer :: ~CDBDotAPlayer( ) } -string CDBDotAPlayer :: GetItem( unsigned int i ) +QString CDBDotAPlayer :: GetItem( unsigned int i ) { if( i < 6 ) return m_Items[i]; - return string( ); + return QString( ); } -void CDBDotAPlayer :: SetItem( unsigned int i, string item ) +void CDBDotAPlayer :: SetItem( unsigned int i, QString item ) { if( i < 6 ) m_Items[i] = item; @@ -597,7 +597,7 @@ void CDBDotAPlayer :: SetItem( unsigned int i, string item ) // CDBDotAPlayerSummary // -CDBDotAPlayerSummary :: CDBDotAPlayerSummary( string nServer, string nName, uint32_t nTotalGames, uint32_t nTotalWins, uint32_t nTotalLosses, uint32_t nTotalKills, uint32_t nTotalDeaths, uint32_t nTotalCreepKills, uint32_t nTotalCreepDenies, uint32_t nTotalAssists, uint32_t nTotalNeutralKills, uint32_t nTotalTowerKills, uint32_t nTotalRaxKills, uint32_t nTotalCourierKills ) +CDBDotAPlayerSummary :: CDBDotAPlayerSummary( QString nServer, QString nName, uint32_t nTotalGames, uint32_t nTotalWins, uint32_t nTotalLosses, uint32_t nTotalKills, uint32_t nTotalDeaths, uint32_t nTotalCreepKills, uint32_t nTotalCreepDenies, uint32_t nTotalAssists, uint32_t nTotalNeutralKills, uint32_t nTotalTowerKills, uint32_t nTotalRaxKills, uint32_t nTotalCourierKills ) { m_Server = nServer; m_Name = nName; diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index 48934f9..1f7f229 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -52,21 +52,21 @@ class CDBGamePlayer; class CDBGamePlayerSummary; class CDBDotAPlayerSummary; -typedef pair VarP; +typedef pair VarP; class CGHostDB { protected: bool m_HasError; - string m_Error; + QString m_Error; public: CGHostDB( CConfig *CFG ); virtual ~CGHostDB( ); bool HasError( ) { return m_HasError; } - string GetError( ) { return m_Error; } - virtual string GetStatus( ) { return "DB STATUS --- OK"; } + QString GetError( ) { return m_Error; } + virtual QString GetStatus( ) { return "DB STATUS --- OK"; } virtual void RecoverCallable( CBaseCallable *callable ); @@ -74,59 +74,59 @@ class CGHostDB virtual bool Begin( ); virtual bool Commit( ); - virtual uint32_t AdminCount( string server ); - virtual bool AdminCheck( string server, string user ); - virtual bool AdminAdd( string server, string user ); - virtual bool AdminRemove( string server, string user ); - virtual vector AdminList( string server ); - virtual uint32_t BanCount( string server ); - virtual CDBBan *BanCheck( string server, string user, string ip ); - virtual bool BanAdd( string server, string user, string ip, string gamename, string admin, string reason ); - virtual bool BanRemove( string server, string user ); - virtual bool BanRemove( string user ); - virtual vector BanList( string server ); - virtual uint32_t GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); - virtual uint32_t GamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); - virtual uint32_t GamePlayerCount( string name ); - virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( string name ); + virtual uint32_t AdminCount( QString server ); + virtual bool AdminCheck( QString server, QString user ); + virtual bool AdminAdd( QString server, QString user ); + virtual bool AdminRemove( QString server, QString user ); + virtual vector AdminList( QString server ); + virtual uint32_t BanCount( QString server ); + virtual CDBBan *BanCheck( QString server, QString user, QString ip ); + virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); + virtual bool BanRemove( QString server, QString user ); + virtual bool BanRemove( QString user ); + virtual vector BanList( QString server ); + virtual uint32_t GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); + virtual uint32_t GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual uint32_t GamePlayerCount( QString name ); + virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( QString name ); virtual uint32_t DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual uint32_t DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual uint32_t DotAPlayerCount( string name ); - virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( string name ); - virtual string FromCheck( uint32_t ip ); - virtual bool FromAdd( uint32_t ip1, uint32_t ip2, string country ); - virtual bool DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); - virtual uint32_t W3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); + virtual uint32_t DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual uint32_t DotAPlayerCount( QString name ); + virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( QString name ); + virtual QString FromCheck( uint32_t ip ); + virtual bool FromAdd( uint32_t ip1, uint32_t ip2, QString country ); + virtual bool DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual uint32_t W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); virtual bool W3MMDVarAdd( uint32_t gameid, map var_ints ); virtual bool W3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual bool W3MMDVarAdd( uint32_t gameid, map var_strings ); // threaded database functions virtual void CreateThread( CBaseCallable *callable ); - virtual CCallableAdminCount *ThreadedAdminCount( string server ); - virtual CCallableAdminCheck *ThreadedAdminCheck( string server, string user ); - virtual CCallableAdminAdd *ThreadedAdminAdd( string server, string user ); - virtual CCallableAdminRemove *ThreadedAdminRemove( string server, string user ); - virtual CCallableAdminList *ThreadedAdminList( string server ); - virtual CCallableBanCount *ThreadedBanCount( string server ); - virtual CCallableBanCheck *ThreadedBanCheck( string server, string user, string ip ); - virtual CCallableBanAdd *ThreadedBanAdd( string server, string user, string ip, string gamename, string admin, string reason ); - virtual CCallableBanRemove *ThreadedBanRemove( string server, string user ); - virtual CCallableBanRemove *ThreadedBanRemove( string user ); - virtual CCallableBanList *ThreadedBanList( string server ); - virtual CCallableGameAdd *ThreadedGameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); - virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); - virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( string name ); + virtual CCallableAdminCount *ThreadedAdminCount( QString server ); + virtual CCallableAdminCheck *ThreadedAdminCheck( QString server, QString user ); + virtual CCallableAdminAdd *ThreadedAdminAdd( QString server, QString user ); + virtual CCallableAdminRemove *ThreadedAdminRemove( QString server, QString user ); + virtual CCallableAdminList *ThreadedAdminList( QString server ); + virtual CCallableBanCount *ThreadedBanCount( QString server ); + virtual CCallableBanCheck *ThreadedBanCheck( QString server, QString user, QString ip ); + virtual CCallableBanAdd *ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); + virtual CCallableBanRemove *ThreadedBanRemove( QString server, QString user ); + virtual CCallableBanRemove *ThreadedBanRemove( QString user ); + virtual CCallableBanList *ThreadedBanList( QString server ); + virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); + virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( QString name ); virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( string name ); - virtual CCallableDownloadAdd *ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); - virtual CCallableScoreCheck *ThreadedScoreCheck( string category, string name, string server ); - virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); + virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); + virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual CCallableScoreCheck *ThreadedScoreCheck( QString category, QString name, QString server ); + virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ); }; // @@ -155,7 +155,7 @@ class CGHostDB class CBaseCallable { protected: - string m_Error; + QString m_Error; volatile bool m_Ready; uint32_t m_StartTicks; uint32_t m_EndTicks; @@ -169,7 +169,7 @@ class CBaseCallable virtual void Init( ); virtual void Close( ); - virtual string GetError( ) { return m_Error; } + virtual QString GetError( ) { return m_Error; } virtual bool GetReady( ) { return m_Ready; } virtual void SetReady( bool nReady ) { m_Ready = nReady; } virtual uint32_t GetElapsed( ) { return m_Ready ? m_EndTicks - m_StartTicks : 0; } @@ -178,14 +178,14 @@ class CBaseCallable class CCallableAdminCount : virtual public CBaseCallable { protected: - string m_Server; + QString m_Server; uint32_t m_Result; public: - CCallableAdminCount( string nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } + CCallableAdminCount( QString nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } virtual ~CCallableAdminCount( ); - virtual string GetServer( ) { return m_Server; } + virtual QString GetServer( ) { return m_Server; } virtual uint32_t GetResult( ) { return m_Result; } virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } }; @@ -193,16 +193,16 @@ class CCallableAdminCount : virtual public CBaseCallable class CCallableAdminCheck : virtual public CBaseCallable { protected: - string m_Server; - string m_User; + QString m_Server; + QString m_User; bool m_Result; public: - CCallableAdminCheck( string nServer, string nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } + CCallableAdminCheck( QString nServer, QString nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } virtual ~CCallableAdminCheck( ); - virtual string GetServer( ) { return m_Server; } - virtual string GetUser( ) { return m_User; } + virtual QString GetServer( ) { return m_Server; } + virtual QString GetUser( ) { return m_User; } virtual bool GetResult( ) { return m_Result; } virtual void SetResult( bool nResult ) { m_Result = nResult; } }; @@ -210,16 +210,16 @@ class CCallableAdminCheck : virtual public CBaseCallable class CCallableAdminAdd : virtual public CBaseCallable { protected: - string m_Server; - string m_User; + QString m_Server; + QString m_User; bool m_Result; public: - CCallableAdminAdd( string nServer, string nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } + CCallableAdminAdd( QString nServer, QString nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } virtual ~CCallableAdminAdd( ); - virtual string GetServer( ) { return m_Server; } - virtual string GetUser( ) { return m_User; } + virtual QString GetServer( ) { return m_Server; } + virtual QString GetUser( ) { return m_User; } virtual bool GetResult( ) { return m_Result; } virtual void SetResult( bool nResult ) { m_Result = nResult; } }; @@ -227,16 +227,16 @@ class CCallableAdminAdd : virtual public CBaseCallable class CCallableAdminRemove : virtual public CBaseCallable { protected: - string m_Server; - string m_User; + QString m_Server; + QString m_User; bool m_Result; public: - CCallableAdminRemove( string nServer, string nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } + CCallableAdminRemove( QString nServer, QString nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } virtual ~CCallableAdminRemove( ); - virtual string GetServer( ) { return m_Server; } - virtual string GetUser( ) { return m_User; } + virtual QString GetServer( ) { return m_Server; } + virtual QString GetUser( ) { return m_User; } virtual bool GetResult( ) { return m_Result; } virtual void SetResult( bool nResult ) { m_Result = nResult; } }; @@ -244,28 +244,28 @@ class CCallableAdminRemove : virtual public CBaseCallable class CCallableAdminList : virtual public CBaseCallable { protected: - string m_Server; - vector m_Result; + QString m_Server; + vector m_Result; public: - CCallableAdminList( string nServer ) : CBaseCallable( ), m_Server( nServer ) { } + CCallableAdminList( QString nServer ) : CBaseCallable( ), m_Server( nServer ) { } virtual ~CCallableAdminList( ); - virtual vector GetResult( ) { return m_Result; } - virtual void SetResult( vector nResult ) { m_Result = nResult; } + virtual vector GetResult( ) { return m_Result; } + virtual void SetResult( vector nResult ) { m_Result = nResult; } }; class CCallableBanCount : virtual public CBaseCallable { protected: - string m_Server; + QString m_Server; uint32_t m_Result; public: - CCallableBanCount( string nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } + CCallableBanCount( QString nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } virtual ~CCallableBanCount( ); - virtual string GetServer( ) { return m_Server; } + virtual QString GetServer( ) { return m_Server; } virtual uint32_t GetResult( ) { return m_Result; } virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } }; @@ -273,18 +273,18 @@ class CCallableBanCount : virtual public CBaseCallable class CCallableBanCheck : virtual public CBaseCallable { protected: - string m_Server; - string m_User; - string m_IP; + QString m_Server; + QString m_User; + QString m_IP; CDBBan *m_Result; public: - CCallableBanCheck( string nServer, string nUser, string nIP ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_IP( nIP ), m_Result( NULL ) { } + CCallableBanCheck( QString nServer, QString nUser, QString nIP ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_IP( nIP ), m_Result( NULL ) { } virtual ~CCallableBanCheck( ); - virtual string GetServer( ) { return m_Server; } - virtual string GetUser( ) { return m_User; } - virtual string GetIP( ) { return m_IP; } + virtual QString GetServer( ) { return m_Server; } + virtual QString GetUser( ) { return m_User; } + virtual QString GetIP( ) { return m_IP; } virtual CDBBan *GetResult( ) { return m_Result; } virtual void SetResult( CDBBan *nResult ) { m_Result = nResult; } }; @@ -292,24 +292,24 @@ class CCallableBanCheck : virtual public CBaseCallable class CCallableBanAdd : virtual public CBaseCallable { protected: - string m_Server; - string m_User; - string m_IP; - string m_GameName; - string m_Admin; - string m_Reason; + QString m_Server; + QString m_User; + QString m_IP; + QString m_GameName; + QString m_Admin; + QString m_Reason; bool m_Result; public: - CCallableBanAdd( string nServer, string nUser, string nIP, string nGameName, string nAdmin, string nReason ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_IP( nIP ), m_GameName( nGameName ), m_Admin( nAdmin ), m_Reason( nReason ), m_Result( false ) { } + CCallableBanAdd( QString nServer, QString nUser, QString nIP, QString nGameName, QString nAdmin, QString nReason ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_IP( nIP ), m_GameName( nGameName ), m_Admin( nAdmin ), m_Reason( nReason ), m_Result( false ) { } virtual ~CCallableBanAdd( ); - virtual string GetServer( ) { return m_Server; } - virtual string GetUser( ) { return m_User; } - virtual string GetIP( ) { return m_IP; } - virtual string GetGameName( ) { return m_GameName; } - virtual string GetAdmin( ) { return m_Admin; } - virtual string GetReason( ) { return m_Reason; } + virtual QString GetServer( ) { return m_Server; } + virtual QString GetUser( ) { return m_User; } + virtual QString GetIP( ) { return m_IP; } + virtual QString GetGameName( ) { return m_GameName; } + virtual QString GetAdmin( ) { return m_Admin; } + virtual QString GetReason( ) { return m_Reason; } virtual bool GetResult( ) { return m_Result; } virtual void SetResult( bool nResult ) { m_Result = nResult; } }; @@ -317,16 +317,16 @@ class CCallableBanAdd : virtual public CBaseCallable class CCallableBanRemove : virtual public CBaseCallable { protected: - string m_Server; - string m_User; + QString m_Server; + QString m_User; bool m_Result; public: - CCallableBanRemove( string nServer, string nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } + CCallableBanRemove( QString nServer, QString nUser ) : CBaseCallable( ), m_Server( nServer ), m_User( nUser ), m_Result( false ) { } virtual ~CCallableBanRemove( ); - virtual string GetServer( ) { return m_Server; } - virtual string GetUser( ) { return m_User; } + virtual QString GetServer( ) { return m_Server; } + virtual QString GetUser( ) { return m_User; } virtual bool GetResult( ) { return m_Result; } virtual void SetResult( bool nResult ) { m_Result = nResult; } }; @@ -334,11 +334,11 @@ class CCallableBanRemove : virtual public CBaseCallable class CCallableBanList : virtual public CBaseCallable { protected: - string m_Server; + QString m_Server; vector m_Result; public: - CCallableBanList( string nServer ) : CBaseCallable( ), m_Server( nServer ) { } + CCallableBanList( QString nServer ) : CBaseCallable( ), m_Server( nServer ) { } virtual ~CCallableBanList( ); virtual vector GetResult( ) { return m_Result; } @@ -348,18 +348,18 @@ class CCallableBanList : virtual public CBaseCallable class CCallableGameAdd : virtual public CBaseCallable { protected: - string m_Server; - string m_Map; - string m_GameName; - string m_OwnerName; + QString m_Server; + QString m_Map; + QString m_GameName; + QString m_OwnerName; uint32_t m_Duration; uint32_t m_GameState; - string m_CreatorName; - string m_CreatorServer; + QString m_CreatorName; + QString m_CreatorServer; uint32_t m_Result; public: - CCallableGameAdd( string nServer, string nMap, string nGameName, string nOwnerName, uint32_t nDuration, uint32_t nGameState, string nCreatorName, string nCreatorServer ) : CBaseCallable( ), m_Server( nServer ), m_Map( nMap ), m_GameName( nGameName ), m_OwnerName( nOwnerName ), m_Duration( nDuration ), m_GameState( nGameState ), m_CreatorName( nCreatorName ), m_CreatorServer( nCreatorServer ), m_Result( 0 ) { } + CCallableGameAdd( QString nServer, QString nMap, QString nGameName, QString nOwnerName, uint32_t nDuration, uint32_t nGameState, QString nCreatorName, QString nCreatorServer ) : CBaseCallable( ), m_Server( nServer ), m_Map( nMap ), m_GameName( nGameName ), m_OwnerName( nOwnerName ), m_Duration( nDuration ), m_GameState( nGameState ), m_CreatorName( nCreatorName ), m_CreatorServer( nCreatorServer ), m_Result( 0 ) { } virtual ~CCallableGameAdd( ); virtual uint32_t GetResult( ) { return m_Result; } @@ -370,20 +370,20 @@ class CCallableGamePlayerAdd : virtual public CBaseCallable { protected: uint32_t m_GameID; - string m_Name; - string m_IP; + QString m_Name; + QString m_IP; uint32_t m_Spoofed; - string m_SpoofedRealm; + QString m_SpoofedRealm; uint32_t m_Reserved; uint32_t m_LoadingTime; uint32_t m_Left; - string m_LeftReason; + QString m_LeftReason; uint32_t m_Team; uint32_t m_Colour; uint32_t m_Result; public: - CCallableGamePlayerAdd( uint32_t nGameID, string nName, string nIP, uint32_t nSpoofed, string nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, string nLeftReason, uint32_t nTeam, uint32_t nColour ) : CBaseCallable( ), m_GameID( nGameID ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_Reserved( nReserved ), m_LoadingTime( nLoadingTime ), m_Left( nLeft ), m_LeftReason( nLeftReason ), m_Team( nTeam ), m_Colour( nColour ), m_Result( 0 ) { } + CCallableGamePlayerAdd( uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour ) : CBaseCallable( ), m_GameID( nGameID ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_Reserved( nReserved ), m_LoadingTime( nLoadingTime ), m_Left( nLeft ), m_LeftReason( nLeftReason ), m_Team( nTeam ), m_Colour( nColour ), m_Result( 0 ) { } virtual ~CCallableGamePlayerAdd( ); virtual uint32_t GetResult( ) { return m_Result; } @@ -393,14 +393,14 @@ class CCallableGamePlayerAdd : virtual public CBaseCallable class CCallableGamePlayerSummaryCheck : virtual public CBaseCallable { protected: - string m_Name; + QString m_Name; CDBGamePlayerSummary *m_Result; public: - CCallableGamePlayerSummaryCheck( string nName ) : CBaseCallable( ), m_Name( nName ), m_Result( NULL ) { } + CCallableGamePlayerSummaryCheck( QString nName ) : CBaseCallable( ), m_Name( nName ), m_Result( NULL ) { } virtual ~CCallableGamePlayerSummaryCheck( ); - virtual string GetName( ) { return m_Name; } + virtual QString GetName( ) { return m_Name; } virtual CDBGamePlayerSummary *GetResult( ) { return m_Result; } virtual void SetResult( CDBGamePlayerSummary *nResult ) { m_Result = nResult; } }; @@ -434,13 +434,13 @@ class CCallableDotAPlayerAdd : virtual public CBaseCallable uint32_t m_Assists; uint32_t m_Gold; uint32_t m_NeutralKills; - string m_Item1; - string m_Item2; - string m_Item3; - string m_Item4; - string m_Item5; - string m_Item6; - string m_Hero; + QString m_Item1; + QString m_Item2; + QString m_Item3; + QString m_Item4; + QString m_Item5; + QString m_Item6; + QString m_Hero; uint32_t m_NewColour; uint32_t m_TowerKills; uint32_t m_RaxKills; @@ -448,7 +448,7 @@ class CCallableDotAPlayerAdd : virtual public CBaseCallable uint32_t m_Result; public: - CCallableDotAPlayerAdd( uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, string nItem1, string nItem2, string nItem3, string nItem4, string nItem5, string nItem6, string nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ) : CBaseCallable( ), m_GameID( nGameID ), m_Colour( nColour ), m_Kills( nKills ), m_Deaths( nDeaths ), m_CreepKills( nCreepKills ), m_CreepDenies( nCreepDenies ), m_Assists( nAssists ), m_Gold( nGold ), m_NeutralKills( nNeutralKills ), m_Item1( nItem1 ), m_Item2( nItem2 ), m_Item3( nItem3 ), m_Item4( nItem4 ), m_Item5( nItem5 ), m_Item6( nItem6 ), m_Hero( nHero ), m_NewColour( nNewColour ), m_TowerKills( nTowerKills ), m_RaxKills( nRaxKills ), m_CourierKills( nCourierKills ), m_Result( 0 ) { } + CCallableDotAPlayerAdd( uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ) : CBaseCallable( ), m_GameID( nGameID ), m_Colour( nColour ), m_Kills( nKills ), m_Deaths( nDeaths ), m_CreepKills( nCreepKills ), m_CreepDenies( nCreepDenies ), m_Assists( nAssists ), m_Gold( nGold ), m_NeutralKills( nNeutralKills ), m_Item1( nItem1 ), m_Item2( nItem2 ), m_Item3( nItem3 ), m_Item4( nItem4 ), m_Item5( nItem5 ), m_Item6( nItem6 ), m_Hero( nHero ), m_NewColour( nNewColour ), m_TowerKills( nTowerKills ), m_RaxKills( nRaxKills ), m_CourierKills( nCourierKills ), m_Result( 0 ) { } virtual ~CCallableDotAPlayerAdd( ); virtual uint32_t GetResult( ) { return m_Result; } @@ -458,14 +458,14 @@ class CCallableDotAPlayerAdd : virtual public CBaseCallable class CCallableDotAPlayerSummaryCheck : virtual public CBaseCallable { protected: - string m_Name; + QString m_Name; CDBDotAPlayerSummary *m_Result; public: - CCallableDotAPlayerSummaryCheck( string nName ) : CBaseCallable( ), m_Name( nName ), m_Result( NULL ) { } + CCallableDotAPlayerSummaryCheck( QString nName ) : CBaseCallable( ), m_Name( nName ), m_Result( NULL ) { } virtual ~CCallableDotAPlayerSummaryCheck( ); - virtual string GetName( ) { return m_Name; } + virtual QString GetName( ) { return m_Name; } virtual CDBDotAPlayerSummary *GetResult( ) { return m_Result; } virtual void SetResult( CDBDotAPlayerSummary *nResult ) { m_Result = nResult; } }; @@ -473,17 +473,17 @@ class CCallableDotAPlayerSummaryCheck : virtual public CBaseCallable class CCallableDownloadAdd : virtual public CBaseCallable { protected: - string m_Map; + QString m_Map; uint32_t m_MapSize; - string m_Name; - string m_IP; + QString m_Name; + QString m_IP; uint32_t m_Spoofed; - string m_SpoofedRealm; + QString m_SpoofedRealm; uint32_t m_DownloadTime; bool m_Result; public: - CCallableDownloadAdd( string nMap, uint32_t nMapSize, string nName, string nIP, uint32_t nSpoofed, string nSpoofedRealm, uint32_t nDownloadTime ) : CBaseCallable( ), m_Map( nMap ), m_MapSize( nMapSize ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_DownloadTime( nDownloadTime ), m_Result( false ) { } + CCallableDownloadAdd( QString nMap, uint32_t nMapSize, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nDownloadTime ) : CBaseCallable( ), m_Map( nMap ), m_MapSize( nMapSize ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_DownloadTime( nDownloadTime ), m_Result( false ) { } virtual ~CCallableDownloadAdd( ); virtual bool GetResult( ) { return m_Result; } @@ -493,16 +493,16 @@ class CCallableDownloadAdd : virtual public CBaseCallable class CCallableScoreCheck : virtual public CBaseCallable { protected: - string m_Category; - string m_Name; - string m_Server; + QString m_Category; + QString m_Name; + QString m_Server; double m_Result; public: - CCallableScoreCheck( string nCategory, string nName, string nServer ) : CBaseCallable( ), m_Category( nCategory ), m_Name( nName ), m_Server( nServer ), m_Result( 0.0 ) { } + CCallableScoreCheck( QString nCategory, QString nName, QString nServer ) : CBaseCallable( ), m_Category( nCategory ), m_Name( nName ), m_Server( nServer ), m_Result( 0.0 ) { } virtual ~CCallableScoreCheck( ); - virtual string GetName( ) { return m_Name; } + virtual QString GetName( ) { return m_Name; } virtual double GetResult( ) { return m_Result; } virtual void SetResult( double nResult ) { m_Result = nResult; } }; @@ -510,17 +510,17 @@ class CCallableScoreCheck : virtual public CBaseCallable class CCallableW3MMDPlayerAdd : virtual public CBaseCallable { protected: - string m_Category; + QString m_Category; uint32_t m_GameID; uint32_t m_PID; - string m_Name; - string m_Flag; + QString m_Name; + QString m_Flag; uint32_t m_Leaver; uint32_t m_Practicing; uint32_t m_Result; public: - CCallableW3MMDPlayerAdd( string nCategory, uint32_t nGameID, uint32_t nPID, string nName, string nFlag, uint32_t nLeaver, uint32_t nPracticing ) : CBaseCallable( ), m_Category( nCategory ), m_GameID( nGameID ), m_PID( nPID ), m_Name( nName ), m_Flag( nFlag ), m_Leaver( nLeaver ), m_Practicing( nPracticing ), m_Result( 0 ) { } + CCallableW3MMDPlayerAdd( QString nCategory, uint32_t nGameID, uint32_t nPID, QString nName, QString nFlag, uint32_t nLeaver, uint32_t nPracticing ) : CBaseCallable( ), m_Category( nCategory ), m_GameID( nGameID ), m_PID( nPID ), m_Name( nName ), m_Flag( nFlag ), m_Leaver( nLeaver ), m_Practicing( nPracticing ), m_Result( 0 ) { } virtual ~CCallableW3MMDPlayerAdd( ); virtual uint32_t GetResult( ) { return m_Result; } @@ -533,7 +533,7 @@ class CCallableW3MMDVarAdd : virtual public CBaseCallable uint32_t m_GameID; map m_VarInts; map m_VarReals; - map m_VarStrings; + map m_VarStrings; enum ValueType { VALUETYPE_INT = 1, @@ -547,7 +547,7 @@ class CCallableW3MMDVarAdd : virtual public CBaseCallable public: CCallableW3MMDVarAdd( uint32_t nGameID, map nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } CCallableW3MMDVarAdd( uint32_t nGameID, map nVarReals ) : CBaseCallable( ), m_GameID( nGameID ), m_VarReals( nVarReals ), m_ValueType( VALUETYPE_REAL ), m_Result( false ) { } - CCallableW3MMDVarAdd( uint32_t nGameID, map nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } + CCallableW3MMDVarAdd( uint32_t nGameID, map nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } virtual ~CCallableW3MMDVarAdd( ); virtual bool GetResult( ) { return m_Result; } @@ -561,25 +561,25 @@ class CCallableW3MMDVarAdd : virtual public CBaseCallable class CDBBan { private: - string m_Server; - string m_Name; - string m_IP; - string m_Date; - string m_GameName; - string m_Admin; - string m_Reason; + QString m_Server; + QString m_Name; + QString m_IP; + QString m_Date; + QString m_GameName; + QString m_Admin; + QString m_Reason; public: - CDBBan( string nServer, string nName, string nIP, string nDate, string nGameName, string nAdmin, string nReason ); + CDBBan( QString nServer, QString nName, QString nIP, QString nDate, QString nGameName, QString nAdmin, QString nReason ); ~CDBBan( ); - string GetServer( ) { return m_Server; } - string GetName( ) { return m_Name; } - string GetIP( ) { return m_IP; } - string GetDate( ) { return m_Date; } - string GetGameName( ) { return m_GameName; } - string GetAdmin( ) { return m_Admin; } - string GetReason( ) { return m_Reason; } + QString GetServer( ) { return m_Server; } + QString GetName( ) { return m_Name; } + QString GetIP( ) { return m_IP; } + QString GetDate( ) { return m_Date; } + QString GetGameName( ) { return m_GameName; } + QString GetAdmin( ) { return m_Admin; } + QString GetReason( ) { return m_Reason; } }; // @@ -590,23 +590,23 @@ class CDBGame { private: uint32_t m_ID; - string m_Server; - string m_Map; - string m_DateTime; - string m_GameName; - string m_OwnerName; + QString m_Server; + QString m_Map; + QString m_DateTime; + QString m_GameName; + QString m_OwnerName; uint32_t m_Duration; public: - CDBGame( uint32_t nID, string nServer, string nMap, string nDateTime, string nGameName, string nOwnerName, uint32_t nDuration ); + CDBGame( uint32_t nID, QString nServer, QString nMap, QString nDateTime, QString nGameName, QString nOwnerName, uint32_t nDuration ); ~CDBGame( ); uint32_t GetID( ) { return m_ID; } - string GetServer( ) { return m_Server; } - string GetMap( ) { return m_Map; } - string GetDateTime( ) { return m_DateTime; } - string GetGameName( ) { return m_GameName; } - string GetOwnerName( ) { return m_OwnerName; } + QString GetServer( ) { return m_Server; } + QString GetMap( ) { return m_Map; } + QString GetDateTime( ) { return m_DateTime; } + QString GetGameName( ) { return m_GameName; } + QString GetOwnerName( ) { return m_OwnerName; } uint32_t GetDuration( ) { return m_Duration; } void SetDuration( uint32_t nDuration ) { m_Duration = nDuration; } @@ -621,37 +621,37 @@ class CDBGamePlayer private: uint32_t m_ID; uint32_t m_GameID; - string m_Name; - string m_IP; + QString m_Name; + QString m_IP; uint32_t m_Spoofed; - string m_SpoofedRealm; + QString m_SpoofedRealm; uint32_t m_Reserved; uint32_t m_LoadingTime; uint32_t m_Left; - string m_LeftReason; + QString m_LeftReason; uint32_t m_Team; uint32_t m_Colour; public: - CDBGamePlayer( uint32_t nID, uint32_t nGameID, string nName, string nIP, uint32_t nSpoofed, string nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, string nLeftReason, uint32_t nTeam, uint32_t nColour ); + CDBGamePlayer( uint32_t nID, uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour ); ~CDBGamePlayer( ); uint32_t GetID( ) { return m_ID; } uint32_t GetGameID( ) { return m_GameID; } - string GetName( ) { return m_Name; } - string GetIP( ) { return m_IP; } + QString GetName( ) { return m_Name; } + QString GetIP( ) { return m_IP; } uint32_t GetSpoofed( ) { return m_Spoofed; } - string GetSpoofedRealm( ) { return m_SpoofedRealm; } + QString GetSpoofedRealm( ) { return m_SpoofedRealm; } uint32_t GetReserved( ) { return m_Reserved; } uint32_t GetLoadingTime( ) { return m_LoadingTime; } uint32_t GetLeft( ) { return m_Left; } - string GetLeftReason( ) { return m_LeftReason; } + QString GetLeftReason( ) { return m_LeftReason; } uint32_t GetTeam( ) { return m_Team; } uint32_t GetColour( ) { return m_Colour; } void SetLoadingTime( uint32_t nLoadingTime ) { m_LoadingTime = nLoadingTime; } void SetLeft( uint32_t nLeft ) { m_Left = nLeft; } - void SetLeftReason( string nLeftReason ) { m_LeftReason = nLeftReason; } + void SetLeftReason( QString nLeftReason ) { m_LeftReason = nLeftReason; } }; // @@ -661,10 +661,10 @@ class CDBGamePlayer class CDBGamePlayerSummary { private: - string m_Server; - string m_Name; - string m_FirstGameDateTime; // datetime of first game played - string m_LastGameDateTime; // datetime of last game played + QString m_Server; + QString m_Name; + QString m_FirstGameDateTime; // datetime of first game played + QString m_LastGameDateTime; // datetime of last game played uint32_t m_TotalGames; // total number of games played uint32_t m_MinLoadingTime; // minimum loading time in milliseconds (this could be skewed because different maps have different load times) uint32_t m_AvgLoadingTime; // average loading time in milliseconds (this could be skewed because different maps have different load times) @@ -677,13 +677,13 @@ class CDBGamePlayerSummary uint32_t m_MaxDuration; // maximum game duration in seconds public: - CDBGamePlayerSummary( string nServer, string nName, string nFirstGameDateTime, string nLastGameDateTime, uint32_t nTotalGames, uint32_t nMinLoadingTime, uint32_t nAvgLoadingTime, uint32_t nMaxLoadingTime, uint32_t nMinLeftPercent, uint32_t nAvgLeftPercent, uint32_t nMaxLeftPercent, uint32_t nMinDuration, uint32_t nAvgDuration, uint32_t nMaxDuration ); + CDBGamePlayerSummary( QString nServer, QString nName, QString nFirstGameDateTime, QString nLastGameDateTime, uint32_t nTotalGames, uint32_t nMinLoadingTime, uint32_t nAvgLoadingTime, uint32_t nMaxLoadingTime, uint32_t nMinLeftPercent, uint32_t nAvgLeftPercent, uint32_t nMaxLeftPercent, uint32_t nMinDuration, uint32_t nAvgDuration, uint32_t nMaxDuration ); ~CDBGamePlayerSummary( ); - string GetServer( ) { return m_Server; } - string GetName( ) { return m_Name; } - string GetFirstGameDateTime( ) { return m_FirstGameDateTime; } - string GetLastGameDateTime( ) { return m_LastGameDateTime; } + QString GetServer( ) { return m_Server; } + QString GetName( ) { return m_Name; } + QString GetFirstGameDateTime( ) { return m_FirstGameDateTime; } + QString GetLastGameDateTime( ) { return m_LastGameDateTime; } uint32_t GetTotalGames( ) { return m_TotalGames; } uint32_t GetMinLoadingTime( ) { return m_MinLoadingTime; } uint32_t GetAvgLoadingTime( ) { return m_AvgLoadingTime; } @@ -737,8 +737,8 @@ class CDBDotAPlayer uint32_t m_Assists; uint32_t m_Gold; uint32_t m_NeutralKills; - string m_Items[6]; - string m_Hero; + QString m_Items[6]; + QString m_Hero; uint32_t m_NewColour; uint32_t m_TowerKills; uint32_t m_RaxKills; @@ -746,7 +746,7 @@ class CDBDotAPlayer public: CDBDotAPlayer( ); - CDBDotAPlayer( uint32_t nID, uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, string nItem1, string nItem2, string nItem3, string nItem4, string nItem5, string nItem6, string nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ); + CDBDotAPlayer( uint32_t nID, uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ); ~CDBDotAPlayer( ); uint32_t GetID( ) { return m_ID; } @@ -759,8 +759,8 @@ class CDBDotAPlayer uint32_t GetAssists( ) { return m_Assists; } uint32_t GetGold( ) { return m_Gold; } uint32_t GetNeutralKills( ) { return m_NeutralKills; } - string GetItem( unsigned int i ); - string GetHero( ) { return m_Hero; } + QString GetItem( unsigned int i ); + QString GetHero( ) { return m_Hero; } uint32_t GetNewColour( ) { return m_NewColour; } uint32_t GetTowerKills( ) { return m_TowerKills; } uint32_t GetRaxKills( ) { return m_RaxKills; } @@ -774,8 +774,8 @@ class CDBDotAPlayer void SetAssists( uint32_t nAssists ) { m_Assists = nAssists; } void SetGold( uint32_t nGold ) { m_Gold = nGold; } void SetNeutralKills( uint32_t nNeutralKills ) { m_NeutralKills = nNeutralKills; } - void SetItem( unsigned int i, string item ); - void SetHero( string nHero ) { m_Hero = nHero; } + void SetItem( unsigned int i, QString item ); + void SetHero( QString nHero ) { m_Hero = nHero; } void SetNewColour( uint32_t nNewColour ) { m_NewColour = nNewColour; } void SetTowerKills( uint32_t nTowerKills ) { m_TowerKills = nTowerKills; } void SetRaxKills( uint32_t nRaxKills ) { m_RaxKills = nRaxKills; } @@ -789,8 +789,8 @@ class CDBDotAPlayer class CDBDotAPlayerSummary { private: - string m_Server; - string m_Name; + QString m_Server; + QString m_Name; uint32_t m_TotalGames; // total number of dota games played uint32_t m_TotalWins; // total number of dota games won uint32_t m_TotalLosses; // total number of dota games lost @@ -805,11 +805,11 @@ class CDBDotAPlayerSummary uint32_t m_TotalCourierKills; // total number of courier kills public: - CDBDotAPlayerSummary( string nServer, string nName, uint32_t nTotalGames, uint32_t nTotalWins, uint32_t nTotalLosses, uint32_t nTotalKills, uint32_t nTotalDeaths, uint32_t nTotalCreepKills, uint32_t nTotalCreepDenies, uint32_t nTotalAssists, uint32_t nTotalNeutralKills, uint32_t nTotalTowerKills, uint32_t nTotalRaxKills, uint32_t nTotalCourierKills ); + CDBDotAPlayerSummary( QString nServer, QString nName, uint32_t nTotalGames, uint32_t nTotalWins, uint32_t nTotalLosses, uint32_t nTotalKills, uint32_t nTotalDeaths, uint32_t nTotalCreepKills, uint32_t nTotalCreepDenies, uint32_t nTotalAssists, uint32_t nTotalNeutralKills, uint32_t nTotalTowerKills, uint32_t nTotalRaxKills, uint32_t nTotalCourierKills ); ~CDBDotAPlayerSummary( ); - string GetServer( ) { return m_Server; } - string GetName( ) { return m_Name; } + QString GetServer( ) { return m_Server; } + QString GetName( ) { return m_Name; } uint32_t GetTotalGames( ) { return m_TotalGames; } uint32_t GetTotalWins( ) { return m_TotalWins; } uint32_t GetTotalLosses( ) { return m_TotalLosses; } diff --git a/ghost/ghostdbmysql.cpp b/ghost/ghostdbmysql.cpp index ae7b7bf..b603c16 100644 --- a/ghost/ghostdbmysql.cpp +++ b/ghost/ghostdbmysql.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -41,10 +41,10 @@ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) { - m_Server = CFG->GetString( "db_mysql_server", string( ) ); + m_Server = CFG->GetString( "db_mysql_server", QString( ) ); m_Database = CFG->GetString( "db_mysql_database", "ghost" ); - m_User = CFG->GetString( "db_mysql_user", string( ) ); - m_Password = CFG->GetString( "db_mysql_password", string( ) ); + m_User = CFG->GetString( "db_mysql_user", QString( ) ); + m_Password = CFG->GetString( "db_mysql_password", QString( ) ); m_Port = CFG->GetInt( "db_mysql_port", 0 ); m_BotID = CFG->GetInt( "db_mysql_botid", 0 ); m_NumConnections = 1; @@ -59,7 +59,7 @@ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) if( !( Connection = mysql_init( NULL ) ) ) { - CONSOLE_Print( string( "[MYSQL] " ) + mysql_error( Connection ) ); + CONSOLE_Print( QString( "[MYSQL] " ) + mysql_error( Connection ) ); m_HasError = true; m_Error = "error initializing MySQL connection"; return; @@ -70,7 +70,7 @@ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) if( !( mysql_real_connect( Connection, m_Server.c_str( ), m_User.c_str( ), m_Password.c_str( ), m_Database.c_str( ), m_Port, NULL, 0 ) ) ) { - CONSOLE_Print( string( "[MYSQL] " ) + mysql_error( Connection ) ); + CONSOLE_Print( QString( "[MYSQL] " ) + mysql_error( Connection ) ); m_HasError = true; m_Error = "error connecting to MySQL server"; return; @@ -95,7 +95,7 @@ CGHostDBMySQL :: ~CGHostDBMySQL( ) mysql_library_end( ); } -string CGHostDBMySQL :: GetStatus( ) +QString CGHostDBMySQL :: GetStatus( ) { return "DB STATUS --- Connections: " + UTIL_ToString( m_IdleConnections.size( ) ) + "/" + UTIL_ToString( m_NumConnections ) + " idle. Outstanding callables: " + UTIL_ToString( m_OutstandingCallables ) + "."; } @@ -134,7 +134,7 @@ void CGHostDBMySQL :: CreateThread( CBaseCallable *callable ) } catch( boost :: thread_resource_error tre ) { - CONSOLE_Print( "[MYSQL] error spawning thread on attempt #1 [" + string( tre.what( ) ) + "], pausing execution and trying again in 50ms" ); + CONSOLE_Print( "[MYSQL] error spawning thread on attempt #1 [" + QString( tre.what( ) ) + "], pausing execution and trying again in 50ms" ); MILLISLEEP( 50 ); try @@ -143,13 +143,13 @@ void CGHostDBMySQL :: CreateThread( CBaseCallable *callable ) } catch( boost :: thread_resource_error tre2 ) { - CONSOLE_Print( "[MYSQL] error spawning thread on attempt #2 [" + string( tre2.what( ) ) + "], giving up" ); + CONSOLE_Print( "[MYSQL] error spawning thread on attempt #2 [" + QString( tre2.what( ) ) + "], giving up" ); callable->SetReady( true ); } } } -CCallableAdminCount *CGHostDBMySQL :: ThreadedAdminCount( string server ) +CCallableAdminCount *CGHostDBMySQL :: ThreadedAdminCount( QString server ) { void *Connection = GetIdleConnection( ); @@ -162,7 +162,7 @@ CCallableAdminCount *CGHostDBMySQL :: ThreadedAdminCount( string server ) return Callable; } -CCallableAdminCheck *CGHostDBMySQL :: ThreadedAdminCheck( string server, string user ) +CCallableAdminCheck *CGHostDBMySQL :: ThreadedAdminCheck( QString server, QString user ) { void *Connection = GetIdleConnection( ); @@ -175,7 +175,7 @@ CCallableAdminCheck *CGHostDBMySQL :: ThreadedAdminCheck( string server, string return Callable; } -CCallableAdminAdd *CGHostDBMySQL :: ThreadedAdminAdd( string server, string user ) +CCallableAdminAdd *CGHostDBMySQL :: ThreadedAdminAdd( QString server, QString user ) { void *Connection = GetIdleConnection( ); @@ -188,7 +188,7 @@ CCallableAdminAdd *CGHostDBMySQL :: ThreadedAdminAdd( string server, string user return Callable; } -CCallableAdminRemove *CGHostDBMySQL :: ThreadedAdminRemove( string server, string user ) +CCallableAdminRemove *CGHostDBMySQL :: ThreadedAdminRemove( QString server, QString user ) { void *Connection = GetIdleConnection( ); @@ -201,7 +201,7 @@ CCallableAdminRemove *CGHostDBMySQL :: ThreadedAdminRemove( string server, strin return Callable; } -CCallableAdminList *CGHostDBMySQL :: ThreadedAdminList( string server ) +CCallableAdminList *CGHostDBMySQL :: ThreadedAdminList( QString server ) { void *Connection = GetIdleConnection( ); @@ -214,7 +214,7 @@ CCallableAdminList *CGHostDBMySQL :: ThreadedAdminList( string server ) return Callable; } -CCallableBanCount *CGHostDBMySQL :: ThreadedBanCount( string server ) +CCallableBanCount *CGHostDBMySQL :: ThreadedBanCount( QString server ) { void *Connection = GetIdleConnection( ); @@ -227,7 +227,7 @@ CCallableBanCount *CGHostDBMySQL :: ThreadedBanCount( string server ) return Callable; } -CCallableBanCheck *CGHostDBMySQL :: ThreadedBanCheck( string server, string user, string ip ) +CCallableBanCheck *CGHostDBMySQL :: ThreadedBanCheck( QString server, QString user, QString ip ) { void *Connection = GetIdleConnection( ); @@ -240,7 +240,7 @@ CCallableBanCheck *CGHostDBMySQL :: ThreadedBanCheck( string server, string user return Callable; } -CCallableBanAdd *CGHostDBMySQL :: ThreadedBanAdd( string server, string user, string ip, string gamename, string admin, string reason ) +CCallableBanAdd *CGHostDBMySQL :: ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { void *Connection = GetIdleConnection( ); @@ -253,7 +253,7 @@ CCallableBanAdd *CGHostDBMySQL :: ThreadedBanAdd( string server, string user, st return Callable; } -CCallableBanRemove *CGHostDBMySQL :: ThreadedBanRemove( string server, string user ) +CCallableBanRemove *CGHostDBMySQL :: ThreadedBanRemove( QString server, QString user ) { void *Connection = GetIdleConnection( ); @@ -266,20 +266,20 @@ CCallableBanRemove *CGHostDBMySQL :: ThreadedBanRemove( string server, string us return Callable; } -CCallableBanRemove *CGHostDBMySQL :: ThreadedBanRemove( string user ) +CCallableBanRemove *CGHostDBMySQL :: ThreadedBanRemove( QString user ) { void *Connection = GetIdleConnection( ); if( !Connection ) m_NumConnections++; - CCallableBanRemove *Callable = new CMySQLCallableBanRemove( string( ), user, Connection, m_BotID, m_Server, m_Database, m_User, m_Password, m_Port ); + CCallableBanRemove *Callable = new CMySQLCallableBanRemove( QString( ), user, Connection, m_BotID, m_Server, m_Database, m_User, m_Password, m_Port ); CreateThread( Callable ); m_OutstandingCallables++; return Callable; } -CCallableBanList *CGHostDBMySQL :: ThreadedBanList( string server ) +CCallableBanList *CGHostDBMySQL :: ThreadedBanList( QString server ) { void *Connection = GetIdleConnection( ); @@ -292,7 +292,7 @@ CCallableBanList *CGHostDBMySQL :: ThreadedBanList( string server ) return Callable; } -CCallableGameAdd *CGHostDBMySQL :: ThreadedGameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) +CCallableGameAdd *CGHostDBMySQL :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) { void *Connection = GetIdleConnection( ); @@ -305,7 +305,7 @@ CCallableGameAdd *CGHostDBMySQL :: ThreadedGameAdd( string server, string map, s return Callable; } -CCallableGamePlayerAdd *CGHostDBMySQL :: ThreadedGamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ) +CCallableGamePlayerAdd *CGHostDBMySQL :: ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { void *Connection = GetIdleConnection( ); @@ -318,7 +318,7 @@ CCallableGamePlayerAdd *CGHostDBMySQL :: ThreadedGamePlayerAdd( uint32_t gameid, return Callable; } -CCallableGamePlayerSummaryCheck *CGHostDBMySQL :: ThreadedGamePlayerSummaryCheck( string name ) +CCallableGamePlayerSummaryCheck *CGHostDBMySQL :: ThreadedGamePlayerSummaryCheck( QString name ) { void *Connection = GetIdleConnection( ); @@ -344,7 +344,7 @@ CCallableDotAGameAdd *CGHostDBMySQL :: ThreadedDotAGameAdd( uint32_t gameid, uin return Callable; } -CCallableDotAPlayerAdd *CGHostDBMySQL :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +CCallableDotAPlayerAdd *CGHostDBMySQL :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) { void *Connection = GetIdleConnection( ); @@ -357,7 +357,7 @@ CCallableDotAPlayerAdd *CGHostDBMySQL :: ThreadedDotAPlayerAdd( uint32_t gameid, return Callable; } -CCallableDotAPlayerSummaryCheck *CGHostDBMySQL :: ThreadedDotAPlayerSummaryCheck( string name ) +CCallableDotAPlayerSummaryCheck *CGHostDBMySQL :: ThreadedDotAPlayerSummaryCheck( QString name ) { void *Connection = GetIdleConnection( ); @@ -370,7 +370,7 @@ CCallableDotAPlayerSummaryCheck *CGHostDBMySQL :: ThreadedDotAPlayerSummaryCheck return Callable; } -CCallableDownloadAdd *CGHostDBMySQL :: ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) +CCallableDownloadAdd *CGHostDBMySQL :: ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) { void *Connection = GetIdleConnection( ); @@ -383,7 +383,7 @@ CCallableDownloadAdd *CGHostDBMySQL :: ThreadedDownloadAdd( string map, uint32_t return Callable; } -CCallableScoreCheck *CGHostDBMySQL :: ThreadedScoreCheck( string category, string name, string server ) +CCallableScoreCheck *CGHostDBMySQL :: ThreadedScoreCheck( QString category, QString name, QString server ) { void *Connection = GetIdleConnection( ); @@ -396,7 +396,7 @@ CCallableScoreCheck *CGHostDBMySQL :: ThreadedScoreCheck( string category, strin return Callable; } -CCallableW3MMDPlayerAdd *CGHostDBMySQL :: ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ) +CCallableW3MMDPlayerAdd *CGHostDBMySQL :: ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) { void *Connection = GetIdleConnection( ); @@ -435,7 +435,7 @@ CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) { void *Connection = GetIdleConnection( ); @@ -465,18 +465,18 @@ void *CGHostDBMySQL :: GetIdleConnection( ) // unprototyped global helper functions // -string MySQLEscapeString( void *conn, string str ) +QString MySQLEscapeString( void *conn, QString str ) { char *to = new char[str.size( ) * 2 + 1]; - unsigned long size = mysql_real_escape_string( (MYSQL *)conn, to, str.c_str( ), str.size( ) ); - string result( to, size ); + unsigned long size = mysql_real_escape_QString( (MYSQL *)conn, to, str.c_str( ), str.size( ) ); + QString result( to, size ); delete [] to; return result; } -vector MySQLFetchRow( MYSQL_RES *res ) +vector MySQLFetchRow( MYSQL_RES *res ) { - vector Result; + vector Result; MYSQL_ROW Row = mysql_fetch_row( res ); @@ -488,9 +488,9 @@ vector MySQLFetchRow( MYSQL_RES *res ) for( unsigned int i = 0; i < mysql_num_fields( res ); i++ ) { if( Row[i] ) - Result.push_back( string( Row[i], Lengths[i] ) ); + Result.push_back( QString( Row[i], Lengths[i] ) ); else - Result.push_back( string( ) ); + Result.push_back( QString( ) ); } } @@ -501,11 +501,11 @@ vector MySQLFetchRow( MYSQL_RES *res ) // global helper functions // -uint32_t MySQLAdminCount( void *conn, string *error, uint32_t botid, string server ) +uint32_t MySQLAdminCount( void *conn, QString *error, uint32_t botid, QString server ) { - string EscServer = MySQLEscapeString( conn, server ); + QString EscServer = MySQLEscapeString( conn, server ); uint32_t Count = 0; - string Query = "SELECT COUNT(*) FROM admins WHERE server='" + EscServer + "'"; + QString Query = "SELECT COUNT(*) FROM admins WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -515,7 +515,7 @@ uint32_t MySQLAdminCount( void *conn, string *error, uint32_t botid, string serv if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Count = UTIL_ToUInt32( Row[0] ); @@ -531,13 +531,13 @@ uint32_t MySQLAdminCount( void *conn, string *error, uint32_t botid, string serv return Count; } -bool MySQLAdminCheck( void *conn, string *error, uint32_t botid, string server, string user ) +bool MySQLAdminCheck( void *conn, QString *error, uint32_t botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscServer = MySQLEscapeString( conn, server ); - string EscUser = MySQLEscapeString( conn, user ); + QString EscServer = MySQLEscapeString( conn, server ); + QString EscUser = MySQLEscapeString( conn, user ); bool IsAdmin = false; - string Query = "SELECT * FROM admins WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; + QString Query = "SELECT * FROM admins WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -547,7 +547,7 @@ bool MySQLAdminCheck( void *conn, string *error, uint32_t botid, string server, if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( !Row.empty( ) ) IsAdmin = true; @@ -561,13 +561,13 @@ bool MySQLAdminCheck( void *conn, string *error, uint32_t botid, string server, return IsAdmin; } -bool MySQLAdminAdd( void *conn, string *error, uint32_t botid, string server, string user ) +bool MySQLAdminAdd( void *conn, QString *error, uint32_t botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscServer = MySQLEscapeString( conn, server ); - string EscUser = MySQLEscapeString( conn, user ); + QString EscServer = MySQLEscapeString( conn, server ); + QString EscUser = MySQLEscapeString( conn, user ); bool Success = false; - string Query = "INSERT INTO admins ( botid, server, name ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscUser + "' )"; + QString Query = "INSERT INTO admins ( botid, server, name ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscUser + "' )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -577,13 +577,13 @@ bool MySQLAdminAdd( void *conn, string *error, uint32_t botid, string server, st return Success; } -bool MySQLAdminRemove( void *conn, string *error, uint32_t botid, string server, string user ) +bool MySQLAdminRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscServer = MySQLEscapeString( conn, server ); - string EscUser = MySQLEscapeString( conn, user ); + QString EscServer = MySQLEscapeString( conn, server ); + QString EscUser = MySQLEscapeString( conn, user ); bool Success = false; - string Query = "DELETE FROM admins WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; + QString Query = "DELETE FROM admins WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -593,11 +593,11 @@ bool MySQLAdminRemove( void *conn, string *error, uint32_t botid, string server, return Success; } -vector MySQLAdminList( void *conn, string *error, uint32_t botid, string server ) +vector MySQLAdminList( void *conn, QString *error, uint32_t botid, QString server ) { - string EscServer = MySQLEscapeString( conn, server ); - vector AdminList; - string Query = "SELECT name FROM admins WHERE server='" + EscServer + "'"; + QString EscServer = MySQLEscapeString( conn, server ); + vector AdminList; + QString Query = "SELECT name FROM admins WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -607,7 +607,7 @@ vector MySQLAdminList( void *conn, string *error, uint32_t botid, string if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); while( !Row.empty( ) ) { @@ -624,11 +624,11 @@ vector MySQLAdminList( void *conn, string *error, uint32_t botid, string return AdminList; } -uint32_t MySQLBanCount( void *conn, string *error, uint32_t botid, string server ) +uint32_t MySQLBanCount( void *conn, QString *error, uint32_t botid, QString server ) { - string EscServer = MySQLEscapeString( conn, server ); + QString EscServer = MySQLEscapeString( conn, server ); uint32_t Count = 0; - string Query = "SELECT COUNT(*) FROM bans WHERE server='" + EscServer + "'"; + QString Query = "SELECT COUNT(*) FROM bans WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -638,7 +638,7 @@ uint32_t MySQLBanCount( void *conn, string *error, uint32_t botid, string server if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Count = UTIL_ToUInt32( Row[0] ); @@ -654,14 +654,14 @@ uint32_t MySQLBanCount( void *conn, string *error, uint32_t botid, string server return Count; } -CDBBan *MySQLBanCheck( void *conn, string *error, uint32_t botid, string server, string user, string ip ) +CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscServer = MySQLEscapeString( conn, server ); - string EscUser = MySQLEscapeString( conn, user ); - string EscIP = MySQLEscapeString( conn, ip ); + QString EscServer = MySQLEscapeString( conn, server ); + QString EscUser = MySQLEscapeString( conn, user ); + QString EscIP = MySQLEscapeString( conn, ip ); CDBBan *Ban = NULL; - string Query; + QString Query; if( ip.empty( ) ) Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; @@ -676,7 +676,7 @@ CDBBan *MySQLBanCheck( void *conn, string *error, uint32_t botid, string server, if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( Row.size( ) == 6 ) Ban = new CDBBan( server, Row[0], Row[1], Row[2], Row[3], Row[4], Row[5] ); @@ -692,17 +692,17 @@ CDBBan *MySQLBanCheck( void *conn, string *error, uint32_t botid, string server, return Ban; } -bool MySQLBanAdd( void *conn, string *error, uint32_t botid, string server, string user, string ip, string gamename, string admin, string reason ) +bool MySQLBanAdd( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscServer = MySQLEscapeString( conn, server ); - string EscUser = MySQLEscapeString( conn, user ); - string EscIP = MySQLEscapeString( conn, ip ); - string EscGameName = MySQLEscapeString( conn, gamename ); - string EscAdmin = MySQLEscapeString( conn, admin ); - string EscReason = MySQLEscapeString( conn, reason ); + QString EscServer = MySQLEscapeString( conn, server ); + QString EscUser = MySQLEscapeString( conn, user ); + QString EscIP = MySQLEscapeString( conn, ip ); + QString EscGameName = MySQLEscapeString( conn, gamename ); + QString EscAdmin = MySQLEscapeString( conn, admin ); + QString EscReason = MySQLEscapeString( conn, reason ); bool Success = false; - string Query = "INSERT INTO bans ( botid, server, name, ip, date, gamename, admin, reason ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscUser + "', '" + EscIP + "', CURDATE( ), '" + EscGameName + "', '" + EscAdmin + "', '" + EscReason + "' )"; + QString Query = "INSERT INTO bans ( botid, server, name, ip, date, gamename, admin, reason ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscUser + "', '" + EscIP + "', CURDATE( ), '" + EscGameName + "', '" + EscAdmin + "', '" + EscReason + "' )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -712,13 +712,13 @@ bool MySQLBanAdd( void *conn, string *error, uint32_t botid, string server, stri return Success; } -bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string server, string user ) +bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscServer = MySQLEscapeString( conn, server ); - string EscUser = MySQLEscapeString( conn, user ); + QString EscServer = MySQLEscapeString( conn, server ); + QString EscUser = MySQLEscapeString( conn, user ); bool Success = false; - string Query = "DELETE FROM bans WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; + QString Query = "DELETE FROM bans WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -728,12 +728,12 @@ bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string server, s return Success; } -bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string user ) +bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); - string EscUser = MySQLEscapeString( conn, user ); + QString EscUser = MySQLEscapeString( conn, user ); bool Success = false; - string Query = "DELETE FROM bans WHERE name='" + EscUser + "'"; + QString Query = "DELETE FROM bans WHERE name='" + EscUser + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -743,11 +743,11 @@ bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string user ) return Success; } -vector MySQLBanList( void *conn, string *error, uint32_t botid, string server ) +vector MySQLBanList( void *conn, QString *error, uint32_t botid, QString server ) { - string EscServer = MySQLEscapeString( conn, server ); + QString EscServer = MySQLEscapeString( conn, server ); vector BanList; - string Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE server='" + EscServer + "'"; + QString Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -757,7 +757,7 @@ vector MySQLBanList( void *conn, string *error, uint32_t botid, string if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); while( Row.size( ) == 6 ) { @@ -774,16 +774,16 @@ vector MySQLBanList( void *conn, string *error, uint32_t botid, string return BanList; } -uint32_t MySQLGameAdd( void *conn, string *error, uint32_t botid, string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) +uint32_t MySQLGameAdd( void *conn, QString *error, uint32_t botid, QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) { uint32_t RowID = 0; - string EscServer = MySQLEscapeString( conn, server ); - string EscMap = MySQLEscapeString( conn, map ); - string EscGameName = MySQLEscapeString( conn, gamename ); - string EscOwnerName = MySQLEscapeString( conn, ownername ); - string EscCreatorName = MySQLEscapeString( conn, creatorname ); - string EscCreatorServer = MySQLEscapeString( conn, creatorserver ); - string Query = "INSERT INTO games ( botid, server, map, datetime, gamename, ownername, duration, gamestate, creatorname, creatorserver ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscMap + "', NOW( ), '" + EscGameName + "', '" + EscOwnerName + "', " + UTIL_ToString( duration ) + ", " + UTIL_ToString( gamestate ) + ", '" + EscCreatorName + "', '" + EscCreatorServer + "' )"; + QString EscServer = MySQLEscapeString( conn, server ); + QString EscMap = MySQLEscapeString( conn, map ); + QString EscGameName = MySQLEscapeString( conn, gamename ); + QString EscOwnerName = MySQLEscapeString( conn, ownername ); + QString EscCreatorName = MySQLEscapeString( conn, creatorname ); + QString EscCreatorServer = MySQLEscapeString( conn, creatorserver ); + QString Query = "INSERT INTO games ( botid, server, map, datetime, gamename, ownername, duration, gamestate, creatorname, creatorserver ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscMap + "', NOW( ), '" + EscGameName + "', '" + EscOwnerName + "', " + UTIL_ToString( duration ) + ", " + UTIL_ToString( gamestate ) + ", '" + EscCreatorName + "', '" + EscCreatorServer + "' )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -793,15 +793,15 @@ uint32_t MySQLGameAdd( void *conn, string *error, uint32_t botid, string server, return RowID; } -uint32_t MySQLGamePlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ) +uint32_t MySQLGamePlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); uint32_t RowID = 0; - string EscName = MySQLEscapeString( conn, name ); - string EscIP = MySQLEscapeString( conn, ip ); - string EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm ); - string EscLeftReason = MySQLEscapeString( conn, leftreason ); - string Query = "INSERT INTO gameplayers ( botid, gameid, name, ip, spoofed, reserved, loadingtime, `left`, leftreason, team, colour, spoofedrealm ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", '" + EscName + "', '" + EscIP + "', " + UTIL_ToString( spoofed ) + ", " + UTIL_ToString( reserved ) + ", " + UTIL_ToString( loadingtime ) + ", " + UTIL_ToString( left ) + ", '" + EscLeftReason + "', " + UTIL_ToString( team ) + ", " + UTIL_ToString( colour ) + ", '" + EscSpoofedRealm + "' )"; + QString EscName = MySQLEscapeString( conn, name ); + QString EscIP = MySQLEscapeString( conn, ip ); + QString EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm ); + QString EscLeftReason = MySQLEscapeString( conn, leftreason ); + QString Query = "INSERT INTO gameplayers ( botid, gameid, name, ip, spoofed, reserved, loadingtime, `left`, leftreason, team, colour, spoofedrealm ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", '" + EscName + "', '" + EscIP + "', " + UTIL_ToString( spoofed ) + ", " + UTIL_ToString( reserved ) + ", " + UTIL_ToString( loadingtime ) + ", " + UTIL_ToString( left ) + ", '" + EscLeftReason + "', " + UTIL_ToString( team ) + ", " + UTIL_ToString( colour ) + ", '" + EscSpoofedRealm + "' )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -811,12 +811,12 @@ uint32_t MySQLGamePlayerAdd( void *conn, string *error, uint32_t botid, uint32_t return RowID; } -CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, string *error, uint32_t botid, string name ) +CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - string EscName = MySQLEscapeString( conn, name ); + QString EscName = MySQLEscapeString( conn, name ); CDBGamePlayerSummary *GamePlayerSummary = NULL; - string Query = "SELECT MIN(DATE(datetime)), MAX(DATE(datetime)), COUNT(*), MIN(loadingtime), AVG(loadingtime), MAX(loadingtime), MIN(`left`/duration)*100, AVG(`left`/duration)*100, MAX(`left`/duration)*100, MIN(duration), AVG(duration), MAX(duration) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE LOWER(name)='" + EscName + "'"; + QString Query = "SELECT MIN(DATE(datetime)), MAX(DATE(datetime)), COUNT(*), MIN(loadingtime), AVG(loadingtime), MAX(loadingtime), MIN(`left`/duration)*100, AVG(`left`/duration)*100, MAX(`left`/duration)*100, MIN(duration), AVG(duration), MAX(duration) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE LOWER(name)='" + EscName + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -826,12 +826,12 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, string *error, ui if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( Row.size( ) == 12 ) { - string FirstGameDateTime = Row[0]; - string LastGameDateTime = Row[1]; + QString FirstGameDateTime = Row[0]; + QString LastGameDateTime = Row[1]; uint32_t TotalGames = UTIL_ToUInt32( Row[2] ); uint32_t MinLoadingTime = UTIL_ToUInt32( Row[3] ); uint32_t AvgLoadingTime = UTIL_ToUInt32( Row[4] ); @@ -842,7 +842,7 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, string *error, ui uint32_t MinDuration = UTIL_ToUInt32( Row[9] ); uint32_t AvgDuration = UTIL_ToUInt32( Row[10] ); uint32_t MaxDuration = UTIL_ToUInt32( Row[11] ); - GamePlayerSummary = new CDBGamePlayerSummary( string( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); + GamePlayerSummary = new CDBGamePlayerSummary( QString( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); } else *error = "error checking gameplayersummary [" + name + "] - row doesn't have 12 columns"; @@ -856,10 +856,10 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, string *error, ui return GamePlayerSummary; } -uint32_t MySQLDotAGameAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +uint32_t MySQLDotAGameAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) { uint32_t RowID = 0; - string Query = "INSERT INTO dotagames ( botid, gameid, winner, min, sec ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( winner ) + ", " + UTIL_ToString( min ) + ", " + UTIL_ToString( sec ) + " )"; + QString Query = "INSERT INTO dotagames ( botid, gameid, winner, min, sec ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( winner ) + ", " + UTIL_ToString( min ) + ", " + UTIL_ToString( sec ) + " )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -869,17 +869,17 @@ uint32_t MySQLDotAGameAdd( void *conn, string *error, uint32_t botid, uint32_t g return RowID; } -uint32_t MySQLDotAPlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +uint32_t MySQLDotAPlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) { uint32_t RowID = 0; - string EscItem1 = MySQLEscapeString( conn, item1 ); - string EscItem2 = MySQLEscapeString( conn, item2 ); - string EscItem3 = MySQLEscapeString( conn, item3 ); - string EscItem4 = MySQLEscapeString( conn, item4 ); - string EscItem5 = MySQLEscapeString( conn, item5 ); - string EscItem6 = MySQLEscapeString( conn, item6 ); - string EscHero = MySQLEscapeString( conn, hero ); - string Query = "INSERT INTO dotaplayers ( botid, gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( colour ) + ", " + UTIL_ToString( kills ) + ", " + UTIL_ToString( deaths ) + ", " + UTIL_ToString( creepkills ) + ", " + UTIL_ToString( creepdenies ) + ", " + UTIL_ToString( assists ) + ", " + UTIL_ToString( gold ) + ", " + UTIL_ToString( neutralkills ) + ", '" + EscItem1 + "', '" + EscItem2 + "', '" + EscItem3 + "', '" + EscItem4 + "', '" + EscItem5 + "', '" + EscItem6 + "', '" + EscHero + "', " + UTIL_ToString( newcolour ) + ", " + UTIL_ToString( towerkills ) + ", " + UTIL_ToString( raxkills ) + ", " + UTIL_ToString( courierkills ) + " )"; + QString EscItem1 = MySQLEscapeString( conn, item1 ); + QString EscItem2 = MySQLEscapeString( conn, item2 ); + QString EscItem3 = MySQLEscapeString( conn, item3 ); + QString EscItem4 = MySQLEscapeString( conn, item4 ); + QString EscItem5 = MySQLEscapeString( conn, item5 ); + QString EscItem6 = MySQLEscapeString( conn, item6 ); + QString EscHero = MySQLEscapeString( conn, hero ); + QString Query = "INSERT INTO dotaplayers ( botid, gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( colour ) + ", " + UTIL_ToString( kills ) + ", " + UTIL_ToString( deaths ) + ", " + UTIL_ToString( creepkills ) + ", " + UTIL_ToString( creepdenies ) + ", " + UTIL_ToString( assists ) + ", " + UTIL_ToString( gold ) + ", " + UTIL_ToString( neutralkills ) + ", '" + EscItem1 + "', '" + EscItem2 + "', '" + EscItem3 + "', '" + EscItem4 + "', '" + EscItem5 + "', '" + EscItem6 + "', '" + EscHero + "', " + UTIL_ToString( newcolour ) + ", " + UTIL_ToString( towerkills ) + ", " + UTIL_ToString( raxkills ) + ", " + UTIL_ToString( courierkills ) + " )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -889,12 +889,12 @@ uint32_t MySQLDotAPlayerAdd( void *conn, string *error, uint32_t botid, uint32_t return RowID; } -CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, uint32_t botid, string name ) +CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - string EscName = MySQLEscapeString( conn, name ); + QString EscName = MySQLEscapeString( conn, name ); CDBDotAPlayerSummary *DotAPlayerSummary = NULL; - string Query = "SELECT COUNT(dotaplayers.id), SUM(kills), SUM(deaths), SUM(creepkills), SUM(creepdenies), SUM(assists), SUM(neutralkills), SUM(towerkills), SUM(raxkills), SUM(courierkills) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE LOWER(name)='" + EscName + "'"; + QString Query = "SELECT COUNT(dotaplayers.id), SUM(kills), SUM(deaths), SUM(creepkills), SUM(creepdenies), SUM(assists), SUM(neutralkills), SUM(towerkills), SUM(raxkills), SUM(courierkills) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE LOWER(name)='" + EscName + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -904,7 +904,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( Row.size( ) == 10 ) { @@ -926,7 +926,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui // calculate total wins - string Query2 = "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour LEFT JOIN dotagames ON games.id=dotagames.gameid WHERE name='" + EscName + "' AND ((winner=1 AND dotaplayers.newcolour>=1 AND dotaplayers.newcolour<=5) OR (winner=2 AND dotaplayers.newcolour>=7 AND dotaplayers.newcolour<=11))"; + QString Query2 = "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour LEFT JOIN dotagames ON games.id=dotagames.gameid WHERE name='" + EscName + "' AND ((winner=1 AND dotaplayers.newcolour>=1 AND dotaplayers.newcolour<=5) OR (winner=2 AND dotaplayers.newcolour>=7 AND dotaplayers.newcolour<=11))"; if( mysql_real_query( (MYSQL *)conn, Query2.c_str( ), Query2.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -936,7 +936,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui if( Result2 ) { - vector Row2 = MySQLFetchRow( Result2 ); + vector Row2 = MySQLFetchRow( Result2 ); if( Row2.size( ) == 1 ) TotalWins = UTIL_ToUInt32( Row2[0] ); @@ -951,7 +951,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui // calculate total losses - string Query3 = "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour LEFT JOIN dotagames ON games.id=dotagames.gameid WHERE name='" + EscName + "' AND ((winner=2 AND dotaplayers.newcolour>=1 AND dotaplayers.newcolour<=5) OR (winner=1 AND dotaplayers.newcolour>=7 AND dotaplayers.newcolour<=11))"; + QString Query3 = "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour LEFT JOIN dotagames ON games.id=dotagames.gameid WHERE name='" + EscName + "' AND ((winner=2 AND dotaplayers.newcolour>=1 AND dotaplayers.newcolour<=5) OR (winner=1 AND dotaplayers.newcolour>=7 AND dotaplayers.newcolour<=11))"; if( mysql_real_query( (MYSQL *)conn, Query3.c_str( ), Query3.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -961,7 +961,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui if( Result3 ) { - vector Row3 = MySQLFetchRow( Result3 ); + vector Row3 = MySQLFetchRow( Result3 ); if( Row3.size( ) == 1 ) TotalLosses = UTIL_ToUInt32( Row3[0] ); @@ -976,7 +976,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui // done - DotAPlayerSummary = new CDBDotAPlayerSummary( string( ), name, TotalGames, TotalWins, TotalLosses, TotalKills, TotalDeaths, TotalCreepKills, TotalCreepDenies, TotalAssists, TotalNeutralKills, TotalTowerKills, TotalRaxKills, TotalCourierKills ); + DotAPlayerSummary = new CDBDotAPlayerSummary( QString( ), name, TotalGames, TotalWins, TotalLosses, TotalKills, TotalDeaths, TotalCreepKills, TotalCreepDenies, TotalAssists, TotalNeutralKills, TotalTowerKills, TotalRaxKills, TotalCourierKills ); } } else @@ -991,14 +991,14 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui return DotAPlayerSummary; } -bool MySQLDownloadAdd( void *conn, string *error, uint32_t botid, string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) +bool MySQLDownloadAdd( void *conn, QString *error, uint32_t botid, QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) { bool Success = false; - string EscMap = MySQLEscapeString( conn, map ); - string EscName = MySQLEscapeString( conn, name ); - string EscIP = MySQLEscapeString( conn, ip ); - string EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm ); - string Query = "INSERT INTO downloads ( botid, map, mapsize, datetime, name, ip, spoofed, spoofedrealm, downloadtime ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscMap + "', " + UTIL_ToString( mapsize ) + ", NOW( ), '" + EscName + "', '" + EscIP + "', " + UTIL_ToString( spoofed ) + ", '" + EscSpoofedRealm + "', " + UTIL_ToString( downloadtime ) + " )"; + QString EscMap = MySQLEscapeString( conn, map ); + QString EscName = MySQLEscapeString( conn, name ); + QString EscIP = MySQLEscapeString( conn, ip ); + QString EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm ); + QString Query = "INSERT INTO downloads ( botid, map, mapsize, datetime, name, ip, spoofed, spoofedrealm, downloadtime ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscMap + "', " + UTIL_ToString( mapsize ) + ", NOW( ), '" + EscName + "', '" + EscIP + "', " + UTIL_ToString( spoofed ) + ", '" + EscSpoofedRealm + "', " + UTIL_ToString( downloadtime ) + " )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -1008,14 +1008,14 @@ bool MySQLDownloadAdd( void *conn, string *error, uint32_t botid, string map, ui return Success; } -double MySQLScoreCheck( void *conn, string *error, uint32_t botid, string category, string name, string server ) +double MySQLScoreCheck( void *conn, QString *error, uint32_t botid, QString category, QString name, QString server ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - string EscCategory = MySQLEscapeString( conn, category ); - string EscName = MySQLEscapeString( conn, name ); - string EscServer = MySQLEscapeString( conn, server ); + QString EscCategory = MySQLEscapeString( conn, category ); + QString EscName = MySQLEscapeString( conn, name ); + QString EscServer = MySQLEscapeString( conn, server ); double Score = -100000.0; - string Query = "SELECT score FROM scores WHERE category='" + EscCategory + "' AND name='" + EscName + "' AND server='" + EscServer + "'"; + QString Query = "SELECT score FROM scores WHERE category='" + EscCategory + "' AND name='" + EscName + "' AND server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -1025,7 +1025,7 @@ double MySQLScoreCheck( void *conn, string *error, uint32_t botid, string catego if( Result ) { - vector Row = MySQLFetchRow( Result ); + vector Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Score = UTIL_ToDouble( Row[0] ); @@ -1041,14 +1041,14 @@ double MySQLScoreCheck( void *conn, string *error, uint32_t botid, string catego return Score; } -uint32_t MySQLW3MMDPlayerAdd( void *conn, string *error, uint32_t botid, string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ) +uint32_t MySQLW3MMDPlayerAdd( void *conn, QString *error, uint32_t botid, QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); uint32_t RowID = 0; - string EscCategory = MySQLEscapeString( conn, category ); - string EscName = MySQLEscapeString( conn, name ); - string EscFlag = MySQLEscapeString( conn, flag ); - string Query = "INSERT INTO w3mmdplayers ( botid, category, gameid, pid, name, flag, leaver, practicing ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscCategory + "', " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( pid ) + ", '" + EscName + "', '" + EscFlag + "', " + UTIL_ToString( leaver ) + ", " + UTIL_ToString( practicing ) + " )"; + QString EscCategory = MySQLEscapeString( conn, category ); + QString EscName = MySQLEscapeString( conn, name ); + QString EscFlag = MySQLEscapeString( conn, flag ); + QString Query = "INSERT INTO w3mmdplayers ( botid, category, gameid, pid, name, flag, leaver, practicing ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscCategory + "', " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( pid ) + ", '" + EscName + "', '" + EscFlag + "', " + UTIL_ToString( leaver ) + ", " + UTIL_ToString( practicing ) + " )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) *error = mysql_error( (MYSQL *)conn ); @@ -1058,17 +1058,17 @@ uint32_t MySQLW3MMDPlayerAdd( void *conn, string *error, uint32_t botid, string return RowID; } -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, map var_ints ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, map var_ints ) { if( var_ints.empty( ) ) return false; bool Success = false; - string Query; + QString Query; for( map :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) { - string EscVarName = MySQLEscapeString( conn, i->first.second ); + QString EscVarName = MySQLEscapeString( conn, i->first.second ); if( Query.empty( ) ) Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_int ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', " + UTIL_ToString( i->second ) + " )"; @@ -1084,17 +1084,17 @@ bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gamei return Success; } -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, map var_reals ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, map var_reals ) { if( var_reals.empty( ) ) return false; bool Success = false; - string Query; + QString Query; for( map :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) { - string EscVarName = MySQLEscapeString( conn, i->first.second ); + QString EscVarName = MySQLEscapeString( conn, i->first.second ); if( Query.empty( ) ) Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_real ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', " + UTIL_ToString( i->second, 10 ) + " )"; @@ -1110,21 +1110,21 @@ bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gamei return Success; } -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, map var_strings ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, map var_strings ) { if( var_strings.empty( ) ) return false; bool Success = false; - string Query; + QString Query; - for( map :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) + for( map :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) { - string EscVarName = MySQLEscapeString( conn, i->first.second ); - string EscValueString = MySQLEscapeString( conn, i->second ); + QString EscVarName = MySQLEscapeString( conn, i->first.second ); + QString EscValueString = MySQLEscapeString( conn, i->second ); if( Query.empty( ) ) - Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_string ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', '" + EscValueString + "' )"; + Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_QString ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', '" + EscValueString + "' )"; else Query += ", ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', '" + EscValueString + "' )"; } diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index 2c08443..9d6dd33 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -29,7 +29,7 @@ // CQSLITE3 (wrapper class) // -CSQLITE3 :: CSQLITE3( string filename ) +CSQLITE3 :: CSQLITE3( QString filename ) { m_Ready = true; @@ -42,12 +42,12 @@ CSQLITE3 :: ~CSQLITE3( ) sqlite3_close( (sqlite3 *)m_DB ); } -string CSQLITE3 :: GetError( ) +QString CSQLITE3 :: GetError( ) { return sqlite3_errmsg( (sqlite3 *)m_DB ); } -int CSQLITE3 :: Prepare( string query, void **Statement ) +int CSQLITE3 :: Prepare( QString query, void **Statement ) { return sqlite3_prepare_v2( (sqlite3 *)m_DB, query.c_str( ), -1, (sqlite3_stmt **)Statement, NULL ); } @@ -67,7 +67,7 @@ int CSQLITE3 :: Step( void *Statement ) if( ColumnText ) m_Row.push_back( ColumnText ); else - m_Row.push_back( string( ) ); + m_Row.push_back( QString( ) ); } } @@ -89,7 +89,7 @@ int CSQLITE3 :: ClearBindings( void *Statement ) return sqlite3_clear_bindings( (sqlite3_stmt *)Statement ); } -int CSQLITE3 :: Exec( string query ) +int CSQLITE3 :: Exec( QString query ) { return sqlite3_exec( (sqlite3 *)m_DB, query.c_str( ), NULL, NULL, NULL ); } @@ -106,7 +106,7 @@ uint32_t CSQLITE3 :: LastRowID( ) CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) { m_File = CFG->GetString( "db_sqlite3_file", "ghost.dbs" ); - CONSOLE_Print( "[SQLITE3] version " + string( SQLITE_VERSION ) ); + CONSOLE_Print( "[SQLITE3] version " + QString( SQLITE_VERSION ) ); CONSOLE_Print( "[SQLITE3] opening database [" + m_File + "]" ); m_DB = new CSQLITE3( m_File ); @@ -115,7 +115,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) // setting m_HasError to true indicates there's been a critical error and we want GHost to shutdown // this is okay here because we're in the constructor so we're not dropping any games or players - CONSOLE_Print( string( "[SQLITE3] error opening database [" + m_File + "] - " ) + m_DB->GetError( ) ); + CONSOLE_Print( QString( "[SQLITE3] error opening database [" + m_File + "] - " ) + m_DB->GetError( ) ); m_HasError = true; m_Error = "error opening database"; return; @@ -123,7 +123,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) // find the schema number so we can determine whether we need to upgrade or not - string SchemaNumber; + QString SchemaNumber; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT value FROM config WHERE name=\"schema_number\"", (void **)&Statement ); @@ -133,7 +133,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) if( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + vector *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) SchemaNumber = (*Row)[0]; @@ -232,7 +232,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) if( m_DB->Exec( "CREATE TABLE w3mmdplayers ( id INTEGER PRIMARY KEY, category TEXT NOT NULL, gameid INTEGER NOT NULL, pid INTEGER NOT NULL, name TEXT NOT NULL, flag TEXT NOT NULL, leaver INTEGER NOT NULL, practicing INTEGER NOT NULL )" ) != SQLITE_OK ) CONSOLE_Print( "[SQLITE3] error creating w3mmdplayers table - " + m_DB->GetError( ) ); - if( m_DB->Exec( "CREATE TABLE w3mmdvars ( id INTEGER PRIMARY KEY, gameid INTEGER NOT NULL, pid INTEGER NOT NULL, varname TEXT NOT NULL, value_int INTEGER DEFAULT NULL, value_real REAL DEFAULT NULL, value_string TEXT DEFAULT NULL )" ) != SQLITE_OK ) + if( m_DB->Exec( "CREATE TABLE w3mmdvars ( id INTEGER PRIMARY KEY, gameid INTEGER NOT NULL, pid INTEGER NOT NULL, varname TEXT NOT NULL, value_int INTEGER DEFAULT NULL, value_real REAL DEFAULT NULL, value_QString TEXT DEFAULT NULL )" ) != SQLITE_OK ) CONSOLE_Print( "[SQLITE3] error creating w3mmdvars table - " + m_DB->GetError( ) ); if( m_DB->Exec( "CREATE INDEX idx_gameid ON gameplayers ( gameid )" ) != SQLITE_OK ) @@ -530,7 +530,7 @@ void CGHostDBSQLite :: Upgrade7_8( ) else CONSOLE_Print( "[SQLITE3] created w3mmdplayers table" ); - if( m_DB->Exec( "CREATE TABLE w3mmdvars ( id INTEGER PRIMARY KEY, gameid INTEGER NOT NULL, pid INTEGER NOT NULL, varname TEXT NOT NULL, value_int INTEGER DEFAULT NULL, value_real REAL DEFAULT NULL, value_string TEXT DEFAULT NULL )" ) != SQLITE_OK ) + if( m_DB->Exec( "CREATE TABLE w3mmdvars ( id INTEGER PRIMARY KEY, gameid INTEGER NOT NULL, pid INTEGER NOT NULL, varname TEXT NOT NULL, value_int INTEGER DEFAULT NULL, value_real REAL DEFAULT NULL, value_QString TEXT DEFAULT NULL )" ) != SQLITE_OK ) CONSOLE_Print( "[SQLITE3] error creating w3mmdvars table - " + m_DB->GetError( ) ); else CONSOLE_Print( "[SQLITE3] created w3mmdvars table" ); @@ -555,7 +555,7 @@ bool CGHostDBSQLite :: Commit( ) return m_DB->Exec( "COMMIT TRANSACTION" ) == SQLITE_OK; } -uint32_t CGHostDBSQLite :: AdminCount( string server ) +uint32_t CGHostDBSQLite :: AdminCount( QString server ) { uint32_t Count = 0; sqlite3_stmt *Statement; @@ -579,7 +579,7 @@ uint32_t CGHostDBSQLite :: AdminCount( string server ) return Count; } -bool CGHostDBSQLite :: AdminCheck( string server, string user ) +bool CGHostDBSQLite :: AdminCheck( QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); bool IsAdmin = false; @@ -607,7 +607,7 @@ bool CGHostDBSQLite :: AdminCheck( string server, string user ) return IsAdmin; } -bool CGHostDBSQLite :: AdminAdd( string server, string user ) +bool CGHostDBSQLite :: AdminAdd( QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); bool Success = false; @@ -633,7 +633,7 @@ bool CGHostDBSQLite :: AdminAdd( string server, string user ) return Success; } -bool CGHostDBSQLite :: AdminRemove( string server, string user ) +bool CGHostDBSQLite :: AdminRemove( QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); bool Success = false; @@ -659,9 +659,9 @@ bool CGHostDBSQLite :: AdminRemove( string server, string user ) return Success; } -vector CGHostDBSQLite :: AdminList( string server ) +vector CGHostDBSQLite :: AdminList( QString server ) { - vector AdminList; + vector AdminList; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT name FROM admins WHERE server=?", (void **)&Statement ); @@ -672,7 +672,7 @@ vector CGHostDBSQLite :: AdminList( string server ) while( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + vector *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) AdminList.push_back( (*Row)[0] ); @@ -691,7 +691,7 @@ vector CGHostDBSQLite :: AdminList( string server ) return AdminList; } -uint32_t CGHostDBSQLite :: BanCount( string server ) +uint32_t CGHostDBSQLite :: BanCount( QString server ) { uint32_t Count = 0; sqlite3_stmt *Statement; @@ -715,7 +715,7 @@ uint32_t CGHostDBSQLite :: BanCount( string server ) return Count; } -CDBBan *CGHostDBSQLite :: BanCheck( string server, string user, string ip ) +CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); CDBBan *Ban = NULL; @@ -738,7 +738,7 @@ CDBBan *CGHostDBSQLite :: BanCheck( string server, string user, string ip ) if( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + vector *Row = m_DB->GetRow( ); if( Row->size( ) == 6 ) Ban = new CDBBan( server, (*Row)[0], (*Row)[1], (*Row)[2], (*Row)[3], (*Row)[4], (*Row)[5] ); @@ -756,7 +756,7 @@ CDBBan *CGHostDBSQLite :: BanCheck( string server, string user, string ip ) return Ban; } -bool CGHostDBSQLite :: BanAdd( string server, string user, string ip, string gamename, string admin, string reason ) +bool CGHostDBSQLite :: BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); bool Success = false; @@ -787,7 +787,7 @@ bool CGHostDBSQLite :: BanAdd( string server, string user, string ip, string gam return Success; } -bool CGHostDBSQLite :: BanRemove( string server, string user ) +bool CGHostDBSQLite :: BanRemove( QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); bool Success = false; @@ -813,7 +813,7 @@ bool CGHostDBSQLite :: BanRemove( string server, string user ) return Success; } -bool CGHostDBSQLite :: BanRemove( string user ) +bool CGHostDBSQLite :: BanRemove( QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); bool Success = false; @@ -838,7 +838,7 @@ bool CGHostDBSQLite :: BanRemove( string user ) return Success; } -vector CGHostDBSQLite :: BanList( string server ) +vector CGHostDBSQLite :: BanList( QString server ) { vector BanList; sqlite3_stmt *Statement; @@ -851,7 +851,7 @@ vector CGHostDBSQLite :: BanList( string server ) while( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + vector *Row = m_DB->GetRow( ); if( Row->size( ) == 6 ) BanList.push_back( new CDBBan( server, (*Row)[0], (*Row)[1], (*Row)[2], (*Row)[3], (*Row)[4], (*Row)[5] ) ); @@ -870,7 +870,7 @@ vector CGHostDBSQLite :: BanList( string server ) return BanList; } -uint32_t CGHostDBSQLite :: GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) +uint32_t CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) { uint32_t RowID = 0; sqlite3_stmt *Statement; @@ -902,7 +902,7 @@ uint32_t CGHostDBSQLite :: GameAdd( string server, string map, string gamename, return RowID; } -uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ) +uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); uint32_t RowID = 0; @@ -938,7 +938,7 @@ uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, string name, string i return RowID; } -uint32_t CGHostDBSQLite :: GamePlayerCount( string name ) +uint32_t CGHostDBSQLite :: GamePlayerCount( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); uint32_t Count = 0; @@ -963,7 +963,7 @@ uint32_t CGHostDBSQLite :: GamePlayerCount( string name ) return Count; } -CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( string name ) +CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( QString name ) { if( GamePlayerCount( name ) == 0 ) return NULL; @@ -984,8 +984,8 @@ CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( string name ) { char *First = (char *)sqlite3_column_text( (sqlite3_stmt *)Statement, 0 ); char *Last = (char *)sqlite3_column_text( (sqlite3_stmt *)Statement, 1 ); - string FirstGameDateTime; - string LastGameDateTime; + QString FirstGameDateTime; + QString LastGameDateTime; if( First ) FirstGameDateTime = First; @@ -1003,7 +1003,7 @@ CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( string name ) uint32_t MinDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 9 ); uint32_t AvgDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 10 ); uint32_t MaxDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 11 ); - GamePlayerSummary = new CDBGamePlayerSummary( string( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); + GamePlayerSummary = new CDBGamePlayerSummary( QString( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); } else CONSOLE_Print( "[SQLITE3] error checking gameplayersummary [" + name + "] - row doesn't have 12 columns" ); @@ -1047,7 +1047,7 @@ uint32_t CGHostDBSQLite :: DotAGameAdd( uint32_t gameid, uint32_t winner, uint32 return RowID; } -uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) { uint32_t RowID = 0; sqlite3_stmt *Statement; @@ -1091,7 +1091,7 @@ uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint return RowID; } -uint32_t CGHostDBSQLite :: DotAPlayerCount( string name ) +uint32_t CGHostDBSQLite :: DotAPlayerCount( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); uint32_t Count = 0; @@ -1116,7 +1116,7 @@ uint32_t CGHostDBSQLite :: DotAPlayerCount( string name ) return Count; } -CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( string name ) +CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) { if( DotAPlayerCount( name ) == 0 ) return NULL; @@ -1190,7 +1190,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( string name ) // done - DotAPlayerSummary = new CDBDotAPlayerSummary( string( ), name, TotalGames, TotalWins, TotalLosses, TotalKills, TotalDeaths, TotalCreepKills, TotalCreepDenies, TotalAssists, TotalNeutralKills, TotalTowerKills, TotalRaxKills, TotalCourierKills ); + DotAPlayerSummary = new CDBDotAPlayerSummary( QString( ), name, TotalGames, TotalWins, TotalLosses, TotalKills, TotalDeaths, TotalCreepKills, TotalCreepDenies, TotalAssists, TotalNeutralKills, TotalTowerKills, TotalRaxKills, TotalCourierKills ); } else CONSOLE_Print( "[SQLITE3] error checking dotaplayersummary [" + name + "] - row doesn't have 7 columns" ); @@ -1206,11 +1206,11 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( string name ) return DotAPlayerSummary; } -string CGHostDBSQLite :: FromCheck( uint32_t ip ) +QString CGHostDBSQLite :: FromCheck( uint32_t ip ) { // a big thank you to tjado for help with the iptocountry feature - string From = "??"; + QString From = "??"; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT country FROM iptocountry WHERE ip1<=? AND ip2>=?", (void **)&Statement ); @@ -1224,7 +1224,7 @@ string CGHostDBSQLite :: FromCheck( uint32_t ip ) if( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + vector *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) From = (*Row)[0]; @@ -1242,7 +1242,7 @@ string CGHostDBSQLite :: FromCheck( uint32_t ip ) return From; } -bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, string country ) +bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) { // a big thank you to tjado for help with the iptocountry feature @@ -1274,7 +1274,7 @@ bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, string country ) return Success; } -bool CGHostDBSQLite :: DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) +bool CGHostDBSQLite :: DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) { bool Success = false; sqlite3_stmt *Statement; @@ -1305,7 +1305,7 @@ bool CGHostDBSQLite :: DownloadAdd( string map, uint32_t mapsize, string name, s return Success; } -uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ) +uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) { uint32_t RowID = 0; sqlite3_stmt *Statement; @@ -1426,7 +1426,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_reals return Success; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_strings ) +bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_strings ) { if( var_strings.empty( ) ) return false; @@ -1434,10 +1434,10 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_string bool Success = true; sqlite3_stmt *Statement = NULL; - for( map :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) + for( map :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) { if( !Statement ) - m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_string ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); + m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_QString ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); if( Statement ) { @@ -1451,7 +1451,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_string if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-string [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + i->second + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + i->second + "] - " + m_DB->GetError( ) ); break; } @@ -1460,7 +1460,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_string else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-string [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + i->second + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + i->second + "] - " + m_DB->GetError( ) ); break; } } @@ -1471,7 +1471,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_string return Success; } -CCallableAdminCount *CGHostDBSQLite :: ThreadedAdminCount( string server ) +CCallableAdminCount *CGHostDBSQLite :: ThreadedAdminCount( QString server ) { CCallableAdminCount *Callable = new CCallableAdminCount( server ); Callable->SetResult( AdminCount( server ) ); @@ -1479,7 +1479,7 @@ CCallableAdminCount *CGHostDBSQLite :: ThreadedAdminCount( string server ) return Callable; } -CCallableAdminCheck *CGHostDBSQLite :: ThreadedAdminCheck( string server, string user ) +CCallableAdminCheck *CGHostDBSQLite :: ThreadedAdminCheck( QString server, QString user ) { CCallableAdminCheck *Callable = new CCallableAdminCheck( server, user ); Callable->SetResult( AdminCheck( server, user ) ); @@ -1487,7 +1487,7 @@ CCallableAdminCheck *CGHostDBSQLite :: ThreadedAdminCheck( string server, string return Callable; } -CCallableAdminAdd *CGHostDBSQLite :: ThreadedAdminAdd( string server, string user ) +CCallableAdminAdd *CGHostDBSQLite :: ThreadedAdminAdd( QString server, QString user ) { CCallableAdminAdd *Callable = new CCallableAdminAdd( server, user ); Callable->SetResult( AdminAdd( server, user ) ); @@ -1495,7 +1495,7 @@ CCallableAdminAdd *CGHostDBSQLite :: ThreadedAdminAdd( string server, string use return Callable; } -CCallableAdminRemove *CGHostDBSQLite :: ThreadedAdminRemove( string server, string user ) +CCallableAdminRemove *CGHostDBSQLite :: ThreadedAdminRemove( QString server, QString user ) { CCallableAdminRemove *Callable = new CCallableAdminRemove( server, user ); Callable->SetResult( AdminRemove( server, user ) ); @@ -1503,7 +1503,7 @@ CCallableAdminRemove *CGHostDBSQLite :: ThreadedAdminRemove( string server, stri return Callable; } -CCallableAdminList *CGHostDBSQLite :: ThreadedAdminList( string server ) +CCallableAdminList *CGHostDBSQLite :: ThreadedAdminList( QString server ) { CCallableAdminList *Callable = new CCallableAdminList( server ); Callable->SetResult( AdminList( server ) ); @@ -1511,7 +1511,7 @@ CCallableAdminList *CGHostDBSQLite :: ThreadedAdminList( string server ) return Callable; } -CCallableBanCount *CGHostDBSQLite :: ThreadedBanCount( string server ) +CCallableBanCount *CGHostDBSQLite :: ThreadedBanCount( QString server ) { CCallableBanCount *Callable = new CCallableBanCount( server ); Callable->SetResult( BanCount( server ) ); @@ -1519,7 +1519,7 @@ CCallableBanCount *CGHostDBSQLite :: ThreadedBanCount( string server ) return Callable; } -CCallableBanCheck *CGHostDBSQLite :: ThreadedBanCheck( string server, string user, string ip ) +CCallableBanCheck *CGHostDBSQLite :: ThreadedBanCheck( QString server, QString user, QString ip ) { CCallableBanCheck *Callable = new CCallableBanCheck( server, user, ip ); Callable->SetResult( BanCheck( server, user, ip ) ); @@ -1527,7 +1527,7 @@ CCallableBanCheck *CGHostDBSQLite :: ThreadedBanCheck( string server, string use return Callable; } -CCallableBanAdd *CGHostDBSQLite :: ThreadedBanAdd( string server, string user, string ip, string gamename, string admin, string reason ) +CCallableBanAdd *CGHostDBSQLite :: ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { CCallableBanAdd *Callable = new CCallableBanAdd( server, user, ip, gamename, admin, reason ); Callable->SetResult( BanAdd( server, user, ip, gamename, admin, reason ) ); @@ -1535,7 +1535,7 @@ CCallableBanAdd *CGHostDBSQLite :: ThreadedBanAdd( string server, string user, s return Callable; } -CCallableBanRemove *CGHostDBSQLite :: ThreadedBanRemove( string server, string user ) +CCallableBanRemove *CGHostDBSQLite :: ThreadedBanRemove( QString server, QString user ) { CCallableBanRemove *Callable = new CCallableBanRemove( server, user ); Callable->SetResult( BanRemove( server, user ) ); @@ -1543,15 +1543,15 @@ CCallableBanRemove *CGHostDBSQLite :: ThreadedBanRemove( string server, string u return Callable; } -CCallableBanRemove *CGHostDBSQLite :: ThreadedBanRemove( string user ) +CCallableBanRemove *CGHostDBSQLite :: ThreadedBanRemove( QString user ) { - CCallableBanRemove *Callable = new CCallableBanRemove( string( ), user ); + CCallableBanRemove *Callable = new CCallableBanRemove( QString( ), user ); Callable->SetResult( BanRemove( user ) ); Callable->SetReady( true ); return Callable; } -CCallableBanList *CGHostDBSQLite :: ThreadedBanList( string server ) +CCallableBanList *CGHostDBSQLite :: ThreadedBanList( QString server ) { CCallableBanList *Callable = new CCallableBanList( server ); Callable->SetResult( BanList( server ) ); @@ -1559,7 +1559,7 @@ CCallableBanList *CGHostDBSQLite :: ThreadedBanList( string server ) return Callable; } -CCallableGameAdd *CGHostDBSQLite :: ThreadedGameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) +CCallableGameAdd *CGHostDBSQLite :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) { CCallableGameAdd *Callable = new CCallableGameAdd( server, map, gamename, ownername, duration, gamestate, creatorname, creatorserver ); Callable->SetResult( GameAdd( server, map, gamename, ownername, duration, gamestate, creatorname, creatorserver ) ); @@ -1567,7 +1567,7 @@ CCallableGameAdd *CGHostDBSQLite :: ThreadedGameAdd( string server, string map, return Callable; } -CCallableGamePlayerAdd *CGHostDBSQLite :: ThreadedGamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ) +CCallableGamePlayerAdd *CGHostDBSQLite :: ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { CCallableGamePlayerAdd *Callable = new CCallableGamePlayerAdd( gameid, name, ip, spoofed, spoofedrealm, reserved, loadingtime, left, leftreason, team, colour ); Callable->SetResult( GamePlayerAdd( gameid, name, ip, spoofed, spoofedrealm, reserved, loadingtime, left, leftreason, team, colour ) ); @@ -1575,7 +1575,7 @@ CCallableGamePlayerAdd *CGHostDBSQLite :: ThreadedGamePlayerAdd( uint32_t gameid return Callable; } -CCallableGamePlayerSummaryCheck *CGHostDBSQLite :: ThreadedGamePlayerSummaryCheck( string name ) +CCallableGamePlayerSummaryCheck *CGHostDBSQLite :: ThreadedGamePlayerSummaryCheck( QString name ) { CCallableGamePlayerSummaryCheck *Callable = new CCallableGamePlayerSummaryCheck( name ); Callable->SetResult( GamePlayerSummaryCheck( name ) ); @@ -1591,7 +1591,7 @@ CCallableDotAGameAdd *CGHostDBSQLite :: ThreadedDotAGameAdd( uint32_t gameid, ui return Callable; } -CCallableDotAPlayerAdd *CGHostDBSQLite :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +CCallableDotAPlayerAdd *CGHostDBSQLite :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) { CCallableDotAPlayerAdd *Callable = new CCallableDotAPlayerAdd( gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ); Callable->SetResult( DotAPlayerAdd( gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) ); @@ -1599,7 +1599,7 @@ CCallableDotAPlayerAdd *CGHostDBSQLite :: ThreadedDotAPlayerAdd( uint32_t gameid return Callable; } -CCallableDotAPlayerSummaryCheck *CGHostDBSQLite :: ThreadedDotAPlayerSummaryCheck( string name ) +CCallableDotAPlayerSummaryCheck *CGHostDBSQLite :: ThreadedDotAPlayerSummaryCheck( QString name ) { CCallableDotAPlayerSummaryCheck *Callable = new CCallableDotAPlayerSummaryCheck( name ); Callable->SetResult( DotAPlayerSummaryCheck( name ) ); @@ -1607,7 +1607,7 @@ CCallableDotAPlayerSummaryCheck *CGHostDBSQLite :: ThreadedDotAPlayerSummaryChec return Callable; } -CCallableDownloadAdd *CGHostDBSQLite :: ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) +CCallableDownloadAdd *CGHostDBSQLite :: ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) { CCallableDownloadAdd *Callable = new CCallableDownloadAdd( map, mapsize, name, ip, spoofed, spoofedrealm, downloadtime ); Callable->SetResult( DownloadAdd( map, mapsize, name, ip, spoofed, spoofedrealm, downloadtime ) ); @@ -1615,7 +1615,7 @@ CCallableDownloadAdd *CGHostDBSQLite :: ThreadedDownloadAdd( string map, uint32_ return Callable; } -CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ) +CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) { CCallableW3MMDPlayerAdd *Callable = new CCallableW3MMDPlayerAdd( category, gameid, pid, name, flag, leaver, practicing ); Callable->SetResult( W3MMDPlayerAdd( category, gameid, pid, name, flag, leaver, practicing ) ); @@ -1639,7 +1639,7 @@ CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, ma return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_strings ); Callable->SetResult( W3MMDVarAdd( gameid, var_strings ) ); diff --git a/ghost/includes.h b/ghost/includes.h index f2954bb..cb17762 100644 --- a/ghost/includes.h +++ b/ghost/includes.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -39,13 +39,15 @@ #include #include #include -#include +#include #include +#include + using namespace std; typedef vector BYTEARRAY; -typedef pair PIDPlayer; +typedef pair PIDPlayer; // time @@ -65,8 +67,8 @@ uint32_t GetTicks( ); // milliseconds // output -void CONSOLE_Print( string message ); -void DEBUG_Print( string message ); +void CONSOLE_Print( QString message ); +void DEBUG_Print( QString message ); void DEBUG_Print( BYTEARRAY b ); #endif diff --git a/ghost/language.cpp b/ghost/language.cpp index 7802ceb..1a3c2a5 100644 --- a/ghost/language.cpp +++ b/ghost/language.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -27,7 +27,7 @@ // CLanguage // -CLanguage :: CLanguage( string nCFGFile ) +CLanguage :: CLanguage( QString nCFGFile ) { m_CFG = new CConfig( ); m_CFG->Read( nCFGFile ); @@ -38,86 +38,86 @@ CLanguage :: ~CLanguage( ) delete m_CFG; } -string CLanguage :: UnableToCreateGameTryAnotherName( string server, string gamename ) +QString CLanguage :: UnableToCreateGameTryAnotherName( QString server, QString gamename ) { - string Out = m_CFG->GetString( "lang_0001", "lang_0001" ); + QString Out = m_CFG->GetString( "lang_0001", "lang_0001" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: UserIsAlreadyAnAdmin( string server, string user ) +QString CLanguage :: UserIsAlreadyAnAdmin( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0002", "lang_0002" ); + QString Out = m_CFG->GetString( "lang_0002", "lang_0002" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: AddedUserToAdminDatabase( string server, string user ) +QString CLanguage :: AddedUserToAdminDatabase( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0003", "lang_0003" ); + QString Out = m_CFG->GetString( "lang_0003", "lang_0003" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: ErrorAddingUserToAdminDatabase( string server, string user ) +QString CLanguage :: ErrorAddingUserToAdminDatabase( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0004", "lang_0004" ); + QString Out = m_CFG->GetString( "lang_0004", "lang_0004" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: YouDontHaveAccessToThatCommand( ) +QString CLanguage :: YouDontHaveAccessToThatCommand( ) { return m_CFG->GetString( "lang_0005", "lang_0005" ); } -string CLanguage :: UserIsAlreadyBanned( string server, string victim ) +QString CLanguage :: UserIsAlreadyBanned( QString server, QString victim ) { - string Out = m_CFG->GetString( "lang_0006", "lang_0006" ); + QString Out = m_CFG->GetString( "lang_0006", "lang_0006" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: BannedUser( string server, string victim ) +QString CLanguage :: BannedUser( QString server, QString victim ) { - string Out = m_CFG->GetString( "lang_0007", "lang_0007" ); + QString Out = m_CFG->GetString( "lang_0007", "lang_0007" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: ErrorBanningUser( string server, string victim ) +QString CLanguage :: ErrorBanningUser( QString server, QString victim ) { - string Out = m_CFG->GetString( "lang_0008", "lang_0008" ); + QString Out = m_CFG->GetString( "lang_0008", "lang_0008" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: UserIsAnAdmin( string server, string user ) +QString CLanguage :: UserIsAnAdmin( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0009", "lang_0009" ); + QString Out = m_CFG->GetString( "lang_0009", "lang_0009" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UserIsNotAnAdmin( string server, string user ) +QString CLanguage :: UserIsNotAnAdmin( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0010", "lang_0010" ); + QString Out = m_CFG->GetString( "lang_0010", "lang_0010" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UserWasBannedOnByBecause( string server, string victim, string date, string admin, string reason ) +QString CLanguage :: UserWasBannedOnByBecause( QString server, QString victim, QString date, QString admin, QString reason ) { - string Out = m_CFG->GetString( "lang_0011", "lang_0011" ); + QString Out = m_CFG->GetString( "lang_0011", "lang_0011" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$DATE$", date ); @@ -126,356 +126,356 @@ string CLanguage :: UserWasBannedOnByBecause( string server, string victim, stri return Out; } -string CLanguage :: UserIsNotBanned( string server, string victim ) +QString CLanguage :: UserIsNotBanned( QString server, QString victim ) { - string Out = m_CFG->GetString( "lang_0012", "lang_0012" ); + QString Out = m_CFG->GetString( "lang_0012", "lang_0012" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: ThereAreNoAdmins( string server ) +QString CLanguage :: ThereAreNoAdmins( QString server ) { - string Out = m_CFG->GetString( "lang_0013", "lang_0013" ); + QString Out = m_CFG->GetString( "lang_0013", "lang_0013" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: ThereIsAdmin( string server ) +QString CLanguage :: ThereIsAdmin( QString server ) { - string Out = m_CFG->GetString( "lang_0014", "lang_0014" ); + QString Out = m_CFG->GetString( "lang_0014", "lang_0014" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: ThereAreAdmins( string server, string count ) +QString CLanguage :: ThereAreAdmins( QString server, QString count ) { - string Out = m_CFG->GetString( "lang_0015", "lang_0015" ); + QString Out = m_CFG->GetString( "lang_0015", "lang_0015" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$COUNT$", count ); return Out; } -string CLanguage :: ThereAreNoBannedUsers( string server ) +QString CLanguage :: ThereAreNoBannedUsers( QString server ) { - string Out = m_CFG->GetString( "lang_0016", "lang_0016" ); + QString Out = m_CFG->GetString( "lang_0016", "lang_0016" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: ThereIsBannedUser( string server ) +QString CLanguage :: ThereIsBannedUser( QString server ) { - string Out = m_CFG->GetString( "lang_0017", "lang_0017" ); + QString Out = m_CFG->GetString( "lang_0017", "lang_0017" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: ThereAreBannedUsers( string server, string count ) +QString CLanguage :: ThereAreBannedUsers( QString server, QString count ) { - string Out = m_CFG->GetString( "lang_0018", "lang_0018" ); + QString Out = m_CFG->GetString( "lang_0018", "lang_0018" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$COUNT$", count ); return Out; } -string CLanguage :: YouCantDeleteTheRootAdmin( ) +QString CLanguage :: YouCantDeleteTheRootAdmin( ) { return m_CFG->GetString( "lang_0019", "lang_0019" ); } -string CLanguage :: DeletedUserFromAdminDatabase( string server, string user ) +QString CLanguage :: DeletedUserFromAdminDatabase( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0020", "lang_0020" ); + QString Out = m_CFG->GetString( "lang_0020", "lang_0020" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: ErrorDeletingUserFromAdminDatabase( string server, string user ) +QString CLanguage :: ErrorDeletingUserFromAdminDatabase( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0021", "lang_0021" ); + QString Out = m_CFG->GetString( "lang_0021", "lang_0021" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UnbannedUser( string victim ) +QString CLanguage :: UnbannedUser( QString victim ) { - string Out = m_CFG->GetString( "lang_0022", "lang_0022" ); + QString Out = m_CFG->GetString( "lang_0022", "lang_0022" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: ErrorUnbanningUser( string victim ) +QString CLanguage :: ErrorUnbanningUser( QString victim ) { - string Out = m_CFG->GetString( "lang_0023", "lang_0023" ); + QString Out = m_CFG->GetString( "lang_0023", "lang_0023" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: GameNumberIs( string number, string description ) +QString CLanguage :: GameNumberIs( QString number, QString description ) { - string Out = m_CFG->GetString( "lang_0024", "lang_0024" ); + QString Out = m_CFG->GetString( "lang_0024", "lang_0024" ); UTIL_Replace( Out, "$NUMBER$", number ); UTIL_Replace( Out, "$DESCRIPTION$", description ); return Out; } -string CLanguage :: GameNumberDoesntExist( string number ) +QString CLanguage :: GameNumberDoesntExist( QString number ) { - string Out = m_CFG->GetString( "lang_0025", "lang_0025" ); + QString Out = m_CFG->GetString( "lang_0025", "lang_0025" ); UTIL_Replace( Out, "$NUMBER$", number ); return Out; } -string CLanguage :: GameIsInTheLobby( string description, string current, string max ) +QString CLanguage :: GameIsInTheLobby( QString description, QString current, QString max ) { - string Out = m_CFG->GetString( "lang_0026", "lang_0026" ); + QString Out = m_CFG->GetString( "lang_0026", "lang_0026" ); UTIL_Replace( Out, "$DESCRIPTION$", description ); UTIL_Replace( Out, "$CURRENT$", current ); UTIL_Replace( Out, "$MAX$", max ); return Out; } -string CLanguage :: ThereIsNoGameInTheLobby( string current, string max ) +QString CLanguage :: ThereIsNoGameInTheLobby( QString current, QString max ) { - string Out = m_CFG->GetString( "lang_0027", "lang_0027" ); + QString Out = m_CFG->GetString( "lang_0027", "lang_0027" ); UTIL_Replace( Out, "$CURRENT$", current ); UTIL_Replace( Out, "$MAX$", max ); return Out; } -string CLanguage :: UnableToLoadConfigFilesOutside( ) +QString CLanguage :: UnableToLoadConfigFilesOutside( ) { return m_CFG->GetString( "lang_0028", "lang_0028" ); } -string CLanguage :: LoadingConfigFile( string file ) +QString CLanguage :: LoadingConfigFile( QString file ) { - string Out = m_CFG->GetString( "lang_0029", "lang_0029" ); + QString Out = m_CFG->GetString( "lang_0029", "lang_0029" ); UTIL_Replace( Out, "$FILE$", file ); return Out; } -string CLanguage :: UnableToLoadConfigFileDoesntExist( string file ) +QString CLanguage :: UnableToLoadConfigFileDoesntExist( QString file ) { - string Out = m_CFG->GetString( "lang_0030", "lang_0030" ); + QString Out = m_CFG->GetString( "lang_0030", "lang_0030" ); UTIL_Replace( Out, "$FILE$", file ); return Out; } -string CLanguage :: CreatingPrivateGame( string gamename, string user ) +QString CLanguage :: CreatingPrivateGame( QString gamename, QString user ) { - string Out = m_CFG->GetString( "lang_0031", "lang_0031" ); + QString Out = m_CFG->GetString( "lang_0031", "lang_0031" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: CreatingPublicGame( string gamename, string user ) +QString CLanguage :: CreatingPublicGame( QString gamename, QString user ) { - string Out = m_CFG->GetString( "lang_0032", "lang_0032" ); + QString Out = m_CFG->GetString( "lang_0032", "lang_0032" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UnableToUnhostGameCountdownStarted( string description ) +QString CLanguage :: UnableToUnhostGameCountdownStarted( QString description ) { - string Out = m_CFG->GetString( "lang_0033", "lang_0033" ); + QString Out = m_CFG->GetString( "lang_0033", "lang_0033" ); UTIL_Replace( Out, "$DESCRIPTION$", description ); return Out; } -string CLanguage :: UnhostingGame( string description ) +QString CLanguage :: UnhostingGame( QString description ) { - string Out = m_CFG->GetString( "lang_0034", "lang_0034" ); + QString Out = m_CFG->GetString( "lang_0034", "lang_0034" ); UTIL_Replace( Out, "$DESCRIPTION$", description ); return Out; } -string CLanguage :: UnableToUnhostGameNoGameInLobby( ) +QString CLanguage :: UnableToUnhostGameNoGameInLobby( ) { return m_CFG->GetString( "lang_0035", "lang_0035" ); } -string CLanguage :: VersionAdmin( string version ) +QString CLanguage :: VersionAdmin( QString version ) { - string Out = m_CFG->GetString( "lang_0036", "lang_0036" ); + QString Out = m_CFG->GetString( "lang_0036", "lang_0036" ); UTIL_Replace( Out, "$VERSION$", version ); return Out; } -string CLanguage :: VersionNotAdmin( string version ) +QString CLanguage :: VersionNotAdmin( QString version ) { - string Out = m_CFG->GetString( "lang_0037", "lang_0037" ); + QString Out = m_CFG->GetString( "lang_0037", "lang_0037" ); UTIL_Replace( Out, "$VERSION$", version ); return Out; } -string CLanguage :: UnableToCreateGameAnotherGameInLobby( string gamename, string description ) +QString CLanguage :: UnableToCreateGameAnotherGameInLobby( QString gamename, QString description ) { - string Out = m_CFG->GetString( "lang_0038", "lang_0038" ); + QString Out = m_CFG->GetString( "lang_0038", "lang_0038" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); UTIL_Replace( Out, "$DESCRIPTION$", description ); return Out; } -string CLanguage :: UnableToCreateGameMaxGamesReached( string gamename, string max ) +QString CLanguage :: UnableToCreateGameMaxGamesReached( QString gamename, QString max ) { - string Out = m_CFG->GetString( "lang_0039", "lang_0039" ); + QString Out = m_CFG->GetString( "lang_0039", "lang_0039" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); UTIL_Replace( Out, "$MAX$", max ); return Out; } -string CLanguage :: GameIsOver( string description ) +QString CLanguage :: GameIsOver( QString description ) { - string Out = m_CFG->GetString( "lang_0040", "lang_0040" ); + QString Out = m_CFG->GetString( "lang_0040", "lang_0040" ); UTIL_Replace( Out, "$DESCRIPTION$", description ); return Out; } -string CLanguage :: SpoofCheckByReplying( ) +QString CLanguage :: SpoofCheckByReplying( ) { return m_CFG->GetString( "lang_0041", "lang_0041" ); } -string CLanguage :: GameRefreshed( ) +QString CLanguage :: GameRefreshed( ) { return m_CFG->GetString( "lang_0042", "lang_0042" ); } -string CLanguage :: SpoofPossibleIsAway( string user ) +QString CLanguage :: SpoofPossibleIsAway( QString user ) { - string Out = m_CFG->GetString( "lang_0043", "lang_0043" ); + QString Out = m_CFG->GetString( "lang_0043", "lang_0043" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: SpoofPossibleIsUnavailable( string user ) +QString CLanguage :: SpoofPossibleIsUnavailable( QString user ) { - string Out = m_CFG->GetString( "lang_0044", "lang_0044" ); + QString Out = m_CFG->GetString( "lang_0044", "lang_0044" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: SpoofPossibleIsRefusingMessages( string user ) +QString CLanguage :: SpoofPossibleIsRefusingMessages( QString user ) { - string Out = m_CFG->GetString( "lang_0045", "lang_0045" ); + QString Out = m_CFG->GetString( "lang_0045", "lang_0045" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: SpoofDetectedIsNotInGame( string user ) +QString CLanguage :: SpoofDetectedIsNotInGame( QString user ) { - string Out = m_CFG->GetString( "lang_0046", "lang_0046" ); + QString Out = m_CFG->GetString( "lang_0046", "lang_0046" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: SpoofDetectedIsInPrivateChannel( string user ) +QString CLanguage :: SpoofDetectedIsInPrivateChannel( QString user ) { - string Out = m_CFG->GetString( "lang_0047", "lang_0047" ); + QString Out = m_CFG->GetString( "lang_0047", "lang_0047" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: SpoofDetectedIsInAnotherGame( string user ) +QString CLanguage :: SpoofDetectedIsInAnotherGame( QString user ) { - string Out = m_CFG->GetString( "lang_0048", "lang_0048" ); + QString Out = m_CFG->GetString( "lang_0048", "lang_0048" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: CountDownAborted( ) +QString CLanguage :: CountDownAborted( ) { return m_CFG->GetString( "lang_0049", "lang_0049" ); } -string CLanguage :: TryingToJoinTheGameButBanned( string victim ) +QString CLanguage :: TryingToJoinTheGameButBanned( QString victim ) { - string Out = m_CFG->GetString( "lang_0050", "lang_0050" ); + QString Out = m_CFG->GetString( "lang_0050", "lang_0050" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: UnableToBanNoMatchesFound( string victim ) +QString CLanguage :: UnableToBanNoMatchesFound( QString victim ) { - string Out = m_CFG->GetString( "lang_0051", "lang_0051" ); + QString Out = m_CFG->GetString( "lang_0051", "lang_0051" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: PlayerWasBannedByPlayer( string server, string victim, string user ) +QString CLanguage :: PlayerWasBannedByPlayer( QString server, QString victim, QString user ) { - string Out = m_CFG->GetString( "lang_0052", "lang_0052" ); + QString Out = m_CFG->GetString( "lang_0052", "lang_0052" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UnableToBanFoundMoreThanOneMatch( string victim ) +QString CLanguage :: UnableToBanFoundMoreThanOneMatch( QString victim ) { - string Out = m_CFG->GetString( "lang_0053", "lang_0053" ); + QString Out = m_CFG->GetString( "lang_0053", "lang_0053" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: AddedPlayerToTheHoldList( string user ) +QString CLanguage :: AddedPlayerToTheHoldList( QString user ) { - string Out = m_CFG->GetString( "lang_0054", "lang_0054" ); + QString Out = m_CFG->GetString( "lang_0054", "lang_0054" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UnableToKickNoMatchesFound( string victim ) +QString CLanguage :: UnableToKickNoMatchesFound( QString victim ) { - string Out = m_CFG->GetString( "lang_0055", "lang_0055" ); + QString Out = m_CFG->GetString( "lang_0055", "lang_0055" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: UnableToKickFoundMoreThanOneMatch( string victim ) +QString CLanguage :: UnableToKickFoundMoreThanOneMatch( QString victim ) { - string Out = m_CFG->GetString( "lang_0056", "lang_0056" ); + QString Out = m_CFG->GetString( "lang_0056", "lang_0056" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: SettingLatencyToMinimum( string min ) +QString CLanguage :: SettingLatencyToMinimum( QString min ) { - string Out = m_CFG->GetString( "lang_0057", "lang_0057" ); + QString Out = m_CFG->GetString( "lang_0057", "lang_0057" ); UTIL_Replace( Out, "$MIN$", min ); return Out; } -string CLanguage :: SettingLatencyToMaximum( string max ) +QString CLanguage :: SettingLatencyToMaximum( QString max ) { - string Out = m_CFG->GetString( "lang_0058", "lang_0058" ); + QString Out = m_CFG->GetString( "lang_0058", "lang_0058" ); UTIL_Replace( Out, "$MAX$", max ); return Out; } -string CLanguage :: SettingLatencyTo( string latency ) +QString CLanguage :: SettingLatencyTo( QString latency ) { - string Out = m_CFG->GetString( "lang_0059", "lang_0059" ); + QString Out = m_CFG->GetString( "lang_0059", "lang_0059" ); UTIL_Replace( Out, "$LATENCY$", latency ); return Out; } -string CLanguage :: KickingPlayersWithPingsGreaterThan( string total, string ping ) +QString CLanguage :: KickingPlayersWithPingsGreaterThan( QString total, QString ping ) { - string Out = m_CFG->GetString( "lang_0060", "lang_0060" ); + QString Out = m_CFG->GetString( "lang_0060", "lang_0060" ); UTIL_Replace( Out, "$TOTAL$", total ); UTIL_Replace( Out, "$PING$", ping ); return Out; } -string CLanguage :: HasPlayedGamesWithThisBot( string user, string firstgame, string lastgame, string totalgames, string avgloadingtime, string avgstay ) +QString CLanguage :: HasPlayedGamesWithThisBot( QString user, QString firstgame, QString lastgame, QString totalgames, QString avgloadingtime, QString avgstay ) { - string Out = m_CFG->GetString( "lang_0061", "lang_0061" ); + QString Out = m_CFG->GetString( "lang_0061", "lang_0061" ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$FIRSTGAME$", firstgame ); UTIL_Replace( Out, "$LASTGAME$", lastgame ); @@ -485,93 +485,93 @@ string CLanguage :: HasPlayedGamesWithThisBot( string user, string firstgame, st return Out; } -string CLanguage :: HasntPlayedGamesWithThisBot( string user ) +QString CLanguage :: HasntPlayedGamesWithThisBot( QString user ) { - string Out = m_CFG->GetString( "lang_0062", "lang_0062" ); + QString Out = m_CFG->GetString( "lang_0062", "lang_0062" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: AutokickingPlayerForExcessivePing( string victim, string ping ) +QString CLanguage :: AutokickingPlayerForExcessivePing( QString victim, QString ping ) { - string Out = m_CFG->GetString( "lang_0063", "lang_0063" ); + QString Out = m_CFG->GetString( "lang_0063", "lang_0063" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$PING$", ping ); return Out; } -string CLanguage :: SpoofCheckAcceptedFor( string server, string user ) +QString CLanguage :: SpoofCheckAcceptedFor( QString server, QString user ) { - string Out = m_CFG->GetString( "lang_0064", "lang_0064" ); + QString Out = m_CFG->GetString( "lang_0064", "lang_0064" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: PlayersNotYetSpoofChecked( string notspoofchecked ) +QString CLanguage :: PlayersNotYetSpoofChecked( QString notspoofchecked ) { - string Out = m_CFG->GetString( "lang_0065", "lang_0065" ); + QString Out = m_CFG->GetString( "lang_0065", "lang_0065" ); UTIL_Replace( Out, "$NOTSPOOFCHECKED$", notspoofchecked ); return Out; } -string CLanguage :: ManuallySpoofCheckByWhispering( string hostname ) +QString CLanguage :: ManuallySpoofCheckByWhispering( QString hostname ) { - string Out = m_CFG->GetString( "lang_0066", "lang_0066" ); + QString Out = m_CFG->GetString( "lang_0066", "lang_0066" ); UTIL_Replace( Out, "$HOSTNAME$", hostname ); return Out; } -string CLanguage :: SpoofCheckByWhispering( string hostname ) +QString CLanguage :: SpoofCheckByWhispering( QString hostname ) { - string Out = m_CFG->GetString( "lang_0067", "lang_0067" ); + QString Out = m_CFG->GetString( "lang_0067", "lang_0067" ); UTIL_Replace( Out, "$HOSTNAME$", hostname ); return Out; } -string CLanguage :: EveryoneHasBeenSpoofChecked( ) +QString CLanguage :: EveryoneHasBeenSpoofChecked( ) { return m_CFG->GetString( "lang_0068", "lang_0068" ); } -string CLanguage :: PlayersNotYetPinged( string notpinged ) +QString CLanguage :: PlayersNotYetPinged( QString notpinged ) { - string Out = m_CFG->GetString( "lang_0069", "lang_0069" ); + QString Out = m_CFG->GetString( "lang_0069", "lang_0069" ); UTIL_Replace( Out, "$NOTPINGED$", notpinged ); return Out; } -string CLanguage :: EveryoneHasBeenPinged( ) +QString CLanguage :: EveryoneHasBeenPinged( ) { return m_CFG->GetString( "lang_0070", "lang_0070" ); } -string CLanguage :: ShortestLoadByPlayer( string user, string loadingtime ) +QString CLanguage :: ShortestLoadByPlayer( QString user, QString loadingtime ) { - string Out = m_CFG->GetString( "lang_0071", "lang_0071" ); + QString Out = m_CFG->GetString( "lang_0071", "lang_0071" ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$LOADINGTIME$", loadingtime ); return Out; } -string CLanguage :: LongestLoadByPlayer( string user, string loadingtime ) +QString CLanguage :: LongestLoadByPlayer( QString user, QString loadingtime ) { - string Out = m_CFG->GetString( "lang_0072", "lang_0072" ); + QString Out = m_CFG->GetString( "lang_0072", "lang_0072" ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$LOADINGTIME$", loadingtime ); return Out; } -string CLanguage :: YourLoadingTimeWas( string loadingtime ) +QString CLanguage :: YourLoadingTimeWas( QString loadingtime ) { - string Out = m_CFG->GetString( "lang_0073", "lang_0073" ); + QString Out = m_CFG->GetString( "lang_0073", "lang_0073" ); UTIL_Replace( Out, "$LOADINGTIME$", loadingtime ); return Out; } -string CLanguage :: HasPlayedDotAGamesWithThisBot( string user, string totalgames, string totalwins, string totallosses, string totalkills, string totaldeaths, string totalcreepkills, string totalcreepdenies, string totalassists, string totalneutralkills, string totaltowerkills, string totalraxkills, string totalcourierkills, string avgkills, string avgdeaths, string avgcreepkills, string avgcreepdenies, string avgassists, string avgneutralkills, string avgtowerkills, string avgraxkills, string avgcourierkills ) +QString CLanguage :: HasPlayedDotAGamesWithThisBot( QString user, QString totalgames, QString totalwins, QString totallosses, QString totalkills, QString totaldeaths, QString totalcreepkills, QString totalcreepdenies, QString totalassists, QString totalneutralkills, QString totaltowerkills, QString totalraxkills, QString totalcourierkills, QString avgkills, QString avgdeaths, QString avgcreepkills, QString avgcreepdenies, QString avgassists, QString avgneutralkills, QString avgtowerkills, QString avgraxkills, QString avgcourierkills ) { - string Out = m_CFG->GetString( "lang_0074", "lang_0074" ); + QString Out = m_CFG->GetString( "lang_0074", "lang_0074" ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$TOTALGAMES$", totalgames ); UTIL_Replace( Out, "$TOTALWINS$", totalwins ); @@ -597,309 +597,309 @@ string CLanguage :: HasPlayedDotAGamesWithThisBot( string user, string totalgame return Out; } -string CLanguage :: HasntPlayedDotAGamesWithThisBot( string user ) +QString CLanguage :: HasntPlayedDotAGamesWithThisBot( QString user ) { - string Out = m_CFG->GetString( "lang_0075", "lang_0075" ); + QString Out = m_CFG->GetString( "lang_0075", "lang_0075" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: WasKickedForReservedPlayer( string reserved ) +QString CLanguage :: WasKickedForReservedPlayer( QString reserved ) { - string Out = m_CFG->GetString( "lang_0076", "lang_0076" ); + QString Out = m_CFG->GetString( "lang_0076", "lang_0076" ); UTIL_Replace( Out, "$RESERVED$", reserved ); return Out; } -string CLanguage :: WasKickedForOwnerPlayer( string owner ) +QString CLanguage :: WasKickedForOwnerPlayer( QString owner ) { - string Out = m_CFG->GetString( "lang_0077", "lang_0077" ); + QString Out = m_CFG->GetString( "lang_0077", "lang_0077" ); UTIL_Replace( Out, "$OWNER$", owner ); return Out; } -string CLanguage :: WasKickedByPlayer( string user ) +QString CLanguage :: WasKickedByPlayer( QString user ) { - string Out = m_CFG->GetString( "lang_0078", "lang_0078" ); + QString Out = m_CFG->GetString( "lang_0078", "lang_0078" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: HasLostConnectionPlayerError( string error ) +QString CLanguage :: HasLostConnectionPlayerError( QString error ) { - string Out = m_CFG->GetString( "lang_0079", "lang_0079" ); + QString Out = m_CFG->GetString( "lang_0079", "lang_0079" ); UTIL_Replace( Out, "$ERROR$", error ); return Out; } -string CLanguage :: HasLostConnectionSocketError( string error ) +QString CLanguage :: HasLostConnectionSocketError( QString error ) { - string Out = m_CFG->GetString( "lang_0080", "lang_0080" ); + QString Out = m_CFG->GetString( "lang_0080", "lang_0080" ); UTIL_Replace( Out, "$ERROR$", error ); return Out; } -string CLanguage :: HasLostConnectionClosedByRemoteHost( ) +QString CLanguage :: HasLostConnectionClosedByRemoteHost( ) { return m_CFG->GetString( "lang_0081", "lang_0081" ); } -string CLanguage :: HasLeftVoluntarily( ) +QString CLanguage :: HasLeftVoluntarily( ) { return m_CFG->GetString( "lang_0082", "lang_0082" ); } -string CLanguage :: EndingGame( string description ) +QString CLanguage :: EndingGame( QString description ) { - string Out = m_CFG->GetString( "lang_0083", "lang_0083" ); + QString Out = m_CFG->GetString( "lang_0083", "lang_0083" ); UTIL_Replace( Out, "$DESCRIPTION$", description ); return Out; } -string CLanguage :: HasLostConnectionTimedOut( ) +QString CLanguage :: HasLostConnectionTimedOut( ) { return m_CFG->GetString( "lang_0084", "lang_0084" ); } -string CLanguage :: GlobalChatMuted( ) +QString CLanguage :: GlobalChatMuted( ) { return m_CFG->GetString( "lang_0085", "lang_0085" ); } -string CLanguage :: GlobalChatUnmuted( ) +QString CLanguage :: GlobalChatUnmuted( ) { return m_CFG->GetString( "lang_0086", "lang_0086" ); } -string CLanguage :: ShufflingPlayers( ) +QString CLanguage :: ShufflingPlayers( ) { return m_CFG->GetString( "lang_0087", "lang_0087" ); } -string CLanguage :: UnableToLoadConfigFileGameInLobby( ) +QString CLanguage :: UnableToLoadConfigFileGameInLobby( ) { return m_CFG->GetString( "lang_0088", "lang_0088" ); } -string CLanguage :: PlayersStillDownloading( string stilldownloading ) +QString CLanguage :: PlayersStillDownloading( QString stilldownloading ) { - string Out = m_CFG->GetString( "lang_0089", "lang_0089" ); + QString Out = m_CFG->GetString( "lang_0089", "lang_0089" ); UTIL_Replace( Out, "$STILLDOWNLOADING$", stilldownloading ); return Out; } -string CLanguage :: RefreshMessagesEnabled( ) +QString CLanguage :: RefreshMessagesEnabled( ) { return m_CFG->GetString( "lang_0090", "lang_0090" ); } -string CLanguage :: RefreshMessagesDisabled( ) +QString CLanguage :: RefreshMessagesDisabled( ) { return m_CFG->GetString( "lang_0091", "lang_0091" ); } -string CLanguage :: AtLeastOneGameActiveUseForceToShutdown( ) +QString CLanguage :: AtLeastOneGameActiveUseForceToShutdown( ) { return m_CFG->GetString( "lang_0092", "lang_0092" ); } -string CLanguage :: CurrentlyLoadedMapCFGIs( string mapcfg ) +QString CLanguage :: CurrentlyLoadedMapCFGIs( QString mapcfg ) { - string Out = m_CFG->GetString( "lang_0093", "lang_0093" ); + QString Out = m_CFG->GetString( "lang_0093", "lang_0093" ); UTIL_Replace( Out, "$MAPCFG$", mapcfg ); return Out; } -string CLanguage :: LaggedOutDroppedByAdmin( ) +QString CLanguage :: LaggedOutDroppedByAdmin( ) { return m_CFG->GetString( "lang_0094", "lang_0094" ); } -string CLanguage :: LaggedOutDroppedByVote( ) +QString CLanguage :: LaggedOutDroppedByVote( ) { return m_CFG->GetString( "lang_0095", "lang_0095" ); } -string CLanguage :: PlayerVotedToDropLaggers( string user ) +QString CLanguage :: PlayerVotedToDropLaggers( QString user ) { - string Out = m_CFG->GetString( "lang_0096", "lang_0096" ); + QString Out = m_CFG->GetString( "lang_0096", "lang_0096" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: LatencyIs( string latency ) +QString CLanguage :: LatencyIs( QString latency ) { - string Out = m_CFG->GetString( "lang_0097", "lang_0097" ); + QString Out = m_CFG->GetString( "lang_0097", "lang_0097" ); UTIL_Replace( Out, "$LATENCY$", latency ); return Out; } -string CLanguage :: SyncLimitIs( string synclimit ) +QString CLanguage :: SyncLimitIs( QString synclimit ) { - string Out = m_CFG->GetString( "lang_0098", "lang_0098" ); + QString Out = m_CFG->GetString( "lang_0098", "lang_0098" ); UTIL_Replace( Out, "$SYNCLIMIT$", synclimit ); return Out; } -string CLanguage :: SettingSyncLimitToMinimum( string min ) +QString CLanguage :: SettingSyncLimitToMinimum( QString min ) { - string Out = m_CFG->GetString( "lang_0099", "lang_0099" ); + QString Out = m_CFG->GetString( "lang_0099", "lang_0099" ); UTIL_Replace( Out, "$MIN$", min ); return Out; } -string CLanguage :: SettingSyncLimitToMaximum( string max ) +QString CLanguage :: SettingSyncLimitToMaximum( QString max ) { - string Out = m_CFG->GetString( "lang_0100", "lang_0100" ); + QString Out = m_CFG->GetString( "lang_0100", "lang_0100" ); UTIL_Replace( Out, "$MAX$", max ); return Out; } -string CLanguage :: SettingSyncLimitTo( string synclimit ) +QString CLanguage :: SettingSyncLimitTo( QString synclimit ) { - string Out = m_CFG->GetString( "lang_0101", "lang_0101" ); + QString Out = m_CFG->GetString( "lang_0101", "lang_0101" ); UTIL_Replace( Out, "$SYNCLIMIT$", synclimit ); return Out; } -string CLanguage :: UnableToCreateGameNotLoggedIn( string gamename ) +QString CLanguage :: UnableToCreateGameNotLoggedIn( QString gamename ) { - string Out = m_CFG->GetString( "lang_0102", "lang_0102" ); + QString Out = m_CFG->GetString( "lang_0102", "lang_0102" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: AdminLoggedIn( ) +QString CLanguage :: AdminLoggedIn( ) { return m_CFG->GetString( "lang_0103", "lang_0103" ); } -string CLanguage :: AdminInvalidPassword( string attempt ) +QString CLanguage :: AdminInvalidPassword( QString attempt ) { - string Out = m_CFG->GetString( "lang_0104", "lang_0104" ); + QString Out = m_CFG->GetString( "lang_0104", "lang_0104" ); UTIL_Replace( Out, "$ATTEMPT$", attempt ); return Out; } -string CLanguage :: ConnectingToBNET( string server ) +QString CLanguage :: ConnectingToBNET( QString server ) { - string Out = m_CFG->GetString( "lang_0105", "lang_0105" ); + QString Out = m_CFG->GetString( "lang_0105", "lang_0105" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: ConnectedToBNET( string server ) +QString CLanguage :: ConnectedToBNET( QString server ) { - string Out = m_CFG->GetString( "lang_0106", "lang_0106" ); + QString Out = m_CFG->GetString( "lang_0106", "lang_0106" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: DisconnectedFromBNET( string server ) +QString CLanguage :: DisconnectedFromBNET( QString server ) { - string Out = m_CFG->GetString( "lang_0107", "lang_0107" ); + QString Out = m_CFG->GetString( "lang_0107", "lang_0107" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: LoggedInToBNET( string server ) +QString CLanguage :: LoggedInToBNET( QString server ) { - string Out = m_CFG->GetString( "lang_0108", "lang_0108" ); + QString Out = m_CFG->GetString( "lang_0108", "lang_0108" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: BNETGameHostingSucceeded( string server ) +QString CLanguage :: BNETGameHostingSucceeded( QString server ) { - string Out = m_CFG->GetString( "lang_0109", "lang_0109" ); + QString Out = m_CFG->GetString( "lang_0109", "lang_0109" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: BNETGameHostingFailed( string server, string gamename ) +QString CLanguage :: BNETGameHostingFailed( QString server, QString gamename ) { - string Out = m_CFG->GetString( "lang_0110", "lang_0110" ); + QString Out = m_CFG->GetString( "lang_0110", "lang_0110" ); UTIL_Replace( Out, "$SERVER$", server ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: ConnectingToBNETTimedOut( string server ) +QString CLanguage :: ConnectingToBNETTimedOut( QString server ) { - string Out = m_CFG->GetString( "lang_0111", "lang_0111" ); + QString Out = m_CFG->GetString( "lang_0111", "lang_0111" ); UTIL_Replace( Out, "$SERVER$", server ); return Out; } -string CLanguage :: PlayerDownloadedTheMap( string user, string seconds, string rate ) +QString CLanguage :: PlayerDownloadedTheMap( QString user, QString seconds, QString rate ) { - string Out = m_CFG->GetString( "lang_0112", "lang_0112" ); + QString Out = m_CFG->GetString( "lang_0112", "lang_0112" ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$SECONDS$", seconds ); UTIL_Replace( Out, "$RATE$", rate ); return Out; } -string CLanguage :: UnableToCreateGameNameTooLong( string gamename ) +QString CLanguage :: UnableToCreateGameNameTooLong( QString gamename ) { - string Out = m_CFG->GetString( "lang_0113", "lang_0113" ); + QString Out = m_CFG->GetString( "lang_0113", "lang_0113" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: SettingGameOwnerTo( string owner ) +QString CLanguage :: SettingGameOwnerTo( QString owner ) { - string Out = m_CFG->GetString( "lang_0114", "lang_0114" ); + QString Out = m_CFG->GetString( "lang_0114", "lang_0114" ); UTIL_Replace( Out, "$OWNER$", owner ); return Out; } -string CLanguage :: TheGameIsLocked( ) +QString CLanguage :: TheGameIsLocked( ) { return m_CFG->GetString( "lang_0115", "lang_0115" ); } -string CLanguage :: GameLocked( ) +QString CLanguage :: GameLocked( ) { return m_CFG->GetString( "lang_0116", "lang_0116" ); } -string CLanguage :: GameUnlocked( ) +QString CLanguage :: GameUnlocked( ) { return m_CFG->GetString( "lang_0117", "lang_0117" ); } -string CLanguage :: UnableToStartDownloadNoMatchesFound( string victim ) +QString CLanguage :: UnableToStartDownloadNoMatchesFound( QString victim ) { - string Out = m_CFG->GetString( "lang_0118", "lang_0118" ); + QString Out = m_CFG->GetString( "lang_0118", "lang_0118" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( string victim ) +QString CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( QString victim ) { - string Out = m_CFG->GetString( "lang_0119", "lang_0119" ); + QString Out = m_CFG->GetString( "lang_0119", "lang_0119" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: UnableToSetGameOwner( string owner ) +QString CLanguage :: UnableToSetGameOwner( QString owner ) { - string Out = m_CFG->GetString( "lang_0120", "lang_0120" ); + QString Out = m_CFG->GetString( "lang_0120", "lang_0120" ); UTIL_Replace( Out, "$OWNER$", owner ); return Out; } -string CLanguage :: UnableToCheckPlayerNoMatchesFound( string victim ) +QString CLanguage :: UnableToCheckPlayerNoMatchesFound( QString victim ) { - string Out = m_CFG->GetString( "lang_0121", "lang_0121" ); + QString Out = m_CFG->GetString( "lang_0121", "lang_0121" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: CheckedPlayer( string victim, string ping, string from, string admin, string owner, string spoofed, string spoofedrealm, string reserved ) +QString CLanguage :: CheckedPlayer( QString victim, QString ping, QString from, QString admin, QString owner, QString spoofed, QString spoofedrealm, QString reserved ) { - string Out = m_CFG->GetString( "lang_0122", "lang_0122" ); + QString Out = m_CFG->GetString( "lang_0122", "lang_0122" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$PING$", ping ); UTIL_Replace( Out, "$FROM$", from ); @@ -911,625 +911,625 @@ string CLanguage :: CheckedPlayer( string victim, string ping, string from, stri return Out; } -string CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( string victim ) +QString CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( QString victim ) { - string Out = m_CFG->GetString( "lang_0123", "lang_0123" ); + QString Out = m_CFG->GetString( "lang_0123", "lang_0123" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: TheGameIsLockedBNET( ) +QString CLanguage :: TheGameIsLockedBNET( ) { return m_CFG->GetString( "lang_0124", "lang_0124" ); } -string CLanguage :: UnableToCreateGameDisabled( string gamename ) +QString CLanguage :: UnableToCreateGameDisabled( QString gamename ) { - string Out = m_CFG->GetString( "lang_0125", "lang_0125" ); + QString Out = m_CFG->GetString( "lang_0125", "lang_0125" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: BotDisabled( ) +QString CLanguage :: BotDisabled( ) { return m_CFG->GetString( "lang_0126", "lang_0126" ); } -string CLanguage :: BotEnabled( ) +QString CLanguage :: BotEnabled( ) { return m_CFG->GetString( "lang_0127", "lang_0127" ); } -string CLanguage :: UnableToCreateGameInvalidMap( string gamename ) +QString CLanguage :: UnableToCreateGameInvalidMap( QString gamename ) { - string Out = m_CFG->GetString( "lang_0128", "lang_0128" ); + QString Out = m_CFG->GetString( "lang_0128", "lang_0128" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: WaitingForPlayersBeforeAutoStart( string players, string playersleft ) +QString CLanguage :: WaitingForPlayersBeforeAutoStart( QString players, QString playersleft ) { - string Out = m_CFG->GetString( "lang_0129", "lang_0129" ); + QString Out = m_CFG->GetString( "lang_0129", "lang_0129" ); UTIL_Replace( Out, "$PLAYERS$", players ); UTIL_Replace( Out, "$PLAYERSLEFT$", playersleft ); return Out; } -string CLanguage :: AutoStartDisabled( ) +QString CLanguage :: AutoStartDisabled( ) { return m_CFG->GetString( "lang_0130", "lang_0130" ); } -string CLanguage :: AutoStartEnabled( string players ) +QString CLanguage :: AutoStartEnabled( QString players ) { - string Out = m_CFG->GetString( "lang_0131", "lang_0131" ); + QString Out = m_CFG->GetString( "lang_0131", "lang_0131" ); UTIL_Replace( Out, "$PLAYERS$", players ); return Out; } -string CLanguage :: AnnounceMessageEnabled( ) +QString CLanguage :: AnnounceMessageEnabled( ) { return m_CFG->GetString( "lang_0132", "lang_0132" ); } -string CLanguage :: AnnounceMessageDisabled( ) +QString CLanguage :: AnnounceMessageDisabled( ) { return m_CFG->GetString( "lang_0133", "lang_0133" ); } -string CLanguage :: AutoHostEnabled( ) +QString CLanguage :: AutoHostEnabled( ) { return m_CFG->GetString( "lang_0134", "lang_0134" ); } -string CLanguage :: AutoHostDisabled( ) +QString CLanguage :: AutoHostDisabled( ) { return m_CFG->GetString( "lang_0135", "lang_0135" ); } -string CLanguage :: UnableToLoadSaveGamesOutside( ) +QString CLanguage :: UnableToLoadSaveGamesOutside( ) { return m_CFG->GetString( "lang_0136", "lang_0136" ); } -string CLanguage :: UnableToLoadSaveGameGameInLobby( ) +QString CLanguage :: UnableToLoadSaveGameGameInLobby( ) { return m_CFG->GetString( "lang_0137", "lang_0137" ); } -string CLanguage :: LoadingSaveGame( string file ) +QString CLanguage :: LoadingSaveGame( QString file ) { - string Out = m_CFG->GetString( "lang_0138", "lang_0138" ); + QString Out = m_CFG->GetString( "lang_0138", "lang_0138" ); UTIL_Replace( Out, "$FILE$", file ); return Out; } -string CLanguage :: UnableToLoadSaveGameDoesntExist( string file ) +QString CLanguage :: UnableToLoadSaveGameDoesntExist( QString file ) { - string Out = m_CFG->GetString( "lang_0139", "lang_0139" ); + QString Out = m_CFG->GetString( "lang_0139", "lang_0139" ); UTIL_Replace( Out, "$FILE$", file ); return Out; } -string CLanguage :: UnableToCreateGameInvalidSaveGame( string gamename ) +QString CLanguage :: UnableToCreateGameInvalidSaveGame( QString gamename ) { - string Out = m_CFG->GetString( "lang_0140", "lang_0140" ); + QString Out = m_CFG->GetString( "lang_0140", "lang_0140" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: UnableToCreateGameSaveGameMapMismatch( string gamename ) +QString CLanguage :: UnableToCreateGameSaveGameMapMismatch( QString gamename ) { - string Out = m_CFG->GetString( "lang_0141", "lang_0141" ); + QString Out = m_CFG->GetString( "lang_0141", "lang_0141" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: AutoSaveEnabled( ) +QString CLanguage :: AutoSaveEnabled( ) { return m_CFG->GetString( "lang_0142", "lang_0142" ); } -string CLanguage :: AutoSaveDisabled( ) +QString CLanguage :: AutoSaveDisabled( ) { return m_CFG->GetString( "lang_0143", "lang_0143" ); } -string CLanguage :: DesyncDetected( ) +QString CLanguage :: DesyncDetected( ) { return m_CFG->GetString( "lang_0144", "lang_0144" ); } -string CLanguage :: UnableToMuteNoMatchesFound( string victim ) +QString CLanguage :: UnableToMuteNoMatchesFound( QString victim ) { - string Out = m_CFG->GetString( "lang_0145", "lang_0145" ); + QString Out = m_CFG->GetString( "lang_0145", "lang_0145" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: MutedPlayer( string victim, string user ) +QString CLanguage :: MutedPlayer( QString victim, QString user ) { - string Out = m_CFG->GetString( "lang_0146", "lang_0146" ); + QString Out = m_CFG->GetString( "lang_0146", "lang_0146" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UnmutedPlayer( string victim, string user ) +QString CLanguage :: UnmutedPlayer( QString victim, QString user ) { - string Out = m_CFG->GetString( "lang_0147", "lang_0147" ); + QString Out = m_CFG->GetString( "lang_0147", "lang_0147" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: UnableToMuteFoundMoreThanOneMatch( string victim ) +QString CLanguage :: UnableToMuteFoundMoreThanOneMatch( QString victim ) { - string Out = m_CFG->GetString( "lang_0148", "lang_0148" ); + QString Out = m_CFG->GetString( "lang_0148", "lang_0148" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: PlayerIsSavingTheGame( string player ) +QString CLanguage :: PlayerIsSavingTheGame( QString player ) { - string Out = m_CFG->GetString( "lang_0149", "lang_0149" ); + QString Out = m_CFG->GetString( "lang_0149", "lang_0149" ); UTIL_Replace( Out, "$PLAYER$", player ); return Out; } -string CLanguage :: UpdatingClanList( ) +QString CLanguage :: UpdatingClanList( ) { return m_CFG->GetString( "lang_0150", "lang_0150" ); } -string CLanguage :: UpdatingFriendsList( ) +QString CLanguage :: UpdatingFriendsList( ) { return m_CFG->GetString( "lang_0151", "lang_0151" ); } -string CLanguage :: MultipleIPAddressUsageDetected( string player, string others ) +QString CLanguage :: MultipleIPAddressUsageDetected( QString player, QString others ) { - string Out = m_CFG->GetString( "lang_0152", "lang_0152" ); + QString Out = m_CFG->GetString( "lang_0152", "lang_0152" ); UTIL_Replace( Out, "$PLAYER$", player ); UTIL_Replace( Out, "$OTHERS$", others ); return Out; } -string CLanguage :: UnableToVoteKickAlreadyInProgress( ) +QString CLanguage :: UnableToVoteKickAlreadyInProgress( ) { return m_CFG->GetString( "lang_0153", "lang_0153" ); } -string CLanguage :: UnableToVoteKickNotEnoughPlayers( ) +QString CLanguage :: UnableToVoteKickNotEnoughPlayers( ) { return m_CFG->GetString( "lang_0154", "lang_0154" ); } -string CLanguage :: UnableToVoteKickNoMatchesFound( string victim ) +QString CLanguage :: UnableToVoteKickNoMatchesFound( QString victim ) { - string Out = m_CFG->GetString( "lang_0155", "lang_0155" ); + QString Out = m_CFG->GetString( "lang_0155", "lang_0155" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: UnableToVoteKickPlayerIsReserved( string victim ) +QString CLanguage :: UnableToVoteKickPlayerIsReserved( QString victim ) { - string Out = m_CFG->GetString( "lang_0156", "lang_0156" ); + QString Out = m_CFG->GetString( "lang_0156", "lang_0156" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: StartedVoteKick( string victim, string user, string votesneeded ) +QString CLanguage :: StartedVoteKick( QString victim, QString user, QString votesneeded ) { - string Out = m_CFG->GetString( "lang_0157", "lang_0157" ); + QString Out = m_CFG->GetString( "lang_0157", "lang_0157" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$VOTESNEEDED$", votesneeded ); return Out; } -string CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( string victim ) +QString CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( QString victim ) { - string Out = m_CFG->GetString( "lang_0158", "lang_0158" ); + QString Out = m_CFG->GetString( "lang_0158", "lang_0158" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: VoteKickPassed( string victim ) +QString CLanguage :: VoteKickPassed( QString victim ) { - string Out = m_CFG->GetString( "lang_0159", "lang_0159" ); + QString Out = m_CFG->GetString( "lang_0159", "lang_0159" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: ErrorVoteKickingPlayer( string victim ) +QString CLanguage :: ErrorVoteKickingPlayer( QString victim ) { - string Out = m_CFG->GetString( "lang_0160", "lang_0160" ); + QString Out = m_CFG->GetString( "lang_0160", "lang_0160" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: VoteKickAcceptedNeedMoreVotes( string victim, string user, string votes ) +QString CLanguage :: VoteKickAcceptedNeedMoreVotes( QString victim, QString user, QString votes ) { - string Out = m_CFG->GetString( "lang_0161", "lang_0161" ); + QString Out = m_CFG->GetString( "lang_0161", "lang_0161" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$USER$", user ); UTIL_Replace( Out, "$VOTES$", votes ); return Out; } -string CLanguage :: VoteKickCancelled( string victim ) +QString CLanguage :: VoteKickCancelled( QString victim ) { - string Out = m_CFG->GetString( "lang_0162", "lang_0162" ); + QString Out = m_CFG->GetString( "lang_0162", "lang_0162" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: VoteKickExpired( string victim ) +QString CLanguage :: VoteKickExpired( QString victim ) { - string Out = m_CFG->GetString( "lang_0163", "lang_0163" ); + QString Out = m_CFG->GetString( "lang_0163", "lang_0163" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: WasKickedByVote( ) +QString CLanguage :: WasKickedByVote( ) { return m_CFG->GetString( "lang_0164", "lang_0164" ); } -string CLanguage :: TypeYesToVote( string commandtrigger ) +QString CLanguage :: TypeYesToVote( QString commandtrigger ) { - string Out = m_CFG->GetString( "lang_0165", "lang_0165" ); + QString Out = m_CFG->GetString( "lang_0165", "lang_0165" ); UTIL_Replace( Out, "$COMMANDTRIGGER$", commandtrigger ); return Out; } -string CLanguage :: PlayersNotYetPingedAutoStart( string notpinged ) +QString CLanguage :: PlayersNotYetPingedAutoStart( QString notpinged ) { - string Out = m_CFG->GetString( "lang_0166", "lang_0166" ); + QString Out = m_CFG->GetString( "lang_0166", "lang_0166" ); UTIL_Replace( Out, "$NOTPINGED$", notpinged ); return Out; } -string CLanguage :: WasKickedForNotSpoofChecking( ) +QString CLanguage :: WasKickedForNotSpoofChecking( ) { return m_CFG->GetString( "lang_0167", "lang_0167" ); } -string CLanguage :: WasKickedForHavingFurthestScore( string score, string average ) +QString CLanguage :: WasKickedForHavingFurthestScore( QString score, QString average ) { - string Out = m_CFG->GetString( "lang_0168", "lang_0168" ); + QString Out = m_CFG->GetString( "lang_0168", "lang_0168" ); UTIL_Replace( Out, "$SCORE$", score ); UTIL_Replace( Out, "$AVERAGE$", average ); return Out; } -string CLanguage :: PlayerHasScore( string player, string score ) +QString CLanguage :: PlayerHasScore( QString player, QString score ) { - string Out = m_CFG->GetString( "lang_0169", "lang_0169" ); + QString Out = m_CFG->GetString( "lang_0169", "lang_0169" ); UTIL_Replace( Out, "$PLAYER$", player ); UTIL_Replace( Out, "$SCORE$", score ); return Out; } -string CLanguage :: RatedPlayersSpread( string rated, string total, string spread ) +QString CLanguage :: RatedPlayersSpread( QString rated, QString total, QString spread ) { - string Out = m_CFG->GetString( "lang_0170", "lang_0170" ); + QString Out = m_CFG->GetString( "lang_0170", "lang_0170" ); UTIL_Replace( Out, "$RATED$", rated ); UTIL_Replace( Out, "$TOTAL$", total ); UTIL_Replace( Out, "$SPREAD$", spread ); return Out; } -string CLanguage :: ErrorListingMaps( ) +QString CLanguage :: ErrorListingMaps( ) { return m_CFG->GetString( "lang_0171", "lang_0171" ); } -string CLanguage :: FoundMaps( string maps ) +QString CLanguage :: FoundMaps( QString maps ) { - string Out = m_CFG->GetString( "lang_0172", "lang_0172" ); + QString Out = m_CFG->GetString( "lang_0172", "lang_0172" ); UTIL_Replace( Out, "$MAPS$", maps ); return Out; } -string CLanguage :: NoMapsFound( ) +QString CLanguage :: NoMapsFound( ) { return m_CFG->GetString( "lang_0173", "lang_0173" ); } -string CLanguage :: ErrorListingMapConfigs( ) +QString CLanguage :: ErrorListingMapConfigs( ) { return m_CFG->GetString( "lang_0174", "lang_0174" ); } -string CLanguage :: FoundMapConfigs( string mapconfigs ) +QString CLanguage :: FoundMapConfigs( QString mapconfigs ) { - string Out = m_CFG->GetString( "lang_0175", "lang_0175" ); + QString Out = m_CFG->GetString( "lang_0175", "lang_0175" ); UTIL_Replace( Out, "$MAPCONFIGS$", mapconfigs ); return Out; } -string CLanguage :: NoMapConfigsFound( ) +QString CLanguage :: NoMapConfigsFound( ) { return m_CFG->GetString( "lang_0176", "lang_0176" ); } -string CLanguage :: PlayerFinishedLoading( string user ) +QString CLanguage :: PlayerFinishedLoading( QString user ) { - string Out = m_CFG->GetString( "lang_0177", "lang_0177" ); + QString Out = m_CFG->GetString( "lang_0177", "lang_0177" ); UTIL_Replace( Out, "$USER$", user ); return Out; } -string CLanguage :: PleaseWaitPlayersStillLoading( ) +QString CLanguage :: PleaseWaitPlayersStillLoading( ) { return m_CFG->GetString( "lang_0178", "lang_0178" ); } -string CLanguage :: MapDownloadsDisabled( ) +QString CLanguage :: MapDownloadsDisabled( ) { return m_CFG->GetString( "lang_0179", "lang_0179" ); } -string CLanguage :: MapDownloadsEnabled( ) +QString CLanguage :: MapDownloadsEnabled( ) { return m_CFG->GetString( "lang_0180", "lang_0180" ); } -string CLanguage :: MapDownloadsConditional( ) +QString CLanguage :: MapDownloadsConditional( ) { return m_CFG->GetString( "lang_0181", "lang_0181" ); } -string CLanguage :: SettingHCL( string HCL ) +QString CLanguage :: SettingHCL( QString HCL ) { - string Out = m_CFG->GetString( "lang_0182", "lang_0182" ); + QString Out = m_CFG->GetString( "lang_0182", "lang_0182" ); UTIL_Replace( Out, "$HCL$", HCL ); return Out; } -string CLanguage :: UnableToSetHCLInvalid( ) +QString CLanguage :: UnableToSetHCLInvalid( ) { return m_CFG->GetString( "lang_0183", "lang_0183" ); } -string CLanguage :: UnableToSetHCLTooLong( ) +QString CLanguage :: UnableToSetHCLTooLong( ) { return m_CFG->GetString( "lang_0184", "lang_0184" ); } -string CLanguage :: TheHCLIs( string HCL ) +QString CLanguage :: TheHCLIs( QString HCL ) { - string Out = m_CFG->GetString( "lang_0185", "lang_0185" ); + QString Out = m_CFG->GetString( "lang_0185", "lang_0185" ); UTIL_Replace( Out, "$HCL$", HCL ); return Out; } -string CLanguage :: TheHCLIsTooLongUseForceToStart( ) +QString CLanguage :: TheHCLIsTooLongUseForceToStart( ) { return m_CFG->GetString( "lang_0186", "lang_0186" ); } -string CLanguage :: ClearingHCL( ) +QString CLanguage :: ClearingHCL( ) { return m_CFG->GetString( "lang_0187", "lang_0187" ); } -string CLanguage :: TryingToRehostAsPrivateGame( string gamename ) +QString CLanguage :: TryingToRehostAsPrivateGame( QString gamename ) { - string Out = m_CFG->GetString( "lang_0188", "lang_0188" ); + QString Out = m_CFG->GetString( "lang_0188", "lang_0188" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: TryingToRehostAsPublicGame( string gamename ) +QString CLanguage :: TryingToRehostAsPublicGame( QString gamename ) { - string Out = m_CFG->GetString( "lang_0189", "lang_0189" ); + QString Out = m_CFG->GetString( "lang_0189", "lang_0189" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: RehostWasSuccessful( ) +QString CLanguage :: RehostWasSuccessful( ) { return m_CFG->GetString( "lang_0190", "lang_0190" ); } -string CLanguage :: TryingToJoinTheGameButBannedByName( string victim ) +QString CLanguage :: TryingToJoinTheGameButBannedByName( QString victim ) { - string Out = m_CFG->GetString( "lang_0191", "lang_0191" ); + QString Out = m_CFG->GetString( "lang_0191", "lang_0191" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: TryingToJoinTheGameButBannedByIP( string victim, string ip, string bannedname ) +QString CLanguage :: TryingToJoinTheGameButBannedByIP( QString victim, QString ip, QString bannedname ) { - string Out = m_CFG->GetString( "lang_0192", "lang_0192" ); + QString Out = m_CFG->GetString( "lang_0192", "lang_0192" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$IP$", ip ); UTIL_Replace( Out, "$BANNEDNAME$", bannedname ); return Out; } -string CLanguage :: HasBannedName( string victim ) +QString CLanguage :: HasBannedName( QString victim ) { - string Out = m_CFG->GetString( "lang_0193", "lang_0193" ); + QString Out = m_CFG->GetString( "lang_0193", "lang_0193" ); UTIL_Replace( Out, "$VICTIM$", victim ); return Out; } -string CLanguage :: HasBannedIP( string victim, string ip, string bannedname ) +QString CLanguage :: HasBannedIP( QString victim, QString ip, QString bannedname ) { - string Out = m_CFG->GetString( "lang_0194", "lang_0194" ); + QString Out = m_CFG->GetString( "lang_0194", "lang_0194" ); UTIL_Replace( Out, "$VICTIM$", victim ); UTIL_Replace( Out, "$IP$", ip ); UTIL_Replace( Out, "$BANNEDNAME$", bannedname ); return Out; } -string CLanguage :: PlayersInGameState( string number, string players ) +QString CLanguage :: PlayersInGameState( QString number, QString players ) { - string Out = m_CFG->GetString( "lang_0195", "lang_0195" ); + QString Out = m_CFG->GetString( "lang_0195", "lang_0195" ); UTIL_Replace( Out, "$NUMBER$", number ); UTIL_Replace( Out, "$PLAYERS$", players ); return Out; } -string CLanguage :: ValidServers( string servers ) +QString CLanguage :: ValidServers( QString servers ) { - string Out = m_CFG->GetString( "lang_0196", "lang_0196" ); + QString Out = m_CFG->GetString( "lang_0196", "lang_0196" ); UTIL_Replace( Out, "$SERVERS$", servers ); return Out; } -string CLanguage :: TeamCombinedScore( string team, string score ) +QString CLanguage :: TeamCombinedScore( QString team, QString score ) { - string Out = m_CFG->GetString( "lang_0197", "lang_0197" ); + QString Out = m_CFG->GetString( "lang_0197", "lang_0197" ); UTIL_Replace( Out, "$TEAM$", team ); UTIL_Replace( Out, "$SCORE$", score ); return Out; } -string CLanguage :: BalancingSlotsCompleted( ) +QString CLanguage :: BalancingSlotsCompleted( ) { return m_CFG->GetString( "lang_0198", "lang_0198" ); } -string CLanguage :: PlayerWasKickedForFurthestScore( string name, string score, string average ) +QString CLanguage :: PlayerWasKickedForFurthestScore( QString name, QString score, QString average ) { - string Out = m_CFG->GetString( "lang_0199", "lang_0199" ); + QString Out = m_CFG->GetString( "lang_0199", "lang_0199" ); UTIL_Replace( Out, "$NAME$", name ); UTIL_Replace( Out, "$SCORE$", score ); UTIL_Replace( Out, "$AVERAGE$", average ); return Out; } -string CLanguage :: LocalAdminMessagesEnabled( ) +QString CLanguage :: LocalAdminMessagesEnabled( ) { return m_CFG->GetString( "lang_0200", "lang_0200" ); } -string CLanguage :: LocalAdminMessagesDisabled( ) +QString CLanguage :: LocalAdminMessagesDisabled( ) { return m_CFG->GetString( "lang_0201", "lang_0201" ); } -string CLanguage :: WasDroppedDesync( ) +QString CLanguage :: WasDroppedDesync( ) { return m_CFG->GetString( "lang_0202", "lang_0202" ); } -string CLanguage :: WasKickedForHavingLowestScore( string score ) +QString CLanguage :: WasKickedForHavingLowestScore( QString score ) { - string Out = m_CFG->GetString( "lang_0203", "lang_0203" ); + QString Out = m_CFG->GetString( "lang_0203", "lang_0203" ); UTIL_Replace( Out, "$SCORE$", score ); return Out; } -string CLanguage :: PlayerWasKickedForLowestScore( string name, string score ) +QString CLanguage :: PlayerWasKickedForLowestScore( QString name, QString score ) { - string Out = m_CFG->GetString( "lang_0204", "lang_0204" ); + QString Out = m_CFG->GetString( "lang_0204", "lang_0204" ); UTIL_Replace( Out, "$NAME$", name ); UTIL_Replace( Out, "$SCORE$", score ); return Out; } -string CLanguage :: ReloadingConfigurationFiles( ) +QString CLanguage :: ReloadingConfigurationFiles( ) { return m_CFG->GetString( "lang_0205", "lang_0205" ); } -string CLanguage :: CountDownAbortedSomeoneLeftRecently( ) +QString CLanguage :: CountDownAbortedSomeoneLeftRecently( ) { return m_CFG->GetString( "lang_0206", "lang_0206" ); } -string CLanguage :: UnableToCreateGameMustEnforceFirst( string gamename ) +QString CLanguage :: UnableToCreateGameMustEnforceFirst( QString gamename ) { - string Out = m_CFG->GetString( "lang_0207", "lang_0207" ); + QString Out = m_CFG->GetString( "lang_0207", "lang_0207" ); UTIL_Replace( Out, "$GAMENAME$", gamename ); return Out; } -string CLanguage :: UnableToLoadReplaysOutside( ) +QString CLanguage :: UnableToLoadReplaysOutside( ) { return m_CFG->GetString( "lang_0208", "lang_0208" ); } -string CLanguage :: LoadingReplay( string file ) +QString CLanguage :: LoadingReplay( QString file ) { - string Out = m_CFG->GetString( "lang_0209", "lang_0209" ); + QString Out = m_CFG->GetString( "lang_0209", "lang_0209" ); UTIL_Replace( Out, "$FILE$", file ); return Out; } -string CLanguage :: UnableToLoadReplayDoesntExist( string file ) +QString CLanguage :: UnableToLoadReplayDoesntExist( QString file ) { - string Out = m_CFG->GetString( "lang_0210", "lang_0210" ); + QString Out = m_CFG->GetString( "lang_0210", "lang_0210" ); UTIL_Replace( Out, "$FILE$", file ); return Out; } -string CLanguage :: CommandTrigger( string trigger ) +QString CLanguage :: CommandTrigger( QString trigger ) { - string Out = m_CFG->GetString( "lang_0211", "lang_0211" ); + QString Out = m_CFG->GetString( "lang_0211", "lang_0211" ); UTIL_Replace( Out, "$TRIGGER$", trigger ); return Out; } -string CLanguage :: CantEndGameOwnerIsStillPlaying( string owner ) +QString CLanguage :: CantEndGameOwnerIsStillPlaying( QString owner ) { - string Out = m_CFG->GetString( "lang_0212", "lang_0212" ); + QString Out = m_CFG->GetString( "lang_0212", "lang_0212" ); UTIL_Replace( Out, "$OWNER$", owner ); return Out; } -string CLanguage :: CantUnhostGameOwnerIsPresent( string owner ) +QString CLanguage :: CantUnhostGameOwnerIsPresent( QString owner ) { - string Out = m_CFG->GetString( "lang_0213", "lang_0213" ); + QString Out = m_CFG->GetString( "lang_0213", "lang_0213" ); UTIL_Replace( Out, "$OWNER$", owner ); return Out; } -string CLanguage :: WasAutomaticallyDroppedAfterSeconds( string seconds ) +QString CLanguage :: WasAutomaticallyDroppedAfterSeconds( QString seconds ) { - string Out = m_CFG->GetString( "lang_0214", "lang_0214" ); + QString Out = m_CFG->GetString( "lang_0214", "lang_0214" ); UTIL_Replace( Out, "$SECONDS$", seconds ); return Out; } -string CLanguage :: HasLostConnectionTimedOutGProxy( ) +QString CLanguage :: HasLostConnectionTimedOutGProxy( ) { return m_CFG->GetString( "lang_0215", "lang_0215" ); } -string CLanguage :: HasLostConnectionSocketErrorGProxy( string error ) +QString CLanguage :: HasLostConnectionSocketErrorGProxy( QString error ) { - string Out = m_CFG->GetString( "lang_0216", "lang_0216" ); + QString Out = m_CFG->GetString( "lang_0216", "lang_0216" ); UTIL_Replace( Out, "$ERROR$", error ); return Out; } -string CLanguage :: HasLostConnectionClosedByRemoteHostGProxy( ) +QString CLanguage :: HasLostConnectionClosedByRemoteHostGProxy( ) { return m_CFG->GetString( "lang_0217", "lang_0217" ); } -string CLanguage :: WaitForReconnectSecondsRemain( string seconds ) +QString CLanguage :: WaitForReconnectSecondsRemain( QString seconds ) { - string Out = m_CFG->GetString( "lang_0218", "lang_0218" ); + QString Out = m_CFG->GetString( "lang_0218", "lang_0218" ); UTIL_Replace( Out, "$SECONDS$", seconds ); return Out; } -string CLanguage :: WasUnrecoverablyDroppedFromGProxy( ) +QString CLanguage :: WasUnrecoverablyDroppedFromGProxy( ) { return m_CFG->GetString( "lang_0219", "lang_0219" ); } -string CLanguage :: PlayerReconnectedWithGProxy( string name ) +QString CLanguage :: PlayerReconnectedWithGProxy( QString name ) { - string Out = m_CFG->GetString( "lang_0220", "lang_0220" ); + QString Out = m_CFG->GetString( "lang_0220", "lang_0220" ); UTIL_Replace( Out, "$NAME$", name ); return Out; } diff --git a/ghost/main.cpp b/ghost/main.cpp index bfb6db4..a957739 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -1,17 +1,20 @@ #include #include #include +#include +#include +#include #include "ghost.h" #include "util.h" #include "config.h" QTime gBasicTime; +QFile gLogFile; +QTextStream gLogStream(&gLogFile); -string gCFGFile; -string gLogFile; +QString gCFGFile; uint32_t gLogMethod; -ofstream *gLog = NULL; CGHost *gGHost = NULL; uint32_t GetTime() @@ -52,49 +55,30 @@ void SignalCatcher( int s ) exit( 1 ); } -void CONSOLE_Print( string message ) +void CONSOLE_Print( QString message ) { cout << message << endl; // logging - if( !gLogFile.empty( ) ) + if (!gLogFile.fileName().isEmpty()) { if( gLogMethod == 1 ) { - ofstream Log; - Log.open( gLogFile.c_str( ), ios :: app ); + gLogFile.open(QFile::WriteOnly | QFile::Append); - if( !Log.fail( ) ) + if( gLogFile.isWritable() ) { - time_t Now = time( NULL ); - string Time = asctime( localtime( &Now ) ); - - // erase the newline - - Time.erase( Time.size( ) - 1 ); - Log << "[" << Time << "] " << message << endl; - Log.close( ); - } - } - else if( gLogMethod == 2 ) - { - if( gLog && !gLog->fail( ) ) - { - time_t Now = time( NULL ); - string Time = asctime( localtime( &Now ) ); - - // erase the newline - - Time.erase( Time.size( ) - 1 ); - *gLog << "[" << Time << "] " << message << endl; - gLog->flush( ); + gLogStream << "[" << QTime::currentTime().toString() << "] " << QString::fromStdString(message) << endl; + gLogFile.close(); } } + else if( gLogMethod == 2 && gLogFile.isWritable() ) + gLogStream << "[" << QTime::currentTime().toString() << "] " << QString::fromStdString(message) << endl; } } -void DEBUG_Print( string message ) +void DEBUG_Print( QString message ) { cout << message << endl; } @@ -127,10 +111,10 @@ int main( int argc, char **argv ) CConfig CFG; CFG.Read( "default.cfg" ); CFG.Read( gCFGFile ); - gLogFile = CFG.GetString( "bot_log", string( ) ); + gLogFile.setFileName(QString::fromStdString(CFG.GetString( "bot_log", QString( ) ))); gLogMethod = CFG.GetInt( "bot_logmethod", 1 ); - if( !gLogFile.empty( ) ) + if( !gLogFile.fileName().isEmpty() ) { if( gLogMethod == 1 ) { @@ -143,23 +127,22 @@ int main( int argc, char **argv ) // log method 2: open the log on startup, flush the log for every message, close the log on shutdown // the log file CANNOT be edited/moved/deleted while GHost++ is running - gLog = new ofstream( ); - gLog->open( gLogFile.c_str( ), ios :: app ); + gLogFile.open(QFile::WriteOnly | QFile::Append); } } CONSOLE_Print( "[GHOST] starting up" ); - if( !gLogFile.empty( ) ) + if( !gLogFile.fileName().isEmpty() ) { if( gLogMethod == 1 ) - CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile + "] will not be locked" ); + CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile.fileName().toStdString() + "] will not be locked" ); else if( gLogMethod == 2 ) { - if( gLog->fail( ) ) - CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile + "] for appending, logging is disabled" ); + if( gLogFile.error() != QFile::NoError ) + CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile.fileName().toStdString() + "] for appending, logging is disabled" ); else - CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile + "] is now locked" ); + CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile.fileName().toStdString() + "] is now locked" ); } } else @@ -176,42 +159,6 @@ int main( int argc, char **argv ) signal( SIGPIPE, SIG_IGN ); #endif -#ifdef WIN32 - // initialize timer resolution - // attempt to set the resolution as low as possible from 1ms to 5ms - - unsigned int TimerResolution = 0; - - for( unsigned int i = 1; i <= 5; i++ ) - { - if( timeBeginPeriod( i ) == TIMERR_NOERROR ) - { - TimerResolution = i; - break; - } - else if( i < 5 ) - CONSOLE_Print( "[GHOST] error setting Windows timer resolution to " + UTIL_ToString( i ) + " milliseconds, trying a higher resolution" ); - else - { - CONSOLE_Print( "[GHOST] error setting Windows timer resolution" ); - return 1; - } - } - - CONSOLE_Print( "[GHOST] using Windows timer with resolution " + UTIL_ToString( TimerResolution ) + " milliseconds" ); -#elif __APPLE__ - // not sure how to get the resolution -#else - // print the timer resolution - - struct timespec Resolution; - - if( clock_getres( CLOCK_MONOTONIC, &Resolution ) == -1 ) - CONSOLE_Print( "[GHOST] error getting monotonic timer resolution" ); - else - CONSOLE_Print( "[GHOST] using monotonic timer with resolution " + UTIL_ToString( (double)( Resolution.tv_nsec / 1000 ), 2 ) + " microseconds" ); -#endif - #ifdef WIN32 // initialize winsock @@ -234,14 +181,7 @@ int main( int argc, char **argv ) gGHost = new CGHost( &CFG, gCFGFile ); - while( 1 ) - { - // block for 50ms on all sockets - if you intend to perform any timed actions more frequently you should change this - // that said it's likely we'll loop more often than this due to there being data waiting on one of the sockets but there aren't any guarantees - - if( gGHost->Update( 50000 ) ) - break; - } + int ret = a.exec(); // shutdown ghost @@ -260,13 +200,5 @@ int main( int argc, char **argv ) timeEndPeriod( TimerResolution ); #endif - if( gLog ) - { - if( !gLog->fail( ) ) - gLog->close( ); - - delete gLog; - } - - return a.exec(); + return ret; } diff --git a/ghost/map.cpp b/ghost/map.cpp index 857a997..22308bb 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -73,7 +73,7 @@ CMap :: CMap( CGHost *nGHost ) m_Slots.push_back( CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, 11, 11, SLOTRACE_RANDOM | SLOTRACE_SELECTABLE ) ); } -CMap :: CMap( CGHost *nGHost, CConfig *CFG, string nCFGFile ) +CMap :: CMap( CGHost *nGHost, CConfig *CFG, QString nCFGFile ) { m_GHost = nGHost; Load( CFG, nCFGFile ); @@ -162,34 +162,34 @@ uint32_t CMap :: GetMapGameType( ) { /* spec stolen from Strilanc as follows: - Public Enum GameTypes As UInteger - None = 0 - Unknown0 = 1 << 0 '[always seems to be set?] + Public Enum GameTypes As UInteger + None = 0 + Unknown0 = 1 << 0 '[always seems to be set?] - '''Setting this bit causes wc3 to check the map and disc if it is not signed by Blizzard - AuthenticatedMakerBlizzard = 1 << 3 - OfficialMeleeGame = 1 << 5 + '''Setting this bit causes wc3 to check the map and disc if it is not signed by Blizzard + AuthenticatedMakerBlizzard = 1 << 3 + OfficialMeleeGame = 1 << 5 SavedGame = 1 << 9 - PrivateGame = 1 << 11 - - MakerUser = 1 << 13 - MakerBlizzard = 1 << 14 - TypeMelee = 1 << 15 - TypeScenario = 1 << 16 - SizeSmall = 1 << 17 - SizeMedium = 1 << 18 - SizeLarge = 1 << 19 - ObsFull = 1 << 20 - ObsOnDeath = 1 << 21 - ObsNone = 1 << 22 - - MaskObs = ObsFull Or ObsOnDeath Or ObsNone - MaskMaker = MakerBlizzard Or MakerUser - MaskType = TypeMelee Or TypeScenario - MaskSize = SizeLarge Or SizeMedium Or SizeSmall - MaskFilterable = MaskObs Or MaskMaker Or MaskType Or MaskSize - End Enum + PrivateGame = 1 << 11 + + MakerUser = 1 << 13 + MakerBlizzard = 1 << 14 + TypeMelee = 1 << 15 + TypeScenario = 1 << 16 + SizeSmall = 1 << 17 + SizeMedium = 1 << 18 + SizeLarge = 1 << 19 + ObsFull = 1 << 20 + ObsOnDeath = 1 << 21 + ObsNone = 1 << 22 + + MaskObs = ObsFull Or ObsOnDeath Or ObsNone + MaskMaker = MakerBlizzard Or MakerUser + MaskType = TypeMelee Or TypeScenario + MaskSize = SizeLarge Or SizeMedium Or SizeSmall + MaskFilterable = MaskObs Or MaskMaker Or MaskType Or MaskSize + End Enum */ @@ -249,14 +249,14 @@ unsigned char CMap :: GetMapLayoutStyle( ) return 3; } -void CMap :: Load( CConfig *CFG, string nCFGFile ) +void CMap :: Load( CConfig *CFG, QString nCFGFile ) { m_Valid = true; m_CFGFile = nCFGFile; // load the map data - m_MapLocalPath = CFG->GetString( "map_localpath", string( ) ); + m_MapLocalPath = CFG->GetString( "map_localpath", QString( ) ); m_MapData.clear( ); if( !m_MapLocalPath.empty( ) ) @@ -264,7 +264,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) // load the map MPQ - string MapMPQFileName = m_GHost->m_MapPath + m_MapLocalPath; + QString MapMPQFileName = m_GHost->m_MapPath + m_MapLocalPath; HANDLE MapMPQ; bool MapMPQReady = false; @@ -300,13 +300,13 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) // calculate map_crc (this is not the CRC) and map_sha1 // a big thank you to Strilanc for figuring the map_crc algorithm out - string CommonJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "common.j" ); + QString CommonJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "common.j" ); if( CommonJ.empty( ) ) CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "common.j]" ); else { - string BlizzardJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "blizzard.j" ); + QString BlizzardJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "blizzard.j" ); if( BlizzardJ.empty( ) ) CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "blizzard.j]" ); @@ -398,7 +398,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) if( MapMPQReady ) { - vector FileList; + vector FileList; FileList.push_back( "war3map.j" ); FileList.push_back( "scripts\\war3map.j" ); FileList.push_back( "war3map.w3e" ); @@ -411,7 +411,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) FileList.push_back( "war3map.w3q" ); bool FoundScript = false; - for( vector :: iterator i = FileList.begin( ); i != FileList.end( ); i++ ) + for( vector :: iterator i = FileList.begin( ); i != FileList.end( ); i++ ) { // don't use scripts\war3map.j if we've already used war3map.j (yes, some maps have both but only war3map.j is used) @@ -497,11 +497,11 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) ) { - istringstream ISS( string( SubFileData, BytesRead ) ); + istringstream ISS( QString( SubFileData, BytesRead ) ); // war3map.w3i format found at http://www.wc3campaigns.net/tools/specs/index.html by Zepir/PitzerMike - string GarbageString; + QString GarbageString; uint32_t FileFormat; uint32_t RawMapWidth; uint32_t RawMapHeight; @@ -716,44 +716,44 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) if( MapMPQReady ) SFileCloseArchive( MapMPQ ); - m_MapPath = CFG->GetString( "map_path", string( ) ); + m_MapPath = CFG->GetString( "map_path", QString( ) ); if( MapSize.empty( ) ) - MapSize = UTIL_ExtractNumbers( CFG->GetString( "map_size", string( ) ), 4 ); + MapSize = UTIL_ExtractNumbers( CFG->GetString( "map_size", QString( ) ), 4 ); else if( CFG->Exists( "map_size" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_size with config value map_size = " + CFG->GetString( "map_size", string( ) ) ); - MapSize = UTIL_ExtractNumbers( CFG->GetString( "map_size", string( ) ), 4 ); + CONSOLE_Print( "[MAP] overriding calculated map_size with config value map_size = " + CFG->GetString( "map_size", QString( ) ) ); + MapSize = UTIL_ExtractNumbers( CFG->GetString( "map_size", QString( ) ), 4 ); } m_MapSize = MapSize; if( MapInfo.empty( ) ) - MapInfo = UTIL_ExtractNumbers( CFG->GetString( "map_info", string( ) ), 4 ); + MapInfo = UTIL_ExtractNumbers( CFG->GetString( "map_info", QString( ) ), 4 ); else if( CFG->Exists( "map_info" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_info with config value map_info = " + CFG->GetString( "map_info", string( ) ) ); - MapInfo = UTIL_ExtractNumbers( CFG->GetString( "map_info", string( ) ), 4 ); + CONSOLE_Print( "[MAP] overriding calculated map_info with config value map_info = " + CFG->GetString( "map_info", QString( ) ) ); + MapInfo = UTIL_ExtractNumbers( CFG->GetString( "map_info", QString( ) ), 4 ); } m_MapInfo = MapInfo; if( MapCRC.empty( ) ) - MapCRC = UTIL_ExtractNumbers( CFG->GetString( "map_crc", string( ) ), 4 ); + MapCRC = UTIL_ExtractNumbers( CFG->GetString( "map_crc", QString( ) ), 4 ); else if( CFG->Exists( "map_crc" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_crc with config value map_crc = " + CFG->GetString( "map_crc", string( ) ) ); - MapCRC = UTIL_ExtractNumbers( CFG->GetString( "map_crc", string( ) ), 4 ); + CONSOLE_Print( "[MAP] overriding calculated map_crc with config value map_crc = " + CFG->GetString( "map_crc", QString( ) ) ); + MapCRC = UTIL_ExtractNumbers( CFG->GetString( "map_crc", QString( ) ), 4 ); } m_MapCRC = MapCRC; if( MapSHA1.empty( ) ) - MapSHA1 = UTIL_ExtractNumbers( CFG->GetString( "map_sha1", string( ) ), 20 ); + MapSHA1 = UTIL_ExtractNumbers( CFG->GetString( "map_sha1", QString( ) ), 20 ); else if( CFG->Exists( "map_sha1" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_sha1 with config value map_sha1 = " + CFG->GetString( "map_sha1", string( ) ) ); - MapSHA1 = UTIL_ExtractNumbers( CFG->GetString( "map_sha1", string( ) ), 20 ); + CONSOLE_Print( "[MAP] overriding calculated map_sha1 with config value map_sha1 = " + CFG->GetString( "map_sha1", QString( ) ) ); + MapSHA1 = UTIL_ExtractNumbers( CFG->GetString( "map_sha1", QString( ) ), 20 ); } m_MapSHA1 = MapSHA1; @@ -772,35 +772,35 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) MapOptions = CFG->GetInt( "map_options", 0 ); else if( CFG->Exists( "map_options" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_options with config value map_options = " + CFG->GetString( "map_options", string( ) ) ); + CONSOLE_Print( "[MAP] overriding calculated map_options with config value map_options = " + CFG->GetString( "map_options", QString( ) ) ); MapOptions = CFG->GetInt( "map_options", 0 ); } m_MapOptions = MapOptions; if( MapWidth.empty( ) ) - MapWidth = UTIL_ExtractNumbers( CFG->GetString( "map_width", string( ) ), 2 ); + MapWidth = UTIL_ExtractNumbers( CFG->GetString( "map_width", QString( ) ), 2 ); else if( CFG->Exists( "map_width" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_width with config value map_width = " + CFG->GetString( "map_width", string( ) ) ); - MapWidth = UTIL_ExtractNumbers( CFG->GetString( "map_width", string( ) ), 2 ); + CONSOLE_Print( "[MAP] overriding calculated map_width with config value map_width = " + CFG->GetString( "map_width", QString( ) ) ); + MapWidth = UTIL_ExtractNumbers( CFG->GetString( "map_width", QString( ) ), 2 ); } m_MapWidth = MapWidth; if( MapHeight.empty( ) ) - MapHeight = UTIL_ExtractNumbers( CFG->GetString( "map_height", string( ) ), 2 ); + MapHeight = UTIL_ExtractNumbers( CFG->GetString( "map_height", QString( ) ), 2 ); else if( CFG->Exists( "map_height" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_height with config value map_height = " + CFG->GetString( "map_height", string( ) ) ); - MapHeight = UTIL_ExtractNumbers( CFG->GetString( "map_height", string( ) ), 2 ); + CONSOLE_Print( "[MAP] overriding calculated map_height with config value map_height = " + CFG->GetString( "map_height", QString( ) ) ); + MapHeight = UTIL_ExtractNumbers( CFG->GetString( "map_height", QString( ) ), 2 ); } m_MapHeight = MapHeight; - m_MapType = CFG->GetString( "map_type", string( ) ); - m_MapMatchMakingCategory = CFG->GetString( "map_matchmakingcategory", string( ) ); - m_MapStatsW3MMDCategory = CFG->GetString( "map_statsw3mmdcategory", string( ) ); - m_MapDefaultHCL = CFG->GetString( "map_defaulthcl", string( ) ); + m_MapType = CFG->GetString( "map_type", QString( ) ); + m_MapMatchMakingCategory = CFG->GetString( "map_matchmakingcategory", QString( ) ); + m_MapStatsW3MMDCategory = CFG->GetString( "map_statsw3mmdcategory", QString( ) ); + m_MapDefaultHCL = CFG->GetString( "map_defaulthcl", QString( ) ); m_MapDefaultPlayerScore = CFG->GetInt( "map_defaultplayerscore", 1000 ); m_MapLoadInGame = CFG->GetInt( "map_loadingame", 0 ) == 0 ? false : true; @@ -808,7 +808,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) MapNumPlayers = CFG->GetInt( "map_numplayers", 0 ); else if( CFG->Exists( "map_numplayers" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_numplayers with config value map_numplayers = " + CFG->GetString( "map_numplayers", string( ) ) ); + CONSOLE_Print( "[MAP] overriding calculated map_numplayers with config value map_numplayers = " + CFG->GetString( "map_numplayers", QString( ) ) ); MapNumPlayers = CFG->GetInt( "map_numplayers", 0 ); } @@ -818,7 +818,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) MapNumTeams = CFG->GetInt( "map_numteams", 0 ); else if( CFG->Exists( "map_numteams" ) ) { - CONSOLE_Print( "[MAP] overriding calculated map_numteams with config value map_numteams = " + CFG->GetString( "map_numteams", string( ) ) ); + CONSOLE_Print( "[MAP] overriding calculated map_numteams with config value map_numteams = " + CFG->GetString( "map_numteams", QString( ) ) ); MapNumTeams = CFG->GetInt( "map_numteams", 0 ); } @@ -828,7 +828,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) { for( uint32_t Slot = 1; Slot <= 12; Slot++ ) { - string SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), string( ) ); + QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); if( SlotString.empty( ) ) break; @@ -844,7 +844,7 @@ void CMap :: Load( CConfig *CFG, string nCFGFile ) for( uint32_t Slot = 1; Slot <= 12; Slot++ ) { - string SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), string( ) ); + QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); if( SlotString.empty( ) ) break; @@ -891,7 +891,7 @@ void CMap :: CheckValid( ) else if( m_MapPath[0] == '\\' ) CONSOLE_Print( "[MAP] warning - map_path starts with '\\', any replays saved by GHost++ will not be playable in Warcraft III" ); - if( m_MapPath.find( '/' ) != string :: npos ) + if( m_MapPath.find( '/' ) != QString :: npos ) CONSOLE_Print( "[MAP] warning - map_path contains forward slashes '/' but it must use Windows style back slashes '\\'" ); if( m_MapSize.size( ) != 4 ) diff --git a/ghost/packed.cpp b/ghost/packed.cpp index f0a9f6a..62537ea 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -88,7 +88,7 @@ CPacked :: ~CPacked( ) delete m_CRC; } -void CPacked :: Load( string fileName, bool allBlocks ) +void CPacked :: Load( QString fileName, bool allBlocks ) { m_Valid = true; CONSOLE_Print( "[PACKED] loading data from file [" + fileName + "]" ); @@ -96,7 +96,7 @@ void CPacked :: Load( string fileName, bool allBlocks ) Decompress( allBlocks ); } -bool CPacked :: Save( bool TFT, string fileName ) +bool CPacked :: Save( bool TFT, QString fileName ) { Compress( TFT ); @@ -109,7 +109,7 @@ bool CPacked :: Save( bool TFT, string fileName ) return false; } -bool CPacked :: Extract( string inFileName, string outFileName ) +bool CPacked :: Extract( QString inFileName, QString outFileName ) { m_Valid = true; CONSOLE_Print( "[PACKED] extracting data from file [" + inFileName + "] to file [" + outFileName + "]" ); @@ -122,7 +122,7 @@ bool CPacked :: Extract( string inFileName, string outFileName ) return false; } -bool CPacked :: Pack( bool TFT, string inFileName, string outFileName ) +bool CPacked :: Pack( bool TFT, QString inFileName, QString outFileName ) { m_Valid = true; CONSOLE_Print( "[PACKET] packing data from file [" + inFileName + "] to file [" + outFileName + "]" ); @@ -143,7 +143,7 @@ void CPacked :: Decompress( bool allBlocks ) m_Decompressed.clear( ); istringstream ISS( m_Compressed ); - string GarbageString; + QString GarbageString; // read header @@ -253,7 +253,7 @@ void CPacked :: Decompress( bool allBlocks ) return; } - m_Decompressed += string( (char *)DecompressedData, BlockDecompressedLong ); + m_Decompressed += QString( (char *)DecompressedData, BlockDecompressedLong ); delete [] DecompressedData; delete [] CompressedData; @@ -293,10 +293,10 @@ void CPacked :: Compress( bool TFT ) // use a buffer of size 8213 bytes because in the worst case zlib will grow the data 0.1% plus 12 bytes uint32_t CompressedSize = 0; - string Padded = m_Decompressed; + QString Padded = m_Decompressed; Padded.append( 8192 - ( Padded.size( ) % 8192 ), 0 ); - vector CompressedBlocks; - string :: size_type Position = 0; + vector CompressedBlocks; + QString :: size_type Position = 0; unsigned char *CompressedData = new unsigned char[8213]; while( Position < Padded.size( ) ) @@ -312,7 +312,7 @@ void CPacked :: Compress( bool TFT ) return; } - CompressedBlocks.push_back( string( (char *)CompressedData, BlockCompressedLong ) ); + CompressedBlocks.push_back( QString( (char *)CompressedData, BlockCompressedLong ) ); CompressedSize += BlockCompressedLong; Position += 8192; } @@ -360,7 +360,7 @@ void CPacked :: Compress( bool TFT ) // calculate header CRC - string HeaderString = string( Header.begin( ), Header.end( ) ); + QString HeaderString = QString( Header.begin( ), Header.end( ) ); uint32_t CRC = m_CRC->FullCRC( (unsigned char *)HeaderString.c_str( ), HeaderString.size( ) ); // overwrite the (currently zero) header CRC with the calculated CRC @@ -370,11 +370,11 @@ void CPacked :: Compress( bool TFT ) // append header - m_Compressed += string( Header.begin( ), Header.end( ) ); + m_Compressed += QString( Header.begin( ), Header.end( ) ); // append blocks - for( vector :: iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) + for( vector :: iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { BYTEARRAY BlockHeader; UTIL_AppendByteArray( BlockHeader, (uint16_t)(*i).size( ), false ); @@ -386,7 +386,7 @@ void CPacked :: Compress( bool TFT ) // calculate block header CRC - string BlockHeaderString = string( BlockHeader.begin( ), BlockHeader.end( ) ); + QString BlockHeaderString = QString( BlockHeader.begin( ), BlockHeader.end( ) ); uint32_t CRC1 = m_CRC->FullCRC( (unsigned char *)BlockHeaderString.c_str( ), BlockHeaderString.size( ) ); CRC1 = CRC1 ^ ( CRC1 >> 16 ); uint32_t CRC2 = m_CRC->FullCRC( (unsigned char *)(*i).c_str( ), (*i).size( ) ); @@ -400,7 +400,7 @@ void CPacked :: Compress( bool TFT ) // append block header and data - m_Compressed += string( BlockHeader.begin( ), BlockHeader.end( ) ); + m_Compressed += QString( BlockHeader.begin( ), BlockHeader.end( ) ); m_Compressed += *i; } } diff --git a/ghost/replay.cpp b/ghost/replay.cpp index f9ff04d..9772091 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -46,99 +46,99 @@ CReplay :: ~CReplay( ) void CReplay :: AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t result ) { - BYTEARRAY Block; + QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); - UTIL_AppendByteArray( Block, reason, false ); + UTIL_AppendQByteArray( Block, reason, false ); Block.push_back( PID ); - UTIL_AppendByteArray( Block, result, false ); - UTIL_AppendByteArray( Block, (uint32_t)1, false ); - m_CompiledBlocks += string( Block.begin( ), Block.end( ) ); + UTIL_AppendQByteArray( Block, result, false ); + UTIL_AppendQByteArray( Block, (uint32_t)1, false ); + m_CompiledBlocks += Block; } void CReplay :: AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, uint32_t result ) { - BYTEARRAY Block; + QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); - UTIL_AppendByteArray( Block, reason, false ); + UTIL_AppendQByteArray( Block, reason, false ); Block.push_back( PID ); - UTIL_AppendByteArray( Block, result, false ); - UTIL_AppendByteArray( Block, (uint32_t)1, false ); + UTIL_AppendQByteArray( Block, result, false ); + UTIL_AppendQByteArray( Block, (uint32_t)1, false ); m_LoadingBlocks.push( Block ); } void CReplay :: AddTimeSlot2( queue actions ) { - BYTEARRAY Block; + QByteArray Block; Block.push_back( REPLAY_TIMESLOT2 ); - UTIL_AppendByteArray( Block, (uint16_t)0, false ); - UTIL_AppendByteArray( Block, (uint16_t)0, false ); + UTIL_AppendQByteArray( Block, (uint16_t)0, false ); + UTIL_AppendQByteArray( Block, (uint16_t)0, false ); while( !actions.empty( ) ) { CIncomingAction *Action = actions.front( ); actions.pop( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendByteArrayFast( Block, *Action->GetAction( ) ); + UTIL_AppendQByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendQByteArrayFast( Block, *Action->GetAction( ) ); } // assign length - BYTEARRAY LengthBytes = UTIL_CreateByteArray( (uint16_t)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = UTIL_CreateQByteArray( (uint16_t)( Block.size( ) - 3 ), false ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; - m_CompiledBlocks += string( Block.begin( ), Block.end( ) ); + m_CompiledBlocks += Block; } void CReplay :: AddTimeSlot( uint16_t timeIncrement, queue actions ) { - BYTEARRAY Block; + QByteArray Block; Block.push_back( REPLAY_TIMESLOT ); - UTIL_AppendByteArray( Block, (uint16_t)0, false ); - UTIL_AppendByteArray( Block, timeIncrement, false ); + UTIL_AppendQByteArray( Block, (uint16_t)0, false ); + UTIL_AppendQByteArray( Block, timeIncrement, false ); while( !actions.empty( ) ) { CIncomingAction *Action = actions.front( ); actions.pop( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendByteArrayFast( Block, *Action->GetAction( ) ); + UTIL_AppendQByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendQByteArrayFast( Block, *Action->GetAction( ) ); } // assign length - BYTEARRAY LengthBytes = UTIL_CreateByteArray( (uint16_t)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = UTIL_CreateQByteArray( (uint16_t)( Block.size( ) - 3 ), false ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; - m_CompiledBlocks += string( Block.begin( ), Block.end( ) ); + m_CompiledBlocks += Block; m_ReplayLength += timeIncrement; } -void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, string message ) +void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, QString message ) { - BYTEARRAY Block; + QByteArray Block; Block.push_back( REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendByteArray( Block, (uint16_t)0, false ); + UTIL_AppendQByteArray( Block, (uint16_t)0, false ); Block.push_back( flags ); - UTIL_AppendByteArray( Block, chatMode, false ); - UTIL_AppendByteArrayFast( Block, message ); + UTIL_AppendQByteArray( Block, chatMode, false ); + UTIL_AppendQByteArrayFast( Block, message ); // assign length - BYTEARRAY LengthBytes = UTIL_CreateByteArray( (uint16_t)( Block.size( ) - 4 ), false ); + QByteArray LengthBytes = UTIL_CreateQByteArray( (uint16_t)( Block.size( ) - 4 ), false ); Block[2] = LengthBytes[0]; Block[3] = LengthBytes[1]; - m_CompiledBlocks += string( Block.begin( ), Block.end( ) ); + m_CompiledBlocks += Block; } -void CReplay :: AddLoadingBlock( BYTEARRAY &loadingBlock ) +void CReplay :: AddLoadingBlock( QByteArray &loadingBlock ) { m_LoadingBlocks.push( loadingBlock ); } -void CReplay :: BuildReplay( string gameName, string statString, uint32_t war3Version, uint16_t buildNumber ) +void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3Version, uint16_t buildNumber ) { m_War3Version = war3Version; m_BuildNumber = buildNumber; @@ -148,22 +148,22 @@ void CReplay :: BuildReplay( string gameName, string statString, uint32_t war3Ve uint32_t LanguageID = 0x0012F8B0; - BYTEARRAY Replay; + QByteArray Replay; Replay.push_back( 16 ); // Unknown (4.0) Replay.push_back( 1 ); // Unknown (4.0) Replay.push_back( 0 ); // Unknown (4.0) Replay.push_back( 0 ); // Unknown (4.0) Replay.push_back( 0 ); // Host RecordID (4.1) Replay.push_back( m_HostPID ); // Host PlayerID (4.1) - UTIL_AppendByteArrayFast( Replay, m_HostName ); // Host PlayerName (4.1) + UTIL_AppendQByteArrayFast( Replay, m_HostName ); // Host PlayerName (4.1) Replay.push_back( 1 ); // Host AdditionalSize (4.1) Replay.push_back( 0 ); // Host AdditionalData (4.1) - UTIL_AppendByteArrayFast( Replay, gameName ); // GameName (4.2) + UTIL_AppendQByteArrayFast( Replay, gameName ); // GameName (4.2) Replay.push_back( 0 ); // Null (4.0) - UTIL_AppendByteArrayFast( Replay, statString ); // StatString (4.3) - UTIL_AppendByteArray( Replay, (uint32_t)m_Slots.size( ), false ); // PlayerCount (4.6) - UTIL_AppendByteArray( Replay, m_MapGameType, false ); // GameType (4.7) - UTIL_AppendByteArray( Replay, LanguageID, false ); // LanguageID (4.8) + UTIL_AppendQByteArrayFast( Replay, statString ); // StatString (4.3) + UTIL_AppendQByteArray( Replay, (uint32_t)m_Slots.size( ), false ); // PlayerCount (4.6) + UTIL_AppendQByteArray( Replay, m_MapGameType, false ); // GameType (4.7) + UTIL_AppendQByteArray( Replay, LanguageID, false ); // LanguageID (4.8) // PlayerList (4.9) @@ -173,47 +173,47 @@ void CReplay :: BuildReplay( string gameName, string statString, uint32_t war3Ve { Replay.push_back( 22 ); // Player RecordID (4.1) Replay.push_back( (*i).first ); // Player PlayerID (4.1) - UTIL_AppendByteArrayFast( Replay, (*i).second ); // Player PlayerName (4.1) + UTIL_AppendQByteArrayFast( Replay, (*i).second ); // Player PlayerName (4.1) Replay.push_back( 1 ); // Player AdditionalSize (4.1) Replay.push_back( 0 ); // Player AdditionalData (4.1) - UTIL_AppendByteArray( Replay, (uint32_t)0, false ); // Unknown + UTIL_AppendQByteArray( Replay, (uint32_t)0, false ); // Unknown } } // GameStartRecord (4.10) Replay.push_back( 25 ); // RecordID (4.10) - UTIL_AppendByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) + UTIL_AppendQByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) Replay.push_back( m_Slots.size( ) ); // NumSlots (4.10) for( unsigned char i = 0; i < m_Slots.size( ); i++ ) - UTIL_AppendByteArray( Replay, m_Slots[i].GetByteArray( ) ); + UTIL_AppendQByteArray( Replay, m_Slots[i].GetQByteArray( ) ); - UTIL_AppendByteArray( Replay, m_RandomSeed, false ); // RandomSeed (4.10) + UTIL_AppendQByteArray( Replay, m_RandomSeed, false ); // RandomSeed (4.10) Replay.push_back( m_SelectMode ); // SelectMode (4.10) Replay.push_back( m_StartSpotCount ); // StartSpotCount (4.10) // ReplayData (5.0) Replay.push_back( REPLAY_FIRSTSTARTBLOCK ); - UTIL_AppendByteArray( Replay, (uint32_t)1, false ); + UTIL_AppendQByteArray( Replay, (uint32_t)1, false ); Replay.push_back( REPLAY_SECONDSTARTBLOCK ); - UTIL_AppendByteArray( Replay, (uint32_t)1, false ); + UTIL_AppendQByteArray( Replay, (uint32_t)1, false ); // leavers during loading need to be stored between the second and third start blocks while( !m_LoadingBlocks.empty( ) ) { - UTIL_AppendByteArray( Replay, m_LoadingBlocks.front( ) ); + UTIL_AppendQByteArray( Replay, m_LoadingBlocks.front( ) ); m_LoadingBlocks.pop( ); } Replay.push_back( REPLAY_THIRDSTARTBLOCK ); - UTIL_AppendByteArray( Replay, (uint32_t)1, false ); + UTIL_AppendQByteArray( Replay, (uint32_t)1, false ); // done - m_Decompressed = string( Replay.begin( ), Replay.end( ) ); + m_Decompressed = QString( Replay.begin( ), Replay.end( ) ); m_Decompressed += m_CompiledBlocks; } @@ -233,8 +233,8 @@ void CReplay :: ParseReplay( bool parseBlocks ) m_RandomSeed = 0; m_SelectMode = 0; m_StartSpotCount = 0; - m_LoadingBlocks = queue( ); - m_Blocks = queue( ); + m_LoadingBlocks = queue( ); + m_Blocks = queue( ); m_CheckSums = queue( ); if( m_Flags != 32768 ) @@ -248,7 +248,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) unsigned char Garbage1; uint32_t Garbage4; - string GarbageString; + QString GarbageString; unsigned char GarbageData[65535]; READB( ISS, &Garbage4, 4 ); // Unknown (4.0) @@ -320,7 +320,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) if( Garbage1 == 22 ) { unsigned char PlayerID; - string PlayerName; + QString PlayerName; READB( ISS, &PlayerID, 1 ); // Player PlayerID (4.1) if( PlayerID > 15 ) @@ -393,7 +393,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) { unsigned char SlotData[9]; READB( ISS, SlotData, 9 ); - BYTEARRAY SlotDataBA = UTIL_CreateByteArray( SlotData, 9 ); + QByteArray SlotDataBA = UTIL_CreateQByteArray( SlotData, 9 ); m_Slots.push_back( CGameSlot( SlotDataBA ) ); } @@ -460,9 +460,9 @@ void CReplay :: ParseReplay( bool parseBlocks ) if( Garbage1 == CReplay :: REPLAY_LEAVEGAME ) { READB( ISS, GarbageData, 13 ); - BYTEARRAY LoadingBlock; + QByteArray LoadingBlock; LoadingBlock.push_back( Garbage1 ); - UTIL_AppendByteArray( LoadingBlock, GarbageData, 13 ); + UTIL_AppendQByteArray( LoadingBlock, GarbageData, 13 ); m_LoadingBlocks.push( LoadingBlock ); } else if( Garbage1 == CReplay :: REPLAY_THIRDSTARTBLOCK ) @@ -505,9 +505,9 @@ void CReplay :: ParseReplay( bool parseBlocks ) // reconstruct the block - BYTEARRAY Block; + QByteArray Block; Block.push_back( CReplay :: REPLAY_LEAVEGAME ); - UTIL_AppendByteArray( Block, GarbageData, 13 ); + UTIL_AppendQByteArray( Block, GarbageData, 13 ); m_Blocks.push( Block ); } else if( Garbage1 == CReplay :: REPLAY_TIMESLOT ) @@ -521,10 +521,10 @@ void CReplay :: ParseReplay( bool parseBlocks ) // reconstruct the block - BYTEARRAY Block; + QByteArray Block; Block.push_back( CReplay :: REPLAY_TIMESLOT ); - UTIL_AppendByteArray( Block, BlockSize, false ); - UTIL_AppendByteArray( Block, GarbageData, BlockSize ); + UTIL_AppendQByteArray( Block, BlockSize, false ); + UTIL_AppendQByteArray( Block, GarbageData, BlockSize ); m_Blocks.push( Block ); } else if( Garbage1 == CReplay :: REPLAY_CHATMESSAGE ) @@ -545,11 +545,11 @@ void CReplay :: ParseReplay( bool parseBlocks ) // reconstruct the block - BYTEARRAY Block; + QByteArray Block; Block.push_back( CReplay :: REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendByteArray( Block, BlockSize, false ); - UTIL_AppendByteArray( Block, GarbageData, BlockSize ); + UTIL_AppendQByteArray( Block, BlockSize, false ); + UTIL_AppendQByteArray( Block, GarbageData, BlockSize ); m_Blocks.push( Block ); } else if( Garbage1 == CReplay :: REPLAY_CHECKSUM ) diff --git a/ghost/replay.h b/ghost/replay.h index b38a313..441b099 100644 --- a/ghost/replay.h +++ b/ghost/replay.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -22,6 +22,7 @@ #define REPLAY_H #include "gameslot.h" +#include // // CReplay @@ -46,9 +47,9 @@ class CReplay : public CPacked private: unsigned char m_HostPID; - string m_HostName; - string m_GameName; - string m_StatString; + QString m_HostName; + QString m_GameName; + QString m_StatString; uint32_t m_PlayerCount; uint32_t m_MapGameType; vector m_Players; @@ -56,19 +57,19 @@ class CReplay : public CPacked uint32_t m_RandomSeed; unsigned char m_SelectMode; // also known as the "layout style" elsewhere in this project unsigned char m_StartSpotCount; - queue m_LoadingBlocks; - queue m_Blocks; + queue m_LoadingBlocks; + queue m_Blocks; queue m_CheckSums; - string m_CompiledBlocks; + QString m_CompiledBlocks; public: CReplay( ); virtual ~CReplay( ); unsigned char GetHostPID( ) { return m_HostPID; } - string GetHostName( ) { return m_HostName; } - string GetGameName( ) { return m_GameName; } - string GetStatString( ) { return m_StatString; } + QString GetHostName( ) { return m_HostName; } + QString GetGameName( ) { return m_GameName; } + QString GetStatString( ) { return m_StatString; } uint32_t GetPlayerCount( ) { return m_PlayerCount; } uint32_t GetMapGameType( ) { return m_MapGameType; } vector GetPlayers( ) { return m_Players; } @@ -76,26 +77,26 @@ class CReplay : public CPacked uint32_t GetRandomSeed( ) { return m_RandomSeed; } unsigned char GetSelectMode( ) { return m_SelectMode; } unsigned char GetStartSpotCount( ) { return m_StartSpotCount; } - queue *GetLoadingBlocks( ) { return &m_LoadingBlocks; } - queue *GetBlocks( ) { return &m_Blocks; } + queue *GetLoadingBlocks( ) { return &m_LoadingBlocks; } + queue *GetBlocks( ) { return &m_Blocks; } queue *GetCheckSums( ) { return &m_CheckSums; } - void AddPlayer( unsigned char nPID, string nName ) { m_Players.push_back( PIDPlayer( nPID, nName ) ); } + void AddPlayer( unsigned char nPID, QString nName ) { m_Players.push_back( PIDPlayer( nPID, nName ) ); } void SetSlots( vector nSlots ) { m_Slots = nSlots; } void SetRandomSeed( uint32_t nRandomSeed ) { m_RandomSeed = nRandomSeed; } void SetSelectMode( unsigned char nSelectMode ) { m_SelectMode = nSelectMode; } void SetStartSpotCount( unsigned char nStartSpotCount ) { m_StartSpotCount = nStartSpotCount; } void SetMapGameType( uint32_t nMapGameType ) { m_MapGameType = nMapGameType; } void SetHostPID( unsigned char nHostPID ) { m_HostPID = nHostPID; } - void SetHostName( string nHostName ) { m_HostName = nHostName; } + void SetHostName( QString nHostName ) { m_HostName = nHostName; } void AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t result ); void AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, uint32_t result ); void AddTimeSlot2( queue actions ); void AddTimeSlot( uint16_t timeIncrement, queue actions ); - void AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, string message ); - void AddLoadingBlock( BYTEARRAY &loadingBlock ); - void BuildReplay( string gameName, string statString, uint32_t war3Version, uint16_t buildNumber ); + void AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, QString message ); + void AddLoadingBlock( QByteArray &loadingBlock ); + void BuildReplay( QString gameName, QString statString, uint32_t war3Version, uint16_t buildNumber ); void ParseReplay( bool parseBlocks ); }; diff --git a/ghost/savegame.cpp b/ghost/savegame.cpp index 9c9ce6f..23dcb91 100644 --- a/ghost/savegame.cpp +++ b/ghost/savegame.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -42,7 +42,7 @@ CSaveGame :: ~CSaveGame( ) #define READSTR( x, y ) getline( (x), (y), '\0' ) void CSaveGame :: ParseSaveGame( ) -{ +{/* m_MapPath.clear( ); m_GameName.clear( ); m_NumSlots = 0; @@ -60,11 +60,11 @@ void CSaveGame :: ParseSaveGame( ) istringstream ISS( m_Decompressed ); // savegame format figured out by Varlock: - // string -> map path - // 0 (string?) -> ??? (no idea what this is) - // string -> game name - // 0 (string?) -> ??? (maybe original game password) - // string -> stat string + // QString -> map path + // 0 (QString?) -> ??? (no idea what this is) + // QString -> game name + // 0 (QString?) -> ??? (maybe original game password) + // QString -> stat QString // 4 bytes -> ??? (seems to be # of slots) // 4 bytes -> ??? (seems to be 0x01 0x28 0x49 0x00 on both of the savegames examined) // 2 bytes -> ??? (no idea what this is) @@ -74,14 +74,14 @@ void CSaveGame :: ParseSaveGame( ) unsigned char Garbage1; uint16_t Garbage2; uint32_t Garbage4; - string GarbageString; + QString GarbageString; uint32_t MagicNumber; READSTR( ISS, m_MapPath ); // map path READSTR( ISS, GarbageString ); // ??? READSTR( ISS, m_GameName ); // game name READSTR( ISS, GarbageString ); // ??? - READSTR( ISS, GarbageString ); // stat string + READSTR( ISS, GarbageString ); // stat QString READB( ISS, &Garbage4, 4 ); // ??? READB( ISS, &Garbage4, 4 ); // ??? READB( ISS, &Garbage2, 2 ); // ??? @@ -113,6 +113,6 @@ void CSaveGame :: ParseSaveGame( ) return; } - m_MagicNumber = UTIL_CreateByteArray( MagicNumber, false ); - m_Valid = true; + m_MagicNumber = UTIL_CreateQByteArray( MagicNumber, false ); + m_Valid = true;*/ } diff --git a/ghost/savegame.h b/ghost/savegame.h index 326bcf5..ffe8a64 100644 --- a/ghost/savegame.h +++ b/ghost/savegame.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -30,10 +30,10 @@ class CSaveGame : public CPacked { private: - string m_FileName; - string m_FileNameNoPath; - string m_MapPath; - string m_GameName; + QString m_FileName; + QString m_FileNameNoPath; + QString m_MapPath; + QString m_GameName; unsigned char m_NumSlots; vector m_Slots; uint32_t m_RandomSeed; @@ -43,17 +43,17 @@ class CSaveGame : public CPacked CSaveGame( ); virtual ~CSaveGame( ); - string GetFileName( ) { return m_FileName; } - string GetFileNameNoPath( ) { return m_FileNameNoPath; } - string GetMapPath( ) { return m_MapPath; } - string GetGameName( ) { return m_GameName; } + QString GetFileName( ) { return m_FileName; } + QString GetFileNameNoPath( ) { return m_FileNameNoPath; } + QString GetMapPath( ) { return m_MapPath; } + QString GetGameName( ) { return m_GameName; } unsigned char GetNumSlots( ) { return m_NumSlots; } vector GetSlots( ) { return m_Slots; } uint32_t GetRandomSeed( ) { return m_RandomSeed; } BYTEARRAY GetMagicNumber( ) { return m_MagicNumber; } - void SetFileName( string nFileName ) { m_FileName = nFileName; } - void SetFileNameNoPath( string nFileNameNoPath ) { m_FileNameNoPath = nFileNameNoPath; } + void SetFileName( QString nFileName ) { m_FileName = nFileName; } + void SetFileNameNoPath( QString nFileNameNoPath ) { m_FileNameNoPath = nFileNameNoPath; } void ParseSaveGame( ); }; diff --git a/ghost/socket.cpp b/ghost/socket.cpp index f25e915..79b2716 100644 --- a/ghost/socket.cpp +++ b/ghost/socket.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -22,7 +22,7 @@ #include "util.h" #include "socket.h" -#include +#include #ifndef WIN32 int GetLastError( ) { return errno; } @@ -54,22 +54,22 @@ CSocket :: ~CSocket( ) closesocket( m_Socket ); } -BYTEARRAY CSocket :: GetPort( ) +QByteArray CSocket :: GetPort( ) { - return UTIL_CreateByteArray( m_SIN.sin_port, false ); + return UTIL_CreateQByteArray( m_SIN.sin_port, false ); } -BYTEARRAY CSocket :: GetIP( ) +QByteArray CSocket :: GetIP( ) { - return UTIL_CreateByteArray( (uint32_t)m_SIN.sin_addr.s_addr, false ); + return UTIL_CreateQByteArray( (uint32_t)m_SIN.sin_addr.s_addr, false ); } -string CSocket :: GetIPString( ) +QString CSocket :: GetIPString( ) { return inet_ntoa( m_SIN.sin_addr ); } -string CSocket :: GetErrorString( ) +QString CSocket :: GetErrorString( ) { if( !m_HasError ) return "NO ERROR"; @@ -216,28 +216,16 @@ void CTCPSocket :: Reset( ) #else fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK ); #endif - - if( !m_LogFile.empty( ) ) - { - ofstream Log; - Log.open( m_LogFile.c_str( ), ios :: app ); - - if( !Log.fail( ) ) - { - Log << "----------RESET----------" << endl; - Log.close( ); - } - } } -void CTCPSocket :: PutBytes( string bytes ) +void CTCPSocket :: PutBytes( QString bytes ) { - m_SendBuffer += bytes; + m_SendBuffer.append(bytes); } -void CTCPSocket :: PutBytes( BYTEARRAY bytes ) +void CTCPSocket :: PutBytes( QByteArray bytes ) { - m_SendBuffer += string( bytes.begin( ), bytes.end( ) ); + m_SendBuffer.append(bytes); } void CTCPSocket :: DoRecv( fd_set *fd ) @@ -279,12 +267,12 @@ void CTCPSocket :: DoRecv( fd_set *fd ) if( !Log.fail( ) ) { - Log << " RECEIVE <<< " << UTIL_ByteArrayToHexString( UTIL_CreateByteArray( (unsigned char *)buffer, c ) ) << endl; + Log << " RECEIVE <<< " << UTIL_QByteArrayToHexString( UTIL_CreateQByteArray( (unsigned char *)buffer, c ) ) << endl; Log.close( ); } } - m_RecvBuffer += string( buffer, c ); + m_RecvBuffer += QString( buffer, c ); m_LastRecv = GetTime( ); } } @@ -321,7 +309,7 @@ void CTCPSocket :: DoSend( fd_set *send_fd ) if( !Log.fail( ) ) { - Log << "SEND >>> " << UTIL_ByteArrayToHexString( BYTEARRAY( m_SendBuffer.begin( ), m_SendBuffer.begin( ) + s ) ) << endl; + Log << "SEND >>> " << UTIL_QByteArrayToHexString( QByteArray( m_SendBuffer.begin( ), m_SendBuffer.begin( ) + s ) ) << endl; Log.close( ); } } @@ -376,7 +364,7 @@ void CTCPClient :: Disconnect( ) m_Connecting = false; } -void CTCPClient :: Connect( string localaddress, string address, uint16_t port ) +void CTCPClient :: Connect( QString localaddress, QString address, uint16_t port ) { if( m_Socket == INVALID_SOCKET || m_HasError || m_Connecting || m_Connected ) return; @@ -497,7 +485,7 @@ CTCPServer :: ~CTCPServer( ) } -bool CTCPServer :: Listen( string address, uint16_t port ) +bool CTCPServer :: Listen( QString address, uint16_t port ) { if( m_Socket == INVALID_SOCKET || m_HasError ) return false; @@ -579,7 +567,7 @@ CUDPSocket :: CUDPSocket( ) : CSocket( ) int OptVal = 1; setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (const char *)&OptVal, sizeof( int ) ); - + // set default broadcast target m_BroadcastTarget.s_addr = INADDR_BROADCAST; } @@ -589,12 +577,12 @@ CUDPSocket :: ~CUDPSocket( ) } -bool CUDPSocket :: SendTo( struct sockaddr_in sin, BYTEARRAY message ) +bool CUDPSocket :: SendTo( struct sockaddr_in sin, QByteArray message ) { if( m_Socket == INVALID_SOCKET || m_HasError ) return false; - string MessageString = string( message.begin( ), message.end( ) ); + QString MessageString = QString( message.begin( ), message.end( ) ); if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 ) return false; @@ -602,7 +590,7 @@ bool CUDPSocket :: SendTo( struct sockaddr_in sin, BYTEARRAY message ) return true; } -bool CUDPSocket :: SendTo( string address, uint16_t port, BYTEARRAY message ) +bool CUDPSocket :: SendTo( QString address, uint16_t port, QByteArray message ) { if( m_Socket == INVALID_SOCKET || m_HasError ) return false; @@ -630,7 +618,7 @@ bool CUDPSocket :: SendTo( string address, uint16_t port, BYTEARRAY message ) return SendTo( sin, message ); } -bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message ) +bool CUDPSocket :: Broadcast( uint16_t port, QByteArray message ) { if( m_Socket == INVALID_SOCKET || m_HasError ) return false; @@ -640,7 +628,7 @@ bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message ) sin.sin_addr.s_addr = m_BroadcastTarget.s_addr; sin.sin_port = htons( port ); - string MessageString = string( message.begin( ), message.end( ) ); + QString MessageString = QString( message.begin( ), message.end( ) ); if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 ) { @@ -651,7 +639,7 @@ bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message ) return true; } -void CUDPSocket :: SetBroadcastTarget( string subnet ) +void CUDPSocket :: SetBroadcastTarget( QString subnet ) { if( subnet.empty( ) ) { @@ -661,7 +649,7 @@ void CUDPSocket :: SetBroadcastTarget( string subnet ) else { // this function does not check whether the given subnet is a valid subnet the user is on - // convert string representation of ip/subnet to in_addr + // convert QString representation of ip/subnet to in_addr CONSOLE_Print( "[UDPSOCKET] using broadcast target [" + subnet + "]" ); m_BroadcastTarget.s_addr = inet_addr( subnet.c_str( ) ); @@ -739,7 +727,7 @@ bool CUDPServer :: Bind( struct sockaddr_in sin ) return true; } -bool CUDPServer :: Bind( string address, uint16_t port ) +bool CUDPServer :: Bind( QString address, uint16_t port ) { if( m_Socket == INVALID_SOCKET || m_HasError ) return false; @@ -760,7 +748,7 @@ bool CUDPServer :: Bind( string address, uint16_t port ) return Bind( sin ); } -void CUDPServer :: RecvFrom( fd_set *fd, struct sockaddr_in *sin, string *message ) +void CUDPServer :: RecvFrom( fd_set *fd, struct sockaddr_in *sin, QString *message ) { if( m_Socket == INVALID_SOCKET || m_HasError || !sin || !message ) return; @@ -791,7 +779,7 @@ void CUDPServer :: RecvFrom( fd_set *fd, struct sockaddr_in *sin, string *messag { // success! - *message = string( buffer, c ); + *message = QString( buffer, c ); } } } diff --git a/ghost/socket.h b/ghost/socket.h index 8fa879b..86b1502 100644 --- a/ghost/socket.h +++ b/ghost/socket.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -112,12 +112,12 @@ class CSocket CSocket( SOCKET nSocket, struct sockaddr_in nSIN ); ~CSocket( ); - virtual BYTEARRAY GetPort( ); - virtual BYTEARRAY GetIP( ); - virtual string GetIPString( ); + virtual QByteArray GetPort( ); + virtual QByteArray GetIP( ); + virtual QString GetIPString( ); virtual bool HasError( ) { return m_HasError; } virtual int GetError( ) { return m_Error; } - virtual string GetErrorString( ); + virtual QString GetErrorString( ); virtual void SetFD( fd_set *fd, fd_set *send_fd, int *nfds ); virtual void Allocate( int type ); virtual void Reset( ); @@ -131,11 +131,11 @@ class CTCPSocket : public CSocket { protected: bool m_Connected; - string m_LogFile; + QString m_LogFile; private: - string m_RecvBuffer; - string m_SendBuffer; + QString m_RecvBuffer; + QString m_SendBuffer; uint32_t m_LastRecv; uint32_t m_LastSend; @@ -146,9 +146,9 @@ class CTCPSocket : public CSocket virtual void Reset( ); virtual bool GetConnected( ) { return m_Connected; } - virtual string *GetBytes( ) { return &m_RecvBuffer; } - virtual void PutBytes( string bytes ); - virtual void PutBytes( BYTEARRAY bytes ); + virtual QString *GetBytes( ) { return &m_RecvBuffer; } + virtual void PutBytes( QString bytes ); + virtual void PutBytes( QByteArray bytes ); virtual void ClearRecvBuffer( ) { m_RecvBuffer.clear( ); } virtual void ClearSendBuffer( ) { m_SendBuffer.clear( ); } virtual uint32_t GetLastRecv( ) { return m_LastRecv; } @@ -157,7 +157,7 @@ class CTCPSocket : public CSocket virtual void DoSend( fd_set *send_fd ); virtual void Disconnect( ); virtual void SetNoDelay( bool noDelay ); - virtual void SetLogFile( string nLogFile ) { m_LogFile = nLogFile; } + virtual void SetLogFile( QString nLogFile ) { m_LogFile = nLogFile; } }; // @@ -176,7 +176,7 @@ class CTCPClient : public CTCPSocket virtual void Reset( ); virtual void Disconnect( ); virtual bool GetConnecting( ) { return m_Connecting; } - virtual void Connect( string localaddress, string address, uint16_t port ); + virtual void Connect( QString localaddress, QString address, uint16_t port ); virtual bool CheckConnect( ); }; @@ -190,7 +190,7 @@ class CTCPServer : public CTCPSocket CTCPServer( ); virtual ~CTCPServer( ); - virtual bool Listen( string address, uint16_t port ); + virtual bool Listen( QString address, uint16_t port ); virtual CTCPSocket *Accept( fd_set *fd ); }; @@ -206,10 +206,10 @@ class CUDPSocket : public CSocket CUDPSocket( ); virtual ~CUDPSocket( ); - virtual bool SendTo( struct sockaddr_in sin, BYTEARRAY message ); - virtual bool SendTo( string address, uint16_t port, BYTEARRAY message ); - virtual bool Broadcast( uint16_t port, BYTEARRAY message ); - virtual void SetBroadcastTarget( string subnet ); + virtual bool SendTo( struct sockaddr_in sin, QByteArray message ); + virtual bool SendTo( QString address, uint16_t port, QByteArray message ); + virtual bool Broadcast( uint16_t port, QByteArray message ); + virtual void SetBroadcastTarget( QString subnet ); virtual void SetDontRoute( bool dontRoute ); }; @@ -224,8 +224,8 @@ class CUDPServer : public CUDPSocket virtual ~CUDPServer( ); virtual bool Bind( struct sockaddr_in sin ); - virtual bool Bind( string address, uint16_t port ); - virtual void RecvFrom( fd_set *fd, struct sockaddr_in *sin, string *message ); + virtual bool Bind( QString address, uint16_t port ); + virtual void RecvFrom( fd_set *fd, struct sockaddr_in *sin, QString *message ); }; #endif diff --git a/ghost/statsdota.cpp b/ghost/statsdota.cpp index f7499a8..58bcd8e 100644 --- a/ghost/statsdota.cpp +++ b/ghost/statsdota.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -27,6 +27,8 @@ #include "stats.h" #include "statsdota.h" +#include + // // CStatsDOTA // @@ -55,12 +57,12 @@ CStatsDOTA :: ~CStatsDOTA( ) bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { unsigned int i = 0; - BYTEARRAY *ActionData = Action->GetAction( ); - BYTEARRAY Data; - BYTEARRAY Key; - BYTEARRAY Value; + QByteArray *ActionData = Action->GetAction( ); + QByteArray Data; + QByteArray Key; + QByteArray Value; - // dota actions with real time replay data start with 0x6b then the null terminated string "dr.x" + // dota actions with real time replay data start with 0x6b then the null terminated QString "dr.x" // unfortunately more than one action can be sent in a single packet and the length of each action isn't explicitly represented in the packet // so we have to either parse all the actions and calculate the length based on the type or we can search for an identifying sequence // parsing the actions would be more correct but would be a lot more difficult to write for relatively little gain @@ -75,13 +77,13 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) if( ActionData->size( ) >= i + 7 ) { - // the first null terminated string should either be the strings "Data" or "Global" or a player id in ASCII representation, e.g. "1" or "2" + // the first null terminated QString should either be the strings "Data" or "Global" or a player id in ASCII representation, e.g. "1" or "2" Data = UTIL_ExtractCString( *ActionData, i + 6 ); if( ActionData->size( ) >= i + 8 + Data.size( ) ) { - // the second null terminated string should be the key + // the second null terminated QString should be the key Key = UTIL_ExtractCString( *ActionData, i + 7 + Data.size( ) ); @@ -89,10 +91,10 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { // the 4 byte integer should be the value - Value = BYTEARRAY( ActionData->begin( ) + i + 8 + Data.size( ) + Key.size( ), ActionData->begin( ) + i + 12 + Data.size( ) + Key.size( ) ); - string DataString = string( Data.begin( ), Data.end( ) ); - string KeyString = string( Key.begin( ), Key.end( ) ); - uint32_t ValueInt = UTIL_ByteArrayToUInt32( Value, false ); + Value = ActionData->mid(i + 8 + Data.size( ) + Key.size( ), 4 ); + QString DataString = Data; + QString KeyString = Key; + uint32_t ValueInt = UTIL_QByteArrayToUInt32( Value, false ); // CONSOLE_Print( "[STATS] " + DataString + ", " + KeyString + ", " + UTIL_ToString( ValueInt ) ); @@ -102,11 +104,11 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) // you could use these to calculate killing sprees and double or triple kills (you'd have to make up your own time restrictions though) // you could also build a table of "who killed who" data - if( KeyString.size( ) >= 5 && KeyString.substr( 0, 4 ) == "Hero" ) + if( KeyString.size( ) >= 5 && KeyString.mid( 0, 4 ) == "Hero" ) { // a hero died - string VictimColourString = KeyString.substr( 4 ); + QString VictimColourString = KeyString.mid( 4 ); uint32_t VictimColour = UTIL_ToUInt32( VictimColourString ); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); CGamePlayer *Victim = m_Game->GetPlayerFromColour( VictimColour ); @@ -121,7 +123,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Scourge killed player [" + Victim->GetName( ) + "]" ); } } - else if( KeyString.size( ) >= 8 && KeyString.substr( 0, 7 ) == "Courier" ) + else if( KeyString.size( ) >= 8 && KeyString.mid( 0, 7 ) == "Courier" ) { // a courier died @@ -133,7 +135,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) m_Players[ValueInt]->SetCourierKills( m_Players[ValueInt]->GetCourierKills( ) + 1 ); } - string VictimColourString = KeyString.substr( 7 ); + QString VictimColourString = KeyString.mid( 7 ); uint32_t VictimColour = UTIL_ToUInt32( VictimColourString ); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); CGamePlayer *Victim = m_Game->GetPlayerFromColour( VictimColour ); @@ -148,7 +150,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Scourge killed a courier owned by player [" + Victim->GetName( ) + "]" ); } } - else if( KeyString.size( ) >= 8 && KeyString.substr( 0, 5 ) == "Tower" ) + else if( KeyString.size( ) >= 8 && KeyString.mid( 0, 5 ) == "Tower" ) { // a tower died @@ -160,12 +162,12 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) m_Players[ValueInt]->SetTowerKills( m_Players[ValueInt]->GetTowerKills( ) + 1 ); } - string Alliance = KeyString.substr( 5, 1 ); - string Level = KeyString.substr( 6, 1 ); - string Side = KeyString.substr( 7, 1 ); + QString Alliance = KeyString.mid( 5, 1 ); + QString Level = KeyString.mid( 6, 1 ); + QString Side = KeyString.mid( 7, 1 ); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); - string AllianceString; - string SideString; + QString AllianceString; + QString SideString; if( Alliance == "0" ) AllianceString = "Sentinel"; @@ -193,7 +195,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Scourge destroyed a level [" + Level + "] " + AllianceString + " tower (" + SideString + ")" ); } } - else if( KeyString.size( ) >= 6 && KeyString.substr( 0, 3 ) == "Rax" ) + else if( KeyString.size( ) >= 6 && KeyString.mid( 0, 3 ) == "Rax" ) { // a rax died @@ -205,13 +207,13 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) m_Players[ValueInt]->SetRaxKills( m_Players[ValueInt]->GetRaxKills( ) + 1 ); } - string Alliance = KeyString.substr( 3, 1 ); - string Side = KeyString.substr( 4, 1 ); - string Type = KeyString.substr( 5, 1 ); + QString Alliance = KeyString.mid( 3, 1 ); + QString Side = KeyString.mid( 4, 1 ); + QString Type = KeyString.mid( 5, 1 ); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); - string AllianceString; - string SideString; - string TypeString; + QString AllianceString; + QString SideString; + QString TypeString; if( Alliance == "0" ) AllianceString = "Sentinel"; @@ -246,19 +248,19 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Scourge destroyed a " + TypeString + " " + AllianceString + " rax (" + SideString + ")" ); } } - else if( KeyString.size( ) >= 6 && KeyString.substr( 0, 6 ) == "Throne" ) + else if( KeyString.size( ) >= 6 && KeyString.mid( 0, 6 ) == "Throne" ) { // the frozen throne got hurt CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Frozen Throne is now at " + UTIL_ToString( ValueInt ) + "% HP" ); } - else if( KeyString.size( ) >= 4 && KeyString.substr( 0, 4 ) == "Tree" ) + else if( KeyString.size( ) >= 4 && KeyString.mid( 0, 4 ) == "Tree" ) { // the world tree got hurt CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the World Tree is now at " + UTIL_ToString( ValueInt ) + "% HP" ); } - else if( KeyString.size( ) >= 2 && KeyString.substr( 0, 2 ) == "CK" ) + else if( KeyString.size( ) >= 2 && KeyString.mid( 0, 2 ) == "CK" ) { // a player disconnected } @@ -286,7 +288,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) else if( KeyString == "s" ) m_Sec = ValueInt; } - else if( DataString.size( ) <= 2 && DataString.find_first_not_of( "1234567890" ) == string :: npos ) + else if( DataString.size( ) <= 2 && DataString.indexOf(QRegExp( "[^0-9]" )) == -1 ) { // these are only received at the end of the game @@ -330,19 +332,19 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) else if( KeyString == "7" ) m_Players[ID]->SetNeutralKills( ValueInt ); else if( KeyString == "8_0" ) - m_Players[ID]->SetItem( 0, string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetItem( 0, QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "8_1" ) - m_Players[ID]->SetItem( 1, string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetItem( 1, QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "8_2" ) - m_Players[ID]->SetItem( 2, string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetItem( 2, QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "8_3" ) - m_Players[ID]->SetItem( 3, string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetItem( 3, QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "8_4" ) - m_Players[ID]->SetItem( 4, string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetItem( 4, QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "8_5" ) - m_Players[ID]->SetItem( 5, string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetItem( 5, QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "9" ) - m_Players[ID]->SetHero( string( Value.rbegin( ), Value.rend( ) ) ); + m_Players[ID]->SetHero( QString( UTIL_QByteArrayReverse(Value) ) ); else if( KeyString == "id" ) { // DotA sends id values from 1-10 with 1-5 being sentinel players and 6-10 being scourge players diff --git a/ghost/statsw3mmd.cpp b/ghost/statsw3mmd.cpp index 638f386..93a7d23 100644 --- a/ghost/statsw3mmd.cpp +++ b/ghost/statsw3mmd.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -26,11 +26,13 @@ #include "stats.h" #include "statsw3mmd.h" +#include + // // CStatsW3MMD // -CStatsW3MMD :: CStatsW3MMD( CBaseGame *nGame, string nCategory ) : CStats( nGame ) +CStatsW3MMD :: CStatsW3MMD( CBaseGame *nGame, QString nCategory ) : CStats( nGame ) { CONSOLE_Print( "[STATSW3MMD] using Warcraft 3 Map Meta Data stats parser version 1" ); CONSOLE_Print( "[STATSW3MMD] using map_statsw3mmdcategory [" + nCategory + "]" ); @@ -47,10 +49,10 @@ CStatsW3MMD :: ~CStatsW3MMD( ) bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { unsigned int i = 0; - BYTEARRAY *ActionData = Action->GetAction( ); - BYTEARRAY MissionKey; - BYTEARRAY Key; - BYTEARRAY Value; + QByteArray *ActionData = Action->GetAction( ); + QByteArray MissionKey; + QByteArray Key; + QByteArray Value; while( ActionData->size( ) >= i + 9 ) { @@ -74,18 +76,18 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) if( ActionData->size( ) >= i + 15 + MissionKey.size( ) + Key.size( ) ) { - Value = BYTEARRAY( ActionData->begin( ) + i + 11 + MissionKey.size( ) + Key.size( ), ActionData->begin( ) + i + 15 + MissionKey.size( ) + Key.size( ) ); - string MissionKeyString = string( MissionKey.begin( ), MissionKey.end( ) ); - string KeyString = string( Key.begin( ), Key.end( ) ); - uint32_t ValueInt = UTIL_ByteArrayToUInt32( Value, false ); + Value = ActionData->mid(i + 11 + MissionKey.size( ) + Key.size( ), 4 ); + QString MissionKeyString = MissionKey; + QString KeyString = Key; + uint32_t ValueInt = UTIL_QByteArrayToUInt32( Value, false ); // CONSOLE_Print( "[STATSW3MMD] DEBUG: mkey [" + MissionKeyString + "], key [" + KeyString + "], value [" + UTIL_ToString( ValueInt ) + "]" ); - if( MissionKeyString.size( ) > 4 && MissionKeyString.substr( 0, 4 ) == "val:" ) + if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "val:" ) { - string ValueIDString = MissionKeyString.substr( 4 ); + QString ValueIDString = MissionKeyString.mid( 4 ); uint32_t ValueID = UTIL_ToUInt32( ValueIDString ); - vector Tokens = TokenizeKey( KeyString ); + vector Tokens = TokenizeKey( KeyString ); if( !Tokens.empty( ) ) { @@ -125,7 +127,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] duplicate DefVarP [" + KeyString + "] found, ignoring" ); else { - if( Tokens[2] == "int" || Tokens[2] == "real" || Tokens[2] == "string" ) + if( Tokens[2] == "int" || Tokens[2] == "real" || Tokens[2] == "QString" ) m_DefVarPs[Tokens[1]] = Tokens[2]; else CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown DefVarP [" + KeyString + "] found, ignoring" ); @@ -143,7 +145,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] VarP [" + KeyString + "] found without a corresponding DefVarP, ignoring" ); else { - string ValueType = m_DefVarPs[Tokens[2]]; + QString ValueType = m_DefVarPs[Tokens[2]]; if( ValueType == "int" ) { @@ -210,7 +212,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) if( Tokens[3] == "=" ) m_VarPStrings[VP] = Tokens[4]; else - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown string VarP [" + KeyString + "] operation [" + Tokens[3] + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown QString VarP [" + KeyString + "] operation [" + Tokens[3] + "] found, ignoring" ); } } } @@ -252,7 +254,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) uint32_t Arguments = UTIL_ToUInt32( Tokens[2] ); if( Tokens.size( ) == Arguments + 4 ) - m_DefEvents[Tokens[1]] = vector( Tokens.begin( ) + 3, Tokens.end( ) ); + m_DefEvents[Tokens[1]] = vector( Tokens.begin( ) + 3, Tokens.end( ) ); } } else if( Tokens[0] == "Event" && Tokens.size( ) >= 2 ) @@ -264,23 +266,23 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + KeyString + "] found without a corresponding DefEvent, ignoring" ); else { - vector DefEvent = m_DefEvents[Tokens[1]]; + vector DefEvent = m_DefEvents[Tokens[1]]; if( !DefEvent.empty( ) ) { - string Format = DefEvent[DefEvent.size( ) - 1]; + QString Format = DefEvent[DefEvent.size( ) - 1]; if( Tokens.size( ) - 2 != DefEvent.size( ) - 1 ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + KeyString + "] found with " + UTIL_ToString( Tokens.size( ) - 2 ) + " arguments but expected " + UTIL_ToString( DefEvent.size( ) - 1 ) + " arguments, ignoring" ); else { - // replace the markers in the format string with the arguments + // replace the markers in the format QString with the arguments for( uint32_t i = 0; i < Tokens.size( ) - 2; i++ ) { // check if the marker is a PID marker - if( DefEvent[i].substr( 0, 4 ) == "pid:" ) + if( DefEvent[i].midRef( 0, 4 ) == "pid:" ) { // replace it with the player's name rather than their PID @@ -316,9 +318,9 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) m_NextValueID++; } - else if( MissionKeyString.size( ) > 4 && MissionKeyString.substr( 0, 4 ) == "chk:" ) + else if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "chk:" ) { - string CheckIDString = MissionKeyString.substr( 4 ); + QString CheckIDString = MissionKeyString.mid( 4 ); uint32_t CheckID = UTIL_ToUInt32( CheckIDString ); // todotodo: cheat detection @@ -355,9 +357,9 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) // todotodo: there's no reason to create a new callable for each entry in this map // rewrite ThreadedW3MMDPlayerAdd to act more like ThreadedW3MMDVarAdd - for( map :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) + for( map :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) { - string Flags = m_Flags[i->first]; + QString Flags = m_Flags[i->first]; uint32_t Leaver = 0; uint32_t Practicing = 0; @@ -365,7 +367,7 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) { Leaver = 1; - if( !Flags.empty( ) ) + if( !Flags.isEmpty( ) ) Flags += "/"; Flags += "leaver"; @@ -375,7 +377,7 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) { Practicing = 1; - if( !Flags.empty( ) ) + if( !Flags.isEmpty( ) ) Flags += "/"; Flags += "practicing"; @@ -403,13 +405,13 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unable to begin database transaction, data not saved" ); } -vector CStatsW3MMD :: TokenizeKey( string key ) +vector CStatsW3MMD :: TokenizeKey( QString key ) { - vector Tokens; - string Token; + vector Tokens; + QString Token; bool Escaping = false; - for( string :: iterator i = key.begin( ); i != key.end( ); i++ ) + for( QString :: iterator i = key.begin( ); i != key.end( ); i++ ) { if( Escaping ) { @@ -420,7 +422,7 @@ vector CStatsW3MMD :: TokenizeKey( string key ) else { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], invalid escape sequence found, ignoring" ); - return vector( ); + return vector( ); } Escaping = false; @@ -429,10 +431,10 @@ vector CStatsW3MMD :: TokenizeKey( string key ) { if( *i == ' ' ) { - if( Token.empty( ) ) + if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return vector( ); + return vector( ); } Tokens.push_back( Token ); @@ -445,10 +447,10 @@ vector CStatsW3MMD :: TokenizeKey( string key ) } } - if( Token.empty( ) ) + if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return vector( ); + return vector( ); } Tokens.push_back( Token ); diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index b6ed218..41c7224 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -25,31 +25,31 @@ // CStatsW3MMD // -typedef pair VarP; +typedef pair VarP; class CStatsW3MMD : public CStats { private: - string m_Category; + QString m_Category; uint32_t m_NextValueID; uint32_t m_NextCheckID; - map m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case - map m_Flags; // pid -> flag (e.g. 0 -> "winner") + map m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case + map m_Flags; // pid -> flag (e.g. 0 -> "winner") map m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true map m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true - map m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") + map m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") map m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) map m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) - map m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") - map > m_DefEvents; // event -> vector of arguments + format + map m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") + map > m_DefEvents; // event -> vector of arguments + format public: - CStatsW3MMD( CBaseGame *nGame, string nCategory ); + CStatsW3MMD( CBaseGame *nGame, QString nCategory ); virtual ~CStatsW3MMD( ); virtual bool ProcessAction( CIncomingAction *Action ); virtual void Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ); - virtual vector TokenizeKey( string key ); + virtual vector TokenizeKey( QString key ); }; #endif diff --git a/ghost/util.cpp b/ghost/util.cpp index 6f158c0..9d76ae5 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -21,206 +21,165 @@ #include "ghost.h" #include "util.h" -#include +#include +#include -BYTEARRAY UTIL_CreateByteArray( unsigned char *a, int size ) +QByteArray UTIL_CreateQByteArray( unsigned char c ) { - if( size < 1 ) - return BYTEARRAY( ); - - return BYTEARRAY( a, a + size ); -} - -BYTEARRAY UTIL_CreateByteArray( unsigned char c ) -{ - BYTEARRAY result; + QByteArray result; result.push_back( c ); return result; } -BYTEARRAY UTIL_CreateByteArray( uint16_t i, bool reverse ) +QByteArray UTIL_CreateQByteArray( uint16_t i, bool reverse ) { - BYTEARRAY result; - result.push_back( (unsigned char)i ); + QByteArray result; + + if (!reverse) + result.push_back( (unsigned char)i ); + result.push_back( (unsigned char)( i >> 8 ) ); - if( reverse ) - return BYTEARRAY( result.rbegin( ), result.rend( ) ); - else - return result; + if (reverse) + result.push_back( (unsigned char)i ); + + return result; } -BYTEARRAY UTIL_CreateByteArray( uint32_t i, bool reverse ) +QByteArray UTIL_CreateQByteArray( uint32_t i, bool reverse ) { - BYTEARRAY result; - result.push_back( (unsigned char)i ); - result.push_back( (unsigned char)( i >> 8 ) ); - result.push_back( (unsigned char)( i >> 16 ) ); - result.push_back( (unsigned char)( i >> 24 ) ); + QByteArray result; if( reverse ) - return BYTEARRAY( result.rbegin( ), result.rend( ) ); + { + result.push_back( (unsigned char)( i >> 24 ) ); + result.push_back( (unsigned char)( i >> 16 ) ); + result.push_back( (unsigned char)( i >> 8 ) ); + result.push_back( (unsigned char)i ); + } + else - return result; + { + result.push_back( (unsigned char)i ); + result.push_back( (unsigned char)( i >> 8 ) ); + result.push_back( (unsigned char)( i >> 16 ) ); + result.push_back( (unsigned char)( i >> 24 ) ); + } + + return result; } -uint16_t UTIL_ByteArrayToUInt16( BYTEARRAY b, bool reverse, unsigned int start ) +uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start ) { if( b.size( ) < start + 2 ) return 0; - BYTEARRAY temp = BYTEARRAY( b.begin( ) + start, b.begin( ) + start + 2 ); + QByteArray temp = b.mid(start, 2); - if( reverse ) - temp = BYTEARRAY( temp.rbegin( ), temp.rend( ) ); - - return (uint16_t)( temp[1] << 8 | temp[0] ); + return (uint16_t)( reverse ? (temp[0] << 8 | temp[1]) : (temp[1] << 8 | temp[0]) ); } -uint32_t UTIL_ByteArrayToUInt32( BYTEARRAY b, bool reverse, unsigned int start ) +uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start ) { if( b.size( ) < start + 4 ) return 0; - BYTEARRAY temp = BYTEARRAY( b.begin( ) + start, b.begin( ) + start + 4 ); + QByteArray temp = b.mid(start, 4); - if( reverse ) - temp = BYTEARRAY( temp.rbegin( ), temp.rend( ) ); + if (reverse) + return (uint32_t)( temp[0] << 24 | temp[1] << 16 | temp[2] << 8 | temp[3] ); return (uint32_t)( temp[3] << 24 | temp[2] << 16 | temp[1] << 8 | temp[0] ); } -string UTIL_ByteArrayToDecString( BYTEARRAY b ) +QString UTIL_QByteArrayToDecString( QByteArray b ) { - if( b.empty( ) ) - return string( ); + if( b.isEmpty( ) ) + return QString( ); - string result = UTIL_ToString( b[0] ); + QString result = QString::number( b[0] ); - for( BYTEARRAY :: iterator i = b.begin( ) + 1; i != b.end( ); i++ ) - result += " " + UTIL_ToString( *i ); + for( QByteArray :: iterator i = b.begin( ) + 1; i != b.end( ); i++ ) + result += " " + QString::number( *i ); return result; } -string UTIL_ByteArrayToHexString( BYTEARRAY b ) +QString UTIL_QByteArrayToHexString( QByteArray b ) { - if( b.empty( ) ) - return string( ); - - string result = UTIL_ToHexString( b[0] ); - - for( BYTEARRAY :: iterator i = b.begin( ) + 1; i != b.end( ); i++ ) - { - if( *i < 16 ) - result += " 0" + UTIL_ToHexString( *i ); - else - result += " " + UTIL_ToHexString( *i ); - } - - return result; + return QString::fromAscii(b.toHex()); } -void UTIL_AppendByteArray( BYTEARRAY &b, BYTEARRAY append ) +void UTIL_AppendQByteArray( QByteArray &b, QByteArray append ) { - b.insert( b.end( ), append.begin( ), append.end( ) ); + b.append(append); } -void UTIL_AppendByteArrayFast( BYTEARRAY &b, BYTEARRAY &append ) +void UTIL_AppendQByteArrayFast( QByteArray &b, QByteArray &append ) { - b.insert( b.end( ), append.begin( ), append.end( ) ); + b.append(append); } -void UTIL_AppendByteArray( BYTEARRAY &b, unsigned char *a, int size ) +void UTIL_AppendQByteArray( QByteArray &b, unsigned char *a, int size ) { - UTIL_AppendByteArray( b, UTIL_CreateByteArray( a, size ) ); + b.append((char*)a, size); } -void UTIL_AppendByteArray( BYTEARRAY &b, string append, bool terminator ) +void UTIL_AppendQByteArray( QByteArray &b, QString append, bool terminator ) { - // append the string plus a null terminator - - b.insert( b.end( ), append.begin( ), append.end( ) ); + b.append(append); if( terminator ) - b.push_back( 0 ); + b.push_back( (char)0 ); } -void UTIL_AppendByteArrayFast( BYTEARRAY &b, string &append, bool terminator ) +void UTIL_AppendQByteArrayFast( QByteArray &b, QString &append, bool terminator ) { - // append the string plus a null terminator - - b.insert( b.end( ), append.begin( ), append.end( ) ); + b.append(append); if( terminator ) - b.push_back( 0 ); + b.push_back( (char)0 ); } -void UTIL_AppendByteArray( BYTEARRAY &b, uint16_t i, bool reverse ) +void UTIL_AppendQByteArray( QByteArray &b, uint16_t i, bool reverse ) { - UTIL_AppendByteArray( b, UTIL_CreateByteArray( i, reverse ) ); + b.append( UTIL_CreateQByteArray( i, reverse ) ); } -void UTIL_AppendByteArray( BYTEARRAY &b, uint32_t i, bool reverse ) +void UTIL_AppendQByteArray( QByteArray &b, uint32_t i, bool reverse ) { - UTIL_AppendByteArray( b, UTIL_CreateByteArray( i, reverse ) ); + b.append( UTIL_CreateQByteArray( i, reverse ) ); } -BYTEARRAY UTIL_ExtractCString( BYTEARRAY &b, unsigned int start ) +QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ) { // start searching the byte array at position 'start' for the first null value // if found, return the subarray from 'start' to the null value but not including the null value - if( start < b.size( ) ) - { - for( unsigned int i = start; i < b.size( ); i++ ) - { - if( b[i] == 0 ) - return BYTEARRAY( b.begin( ) + start, b.begin( ) + i ); - } - - // no null value found, return the rest of the byte array - - return BYTEARRAY( b.begin( ) + start, b.end( ) ); - } - - return BYTEARRAY( ); + QString s(b.mid(start).data()); + return s.toUtf8(); } -unsigned char UTIL_ExtractHex( BYTEARRAY &b, unsigned int start, bool reverse ) +unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ) { // consider the byte array to contain a 2 character ASCII encoded hex value at b[start] and b[start + 1] e.g. "FF" // extract it as a single decoded byte - if( start + 1 < b.size( ) ) - { - unsigned int c; - string temp = string( b.begin( ) + start, b.begin( ) + start + 2 ); - - if( reverse ) - temp = string( temp.rend( ), temp.rbegin( ) ); - - stringstream SS; - SS << temp; - SS >> hex >> c; - return c; - } - - return 0; + return (unsigned char)b.mid(start, 2).toUShort(NULL, 16); } -BYTEARRAY UTIL_ExtractNumbers( string s, unsigned int count ) +QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ) { - // consider the string to contain a bytearray in dec-text form, e.g. "52 99 128 1" + // consider the QString to contain a QByteArray in dec-text form, e.g. "52 99 128 1" - BYTEARRAY result; + QByteArray result; unsigned int c; - stringstream SS; + QTextStream SS; SS << s; for( unsigned int i = 0; i < count; i++ ) { - if( SS.eof( ) ) + if( SS.atEnd() ) break; SS >> c; @@ -233,16 +192,16 @@ BYTEARRAY UTIL_ExtractNumbers( string s, unsigned int count ) return result; } -BYTEARRAY UTIL_ExtractHexNumbers( string s ) +QByteArray UTIL_ExtractHexNumbers( QString s ) { - // consider the string to contain a bytearray in hex-text form, e.g. "4e 17 b7 e6" + // consider the QString to contain a QByteArray in hex-text form, e.g. "4e 17 b7 e6" - BYTEARRAY result; + QByteArray result; unsigned int c; - stringstream SS; + QTextStream SS; SS << s; - while( !SS.eof( ) ) + while( !SS.atEnd() ) { SS >> hex >> c; @@ -254,138 +213,139 @@ BYTEARRAY UTIL_ExtractHexNumbers( string s ) return result; } -string UTIL_ToString( unsigned long i ) +QString UTIL_ToString( unsigned long i ) { - string result; - stringstream SS; + QString result; + QTextStream SS; SS << i; SS >> result; return result; } -string UTIL_ToString( unsigned short i ) +QString UTIL_ToString( unsigned short i ) { - string result; - stringstream SS; + QString result; + QTextStream SS; SS << i; SS >> result; return result; } -string UTIL_ToString( unsigned int i ) +QString UTIL_ToString( unsigned int i ) { - string result; - stringstream SS; + QString result; + QTextStream SS; SS << i; SS >> result; return result; } -string UTIL_ToString( long i ) +QString UTIL_ToString( long i ) { - string result; - stringstream SS; + QString result; + QTextStream SS; SS << i; SS >> result; return result; } -string UTIL_ToString( short i ) +QString UTIL_ToString( short i ) { - string result; - stringstream SS; + QString result; + QTextStream SS; SS << i; SS >> result; return result; } -string UTIL_ToString( int i ) +QString UTIL_ToString( int i ) { - string result; - stringstream SS; + QString result; + QTextStream SS; SS << i; SS >> result; return result; } -string UTIL_ToString( float f, int digits ) +QString UTIL_ToString( float f, int digits ) { - string result; - stringstream SS; - SS << std :: fixed << std :: setprecision( digits ) << f; + QString result; + QTextStream SS; + SS.setRealNumberPrecision( digits ); + SS << QTextStream::FixedNotation << f; SS >> result; return result; } -string UTIL_ToString( double d, int digits ) +QString UTIL_ToString( double d, int digits ) { - string result; - stringstream SS; - SS << std :: fixed << std :: setprecision( digits ) << d; + QString result; + QTextStream SS; + SS << fixed << qSetRealNumberPrecision( digits ) << d; SS >> result; return result; } -string UTIL_ToHexString( uint32_t i ) +QString UTIL_ToHexString( uint32_t i ) { - string result; - stringstream SS; - SS << std :: hex << i; + QString result; + QTextStream SS; + SS << hex << i; SS >> result; return result; } // todotodo: these UTIL_ToXXX functions don't fail gracefully, they just return garbage (in the uint case usually just -1 casted to an unsigned type it looks like) -uint16_t UTIL_ToUInt16( string &s ) +uint16_t UTIL_ToUInt16( QString &s ) { uint16_t result; - stringstream SS; + QTextStream SS; SS << s; SS >> result; return result; } -uint32_t UTIL_ToUInt32( string &s ) +uint32_t UTIL_ToUInt32( QString &s ) { uint32_t result; - stringstream SS; + QTextStream SS; SS << s; SS >> result; return result; } -int16_t UTIL_ToInt16( string &s ) +int16_t UTIL_ToInt16( QString &s ) { int16_t result; - stringstream SS; + QTextStream SS; SS << s; SS >> result; return result; } -int32_t UTIL_ToInt32( string &s ) +int32_t UTIL_ToInt32( QString &s ) { int32_t result; - stringstream SS; + QTextStream SS; SS << s; SS >> result; return result; } -double UTIL_ToDouble( string &s ) +double UTIL_ToDouble( QString &s ) { double result; - stringstream SS; + QTextStream SS; SS << s; SS >> result; return result; } -string UTIL_MSToString( uint32_t ms ) +QString UTIL_MSToString( uint32_t ms ) { - string MinString = UTIL_ToString( ( ms / 1000 ) / 60 ); - string SecString = UTIL_ToString( ( ms / 1000 ) % 60 ); + QString MinString = UTIL_ToString( ( ms / 1000 ) / 60 ); + QString SecString = UTIL_ToString( ( ms / 1000 ) % 60 ); if( MinString.size( ) == 1 ) MinString.insert( 0, "0" ); @@ -396,133 +356,81 @@ string UTIL_MSToString( uint32_t ms ) return MinString + "m" + SecString + "s"; } -bool UTIL_FileExists( string file ) +bool UTIL_FileExists( QString file ) { - struct stat fileinfo; - - if( stat( file.c_str( ), &fileinfo ) == 0 ) - return true; - - return false; + return QFile::exists(file); } -string UTIL_FileRead( string file, uint32_t start, uint32_t length ) +QByteArray UTIL_FileRead( QString file, uint32_t start, uint32_t length ) { - ifstream IS; - IS.open( file.c_str( ), ios :: binary ); + QFile f(file); + f.open(QFile::ReadOnly); - if( IS.fail( ) ) + if (f.error() != QFile::NoError) { CONSOLE_Print( "[UTIL] warning - unable to read file part [" + file + "]" ); - return string( ); + return QByteArray(); } - // get length of file - - IS.seekg( 0, ios :: end ); - uint32_t FileLength = IS.tellg( ); - - if( start > FileLength ) - { - IS.close( ); - return string( ); - } - - IS.seekg( start, ios :: beg ); - - // read data - - char *Buffer = new char[length]; - IS.read( Buffer, length ); - string BufferString = string( Buffer, IS.gcount( ) ); - IS.close( ); - delete [] Buffer; - return BufferString; + f.seek(start); + return f.read(length); } -string UTIL_FileRead( string file ) +QByteArray UTIL_FileRead( QString file ) { - ifstream IS; - IS.open( file.c_str( ), ios :: binary ); + QFile f(file); + f.open(QFile::ReadOnly); - if( IS.fail( ) ) + if (f.error() != QFile::NoError) { CONSOLE_Print( "[UTIL] warning - unable to read file [" + file + "]" ); - return string( ); + return QByteArray(); } - // get length of file - - IS.seekg( 0, ios :: end ); - uint32_t FileLength = IS.tellg( ); - IS.seekg( 0, ios :: beg ); - - // read data - - char *Buffer = new char[FileLength]; - IS.read( Buffer, FileLength ); - string BufferString = string( Buffer, IS.gcount( ) ); - IS.close( ); - delete [] Buffer; - - if( BufferString.size( ) == FileLength ) - return BufferString; - else - return string( ); + return f.readAll(); } -bool UTIL_FileWrite( string file, unsigned char *data, uint32_t length ) +bool UTIL_FileWrite( QString file, unsigned char *data, uint32_t length ) { - ofstream OS; - OS.open( file.c_str( ), ios :: binary ); + QFile f(file); + f.open(QFile::Truncate); - if( OS.fail( ) ) + if (f.error() != QFile::NoError || !f.isWritable()) { CONSOLE_Print( "[UTIL] warning - unable to write file [" + file + "]" ); return false; } - // write data - - OS.write( (const char *)data, length ); - OS.close( ); + f.write((char*)data, length); return true; } -string UTIL_FileSafeName( string fileName ) +QString UTIL_FileSafeName( QString fileName ) { - string :: size_type BadStart = fileName.find_first_of( "\\/:*?<>|" ); - - while( BadStart != string :: npos ) - { - fileName.replace( BadStart, 1, 1, '_' ); - BadStart = fileName.find_first_of( "\\/:*?<>|" ); - } - - return fileName; + return fileName.replace(QRegExp("\\\\\\/\\:\\*\\?\\<\\>\\|"), "_"); } -string UTIL_AddPathSeperator( string path ) +QString UTIL_AddPathSeperator( QString path ) { - if( path.empty( ) ) - return string( ); + if( path.isEmpty( ) ) + return path; #ifdef WIN32 - char Seperator = '\\'; + QString Seperator = "\\"; #else - char Seperator = '/'; + QString Seperator = "/"; #endif - if( *(path.end( ) - 1) == Seperator ) + if( path.right(1) == Seperator ) return path; else - return path + string( 1, Seperator ); + return path + Seperator; } -BYTEARRAY UTIL_EncodeStatString( BYTEARRAY &data ) +QByteArray UTIL_EncodeStatString( QByteArray &data ) { unsigned char Mask = 1; - BYTEARRAY Result; + QByteArray Result; for( unsigned int i = 0; i < data.size( ); i++ ) { @@ -536,7 +444,7 @@ BYTEARRAY UTIL_EncodeStatString( BYTEARRAY &data ) if( i % 7 == 6 || i == data.size( ) - 1 ) { - Result.insert( Result.end( ) - 1 - ( i % 7 ), Mask ); + Result.insert( Result.size() - 1 - ( i % 7 ), Mask); Mask = 1; } } @@ -544,10 +452,20 @@ BYTEARRAY UTIL_EncodeStatString( BYTEARRAY &data ) return Result; } -BYTEARRAY UTIL_DecodeStatString( BYTEARRAY &data ) +QByteArray UTIL_QByteArrayReverse(const QByteArray &b) +{ + QByteArray res; + QByteArray::const_iterator it; + for (it = b.end(); it != b.begin(); it--) + res.push_back(*it); + + return res; +} + +QByteArray UTIL_DecodeStatString( QByteArray &data ) { unsigned char Mask; - BYTEARRAY Result; + QByteArray Result; for( unsigned int i = 0; i < data.size( ); i++ ) { @@ -565,7 +483,7 @@ BYTEARRAY UTIL_DecodeStatString( BYTEARRAY &data ) return Result; } -bool UTIL_IsLanIP( BYTEARRAY ip ) +bool UTIL_IsLanIP( QByteArray ip ) { if( ip.size( ) != 4 ) return false; @@ -595,12 +513,12 @@ bool UTIL_IsLanIP( BYTEARRAY ip ) return false; } -bool UTIL_IsLocalIP( BYTEARRAY ip, vector &localIPs ) +bool UTIL_IsLocalIP( QByteArray ip, vector &localIPs ) { if( ip.size( ) != 4 ) return false; - for( vector :: iterator i = localIPs.begin( ); i != localIPs.end( ); i++ ) + for( vector :: iterator i = localIPs.begin( ); i != localIPs.end( ); i++ ) { if( (*i).size( ) != 4 ) continue; @@ -612,32 +530,21 @@ bool UTIL_IsLocalIP( BYTEARRAY ip, vector &localIPs ) return false; } -void UTIL_Replace( string &Text, string Key, string Value ) +void UTIL_Replace( QString &Text, QString Key, QString Value ) { - // don't allow any infinite loops - - if( Value.find( Key ) != string :: npos ) - return; - - string :: size_type KeyStart = Text.find( Key ); - - while( KeyStart != string :: npos ) - { - Text.replace( KeyStart, Key.size( ), Value ); - KeyStart = Text.find( Key ); - } + Text.replace(Key, Value); } -vector UTIL_Tokenize( string s, char delim ) +vector UTIL_Tokenize( QString s, char delim ) { - vector Tokens; - string Token; + vector Tokens; + QString Token; - for( string :: iterator i = s.begin( ); i != s.end( ); i++ ) + for( QString :: iterator i = s.begin( ); i != s.end( ); i++ ) { if( *i == delim ) { - if( Token.empty( ) ) + if( Token.isEmpty( ) ) continue; Tokens.push_back( Token ); @@ -647,7 +554,7 @@ vector UTIL_Tokenize( string s, char delim ) Token += *i; } - if( !Token.empty( ) ) + if( !Token.isEmpty( ) ) Tokens.push_back( Token ); return Tokens; diff --git a/ghost/util.h b/ghost/util.h index 93c724f..cdbcdfb 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -21,66 +21,70 @@ #ifndef UTIL_H #define UTIL_H +#include +#include + // byte arrays -BYTEARRAY UTIL_CreateByteArray( unsigned char *a, int size ); -BYTEARRAY UTIL_CreateByteArray( unsigned char c ); -BYTEARRAY UTIL_CreateByteArray( uint16_t i, bool reverse ); -BYTEARRAY UTIL_CreateByteArray( uint32_t i, bool reverse ); -uint16_t UTIL_ByteArrayToUInt16( BYTEARRAY b, bool reverse, unsigned int start = 0 ); -uint32_t UTIL_ByteArrayToUInt32( BYTEARRAY b, bool reverse, unsigned int start = 0 ); -string UTIL_ByteArrayToDecString( BYTEARRAY b ); -string UTIL_ByteArrayToHexString( BYTEARRAY b ); -void UTIL_AppendByteArray( BYTEARRAY &b, BYTEARRAY append ); -void UTIL_AppendByteArrayFast( BYTEARRAY &b, BYTEARRAY &append ); -void UTIL_AppendByteArray( BYTEARRAY &b, unsigned char *a, int size ); -void UTIL_AppendByteArray( BYTEARRAY &b, string append, bool terminator = true ); -void UTIL_AppendByteArrayFast( BYTEARRAY &b, string &append, bool terminator = true ); -void UTIL_AppendByteArray( BYTEARRAY &b, uint16_t i, bool reverse ); -void UTIL_AppendByteArray( BYTEARRAY &b, uint32_t i, bool reverse ); -BYTEARRAY UTIL_ExtractCString( BYTEARRAY &b, unsigned int start ); -unsigned char UTIL_ExtractHex( BYTEARRAY &b, unsigned int start, bool reverse ); -BYTEARRAY UTIL_ExtractNumbers( string s, unsigned int count ); -BYTEARRAY UTIL_ExtractHexNumbers( string s ); +QByteArray UTIL_CreateQByteArray( unsigned char *a, int size ); +QByteArray UTIL_CreateQByteArray( unsigned char c ); +QByteArray UTIL_CreateQByteArray( uint16_t i, bool reverse ); +QByteArray UTIL_CreateQByteArray( uint32_t i, bool reverse ); +uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start = 0 ); +uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start = 0 ); +QString UTIL_QByteArrayToDecString( QByteArray b ); +QString UTIL_QByteArrayToHexString( QByteArray b ); +void UTIL_AppendQByteArray( QByteArray &b, QByteArray append ); +void UTIL_AppendQByteArrayFast( QByteArray &b, QByteArray &append ); +void UTIL_AppendQByteArray( QByteArray &b, unsigned char *a, int size ); +void UTIL_AppendQByteArray( QByteArray &b, QString append, bool terminator = true ); +void UTIL_AppendQByteArrayFast( QByteArray &b, QString &append, bool terminator = true ); +void UTIL_AppendQByteArray( QByteArray &b, uint16_t i, bool reverse ); +void UTIL_AppendQByteArray( QByteArray &b, uint32_t i, bool reverse ); +QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ); +unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ); +QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ); +QByteArray UTIL_ExtractHexNumbers( QString s ); +QByteArray UTIL_QByteArrayReverse(const QByteArray &b); // conversions -string UTIL_ToString( unsigned long i ); -string UTIL_ToString( unsigned short i ); -string UTIL_ToString( unsigned int i ); -string UTIL_ToString( long i ); -string UTIL_ToString( short i ); -string UTIL_ToString( int i ); -string UTIL_ToString( float f, int digits ); -string UTIL_ToString( double d, int digits ); -string UTIL_ToHexString( uint32_t i ); -uint16_t UTIL_ToUInt16( string &s ); -uint32_t UTIL_ToUInt32( string &s ); -int16_t UTIL_ToInt16( string &s ); -int32_t UTIL_ToInt32( string &s ); -double UTIL_ToDouble( string &s ); -string UTIL_MSToString( uint32_t ms ); +QString UTIL_ToString( unsigned long i ); +QString UTIL_ToString( unsigned short i ); +QString UTIL_ToString( unsigned int i ); +QString UTIL_ToString( long i ); +QString UTIL_ToString( short i ); +QString UTIL_ToString( int i ); +QString UTIL_ToString( float f, int digits ); +QString UTIL_ToString( double d, int digits ); +QString UTIL_ToHexString( uint32_t i ); +uint16_t UTIL_ToUInt16( QString &s ); +uint32_t UTIL_ToUInt32( QString &s ); +int16_t UTIL_ToInt16( QString &s ); +int32_t UTIL_ToInt32( QString &s ); +double UTIL_ToDouble( QString &s ); +QString UTIL_MSToString( uint32_t ms ); // files -bool UTIL_FileExists( string file ); -string UTIL_FileRead( string file, uint32_t start, uint32_t length ); -string UTIL_FileRead( string file ); -bool UTIL_FileWrite( string file, unsigned char *data, uint32_t length ); -string UTIL_FileSafeName( string fileName ); -string UTIL_AddPathSeperator( string path ); +bool UTIL_FileExists( QString file ); +QByteArray UTIL_FileRead( QString file, uint32_t start, uint32_t length ); +QByteArray UTIL_FileRead( QString file ); +bool UTIL_FileWrite( QString file, unsigned char *data, uint32_t length ); +QString UTIL_FileSafeName( QString fileName ); +QString UTIL_AddPathSeperator( QString path ); // stat strings -BYTEARRAY UTIL_EncodeStatString( BYTEARRAY &data ); -BYTEARRAY UTIL_DecodeStatString( BYTEARRAY &data ); +QByteArray UTIL_EncodeStatString( QByteArray &data ); +QByteArray UTIL_DecodeStatString( QByteArray &data ); // other -bool UTIL_IsLanIP( BYTEARRAY ip ); -bool UTIL_IsLocalIP( BYTEARRAY ip, vector &localIPs ); -void UTIL_Replace( string &Text, string Key, string Value ); -vector UTIL_Tokenize( string s, char delim ); +bool UTIL_IsLanIP( QByteArray ip ); +bool UTIL_IsLocalIP( QByteArray ip, vector &localIPs ); +void UTIL_Replace( QString &Text, QString Key, QString Value ); +vector UTIL_Tokenize( QString s, char delim ); // math From 0e7f5c65f2a845bb210215dad24e97f04b86a2de Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Mon, 19 Apr 2010 14:02:55 +0000 Subject: [PATCH 03/69] not working so far --- ghost/bncsutilinterface.cpp | 32 +-- ghost/bncsutilinterface.h | 38 +-- ghost/bnet.cpp | 314 +++++++++++------------ ghost/bnet.h | 40 +-- ghost/bnetprotocol.cpp | 350 +++++++++++++------------- ghost/bnetprotocol.h | 128 +++++----- ghost/bnlsclient.cpp | 40 +-- ghost/bnlsclient.h | 10 +- ghost/bnlsprotocol.cpp | 54 ++-- ghost/bnlsprotocol.h | 14 +- ghost/commandpacket.cpp | 2 +- ghost/commandpacket.h | 6 +- ghost/config.cpp | 4 +- ghost/config.h | 2 +- ghost/game.cpp | 178 +++++++------- ghost/game.h | 12 +- ghost/game_admin.cpp | 148 +++++------ ghost/game_admin.h | 14 +- ghost/game_base.cpp | 478 ++++++++++++++++++------------------ ghost/game_base.h | 39 +-- ghost/gameplayer.cpp | 66 ++--- ghost/gameplayer.h | 34 +-- ghost/gameprotocol.cpp | 38 +-- ghost/gameprotocol.h | 12 +- ghost/gameslot.cpp | 13 +- ghost/gameslot.h | 7 +- ghost/ghost.cpp | 116 ++++----- ghost/ghost.h | 12 +- ghost/ghostdb.cpp | 20 +- ghost/ghostdb.h | 40 +-- ghost/ghostdbmysql.cpp | 126 +++++----- ghost/ghostdbmysql.h | 24 +- ghost/ghostdbsqlite.cpp | 48 ++-- ghost/ghostdbsqlite.h | 20 +- ghost/gpsprotocol.cpp | 58 ++--- ghost/gpsprotocol.h | 18 +- ghost/includes.h | 9 +- ghost/main.cpp | 2 +- ghost/map.cpp | 96 ++++---- ghost/map.h | 30 +-- ghost/packed.cpp | 40 +-- ghost/replay.cpp | 60 ++--- ghost/replay.h | 26 +- ghost/savegame.h | 8 +- ghost/socket.cpp | 16 +- ghost/statsw3mmd.cpp | 38 +-- ghost/statsw3mmd.h | 20 +- ghost/util.cpp | 8 +- ghost/util.h | 5 +- 49 files changed, 1461 insertions(+), 1452 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index a63564c..c553baf 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -48,7 +48,7 @@ void CBNCSUtilInterface :: Reset( QString userName, QString userPassword ) m_NLS = new NLS( userName, userPassword ); } -bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, BYTEARRAY clientToken, BYTEARRAY serverToken ) +bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, QByteArray clientToken, QByteArray serverToken ) { // set m_EXEVersion, m_EXEVersionHash, m_EXEInfo, m_InfoROC, m_InfoTFT @@ -71,14 +71,14 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr uint32_t EXEVersion; getExeInfo( FileWar3EXE.c_str( ), (char *)&buf, 1024, (uint32_t *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); m_EXEInfo = buf; - m_EXEVersion = UTIL_CreateByteArray( EXEVersion, false ); + m_EXEVersion = UTIL_CreateQByteArray( EXEVersion, false ); uint32_t EXEVersionHash; checkRevisionFlat( valueStringFormula.c_str( ), FileWar3EXE.c_str( ), FileStormDLL.c_str( ), FileGameDLL.c_str( ), extractMPQNumber( mpqFileName.c_str( ) ), (unsigned long *)&EXEVersionHash ); - m_EXEVersionHash = UTIL_CreateByteArray( EXEVersionHash, false ); - m_KeyInfoROC = CreateKeyInfo( keyROC, UTIL_ByteArrayToUInt32( clientToken, false ), UTIL_ByteArrayToUInt32( serverToken, false ) ); + m_EXEVersionHash = UTIL_CreateQByteArray( EXEVersionHash, false ); + m_KeyInfoROC = CreateKeyInfo( keyROC, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); if( TFT ) - m_KeyInfoTFT = CreateKeyInfo( keyTFT, UTIL_ByteArrayToUInt32( clientToken, false ), UTIL_ByteArrayToUInt32( serverToken, false ) ); + m_KeyInfoTFT = CreateKeyInfo( keyTFT, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); if( m_KeyInfoROC.size( ) == 36 && ( !TFT || m_KeyInfoTFT.size( ) == 36 ) ) return true; @@ -113,18 +113,18 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGON( ) char buf[32]; // nls_get_A( (nls_t *)m_nls, buf ); ( (NLS *)m_NLS )->getPublicKey( buf ); - m_ClientKey = UTIL_CreateByteArray( (unsigned char *)buf, 32 ); + m_ClientKey = UTIL_CreateQByteArray( (unsigned char *)buf, 32 ); return true; } -bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY salt, BYTEARRAY serverKey ) +bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray salt, QByteArray serverKey ) { // set m_M1 char buf[20]; // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).c_str( ), QString( salt.begin( ), salt.end( ) ).c_str( ) ); ( (NLS *)m_NLS )->getClientSessionKey( buf, QString( salt.begin( ), salt.end( ) ).c_str( ), QString( serverKey.begin( ), serverKey.end( ) ).c_str( ) ); - m_M1 = UTIL_CreateByteArray( (unsigned char *)buf, 20 ); + m_M1 = UTIL_CreateQByteArray( (unsigned char *)buf, 20 ); return true; } @@ -134,26 +134,26 @@ bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( QString userPassword ) char buf[20]; hashPassword( userPassword.c_str( ), buf ); - m_PvPGNPasswordHash = UTIL_CreateByteArray( (unsigned char *)buf, 20 ); + m_PvPGNPasswordHash = UTIL_CreateQByteArray( (unsigned char *)buf, 20 ); return true; } -BYTEARRAY CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ) +QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; - BYTEARRAY KeyInfo; + QByteArray KeyInfo; CDKeyDecoder Decoder( key.c_str( ), key.size( ) ); if( Decoder.isKeyValid( ) ) { - UTIL_AppendByteArray( KeyInfo, UTIL_CreateByteArray( (uint32_t)key.size( ), false ) ); - UTIL_AppendByteArray( KeyInfo, UTIL_CreateByteArray( Decoder.getProduct( ), false ) ); - UTIL_AppendByteArray( KeyInfo, UTIL_CreateByteArray( Decoder.getVal1( ), false ) ); - UTIL_AppendByteArray( KeyInfo, UTIL_CreateByteArray( Zeros, 4 ) ); + UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( (uint32_t)key.size( ), false ) ); + UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Decoder.getProduct( ), false ) ); + UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Decoder.getVal1( ), false ) ); + UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Zeros, 4 ) ); size_t Length = Decoder.calculateHash( clientToken, serverToken ); char *buf = new char[Length]; Length = Decoder.getHash( buf ); - UTIL_AppendByteArray( KeyInfo, UTIL_CreateByteArray( (unsigned char *)buf, Length ) ); + UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( (unsigned char *)buf, Length ) ); delete [] buf; } diff --git a/ghost/bncsutilinterface.h b/ghost/bncsutilinterface.h index be6753d..d47c1af 100644 --- a/ghost/bncsutilinterface.h +++ b/ghost/bncsutilinterface.h @@ -29,40 +29,40 @@ class CBNCSUtilInterface { private: void *m_NLS; - BYTEARRAY m_EXEVersion; // set in HELP_SID_AUTH_CHECK - BYTEARRAY m_EXEVersionHash; // set in HELP_SID_AUTH_CHECK + QByteArray m_EXEVersion; // set in HELP_SID_AUTH_CHECK + QByteArray m_EXEVersionHash; // set in HELP_SID_AUTH_CHECK QString m_EXEInfo; // set in HELP_SID_AUTH_CHECK - BYTEARRAY m_KeyInfoROC; // set in HELP_SID_AUTH_CHECK - BYTEARRAY m_KeyInfoTFT; // set in HELP_SID_AUTH_CHECK - BYTEARRAY m_ClientKey; // set in HELP_SID_AUTH_ACCOUNTLOGON - BYTEARRAY m_M1; // set in HELP_SID_AUTH_ACCOUNTLOGONPROOF - BYTEARRAY m_PvPGNPasswordHash; // set in HELP_PvPGNPasswordHash + QByteArray m_KeyInfoROC; // set in HELP_SID_AUTH_CHECK + QByteArray m_KeyInfoTFT; // set in HELP_SID_AUTH_CHECK + QByteArray m_ClientKey; // set in HELP_SID_AUTH_ACCOUNTLOGON + QByteArray m_M1; // set in HELP_SID_AUTH_ACCOUNTLOGONPROOF + QByteArray m_PvPGNPasswordHash; // set in HELP_PvPGNPasswordHash public: CBNCSUtilInterface( QString userName, QString userPassword ); ~CBNCSUtilInterface( ); - BYTEARRAY GetEXEVersion( ) { return m_EXEVersion; } - BYTEARRAY GetEXEVersionHash( ) { return m_EXEVersionHash; } + QByteArray GetEXEVersion( ) { return m_EXEVersion; } + QByteArray GetEXEVersionHash( ) { return m_EXEVersionHash; } QString GetEXEInfo( ) { return m_EXEInfo; } - BYTEARRAY GetKeyInfoROC( ) { return m_KeyInfoROC; } - BYTEARRAY GetKeyInfoTFT( ) { return m_KeyInfoTFT; } - BYTEARRAY GetClientKey( ) { return m_ClientKey; } - BYTEARRAY GetM1( ) { return m_M1; } - BYTEARRAY GetPvPGNPasswordHash( ) { return m_PvPGNPasswordHash; } + QByteArray GetKeyInfoROC( ) { return m_KeyInfoROC; } + QByteArray GetKeyInfoTFT( ) { return m_KeyInfoTFT; } + QByteArray GetClientKey( ) { return m_ClientKey; } + QByteArray GetM1( ) { return m_M1; } + QByteArray GetPvPGNPasswordHash( ) { return m_PvPGNPasswordHash; } - void SetEXEVersion( BYTEARRAY &nEXEVersion ) { m_EXEVersion = nEXEVersion; } - void SetEXEVersionHash( BYTEARRAY &nEXEVersionHash ) { m_EXEVersionHash = nEXEVersionHash; } + void SetEXEVersion( QByteArray &nEXEVersion ) { m_EXEVersion = nEXEVersion; } + void SetEXEVersionHash( QByteArray &nEXEVersionHash ) { m_EXEVersionHash = nEXEVersionHash; } void Reset( QString userName, QString userPassword ); - bool HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, BYTEARRAY clientToken, BYTEARRAY serverToken ); + bool HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, QByteArray clientToken, QByteArray serverToken ); bool HELP_SID_AUTH_ACCOUNTLOGON( ); - bool HELP_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY salt, BYTEARRAY serverKey ); + bool HELP_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray salt, QByteArray serverKey ); bool HELP_PvPGNPasswordHash( QString userPassword ); private: - BYTEARRAY CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ); + QByteArray CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ); }; #endif diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 1c6cc87..1f27f6f 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -44,7 +44,7 @@ using namespace boost :: filesystem; // CBNET // -CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, BYTEARRAY nEXEVersion, BYTEARRAY nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ) +CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ) { // todotodo: append path seperator to Warcraft3Path if needed @@ -60,7 +60,7 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n QString LowerServer = m_Server; transform( LowerServer.begin( ), LowerServer.end( ), LowerServer.begin( ), (int(*)(int))tolower ); - if( !nServerAlias.empty( ) ) + if( !nServerAlias.isEmpty( ) ) m_ServerAlias = nServerAlias; else if( LowerServer == "useast.battle.net" ) m_ServerAlias = "USEast"; @@ -73,7 +73,7 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n else m_ServerAlias = m_Server; - if( nPasswordHashType == "pvpgn" && !nBNLSServer.empty( ) ) + if( nPasswordHashType == "pvpgn" && !nBNLSServer.isEmpty( ) ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] pvpgn connection found with a configured BNLS server, ignoring BNLS server" ); nBNLSServer.clear( ); @@ -138,42 +138,42 @@ CBNET :: ~CBNET( ) delete m_Protocol; delete m_BNLSClient; - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { delete m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); } delete m_BNCSUtil; - for( vector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) + for( QVector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) delete *i; - for( vector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) + for( QVector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) delete *i; - for( vector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) + for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) + for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) + for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) + for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) + for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); if( m_CallableAdminList ) @@ -182,11 +182,11 @@ CBNET :: ~CBNET( ) if( m_CallableBanList ) m_GHost->m_Callables.push_back( m_CallableBanList ); - for( vector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) delete *i; } -BYTEARRAY CBNET :: GetUniqueName( ) +QByteArray CBNET :: GetUniqueName( ) { return m_Protocol->GetUniqueName( ); } @@ -213,18 +213,18 @@ bool CBNET :: Update( void *fd, void *send_fd ) // update callables // - for( vector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) + for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) { if( i->second->GetReady( ) ) { uint32_t Count = i->second->GetResult( ); if( Count == 0 ) - QueueChatCommand( m_GHost->m_Language->ThereAreNoAdmins( m_Server ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereAreNoAdmins( m_Server ), i->first, !i->first.isEmpty( ) ); else if( Count == 1 ) - QueueChatCommand( m_GHost->m_Language->ThereIsAdmin( m_Server ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereIsAdmin( m_Server ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->ThereAreAdmins( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereAreAdmins( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -234,17 +234,17 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) + for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { AddAdmin( i->second->GetUser( ) ); - QueueChatCommand( m_GHost->m_Language->AddedUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->AddedUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorAddingUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ErrorAddingUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -254,17 +254,17 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) + for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { RemoveAdmin( i->second->GetUser( ) ); - QueueChatCommand( m_GHost->m_Language->DeletedUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->DeletedUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorDeletingUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ErrorDeletingUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -274,18 +274,18 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) + for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) { if( i->second->GetReady( ) ) { uint32_t Count = i->second->GetResult( ); if( Count == 0 ) - QueueChatCommand( m_GHost->m_Language->ThereAreNoBannedUsers( m_Server ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereAreNoBannedUsers( m_Server ), i->first, !i->first.isEmpty( ) ); else if( Count == 1 ) - QueueChatCommand( m_GHost->m_Language->ThereIsBannedUser( m_Server ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereIsBannedUser( m_Server ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->ThereAreBannedUsers( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereAreBannedUsers( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -295,17 +295,17 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) + for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); - QueueChatCommand( m_GHost->m_Language->BannedUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->BannedUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -315,17 +315,17 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) + for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { RemoveBan( i->second->GetUser( ) ); - QueueChatCommand( m_GHost->m_Language->UnbannedUser( i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->UnbannedUser( i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorUnbanningUser( i->second->GetUser( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->ErrorUnbanningUser( i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -335,16 +335,16 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) + for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) { if( i->second->GetReady( ) ) { CDBGamePlayerSummary *GamePlayerSummary = i->second->GetResult( ); if( GamePlayerSummary ) - QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), UTIL_ToString( GamePlayerSummary->GetTotalGames( ) ), UTIL_ToString( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 2 ), UTIL_ToString( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), UTIL_ToString( GamePlayerSummary->GetTotalGames( ) ), UTIL_ToString( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 2 ), UTIL_ToString( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -354,7 +354,7 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) + for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -385,10 +385,10 @@ bool CBNET :: Update( void *fd, void *send_fd ) UTIL_ToString( DotAPlayerSummary->GetAvgRaxKills( ), 2 ), UTIL_ToString( DotAPlayerSummary->GetAvgCourierKills( ), 2 ) ); - QueueChatCommand( Summary, i->first, !i->first.empty( ) ); + QueueChatCommand( Summary, i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.empty( ) ); + QueueChatCommand( m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -422,7 +422,7 @@ bool CBNET :: Update( void *fd, void *send_fd ) { // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed ban list (" + UTIL_ToString( m_Bans.size( ) ) + " -> " + UTIL_ToString( m_CallableBanList->GetResult( ).size( ) ) + " bans)" ); - for( vector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) delete *i; m_Bans = m_CallableBanList->GetResult( ); @@ -496,9 +496,9 @@ bool CBNET :: Update( void *fd, void *send_fd ) } else { - BYTEARRAY WardenResponse = m_BNLSClient->GetWardenResponse( ); + QByteArray WardenResponse = m_BNLSClient->GetWardenResponse( ); - if( !WardenResponse.empty( ) ) + if( !WardenResponse.isEmpty( ) ) m_Socket->PutBytes( m_Protocol->SEND_SID_WARDEN( WardenResponse ) ); } } @@ -515,14 +515,14 @@ bool CBNET :: Update( void *fd, void *send_fd ) else WaitTicks = 4000; - if( !m_OutPackets.empty( ) && GetTicks( ) - m_LastOutPacketTicks >= WaitTicks ) + if( !m_OutPackets.isEmpty( ) && GetTicks( ) - m_LastOutPacketTicks >= WaitTicks ) { if( m_OutPackets.size( ) > 7 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); m_Socket->PutBytes( m_OutPackets.front( ) ); m_LastOutPacketSize = m_OutPackets.front( ).size( ); - m_OutPackets.pop( ); + m_OutPackets.dequeue( ); m_LastOutPacketTicks = GetTicks( ); } @@ -554,8 +554,8 @@ bool CBNET :: Update( void *fd, void *send_fd ) m_LastNullTime = GetTime( ); m_LastOutPacketTicks = GetTicks( ); - while( !m_OutPackets.empty( ) ) - m_OutPackets.pop( ); + while( !m_OutPackets.isEmpty( ) ) + m_OutPackets.dequeue( ); return m_Exiting; } @@ -581,10 +581,10 @@ bool CBNET :: Update( void *fd, void *send_fd ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connecting to server [" + m_Server + "] on port 6112" ); m_GHost->EventBNETConnecting( this ); - if( !m_GHost->m_BindAddress.empty( ) ) + if( !m_GHost->m_BindAddress.isEmpty( ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to bind to address [" + m_GHost->m_BindAddress + "]" ); - if( m_ServerIP.empty( ) ) + if( m_ServerIP.isEmpty( ) ) { m_Socket->Connect( m_GHost->m_BindAddress, m_Server, 6112 ); @@ -615,7 +615,7 @@ void CBNET :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue QString *RecvBuffer = m_Socket->GetBytes( ); - BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -627,15 +627,15 @@ void CBNET :: ExtractPackets( ) { // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 ); + uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); if( Length >= 4 ) { if( Bytes.size( ) >= Length ) { - m_Packets.push( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes[1], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); + m_Packets.enqueue( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes[1], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) ); + Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); } else return; @@ -660,17 +660,17 @@ void CBNET :: ProcessPackets( ) { CIncomingGameHost *GameHost = NULL; CIncomingChatEvent *ChatEvent = NULL; - BYTEARRAY WardenData; - vector Friends; - vector Clans; + QByteArray WardenData; + QVector Friends; + QVector Clans; // process all the received packets in the m_Packets queue // this normally means sending some kind of response - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { CCommandPacket *Packet = m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); if( Packet->GetPacketType( ) == BNET_HEADER_CONSTANT ) { @@ -766,12 +766,12 @@ void CBNET :: ProcessPackets( ) // the Warden seed is the first 4 bytes of the ROC key hash // initialize the Warden handler - if( !m_BNLSServer.empty( ) ) + if( !m_BNLSServer.isEmpty( ) ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] creating BNLS client" ); delete m_BNLSClient; m_BNLSClient = new CBNLSClient( m_BNLSServer, m_BNLSPort, m_BNLSWardenCookie ); - m_BNLSClient->QueueWardenSeed( UTIL_ByteArrayToUInt32( m_BNCSUtil->GetKeyInfoROC( ), false, 16 ) ); + m_BNLSClient->QueueWardenSeed( UTIL_QByteArrayToUInt32( m_BNCSUtil->GetKeyInfoROC( ), false, 16 ) ); } } else @@ -798,7 +798,7 @@ void CBNET :: ProcessPackets( ) { // cd keys not accepted - switch( UTIL_ByteArrayToUInt32( m_Protocol->GetKeyState( ), false ) ) + switch( UTIL_QByteArrayToUInt32( m_Protocol->GetKeyState( ), false ) ) { case CBNETProtocol :: KR_ROC_KEY_IN_USE: CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - ROC CD key in use by user [" + m_Protocol->GetKeyStateDescription( ) + "], disconnecting" ); @@ -903,16 +903,16 @@ void CBNET :: ProcessPackets( ) case CBNETProtocol :: SID_FRIENDSLIST: Friends = m_Protocol->RECEIVE_SID_FRIENDSLIST( Packet->GetData( ) ); - for( vector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) + for( QVector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) delete *i; m_Friends = Friends; break; case CBNETProtocol :: SID_CLANMEMBERLIST: - vector Clans = m_Protocol->RECEIVE_SID_CLANMEMBERLIST( Packet->GetData( ) ); + QVector Clans = m_Protocol->RECEIVE_SID_CLANMEMBERLIST( Packet->GetData( ) ); - for( vector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) + for( QVector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) delete *i; m_Clans = Clans; @@ -962,7 +962,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // the equivalent pvpgn message is: [PvPGN Realm] Your friend abc has entered a Warcraft III Frozen Throne game named "xyz". - vector Tokens = UTIL_Tokenize( Message, ' ' ); + QVector Tokens = UTIL_Tokenize( Message, ' ' ); if( Tokens.size( ) >= 3 ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, Tokens[2], false ); @@ -976,7 +976,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Message == "?trigger" && ( IsAdmin( User ) || IsRootAdmin( User ) || ( m_PublicCommands && m_OutPackets.size( ) <= 3 ) ) ) QueueChatCommand( m_GHost->m_Language->CommandTrigger( QString( 1, m_CommandTrigger ) ), User, Whisper ); - else if( !Message.empty( ) && Message[0] == m_CommandTrigger ) + else if( !Message.isEmpty( ) && Message[0] == m_CommandTrigger ) { // extract the command trigger, the command, and the payload // e.g. "!say hello world" -> command: "say", payload: "hello world" @@ -987,11 +987,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( PayloadStart != QString :: npos ) { - Command = Message.substr( 1, PayloadStart - 1 ); - Payload = Message.substr( PayloadStart + 1 ); + Command = Message.mid( 1, PayloadStart - 1 ); + Payload = Message.mid( PayloadStart + 1 ); } else - Command = Message.substr( 1 ); + Command = Message.mid( 1 ); transform( Command.begin( ), Command.end( ), Command.begin( ), (int(*)(int))tolower ); @@ -1007,7 +1007,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !ADDADMIN // - if( Command == "addadmin" && !Payload.empty( ) ) + if( Command == "addadmin" && !Payload.isEmpty( ) ) { if( IsRootAdmin( User ) ) { @@ -1025,7 +1025,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !BAN // - if( ( Command == "addban" || Command == "ban" ) && !Payload.empty( ) ) + if( ( Command == "addban" || Command == "ban" ) && !Payload.isEmpty( ) ) { // extract the victim and the reason // e.g. "Varlock leaver after dying" -> victim: "Varlock", reason: "leaver after dying" @@ -1042,7 +1042,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString :: size_type Start = Reason.find_first_not_of( " " ); if( Start != QString :: npos ) - Reason = Reason.substr( Start ); + Reason = Reason.mid( Start ); } if( IsBannedName( Victim ) ) @@ -1057,7 +1057,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "announce" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { QueueChatCommand( m_GHost->m_Language->AnnounceMessageDisabled( ), User, Whisper ); m_GHost->m_CurrentGame->SetAnnounce( 0, QString( ) ); @@ -1085,7 +1085,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString :: size_type Start = Message.find_first_not_of( " " ); if( Start != QString :: npos ) - Message = Message.substr( Start ); + Message = Message.mid( Start ); QueueChatCommand( m_GHost->m_Language->AnnounceMessageEnabled( ), User, Whisper ); m_GHost->m_CurrentGame->SetAnnounce( Interval, Message ); @@ -1102,7 +1102,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( IsRootAdmin( User ) ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { QueueChatCommand( m_GHost->m_Language->AutoHostDisabled( ), User, Whisper ); m_GHost->m_AutoHostGameName.clear( ); @@ -1145,7 +1145,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString :: size_type Start = GameName.find_first_not_of( " " ); if( Start != QString :: npos ) - GameName = GameName.substr( Start ); + GameName = GameName.mid( Start ); QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); delete m_GHost->m_AutoHostMap; @@ -1176,7 +1176,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( IsRootAdmin( User ) ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { QueueChatCommand( m_GHost->m_Language->AutoHostDisabled( ), User, Whisper ); m_GHost->m_AutoHostGameName.clear( ); @@ -1233,7 +1233,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString :: size_type Start = GameName.find_first_not_of( " " ); if( Start != QString :: npos ) - GameName = GameName.substr( Start ); + GameName = GameName.mid( Start ); QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); delete m_GHost->m_AutoHostMap; @@ -1264,7 +1264,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "autostart" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { QueueChatCommand( m_GHost->m_Language->AutoStartDisabled( ), User, Whisper ); m_GHost->m_CurrentGame->SetAutoStartPlayers( 0 ); @@ -1285,14 +1285,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !CHANNEL (change channel) // - if( Command == "channel" && !Payload.empty( ) ) + if( Command == "channel" && !Payload.isEmpty( ) ) QueueChatCommand( "/join " + Payload ); // // !CHECKADMIN // - if( Command == "checkadmin" && !Payload.empty( ) ) + if( Command == "checkadmin" && !Payload.isEmpty( ) ) { if( IsRootAdmin( User ) ) { @@ -1309,7 +1309,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !CHECKBAN // - if( Command == "checkban" && !Payload.empty( ) ) + if( Command == "checkban" && !Payload.isEmpty( ) ) { CDBBan *Ban = IsBannedName( Payload ); @@ -1323,7 +1323,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !CLOSE (close slot) // - if( Command == "close" && !Payload.empty( ) && m_GHost->m_CurrentGame ) + if( Command == "close" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) { if( !m_GHost->m_CurrentGame->GetLocked( ) ) { @@ -1392,7 +1392,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !DELADMIN // - if( Command == "deladmin" && !Payload.empty( ) ) + if( Command == "deladmin" && !Payload.isEmpty( ) ) { if( IsRootAdmin( User ) ) { @@ -1410,7 +1410,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !UNBAN // - if( ( Command == "delban" || Command == "unban" ) && !Payload.empty( ) ) + if( ( Command == "delban" || Command == "unban" ) && !Payload.isEmpty( ) ) m_PairedBanRemoves.push_back( PairedBanRemove( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedBanRemove( Payload ) ) ); // @@ -1432,7 +1432,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !DOWNLOADS // - if( Command == "downloads" && !Payload.empty( ) ) + if( Command == "downloads" && !Payload.isEmpty( ) ) { uint32_t Downloads = UTIL_ToUInt32( Payload ); @@ -1472,7 +1472,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !END // - if( Command == "end" && !Payload.empty( ) ) + if( Command == "end" && !Payload.isEmpty( ) ) { // todotodo: what if a game ends just as you're typing this command and the numbering changes? @@ -1499,7 +1499,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !ENFORCESG // - if( Command == "enforcesg" && !Payload.empty( ) ) + if( Command == "enforcesg" && !Payload.isEmpty( ) ) { // only load files in the current directory just to be safe @@ -1538,7 +1538,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_Exiting = true; else { - if( m_GHost->m_CurrentGame || !m_GHost->m_Games.empty( ) ) + if( m_GHost->m_CurrentGame || !m_GHost->m_Games.isEmpty( ) ) QueueChatCommand( m_GHost->m_Language->AtLeastOneGameActiveUseForceToShutdown( ), User, Whisper ); else m_Exiting = true; @@ -1572,7 +1572,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !GETGAME // - if( Command == "getgame" && !Payload.empty( ) ) + if( Command == "getgame" && !Payload.isEmpty( ) ) { uint32_t GameNumber = UTIL_ToUInt32( Payload ) - 1; @@ -1598,7 +1598,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !HOLD (hold a slot for someone) // - if( Command == "hold" && !Payload.empty( ) && m_GHost->m_CurrentGame ) + if( Command == "hold" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" @@ -1627,7 +1627,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !HOSTSG // - if( Command == "hostsg" && !Payload.empty( ) ) + if( Command == "hostsg" && !Payload.isEmpty( ) ) m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, true, Payload, User, User, m_Server, Whisper ); // @@ -1636,7 +1636,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "load" ) { - if( Payload.empty( ) ) + if( Payload.isEmpty( ) ) QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); else { @@ -1671,7 +1671,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) LastMatch = i->path( ); Matches++; - if( FoundMapConfigs.empty( ) ) + if( FoundMapConfigs.isEmpty( ) ) FoundMapConfigs = i->filename( ); else FoundMapConfigs += ", " + i->filename( ); @@ -1712,7 +1712,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !LOADSG // - if( Command == "loadsg" && !Payload.empty( ) ) + if( Command == "loadsg" && !Payload.isEmpty( ) ) { // only load files in the current directory just to be safe @@ -1747,7 +1747,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "map" ) { - if( Payload.empty( ) ) + if( Payload.isEmpty( ) ) QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); else { @@ -1782,7 +1782,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) LastMatch = i->path( ); Matches++; - if( FoundMaps.empty( ) ) + if( FoundMaps.isEmpty( ) ) FoundMaps = i->filename( ); else FoundMaps += ", " + i->filename( ); @@ -1827,7 +1827,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !OPEN (open slot) // - if( Command == "open" && !Payload.empty( ) && m_GHost->m_CurrentGame ) + if( Command == "open" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) { if( !m_GHost->m_CurrentGame->GetLocked( ) ) { @@ -1870,14 +1870,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !PRIV (host private game) // - if( Command == "priv" && !Payload.empty( ) ) + if( Command == "priv" && !Payload.isEmpty( ) ) m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, Payload, User, User, m_Server, Whisper ); // // !PRIVBY (host private game by other player) // - if( Command == "privby" && !Payload.empty( ) ) + if( Command == "privby" && !Payload.isEmpty( ) ) { // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" @@ -1888,8 +1888,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( GameNameStart != QString :: npos ) { - Owner = Payload.substr( 0, GameNameStart ); - GameName = Payload.substr( GameNameStart + 1 ); + Owner = Payload.mid( 0, GameNameStart ); + GameName = Payload.mid( GameNameStart + 1 ); m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, GameName, Owner, User, m_Server, Whisper ); } } @@ -1898,14 +1898,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !PUB (host public game) // - if( Command == "pub" && !Payload.empty( ) ) + if( Command == "pub" && !Payload.isEmpty( ) ) m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, Payload, User, User, m_Server, Whisper ); // // !PUBBY (host public game by other player) // - if( Command == "pubby" && !Payload.empty( ) ) + if( Command == "pubby" && !Payload.isEmpty( ) ) { // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" @@ -1916,8 +1916,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( GameNameStart != QString :: npos ) { - Owner = Payload.substr( 0, GameNameStart ); - GameName = Payload.substr( GameNameStart + 1 ); + Owner = Payload.mid( 0, GameNameStart ); + GameName = Payload.mid( GameNameStart + 1 ); m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, GameName, Owner, User, m_Server, Whisper ); } } @@ -1941,14 +1941,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !SAY // - if( Command == "say" && !Payload.empty( ) ) + if( Command == "say" && !Payload.isEmpty( ) ) QueueChatCommand( Payload ); // // !SAYGAME // - if( Command == "saygame" && !Payload.empty( ) ) + if( Command == "saygame" && !Payload.isEmpty( ) ) { if( IsRootAdmin( User ) ) { @@ -1973,7 +1973,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString :: size_type Start = Message.find_first_not_of( " " ); if( Start != QString :: npos ) - Message = Message.substr( Start ); + Message = Message.mid( Start ); if( GameNumber - 1 < m_GHost->m_Games.size( ) ) m_GHost->m_Games[GameNumber - 1]->SendAllChat( "ADMIN: " + Message ); @@ -1990,14 +1990,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !SAYGAMES // - if( Command == "saygames" && !Payload.empty( ) ) + if( Command == "saygames" && !Payload.isEmpty( ) ) { if( IsRootAdmin( User ) ) { if( m_GHost->m_CurrentGame ) m_GHost->m_CurrentGame->SendAllChat( Payload ); - for( vector :: iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) (*i)->SendAllChat( "ADMIN: " + Payload ); } else @@ -2043,7 +2043,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !SWAP (swap slots) // - if( Command == "swap" && !Payload.empty( ) && m_GHost->m_CurrentGame ) + if( Command == "swap" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) { if( !m_GHost->m_CurrentGame->GetLocked( ) ) { @@ -2133,12 +2133,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { QString StatsUser = User; - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) StatsUser = Payload; // check for potential abuse - if( !StatsUser.empty( ) && StatsUser.size( ) < 16 && StatsUser[0] != '/' ) + if( !StatsUser.isEmpty( ) && StatsUser.size( ) < 16 && StatsUser[0] != '/' ) m_PairedGPSChecks.push_back( PairedGPSCheck( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedGamePlayerSummaryCheck( StatsUser ) ) ); } @@ -2150,12 +2150,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { QString StatsUser = User; - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) StatsUser = Payload; // check for potential abuse - if( !StatsUser.empty( ) && StatsUser.size( ) < 16 && StatsUser[0] != '/' ) + if( !StatsUser.isEmpty( ) && StatsUser.size( ) < 16 && StatsUser[0] != '/' ) m_PairedDPSChecks.push_back( PairedDPSCheck( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedDotAPlayerSummaryCheck( StatsUser ) ) ); } @@ -2191,9 +2191,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString :: size_type Split = Message.find( " " ); if( Split != QString :: npos ) - UserName = Message.substr( 0, Split ); + UserName = Message.mid( 0, Split ); else - UserName = Message.substr( 0 ); + UserName = Message.mid( 0 ); // handle spoof checking for current game // this case covers whois results which are used when hosting a public game (we send out a "/whois [player]" for each player) @@ -2257,35 +2257,35 @@ void CBNET :: SendGetClanList( ) void CBNET :: QueueEnterChat( ) { if( m_LoggedIn ) - m_OutPackets.push( m_Protocol->SEND_SID_ENTERCHAT( ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_ENTERCHAT( ) ); } void CBNET :: QueueChatCommand( QString chatCommand ) { - if( chatCommand.empty( ) ) + if( chatCommand.isEmpty( ) ) return; if( m_LoggedIn ) { if( m_PasswordHashType == "pvpgn" && chatCommand.size( ) > m_MaxMessageLength ) - chatCommand = chatCommand.substr( 0, m_MaxMessageLength ); + chatCommand = chatCommand.mid( 0, m_MaxMessageLength ); if( chatCommand.size( ) > 255 ) - chatCommand = chatCommand.substr( 0, 255 ); + chatCommand = chatCommand.mid( 0, 255 ); if( m_OutPackets.size( ) > 10 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + UTIL_ToString( m_OutPackets.size( ) ) + ") packets queued, discarding" ); else { CONSOLE_Print( "[QUEUED: " + m_ServerAlias + "] " + chatCommand ); - m_OutPackets.push( m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ) ); } } } void CBNET :: QueueChatCommand( QString chatCommand, QString user, bool whisper ) { - if( chatCommand.empty( ) ) + if( chatCommand.isEmpty( ) ) return; // if whisper is true send the chat command as a whisper to user, otherwise just queue the chat command @@ -2300,7 +2300,7 @@ void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString ho { if( m_LoggedIn && map ) { - if( !m_CurrentChannel.empty( ) ) + if( !m_CurrentChannel.isEmpty( ) ) m_FirstChannel = m_CurrentChannel; m_InChat = false; @@ -2313,9 +2313,9 @@ void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString ho void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ) { - if( hostName.empty( ) ) + if( hostName.isEmpty( ) ) { - BYTEARRAY UniqueName = m_Protocol->GetUniqueName( ); + QByteArray UniqueName = m_Protocol->GetUniqueName( ); hostName = QString( UniqueName.begin( ), UniqueName.end( ) ); } @@ -2341,17 +2341,17 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h // use an invalid map width/height to indicate reconnectable games - BYTEARRAY MapWidth; + QByteArray MapWidth; MapWidth.push_back( 192 ); MapWidth.push_back( 7 ); - BYTEARRAY MapHeight; + QByteArray MapHeight; MapHeight.push_back( 192 ); MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.push( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateByteArray( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.push( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateByteArray( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateByteArray( (uint16_t)0, false ), UTIL_CreateByteArray( (uint16_t)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateQByteArray( (uint16_t)0, false ), UTIL_CreateQByteArray( (uint16_t)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); } else { @@ -2363,17 +2363,17 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h // use an invalid map width/height to indicate reconnectable games - BYTEARRAY MapWidth; + QByteArray MapWidth; MapWidth.push_back( 192 ); MapWidth.push_back( 7 ); - BYTEARRAY MapHeight; + QByteArray MapHeight; MapHeight.push_back( 192 ); MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.push( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateByteArray( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.push( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateByteArray( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); } } } @@ -2381,25 +2381,25 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h void CBNET :: QueueGameUncreate( ) { if( m_LoggedIn ) - m_OutPackets.push( m_Protocol->SEND_SID_STOPADV( ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STOPADV( ) ); } void CBNET :: UnqueuePackets( unsigned char type ) { - queue Packets; + QQueue Packets; uint32_t Unqueued = 0; - while( !m_OutPackets.empty( ) ) + while( !m_OutPackets.isEmpty( ) ) { // todotodo: it's very inefficient to have to copy all these packets while searching the queue - BYTEARRAY Packet = m_OutPackets.front( ); - m_OutPackets.pop( ); + QByteArray Packet = m_OutPackets.front( ); + m_OutPackets.dequeue( ); if( Packet.size( ) >= 2 && Packet[1] == type ) Unqueued++; else - Packets.push( Packet ); + Packets.enqueue( Packet ); } m_OutPackets = Packets; @@ -2414,21 +2414,21 @@ void CBNET :: UnqueueChatCommand( QString chatCommand ) // generate the packet that would be sent for this chat command // then search the queue for that exact packet - BYTEARRAY PacketToUnqueue = m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ); - queue Packets; + QByteArray PacketToUnqueue = m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ); + QQueue Packets; uint32_t Unqueued = 0; - while( !m_OutPackets.empty( ) ) + while( !m_OutPackets.isEmpty( ) ) { // todotodo: it's very inefficient to have to copy all these packets while searching the queue - BYTEARRAY Packet = m_OutPackets.front( ); - m_OutPackets.pop( ); + QByteArray Packet = m_OutPackets.front( ); + m_OutPackets.dequeue( ); if( Packet == PacketToUnqueue ) Unqueued++; else - Packets.push( Packet ); + Packets.enqueue( Packet ); } m_OutPackets = Packets; @@ -2446,7 +2446,7 @@ bool CBNET :: IsAdmin( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) + for( QVector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) { if( *i == name ) return true; @@ -2486,7 +2486,7 @@ CDBBan *CBNET :: IsBannedName( QString name ) // todotodo: optimize this - maybe use a map? - for( vector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) { if( (*i)->GetName( ) == name ) return *i; @@ -2499,7 +2499,7 @@ CDBBan *CBNET :: IsBannedIP( QString ip ) { // todotodo: optimize this - maybe use a map? - for( vector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) { if( (*i)->GetIP( ) == ip ) return *i; @@ -2524,7 +2524,7 @@ void CBNET :: RemoveAdmin( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) + for( QVector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) { if( *i == name ) i = m_Admins.erase( i ); @@ -2537,7 +2537,7 @@ void CBNET :: RemoveBan( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); ) + for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); ) { if( (*i)->GetName( ) == name ) i = m_Bans.erase( i ); @@ -2550,7 +2550,7 @@ void CBNET :: HoldFriends( CBaseGame *game ) { if( game ) { - for( vector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) + for( QVector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) game->AddToReserved( (*i)->GetAccount( ) ); } } @@ -2559,7 +2559,7 @@ void CBNET :: HoldClan( CBaseGame *game ) { if( game ) { - for( vector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) + for( QVector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) game->AddToReserved( (*i)->GetName( ) ); } } diff --git a/ghost/bnet.h b/ghost/bnet.h index 488afbb..1d85415 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -63,23 +63,23 @@ class CBNET CTCPClient *m_Socket; // the connection to battle.net CBNETProtocol *m_Protocol; // battle.net protocol CBNLSClient *m_BNLSClient; // the BNLS client (for external warden handling) - queue m_Packets; // queue of incoming packets + QQueue m_Packets; // queue of incoming packets CBNCSUtilInterface *m_BNCSUtil; // the interface to the bncsutil library (used for logging into battle.net) - queue m_OutPackets; // queue of outgoing packets to be sent (to prevent getting kicked for flooding) - vector m_Friends; // vector of friends - vector m_Clans; // vector of clan members - vector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress - vector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress - vector m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress - vector m_PairedBanCounts; // vector of paired threaded database ban counts in progress - vector m_PairedBanAdds; // vector of paired threaded database ban adds in progress - vector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress - vector m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress - vector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress + QQueue m_OutPackets; // queue of outgoing packets to be sent (to prevent getting kicked for flooding) + QVector m_Friends; // vector of friends + QVector m_Clans; // vector of clan members + QVector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress + QVector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress + QVector m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress + QVector m_PairedBanCounts; // vector of paired threaded database ban counts in progress + QVector m_PairedBanAdds; // vector of paired threaded database ban adds in progress + QVector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress + QVector m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress + QVector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress CCallableAdminList *m_CallableAdminList; // threaded database admin list in progress CCallableBanList *m_CallableBanList; // threaded database ban list in progress - vector m_Admins; // vector of cached admins - vector m_Bans; // vector of cached bans + QVector m_Admins; // vector of cached admins + QVector m_Bans; // vector of cached bans bool m_Exiting; // set to true and this class will be deleted next update string m_Server; // battle.net server to connect to string m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) @@ -99,8 +99,8 @@ class CBNET string m_RootAdmin; // the root admin char m_CommandTrigger; // the character prefix to identify commands unsigned char m_War3Version; // custom warcraft 3 version for PvPGN users - BYTEARRAY m_EXEVersion; // custom exe version for PvPGN users - BYTEARRAY m_EXEVersionHash; // custom exe version hash for PvPGN users + QByteArray m_EXEVersion; // custom exe version for PvPGN users + QByteArray m_EXEVersionHash; // custom exe version hash for PvPGN users string m_PasswordHashType; // password hash type for PvPGN users string m_PVPGNRealmName; // realm name for PvPGN users (for mutual friend spoofchecks) uint32_t m_MaxMessageLength; // maximum message length for PvPGN users @@ -121,7 +121,7 @@ class CBNET bool m_PublicCommands; // whether to allow public commands or not public: - CBNET( CGHost *nGHost, string nServer, string nServerAlias, string nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, uint32_t nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, BYTEARRAY nEXEVersion, BYTEARRAY nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ); + CBNET( CGHost *nGHost, string nServer, string nServerAlias, string nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, uint32_t nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ); ~CBNET( ); bool GetExiting( ) { return m_Exiting; } @@ -135,8 +135,8 @@ class CBNET string GetCurrentChannel( ) { return m_CurrentChannel; } string GetRootAdmin( ) { return m_RootAdmin; } char GetCommandTrigger( ) { return m_CommandTrigger; } - BYTEARRAY GetEXEVersion( ) { return m_EXEVersion; } - BYTEARRAY GetEXEVersionHash( ) { return m_EXEVersionHash; } + QByteArray GetEXEVersion( ) { return m_EXEVersion; } + QByteArray GetEXEVersionHash( ) { return m_EXEVersionHash; } string GetPasswordHashType( ) { return m_PasswordHashType; } string GetPVPGNRealmName( ) { return m_PVPGNRealmName; } uint32_t GetHostCounterID( ) { return m_HostCounterID; } @@ -146,7 +146,7 @@ class CBNET bool GetHoldClan( ) { return m_HoldClan; } bool GetPublicCommands( ) { return m_PublicCommands; } uint32_t GetOutPacketsQueued( ) { return m_OutPackets.size( ); } - BYTEARRAY GetUniqueName( ); + QByteArray GetUniqueName( ); // processing functions diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 0b4d9fd..31f561a 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -25,7 +25,7 @@ CBNETProtocol :: CBNETProtocol( ) { unsigned char ClientToken[] = { 220, 1, 203, 7 }; - m_ClientToken = UTIL_CreateByteArray( ClientToken, 4 ); + m_ClientToken = UTIL_CreateQByteArray( ClientToken, 4 ); } CBNETProtocol :: ~CBNETProtocol( ) @@ -37,7 +37,7 @@ CBNETProtocol :: ~CBNETProtocol( ) // RECEIVE FUNCTIONS // /////////////////////// -bool CBNETProtocol :: RECEIVE_SID_NULL( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_NULL( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_NULL" ); // DEBUG_Print( data ); @@ -48,7 +48,7 @@ bool CBNETProtocol :: RECEIVE_SID_NULL( BYTEARRAY data ) return ValidateLength( data ); } -CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data ) +CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_GETADVLISTEX" ); // DEBUG_Print( data ); @@ -66,23 +66,23 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - BYTEARRAY GamesFound = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray GamesFound = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - if( UTIL_ByteArrayToUInt32( GamesFound, false ) > 0 && data.size( ) >= 25 ) + if( UTIL_QByteArrayToUInt32( GamesFound, false ) > 0 && data.size( ) >= 25 ) { - BYTEARRAY Port = BYTEARRAY( data.begin( ) + 18, data.begin( ) + 20 ); - BYTEARRAY IP = BYTEARRAY( data.begin( ) + 20, data.begin( ) + 24 ); - BYTEARRAY GameName = UTIL_ExtractCString( data, 24 ); + QByteArray Port = QByteArray( data.begin( ) + 18, data.begin( ) + 20 ); + QByteArray IP = QByteArray( data.begin( ) + 20, data.begin( ) + 24 ); + QByteArray GameName = UTIL_ExtractCString( data, 24 ); if( data.size( ) >= GameName.size( ) + 35 ) { - BYTEARRAY HostCounter; + QByteArray HostCounter; HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 27, true ) ); HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 29, true ) ); HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 31, true ) ); HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 33, true ) ); return new CIncomingGameHost( IP, - UTIL_ByteArrayToUInt16( Port, false ), + UTIL_QByteArrayToUInt16( Port, false ), QString( GameName.begin( ), GameName.end( ) ), HostCounter ); } @@ -92,7 +92,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( BYTEARRAY data ) return NULL; } -bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_ENTERCHAT" ); // DEBUG_Print( data ); @@ -110,7 +110,7 @@ bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( BYTEARRAY data ) return false; } -CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data ) +CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_CHATEVENT" ); // DEBUG_Print( data ); @@ -126,12 +126,12 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 29 ) { - BYTEARRAY EventID = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); - BYTEARRAY Ping = BYTEARRAY( data.begin( ) + 12, data.begin( ) + 16 ); - BYTEARRAY User = UTIL_ExtractCString( data, 28 ); - BYTEARRAY Message = UTIL_ExtractCString( data, User.size( ) + 29 ); + QByteArray EventID = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Ping = QByteArray( data.begin( ) + 12, data.begin( ) + 16 ); + QByteArray User = UTIL_ExtractCString( data, 28 ); + QByteArray Message = UTIL_ExtractCString( data, User.size( ) + 29 ); - switch( UTIL_ByteArrayToUInt32( EventID, false ) ) + switch( UTIL_QByteArrayToUInt32( EventID, false ) ) { case CBNETProtocol :: EID_SHOWUSER: case CBNETProtocol :: EID_JOIN: @@ -148,8 +148,8 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data ) case CBNETProtocol :: EID_INFO: case CBNETProtocol :: EID_ERROR: case CBNETProtocol :: EID_EMOTE: - return new CIncomingChatEvent( (CBNETProtocol :: IncomingChatEvent)UTIL_ByteArrayToUInt32( EventID, false ), - UTIL_ByteArrayToUInt32( Ping, false ), + return new CIncomingChatEvent( (CBNETProtocol :: IncomingChatEvent)UTIL_QByteArrayToUInt32( EventID, false ), + UTIL_QByteArrayToUInt32( Ping, false ), QString( User.begin( ), User.end( ) ), QString( Message.begin( ), Message.end( ) ) ); } @@ -159,7 +159,7 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( BYTEARRAY data ) return NULL; } -bool CBNETProtocol :: RECEIVE_SID_CHECKAD( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_CHECKAD( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_CHECKAD" ); // DEBUG_Print( data ); @@ -170,7 +170,7 @@ bool CBNETProtocol :: RECEIVE_SID_CHECKAD( BYTEARRAY data ) return ValidateLength( data ); } -bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_STARTADVEX3" ); // DEBUG_Print( data ); @@ -181,16 +181,16 @@ bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - BYTEARRAY Status = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - if( UTIL_ByteArrayToUInt32( Status, false ) == 0 ) + if( UTIL_QByteArrayToUInt32( Status, false ) == 0 ) return true; } return false; } -BYTEARRAY CBNETProtocol :: RECEIVE_SID_PING( BYTEARRAY data ) +QByteArray CBNETProtocol :: RECEIVE_SID_PING( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_PING" ); // DEBUG_Print( data ); @@ -200,12 +200,12 @@ BYTEARRAY CBNETProtocol :: RECEIVE_SID_PING( BYTEARRAY data ) // 4 bytes -> Ping if( ValidateLength( data ) && data.size( ) >= 8 ) - return BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + return QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - return BYTEARRAY( ); + return QByteArray( ); } -bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_LOGONRESPONSE" ); // DEBUG_Print( data ); @@ -216,16 +216,16 @@ bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - BYTEARRAY Status = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - if( UTIL_ByteArrayToUInt32( Status, false ) == 1 ) + if( UTIL_QByteArrayToUInt32( Status, false ) == 1 ) return true; } return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_AUTH_INFO" ); // DEBUG_Print( data ); @@ -241,9 +241,9 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 25 ) { - m_LogonType = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); - m_ServerToken = BYTEARRAY( data.begin( ) + 8, data.begin( ) + 12 ); - m_MPQFileTime = BYTEARRAY( data.begin( ) + 16, data.begin( ) + 24 ); + m_LogonType = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + m_ServerToken = QByteArray( data.begin( ) + 8, data.begin( ) + 12 ); + m_MPQFileTime = QByteArray( data.begin( ) + 16, data.begin( ) + 24 ); m_IX86VerFileName = UTIL_ExtractCString( data, 24 ); m_ValueStringFormula = UTIL_ExtractCString( data, m_IX86VerFileName.size( ) + 25 ); return true; @@ -252,7 +252,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( BYTEARRAY data ) return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_AUTH_CHECK" ); // DEBUG_Print( data ); @@ -264,17 +264,17 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 9 ) { - m_KeyState = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + m_KeyState = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); m_KeyStateDescription = UTIL_ExtractCString( data, 8 ); - if( UTIL_ByteArrayToUInt32( m_KeyState, false ) == KR_GOOD ) + if( UTIL_QByteArrayToUInt32( m_KeyState, false ) == KR_GOOD ) return true; } return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_AUTH_ACCOUNTLOGON" ); // DEBUG_Print( data ); @@ -288,12 +288,12 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - BYTEARRAY status = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - if( UTIL_ByteArrayToUInt32( status, false ) == 0 && data.size( ) >= 72 ) + if( UTIL_QByteArrayToUInt32( status, false ) == 0 && data.size( ) >= 72 ) { - m_Salt = BYTEARRAY( data.begin( ) + 8, data.begin( ) + 40 ); - m_ServerPublicKey = BYTEARRAY( data.begin( ) + 40, data.begin( ) + 72 ); + m_Salt = QByteArray( data.begin( ) + 8, data.begin( ) + 40 ); + m_ServerPublicKey = QByteArray( data.begin( ) + 40, data.begin( ) + 72 ); return true; } } @@ -301,7 +301,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( BYTEARRAY data ) return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_AUTH_ACCOUNTLOGONPROOF" ); // DEBUG_Print( data ); @@ -312,16 +312,16 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - BYTEARRAY Status = BYTEARRAY( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - if( UTIL_ByteArrayToUInt32( Status, false ) == 0 ) + if( UTIL_QByteArrayToUInt32( Status, false ) == 0 ) return true; } return false; } -BYTEARRAY CBNETProtocol :: RECEIVE_SID_WARDEN( BYTEARRAY data ) +QByteArray CBNETProtocol :: RECEIVE_SID_WARDEN( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_WARDEN" ); // DEBUG_PRINT( data ); @@ -331,12 +331,12 @@ BYTEARRAY CBNETProtocol :: RECEIVE_SID_WARDEN( BYTEARRAY data ) // n bytes -> Data if( ValidateLength( data ) && data.size( ) >= 4 ) - return BYTEARRAY( data.begin( ) + 4, data.end( ) ); + return QByteArray( data.begin( ) + 4, data.end( ) ); - return BYTEARRAY( ); + return QByteArray( ); } -vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRAY data ) +QVector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_FRIENDSLIST" ); // DEBUG_Print( data ); @@ -351,7 +351,7 @@ vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRA // 4 bytes -> ??? // null term QString -> Location - vector Friends; + QVector Friends; if( ValidateLength( data ) && data.size( ) >= 5 ) { @@ -365,7 +365,7 @@ vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRA if( data.size( ) < i + 1 ) break; - BYTEARRAY Account = UTIL_ExtractCString( data, i ); + QByteArray Account = UTIL_ExtractCString( data, i ); i += Account.size( ) + 1; if( data.size( ) < i + 7 ) @@ -374,7 +374,7 @@ vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRA unsigned char Status = data[i]; unsigned char Area = data[i + 1]; i += 6; - BYTEARRAY Location = UTIL_ExtractCString( data, i ); + QByteArray Location = UTIL_ExtractCString( data, i ); i += Location.size( ) + 1; Friends.push_back( new CIncomingFriendList( QString( Account.begin( ), Account.end( ) ), Status, @@ -386,7 +386,7 @@ vector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( BYTEARRA return Friends; } -vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARRAY data ) +QVector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_CLANMEMBERLIST" ); // DEBUG_Print( data ); @@ -401,7 +401,7 @@ vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARR // 1 byte -> Status // null term QString -> Location - vector ClanList; + QVector ClanList; if( ValidateLength( data ) && data.size( ) >= 9 ) { @@ -415,7 +415,7 @@ vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARR if( data.size( ) < i + 1 ) break; - BYTEARRAY Name = UTIL_ExtractCString( data, i ); + QByteArray Name = UTIL_ExtractCString( data, i ); i += Name.size( ) + 1; if( data.size( ) < i + 3 ) @@ -427,7 +427,7 @@ vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARR // in the original VB source the location QString is read but discarded, so that's what I do here - BYTEARRAY Location = UTIL_ExtractCString( data, i ); + QByteArray Location = UTIL_ExtractCString( data, i ); i += Location.size( ) + 1; ClanList.push_back( new CIncomingClanList( QString( Name.begin( ), Name.end( ) ), Rank, @@ -438,7 +438,7 @@ vector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( BYTEARR return ClanList; } -CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRAY data ) +CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_CLANMEMBERSTATUSCHANGE" ); // DEBUG_Print( data ); @@ -452,7 +452,7 @@ CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRA if( ValidateLength( data ) && data.size( ) >= 5 ) { - BYTEARRAY Name = UTIL_ExtractCString( data, 4 ); + QByteArray Name = UTIL_ExtractCString( data, 4 ); if( data.size( ) >= Name.size( ) + 7 ) { @@ -461,7 +461,7 @@ CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRA // in the original VB source the location QString is read but discarded, so that's what I do here - BYTEARRAY Location = UTIL_ExtractCString( data, Name.size( ) + 7 ); + QByteArray Location = UTIL_ExtractCString( data, Name.size( ) + 7 ); return new CIncomingClanList( QString( Name.begin( ), Name.end( ) ), Rank, Status ); @@ -475,18 +475,18 @@ CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRA // SEND FUNCTIONS // //////////////////// -BYTEARRAY CBNETProtocol :: SEND_PROTOCOL_INITIALIZE_SELECTOR( ) +QByteArray CBNETProtocol :: SEND_PROTOCOL_INITIALIZE_SELECTOR( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( 1 ); // DEBUG_Print( "SENT PROTOCOL_INITIALIZE_SELECTOR" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_NULL( ) +QByteArray CBNETProtocol :: SEND_SID_NULL( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NULL ); // SID_NULL packet.push_back( 0 ); // packet length will be assigned later @@ -497,9 +497,9 @@ BYTEARRAY CBNETProtocol :: SEND_SID_NULL( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_STOPADV( ) +QByteArray CBNETProtocol :: SEND_SID_STOPADV( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_STOPADV ); // SID_STOPADV packet.push_back( 0 ); // packet length will be assigned later @@ -510,23 +510,23 @@ BYTEARRAY CBNETProtocol :: SEND_SID_STOPADV( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) +QByteArray CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) { unsigned char MapFilter1[] = { 255, 3, 0, 0 }; unsigned char MapFilter2[] = { 255, 3, 0, 0 }; unsigned char MapFilter3[] = { 0, 0, 0, 0 }; unsigned char NumGames[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_GETADVLISTEX ); // SID_GETADVLISTEX packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, MapFilter1, 4 ); // Map Filter - UTIL_AppendByteArray( packet, MapFilter2, 4 ); // Map Filter - UTIL_AppendByteArray( packet, MapFilter3, 4 ); // Map Filter - UTIL_AppendByteArray( packet, NumGames, 4 ); // maximum number of games to list - UTIL_AppendByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendQByteArray( packet, MapFilter1, 4 ); // Map Filter + UTIL_AppendQByteArray( packet, MapFilter2, 4 ); // Map Filter + UTIL_AppendQByteArray( packet, MapFilter3, 4 ); // Map Filter + UTIL_AppendQByteArray( packet, NumGames, 4 ); // maximum number of games to list + UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name packet.push_back( 0 ); // Game Password is NULL packet.push_back( 0 ); // Game Stats is NULL AssignLength( packet ); @@ -535,9 +535,9 @@ BYTEARRAY CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_ENTERCHAT( ) +QByteArray CBNETProtocol :: SEND_SID_ENTERCHAT( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_ENTERCHAT ); // SID_ENTERCHAT packet.push_back( 0 ); // packet length will be assigned later @@ -550,63 +550,63 @@ BYTEARRAY CBNETProtocol :: SEND_SID_ENTERCHAT( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) +QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) { unsigned char NoCreateJoin[] = { 2, 0, 0, 0 }; unsigned char FirstJoin[] = { 1, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_JOINCHANNEL ); // SID_JOINCHANNEL packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later if( channel.size( ) > 0 ) - UTIL_AppendByteArray( packet, NoCreateJoin, 4 ); // flags for no create join + UTIL_AppendQByteArray( packet, NoCreateJoin, 4 ); // flags for no create join else - UTIL_AppendByteArray( packet, FirstJoin, 4 ); // flags for first join + UTIL_AppendQByteArray( packet, FirstJoin, 4 ); // flags for first join - UTIL_AppendByteArrayFast( packet, channel ); + UTIL_AppendQByteArrayFast( packet, channel ); AssignLength( packet ); // DEBUG_Print( "SENT SID_JOINCHANNEL" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) +QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CHATCOMMAND ); // SID_CHATCOMMAND packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, command ); // Message + UTIL_AppendQByteArrayFast( packet, command ); // Message AssignLength( packet ); // DEBUG_Print( "SENT SID_CHATCOMMAND" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_CHECKAD( ) +QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CHECKAD ); // SID_CHECKAD packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? AssignLength( packet ); // DEBUG_Print( "SENT SID_CHECKAD" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, BYTEARRAY mapGameType, BYTEARRAY mapFlags, BYTEARRAY mapWidth, BYTEARRAY mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, BYTEARRAY mapCRC, BYTEARRAY mapSHA1, uint32_t hostCounter ) +QByteArray CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, uint32_t hostCounter ) { // todotodo: sort out how GameType works, the documentation is horrendous @@ -644,23 +644,23 @@ Observers: (mask 0x00700000) cant be combined HostCounterString = QString( HostCounterString.rbegin( ), HostCounterString.rend( ) ); - BYTEARRAY packet; + QByteArray packet; // make the stat QString - BYTEARRAY StatString; - UTIL_AppendByteArrayFast( StatString, mapFlags ); + QByteArray StatString; + UTIL_AppendQByteArrayFast( StatString, mapFlags ); StatString.push_back( 0 ); - UTIL_AppendByteArrayFast( StatString, mapWidth ); - UTIL_AppendByteArrayFast( StatString, mapHeight ); - UTIL_AppendByteArrayFast( StatString, mapCRC ); - UTIL_AppendByteArrayFast( StatString, mapPath ); - UTIL_AppendByteArrayFast( StatString, hostName ); + UTIL_AppendQByteArrayFast( StatString, mapWidth ); + UTIL_AppendQByteArrayFast( StatString, mapHeight ); + UTIL_AppendQByteArrayFast( StatString, mapCRC ); + UTIL_AppendQByteArrayFast( StatString, mapPath ); + UTIL_AppendQByteArrayFast( StatString, hostName ); StatString.push_back( 0 ); - UTIL_AppendByteArrayFast( StatString, mapSHA1 ); + UTIL_AppendQByteArrayFast( StatString, mapSHA1 ); StatString = UTIL_EncodeStatString( StatString ); - if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.empty( ) && !hostName.empty( ) && !mapPath.empty( ) && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 && StatString.size( ) < 128 && HostCounterString.size( ) == 8 ) + if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.isEmpty( ) && !hostName.isEmpty( ) && !mapPath.isEmpty( ) && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 && StatString.size( ) < 128 && HostCounterString.size( ) == 8 ) { // make the rest of the packet @@ -672,15 +672,15 @@ Observers: (mask 0x00700000) cant be combined packet.push_back( 0 ); // State continued... packet.push_back( 0 ); // State continued... packet.push_back( 0 ); // State continued... - UTIL_AppendByteArray( packet, upTime, false ); // time since creation - UTIL_AppendByteArrayFast( packet, mapGameType ); // Game Type, Parameter - UTIL_AppendByteArray( packet, Unknown, 4 ); // ??? - UTIL_AppendByteArray( packet, CustomGame, 4 ); // Custom Game - UTIL_AppendByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendQByteArray( packet, upTime, false ); // time since creation + UTIL_AppendQByteArrayFast( packet, mapGameType ); // Game Type, Parameter + UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendQByteArray( packet, CustomGame, 4 ); // Custom Game + UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name packet.push_back( 0 ); // Game Password is NULL packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate - UTIL_AppendByteArrayFast( packet, HostCounterString, false ); // Host Counter - UTIL_AppendByteArrayFast( packet, StatString ); // Stat String + UTIL_AppendQByteArrayFast( packet, HostCounterString, false ); // Host Counter + UTIL_AppendQByteArrayFast( packet, StatString ); // Stat String packet.push_back( 0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) AssignLength( packet ); } @@ -692,19 +692,19 @@ Observers: (mask 0x00700000) cant be combined return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) +QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) { unsigned char ProductID[] = { 0, 0, 0, 0 }; unsigned char ProductVersion[] = { 14, 0, 0, 0 }; // Warcraft III is 14 - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NOTIFYJOIN ); // SID_NOTIFYJOIN packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, ProductID, 4 ); // Product ID - UTIL_AppendByteArray( packet, ProductVersion, 4 ); // Product Version - UTIL_AppendByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendQByteArray( packet, ProductID, 4 ); // Product ID + UTIL_AppendQByteArray( packet, ProductVersion, 4 ); // Product Version + UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name packet.push_back( 0 ); // Game Password is NULL AssignLength( packet ); // DEBUG_Print( "SENT SID_NOTIFYJOIN" ); @@ -712,9 +712,9 @@ BYTEARRAY CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_PING( BYTEARRAY pingValue ) +QByteArray CBNETProtocol :: SEND_SID_PING( QByteArray pingValue ) { - BYTEARRAY packet; + QByteArray packet; if( pingValue.size( ) == 4 ) { @@ -722,7 +722,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_PING( BYTEARRAY pingValue ) packet.push_back( SID_PING ); // SID_PING packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, pingValue ); // Ping Value + UTIL_AppendQByteArrayFast( packet, pingValue ); // Ping Value AssignLength( packet ); } else @@ -733,40 +733,40 @@ BYTEARRAY CBNETProtocol :: SEND_SID_PING( BYTEARRAY pingValue ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_LOGONRESPONSE( BYTEARRAY clientToken, BYTEARRAY serverToken, BYTEARRAY passwordHash, QString accountName ) +QByteArray CBNETProtocol :: SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByteArray serverToken, QByteArray passwordHash, QString accountName ) { - // todotodo: check that the passed BYTEARRAY sizes are correct (don't know what they should be right now so I can't do this today) + // todotodo: check that the passed QByteArray sizes are correct (don't know what they should be right now so I can't do this today) - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_LOGONRESPONSE ); // SID_LOGONRESPONSE packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, clientToken ); // Client Token - UTIL_AppendByteArrayFast( packet, serverToken ); // Server Token - UTIL_AppendByteArrayFast( packet, passwordHash ); // Password Hash - UTIL_AppendByteArrayFast( packet, accountName ); // Account Name + UTIL_AppendQByteArrayFast( packet, clientToken ); // Client Token + UTIL_AppendQByteArrayFast( packet, serverToken ); // Server Token + UTIL_AppendQByteArrayFast( packet, passwordHash ); // Password Hash + UTIL_AppendQByteArrayFast( packet, accountName ); // Account Name AssignLength( packet ); // DEBUG_Print( "SENT SID_LOGONRESPONSE" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) +QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NETGAMEPORT ); // SID_NETGAMEPORT packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, serverPort, false ); // local game server port + UTIL_AppendQByteArray( packet, serverPort, false ); // local game server port AssignLength( packet ); // DEBUG_Print( "SENT SID_NETGAMEPORT" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, QString countryAbbrev, QString country ) +QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, QString countryAbbrev, QString country ) { unsigned char ProtocolID[] = { 0, 0, 0, 0 }; unsigned char PlatformID[] = { 54, 56, 88, 73 }; // "IX86" @@ -777,34 +777,34 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint unsigned char LocalIP[] = { 127, 0, 0, 1 }; unsigned char TimeZoneBias[] = { 44, 1, 0, 0 }; // 300 minutes (GMT -0500) - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_INFO ); // SID_AUTH_INFO packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, ProtocolID, 4 ); // Protocol ID - UTIL_AppendByteArray( packet, PlatformID, 4 ); // Platform ID + UTIL_AppendQByteArray( packet, ProtocolID, 4 ); // Protocol ID + UTIL_AppendQByteArray( packet, PlatformID, 4 ); // Platform ID if( TFT ) - UTIL_AppendByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) - - UTIL_AppendByteArray( packet, Version, 4 ); // Version - UTIL_AppendByteArray( packet, Language, 4 ); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English) - UTIL_AppendByteArray( packet, LocalIP, 4 ); // Local IP for NAT compatibility - UTIL_AppendByteArray( packet, TimeZoneBias, 4 ); // Time Zone Bias - UTIL_AppendByteArray( packet, localeID, false ); // Locale ID - UTIL_AppendByteArray( packet, localeID, false ); // Language ID (copying the locale ID should be sufficient since we don't care about sublanguages) - UTIL_AppendByteArrayFast( packet, countryAbbrev ); // Country Abbreviation - UTIL_AppendByteArrayFast( packet, country ); // Country + UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + + UTIL_AppendQByteArray( packet, Version, 4 ); // Version + UTIL_AppendQByteArray( packet, Language, 4 ); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English) + UTIL_AppendQByteArray( packet, LocalIP, 4 ); // Local IP for NAT compatibility + UTIL_AppendQByteArray( packet, TimeZoneBias, 4 ); // Time Zone Bias + UTIL_AppendQByteArray( packet, localeID, false ); // Locale ID + UTIL_AppendQByteArray( packet, localeID, false ); // Language ID (copying the locale ID should be sufficient since we don't care about sublanguages) + UTIL_AppendQByteArrayFast( packet, countryAbbrev ); // Country Abbreviation + UTIL_AppendQByteArrayFast( packet, country ); // Country AssignLength( packet ); // DEBUG_Print( "SENT SID_AUTH_INFO" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, BYTEARRAY exeVersion, BYTEARRAY exeVersionHash, BYTEARRAY keyInfoROC, BYTEARRAY keyInfoTFT, QString exeInfo, QString keyOwnerName ) +QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToken, QByteArray exeVersion, QByteArray exeVersionHash, QByteArray keyInfoROC, QByteArray keyInfoTFT, QString exeInfo, QString keyOwnerName ) { uint32_t NumKeys = 0; @@ -813,7 +813,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, else NumKeys = 1; - BYTEARRAY packet; + QByteArray packet; if( clientToken.size( ) == 4 && exeVersion.size( ) == 4 && exeVersionHash.size( ) == 4 && keyInfoROC.size( ) == 36 && ( !TFT || keyInfoTFT.size( ) == 36 ) ) { @@ -821,18 +821,18 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, packet.push_back( SID_AUTH_CHECK ); // SID_AUTH_CHECK packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, clientToken ); // Client Token - UTIL_AppendByteArrayFast( packet, exeVersion ); // EXE Version - UTIL_AppendByteArrayFast( packet, exeVersionHash ); // EXE Version Hash - UTIL_AppendByteArray( packet, NumKeys, false ); // number of keys in this packet - UTIL_AppendByteArray( packet, (uint32_t)0, false ); // boolean Using Spawn (32 bit) - UTIL_AppendByteArrayFast( packet, keyInfoROC ); // ROC Key Info + UTIL_AppendQByteArrayFast( packet, clientToken ); // Client Token + UTIL_AppendQByteArrayFast( packet, exeVersion ); // EXE Version + UTIL_AppendQByteArrayFast( packet, exeVersionHash ); // EXE Version Hash + UTIL_AppendQByteArray( packet, NumKeys, false ); // number of keys in this packet + UTIL_AppendQByteArray( packet, (uint32_t)0, false ); // boolean Using Spawn (32 bit) + UTIL_AppendQByteArrayFast( packet, keyInfoROC ); // ROC Key Info if( TFT ) - UTIL_AppendByteArrayFast( packet, keyInfoTFT ); // TFT Key Info + UTIL_AppendQByteArrayFast( packet, keyInfoTFT ); // TFT Key Info - UTIL_AppendByteArrayFast( packet, exeInfo ); // EXE Info - UTIL_AppendByteArrayFast( packet, keyOwnerName ); // CD Key Owner Name + UTIL_AppendQByteArrayFast( packet, exeInfo ); // EXE Info + UTIL_AppendQByteArrayFast( packet, keyOwnerName ); // CD Key Owner Name AssignLength( packet ); } else @@ -843,9 +843,9 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( BYTEARRAY clientPublicKey, QString accountName ) +QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicKey, QString accountName ) { - BYTEARRAY packet; + QByteArray packet; if( clientPublicKey.size( ) == 32 ) { @@ -853,8 +853,8 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( BYTEARRAY clientPublicKey packet.push_back( SID_AUTH_ACCOUNTLOGON ); // SID_AUTH_ACCOUNTLOGON packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, clientPublicKey ); // Client Key - UTIL_AppendByteArrayFast( packet, accountName ); // Account Name + UTIL_AppendQByteArrayFast( packet, clientPublicKey ); // Client Key + UTIL_AppendQByteArrayFast( packet, accountName ); // Account Name AssignLength( packet ); } else @@ -865,9 +865,9 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( BYTEARRAY clientPublicKey return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY clientPasswordProof ) +QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPasswordProof ) { - BYTEARRAY packet; + QByteArray packet; if( clientPasswordProof.size( ) == 20 ) { @@ -875,7 +875,7 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY clientPass packet.push_back( SID_AUTH_ACCOUNTLOGONPROOF ); // SID_AUTH_ACCOUNTLOGONPROOF packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, clientPasswordProof ); // Client Password Proof + UTIL_AppendQByteArrayFast( packet, clientPasswordProof ); // Client Password Proof AssignLength( packet ); } else @@ -886,23 +886,23 @@ BYTEARRAY CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY clientPass return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_WARDEN( BYTEARRAY wardenResponse ) +QByteArray CBNETProtocol :: SEND_SID_WARDEN( QByteArray wardenResponse ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_WARDEN ); // SID_WARDEN packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArrayFast( packet, wardenResponse ); // warden response + UTIL_AppendQByteArrayFast( packet, wardenResponse ); // warden response AssignLength( packet ); // DEBUG_Print( "SENT SID_WARDEN" ); // DEBUG_Print( packet ); return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_FRIENDSLIST( ) +QByteArray CBNETProtocol :: SEND_SID_FRIENDSLIST( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_FRIENDSLIST ); // SID_FRIENDSLIST packet.push_back( 0 ); // packet length will be assigned later @@ -913,16 +913,16 @@ BYTEARRAY CBNETProtocol :: SEND_SID_FRIENDSLIST( ) return packet; } -BYTEARRAY CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) +QByteArray CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) { unsigned char Cookie[] = { 0, 0, 0, 0 }; - BYTEARRAY packet; + QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CLANMEMBERLIST ); // SID_CLANMEMBERLIST packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later - UTIL_AppendByteArray( packet, Cookie, 4 ); // cookie + UTIL_AppendQByteArray( packet, Cookie, 4 ); // cookie AssignLength( packet ); // DEBUG_Print( "SENT SID_CLANMEMBERLIST" ); // DEBUG_Print( packet ); @@ -933,15 +933,15 @@ BYTEARRAY CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) // OTHER FUNCTIONS // ///////////////////// -bool CBNETProtocol :: AssignLength( BYTEARRAY &content ) +bool CBNETProtocol :: AssignLength( QByteArray &content ) { // insert the actual length of the content array into bytes 3 and 4 (indices 2 and 3) - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -950,18 +950,18 @@ bool CBNETProtocol :: AssignLength( BYTEARRAY &content ) return false; } -bool CBNETProtocol :: ValidateLength( BYTEARRAY &content ) +bool CBNETProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length uint16_t Length; - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) { LengthBytes.push_back( content[2] ); LengthBytes.push_back( content[3] ); - Length = UTIL_ByteArrayToUInt16( LengthBytes, false ); + Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); if( Length == content.size( ) ) return true; @@ -974,7 +974,7 @@ bool CBNETProtocol :: ValidateLength( BYTEARRAY &content ) // CIncomingGameHost // -CIncomingGameHost :: CIncomingGameHost( BYTEARRAY &nIP, uint16_t nPort, QString nGameName, BYTEARRAY &nHostCounter ) +CIncomingGameHost :: CIncomingGameHost( QByteArray &nIP, uint16_t nPort, QString nGameName, QByteArray &nHostCounter ) { m_IP = nIP; m_Port = nPort; @@ -1062,7 +1062,7 @@ QString CIncomingFriendList :: ExtractStatus( unsigned char status ) if( status & 4 ) Result += ""; - if( Result.empty( ) ) + if( Result.isEmpty( ) ) Result = ""; return Result; @@ -1087,10 +1087,10 @@ QString CIncomingFriendList :: ExtractLocation( QString location ) { QString Result; - if( location.substr( 0, 4 ) == "PX3W" ) - Result = location.substr( 4 ); + if( location.mid( 0, 4 ) == "PX3W" ) + Result = location.mid( 4 ); - if( Result.empty( ) ) + if( Result.isEmpty( ) ) Result = "."; return Result; diff --git a/ghost/bnetprotocol.h b/ghost/bnetprotocol.h index 4d7cfb9..395ec13 100644 --- a/ghost/bnetprotocol.h +++ b/ghost/bnetprotocol.h @@ -88,83 +88,83 @@ class CBNETProtocol }; private: - BYTEARRAY m_ClientToken; // set in constructor - BYTEARRAY m_LogonType; // set in RECEIVE_SID_AUTH_INFO - BYTEARRAY m_ServerToken; // set in RECEIVE_SID_AUTH_INFO - BYTEARRAY m_MPQFileTime; // set in RECEIVE_SID_AUTH_INFO - BYTEARRAY m_IX86VerFileName; // set in RECEIVE_SID_AUTH_INFO - BYTEARRAY m_ValueStringFormula; // set in RECEIVE_SID_AUTH_INFO - BYTEARRAY m_KeyState; // set in RECEIVE_SID_AUTH_CHECK - BYTEARRAY m_KeyStateDescription; // set in RECEIVE_SID_AUTH_CHECK - BYTEARRAY m_Salt; // set in RECEIVE_SID_AUTH_ACCOUNTLOGON - BYTEARRAY m_ServerPublicKey; // set in RECEIVE_SID_AUTH_ACCOUNTLOGON - BYTEARRAY m_UniqueName; // set in RECEIVE_SID_ENTERCHAT + QByteArray m_ClientToken; // set in constructor + QByteArray m_LogonType; // set in RECEIVE_SID_AUTH_INFO + QByteArray m_ServerToken; // set in RECEIVE_SID_AUTH_INFO + QByteArray m_MPQFileTime; // set in RECEIVE_SID_AUTH_INFO + QByteArray m_IX86VerFileName; // set in RECEIVE_SID_AUTH_INFO + QByteArray m_ValueStringFormula; // set in RECEIVE_SID_AUTH_INFO + QByteArray m_KeyState; // set in RECEIVE_SID_AUTH_CHECK + QByteArray m_KeyStateDescription; // set in RECEIVE_SID_AUTH_CHECK + QByteArray m_Salt; // set in RECEIVE_SID_AUTH_ACCOUNTLOGON + QByteArray m_ServerPublicKey; // set in RECEIVE_SID_AUTH_ACCOUNTLOGON + QByteArray m_UniqueName; // set in RECEIVE_SID_ENTERCHAT public: CBNETProtocol( ); ~CBNETProtocol( ); - BYTEARRAY GetClientToken( ) { return m_ClientToken; } - BYTEARRAY GetLogonType( ) { return m_LogonType; } - BYTEARRAY GetServerToken( ) { return m_ServerToken; } - BYTEARRAY GetMPQFileTime( ) { return m_MPQFileTime; } - BYTEARRAY GetIX86VerFileName( ) { return m_IX86VerFileName; } + QByteArray GetClientToken( ) { return m_ClientToken; } + QByteArray GetLogonType( ) { return m_LogonType; } + QByteArray GetServerToken( ) { return m_ServerToken; } + QByteArray GetMPQFileTime( ) { return m_MPQFileTime; } + QByteArray GetIX86VerFileName( ) { return m_IX86VerFileName; } string GetIX86VerFileNameString( ) { return string( m_IX86VerFileName.begin( ), m_IX86VerFileName.end( ) ); } - BYTEARRAY GetValueStringFormula( ) { return m_ValueStringFormula; } + QByteArray GetValueStringFormula( ) { return m_ValueStringFormula; } string GetValueStringFormulaString( ) { return string( m_ValueStringFormula.begin( ), m_ValueStringFormula.end( ) ); } - BYTEARRAY GetKeyState( ) { return m_KeyState; } + QByteArray GetKeyState( ) { return m_KeyState; } string GetKeyStateDescription( ) { return string( m_KeyStateDescription.begin( ), m_KeyStateDescription.end( ) ); } - BYTEARRAY GetSalt( ) { return m_Salt; } - BYTEARRAY GetServerPublicKey( ) { return m_ServerPublicKey; } - BYTEARRAY GetUniqueName( ) { return m_UniqueName; } + QByteArray GetSalt( ) { return m_Salt; } + QByteArray GetServerPublicKey( ) { return m_ServerPublicKey; } + QByteArray GetUniqueName( ) { return m_UniqueName; } // receive functions - bool RECEIVE_SID_NULL( BYTEARRAY data ); - CIncomingGameHost *RECEIVE_SID_GETADVLISTEX( BYTEARRAY data ); - bool RECEIVE_SID_ENTERCHAT( BYTEARRAY data ); - CIncomingChatEvent *RECEIVE_SID_CHATEVENT( BYTEARRAY data ); - bool RECEIVE_SID_CHECKAD( BYTEARRAY data ); - bool RECEIVE_SID_STARTADVEX3( BYTEARRAY data ); - BYTEARRAY RECEIVE_SID_PING( BYTEARRAY data ); - bool RECEIVE_SID_LOGONRESPONSE( BYTEARRAY data ); - bool RECEIVE_SID_AUTH_INFO( BYTEARRAY data ); - bool RECEIVE_SID_AUTH_CHECK( BYTEARRAY data ); - bool RECEIVE_SID_AUTH_ACCOUNTLOGON( BYTEARRAY data ); - bool RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY data ); - BYTEARRAY RECEIVE_SID_WARDEN( BYTEARRAY data ); - vector RECEIVE_SID_FRIENDSLIST( BYTEARRAY data ); - vector RECEIVE_SID_CLANMEMBERLIST( BYTEARRAY data ); - CIncomingClanList *RECEIVE_SID_CLANMEMBERSTATUSCHANGE( BYTEARRAY data ); + bool RECEIVE_SID_NULL( QByteArray data ); + CIncomingGameHost *RECEIVE_SID_GETADVLISTEX( QByteArray data ); + bool RECEIVE_SID_ENTERCHAT( QByteArray data ); + CIncomingChatEvent *RECEIVE_SID_CHATEVENT( QByteArray data ); + bool RECEIVE_SID_CHECKAD( QByteArray data ); + bool RECEIVE_SID_STARTADVEX3( QByteArray data ); + QByteArray RECEIVE_SID_PING( QByteArray data ); + bool RECEIVE_SID_LOGONRESPONSE( QByteArray data ); + bool RECEIVE_SID_AUTH_INFO( QByteArray data ); + bool RECEIVE_SID_AUTH_CHECK( QByteArray data ); + bool RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ); + bool RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ); + QByteArray RECEIVE_SID_WARDEN( QByteArray data ); + QVector RECEIVE_SID_FRIENDSLIST( QByteArray data ); + QVector RECEIVE_SID_CLANMEMBERLIST( QByteArray data ); + CIncomingClanList *RECEIVE_SID_CLANMEMBERSTATUSCHANGE( QByteArray data ); // send functions - BYTEARRAY SEND_PROTOCOL_INITIALIZE_SELECTOR( ); - BYTEARRAY SEND_SID_NULL( ); - BYTEARRAY SEND_SID_STOPADV( ); - BYTEARRAY SEND_SID_GETADVLISTEX( string gameName ); - BYTEARRAY SEND_SID_ENTERCHAT( ); - BYTEARRAY SEND_SID_JOINCHANNEL( string channel ); - BYTEARRAY SEND_SID_CHATCOMMAND( string command ); - BYTEARRAY SEND_SID_CHECKAD( ); - BYTEARRAY SEND_SID_STARTADVEX3( unsigned char state, BYTEARRAY mapGameType, BYTEARRAY mapFlags, BYTEARRAY mapWidth, BYTEARRAY mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, BYTEARRAY mapCRC, BYTEARRAY mapSHA1, uint32_t hostCounter ); - BYTEARRAY SEND_SID_NOTIFYJOIN( string gameName ); - BYTEARRAY SEND_SID_PING( BYTEARRAY pingValue ); - BYTEARRAY SEND_SID_LOGONRESPONSE( BYTEARRAY clientToken, BYTEARRAY serverToken, BYTEARRAY passwordHash, string accountName ); - BYTEARRAY SEND_SID_NETGAMEPORT( uint16_t serverPort ); - BYTEARRAY SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, string countryAbbrev, string country ); - BYTEARRAY SEND_SID_AUTH_CHECK( bool TFT, BYTEARRAY clientToken, BYTEARRAY exeVersion, BYTEARRAY exeVersionHash, BYTEARRAY keyInfoROC, BYTEARRAY keyInfoTFT, string exeInfo, string keyOwnerName ); - BYTEARRAY SEND_SID_AUTH_ACCOUNTLOGON( BYTEARRAY clientPublicKey, string accountName ); - BYTEARRAY SEND_SID_AUTH_ACCOUNTLOGONPROOF( BYTEARRAY clientPasswordProof ); - BYTEARRAY SEND_SID_WARDEN( BYTEARRAY wardenResponse ); - BYTEARRAY SEND_SID_FRIENDSLIST( ); - BYTEARRAY SEND_SID_CLANMEMBERLIST( ); + QByteArray SEND_PROTOCOL_INITIALIZE_SELECTOR( ); + QByteArray SEND_SID_NULL( ); + QByteArray SEND_SID_STOPADV( ); + QByteArray SEND_SID_GETADVLISTEX( string gameName ); + QByteArray SEND_SID_ENTERCHAT( ); + QByteArray SEND_SID_JOINCHANNEL( string channel ); + QByteArray SEND_SID_CHATCOMMAND( string command ); + QByteArray SEND_SID_CHECKAD( ); + QByteArray SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, QByteArray mapCRC, QByteArray mapSHA1, uint32_t hostCounter ); + QByteArray SEND_SID_NOTIFYJOIN( string gameName ); + QByteArray SEND_SID_PING( QByteArray pingValue ); + QByteArray SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByteArray serverToken, QByteArray passwordHash, string accountName ); + QByteArray SEND_SID_NETGAMEPORT( uint16_t serverPort ); + QByteArray SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, string countryAbbrev, string country ); + QByteArray SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToken, QByteArray exeVersion, QByteArray exeVersionHash, QByteArray keyInfoROC, QByteArray keyInfoTFT, string exeInfo, string keyOwnerName ); + QByteArray SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicKey, string accountName ); + QByteArray SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPasswordProof ); + QByteArray SEND_SID_WARDEN( QByteArray wardenResponse ); + QByteArray SEND_SID_FRIENDSLIST( ); + QByteArray SEND_SID_CLANMEMBERLIST( ); // other functions private: - bool AssignLength( BYTEARRAY &content ); - bool ValidateLength( BYTEARRAY &content ); + bool AssignLength( QByteArray &content ); + bool ValidateLength( QByteArray &content ); }; // @@ -174,20 +174,20 @@ class CBNETProtocol class CIncomingGameHost { private: - BYTEARRAY m_IP; + QByteArray m_IP; uint16_t m_Port; string m_GameName; - BYTEARRAY m_HostCounter; + QByteArray m_HostCounter; public: - CIncomingGameHost( BYTEARRAY &nIP, uint16_t nPort, string nGameName, BYTEARRAY &nHostCounter ); + CIncomingGameHost( QByteArray &nIP, uint16_t nPort, string nGameName, QByteArray &nHostCounter ); ~CIncomingGameHost( ); - BYTEARRAY GetIP( ) { return m_IP; } + QByteArray GetIP( ) { return m_IP; } string GetIPString( ); uint16_t GetPort( ) { return m_Port; } string GetGameName( ) { return m_GameName; } - BYTEARRAY GetHostCounter( ) { return m_HostCounter; } + QByteArray GetHostCounter( ) { return m_HostCounter; } }; // diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index d07a05f..b58b8c8 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -47,21 +47,21 @@ CBNLSClient :: ~CBNLSClient( ) delete m_Socket; delete m_Protocol; - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { delete m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); } } -BYTEARRAY CBNLSClient :: GetWardenResponse( ) +QByteArray CBNLSClient :: GetWardenResponse( ) { - BYTEARRAY WardenResponse; + QByteArray WardenResponse; - if( !m_WardenResponses.empty( ) ) + if( !m_WardenResponses.isEmpty( ) ) { WardenResponse = m_WardenResponses.front( ); - m_WardenResponses.pop( ); + m_WardenResponses.dequeue( ); m_TotalWardenOut++; } @@ -105,10 +105,10 @@ bool CBNLSClient :: Update( void *fd, void *send_fd ) m_LastNullTime = GetTime( ); } - while( !m_OutPackets.empty( ) ) + while( !m_OutPackets.isEmpty( ) ) { m_Socket->PutBytes( m_OutPackets.front( ) ); - m_OutPackets.pop( ); + m_OutPackets.dequeue( ); } m_Socket->DoSend( (fd_set *)send_fd ); @@ -136,19 +136,19 @@ bool CBNLSClient :: Update( void *fd, void *send_fd ) void CBNLSClient :: ExtractPackets( ) { QString *RecvBuffer = m_Socket->GetBytes( ); - BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); while( Bytes.size( ) >= 3 ) { - uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false ); + uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false ); if( Length >= 3 ) { if( Bytes.size( ) >= Length ) { - m_Packets.push( new CCommandPacket( 0, Bytes[2], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); + m_Packets.enqueue( new CCommandPacket( 0, Bytes[2], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) ); + Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); } else return; @@ -164,17 +164,17 @@ void CBNLSClient :: ExtractPackets( ) void CBNLSClient :: ProcessPackets( ) { - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { CCommandPacket *Packet = m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); if( Packet->GetID( ) == CBNLSProtocol :: BNLS_WARDEN ) { - BYTEARRAY WardenResponse = m_Protocol->RECEIVE_BNLS_WARDEN( Packet->GetData( ) ); + QByteArray WardenResponse = m_Protocol->RECEIVE_BNLS_WARDEN( Packet->GetData( ) ); - if( !WardenResponse.empty( ) ) - m_WardenResponses.push( WardenResponse ); + if( !WardenResponse.isEmpty( ) ) + m_WardenResponses.enqueue( WardenResponse ); } delete Packet; @@ -183,11 +183,11 @@ void CBNLSClient :: ProcessPackets( ) void CBNLSClient :: QueueWardenSeed( uint32_t seed ) { - m_OutPackets.push( m_Protocol->SEND_BNLS_WARDEN_SEED( m_WardenCookie, seed ) ); + m_OutPackets.enqueue( m_Protocol->SEND_BNLS_WARDEN_SEED( m_WardenCookie, seed ) ); } -void CBNLSClient :: QueueWardenRaw( BYTEARRAY wardenRaw ) +void CBNLSClient :: QueueWardenRaw( QByteArray wardenRaw ) { - m_OutPackets.push( m_Protocol->SEND_BNLS_WARDEN_RAW( m_WardenCookie, wardenRaw ) ); + m_OutPackets.enqueue( m_Protocol->SEND_BNLS_WARDEN_RAW( m_WardenCookie, wardenRaw ) ); m_TotalWardenIn++; } diff --git a/ghost/bnlsclient.h b/ghost/bnlsclient.h index 0562c37..9ff5445 100644 --- a/ghost/bnlsclient.h +++ b/ghost/bnlsclient.h @@ -34,14 +34,14 @@ class CBNLSClient private: CTCPClient *m_Socket; // the connection to the BNLS server CBNLSProtocol *m_Protocol; // battle.net protocol - queue m_Packets; // queue of incoming packets + QQueue m_Packets; // queue of incoming packets bool m_WasConnected; string m_Server; uint16_t m_Port; uint32_t m_LastNullTime; uint32_t m_WardenCookie; // the warden cookie - queue m_OutPackets; // queue of outgoing packets to be sent - queue m_WardenResponses; // the warden responses to be sent to battle.net + QQueue m_OutPackets; // queue of outgoing packets to be sent + QQueue m_WardenResponses; // the warden responses to be sent to battle.net uint32_t m_TotalWardenIn; uint32_t m_TotalWardenOut; @@ -49,7 +49,7 @@ class CBNLSClient CBNLSClient( string nServer, uint16_t nPort, uint32_t nWardenCookie ); ~CBNLSClient( ); - BYTEARRAY GetWardenResponse( ); + QByteArray GetWardenResponse( ); uint32_t GetTotalWardenIn( ) { return m_TotalWardenIn; } uint32_t GetTotalWardenOut( ) { return m_TotalWardenOut; } @@ -63,7 +63,7 @@ class CBNLSClient // other functions void QueueWardenSeed( uint32_t seed ); - void QueueWardenRaw( BYTEARRAY wardenRaw ); + void QueueWardenRaw( QByteArray wardenRaw ); }; #endif diff --git a/ghost/bnlsprotocol.cpp b/ghost/bnlsprotocol.cpp index 8929ef9..9ff30d1 100644 --- a/ghost/bnlsprotocol.cpp +++ b/ghost/bnlsprotocol.cpp @@ -36,7 +36,7 @@ CBNLSProtocol :: ~CBNLSProtocol( ) // RECEIVE FUNCTIONS // /////////////////////// -BYTEARRAY CBNLSProtocol :: RECEIVE_BNLS_WARDEN( BYTEARRAY data ) +QByteArray CBNLSProtocol :: RECEIVE_BNLS_WARDEN( QByteArray data ) { // 2 bytes -> Length // 1 byte -> ID @@ -49,26 +49,26 @@ BYTEARRAY CBNLSProtocol :: RECEIVE_BNLS_WARDEN( BYTEARRAY data ) if( ValidateLength( data ) && data.size( ) >= 11 ) { unsigned char Usage = data[3]; - uint32_t Cookie = UTIL_ByteArrayToUInt32( data, false, 4 ); + uint32_t Cookie = UTIL_QByteArrayToUInt32( data, false, 4 ); unsigned char Result = data[8]; - uint16_t Length = UTIL_ByteArrayToUInt16( data, false, 10 ); + uint16_t Length = UTIL_QByteArrayToUInt16( data, false, 10 ); if( Result == 0x00 ) - return BYTEARRAY( data.begin( ) + 11, data.end( ) ); + return QByteArray( data.begin( ) + 11, data.end( ) ); else CONSOLE_Print( "[BNLSPROTO] received error code " + UTIL_ToString( data[8] ) ); } - return BYTEARRAY( ); + return QByteArray( ); } //////////////////// // SEND FUNCTIONS // //////////////////// -BYTEARRAY CBNLSProtocol :: SEND_BNLS_NULL( ) +QByteArray CBNLSProtocol :: SEND_BNLS_NULL( ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later packet.push_back( BNLS_NULL ); // BNLS_NULL @@ -76,58 +76,58 @@ BYTEARRAY CBNLSProtocol :: SEND_BNLS_NULL( ) return packet; } -BYTEARRAY CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t seed ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t seed ) { unsigned char Client[] = { 80, 88, 51, 87 }; // "W3XP" - BYTEARRAY packet; + QByteArray packet; packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( 0 ); // BNLS_WARDEN_SEED - UTIL_AppendByteArray( packet, cookie, false ); // cookie - UTIL_AppendByteArray( packet, Client, 4 ); // Client - UTIL_AppendByteArray( packet, (uint16_t)4, false ); // length of seed - UTIL_AppendByteArray( packet, seed, false ); // seed + UTIL_AppendQByteArray( packet, cookie, false ); // cookie + UTIL_AppendQByteArray( packet, Client, 4 ); // Client + UTIL_AppendQByteArray( packet, (uint16_t)4, false ); // length of seed + UTIL_AppendQByteArray( packet, seed, false ); // seed packet.push_back( 0 ); // username is blank - UTIL_AppendByteArray( packet, (uint16_t)0, false ); // password length + UTIL_AppendQByteArray( packet, (uint16_t)0, false ); // password length // password AssignLength( packet ); return packet; } -BYTEARRAY CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, BYTEARRAY raw ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray raw ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( 0 ); // packet length will be assigned later packet.push_back( 0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( 1 ); // BNLS_WARDEN_RAW - UTIL_AppendByteArray( packet, cookie, false ); // cookie - UTIL_AppendByteArray( packet, (uint16_t)raw.size( ), false ); // raw length - UTIL_AppendByteArray( packet, raw ); // raw + UTIL_AppendQByteArray( packet, cookie, false ); // cookie + UTIL_AppendQByteArray( packet, (uint16_t)raw.size( ), false ); // raw length + UTIL_AppendQByteArray( packet, raw ); // raw AssignLength( packet ); return packet; } -BYTEARRAY CBNLSProtocol :: SEND_BNLS_WARDEN_RUNMODULE( uint32_t cookie ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RUNMODULE( uint32_t cookie ) { - return BYTEARRAY( ); + return QByteArray( ); } ///////////////////// // OTHER FUNCTIONS // ///////////////////// -bool CBNLSProtocol :: AssignLength( BYTEARRAY &content ) +bool CBNLSProtocol :: AssignLength( QByteArray &content ) { // insert the actual length of the content array into bytes 1 and 2 (indices 0 and 1) - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 2 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); content[0] = LengthBytes[0]; content[1] = LengthBytes[1]; return true; @@ -136,18 +136,18 @@ bool CBNLSProtocol :: AssignLength( BYTEARRAY &content ) return false; } -bool CBNLSProtocol :: ValidateLength( BYTEARRAY &content ) +bool CBNLSProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 1 and 2 (indices 0 and 1) of the content array describe the length uint16_t Length; - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 2 && content.size( ) <= 65535 ) { LengthBytes.push_back( content[0] ); LengthBytes.push_back( content[1] ); - Length = UTIL_ByteArrayToUInt16( LengthBytes, false ); + Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); if( Length == content.size( ) ) return true; diff --git a/ghost/bnlsprotocol.h b/ghost/bnlsprotocol.h index d0f9f10..5ef3cac 100644 --- a/ghost/bnlsprotocol.h +++ b/ghost/bnlsprotocol.h @@ -65,20 +65,20 @@ class CBNLSProtocol // receive functions - BYTEARRAY RECEIVE_BNLS_WARDEN( BYTEARRAY data ); + QByteArray RECEIVE_BNLS_WARDEN( QByteArray data ); // send functions - BYTEARRAY SEND_BNLS_NULL( ); - BYTEARRAY SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t seed ); - BYTEARRAY SEND_BNLS_WARDEN_RAW( uint32_t cookie, BYTEARRAY raw ); - BYTEARRAY SEND_BNLS_WARDEN_RUNMODULE( uint32_t cookie ); + QByteArray SEND_BNLS_NULL( ); + QByteArray SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t seed ); + QByteArray SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray raw ); + QByteArray SEND_BNLS_WARDEN_RUNMODULE( uint32_t cookie ); // other functions private: - bool AssignLength( BYTEARRAY &content ); - bool ValidateLength( BYTEARRAY &content ); + bool AssignLength( QByteArray &content ); + bool ValidateLength( QByteArray &content ); }; #endif diff --git a/ghost/commandpacket.cpp b/ghost/commandpacket.cpp index 9c22f74..d51d99c 100644 --- a/ghost/commandpacket.cpp +++ b/ghost/commandpacket.cpp @@ -25,7 +25,7 @@ // CCommandPacket // -CCommandPacket :: CCommandPacket( unsigned char nPacketType, int nID, BYTEARRAY nData ) +CCommandPacket :: CCommandPacket( unsigned char nPacketType, int nID, QByteArray nData ) { m_PacketType = nPacketType; m_ID = nID; diff --git a/ghost/commandpacket.h b/ghost/commandpacket.h index dc75488..1c90015 100644 --- a/ghost/commandpacket.h +++ b/ghost/commandpacket.h @@ -30,15 +30,15 @@ class CCommandPacket private: unsigned char m_PacketType; int m_ID; - BYTEARRAY m_Data; + QByteArray m_Data; public: - CCommandPacket( unsigned char nPacketType, int nID, BYTEARRAY nData ); + CCommandPacket( unsigned char nPacketType, int nID, QByteArray nData ); ~CCommandPacket( ); unsigned char GetPacketType( ) { return m_PacketType; } int GetID( ) { return m_ID; } - BYTEARRAY GetData( ) { return m_Data; } + QByteArray GetData( ) { return m_Data; } }; #endif diff --git a/ghost/config.cpp b/ghost/config.cpp index 84729e4..5488c28 100644 --- a/ghost/config.cpp +++ b/ghost/config.cpp @@ -55,7 +55,7 @@ void CConfig :: Read( QString file ) // ignore blank lines and comments - if( Line.empty( ) || Line[0] == '#' ) + if( Line.isEmpty( ) || Line[0] == '#' ) continue; // remove newlines and partial newlines to help fix issues with Windows formatted config files on Linux systems @@ -74,7 +74,7 @@ void CConfig :: Read( QString file ) QString :: size_type ValueEnd = Line.size( ); if( ValueStart != QString :: npos ) - m_CFG[Line.substr( KeyStart, KeyEnd - KeyStart )] = Line.substr( ValueStart, ValueEnd - ValueStart ); + m_CFG[Line.mid( KeyStart, KeyEnd - KeyStart )] = Line.mid( ValueStart, ValueEnd - ValueStart ); } in.close( ); diff --git a/ghost/config.h b/ghost/config.h index ccd3b7f..a755974 100644 --- a/ghost/config.h +++ b/ghost/config.h @@ -28,7 +28,7 @@ class CConfig { private: - map m_CFG; + QMap m_CFG; public: CConfig( ); diff --git a/ghost/game.cpp b/ghost/game.cpp index 1635204..d4a2455 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -37,7 +37,7 @@ #include "statsw3mmd.h" #include -#include +#include #include // @@ -91,7 +91,7 @@ CGame :: ~CGame( ) // store the CDBGamePlayers in the database - for( vector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) + for( QVector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) m_GHost->m_Callables.push_back( m_GHost->m_DB->ThreadedGamePlayerAdd( m_CallableGameAdd->GetResult( ), (*i)->GetName( ), (*i)->GetIP( ), (*i)->GetSpoofed( ), (*i)->GetSpoofedRealm( ), (*i)->GetReserved( ), (*i)->GetLoadingTime( ), (*i)->GetLeft( ), (*i)->GetLeftReason( ), (*i)->GetTeam( ), (*i)->GetColour( ) ) ); // store the stats in the database @@ -107,24 +107,24 @@ CGame :: ~CGame( ) m_CallableGameAdd = NULL; } - for( vector :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) + for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) + for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) + for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) delete *i; delete m_DBGame; - for( vector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) + for( QVector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) delete *i; delete m_Stats; @@ -145,7 +145,7 @@ bool CGame :: Update( void *fd, void *send_fd ) { // update callables - for( vector :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); ) + for( QVector :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -164,13 +164,13 @@ bool CGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) + for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( vector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); @@ -187,7 +187,7 @@ bool CGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) + for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -195,7 +195,7 @@ bool CGame :: Update( void *fd, void *send_fd ) if( GamePlayerSummary ) { - if( i->first.empty( ) ) + if( i->first.isEmpty( ) ) SendAllChat( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), UTIL_ToString( GamePlayerSummary->GetTotalGames( ) ), UTIL_ToString( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 2 ), UTIL_ToString( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); else { @@ -207,7 +207,7 @@ bool CGame :: Update( void *fd, void *send_fd ) } else { - if( i->first.empty( ) ) + if( i->first.isEmpty( ) ) SendAllChat( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ) ); else { @@ -226,7 +226,7 @@ bool CGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) + for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -257,7 +257,7 @@ bool CGame :: Update( void *fd, void *send_fd ) UTIL_ToString( DotAPlayerSummary->GetAvgRaxKills( ), 2 ), UTIL_ToString( DotAPlayerSummary->GetAvgCourierKills( ), 2 ) ); - if( i->first.empty( ) ) + if( i->first.isEmpty( ) ) SendAllChat( Summary ); else { @@ -269,7 +269,7 @@ bool CGame :: Update( void *fd, void *send_fd ) } else { - if( i->first.empty( ) ) + if( i->first.isEmpty( ) ) SendAllChat( m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ) ); else { @@ -319,7 +319,7 @@ void CGame :: EventPlayerDeleted( CGamePlayer *player ) // also keep track of the last player to leave for the !banlast command - for( vector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) + for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) { if( (*i)->GetName( ) == player->GetName( ) ) m_DBBanLast = *i; @@ -353,7 +353,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri bool AdminCheck = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == player->GetSpoofedRealm( ) && (*i)->IsAdmin( User ) ) { @@ -364,7 +364,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri bool RootAdminCheck = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == player->GetSpoofedRealm( ) && (*i)->IsRootAdmin( User ) ) { @@ -401,7 +401,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !BAN // - if( ( Command == "addban" || Command == "ban" ) && !Payload.empty( ) && !m_GHost->m_BNETs.empty( ) ) + if( ( Command == "addban" || Command == "ban" ) && !Payload.isEmpty( ) && !m_GHost->m_BNETs.isEmpty( ) ) { // extract the victim and the reason // e.g. "Varlock leaver after dying" -> victim: "Varlock", reason: "leaver after dying" @@ -418,7 +418,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString :: size_type Start = Reason.find_first_not_of( " " ); if( Start != QString :: npos ) - Reason = Reason.substr( Start ); + Reason = Reason.mid( Start ); } if( m_GameLoaded ) @@ -431,7 +431,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") // we use the m_DBBans vector for this in case the player already left and thus isn't in the m_Players vector anymore - for( vector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) + for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) { QString TestName = (*i)->GetName( ); transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); @@ -478,7 +478,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "announce" && !m_CountDownStarted ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { SendAllChat( m_GHost->m_Language->AnnounceMessageDisabled( ) ); SetAnnounce( 0, QString( ) ); @@ -506,7 +506,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString :: size_type Start = Message.find_first_not_of( " " ); if( Start != QString :: npos ) - Message = Message.substr( Start ); + Message = Message.mid( Start ); SendAllChat( m_GHost->m_Language->AnnounceMessageEnabled( ) ); SetAnnounce( Interval, Message ); @@ -539,7 +539,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "autostart" && !m_CountDownStarted ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { SendAllChat( m_GHost->m_Language->AutoStartDisabled( ) ); m_AutoStartPlayers = 0; @@ -560,7 +560,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !BANLAST // - if( Command == "banlast" && m_GameLoaded && !m_GHost->m_BNETs.empty( ) && m_DBBanLast ) + if( Command == "banlast" && m_GameLoaded && !m_GHost->m_BNETs.isEmpty( ) && m_DBBanLast ) m_PairedBanAdds.push_back( PairedBanAdd( User, m_GHost->m_DB->ThreadedBanAdd( m_DBBanLast->GetServer( ), m_DBBanLast->GetName( ), m_DBBanLast->GetIP( ), m_GameName, User, Payload ) ) ); // @@ -569,7 +569,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "check" ) { - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) { CGamePlayer *LastMatch = NULL; uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); @@ -580,7 +580,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { bool LastMatchAdminCheck = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == LastMatch->GetSpoofedRealm( ) && (*i)->IsAdmin( LastMatch->GetName( ) ) ) { @@ -591,7 +591,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri bool LastMatchRootAdminCheck = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == LastMatch->GetSpoofedRealm( ) && (*i)->IsRootAdmin( LastMatch->GetName( ) ) ) { @@ -600,22 +600,22 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } } - SendAllChat( m_GHost->m_Language->CheckedPlayer( LastMatch->GetName( ), LastMatch->GetNumPings( ) > 0 ? UTIL_ToString( LastMatch->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_ByteArrayToUInt32( LastMatch->GetExternalIP( ), true ) ), LastMatchAdminCheck || LastMatchRootAdminCheck ? "Yes" : "No", IsOwner( LastMatch->GetName( ) ) ? "Yes" : "No", LastMatch->GetSpoofed( ) ? "Yes" : "No", LastMatch->GetSpoofedRealm( ).empty( ) ? "N/A" : LastMatch->GetSpoofedRealm( ), LastMatch->GetReserved( ) ? "Yes" : "No" ) ); + SendAllChat( m_GHost->m_Language->CheckedPlayer( LastMatch->GetName( ), LastMatch->GetNumPings( ) > 0 ? UTIL_ToString( LastMatch->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( LastMatch->GetExternalIP( ), true ) ), LastMatchAdminCheck || LastMatchRootAdminCheck ? "Yes" : "No", IsOwner( LastMatch->GetName( ) ) ? "Yes" : "No", LastMatch->GetSpoofed( ) ? "Yes" : "No", LastMatch->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : LastMatch->GetSpoofedRealm( ), LastMatch->GetReserved( ) ? "Yes" : "No" ) ); } else SendAllChat( m_GHost->m_Language->UnableToCheckPlayerFoundMoreThanOneMatch( Payload ) ); } else - SendAllChat( m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_ByteArrayToUInt32( player->GetExternalIP( ), true ) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).empty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); + SendAllChat( m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( player->GetExternalIP( ), true ) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); } // // !CHECKBAN // - if( Command == "checkban" && !Payload.empty( ) && !m_GHost->m_BNETs.empty( ) ) + if( Command == "checkban" && !Payload.isEmpty( ) && !m_GHost->m_BNETs.isEmpty( ) ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) m_PairedBanChecks.push_back( PairedBanCheck( User, m_GHost->m_DB->ThreadedBanCheck( (*i)->GetServer( ), Payload, QString( ) ) ) ); } @@ -633,7 +633,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !CLOSE (close slot) // - if( Command == "close" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded ) + if( Command == "close" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 @@ -666,7 +666,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !COMP (computer slot) // - if( Command == "comp" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) + if( Command == "comp" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) { // extract the slot and the skill // e.g. "1 2" -> slot: "1", skill: "2" @@ -695,7 +695,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !COMPCOLOUR (computer colour change) // - if( Command == "compcolour" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) + if( Command == "compcolour" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) { // extract the slot and the colour // e.g. "1 2" -> slot: "1", colour: "2" @@ -736,7 +736,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !COMPHANDICAP (computer handicap change) // - if( Command == "comphandicap" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) + if( Command == "comphandicap" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) { // extract the slot and the handicap // e.g. "1 50" -> slot: "1", handicap: "50" @@ -780,7 +780,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !COMPRACE (computer race change) // - if( Command == "comprace" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) + if( Command == "comprace" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) { // extract the slot and the race // e.g. "1 human" -> slot: "1", race: "human" @@ -803,7 +803,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString :: size_type Start = Race.find_first_not_of( " " ); if( Start != QString :: npos ) - Race = Race.substr( Start ); + Race = Race.mid( Start ); transform( Race.begin( ), Race.end( ), Race.begin( ), (int(*)(int))tolower ); unsigned char SID = (unsigned char)( Slot - 1 ); @@ -849,7 +849,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !COMPTEAM (computer team change) // - if( Command == "compteam" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) + if( Command == "compteam" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded && !m_SaveGame ) { // extract the slot and the team // e.g. "1 2" -> slot: "1", team: "2" @@ -901,7 +901,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !DL // - if( ( Command == "download" || Command == "dl" ) && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded ) + if( ( Command == "download" || Command == "dl" ) && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { CGamePlayer *LastMatch = NULL; uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); @@ -965,10 +965,10 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "fppause" && m_FakePlayerPID != 255 && m_GameLoaded ) { - BYTEARRAY CRC; - BYTEARRAY Action; + QByteArray CRC; + QByteArray Action; Action.push_back( 1 ); - m_Actions.push( new CIncomingAction( m_FakePlayerPID, CRC, Action ) ); + m_Actions.enqueue( new CIncomingAction( m_FakePlayerPID, CRC, Action ) ); } // @@ -977,10 +977,10 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "fpresume" && m_FakePlayerPID != 255 && m_GameLoaded ) { - BYTEARRAY CRC; - BYTEARRAY Action; + QByteArray CRC; + QByteArray Action; Action.push_back( 2 ); - m_Actions.push( new CIncomingAction( m_FakePlayerPID, CRC, Action ) ); + m_Actions.enqueue( new CIncomingAction( m_FakePlayerPID, CRC, Action ) ); } // @@ -991,13 +991,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { QString Froms; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { // we reverse the byte order on the IP because it's stored in network byte order Froms += (*i)->GetNameTerminated( ); Froms += ": ("; - Froms += m_GHost->m_DBLocal->FromCheck( UTIL_ByteArrayToUInt32( (*i)->GetExternalIP( ), true ) ); + Froms += m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( (*i)->GetExternalIP( ), true ) ); Froms += ")"; if( i != m_Players.end( ) - 1 ) @@ -1012,7 +1012,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } } - if( !Froms.empty( ) ) + if( !Froms.isEmpty( ) ) SendAllChat( Froms ); } @@ -1022,7 +1022,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "hcl" && !m_CountDownStarted ) { - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) { if( Payload.size( ) <= m_Slots.size( ) ) { @@ -1047,7 +1047,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !HOLD (hold a slot for someone) // - if( Command == "hold" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded ) + if( Command == "hold" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" @@ -1076,7 +1076,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !KICK (kick a player) // - if( Command == "kick" && !Payload.empty( ) ) + if( Command == "kick" && !Payload.isEmpty( ) ) { CGamePlayer *LastMatch = NULL; uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); @@ -1106,7 +1106,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "latency" ) { - if( Payload.empty( ) ) + if( Payload.isEmpty( ) ) SendAllChat( m_GHost->m_Language->LatencyIs( UTIL_ToString( m_Latency ) ) ); else { @@ -1189,7 +1189,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !OPEN (open slot) // - if( Command == "open" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded ) + if( Command == "open" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { // open as many slots as specified, e.g. "5 10" opens slots 5 and 10 @@ -1226,7 +1226,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( RootAdminCheck || IsOwner( User ) || !GetPlayerFromName( m_OwnerName, false ) ) { - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) { SendAllChat( m_GHost->m_Language->SettingGameOwnerTo( Payload ) ); m_OwnerName = Payload; @@ -1253,16 +1253,16 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Kicked = 0; uint32_t KickPing = 0; - if( !m_GameLoading && !m_GameLoaded && !Payload.empty( ) ) + if( !m_GameLoading && !m_GameLoaded && !Payload.isEmpty( ) ) KickPing = UTIL_ToUInt32( Payload ); // copy the m_Players vector so we can sort by descending ping so it's easier to find players with high pings - vector SortedPlayers = m_Players; + QVector SortedPlayers = m_Players; sort( SortedPlayers.begin( ), SortedPlayers.end( ), CGamePlayerSortDescByPing( ) ); QString Pings; - for( vector :: iterator i = SortedPlayers.begin( ); i != SortedPlayers.end( ); i++ ) + for( QVector :: iterator i = SortedPlayers.begin( ); i != SortedPlayers.end( ); i++ ) { Pings += (*i)->GetNameTerminated( ); Pings += ": "; @@ -1297,7 +1297,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } } - if( !Pings.empty( ) ) + if( !Pings.isEmpty( ) ) SendAllChat( Pings ); if( Kicked > 0 ) @@ -1308,7 +1308,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !PRIV (rehost as private game) // - if( Command == "priv" && !Payload.empty( ) && !m_CountDownStarted && !m_SaveGame ) + if( Command == "priv" && !Payload.isEmpty( ) && !m_CountDownStarted && !m_SaveGame ) { CONSOLE_Print( "[GAME: " + m_GameName + "] trying to rehost as private game [" + Payload + "]" ); SendAllChat( m_GHost->m_Language->TryingToRehostAsPrivateGame( Payload ) ); @@ -1319,7 +1319,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_RefreshError = false; m_RefreshRehosted = true; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // unqueue any existing game refreshes because we're going to assume the next successful game refresh indicates that the rehost worked // this ignores the fact that it's possible a game refresh was just sent and no response has been received yet @@ -1345,7 +1345,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !PUB (rehost as public game) // - if( Command == "pub" && !Payload.empty( ) && !m_CountDownStarted && !m_SaveGame ) + if( Command == "pub" && !Payload.isEmpty( ) && !m_CountDownStarted && !m_SaveGame ) { CONSOLE_Print( "[GAME: " + m_GameName + "] trying to rehost as public game [" + Payload + "]" ); SendAllChat( m_GHost->m_Language->TryingToRehostAsPublicGame( Payload ) ); @@ -1356,7 +1356,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_RefreshError = false; m_RefreshRehosted = true; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // unqueue any existing game refreshes because we're going to assume the next successful game refresh indicates that the rehost worked // this ignores the fact that it's possible a game refresh was just sent and no response has been received yet @@ -1395,9 +1395,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !SAY // - if( Command == "say" && !Payload.empty( ) ) + if( Command == "say" && !Payload.isEmpty( ) ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Payload ); HideCommand = true; @@ -1407,7 +1407,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !SENDLAN // - if( Command == "sendlan" && !Payload.empty( ) && !m_CountDownStarted ) + if( Command == "sendlan" && !Payload.isEmpty( ) && !m_CountDownStarted ) { // extract the ip and the port // e.g. "1.2.3.4 6112" -> ip: "1.2.3.4", port: "6112" @@ -1439,13 +1439,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; - BYTEARRAY MapWidth; + QByteArray MapWidth; MapWidth.push_back( 0 ); MapWidth.push_back( 0 ); - BYTEARRAY MapHeight; + QByteArray MapHeight; MapHeight.push_back( 0 ); MapHeight.push_back( 0 ); - m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ) ); + m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ) ); } else { @@ -1453,7 +1453,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ) ); + m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ) ); } } } @@ -1492,7 +1492,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !SWAP (swap slots) // - if( Command == "swap" && !Payload.empty( ) && !m_GameLoading && !m_GameLoaded ) + if( Command == "swap" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { uint32_t SID1; uint32_t SID2; @@ -1524,7 +1524,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "synclimit" ) { - if( Payload.empty( ) ) + if( Payload.isEmpty( ) ) SendAllChat( m_GHost->m_Language->SyncLimitIs( UTIL_ToString( m_SyncLimit ) ) ); else { @@ -1596,7 +1596,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !VIRTUALHOST // - if( Command == "virtualhost" && !Payload.empty( ) && Payload.size( ) <= 15 && !m_CountDownStarted ) + if( Command == "virtualhost" && !Payload.isEmpty( ) && Payload.size( ) <= 15 && !m_CountDownStarted ) { DeleteVirtualHost( ); m_VirtualHostName = Payload; @@ -1606,7 +1606,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !VOTECANCEL // - if( Command == "votecancel" && !m_KickVotePlayer.empty( ) ) + if( Command == "votecancel" && !m_KickVotePlayer.isEmpty( ) ) { SendAllChat( m_GHost->m_Language->VoteKickCancelled( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); @@ -1617,7 +1617,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !W // - if( Command == "w" && !Payload.empty( ) ) + if( Command == "w" && !Payload.isEmpty( ) ) { // extract the name and the message // e.g. "Varlock hello there!" -> name: "Varlock", message: "hello there!" @@ -1628,10 +1628,10 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( MessageStart != QString :: npos ) { - Name = Payload.substr( 0, MessageStart ); - Message = Payload.substr( MessageStart + 1 ); + Name = Payload.mid( 0, MessageStart ); + Message = Payload.mid( MessageStart + 1 ); - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Message, Name, true ); } @@ -1661,7 +1661,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // if( Command == "checkme" ) - SendChat( player, m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_ByteArrayToUInt32( player->GetExternalIP( ), true ) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).empty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); + SendChat( player, m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( player->GetExternalIP( ), true ) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); // // !STATS @@ -1671,7 +1671,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { QString StatsUser = User; - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) StatsUser = Payload; if( player->GetSpoofed( ) && ( AdminCheck || RootAdminCheck || IsOwner( User ) ) ) @@ -1690,7 +1690,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { QString StatsUser = User; - if( !Payload.empty( ) ) + if( !Payload.isEmpty( ) ) StatsUser = Payload; if( player->GetSpoofed( ) && ( AdminCheck || RootAdminCheck || IsOwner( User ) ) ) @@ -1717,9 +1717,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !VOTEKICK // - if( Command == "votekick" && m_GHost->m_VoteKickAllowed && !Payload.empty( ) ) + if( Command == "votekick" && m_GHost->m_VoteKickAllowed && !Payload.isEmpty( ) ) { - if( !m_KickVotePlayer.empty( ) ) + if( !m_KickVotePlayer.isEmpty( ) ) SendChat( player, m_GHost->m_Language->UnableToVoteKickAlreadyInProgress( ) ); else if( m_Players.size( ) == 2 ) SendChat( player, m_GHost->m_Language->UnableToVoteKickNotEnoughPlayers( ) ); @@ -1739,7 +1739,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_KickVotePlayer = LastMatch->GetName( ); m_StartedKickVoteTime = GetTime( ); - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->SetKickVote( false ); player->SetKickVote( true ); @@ -1757,13 +1757,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // !YES // - if( Command == "yes" && !m_KickVotePlayer.empty( ) && player->GetName( ) != m_KickVotePlayer && !player->GetKickVote( ) ) + if( Command == "yes" && !m_KickVotePlayer.isEmpty( ) && player->GetName( ) != m_KickVotePlayer && !player->GetKickVote( ) ) { player->SetKickVote( true ); uint32_t VotesNeeded = (uint32_t)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ); uint32_t Votes = 0; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetKickVote( ) ) Votes++; @@ -1811,7 +1811,7 @@ void CGame :: EventGameStarted( ) // but since the player has already left the game we don't have access to their information anymore // so we create a "potential ban" for each player and only store it in the database if requested to by an admin - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) m_DBBans.push_back( new CDBBan( (*i)->GetJoinedRealm( ), (*i)->GetName( ), (*i)->GetExternalIPString( ), QString( ), QString( ), QString( ), QString( ) ) ); } diff --git a/ghost/game.h b/ghost/game.h index 4d45f17..9318d4a 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -44,15 +44,15 @@ class CGame : public CBaseGame { protected: CDBBan *m_DBBanLast; // last ban for the !banlast command - this is a pointer to one of the items in m_DBBans - vector m_DBBans; // vector of potential ban data for the database (see the Update function for more info, it's not as straightforward as you might think) + QVector m_DBBans; // vector of potential ban data for the database (see the Update function for more info, it's not as straightforward as you might think) CDBGame *m_DBGame; // potential game data for the database - vector m_DBGamePlayers; // vector of potential gameplayer data for the database + QVector m_DBGamePlayers; // vector of potential gameplayer data for the database CStats *m_Stats; // class to keep track of game stats such as kills/deaths/assists in dota CCallableGameAdd *m_CallableGameAdd; // threaded database game addition in progress - vector m_PairedBanChecks; // vector of paired threaded database ban checks in progress - vector m_PairedBanAdds; // vector of paired threaded database ban adds in progress - vector m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress - vector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress + QVector m_PairedBanChecks; // vector of paired threaded database ban checks in progress + QVector m_PairedBanAdds; // vector of paired threaded database ban adds in progress + QVector m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress + QVector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress public: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index ea0443f..68bfe55 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -34,7 +34,7 @@ #include "game_base.h" #include "game_admin.h" -#include +#include #include @@ -53,26 +53,26 @@ CAdminGame :: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint CAdminGame :: ~CAdminGame( ) { - for( vector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) + for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) + for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) + for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( vector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); /* - for( vector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); */ - for( vector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) + for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); } @@ -82,7 +82,7 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) // update callables // - for( vector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) + for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) { if( i->second->GetReady( ) ) { @@ -108,13 +108,13 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) + for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( vector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->AddAdmin( i->second->GetUser( ) ); @@ -139,13 +139,13 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) + for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( vector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->RemoveAdmin( i->second->GetUser( ) ); @@ -170,7 +170,7 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) + for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) { if( i->second->GetReady( ) ) { @@ -198,13 +198,13 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) /* - for( vector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) + for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( vector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); @@ -231,13 +231,13 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) */ - for( vector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) + for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( vector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->RemoveBan( i->second->GetUser( ) ); @@ -270,7 +270,7 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) void CAdminGame :: SendAdminChat( QString message ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLoggedIn( ) ) SendChat( *i, message ); @@ -293,7 +293,7 @@ void CAdminGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoin { uint32_t Time = GetTime( ); - for( vector :: iterator i = m_TempBans.begin( ); i != m_TempBans.end( ); ) + for( QVector :: iterator i = m_TempBans.begin( ); i != m_TempBans.end( ); ) { // remove old tempbans (after 5 seconds) @@ -340,7 +340,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !ADDADMIN // - if( Command == "addadmin" && !Payload.empty( ) ) + if( Command == "addadmin" && !Payload.isEmpty( ) ) { // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" @@ -361,14 +361,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else SS >> Server; - if( !Server.empty( ) ) + if( !Server.isEmpty( ) ) { QString Servers; bool FoundServer = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { - if( Servers.empty( ) ) + if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); else Servers += ", " + (*i)->GetServer( ); @@ -397,7 +397,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "autohost" ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { SendChat( player, m_GHost->m_Language->AutoHostDisabled( ) ); m_GHost->m_AutoHostGameName.clear( ); @@ -440,7 +440,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString :: size_type Start = GameName.find_first_not_of( " " ); if( Start != QString :: npos ) - GameName = GameName.substr( Start ); + GameName = GameName.mid( Start ); SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); delete m_GHost->m_AutoHostMap; @@ -466,7 +466,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "autohostmm" ) { - if( Payload.empty( ) || Payload == "off" ) + if( Payload.isEmpty( ) || Payload == "off" ) { SendChat( player, m_GHost->m_Language->AutoHostDisabled( ) ); m_GHost->m_AutoHostGameName.clear( ); @@ -523,7 +523,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString :: size_type Start = GameName.find_first_not_of( " " ); if( Start != QString :: npos ) - GameName = GameName.substr( Start ); + GameName = GameName.mid( Start ); SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); delete m_GHost->m_AutoHostMap; @@ -549,7 +549,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !CHECKADMIN // - if( Command == "checkadmin" && !Payload.empty( ) ) + if( Command == "checkadmin" && !Payload.isEmpty( ) ) { // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" @@ -570,14 +570,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else SS >> Server; - if( !Server.empty( ) ) + if( !Server.isEmpty( ) ) { QString Servers; bool FoundServer = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { - if( Servers.empty( ) ) + if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); else Servers += ", " + (*i)->GetServer( ); @@ -604,7 +604,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !CHECKBAN // - if( Command == "checkban" && !Payload.empty( ) ) + if( Command == "checkban" && !Payload.isEmpty( ) ) { // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" @@ -625,14 +625,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else SS >> Server; - if( !Server.empty( ) ) + if( !Server.isEmpty( ) ) { QString Servers; bool FoundServer = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { - if( Servers.empty( ) ) + if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); else Servers += ", " + (*i)->GetServer( ); @@ -664,10 +664,10 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { QString Server = Payload; - if( Server.empty( ) && m_GHost->m_BNETs.size( ) == 1 ) + if( Server.isEmpty( ) && m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); - if( !Server.empty( ) ) + if( !Server.isEmpty( ) ) m_PairedAdminCounts.push_back( PairedAdminCount( player->GetName( ), m_GHost->m_DB->ThreadedAdminCount( Server ) ) ); } @@ -679,10 +679,10 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { QString Server = Payload; - if( Server.empty( ) && m_GHost->m_BNETs.size( ) == 1 ) + if( Server.isEmpty( ) && m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); - if( !Server.empty( ) ) + if( !Server.isEmpty( ) ) m_PairedBanCounts.push_back( PairedBanCount( player->GetName( ), m_GHost->m_DB->ThreadedBanCount( Server ) ) ); } @@ -690,7 +690,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !DELADMIN // - if( Command == "deladmin" && !Payload.empty( ) ) + if( Command == "deladmin" && !Payload.isEmpty( ) ) { // extract the name and the server // e.g. "Varlock useast.battle.net" -> name: "Varlock", server: "useast.battle.net" @@ -711,14 +711,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else SS >> Server; - if( !Server.empty( ) ) + if( !Server.isEmpty( ) ) { QString Servers; bool FoundServer = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { - if( Servers.empty( ) ) + if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); else Servers += ", " + (*i)->GetServer( ); @@ -746,7 +746,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !UNBAN // - if( ( Command == "delban" || Command == "unban" ) && !Payload.empty( ) ) + if( ( Command == "delban" || Command == "unban" ) && !Payload.isEmpty( ) ) m_PairedBanRemoves.push_back( PairedBanRemove( player->GetName( ), m_GHost->m_DB->ThreadedBanRemove( Payload ) ) ); // @@ -763,7 +763,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !DOWNLOADS // - if( Command == "downloads" && !Payload.empty( ) ) + if( Command == "downloads" && !Payload.isEmpty( ) ) { uint32_t Downloads = UTIL_ToUInt32( Payload ); @@ -798,7 +798,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !END // - if( Command == "end" && !Payload.empty( ) ) + if( Command == "end" && !Payload.isEmpty( ) ) { // todotodo: what if a game ends just as you're typing this command and the numbering changes? @@ -818,7 +818,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !ENFORCESG // - if( Command == "enforcesg" && !Payload.empty( ) ) + if( Command == "enforcesg" && !Payload.isEmpty( ) ) { // only load files in the current directory just to be safe @@ -855,7 +855,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, m_Exiting = true; else { - if( m_GHost->m_CurrentGame || !m_GHost->m_Games.empty( ) ) + if( m_GHost->m_CurrentGame || !m_GHost->m_Games.isEmpty( ) ) SendChat( player, m_GHost->m_Language->AtLeastOneGameActiveUseForceToShutdown( ) ); else m_Exiting = true; @@ -866,7 +866,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !GETGAME // - if( Command == "getgame" && !Payload.empty( ) ) + if( Command == "getgame" && !Payload.isEmpty( ) ) { uint32_t GameNumber = UTIL_ToUInt32( Payload ) - 1; @@ -892,7 +892,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !HOSTSG // - if( Command == "hostsg" && !Payload.empty( ) ) + if( Command == "hostsg" && !Payload.isEmpty( ) ) m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, true, Payload, User, User, QString( ), false ); // @@ -901,7 +901,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "load" ) { - if( Payload.empty( ) ) + if( Payload.isEmpty( ) ) SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); else { @@ -936,7 +936,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, LastMatch = i->path( ); Matches++; - if( FoundMapConfigs.empty( ) ) + if( FoundMapConfigs.isEmpty( ) ) FoundMapConfigs = i->filename( ); else FoundMapConfigs += ", " + i->filename( ); @@ -977,7 +977,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !LOADSG // - if( Command == "loadsg" && !Payload.empty( ) ) + if( Command == "loadsg" && !Payload.isEmpty( ) ) { // only load files in the current directory just to be safe @@ -1012,7 +1012,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "map" ) { - if( Payload.empty( ) ) + if( Payload.isEmpty( ) ) SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); else { @@ -1047,7 +1047,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, LastMatch = i->path( ); Matches++; - if( FoundMaps.empty( ) ) + if( FoundMaps.isEmpty( ) ) FoundMaps = i->filename( ); else FoundMaps += ", " + i->filename( ); @@ -1092,14 +1092,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !PRIV (host private game) // - if( Command == "priv" && !Payload.empty( ) ) + if( Command == "priv" && !Payload.isEmpty( ) ) m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, Payload, User, User, QString( ), false ); // // !PRIVBY (host private game by other player) // - if( Command == "privby" && !Payload.empty( ) ) + if( Command == "privby" && !Payload.isEmpty( ) ) { // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" @@ -1110,8 +1110,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( GameNameStart != QString :: npos ) { - Owner = Payload.substr( 0, GameNameStart ); - GameName = Payload.substr( GameNameStart + 1 ); + Owner = Payload.mid( 0, GameNameStart ); + GameName = Payload.mid( GameNameStart + 1 ); m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, GameName, Owner, User, QString( ), false ); } } @@ -1120,14 +1120,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !PUB (host public game) // - if( Command == "pub" && !Payload.empty( ) ) + if( Command == "pub" && !Payload.isEmpty( ) ) m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, Payload, User, User, QString( ), false ); // // !PUBBY (host public game by other player) // - if( Command == "pubby" && !Payload.empty( ) ) + if( Command == "pubby" && !Payload.isEmpty( ) ) { // extract the owner and the game name // e.g. "Varlock dota 6.54b arem ~~~" -> owner: "Varlock", game name: "dota 6.54b arem ~~~" @@ -1138,8 +1138,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( GameNameStart != QString :: npos ) { - Owner = Payload.substr( 0, GameNameStart ); - GameName = Payload.substr( GameNameStart + 1 ); + Owner = Payload.mid( 0, GameNameStart ); + GameName = Payload.mid( GameNameStart + 1 ); m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, GameName, Owner, User, QString( ), false ); } } @@ -1158,9 +1158,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !SAY // - if( Command == "say" && !Payload.empty( ) ) + if( Command == "say" && !Payload.isEmpty( ) ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Payload ); } @@ -1168,7 +1168,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !SAYGAME // - if( Command == "saygame" && !Payload.empty( ) ) + if( Command == "saygame" && !Payload.isEmpty( ) ) { // extract the game number and the message // e.g. "3 hello everyone" -> game number: "3", message: "hello everyone" @@ -1191,7 +1191,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString :: size_type Start = Message.find_first_not_of( " " ); if( Start != QString :: npos ) - Message = Message.substr( Start ); + Message = Message.mid( Start ); if( GameNumber - 1 < m_GHost->m_Games.size( ) ) m_GHost->m_Games[GameNumber - 1]->SendAllChat( "ADMIN: " + Message ); @@ -1205,12 +1205,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !SAYGAMES // - if( Command == "saygames" && !Payload.empty( ) ) + if( Command == "saygames" && !Payload.isEmpty( ) ) { if( m_GHost->m_CurrentGame ) m_GHost->m_CurrentGame->SendAllChat( Payload ); - for( vector :: iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) (*i)->SendAllChat( "ADMIN: " + Payload ); } @@ -1238,7 +1238,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // !W // - if( Command == "w" && !Payload.empty( ) ) + if( Command == "w" && !Payload.isEmpty( ) ) { // extract the name and the message // e.g. "Varlock hello there!" -> name: "Varlock", message: "hello there!" @@ -1249,10 +1249,10 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( MessageStart != QString :: npos ) { - Name = Payload.substr( 0, MessageStart ); - Message = Payload.substr( MessageStart + 1 ); + Name = Payload.mid( 0, MessageStart ); + Message = Payload.mid( MessageStart + 1 ); - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Message, Name, true ); } } @@ -1270,7 +1270,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "password" && !player->GetLoggedIn( ) ) { - if( !m_Password.empty( ) && Payload == m_Password ) + if( !m_Password.isEmpty( ) && Payload == m_Password ) { CONSOLE_Print( "[ADMINGAME] user [" + User + "] logged in" ); SendChat( player, m_GHost->m_Language->AdminLoggedIn( ) ); diff --git a/ghost/game_admin.h b/ghost/game_admin.h index 04fdf07..660f822 100644 --- a/ghost/game_admin.h +++ b/ghost/game_admin.h @@ -45,13 +45,13 @@ class CAdminGame : public CBaseGame { protected: QString m_Password; - vector m_TempBans; - vector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress - vector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress - vector m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress - vector m_PairedBanCounts; // vector of paired threaded database ban counts in progress - // vector m_PairedBanAdds; // vector of paired threaded database ban adds in progress - vector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress + QVector m_TempBans; + QVector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress + QVector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress + QVector m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress + QVector m_PairedBanCounts; // vector of paired threaded database ban counts in progress + // QVector m_PairedBanAdds; // vector of paired threaded database ban adds in progress + QVector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress public: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 2bb8580..91ea5f2 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -34,7 +34,7 @@ #include "game_base.h" #include -#include +#include #include #include "next_combination.h" @@ -142,7 +142,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 // we really just want the open/closed/computer entries // so open all the player slots - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 ) { @@ -155,7 +155,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 else m_Slots = m_Map->GetSlots( ); - if( !m_GHost->m_IPBlackListFile.empty( ) ) + if( !m_GHost->m_IPBlackListFile.isEmpty( ) ) { ifstream in; in.open( m_GHost->m_IPBlackListFile.c_str( ) ); @@ -173,7 +173,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 // ignore blank lines and comments - if( Line.empty( ) || Line[0] == '#' ) + if( Line.isEmpty( ) || Line[0] == '#' ) continue; // remove newlines and partial newlines to help fix issues with Windows formatted files on Linux systems @@ -198,7 +198,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 // start listening for connections - if( !m_GHost->m_BindAddress.empty( ) ) + if( !m_GHost->m_BindAddress.isEmpty( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] attempting to bind to address [" + m_GHost->m_BindAddress + "]" ); else CONSOLE_Print( "[GAME: " + m_GameName + "] attempting to bind to all available addresses" ); @@ -241,19 +241,19 @@ CBaseGame :: ~CBaseGame( ) delete m_Map; delete m_Replay; - for( vector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) delete *i; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) delete *i; - for( vector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); i++ ) + for( QVector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); i++ ) m_GHost->m_Callables.push_back( *i ); - while( !m_Actions.empty( ) ) + while( !m_Actions.isEmpty( ) ) { delete m_Actions.front( ); - m_Actions.pop( ); + m_Actions.dequeue( ); } } @@ -279,7 +279,7 @@ uint32_t CBaseGame :: GetSlotsOccupied( ) { uint32_t NumSlotsOccupied = 0; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED ) NumSlotsOccupied++; @@ -292,7 +292,7 @@ uint32_t CBaseGame :: GetSlotsOpen( ) { uint32_t NumSlotsOpen = 0; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OPEN ) NumSlotsOpen++; @@ -315,7 +315,7 @@ uint32_t CBaseGame :: GetNumHumanPlayers( ) { uint32_t NumHumanPlayers = 0; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) NumHumanPlayers++; @@ -353,7 +353,7 @@ unsigned int CBaseGame :: SetFD( void *fd, void *send_fd, int *nfds ) NumFDs++; } - for( vector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) { if( (*i)->GetSocket( ) ) { @@ -362,7 +362,7 @@ unsigned int CBaseGame :: SetFD( void *fd, void *send_fd, int *nfds ) } } - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetSocket( ) ) { @@ -378,13 +378,13 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { // update callables - for( vector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); ) + for( QVector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); ) { if( (*i)->GetReady( ) ) { double Score = (*i)->GetResult( ); - for( vector :: iterator j = m_Potentials.begin( ); j != m_Potentials.end( ); j++ ) + for( QVector :: iterator j = m_Potentials.begin( ); j != m_Potentials.end( ); j++ ) { if( (*j)->GetJoinPlayer( ) && (*j)->GetJoinPlayer( )->GetName( ) == (*i)->GetName( ) ) EventPlayerJoinedWithScore( *j, (*j)->GetJoinPlayer( ), Score ); @@ -400,7 +400,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // update players - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); ) { if( (*i)->Update( fd ) ) { @@ -412,7 +412,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) i++; } - for( vector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); ) + for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); ) { if( (*i)->Update( fd ) ) { @@ -474,13 +474,13 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; - BYTEARRAY MapWidth; + QByteArray MapWidth; MapWidth.push_back( 0 ); MapWidth.push_back( 0 ); - BYTEARRAY MapHeight; + QByteArray MapHeight; MapHeight.push_back( 0 ); MapHeight.push_back( 0 ); - m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, FixedHostCounter ) ); + m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, FixedHostCounter ) ); } else { @@ -488,7 +488,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ) ); + m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ) ); } } @@ -497,7 +497,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // auto rehost if there was a refresh error in autohosted games - if( m_RefreshError && !m_CountDownStarted && m_GameState == GAME_PUBLIC && !m_GHost->m_AutoHostGameName.empty( ) && m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) + if( m_RefreshError && !m_CountDownStarted && m_GameState == GAME_PUBLIC && !m_GHost->m_AutoHostGameName.isEmpty( ) && m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) { // there's a slim chance that this isn't actually an autohosted game since there is no explicit autohost flag // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted @@ -510,7 +510,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) m_HostCounter = m_GHost->m_HostCounter++; m_RefreshError = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { (*i)->QueueGameUncreate( ); (*i)->QueueEnterChat( ); @@ -530,7 +530,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) bool Refreshed = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // don't queue a game refresh message if the queue contains more than 1 packet because they're very low priority @@ -567,7 +567,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { uint32_t Downloaders = 0; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetDownloadStarted( ) && !(*i)->GetDownloadFinished( ) ) { @@ -590,7 +590,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // in addition to this, the throughput is limited by the configuration value bot_maxdownloadspeed // in summary: the actual throughput is MIN( 140 * 1000 / ping, 1400, bot_maxdownloadspeed ) in KB/sec assuming only one player is downloading the map - uint32_t MapSize = UTIL_ByteArrayToUInt32( m_Map->GetMapSize( ), false ); + uint32_t MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); while( (*i)->GetLastMapPartSent( ) < (*i)->GetLastMapPartAcked( ) + 1442 * 100 && (*i)->GetLastMapPartSent( ) < MapSize ) { @@ -620,7 +620,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // announce every m_AnnounceInterval seconds - if( !m_AnnounceMessage.empty( ) && !m_CountDownStarted && GetTime( ) - m_LastAnnounceTime >= m_AnnounceInterval ) + if( !m_AnnounceMessage.isEmpty( ) && !m_CountDownStarted && GetTime( ) - m_LastAnnounceTime >= m_AnnounceInterval ) { SendAllChat( m_AnnounceMessage ); m_LastAnnounceTime = GetTime( ); @@ -628,9 +628,9 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // kick players who don't spoof check within 20 seconds when spoof checks are required and the game is autohosted - if( !m_CountDownStarted && m_GHost->m_RequireSpoofChecks && m_GameState == GAME_PUBLIC && !m_GHost->m_AutoHostGameName.empty( ) && m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) + if( !m_CountDownStarted && m_GHost->m_RequireSpoofChecks && m_GameState == GAME_PUBLIC && !m_GHost->m_AutoHostGameName.isEmpty( ) && m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetSpoofed( ) && GetTime( ) - (*i)->GetJoinTime( ) >= 20 ) { @@ -675,7 +675,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { // check if there's a player with reserved status in the game - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetReserved( ) ) m_LastReservedSeen = GetTime( ); @@ -696,7 +696,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { bool FinishedLoading = true; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { FinishedLoading = (*i)->GetFinishedLoading( ); @@ -719,19 +719,19 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { bool UsingGProxy = false; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) UsingGProxy = true; } - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetFinishedLoading( ) ) { // stop the lag screen - for( vector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { if( !(*j)->GetFinishedLoading( ) ) Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j, true ) ); @@ -750,10 +750,10 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // empty actions are used to extend the time a player can use when reconnecting for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); } - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); // start the lag screen @@ -770,10 +770,10 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // empty actions are used to extend the time a player can use when reconnecting for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); } - (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); } } @@ -784,10 +784,10 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) if( UsingGProxy ) { for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) - m_Replay->AddTimeSlot( 0, queue( ) ); + m_Replay->AddTimeSlot( 0, QQueue( ) ); } - m_Replay->AddTimeSlot( 0, queue( ) ); + m_Replay->AddTimeSlot( 0, QQueue( ) ); } // Warcraft III doesn't seem to respond to empty actions @@ -813,7 +813,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { QString LaggingString; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( m_SyncCounter - (*i)->GetSyncCounter( ) > m_SyncLimit ) { @@ -822,7 +822,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) m_Lagging = true; m_StartedLaggingTime = GetTime( ); - if( LaggingString.empty( ) ) + if( LaggingString.isEmpty( ) ) LaggingString = (*i)->GetName( ); else LaggingString += ", " + (*i)->GetName( ); @@ -838,7 +838,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // reset everyone's drop vote - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->SetDropVote( false ); m_LastLagScreenResetTime = GetTime( ); @@ -849,7 +849,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { bool UsingGProxy = false; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) UsingGProxy = true; @@ -870,11 +870,11 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) if( GetTime( ) - m_LastLagScreenResetTime >= 60 ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { // stop the lag screen - for( vector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { if( (*j)->GetLagging( ) ) Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j ) ); @@ -890,10 +890,10 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // empty actions are used to extend the time a player can use when reconnecting for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); } - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); // start the lag screen @@ -907,10 +907,10 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) if( UsingGProxy ) { for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) - m_Replay->AddTimeSlot( 0, queue( ) ); + m_Replay->AddTimeSlot( 0, QQueue( ) ); } - m_Replay->AddTimeSlot( 0, queue( ) ); + m_Replay->AddTimeSlot( 0, QQueue( ) ); } // Warcraft III doesn't seem to respond to empty actions @@ -925,7 +925,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // check if anyone has stopped lagging normally // we consider a player to have stopped lagging if they're less than half m_SyncLimit keepalives behind - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLagging( ) && m_SyncCounter - (*i)->GetSyncCounter( ) < m_SyncLimit / 2 ) { @@ -942,7 +942,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) bool Lagging = false; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLagging( ) ) Lagging = true; @@ -969,7 +969,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // expire the votekick - if( !m_KickVotePlayer.empty( ) && GetTime( ) - m_StartedKickVoteTime >= 60 ) + if( !m_KickVotePlayer.isEmpty( ) && GetTime( ) - m_StartedKickVoteTime >= 60 ) { CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] expired" ); SendAllChat( m_GHost->m_Language->VoteKickExpired( m_KickVotePlayer ) ); @@ -991,7 +991,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) { bool AlreadyStopped = true; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetDeleteMe( ) ) { @@ -1009,7 +1009,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) // end the game if there aren't any players left - if( m_Players.empty( ) && ( m_GameLoading || m_GameLoaded ) ) + if( m_Players.isEmpty( ) && ( m_GameLoading || m_GameLoaded ) ) { if( !m_Saving ) { @@ -1058,39 +1058,39 @@ void CBaseGame :: UpdatePost( void *send_fd ) // this is in case player 2 generates a packet for player 1 during the update but it doesn't get sent because player 1 already finished updating // in reality since we're queueing actions it might not make a big difference but oh well - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetSocket( ) ) (*i)->GetSocket( )->DoSend( (fd_set *)send_fd ); } - for( vector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) { if( (*i)->GetSocket( ) ) (*i)->GetSocket( )->DoSend( (fd_set *)send_fd ); } } -void CBaseGame :: Send( CGamePlayer *player, BYTEARRAY data ) +void CBaseGame :: Send( CGamePlayer *player, QByteArray data ) { if( player ) player->Send( data ); } -void CBaseGame :: Send( unsigned char PID, BYTEARRAY data ) +void CBaseGame :: Send( unsigned char PID, QByteArray data ) { Send( GetPlayerFromPID( PID ), data ); } -void CBaseGame :: Send( BYTEARRAY PIDs, BYTEARRAY data ) +void CBaseGame :: Send( QByteArray PIDs, QByteArray data ) { for( unsigned int i = 0; i < PIDs.size( ); i++ ) Send( PIDs[i], data ); } -void CBaseGame :: SendAll( BYTEARRAY data ) +void CBaseGame :: SendAll( QByteArray data ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->Send( data ); } @@ -1103,9 +1103,9 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString if( !m_GameLoading && !m_GameLoaded ) { if( message.size( ) > 254 ) - message = message.substr( 0, 254 ); + message = message.mid( 0, 254 ); - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateByteArray( player->GetPID( ) ), 16, BYTEARRAY( ), message ) ); + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateQByteArray( player->GetPID( ) ), 16, QByteArray( ), message ) ); } else { @@ -1119,9 +1119,9 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString ExtraFlags[0] = 3 + m_Slots[SID].GetColour( ); if( message.size( ) > 127 ) - message = message.substr( 0, 127 ); + message = message.mid( 0, 127 ); - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateByteArray( player->GetPID( ) ), 32, UTIL_CreateByteArray( ExtraFlags, 4 ), message ) ); + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateQByteArray( player->GetPID( ) ), 32, UTIL_CreateQByteArray( ExtraFlags, 4 ), message ) ); } } } @@ -1152,16 +1152,16 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) if( !m_GameLoading && !m_GameLoaded ) { if( message.size( ) > 254 ) - message = message.substr( 0, 254 ); + message = message.mid( 0, 254 ); - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 16, BYTEARRAY( ), message ) ); + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 16, QByteArray( ), message ) ); } else { if( message.size( ) > 127 ) - message = message.substr( 0, 127 ); + message = message.mid( 0, 127 ); - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateByteArray( (uint32_t)0, false ), message ) ); + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateQByteArray( (uint32_t)0, false ), message ) ); if( m_Replay ) m_Replay->AddChatMessage( fromPID, 32, 0, message ); @@ -1183,7 +1183,7 @@ void CBaseGame :: SendLocalAdminChat( QString message ) // at the time of this writing it is only possible for the game owner to meet this criteria because being an admin requires spoof checking // this is mainly used for relaying battle.net whispers, chat messages, and emotes to these players - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetSpoofed( ) && IsOwner( (*i)->GetName( ) ) && ( UTIL_IsLanIP( (*i)->GetExternalIP( ) ) || UTIL_IsLocalIP( (*i)->GetExternalIP( ), m_GHost->m_LocalAddresses ) ) ) { @@ -1213,7 +1213,7 @@ void CBaseGame :: SendVirtualHostPlayerInfo( CGamePlayer *player ) if( m_VirtualHostPID == 255 ) return; - BYTEARRAY IP; + QByteArray IP; IP.push_back( 0 ); IP.push_back( 0 ); IP.push_back( 0 ); @@ -1226,7 +1226,7 @@ void CBaseGame :: SendFakePlayerInfo( CGamePlayer *player ) if( m_FakePlayerPID == 255 ) return; - BYTEARRAY IP; + QByteArray IP; IP.push_back( 0 ); IP.push_back( 0 ); IP.push_back( 0 ); @@ -1238,7 +1238,7 @@ void CBaseGame :: SendAllActions( ) { bool UsingGProxy = false; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) UsingGProxy = true; @@ -1252,19 +1252,19 @@ void CBaseGame :: SendAllActions( ) // GProxy++ will insert these itself so we don't need to send them to GProxy++ players // empty actions are used to extend the time a player can use when reconnecting - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetGProxy( ) ) { for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue( ), 0 ) ); + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); } } if( m_Replay ) { for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) - m_Replay->AddTimeSlot( 0, queue( ) ); + m_Replay->AddTimeSlot( 0, QQueue( ) ); } } @@ -1277,21 +1277,21 @@ void CBaseGame :: SendAllActions( ) // we aren't allowed to send more than 1460 bytes in a single packet but it's possible we might have more than that many bytes waiting in the queue - if( !m_Actions.empty( ) ) + if( !m_Actions.isEmpty( ) ) { // we use a "sub actions queue" which we keep adding actions to until we reach the size limit // start by adding one action to the sub actions queue - queue SubActions; + QQueue SubActions; CIncomingAction *Action = m_Actions.front( ); - m_Actions.pop( ); - SubActions.push( Action ); + m_Actions.dequeue( ); + SubActions.enqueue( Action ); uint32_t SubActionsLength = Action->GetLength( ); - while( !m_Actions.empty( ) ) + while( !m_Actions.isEmpty( ) ) { Action = m_Actions.front( ); - m_Actions.pop( ); + m_Actions.dequeue( ); // check if adding the next action to the sub actions queue would put us over the limit (1452 because the INCOMING_ACTION and INCOMING_ACTION2 packets use an extra 8 bytes) @@ -1306,16 +1306,16 @@ void CBaseGame :: SendAllActions( ) if( m_Replay ) m_Replay->AddTimeSlot2( SubActions ); - while( !SubActions.empty( ) ) + while( !SubActions.isEmpty( ) ) { delete SubActions.front( ); - SubActions.pop( ); + SubActions.dequeue( ); } SubActionsLength = 0; } - SubActions.push( Action ); + SubActions.enqueue( Action ); SubActionsLength += Action->GetLength( ); } @@ -1324,10 +1324,10 @@ void CBaseGame :: SendAllActions( ) if( m_Replay ) m_Replay->AddTimeSlot( m_Latency, SubActions ); - while( !SubActions.empty( ) ) + while( !SubActions.isEmpty( ) ) { delete SubActions.front( ); - SubActions.pop( ); + SubActions.dequeue( ); } } else @@ -1366,7 +1366,7 @@ void CBaseGame :: SendWelcomeMessage( CGamePlayer *player ) { // default welcome message - if( m_HCLCommandString.empty( ) ) + if( m_HCLCommandString.isEmpty( ) ) SendChat( player, " " ); SendChat( player, " " ); @@ -1376,7 +1376,7 @@ void CBaseGame :: SendWelcomeMessage( CGamePlayer *player ) SendChat( player, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" ); SendChat( player, " Game Name: " + m_GameName ); - if( !m_HCLCommandString.empty( ) ) + if( !m_HCLCommandString.isEmpty( ) ) SendChat( player, " HCL Command String: " + m_HCLCommandString ); } else @@ -1391,7 +1391,7 @@ void CBaseGame :: SendWelcomeMessage( CGamePlayer *player ) { getline( in, Line ); - if( Line.empty( ) ) + if( Line.isEmpty( ) ) { if( !in.eof( ) ) SendChat( player, " " ); @@ -1424,7 +1424,7 @@ void CBaseGame :: SendEndMessage( ) { getline( in, Line ); - if( Line.empty( ) ) + if( Line.isEmpty( ) ) { if( !in.eof( ) ) SendAllChat( " " ); @@ -1445,9 +1445,9 @@ void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) // remove any queued spoofcheck messages for this player - if( player->GetWhoisSent( ) && !player->GetJoinedRealm( ).empty( ) && player->GetSpoofedRealm( ).empty( ) ) + if( player->GetWhoisSent( ) && !player->GetJoinedRealm( ).isEmpty( ) && player->GetSpoofedRealm( ).isEmpty( ) ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == player->GetJoinedRealm( ) ) { @@ -1482,11 +1482,11 @@ void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) { QString SaveGameName = UTIL_FileSafeName( "GHost++ AutoSave " + m_GameName + " (" + player->GetName( ) + ").w3z" ); CONSOLE_Print( "[GAME: " + m_GameName + "] auto saving [" + SaveGameName + "] before player drop, shortened send interval = " + UTIL_ToString( GetTicks( ) - m_LastActionSentTicks ) ); - BYTEARRAY CRC; - BYTEARRAY Action; + QByteArray CRC; + QByteArray Action; Action.push_back( 6 ); - UTIL_AppendByteArray( Action, SaveGameName ); - m_Actions.push( new CIncomingAction( player->GetPID( ), CRC, Action ) ); + UTIL_AppendQByteArray( Action, SaveGameName ); + m_Actions.enqueue( new CIncomingAction( player->GetPID( ), CRC, Action ) ); // todotodo: with the new latency system there needs to be a way to send a 0-time action @@ -1498,7 +1498,7 @@ void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) // we must buffer player leave messages when using "load in game" to prevent desyncs // this ensures the player leave messages are correctly interleaved with the empty updates sent to each player - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetFinishedLoading( ) ) { @@ -1544,7 +1544,7 @@ void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) // abort the votekick - if( !m_KickVotePlayer.empty( ) ) + if( !m_KickVotePlayer.isEmpty( ) ) SendAllChat( m_GHost->m_Language->VoteKickCancelled( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); @@ -1671,7 +1671,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP { // check if the new player's name is empty or too long - if( joinPlayer->GetName( ).empty( ) || joinPlayer->GetName( ).size( ) > 15 ) + if( joinPlayer->GetName( ).isEmpty( ) || joinPlayer->GetName( ).size( ) > 15 ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game with an invalid name of length " + UTIL_ToString( joinPlayer->GetName( ).size( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); @@ -1712,7 +1712,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( HostCounterID != 0 ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetHostCounterID( ) == HostCounterID ) JoinedRealm = (*i)->GetServer( ); @@ -1725,7 +1725,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_BanMethod != 0 ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == JoinedRealm ) { @@ -1747,7 +1747,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // let banned players "join" the game with an arbitrary PID then immediately close the connection // this causes them to be kicked back to the chat channel on battle.net - vector Slots = m_Map->GetSlots( ); + QVector Slots = m_Map->GetSlots( ); potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, potential->GetSocket( )->GetPort( ), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; @@ -1775,7 +1775,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // let banned players "join" the game with an arbitrary PID then immediately close the connection // this causes them to be kicked back to the chat channel on battle.net - vector Slots = m_Map->GetSlots( ); + QVector Slots = m_Map->GetSlots( ); potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, potential->GetSocket( )->GetPort( ), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; @@ -1786,7 +1786,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP } } - if( m_MatchMaking && m_AutoStartPlayers != 0 && !m_Map->GetMapMatchMakingCategory( ).empty( ) && m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) + if( m_MatchMaking && m_AutoStartPlayers != 0 && !m_Map->GetMapMatchMakingCategory( ).isEmpty( ) && m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) { // matchmaking is enabled // start a database query to determine the player's score @@ -1801,7 +1801,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP bool AnyAdminCheck = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->IsAdmin( joinPlayer->GetName( ) ) || (*i)->IsRootAdmin( joinPlayer->GetName( ) ) ) { @@ -1825,13 +1825,13 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // unfortunately we don't know how to extract the player layout from the saved game so we use the data from a replay instead // the !enforcesg command defines the player layout by parsing a replay - for( vector :: iterator i = m_EnforcePlayers.begin( ); i != m_EnforcePlayers.end( ); i++ ) + for( QVector :: iterator i = m_EnforcePlayers.begin( ); i != m_EnforcePlayers.end( ); i++ ) { if( (*i).second == joinPlayer->GetName( ) ) EnforcePID = (*i).first; } - for( vector :: iterator i = m_EnforceSlots.begin( ); i != m_EnforceSlots.end( ); i++ ) + for( QVector :: iterator i = m_EnforceSlots.begin( ); i != m_EnforceSlots.end( ); i++ ) { if( (*i).GetPID( ) == EnforcePID ) { @@ -1929,7 +1929,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_BanMethod == 0 ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == JoinedRealm ) { @@ -1972,7 +1972,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // consider LAN players to have already spoof checked since they can't // since so many people have trouble with this feature we now use the JoinedRealm to determine LAN status - if( JoinedRealm.empty( ) ) + if( JoinedRealm.isEmpty( ) ) Player->SetSpoofed( true ); Player->SetWhoisShouldBeSent( m_GHost->m_SpoofChecks == 1 || ( m_GHost->m_SpoofChecks == 2 && AnyAdminCheck ) ); @@ -2026,13 +2026,13 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP SendVirtualHostPlayerInfo( Player ); SendFakePlayerInfo( Player ); - BYTEARRAY BlankIP; + QByteArray BlankIP; BlankIP.push_back( 0 ); BlankIP.push_back( 0 ); BlankIP.push_back( 0 ); BlankIP.push_back( 0 ); - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && *i != Player ) { @@ -2072,14 +2072,14 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_RequireSpoofChecks && !Player->GetWhoisShouldBeSent( ) ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // note: the following (commented out) line of code will crash because calling GetUniqueName( ) twice will result in two different return values // and unfortunately iterators are not valid if compared against different containers // this comment shall serve as warning to not make this mistake again since it has now been made twice before in GHost++ // QString( (*i)->GetUniqueName( ).begin( ), (*i)->GetUniqueName( ).end( ) ) - BYTEARRAY UniqueName = (*i)->GetUniqueName( ); + QByteArray UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( QString( UniqueName.begin( ), UniqueName.end( ) ) ) ); @@ -2092,18 +2092,18 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP { QString Others; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( Player != *i && Player->GetExternalIPString( ) == (*i)->GetExternalIPString( ) ) { - if( Others.empty( ) ) + if( Others.isEmpty( ) ) Others = (*i)->GetName( ); else Others += ", " + (*i)->GetName( ); } } - if( !Others.empty( ) ) + if( !Others.isEmpty( ) ) SendAllChat( m_GHost->m_Language->MultipleIPAddressUsageDetected( joinPlayer->GetName( ), Others ) ); } @@ -2171,7 +2171,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco bool AnyAdminCheck = false; - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->IsAdmin( joinPlayer->GetName( ) ) || (*i)->IsRootAdmin( joinPlayer->GetName( ) ) ) { @@ -2206,7 +2206,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco PlayersScored = 1; } - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetScore( ) > -99999.0 ) { @@ -2222,7 +2222,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CGamePlayer *FurthestPlayer = NULL; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !FurthestPlayer || (*i)->GetScore( ) < -99999.0 || abs( (*i)->GetScore( ) - AverageScore ) > abs( FurthestPlayer->GetScore( ) - AverageScore ) ) FurthestPlayer = *i; @@ -2282,7 +2282,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CGamePlayer *LowestPlayer = NULL; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !LowestPlayer || (*i)->GetScore( ) < -99999.0 || (*i)->GetScore( ) < LowestPlayer->GetScore( ) ) LowestPlayer = *i; @@ -2362,7 +2362,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( HostCounterID != 0 ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetHostCounterID( ) == HostCounterID ) JoinedRealm = (*i)->GetServer( ); @@ -2379,7 +2379,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // consider LAN players to have already spoof checked since they can't // since so many people have trouble with this feature we now use the JoinedRealm to determine LAN status - if( JoinedRealm.empty( ) ) + if( JoinedRealm.isEmpty( ) ) Player->SetSpoofed( true ); Player->SetWhoisShouldBeSent( m_GHost->m_SpoofChecks == 1 || ( m_GHost->m_SpoofChecks == 2 && AnyAdminCheck ) ); @@ -2399,13 +2399,13 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SendVirtualHostPlayerInfo( Player ); SendFakePlayerInfo( Player ); - BYTEARRAY BlankIP; + QByteArray BlankIP; BlankIP.push_back( 0 ); BlankIP.push_back( 0 ); BlankIP.push_back( 0 ); BlankIP.push_back( 0 ); - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && *i != Player ) { @@ -2445,14 +2445,14 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( m_GHost->m_RequireSpoofChecks && !Player->GetWhoisShouldBeSent( ) ) { - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // note: the following (commented out) line of code will crash because calling GetUniqueName( ) twice will result in two different return values // and unfortunately iterators are not valid if compared against different containers // this comment shall serve as warning to not make this mistake again since it has now been made twice before in GHost++ // QString( (*i)->GetUniqueName( ).begin( ), (*i)->GetUniqueName( ).end( ) ) - BYTEARRAY UniqueName = (*i)->GetUniqueName( ); + QByteArray UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( QString( UniqueName.begin( ), UniqueName.end( ) ) ) ); @@ -2471,7 +2471,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco double MaxScore = 0.0; bool Found = false; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { @@ -2502,18 +2502,18 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco { QString Others; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( Player != *i && Player->GetExternalIPString( ) == (*i)->GetExternalIPString( ) ) { - if( Others.empty( ) ) + if( Others.isEmpty( ) ) Others = (*i)->GetName( ); else Others += ", " + (*i)->GetName( ); } } - if( !Others.empty( ) ) + if( !Others.isEmpty( ) ) SendAllChat( m_GHost->m_Language->MultipleIPAddressUsageDetected( joinPlayer->GetName( ), Others ) ); } @@ -2566,7 +2566,7 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) // see the Update function for more information about why we do this // this includes player loaded messages, game updates, and player leave messages - queue *LoadInGameData = player->GetLoadInGameData( ); + QQueue *LoadInGameData = player->GetLoadInGameData( ); while( !LoadInGameData->empty( ) ) { @@ -2578,7 +2578,7 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) bool FinishedLoading = true; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { FinishedLoading = (*i)->GetFinishedLoading( ); @@ -2591,7 +2591,7 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) // remove the new player from previously loaded players' lag screens - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( *i != player && (*i)->GetFinishedLoading( ) ) Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( player ) ); @@ -2599,7 +2599,7 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) // send a chat message to previously loaded players - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( *i != player && (*i)->GetFinishedLoading( ) ) SendChat( *i, m_GHost->m_Language->PlayerFinishedLoading( player->GetName( ) ) ); @@ -2614,7 +2614,7 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *action ) { - m_Actions.push( action ); + m_Actions.enqueue( action ); // check for players saving the game and notify everyone @@ -2631,7 +2631,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) // however, it's possible that not every player has sent a checksum for this frame yet // first we verify that we have enough checksums to work with otherwise we won't know exactly who desynced - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetDeleteMe( ) && (*i)->GetCheckSums( )->empty( ) ) return; @@ -2642,7 +2642,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) bool FoundPlayer = false; uint32_t FirstCheckSum = 0; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetDeleteMe( ) ) { @@ -2657,7 +2657,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) bool AddToReplay = true; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetDeleteMe( ) && (*i)->GetCheckSums( )->front( ) != FirstCheckSum ) { @@ -2668,19 +2668,19 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) // this is complicated by the fact that we don't know what the correct game state is so we let the players vote // put the players into bins based on their game state - map > Bins; + QMap > Bins; - for( vector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { if( !(*j)->GetDeleteMe( ) ) Bins[(*j)->GetCheckSums( )->front( )].push_back( (*j)->GetPID( ) ); } uint32_t StateNumber = 1; - map > :: iterator LargestBin = Bins.begin( ); + QMap > :: iterator LargestBin = Bins.begin( ); bool Tied = false; - for( map > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) + for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { if( (*j).second.size( ) > (*LargestBin).second.size( ) ) { @@ -2692,13 +2692,13 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) QString Players; - for( vector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) + for( QVector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) { CGamePlayer *Player = GetPlayerFromPID( *k ); if( Player ) { - if( Players.empty( ) ) + if( Players.isEmpty( ) ) Players = Player->GetName( ); else Players += ", " + Player->GetName( ); @@ -2728,7 +2728,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) { CONSOLE_Print( "[GAME: " + m_GameName + "] kicking desynced players" ); - for( map > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) + for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { // kick players who are NOT in the largest bin // examples: suppose there are 10 players @@ -2737,7 +2737,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) if( (*j).first != (*LargestBin).first ) { - for( vector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) + for( QVector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) { CGamePlayer *Player = GetPlayerFromPID( *k ); @@ -2758,7 +2758,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) } } - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetDeleteMe( ) ) (*i)->GetCheckSums( )->pop( ); @@ -2779,7 +2779,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye // relay the chat message to other players bool Relay = !player->GetMuted( ); - BYTEARRAY ExtraFlags = chatPlayer->GetExtraFlags( ); + QByteArray ExtraFlags = chatPlayer->GetExtraFlags( ); // calculate timestamp @@ -2792,7 +2792,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye if( SecString.size( ) == 1 ) SecString.insert( 0, "0" ); - if( !ExtraFlags.empty( ) ) + if( !ExtraFlags.isEmpty( ) ) { if( ExtraFlags[0] == 0 ) { @@ -2819,7 +2819,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye // this includes allied chat and private chat from both teams as long as it was relayed if( m_Replay ) - m_Replay->AddChatMessage( chatPlayer->GetFromPID( ), chatPlayer->GetFlag( ), UTIL_ByteArrayToUInt32( chatPlayer->GetExtraFlags( ), false ), chatPlayer->GetMessage( ) ); + m_Replay->AddChatMessage( chatPlayer->GetFromPID( ), chatPlayer->GetFlag( ), UTIL_QByteArrayToUInt32( chatPlayer->GetExtraFlags( ), false ), chatPlayer->GetMessage( ) ); } } else @@ -2838,7 +2838,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye if( Message == "?trigger" ) SendChat( player, m_GHost->m_Language->CommandTrigger( QString( 1, m_GHost->m_CommandTrigger ) ) ); - else if( !Message.empty( ) && Message[0] == m_GHost->m_CommandTrigger ) + else if( !Message.isEmpty( ) && Message[0] == m_GHost->m_CommandTrigger ) { // extract the command trigger, the command, and the payload // e.g. "!say hello world" -> command: "say", payload: "hello world" @@ -2849,11 +2849,11 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye if( PayloadStart != QString :: npos ) { - Command = Message.substr( 1, PayloadStart - 1 ); - Payload = Message.substr( PayloadStart + 1 ); + Command = Message.mid( 1, PayloadStart - 1 ); + Payload = Message.mid( PayloadStart + 1 ); } else - Command = Message.substr( 1 ); + Command = Message.mid( 1 ); transform( Command.begin( ), Command.end( ), Command.begin( ), (int(*)(int))tolower ); @@ -3037,7 +3037,7 @@ void CBaseGame :: EventPlayerDropRequest( CGamePlayer *player ) uint32_t Votes = 0; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetDropVote( ) ) Votes++; @@ -3055,7 +3055,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map // todotodo: the variable names here are confusing due to extremely poor design on my part - uint32_t MapSize = UTIL_ByteArrayToUInt32( m_Map->GetMapSize( ), false ); + uint32_t MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); if( mapSize->GetSizeFlag( ) != 1 || mapSize->GetMapSize( ) != MapSize ) { @@ -3190,7 +3190,7 @@ void CBaseGame :: EventGameStarted( ) // note: if you attempt to use the HCL system on a map that does not support HCL the bot will drastically modify the handicaps // since the map won't automatically restore the original handicaps in this case your game will be ruined - if( !m_HCLCommandString.empty( ) ) + if( !m_HCLCommandString.isEmpty( ) ) { if( m_HCLCommandString.size( ) <= GetSlotsOccupied( ) ) { @@ -3275,7 +3275,7 @@ void CBaseGame :: EventGameStarted( ) // delete any potential players that are still hanging around - for( vector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) delete *i; m_Potentials.clear( ); @@ -3284,7 +3284,7 @@ void CBaseGame :: EventGameStarted( ) if( m_Replay ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) m_Replay->AddPlayer( (*i)->GetPID( ), (*i)->GetName( ) ); if( m_FakePlayerPID != 255 ) @@ -3315,7 +3315,7 @@ void CBaseGame :: EventGameStarted( ) m_Replay->SetMapGameType( MapGameType ); } - if( !m_Players.empty( ) ) + if( !m_Players.isEmpty( ) ) { // this might not be necessary since we're going to overwrite the replay's host PID and name everytime a player leaves @@ -3327,16 +3327,16 @@ void CBaseGame :: EventGameStarted( ) // build a stat QString for use when saving the replay // we have to build this now because the map data is going to be deleted - BYTEARRAY StatString; - UTIL_AppendByteArray( StatString, m_Map->GetMapGameFlags( ) ); + QByteArray StatString; + UTIL_AppendQByteArray( StatString, m_Map->GetMapGameFlags( ) ); StatString.push_back( 0 ); - UTIL_AppendByteArray( StatString, m_Map->GetMapWidth( ) ); - UTIL_AppendByteArray( StatString, m_Map->GetMapHeight( ) ); - UTIL_AppendByteArray( StatString, m_Map->GetMapCRC( ) ); - UTIL_AppendByteArray( StatString, m_Map->GetMapPath( ) ); - UTIL_AppendByteArray( StatString, "GHost++" ); + UTIL_AppendQByteArray( StatString, m_Map->GetMapWidth( ) ); + UTIL_AppendQByteArray( StatString, m_Map->GetMapHeight( ) ); + UTIL_AppendQByteArray( StatString, m_Map->GetMapCRC( ) ); + UTIL_AppendQByteArray( StatString, m_Map->GetMapPath( ) ); + UTIL_AppendQByteArray( StatString, "GHost++" ); StatString.push_back( 0 ); - UTIL_AppendByteArray( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing + UTIL_AppendQByteArray( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing StatString = UTIL_EncodeStatString( StatString ); m_StatString = QString( StatString.begin( ), StatString.end( ) ); @@ -3351,9 +3351,9 @@ void CBaseGame :: EventGameStarted( ) // this ensures that every player receives the same set of player loaded messages in the same order, even if someone leaves during loading // if someone leaves during loading we buffer the leave message to ensure it gets sent in the correct position but the player loaded message wouldn't get sent if we didn't buffer it now - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - for( vector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) (*j)->AddLoadInGameData( m_Protocol->SEND_W3GS_GAMELOADED_OTHERS( (*i)->GetPID( ) ) ); } } @@ -3365,7 +3365,7 @@ void CBaseGame :: EventGameStarted( ) // and finally reenter battle.net chat - for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { (*i)->QueueGameUncreate( ); (*i)->QueueEnterChat( ); @@ -3381,7 +3381,7 @@ void CBaseGame :: EventGameLoaded( ) CGamePlayer *Shortest = NULL; CGamePlayer *Longest = NULL; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !Shortest || (*i)->GetFinishedLoadingTicks( ) < Shortest->GetFinishedLoadingTicks( ) ) Shortest = *i; @@ -3396,7 +3396,7 @@ void CBaseGame :: EventGameLoaded( ) SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), UTIL_ToString( (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); } - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( UTIL_ToString( (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); // read from gameloaded.txt if available @@ -3415,7 +3415,7 @@ void CBaseGame :: EventGameLoaded( ) { getline( in, Line ); - if( Line.empty( ) ) + if( Line.isEmpty( ) ) { if( !in.eof( ) ) SendAllChat( " " ); @@ -3446,7 +3446,7 @@ unsigned char CBaseGame :: GetSIDFromPID( unsigned char PID ) CGamePlayer *CBaseGame :: GetPlayerFromPID( unsigned char PID ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && (*i)->GetPID( ) == PID ) return *i; @@ -3468,7 +3468,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) if( !sensitive ) transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { @@ -3493,7 +3493,7 @@ uint32_t CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **play // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { @@ -3541,7 +3541,7 @@ unsigned char CBaseGame :: GetNewPID( ) bool InUse = false; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && (*i)->GetPID( ) == TestPID ) { @@ -3585,11 +3585,11 @@ unsigned char CBaseGame :: GetNewColour( ) return 12; } -BYTEARRAY CBaseGame :: GetPIDs( ) +QByteArray CBaseGame :: GetPIDs( ) { - BYTEARRAY result; + QByteArray result; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) result.push_back( (*i)->GetPID( ) ); @@ -3598,11 +3598,11 @@ BYTEARRAY CBaseGame :: GetPIDs( ) return result; } -BYTEARRAY CBaseGame :: GetPIDs( unsigned char excludePID ) +QByteArray CBaseGame :: GetPIDs( unsigned char excludePID ) { - BYTEARRAY result; + QByteArray result; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && (*i)->GetPID( ) != excludePID ) result.push_back( (*i)->GetPID( ) ); @@ -3626,7 +3626,7 @@ unsigned char CBaseGame :: GetHostPID( ) // try to find the owner player next - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && IsOwner( (*i)->GetName( ) ) ) return (*i)->GetPID( ); @@ -3634,7 +3634,7 @@ unsigned char CBaseGame :: GetHostPID( ) // okay then, just use the first available player - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) return (*i)->GetPID( ); @@ -3653,7 +3653,7 @@ unsigned char CBaseGame :: GetEmptySlot( bool reserved ) // unfortunately we don't know which slot each player was assigned in the savegame // but we do know which slots were occupied and which weren't so let's at least force players to use previously occupied slots - vector SaveGameSlots = m_SaveGame->GetSlots( ); + QVector SaveGameSlots = m_SaveGame->GetSlots( ); for( unsigned char i = 0; i < m_Slots.size( ); i++ ) { @@ -3740,7 +3740,7 @@ unsigned char CBaseGame :: GetEmptySlot( unsigned char team, unsigned char PID ) if( m_SaveGame ) { - vector SaveGameSlots = m_SaveGame->GetSlots( ); + QVector SaveGameSlots = m_SaveGame->GetSlots( ); for( unsigned char i = StartSlot; i < m_Slots.size( ); i++ ) { @@ -3913,7 +3913,7 @@ void CBaseGame :: OpenAllSlots( ) { bool Changed = false; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_CLOSED ) { @@ -3930,7 +3930,7 @@ void CBaseGame :: CloseAllSlots( ) { bool Changed = false; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OPEN ) { @@ -3949,9 +3949,9 @@ void CBaseGame :: ShuffleSlots( ) // that means we need to prevent this function from shuffling the open/closed/computer slots too // so we start by copying the player slots to a temporary vector - vector PlayerSlots; + QVector PlayerSlots; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != 12 ) PlayerSlots.push_back( *i ); @@ -3966,7 +3966,7 @@ void CBaseGame :: ShuffleSlots( ) // unfortunately we can't just use PlayerSlots because the team/colour/race shouldn't be modified // so make a vector we can use - vector SIDs; + QVector SIDs; for( unsigned char i = 0; i < PlayerSlots.size( ); i++ ) SIDs.push_back( i ); @@ -3975,7 +3975,7 @@ void CBaseGame :: ShuffleSlots( ) // now put the PlayerSlots vector in the same order as the SIDs vector - vector Slots; + QVector Slots; // as usual don't modify the team/colour/race @@ -3994,10 +3994,10 @@ void CBaseGame :: ShuffleSlots( ) // now we put m_Slots back together again - vector :: iterator CurrentPlayer = PlayerSlots.begin( ); - vector Slots; + QVector :: iterator CurrentPlayer = PlayerSlots.begin( ); + QVector Slots; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != 12 ) { @@ -4015,7 +4015,7 @@ void CBaseGame :: ShuffleSlots( ) SendAllSlotInfo( ); } -vector CBaseGame :: BalanceSlotsRecursive( vector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ) +QVector CBaseGame :: BalanceSlotsRecursive( QVector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ) { // take a brute force approach to finding the best balance by iterating through every possible combination of players // 1.) since the number of teams is arbitrary this algorithm must be recursive @@ -4024,7 +4024,7 @@ vector CBaseGame :: BalanceSlotsRecursive( vector // 4.) for every possible combination, check the largest difference in total scores between any two actual teams // 5.) minimize this value by choosing the combination of players with the smallest difference - vector BestOrdering = PlayerIDs; + QVector BestOrdering = PlayerIDs; double BestDifference = -1.0; for( unsigned char i = StartTeam; i < 12; i++ ) @@ -4043,17 +4043,17 @@ vector CBaseGame :: BalanceSlotsRecursive( vector // for example, it could contain one, two, or more actual teams worth of players // so recurse using the second "team" as the full set of players to perform the balancing on - vector BestSubOrdering = BalanceSlotsRecursive( vector( PlayerIDs.begin( ) + Mid, PlayerIDs.end( ) ), TeamSizes, PlayerScores, i + 1 ); + QVector BestSubOrdering = BalanceSlotsRecursive( QVector( PlayerIDs.begin( ) + Mid, PlayerIDs.end( ) ), TeamSizes, PlayerScores, i + 1 ); // BestSubOrdering now contains the best ordering of all the remaining players (the "right team") given this particular combination of players into two "teams" // in order to calculate the largest difference in total scores we need to recombine the subordering with the first team - vector TestOrdering = vector( PlayerIDs.begin( ), PlayerIDs.begin( ) + Mid ); + QVector TestOrdering = QVector( PlayerIDs.begin( ), PlayerIDs.begin( ) + Mid ); TestOrdering.insert( TestOrdering.end( ), BestSubOrdering.begin( ), BestSubOrdering.end( ) ); // now calculate the team scores for all the teams that we know about (e.g. on subsequent recursion steps this will NOT be every possible team) - vector :: iterator CurrentPID = TestOrdering.begin( ); + QVector :: iterator CurrentPID = TestOrdering.begin( ); double TeamScores[12]; for( unsigned char j = StartTeam; j < 12; j++ ) @@ -4113,12 +4113,12 @@ void CBaseGame :: BalanceSlots( ) // setup the necessary variables for the balancing algorithm // use an array of 13 elements for 12 players because GHost++ allocates PID's from 1-12 (i.e. excluding 0) and we use the PID to index the array - vector PlayerIDs; + QVector PlayerIDs; unsigned char TeamSizes[12]; double PlayerScores[13]; memset( TeamSizes, 0, sizeof( unsigned char ) * 12 ); - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { unsigned char PID = (*i)->GetPID( ); @@ -4190,13 +4190,13 @@ void CBaseGame :: BalanceSlots( ) } uint32_t StartTicks = GetTicks( ); - vector BestOrdering = BalanceSlotsRecursive( PlayerIDs, TeamSizes, PlayerScores, 0 ); + QVector BestOrdering = BalanceSlotsRecursive( PlayerIDs, TeamSizes, PlayerScores, 0 ); uint32_t EndTicks = GetTicks( ); // the BestOrdering assumes the teams are in slot order although this may not be the case // so put the players on the correct teams regardless of slot order - vector :: iterator CurrentPID = BestOrdering.begin( ); + QVector :: iterator CurrentPID = BestOrdering.begin( ); for( unsigned char i = 0; i < 12; i++ ) { @@ -4241,7 +4241,7 @@ void CBaseGame :: BalanceSlots( ) bool TeamHasPlayers = false; double TeamScore = 0.0; - for( vector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { unsigned char SID = GetSIDFromPID( (*j)->GetPID( ) ); @@ -4282,7 +4282,7 @@ void CBaseGame :: AddToReserved( QString name ) // check that the user is not already reserved - for( vector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) + for( QVector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { if( *i == name ) return; @@ -4292,7 +4292,7 @@ void CBaseGame :: AddToReserved( QString name ) // upgrade the user if they're already in the game - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { QString NameLower = (*i)->GetName( ); transform( NameLower.begin( ), NameLower.end( ), NameLower.begin( ), (int(*)(int))tolower ); @@ -4314,7 +4314,7 @@ bool CBaseGame :: IsReserved( QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - for( vector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) + for( QVector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { if( *i == name ) return true; @@ -4327,7 +4327,7 @@ bool CBaseGame :: IsDownloading( ) { // returns true if at least one player is downloading the map - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetDownloadStarted( ) && !(*i)->GetDownloadFinished( ) ) return true; @@ -4369,7 +4369,7 @@ void CBaseGame :: StartCountDown( bool force ) QString StillDownloading; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetDownloadStatus( ) != 100 ) { @@ -4377,7 +4377,7 @@ void CBaseGame :: StartCountDown( bool force ) if( Player ) { - if( StillDownloading.empty( ) ) + if( StillDownloading.isEmpty( ) ) StillDownloading = Player->GetName( ); else StillDownloading += ", " + Player->GetName( ); @@ -4385,7 +4385,7 @@ void CBaseGame :: StartCountDown( bool force ) } } - if( !StillDownloading.empty( ) ) + if( !StillDownloading.isEmpty( ) ) SendAllChat( m_GHost->m_Language->PlayersStillDownloading( StillDownloading ) ); // check if everyone is spoof checked @@ -4394,18 +4394,18 @@ void CBaseGame :: StartCountDown( bool force ) if( m_GHost->m_RequireSpoofChecks ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetSpoofed( ) ) { - if( NotSpoofChecked.empty( ) ) + if( NotSpoofChecked.isEmpty( ) ) NotSpoofChecked = (*i)->GetName( ); else NotSpoofChecked += ", " + (*i)->GetName( ); } } - if( !NotSpoofChecked.empty( ) ) + if( !NotSpoofChecked.isEmpty( ) ) SendAllChat( m_GHost->m_Language->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); } @@ -4414,23 +4414,23 @@ void CBaseGame :: StartCountDown( bool force ) QString NotPinged; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetReserved( ) && (*i)->GetNumPings( ) < 3 ) { - if( NotPinged.empty( ) ) + if( NotPinged.isEmpty( ) ) NotPinged = (*i)->GetName( ); else NotPinged += ", " + (*i)->GetName( ); } } - if( !NotPinged.empty( ) ) + if( !NotPinged.isEmpty( ) ) SendAllChat( m_GHost->m_Language->PlayersNotYetPinged( NotPinged ) ); // if no problems found start the game - if( StillDownloading.empty( ) && NotSpoofChecked.empty( ) && NotPinged.empty( ) ) + if( StillDownloading.isEmpty( ) && NotSpoofChecked.isEmpty( ) && NotPinged.isEmpty( ) ) { m_CountDownStarted = true; m_CountDownCounter = 5; @@ -4455,7 +4455,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) QString StillDownloading; - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetDownloadStatus( ) != 100 ) { @@ -4463,7 +4463,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( Player ) { - if( StillDownloading.empty( ) ) + if( StillDownloading.isEmpty( ) ) StillDownloading = Player->GetName( ); else StillDownloading += ", " + Player->GetName( ); @@ -4471,7 +4471,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) } } - if( !StillDownloading.empty( ) ) + if( !StillDownloading.isEmpty( ) ) { SendAllChat( m_GHost->m_Language->PlayersStillDownloading( StillDownloading ) ); return; @@ -4483,18 +4483,18 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( requireSpoofChecks ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetSpoofed( ) ) { - if( NotSpoofChecked.empty( ) ) + if( NotSpoofChecked.isEmpty( ) ) NotSpoofChecked = (*i)->GetName( ); else NotSpoofChecked += ", " + (*i)->GetName( ); } } - if( !NotSpoofChecked.empty( ) ) + if( !NotSpoofChecked.isEmpty( ) ) SendAllChat( m_GHost->m_Language->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); } @@ -4503,18 +4503,18 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) QString NotPinged; - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetReserved( ) && (*i)->GetNumPings( ) < 3 ) { - if( NotPinged.empty( ) ) + if( NotPinged.isEmpty( ) ) NotPinged = (*i)->GetName( ); else NotPinged += ", " + (*i)->GetName( ); } } - if( !NotPinged.empty( ) ) + if( !NotPinged.isEmpty( ) ) { SendAllChat( m_GHost->m_Language->PlayersNotYetPingedAutoStart( NotPinged ) ); return; @@ -4522,7 +4522,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) // if no problems found start the game - if( StillDownloading.empty( ) && NotSpoofChecked.empty( ) && NotPinged.empty( ) ) + if( StillDownloading.isEmpty( ) && NotSpoofChecked.isEmpty( ) && NotPinged.isEmpty( ) ) { m_CountDownStarted = true; m_CountDownCounter = 10; @@ -4537,7 +4537,7 @@ void CBaseGame :: StopPlayers( QString reason ) // therefore calling this function when m_GameLoading || m_GameLoaded is roughly equivalent to setting m_Exiting = true // the only difference is whether the code in the Update function is executed or not - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { (*i)->SetDeleteMe( true ); (*i)->SetLeftReason( reason ); @@ -4547,7 +4547,7 @@ void CBaseGame :: StopPlayers( QString reason ) void CBaseGame :: StopLaggers( QString reason ) { - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLagging( ) ) { @@ -4564,7 +4564,7 @@ void CBaseGame :: CreateVirtualHost( ) return; m_VirtualHostPID = GetNewPID( ); - BYTEARRAY IP; + QByteArray IP; IP.push_back( 0 ); IP.push_back( 0 ); IP.push_back( 0 ); @@ -4594,7 +4594,7 @@ void CBaseGame :: CreateFakePlayer( ) DeleteVirtualHost( ); m_FakePlayerPID = GetNewPID( ); - BYTEARRAY IP; + QByteArray IP; IP.push_back( 0 ); IP.push_back( 0 ); IP.push_back( 0 ); diff --git a/ghost/game_base.h b/ghost/game_base.h index e5500e0..268dc49 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -21,6 +21,7 @@ #ifndef GAME_BASE_H #define GAME_BASE_H +#include "includes.h" #include "gameslot.h" // @@ -48,16 +49,16 @@ class CBaseGame protected: CTCPServer *m_Socket; // listening socket CGameProtocol *m_Protocol; // game protocol - vector m_Slots; // vector of slots - vector m_Potentials; // vector of potential players (connections that haven't sent a W3GS_REQJOIN packet yet) - vector m_Players; // vector of players - vector m_ScoreChecks; - queue m_Actions; // queue of actions to be sent - vector m_Reserved; // vector of player names with reserved slots (from the !hold command) + QVector m_Slots; // vector of slots + QVector m_Potentials; // vector of potential players (connections that haven't sent a W3GS_REQJOIN packet yet) + QVector m_Players; // vector of players + QVector m_ScoreChecks; + QQueue m_Actions; // queue of actions to be sent + QVector m_Reserved; // vector of player names with reserved slots (from the !hold command) set m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed set m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) - vector m_EnforceSlots; // vector of slots to force players to use (used with saved games) - vector m_EnforcePlayers; // vector of pids to force players to use (used with saved games) + QVector m_EnforceSlots; // vector of slots to force players to use (used with saved games) + QVector m_EnforcePlayers; // vector of pids to force players to use (used with saved games) CMap *m_Map; // map data CSaveGame *m_SaveGame; // savegame data (this is a pointer to global data) CReplay *m_Replay; // replay @@ -129,8 +130,8 @@ class CBaseGame CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CBaseGame( ); - virtual vector GetEnforceSlots( ) { return m_EnforceSlots; } - virtual vector GetEnforcePlayers( ) { return m_EnforcePlayers; } + virtual QVector GetEnforceSlots( ) { return m_EnforceSlots; } + virtual QVector GetEnforcePlayers( ) { return m_EnforcePlayers; } virtual CSaveGame *GetSaveGame( ) { return m_SaveGame; } virtual uint16_t GetHostPort( ) { return m_HostPort; } virtual unsigned char GetGameState( ) { return m_GameState; } @@ -150,8 +151,8 @@ class CBaseGame virtual bool GetGameLoaded( ) { return m_GameLoaded; } virtual bool GetLagging( ) { return m_Lagging; } - virtual void SetEnforceSlots( vector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } - virtual void SetEnforcePlayers( vector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } + virtual void SetEnforceSlots( QVector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } + virtual void SetEnforcePlayers( QVector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } virtual void SetExiting( bool nExiting ) { m_Exiting = nExiting; } virtual void SetAutoStartPlayers( uint32_t nAutoStartPlayers ) { m_AutoStartPlayers = nAutoStartPlayers; } virtual void SetMinimumScore( double nMinimumScore ) { m_MinimumScore = nMinimumScore; } @@ -176,10 +177,10 @@ class CBaseGame // generic functions to send packets to players - virtual void Send( CGamePlayer *player, BYTEARRAY data ); - virtual void Send( unsigned char PID, BYTEARRAY data ); - virtual void Send( BYTEARRAY PIDs, BYTEARRAY data ); - virtual void SendAll( BYTEARRAY data ); + virtual void Send( CGamePlayer *player, QByteArray data ); + virtual void Send( unsigned char PID, QByteArray data ); + virtual void Send( QByteArray PIDs, QByteArray data ); + virtual void SendAll( QByteArray data ); // functions to send packets to players @@ -238,8 +239,8 @@ class CBaseGame virtual CGamePlayer *GetPlayerFromColour( unsigned char colour ); virtual unsigned char GetNewPID( ); virtual unsigned char GetNewColour( ); - virtual BYTEARRAY GetPIDs( ); - virtual BYTEARRAY GetPIDs( unsigned char excludePID ); + virtual QByteArray GetPIDs( ); + virtual QByteArray GetPIDs( unsigned char excludePID ); virtual unsigned char GetHostPID( ); virtual unsigned char GetEmptySlot( bool reserved ); virtual unsigned char GetEmptySlot( unsigned char team, unsigned char PID ); @@ -251,7 +252,7 @@ class CBaseGame virtual void OpenAllSlots( ); virtual void CloseAllSlots( ); virtual void ShuffleSlots( ); - virtual vector BalanceSlotsRecursive( vector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ); + virtual QVector BalanceSlotsRecursive( QVector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ); virtual void BalanceSlots( ); virtual void AddToSpoofed( QString server, QString name, bool sendMessage ); virtual void AddToReserved( QString name ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 7f3479b..386fd43 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -49,23 +49,23 @@ CPotentialPlayer :: ~CPotentialPlayer( ) if( m_Socket ) delete m_Socket; - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { delete m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); } delete m_IncomingJoinPlayer; } -BYTEARRAY CPotentialPlayer :: GetExternalIP( ) +QByteArray CPotentialPlayer :: GetExternalIP( ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; if( m_Socket ) return m_Socket->GetIP( ); - return UTIL_CreateByteArray( Zeros, 4 ); + return UTIL_CreateQByteArray( Zeros, 4 ); } QString CPotentialPlayer :: GetExternalIPString( ) @@ -102,7 +102,7 @@ void CPotentialPlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue QString *RecvBuffer = m_Socket->GetBytes( ); - BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -112,15 +112,15 @@ void CPotentialPlayer :: ExtractPackets( ) { // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 ); + uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); if( Length >= 4 ) { if( Bytes.size( ) >= Length ) { - m_Packets.push( new CCommandPacket( Bytes[0], Bytes[1], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); + m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) ); + Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); } else return; @@ -148,10 +148,10 @@ void CPotentialPlayer :: ProcessPackets( ) // process all the received packets in the m_Packets queue - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { CCommandPacket *Packet = m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); if( Packet->GetPacketType( ) == W3GS_HEADER_CONSTANT ) { @@ -179,7 +179,7 @@ void CPotentialPlayer :: ProcessPackets( ) } } -void CPotentialPlayer :: Send( BYTEARRAY data ) +void CPotentialPlayer :: Send( QByteArray data ) { if( m_Socket ) m_Socket->PutBytes( data ); @@ -189,7 +189,7 @@ void CPotentialPlayer :: Send( BYTEARRAY data ) // CGamePlayer // -CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ) : CPotentialPlayer( nProtocol, nGame, nSocket ) +CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) : CPotentialPlayer( nProtocol, nGame, nSocket ) { m_PID = nPID; m_Name = nName; @@ -231,7 +231,7 @@ CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSock m_LastGProxyAckTime = 0; } -CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ) : CPotentialPlayer( potential->m_Protocol, potential->m_Game, potential->GetSocket( ) ) +CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) : CPotentialPlayer( potential->m_Protocol, potential->m_Game, potential->GetSocket( ) ) { // todotodo: properly copy queued packets to the new player, this just discards them // this isn't a big problem because official Warcraft III clients don't send any packets after the join request until they receive a response @@ -308,7 +308,7 @@ uint32_t CGamePlayer :: GetPing( bool LCPing ) { // just average all the pings in the vector, nothing fancy - if( m_Pings.empty( ) ) + if( m_Pings.isEmpty( ) ) return 0; uint32_t AvgPing = 0; @@ -329,11 +329,11 @@ bool CGamePlayer :: Update( void *fd ) // wait 4 seconds after joining before sending the /whois or /w // if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results - if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.empty( ) && GetTime( ) - m_JoinTime >= 4 ) + if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.isEmpty( ) && GetTime( ) - m_JoinTime >= 4 ) { // todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking - for( vector :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == m_JoinedRealm ) { @@ -406,7 +406,7 @@ void CGamePlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue QString *RecvBuffer = m_Socket->GetBytes( ); - BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -416,19 +416,19 @@ void CGamePlayer :: ExtractPackets( ) { // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 ); + uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); if( Length >= 4 ) { if( Bytes.size( ) >= Length ) { - m_Packets.push( new CCommandPacket( Bytes[0], Bytes[1], BYTEARRAY( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); + m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); if( Bytes[0] == W3GS_HEADER_CONSTANT ) m_TotalPacketsReceived++; *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) ); + Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); } else return; @@ -463,10 +463,10 @@ void CGamePlayer :: ProcessPackets( ) // process all the received packets in the m_Packets queue - while( !m_Packets.empty( ) ) + while( !m_Packets.isEmpty( ) ) { CCommandPacket *Packet = m_Packets.front( ); - m_Packets.pop( ); + m_Packets.dequeue( ); if( Packet->GetPacketType( ) == W3GS_HEADER_CONSTANT ) { @@ -505,7 +505,7 @@ void CGamePlayer :: ProcessPackets( ) case CGameProtocol :: W3GS_OUTGOING_KEEPALIVE: CheckSum = m_Protocol->RECEIVE_W3GS_OUTGOING_KEEPALIVE( Packet->GetData( ) ); - m_CheckSums.push( CheckSum ); + m_CheckSums.enqueue( CheckSum ); m_SyncCounter++; m_Game->EventPlayerKeepAlive( this, CheckSum ); break; @@ -572,7 +572,7 @@ void CGamePlayer :: ProcessPackets( ) } else if( Packet->GetPacketType( ) == GPS_HEADER_CONSTANT ) { - BYTEARRAY Data = Packet->GetData( ); + QByteArray Data = Packet->GetData( ); if( Packet->GetID( ) == CGPSProtocol :: GPS_INIT ) { @@ -595,7 +595,7 @@ void CGamePlayer :: ProcessPackets( ) } else if( Packet->GetID( ) == CGPSProtocol :: GPS_ACK && Data.size( ) == 8 ) { - uint32_t LastPacket = UTIL_ByteArrayToUInt32( Data, false, 4 ); + uint32_t LastPacket = UTIL_QByteArrayToUInt32( Data, false, 4 ); uint32_t PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); if( LastPacket > PacketsAlreadyUnqueued ) @@ -607,7 +607,7 @@ void CGamePlayer :: ProcessPackets( ) while( PacketsToUnqueue > 0 ) { - m_GProxyBuffer.pop( ); + m_GProxyBuffer.dequeue( ); PacketsToUnqueue--; } } @@ -618,7 +618,7 @@ void CGamePlayer :: ProcessPackets( ) } } -void CGamePlayer :: Send( BYTEARRAY data ) +void CGamePlayer :: Send( QByteArray data ) { // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts @@ -627,7 +627,7 @@ void CGamePlayer :: Send( BYTEARRAY data ) m_TotalPacketsSent++; if( m_GProxy && m_Game->GetGameLoaded( ) ) - m_GProxyBuffer.push( data ); + m_GProxyBuffer.enqueue( data ); CPotentialPlayer :: Send( data ); } @@ -649,20 +649,20 @@ void CGamePlayer :: EventGProxyReconnect( CTCPSocket *NewSocket, uint32_t LastPa while( PacketsToUnqueue > 0 ) { - m_GProxyBuffer.pop( ); + m_GProxyBuffer.dequeue( ); PacketsToUnqueue--; } } // send remaining packets from buffer, preserve buffer - queue TempBuffer; + QQueue TempBuffer; - while( !m_GProxyBuffer.empty( ) ) + while( !m_GProxyBuffer.isEmpty( ) ) { m_Socket->PutBytes( m_GProxyBuffer.front( ) ); - TempBuffer.push( m_GProxyBuffer.front( ) ); - m_GProxyBuffer.pop( ); + TempBuffer.enqueue( m_GProxyBuffer.front( ) ); + m_GProxyBuffer.dequeue( ); } m_GProxyBuffer = TempBuffer; diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index d6ee8e7..49c43db 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -27,6 +27,8 @@ class CGameProtocol; class CGame; class CIncomingJoinPlayer; +#include "includes.h" + // // CPotentialPlayer // @@ -42,7 +44,7 @@ class CPotentialPlayer // it also allows us to convert CPotentialPlayers to CGamePlayers without the CPotentialPlayer's destructor closing the socket CTCPSocket *m_Socket; - queue m_Packets; + QQueue m_Packets; bool m_DeleteMe; bool m_Error; QString m_ErrorString; @@ -53,9 +55,9 @@ class CPotentialPlayer virtual ~CPotentialPlayer( ); virtual CTCPSocket *GetSocket( ) { return m_Socket; } - virtual BYTEARRAY GetExternalIP( ); + virtual QByteArray GetExternalIP( ); virtual QString GetExternalIPString( ); - virtual queue GetPackets( ) { return m_Packets; } + virtual QQueue GetPackets( ) { return m_Packets; } virtual bool GetDeleteMe( ) { return m_DeleteMe; } virtual bool GetError( ) { return m_Error; } virtual QString GetErrorString( ) { return m_ErrorString; } @@ -72,7 +74,7 @@ class CPotentialPlayer // other functions - virtual void Send( BYTEARRAY data ); + virtual void Send( QByteArray data ); }; // @@ -84,9 +86,9 @@ class CGamePlayer : public CPotentialPlayer private: unsigned char m_PID; QString m_Name; // the player's name - BYTEARRAY m_InternalIP; // the player's internal IP address as reported by the player when connecting - vector m_Pings; // store the last few (20) pings received so we can take an average - queue m_CheckSums; // the last few checksums the player has sent (for detecting desyncs) + QByteArray m_InternalIP; // the player's internal IP address as reported by the player when connecting + QVector m_Pings; // store the last few (20) pings received so we can take an average + QQueue m_CheckSums; // the last few checksums the player has sent (for detecting desyncs) QString m_LeftReason; // the reason the player left the game QString m_SpoofedRealm; // the realm the player last spoof checked on QString m_JoinedRealm; // the realm the player joined on (probable, can be spoofed) @@ -105,7 +107,7 @@ class CGamePlayer : public CPotentialPlayer uint32_t m_StatsSentTime; // GetTime when we sent this player's stats to the chat (to prevent players from spamming !stats) uint32_t m_StatsDotASentTime; // GetTime when we sent this player's dota stats to the chat (to prevent players from spamming !statsdota) uint32_t m_LastGProxyWaitNoticeSentTime; - queue m_LoadInGameData; // queued data to be sent when the player finishes loading when using "load in game" + QQueue m_LoadInGameData; // queued data to be sent when the player finishes loading when using "load in game" double m_Score; // the player's generic "score" for the matchmaking algorithm bool m_LoggedIn; // if the player has logged in or not (used with CAdminGame only) bool m_Spoofed; // if the player has spoof checked or not @@ -123,21 +125,21 @@ class CGamePlayer : public CPotentialPlayer bool m_LeftMessageSent; // if the playerleave message has been sent or not bool m_GProxy; // if the player is using GProxy++ bool m_GProxyDisconnectNoticeSent; // if a disconnection notice has been sent or not when using GProxy++ - queue m_GProxyBuffer; + QQueue m_GProxyBuffer; uint32_t m_GProxyReconnectKey; uint32_t m_LastGProxyAckTime; public: - CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ); - CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, BYTEARRAY nInternalIP, bool nReserved ); + CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); + CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); virtual ~CGamePlayer( ); unsigned char GetPID( ) { return m_PID; } QString GetName( ) { return m_Name; } - BYTEARRAY GetInternalIP( ) { return m_InternalIP; } + QByteArray GetInternalIP( ) { return m_InternalIP; } unsigned int GetNumPings( ) { return m_Pings.size( ); } unsigned int GetNumCheckSums( ) { return m_CheckSums.size( ); } - queue *GetCheckSums( ) { return &m_CheckSums; } + QQueue *GetCheckSums( ) { return &m_CheckSums; } QString GetLeftReason( ) { return m_LeftReason; } QString GetSpoofedRealm( ) { return m_SpoofedRealm; } QString GetJoinedRealm( ) { return m_JoinedRealm; } @@ -154,7 +156,7 @@ class CGamePlayer : public CPotentialPlayer uint32_t GetStatsSentTime( ) { return m_StatsSentTime; } uint32_t GetStatsDotASentTime( ) { return m_StatsDotASentTime; } uint32_t GetLastGProxyWaitNoticeSentTime( ) { return m_LastGProxyWaitNoticeSentTime; } - queue *GetLoadInGameData( ) { return &m_LoadInGameData; } + QQueue *GetLoadInGameData( ) { return &m_LoadInGameData; } double GetScore( ) { return m_Score; } bool GetLoggedIn( ) { return m_LoggedIn; } bool GetSpoofed( ) { return m_Spoofed; } @@ -205,7 +207,7 @@ class CGamePlayer : public CPotentialPlayer QString GetNameTerminated( ); uint32_t GetPing( bool LCPing ); - void AddLoadInGameData( BYTEARRAY nLoadInGameData ) { m_LoadInGameData.push( nLoadInGameData ); } + void AddLoadInGameData( QByteArray nLoadInGameData ) { m_LoadInGameData.enqueue( nLoadInGameData ); } // processing functions @@ -215,7 +217,7 @@ class CGamePlayer : public CPotentialPlayer // other functions - virtual void Send( BYTEARRAY data ); + virtual void Send( QByteArray data ); virtual void EventGProxyReconnect( CTCPSocket *NewSocket, uint32_t LastPacket ); }; diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index af638d7..19f7dca 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -66,7 +66,7 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) uint32_t HostCounter = UTIL_QByteArrayToUInt32( data, false, 4 ); QByteArray Name = UTIL_ExtractCString( data, 19 ); - if( !Name.empty( ) && data.size( ) >= Name.size( ) + 30 ) + if( !Name.isEmpty( ) && data.size( ) >= Name.size( ) + 30 ) { QByteArray InternalIP = QByteArray( data.begin( ) + Name.size( ) + 26, data.begin( ) + Name.size( ) + 30 ); return new CIncomingJoinPlayer( HostCounter, QString( Name.begin( ), Name.end( ) ), InternalIP ); @@ -309,7 +309,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; @@ -362,7 +362,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString nam QByteArray packet; - if( !name.empty( ) && name.size( ) <= 15 && externalIP.size( ) == 4 && internalIP.size( ) == 4 ) + if( !name.isEmpty( ) && name.size( ) <= 15 && externalIP.size( ) == 4 && internalIP.size( ) == 4 ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_PLAYERINFO ); // W3GS_PLAYERINFO @@ -440,7 +440,7 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; @@ -482,7 +482,7 @@ QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( queue actions, uint16_t sendInterval ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue actions, uint16_t sendInterval ) { QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -493,14 +493,14 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( queue // create subpacket - if( !actions.empty( ) ) + if( !actions.isEmpty( ) ) { QByteArray subpacket; - while( !actions.empty( ) ) + while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); - actions.pop( ); + actions.dequeue( ); subpacket.push_back( Action->GetPID( ) ); UTIL_AppendQByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); UTIL_AppendQByteArrayFast( subpacket, *Action->GetAction( ) ); @@ -527,7 +527,7 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy { QByteArray packet; - if( !toPIDs.empty( ) && !message.empty( ) && message.size( ) < 255 ) + if( !toPIDs.isEmpty( ) && !message.isEmpty( ) && message.size( ) < 255 ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_CHAT_FROM_HOST ); // W3GS_CHAT_FROM_HOST @@ -549,13 +549,13 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy return packet; } -QByteArray CGameProtocol :: SEND_W3GS_START_LAG( vector players, bool loadInGame ) +QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, bool loadInGame ) { QByteArray packet; unsigned char NumLaggers = 0; - for( vector :: iterator i = players.begin( ); i != players.end( ); i++ ) + for( QVector :: iterator i = players.begin( ); i != players.end( ); i++ ) { if( loadInGame ) { @@ -577,7 +577,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( vector players, packet.push_back( 0 ); // packet length will be assigned later packet.push_back( NumLaggers ); - for( vector :: iterator i = players.begin( ); i != players.end( ); i++ ) + for( QVector :: iterator i = players.begin( ); i != players.end( ); i++ ) { if( loadInGame ) { @@ -663,7 +663,7 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers QByteArray packet; - if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.empty( ) && !hostName.empty( ) && !mapPath.empty( ) && mapCRC.size( ) == 4 ) + if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.isEmpty( ) && !hostName.isEmpty( ) && !mapPath.isEmpty( ) && mapCRC.size( ) == 4 ) { // make the stat QString @@ -779,7 +779,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapS QByteArray packet; - if( !mapPath.empty( ) && mapSize.size( ) == 4 && mapInfo.size( ) == 4 && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 ) + if( !mapPath.isEmpty( ) && mapSize.size( ) == 4 && mapInfo.size( ) == 4 && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_MAPCHECK ); // W3GS_MAPCHECK @@ -861,7 +861,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c return packet; } -QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue actions ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueue actions ) { QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -873,14 +873,14 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( queue // create subpacket - if( !actions.empty( ) ) + if( !actions.isEmpty( ) ) { QByteArray subpacket; - while( !actions.empty( ) ) + while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); - actions.pop( ); + actions.dequeue( ); subpacket.push_back( Action->GetPID( ) ); UTIL_AppendQByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); UTIL_AppendQByteArrayFast( subpacket, *Action->GetAction( ) ); @@ -944,7 +944,7 @@ bool CGameProtocol :: ValidateLength( QByteArray &content ) return false; } -QByteArray CGameProtocol :: EncodeSlotInfo( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: EncodeSlotInfo( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo; SlotInfo.push_back( (unsigned char)slots.size( ) ); // number of slots diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index 1f3421a..59339d1 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -120,17 +120,17 @@ class CGameProtocol // send functions QByteArray SEND_W3GS_PING_FROM_HOST( ); - QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_REJECTJOIN( uint32_t reason ); QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, string name, QByteArray externalIP, QByteArray internalIP ); QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ); QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); - QByteArray SEND_W3GS_SLOTINFO( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFO( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_COUNTDOWN_START( ); QByteArray SEND_W3GS_COUNTDOWN_END( ); - QByteArray SEND_W3GS_INCOMING_ACTION( queue actions, uint16_t sendInterval ); + QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, uint16_t sendInterval ); QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, string message ); - QByteArray SEND_W3GS_START_LAG( vector players, bool loadInGame = false ); + QByteArray SEND_W3GS_START_LAG( QVector players, bool loadInGame = false ); QByteArray SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); QByteArray SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ); @@ -140,14 +140,14 @@ class CGameProtocol QByteArray SEND_W3GS_MAPCHECK( string mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); QByteArray SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, string *mapData ); - QByteArray SEND_W3GS_INCOMING_ACTION2( queue actions ); + QByteArray SEND_W3GS_INCOMING_ACTION2( QQueue actions ); // other functions private: bool AssignLength( QByteArray &content ); bool ValidateLength( QByteArray &content ); - QByteArray EncodeSlotInfo( vector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray EncodeSlotInfo( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); }; // diff --git a/ghost/gameslot.cpp b/ghost/gameslot.cpp index a04b203..8045197 100644 --- a/ghost/gameslot.cpp +++ b/ghost/gameslot.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -25,7 +25,7 @@ // CGameSlot // -CGameSlot :: CGameSlot( BYTEARRAY &n ) +CGameSlot :: CGameSlot( QByteArray &n ) { if( n.size( ) >= 7 ) { @@ -74,14 +74,19 @@ CGameSlot :: CGameSlot( unsigned char nPID, unsigned char nDownloadStatus, unsig m_Handicap = nHandicap; } +CGameSlot :: CGameSlot( ) +{ + // do not use this one, only for vector growing +} + CGameSlot :: ~CGameSlot( ) { } -BYTEARRAY CGameSlot :: GetByteArray( ) const +QByteArray CGameSlot :: GetQByteArray( ) const { - BYTEARRAY b; + QByteArray b; b.push_back( m_PID ); b.push_back( m_DownloadStatus ); b.push_back( m_SlotStatus ); diff --git a/ghost/gameslot.h b/ghost/gameslot.h index 476bfab..f4644f9 100644 --- a/ghost/gameslot.h +++ b/ghost/gameslot.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -54,7 +54,8 @@ class CGameSlot unsigned char m_Handicap; // handicap public: - CGameSlot( BYTEARRAY &n ); + CGameSlot( ); + CGameSlot( QByteArray &n ); CGameSlot( unsigned char nPID, unsigned char nDownloadStatus, unsigned char nSlotStatus, unsigned char nComputer, unsigned char nTeam, unsigned char nColour, unsigned char nRace, unsigned char nComputerType = 1, unsigned char nHandicap = 100 ); ~CGameSlot( ); @@ -78,7 +79,7 @@ class CGameSlot void SetComputerType( unsigned char nComputerType ) { m_ComputerType = nComputerType; } void SetHandicap( unsigned char nHandicap ) { m_Handicap = nHandicap; } - BYTEARRAY GetByteArray( ) const; + QByteArray GetQByteArray( ) const; }; #endif diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 8ab0f57..671da0f 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -114,7 +114,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) sockaddr_in *pAddress; pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress); CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + QString( inet_ntoa( pAddress->sin_addr ) ) + "]" ); - m_LocalAddresses.push_back( UTIL_CreateByteArray( (uint32_t)pAddress->sin_addr.s_addr, false ) ); + m_LocalAddresses.push_back( UTIL_CreateQByteArray( (uint32_t)pAddress->sin_addr.s_addr, false ) ); } } @@ -141,7 +141,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) struct in_addr Address; memcpy( &Address, HostEnt->h_addr_list[i], sizeof(struct in_addr) ); CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + QString( inet_ntoa( Address ) ) + "]" ); - m_LocalAddresses.push_back( UTIL_CreateByteArray( (uint32_t)Address.s_addr, false ) ); + m_LocalAddresses.push_back( UTIL_CreateQByteArray( (uint32_t)Address.s_addr, false ) ); } } } @@ -221,7 +221,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) QString RootAdmin = CFG->GetString( Prefix + "rootadmin", QString( ) ); QString BNETCommandTrigger = CFG->GetString( Prefix + "commandtrigger", "!" ); - if( BNETCommandTrigger.empty( ) ) + if( BNETCommandTrigger.isEmpty( ) ) BNETCommandTrigger = "!"; bool HoldFriends = CFG->GetInt( Prefix + "holdfriends", 1 ) == 0 ? false : true; @@ -231,34 +231,34 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) int BNLSPort = CFG->GetInt( Prefix + "bnlsport", 9367 ); int BNLSWardenCookie = CFG->GetInt( Prefix + "bnlswardencookie", 0 ); unsigned char War3Version = CFG->GetInt( Prefix + "custom_war3version", 24 ); - BYTEARRAY EXEVersion = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversion", QString( ) ), 4 ); - BYTEARRAY EXEVersionHash = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversionhash", QString( ) ), 4 ); + QByteArray EXEVersion = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversion", QString( ) ), 4 ); + QByteArray EXEVersionHash = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversionhash", QString( ) ), 4 ); QString PasswordHashType = CFG->GetString( Prefix + "custom_passwordhashtype", QString( ) ); QString PVPGNRealmName = CFG->GetString( Prefix + "custom_pvpgnrealmname", "PvPGN Realm" ); uint32_t MaxMessageLength = CFG->GetInt( Prefix + "custom_maxmessagelength", 200 ); - if( Server.empty( ) ) + if( Server.isEmpty( ) ) break; - if( CDKeyROC.empty( ) ) + if( CDKeyROC.isEmpty( ) ) { CONSOLE_Print( "[GHOST] missing " + Prefix + "cdkeyroc, skipping this battle.net connection" ); continue; } - if( m_TFT && CDKeyTFT.empty( ) ) + if( m_TFT && CDKeyTFT.isEmpty( ) ) { CONSOLE_Print( "[GHOST] missing " + Prefix + "cdkeytft, skipping this battle.net connection" ); continue; } - if( UserName.empty( ) ) + if( UserName.isEmpty( ) ) { CONSOLE_Print( "[GHOST] missing " + Prefix + "username, skipping this battle.net connection" ); continue; } - if( UserPassword.empty( ) ) + if( UserPassword.isEmpty( ) ) { CONSOLE_Print( "[GHOST] missing " + Prefix + "password, skipping this battle.net connection" ); continue; @@ -278,7 +278,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_BNETs.push_back( new CBNET( this, Server, ServerAlias, BNLSServer, (uint16_t)BNLSPort, (uint32_t)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger[0], HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ) ); } - if( m_BNETs.empty( ) ) + if( m_BNETs.isEmpty( ) ) CONSOLE_Print( "[GHOST] warning - no battle.net connections found in config file" ); // extract common.j and blizzard.j from War3Patch.mpq if we can @@ -289,7 +289,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) // load the default maps (note: make sure to run ExtractScripts first) - if( m_DefaultMap.size( ) < 4 || m_DefaultMap.substr( m_DefaultMap.size( ) - 4 ) != ".cfg" ) + if( m_DefaultMap.size( ) < 4 || m_DefaultMap.mid( m_DefaultMap.size( ) - 4 ) != ".cfg" ) { m_DefaultMap += ".cfg"; CONSOLE_Print( "[GHOST] adding \".cfg\" to default map -> new default is [" + m_DefaultMap + "]" ); @@ -299,9 +299,9 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) MapCFG.Read( m_MapCFGPath + m_DefaultMap ); m_Map = new CMap( this, &MapCFG, m_MapCFGPath + m_DefaultMap ); - if( !m_AdminGameMap.empty( ) ) + if( !m_AdminGameMap.isEmpty( ) ) { - if( m_AdminGameMap.size( ) < 4 || m_AdminGameMap.substr( m_AdminGameMap.size( ) - 4 ) != ".cfg" ) + if( m_AdminGameMap.size( ) < 4 || m_AdminGameMap.mid( m_AdminGameMap.size( ) - 4 ) != ".cfg" ) { m_AdminGameMap += ".cfg"; CONSOLE_Print( "[GHOST] adding \".cfg\" to default admin game map -> new default is [" + m_AdminGameMap + "]" ); @@ -345,7 +345,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) else m_AdminGame = NULL; - if( m_BNETs.empty( ) && !m_AdminGame ) + if( m_BNETs.isEmpty( ) && !m_AdminGame ) CONSOLE_Print( "[GHOST] warning - no battle.net connections found and no admin game created" ); #ifdef GHOST_MYSQL @@ -360,20 +360,20 @@ CGHost :: ~CGHost( ) delete m_UDPSocket; delete m_ReconnectSocket; - for( vector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); i++ ) + for( QVector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); i++ ) delete *i; delete m_GPSProtocol; delete m_CRC; delete m_SHA; - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) delete *i; delete m_CurrentGame; delete m_AdminGame; - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) delete *i; delete m_DB; @@ -383,7 +383,7 @@ CGHost :: ~CGHost( ) // this is fine if the program is currently exiting because the OS will clean up after us // but if you try to recreate the CGHost object within a single session you will probably leak resources! - if( !m_Callables.empty( ) ) + if( !m_Callables.isEmpty( ) ) CONSOLE_Print( "[GHOST] warning - " + UTIL_ToString( m_Callables.size( ) ) + " orphaned callables were leaked (this is not an error)" ); delete m_Language; @@ -413,11 +413,11 @@ bool CGHost :: Update( long usecBlock ) if( m_ExitingNice ) { - if( !m_BNETs.empty( ) ) + if( !m_BNETs.isEmpty( ) ) { CONSOLE_Print( "[GHOST] deleting all battle.net connections in preparation for exiting nicely" ); - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) delete *i; m_BNETs.clear( ); @@ -437,7 +437,7 @@ bool CGHost :: Update( long usecBlock ) m_AdminGame = NULL; } - if( m_Games.empty( ) ) + if( m_Games.isEmpty( ) ) { if( !m_AllGamesFinished ) { @@ -448,7 +448,7 @@ bool CGHost :: Update( long usecBlock ) } else { - if( m_Callables.empty( ) ) + if( m_Callables.isEmpty( ) ) { CONSOLE_Print( "[GHOST] all threads finished, exiting nicely" ); m_Exiting = true; @@ -465,7 +465,7 @@ bool CGHost :: Update( long usecBlock ) // update callables - for( vector :: iterator i = m_Callables.begin( ); i != m_Callables.end( ); ) + for( QVector :: iterator i = m_Callables.begin( ); i != m_Callables.end( ); ) { if( (*i)->GetReady( ) ) { @@ -516,7 +516,7 @@ bool CGHost :: Update( long usecBlock ) // 1. all battle.net sockets - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) NumFDs += (*i)->SetFD( &fd, &send_fd, &nfds ); // 2. the current game's server and player sockets @@ -531,7 +531,7 @@ bool CGHost :: Update( long usecBlock ) // 4. all running games' player sockets - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) NumFDs += (*i)->SetFD( &fd, &send_fd, &nfds ); // 5. the GProxy++ reconnect socket(s) @@ -542,7 +542,7 @@ bool CGHost :: Update( long usecBlock ) NumFDs++; } - for( vector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); i++ ) + for( QVector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); i++ ) { (*i)->SetFD( &fd, &send_fd, &nfds ); NumFDs++; @@ -553,7 +553,7 @@ bool CGHost :: Update( long usecBlock ) // however, in an effort to make game updates happen closer to the desired latency setting we now use a dynamic block interval // note: we still use the passed usecBlock as a hard maximum - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) { if( (*i)->GetNextTimedActionTicks( ) * 1000 < usecBlock ) usecBlock = (*i)->GetNextTimedActionTicks( ) * 1000; @@ -604,7 +604,7 @@ bool CGHost :: Update( long usecBlock ) delete m_CurrentGame; m_CurrentGame = NULL; - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { (*i)->QueueGameUncreate( ); (*i)->QueueEnterChat( ); @@ -631,7 +631,7 @@ bool CGHost :: Update( long usecBlock ) // update running games - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); ) { if( (*i)->Update( &fd, &send_fd ) ) { @@ -649,7 +649,7 @@ bool CGHost :: Update( long usecBlock ) // update battle.net connections - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->Update( &fd, &send_fd ) ) BNETExit = true; @@ -665,7 +665,7 @@ bool CGHost :: Update( long usecBlock ) m_ReconnectSockets.push_back( NewSocket ); } - for( vector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); ) + for( QVector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); ) { if( (*i)->HasError( ) || !(*i)->GetConnected( ) || GetTime( ) - (*i)->GetLastRecv( ) >= 10 ) { @@ -676,7 +676,7 @@ bool CGHost :: Update( long usecBlock ) (*i)->DoRecv( &fd ); QString *RecvBuffer = (*i)->GetBytes( ); - BYTEARRAY Bytes = UTIL_CreateByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); // a packet is at least 4 bytes @@ -686,7 +686,7 @@ bool CGHost :: Update( long usecBlock ) { // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_ByteArrayToUInt16( Bytes, false, 2 ); + uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); if( Length >= 4 ) { @@ -695,14 +695,14 @@ bool CGHost :: Update( long usecBlock ) if( Bytes[1] == CGPSProtocol :: GPS_RECONNECT && Length == 13 ) { unsigned char PID = Bytes[4]; - uint32_t ReconnectKey = UTIL_ByteArrayToUInt32( Bytes, false, 5 ); - uint32_t LastPacket = UTIL_ByteArrayToUInt32( Bytes, false, 9 ); + uint32_t ReconnectKey = UTIL_QByteArrayToUInt32( Bytes, false, 5 ); + uint32_t LastPacket = UTIL_QByteArrayToUInt32( Bytes, false, 9 ); // look for a matching player in a running game CGamePlayer *Match = NULL; - for( vector :: iterator j = m_Games.begin( ); j != m_Games.end( ); j++ ) + for( QVector :: iterator j = m_Games.begin( ); j != m_Games.end( ); j++ ) { if( (*j)->GetGameLoaded( ) ) { @@ -769,7 +769,7 @@ bool CGHost :: Update( long usecBlock ) // autohost - if( !m_AutoHostGameName.empty( ) && m_AutoHostMaximumGames != 0 && m_AutoHostAutoStartPlayers != 0 && GetTime( ) - m_LastAutoHostTime >= 30 ) + if( !m_AutoHostGameName.isEmpty( ) && m_AutoHostMaximumGames != 0 && m_AutoHostAutoStartPlayers != 0 && GetTime( ) - m_LastAutoHostTime >= 30 ) { // copy all the checks from CGHost :: CreateGame here because we don't want to spam the chat when there's an error // instead we fail silently and try again soon @@ -790,7 +790,7 @@ bool CGHost :: Update( long usecBlock ) if( m_AutoHostMatchMaking ) { - if( !m_Map->GetMapMatchMakingCategory( ).empty( ) ) + if( !m_Map->GetMapMatchMakingCategory( ).isEmpty( ) ) { if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) ) CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory [" + m_Map->GetMapMatchMakingCategory( ) + "] found but matchmaking can only be used with fixed player settings, matchmaking disabled" ); @@ -890,7 +890,7 @@ void CGHost :: EventBNETGameRefreshFailed( CBNET *bnet ) { if( m_CurrentGame ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { (*i)->QueueChatCommand( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); @@ -932,7 +932,7 @@ void CGHost :: EventBNETWhisper( CBNET *bnet, QString user, QString message ) if( m_CurrentGame ) m_CurrentGame->SendLocalAdminChat( "[W: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) (*i)->SendLocalAdminChat( "[W: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); } } @@ -946,7 +946,7 @@ void CGHost :: EventBNETChat( CBNET *bnet, QString user, QString message ) if( m_CurrentGame ) m_CurrentGame->SendLocalAdminChat( "[L: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) (*i)->SendLocalAdminChat( "[L: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); } } @@ -960,14 +960,14 @@ void CGHost :: EventBNETEmote( CBNET *bnet, QString user, QString message ) if( m_CurrentGame ) m_CurrentGame->SendLocalAdminChat( "[E: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); - for( vector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) (*i)->SendLocalAdminChat( "[E: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); } } void CGHost :: EventGameDeleted( CBaseGame *game ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { (*i)->QueueChatCommand( m_Language->GameIsOver( game->GetDescription( ) ) ); @@ -998,7 +998,7 @@ void CGHost :: SetConfigs( CConfig *CFG ) m_MaxGames = CFG->GetInt( "bot_maxgames", 5 ); QString BotCommandTrigger = CFG->GetString( "bot_commandtrigger", "!" ); - if( BotCommandTrigger.empty( ) ) + if( BotCommandTrigger.isEmpty( ) ) BotCommandTrigger = "!"; m_CommandTrigger = BotCommandTrigger[0]; @@ -1157,7 +1157,7 @@ void CGHost :: LoadIPToCountryData( ) { getline( in, Line ); - if( Line.empty( ) ) + if( Line.isEmpty( ) ) continue; parser << Line; @@ -1192,7 +1192,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS { if( !m_Enabled ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameDisabled( gameName ), creatorName, whisper ); @@ -1206,7 +1206,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( gameName.size( ) > 31 ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameNameTooLong( gameName ), creatorName, whisper ); @@ -1220,7 +1220,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( !map->GetValid( ) ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameInvalidMap( gameName ), creatorName, whisper ); @@ -1236,7 +1236,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS { if( !m_SaveGame->GetValid( ) ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameInvalidSaveGame( gameName ), creatorName, whisper ); @@ -1257,7 +1257,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS { CONSOLE_Print( "[GHOST] path mismatch, saved game path is [" + MapPath1 + "] but map path is [" + MapPath2 + "]" ); - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameSaveGameMapMismatch( gameName ), creatorName, whisper ); @@ -1269,9 +1269,9 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS return; } - if( m_EnforcePlayers.empty( ) ) + if( m_EnforcePlayers.isEmpty( ) ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameMustEnforceFirst( gameName ), creatorName, whisper ); @@ -1286,7 +1286,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( m_CurrentGame ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameAnotherGameInLobby( gameName, m_CurrentGame->GetDescription( ) ), creatorName, whisper ); @@ -1300,7 +1300,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( m_Games.size( ) >= m_MaxGames ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameMaxGamesReached( gameName, UTIL_ToString( m_MaxGames ) ), creatorName, whisper ); @@ -1327,7 +1327,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS m_EnforcePlayers.clear( ); } - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( whisper && (*i)->GetServer( ) == creatorServer ) { @@ -1368,7 +1368,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( gameState == GAME_PRIVATE ) { - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetPasswordHashType( ) != "pvpgn" ) (*i)->QueueEnterChat( ); @@ -1377,7 +1377,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS // hold friends and/or clan members - for( vector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetHoldFriends( ) ) (*i)->HoldFriends( m_CurrentGame ); diff --git a/ghost/ghost.h b/ghost/ghost.h index 5aedbde..2949111 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -50,24 +50,24 @@ class CGHost : public QObject public: CUDPSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) CTCPServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects - vector m_ReconnectSockets;// vector of sockets attempting to reconnect (connected but not identified yet) + QVector m_ReconnectSockets;// vector of sockets attempting to reconnect (connected but not identified yet) CGPSProtocol *m_GPSProtocol; CCRC32 *m_CRC; // for calculating CRC's CSHA1 *m_SHA; // for calculating SHA1's - vector m_BNETs; // all our battle.net connections (there can be more than one) + QVector m_BNETs; // all our battle.net connections (there can be more than one) CBaseGame *m_CurrentGame; // this game is still in the lobby state CAdminGame *m_AdminGame; // this "fake game" allows an admin who knows the password to control the bot from the local network - vector m_Games; // these games are in progress + QVector m_Games; // these games are in progress CGHostDB *m_DB; // database CGHostDB *m_DBLocal; // local database (for temporary data) - vector m_Callables; // vector of orphaned callables waiting to die - vector m_LocalAddresses; // vector of local IP addresses + QVector m_Callables; // vector of orphaned callables waiting to die + QVector m_LocalAddresses; // vector of local IP addresses CLanguage *m_Language; // language CMap *m_Map; // the currently loaded map CMap *m_AdminMap; // the map to use in the admin game CMap *m_AutoHostMap; // the map to use when autohosting CSaveGame *m_SaveGame; // the save game to use - vector m_EnforcePlayers; // vector of pids to force players to use in the next game (used with saved games) + QVector m_EnforcePlayers; // vector of pids to force players to use in the next game (used with saved games) bool m_Exiting; // set to true to force ghost to shutdown next update (used by SignalCatcher) bool m_ExitingNice; // set to true to force ghost to disconnect from all battle.net connections and wait for all games to finish before shutting down bool m_Enabled; // set to false to prevent new games from being created diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index 68f70c7..fcb9f33 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -72,9 +72,9 @@ bool CGHostDB :: AdminRemove( QString server, QString user ) return false; } -vector CGHostDB :: AdminList( QString server ) +QVector CGHostDB :: AdminList( QString server ) { - return vector( ); + return QVector( ); } uint32_t CGHostDB :: BanCount( QString server ) @@ -102,9 +102,9 @@ bool CGHostDB :: BanRemove( QString user ) return false; } -vector CGHostDB :: BanList( QString server ) +QVector CGHostDB :: BanList( QString server ) { - return vector( ); + return QVector( ); } uint32_t CGHostDB :: GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) @@ -167,17 +167,17 @@ uint32_t CGHostDB :: W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t return 0; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, map var_ints ) +bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, QMap var_ints ) { return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, map var_reals ) +bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, QMap var_reals ) { return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, map var_strings ) +bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, QMap var_strings ) { return false; } @@ -287,17 +287,17 @@ CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString category, u return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ) { return NULL; } diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index 1f7f229..4bfe051 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -78,13 +78,13 @@ class CGHostDB virtual bool AdminCheck( QString server, QString user ); virtual bool AdminAdd( QString server, QString user ); virtual bool AdminRemove( QString server, QString user ); - virtual vector AdminList( QString server ); + virtual QVector AdminList( QString server ); virtual uint32_t BanCount( QString server ); virtual CDBBan *BanCheck( QString server, QString user, QString ip ); virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); virtual bool BanRemove( QString server, QString user ); virtual bool BanRemove( QString user ); - virtual vector BanList( QString server ); + virtual QVector BanList( QString server ); virtual uint32_t GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); virtual uint32_t GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); virtual uint32_t GamePlayerCount( QString name ); @@ -97,9 +97,9 @@ class CGHostDB virtual bool FromAdd( uint32_t ip1, uint32_t ip2, QString country ); virtual bool DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); virtual uint32_t W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_ints ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_ints ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_reals ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_strings ); // threaded database functions @@ -124,9 +124,9 @@ class CGHostDB virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); virtual CCallableScoreCheck *ThreadedScoreCheck( QString category, QString name, QString server ); virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); }; // @@ -245,14 +245,14 @@ class CCallableAdminList : virtual public CBaseCallable { protected: QString m_Server; - vector m_Result; + QVector m_Result; public: CCallableAdminList( QString nServer ) : CBaseCallable( ), m_Server( nServer ) { } virtual ~CCallableAdminList( ); - virtual vector GetResult( ) { return m_Result; } - virtual void SetResult( vector nResult ) { m_Result = nResult; } + virtual QVector GetResult( ) { return m_Result; } + virtual void SetResult( QVector nResult ) { m_Result = nResult; } }; class CCallableBanCount : virtual public CBaseCallable @@ -335,14 +335,14 @@ class CCallableBanList : virtual public CBaseCallable { protected: QString m_Server; - vector m_Result; + QVector m_Result; public: CCallableBanList( QString nServer ) : CBaseCallable( ), m_Server( nServer ) { } virtual ~CCallableBanList( ); - virtual vector GetResult( ) { return m_Result; } - virtual void SetResult( vector nResult ) { m_Result = nResult; } + virtual QVector GetResult( ) { return m_Result; } + virtual void SetResult( QVector nResult ) { m_Result = nResult; } }; class CCallableGameAdd : virtual public CBaseCallable @@ -531,9 +531,9 @@ class CCallableW3MMDVarAdd : virtual public CBaseCallable { protected: uint32_t m_GameID; - map m_VarInts; - map m_VarReals; - map m_VarStrings; + QMap m_VarInts; + QMap m_VarReals; + QMap m_VarStrings; enum ValueType { VALUETYPE_INT = 1, @@ -545,9 +545,9 @@ class CCallableW3MMDVarAdd : virtual public CBaseCallable bool m_Result; public: - CCallableW3MMDVarAdd( uint32_t nGameID, map nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } - CCallableW3MMDVarAdd( uint32_t nGameID, map nVarReals ) : CBaseCallable( ), m_GameID( nGameID ), m_VarReals( nVarReals ), m_ValueType( VALUETYPE_REAL ), m_Result( false ) { } - CCallableW3MMDVarAdd( uint32_t nGameID, map nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } + CCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } + CCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarReals ) : CBaseCallable( ), m_GameID( nGameID ), m_VarReals( nVarReals ), m_ValueType( VALUETYPE_REAL ), m_Result( false ) { } + CCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } virtual ~CCallableW3MMDVarAdd( ); virtual bool GetResult( ) { return m_Result; } diff --git a/ghost/ghostdbmysql.cpp b/ghost/ghostdbmysql.cpp index b603c16..9ec6434 100644 --- a/ghost/ghostdbmysql.cpp +++ b/ghost/ghostdbmysql.cpp @@ -76,17 +76,17 @@ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) return; } - m_IdleConnections.push( Connection ); + m_IdleConnections.enqueue( Connection ); } CGHostDBMySQL :: ~CGHostDBMySQL( ) { CONSOLE_Print( "[MYSQL] closing " + UTIL_ToString( m_IdleConnections.size( ) ) + "/" + UTIL_ToString( m_NumConnections ) + " idle MySQL connections" ); - while( !m_IdleConnections.empty( ) ) + while( !m_IdleConnections.isEmpty( ) ) { mysql_close( (MYSQL *)m_IdleConnections.front( ) ); - m_IdleConnections.pop( ); + m_IdleConnections.dequeue( ); } if( m_OutstandingCallables > 0 ) @@ -112,14 +112,14 @@ void CGHostDBMySQL :: RecoverCallable( CBaseCallable *callable ) m_NumConnections--; } else - m_IdleConnections.push( MySQLCallable->GetConnection( ) ); + m_IdleConnections.enqueue( MySQLCallable->GetConnection( ) ); if( m_OutstandingCallables == 0 ) CONSOLE_Print( "[MYSQL] recovered a mysql callable with zero outstanding" ); else m_OutstandingCallables--; - if( !MySQLCallable->GetError( ).empty( ) ) + if( !MySQLCallable->GetError( ).isEmpty( ) ) CONSOLE_Print( "[MYSQL] error --- " + MySQLCallable->GetError( ) ); } else @@ -409,7 +409,7 @@ CCallableW3MMDPlayerAdd *CGHostDBMySQL :: ThreadedW3MMDPlayerAdd( QString catego return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ) { void *Connection = GetIdleConnection( ); @@ -422,7 +422,7 @@ CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ) { void *Connection = GetIdleConnection( ); @@ -435,7 +435,7 @@ CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ) { void *Connection = GetIdleConnection( ); @@ -452,10 +452,10 @@ void *CGHostDBMySQL :: GetIdleConnection( ) { void *Connection = NULL; - if( !m_IdleConnections.empty( ) ) + if( !m_IdleConnections.isEmpty( ) ) { Connection = m_IdleConnections.front( ); - m_IdleConnections.pop( ); + m_IdleConnections.dequeue( ); } return Connection; @@ -474,9 +474,9 @@ QString MySQLEscapeString( void *conn, QString str ) return result; } -vector MySQLFetchRow( MYSQL_RES *res ) +QVector MySQLFetchRow( MYSQL_RES *res ) { - vector Result; + QVector Result; MYSQL_ROW Row = mysql_fetch_row( res ); @@ -515,7 +515,7 @@ uint32_t MySQLAdminCount( void *conn, QString *error, uint32_t botid, QString se if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Count = UTIL_ToUInt32( Row[0] ); @@ -547,9 +547,9 @@ bool MySQLAdminCheck( void *conn, QString *error, uint32_t botid, QString server if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); - if( !Row.empty( ) ) + if( !Row.isEmpty( ) ) IsAdmin = true; mysql_free_result( Result ); @@ -593,10 +593,10 @@ bool MySQLAdminRemove( void *conn, QString *error, uint32_t botid, QString serve return Success; } -vector MySQLAdminList( void *conn, QString *error, uint32_t botid, QString server ) +QVector MySQLAdminList( void *conn, QString *error, uint32_t botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); - vector AdminList; + QVector AdminList; QString Query = "SELECT name FROM admins WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -607,9 +607,9 @@ vector MySQLAdminList( void *conn, QString *error, uint32_t botid, QStr if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); - while( !Row.empty( ) ) + while( !Row.isEmpty( ) ) { AdminList.push_back( Row[0] ); Row = MySQLFetchRow( Result ); @@ -638,7 +638,7 @@ uint32_t MySQLBanCount( void *conn, QString *error, uint32_t botid, QString serv if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Count = UTIL_ToUInt32( Row[0] ); @@ -663,7 +663,7 @@ CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString serve CDBBan *Ban = NULL; QString Query; - if( ip.empty( ) ) + if( ip.isEmpty( ) ) Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE server='" + EscServer + "' AND name='" + EscUser + "'"; else Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE (server='" + EscServer + "' AND name='" + EscUser + "') OR ip='" + EscIP + "'"; @@ -676,7 +676,7 @@ CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString serve if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); if( Row.size( ) == 6 ) Ban = new CDBBan( server, Row[0], Row[1], Row[2], Row[3], Row[4], Row[5] ); @@ -743,10 +743,10 @@ bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString user ) return Success; } -vector MySQLBanList( void *conn, QString *error, uint32_t botid, QString server ) +QVector MySQLBanList( void *conn, QString *error, uint32_t botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); - vector BanList; + QVector BanList; QString Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -757,7 +757,7 @@ vector MySQLBanList( void *conn, QString *error, uint32_t botid, QStri if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); while( Row.size( ) == 6 ) { @@ -826,7 +826,7 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, u if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); if( Row.size( ) == 12 ) { @@ -904,7 +904,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, u if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); if( Row.size( ) == 10 ) { @@ -936,7 +936,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, u if( Result2 ) { - vector Row2 = MySQLFetchRow( Result2 ); + QVector Row2 = MySQLFetchRow( Result2 ); if( Row2.size( ) == 1 ) TotalWins = UTIL_ToUInt32( Row2[0] ); @@ -961,7 +961,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, u if( Result3 ) { - vector Row3 = MySQLFetchRow( Result3 ); + QVector Row3 = MySQLFetchRow( Result3 ); if( Row3.size( ) == 1 ) TotalLosses = UTIL_ToUInt32( Row3[0] ); @@ -1025,7 +1025,7 @@ double MySQLScoreCheck( void *conn, QString *error, uint32_t botid, QString cate if( Result ) { - vector Row = MySQLFetchRow( Result ); + QVector Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Score = UTIL_ToDouble( Row[0] ); @@ -1058,19 +1058,19 @@ uint32_t MySQLW3MMDPlayerAdd( void *conn, QString *error, uint32_t botid, QStrin return RowID; } -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, map var_ints ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_ints ) { - if( var_ints.empty( ) ) + if( var_ints.isEmpty( ) ) return false; bool Success = false; QString Query; - for( map :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) + for( QMap :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) { QString EscVarName = MySQLEscapeString( conn, i->first.second ); - if( Query.empty( ) ) + if( Query.isEmpty( ) ) Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_int ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', " + UTIL_ToString( i->second ) + " )"; else Query += ", ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', " + UTIL_ToString( i->second ) + " )"; @@ -1084,19 +1084,19 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t game return Success; } -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, map var_reals ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_reals ) { - if( var_reals.empty( ) ) + if( var_reals.isEmpty( ) ) return false; bool Success = false; QString Query; - for( map :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) + for( QMap :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) { QString EscVarName = MySQLEscapeString( conn, i->first.second ); - if( Query.empty( ) ) + if( Query.isEmpty( ) ) Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_real ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', " + UTIL_ToString( i->second, 10 ) + " )"; else Query += ", ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', " + UTIL_ToString( i->second, 10 ) + " )"; @@ -1110,20 +1110,20 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t game return Success; } -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, map var_strings ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_strings ) { - if( var_strings.empty( ) ) + if( var_strings.isEmpty( ) ) return false; bool Success = false; QString Query; - for( map :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) + for( QMap :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) { QString EscVarName = MySQLEscapeString( conn, i->first.second ); QString EscValueString = MySQLEscapeString( conn, i->second ); - if( Query.empty( ) ) + if( Query.isEmpty( ) ) Query = "INSERT INTO w3mmdvars ( botid, gameid, pid, varname, value_QString ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', '" + EscValueString + "' )"; else Query += ", ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( i->first.first ) + ", '" + EscVarName + "', '" + EscValueString + "' )"; @@ -1180,7 +1180,7 @@ void CMySQLCallableAdminCount :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLAdminCount( m_Connection, &m_Error, m_SQLBotID, m_Server ); Close( ); @@ -1190,7 +1190,7 @@ void CMySQLCallableAdminCheck :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLAdminCheck( m_Connection, &m_Error, m_SQLBotID, m_Server, m_User ); Close( ); @@ -1200,7 +1200,7 @@ void CMySQLCallableAdminAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLAdminAdd( m_Connection, &m_Error, m_SQLBotID, m_Server, m_User ); Close( ); @@ -1210,7 +1210,7 @@ void CMySQLCallableAdminRemove :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLAdminRemove( m_Connection, &m_Error, m_SQLBotID, m_Server, m_User ); Close( ); @@ -1220,7 +1220,7 @@ void CMySQLCallableAdminList :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLAdminList( m_Connection, &m_Error, m_SQLBotID, m_Server ); Close( ); @@ -1230,7 +1230,7 @@ void CMySQLCallableBanCount :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLBanCount( m_Connection, &m_Error, m_SQLBotID, m_Server ); Close( ); @@ -1240,7 +1240,7 @@ void CMySQLCallableBanCheck :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLBanCheck( m_Connection, &m_Error, m_SQLBotID, m_Server, m_User, m_IP ); Close( ); @@ -1250,7 +1250,7 @@ void CMySQLCallableBanAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLBanAdd( m_Connection, &m_Error, m_SQLBotID, m_Server, m_User, m_IP, m_GameName, m_Admin, m_Reason ); Close( ); @@ -1260,9 +1260,9 @@ void CMySQLCallableBanRemove :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) { - if( m_Server.empty( ) ) + if( m_Server.isEmpty( ) ) m_Result = MySQLBanRemove( m_Connection, &m_Error, m_SQLBotID, m_User ); else m_Result = MySQLBanRemove( m_Connection, &m_Error, m_SQLBotID, m_Server, m_User ); @@ -1275,7 +1275,7 @@ void CMySQLCallableBanList :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLBanList( m_Connection, &m_Error, m_SQLBotID, m_Server ); Close( ); @@ -1285,7 +1285,7 @@ void CMySQLCallableGameAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLGameAdd( m_Connection, &m_Error, m_SQLBotID, m_Server, m_Map, m_GameName, m_OwnerName, m_Duration, m_GameState, m_CreatorName, m_CreatorServer ); Close( ); @@ -1295,7 +1295,7 @@ void CMySQLCallableGamePlayerAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLGamePlayerAdd( m_Connection, &m_Error, m_SQLBotID, m_GameID, m_Name, m_IP, m_Spoofed, m_SpoofedRealm, m_Reserved, m_LoadingTime, m_Left, m_LeftReason, m_Team, m_Colour ); Close( ); @@ -1305,7 +1305,7 @@ void CMySQLCallableGamePlayerSummaryCheck :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLGamePlayerSummaryCheck( m_Connection, &m_Error, m_SQLBotID, m_Name ); Close( ); @@ -1315,7 +1315,7 @@ void CMySQLCallableDotAGameAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLDotAGameAdd( m_Connection, &m_Error, m_SQLBotID, m_GameID, m_Winner, m_Min, m_Sec ); Close( ); @@ -1325,7 +1325,7 @@ void CMySQLCallableDotAPlayerAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLDotAPlayerAdd( m_Connection, &m_Error, m_SQLBotID, m_GameID, m_Colour, m_Kills, m_Deaths, m_CreepKills, m_CreepDenies, m_Assists, m_Gold, m_NeutralKills, m_Item1, m_Item2, m_Item3, m_Item4, m_Item5, m_Item6, m_Hero, m_NewColour, m_TowerKills, m_RaxKills, m_CourierKills ); Close( ); @@ -1335,7 +1335,7 @@ void CMySQLCallableDotAPlayerSummaryCheck :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLDotAPlayerSummaryCheck( m_Connection, &m_Error, m_SQLBotID, m_Name ); Close( ); @@ -1345,7 +1345,7 @@ void CMySQLCallableDownloadAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLDownloadAdd( m_Connection, &m_Error, m_SQLBotID, m_Map, m_MapSize, m_Name, m_IP, m_Spoofed, m_SpoofedRealm, m_DownloadTime ); Close( ); @@ -1355,7 +1355,7 @@ void CMySQLCallableScoreCheck :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLScoreCheck( m_Connection, &m_Error, m_SQLBotID, m_Category, m_Name, m_Server ); Close( ); @@ -1365,7 +1365,7 @@ void CMySQLCallableW3MMDPlayerAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) m_Result = MySQLW3MMDPlayerAdd( m_Connection, &m_Error, m_SQLBotID, m_Category, m_GameID, m_PID, m_Name, m_Flag, m_Leaver, m_Practicing ); Close( ); @@ -1375,7 +1375,7 @@ void CMySQLCallableW3MMDVarAdd :: operator( )( ) { Init( ); - if( m_Error.empty( ) ) + if( m_Error.isEmpty( ) ) { if( m_ValueType == VALUETYPE_INT ) m_Result = MySQLW3MMDVarAdd( m_Connection, &m_Error, m_SQLBotID, m_GameID, m_VarInts ); diff --git a/ghost/ghostdbmysql.h b/ghost/ghostdbmysql.h index f074871..e1dec30 100644 --- a/ghost/ghostdbmysql.h +++ b/ghost/ghostdbmysql.h @@ -173,7 +173,7 @@ class CGHostDBMySQL : public CGHostDB string m_Password; uint16_t m_Port; uint32_t m_BotID; - queue m_IdleConnections; + QQueue m_IdleConnections; uint32_t m_NumConnections; uint32_t m_OutstandingCallables; @@ -208,9 +208,9 @@ class CGHostDBMySQL : public CGHostDB virtual CCallableDownloadAdd *ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); virtual CCallableScoreCheck *ThreadedScoreCheck( string category, string name, string server ); virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); // other database functions @@ -225,13 +225,13 @@ uint32_t MySQLAdminCount( void *conn, string *error, uint32_t botid, string serv bool MySQLAdminCheck( void *conn, string *error, uint32_t botid, string server, string user ); bool MySQLAdminAdd( void *conn, string *error, uint32_t botid, string server, string user ); bool MySQLAdminRemove( void *conn, string *error, uint32_t botid, string server, string user ); -vector MySQLAdminList( void *conn, string *error, uint32_t botid, string server ); +QVector MySQLAdminList( void *conn, string *error, uint32_t botid, string server ); uint32_t MySQLBanCount( void *conn, string *error, uint32_t botid, string server ); CDBBan *MySQLBanCheck( void *conn, string *error, uint32_t botid, string server, string user, string ip ); bool MySQLBanAdd( void *conn, string *error, uint32_t botid, string server, string user, string ip, string gamename, string admin, string reason ); bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string server, string user ); bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string user ); -vector MySQLBanList( void *conn, string *error, uint32_t botid, string server ); +QVector MySQLBanList( void *conn, string *error, uint32_t botid, string server ); uint32_t MySQLGameAdd( void *conn, string *error, uint32_t botid, string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); uint32_t MySQLGamePlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, string *error, uint32_t botid, string name ); @@ -241,9 +241,9 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, ui bool MySQLDownloadAdd( void *conn, string *error, uint32_t botid, string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); double MySQLScoreCheck( void *conn, string *error, uint32_t botid, string category, string name, string server ); uint32_t MySQLW3MMDPlayerAdd( void *conn, string *error, uint32_t botid, string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, map var_ints ); -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, map var_reals ); -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, map var_strings ); +bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, QMap var_ints ); +bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, QMap var_reals ); +bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, QMap var_strings ); // // MySQL Callables @@ -482,9 +482,9 @@ class CMySQLCallableW3MMDPlayerAdd : public CCallableW3MMDPlayerAdd, public CMyS class CMySQLCallableW3MMDVarAdd : public CCallableW3MMDVarAdd, public CMySQLCallable { public: - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, map nVarInts, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarInts ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, map nVarReals, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarReals ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, map nVarStrings, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarStrings ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarInts, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarInts ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarReals, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarReals ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarStrings, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarStrings ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableW3MMDVarAdd( ) { } virtual void operator( )( ); diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index 9d6dd33..2f2206d 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -133,7 +133,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) if( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + QVector *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) SchemaNumber = (*Row)[0]; @@ -148,7 +148,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) else CONSOLE_Print( "[SQLITE3] prepare error getting schema number - " + m_DB->GetError( ) ); - if( SchemaNumber.empty( ) ) + if( SchemaNumber.isEmpty( ) ) { // couldn't find the schema number // unfortunately the very first schema didn't have a config table @@ -659,9 +659,9 @@ bool CGHostDBSQLite :: AdminRemove( QString server, QString user ) return Success; } -vector CGHostDBSQLite :: AdminList( QString server ) +QVector CGHostDBSQLite :: AdminList( QString server ) { - vector AdminList; + QVector AdminList; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT name FROM admins WHERE server=?", (void **)&Statement ); @@ -672,7 +672,7 @@ vector CGHostDBSQLite :: AdminList( QString server ) while( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + QVector *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) AdminList.push_back( (*Row)[0] ); @@ -721,7 +721,7 @@ CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) CDBBan *Ban = NULL; sqlite3_stmt *Statement; - if( ip.empty( ) ) + if( ip.isEmpty( ) ) m_DB->Prepare( "SELECT name, ip, date, gamename, admin, reason FROM bans WHERE server=? AND name=?", (void **)&Statement ); else m_DB->Prepare( "SELECT name, ip, date, gamename, admin, reason FROM bans WHERE (server=? AND name=?) OR ip=?", (void **)&Statement ); @@ -731,14 +731,14 @@ CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); - if( !ip.empty( ) ) + if( !ip.isEmpty( ) ) sqlite3_bind_text( Statement, 3, ip.c_str( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + QVector *Row = m_DB->GetRow( ); if( Row->size( ) == 6 ) Ban = new CDBBan( server, (*Row)[0], (*Row)[1], (*Row)[2], (*Row)[3], (*Row)[4], (*Row)[5] ); @@ -838,9 +838,9 @@ bool CGHostDBSQLite :: BanRemove( QString user ) return Success; } -vector CGHostDBSQLite :: BanList( QString server ) +QVector CGHostDBSQLite :: BanList( QString server ) { - vector BanList; + QVector BanList; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT name, ip, date, gamename, admin, reason FROM bans WHERE server=?", (void **)&Statement ); @@ -851,7 +851,7 @@ vector CGHostDBSQLite :: BanList( QString server ) while( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + QVector *Row = m_DB->GetRow( ); if( Row->size( ) == 6 ) BanList.push_back( new CDBBan( server, (*Row)[0], (*Row)[1], (*Row)[2], (*Row)[3], (*Row)[4], (*Row)[5] ) ); @@ -1224,7 +1224,7 @@ QString CGHostDBSQLite :: FromCheck( uint32_t ip ) if( RC == SQLITE_ROW ) { - vector *Row = m_DB->GetRow( ); + QVector *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) From = (*Row)[0]; @@ -1336,15 +1336,15 @@ uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( QString category, uint32_t gameid, ui return RowID; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_ints ) +bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_ints ) { - if( var_ints.empty( ) ) + if( var_ints.isEmpty( ) ) return false; bool Success = true; sqlite3_stmt *Statement = NULL; - for( map :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) + for( QMap :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_int ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1381,15 +1381,15 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_ints return Success; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_reals ) +bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_reals ) { - if( var_reals.empty( ) ) + if( var_reals.isEmpty( ) ) return false; bool Success = true; sqlite3_stmt *Statement = NULL; - for( map :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) + for( QMap :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_real ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1426,15 +1426,15 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_reals return Success; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, map var_strings ) +bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_strings ) { - if( var_strings.empty( ) ) + if( var_strings.isEmpty( ) ) return false; bool Success = true; sqlite3_stmt *Statement = NULL; - for( map :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) + for( QMap :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_QString ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1623,7 +1623,7 @@ CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( QString categ return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_ints ); Callable->SetResult( W3MMDVarAdd( gameid, var_ints ) ); @@ -1631,7 +1631,7 @@ CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, ma return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_reals ); Callable->SetResult( W3MMDVarAdd( gameid, var_reals ) ); @@ -1639,7 +1639,7 @@ CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, ma return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_strings ); Callable->SetResult( W3MMDVarAdd( gameid, var_strings ) ); diff --git a/ghost/ghostdbsqlite.h b/ghost/ghostdbsqlite.h index fe0d03e..b415415 100644 --- a/ghost/ghostdbsqlite.h +++ b/ghost/ghostdbsqlite.h @@ -163,14 +163,14 @@ class CSQLITE3 private: void *m_DB; bool m_Ready; - vector m_Row; + QVector m_Row; public: CSQLITE3( string filename ); ~CSQLITE3( ); bool GetReady( ) { return m_Ready; } - vector *GetRow( ) { return &m_Row; } + QVector *GetRow( ) { return &m_Row; } string GetError( ); int Prepare( string query, void **Statement ); @@ -216,13 +216,13 @@ class CGHostDBSQLite : public CGHostDB virtual bool AdminCheck( string server, string user ); virtual bool AdminAdd( string server, string user ); virtual bool AdminRemove( string server, string user ); - virtual vector AdminList( string server ); + virtual QVector AdminList( string server ); virtual uint32_t BanCount( string server ); virtual CDBBan *BanCheck( string server, string user, string ip ); virtual bool BanAdd( string server, string user, string ip, string gamename, string admin, string reason ); virtual bool BanRemove( string server, string user ); virtual bool BanRemove( string user ); - virtual vector BanList( string server ); + virtual QVector BanList( string server ); virtual uint32_t GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); virtual uint32_t GamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); virtual uint32_t GamePlayerCount( string name ); @@ -235,9 +235,9 @@ class CGHostDBSQLite : public CGHostDB virtual bool FromAdd( uint32_t ip1, uint32_t ip2, string country ); virtual bool DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); virtual uint32_t W3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_ints ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual bool W3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_ints ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_reals ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_strings ); // threaded database functions // note: these are not actually implemented with threads at the moment, they WILL block until the query is complete @@ -262,9 +262,9 @@ class CGHostDBSQLite : public CGHostDB virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( string name ); virtual CCallableDownloadAdd *ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_ints ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, map var_strings ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); }; #endif diff --git a/ghost/gpsprotocol.cpp b/ghost/gpsprotocol.cpp index 60de892..c87c385 100644 --- a/ghost/gpsprotocol.cpp +++ b/ghost/gpsprotocol.cpp @@ -42,91 +42,91 @@ CGPSProtocol :: ~CGPSProtocol( ) // SEND FUNCTIONS // //////////////////// -BYTEARRAY CGPSProtocol :: SEND_GPSC_INIT( uint32_t version ) +QByteArray CGPSProtocol :: SEND_GPSC_INIT( uint32_t version ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_INIT ); packet.push_back( 0 ); packet.push_back( 0 ); - UTIL_AppendByteArray( packet, version, false ); + UTIL_AppendQByteArray( packet, version, false ); AssignLength( packet ); return packet; } -BYTEARRAY CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reconnectKey, uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reconnectKey, uint32_t lastPacket ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_RECONNECT ); packet.push_back( 0 ); packet.push_back( 0 ); packet.push_back( PID ); - UTIL_AppendByteArray( packet, reconnectKey, false ); - UTIL_AppendByteArray( packet, lastPacket, false ); + UTIL_AppendQByteArray( packet, reconnectKey, false ); + UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; } -BYTEARRAY CGPSProtocol :: SEND_GPSC_ACK( uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSC_ACK( uint32_t lastPacket ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_ACK ); packet.push_back( 0 ); packet.push_back( 0 ); - UTIL_AppendByteArray( packet, lastPacket, false ); + UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; } -BYTEARRAY CGPSProtocol :: SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char PID, uint32_t reconnectKey, unsigned char numEmptyActions ) +QByteArray CGPSProtocol :: SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char PID, uint32_t reconnectKey, unsigned char numEmptyActions ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_INIT ); packet.push_back( 0 ); packet.push_back( 0 ); - UTIL_AppendByteArray( packet, reconnectPort, false ); + UTIL_AppendQByteArray( packet, reconnectPort, false ); packet.push_back( PID ); - UTIL_AppendByteArray( packet, reconnectKey, false ); + UTIL_AppendQByteArray( packet, reconnectKey, false ); packet.push_back( numEmptyActions ); AssignLength( packet ); return packet; } -BYTEARRAY CGPSProtocol :: SEND_GPSS_RECONNECT( uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( uint32_t lastPacket ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_RECONNECT ); packet.push_back( 0 ); packet.push_back( 0 ); - UTIL_AppendByteArray( packet, lastPacket, false ); + UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; } -BYTEARRAY CGPSProtocol :: SEND_GPSS_ACK( uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSS_ACK( uint32_t lastPacket ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_ACK ); packet.push_back( 0 ); packet.push_back( 0 ); - UTIL_AppendByteArray( packet, lastPacket, false ); + UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; } -BYTEARRAY CGPSProtocol :: SEND_GPSS_REJECT( uint32_t reason ) +QByteArray CGPSProtocol :: SEND_GPSS_REJECT( uint32_t reason ) { - BYTEARRAY packet; + QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_REJECT ); packet.push_back( 0 ); packet.push_back( 0 ); - UTIL_AppendByteArray( packet, reason, false ); + UTIL_AppendQByteArray( packet, reason, false ); AssignLength( packet ); return packet; } @@ -135,15 +135,15 @@ BYTEARRAY CGPSProtocol :: SEND_GPSS_REJECT( uint32_t reason ) // OTHER FUNCTIONS // ///////////////////// -bool CGPSProtocol :: AssignLength( BYTEARRAY &content ) +bool CGPSProtocol :: AssignLength( QByteArray &content ) { // insert the actual length of the content array into bytes 3 and 4 (indices 2 and 3) - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -152,18 +152,18 @@ bool CGPSProtocol :: AssignLength( BYTEARRAY &content ) return false; } -bool CGPSProtocol :: ValidateLength( BYTEARRAY &content ) +bool CGPSProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length uint16_t Length; - BYTEARRAY LengthBytes; + QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) { LengthBytes.push_back( content[2] ); LengthBytes.push_back( content[3] ); - Length = UTIL_ByteArrayToUInt16( LengthBytes, false ); + Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); if( Length == content.size( ) ) return true; diff --git a/ghost/gpsprotocol.h b/ghost/gpsprotocol.h index 2c38bea..9f46b38 100644 --- a/ghost/gpsprotocol.h +++ b/ghost/gpsprotocol.h @@ -45,20 +45,20 @@ class CGPSProtocol // send functions - BYTEARRAY SEND_GPSC_INIT( uint32_t version ); - BYTEARRAY SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reconnectKey, uint32_t lastPacket ); - BYTEARRAY SEND_GPSC_ACK( uint32_t lastPacket ); + QByteArray SEND_GPSC_INIT( uint32_t version ); + QByteArray SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reconnectKey, uint32_t lastPacket ); + QByteArray SEND_GPSC_ACK( uint32_t lastPacket ); - BYTEARRAY SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char PID, uint32_t reconnectKey, unsigned char numEmptyActions ); - BYTEARRAY SEND_GPSS_RECONNECT( uint32_t lastPacket ); - BYTEARRAY SEND_GPSS_ACK( uint32_t lastPacket ); - BYTEARRAY SEND_GPSS_REJECT( uint32_t reason ); + QByteArray SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char PID, uint32_t reconnectKey, unsigned char numEmptyActions ); + QByteArray SEND_GPSS_RECONNECT( uint32_t lastPacket ); + QByteArray SEND_GPSS_ACK( uint32_t lastPacket ); + QByteArray SEND_GPSS_REJECT( uint32_t reason ); // other functions private: - bool AssignLength( BYTEARRAY &content ); - bool ValidateLength( BYTEARRAY &content ); + bool AssignLength( QByteArray &content ); + bool ValidateLength( QByteArray &content ); }; #endif diff --git a/ghost/includes.h b/ghost/includes.h index cb17762..e90426a 100644 --- a/ghost/includes.h +++ b/ghost/includes.h @@ -36,17 +36,16 @@ #include #include #include -#include #include #include -#include -#include +#include +#include +#include #include using namespace std; -typedef vector BYTEARRAY; typedef pair PIDPlayer; // time @@ -69,6 +68,6 @@ uint32_t GetTicks( ); // milliseconds void CONSOLE_Print( QString message ); void DEBUG_Print( QString message ); -void DEBUG_Print( BYTEARRAY b ); +void DEBUG_Print( QByteArray b ); #endif diff --git a/ghost/main.cpp b/ghost/main.cpp index a957739..6f0903d 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -83,7 +83,7 @@ void DEBUG_Print( QString message ) cout << message << endl; } -void DEBUG_Print( BYTEARRAY b ) +void DEBUG_Print( QByteArray b ) { cout << "{ "; diff --git a/ghost/map.cpp b/ghost/map.cpp index 22308bb..6420ba5 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -84,7 +84,7 @@ CMap :: ~CMap( ) } -BYTEARRAY CMap :: GetMapGameFlags( ) +QByteArray CMap :: GetMapGameFlags( ) { /* @@ -155,7 +155,7 @@ BYTEARRAY CMap :: GetMapGameFlags( ) if( m_MapFlags & MAPFLAG_RANDOMRACES ) GameFlags |= 0x04000000; - return UTIL_CreateByteArray( GameFlags, false ); + return UTIL_CreateQByteArray( GameFlags, false ); } uint32_t CMap :: GetMapGameType( ) @@ -259,7 +259,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapLocalPath = CFG->GetString( "map_localpath", QString( ) ); m_MapData.clear( ); - if( !m_MapLocalPath.empty( ) ) + if( !m_MapLocalPath.isEmpty( ) ) m_MapData = UTIL_FileRead( m_GHost->m_MapPath + m_MapLocalPath ); // load the map MPQ @@ -278,37 +278,37 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // try to calculate map_size, map_info, map_crc, map_sha1 - BYTEARRAY MapSize; - BYTEARRAY MapInfo; - BYTEARRAY MapCRC; - BYTEARRAY MapSHA1; + QByteArray MapSize; + QByteArray MapInfo; + QByteArray MapCRC; + QByteArray MapSHA1; - if( !m_MapData.empty( ) ) + if( !m_MapData.isEmpty( ) ) { m_GHost->m_SHA->Reset( ); // calculate map_size - MapSize = UTIL_CreateByteArray( (uint32_t)m_MapData.size( ), false ); - CONSOLE_Print( "[MAP] calculated map_size = " + UTIL_ByteArrayToDecString( MapSize ) ); + MapSize = UTIL_CreateQByteArray( (uint32_t)m_MapData.size( ), false ); + CONSOLE_Print( "[MAP] calculated map_size = " + UTIL_QByteArrayToDecString( MapSize ) ); // calculate map_info (this is actually the CRC) - MapInfo = UTIL_CreateByteArray( (uint32_t)m_GHost->m_CRC->FullCRC( (unsigned char *)m_MapData.c_str( ), m_MapData.size( ) ), false ); - CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_ByteArrayToDecString( MapInfo ) ); + MapInfo = UTIL_CreateQByteArray( (uint32_t)m_GHost->m_CRC->FullCRC( (unsigned char *)m_MapData.c_str( ), m_MapData.size( ) ), false ); + CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_QByteArrayToDecString( MapInfo ) ); // calculate map_crc (this is not the CRC) and map_sha1 // a big thank you to Strilanc for figuring the map_crc algorithm out QString CommonJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "common.j" ); - if( CommonJ.empty( ) ) + if( CommonJ.isEmpty( ) ) CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "common.j]" ); else { QString BlizzardJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "blizzard.j" ); - if( BlizzardJ.empty( ) ) + if( BlizzardJ.isEmpty( ) ) CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "blizzard.j]" ); else { @@ -398,7 +398,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( MapMPQReady ) { - vector FileList; + QVector FileList; FileList.push_back( "war3map.j" ); FileList.push_back( "scripts\\war3map.j" ); FileList.push_back( "war3map.w3e" ); @@ -411,7 +411,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) FileList.push_back( "war3map.w3q" ); bool FoundScript = false; - for( vector :: iterator i = FileList.begin( ); i != FileList.end( ); i++ ) + for( QVector :: iterator i = FileList.begin( ); i != FileList.end( ); i++ ) { // don't use scripts\war3map.j if we've already used war3map.j (yes, some maps have both but only war3map.j is used) @@ -453,15 +453,15 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( !FoundScript ) CONSOLE_Print( "[MAP] couldn't find war3map.j or scripts\\war3map.j in MPQ file, calculated map_crc/sha1 is probably wrong" ); - MapCRC = UTIL_CreateByteArray( Val, false ); - CONSOLE_Print( "[MAP] calculated map_crc = " + UTIL_ByteArrayToDecString( MapCRC ) ); + MapCRC = UTIL_CreateQByteArray( Val, false ); + CONSOLE_Print( "[MAP] calculated map_crc = " + UTIL_QByteArrayToDecString( MapCRC ) ); m_GHost->m_SHA->Final( ); unsigned char SHA1[20]; memset( SHA1, 0, sizeof( unsigned char ) * 20 ); m_GHost->m_SHA->GetHash( SHA1 ); - MapSHA1 = UTIL_CreateByteArray( SHA1, 20 ); - CONSOLE_Print( "[MAP] calculated map_sha1 = " + UTIL_ByteArrayToDecString( MapSHA1 ) ); + MapSHA1 = UTIL_CreateQByteArray( SHA1, 20 ); + CONSOLE_Print( "[MAP] calculated map_sha1 = " + UTIL_QByteArrayToDecString( MapSHA1 ) ); } else CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - map MPQ file not loaded" ); @@ -474,13 +474,13 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // try to calculate map_width, map_height, map_slot, map_numplayers, map_numteams uint32_t MapOptions = 0; - BYTEARRAY MapWidth; - BYTEARRAY MapHeight; + QByteArray MapWidth; + QByteArray MapHeight; uint32_t MapNumPlayers = 0; uint32_t MapNumTeams = 0; - vector Slots; + QVector Slots; - if( !m_MapData.empty( ) ) + if( !m_MapData.isEmpty( ) ) { if( MapMPQReady ) { @@ -635,7 +635,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { if( PlayerMask & 1 ) { - for( vector :: iterator k = Slots.begin( ); k != Slots.end( ); k++ ) + for( QVector :: iterator k = Slots.begin( ); k != Slots.end( ); k++ ) { if( (*k).GetColour( ) == j ) (*k).SetTeam( i ); @@ -653,10 +653,10 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) MapOptions = RawMapFlags & ( MAPOPT_MELEE | MAPOPT_FIXEDPLAYERSETTINGS | MAPOPT_CUSTOMFORCES ); CONSOLE_Print( "[MAP] calculated map_options = " + UTIL_ToString( MapOptions ) ); - MapWidth = UTIL_CreateByteArray( (uint16_t)RawMapWidth, false ); - CONSOLE_Print( "[MAP] calculated map_width = " + UTIL_ByteArrayToDecString( MapWidth ) ); - MapHeight = UTIL_CreateByteArray( (uint16_t)RawMapHeight, false ); - CONSOLE_Print( "[MAP] calculated map_height = " + UTIL_ByteArrayToDecString( MapHeight ) ); + MapWidth = UTIL_CreateQByteArray( (uint16_t)RawMapWidth, false ); + CONSOLE_Print( "[MAP] calculated map_width = " + UTIL_QByteArrayToDecString( MapWidth ) ); + MapHeight = UTIL_CreateQByteArray( (uint16_t)RawMapHeight, false ); + CONSOLE_Print( "[MAP] calculated map_height = " + UTIL_QByteArrayToDecString( MapHeight ) ); MapNumPlayers = RawMapNumPlayers - ClosedSlots; CONSOLE_Print( "[MAP] calculated map_numplayers = " + UTIL_ToString( MapNumPlayers ) ); MapNumTeams = RawMapNumTeams; @@ -664,9 +664,9 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) uint32_t SlotNum = 1; - for( vector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) + for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) { - CONSOLE_Print( "[MAP] calculated map_slot" + UTIL_ToString( SlotNum ) + " = " + UTIL_ByteArrayToDecString( (*i).GetByteArray( ) ) ); + CONSOLE_Print( "[MAP] calculated map_slot" + UTIL_ToString( SlotNum ) + " = " + UTIL_QByteArrayToDecString( (*i).GetQByteArray( ) ) ); SlotNum++; } @@ -678,7 +678,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) unsigned char Team = 0; - for( vector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) + for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) { (*i).SetTeam( Team++ ); (*i).SetRace( SLOTRACE_RANDOM ); @@ -689,7 +689,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { // make races selectable - for( vector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) + for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) (*i).SetRace( (*i).GetRace( ) | SLOTRACE_SELECTABLE ); } } @@ -718,7 +718,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapPath = CFG->GetString( "map_path", QString( ) ); - if( MapSize.empty( ) ) + if( MapSize.isEmpty( ) ) MapSize = UTIL_ExtractNumbers( CFG->GetString( "map_size", QString( ) ), 4 ); else if( CFG->Exists( "map_size" ) ) { @@ -728,7 +728,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapSize = MapSize; - if( MapInfo.empty( ) ) + if( MapInfo.isEmpty( ) ) MapInfo = UTIL_ExtractNumbers( CFG->GetString( "map_info", QString( ) ), 4 ); else if( CFG->Exists( "map_info" ) ) { @@ -738,7 +738,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapInfo = MapInfo; - if( MapCRC.empty( ) ) + if( MapCRC.isEmpty( ) ) MapCRC = UTIL_ExtractNumbers( CFG->GetString( "map_crc", QString( ) ), 4 ); else if( CFG->Exists( "map_crc" ) ) { @@ -748,7 +748,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapCRC = MapCRC; - if( MapSHA1.empty( ) ) + if( MapSHA1.isEmpty( ) ) MapSHA1 = UTIL_ExtractNumbers( CFG->GetString( "map_sha1", QString( ) ), 20 ); else if( CFG->Exists( "map_sha1" ) ) { @@ -778,7 +778,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapOptions = MapOptions; - if( MapWidth.empty( ) ) + if( MapWidth.isEmpty( ) ) MapWidth = UTIL_ExtractNumbers( CFG->GetString( "map_width", QString( ) ), 2 ); else if( CFG->Exists( "map_width" ) ) { @@ -788,7 +788,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapWidth = MapWidth; - if( MapHeight.empty( ) ) + if( MapHeight.isEmpty( ) ) MapHeight = UTIL_ExtractNumbers( CFG->GetString( "map_height", QString( ) ), 2 ); else if( CFG->Exists( "map_height" ) ) { @@ -824,16 +824,16 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapNumTeams = MapNumTeams; - if( Slots.empty( ) ) + if( Slots.isEmpty( ) ) { for( uint32_t Slot = 1; Slot <= 12; Slot++ ) { QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); - if( SlotString.empty( ) ) + if( SlotString.isEmpty( ) ) break; - BYTEARRAY SlotData = UTIL_ExtractNumbers( SlotString, 9 ); + QByteArray SlotData = UTIL_ExtractNumbers( SlotString, 9 ); Slots.push_back( CGameSlot( SlotData ) ); } } @@ -846,10 +846,10 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); - if( SlotString.empty( ) ) + if( SlotString.isEmpty( ) ) break; - BYTEARRAY SlotData = UTIL_ExtractNumbers( SlotString, 9 ); + QByteArray SlotData = UTIL_ExtractNumbers( SlotString, 9 ); Slots.push_back( CGameSlot( SlotData ) ); } } @@ -862,7 +862,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { CONSOLE_Print( "[MAP] forcing races to random" ); - for( vector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) (*i).SetRace( SLOTRACE_RANDOM ); } @@ -883,7 +883,7 @@ void CMap :: CheckValid( ) { // todotodo: should this code fix any errors it sees rather than just warning the user? - if( m_MapPath.empty( ) ) + if( m_MapPath.isEmpty( ) ) { m_Valid = false; CONSOLE_Print( "[MAP] invalid map_path detected" ); @@ -899,7 +899,7 @@ void CMap :: CheckValid( ) m_Valid = false; CONSOLE_Print( "[MAP] invalid map_size detected" ); } - else if( !m_MapData.empty( ) && m_MapData.size( ) != UTIL_ByteArrayToUInt32( m_MapSize, false ) ) + else if( !m_MapData.isEmpty( ) && m_MapData.size( ) != UTIL_QByteArrayToUInt32( m_MapSize, false ) ) { m_Valid = false; CONSOLE_Print( "[MAP] invalid map_size detected - size mismatch with actual map data" ); @@ -968,7 +968,7 @@ void CMap :: CheckValid( ) CONSOLE_Print( "[MAP] invalid map_numteams detected" ); } - if( m_Slots.empty( ) || m_Slots.size( ) > 12 ) + if( m_Slots.isEmpty( ) || m_Slots.size( ) > 12 ) { m_Valid = false; CONSOLE_Print( "[MAP] invalid map_slot detected" ); diff --git a/ghost/map.h b/ghost/map.h index 48acc3f..ac3a7d2 100644 --- a/ghost/map.h +++ b/ghost/map.h @@ -98,10 +98,10 @@ class CMap bool m_Valid; string m_CFGFile; string m_MapPath; // config value: map path - BYTEARRAY m_MapSize; // config value: map size (4 bytes) - BYTEARRAY m_MapInfo; // config value: map info (4 bytes) -> this is the real CRC - BYTEARRAY m_MapCRC; // config value: map crc (4 bytes) -> this is not the real CRC, it's the "xoro" value - BYTEARRAY m_MapSHA1; // config value: map sha1 (20 bytes) + QByteArray m_MapSize; // config value: map size (4 bytes) + QByteArray m_MapInfo; // config value: map info (4 bytes) -> this is the real CRC + QByteArray m_MapCRC; // config value: map crc (4 bytes) -> this is not the real CRC, it's the "xoro" value + QByteArray m_MapSHA1; // config value: map sha1 (20 bytes) unsigned char m_MapSpeed; unsigned char m_MapVisibility; unsigned char m_MapObservers; @@ -111,8 +111,8 @@ class CMap unsigned char m_MapFilterSize; unsigned char m_MapFilterObs; uint32_t m_MapOptions; - BYTEARRAY m_MapWidth; // config value: map width (2 bytes) - BYTEARRAY m_MapHeight; // config value: map height (2 bytes) + QByteArray m_MapWidth; // config value: map width (2 bytes) + QByteArray m_MapHeight; // config value: map height (2 bytes) string m_MapType; // config value: map type (for stats class) string m_MapMatchMakingCategory; // config value: map matchmaking category (for matchmaking) string m_MapStatsW3MMDCategory; // config value: map stats w3mmd category (for saving w3mmd stats) @@ -123,7 +123,7 @@ class CMap string m_MapData; // the map data itself, for sending the map to players uint32_t m_MapNumPlayers; uint32_t m_MapNumTeams; - vector m_Slots; + QVector m_Slots; public: CMap( CGHost *nGHost ); @@ -133,20 +133,20 @@ class CMap bool GetValid( ) { return m_Valid; } string GetCFGFile( ) { return m_CFGFile; } string GetMapPath( ) { return m_MapPath; } - BYTEARRAY GetMapSize( ) { return m_MapSize; } - BYTEARRAY GetMapInfo( ) { return m_MapInfo; } - BYTEARRAY GetMapCRC( ) { return m_MapCRC; } - BYTEARRAY GetMapSHA1( ) { return m_MapSHA1; } + QByteArray GetMapSize( ) { return m_MapSize; } + QByteArray GetMapInfo( ) { return m_MapInfo; } + QByteArray GetMapCRC( ) { return m_MapCRC; } + QByteArray GetMapSHA1( ) { return m_MapSHA1; } unsigned char GetMapSpeed( ) { return m_MapSpeed; } unsigned char GetMapVisibility( ) { return m_MapVisibility; } unsigned char GetMapObservers( ) { return m_MapObservers; } unsigned char GetMapFlags( ) { return m_MapFlags; } - BYTEARRAY GetMapGameFlags( ); + QByteArray GetMapGameFlags( ); uint32_t GetMapGameType( ); uint32_t GetMapOptions( ) { return m_MapOptions; } unsigned char GetMapLayoutStyle( ); - BYTEARRAY GetMapWidth( ) { return m_MapWidth; } - BYTEARRAY GetMapHeight( ) { return m_MapHeight; } + QByteArray GetMapWidth( ) { return m_MapWidth; } + QByteArray GetMapHeight( ) { return m_MapHeight; } string GetMapType( ) { return m_MapType; } string GetMapMatchMakingCategory( ) { return m_MapMatchMakingCategory; } string GetMapStatsW3MMDCategory( ) { return m_MapStatsW3MMDCategory; } @@ -157,7 +157,7 @@ class CMap string *GetMapData( ) { return &m_MapData; } uint32_t GetMapNumPlayers( ) { return m_MapNumPlayers; } uint32_t GetMapNumTeams( ) { return m_MapNumTeams; } - vector GetSlots( ) { return m_Slots; } + QVector GetSlots( ) { return m_Slots; } void Load( CConfig *CFG, string nCFGFile ); void CheckValid( ); diff --git a/ghost/packed.cpp b/ghost/packed.cpp index 62537ea..35d1908 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -295,7 +295,7 @@ void CPacked :: Compress( bool TFT ) uint32_t CompressedSize = 0; QString Padded = m_Decompressed; Padded.append( 8192 - ( Padded.size( ) % 8192 ), 0 ); - vector CompressedBlocks; + QVector CompressedBlocks; QString :: size_type Position = 0; unsigned char *CompressedData = new unsigned char[8213]; @@ -324,13 +324,13 @@ void CPacked :: Compress( bool TFT ) uint32_t HeaderSize = 68; uint32_t HeaderCompressedSize = HeaderSize + CompressedSize + CompressedBlocks.size( ) * 8; uint32_t HeaderVersion = 1; - BYTEARRAY Header; - UTIL_AppendByteArray( Header, "Warcraft III recorded game\x01A" ); - UTIL_AppendByteArray( Header, HeaderSize, false ); - UTIL_AppendByteArray( Header, HeaderCompressedSize, false ); - UTIL_AppendByteArray( Header, HeaderVersion, false ); - UTIL_AppendByteArray( Header, (uint32_t)m_Decompressed.size( ), false ); - UTIL_AppendByteArray( Header, (uint32_t)CompressedBlocks.size( ), false ); + QByteArray Header; + UTIL_AppendQByteArray( Header, "Warcraft III recorded game\x01A" ); + UTIL_AppendQByteArray( Header, HeaderSize, false ); + UTIL_AppendQByteArray( Header, HeaderCompressedSize, false ); + UTIL_AppendQByteArray( Header, HeaderVersion, false ); + UTIL_AppendQByteArray( Header, (uint32_t)m_Decompressed.size( ), false ); + UTIL_AppendQByteArray( Header, (uint32_t)CompressedBlocks.size( ), false ); if( TFT ) { @@ -347,16 +347,16 @@ void CPacked :: Compress( bool TFT ) Header.push_back( 'W' ); } - UTIL_AppendByteArray( Header, m_War3Version, false ); - UTIL_AppendByteArray( Header, m_BuildNumber, false ); - UTIL_AppendByteArray( Header, m_Flags, false ); - UTIL_AppendByteArray( Header, m_ReplayLength, false ); + UTIL_AppendQByteArray( Header, m_War3Version, false ); + UTIL_AppendQByteArray( Header, m_BuildNumber, false ); + UTIL_AppendQByteArray( Header, m_Flags, false ); + UTIL_AppendQByteArray( Header, m_ReplayLength, false ); // append zero header CRC // the header CRC is calculated over the entire header with itself set to zero // we'll overwrite the zero header CRC after we calculate it - UTIL_AppendByteArray( Header, (uint32_t)0, false ); + UTIL_AppendQByteArray( Header, (uint32_t)0, false ); // calculate header CRC @@ -366,7 +366,7 @@ void CPacked :: Compress( bool TFT ) // overwrite the (currently zero) header CRC with the calculated CRC Header.erase( Header.end( ) - 4, Header.end( ) ); - UTIL_AppendByteArray( Header, CRC, false ); + UTIL_AppendQByteArray( Header, CRC, false ); // append header @@ -374,15 +374,15 @@ void CPacked :: Compress( bool TFT ) // append blocks - for( vector :: iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) + for( QVector :: iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { - BYTEARRAY BlockHeader; - UTIL_AppendByteArray( BlockHeader, (uint16_t)(*i).size( ), false ); - UTIL_AppendByteArray( BlockHeader, (uint16_t)8192, false ); + QByteArray BlockHeader; + UTIL_AppendQByteArray( BlockHeader, (uint16_t)(*i).size( ), false ); + UTIL_AppendQByteArray( BlockHeader, (uint16_t)8192, false ); // append zero block header CRC - UTIL_AppendByteArray( BlockHeader, (uint32_t)0, false ); + UTIL_AppendQByteArray( BlockHeader, (uint32_t)0, false ); // calculate block header CRC @@ -396,7 +396,7 @@ void CPacked :: Compress( bool TFT ) // overwrite the block header CRC with the calculated CRC BlockHeader.erase( BlockHeader.end( ) - 4, BlockHeader.end( ) ); - UTIL_AppendByteArray( BlockHeader, BlockCRC, false ); + UTIL_AppendQByteArray( BlockHeader, BlockCRC, false ); // append block header and data diff --git a/ghost/replay.cpp b/ghost/replay.cpp index 9772091..db9303e 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -63,20 +63,20 @@ void CReplay :: AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, u Block.push_back( PID ); UTIL_AppendQByteArray( Block, result, false ); UTIL_AppendQByteArray( Block, (uint32_t)1, false ); - m_LoadingBlocks.push( Block ); + m_LoadingBlocks.enqueue( Block ); } -void CReplay :: AddTimeSlot2( queue actions ) +void CReplay :: AddTimeSlot2( QQueue actions ) { QByteArray Block; Block.push_back( REPLAY_TIMESLOT2 ); UTIL_AppendQByteArray( Block, (uint16_t)0, false ); UTIL_AppendQByteArray( Block, (uint16_t)0, false ); - while( !actions.empty( ) ) + while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); - actions.pop( ); + actions.dequeue( ); Block.push_back( Action->GetPID( ) ); UTIL_AppendQByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); UTIL_AppendQByteArrayFast( Block, *Action->GetAction( ) ); @@ -90,17 +90,17 @@ void CReplay :: AddTimeSlot2( queue actions ) m_CompiledBlocks += Block; } -void CReplay :: AddTimeSlot( uint16_t timeIncrement, queue actions ) +void CReplay :: AddTimeSlot( uint16_t timeIncrement, QQueue actions ) { QByteArray Block; Block.push_back( REPLAY_TIMESLOT ); UTIL_AppendQByteArray( Block, (uint16_t)0, false ); UTIL_AppendQByteArray( Block, timeIncrement, false ); - while( !actions.empty( ) ) + while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); - actions.pop( ); + actions.dequeue( ); Block.push_back( Action->GetPID( ) ); UTIL_AppendQByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); UTIL_AppendQByteArrayFast( Block, *Action->GetAction( ) ); @@ -135,7 +135,7 @@ void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, uint32_t void CReplay :: AddLoadingBlock( QByteArray &loadingBlock ) { - m_LoadingBlocks.push( loadingBlock ); + m_LoadingBlocks.enqueue( loadingBlock ); } void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3Version, uint16_t buildNumber ) @@ -149,17 +149,17 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 uint32_t LanguageID = 0x0012F8B0; QByteArray Replay; - Replay.push_back( 16 ); // Unknown (4.0) - Replay.push_back( 1 ); // Unknown (4.0) - Replay.push_back( 0 ); // Unknown (4.0) - Replay.push_back( 0 ); // Unknown (4.0) - Replay.push_back( 0 ); // Host RecordID (4.1) - Replay.push_back( m_HostPID ); // Host PlayerID (4.1) + Replay.push_back( (char)16 ); // Unknown (4.0) + Replay.push_back( (char)1 ); // Unknown (4.0) + Replay.push_back( (char)0 ); // Unknown (4.0) + Replay.push_back( (char)0 ); // Unknown (4.0) + Replay.push_back( (char)0 ); // Host RecordID (4.1) + Replay.push_back( (char)m_HostPID ); // Host PlayerID (4.1) UTIL_AppendQByteArrayFast( Replay, m_HostName ); // Host PlayerName (4.1) - Replay.push_back( 1 ); // Host AdditionalSize (4.1) - Replay.push_back( 0 ); // Host AdditionalData (4.1) + Replay.push_back( (char)1 ); // Host AdditionalSize (4.1) + Replay.push_back( (char)0 ); // Host AdditionalData (4.1) UTIL_AppendQByteArrayFast( Replay, gameName ); // GameName (4.2) - Replay.push_back( 0 ); // Null (4.0) + Replay.push_back( (char)0 ); // Null (4.0) UTIL_AppendQByteArrayFast( Replay, statString ); // StatString (4.3) UTIL_AppendQByteArray( Replay, (uint32_t)m_Slots.size( ), false ); // PlayerCount (4.6) UTIL_AppendQByteArray( Replay, m_MapGameType, false ); // GameType (4.7) @@ -167,7 +167,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 // PlayerList (4.9) - for( vector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i).first != m_HostPID ) { @@ -175,7 +175,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 Replay.push_back( (*i).first ); // Player PlayerID (4.1) UTIL_AppendQByteArrayFast( Replay, (*i).second ); // Player PlayerName (4.1) Replay.push_back( 1 ); // Player AdditionalSize (4.1) - Replay.push_back( 0 ); // Player AdditionalData (4.1) + Replay.push_back( (char)0 ); // Player AdditionalData (4.1) UTIL_AppendQByteArray( Replay, (uint32_t)0, false ); // Unknown } } @@ -202,10 +202,10 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 // leavers during loading need to be stored between the second and third start blocks - while( !m_LoadingBlocks.empty( ) ) + while( !m_LoadingBlocks.isEmpty( ) ) { UTIL_AppendQByteArray( Replay, m_LoadingBlocks.front( ) ); - m_LoadingBlocks.pop( ); + m_LoadingBlocks.dequeue( ); } Replay.push_back( REPLAY_THIRDSTARTBLOCK ); @@ -213,7 +213,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 // done - m_Decompressed = QString( Replay.begin( ), Replay.end( ) ); + m_Decompressed = Replay; m_Decompressed += m_CompiledBlocks; } @@ -233,9 +233,9 @@ void CReplay :: ParseReplay( bool parseBlocks ) m_RandomSeed = 0; m_SelectMode = 0; m_StartSpotCount = 0; - m_LoadingBlocks = queue( ); - m_Blocks = queue( ); - m_CheckSums = queue( ); + m_LoadingBlocks = QQueue( ); + m_Blocks = QQueue( ); + m_CheckSums = QQueue( ); if( m_Flags != 32768 ) { @@ -463,7 +463,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) QByteArray LoadingBlock; LoadingBlock.push_back( Garbage1 ); UTIL_AppendQByteArray( LoadingBlock, GarbageData, 13 ); - m_LoadingBlocks.push( LoadingBlock ); + m_LoadingBlocks.enqueue( LoadingBlock ); } else if( Garbage1 == CReplay :: REPLAY_THIRDSTARTBLOCK ) break; @@ -508,7 +508,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) QByteArray Block; Block.push_back( CReplay :: REPLAY_LEAVEGAME ); UTIL_AppendQByteArray( Block, GarbageData, 13 ); - m_Blocks.push( Block ); + m_Blocks.enqueue( Block ); } else if( Garbage1 == CReplay :: REPLAY_TIMESLOT ) { @@ -525,7 +525,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) Block.push_back( CReplay :: REPLAY_TIMESLOT ); UTIL_AppendQByteArray( Block, BlockSize, false ); UTIL_AppendQByteArray( Block, GarbageData, BlockSize ); - m_Blocks.push( Block ); + m_Blocks.enqueue( Block ); } else if( Garbage1 == CReplay :: REPLAY_CHATMESSAGE ) { @@ -550,7 +550,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) Block.push_back( PID ); UTIL_AppendQByteArray( Block, BlockSize, false ); UTIL_AppendQByteArray( Block, GarbageData, BlockSize ); - m_Blocks.push( Block ); + m_Blocks.enqueue( Block ); } else if( Garbage1 == CReplay :: REPLAY_CHECKSUM ) { @@ -565,7 +565,7 @@ void CReplay :: ParseReplay( bool parseBlocks ) uint32_t CheckSum; READB( ISS, &CheckSum, 4 ); - m_CheckSums.push( CheckSum ); + m_CheckSums.enqueue( CheckSum ); } else { diff --git a/ghost/replay.h b/ghost/replay.h index 441b099..ed419c6 100644 --- a/ghost/replay.h +++ b/ghost/replay.h @@ -52,14 +52,14 @@ class CReplay : public CPacked QString m_StatString; uint32_t m_PlayerCount; uint32_t m_MapGameType; - vector m_Players; - vector m_Slots; + QVector m_Players; + QVector m_Slots; uint32_t m_RandomSeed; unsigned char m_SelectMode; // also known as the "layout style" elsewhere in this project unsigned char m_StartSpotCount; - queue m_LoadingBlocks; - queue m_Blocks; - queue m_CheckSums; + QQueue m_LoadingBlocks; + QQueue m_Blocks; + QQueue m_CheckSums; QString m_CompiledBlocks; public: @@ -72,17 +72,17 @@ class CReplay : public CPacked QString GetStatString( ) { return m_StatString; } uint32_t GetPlayerCount( ) { return m_PlayerCount; } uint32_t GetMapGameType( ) { return m_MapGameType; } - vector GetPlayers( ) { return m_Players; } - vector GetSlots( ) { return m_Slots; } + QVector GetPlayers( ) { return m_Players; } + QVector GetSlots( ) { return m_Slots; } uint32_t GetRandomSeed( ) { return m_RandomSeed; } unsigned char GetSelectMode( ) { return m_SelectMode; } unsigned char GetStartSpotCount( ) { return m_StartSpotCount; } - queue *GetLoadingBlocks( ) { return &m_LoadingBlocks; } - queue *GetBlocks( ) { return &m_Blocks; } - queue *GetCheckSums( ) { return &m_CheckSums; } + QQueue *GetLoadingBlocks( ) { return &m_LoadingBlocks; } + QQueue *GetBlocks( ) { return &m_Blocks; } + QQueue *GetCheckSums( ) { return &m_CheckSums; } void AddPlayer( unsigned char nPID, QString nName ) { m_Players.push_back( PIDPlayer( nPID, nName ) ); } - void SetSlots( vector nSlots ) { m_Slots = nSlots; } + void SetSlots( QVector nSlots ) { m_Slots = nSlots; } void SetRandomSeed( uint32_t nRandomSeed ) { m_RandomSeed = nRandomSeed; } void SetSelectMode( unsigned char nSelectMode ) { m_SelectMode = nSelectMode; } void SetStartSpotCount( unsigned char nStartSpotCount ) { m_StartSpotCount = nStartSpotCount; } @@ -92,8 +92,8 @@ class CReplay : public CPacked void AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t result ); void AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, uint32_t result ); - void AddTimeSlot2( queue actions ); - void AddTimeSlot( uint16_t timeIncrement, queue actions ); + void AddTimeSlot2( QQueue actions ); + void AddTimeSlot( uint16_t timeIncrement, QQueue actions ); void AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, QString message ); void AddLoadingBlock( QByteArray &loadingBlock ); void BuildReplay( QString gameName, QString statString, uint32_t war3Version, uint16_t buildNumber ); diff --git a/ghost/savegame.h b/ghost/savegame.h index ffe8a64..a9520c5 100644 --- a/ghost/savegame.h +++ b/ghost/savegame.h @@ -35,9 +35,9 @@ class CSaveGame : public CPacked QString m_MapPath; QString m_GameName; unsigned char m_NumSlots; - vector m_Slots; + QVector m_Slots; uint32_t m_RandomSeed; - BYTEARRAY m_MagicNumber; + QByteArray m_MagicNumber; public: CSaveGame( ); @@ -48,9 +48,9 @@ class CSaveGame : public CPacked QString GetMapPath( ) { return m_MapPath; } QString GetGameName( ) { return m_GameName; } unsigned char GetNumSlots( ) { return m_NumSlots; } - vector GetSlots( ) { return m_Slots; } + QVector GetSlots( ) { return m_Slots; } uint32_t GetRandomSeed( ) { return m_RandomSeed; } - BYTEARRAY GetMagicNumber( ) { return m_MagicNumber; } + QByteArray GetMagicNumber( ) { return m_MagicNumber; } void SetFileName( QString nFileName ) { m_FileName = nFileName; } void SetFileNameNoPath( QString nFileNameNoPath ) { m_FileNameNoPath = nFileNameNoPath; } diff --git a/ghost/socket.cpp b/ghost/socket.cpp index 79b2716..f859005 100644 --- a/ghost/socket.cpp +++ b/ghost/socket.cpp @@ -260,7 +260,7 @@ void CTCPSocket :: DoRecv( fd_set *fd ) { // success! add the received data to the buffer - if( !m_LogFile.empty( ) ) + if( !m_LogFile.isEmpty( ) ) { ofstream Log; Log.open( m_LogFile.c_str( ), ios :: app ); @@ -280,7 +280,7 @@ void CTCPSocket :: DoRecv( fd_set *fd ) void CTCPSocket :: DoSend( fd_set *send_fd ) { - if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected || m_SendBuffer.empty( ) ) + if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected || m_SendBuffer.isEmpty( ) ) return; if( FD_ISSET( m_Socket, send_fd ) ) @@ -302,7 +302,7 @@ void CTCPSocket :: DoSend( fd_set *send_fd ) { // success! only some of the data may have been sent, remove it from the buffer - if( !m_LogFile.empty( ) ) + if( !m_LogFile.isEmpty( ) ) { ofstream Log; Log.open( m_LogFile.c_str( ), ios :: app ); @@ -314,7 +314,7 @@ void CTCPSocket :: DoSend( fd_set *send_fd ) } } - m_SendBuffer = m_SendBuffer.substr( s ); + m_SendBuffer = m_SendBuffer.mid( s ); m_LastSend = GetTime( ); } } @@ -369,7 +369,7 @@ void CTCPClient :: Connect( QString localaddress, QString address, uint16_t port if( m_Socket == INVALID_SOCKET || m_HasError || m_Connecting || m_Connected ) return; - if( !localaddress.empty( ) ) + if( !localaddress.isEmpty( ) ) { struct sockaddr_in LocalSIN; memset( &LocalSIN, 0, sizeof( LocalSIN ) ); @@ -492,7 +492,7 @@ bool CTCPServer :: Listen( QString address, uint16_t port ) m_SIN.sin_family = AF_INET; - if( !address.empty( ) ) + if( !address.isEmpty( ) ) { if( ( m_SIN.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE ) m_SIN.sin_addr.s_addr = INADDR_ANY; @@ -641,7 +641,7 @@ bool CUDPSocket :: Broadcast( uint16_t port, QByteArray message ) void CUDPSocket :: SetBroadcastTarget( QString subnet ) { - if( subnet.empty( ) ) + if( subnet.isEmpty( ) ) { CONSOLE_Print( "[UDPSOCKET] using default broadcast target" ); m_BroadcastTarget.s_addr = INADDR_BROADCAST; @@ -735,7 +735,7 @@ bool CUDPServer :: Bind( QString address, uint16_t port ) struct sockaddr_in sin; sin.sin_family = AF_INET; - if( !address.empty( ) ) + if( !address.isEmpty( ) ) { if( ( sin.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE ) sin.sin_addr.s_addr = INADDR_ANY; diff --git a/ghost/statsw3mmd.cpp b/ghost/statsw3mmd.cpp index 93a7d23..0ecf0bb 100644 --- a/ghost/statsw3mmd.cpp +++ b/ghost/statsw3mmd.cpp @@ -87,9 +87,9 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { QString ValueIDString = MissionKeyString.mid( 4 ); uint32_t ValueID = UTIL_ToUInt32( ValueIDString ); - vector Tokens = TokenizeKey( KeyString ); + QVector Tokens = TokenizeKey( KeyString ); - if( !Tokens.empty( ) ) + if( !Tokens.isEmpty( ) ) { if( Tokens[0] == "init" && Tokens.size( ) >= 2 ) { @@ -254,7 +254,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) uint32_t Arguments = UTIL_ToUInt32( Tokens[2] ); if( Tokens.size( ) == Arguments + 4 ) - m_DefEvents[Tokens[1]] = vector( Tokens.begin( ) + 3, Tokens.end( ) ); + m_DefEvents[Tokens[1]] = Tokens.mid(3); } } else if( Tokens[0] == "Event" && Tokens.size( ) >= 2 ) @@ -266,9 +266,9 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + KeyString + "] found without a corresponding DefEvent, ignoring" ); else { - vector DefEvent = m_DefEvents[Tokens[1]]; + QVector DefEvent = m_DefEvents[Tokens[1]]; - if( !DefEvent.empty( ) ) + if( !DefEvent.isEmpty( ) ) { QString Format = DefEvent[DefEvent.size( ) - 1]; @@ -357,13 +357,13 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) // todotodo: there's no reason to create a new callable for each entry in this map // rewrite ThreadedW3MMDPlayerAdd to act more like ThreadedW3MMDVarAdd - for( map :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) + for( QMap :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) { - QString Flags = m_Flags[i->first]; + QString Flags = m_Flags[i.key()]; uint32_t Leaver = 0; uint32_t Practicing = 0; - if( m_FlagsLeaver.find( i->first ) != m_FlagsLeaver.end( ) && m_FlagsLeaver[i->first] ) + if( m_FlagsLeaver.find( i.key() ) != m_FlagsLeaver.end( ) && m_FlagsLeaver[i.key()] ) { Leaver = 1; @@ -373,7 +373,7 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) Flags += "leaver"; } - if( m_FlagsPracticing.find( i->first ) != m_FlagsPracticing.end( ) && m_FlagsPracticing[i->first] ) + if( m_FlagsPracticing.find( i.key() ) != m_FlagsPracticing.end( ) && m_FlagsPracticing[i.key()] ) { Practicing = 1; @@ -383,17 +383,17 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) Flags += "practicing"; } - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] recorded flags [" + Flags + "] for player [" + i->second + "] with PID [" + UTIL_ToString( i->first ) + "]" ); - GHost->m_Callables.push_back( DB->ThreadedW3MMDPlayerAdd( m_Category, GameID, i->first, i->second, m_Flags[i->first], Leaver, Practicing ) ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] recorded flags [" + Flags + "] for player [" + i.value() + "] with PID [" + UTIL_ToString( i.key() ) + "]" ); + GHost->m_Callables.push_back( DB->ThreadedW3MMDPlayerAdd( m_Category, GameID, i.key(), i.value(), m_Flags[i.key()], Leaver, Practicing ) ); } - if( !m_VarPInts.empty( ) ) + if( !m_VarPInts.isEmpty( ) ) GHost->m_Callables.push_back( DB->ThreadedW3MMDVarAdd( GameID, m_VarPInts ) ); - if( !m_VarPReals.empty( ) ) + if( !m_VarPReals.isEmpty( ) ) GHost->m_Callables.push_back( DB->ThreadedW3MMDVarAdd( GameID, m_VarPReals ) ); - if( !m_VarPStrings.empty( ) ) + if( !m_VarPStrings.isEmpty( ) ) GHost->m_Callables.push_back( DB->ThreadedW3MMDVarAdd( GameID, m_VarPStrings ) ); if( DB->Commit( ) ) @@ -405,9 +405,9 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unable to begin database transaction, data not saved" ); } -vector CStatsW3MMD :: TokenizeKey( QString key ) +QVector CStatsW3MMD :: TokenizeKey( QString key ) { - vector Tokens; + QVector Tokens; QString Token; bool Escaping = false; @@ -422,7 +422,7 @@ vector CStatsW3MMD :: TokenizeKey( QString key ) else { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], invalid escape sequence found, ignoring" ); - return vector( ); + return QVector( ); } Escaping = false; @@ -434,7 +434,7 @@ vector CStatsW3MMD :: TokenizeKey( QString key ) if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return vector( ); + return QVector( ); } Tokens.push_back( Token ); @@ -450,7 +450,7 @@ vector CStatsW3MMD :: TokenizeKey( QString key ) if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return vector( ); + return QVector( ); } Tokens.push_back( Token ); diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index 41c7224..e3d48a2 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -33,15 +33,15 @@ class CStatsW3MMD : public CStats QString m_Category; uint32_t m_NextValueID; uint32_t m_NextCheckID; - map m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case - map m_Flags; // pid -> flag (e.g. 0 -> "winner") - map m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true - map m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true - map m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") - map m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) - map m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) - map m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") - map > m_DefEvents; // event -> vector of arguments + format + QMap m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case + QMap m_Flags; // pid -> flag (e.g. 0 -> "winner") + QMap m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true + QMap m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true + QMap m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") + QMap m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) + QMap m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) + QMap m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") + QMap > m_DefEvents; // event -> vector of arguments + format public: CStatsW3MMD( CBaseGame *nGame, QString nCategory ); @@ -49,7 +49,7 @@ class CStatsW3MMD : public CStats virtual bool ProcessAction( CIncomingAction *Action ); virtual void Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ); - virtual vector TokenizeKey( QString key ); + virtual QVector TokenizeKey( QString key ); }; #endif diff --git a/ghost/util.cpp b/ghost/util.cpp index 9d76ae5..6b7b8dc 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -513,12 +513,12 @@ bool UTIL_IsLanIP( QByteArray ip ) return false; } -bool UTIL_IsLocalIP( QByteArray ip, vector &localIPs ) +bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ) { if( ip.size( ) != 4 ) return false; - for( vector :: iterator i = localIPs.begin( ); i != localIPs.end( ); i++ ) + for( QVector :: iterator i = localIPs.begin( ); i != localIPs.end( ); i++ ) { if( (*i).size( ) != 4 ) continue; @@ -535,9 +535,9 @@ void UTIL_Replace( QString &Text, QString Key, QString Value ) Text.replace(Key, Value); } -vector UTIL_Tokenize( QString s, char delim ) +QVector UTIL_Tokenize( QString s, char delim ) { - vector Tokens; + QVector Tokens; QString Token; for( QString :: iterator i = s.begin( ); i != s.end( ); i++ ) diff --git a/ghost/util.h b/ghost/util.h index cdbcdfb..accde08 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -23,6 +23,7 @@ #include #include +#include // byte arrays @@ -82,9 +83,9 @@ QByteArray UTIL_DecodeStatString( QByteArray &data ); // other bool UTIL_IsLanIP( QByteArray ip ); -bool UTIL_IsLocalIP( QByteArray ip, vector &localIPs ); +bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ); void UTIL_Replace( QString &Text, QString Key, QString Value ); -vector UTIL_Tokenize( QString s, char delim ); +QVector UTIL_Tokenize( QString s, char delim ); // math From 9d6be895a8726e4db24d09afe80e33dfa82184a0 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Mon, 19 Apr 2010 16:21:56 +0000 Subject: [PATCH 04/69] not working so far --- ghost/bncsutilinterface.cpp | 16 +- ghost/bnet.cpp | 291 ++++++++++-------------- ghost/bnet.h | 102 ++++----- ghost/bnetprotocol.cpp | 155 ++++++------- ghost/bnetprotocol.h | 75 +++--- ghost/bnlsclient.cpp | 8 +- ghost/bnlsclient.h | 4 +- ghost/bnlsprotocol.cpp | 20 +- ghost/config.cpp | 33 +-- ghost/config.h | 14 +- ghost/crc32.cpp | 6 +- ghost/crc32.h | 4 +- ghost/csvparser.cpp | 4 +- ghost/csvparser.h | 13 +- ghost/game.cpp | 126 +++++----- ghost/game_admin.cpp | 187 ++++++--------- ghost/game_base.cpp | 233 ++++++++----------- ghost/gameplayer.cpp | 25 +- ghost/gameprotocol.cpp | 156 ++++++------- ghost/gameprotocol.h | 24 +- ghost/ghost.cpp | 40 ++-- ghost/ghostdbmysql.h | 148 ++++++------ ghost/ghostdbsqlite.cpp | 168 +++++++------- ghost/ghostdbsqlite.h | 102 +++++---- ghost/gpsprotocol.cpp | 28 +-- ghost/language.h | 442 ++++++++++++++++++------------------ ghost/main.cpp | 16 +- ghost/map.cpp | 22 +- ghost/map.h | 36 +-- ghost/packed.cpp | 39 ++-- ghost/packed.h | 14 +- ghost/replay.cpp | 2 + ghost/sha1.cpp | 2 +- ghost/sqlite3.h | 112 ++++----- ghost/util.cpp | 4 +- ghost/util.h | 4 +- 36 files changed, 1266 insertions(+), 1409 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index c553baf..d5d32bc 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -31,7 +31,7 @@ CBNCSUtilInterface :: CBNCSUtilInterface( QString userName, QString userPassword ) { // m_nls = (void *)nls_init( userName.c_str( ), userPassword.c_str( ) ); - m_NLS = new NLS( userName, userPassword ); + m_NLS = new NLS( userName.toStdString(), userPassword.toStdString() ); } CBNCSUtilInterface :: ~CBNCSUtilInterface( ) @@ -45,7 +45,7 @@ void CBNCSUtilInterface :: Reset( QString userName, QString userPassword ) // nls_free( (nls_t *)m_nls ); // m_nls = (void *)nls_init( userName.c_str( ), userPassword.c_str( ) ); delete (NLS *)m_NLS; - m_NLS = new NLS( userName, userPassword ); + m_NLS = new NLS( userName.toStdString(), userPassword.toStdString() ); } bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, QByteArray clientToken, QByteArray serverToken ) @@ -69,11 +69,11 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr char buf[1024]; uint32_t EXEVersion; - getExeInfo( FileWar3EXE.c_str( ), (char *)&buf, 1024, (uint32_t *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); + getExeInfo( FileWar3EXE.toStdString().c_str( ), (char *)&buf, 1024, (uint32_t *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); m_EXEInfo = buf; m_EXEVersion = UTIL_CreateQByteArray( EXEVersion, false ); uint32_t EXEVersionHash; - checkRevisionFlat( valueStringFormula.c_str( ), FileWar3EXE.c_str( ), FileStormDLL.c_str( ), FileGameDLL.c_str( ), extractMPQNumber( mpqFileName.c_str( ) ), (unsigned long *)&EXEVersionHash ); + checkRevisionFlat( valueStringFormula.toStdString().c_str( ), FileWar3EXE.toStdString().c_str( ), FileStormDLL.toStdString().c_str( ), FileGameDLL.toStdString().c_str( ), extractMPQNumber( mpqFileName.toStdString().c_str( ) ), (unsigned long *)&EXEVersionHash ); m_EXEVersionHash = UTIL_CreateQByteArray( EXEVersionHash, false ); m_KeyInfoROC = CreateKeyInfo( keyROC, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); @@ -122,8 +122,8 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray salt, QBy // set m_M1 char buf[20]; - // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).c_str( ), QString( salt.begin( ), salt.end( ) ).c_str( ) ); - ( (NLS *)m_NLS )->getClientSessionKey( buf, QString( salt.begin( ), salt.end( ) ).c_str( ), QString( serverKey.begin( ), serverKey.end( ) ).c_str( ) ); + // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).toStdString().c_str( ), QString( salt.begin( ), salt.end( ) ).toStdString().c_str( ) ); + ( (NLS *)m_NLS )->getClientSessionKey( buf, salt.data(), serverKey.data() ); m_M1 = UTIL_CreateQByteArray( (unsigned char *)buf, 20 ); return true; } @@ -133,7 +133,7 @@ bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( QString userPassword ) // set m_PvPGNPasswordHash char buf[20]; - hashPassword( userPassword.c_str( ), buf ); + hashPassword( userPassword.toStdString().c_str( ), buf ); m_PvPGNPasswordHash = UTIL_CreateQByteArray( (unsigned char *)buf, 20 ); return true; } @@ -142,7 +142,7 @@ QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToke { unsigned char Zeros[] = { 0, 0, 0, 0 }; QByteArray KeyInfo; - CDKeyDecoder Decoder( key.c_str( ), key.size( ) ); + CDKeyDecoder Decoder( key.toStdString().c_str( ), key.size( ) ); if( Decoder.isKeyValid( ) ) { diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 1f27f6f..b01c8b0 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -35,10 +35,11 @@ #include "replay.h" #include "gameprotocol.h" #include "game_base.h" +#include "includes.h" -#include - -using namespace boost :: filesystem; +#include +#include +#include // // CBNET @@ -58,7 +59,7 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_Exiting = false; m_Server = nServer; QString LowerServer = m_Server; - transform( LowerServer.begin( ), LowerServer.end( ), LowerServer.begin( ), (int(*)(int))tolower ); + LowerServer = LowerServer.toLower(); if( !nServerAlias.isEmpty( ) ) m_ServerAlias = nServerAlias; @@ -89,10 +90,8 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n // remove dashes from CD keys and convert to uppercase - m_CDKeyROC.erase( remove( m_CDKeyROC.begin( ), m_CDKeyROC.end( ), '-' ), m_CDKeyROC.end( ) ); - m_CDKeyTFT.erase( remove( m_CDKeyTFT.begin( ), m_CDKeyTFT.end( ), '-' ), m_CDKeyTFT.end( ) ); - transform( m_CDKeyROC.begin( ), m_CDKeyROC.end( ), m_CDKeyROC.begin( ), (int(*)(int))toupper ); - transform( m_CDKeyTFT.begin( ), m_CDKeyTFT.end( ), m_CDKeyTFT.begin( ), (int(*)(int))toupper ); + m_CDKeyROC = m_CDKeyROC.replace('-', "").toLower(); + m_CDKeyTFT = m_CDKeyTFT.replace('-', "").toLower(); if( m_CDKeyROC.size( ) != 26 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] warning - your ROC CD key is not 26 characters long and is probably invalid" ); @@ -107,7 +106,7 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_UserPassword = nUserPassword; m_FirstChannel = nFirstChannel; m_RootAdmin = nRootAdmin; - transform( m_RootAdmin.begin( ), m_RootAdmin.end( ), m_RootAdmin.begin( ), (int(*)(int))tolower ); + m_RootAdmin = m_RootAdmin.toLower(); m_CommandTrigger = nCommandTrigger; m_War3Version = nWar3Version; m_EXEVersion = nEXEVersion; @@ -615,7 +614,7 @@ void CBNET :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = RecvBuffer->toUtf8(); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -633,9 +632,9 @@ void CBNET :: ExtractPackets( ) { if( Bytes.size( ) >= Length ) { - m_Packets.enqueue( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes[1], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); - *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); + m_Packets.enqueue( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes[1], Bytes.left(Length) ) ); + *RecvBuffer = RecvBuffer->mid( Length ); + Bytes.remove(0, Length); } else return; @@ -876,7 +875,7 @@ void CBNET :: ProcessPackets( ) // try to figure out if the user might be using the wrong logon type since too many people are confused by this QString Server = m_Server; - transform( Server.begin( ), Server.end( ), Server.begin( ), (int(*)(int))tolower ); + Server = Server.toLower(); if( m_PasswordHashType == "pvpgn" && ( Server == "useast.battle.net" || Server == "uswest.battle.net" || Server == "asia.battle.net" || Server == "europe.battle.net" ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] it looks like you're trying to connect to a battle.net server using a pvpgn logon type, check your config file's \"battle.net custom data\" section" ); @@ -952,7 +951,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( Message == "s" || Message == "sc" || Message == "spoof" || Message == "check" || Message == "spoofcheck" ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, User, true ); - else if( Message.find( m_GHost->m_CurrentGame->GetGameName( ) ) != QString :: npos ) + else if( Message.indexOf( m_GHost->m_CurrentGame->GetGameName( ) ) != -1 ) { // look for messages like "entered a Warcraft III The Frozen Throne game called XYZ" // we don't look for the English part of the text anymore because we want this to work with multiple languages @@ -983,9 +982,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString Command; QString Payload; - QString :: size_type PayloadStart = Message.find( " " ); + int PayloadStart = Message.indexOf( " " ); - if( PayloadStart != QString :: npos ) + if( PayloadStart != -1 ) { Command = Message.mid( 1, PayloadStart - 1 ); Payload = Message.mid( PayloadStart + 1 ); @@ -993,7 +992,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else Command = Message.mid( 1 ); - transform( Command.begin( ), Command.end( ), Command.begin( ), (int(*)(int))tolower ); + Command = Command.toLower(); if( IsAdmin( User ) || IsRootAdmin( User ) ) { @@ -1032,16 +1031,16 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString Victim; QString Reason; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Victim; - if( !SS.eof( ) ) + if( !SS.atEnd( ) ) { - getline( SS, Reason ); - QString :: size_type Start = Reason.find_first_not_of( " " ); + Reason = SS.readLine(); + int Start = Reason.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Reason = Reason.mid( Start ); } @@ -1069,22 +1068,22 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t Interval; QString Message; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Interval; - if( SS.fail( ) || Interval == 0 ) + if( SS.status() != QTextStream::Ok || Interval == 0 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to announce command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #2 to announce command" ); else { - getline( SS, Message ); - QString :: size_type Start = Message.find_first_not_of( " " ); + Message = SS.readLine(); + int Start = Message.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Message = Message.mid( Start ); QueueChatCommand( m_GHost->m_Language->AnnounceMessageEnabled( ), User, Whisper ); @@ -1123,28 +1122,28 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t MaximumGames; uint32_t AutoStartPlayers; QString GameName; - stringstream SS; + QTextStream SS; SS << Payload; SS >> MaximumGames; - if( SS.fail( ) || MaximumGames == 0 ) + if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to autohost command" ); else { SS >> AutoStartPlayers; - if( SS.fail( ) || AutoStartPlayers == 0 ) + if( SS.status() != QTextStream::Ok || AutoStartPlayers == 0 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #2 to autohost command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #3 to autohost command" ); else { - getline( SS, GameName ); - QString :: size_type Start = GameName.find_first_not_of( " " ); + GameName = SS.readLine(); + int Start = GameName.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) GameName = GameName.mid( Start ); QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); @@ -1199,40 +1198,40 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) double MinimumScore; double MaximumScore; QString GameName; - stringstream SS; + QTextStream SS; SS << Payload; SS >> MaximumGames; - if( SS.fail( ) || MaximumGames == 0 ) + if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to autohostmm command" ); else { SS >> AutoStartPlayers; - if( SS.fail( ) || AutoStartPlayers == 0 ) + if( SS.status() != QTextStream::Ok || AutoStartPlayers == 0 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #2 to autohostmm command" ); else { SS >> MinimumScore; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #3 to autohostmm command" ); else { SS >> MaximumScore; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #4 to autohostmm command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #5 to autohostmm command" ); else { - getline( SS, GameName ); - QString :: size_type Start = GameName.find_first_not_of( " " ); + GameName = SS.readLine(); + int Start = GameName.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) GameName = GameName.mid( Start ); QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); @@ -1329,15 +1328,15 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 - stringstream SS; + QTextStream SS; SS << Payload; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { uint32_t SID; SS >> SID; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input to close command" ); break; @@ -1503,7 +1502,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) + if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) QueueChatCommand( m_GHost->m_Language->UnableToLoadReplaysOutside( ), User, Whisper ); else { @@ -1602,15 +1601,15 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" - stringstream SS; + QTextStream SS; SS << Payload; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { QString HoldName; SS >> HoldName; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input to hold command" ); break; @@ -1640,69 +1639,45 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); else { - QString FoundMapConfigs; - try { - path MapCFGPath( m_GHost->m_MapCFGPath ); - QString Pattern = Payload; - transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); + QDir MapCFGPath( m_GHost->m_MapCFGPath ); + QString Pattern = Payload.toLower(); - if( !exists( MapCFGPath ) ) + if( !MapCFGPath.exists() ) { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error listing map configs - map config path doesn't exist" ); + CONSOLE_Print( "[ADMINGAME] error listing map configs - map config path doesn't exist" ); QueueChatCommand( m_GHost->m_Language->ErrorListingMapConfigs( ), User, Whisper ); } else { - directory_iterator EndIterator; - path LastMatch; - uint32_t Matches = 0; - - for( directory_iterator i( MapCFGPath ); i != EndIterator; i++ ) - { - QString FileName = i->filename( ); - QString Stem = i->path( ).stem( ); - transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); - transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - - if( !is_directory( i->status( ) ) && i->path( ).extension( ) == ".cfg" && FileName.find( Pattern ) != QString :: npos ) - { - LastMatch = i->path( ); - Matches++; - - if( FoundMapConfigs.isEmpty( ) ) - FoundMapConfigs = i->filename( ); - else - FoundMapConfigs += ", " + i->filename( ); - - // if the pattern matches the filename exactly, with or without extension, stop any further matching - - if( FileName == Pattern || Stem == Pattern ) - { - Matches = 1; - break; - } - } - } + QStringList files = MapCFGPath.entryList(QStringList("*" + Pattern + "*"), QDir::Files, QDir::Name); + uint32_t Matches = files.size(); if( Matches == 0 ) QueueChatCommand( m_GHost->m_Language->NoMapConfigsFound( ), User, Whisper ); - else if( Matches == 1 ) + else if (files.contains(Pattern)) + { + QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ), User, Whisper ); + CConfig MapCFG; + MapCFG.Read( Pattern ); + m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); + } + else if (Matches == 1) { - QString File = LastMatch.filename( ); + QString File = files.at(0); QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + File ), User, Whisper ); CConfig MapCFG; - MapCFG.Read( LastMatch.QString( ) ); + MapCFG.Read( m_GHost->m_MapCFGPath + File ); m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); } else - QueueChatCommand( m_GHost->m_Language->FoundMapConfigs( FoundMapConfigs ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->FoundMapConfigs( files.join(", ") ), User, Whisper ); } } catch( const exception &ex ) { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error listing map configs - caught exception [" + ex.what( ) + "]" ); + CONSOLE_Print( QString( "[ADMINGAME] error listing map configs - caught exception [" ) + ex.what( ) + "]" ); QueueChatCommand( m_GHost->m_Language->ErrorListingMapConfigs( ), User, Whisper ); } } @@ -1716,7 +1691,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) + if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) QueueChatCommand( m_GHost->m_Language->UnableToLoadSaveGamesOutside( ), User, Whisper ); else { @@ -1755,53 +1730,35 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) try { - path MapPath( m_GHost->m_MapPath ); - QString Pattern = Payload; - transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); + QDir MapPath( m_GHost->m_MapPath ); + QString Pattern = Payload.toLower(); - if( !exists( MapPath ) ) + if( !MapPath.exists() ) { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error listing maps - map path doesn't exist" ); + CONSOLE_Print( "[ADMINGAME] error listing maps - map path doesn't exist" ); QueueChatCommand( m_GHost->m_Language->ErrorListingMaps( ), User, Whisper ); } else { - directory_iterator EndIterator; - path LastMatch; - uint32_t Matches = 0; + QStringList files = MapPath.entryList(QStringList("*"+Pattern+"*"), QDir::Files, QDir::Name); + uint32_t Matches = files.size(); - for( directory_iterator i( MapPath ); i != EndIterator; i++ ) + if( Matches == 0 ) + QueueChatCommand( m_GHost->m_Language->NoMapsFound( ), User, Whisper ); + else if (files.contains(Pattern)) { - QString FileName = i->filename( ); - QString Stem = i->path( ).stem( ); - transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); - transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - - if( !is_directory( i->status( ) ) && FileName.find( Pattern ) != QString :: npos ) - { - LastMatch = i->path( ); - Matches++; - - if( FoundMaps.isEmpty( ) ) - FoundMaps = i->filename( ); - else - FoundMaps += ", " + i->filename( ); + QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( Pattern ), User, Whisper ); - // if the pattern matches the filename exactly, with or without extension, stop any further matching + // hackhack: create a config file in memory with the required information to load the map - if( FileName == Pattern || Stem == Pattern ) - { - Matches = 1; - break; - } - } + CConfig MapCFG; + MapCFG.Set( "map_path", "Maps\\Download\\" + Pattern ); + MapCFG.Set( "map_localpath", Pattern ); + m_GHost->m_Map->Load( &MapCFG, Pattern ); } - - if( Matches == 0 ) - QueueChatCommand( m_GHost->m_Language->NoMapsFound( ), User, Whisper ); else if( Matches == 1 ) { - QString File = LastMatch.filename( ); + QString File = files.at(0); QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( File ), User, Whisper ); // hackhack: create a config file in memory with the required information to load the map @@ -1812,7 +1769,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_GHost->m_Map->Load( &MapCFG, File ); } else - QueueChatCommand( m_GHost->m_Language->FoundMaps( FoundMaps ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->FoundMaps( files.join(", ") ), User, Whisper ); } } catch( const exception &ex ) @@ -1833,15 +1790,15 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // open as many slots as specified, e.g. "5 10" opens slots 5 and 10 - stringstream SS; + QTextStream SS; SS << Payload; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { uint32_t SID; SS >> SID; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input to open command" ); break; @@ -1884,9 +1841,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString Owner; QString GameName; - QString :: size_type GameNameStart = Payload.find( " " ); + int GameNameStart = Payload.indexOf( " " ); - if( GameNameStart != QString :: npos ) + if( GameNameStart != -1 ) { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); @@ -1912,9 +1869,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString Owner; QString GameName; - QString :: size_type GameNameStart = Payload.find( " " ); + int GameNameStart = Payload.indexOf( " " ); - if( GameNameStart != QString :: npos ) + if( GameNameStart != -1 ) { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); @@ -1957,22 +1914,22 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t GameNumber; QString Message; - stringstream SS; + QTextStream SS; SS << Payload; SS >> GameNumber; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to saygame command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #2 to saygame command" ); else { - getline( SS, Message ); - QString :: size_type Start = Message.find_first_not_of( " " ); + Message = SS.readLine(); + int Start = Message.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Message = Message.mid( Start ); if( GameNumber - 1 < m_GHost->m_Games.size( ) ) @@ -2049,21 +2006,21 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { uint32_t SID1; uint32_t SID2; - stringstream SS; + QTextStream SS; SS << Payload; SS >> SID1; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to swap command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #2 to swap command" ); else { SS >> SID2; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #2 to swap command" ); else m_GHost->m_CurrentGame->SwapSlots( (unsigned char)( SID1 - 1 ), (unsigned char)( SID2 - 1 ) ); @@ -2188,9 +2145,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // this is not necessarily true though since info messages also include channel MOTD's and such QString UserName; - QString :: size_type Split = Message.find( " " ); + int Split = Message.indexOf( " " ); - if( Split != QString :: npos ) + if( Split != -1 ) UserName = Message.mid( 0, Split ); else UserName = Message.mid( 0 ); @@ -2201,26 +2158,26 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( m_GHost->m_CurrentGame && m_GHost->m_CurrentGame->GetPlayerFromName( UserName, true ) ) { - if( Message.find( "is away" ) != QString :: npos ) + if( Message.indexOf( "is away" ) != -1 ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsAway( UserName ) ); - else if( Message.find( "is unavailable" ) != QString :: npos ) + else if( Message.indexOf( "is unavailable" ) != -1 ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsUnavailable( UserName ) ); - else if( Message.find( "is refusing messages" ) != QString :: npos ) + else if( Message.indexOf( "is refusing messages" ) != -1 ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsRefusingMessages( UserName ) ); - else if( Message.find( "is using Warcraft III The Frozen Throne in the channel" ) != QString :: npos ) + else if( Message.indexOf( "is using Warcraft III The Frozen Throne in the channel" ) != -1 ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsNotInGame( UserName ) ); - else if( Message.find( "is using Warcraft III The Frozen Throne in channel" ) != QString :: npos ) + else if( Message.indexOf( "is using Warcraft III The Frozen Throne in channel" ) != -1 ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsNotInGame( UserName ) ); - else if( Message.find( "is using Warcraft III The Frozen Throne in a private channel" ) != QString :: npos ) + else if( Message.indexOf( "is using Warcraft III The Frozen Throne in a private channel" ) != -1 ) m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsInPrivateChannel( UserName ) ); - if( Message.find( "is using Warcraft III The Frozen Throne in game" ) != QString :: npos || Message.find( "is using Warcraft III Frozen Throne and is currently in game" ) != QString :: npos ) + if( Message.indexOf( "is using Warcraft III The Frozen Throne in game" ) != -1 || Message.indexOf( "is using Warcraft III Frozen Throne and is currently in game" ) != -1 ) { // check both the current game name and the last game name against the /whois response // this is because when the game is rehosted, players who joined recently will be in the previous game according to battle.net // note: if the game is rehosted more than once it is possible (but unlikely) for a false positive because only two game names are checked - if( Message.find( m_GHost->m_CurrentGame->GetGameName( ) ) != QString :: npos || Message.find( m_GHost->m_CurrentGame->GetLastGameName( ) ) != QString :: npos ) + if( Message.indexOf( m_GHost->m_CurrentGame->GetGameName( ) ) != -1 || Message.indexOf( m_GHost->m_CurrentGame->GetLastGameName( ) ) != -1 ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, UserName, false ); else m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsInAnotherGame( UserName ) ); @@ -2316,7 +2273,7 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h if( hostName.isEmpty( ) ) { QByteArray UniqueName = m_Protocol->GetUniqueName( ); - hostName = QString( UniqueName.begin( ), UniqueName.end( ) ); + hostName = UniqueName; } if( m_LoggedIn && map ) @@ -2444,7 +2401,7 @@ void CBNET :: UnqueueGameRefreshes( ) bool CBNET :: IsAdmin( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); for( QVector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) { @@ -2459,17 +2416,17 @@ bool CBNET :: IsRootAdmin( QString name ) { // m_RootAdmin was already transformed to lower case in the constructor - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); // updated to permit multiple root admins seperated by a space, e.g. "Varlock Kilranin Instinct121" // note: this function gets called frequently so it would be better to parse the root admins just once and store them in a list somewhere // however, it's hardly worth optimizing at this point since the code's already written - stringstream SS; + QTextStream SS; QString s; SS << m_RootAdmin; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { SS >> s; @@ -2482,7 +2439,7 @@ bool CBNET :: IsRootAdmin( QString name ) CDBBan *CBNET :: IsBannedName( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); // todotodo: optimize this - maybe use a map? @@ -2510,19 +2467,19 @@ CDBBan *CBNET :: IsBannedIP( QString ip ) void CBNET :: AddAdmin( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); m_Admins.push_back( name ); } void CBNET :: AddBan( QString name, QString ip, QString gamename, QString admin, QString reason ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); m_Bans.push_back( new CDBBan( m_Server, name, ip, "N/A", gamename, admin, reason ) ); } void CBNET :: RemoveAdmin( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); for( QVector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) { @@ -2535,7 +2492,7 @@ void CBNET :: RemoveAdmin( QString name ) void CBNET :: RemoveBan( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); ) { diff --git a/ghost/bnet.h b/ghost/bnet.h index 1d85415..e135dba 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -45,14 +45,14 @@ class CCallableGamePlayerSummaryCheck; class CCallableDotAPlayerSummaryCheck; class CDBBan; -typedef pair PairedAdminCount; -typedef pair PairedAdminAdd; -typedef pair PairedAdminRemove; -typedef pair PairedBanCount; -typedef pair PairedBanAdd; -typedef pair PairedBanRemove; -typedef pair PairedGPSCheck; -typedef pair PairedDPSCheck; +typedef pair PairedAdminCount; +typedef pair PairedAdminAdd; +typedef pair PairedAdminRemove; +typedef pair PairedBanCount; +typedef pair PairedBanAdd; +typedef pair PairedBanRemove; +typedef pair PairedGPSCheck; +typedef pair PairedDPSCheck; class CBNET { @@ -78,31 +78,31 @@ class CBNET QVector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress CCallableAdminList *m_CallableAdminList; // threaded database admin list in progress CCallableBanList *m_CallableBanList; // threaded database ban list in progress - QVector m_Admins; // vector of cached admins + QVector m_Admins; // vector of cached admins QVector m_Bans; // vector of cached bans bool m_Exiting; // set to true and this class will be deleted next update - string m_Server; // battle.net server to connect to - string m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) - string m_ServerAlias; // battle.net server alias (short name, e.g. "USEast") - string m_BNLSServer; // BNLS server to connect to (for warden handling) + QString m_Server; // battle.net server to connect to + QString m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) + QString m_ServerAlias; // battle.net server alias (short name, e.g. "USEast") + QString m_BNLSServer; // BNLS server to connect to (for warden handling) uint16_t m_BNLSPort; // BNLS port uint32_t m_BNLSWardenCookie; // BNLS warden cookie - string m_CDKeyROC; // ROC CD key - string m_CDKeyTFT; // TFT CD key - string m_CountryAbbrev; // country abbreviation - string m_Country; // country + QString m_CDKeyROC; // ROC CD key + QString m_CDKeyTFT; // TFT CD key + QString m_CountryAbbrev; // country abbreviation + QString m_Country; // country uint32_t m_LocaleID; // see: http://msdn.microsoft.com/en-us/library/0h88fahh%28VS.85%29.aspx - string m_UserName; // battle.net username - string m_UserPassword; // battle.net password - string m_FirstChannel; // the first chat channel to join upon entering chat (note: we hijack this to store the last channel when entering a game) - string m_CurrentChannel; // the current chat channel - string m_RootAdmin; // the root admin + QString m_UserName; // battle.net username + QString m_UserPassword; // battle.net password + QString m_FirstChannel; // the first chat channel to join upon entering chat (note: we hijack this to store the last channel when entering a game) + QString m_CurrentChannel; // the current chat channel + QString m_RootAdmin; // the root admin char m_CommandTrigger; // the character prefix to identify commands unsigned char m_War3Version; // custom warcraft 3 version for PvPGN users QByteArray m_EXEVersion; // custom exe version for PvPGN users QByteArray m_EXEVersionHash; // custom exe version hash for PvPGN users - string m_PasswordHashType; // password hash type for PvPGN users - string m_PVPGNRealmName; // realm name for PvPGN users (for mutual friend spoofchecks) + QString m_PasswordHashType; // password hash type for PvPGN users + QString m_PVPGNRealmName; // realm name for PvPGN users (for mutual friend spoofchecks) uint32_t m_MaxMessageLength; // maximum message length for PvPGN users uint32_t m_HostCounterID; // the host counter ID to identify players from this realm uint32_t m_LastDisconnectedTime; // GetTime when we were last disconnected from battle.net @@ -121,24 +121,24 @@ class CBNET bool m_PublicCommands; // whether to allow public commands or not public: - CBNET( CGHost *nGHost, string nServer, string nServerAlias, string nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, uint32_t nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ); + CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ); ~CBNET( ); bool GetExiting( ) { return m_Exiting; } - string GetServer( ) { return m_Server; } - string GetServerAlias( ) { return m_ServerAlias; } - string GetCDKeyROC( ) { return m_CDKeyROC; } - string GetCDKeyTFT( ) { return m_CDKeyTFT; } - string GetUserName( ) { return m_UserName; } - string GetUserPassword( ) { return m_UserPassword; } - string GetFirstChannel( ) { return m_FirstChannel; } - string GetCurrentChannel( ) { return m_CurrentChannel; } - string GetRootAdmin( ) { return m_RootAdmin; } + QString GetServer( ) { return m_Server; } + QString GetServerAlias( ) { return m_ServerAlias; } + QString GetCDKeyROC( ) { return m_CDKeyROC; } + QString GetCDKeyTFT( ) { return m_CDKeyTFT; } + QString GetUserName( ) { return m_UserName; } + QString GetUserPassword( ) { return m_UserPassword; } + QString GetFirstChannel( ) { return m_FirstChannel; } + QString GetCurrentChannel( ) { return m_CurrentChannel; } + QString GetRootAdmin( ) { return m_RootAdmin; } char GetCommandTrigger( ) { return m_CommandTrigger; } QByteArray GetEXEVersion( ) { return m_EXEVersion; } QByteArray GetEXEVersionHash( ) { return m_EXEVersionHash; } - string GetPasswordHashType( ) { return m_PasswordHashType; } - string GetPVPGNRealmName( ) { return m_PVPGNRealmName; } + QString GetPasswordHashType( ) { return m_PasswordHashType; } + QString GetPVPGNRealmName( ) { return m_PVPGNRealmName; } uint32_t GetHostCounterID( ) { return m_HostCounterID; } bool GetLoggedIn( ) { return m_LoggedIn; } bool GetInChat( ) { return m_InChat; } @@ -158,30 +158,30 @@ class CBNET // functions to send packets to battle.net - void SendJoinChannel( string channel ); + void SendJoinChannel( QString channel ); void SendGetFriendsList( ); void SendGetClanList( ); void QueueEnterChat( ); - void QueueChatCommand( string chatCommand ); - void QueueChatCommand( string chatCommand, string user, bool whisper ); - void QueueGameCreate( unsigned char state, string gameName, string hostName, CMap *map, CSaveGame *saveGame, uint32_t hostCounter ); - void QueueGameRefresh( unsigned char state, string gameName, string hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ); + void QueueChatCommand( QString chatCommand ); + void QueueChatCommand( QString chatCommand, QString user, bool whisper ); + void QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t hostCounter ); + void QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ); void QueueGameUncreate( ); void UnqueuePackets( unsigned char type ); - void UnqueueChatCommand( string chatCommand ); + void UnqueueChatCommand( QString chatCommand ); void UnqueueGameRefreshes( ); // other functions - bool IsAdmin( string name ); - bool IsRootAdmin( string name ); - CDBBan *IsBannedName( string name ); - CDBBan *IsBannedIP( string ip ); - void AddAdmin( string name ); - void AddBan( string name, string ip, string gamename, string admin, string reason ); - void RemoveAdmin( string name ); - void RemoveBan( string name ); + bool IsAdmin( QString name ); + bool IsRootAdmin( QString name ); + CDBBan *IsBannedName( QString name ); + CDBBan *IsBannedIP( QString ip ); + void AddAdmin( QString name ); + void AddBan( QString name, QString ip, QString gamename, QString admin, QString reason ); + void RemoveAdmin( QString name ); + void RemoveBan( QString name ); void HoldFriends( CBaseGame *game ); void HoldClan( CBaseGame *game ); }; diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 31f561a..69a907c 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -66,12 +66,12 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - QByteArray GamesFound = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray GamesFound = data.mid(4, 4); if( UTIL_QByteArrayToUInt32( GamesFound, false ) > 0 && data.size( ) >= 25 ) { - QByteArray Port = QByteArray( data.begin( ) + 18, data.begin( ) + 20 ); - QByteArray IP = QByteArray( data.begin( ) + 20, data.begin( ) + 24 ); + QByteArray Port = data.mid(18, 2); + QByteArray IP = data.mid(20, 4); QByteArray GameName = UTIL_ExtractCString( data, 24 ); if( data.size( ) >= GameName.size( ) + 35 ) @@ -83,7 +83,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 33, true ) ); return new CIncomingGameHost( IP, UTIL_QByteArrayToUInt16( Port, false ), - QString( GameName.begin( ), GameName.end( ) ), + GameName, HostCounter ); } } @@ -126,8 +126,8 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 29 ) { - QByteArray EventID = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - QByteArray Ping = QByteArray( data.begin( ) + 12, data.begin( ) + 16 ); + QByteArray EventID = data.mid(4, 8 - 4); + QByteArray Ping = data.mid(12, 16 - 12); QByteArray User = UTIL_ExtractCString( data, 28 ); QByteArray Message = UTIL_ExtractCString( data, User.size( ) + 29 ); @@ -150,8 +150,8 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) case CBNETProtocol :: EID_EMOTE: return new CIncomingChatEvent( (CBNETProtocol :: IncomingChatEvent)UTIL_QByteArrayToUInt32( EventID, false ), UTIL_QByteArrayToUInt32( Ping, false ), - QString( User.begin( ), User.end( ) ), - QString( Message.begin( ), Message.end( ) ) ); + User, + Message ); } } @@ -181,7 +181,7 @@ bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - QByteArray Status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Status = data.mid(4, 8 - 4); if( UTIL_QByteArrayToUInt32( Status, false ) == 0 ) return true; @@ -200,7 +200,7 @@ QByteArray CBNETProtocol :: RECEIVE_SID_PING( QByteArray data ) // 4 bytes -> Ping if( ValidateLength( data ) && data.size( ) >= 8 ) - return QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + return data.mid(4, 8 - 4); return QByteArray( ); } @@ -216,7 +216,7 @@ bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - QByteArray Status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Status = data.mid(4, 8 - 4); if( UTIL_QByteArrayToUInt32( Status, false ) == 1 ) return true; @@ -241,9 +241,9 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 25 ) { - m_LogonType = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - m_ServerToken = QByteArray( data.begin( ) + 8, data.begin( ) + 12 ); - m_MPQFileTime = QByteArray( data.begin( ) + 16, data.begin( ) + 24 ); + m_LogonType = data.mid(4, 8 - 4); + m_ServerToken = data.mid(8, 12 - 8); + m_MPQFileTime = data.mid(16, 24 - 16); m_IX86VerFileName = UTIL_ExtractCString( data, 24 ); m_ValueStringFormula = UTIL_ExtractCString( data, m_IX86VerFileName.size( ) + 25 ); return true; @@ -264,7 +264,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 9 ) { - m_KeyState = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + m_KeyState = data.mid(4, 8 - 4); m_KeyStateDescription = UTIL_ExtractCString( data, 8 ); if( UTIL_QByteArrayToUInt32( m_KeyState, false ) == KR_GOOD ) @@ -288,12 +288,12 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - QByteArray status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray status = data.mid(4, 8 - 4); if( UTIL_QByteArrayToUInt32( status, false ) == 0 && data.size( ) >= 72 ) { - m_Salt = QByteArray( data.begin( ) + 8, data.begin( ) + 40 ); - m_ServerPublicKey = QByteArray( data.begin( ) + 40, data.begin( ) + 72 ); + m_Salt = data.mid(8, 40 - 8); + m_ServerPublicKey = data.mid(40, 72 - 40); return true; } } @@ -312,7 +312,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 8 ) { - QByteArray Status = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); + QByteArray Status = data.mid(4, 8 - 4); if( UTIL_QByteArrayToUInt32( Status, false ) == 0 ) return true; @@ -331,7 +331,7 @@ QByteArray CBNETProtocol :: RECEIVE_SID_WARDEN( QByteArray data ) // n bytes -> Data if( ValidateLength( data ) && data.size( ) >= 4 ) - return QByteArray( data.begin( ) + 4, data.end( ) ); + return data.mid(4); return QByteArray( ); } @@ -376,10 +376,10 @@ QVector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteAr i += 6; QByteArray Location = UTIL_ExtractCString( data, i ); i += Location.size( ) + 1; - Friends.push_back( new CIncomingFriendList( QString( Account.begin( ), Account.end( ) ), + Friends.push_back( new CIncomingFriendList( Account, Status, Area, - QString( Location.begin( ), Location.end( ) ) ) ); + Location ) ); } } @@ -429,7 +429,7 @@ QVector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteA QByteArray Location = UTIL_ExtractCString( data, i ); i += Location.size( ) + 1; - ClanList.push_back( new CIncomingClanList( QString( Name.begin( ), Name.end( ) ), + ClanList.push_back( new CIncomingClanList( Name, Rank, Status ) ); } @@ -462,7 +462,7 @@ CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( QByteArr // in the original VB source the location QString is read but discarded, so that's what I do here QByteArray Location = UTIL_ExtractCString( data, Name.size( ) + 7 ); - return new CIncomingClanList( QString( Name.begin( ), Name.end( ) ), + return new CIncomingClanList( Name, Rank, Status ); } @@ -489,8 +489,8 @@ QByteArray CBNETProtocol :: SEND_SID_NULL( ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NULL ); // SID_NULL - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later AssignLength( packet ); // DEBUG_Print( "SENT SID_NULL" ); // DEBUG_Print( packet ); @@ -502,8 +502,8 @@ QByteArray CBNETProtocol :: SEND_SID_STOPADV( ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_STOPADV ); // SID_STOPADV - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later AssignLength( packet ); // DEBUG_Print( "SENT SID_STOPADV" ); // DEBUG_Print( packet ); @@ -520,15 +520,15 @@ QByteArray CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_GETADVLISTEX ); // SID_GETADVLISTEX - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, MapFilter1, 4 ); // Map Filter UTIL_AppendQByteArray( packet, MapFilter2, 4 ); // Map Filter UTIL_AppendQByteArray( packet, MapFilter3, 4 ); // Map Filter UTIL_AppendQByteArray( packet, NumGames, 4 ); // maximum number of games to list UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name - packet.push_back( 0 ); // Game Password is NULL - packet.push_back( 0 ); // Game Stats is NULL + packet.push_back( (char)0 ); // Game Password is NULL + packet.push_back( (char)0 ); // Game Stats is NULL AssignLength( packet ); // DEBUG_Print( "SENT SID_GETADVLISTEX" ); // DEBUG_Print( packet ); @@ -540,10 +540,10 @@ QByteArray CBNETProtocol :: SEND_SID_ENTERCHAT( ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_ENTERCHAT ); // SID_ENTERCHAT - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // Account Name is NULL on Warcraft III/The Frozen Throne - packet.push_back( 0 ); // Stat String is NULL on CDKEY'd products + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // Account Name is NULL on Warcraft III/The Frozen Throne + packet.push_back( (char)0 ); // Stat String is NULL on CDKEY'd products AssignLength( packet ); // DEBUG_Print( "SENT SID_ENTERCHAT" ); // DEBUG_Print( packet ); @@ -558,8 +558,8 @@ QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_JOINCHANNEL ); // SID_JOINCHANNEL - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later if( channel.size( ) > 0 ) UTIL_AppendQByteArray( packet, NoCreateJoin, 4 ); // flags for no create join @@ -578,8 +578,8 @@ QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CHATCOMMAND ); // SID_CHATCOMMAND - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, command ); // Message AssignLength( packet ); // DEBUG_Print( "SENT SID_CHATCOMMAND" ); @@ -594,8 +594,8 @@ QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CHECKAD ); // SID_CHECKAD - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? @@ -639,10 +639,13 @@ Observers: (mask 0x00700000) cant be combined QString HostCounterString = UTIL_ToHexString( hostCounter ); + QString fi; + fi.fill('0', 8 - HostCounterString.size( ) ); + if( HostCounterString.size( ) < 8 ) - HostCounterString.insert( 0, 8 - HostCounterString.size( ), '0' ); + HostCounterString += fi; - HostCounterString = QString( HostCounterString.rbegin( ), HostCounterString.rend( ) ); + HostCounterString = UTIL_QByteArrayReverse( HostCounterString.toUtf8() ); QByteArray packet; @@ -650,13 +653,13 @@ Observers: (mask 0x00700000) cant be combined QByteArray StatString; UTIL_AppendQByteArrayFast( StatString, mapFlags ); - StatString.push_back( 0 ); + StatString.push_back( (char)0 ); UTIL_AppendQByteArrayFast( StatString, mapWidth ); UTIL_AppendQByteArrayFast( StatString, mapHeight ); UTIL_AppendQByteArrayFast( StatString, mapCRC ); UTIL_AppendQByteArrayFast( StatString, mapPath ); UTIL_AppendQByteArrayFast( StatString, hostName ); - StatString.push_back( 0 ); + StatString.push_back( (char)0 ); UTIL_AppendQByteArrayFast( StatString, mapSHA1 ); StatString = UTIL_EncodeStatString( StatString ); @@ -666,22 +669,22 @@ Observers: (mask 0x00700000) cant be combined packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_STARTADVEX3 ); // SID_STARTADVEX3 - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( state ); // State (16 = public, 17 = private, 18 = close) - packet.push_back( 0 ); // State continued... - packet.push_back( 0 ); // State continued... - packet.push_back( 0 ); // State continued... + packet.push_back( (char)0 ); // State continued... + packet.push_back( (char)0 ); // State continued... + packet.push_back( (char)0 ); // State continued... UTIL_AppendQByteArray( packet, upTime, false ); // time since creation UTIL_AppendQByteArrayFast( packet, mapGameType ); // Game Type, Parameter UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? UTIL_AppendQByteArray( packet, CustomGame, 4 ); // Custom Game UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name - packet.push_back( 0 ); // Game Password is NULL + packet.push_back( (char)0 ); // Game Password is NULL packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate UTIL_AppendQByteArrayFast( packet, HostCounterString, false ); // Host Counter UTIL_AppendQByteArrayFast( packet, StatString ); // Stat String - packet.push_back( 0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) + packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) AssignLength( packet ); } else @@ -700,12 +703,12 @@ QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NOTIFYJOIN ); // SID_NOTIFYJOIN - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, ProductID, 4 ); // Product ID UTIL_AppendQByteArray( packet, ProductVersion, 4 ); // Product Version UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name - packet.push_back( 0 ); // Game Password is NULL + packet.push_back( (char)0 ); // Game Password is NULL AssignLength( packet ); // DEBUG_Print( "SENT SID_NOTIFYJOIN" ); // DEBUG_Print( packet ); @@ -720,8 +723,8 @@ QByteArray CBNETProtocol :: SEND_SID_PING( QByteArray pingValue ) { packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_PING ); // SID_PING - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, pingValue ); // Ping Value AssignLength( packet ); } @@ -740,8 +743,8 @@ QByteArray CBNETProtocol :: SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByt QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_LOGONRESPONSE ); // SID_LOGONRESPONSE - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, clientToken ); // Client Token UTIL_AppendQByteArrayFast( packet, serverToken ); // Server Token UTIL_AppendQByteArrayFast( packet, passwordHash ); // Password Hash @@ -757,8 +760,8 @@ QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NETGAMEPORT ); // SID_NETGAMEPORT - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, serverPort, false ); // local game server port AssignLength( packet ); // DEBUG_Print( "SENT SID_NETGAMEPORT" ); @@ -780,8 +783,8 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uin QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_INFO ); // SID_AUTH_INFO - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, ProtocolID, 4 ); // Protocol ID UTIL_AppendQByteArray( packet, PlatformID, 4 ); // Platform ID @@ -819,8 +822,8 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToke { packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_CHECK ); // SID_AUTH_CHECK - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, clientToken ); // Client Token UTIL_AppendQByteArrayFast( packet, exeVersion ); // EXE Version UTIL_AppendQByteArrayFast( packet, exeVersionHash ); // EXE Version Hash @@ -851,8 +854,8 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicK { packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_ACCOUNTLOGON ); // SID_AUTH_ACCOUNTLOGON - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, clientPublicKey ); // Client Key UTIL_AppendQByteArrayFast( packet, accountName ); // Account Name AssignLength( packet ); @@ -873,8 +876,8 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPa { packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_ACCOUNTLOGONPROOF ); // SID_AUTH_ACCOUNTLOGONPROOF - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, clientPasswordProof ); // Client Password Proof AssignLength( packet ); } @@ -891,8 +894,8 @@ QByteArray CBNETProtocol :: SEND_SID_WARDEN( QByteArray wardenResponse ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_WARDEN ); // SID_WARDEN - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArrayFast( packet, wardenResponse ); // warden response AssignLength( packet ); // DEBUG_Print( "SENT SID_WARDEN" ); @@ -905,8 +908,8 @@ QByteArray CBNETProtocol :: SEND_SID_FRIENDSLIST( ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_FRIENDSLIST ); // SID_FRIENDSLIST - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later AssignLength( packet ); // DEBUG_Print( "SENT SID_FRIENDSLIST" ); // DEBUG_Print( packet ); @@ -920,8 +923,8 @@ QByteArray CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CLANMEMBERLIST ); // SID_CLANMEMBERLIST - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, Cookie, 4 ); // cookie AssignLength( packet ); // DEBUG_Print( "SENT SID_CLANMEMBERLIST" ); diff --git a/ghost/bnetprotocol.h b/ghost/bnetprotocol.h index 395ec13..31d60dd 100644 --- a/ghost/bnetprotocol.h +++ b/ghost/bnetprotocol.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -25,6 +25,7 @@ // CBNETProtocol // +#include "includes.h" #define BNET_HEADER_CONSTANT 255 class CIncomingGameHost; @@ -109,11 +110,11 @@ class CBNETProtocol QByteArray GetServerToken( ) { return m_ServerToken; } QByteArray GetMPQFileTime( ) { return m_MPQFileTime; } QByteArray GetIX86VerFileName( ) { return m_IX86VerFileName; } - string GetIX86VerFileNameString( ) { return string( m_IX86VerFileName.begin( ), m_IX86VerFileName.end( ) ); } + QString GetIX86VerFileNameString( ) { return m_IX86VerFileName; } QByteArray GetValueStringFormula( ) { return m_ValueStringFormula; } - string GetValueStringFormulaString( ) { return string( m_ValueStringFormula.begin( ), m_ValueStringFormula.end( ) ); } + QString GetValueStringFormulaString( ) { return m_ValueStringFormula; } QByteArray GetKeyState( ) { return m_KeyState; } - string GetKeyStateDescription( ) { return string( m_KeyStateDescription.begin( ), m_KeyStateDescription.end( ) ); } + QString GetKeyStateDescription( ) { return m_KeyStateDescription; } QByteArray GetSalt( ) { return m_Salt; } QByteArray GetServerPublicKey( ) { return m_ServerPublicKey; } QByteArray GetUniqueName( ) { return m_UniqueName; } @@ -142,19 +143,19 @@ class CBNETProtocol QByteArray SEND_PROTOCOL_INITIALIZE_SELECTOR( ); QByteArray SEND_SID_NULL( ); QByteArray SEND_SID_STOPADV( ); - QByteArray SEND_SID_GETADVLISTEX( string gameName ); + QByteArray SEND_SID_GETADVLISTEX( QString gameName ); QByteArray SEND_SID_ENTERCHAT( ); - QByteArray SEND_SID_JOINCHANNEL( string channel ); - QByteArray SEND_SID_CHATCOMMAND( string command ); + QByteArray SEND_SID_JOINCHANNEL( QString channel ); + QByteArray SEND_SID_CHATCOMMAND( QString command ); QByteArray SEND_SID_CHECKAD( ); - QByteArray SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, QByteArray mapCRC, QByteArray mapSHA1, uint32_t hostCounter ); - QByteArray SEND_SID_NOTIFYJOIN( string gameName ); + QByteArray SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, uint32_t hostCounter ); + QByteArray SEND_SID_NOTIFYJOIN( QString gameName ); QByteArray SEND_SID_PING( QByteArray pingValue ); - QByteArray SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByteArray serverToken, QByteArray passwordHash, string accountName ); + QByteArray SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByteArray serverToken, QByteArray passwordHash, QString accountName ); QByteArray SEND_SID_NETGAMEPORT( uint16_t serverPort ); - QByteArray SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, string countryAbbrev, string country ); - QByteArray SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToken, QByteArray exeVersion, QByteArray exeVersionHash, QByteArray keyInfoROC, QByteArray keyInfoTFT, string exeInfo, string keyOwnerName ); - QByteArray SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicKey, string accountName ); + QByteArray SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, QString countryAbbrev, QString country ); + QByteArray SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToken, QByteArray exeVersion, QByteArray exeVersionHash, QByteArray keyInfoROC, QByteArray keyInfoTFT, QString exeInfo, QString keyOwnerName ); + QByteArray SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicKey, QString accountName ); QByteArray SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPasswordProof ); QByteArray SEND_SID_WARDEN( QByteArray wardenResponse ); QByteArray SEND_SID_FRIENDSLIST( ); @@ -176,17 +177,17 @@ class CIncomingGameHost private: QByteArray m_IP; uint16_t m_Port; - string m_GameName; + QString m_GameName; QByteArray m_HostCounter; public: - CIncomingGameHost( QByteArray &nIP, uint16_t nPort, string nGameName, QByteArray &nHostCounter ); + CIncomingGameHost( QByteArray &nIP, uint16_t nPort, QString nGameName, QByteArray &nHostCounter ); ~CIncomingGameHost( ); QByteArray GetIP( ) { return m_IP; } - string GetIPString( ); + QString GetIPString( ); uint16_t GetPort( ) { return m_Port; } - string GetGameName( ) { return m_GameName; } + QString GetGameName( ) { return m_GameName; } QByteArray GetHostCounter( ) { return m_HostCounter; } }; @@ -199,17 +200,17 @@ class CIncomingChatEvent private: CBNETProtocol :: IncomingChatEvent m_ChatEvent; uint32_t m_Ping; - string m_User; - string m_Message; + QString m_User; + QString m_Message; public: - CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, uint32_t nPing, string nUser, string nMessage ); + CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, uint32_t nPing, QString nUser, QString nMessage ); ~CIncomingChatEvent( ); CBNETProtocol :: IncomingChatEvent GetChatEvent( ) { return m_ChatEvent; } uint32_t GetPing( ) { return m_Ping; } - string GetUser( ) { return m_User; } - string GetMessage( ) { return m_Message; } + QString GetUser( ) { return m_User; } + QString GetMessage( ) { return m_Message; } }; // @@ -219,25 +220,25 @@ class CIncomingChatEvent class CIncomingFriendList { private: - string m_Account; + QString m_Account; unsigned char m_Status; unsigned char m_Area; - string m_Location; + QString m_Location; public: - CIncomingFriendList( string nAccount, unsigned char nStatus, unsigned char nArea, string nLocation ); + CIncomingFriendList( QString nAccount, unsigned char nStatus, unsigned char nArea, QString nLocation ); ~CIncomingFriendList( ); - string GetAccount( ) { return m_Account; } + QString GetAccount( ) { return m_Account; } unsigned char GetStatus( ) { return m_Status; } unsigned char GetArea( ) { return m_Area; } - string GetLocation( ) { return m_Location; } - string GetDescription( ); + QString GetLocation( ) { return m_Location; } + QString GetDescription( ); private: - string ExtractStatus( unsigned char status ); - string ExtractArea( unsigned char area ); - string ExtractLocation( string location ); + QString ExtractStatus( unsigned char status ); + QString ExtractArea( unsigned char area ); + QString ExtractLocation( QString location ); }; // @@ -247,18 +248,18 @@ class CIncomingFriendList class CIncomingClanList { private: - string m_Name; + QString m_Name; unsigned char m_Rank; unsigned char m_Status; public: - CIncomingClanList( string nName, unsigned char nRank, unsigned char nStatus ); + CIncomingClanList( QString nName, unsigned char nRank, unsigned char nStatus ); ~CIncomingClanList( ); - string GetName( ) { return m_Name; } - string GetRank( ); - string GetStatus( ); - string GetDescription( ); + QString GetName( ) { return m_Name; } + QString GetRank( ); + QString GetStatus( ); + QString GetDescription( ); }; #endif diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index b58b8c8..7e08aa9 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -136,7 +136,7 @@ bool CBNLSClient :: Update( void *fd, void *send_fd ) void CBNLSClient :: ExtractPackets( ) { QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = RecvBuffer->toUtf8(); while( Bytes.size( ) >= 3 ) { @@ -146,9 +146,9 @@ void CBNLSClient :: ExtractPackets( ) { if( Bytes.size( ) >= Length ) { - m_Packets.enqueue( new CCommandPacket( 0, Bytes[2], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); - *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); + m_Packets.enqueue( new CCommandPacket( 0, Bytes[2], Bytes.left(Length) ) ); + *RecvBuffer = RecvBuffer->mid( Length ); + Bytes.remove(0, Length); } else return; diff --git a/ghost/bnlsclient.h b/ghost/bnlsclient.h index 9ff5445..eb05647 100644 --- a/ghost/bnlsclient.h +++ b/ghost/bnlsclient.h @@ -36,7 +36,7 @@ class CBNLSClient CBNLSProtocol *m_Protocol; // battle.net protocol QQueue m_Packets; // queue of incoming packets bool m_WasConnected; - string m_Server; + QString m_Server; uint16_t m_Port; uint32_t m_LastNullTime; uint32_t m_WardenCookie; // the warden cookie @@ -46,7 +46,7 @@ class CBNLSClient uint32_t m_TotalWardenOut; public: - CBNLSClient( string nServer, uint16_t nPort, uint32_t nWardenCookie ); + CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCookie ); ~CBNLSClient( ); QByteArray GetWardenResponse( ); diff --git a/ghost/bnlsprotocol.cpp b/ghost/bnlsprotocol.cpp index 9ff30d1..6f9486e 100644 --- a/ghost/bnlsprotocol.cpp +++ b/ghost/bnlsprotocol.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -54,7 +54,7 @@ QByteArray CBNLSProtocol :: RECEIVE_BNLS_WARDEN( QByteArray data ) uint16_t Length = UTIL_QByteArrayToUInt16( data, false, 10 ); if( Result == 0x00 ) - return QByteArray( data.begin( ) + 11, data.end( ) ); + return data.mid(11); else CONSOLE_Print( "[BNLSPROTO] received error code " + UTIL_ToString( data[8] ) ); } @@ -69,8 +69,8 @@ QByteArray CBNLSProtocol :: RECEIVE_BNLS_WARDEN( QByteArray data ) QByteArray CBNLSProtocol :: SEND_BNLS_NULL( ) { QByteArray packet; - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_NULL ); // BNLS_NULL AssignLength( packet ); return packet; @@ -81,15 +81,15 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t see unsigned char Client[] = { 80, 88, 51, 87 }; // "W3XP" QByteArray packet; - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN - packet.push_back( 0 ); // BNLS_WARDEN_SEED + packet.push_back( (char)0 ); // BNLS_WARDEN_SEED UTIL_AppendQByteArray( packet, cookie, false ); // cookie UTIL_AppendQByteArray( packet, Client, 4 ); // Client UTIL_AppendQByteArray( packet, (uint16_t)4, false ); // length of seed UTIL_AppendQByteArray( packet, seed, false ); // seed - packet.push_back( 0 ); // username is blank + packet.push_back( (char)0 ); // username is blank UTIL_AppendQByteArray( packet, (uint16_t)0, false ); // password length // password AssignLength( packet ); @@ -99,8 +99,8 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t see QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray raw ) { QByteArray packet; - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( 1 ); // BNLS_WARDEN_RAW UTIL_AppendQByteArray( packet, cookie, false ); // cookie diff --git a/ghost/config.cpp b/ghost/config.cpp index 5488c28..ccdecd2 100644 --- a/ghost/config.cpp +++ b/ghost/config.cpp @@ -37,21 +37,22 @@ CConfig :: ~CConfig( ) } +#include +#include void CConfig :: Read( QString file ) { - ifstream in; - in.open( file.c_str( ) ); + QFile f(file); - if( in.fail( ) ) + if( !f.open(QFile::ReadOnly) ) CONSOLE_Print( "[CONFIG] warning - unable to read file [" + file + "]" ); else { CONSOLE_Print( "[CONFIG] loading file [" + file + "]" ); QString Line; - while( !in.eof( ) ) + while( !f.atEnd() ) { - getline( in, Line ); + Line = f.readLine(); // ignore blank lines and comments @@ -60,30 +61,20 @@ void CConfig :: Read( QString file ) // remove newlines and partial newlines to help fix issues with Windows formatted config files on Linux systems - Line.erase( remove( Line.begin( ), Line.end( ), '\r' ), Line.end( ) ); - Line.erase( remove( Line.begin( ), Line.end( ), '\n' ), Line.end( ) ); + Line.replace('\r', "").replace('\n', ""); - QString :: size_type Split = Line.find( "=" ); + QStringList parts = Line.split('='); - if( Split == QString :: npos ) - continue; - - QString :: size_type KeyStart = Line.find_first_not_of( " " ); - QString :: size_type KeyEnd = Line.find( " ", KeyStart ); - QString :: size_type ValueStart = Line.find_first_not_of( " ", Split + 1 ); - QString :: size_type ValueEnd = Line.size( ); - - if( ValueStart != QString :: npos ) - m_CFG[Line.mid( KeyStart, KeyEnd - KeyStart )] = Line.mid( ValueStart, ValueEnd - ValueStart ); + m_CFG[parts.at(0).trimmed()] = parts.at(1).trimmed(); } - in.close( ); + f.close( ); } } bool CConfig :: Exists( QString key ) { - return m_CFG.find( key ) != m_CFG.end( ); + return m_CFG.contains(key); } int CConfig :: GetInt( QString key, int x ) @@ -91,7 +82,7 @@ int CConfig :: GetInt( QString key, int x ) if( m_CFG.find( key ) == m_CFG.end( ) ) return x; else - return atoi( m_CFG[key].c_str( ) ); + return m_CFG[key].toInt(); } QString CConfig :: GetString( QString key, QString x ) diff --git a/ghost/config.h b/ghost/config.h index a755974..b34a940 100644 --- a/ghost/config.h +++ b/ghost/config.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -28,17 +28,17 @@ class CConfig { private: - QMap m_CFG; + QMap m_CFG; public: CConfig( ); ~CConfig( ); - void Read( string file ); - bool Exists( string key ); - int GetInt( string key, int x ); - string GetString( string key, string x ); - void Set( string key, string x ); + void Read( QString file ); + bool Exists( QString key ); + int GetInt( QString key, int x ); + QString GetString( QString key, QString x ); + void Set( QString key, QString x ); }; #endif diff --git a/ghost/crc32.cpp b/ghost/crc32.cpp index 510757c..df314d2 100644 --- a/ghost/crc32.cpp +++ b/ghost/crc32.cpp @@ -29,14 +29,14 @@ uint32_t CCRC32 :: Reflect( uint32_t ulReflect, char cChar ) return ulValue; } -uint32_t CCRC32 :: FullCRC( unsigned char *sData, uint32_t ulLength ) +uint32_t CCRC32 :: FullCRC( QString data ) { uint32_t ulCRC = 0xFFFFFFFF; - PartialCRC( &ulCRC, sData, ulLength ); + PartialCRC( &ulCRC, (const unsigned char*)data.toStdString().c_str(), data.toStdString().size() ); return ulCRC ^ 0xFFFFFFFF; } -void CCRC32 :: PartialCRC( uint32_t *ulInCRC, unsigned char *sData, uint32_t ulLength ) +void CCRC32 :: PartialCRC( uint32_t *ulInCRC, const unsigned char *sData, uint32_t ulLength ) { while( ulLength-- ) *ulInCRC = ( *ulInCRC >> 8 ) ^ ulTable[( *ulInCRC & 0xFF ) ^ *sData++]; diff --git a/ghost/crc32.h b/ghost/crc32.h index 00f63ae..a171a7d 100644 --- a/ghost/crc32.h +++ b/ghost/crc32.h @@ -7,8 +7,8 @@ class CCRC32 { public: void Initialize( ); - uint32_t FullCRC( unsigned char *sData, uint32_t ulLength ); - void PartialCRC( uint32_t *ulInCRC, unsigned char *sData, uint32_t ulLength ); + uint32_t FullCRC( QString data ); + void PartialCRC( uint32_t *ulInCRC, const unsigned char *sData, uint32_t ulLength ); private: uint32_t Reflect( uint32_t ulReflect, char cChar ); diff --git a/ghost/csvparser.cpp b/ghost/csvparser.cpp index c174bff..99239ac 100644 --- a/ghost/csvparser.cpp +++ b/ghost/csvparser.cpp @@ -70,7 +70,7 @@ CSVParser & CSVParser::operator >>(int & nOut) sTmp += m_sData[m_nPos++]; m_nPos++; // skip past comma - nOut = atoi(sTmp.c_str()); + nOut = sTmp.toInt(); return *this; } @@ -82,7 +82,7 @@ CSVParser & CSVParser::operator >>(double & nOut) sTmp += m_sData[m_nPos++]; m_nPos++; // skip past comma - nOut = atof(sTmp.c_str()); + nOut = sTmp.toInt(); return *this; } diff --git a/ghost/csvparser.h b/ghost/csvparser.h index 5c414a9..24cbe09 100644 --- a/ghost/csvparser.h +++ b/ghost/csvparser.h @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. +this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the @@ -33,21 +33,20 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -using namespace std; +#include class CSVParser { private: - string m_sData; - string::size_type m_nPos; + QString m_sData; + int m_nPos; void SkipSpaces(void); public: CSVParser(); - const CSVParser & operator << (const string &sIn); + const CSVParser & operator << (const QString &sIn); const CSVParser & operator << (const char *sIn); CSVParser & operator >> (int &nOut); CSVParser & operator >> (double &nOut); - CSVParser & operator >> (string &sOut); + CSVParser & operator >> (QString &sOut); }; #endif diff --git a/ghost/game.cpp b/ghost/game.cpp index d4a2455..6a7768a 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -40,6 +40,11 @@ #include #include +#include +#include +#include +#include + // // sorting classes // @@ -408,23 +413,22 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString Victim; QString Reason; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Victim; - if( !SS.eof( ) ) + if( !SS.atEnd( ) ) { - getline( SS, Reason ); - QString :: size_type Start = Reason.find_first_not_of( " " ); + Reason = SS.readLine(); + int Start = Reason.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Reason = Reason.mid( Start ); } if( m_GameLoaded ) { - QString VictimLower = Victim; - transform( VictimLower.begin( ), VictimLower.end( ), VictimLower.begin( ), (int(*)(int))tolower ); + QString VictimLower = Victim.toLower(); uint32_t Matches = 0; CDBBan *LastMatch = NULL; @@ -433,10 +437,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) { - QString TestName = (*i)->GetName( ); - transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); + QString TestName = (*i)->GetName( ).toLower(); - if( TestName.find( VictimLower ) != QString :: npos ) + if( TestName.indexOf( VictimLower ) != -1 ) { Matches++; LastMatch = *i; @@ -490,22 +493,22 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Interval; QString Message; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Interval; - if( SS.fail( ) || Interval == 0 ) + if( SS.status() != QTextStream::Ok || Interval == 0 ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to announce command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] missing input #2 to announce command" ); else { - getline( SS, Message ); - QString :: size_type Start = Message.find_first_not_of( " " ); + Message = SS.readLine(); + int Start = Message.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Message = Message.mid( Start ); SendAllChat( m_GHost->m_Language->AnnounceMessageEnabled( ) ); @@ -637,15 +640,15 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 - stringstream SS; + QTextStream SS; SS << Payload; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { uint32_t SID; SS >> SID; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) { CONSOLE_Print( "[GAME: " + m_GameName + "] bad input to close command" ); break; @@ -673,18 +676,18 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Skill = 1; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Slot; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to comp command" ); else { - if( !SS.eof( ) ) + if( !SS.atEnd( ) ) SS >> Skill; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #2 to comp command" ); else ComputerSlot( (unsigned char)( Slot - 1 ), (unsigned char)Skill, true ); @@ -702,21 +705,21 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Colour; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Slot; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to compcolour command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] missing input #2 to compcolour command" ); else { SS >> Colour; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #2 to compcolour command" ); else { @@ -743,21 +746,21 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Handicap; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Slot; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to comphandicap command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] missing input #2 to comphandicap command" ); else { SS >> Handicap; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #2 to comphandicap command" ); else { @@ -787,25 +790,24 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; QString Race; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Slot; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to comprace command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] missing input #2 to comprace command" ); else { - getline( SS, Race ); - QString :: size_type Start = Race.find_first_not_of( " " ); + Race = SS.readLine().toLower(); + int Start = Race.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Race = Race.mid( Start ); - transform( Race.begin( ), Race.end( ), Race.begin( ), (int(*)(int))tolower ); unsigned char SID = (unsigned char)( Slot - 1 ); if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) && !( m_Map->GetMapFlags( ) & MAPFLAG_RANDOMRACES ) && SID < m_Slots.size( ) ) @@ -856,21 +858,21 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Team; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Slot; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to compteam command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] missing input #2 to compteam command" ); else { SS >> Team; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #2 to compteam command" ); else { @@ -1028,7 +1030,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { QString HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; - if( Payload.find_first_not_of( HCLChars ) == QString :: npos ) + if( Payload.indexOf( QRegExp("[^" + HCLChars + "]") ) == -1 ) { m_HCLCommandString = Payload; SendAllChat( m_GHost->m_Language->SettingHCL( m_HCLCommandString ) ); @@ -1051,15 +1053,15 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" - stringstream SS; + QTextStream SS; SS << Payload; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { QString HoldName; SS >> HoldName; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) { CONSOLE_Print( "[GAME: " + m_GameName + "] bad input to hold command" ); break; @@ -1193,15 +1195,15 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // open as many slots as specified, e.g. "5 10" opens slots 5 and 10 - stringstream SS; + QTextStream SS; SS << Payload; - while( !SS.eof( ) ) + while( !SS.atEnd( ) ) { uint32_t SID; SS >> SID; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) { CONSOLE_Print( "[GAME: " + m_GameName + "] bad input to open command" ); break; @@ -1414,14 +1416,14 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString IP; uint32_t Port = 6112; - stringstream SS; + QTextStream SS; SS << Payload; SS >> IP; - if( !SS.eof( ) ) + if( !SS.atEnd( ) ) SS >> Port; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad inputs to sendlan command" ); else { @@ -1440,11 +1442,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; QByteArray MapWidth; - MapWidth.push_back( 0 ); - MapWidth.push_back( 0 ); + MapWidth.push_back( (char)0 ); + MapWidth.push_back( (char)0 ); QByteArray MapHeight; - MapHeight.push_back( 0 ); - MapHeight.push_back( 0 ); + MapHeight.push_back( (char)0 ); + MapHeight.push_back( (char)0 ); m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ) ); } else @@ -1496,21 +1498,21 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { uint32_t SID1; uint32_t SID2; - stringstream SS; + QTextStream SS; SS << Payload; SS >> SID1; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #1 to swap command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[GAME: " + m_GameName + "] missing input #2 to swap command" ); else { SS >> SID2; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[GAME: " + m_GameName + "] bad input #2 to swap command" ); else SwapSlots( (unsigned char)( SID1 - 1 ), (unsigned char)( SID2 - 1 ) ); @@ -1624,9 +1626,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString Name; QString Message; - QString :: size_type MessageStart = Payload.find( " " ); + int MessageStart = Payload.indexOf( " " ); - if( MessageStart != QString :: npos ) + if( MessageStart != -1 ) { Name = Payload.mid( 0, MessageStart ); Message = Payload.mid( MessageStart + 1 ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 68bfe55..2a58b26 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -35,6 +35,9 @@ #include "game_admin.h" #include +#include +#include +#include #include @@ -347,11 +350,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Name; - if( SS.eof( ) ) + if( SS.atEnd( ) ) { if( m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); @@ -418,28 +421,28 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, uint32_t MaximumGames; uint32_t AutoStartPlayers; QString GameName; - stringstream SS; + QTextStream SS; SS << Payload; SS >> MaximumGames; - if( SS.fail( ) || MaximumGames == 0 ) + if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) CONSOLE_Print( "[ADMINGAME] bad input #1 to autohost command" ); else { SS >> AutoStartPlayers; - if( SS.fail( ) || AutoStartPlayers == 0 ) + if( SS.status() != QTextStream::Ok || AutoStartPlayers == 0 ) CONSOLE_Print( "[ADMINGAME] bad input #2 to autohost command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[ADMINGAME] missing input #3 to autohost command" ); else { - getline( SS, GameName ); - QString :: size_type Start = GameName.find_first_not_of( " " ); + GameName = SS.readLine( ); + int Start = GameName.indexOf( QRegExp("[^ ]") ); - if( Start != QString :: npos ) + if( Start != -1 ) GameName = GameName.mid( Start ); SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); @@ -489,40 +492,40 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, double MinimumScore; double MaximumScore; QString GameName; - stringstream SS; + QTextStream SS; SS << Payload; SS >> MaximumGames; - if( SS.fail( ) || MaximumGames == 0 ) + if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) CONSOLE_Print( "[ADMINGAME] bad input #1 to autohostmm command" ); else { SS >> AutoStartPlayers; - if( SS.fail( ) || AutoStartPlayers == 0 ) + if( SS.status() != QTextStream::Ok || AutoStartPlayers == 0 ) CONSOLE_Print( "[ADMINGAME] bad input #2 to autohostmm command" ); else { SS >> MinimumScore; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[ADMINGAME] bad input #3 to autohostmm command" ); else { SS >> MaximumScore; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[ADMINGAME] bad input #4 to autohostmm command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[ADMINGAME] missing input #5 to autohostmm command" ); else { - getline( SS, GameName ); - QString :: size_type Start = GameName.find_first_not_of( " " ); + GameName = SS.readLine(); + int Start = GameName.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) GameName = GameName.mid( Start ); SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); @@ -556,11 +559,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Name; - if( SS.eof( ) ) + if( SS.atEnd( ) ) { if( m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); @@ -611,11 +614,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Name; - if( SS.eof( ) ) + if( SS.atEnd( ) ) { if( m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); @@ -697,11 +700,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - stringstream SS; + QTextStream SS; SS << Payload; SS >> Name; - if( SS.eof( ) ) + if( SS.atEnd( ) ) { if( m_GHost->m_BNETs.size( ) == 1 ) Server = m_GHost->m_BNETs[0]->GetServer( ); @@ -822,7 +825,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) + if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) SendChat( player, m_GHost->m_Language->UnableToLoadReplaysOutside( ) ); else { @@ -905,64 +908,40 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); else { - QString FoundMapConfigs; - try { - path MapCFGPath( m_GHost->m_MapCFGPath ); - QString Pattern = Payload; - transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); + QDir MapCFGPath( m_GHost->m_MapCFGPath ); + QString Pattern = Payload.toLower(); - if( !exists( MapCFGPath ) ) + if( !MapCFGPath.exists() ) { CONSOLE_Print( "[ADMINGAME] error listing map configs - map config path doesn't exist" ); SendChat( player, m_GHost->m_Language->ErrorListingMapConfigs( ) ); } else { - directory_iterator EndIterator; - path LastMatch; - uint32_t Matches = 0; - - for( directory_iterator i( MapCFGPath ); i != EndIterator; i++ ) - { - QString FileName = i->filename( ); - QString Stem = i->path( ).stem( ); - transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); - transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - - if( !is_directory( i->status( ) ) && i->path( ).extension( ) == ".cfg" && FileName.find( Pattern ) != QString :: npos ) - { - LastMatch = i->path( ); - Matches++; - - if( FoundMapConfigs.isEmpty( ) ) - FoundMapConfigs = i->filename( ); - else - FoundMapConfigs += ", " + i->filename( ); - - // if the pattern matches the filename exactly, with or without extension, stop any further matching - - if( FileName == Pattern || Stem == Pattern ) - { - Matches = 1; - break; - } - } - } + QStringList files = MapCFGPath.entryList(QStringList("*" + Pattern + "*"), QDir::Files, QDir::Name); + uint32_t Matches = files.size(); if( Matches == 0 ) SendChat( player, m_GHost->m_Language->NoMapConfigsFound( ) ); - else if( Matches == 1 ) + else if (files.contains(Pattern)) + { + SendChat( player, m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ) ); + CConfig MapCFG; + MapCFG.Read( Pattern ); + m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); + } + else if (Matches == 1) { - QString File = LastMatch.filename( ); + QString File = files.at(0); SendChat( player, m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + File ) ); CConfig MapCFG; - MapCFG.Read( LastMatch.QString( ) ); + MapCFG.Read( m_GHost->m_MapCFGPath + File ); m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); } else - SendChat( player, m_GHost->m_Language->FoundMapConfigs( FoundMapConfigs ) ); + SendChat( player, m_GHost->m_Language->FoundMapConfigs( files.join(", ") ) ); } } catch( const exception &ex ) @@ -981,7 +960,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { // only load files in the current directory just to be safe - if( Payload.find( "/" ) != QString :: npos || Payload.find( "\\" ) != QString :: npos ) + if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) SendChat( player, m_GHost->m_Language->UnableToLoadSaveGamesOutside( ) ); else { @@ -1016,57 +995,37 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); else { - QString FoundMaps; - try { - path MapPath( m_GHost->m_MapPath ); - QString Pattern = Payload; - transform( Pattern.begin( ), Pattern.end( ), Pattern.begin( ), (int(*)(int))tolower ); + QDir MapPath( m_GHost->m_MapPath ); + QString Pattern = Payload.toLower(); - if( !exists( MapPath ) ) + if( !MapPath.exists() ) { CONSOLE_Print( "[ADMINGAME] error listing maps - map path doesn't exist" ); SendChat( player, m_GHost->m_Language->ErrorListingMaps( ) ); } else { - directory_iterator EndIterator; - path LastMatch; - uint32_t Matches = 0; + QStringList files = MapPath.entryList(QStringList("*"+Pattern+"*"), QDir::Files, QDir::Name); + uint32_t Matches = files.size(); - for( directory_iterator i( MapPath ); i != EndIterator; i++ ) + if( Matches == 0 ) + SendChat( player, m_GHost->m_Language->NoMapsFound( ) ); + else if (files.contains(Pattern)) { - QString FileName = i->filename( ); - QString Stem = i->path( ).stem( ); - transform( FileName.begin( ), FileName.end( ), FileName.begin( ), (int(*)(int))tolower ); - transform( Stem.begin( ), Stem.end( ), Stem.begin( ), (int(*)(int))tolower ); - - if( !is_directory( i->status( ) ) && FileName.find( Pattern ) != QString :: npos ) - { - LastMatch = i->path( ); - Matches++; - - if( FoundMaps.isEmpty( ) ) - FoundMaps = i->filename( ); - else - FoundMaps += ", " + i->filename( ); + SendChat( player, m_GHost->m_Language->LoadingConfigFile( Pattern ) ); - // if the pattern matches the filename exactly, with or without extension, stop any further matching + // hackhack: create a config file in memory with the required information to load the map - if( FileName == Pattern || Stem == Pattern ) - { - Matches = 1; - break; - } - } + CConfig MapCFG; + MapCFG.Set( "map_path", "Maps\\Download\\" + Pattern ); + MapCFG.Set( "map_localpath", Pattern ); + m_GHost->m_Map->Load( &MapCFG, Pattern ); } - - if( Matches == 0 ) - SendChat( player, m_GHost->m_Language->NoMapsFound( ) ); else if( Matches == 1 ) { - QString File = LastMatch.filename( ); + QString File = files.at(0); SendChat( player, m_GHost->m_Language->LoadingConfigFile( File ) ); // hackhack: create a config file in memory with the required information to load the map @@ -1077,7 +1036,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, m_GHost->m_Map->Load( &MapCFG, File ); } else - SendChat( player, m_GHost->m_Language->FoundMaps( FoundMaps ) ); + SendChat( player, m_GHost->m_Language->FoundMaps( files.join(", ") ) ); } } catch( const exception &ex ) @@ -1106,9 +1065,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Owner; QString GameName; - QString :: size_type GameNameStart = Payload.find( " " ); + int GameNameStart = Payload.indexOf( " " ); - if( GameNameStart != QString :: npos ) + if( GameNameStart != -1 ) { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); @@ -1134,9 +1093,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Owner; QString GameName; - QString :: size_type GameNameStart = Payload.find( " " ); + int GameNameStart = Payload.indexOf( " " ); - if( GameNameStart != QString :: npos ) + if( GameNameStart != -1 ) { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); @@ -1175,22 +1134,22 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, uint32_t GameNumber; QString Message; - stringstream SS; + QTextStream SS; SS << Payload; SS >> GameNumber; - if( SS.fail( ) ) + if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[ADMINGAME] bad input #1 to saygame command" ); else { - if( SS.eof( ) ) + if( SS.atEnd( ) ) CONSOLE_Print( "[ADMINGAME] missing input #2 to saygame command" ); else { - getline( SS, Message ); - QString :: size_type Start = Message.find_first_not_of( " " ); + Message = SS.readLine(); + int Start = Message.indexOf( QRegExp( "[^ ]" )); - if( Start != QString :: npos ) + if( Start != -1 ) Message = Message.mid( Start ); if( GameNumber - 1 < m_GHost->m_Games.size( ) ) @@ -1245,9 +1204,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Message; - QString :: size_type MessageStart = Payload.find( " " ); + int MessageStart = Payload.indexOf( " " ); - if( MessageStart != QString :: npos ) + if( MessageStart != -1 ) { Name = Payload.mid( 0, MessageStart ); Message = Payload.mid( MessageStart + 1 ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 91ea5f2..6060305 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -36,6 +36,10 @@ #include #include #include +#include +#include +#include +#include #include "next_combination.h" @@ -157,19 +161,19 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 if( !m_GHost->m_IPBlackListFile.isEmpty( ) ) { - ifstream in; - in.open( m_GHost->m_IPBlackListFile.c_str( ) ); + QFile f(m_GHost->m_IPBlackListFile); - if( in.fail( ) ) + if( !f.open(QFile::ReadOnly) ) CONSOLE_Print( "[GAME: " + m_GameName + "] error loading IP blacklist file [" + m_GHost->m_IPBlackListFile + "]" ); else { + QTextStream in(&f); CONSOLE_Print( "[GAME: " + m_GameName + "] loading IP blacklist file [" + m_GHost->m_IPBlackListFile + "]" ); QString Line; - while( !in.eof( ) ) + while( !in.atEnd( ) ) { - getline( in, Line ); + Line = in.readLine(); // ignore blank lines and comments @@ -178,19 +182,17 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 // remove newlines and partial newlines to help fix issues with Windows formatted files on Linux systems - Line.erase( remove( Line.begin( ), Line.end( ), ' ' ), Line.end( ) ); - Line.erase( remove( Line.begin( ), Line.end( ), '\r' ), Line.end( ) ); - Line.erase( remove( Line.begin( ), Line.end( ), '\n' ), Line.end( ) ); + Line.replace(QRegExp("[ \r\n]"), ""); // ignore lines that don't look like IP addresses - if( Line.find_first_not_of( "1234567890." ) != QString :: npos ) + if( Line.indexOf( QRegExp("[^0-9\.]") ) != -1 ) continue; m_IPBlackList.insert( Line ); } - in.close( ); + f.close( ); CONSOLE_Print( "[GAME: " + m_GameName + "] loaded " + UTIL_ToString( m_IPBlackList.size( ) ) + " lines from IP blacklist file" ); } @@ -475,11 +477,11 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; QByteArray MapWidth; - MapWidth.push_back( 0 ); - MapWidth.push_back( 0 ); + MapWidth.push_back( (char)0 ); + MapWidth.push_back( (char)0 ); QByteArray MapHeight; - MapHeight.push_back( 0 ); - MapHeight.push_back( 0 ); + MapHeight.push_back( (char)0 ); + MapHeight.push_back( (char)0 ); m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, FixedHostCounter ) ); } else @@ -1214,10 +1216,10 @@ void CBaseGame :: SendVirtualHostPlayerInfo( CGamePlayer *player ) return; QByteArray IP; - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); Send( player, m_Protocol->SEND_W3GS_PLAYERINFO( m_VirtualHostPID, m_VirtualHostName, IP, IP ) ); } @@ -1227,10 +1229,10 @@ void CBaseGame :: SendFakePlayerInfo( CGamePlayer *player ) return; QByteArray IP; - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); Send( player, m_Protocol->SEND_W3GS_PLAYERINFO( m_FakePlayerPID, "FakePlayer", IP, IP ) ); } @@ -1359,10 +1361,9 @@ void CBaseGame :: SendWelcomeMessage( CGamePlayer *player ) { // read from motd.txt if available (thanks to zeeg for this addition) - ifstream in; - in.open( m_GHost->m_MOTDFile.c_str( ) ); + QFile f(m_GHost->m_MOTDFile); - if( in.fail( ) ) + if( !f.open(QFile::ReadOnly) ) { // default welcome message @@ -1383,26 +1384,10 @@ void CBaseGame :: SendWelcomeMessage( CGamePlayer *player ) { // custom welcome message // don't print more than 8 lines + QStringList data = QString::fromUtf8(f.readAll()).replace('\r', "").split('\n'); - uint32_t Count = 0; - QString Line; - - while( !in.eof( ) && Count < 8 ) - { - getline( in, Line ); - - if( Line.isEmpty( ) ) - { - if( !in.eof( ) ) - SendChat( player, " " ); - } - else - SendChat( player, Line ); - - Count++; - } - - in.close( ); + for (int i = 0; i < data.size() && i < 8; i++) + SendChat( player, data.at(i) ); } } @@ -1410,32 +1395,15 @@ void CBaseGame :: SendEndMessage( ) { // read from gameover.txt if available - ifstream in; - in.open( m_GHost->m_GameOverFile.c_str( ) ); + QFile f(m_GHost->m_GameOverFile); - if( !in.fail( ) ) + if( f.open(QFile::ReadOnly) ) { // don't print more than 8 lines + QStringList data = QString::fromUtf8(f.readAll()).replace('\r', "").split('\n'); - uint32_t Count = 0; - QString Line; - - while( !in.eof( ) && Count < 8 ) - { - getline( in, Line ); - - if( Line.isEmpty( ) ) - { - if( !in.eof( ) ) - SendAllChat( " " ); - } - else - SendAllChat( Line ); - - Count++; - } - - in.close( ); + for (int i = 0; i < data.size() && i < 8; i++) + SendAllChat( data.at(i) ); } } @@ -2027,10 +1995,10 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP SendFakePlayerInfo( Player ); QByteArray BlankIP; - BlankIP.push_back( 0 ); - BlankIP.push_back( 0 ); - BlankIP.push_back( 0 ); - BlankIP.push_back( 0 ); + BlankIP.push_back( (char)0 ); + BlankIP.push_back( (char)0 ); + BlankIP.push_back( (char)0 ); + BlankIP.push_back( (char)0 ); for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -2082,7 +2050,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP QByteArray UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) - SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( QString( UniqueName.begin( ), UniqueName.end( ) ) ) ); + SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( UniqueName ) ); } } @@ -2400,10 +2368,10 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SendFakePlayerInfo( Player ); QByteArray BlankIP; - BlankIP.push_back( 0 ); - BlankIP.push_back( 0 ); - BlankIP.push_back( 0 ); - BlankIP.push_back( 0 ); + BlankIP.push_back( (char)0 ); + BlankIP.push_back( (char)0 ); + BlankIP.push_back( (char)0 ); + BlankIP.push_back( (char)0 ); for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -2455,7 +2423,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco QByteArray UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) - SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( QString( UniqueName.begin( ), UniqueName.end( ) ) ) ); + SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( UniqueName.end( )) ); } } @@ -2569,10 +2537,7 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) QQueue *LoadInGameData = player->GetLoadInGameData( ); while( !LoadInGameData->empty( ) ) - { - Send( player, LoadInGameData->front( ) ); - LoadInGameData->pop( ); - } + Send( player, LoadInGameData->dequeue( ) ); // start the lag screen for the new player @@ -2618,7 +2583,7 @@ void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *actio // check for players saving the game and notify everyone - if( !action->GetAction( )->empty( ) && (*action->GetAction( ))[0] == 6 ) + if( !action->GetAction( )->isEmpty( ) && (*action->GetAction( ))[0] == 6 ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] is saving the game" ); SendAllChat( m_GHost->m_Language->PlayerIsSavingTheGame( player->GetName( ) ) ); @@ -2682,17 +2647,17 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { - if( (*j).second.size( ) > (*LargestBin).second.size( ) ) + if( j.value().size( ) > LargestBin.value().size( ) ) { LargestBin = j; Tied = false; } - else if( j != LargestBin && (*j).second.size( ) == (*LargestBin).second.size( ) ) + else if( j != LargestBin && j.value().size( ) == LargestBin.value().size( ) ) Tied = true; QString Players; - for( QVector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) + for( QVector :: iterator k = j.value().begin( ); k != j.value().end( ); k++ ) { CGamePlayer *Player = GetPlayerFromPID( *k ); @@ -2709,7 +2674,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) StateNumber++; } - FirstCheckSum = (*LargestBin).first; + FirstCheckSum = LargestBin.key(); if( Tied ) { @@ -2735,9 +2700,9 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) // the most common case will be 9v1 (e.g. one player desynced and the others were unaffected) and this will kick the single outlier // another (very unlikely) possibility is 8v1v1 or 8v2 and this will kick both of the outliers, regardless of whether their game states match - if( (*j).first != (*LargestBin).first ) + if( j.key() != LargestBin.key() ) { - for( QVector :: iterator k = (*j).second.begin( ); k != (*j).second.end( ); k++ ) + for( QVector :: iterator k = j.value().begin( ); k != j.value().end( ); k++ ) { CGamePlayer *Player = GetPlayerFromPID( *k ); @@ -2761,7 +2726,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetDeleteMe( ) ) - (*i)->GetCheckSums( )->pop( ); + (*i)->GetCheckSums( )->dequeue( ); } // add checksum to replay @@ -2845,9 +2810,9 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye QString Command; QString Payload; - QString :: size_type PayloadStart = Message.find( " " ); + int PayloadStart = Message.indexOf( ' ' ); - if( PayloadStart != QString :: npos ) + if( PayloadStart != -1 ) { Command = Message.mid( 1, PayloadStart - 1 ); Payload = Message.mid( PayloadStart + 1 ); @@ -2855,7 +2820,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye else Command = Message.mid( 1 ); - transform( Command.begin( ), Command.end( ), Command.begin( ), (int(*)(int))tolower ); + Command = Command.toLower(); // don't allow EventPlayerBotCommand to veto a previous instruction to set Relay to false // so if Relay is already false (e.g. because the player is muted) then it cannot be forced back to true here @@ -3065,7 +3030,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map { QString *MapData = m_Map->GetMapData( ); - if( !MapData->empty( ) ) + if( !MapData->isEmpty( ) ) { if( m_GHost->m_AllowDownloads == 1 || ( m_GHost->m_AllowDownloads == 2 && player->GetDownloadAllowed( ) ) ) { @@ -3196,7 +3161,7 @@ void CBaseGame :: EventGameStarted( ) { QString HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; - if( m_HCLCommandString.find_first_not_of( HCLChars ) == QString :: npos ) + if( m_HCLCommandString.indexOf( QRegExp( "[^" + HCLChars + "]" ) ) == -1 ) { unsigned char EncodingMap[256]; unsigned char j = 0; @@ -3219,7 +3184,7 @@ void CBaseGame :: EventGameStarted( ) CurrentSlot++; unsigned char HandicapIndex = ( m_Slots[CurrentSlot].GetHandicap( ) - 50 ) / 10; - unsigned char CharIndex = HCLChars.find( *si ); + unsigned char CharIndex = HCLChars.indexOf( *si ); m_Slots[CurrentSlot++].SetHandicap( EncodingMap[HandicapIndex + CharIndex * 6] ); } @@ -3329,16 +3294,16 @@ void CBaseGame :: EventGameStarted( ) QByteArray StatString; UTIL_AppendQByteArray( StatString, m_Map->GetMapGameFlags( ) ); - StatString.push_back( 0 ); + StatString.push_back( (char)0 ); UTIL_AppendQByteArray( StatString, m_Map->GetMapWidth( ) ); UTIL_AppendQByteArray( StatString, m_Map->GetMapHeight( ) ); UTIL_AppendQByteArray( StatString, m_Map->GetMapCRC( ) ); UTIL_AppendQByteArray( StatString, m_Map->GetMapPath( ) ); UTIL_AppendQByteArray( StatString, "GHost++" ); - StatString.push_back( 0 ); + StatString.push_back( (char)0 ); UTIL_AppendQByteArray( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing StatString = UTIL_EncodeStatString( StatString ); - m_StatString = QString( StatString.begin( ), StatString.end( ) ); + m_StatString = StatString; // delete the map data @@ -3401,32 +3366,15 @@ void CBaseGame :: EventGameLoaded( ) // read from gameloaded.txt if available - ifstream in; - in.open( m_GHost->m_GameLoadedFile.c_str( ) ); + QFile f(m_GHost->m_GameLoadedFile); - if( !in.fail( ) ) + if( f.open(QFile::ReadOnly) ) { // don't print more than 8 lines - uint32_t Count = 0; - QString Line; - - while( !in.eof( ) && Count < 8 ) - { - getline( in, Line ); - - if( Line.isEmpty( ) ) - { - if( !in.eof( ) ) - SendAllChat( " " ); - } - else - SendAllChat( Line ); - - Count++; - } - - in.close( ); + QStringList data = QString::fromUtf8(f.readAll()).replace('\r', "").split('\n'); + for (int i = 0; i < 8 && i < data.size(); i++) + SendAllChat(data.at(i)); } } @@ -3466,7 +3414,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromSID( unsigned char SID ) CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) { if( !sensitive ) - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -3475,7 +3423,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) QString TestName = (*i)->GetName( ); if( !sensitive ) - transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); + TestName = TestName.toLower(); if( TestName == name ) return *i; @@ -3487,7 +3435,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) uint32_t CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **player ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); uint32_t Matches = 0; *player = NULL; @@ -3497,10 +3445,9 @@ uint32_t CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **play { if( !(*i)->GetLeftMessageSent( ) ) { - QString TestName = (*i)->GetName( ); - transform( TestName.begin( ), TestName.end( ), TestName.begin( ), (int(*)(int))tolower ); + QString TestName = (*i)->GetName( ).toLower(); - if( TestName.find( name ) != QString :: npos ) + if( TestName.indexOf( name ) != -1 ) { Matches++; *player = *i; @@ -4043,13 +3990,14 @@ QVector CBaseGame :: BalanceSlotsRecursive( QVector BestSubOrdering = BalanceSlotsRecursive( QVector( PlayerIDs.begin( ) + Mid, PlayerIDs.end( ) ), TeamSizes, PlayerScores, i + 1 ); + QVector BestSubOrdering = BalanceSlotsRecursive( PlayerIDs.mid(Mid), TeamSizes, PlayerScores, i + 1 ); // BestSubOrdering now contains the best ordering of all the remaining players (the "right team") given this particular combination of players into two "teams" // in order to calculate the largest difference in total scores we need to recombine the subordering with the first team - QVector TestOrdering = QVector( PlayerIDs.begin( ), PlayerIDs.begin( ) + Mid ); - TestOrdering.insert( TestOrdering.end( ), BestSubOrdering.begin( ), BestSubOrdering.end( ) ); + QVector TestOrdering = PlayerIDs.mid(0, Mid); + for (int k = 0; k < BestSubOrdering.size(); k++) + TestOrdering.push_back(BestSubOrdering.at(k)); // now calculate the team scores for all the teams that we know about (e.g. on subsequent recursion steps this will NOT be every possible team) @@ -4278,7 +4226,7 @@ void CBaseGame :: AddToSpoofed( QString server, QString name, bool sendMessage ) void CBaseGame :: AddToReserved( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); // check that the user is not already reserved @@ -4294,8 +4242,7 @@ void CBaseGame :: AddToReserved( QString name ) for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - QString NameLower = (*i)->GetName( ); - transform( NameLower.begin( ), NameLower.end( ), NameLower.begin( ), (int(*)(int))tolower ); + QString NameLower = (*i)->GetName( ).toLower(); if( NameLower == name ) (*i)->SetReserved( true ); @@ -4304,15 +4251,13 @@ void CBaseGame :: AddToReserved( QString name ) bool CBaseGame :: IsOwner( QString name ) { - QString OwnerLower = m_OwnerName; - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - transform( OwnerLower.begin( ), OwnerLower.end( ), OwnerLower.begin( ), (int(*)(int))tolower ); - return name == OwnerLower; + QString OwnerLower = m_OwnerName.toLower(); + return name.toLower() == OwnerLower; } bool CBaseGame :: IsReserved( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); for( QVector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { @@ -4565,10 +4510,10 @@ void CBaseGame :: CreateVirtualHost( ) m_VirtualHostPID = GetNewPID( ); QByteArray IP; - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); SendAll( m_Protocol->SEND_W3GS_PLAYERINFO( m_VirtualHostPID, m_VirtualHostName, IP, IP ) ); } @@ -4595,10 +4540,10 @@ void CBaseGame :: CreateFakePlayer( ) m_FakePlayerPID = GetNewPID( ); QByteArray IP; - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); - IP.push_back( 0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); + IP.push_back( (char)0 ); SendAll( m_Protocol->SEND_W3GS_PLAYERINFO( m_FakePlayerPID, "FakePlayer", IP, IP ) ); m_Slots[SID] = CGameSlot( m_FakePlayerPID, 100, SLOTSTATUS_OCCUPIED, 0, m_Slots[SID].GetTeam( ), m_Slots[SID].GetColour( ), m_Slots[SID].GetRace( ) ); SendAllSlotInfo( ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 386fd43..25d26c9 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -102,7 +102,7 @@ void CPotentialPlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = RecvBuffer->toUtf8(); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -118,9 +118,9 @@ void CPotentialPlayer :: ExtractPackets( ) { if( Bytes.size( ) >= Length ) { - m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); - *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); + m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], Bytes.mid(0, Length) ) ); + *RecvBuffer = RecvBuffer->mid( Length ); + Bytes = Bytes.mid(Length); } else return; @@ -293,12 +293,11 @@ QString CGamePlayer :: GetNameTerminated( ) // if the player's name contains an unterminated colour code add the colour terminator to the end of their name // this is useful because it allows you to print the player's name in a longer message which doesn't colour all the subsequent text - QString LowerName = m_Name; - transform( LowerName.begin( ), LowerName.end( ), LowerName.begin( ), (int(*)(int))tolower ); - QString :: size_type Start = LowerName.find( "|c" ); - QString :: size_type End = LowerName.find( "|r" ); + QString LowerName = m_Name.toLower(); + int Start = LowerName.indexOf( "|c" ); + int End = LowerName.indexOf( "|r" ); - if( Start != QString :: npos && ( End == QString :: npos || End < Start ) ) + if( Start != -1 && ( End == -1 || End < Start ) ) return m_Name + "|r"; else return m_Name; @@ -406,7 +405,7 @@ void CGamePlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = RecvBuffer->toUtf8(); // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes @@ -422,13 +421,13 @@ void CGamePlayer :: ExtractPackets( ) { if( Bytes.size( ) >= Length ) { - m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], QByteArray( Bytes.begin( ), Bytes.begin( ) + Length ) ) ); + m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], Bytes.mid(0, Length) ) ); if( Bytes[0] == W3GS_HEADER_CONSTANT ) m_TotalPacketsReceived++; - *RecvBuffer = RecvBuffer->substr( Length ); - Bytes = QByteArray( Bytes.begin( ) + Length, Bytes.end( ) ); + *RecvBuffer = RecvBuffer->mid( Length ); + Bytes.remove(0, Length); } else return; diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 19f7dca..6b43f3e 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -68,8 +68,8 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) if( !Name.isEmpty( ) && data.size( ) >= Name.size( ) + 30 ) { - QByteArray InternalIP = QByteArray( data.begin( ) + Name.size( ) + 26, data.begin( ) + Name.size( ) + 30 ); - return new CIncomingJoinPlayer( HostCounter, QString( Name.begin( ), Name.end( ) ), InternalIP ); + QByteArray InternalIP = data.mid(Name.size() + 26, 4); + return new CIncomingJoinPlayer( HostCounter, Name, InternalIP ); } } @@ -117,8 +117,8 @@ CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, if( PID != 255 && ValidateLength( data ) && data.size( ) >= 8 ) { - QByteArray CRC = QByteArray( data.begin( ) + 4, data.begin( ) + 8 ); - QByteArray Action = QByteArray( data.begin( ) + 8, data.end( ) ); + QByteArray CRC = data.mid(4, 4); + QByteArray Action = data.mid(8); return new CIncomingAction( PID, CRC, Action ); } @@ -174,7 +174,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data if( Total > 0 && data.size( ) >= i + Total ) { - QByteArray ToPIDs = QByteArray( data.begin( ) + i, data.begin( ) + i + Total ); + QByteArray ToPIDs = data.mid(i, Total ); i += Total; unsigned char FromPID = data[i]; unsigned char Flag = data[i + 1]; @@ -185,7 +185,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data // chat message QByteArray Message = UTIL_ExtractCString( data, i ); - return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString( Message.begin( ), Message.end( ) ) ); + return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString::fromUtf8(Message) ); } else if( ( Flag >= 17 && Flag <= 20 ) && data.size( ) >= i + 1 ) { @@ -198,9 +198,9 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data { // chat message with extra flags - QByteArray ExtraFlags = QByteArray( data.begin( ) + i, data.begin( ) + i + 4 ); + QByteArray ExtraFlags = data.mid(i, 4); QByteArray Message = UTIL_ExtractCString( data, i + 4 ); - return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString( Message.begin( ), Message.end( ) ), ExtraFlags ); + return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString::fromUtf8(Message), ExtraFlags ); } } } @@ -300,8 +300,8 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_PING_FROM_HOST ); // W3GS_PING_FROM_HOST - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, GetTicks( ), false ); // ping value AssignLength( packet ); // DEBUG_Print( "SENT W3GS_PING_FROM_HOST" ); @@ -309,24 +309,24 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; - QByteArray SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); + QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; if( port.size( ) == 2 && externalIP.size( ) == 4 ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_SLOTINFOJOIN ); // W3GS_SLOTINFOJOIN - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length UTIL_AppendQByteArrayFast( packet, SlotInfo ); // SlotInfo packet.push_back( PID ); // PID packet.push_back( 2 ); // AF_INET - packet.push_back( 0 ); // AF_INET continued... + packet.push_back( (char)0 ); // AF_INET continued... UTIL_AppendQByteArray( packet, port ); // port UTIL_AppendQByteArrayFast( packet, externalIP ); // external IP UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? @@ -346,8 +346,8 @@ QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( uint32_t reason ) QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_REJECTJOIN ); // W3GS_REJECTJOIN - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, reason, false ); // reason AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REJECTJOIN" ); @@ -366,24 +366,24 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString nam { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_PLAYERINFO ); // W3GS_PLAYERINFO - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, PlayerJoinCounter, 4 ); // player join counter packet.push_back( PID ); // PID UTIL_AppendQByteArrayFast( packet, name ); // player name packet.push_back( 1 ); // ??? - packet.push_back( 0 ); // ??? + packet.push_back( (char)0 ); // ??? packet.push_back( 2 ); // AF_INET - packet.push_back( 0 ); // AF_INET continued... - packet.push_back( 0 ); // port - packet.push_back( 0 ); // port continued... + packet.push_back( (char)0 ); // AF_INET continued... + packet.push_back( (char)0 ); // port + packet.push_back( (char)0 ); // port continued... UTIL_AppendQByteArrayFast( packet, externalIP ); // external IP UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? packet.push_back( 2 ); // AF_INET - packet.push_back( 0 ); // AF_INET continued... - packet.push_back( 0 ); // port - packet.push_back( 0 ); // port continued... + packet.push_back( (char)0 ); // AF_INET continued... + packet.push_back( (char)0 ); // port + packet.push_back( (char)0 ); // port continued... UTIL_AppendQByteArrayFast( packet, internalIP ); // internal IP UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? @@ -405,8 +405,8 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uin { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_PLAYERLEAVE_OTHERS ); // W3GS_PLAYERLEAVE_OTHERS - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( PID ); // PID UTIL_AppendQByteArray( packet, leftCode, false ); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) AssignLength( packet ); @@ -427,8 +427,8 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_GAMELOADED_OTHERS ); // W3GS_GAMELOADED_OTHERS - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( PID ); // PID AssignLength( packet ); } @@ -440,14 +440,14 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { - QByteArray SlotInfo = EncodeSlotInfo( slots, randomSeed, layoutStyle, playerSlots ); + QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_SLOTINFO ); // W3GS_SLOTINFO - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length UTIL_AppendQByteArrayFast( packet, SlotInfo ); // SlotInfo AssignLength( packet ); @@ -461,8 +461,8 @@ QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_START( ) QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_COUNTDOWN_START ); // W3GS_COUNTDOWN_START - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later AssignLength( packet ); // DEBUG_Print( "SENT W3GS_COUNTDOWN_START" ); // DEBUG_Print( packet ); @@ -474,8 +474,8 @@ QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_COUNTDOWN_END ); // W3GS_COUNTDOWN_END - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later AssignLength( packet ); // DEBUG_Print( "SENT W3GS_COUNTDOWN_END" ); // DEBUG_Print( packet ); @@ -487,8 +487,8 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_INCOMING_ACTION ); // W3GS_INCOMING_ACTION - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, sendInterval, false ); // send interval // create subpacket @@ -508,7 +508,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue // calculate crc (we only care about the first 2 bytes though) - QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)QString( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false ); + QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( subpacket ), false ); crc32.resize( 2 ); // finish subpacket @@ -531,8 +531,8 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_CHAT_FROM_HOST ); // W3GS_CHAT_FROM_HOST - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( toPIDs.size( ) ); // number of receivers UTIL_AppendQByteArrayFast( packet, toPIDs ); // receivers packet.push_back( fromPID ); // sender @@ -573,8 +573,8 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_START_LAG ); // W3GS_START_LAG - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( NumLaggers ); for( QVector :: iterator i = players.begin( ); i != players.end( ); i++ ) @@ -612,8 +612,8 @@ QByteArray CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadIn QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_STOP_LAG ); // W3GS_STOP_LAG - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( player->GetPID( ) ); if( loadInGame ) @@ -637,8 +637,8 @@ QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Ve QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_SEARCHGAME ); // W3GS_SEARCHGAME - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) @@ -669,21 +669,21 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers QByteArray StatString; UTIL_AppendQByteArrayFast( StatString, mapFlags ); - StatString.push_back( 0 ); + StatString.push_back( (char)0 ); UTIL_AppendQByteArrayFast( StatString, mapWidth ); UTIL_AppendQByteArrayFast( StatString, mapHeight ); UTIL_AppendQByteArrayFast( StatString, mapCRC ); UTIL_AppendQByteArrayFast( StatString, mapPath ); UTIL_AppendQByteArrayFast( StatString, hostName ); - StatString.push_back( 0 ); + StatString.push_back( (char)0 ); StatString = UTIL_EncodeStatString( StatString ); // make the rest of the packet packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_GAMEINFO ); // W3GS_GAMEINFO - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) @@ -694,9 +694,9 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers UTIL_AppendQByteArray( packet, hostCounter, false ); // Host Counter UTIL_AppendQByteArray( packet, Unknown1, 4 ); // ??? (this varies wildly even between two identical games created one after another) UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name - packet.push_back( 0 ); // ??? (maybe game password) + packet.push_back( (char)0 ); // ??? (maybe game password) UTIL_AppendQByteArrayFast( packet, StatString ); // Stat String - packet.push_back( 0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) + packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) UTIL_AppendQByteArray( packet, slotsTotal, false ); // Slots Total UTIL_AppendQByteArrayFast( packet, mapGameType ); // Game Type UTIL_AppendQByteArray( packet, Unknown2, 4 ); // ??? @@ -723,8 +723,8 @@ QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Ve QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_CREATEGAME ); // W3GS_CREATEGAME - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) @@ -746,8 +746,8 @@ QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t pl QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_REFRESHGAME ); // W3GS_REFRESHGAME - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter UTIL_AppendQByteArray( packet, players, false ); // Players UTIL_AppendQByteArray( packet, playerSlots, false ); // Player Slots @@ -764,8 +764,8 @@ QByteArray CGameProtocol :: SEND_W3GS_DECREATEGAME( ) QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_DECREATEGAME ); // W3GS_DECREATEGAME - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_DECREATEGAME" ); @@ -783,8 +783,8 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapS { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_MAPCHECK ); // W3GS_MAPCHECK - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? UTIL_AppendQByteArrayFast( packet, mapPath ); // map path UTIL_AppendQByteArrayFast( packet, mapSize ); // map size @@ -808,8 +808,8 @@ QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_STARTDOWNLOAD ); // W3GS_STARTDOWNLOAD - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? packet.push_back( fromPID ); // from PID AssignLength( packet ); @@ -828,8 +828,8 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_MAPPART ); // W3GS_MAPPART - packet.push_back( 0 ); // packet length will be assigned later - packet.push_back( 0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( toPID ); // to PID packet.push_back( fromPID ); // from PID UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? @@ -844,12 +844,12 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c // calculate crc - QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( (unsigned char *)mapData->c_str( ) + start, End - start ), false ); + QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( mapData->mid(start, End - start) ), false ); UTIL_AppendQByteArrayFast( packet, crc32 ); // map data - QByteArray Data = UTIL_CreateQByteArray( (unsigned char *)mapData->c_str( ) + start, End - start ); + QByteArray Data = mapData->mid(start, End - start).toUtf8(); UTIL_AppendQByteArrayFast( packet, Data ); AssignLength( packet ); } @@ -866,10 +866,10 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueuem_CRC->FullCRC( (unsigned char *)QString( subpacket.begin( ), subpacket.end( ) ).c_str( ), subpacket.size( ) ), false ); + QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC(subpacket), false ); crc32.resize( 2 ); // finish subpacket @@ -944,13 +944,13 @@ bool CGameProtocol :: ValidateLength( QByteArray &content ) return false; } -QByteArray CGameProtocol :: EncodeSlotInfo( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo; - SlotInfo.push_back( (unsigned char)slots.size( ) ); // number of slots + SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots - for( unsigned int i = 0; i < slots.size( ); i++ ) - UTIL_AppendQByteArray( SlotInfo, slots[i].GetQByteArray( ) ); + for( unsigned int i = 0; i < lslots.size( ); i++ ) + UTIL_AppendQByteArray( SlotInfo, lslots[i].GetQByteArray( ) ); UTIL_AppendQByteArray( SlotInfo, randomSeed, false ); // random seed SlotInfo.push_back( layoutStyle ); // LayoutStyle (0 = melee, 1 = custom forces, 3 = custom forces + fixed player settings) diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index 59339d1..d0d0909 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -122,24 +122,24 @@ class CGameProtocol QByteArray SEND_W3GS_PING_FROM_HOST( ); QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_REJECTJOIN( uint32_t reason ); - QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, string name, QByteArray externalIP, QByteArray internalIP ); + QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ); QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ); QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); QByteArray SEND_W3GS_SLOTINFO( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_COUNTDOWN_START( ); QByteArray SEND_W3GS_COUNTDOWN_END( ); QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, uint16_t sendInterval ); - QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, string message ); + QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, QString message ); QByteArray SEND_W3GS_START_LAG( QVector players, bool loadInGame = false ); QByteArray SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); QByteArray SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); - QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, string gameName, string hostName, uint32_t upTime, string mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ); + QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ); QByteArray SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ); QByteArray SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ); QByteArray SEND_W3GS_DECREATEGAME( ); - QByteArray SEND_W3GS_MAPCHECK( string mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); + QByteArray SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); QByteArray SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); - QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, string *mapData ); + QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, QString *mapData ); QByteArray SEND_W3GS_INCOMING_ACTION2( QQueue actions ); // other functions @@ -158,15 +158,15 @@ class CIncomingJoinPlayer { private: uint32_t m_HostCounter; - string m_Name; + QString m_Name; QByteArray m_InternalIP; public: - CIncomingJoinPlayer( uint32_t nHostCounter, string nName, QByteArray &nInternalIP ); + CIncomingJoinPlayer( uint32_t nHostCounter, QString nName, QByteArray &nInternalIP ); ~CIncomingJoinPlayer( ); uint32_t GetHostCounter( ) { return m_HostCounter; } - string GetName( ) { return m_Name; } + QString GetName( ) { return m_Name; } QByteArray GetInternalIP( ) { return m_InternalIP; } }; @@ -213,13 +213,13 @@ class CIncomingChatPlayer unsigned char m_FromPID; QByteArray m_ToPIDs; unsigned char m_Flag; - string m_Message; + QString m_Message; unsigned char m_Byte; QByteArray m_ExtraFlags; public: - CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, string nMessage ); - CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, string nMessage, QByteArray &nExtraFlags ); + CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage ); + CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage, QByteArray &nExtraFlags ); CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ); ~CIncomingChatPlayer( ); @@ -227,7 +227,7 @@ class CIncomingChatPlayer unsigned char GetFromPID( ) { return m_FromPID; } QByteArray GetToPIDs( ) { return m_ToPIDs; } unsigned char GetFlag( ) { return m_Flag; } - string GetMessage( ) { return m_Message; } + QString GetMessage( ) { return m_Message; } unsigned char GetByte( ) { return m_Byte; } QByteArray GetExtraFlags( ) { return m_ExtraFlags; } }; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 671da0f..14bfe43 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -42,6 +42,8 @@ #include #include +#include +#include #ifdef WIN32 #include // for WSAIoctl @@ -275,7 +277,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) #endif } - m_BNETs.push_back( new CBNET( this, Server, ServerAlias, BNLSServer, (uint16_t)BNLSPort, (uint32_t)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger[0], HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ) ); + m_BNETs.push_back( new CBNET( this, Server, ServerAlias, BNLSServer, (uint16_t)BNLSPort, (uint32_t)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger.at(0).toAscii(), HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ) ); } if( m_BNETs.isEmpty( ) ) @@ -676,7 +678,7 @@ bool CGHost :: Update( long usecBlock ) (*i)->DoRecv( &fd ); QString *RecvBuffer = (*i)->GetBytes( ); - QByteArray Bytes = UTIL_CreateQByteArray( (unsigned char *)RecvBuffer->c_str( ), RecvBuffer->size( ) ); + QByteArray Bytes = RecvBuffer->toUtf8(); // a packet is at least 4 bytes @@ -720,7 +722,7 @@ bool CGHost :: Update( long usecBlock ) { // reconnect successful! - *RecvBuffer = RecvBuffer->substr( Length ); + *RecvBuffer = RecvBuffer->mid( Length ); Match->EventGProxyReconnect( *i, LastPacket ); i = m_ReconnectSockets.erase( i ); continue; @@ -1001,7 +1003,7 @@ void CGHost :: SetConfigs( CConfig *CFG ) if( BotCommandTrigger.isEmpty( ) ) BotCommandTrigger = "!"; - m_CommandTrigger = BotCommandTrigger[0]; + m_CommandTrigger = BotCommandTrigger[0].toAscii(); m_MapCFGPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mapcfgpath", QString( ) ) ); m_SaveGamePath = UTIL_AddPathSeperator( CFG->GetString( "bot_savegamepath", QString( ) ) ); m_MapPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mappath", QString( ) ) ); @@ -1056,7 +1058,7 @@ void CGHost :: ExtractScripts( ) QString PatchMPQFileName = m_Warcraft3Path + "War3Patch.mpq"; HANDLE PatchMPQ; - if( SFileOpenArchive( PatchMPQFileName.c_str( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &PatchMPQ ) ) + if( SFileOpenArchive( (char*)PatchMPQFileName.data( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &PatchMPQ ) ) { CONSOLE_Print( "[GHOST] loading MPQ file [" + PatchMPQFileName + "]" ); HANDLE SubFile; @@ -1075,7 +1077,7 @@ void CGHost :: ExtractScripts( ) if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) ) { CONSOLE_Print( "[GHOST] extracting Scripts\\common.j from MPQ file to [" + m_MapCFGPath + "common.j]" ); - UTIL_FileWrite( m_MapCFGPath + "common.j", (unsigned char *)SubFileData, BytesRead ); + UTIL_FileWrite( m_MapCFGPath + "common.j", QByteArray(SubFileData, BytesRead) ); } else CONSOLE_Print( "[GHOST] warning - unable to extract Scripts\\common.j from MPQ file" ); @@ -1102,7 +1104,7 @@ void CGHost :: ExtractScripts( ) if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) ) { CONSOLE_Print( "[GHOST] extracting Scripts\\blizzard.j from MPQ file to [" + m_MapCFGPath + "blizzard.j]" ); - UTIL_FileWrite( m_MapCFGPath + "blizzard.j", (unsigned char *)SubFileData, BytesRead ); + UTIL_FileWrite( m_MapCFGPath + "blizzard.j", QByteArray(SubFileData, BytesRead) ); } else CONSOLE_Print( "[GHOST] warning - unable to extract Scripts\\blizzard.j from MPQ file" ); @@ -1123,10 +1125,11 @@ void CGHost :: ExtractScripts( ) void CGHost :: LoadIPToCountryData( ) { - ifstream in; - in.open( "ip-to-country.csv" ); + QFile f("ip-to-country.csv"); + f.open(QFile::ReadOnly); + QTextStream in(&f); - if( in.fail( ) ) + if( f.error() != QFile::NoError ) CONSOLE_Print( "[GHOST] warning - unable to read file [ip-to-country.csv], iptocountry data not loaded" ); else { @@ -1149,13 +1152,11 @@ void CGHost :: LoadIPToCountryData( ) // get length of file for the progress meter - in.seekg( 0, ios :: end ); - uint32_t FileLength = in.tellg( ); - in.seekg( 0, ios :: beg ); + uint32_t FileLength = f.size(); - while( !in.eof( ) ) + while( !in.atEnd( ) ) { - getline( in, Line ); + Line = in.readLine(); if( Line.isEmpty( ) ) continue; @@ -1169,7 +1170,7 @@ void CGHost :: LoadIPToCountryData( ) // it's probably going to take awhile to load the iptocountry data (~10 seconds on my 3.2 GHz P4 when using SQLite3) // so let's print a progress meter just to keep the user from getting worried - unsigned char NewPercent = (unsigned char)( (float)in.tellg( ) / FileLength * 100 ); + unsigned char NewPercent = (unsigned char)( (float)f.pos() / FileLength * 100 ); if( NewPercent != Percent && NewPercent % 10 == 0 ) { @@ -1184,7 +1185,7 @@ void CGHost :: LoadIPToCountryData( ) CONSOLE_Print( "[GHOST] finished loading [ip-to-country.csv]" ); } - in.close( ); + f.close( ); } } @@ -1248,10 +1249,9 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS return; } - QString MapPath1 = m_SaveGame->GetMapPath( ); + QString MapPath1 = m_SaveGame->GetMapPath( ).toLower(); QString MapPath2 = map->GetMapPath( ); - transform( MapPath1.begin( ), MapPath1.end( ), MapPath1.begin( ), (int(*)(int))tolower ); - transform( MapPath2.begin( ), MapPath2.end( ), MapPath2.begin( ), (int(*)(int))tolower ); + MapPath2 = MapPath2.toLower(); if( MapPath1 != MapPath2 ) { diff --git a/ghost/ghostdbmysql.h b/ghost/ghostdbmysql.h index e1dec30..41307b9 100644 --- a/ghost/ghostdbmysql.h +++ b/ghost/ghostdbmysql.h @@ -167,10 +167,10 @@ CREATE TABLE w3mmdvars ( class CGHostDBMySQL : public CGHostDB { private: - string m_Server; - string m_Database; - string m_User; - string m_Password; + QString m_Server; + QString m_Database; + QString m_User; + QString m_Password; uint16_t m_Port; uint32_t m_BotID; QQueue m_IdleConnections; @@ -181,33 +181,33 @@ class CGHostDBMySQL : public CGHostDB CGHostDBMySQL( CConfig *CFG ); virtual ~CGHostDBMySQL( ); - virtual string GetStatus( ); + virtual QString GetStatus( ); virtual void RecoverCallable( CBaseCallable *callable ); // threaded database functions virtual void CreateThread( CBaseCallable *callable ); - virtual CCallableAdminCount *ThreadedAdminCount( string server ); - virtual CCallableAdminCheck *ThreadedAdminCheck( string server, string user ); - virtual CCallableAdminAdd *ThreadedAdminAdd( string server, string user ); - virtual CCallableAdminRemove *ThreadedAdminRemove( string server, string user ); - virtual CCallableAdminList *ThreadedAdminList( string server ); - virtual CCallableBanCount *ThreadedBanCount( string server ); - virtual CCallableBanCheck *ThreadedBanCheck( string server, string user, string ip ); - virtual CCallableBanAdd *ThreadedBanAdd( string server, string user, string ip, string gamename, string admin, string reason ); - virtual CCallableBanRemove *ThreadedBanRemove( string server, string user ); - virtual CCallableBanRemove *ThreadedBanRemove( string user ); - virtual CCallableBanList *ThreadedBanList( string server ); - virtual CCallableGameAdd *ThreadedGameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); - virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); - virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( string name ); + virtual CCallableAdminCount *ThreadedAdminCount( QString server ); + virtual CCallableAdminCheck *ThreadedAdminCheck( QString server, QString user ); + virtual CCallableAdminAdd *ThreadedAdminAdd( QString server, QString user ); + virtual CCallableAdminRemove *ThreadedAdminRemove( QString server, QString user ); + virtual CCallableAdminList *ThreadedAdminList( QString server ); + virtual CCallableBanCount *ThreadedBanCount( QString server ); + virtual CCallableBanCheck *ThreadedBanCheck( QString server, QString user, QString ip ); + virtual CCallableBanAdd *ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); + virtual CCallableBanRemove *ThreadedBanRemove( QString server, QString user ); + virtual CCallableBanRemove *ThreadedBanRemove( QString user ); + virtual CCallableBanList *ThreadedBanList( QString server ); + virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); + virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( QString name ); virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( string name ); - virtual CCallableDownloadAdd *ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); - virtual CCallableScoreCheck *ThreadedScoreCheck( string category, string name, string server ); - virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); + virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); + virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual CCallableScoreCheck *ThreadedScoreCheck( QString category, QString name, QString server ); + virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); @@ -221,29 +221,29 @@ class CGHostDBMySQL : public CGHostDB // global helper functions // -uint32_t MySQLAdminCount( void *conn, string *error, uint32_t botid, string server ); -bool MySQLAdminCheck( void *conn, string *error, uint32_t botid, string server, string user ); -bool MySQLAdminAdd( void *conn, string *error, uint32_t botid, string server, string user ); -bool MySQLAdminRemove( void *conn, string *error, uint32_t botid, string server, string user ); -QVector MySQLAdminList( void *conn, string *error, uint32_t botid, string server ); -uint32_t MySQLBanCount( void *conn, string *error, uint32_t botid, string server ); -CDBBan *MySQLBanCheck( void *conn, string *error, uint32_t botid, string server, string user, string ip ); -bool MySQLBanAdd( void *conn, string *error, uint32_t botid, string server, string user, string ip, string gamename, string admin, string reason ); -bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string server, string user ); -bool MySQLBanRemove( void *conn, string *error, uint32_t botid, string user ); -QVector MySQLBanList( void *conn, string *error, uint32_t botid, string server ); -uint32_t MySQLGameAdd( void *conn, string *error, uint32_t botid, string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); -uint32_t MySQLGamePlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); -CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, string *error, uint32_t botid, string name ); -uint32_t MySQLDotAGameAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); -uint32_t MySQLDotAPlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); -CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, string *error, uint32_t botid, string name ); -bool MySQLDownloadAdd( void *conn, string *error, uint32_t botid, string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); -double MySQLScoreCheck( void *conn, string *error, uint32_t botid, string category, string name, string server ); -uint32_t MySQLW3MMDPlayerAdd( void *conn, string *error, uint32_t botid, string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, QMap var_ints ); -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, QMap var_reals ); -bool MySQLW3MMDVarAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, QMap var_strings ); +uint32_t MySQLAdminCount( void *conn, QString *error, uint32_t botid, QString server ); +bool MySQLAdminCheck( void *conn, QString *error, uint32_t botid, QString server, QString user ); +bool MySQLAdminAdd( void *conn, QString *error, uint32_t botid, QString server, QString user ); +bool MySQLAdminRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ); +QVector MySQLAdminList( void *conn, QString *error, uint32_t botid, QString server ); +uint32_t MySQLBanCount( void *conn, QString *error, uint32_t botid, QString server ); +CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip ); +bool MySQLBanAdd( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); +bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ); +bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString user ); +QVector MySQLBanList( void *conn, QString *error, uint32_t botid, QString server ); +uint32_t MySQLGameAdd( void *conn, QString *error, uint32_t botid, QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); +uint32_t MySQLGamePlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); +CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ); +uint32_t MySQLDotAGameAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); +uint32_t MySQLDotAPlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); +CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ); +bool MySQLDownloadAdd( void *conn, QString *error, uint32_t botid, QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); +double MySQLScoreCheck( void *conn, QString *error, uint32_t botid, QString category, QString name, QString server ); +uint32_t MySQLW3MMDPlayerAdd( void *conn, QString *error, uint32_t botid, QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_ints ); +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_reals ); +bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_strings ); // // MySQL Callables @@ -253,15 +253,15 @@ class CMySQLCallable : virtual public CBaseCallable { protected: void *m_Connection; - string m_SQLServer; - string m_SQLDatabase; - string m_SQLUser; - string m_SQLPassword; + QString m_SQLServer; + QString m_SQLDatabase; + QString m_SQLUser; + QString m_SQLPassword; uint16_t m_SQLPort; uint32_t m_SQLBotID; public: - CMySQLCallable( void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), m_Connection( nConnection ), m_SQLBotID( nSQLBotID ), m_SQLServer( nSQLServer ), m_SQLDatabase( nSQLDatabase ), m_SQLUser( nSQLUser ), m_SQLPassword( nSQLPassword ), m_SQLPort( nSQLPort ) { } + CMySQLCallable( void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), m_Connection( nConnection ), m_SQLBotID( nSQLBotID ), m_SQLServer( nSQLServer ), m_SQLDatabase( nSQLDatabase ), m_SQLUser( nSQLUser ), m_SQLPassword( nSQLPassword ), m_SQLPort( nSQLPort ) { } virtual ~CMySQLCallable( ) { } virtual void *GetConnection( ) { return m_Connection; } @@ -273,7 +273,7 @@ class CMySQLCallable : virtual public CBaseCallable class CMySQLCallableAdminCount : public CCallableAdminCount, public CMySQLCallable { public: - CMySQLCallableAdminCount( string nServer, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminCount( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminCount( ) { } virtual void operator( )( ); @@ -284,7 +284,7 @@ class CMySQLCallableAdminCount : public CCallableAdminCount, public CMySQLCallab class CMySQLCallableAdminCheck : public CCallableAdminCheck, public CMySQLCallable { public: - CMySQLCallableAdminCheck( string nServer, string nUser, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminCheck( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminCheck( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminCheck( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminCheck( ) { } virtual void operator( )( ); @@ -295,7 +295,7 @@ class CMySQLCallableAdminCheck : public CCallableAdminCheck, public CMySQLCallab class CMySQLCallableAdminAdd : public CCallableAdminAdd, public CMySQLCallable { public: - CMySQLCallableAdminAdd( string nServer, string nUser, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminAdd( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminAdd( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminAdd( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminAdd( ) { } virtual void operator( )( ); @@ -306,7 +306,7 @@ class CMySQLCallableAdminAdd : public CCallableAdminAdd, public CMySQLCallable class CMySQLCallableAdminRemove : public CCallableAdminRemove, public CMySQLCallable { public: - CMySQLCallableAdminRemove( string nServer, string nUser, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminRemove( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminRemove( ) { } virtual void operator( )( ); @@ -317,7 +317,7 @@ class CMySQLCallableAdminRemove : public CCallableAdminRemove, public CMySQLCall class CMySQLCallableAdminList : public CCallableAdminList, public CMySQLCallable { public: - CMySQLCallableAdminList( string nServer, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminList( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminList( ) { } virtual void operator( )( ); @@ -328,7 +328,7 @@ class CMySQLCallableAdminList : public CCallableAdminList, public CMySQLCallable class CMySQLCallableBanCount : public CCallableBanCount, public CMySQLCallable { public: - CMySQLCallableBanCount( string nServer, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanCount( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanCount( ) { } virtual void operator( )( ); @@ -339,7 +339,7 @@ class CMySQLCallableBanCount : public CCallableBanCount, public CMySQLCallable class CMySQLCallableBanCheck : public CCallableBanCheck, public CMySQLCallable { public: - CMySQLCallableBanCheck( string nServer, string nUser, string nIP, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanCheck( nServer, nUser, nIP ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanCheck( QString nServer, QString nUser, QString nIP, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanCheck( nServer, nUser, nIP ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanCheck( ) { } virtual void operator( )( ); @@ -350,7 +350,7 @@ class CMySQLCallableBanCheck : public CCallableBanCheck, public CMySQLCallable class CMySQLCallableBanAdd : public CCallableBanAdd, public CMySQLCallable { public: - CMySQLCallableBanAdd( string nServer, string nUser, string nIP, string nGameName, string nAdmin, string nReason, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanAdd( nServer, nUser, nIP, nGameName, nAdmin, nReason ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanAdd( QString nServer, QString nUser, QString nIP, QString nGameName, QString nAdmin, QString nReason, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanAdd( nServer, nUser, nIP, nGameName, nAdmin, nReason ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanAdd( ) { } virtual void operator( )( ); @@ -361,7 +361,7 @@ class CMySQLCallableBanAdd : public CCallableBanAdd, public CMySQLCallable class CMySQLCallableBanRemove : public CCallableBanRemove, public CMySQLCallable { public: - CMySQLCallableBanRemove( string nServer, string nUser, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanRemove( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanRemove( ) { } virtual void operator( )( ); @@ -372,7 +372,7 @@ class CMySQLCallableBanRemove : public CCallableBanRemove, public CMySQLCallable class CMySQLCallableBanList : public CCallableBanList, public CMySQLCallable { public: - CMySQLCallableBanList( string nServer, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanList( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanList( ) { } virtual void operator( )( ); @@ -383,7 +383,7 @@ class CMySQLCallableBanList : public CCallableBanList, public CMySQLCallable class CMySQLCallableGameAdd : public CCallableGameAdd, public CMySQLCallable { public: - CMySQLCallableGameAdd( string nServer, string nMap, string nGameName, string nOwnerName, uint32_t nDuration, uint32_t nGameState, string nCreatorName, string nCreatorServer, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGameAdd( nServer, nMap, nGameName, nOwnerName, nDuration, nGameState, nCreatorName, nCreatorServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableGameAdd( QString nServer, QString nMap, QString nGameName, QString nOwnerName, uint32_t nDuration, uint32_t nGameState, QString nCreatorName, QString nCreatorServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGameAdd( nServer, nMap, nGameName, nOwnerName, nDuration, nGameState, nCreatorName, nCreatorServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableGameAdd( ) { } virtual void operator( )( ); @@ -394,7 +394,7 @@ class CMySQLCallableGameAdd : public CCallableGameAdd, public CMySQLCallable class CMySQLCallableGamePlayerAdd : public CCallableGamePlayerAdd, public CMySQLCallable { public: - CMySQLCallableGamePlayerAdd( uint32_t nGameID, string nName, string nIP, uint32_t nSpoofed, string nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, string nLeftReason, uint32_t nTeam, uint32_t nColour, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGamePlayerAdd( nGameID, nName, nIP, nSpoofed, nSpoofedRealm, nReserved, nLoadingTime, nLeft, nLeftReason, nTeam, nColour ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableGamePlayerAdd( uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGamePlayerAdd( nGameID, nName, nIP, nSpoofed, nSpoofedRealm, nReserved, nLoadingTime, nLeft, nLeftReason, nTeam, nColour ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableGamePlayerAdd( ) { } virtual void operator( )( ); @@ -405,7 +405,7 @@ class CMySQLCallableGamePlayerAdd : public CCallableGamePlayerAdd, public CMySQL class CMySQLCallableGamePlayerSummaryCheck : public CCallableGamePlayerSummaryCheck, public CMySQLCallable { public: - CMySQLCallableGamePlayerSummaryCheck( string nName, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGamePlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableGamePlayerSummaryCheck( QString nName, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGamePlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableGamePlayerSummaryCheck( ) { } virtual void operator( )( ); @@ -416,7 +416,7 @@ class CMySQLCallableGamePlayerSummaryCheck : public CCallableGamePlayerSummaryCh class CMySQLCallableDotAGameAdd : public CCallableDotAGameAdd, public CMySQLCallable { public: - CMySQLCallableDotAGameAdd( uint32_t nGameID, uint32_t nWinner, uint32_t nMin, uint32_t nSec, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAGameAdd( nGameID, nWinner, nMin, nSec ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDotAGameAdd( uint32_t nGameID, uint32_t nWinner, uint32_t nMin, uint32_t nSec, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAGameAdd( nGameID, nWinner, nMin, nSec ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDotAGameAdd( ) { } virtual void operator( )( ); @@ -427,7 +427,7 @@ class CMySQLCallableDotAGameAdd : public CCallableDotAGameAdd, public CMySQLCall class CMySQLCallableDotAPlayerAdd : public CCallableDotAPlayerAdd, public CMySQLCallable { public: - CMySQLCallableDotAPlayerAdd( uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, string nItem1, string nItem2, string nItem3, string nItem4, string nItem5, string nItem6, string nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerAdd( nGameID, nColour, nKills, nDeaths, nCreepKills, nCreepDenies, nAssists, nGold, nNeutralKills, nItem1, nItem2, nItem3, nItem4, nItem5, nItem6, nHero, nNewColour, nTowerKills, nRaxKills, nCourierKills ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDotAPlayerAdd( uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerAdd( nGameID, nColour, nKills, nDeaths, nCreepKills, nCreepDenies, nAssists, nGold, nNeutralKills, nItem1, nItem2, nItem3, nItem4, nItem5, nItem6, nHero, nNewColour, nTowerKills, nRaxKills, nCourierKills ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDotAPlayerAdd( ) { } virtual void operator( )( ); @@ -438,7 +438,7 @@ class CMySQLCallableDotAPlayerAdd : public CCallableDotAPlayerAdd, public CMySQL class CMySQLCallableDotAPlayerSummaryCheck : public CCallableDotAPlayerSummaryCheck, public CMySQLCallable { public: - CMySQLCallableDotAPlayerSummaryCheck( string nName, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDotAPlayerSummaryCheck( QString nName, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDotAPlayerSummaryCheck( ) { } virtual void operator( )( ); @@ -449,7 +449,7 @@ class CMySQLCallableDotAPlayerSummaryCheck : public CCallableDotAPlayerSummaryCh class CMySQLCallableDownloadAdd : public CCallableDownloadAdd, public CMySQLCallable { public: - CMySQLCallableDownloadAdd( string nMap, uint32_t nMapSize, string nName, string nIP, uint32_t nSpoofed, string nSpoofedRealm, uint32_t nDownloadTime, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDownloadAdd( nMap, nMapSize, nName, nIP, nSpoofed, nSpoofedRealm, nDownloadTime ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDownloadAdd( QString nMap, uint32_t nMapSize, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nDownloadTime, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDownloadAdd( nMap, nMapSize, nName, nIP, nSpoofed, nSpoofedRealm, nDownloadTime ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDownloadAdd( ) { } virtual void operator( )( ); @@ -460,7 +460,7 @@ class CMySQLCallableDownloadAdd : public CCallableDownloadAdd, public CMySQLCall class CMySQLCallableScoreCheck : public CCallableScoreCheck, public CMySQLCallable { public: - CMySQLCallableScoreCheck( string nCategory, string nName, string nServer, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableScoreCheck( nCategory, nName, nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableScoreCheck( QString nCategory, QString nName, QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableScoreCheck( nCategory, nName, nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableScoreCheck( ) { } virtual void operator( )( ); @@ -471,7 +471,7 @@ class CMySQLCallableScoreCheck : public CCallableScoreCheck, public CMySQLCallab class CMySQLCallableW3MMDPlayerAdd : public CCallableW3MMDPlayerAdd, public CMySQLCallable { public: - CMySQLCallableW3MMDPlayerAdd( string nCategory, uint32_t nGameID, uint32_t nPID, string nName, string nFlag, uint32_t nLeaver, uint32_t nPracticing, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDPlayerAdd( nCategory, nGameID, nPID, nName, nFlag, nLeaver, nPracticing ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDPlayerAdd( QString nCategory, uint32_t nGameID, uint32_t nPID, QString nName, QString nFlag, uint32_t nLeaver, uint32_t nPracticing, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDPlayerAdd( nCategory, nGameID, nPID, nName, nFlag, nLeaver, nPracticing ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableW3MMDPlayerAdd( ) { } virtual void operator( )( ); @@ -482,9 +482,9 @@ class CMySQLCallableW3MMDPlayerAdd : public CCallableW3MMDPlayerAdd, public CMyS class CMySQLCallableW3MMDVarAdd : public CCallableW3MMDVarAdd, public CMySQLCallable { public: - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarInts, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarInts ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarReals, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarReals ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarStrings, void *nConnection, uint32_t nSQLBotID, string nSQLServer, string nSQLDatabase, string nSQLUser, string nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarStrings ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarInts, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarInts ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarReals, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarReals ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarStrings, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarStrings ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableW3MMDVarAdd( ) { } virtual void operator( )( ); diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index 2f2206d..2b0a871 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -33,7 +33,7 @@ CSQLITE3 :: CSQLITE3( QString filename ) { m_Ready = true; - if( sqlite3_open_v2( filename.c_str( ), (sqlite3 **)&m_DB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL ) != SQLITE_OK ) + if( sqlite3_open_v2( (char*)filename.data(), (sqlite3 **)&m_DB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL ) != SQLITE_OK ) m_Ready = false; } @@ -49,7 +49,7 @@ QString CSQLITE3 :: GetError( ) int CSQLITE3 :: Prepare( QString query, void **Statement ) { - return sqlite3_prepare_v2( (sqlite3 *)m_DB, query.c_str( ), -1, (sqlite3_stmt **)Statement, NULL ); + return sqlite3_prepare_v2( (sqlite3 *)m_DB, (char*)query.data( ), -1, (sqlite3_stmt **)Statement, NULL ); } int CSQLITE3 :: Step( void *Statement ) @@ -91,7 +91,7 @@ int CSQLITE3 :: ClearBindings( void *Statement ) int CSQLITE3 :: Exec( QString query ) { - return sqlite3_exec( (sqlite3 *)m_DB, query.c_str( ), NULL, NULL, NULL ); + return sqlite3_exec( (sqlite3 *)m_DB, (char*)query.data( ), NULL, NULL, NULL ); } uint32_t CSQLITE3 :: LastRowID( ) @@ -215,7 +215,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) if( Statement ) { - sqlite3_bind_text( Statement, 1, SchemaNumber.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)SchemaNumber.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ERROR ) @@ -563,7 +563,7 @@ uint32_t CGHostDBSQLite :: AdminCount( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -581,15 +581,15 @@ uint32_t CGHostDBSQLite :: AdminCount( QString server ) bool CGHostDBSQLite :: AdminCheck( QString server, QString user ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); bool IsAdmin = false; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT * FROM admins WHERE server=? AND name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); // we're just checking to see if the query returned a row, we don't need to check the row data itself @@ -609,15 +609,15 @@ bool CGHostDBSQLite :: AdminCheck( QString server, QString user ) bool CGHostDBSQLite :: AdminAdd( QString server, QString user ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); bool Success = false; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO admins ( server, name ) VALUES ( ?, ? )", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -635,15 +635,15 @@ bool CGHostDBSQLite :: AdminAdd( QString server, QString user ) bool CGHostDBSQLite :: AdminRemove( QString server, QString user ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); bool Success = false; sqlite3_stmt *Statement; m_DB->Prepare( "DELETE FROM admins WHERE server=? AND name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -667,7 +667,7 @@ QVector CGHostDBSQLite :: AdminList( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); while( RC == SQLITE_ROW ) @@ -699,7 +699,7 @@ uint32_t CGHostDBSQLite :: BanCount( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -717,7 +717,7 @@ uint32_t CGHostDBSQLite :: BanCount( QString server ) CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); CDBBan *Ban = NULL; sqlite3_stmt *Statement; @@ -728,11 +728,11 @@ CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); if( !ip.isEmpty( ) ) - sqlite3_bind_text( Statement, 3, ip.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -758,19 +758,19 @@ CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) bool CGHostDBSQLite :: BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); bool Success = false; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO bans ( server, name, ip, date, gamename, admin, reason ) VALUES ( ?, ?, ?, date('now'), ?, ?, ? )", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 3, ip.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, gamename.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 5, admin.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 6, reason.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, (char*)gamename.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 5, (char*)admin.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 6, (char*)reason.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -789,15 +789,15 @@ bool CGHostDBSQLite :: BanAdd( QString server, QString user, QString ip, QString bool CGHostDBSQLite :: BanRemove( QString server, QString user ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); bool Success = false; sqlite3_stmt *Statement; m_DB->Prepare( "DELETE FROM bans WHERE server=? AND name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, user.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -815,14 +815,14 @@ bool CGHostDBSQLite :: BanRemove( QString server, QString user ) bool CGHostDBSQLite :: BanRemove( QString user ) { - transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); + user = user.toLower(); bool Success = false; sqlite3_stmt *Statement; m_DB->Prepare( "DELETE FROM bans WHERE name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, user.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)user.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -846,7 +846,7 @@ QVector CGHostDBSQLite :: BanList( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); while( RC == SQLITE_ROW ) @@ -878,14 +878,14 @@ uint32_t CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamenam if( Statement ) { - sqlite3_bind_text( Statement, 1, server.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, map.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 3, gamename.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, ownername.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)map.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, (char*)gamename.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, (char*)ownername.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 5, duration ); sqlite3_bind_int( Statement, 6, gamestate ); - sqlite3_bind_text( Statement, 7, creatorname.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 8, creatorserver.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 7, (char*)creatorname.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 8, (char*)creatorserver.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -904,7 +904,7 @@ uint32_t CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamenam uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); uint32_t RowID = 0; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO gameplayers ( gameid, name, ip, spoofed, reserved, loadingtime, left, leftreason, team, colour, spoofedrealm ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )", (void **)&Statement ); @@ -912,16 +912,16 @@ uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString if( Statement ) { sqlite3_bind_int( Statement, 1, gameid ); - sqlite3_bind_text( Statement, 2, name.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 3, ip.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 4, spoofed ); sqlite3_bind_int( Statement, 5, reserved ); sqlite3_bind_int( Statement, 6, loadingtime ); sqlite3_bind_int( Statement, 7, left ); - sqlite3_bind_text( Statement, 8, leftreason.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 8, (char*)leftreason.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 9, team ); sqlite3_bind_int( Statement, 10, colour ); - sqlite3_bind_text( Statement, 11, spoofedrealm.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 11, (char*)spoofedrealm.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -940,14 +940,14 @@ uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString uint32_t CGHostDBSQLite :: GamePlayerCount( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); uint32_t Count = 0; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, name.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -968,14 +968,14 @@ CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( QString name ) if( GamePlayerCount( name ) == 0 ) return NULL; - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); CDBGamePlayerSummary *GamePlayerSummary = NULL; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT MIN(datetime), MAX(datetime), COUNT(*), MIN(loadingtime), AVG(loadingtime), MAX(loadingtime), MIN(left/CAST(duration AS REAL))*100, AVG(left/CAST(duration AS REAL))*100, MAX(left/CAST(duration AS REAL))*100, MIN(duration), AVG(duration), MAX(duration) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, name.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -1064,13 +1064,13 @@ uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint sqlite3_bind_int( Statement, 7, assists ); sqlite3_bind_int( Statement, 8, gold ); sqlite3_bind_int( Statement, 9, neutralkills ); - sqlite3_bind_text( Statement, 10, item1.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 11, item2.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 12, item3.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 13, item4.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 14, item5.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 15, item6.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 16, hero.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 10, (char*)item1.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 11, (char*)item2.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 12, (char*)item3.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 13, (char*)item4.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 14, (char*)item5.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 15, (char*)item6.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 16, (char*)hero.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 17, newcolour ); sqlite3_bind_int( Statement, 18, towerkills ); sqlite3_bind_int( Statement, 19, raxkills ); @@ -1093,14 +1093,14 @@ uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint uint32_t CGHostDBSQLite :: DotAPlayerCount( QString name ) { - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); uint32_t Count = 0; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(dotaplayers.id) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, name.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -1121,14 +1121,14 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) if( DotAPlayerCount( name ) == 0 ) return NULL; - transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); + name = name.toLower(); CDBDotAPlayerSummary *DotAPlayerSummary = NULL; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(dotaplayers.id), SUM(kills), SUM(deaths), SUM(creepkills), SUM(creepdenies), SUM(assists), SUM(neutralkills), SUM(towerkills), SUM(raxkills), SUM(courierkills) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE name=?", (void **)&Statement ); if( Statement ) { - sqlite3_bind_text( Statement, 1, name.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -1155,7 +1155,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) if( Statement2 ) { - sqlite3_bind_text( Statement2, 1, name.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement2, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); int RC2 = m_DB->Step( Statement2 ); if( RC2 == SQLITE_ROW ) @@ -1175,7 +1175,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) if( Statement3 ) { - sqlite3_bind_text( Statement3, 1, name.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement3, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); int RC3 = m_DB->Step( Statement3 ); if( RC3 == SQLITE_ROW ) @@ -1257,7 +1257,7 @@ bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) sqlite3_bind_int64( (sqlite3_stmt *)FromAddStmt, 1, ip1 ); sqlite3_bind_int64( (sqlite3_stmt *)FromAddStmt, 2, ip2 ); - sqlite3_bind_text( (sqlite3_stmt *)FromAddStmt, 3, country.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( (sqlite3_stmt *)FromAddStmt, 3, (char*)country.data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( FromAddStmt ); @@ -1282,12 +1282,12 @@ bool CGHostDBSQLite :: DownloadAdd( QString map, uint32_t mapsize, QString name, if( Statement ) { - sqlite3_bind_text( Statement, 1, map.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)map.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 2, mapsize ); - sqlite3_bind_text( Statement, 3, name.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, ip.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 5, spoofed ); - sqlite3_bind_text( Statement, 6, spoofedrealm.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 6, (char*)spoofedrealm.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 7, downloadtime ); int RC = m_DB->Step( Statement ); @@ -1313,11 +1313,11 @@ uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( QString category, uint32_t gameid, ui if( Statement ) { - sqlite3_bind_text( Statement, 1, category.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, (char*)category.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 2, gameid ); sqlite3_bind_int( Statement, 3, pid ); - sqlite3_bind_text( Statement, 4, name.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 5, flag.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 5, (char*)flag.data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 6, leaver ); sqlite3_bind_int( Statement, 7, practicing ); @@ -1352,16 +1352,16 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_ints if( Statement ) { sqlite3_bind_int( Statement, 1, gameid ); - sqlite3_bind_int( Statement, 2, i->first.first ); - sqlite3_bind_text( Statement, 3, i->first.second.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_int( Statement, 4, i->second ); + sqlite3_bind_int( Statement, 2, i.key().first ); + sqlite3_bind_text( Statement, 3, (char*)i.key().second.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_int( Statement, 4, i.value() ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-int [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + UTIL_ToString( i->second ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-int [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value() ) + "] - " + m_DB->GetError( ) ); break; } @@ -1370,7 +1370,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_ints else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-int [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + UTIL_ToString( i->second ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-int [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value() ) + "] - " + m_DB->GetError( ) ); break; } } @@ -1397,16 +1397,16 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_reals if( Statement ) { sqlite3_bind_int( Statement, 1, gameid ); - sqlite3_bind_int( Statement, 2, i->first.first ); - sqlite3_bind_text( Statement, 3, i->first.second.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_double( Statement, 4, i->second ); + sqlite3_bind_int( Statement, 2, i.key().first ); + sqlite3_bind_text( Statement, 3, (char*)i.key().second.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_double( Statement, 4, i.value() ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-real [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + UTIL_ToString( i->second, 10 ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-real [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value(), 10 ) + "] - " + m_DB->GetError( ) ); break; } @@ -1415,7 +1415,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_reals else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-real [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + UTIL_ToString( i->second, 10 ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-real [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value(), 10 ) + "] - " + m_DB->GetError( ) ); break; } } @@ -1442,16 +1442,16 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_stri if( Statement ) { sqlite3_bind_int( Statement, 1, gameid ); - sqlite3_bind_int( Statement, 2, i->first.first ); - sqlite3_bind_text( Statement, 3, i->first.second.c_str( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, i->second.c_str( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_int( Statement, 2, i.key().first ); + sqlite3_bind_text( Statement, 3, (char*)i.key().second.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, (char*)i.value().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + i->second + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + i.value() + "] - " + m_DB->GetError( ) ); break; } @@ -1460,7 +1460,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_stri else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i->first.first ) + " : " + i->first.second + " : " + i->second + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + i.value() + "] - " + m_DB->GetError( ) ); break; } } diff --git a/ghost/ghostdbsqlite.h b/ghost/ghostdbsqlite.h index b415415..c110849 100644 --- a/ghost/ghostdbsqlite.h +++ b/ghost/ghostdbsqlite.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -163,22 +163,22 @@ class CSQLITE3 private: void *m_DB; bool m_Ready; - QVector m_Row; + QVector m_Row; public: - CSQLITE3( string filename ); + CSQLITE3( QString filename ); ~CSQLITE3( ); bool GetReady( ) { return m_Ready; } - QVector *GetRow( ) { return &m_Row; } - string GetError( ); + QVector *GetRow( ) { return &m_Row; } + QString GetError( ); - int Prepare( string query, void **Statement ); + int Prepare( QString query, void **Statement ); int Step( void *Statement ); int Finalize( void *Statement ); int Reset( void *Statement ); int ClearBindings( void *Statement ); - int Exec( string query ); + int Exec( QString query ); uint32_t LastRowID( ); }; @@ -186,10 +186,12 @@ class CSQLITE3 // CGHostDBSQLite // +#include "includes.h" + class CGHostDBSQLite : public CGHostDB { private: - string m_File; + QString m_File; CSQLITE3 *m_DB; // we keep some prepared statements in memory rather than recreating them each function call @@ -212,59 +214,59 @@ class CGHostDBSQLite : public CGHostDB virtual bool Begin( ); virtual bool Commit( ); - virtual uint32_t AdminCount( string server ); - virtual bool AdminCheck( string server, string user ); - virtual bool AdminAdd( string server, string user ); - virtual bool AdminRemove( string server, string user ); - virtual QVector AdminList( string server ); - virtual uint32_t BanCount( string server ); - virtual CDBBan *BanCheck( string server, string user, string ip ); - virtual bool BanAdd( string server, string user, string ip, string gamename, string admin, string reason ); - virtual bool BanRemove( string server, string user ); - virtual bool BanRemove( string user ); - virtual QVector BanList( string server ); - virtual uint32_t GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); - virtual uint32_t GamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); - virtual uint32_t GamePlayerCount( string name ); - virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( string name ); + virtual uint32_t AdminCount( QString server ); + virtual bool AdminCheck( QString server, QString user ); + virtual bool AdminAdd( QString server, QString user ); + virtual bool AdminRemove( QString server, QString user ); + virtual QVector AdminList( QString server ); + virtual uint32_t BanCount( QString server ); + virtual CDBBan *BanCheck( QString server, QString user, QString ip ); + virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); + virtual bool BanRemove( QString server, QString user ); + virtual bool BanRemove( QString user ); + virtual QVector BanList( QString server ); + virtual uint32_t GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); + virtual uint32_t GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual uint32_t GamePlayerCount( QString name ); + virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( QString name ); virtual uint32_t DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual uint32_t DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual uint32_t DotAPlayerCount( string name ); - virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( string name ); - virtual string FromCheck( uint32_t ip ); - virtual bool FromAdd( uint32_t ip1, uint32_t ip2, string country ); - virtual bool DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); - virtual uint32_t W3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); + virtual uint32_t DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual uint32_t DotAPlayerCount( QString name ); + virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( QString name ); + virtual QString FromCheck( uint32_t ip ); + virtual bool FromAdd( uint32_t ip1, uint32_t ip2, QString country ); + virtual bool DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual uint32_t W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_ints ); virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_strings ); // threaded database functions // note: these are not actually implemented with threads at the moment, they WILL block until the query is complete // todotodo: implement threads here - virtual CCallableAdminCount *ThreadedAdminCount( string server ); - virtual CCallableAdminCheck *ThreadedAdminCheck( string server, string user ); - virtual CCallableAdminAdd *ThreadedAdminAdd( string server, string user ); - virtual CCallableAdminRemove *ThreadedAdminRemove( string server, string user ); - virtual CCallableAdminList *ThreadedAdminList( string server ); - virtual CCallableBanCount *ThreadedBanCount( string server ); - virtual CCallableBanCheck *ThreadedBanCheck( string server, string user, string ip ); - virtual CCallableBanAdd *ThreadedBanAdd( string server, string user, string ip, string gamename, string admin, string reason ); - virtual CCallableBanRemove *ThreadedBanRemove( string server, string user ); - virtual CCallableBanRemove *ThreadedBanRemove( string user ); - virtual CCallableBanList *ThreadedBanList( string server ); - virtual CCallableGameAdd *ThreadedGameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); - virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour ); - virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( string name ); + virtual CCallableAdminCount *ThreadedAdminCount( QString server ); + virtual CCallableAdminCheck *ThreadedAdminCheck( QString server, QString user ); + virtual CCallableAdminAdd *ThreadedAdminAdd( QString server, QString user ); + virtual CCallableAdminRemove *ThreadedAdminRemove( QString server, QString user ); + virtual CCallableAdminList *ThreadedAdminList( QString server ); + virtual CCallableBanCount *ThreadedBanCount( QString server ); + virtual CCallableBanCheck *ThreadedBanCheck( QString server, QString user, QString ip ); + virtual CCallableBanAdd *ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); + virtual CCallableBanRemove *ThreadedBanRemove( QString server, QString user ); + virtual CCallableBanRemove *ThreadedBanRemove( QString user ); + virtual CCallableBanList *ThreadedBanList( QString server ); + virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); + virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( QString name ); virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( string name ); - virtual CCallableDownloadAdd *ThreadedDownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); - virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing ); + virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); + virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); }; #endif diff --git a/ghost/gpsprotocol.cpp b/ghost/gpsprotocol.cpp index c87c385..ca2a6de 100644 --- a/ghost/gpsprotocol.cpp +++ b/ghost/gpsprotocol.cpp @@ -47,8 +47,8 @@ QByteArray CGPSProtocol :: SEND_GPSC_INIT( uint32_t version ) QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_INIT ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); UTIL_AppendQByteArray( packet, version, false ); AssignLength( packet ); return packet; @@ -59,8 +59,8 @@ QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reco QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_RECONNECT ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); packet.push_back( PID ); UTIL_AppendQByteArray( packet, reconnectKey, false ); UTIL_AppendQByteArray( packet, lastPacket, false ); @@ -73,8 +73,8 @@ QByteArray CGPSProtocol :: SEND_GPSC_ACK( uint32_t lastPacket ) QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_ACK ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; @@ -85,8 +85,8 @@ QByteArray CGPSProtocol :: SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_INIT ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); UTIL_AppendQByteArray( packet, reconnectPort, false ); packet.push_back( PID ); UTIL_AppendQByteArray( packet, reconnectKey, false ); @@ -100,8 +100,8 @@ QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( uint32_t lastPacket ) QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_RECONNECT ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; @@ -112,8 +112,8 @@ QByteArray CGPSProtocol :: SEND_GPSS_ACK( uint32_t lastPacket ) QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_ACK ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); UTIL_AppendQByteArray( packet, lastPacket, false ); AssignLength( packet ); return packet; @@ -124,8 +124,8 @@ QByteArray CGPSProtocol :: SEND_GPSS_REJECT( uint32_t reason ) QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); packet.push_back( GPS_REJECT ); - packet.push_back( 0 ); - packet.push_back( 0 ); + packet.push_back( (char)0 ); + packet.push_back( (char)0 ); UTIL_AppendQByteArray( packet, reason, false ); AssignLength( packet ); return packet; diff --git a/ghost/language.h b/ghost/language.h index 3d12a5c..8596d8b 100644 --- a/ghost/language.h +++ b/ghost/language.h @@ -31,229 +31,229 @@ class CLanguage CConfig *m_CFG; public: - CLanguage( string nCFGFile ); + CLanguage( QString nCFGFile ); ~CLanguage( ); - string UnableToCreateGameTryAnotherName( string server, string gamename ); - string UserIsAlreadyAnAdmin( string server, string user ); - string AddedUserToAdminDatabase( string server, string user ); - string ErrorAddingUserToAdminDatabase( string server, string user ); - string YouDontHaveAccessToThatCommand( ); - string UserIsAlreadyBanned( string server, string victim ); - string BannedUser( string server, string victim ); - string ErrorBanningUser( string server, string victim ); - string UserIsAnAdmin( string server, string user ); - string UserIsNotAnAdmin( string server, string user ); - string UserWasBannedOnByBecause( string server, string victim, string date, string admin, string reason ); - string UserIsNotBanned( string server, string victim ); - string ThereAreNoAdmins( string server ); - string ThereIsAdmin( string server ); - string ThereAreAdmins( string server, string count ); - string ThereAreNoBannedUsers( string server ); - string ThereIsBannedUser( string server ); - string ThereAreBannedUsers( string server, string count ); - string YouCantDeleteTheRootAdmin( ); - string DeletedUserFromAdminDatabase( string server, string user ); - string ErrorDeletingUserFromAdminDatabase( string server, string user ); - string UnbannedUser( string victim ); - string ErrorUnbanningUser( string victim ); - string GameNumberIs( string number, string description ); - string GameNumberDoesntExist( string number ); - string GameIsInTheLobby( string description, string current, string max ); - string ThereIsNoGameInTheLobby( string current, string max ); - string UnableToLoadConfigFilesOutside( ); - string LoadingConfigFile( string file ); - string UnableToLoadConfigFileDoesntExist( string file ); - string CreatingPrivateGame( string gamename, string user ); - string CreatingPublicGame( string gamename, string user ); - string UnableToUnhostGameCountdownStarted( string description ); - string UnhostingGame( string description ); - string UnableToUnhostGameNoGameInLobby( ); - string VersionAdmin( string version ); - string VersionNotAdmin( string version ); - string UnableToCreateGameAnotherGameInLobby( string gamename, string description ); - string UnableToCreateGameMaxGamesReached( string gamename, string max ); - string GameIsOver( string description ); - string SpoofCheckByReplying( ); - string GameRefreshed( ); - string SpoofPossibleIsAway( string user ); - string SpoofPossibleIsUnavailable( string user ); - string SpoofPossibleIsRefusingMessages( string user ); - string SpoofDetectedIsNotInGame( string user ); - string SpoofDetectedIsInPrivateChannel( string user ); - string SpoofDetectedIsInAnotherGame( string user ); - string CountDownAborted( ); - string TryingToJoinTheGameButBanned( string victim ); - string UnableToBanNoMatchesFound( string victim ); - string PlayerWasBannedByPlayer( string server, string victim, string user ); - string UnableToBanFoundMoreThanOneMatch( string victim ); - string AddedPlayerToTheHoldList( string user ); - string UnableToKickNoMatchesFound( string victim ); - string UnableToKickFoundMoreThanOneMatch( string victim ); - string SettingLatencyToMinimum( string min ); - string SettingLatencyToMaximum( string max ); - string SettingLatencyTo( string latency ); - string KickingPlayersWithPingsGreaterThan( string total, string ping ); - string HasPlayedGamesWithThisBot( string user, string firstgame, string lastgame, string totalgames, string avgloadingtime, string avgstay ); - string HasntPlayedGamesWithThisBot( string user ); - string AutokickingPlayerForExcessivePing( string victim, string ping ); - string SpoofCheckAcceptedFor( string server, string user ); - string PlayersNotYetSpoofChecked( string notspoofchecked ); - string ManuallySpoofCheckByWhispering( string hostname ); - string SpoofCheckByWhispering( string hostname ); - string EveryoneHasBeenSpoofChecked( ); - string PlayersNotYetPinged( string notpinged ); - string EveryoneHasBeenPinged( ); - string ShortestLoadByPlayer( string user, string loadingtime ); - string LongestLoadByPlayer( string user, string loadingtime ); - string YourLoadingTimeWas( string loadingtime ); - string HasPlayedDotAGamesWithThisBot( string user, string totalgames, string totalwins, string totallosses, string totalkills, string totaldeaths, string totalcreepkills, string totalcreepdenies, string totalassists, string totalneutralkills, string totaltowerkills, string totalraxkills, string totalcourierkills, string avgkills, string avgdeaths, string avgcreepkills, string avgcreepdenies, string avgassists, string avgneutralkills, string avgtowerkills, string avgraxkills, string avgcourierkills ); - string HasntPlayedDotAGamesWithThisBot( string user ); - string WasKickedForReservedPlayer( string reserved ); - string WasKickedForOwnerPlayer( string owner ); - string WasKickedByPlayer( string user ); - string HasLostConnectionPlayerError( string error ); - string HasLostConnectionSocketError( string error ); - string HasLostConnectionClosedByRemoteHost( ); - string HasLeftVoluntarily( ); - string EndingGame( string description ); - string HasLostConnectionTimedOut( ); - string GlobalChatMuted( ); - string GlobalChatUnmuted( ); - string ShufflingPlayers( ); - string UnableToLoadConfigFileGameInLobby( ); - string PlayersStillDownloading( string stilldownloading ); - string RefreshMessagesEnabled( ); - string RefreshMessagesDisabled( ); - string AtLeastOneGameActiveUseForceToShutdown( ); - string CurrentlyLoadedMapCFGIs( string mapcfg ); - string LaggedOutDroppedByAdmin( ); - string LaggedOutDroppedByVote( ); - string PlayerVotedToDropLaggers( string user ); - string LatencyIs( string latency ); - string SyncLimitIs( string synclimit ); - string SettingSyncLimitToMinimum( string min ); - string SettingSyncLimitToMaximum( string max ); - string SettingSyncLimitTo( string synclimit ); - string UnableToCreateGameNotLoggedIn( string gamename ); - string AdminLoggedIn( ); - string AdminInvalidPassword( string attempt ); - string ConnectingToBNET( string server ); - string ConnectedToBNET( string server ); - string DisconnectedFromBNET( string server ); - string LoggedInToBNET( string server ); - string BNETGameHostingSucceeded( string server ); - string BNETGameHostingFailed( string server, string gamename ); - string ConnectingToBNETTimedOut( string server ); - string PlayerDownloadedTheMap( string user, string seconds, string rate ); - string UnableToCreateGameNameTooLong( string gamename ); - string SettingGameOwnerTo( string owner ); - string TheGameIsLocked( ); - string GameLocked( ); - string GameUnlocked( ); - string UnableToStartDownloadNoMatchesFound( string victim ); - string UnableToStartDownloadFoundMoreThanOneMatch( string victim ); - string UnableToSetGameOwner( string owner ); - string UnableToCheckPlayerNoMatchesFound( string victim ); - string CheckedPlayer( string victim, string ping, string from, string admin, string owner, string spoofed, string spoofedrealm, string reserved ); - string UnableToCheckPlayerFoundMoreThanOneMatch( string victim ); - string TheGameIsLockedBNET( ); - string UnableToCreateGameDisabled( string gamename ); - string BotDisabled( ); - string BotEnabled( ); - string UnableToCreateGameInvalidMap( string gamename ); - string WaitingForPlayersBeforeAutoStart( string players, string playersleft ); - string AutoStartDisabled( ); - string AutoStartEnabled( string players ); - string AnnounceMessageEnabled( ); - string AnnounceMessageDisabled( ); - string AutoHostEnabled( ); - string AutoHostDisabled( ); - string UnableToLoadSaveGamesOutside( ); - string UnableToLoadSaveGameGameInLobby( ); - string LoadingSaveGame( string file ); - string UnableToLoadSaveGameDoesntExist( string file ); - string UnableToCreateGameInvalidSaveGame( string gamename ); - string UnableToCreateGameSaveGameMapMismatch( string gamename ); - string AutoSaveEnabled( ); - string AutoSaveDisabled( ); - string DesyncDetected( ); - string UnableToMuteNoMatchesFound( string victim ); - string MutedPlayer( string victim, string user ); - string UnmutedPlayer( string victim, string user ); - string UnableToMuteFoundMoreThanOneMatch( string victim ); - string PlayerIsSavingTheGame( string player ); - string UpdatingClanList( ); - string UpdatingFriendsList( ); - string MultipleIPAddressUsageDetected( string player, string others ); - string UnableToVoteKickAlreadyInProgress( ); - string UnableToVoteKickNotEnoughPlayers( ); - string UnableToVoteKickNoMatchesFound( string victim ); - string UnableToVoteKickPlayerIsReserved( string victim ); - string StartedVoteKick( string victim, string user, string votesneeded ); - string UnableToVoteKickFoundMoreThanOneMatch( string victim ); - string VoteKickPassed( string victim ); - string ErrorVoteKickingPlayer( string victim ); - string VoteKickAcceptedNeedMoreVotes( string victim, string user, string votes ); - string VoteKickCancelled( string victim ); - string VoteKickExpired( string victim ); - string WasKickedByVote( ); - string TypeYesToVote( string commandtrigger ); - string PlayersNotYetPingedAutoStart( string notpinged ); - string WasKickedForNotSpoofChecking( ); - string WasKickedForHavingFurthestScore( string score, string average ); - string PlayerHasScore( string player, string score ); - string RatedPlayersSpread( string rated, string total, string spread ); - string ErrorListingMaps( ); - string FoundMaps( string maps ); - string NoMapsFound( ); - string ErrorListingMapConfigs( ); - string FoundMapConfigs( string mapconfigs ); - string NoMapConfigsFound( ); - string PlayerFinishedLoading( string user ); - string PleaseWaitPlayersStillLoading( ); - string MapDownloadsDisabled( ); - string MapDownloadsEnabled( ); - string MapDownloadsConditional( ); - string SettingHCL( string HCL ); - string UnableToSetHCLInvalid( ); - string UnableToSetHCLTooLong( ); - string TheHCLIs( string HCL ); - string TheHCLIsTooLongUseForceToStart( ); - string ClearingHCL( ); - string TryingToRehostAsPrivateGame( string gamename ); - string TryingToRehostAsPublicGame( string gamename ); - string RehostWasSuccessful( ); - string TryingToJoinTheGameButBannedByName( string victim ); - string TryingToJoinTheGameButBannedByIP( string victim, string ip, string bannedname ); - string HasBannedName( string victim ); - string HasBannedIP( string victim, string ip, string bannedname ); - string PlayersInGameState( string number, string players ); - string ValidServers( string servers ); - string TeamCombinedScore( string team, string score ); - string BalancingSlotsCompleted( ); - string PlayerWasKickedForFurthestScore( string name, string score, string average ); - string LocalAdminMessagesEnabled( ); - string LocalAdminMessagesDisabled( ); - string WasDroppedDesync( ); - string WasKickedForHavingLowestScore( string score ); - string PlayerWasKickedForLowestScore( string name, string score ); - string ReloadingConfigurationFiles( ); - string CountDownAbortedSomeoneLeftRecently( ); - string UnableToCreateGameMustEnforceFirst( string gamename ); - string UnableToLoadReplaysOutside( ); - string LoadingReplay( string file ); - string UnableToLoadReplayDoesntExist( string file ); - string CommandTrigger( string trigger ); - string CantEndGameOwnerIsStillPlaying( string owner ); - string CantUnhostGameOwnerIsPresent( string owner ); - string WasAutomaticallyDroppedAfterSeconds( string seconds ); - string HasLostConnectionTimedOutGProxy( ); - string HasLostConnectionSocketErrorGProxy( string error ); - string HasLostConnectionClosedByRemoteHostGProxy( ); - string WaitForReconnectSecondsRemain( string seconds ); - string WasUnrecoverablyDroppedFromGProxy( ); - string PlayerReconnectedWithGProxy( string name ); + QString UnableToCreateGameTryAnotherName( QString server, QString gamename ); + QString UserIsAlreadyAnAdmin( QString server, QString user ); + QString AddedUserToAdminDatabase( QString server, QString user ); + QString ErrorAddingUserToAdminDatabase( QString server, QString user ); + QString YouDontHaveAccessToThatCommand( ); + QString UserIsAlreadyBanned( QString server, QString victim ); + QString BannedUser( QString server, QString victim ); + QString ErrorBanningUser( QString server, QString victim ); + QString UserIsAnAdmin( QString server, QString user ); + QString UserIsNotAnAdmin( QString server, QString user ); + QString UserWasBannedOnByBecause( QString server, QString victim, QString date, QString admin, QString reason ); + QString UserIsNotBanned( QString server, QString victim ); + QString ThereAreNoAdmins( QString server ); + QString ThereIsAdmin( QString server ); + QString ThereAreAdmins( QString server, QString count ); + QString ThereAreNoBannedUsers( QString server ); + QString ThereIsBannedUser( QString server ); + QString ThereAreBannedUsers( QString server, QString count ); + QString YouCantDeleteTheRootAdmin( ); + QString DeletedUserFromAdminDatabase( QString server, QString user ); + QString ErrorDeletingUserFromAdminDatabase( QString server, QString user ); + QString UnbannedUser( QString victim ); + QString ErrorUnbanningUser( QString victim ); + QString GameNumberIs( QString number, QString description ); + QString GameNumberDoesntExist( QString number ); + QString GameIsInTheLobby( QString description, QString current, QString max ); + QString ThereIsNoGameInTheLobby( QString current, QString max ); + QString UnableToLoadConfigFilesOutside( ); + QString LoadingConfigFile( QString file ); + QString UnableToLoadConfigFileDoesntExist( QString file ); + QString CreatingPrivateGame( QString gamename, QString user ); + QString CreatingPublicGame( QString gamename, QString user ); + QString UnableToUnhostGameCountdownStarted( QString description ); + QString UnhostingGame( QString description ); + QString UnableToUnhostGameNoGameInLobby( ); + QString VersionAdmin( QString version ); + QString VersionNotAdmin( QString version ); + QString UnableToCreateGameAnotherGameInLobby( QString gamename, QString description ); + QString UnableToCreateGameMaxGamesReached( QString gamename, QString max ); + QString GameIsOver( QString description ); + QString SpoofCheckByReplying( ); + QString GameRefreshed( ); + QString SpoofPossibleIsAway( QString user ); + QString SpoofPossibleIsUnavailable( QString user ); + QString SpoofPossibleIsRefusingMessages( QString user ); + QString SpoofDetectedIsNotInGame( QString user ); + QString SpoofDetectedIsInPrivateChannel( QString user ); + QString SpoofDetectedIsInAnotherGame( QString user ); + QString CountDownAborted( ); + QString TryingToJoinTheGameButBanned( QString victim ); + QString UnableToBanNoMatchesFound( QString victim ); + QString PlayerWasBannedByPlayer( QString server, QString victim, QString user ); + QString UnableToBanFoundMoreThanOneMatch( QString victim ); + QString AddedPlayerToTheHoldList( QString user ); + QString UnableToKickNoMatchesFound( QString victim ); + QString UnableToKickFoundMoreThanOneMatch( QString victim ); + QString SettingLatencyToMinimum( QString min ); + QString SettingLatencyToMaximum( QString max ); + QString SettingLatencyTo( QString latency ); + QString KickingPlayersWithPingsGreaterThan( QString total, QString ping ); + QString HasPlayedGamesWithThisBot( QString user, QString firstgame, QString lastgame, QString totalgames, QString avgloadingtime, QString avgstay ); + QString HasntPlayedGamesWithThisBot( QString user ); + QString AutokickingPlayerForExcessivePing( QString victim, QString ping ); + QString SpoofCheckAcceptedFor( QString server, QString user ); + QString PlayersNotYetSpoofChecked( QString notspoofchecked ); + QString ManuallySpoofCheckByWhispering( QString hostname ); + QString SpoofCheckByWhispering( QString hostname ); + QString EveryoneHasBeenSpoofChecked( ); + QString PlayersNotYetPinged( QString notpinged ); + QString EveryoneHasBeenPinged( ); + QString ShortestLoadByPlayer( QString user, QString loadingtime ); + QString LongestLoadByPlayer( QString user, QString loadingtime ); + QString YourLoadingTimeWas( QString loadingtime ); + QString HasPlayedDotAGamesWithThisBot( QString user, QString totalgames, QString totalwins, QString totallosses, QString totalkills, QString totaldeaths, QString totalcreepkills, QString totalcreepdenies, QString totalassists, QString totalneutralkills, QString totaltowerkills, QString totalraxkills, QString totalcourierkills, QString avgkills, QString avgdeaths, QString avgcreepkills, QString avgcreepdenies, QString avgassists, QString avgneutralkills, QString avgtowerkills, QString avgraxkills, QString avgcourierkills ); + QString HasntPlayedDotAGamesWithThisBot( QString user ); + QString WasKickedForReservedPlayer( QString reserved ); + QString WasKickedForOwnerPlayer( QString owner ); + QString WasKickedByPlayer( QString user ); + QString HasLostConnectionPlayerError( QString error ); + QString HasLostConnectionSocketError( QString error ); + QString HasLostConnectionClosedByRemoteHost( ); + QString HasLeftVoluntarily( ); + QString EndingGame( QString description ); + QString HasLostConnectionTimedOut( ); + QString GlobalChatMuted( ); + QString GlobalChatUnmuted( ); + QString ShufflingPlayers( ); + QString UnableToLoadConfigFileGameInLobby( ); + QString PlayersStillDownloading( QString stilldownloading ); + QString RefreshMessagesEnabled( ); + QString RefreshMessagesDisabled( ); + QString AtLeastOneGameActiveUseForceToShutdown( ); + QString CurrentlyLoadedMapCFGIs( QString mapcfg ); + QString LaggedOutDroppedByAdmin( ); + QString LaggedOutDroppedByVote( ); + QString PlayerVotedToDropLaggers( QString user ); + QString LatencyIs( QString latency ); + QString SyncLimitIs( QString synclimit ); + QString SettingSyncLimitToMinimum( QString min ); + QString SettingSyncLimitToMaximum( QString max ); + QString SettingSyncLimitTo( QString synclimit ); + QString UnableToCreateGameNotLoggedIn( QString gamename ); + QString AdminLoggedIn( ); + QString AdminInvalidPassword( QString attempt ); + QString ConnectingToBNET( QString server ); + QString ConnectedToBNET( QString server ); + QString DisconnectedFromBNET( QString server ); + QString LoggedInToBNET( QString server ); + QString BNETGameHostingSucceeded( QString server ); + QString BNETGameHostingFailed( QString server, QString gamename ); + QString ConnectingToBNETTimedOut( QString server ); + QString PlayerDownloadedTheMap( QString user, QString seconds, QString rate ); + QString UnableToCreateGameNameTooLong( QString gamename ); + QString SettingGameOwnerTo( QString owner ); + QString TheGameIsLocked( ); + QString GameLocked( ); + QString GameUnlocked( ); + QString UnableToStartDownloadNoMatchesFound( QString victim ); + QString UnableToStartDownloadFoundMoreThanOneMatch( QString victim ); + QString UnableToSetGameOwner( QString owner ); + QString UnableToCheckPlayerNoMatchesFound( QString victim ); + QString CheckedPlayer( QString victim, QString ping, QString from, QString admin, QString owner, QString spoofed, QString spoofedrealm, QString reserved ); + QString UnableToCheckPlayerFoundMoreThanOneMatch( QString victim ); + QString TheGameIsLockedBNET( ); + QString UnableToCreateGameDisabled( QString gamename ); + QString BotDisabled( ); + QString BotEnabled( ); + QString UnableToCreateGameInvalidMap( QString gamename ); + QString WaitingForPlayersBeforeAutoStart( QString players, QString playersleft ); + QString AutoStartDisabled( ); + QString AutoStartEnabled( QString players ); + QString AnnounceMessageEnabled( ); + QString AnnounceMessageDisabled( ); + QString AutoHostEnabled( ); + QString AutoHostDisabled( ); + QString UnableToLoadSaveGamesOutside( ); + QString UnableToLoadSaveGameGameInLobby( ); + QString LoadingSaveGame( QString file ); + QString UnableToLoadSaveGameDoesntExist( QString file ); + QString UnableToCreateGameInvalidSaveGame( QString gamename ); + QString UnableToCreateGameSaveGameMapMismatch( QString gamename ); + QString AutoSaveEnabled( ); + QString AutoSaveDisabled( ); + QString DesyncDetected( ); + QString UnableToMuteNoMatchesFound( QString victim ); + QString MutedPlayer( QString victim, QString user ); + QString UnmutedPlayer( QString victim, QString user ); + QString UnableToMuteFoundMoreThanOneMatch( QString victim ); + QString PlayerIsSavingTheGame( QString player ); + QString UpdatingClanList( ); + QString UpdatingFriendsList( ); + QString MultipleIPAddressUsageDetected( QString player, QString others ); + QString UnableToVoteKickAlreadyInProgress( ); + QString UnableToVoteKickNotEnoughPlayers( ); + QString UnableToVoteKickNoMatchesFound( QString victim ); + QString UnableToVoteKickPlayerIsReserved( QString victim ); + QString StartedVoteKick( QString victim, QString user, QString votesneeded ); + QString UnableToVoteKickFoundMoreThanOneMatch( QString victim ); + QString VoteKickPassed( QString victim ); + QString ErrorVoteKickingPlayer( QString victim ); + QString VoteKickAcceptedNeedMoreVotes( QString victim, QString user, QString votes ); + QString VoteKickCancelled( QString victim ); + QString VoteKickExpired( QString victim ); + QString WasKickedByVote( ); + QString TypeYesToVote( QString commandtrigger ); + QString PlayersNotYetPingedAutoStart( QString notpinged ); + QString WasKickedForNotSpoofChecking( ); + QString WasKickedForHavingFurthestScore( QString score, QString average ); + QString PlayerHasScore( QString player, QString score ); + QString RatedPlayersSpread( QString rated, QString total, QString spread ); + QString ErrorListingMaps( ); + QString FoundMaps( QString maps ); + QString NoMapsFound( ); + QString ErrorListingMapConfigs( ); + QString FoundMapConfigs( QString mapconfigs ); + QString NoMapConfigsFound( ); + QString PlayerFinishedLoading( QString user ); + QString PleaseWaitPlayersStillLoading( ); + QString MapDownloadsDisabled( ); + QString MapDownloadsEnabled( ); + QString MapDownloadsConditional( ); + QString SettingHCL( QString HCL ); + QString UnableToSetHCLInvalid( ); + QString UnableToSetHCLTooLong( ); + QString TheHCLIs( QString HCL ); + QString TheHCLIsTooLongUseForceToStart( ); + QString ClearingHCL( ); + QString TryingToRehostAsPrivateGame( QString gamename ); + QString TryingToRehostAsPublicGame( QString gamename ); + QString RehostWasSuccessful( ); + QString TryingToJoinTheGameButBannedByName( QString victim ); + QString TryingToJoinTheGameButBannedByIP( QString victim, QString ip, QString bannedname ); + QString HasBannedName( QString victim ); + QString HasBannedIP( QString victim, QString ip, QString bannedname ); + QString PlayersInGameState( QString number, QString players ); + QString ValidServers( QString servers ); + QString TeamCombinedScore( QString team, QString score ); + QString BalancingSlotsCompleted( ); + QString PlayerWasKickedForFurthestScore( QString name, QString score, QString average ); + QString LocalAdminMessagesEnabled( ); + QString LocalAdminMessagesDisabled( ); + QString WasDroppedDesync( ); + QString WasKickedForHavingLowestScore( QString score ); + QString PlayerWasKickedForLowestScore( QString name, QString score ); + QString ReloadingConfigurationFiles( ); + QString CountDownAbortedSomeoneLeftRecently( ); + QString UnableToCreateGameMustEnforceFirst( QString gamename ); + QString UnableToLoadReplaysOutside( ); + QString LoadingReplay( QString file ); + QString UnableToLoadReplayDoesntExist( QString file ); + QString CommandTrigger( QString trigger ); + QString CantEndGameOwnerIsStillPlaying( QString owner ); + QString CantUnhostGameOwnerIsPresent( QString owner ); + QString WasAutomaticallyDroppedAfterSeconds( QString seconds ); + QString HasLostConnectionTimedOutGProxy( ); + QString HasLostConnectionSocketErrorGProxy( QString error ); + QString HasLostConnectionClosedByRemoteHostGProxy( ); + QString WaitForReconnectSecondsRemain( QString seconds ); + QString WasUnrecoverablyDroppedFromGProxy( ); + QString PlayerReconnectedWithGProxy( QString name ); }; #endif diff --git a/ghost/main.cpp b/ghost/main.cpp index 6f0903d..7dcaa7a 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -57,7 +57,7 @@ void SignalCatcher( int s ) void CONSOLE_Print( QString message ) { - cout << message << endl; + cout << message.toStdString() << endl; // logging @@ -69,18 +69,18 @@ void CONSOLE_Print( QString message ) if( gLogFile.isWritable() ) { - gLogStream << "[" << QTime::currentTime().toString() << "] " << QString::fromStdString(message) << endl; + gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; gLogFile.close(); } } else if( gLogMethod == 2 && gLogFile.isWritable() ) - gLogStream << "[" << QTime::currentTime().toString() << "] " << QString::fromStdString(message) << endl; + gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; } } void DEBUG_Print( QString message ) { - cout << message << endl; + cout << message.toStdString() << endl; } void DEBUG_Print( QByteArray b ) @@ -111,7 +111,7 @@ int main( int argc, char **argv ) CConfig CFG; CFG.Read( "default.cfg" ); CFG.Read( gCFGFile ); - gLogFile.setFileName(QString::fromStdString(CFG.GetString( "bot_log", QString( ) ))); + gLogFile.setFileName(CFG.GetString( "bot_log", QString( ) )); gLogMethod = CFG.GetInt( "bot_logmethod", 1 ); if( !gLogFile.fileName().isEmpty() ) @@ -136,13 +136,13 @@ int main( int argc, char **argv ) if( !gLogFile.fileName().isEmpty() ) { if( gLogMethod == 1 ) - CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile.fileName().toStdString() + "] will not be locked" ); + CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile.fileName() + "] will not be locked" ); else if( gLogMethod == 2 ) { if( gLogFile.error() != QFile::NoError ) - CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile.fileName().toStdString() + "] for appending, logging is disabled" ); + CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile.fileName() + "] for appending, logging is disabled" ); else - CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile.fileName().toStdString() + "] is now locked" ); + CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile.fileName() + "] is now locked" ); } } else diff --git a/ghost/map.cpp b/ghost/map.cpp index 6420ba5..3a7889a 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -268,7 +268,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) HANDLE MapMPQ; bool MapMPQReady = false; - if( SFileOpenArchive( MapMPQFileName.c_str( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &MapMPQ ) ) + if( SFileOpenArchive( MapMPQFileName.toStdString().c_str(), 0, MPQ_OPEN_FORCE_MPQ_V1, &MapMPQ ) ) { CONSOLE_Print( "[MAP] loading MPQ file [" + MapMPQFileName + "]" ); MapMPQReady = true; @@ -294,7 +294,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // calculate map_info (this is actually the CRC) - MapInfo = UTIL_CreateQByteArray( (uint32_t)m_GHost->m_CRC->FullCRC( (unsigned char *)m_MapData.c_str( ), m_MapData.size( ) ), false ); + MapInfo = UTIL_CreateQByteArray( (uint32_t)m_GHost->m_CRC->FullCRC( m_MapData ), false ); CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_QByteArrayToDecString( MapInfo ) ); // calculate map_crc (this is not the CRC) and map_sha1 @@ -352,8 +352,8 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( !OverrodeCommonJ ) { - Val = Val ^ XORRotateLeft( (unsigned char *)CommonJ.c_str( ), CommonJ.size( ) ); - m_GHost->m_SHA->Update( (unsigned char *)CommonJ.c_str( ), CommonJ.size( ) ); + Val = Val ^ XORRotateLeft( (unsigned char *)CommonJ.toStdString().c_str( ), CommonJ.size( ) ); + m_GHost->m_SHA->Update( (unsigned char *)CommonJ.toStdString().c_str( ), CommonJ.size( ) ); } if( MapMPQReady ) @@ -388,8 +388,8 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( !OverrodeBlizzardJ ) { - Val = Val ^ XORRotateLeft( (unsigned char *)BlizzardJ.c_str( ), BlizzardJ.size( ) ); - m_GHost->m_SHA->Update( (unsigned char *)BlizzardJ.c_str( ), BlizzardJ.size( ) ); + Val = Val ^ XORRotateLeft( (unsigned char *)BlizzardJ.toStdString().c_str( ), BlizzardJ.size( ) ); + m_GHost->m_SHA->Update( (unsigned char *)BlizzardJ.toStdString().c_str( ), BlizzardJ.size( ) ); } Val = ROTL( Val, 3 ); @@ -420,7 +420,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) HANDLE SubFile; - if( SFileOpenFileEx( MapMPQ, (*i).c_str( ), 0, &SubFile ) ) + if( SFileOpenFileEx( MapMPQ, (*i).toStdString().c_str( ), 0, &SubFile ) ) { uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); @@ -460,7 +460,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) unsigned char SHA1[20]; memset( SHA1, 0, sizeof( unsigned char ) * 20 ); m_GHost->m_SHA->GetHash( SHA1 ); - MapSHA1 = UTIL_CreateQByteArray( SHA1, 20 ); + MapSHA1 = QByteArray( SHA1, 20 ); CONSOLE_Print( "[MAP] calculated map_sha1 = " + UTIL_QByteArrayToDecString( MapSHA1 ) ); } else @@ -497,11 +497,11 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) ) { - istringstream ISS( QString( SubFileData, BytesRead ) ); + istringstream ISS( string( SubFileData, BytesRead ) ); // war3map.w3i format found at http://www.wc3campaigns.net/tools/specs/index.html by Zepir/PitzerMike - QString GarbageString; + string GarbageString; uint32_t FileFormat; uint32_t RawMapWidth; uint32_t RawMapHeight; @@ -891,7 +891,7 @@ void CMap :: CheckValid( ) else if( m_MapPath[0] == '\\' ) CONSOLE_Print( "[MAP] warning - map_path starts with '\\', any replays saved by GHost++ will not be playable in Warcraft III" ); - if( m_MapPath.find( '/' ) != QString :: npos ) + if( m_MapPath.indexOf( '/' ) != -1 ) CONSOLE_Print( "[MAP] warning - map_path contains forward slashes '/' but it must use Windows style back slashes '\\'" ); if( m_MapSize.size( ) != 4 ) diff --git a/ghost/map.h b/ghost/map.h index ac3a7d2..319b8ce 100644 --- a/ghost/map.h +++ b/ghost/map.h @@ -96,8 +96,8 @@ class CMap private: bool m_Valid; - string m_CFGFile; - string m_MapPath; // config value: map path + QString m_CFGFile; + QString m_MapPath; // config value: map path QByteArray m_MapSize; // config value: map size (4 bytes) QByteArray m_MapInfo; // config value: map info (4 bytes) -> this is the real CRC QByteArray m_MapCRC; // config value: map crc (4 bytes) -> this is not the real CRC, it's the "xoro" value @@ -113,26 +113,26 @@ class CMap uint32_t m_MapOptions; QByteArray m_MapWidth; // config value: map width (2 bytes) QByteArray m_MapHeight; // config value: map height (2 bytes) - string m_MapType; // config value: map type (for stats class) - string m_MapMatchMakingCategory; // config value: map matchmaking category (for matchmaking) - string m_MapStatsW3MMDCategory; // config value: map stats w3mmd category (for saving w3mmd stats) - string m_MapDefaultHCL; // config value: map default HCL to use (this should really be specified elsewhere and not part of the map config) + QString m_MapType; // config value: map type (for stats class) + QString m_MapMatchMakingCategory; // config value: map matchmaking category (for matchmaking) + QString m_MapStatsW3MMDCategory; // config value: map stats w3mmd category (for saving w3mmd stats) + QString m_MapDefaultHCL; // config value: map default HCL to use (this should really be specified elsewhere and not part of the map config) uint32_t m_MapDefaultPlayerScore; // config value: map default player score (for matchmaking) - string m_MapLocalPath; // config value: map local path + QString m_MapLocalPath; // config value: map local path bool m_MapLoadInGame; - string m_MapData; // the map data itself, for sending the map to players + QString m_MapData; // the map data itself, for sending the map to players uint32_t m_MapNumPlayers; uint32_t m_MapNumTeams; QVector m_Slots; public: CMap( CGHost *nGHost ); - CMap( CGHost *nGHost, CConfig *CFG, string nCFGFile ); + CMap( CGHost *nGHost, CConfig *CFG, QString nCFGFile ); ~CMap( ); bool GetValid( ) { return m_Valid; } - string GetCFGFile( ) { return m_CFGFile; } - string GetMapPath( ) { return m_MapPath; } + QString GetCFGFile( ) { return m_CFGFile; } + QString GetMapPath( ) { return m_MapPath; } QByteArray GetMapSize( ) { return m_MapSize; } QByteArray GetMapInfo( ) { return m_MapInfo; } QByteArray GetMapCRC( ) { return m_MapCRC; } @@ -147,19 +147,19 @@ class CMap unsigned char GetMapLayoutStyle( ); QByteArray GetMapWidth( ) { return m_MapWidth; } QByteArray GetMapHeight( ) { return m_MapHeight; } - string GetMapType( ) { return m_MapType; } - string GetMapMatchMakingCategory( ) { return m_MapMatchMakingCategory; } - string GetMapStatsW3MMDCategory( ) { return m_MapStatsW3MMDCategory; } - string GetMapDefaultHCL( ) { return m_MapDefaultHCL; } + QString GetMapType( ) { return m_MapType; } + QString GetMapMatchMakingCategory( ) { return m_MapMatchMakingCategory; } + QString GetMapStatsW3MMDCategory( ) { return m_MapStatsW3MMDCategory; } + QString GetMapDefaultHCL( ) { return m_MapDefaultHCL; } uint32_t GetMapDefaultPlayerScore( ) { return m_MapDefaultPlayerScore; } - string GetMapLocalPath( ) { return m_MapLocalPath; } + QString GetMapLocalPath( ) { return m_MapLocalPath; } bool GetMapLoadInGame( ) { return m_MapLoadInGame; } - string *GetMapData( ) { return &m_MapData; } + QString *GetMapData( ) { return &m_MapData; } uint32_t GetMapNumPlayers( ) { return m_MapNumPlayers; } uint32_t GetMapNumTeams( ) { return m_MapNumTeams; } QVector GetSlots( ) { return m_Slots; } - void Load( CConfig *CFG, string nCFGFile ); + void Load( CConfig *CFG, QString nCFGFile ); void CheckValid( ); uint32_t XORRotateLeft( unsigned char *data, uint32_t length ); }; diff --git a/ghost/packed.cpp b/ghost/packed.cpp index 35d1908..587f5b7 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -103,7 +103,7 @@ bool CPacked :: Save( bool TFT, QString fileName ) if( m_Valid ) { CONSOLE_Print( "[PACKED] saving data to file [" + fileName + "]" ); - return UTIL_FileWrite( fileName, (unsigned char *)m_Compressed.c_str( ), m_Compressed.size( ) ); + return UTIL_FileWrite( fileName, m_Compressed ); } else return false; @@ -117,7 +117,7 @@ bool CPacked :: Extract( QString inFileName, QString outFileName ) Decompress( true ); if( m_Valid ) - return UTIL_FileWrite( outFileName, (unsigned char *)m_Decompressed.c_str( ), m_Decompressed.size( ) ); + return UTIL_FileWrite( outFileName, m_Decompressed ); else return false; } @@ -130,14 +130,14 @@ bool CPacked :: Pack( bool TFT, QString inFileName, QString outFileName ) Compress( TFT ); if( m_Valid ) - return UTIL_FileWrite( outFileName, (unsigned char *)m_Compressed.c_str( ), m_Compressed.size( ) ); + return UTIL_FileWrite( outFileName, m_Compressed ); else return false; } void CPacked :: Decompress( bool allBlocks ) { - CONSOLE_Print( "[PACKED] decompressing data" ); + /*CONSOLE_Print( "[PACKED] decompressing data" ); // format found at http://www.thehelper.net/forums/showthread.php?t=42787 @@ -278,7 +278,7 @@ void CPacked :: Decompress( bool allBlocks ) CONSOLE_Print( "[PACKED] discarding " + UTIL_ToString( m_Decompressed.size( ) - m_DecompressedSize ) + " bytes" ); m_Decompressed.erase( m_DecompressedSize ); - } + }*/ } void CPacked :: Compress( bool TFT ) @@ -293,10 +293,10 @@ void CPacked :: Compress( bool TFT ) // use a buffer of size 8213 bytes because in the worst case zlib will grow the data 0.1% plus 12 bytes uint32_t CompressedSize = 0; - QString Padded = m_Decompressed; + string Padded = QString(m_Decompressed).toStdString(); Padded.append( 8192 - ( Padded.size( ) % 8192 ), 0 ); - QVector CompressedBlocks; - QString :: size_type Position = 0; + QVector CompressedBlocks; + string :: size_type Position = 0; unsigned char *CompressedData = new unsigned char[8213]; while( Position < Padded.size( ) ) @@ -312,7 +312,7 @@ void CPacked :: Compress( bool TFT ) return; } - CompressedBlocks.push_back( QString( (char *)CompressedData, BlockCompressedLong ) ); + CompressedBlocks.push_back( string( (char *)CompressedData, BlockCompressedLong ) ); CompressedSize += BlockCompressedLong; Position += 8192; } @@ -360,21 +360,21 @@ void CPacked :: Compress( bool TFT ) // calculate header CRC - QString HeaderString = QString( Header.begin( ), Header.end( ) ); - uint32_t CRC = m_CRC->FullCRC( (unsigned char *)HeaderString.c_str( ), HeaderString.size( ) ); + QString HeaderString = Header; + uint32_t CRC = m_CRC->FullCRC( HeaderString ); // overwrite the (currently zero) header CRC with the calculated CRC - Header.erase( Header.end( ) - 4, Header.end( ) ); + Header.remove(Header.size() - 4, 4); UTIL_AppendQByteArray( Header, CRC, false ); // append header - m_Compressed += QString( Header.begin( ), Header.end( ) ); + m_Compressed += Header; // append blocks - for( QVector :: iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) + for( QVector :: const_iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { QByteArray BlockHeader; UTIL_AppendQByteArray( BlockHeader, (uint16_t)(*i).size( ), false ); @@ -386,21 +386,20 @@ void CPacked :: Compress( bool TFT ) // calculate block header CRC - QString BlockHeaderString = QString( BlockHeader.begin( ), BlockHeader.end( ) ); - uint32_t CRC1 = m_CRC->FullCRC( (unsigned char *)BlockHeaderString.c_str( ), BlockHeaderString.size( ) ); + uint32_t CRC1 = m_CRC->FullCRC( BlockHeader ); CRC1 = CRC1 ^ ( CRC1 >> 16 ); - uint32_t CRC2 = m_CRC->FullCRC( (unsigned char *)(*i).c_str( ), (*i).size( ) ); + uint32_t CRC2 = m_CRC->FullCRC( QString::fromStdString(*i) ); CRC2 = CRC2 ^ ( CRC2 >> 16 ); uint32_t BlockCRC = ( CRC1 & 0xFFFF ) | ( CRC2 << 16 ); // overwrite the block header CRC with the calculated CRC - BlockHeader.erase( BlockHeader.end( ) - 4, BlockHeader.end( ) ); + BlockHeader.remove( BlockHeader.size() - 4, 4 ); UTIL_AppendQByteArray( BlockHeader, BlockCRC, false ); // append block header and data - m_Compressed += QString( BlockHeader.begin( ), BlockHeader.end( ) ); - m_Compressed += *i; + m_Compressed += BlockHeader; + m_Compressed += QString::fromStdString(*i); } } diff --git a/ghost/packed.h b/ghost/packed.h index d33b839..6289a21 100644 --- a/ghost/packed.h +++ b/ghost/packed.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -34,8 +34,8 @@ class CPacked protected: bool m_Valid; - string m_Compressed; - string m_Decompressed; + QByteArray m_Compressed; + QByteArray m_Decompressed; uint32_t m_HeaderSize; uint32_t m_CompressedSize; uint32_t m_HeaderVersion; @@ -68,10 +68,10 @@ class CPacked virtual void SetFlags( uint16_t nFlags ) { m_Flags = nFlags; } virtual void SetReplayLength( uint32_t nReplayLength ) { m_ReplayLength = nReplayLength; } - virtual void Load( string fileName, bool allBlocks ); - virtual bool Save( bool TFT, string fileName ); - virtual bool Extract( string inFileName, string outFileName ); - virtual bool Pack( bool TFT, string inFileName, string outFileName ); + virtual void Load( QString fileName, bool allBlocks ); + virtual bool Save( bool TFT, QString fileName ); + virtual bool Extract( QString inFileName, QString outFileName ); + virtual bool Pack( bool TFT, QString inFileName, QString outFileName ); virtual void Decompress( bool allBlocks ); virtual void Compress( bool TFT ); }; diff --git a/ghost/replay.cpp b/ghost/replay.cpp index db9303e..3d8c0cd 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -222,6 +222,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 void CReplay :: ParseReplay( bool parseBlocks ) { + /* m_HostPID = 0; m_HostName.clear( ); m_GameName.clear( ); @@ -579,4 +580,5 @@ void CReplay :: ParseReplay( bool parseBlocks ) CONSOLE_Print( "[REPLAY] warning - replay length mismatch (" + UTIL_ToString( m_ReplayLength ) + "ms/" + UTIL_ToString( ActualReplayLength ) + "ms)" ); m_Valid = true; + */ } diff --git a/ghost/sha1.cpp b/ghost/sha1.cpp index 82fb7fa..a73517e 100644 --- a/ghost/sha1.cpp +++ b/ghost/sha1.cpp @@ -152,7 +152,7 @@ void CSHA1::Final() Transform(m_state, m_buffer); } -// Get the final hash as a pre-formatted string +// Get the final hash as a pre-formatted QString void CSHA1::ReportHash(char *szReport, unsigned char uReportType) { /* diff --git a/ghost/sqlite3.h b/ghost/sqlite3.h index cc4d354..0f620c0 100644 --- a/ghost/sqlite3.h +++ b/ghost/sqlite3.h @@ -84,7 +84,7 @@ extern "C" { ** the sqlite3.h file specify the version of SQLite with which ** that header file is associated. ** -** The "version" of SQLite is a string of the form "X.Y.Z". +** The "version" of SQLite is a QString of the form "X.Y.Z". ** The phrase "alpha" or "beta" might be appended after the Z. ** The X value is major version number always 3 in SQLite3. ** The X value only changes when backwards compatibility is @@ -114,8 +114,8 @@ extern "C" { ** [SQLITE_VERSION_NUMBER]. ** ** The sqlite3_libversion() function returns the same information as is -** in the sqlite3_version[] string constant. The function is provided -** for use in DLLs since DLL users usually do not have direct access to string +** in the sqlite3_version[] QString constant. The function is provided +** for use in DLLs since DLL users usually do not have direct access to QString ** constants within the DLL. ** ** Requirements: [H10021] [H10022] [H10023] @@ -264,8 +264,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** message returned through the 5th parameter when it has finished using ** the error message. ** -** If the SQL statement in the 2nd parameter is NULL or an empty string -** or a string containing only whitespace and comments, then no SQL +** If the SQL statement in the 2nd parameter is NULL or an empty QString +** or a QString containing only whitespace and comments, then no SQL ** statements are evaluated and the database is not changed. ** ** The sqlite3_exec() interface is implemented in terms of @@ -657,9 +657,9 @@ typedef struct sqlite3_mutex sqlite3_mutex; ** be unique across all VFS modules. ** ** SQLite will guarantee that the zFilename parameter to xOpen -** is either a NULL pointer or string obtained +** is either a NULL pointer or QString obtained ** from xFullPathname(). SQLite further guarantees that -** the string will be valid and unchanged until xClose() is +** the QString will be valid and unchanged until xClose() is ** called. Because of the previous sentence, ** the [sqlite3_file] can safely store a pointer to the ** filename if it needs to remember the filename for some reason. @@ -1370,11 +1370,11 @@ void sqlite3_interrupt(sqlite3*); ** These routines are useful during command-line input to determine if the ** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into -** SQLite for parsing. These routines return 1 if the input string +** SQLite for parsing. These routines return 1 if the input QString ** appears to be a complete SQL statement. A statement is judged to be ** complete if it ends with a semicolon token and is not a prefix of a ** well-formed CREATE TRIGGER statement. Semicolons that are embedded within -** string literals or quoted identifier names or comments are not +** QString literals or quoted identifier names or comments are not ** independent tokens (they are part of the token in which they are ** embedded) and thus do not count as a statement terminator. Whitespace ** and comments that follow the final semicolon are ignored. @@ -1397,7 +1397,7 @@ void sqlite3_interrupt(sqlite3*); ** UTF-8 string. ** ** The input to [sqlite3_complete16()] must be a zero-terminated -** UTF-16 string in native byte order. +** UTF-16 QString in native byte order. */ int sqlite3_complete(const char *sql); int sqlite3_complete16(const void *sql); @@ -1511,7 +1511,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms); ** to zero-terminated strings that contain the names of the columns. ** The remaining entries all point to query results. NULL values result ** in NULL pointers. All other values are in their UTF-8 zero-terminated -** string representation as returned by [sqlite3_column_text()]. +** QString representation as returned by [sqlite3_column_text()]. ** ** A result table might consist of one or more memory allocations. ** It is not safe to pass a result table directly to [sqlite3_free()]. @@ -1545,7 +1545,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms); ** ** The sqlite3_get_table() function evaluates one or more ** semicolon-separated SQL statements in the zero-terminated UTF-8 -** string of its 2nd parameter. It returns a result table to the +** QString of its 2nd parameter. It returns a result table to the ** pointer given in its 3rd parameter. ** ** After the calling function has finished using the result, it should @@ -1604,7 +1604,7 @@ void sqlite3_free_table(char **result); ** As long as the buffer size is greater than zero, sqlite3_snprintf() ** guarantees that the buffer is always zero-terminated. The first ** parameter "n" is the total size of the buffer, including space for -** the zero terminator. So the longest string that can be completely +** the zero terminator. So the longest QString that can be completely ** written will be n-1 characters. ** ** These routines all implement some additional formatting @@ -1613,12 +1613,12 @@ void sqlite3_free_table(char **result); ** is are "%q", "%Q", and "%z" options. ** ** The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. By doubling each '\'' +** QString from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a QString literal. By doubling each '\'' ** character it escapes that character and allows it to be inserted into ** the string. ** -** For example, assume the string variable zText contains text as follows: +** For example, assume the QString variable zText contains text as follows: ** **
 **  char *zText = "It's a happy day!";
@@ -1632,7 +1632,7 @@ void sqlite3_free_table(char **result);
 **  sqlite3_free(zSQL);
 ** 
** -** Because the %q format string is used, the '\'' character in zText +** Because the %q format QString is used, the '\'' character in zText ** is escaped and the SQL generated is as follows: ** **
@@ -1647,7 +1647,7 @@ void sqlite3_free_table(char **result);
 ** 
** ** This second example is an SQL syntax error. As a general rule you should -** always use %q instead of %s when inserting text into a string literal. +** always use %q instead of %s when inserting text into a QString literal. ** ** The %Q option works like %q except it also adds single quotes around ** the outside of the total string. Additionally, if the parameter in the @@ -1664,7 +1664,7 @@ void sqlite3_free_table(char **result); ** variable even if the zText variable is a NULL pointer. ** ** The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into +** addition that after the QString has been read and copied into ** the result, [sqlite3_free()] is called on the input string. {END} ** ** Requirements: @@ -2118,9 +2118,9 @@ int sqlite3_open_v2( ** ** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. -** Memory to hold the error message string is managed internally. +** Memory to hold the error message QString is managed internally. ** The application does not need to worry about freeing the result. -** However, the error string might be overwritten or deallocated by +** However, the error QString might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions. ** ** When the serialized [threading mode] is in use, it might be the @@ -2221,7 +2221,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** **
**
SQLITE_LIMIT_LENGTH
-**
The maximum size of any string or BLOB or table row.
+**
The maximum size of any QString or BLOB or table row.
** **
SQLITE_LIMIT_SQL_LENGTH
**
The maximum length of an SQL statement.
@@ -2286,11 +2286,11 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** If the nByte argument is less than zero, then zSql is read up to the ** first zero terminator. If nByte is non-negative, then it is the maximum ** number of bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or +** zSql QString ends at either the first '\000' or '\u0000' character or ** the nByte-th byte, whichever comes first. If the caller knows -** that the supplied string is nul-terminated, then there is a small +** that the supplied QString is nul-terminated, then there is a small ** performance advantage to be gained by passing an nByte parameter that -** is equal to the number of bytes in the input string including +** is equal to the number of bytes in the input QString including ** the nul-terminator bytes. ** ** If pzTail is not NULL then *pzTail is made to point to the first byte @@ -2301,7 +2301,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** *ppStmt is left pointing to a compiled [prepared statement] that can be ** executed using [sqlite3_step()]. If there is an error, *ppStmt is set ** to NULL. If the input text contains no SQL (if the input is an empty -** string or a comment) then *ppStmt is set to NULL. +** QString or a comment) then *ppStmt is set to NULL. ** The calling procedure is responsible for deleting the compiled ** SQL statement using [sqlite3_finalize()] after it has finished with it. ** ppStmt may not be NULL. @@ -2476,12 +2476,12 @@ typedef struct sqlite3_context sqlite3_context; ** In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of bytes in the value, not the number of characters. -** If the fourth parameter is negative, the length of the string is +** If the fourth parameter is negative, the length of the QString is ** the number of bytes up to the first zero terminator. ** ** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** string after SQLite has finished with it. If the fifth argument is +** QString after SQLite has finished with it. If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. ** If the fifth argument has the value [SQLITE_TRANSIENT], then @@ -2559,7 +2559,7 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*); ** This routine returns a pointer to the name of the n-th ** [SQL parameter] in a [prepared statement]. ** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" -** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the QString "?NNN" or ":AAA" or "@AAA" or "$AAA" ** respectively. ** In other words, the initial ":" or "$" or "@" or "?" ** is included as part of the name. @@ -2569,7 +2569,7 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*); ** The first host parameter has an index of 1, not 0. ** ** If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. The returned string is +** nameless, then NULL is returned. The returned QString is ** always in UTF-8 encoding even if the named parameter was ** originally specified as UTF-16 in [sqlite3_prepare16()] or ** [sqlite3_prepare16_v2()]. @@ -2631,13 +2631,13 @@ int sqlite3_column_count(sqlite3_stmt *pStmt); ** ** These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF-8 string +** interface returns a pointer to a zero-terminated UTF-8 QString ** and sqlite3_column_name16() returns a pointer to a zero-terminated ** UTF-16 string. The first parameter is the [prepared statement] ** that implements the [SELECT] statement. The second parameter is the ** column number. The leftmost column is number 0. ** -** The returned string pointer is valid until either the [prepared statement] +** The returned QString pointer is valid until either the [prepared statement] ** is destroyed by [sqlite3_finalize()] or until the next call to ** sqlite3_column_name() or sqlite3_column_name16() on the same column. ** @@ -2665,7 +2665,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*, int N); ** either a UTF-8 or UTF-16 string. The _database_ routines return ** the database name, the _table_ routines return the table name, and ** the origin_ routines return the column name. -** The returned string is valid until the [prepared statement] is destroyed +** The returned QString is valid until the [prepared statement] is destroyed ** using [sqlite3_finalize()] or until the same information is requested ** again in a different encoding. ** @@ -2717,7 +2717,7 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); ** expression or subquery) then the declared type of the table ** column is returned. If the Nth column of the result set is an ** expression or subquery, then a NULL pointer is returned. -** The returned string is always UTF-8 encoded. {END} +** The returned QString is always UTF-8 encoded. {END} ** ** For example, given the database schema: ** @@ -2727,7 +2727,7 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); ** ** SELECT c1 + 1, c1 FROM t1; ** -** this routine would return the string "VARIANT" for the second result +** this routine would return the QString "VARIANT" for the second result ** column (i==1), and a NULL pointer for the first result column (i==0). ** ** SQLite uses dynamic run-time typing. So just because a column @@ -2832,7 +2832,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); **
    **
  • 64-bit signed integer **
  • 64-bit IEEE floating point number -**
  • string +**
  • QString **
  • BLOB **
  • NULL **
{END} @@ -2890,12 +2890,12 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); ** versions of SQLite may change the behavior of sqlite3_column_type() ** following a type conversion. ** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** If the result is a BLOB or UTF-8 QString then the sqlite3_column_bytes() ** routine returns the number of bytes in that BLOB or string. ** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. +** the QString to UTF-8 and then returns the number of bytes. ** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** [sqlite3_snprintf()] to convert that value to a UTF-8 QString and returns ** the number of bytes in that string. ** The value returned does not include the zero terminator at the end ** of the string. For clarity: the value returned is the number of @@ -3229,7 +3229,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void ** except that these routines take a single [protected sqlite3_value] object ** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. ** -** The sqlite3_value_text16() interface extracts a UTF-16 string +** The sqlite3_value_text16() interface extracts a UTF-16 QString ** in the native byte-order of the host machine. The ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces ** extract UTF-16 strings as big-endian and little-endian respectively. @@ -3238,7 +3238,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void ** numeric affinity to the value. This means that an attempt is ** made to convert the value to an integer or floating point. If ** such a conversion is possible without loss of information (in other -** words, if the value is a string that looks like a number) +** words, if the value is a QString that looks like a number) ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned. ** @@ -3338,7 +3338,7 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** function. The compiled version of the regular expression is stored as ** metadata associated with the SQL value passed as the regular expression ** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string +** invocations of the same function so that the original pattern QString ** does not need to be recompiled on each invocation. ** ** The sqlite3_get_auxdata() interface returns a pointer to the metadata @@ -3421,11 +3421,11 @@ typedef void (*sqlite3_destructor_type)(void*); ** ** The sqlite3_result_error() and sqlite3_result_error16() functions ** cause the implemented SQL function to throw an exception. -** SQLite uses the string pointed to by the +** SQLite uses the QString pointed to by the ** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() ** as the text of an error message. SQLite interprets the error -** message string from sqlite3_result_error() as UTF-8. SQLite -** interprets the string from sqlite3_result_error16() as UTF-16 in native +** message QString from sqlite3_result_error() as UTF-8. SQLite +** interprets the QString from sqlite3_result_error16() as UTF-16 in native ** byte order. If the third parameter to sqlite3_result_error() ** or sqlite3_result_error16() is negative then SQLite takes as the error ** message all text up through the first zero character. @@ -3442,7 +3442,7 @@ typedef void (*sqlite3_destructor_type)(void*); ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. ** ** The sqlite3_result_toobig() interface causes SQLite to throw an error -** indicating that a string or BLOB is to long to represent. +** indicating that a QString or BLOB is to long to represent. ** ** The sqlite3_result_nomem() interface causes SQLite to throw an error ** indicating that a memory allocation failed. @@ -3460,7 +3460,7 @@ typedef void (*sqlite3_destructor_type)(void*); ** The sqlite3_result_text(), sqlite3_result_text16(), ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces ** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, +** a text QString which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. ** SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. @@ -3526,9 +3526,9 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n); ** These functions are used to add new collation sequences to the ** [database connection] specified as the first argument. ** -** The name of the new collation sequence is specified as a UTF-8 string +** The name of the new collation sequence is specified as a UTF-8 QString ** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). In all cases +** and a UTF-16 QString for sqlite3_create_collation16(). In all cases ** the name is passed as the second function argument. ** ** The third argument may be one of the constants [SQLITE_UTF8], @@ -3552,7 +3552,7 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n); ** each represented by a (length, data) pair and encoded in the encoding ** that was passed as the third argument when the collation sequence was ** registered. {END} The application defined collation routine should -** return negative, zero or positive if the first string is less than, +** return negative, zero or positive if the first QString is less than, ** equal to, or greater than the second string. i.e. (STRING1 - STRING2). ** ** The sqlite3_create_collation_v2() works like sqlite3_create_collation() @@ -3679,7 +3679,7 @@ int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files {H10310} ** -** If this global variable is made to point to a string which is +** If this global variable is made to point to a QString which is ** the name of a folder (a.k.a. directory), then all temporary files ** created by SQLite will be placed in that directory. If this variable ** is a NULL pointer, then SQLite performs a search for an appropriate @@ -3696,7 +3696,7 @@ int sqlite3_sleep(int); ** ** The [temp_store_directory pragma] may modify this variable and cause ** it to point to memory obtained from [sqlite3_malloc]. Furthermore, -** the [temp_store_directory pragma] always assumes that any string +** the [temp_store_directory pragma] always assumes that any QString ** that this variable points to is held in memory obtained from ** [sqlite3_malloc] and the pragma may attempt to free that memory ** using [sqlite3_free]. @@ -4323,10 +4323,10 @@ SQLITE_EXPERIMENTAL int sqlite3_create_module_v2( ** common to all module implementations. ** ** Virtual tables methods can set an error message by assigning a -** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should -** take care that any prior string is freed by a call to [sqlite3_free()] -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically +** QString obtained from [sqlite3_mprintf()] to zErrMsg. The method should +** take care that any prior QString is freed by a call to [sqlite3_free()] +** prior to assigning a new QString to zErrMsg. After the error message +** is delivered up to the client application, the QString will be automatically ** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { diff --git a/ghost/util.cpp b/ghost/util.cpp index 6b7b8dc..22cafb9 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -390,7 +390,7 @@ QByteArray UTIL_FileRead( QString file ) return f.readAll(); } -bool UTIL_FileWrite( QString file, unsigned char *data, uint32_t length ) +bool UTIL_FileWrite( QString file, const QByteArray &data ) { QFile f(file); f.open(QFile::Truncate); @@ -401,7 +401,7 @@ bool UTIL_FileWrite( QString file, unsigned char *data, uint32_t length ) return false; } - f.write((char*)data, length); + f.write(data); return true; } diff --git a/ghost/util.h b/ghost/util.h index accde08..eec1f78 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -27,7 +27,6 @@ // byte arrays -QByteArray UTIL_CreateQByteArray( unsigned char *a, int size ); QByteArray UTIL_CreateQByteArray( unsigned char c ); QByteArray UTIL_CreateQByteArray( uint16_t i, bool reverse ); QByteArray UTIL_CreateQByteArray( uint32_t i, bool reverse ); @@ -35,7 +34,6 @@ uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start = 0 ); QString UTIL_QByteArrayToDecString( QByteArray b ); QString UTIL_QByteArrayToHexString( QByteArray b ); -void UTIL_AppendQByteArray( QByteArray &b, QByteArray append ); void UTIL_AppendQByteArrayFast( QByteArray &b, QByteArray &append ); void UTIL_AppendQByteArray( QByteArray &b, unsigned char *a, int size ); void UTIL_AppendQByteArray( QByteArray &b, QString append, bool terminator = true ); @@ -71,7 +69,7 @@ QString UTIL_MSToString( uint32_t ms ); bool UTIL_FileExists( QString file ); QByteArray UTIL_FileRead( QString file, uint32_t start, uint32_t length ); QByteArray UTIL_FileRead( QString file ); -bool UTIL_FileWrite( QString file, unsigned char *data, uint32_t length ); +bool UTIL_FileWrite( QString file, const QByteArray &data ); QString UTIL_FileSafeName( QString fileName ); QString UTIL_AddPathSeperator( QString path ); From 6265d9d981c9ff3f2b7ee22b666b57426cca2d96 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Mon, 19 Apr 2010 16:24:38 +0000 Subject: [PATCH 05/69] compiles, but doesnt run, so far changed to qstring, qbytearray, next step, change to qtcpclient --- ghost/bncsutilinterface.cpp | 10 +++++----- ghost/bnetprotocol.cpp | 2 +- ghost/game_base.cpp | 2 +- ghost/gameplayer.cpp | 2 +- ghost/map.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index d5d32bc..a563b84 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -113,7 +113,7 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGON( ) char buf[32]; // nls_get_A( (nls_t *)m_nls, buf ); ( (NLS *)m_NLS )->getPublicKey( buf ); - m_ClientKey = UTIL_CreateQByteArray( (unsigned char *)buf, 32 ); + m_ClientKey = QByteArray( (char *)buf, 32 ); return true; } @@ -124,7 +124,7 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray salt, QBy char buf[20]; // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).toStdString().c_str( ), QString( salt.begin( ), salt.end( ) ).toStdString().c_str( ) ); ( (NLS *)m_NLS )->getClientSessionKey( buf, salt.data(), serverKey.data() ); - m_M1 = UTIL_CreateQByteArray( (unsigned char *)buf, 20 ); + m_M1 = QByteArray( (char *)buf, 20 ); return true; } @@ -134,7 +134,7 @@ bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( QString userPassword ) char buf[20]; hashPassword( userPassword.toStdString().c_str( ), buf ); - m_PvPGNPasswordHash = UTIL_CreateQByteArray( (unsigned char *)buf, 20 ); + m_PvPGNPasswordHash = QByteArray( (char *)buf, 20 ); return true; } @@ -149,11 +149,11 @@ QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToke UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( (uint32_t)key.size( ), false ) ); UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Decoder.getProduct( ), false ) ); UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Decoder.getVal1( ), false ) ); - UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Zeros, 4 ) ); + UTIL_AppendQByteArray( KeyInfo, QByteArray( (char*)Zeros, 4 ) ); size_t Length = Decoder.calculateHash( clientToken, serverToken ); char *buf = new char[Length]; Length = Decoder.getHash( buf ); - UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( (unsigned char *)buf, Length ) ); + UTIL_AppendQByteArray( KeyInfo, QByteArray( buf, Length ) ); delete [] buf; } diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 69a907c..db4e298 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -25,7 +25,7 @@ CBNETProtocol :: CBNETProtocol( ) { unsigned char ClientToken[] = { 220, 1, 203, 7 }; - m_ClientToken = UTIL_CreateQByteArray( ClientToken, 4 ); + m_ClientToken = QByteArray( (char*)ClientToken, 4 ); } CBNETProtocol :: ~CBNETProtocol( ) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 6060305..5204070 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -1123,7 +1123,7 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString if( message.size( ) > 127 ) message = message.mid( 0, 127 ); - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateQByteArray( player->GetPID( ) ), 32, UTIL_CreateQByteArray( ExtraFlags, 4 ), message ) ); + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray( (char*)player->GetPID( ) ), 32, QByteArray( (char*)ExtraFlags, 4 ), message ) ); } } } diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 25d26c9..b6fac76 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -65,7 +65,7 @@ QByteArray CPotentialPlayer :: GetExternalIP( ) if( m_Socket ) return m_Socket->GetIP( ); - return UTIL_CreateQByteArray( Zeros, 4 ); + return QByteArray( (char*)Zeros, 4 ); } QString CPotentialPlayer :: GetExternalIPString( ) diff --git a/ghost/map.cpp b/ghost/map.cpp index 3a7889a..fdcef2c 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -460,7 +460,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) unsigned char SHA1[20]; memset( SHA1, 0, sizeof( unsigned char ) * 20 ); m_GHost->m_SHA->GetHash( SHA1 ); - MapSHA1 = QByteArray( SHA1, 20 ); + MapSHA1 = QByteArray( (char*) SHA1, 20 ); CONSOLE_Print( "[MAP] calculated map_sha1 = " + UTIL_QByteArrayToDecString( MapSHA1 ) ); } else From 6125702867c43c0351d2800e8edf20772f9b3690 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 00:16:21 +0000 Subject: [PATCH 06/69] only one more file until it should compile... well it compiles to be exact, but it doesn't link yet --- ghost/Makefile | 33 +- ghost/bnet.cpp | 18 +- ghost/bnet.h | 1 - ghost/bnlsclient.cpp | 156 +++--- ghost/bnlsclient.h | 24 +- ghost/game.cpp | 27 +- ghost/game.h | 7 +- ghost/game_admin.cpp | 12 +- ghost/game_admin.h | 11 +- ghost/game_base.cpp | 1276 +++++++++++++++++++++--------------------- ghost/game_base.h | 64 ++- ghost/gameplayer.cpp | 369 ++++++------ ghost/gameplayer.h | 51 +- ghost/ghost.cpp | 260 ++++----- ghost/ghost.h | 12 +- ghost/ghost.pro | 150 +++-- 16 files changed, 1275 insertions(+), 1196 deletions(-) diff --git a/ghost/Makefile b/ghost/Makefile index c658838..05fbd17 100644 --- a/ghost/Makefile +++ b/ghost/Makefile @@ -1,6 +1,6 @@ ############################################################################# # Makefile for building: ghost -# Generated by qmake (2.01a) (Qt 4.6.2) on: Mon Apr 19 15:36:38 2010 +# Generated by qmake (2.01a) (Qt 4.6.2) on: Tue Apr 20 01:52:45 2010 # Project: ghost.pro # Template: app # Command: /usr/bin/qmake -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro @@ -16,7 +16,7 @@ CXXFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES) INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtNetwork -I/usr/include/qt4/QtSql -I/usr/include/qt4 -I../StormLib -I../bncsutil/src -I. LINK = g++ LFLAGS = -Wl,-rpath,/usr/lib/qt4 -LIBS = $(SUBLIBS) -L/usr/lib/qt4 -L../StormLib/stormlib -L../bncsutil/src/bncsutil -lbncsutil -lStorm -lboost_date_time-mt -lboost_thread-mt -lboost_system-mt -lboost_filesystem-mt -lQtSql -L/usr/lib/mysql -L/usr/lib/qt4 -lQtNetwork -lQtCore -lgthread-2.0 -lrt -lglib-2.0 -lpthread +LIBS = $(SUBLIBS) -L/usr/lib/qt4 -L../StormLib/stormlib -L../bncsutil/src/bncsutil -lbncsutil -lStorm -lQtSql -L/usr/lib/mysql -L/usr/lib/qt4 -lQtNetwork -lQtCore -lgthread-2.0 -lrt -lglib-2.0 -lpthread AR = ar cqs RANLIB = QMAKE = /usr/bin/qmake @@ -74,7 +74,9 @@ SOURCES = util.cpp \ bnetprotocol.cpp \ bnet.cpp \ bncsutilinterface.cpp \ - main.cpp moc_ghost.cpp + main.cpp moc_ghost.cpp \ + moc_gameplayer.cpp \ + moc_game_base.cpp OBJECTS = util.o \ statsw3mmd.o \ statsdota.o \ @@ -107,7 +109,9 @@ OBJECTS = util.o \ bnet.o \ bncsutilinterface.o \ main.o \ - moc_ghost.o + moc_ghost.o \ + moc_gameplayer.o \ + moc_game_base.o DIST = /usr/share/qt4/mkspecs/common/g++.conf \ /usr/share/qt4/mkspecs/common/unix.conf \ /usr/share/qt4/mkspecs/common/linux.conf \ @@ -228,14 +232,25 @@ mocclean: compiler_moc_header_clean compiler_moc_source_clean mocables: compiler_moc_header_make_all compiler_moc_source_make_all -compiler_moc_header_make_all: moc_ghost.cpp +compiler_moc_header_make_all: moc_ghost.cpp moc_gameplayer.cpp moc_game_base.cpp compiler_moc_header_clean: - -$(DEL_FILE) moc_ghost.cpp + -$(DEL_FILE) moc_ghost.cpp moc_gameplayer.cpp moc_game_base.cpp moc_ghost.cpp: includes.h \ ms_stdint.h \ ghost.h /usr/bin/moc $(DEFINES) $(INCPATH) ghost.h -o moc_ghost.cpp +moc_gameplayer.cpp: includes.h \ + ms_stdint.h \ + gameplayer.h + /usr/bin/moc $(DEFINES) $(INCPATH) gameplayer.h -o moc_gameplayer.cpp + +moc_game_base.cpp: includes.h \ + ms_stdint.h \ + gameslot.h \ + game_base.h + /usr/bin/moc $(DEFINES) $(INCPATH) game_base.h -o moc_game_base.cpp + compiler_rcc_make_all: compiler_rcc_clean: compiler_image_collection_make_all: qmake_image_collection.cpp @@ -584,6 +599,12 @@ main.o: main.cpp ghost.h \ moc_ghost.o: moc_ghost.cpp $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_ghost.o moc_ghost.cpp +moc_gameplayer.o: moc_gameplayer.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_gameplayer.o moc_gameplayer.cpp + +moc_game_base.o: moc_game_base.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_game_base.o moc_game_base.cpp + ####### Install install: FORCE diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index b01c8b0..e26fd87 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -198,9 +198,6 @@ unsigned int CBNET :: SetFD( void *fd, void *send_fd, int *nfds ) { m_Socket->SetFD( (fd_set *)fd, (fd_set *)send_fd, nfds ); NumFDs++; - - if( m_BNLSClient ) - NumFDs += m_BNLSClient->SetFD( fd, send_fd, nfds ); } return NumFDs; @@ -487,19 +484,10 @@ bool CBNET :: Update( void *fd, void *send_fd ) if( m_BNLSClient ) { - if( m_BNLSClient->Update( fd, send_fd ) ) - { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] deleting BNLS client" ); - delete m_BNLSClient; - m_BNLSClient = NULL; - } - else - { - QByteArray WardenResponse = m_BNLSClient->GetWardenResponse( ); + QByteArray WardenResponse = m_BNLSClient->GetWardenResponse( ); - if( !WardenResponse.isEmpty( ) ) - m_Socket->PutBytes( m_Protocol->SEND_SID_WARDEN( WardenResponse ) ); - } + if( !WardenResponse.isEmpty( ) ) + m_Socket->PutBytes( m_Protocol->SEND_SID_WARDEN( WardenResponse ) ); } // check if at least one packet is waiting to be sent and if we've waited long enough to prevent flooding diff --git a/ghost/bnet.h b/ghost/bnet.h index e135dba..427e05b 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -58,7 +58,6 @@ class CBNET { public: CGHost *m_GHost; - private: CTCPClient *m_Socket; // the connection to battle.net CBNETProtocol *m_Protocol; // battle.net protocol diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index 7e08aa9..a278aa5 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -31,7 +31,16 @@ CBNLSClient :: CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCookie ) { - m_Socket = new CTCPClient( ); + m_Socket = new QTcpSocket( ); + + QObject::connect(m_Socket, SIGNAL(connected()), this, SLOT(socketConnected())); + QObject::connect(m_Socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); + QObject::connect(m_Socket, SIGNAL(readyRead()), this, SLOT(socketDataReady())); + QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); + QObject::connect(&m_NULLTimer, SIGNAL(timeout()), this, SLOT(timeout_NULL())); + + m_NULLTimer.setInterval(50); + m_Protocol = new CBNLSProtocol( ); m_WasConnected = false; m_Server = nServer; @@ -40,125 +49,106 @@ CBNLSClient :: CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCoo m_WardenCookie = nWardenCookie; m_TotalWardenIn = 0; m_TotalWardenOut = 0; + m_Retries = 0; } -CBNLSClient :: ~CBNLSClient( ) +void CBNLSClient::socketConnect() { - delete m_Socket; - delete m_Protocol; + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connecting to server [" + m_Server + "] on port " + UTIL_ToString( m_Port ) ); + m_Socket->connectToHost( QHostAddress(m_Server), m_Port ); + m_Retries++; +} - while( !m_Packets.isEmpty( ) ) - { - delete m_Packets.front( ); - m_Packets.dequeue( ); - } +void CBNLSClient::socketConnected() +{ + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connected" ); + m_WasConnected = true; + m_NULLTimer.start(); } -QByteArray CBNLSClient :: GetWardenResponse( ) +void CBNLSClient::socketDisconnected() { - QByteArray WardenResponse; + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] disconnected from BNLS server" ); + m_Socket->deleteLater(); + m_Socket = new QTcpSocket(); - if( !m_WardenResponses.isEmpty( ) ) + if (m_Retries > 6) { - WardenResponse = m_WardenResponses.front( ); - m_WardenResponses.dequeue( ); - m_TotalWardenOut++; + CONSOLE_Print("[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] giving up after 5 failed retries." ); + deleteLater(); + return; } - return WardenResponse; + QTimer::singleShot(5000, this, SLOT(socketConnect())); + } -unsigned int CBNLSClient :: SetFD( void *fd, void *send_fd, int *nfds ) +void CBNLSClient::timeout_NULL() { - if( !m_Socket->HasError( ) && m_Socket->GetConnected( ) ) - { - m_Socket->SetFD( (fd_set *)fd, (fd_set *)send_fd, nfds ); - return 1; - } - - return 0; + m_Socket->write( m_Protocol->SEND_BNLS_NULL( ) ); } -bool CBNLSClient :: Update( void *fd, void *send_fd ) +void CBNLSClient::socketDataReady() { - if( m_Socket->HasError( ) ) - { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] disconnected from BNLS server due to socket error" ); - return true; - } - - if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && m_WasConnected ) - { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] disconnected from BNLS server" ); - return true; - } - - if( m_Socket->GetConnected( ) ) - { - m_Socket->DoRecv( (fd_set *)fd ); - ExtractPackets( ); - ProcessPackets( ); + ExtractPackets( ); + ProcessPackets( ); - if( GetTime( ) - m_LastNullTime >= 50 ) - { - m_Socket->PutBytes( m_Protocol->SEND_BNLS_NULL( ) ); - m_LastNullTime = GetTime( ); - } + while( !m_OutPackets.isEmpty( ) ) + m_Socket->write( m_OutPackets.dequeue( ) ); +} - while( !m_OutPackets.isEmpty( ) ) - { - m_Socket->PutBytes( m_OutPackets.front( ) ); - m_OutPackets.dequeue( ); - } +void CBNLSClient::socketError() +{ + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] disconnected from BNLS server due to socket error" ); + m_Socket->deleteLater(); + m_Socket = NULL; +} - m_Socket->DoSend( (fd_set *)send_fd ); - return false; - } +CBNLSClient :: ~CBNLSClient( ) +{ + delete m_Socket; + delete m_Protocol; - if( m_Socket->GetConnecting( ) && m_Socket->CheckConnect( ) ) + while( !m_Packets.isEmpty( ) ) { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connected" ); - m_WasConnected = true; - m_LastNullTime = GetTime( ); - return false; + delete m_Packets.front( ); + m_Packets.dequeue( ); } +} - if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && !m_WasConnected ) +QByteArray CBNLSClient :: GetWardenResponse( ) +{ + QByteArray WardenResponse; + + if( !m_WardenResponses.isEmpty( ) ) { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connecting to server [" + m_Server + "] on port " + UTIL_ToString( m_Port ) ); - m_Socket->Connect( QString( ), m_Server, m_Port ); - return false; + WardenResponse = m_WardenResponses.front( ); + m_WardenResponses.dequeue( ); + m_TotalWardenOut++; } - return false; + return WardenResponse; } void CBNLSClient :: ExtractPackets( ) { - QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = RecvBuffer->toUtf8(); - - while( Bytes.size( ) >= 3 ) + while( m_Socket->bytesAvailable() >= 3 ) { - uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false ); + uint16_t Length = UTIL_QByteArrayToUInt16( m_Socket->peek(2), false ); - if( Length >= 3 ) - { - if( Bytes.size( ) >= Length ) - { - m_Packets.enqueue( new CCommandPacket( 0, Bytes[2], Bytes.left(Length) ) ); - *RecvBuffer = RecvBuffer->mid( Length ); - Bytes.remove(0, Length); - } - else - return; - } - else + if( Length < 3 ) { CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] error - received invalid packet from BNLS server (bad length), disconnecting" ); - m_Socket->Disconnect( ); + m_Socket->abort(); + m_Socket->deleteLater(); return; } + + if( m_Socket->bytesAvailable() < Length ) + return; + + QByteArray Bytes = m_Socket->read(Length); + m_Packets.enqueue( new CCommandPacket( 0, Bytes.at(2), Bytes ) ); } } diff --git a/ghost/bnlsclient.h b/ghost/bnlsclient.h index eb05647..a9545b7 100644 --- a/ghost/bnlsclient.h +++ b/ghost/bnlsclient.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -24,15 +24,28 @@ // // CBNLSClient // +#include "includes.h" +#include +#include -class CTCPClient; class CBNLSProtocol; class CCommandPacket; -class CBNLSClient +class CBNLSClient : public QObject { + Q_OBJECT + +public slots: + void socketConnected(); + void socketDisconnected(); + void socketDataReady(); + void socketConnect(); + void socketError(); + void timeout_NULL(); + private: - CTCPClient *m_Socket; // the connection to the BNLS server + QTimer m_NULLTimer; + QTcpSocket *m_Socket; // the connection to the BNLS server CBNLSProtocol *m_Protocol; // battle.net protocol QQueue m_Packets; // queue of incoming packets bool m_WasConnected; @@ -44,6 +57,7 @@ class CBNLSClient QQueue m_WardenResponses; // the warden responses to be sent to battle.net uint32_t m_TotalWardenIn; uint32_t m_TotalWardenOut; + int m_Retries; public: CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCookie ); @@ -55,8 +69,6 @@ class CBNLSClient // processing functions - unsigned int SetFD( void *fd, void *send_fd, int *nfds ); - bool Update( void *fd, void *send_fd ); void ExtractPackets( ); void ProcessPackets( ); diff --git a/ghost/game.cpp b/ghost/game.cpp index 6a7768a..ff50e9d 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -146,7 +146,7 @@ CGame :: ~CGame( ) } } -bool CGame :: Update( void *fd, void *send_fd ) +void CGame::EventCallableUpdateTimeout() { // update callables @@ -293,12 +293,13 @@ bool CGame :: Update( void *fd, void *send_fd ) i++; } - return CBaseGame :: Update( fd, send_fd ); + return CBaseGame::EventCallableUpdateTimeout(); } -void CGame :: EventPlayerDeleted( CGamePlayer *player ) +void CGame :: EventPlayerDeleted() { - CBaseGame :: EventPlayerDeleted( player ); + CGamePlayer *player = (CGamePlayer*)QObject::sender(); + CBaseGame :: EventPlayerDeleted(); // record everything we need to know about the player for storing in the database later // since we haven't stored the game yet (it's not over yet!) we can't link the gameplayer to the game @@ -338,11 +339,11 @@ void CGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *action ) // give the stats class a chance to process the action - if( m_Stats && m_Stats->ProcessAction( action ) && m_GameOverTime == 0 ) + if( m_Stats && m_Stats->ProcessAction( action ) && !m_GameOverTimer.isActive() ) { CONSOLE_Print( "[GAME: " + m_GameName + "] gameover timer started (stats class reported game over)" ); SendEndMessage( ); - m_GameOverTime = GetTime( ); + m_GameOverTimer.start(); } } @@ -1340,7 +1341,6 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } m_CreationTime = GetTime( ); - m_LastRefreshTime = GetTime( ); } // @@ -1372,7 +1372,6 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } m_CreationTime = GetTime( ); - m_LastRefreshTime = GetTime( ); } // @@ -1447,7 +1446,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QByteArray MapHeight; MapHeight.push_back( (char)0 ); MapHeight.push_back( (char)0 ); - m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ) ); + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), + QHostAddress(IP), Port); } else { @@ -1455,7 +1455,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ) ); + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), + QHostAddress(IP), Port); } } } @@ -1612,7 +1613,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { SendAllChat( m_GHost->m_Language->VoteKickCancelled( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); - m_StartedKickVoteTime = 0; + m_VotekickTimer.stop(); } // @@ -1739,7 +1740,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri else { m_KickVotePlayer = LastMatch->GetName( ); - m_StartedKickVoteTime = GetTime( ); + m_VotekickTimer.start(); for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->SetKickVote( false ); @@ -1795,7 +1796,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( m_GHost->m_Language->ErrorVoteKickingPlayer( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); - m_StartedKickVoteTime = 0; + m_VotekickTimer.stop(); } else SendAllChat( m_GHost->m_Language->VoteKickAcceptedNeedMoreVotes( m_KickVotePlayer, User, UTIL_ToString( VotesNeeded - Votes ) ) ); diff --git a/ghost/game.h b/ghost/game.h index 9318d4a..57cffc4 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -42,6 +42,12 @@ typedef pair PairedDPSCheck; class CGame : public CBaseGame { + Q_OBJECT + +public slots: + virtual void EventPlayerDeleted(); + void EventCallableUpdateTimeout(); + protected: CDBBan *m_DBBanLast; // last ban for the !banlast command - this is a pointer to one of the items in m_DBBans QVector m_DBBans; // vector of potential ban data for the database (see the Update function for more info, it's not as straightforward as you might think) @@ -59,7 +65,6 @@ class CGame : public CBaseGame virtual ~CGame( ); virtual bool Update( void *fd, void *send_fd ); - virtual void EventPlayerDeleted( CGamePlayer *player ); virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); virtual void EventGameStarted( ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 2a58b26..f07f5a0 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -39,9 +39,6 @@ #include #include -#include - -using namespace boost :: filesystem; // // CAdminGame @@ -79,7 +76,7 @@ CAdminGame :: ~CAdminGame( ) m_GHost->m_Callables.push_back( i->second ); } -bool CAdminGame :: Update( void *fd, void *send_fd ) +void CAdminGame::EventCallableUpdateTimeout() { // // update callables @@ -265,10 +262,7 @@ bool CAdminGame :: Update( void *fd, void *send_fd ) i++; } - // reset the last reserved seen timer since the admin game should never be considered abandoned - - m_LastReservedSeen = GetTime( ); - return CBaseGame :: Update( fd, send_fd ); + CBaseGame::EventCallableUpdateTimeout(); } void CAdminGame :: SendAdminChat( QString message ) @@ -308,7 +302,7 @@ void CAdminGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoin { // tempbanned, goodbye - potential->GetSocket( )->PutBytes( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_WRONGPASSWORD ) ); + potential->GetSocket( )->write( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_WRONGPASSWORD ) ); potential->SetDeleteMe( true ); CONSOLE_Print( "[ADMINGAME] player [" + joinPlayer->GetName( ) + "] at ip [" + (*i).first + "] is trying to join the game but is tempbanned" ); return; diff --git a/ghost/game_admin.h b/ghost/game_admin.h index 660f822..95bf297 100644 --- a/ghost/game_admin.h +++ b/ghost/game_admin.h @@ -32,6 +32,10 @@ class CCallableBanCount; // class CCallableBanAdd; class CCallableBanRemove; +#include "includes.h" +#include "game_base.h" +#include + typedef pair PairedAdminCount; typedef pair PairedAdminAdd; typedef pair PairedAdminRemove; @@ -43,6 +47,12 @@ typedef pair TempBan; class CAdminGame : public CBaseGame { + Q_OBJECT + +public slots: + void EventCallableReady(); + void EventCallableUpdateTimeout(); + protected: QString m_Password; QVector m_TempBans; @@ -57,7 +67,6 @@ class CAdminGame : public CBaseGame CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ); virtual ~CAdminGame( ); - virtual bool Update( void *fd, void *send_fd ); virtual void SendAdminChat( QString message ); virtual void SendWelcomeMessage( CGamePlayer *player ); virtual void EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 5204070..3d9bbd3 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -50,7 +50,69 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) { m_GHost = nGHost; - m_Socket = new CTCPServer( ); + m_Socket = new QTcpServer(this); + QObject::connect(m_Socket, SIGNAL(newConnection()), this, SLOT(EventNewConnection())); + + m_BroadcastTimer.start(3000); + QObject::connect(&m_BroadcastTimer, SIGNAL(timeout()), this, SLOT(EventBroadcastTimeout())); + + m_RefreshTimer.start(3000); + QObject::connect(&m_RefreshTimer, SIGNAL(timeout()), this, SLOT(EventRefreshTimeout())); + + m_MapDataTimer.start(100); + QObject::connect(&m_MapDataTimer, SIGNAL(timeout()), this, SLOT(EventMapDataTimeout())); + + m_CountdownTimer.setInterval(500); + QObject::connect(&m_CountdownTimer, SIGNAL(timeout()), this, SLOT(EventCountdownTimeout())); + + m_AutostartTimer.start(10000); + QObject::connect(&m_AutostartTimer, SIGNAL(timeout()), this, SLOT(EventAutostartTimeout())); + + m_GameOverTimer.setInterval(60000); + QObject::connect(&m_GameOverTimer, SIGNAL(timeout()), this, SLOT(EventGameOverTimeout())); + + m_VotekickTimer.setInterval(60000); + QObject::connect(&m_VotekickTimer, SIGNAL(timeout()), this, SLOT(EventVotekickTimeout())); + + m_SlotInfoTimer.setInterval(500); + QObject::connect(&m_SlotInfoTimer, SIGNAL(timeout()), this, SLOT(SendAllSlotInfo())); + + m_CallableUpdateTimer.setInterval(200); + QObject::connect(&m_CallableUpdateTimer, SIGNAL(timeout()), this, SLOT(EventCallableUpdateTimeout())); + + m_DownloadCounterTimer.start(1000); + QObject::connect(&m_DownloadCounterTimer, SIGNAL(timeout()), this, SLOT(EventResetDownloadCounter())); + + QObject::connect(&m_AnnounceTimer, SIGNAL(timeout()), this, SLOT(EventAnnounceTimeout())); + + m_DropLaggerTimer.setInterval(60000); + m_DropLaggerTimer.setSingleShot(true); + QObject::connect(&m_DropLaggerTimer, SIGNAL(timeout()), this, SLOT(EventDropLaggerTimeout())); + + m_ResetLagscreenTimer.setInterval(60000); + QObject::connect(&m_ResetLagscreenTimer, SIGNAL(timeout()), this, SLOT(EventResetLagscreenTimeout())); + + m_LoadInGameTimer.setInterval(30000); + QObject::connect(&m_LoadInGameTimer, SIGNAL(timeout()), this, SLOT(EventLoadInGameTimeout())); + + m_LobbyTimeoutTimer.setInterval(m_GHost->m_LobbyTimeLimit * 60000); + m_LobbyTimeoutTimer.setSingleShot(true); + QObject::connect(&m_LobbyTimeoutTimer, SIGNAL(timeout()), this, SLOT(EventLobbyTimeout())); + + m_Latency = m_GHost->m_Latency; + m_SendActionTimer.setInterval(m_Latency); + QObject::connect(&m_SendActionTimer, SIGNAL(timeout()), this, SLOT(EventSendActions())); + + + + + + + + + + + m_Protocol = new CGameProtocol( m_GHost ); m_Map = new CMap( *nMap ); m_SaveGame = nSaveGame; @@ -92,36 +154,23 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 m_HCLCommandString = m_Map->GetMapDefaultHCL( ); m_RandomSeed = GetTicks( ); m_HostCounter = m_GHost->m_HostCounter++; - m_Latency = m_GHost->m_Latency; m_SyncLimit = m_GHost->m_SyncLimit; m_SyncCounter = 0; m_GameTicks = 0; m_CreationTime = GetTime( ); - m_LastPingTime = GetTime( ); - m_LastRefreshTime = GetTime( ); m_LastDownloadTicks = GetTime( ); m_DownloadCounter = 0; - m_LastDownloadCounterResetTicks = GetTicks( ); - m_LastAnnounceTime = 0; - m_AnnounceInterval = 0; - m_LastAutoStartTime = GetTime( ); m_AutoStartPlayers = 0; - m_LastCountDownTicks = 0; m_CountDownCounter = 0; m_StartedLoadingTicks = 0; m_StartPlayers = 0; - m_LastLagScreenResetTime = 0; m_LastActionSentTicks = 0; m_LastActionLateBy = 0; m_StartedLaggingTime = 0; m_LastLagScreenTime = 0; - m_LastReservedSeen = GetTime( ); - m_StartedKickVoteTime = 0; - m_GameOverTime = 0; m_LastPlayerLeaveTicks = 0; m_MinimumScore = 0.0; m_MaximumScore = 0.0; - m_SlotInfoChanged = false; m_Locked = false; m_RefreshMessages = m_GHost->m_RefreshMessages; m_RefreshError = false; @@ -205,8 +254,8 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 else CONSOLE_Print( "[GAME: " + m_GameName + "] attempting to bind to all available addresses" ); - if( m_Socket->Listen( m_GHost->m_BindAddress, m_HostPort ) ) - CONSOLE_Print( "[GAME: " + m_GameName + "] listening on port " + UTIL_ToString( m_HostPort ) ); + if( m_Socket->listen( QHostAddress(m_GHost->m_BindAddress), m_HostPort ) ) + CONSOLE_Print( "[GAME: " + m_GameName + "] listening on port " + UTIL_ToString( m_Socket->serverPort() ) ); else { CONSOLE_Print( "[GAME: " + m_GameName + "] error listening on port " + UTIL_ToString( m_HostPort ) ); @@ -340,166 +389,216 @@ QString CBaseGame :: GetDescription( ) void CBaseGame :: SetAnnounce( uint32_t interval, QString message ) { - m_AnnounceInterval = interval; + m_AnnounceTimer.start(1000 * interval); m_AnnounceMessage = message; - m_LastAnnounceTime = GetTime( ); } -unsigned int CBaseGame :: SetFD( void *fd, void *send_fd, int *nfds ) +void CBaseGame::CheckGameLoaded() { - unsigned int NumFDs = 0; + bool FinishedLoading = true; - if( m_Socket ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - m_Socket->SetFD( (fd_set *)fd, (fd_set *)send_fd, nfds ); - NumFDs++; - } + FinishedLoading = (*i)->GetFinishedLoading( ); - for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) - { - if( (*i)->GetSocket( ) ) - { - (*i)->GetSocket( )->SetFD( (fd_set *)fd, (fd_set *)send_fd, nfds ); - NumFDs++; - } + if( !FinishedLoading ) + break; } - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + if( FinishedLoading ) { - if( (*i)->GetSocket( ) ) - { - (*i)->GetSocket( )->SetFD( (fd_set *)fd, (fd_set *)send_fd, nfds ); - NumFDs++; - } + m_LastActionSentTicks = GetTicks( ); + m_GameLoading = false; + m_GameLoaded = true; + EventGameLoaded( ); + return; } - - return NumFDs; } -bool CBaseGame :: Update( void *fd, void *send_fd ) +void CBaseGame::EventLoadInGameTimeout() { - // update callables + // reset the "lag" screen (the load-in-game screen) every 30 seconds - for( QVector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); ) + bool UsingGProxy = false; + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - if( (*i)->GetReady( ) ) + if( (*i)->GetGProxy( ) ) + UsingGProxy = true; + } + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( (*i)->GetFinishedLoading( ) ) { - double Score = (*i)->GetResult( ); + // stop the lag screen - for( QVector :: iterator j = m_Potentials.begin( ); j != m_Potentials.end( ); j++ ) + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { - if( (*j)->GetJoinPlayer( ) && (*j)->GetJoinPlayer( )->GetName( ) == (*i)->GetName( ) ) - EventPlayerJoinedWithScore( *j, (*j)->GetJoinPlayer( ), Score ); + if( !(*j)->GetFinishedLoading( ) ) + Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j, true ) ); } - m_GHost->m_DB->RecoverCallable( *i ); - delete *i; - i = m_ScoreChecks.erase( i ); + // send an empty update + // this resets the lag screen timer but creates a rather annoying problem + // in order to prevent a desync we must make sure every player receives the exact same "desyncable game data" (updates and player leaves) in the exact same order + // unfortunately we cannot send updates to players who are still loading the map, so we buffer the updates to those players (see the else clause a few lines down for the code) + // in addition to this we must ensure any player leave messages are sent in the exact same position relative to these updates so those must be buffered too + + if( UsingGProxy && !(*i)->GetGProxy( ) ) + { + // we must send empty actions to non-GProxy++ players + // GProxy++ will insert these itself so we don't need to send them to GProxy++ players + // empty actions are used to extend the time a player can use when reconnecting + + for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); + } + + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); + + // start the lag screen + + Send( *i, m_Protocol->SEND_W3GS_START_LAG( m_Players, true ) ); } else - i++; - } + { + // buffer the empty update since the player is still loading the map - // update players + if( UsingGProxy && !(*i)->GetGProxy( ) ) + { + // we must send empty actions to non-GProxy++ players + // GProxy++ will insert these itself so we don't need to send them to GProxy++ players + // empty actions are used to extend the time a player can use when reconnecting - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); ) - { - if( (*i)->Update( fd ) ) - { - EventPlayerDeleted( *i ); - delete *i; - i = m_Players.erase( i ); + for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) + (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); + } + + (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); } - else - i++; } - for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); ) + // add actions to replay + + if( m_Replay ) { - if( (*i)->Update( fd ) ) + if( UsingGProxy ) { - // flush the socket (e.g. in case a rejection message is queued) - - if( (*i)->GetSocket( ) ) - (*i)->GetSocket( )->DoSend( (fd_set *)send_fd ); - - delete *i; - i = m_Potentials.erase( i ); + for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) + m_Replay->AddTimeSlot( 0, QQueue( ) ); } - else - i++; + + m_Replay->AddTimeSlot( 0, QQueue( ) ); } - // create the virtual host player + // Warcraft III doesn't seem to respond to empty actions - if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < 12 ) - CreateVirtualHost( ); + /* if( UsingGProxy ) + m_SyncCounter += m_GProxyEmptyActions; - // unlock the game + m_SyncCounter++; */ +} - if( m_Locked && !GetPlayerFromName( m_OwnerName, false ) ) +void CBaseGame::EventSendActions() +{ + if (m_Lagging) { - SendAllChat( m_GHost->m_Language->GameUnlocked( ) ); - m_Locked = false; + m_SendActionTimer.stop(); + return; } - // ping every 5 seconds - // changed this to ping during game loading as well to hopefully fix some problems with people disconnecting during loading - // changed this to ping during the game as well + // send actions every m_Latency milliseconds + // actions are at the heart of every Warcraft 3 game but luckily we don't need to know their contents to relay them + // we queue player actions in EventPlayerAction then just resend them in batches to all players here - if( GetTime( ) - m_LastPingTime >= 5 ) - { - // note: we must send pings to players who are downloading the map because Warcraft III disconnects from the lobby if it doesn't receive a ping every ~90 seconds - // so if the player takes longer than 90 seconds to download the map they would be disconnected unless we keep sending pings - // todotodo: ignore pings received from players who have recently finished downloading the map + SendAllActions( ); +} - SendAll( m_Protocol->SEND_W3GS_PING_FROM_HOST( ) ); +void CBaseGame::EventBroadcastTimeout() +{ + // we broadcast the game to the local network every 3 seconds so we hijack this timer for our nefarious purposes + // however we only want to broadcast if the countdown hasn't started + // see the !sendlan code later in this file for some more information about how this works + // todotodo: should we send a game cancel message somewhere? we'll need to implement a host counter for it to work - // we also broadcast the game to the local network every 5 seconds so we hijack this timer for our nefarious purposes - // however we only want to broadcast if the countdown hasn't started - // see the !sendlan code later in this file for some more information about how this works - // todotodo: should we send a game cancel message somewhere? we'll need to implement a host counter for it to work + if (m_GameLoading || m_GameLoaded) + { + m_BroadcastTimer.stop(); + return; + } - if( !m_CountDownStarted ) - { - // construct a fixed host counter which will be used to identify players from this "realm" (i.e. LAN) - // the fixed host counter's 4 most significant bits will contain a 4 bit ID (0-15) - // the rest of the fixed host counter will contain the 28 least significant bits of the actual host counter - // since we're destroying 4 bits of information here the actual host counter should not be greater than 2^28 which is a reasonable assumption - // when a player joins a game we can obtain the ID from the received host counter - // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused + // construct a fixed host counter which will be used to identify players from this "realm" (i.e. LAN) + // the fixed host counter's 4 most significant bits will contain a 4 bit ID (0-15) + // the rest of the fixed host counter will contain the 28 least significant bits of the actual host counter + // since we're destroying 4 bits of information here the actual host counter should not be greater than 2^28 which is a reasonable assumption + // when a player joins a game we can obtain the ID from the received host counter + // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused - uint32_t FixedHostCounter = m_HostCounter & 0x0FFFFFFF; + uint32_t FixedHostCounter = m_HostCounter & 0x0FFFFFFF; - if( m_SaveGame ) - { - // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) - - uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; - QByteArray MapWidth; - MapWidth.push_back( (char)0 ); - MapWidth.push_back( (char)0 ); - QByteArray MapHeight; - MapHeight.push_back( (char)0 ); - MapHeight.push_back( (char)0 ); - m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, FixedHostCounter ) ); - } - else - { - // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) - // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) + if( m_SaveGame ) + { + // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) + + uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; + QByteArray MapWidth; + MapWidth.push_back( (char)0 ); + MapWidth.push_back( (char)0 ); + QByteArray MapHeight; + MapHeight.push_back( (char)0 ); + MapHeight.push_back( (char)0 ); + m_GHost->m_UDPSocket->writeDatagram( + m_Protocol->SEND_W3GS_GAMEINFO( + m_GHost->m_TFT, + m_GHost->m_LANWar3Version, + UTIL_CreateQByteArray( MapGameType, false ), + m_Map->GetMapGameFlags( ), + MapWidth, + MapHeight, + m_GameName, + "Varlock", + GetTime( ) - m_CreationTime, + "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), + m_SaveGame->GetMagicNumber( ), + 12, + 12, + m_HostPort, + FixedHostCounter ), + QHostAddress(m_GHost->m_UDPSocket->property("target").toString()), + 6112); + } + else + { + // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) + // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) - uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ) ); - } - } + uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ), + QHostAddress(m_GHost->m_UDPSocket->property("target").toString()), + 6112 ); + } +} - m_LastPingTime = GetTime( ); +void CBaseGame::EventRefreshError() +{ + if (m_GameLoading || m_GameLoaded) + { + m_RefreshTimer.stop(); + return; } + if (m_CountDownStarted) + return; + // auto rehost if there was a refresh error in autohosted games + m_RefreshError = true; - if( m_RefreshError && !m_CountDownStarted && m_GameState == GAME_PUBLIC && !m_GHost->m_AutoHostGameName.isEmpty( ) && m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) + if(m_GameState == GAME_PUBLIC && + !m_GHost->m_AutoHostGameName.isEmpty( ) && + m_GHost->m_AutoHostMaximumGames != 0 && + m_GHost->m_AutoHostAutoStartPlayers != 0 && + m_AutoStartPlayers != 0 ) { // there's a slim chance that this isn't actually an autohosted game since there is no explicit autohost flag // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted @@ -521,12 +620,19 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) } m_CreationTime = GetTime( ); - m_LastRefreshTime = GetTime( ); } +} - // refresh every 3 seconds +void CBaseGame::EventRefreshTimeout() +{ + if (m_GameLoading || m_GameLoaded) + { + m_RefreshTimer.stop(); + return; + } - if( !m_RefreshError && !m_CountDownStarted && m_GameState == GAME_PUBLIC && GetSlotsOpen( ) > 0 && GetTime( ) - m_LastRefreshTime >= 3 ) + // refresh every 3 seconds + if( !m_RefreshError && m_GameState == GAME_PUBLIC && GetSlotsOpen( ) > 0) { // send a game refresh packet to each battle.net connection @@ -547,530 +653,189 @@ bool CBaseGame :: Update( void *fd, void *send_fd ) if( m_RefreshMessages && Refreshed ) SendAllChat( m_GHost->m_Language->GameRefreshed( ) ); - - m_LastRefreshTime = GetTime( ); } +} - // send more map data - - if( !m_GameLoading && !m_GameLoaded && GetTicks( ) - m_LastDownloadCounterResetTicks >= 1000 ) +void CBaseGame::EventResetDownloadCounter() +{ + // 1 Hz + if (m_GameLoading || m_GameLoaded ) { - // hackhack: another timer hijack is in progress here - // since the download counter is reset once per second it's a great place to update the slot info if necessary - - if( m_SlotInfoChanged ) - SendAllSlotInfo( ); - - m_DownloadCounter = 0; - m_LastDownloadCounterResetTicks = GetTicks( ); + m_DownloadCounterTimer.stop(); + return; } - if( !m_GameLoading && !m_GameLoaded && GetTicks( ) - m_LastDownloadTicks >= 100 ) - { - uint32_t Downloaders = 0; - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetDownloadStarted( ) && !(*i)->GetDownloadFinished( ) ) - { - Downloaders++; - - if( m_GHost->m_MaxDownloaders > 0 && Downloaders > m_GHost->m_MaxDownloaders ) - break; - - // send up to 100 pieces of the map at once so that the download goes faster - // if we wait for each MAPPART packet to be acknowledged by the client it'll take a long time to download - // this is because we would have to wait the round trip time (the ping time) between sending every 1442 bytes of map data - // doing it this way allows us to send at least 140 KB in each round trip interval which is much more reasonable - // the theoretical throughput is [140 KB * 1000 / ping] in KB/sec so someone with 100 ping (round trip ping, not LC ping) could download at 1400 KB/sec - // note: this creates a queue of map data which clogs up the connection when the client is on a slower connection (e.g. dialup) - // in this case any changes to the lobby are delayed by the amount of time it takes to send the queued data (i.e. 140 KB, which could be 30 seconds or more) - // for example, players joining and leaving, slot changes, chat messages would all appear to happen much later for the low bandwidth player - // note: the throughput is also limited by the number of times this code is executed each second - // e.g. if we send the maximum amount (140 KB) 10 times per second the theoretical throughput is 1400 KB/sec - // therefore the maximum throughput is 1400 KB/sec regardless of ping and this value slowly diminishes as the player's ping increases - // in addition to this, the throughput is limited by the configuration value bot_maxdownloadspeed - // in summary: the actual throughput is MIN( 140 * 1000 / ping, 1400, bot_maxdownloadspeed ) in KB/sec assuming only one player is downloading the map - - uint32_t MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); - - while( (*i)->GetLastMapPartSent( ) < (*i)->GetLastMapPartAcked( ) + 1442 * 100 && (*i)->GetLastMapPartSent( ) < MapSize ) - { - if( (*i)->GetLastMapPartSent( ) == 0 ) - { - // overwrite the "started download ticks" since this is the first time we've sent any map data to the player - // prior to this we've only determined if the player needs to download the map but it's possible we could have delayed sending any data due to download limits - - (*i)->SetStartedDownloadingTicks( GetTicks( ) ); - } - - // limit the download speed if we're sending too much data - // the download counter is the # of map bytes downloaded in the last second (it's reset once per second) - - if( m_GHost->m_MaxDownloadSpeed > 0 && m_DownloadCounter > m_GHost->m_MaxDownloadSpeed * 1024 ) - break; - - Send( *i, m_Protocol->SEND_W3GS_MAPPART( GetHostPID( ), (*i)->GetPID( ), (*i)->GetLastMapPartSent( ), m_Map->GetMapData( ) ) ); - (*i)->SetLastMapPartSent( (*i)->GetLastMapPartSent( ) + 1442 ); - m_DownloadCounter += 1442; - } - } - } - - m_LastDownloadTicks = GetTicks( ); - } + m_DownloadCounter = 0; +} +void CBaseGame::EventAnnounceTimeout() +{ // announce every m_AnnounceInterval seconds - if( !m_AnnounceMessage.isEmpty( ) && !m_CountDownStarted && GetTime( ) - m_LastAnnounceTime >= m_AnnounceInterval ) + if( m_AnnounceMessage.isEmpty( ) ) { - SendAllChat( m_AnnounceMessage ); - m_LastAnnounceTime = GetTime( ); - } - - // kick players who don't spoof check within 20 seconds when spoof checks are required and the game is autohosted - - if( !m_CountDownStarted && m_GHost->m_RequireSpoofChecks && m_GameState == GAME_PUBLIC && !m_GHost->m_AutoHostGameName.isEmpty( ) && m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) - { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( !(*i)->GetSpoofed( ) && GetTime( ) - (*i)->GetJoinTime( ) >= 20 ) - { - (*i)->SetDeleteMe( true ); - (*i)->SetLeftReason( m_GHost->m_Language->WasKickedForNotSpoofChecking( ) ); - (*i)->SetLeftCode( PLAYERLEAVE_LOBBY ); - OpenSlot( GetSIDFromPID( (*i)->GetPID( ) ), false ); - } - } - } - - // try to auto start every 10 seconds - - if( !m_CountDownStarted && m_AutoStartPlayers != 0 && GetTime( ) - m_LastAutoStartTime >= 10 ) - { - StartCountDownAuto( m_GHost->m_RequireSpoofChecks ); - m_LastAutoStartTime = GetTime( ); + m_AnnounceTimer.stop(); + return; } - // countdown every 500 ms - - if( m_CountDownStarted && GetTicks( ) - m_LastCountDownTicks >= 500 ) - { - if( m_CountDownCounter > 0 ) - { - // we use a countdown counter rather than a "finish countdown time" here because it might alternately round up or down the count - // this sometimes resulted in a countdown of e.g. "6 5 3 2 1" during my testing which looks pretty dumb - // doing it this way ensures it's always "5 4 3 2 1" but each interval might not be *exactly* the same length - - SendAllChat( UTIL_ToString( m_CountDownCounter ) + ". . ." ); - m_CountDownCounter--; - } - else if( !m_GameLoading && !m_GameLoaded ) - EventGameStarted( ); - - m_LastCountDownTicks = GetTicks( ); - } + if (m_CountDownStarted) + return; - // check if the lobby is "abandoned" and needs to be closed since it will never start + SendAllChat( m_AnnounceMessage ); +} - if( !m_GameLoading && !m_GameLoaded && m_AutoStartPlayers == 0 && m_GHost->m_LobbyTimeLimit > 0 ) +void CBaseGame::EventMapDataTimeout() +{ + if (m_GameLoading || m_GameLoaded ) { - // check if there's a player with reserved status in the game - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetReserved( ) ) - m_LastReservedSeen = GetTime( ); - } - - // check if we've hit the time limit - - if( GetTime( ) - m_LastReservedSeen >= m_GHost->m_LobbyTimeLimit * 60 ) - { - CONSOLE_Print( "[GAME: " + m_GameName + "] is over (lobby time limit hit)" ); - return true; - } + m_MapDataTimer.stop(); + return; } - // check if the game is loaded + uint32_t Downloaders = 0; - if( m_GameLoading ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - bool FinishedLoading = true; - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + if( (*i)->GetDownloadStarted( ) && !(*i)->GetDownloadFinished( ) ) { - FinishedLoading = (*i)->GetFinishedLoading( ); + Downloaders++; - if( !FinishedLoading ) + if( m_GHost->m_MaxDownloaders > 0 && Downloaders > m_GHost->m_MaxDownloaders ) break; - } - if( FinishedLoading ) - { - m_LastActionSentTicks = GetTicks( ); - m_GameLoading = false; - m_GameLoaded = true; - EventGameLoaded( ); - } - else - { - // reset the "lag" screen (the load-in-game screen) every 30 seconds - - if( m_LoadInGame && GetTime( ) - m_LastLagScreenResetTime >= 30 ) + // send up to 100 pieces of the map at once so that the download goes faster + // if we wait for each MAPPART packet to be acknowledged by the client it'll take a long time to download + // this is because we would have to wait the round trip time (the ping time) between sending every 1442 bytes of map data + // doing it this way allows us to send at least 140 KB in each round trip interval which is much more reasonable + // the theoretical throughput is [140 KB * 1000 / ping] in KB/sec so someone with 100 ping (round trip ping, not LC ping) could download at 1400 KB/sec + // note: this creates a queue of map data which clogs up the connection when the client is on a slower connection (e.g. dialup) + // in this case any changes to the lobby are delayed by the amount of time it takes to send the queued data (i.e. 140 KB, which could be 30 seconds or more) + // for example, players joining and leaving, slot changes, chat messages would all appear to happen much later for the low bandwidth player + // note: the throughput is also limited by the number of times this code is executed each second + // e.g. if we send the maximum amount (140 KB) 10 times per second the theoretical throughput is 1400 KB/sec + // therefore the maximum throughput is 1400 KB/sec regardless of ping and this value slowly diminishes as the player's ping increases + // in addition to this, the throughput is limited by the configuration value bot_maxdownloadspeed + // in summary: the actual throughput is MIN( 140 * 1000 / ping, 1400, bot_maxdownloadspeed ) in KB/sec assuming only one player is downloading the map + + uint32_t MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); + + while( (*i)->GetLastMapPartSent( ) < (*i)->GetLastMapPartAcked( ) + 1442 * 100 && (*i)->GetLastMapPartSent( ) < MapSize ) { - bool UsingGProxy = false; - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetGProxy( ) ) - UsingGProxy = true; - } - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + if( (*i)->GetLastMapPartSent( ) == 0 ) { - if( (*i)->GetFinishedLoading( ) ) - { - // stop the lag screen - - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) - { - if( !(*j)->GetFinishedLoading( ) ) - Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j, true ) ); - } - - // send an empty update - // this resets the lag screen timer but creates a rather annoying problem - // in order to prevent a desync we must make sure every player receives the exact same "desyncable game data" (updates and player leaves) in the exact same order - // unfortunately we cannot send updates to players who are still loading the map, so we buffer the updates to those players (see the else clause a few lines down for the code) - // in addition to this we must ensure any player leave messages are sent in the exact same position relative to these updates so those must be buffered too - - if( UsingGProxy && !(*i)->GetGProxy( ) ) - { - // we must send empty actions to non-GProxy++ players - // GProxy++ will insert these itself so we don't need to send them to GProxy++ players - // empty actions are used to extend the time a player can use when reconnecting - - for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); - } - - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); - - // start the lag screen - - Send( *i, m_Protocol->SEND_W3GS_START_LAG( m_Players, true ) ); - } - else - { - // buffer the empty update since the player is still loading the map - - if( UsingGProxy && !(*i)->GetGProxy( ) ) - { - // we must send empty actions to non-GProxy++ players - // GProxy++ will insert these itself so we don't need to send them to GProxy++ players - // empty actions are used to extend the time a player can use when reconnecting + // overwrite the "started download ticks" since this is the first time we've sent any map data to the player + // prior to this we've only determined if the player needs to download the map but it's possible we could have delayed sending any data due to download limits - for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); - } - - (*i)->AddLoadInGameData( m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); - } - } - - // add actions to replay - - if( m_Replay ) - { - if( UsingGProxy ) - { - for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) - m_Replay->AddTimeSlot( 0, QQueue( ) ); - } - - m_Replay->AddTimeSlot( 0, QQueue( ) ); + (*i)->SetStartedDownloadingTicks( GetTicks( ) ); } - // Warcraft III doesn't seem to respond to empty actions + // limit the download speed if we're sending too much data + // the download counter is the # of map bytes downloaded in the last second (it's reset once per second) - /* if( UsingGProxy ) - m_SyncCounter += m_GProxyEmptyActions; - - m_SyncCounter++; */ - m_LastLagScreenResetTime = GetTime( ); - } - } - } - - // keep track of the largest sync counter (the number of keepalive packets received by each player) - // if anyone falls behind by more than m_SyncLimit keepalives we start the lag screen - - if( m_GameLoaded ) - { - // check if anyone has started lagging - // we consider a player to have started lagging if they're more than m_SyncLimit keepalives behind - - if( !m_Lagging ) - { - QString LaggingString; - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( m_SyncCounter - (*i)->GetSyncCounter( ) > m_SyncLimit ) - { - (*i)->SetLagging( true ); - (*i)->SetStartedLaggingTicks( GetTicks( ) ); - m_Lagging = true; - m_StartedLaggingTime = GetTime( ); - - if( LaggingString.isEmpty( ) ) - LaggingString = (*i)->GetName( ); - else - LaggingString += ", " + (*i)->GetName( ); - } - } - - if( m_Lagging ) - { - // start the lag screen - - CONSOLE_Print( "[GAME: " + m_GameName + "] started lagging on [" + LaggingString + "]" ); - SendAll( m_Protocol->SEND_W3GS_START_LAG( m_Players ) ); - - // reset everyone's drop vote - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - (*i)->SetDropVote( false ); - - m_LastLagScreenResetTime = GetTime( ); - } - } - - if( m_Lagging ) - { - bool UsingGProxy = false; - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetGProxy( ) ) - UsingGProxy = true; - } - - uint32_t WaitTime = 60; - - if( UsingGProxy ) - WaitTime = ( m_GProxyEmptyActions + 1 ) * 60; - - if( GetTime( ) - m_StartedLaggingTime >= WaitTime ) - StopLaggers( m_GHost->m_Language->WasAutomaticallyDroppedAfterSeconds( UTIL_ToString( WaitTime ) ) ); - - // we cannot allow the lag screen to stay up for more than ~65 seconds because Warcraft III disconnects if it doesn't receive an action packet at least this often - // one (easy) solution is to simply drop all the laggers if they lag for more than 60 seconds - // another solution is to reset the lag screen the same way we reset it when using load-in-game - // this is required in order to give GProxy++ clients more time to reconnect - - if( GetTime( ) - m_LastLagScreenResetTime >= 60 ) - { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - // stop the lag screen - - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) - { - if( (*j)->GetLagging( ) ) - Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j ) ); - } - - // send an empty update - // this resets the lag screen timer - - if( UsingGProxy && !(*i)->GetGProxy( ) ) - { - // we must send additional empty actions to non-GProxy++ players - // GProxy++ will insert these itself so we don't need to send them to GProxy++ players - // empty actions are used to extend the time a player can use when reconnecting - - for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); - } - - Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); - - // start the lag screen - - Send( *i, m_Protocol->SEND_W3GS_START_LAG( m_Players ) ); - } - - // add actions to replay - - if( m_Replay ) - { - if( UsingGProxy ) - { - for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) - m_Replay->AddTimeSlot( 0, QQueue( ) ); - } - - m_Replay->AddTimeSlot( 0, QQueue( ) ); - } - - // Warcraft III doesn't seem to respond to empty actions - - /* if( UsingGProxy ) - m_SyncCounter += m_GProxyEmptyActions; - - m_SyncCounter++; */ - m_LastLagScreenResetTime = GetTime( ); - } - - // check if anyone has stopped lagging normally - // we consider a player to have stopped lagging if they're less than half m_SyncLimit keepalives behind - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetLagging( ) && m_SyncCounter - (*i)->GetSyncCounter( ) < m_SyncLimit / 2 ) - { - // stop the lag screen for this player - - CONSOLE_Print( "[GAME: " + m_GameName + "] stopped lagging on [" + (*i)->GetName( ) + "]" ); - SendAll( m_Protocol->SEND_W3GS_STOP_LAG( *i ) ); - (*i)->SetLagging( false ); - (*i)->SetStartedLaggingTicks( 0 ); - } - } - - // check if everyone has stopped lagging - - bool Lagging = false; + if( m_GHost->m_MaxDownloadSpeed > 0 && m_DownloadCounter > m_GHost->m_MaxDownloadSpeed * 1024 ) + break; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetLagging( ) ) - Lagging = true; + Send( *i, m_Protocol->SEND_W3GS_MAPPART( GetHostPID( ), (*i)->GetPID( ), (*i)->GetLastMapPartSent( ), m_Map->GetMapData( ) ) ); + (*i)->SetLastMapPartSent( (*i)->GetLastMapPartSent( ) + 1442 ); + m_DownloadCounter += 1442; } - - m_Lagging = Lagging; - - // reset m_LastActionSentTicks because we want the game to stop running while the lag screen is up - - m_LastActionSentTicks = GetTicks( ); - - // keep track of the last lag screen time so we can avoid timing out players - - m_LastLagScreenTime = GetTime( ); } } +} - // send actions every m_Latency milliseconds - // actions are at the heart of every Warcraft 3 game but luckily we don't need to know their contents to relay them - // we queue player actions in EventPlayerAction then just resend them in batches to all players here - - if( m_GameLoaded && !m_Lagging && GetTicks( ) - m_LastActionSentTicks >= m_Latency - m_LastActionLateBy ) - SendAllActions( ); - - // expire the votekick - - if( !m_KickVotePlayer.isEmpty( ) && GetTime( ) - m_StartedKickVoteTime >= 60 ) +void CBaseGame::EventCountdownTimeout() +{ + if( m_CountDownCounter > 0 ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] expired" ); - SendAllChat( m_GHost->m_Language->VoteKickExpired( m_KickVotePlayer ) ); - m_KickVotePlayer.clear( ); - m_StartedKickVoteTime = 0; - } + // we use a countdown counter rather than a "finish countdown time" here because it might alternately round up or down the count + // this sometimes resulted in a countdown of e.g. "6 5 3 2 1" during my testing which looks pretty dumb + // doing it this way ensures it's always "5 4 3 2 1" but each interval might not be *exactly* the same length - // start the gameover timer if there's only one player left + SendAllChat( UTIL_ToString( m_CountDownCounter ) + ". . ." ); + m_CountDownCounter--; + } + else if( !m_GameLoading && !m_GameLoaded ) + EventGameStarted( ); +} - if( m_Players.size( ) == 1 && m_FakePlayerPID == 255 && m_GameOverTime == 0 && ( m_GameLoading || m_GameLoaded ) ) +void CBaseGame::EventAutostartTimeout() +{ + if (m_GameLoading || m_GameLoaded) { - CONSOLE_Print( "[GAME: " + m_GameName + "] gameover timer started (one player left)" ); - m_GameOverTime = GetTime( ); + m_AutostartTimer.stop(); + return; } - // finish the gameover timer - - if( m_GameOverTime != 0 && GetTime( ) - m_GameOverTime >= 60 ) - { - bool AlreadyStopped = true; + // try to auto start every 10 seconds - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( !(*i)->GetDeleteMe( ) ) - { - AlreadyStopped = false; - break; - } - } + if( m_CountDownStarted || m_AutoStartPlayers == 0 ) + return; - if( !AlreadyStopped ) - { - CONSOLE_Print( "[GAME: " + m_GameName + "] is over (gameover timer finished)" ); - StopPlayers( "was disconnected (gameover timer finished)" ); - } - } + StartCountDownAuto( m_GHost->m_RequireSpoofChecks ); +} - // end the game if there aren't any players left +void CBaseGame::EventGameOverTimeout() +{ + bool AlreadyStopped = true; - if( m_Players.isEmpty( ) && ( m_GameLoading || m_GameLoaded ) ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - if( !m_Saving ) + if( !(*i)->GetDeleteMe( ) ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] is over (no players left)" ); - SaveGameData( ); - m_Saving = true; + AlreadyStopped = false; + break; } - else if( IsGameDataSaved( ) ) - return true; } - // accept new connections - - if( m_Socket ) + if( !AlreadyStopped ) { - CTCPSocket *NewSocket = m_Socket->Accept( (fd_set *)fd ); + CONSOLE_Print( "[GAME: " + m_GameName + "] is over (gameover timer finished)" ); + StopPlayers( "was disconnected (gameover timer finished)" ); + } +} - if( NewSocket ) - { - // check the IP blacklist +void CBaseGame::EventVotekickTimeout() +{ + // expire the votekick - if( m_IPBlackList.find( NewSocket->GetIPString( ) ) == m_IPBlackList.end( ) ) - { - if( m_GHost->m_TCPNoDelay ) - NewSocket->SetNoDelay( true ); + if( m_KickVotePlayer.isEmpty( ) ) + return; - m_Potentials.push_back( new CPotentialPlayer( m_Protocol, this, NewSocket ) ); - } - else - { - CONSOLE_Print( "[GAME: " + m_GameName + "] rejected connection from [" + NewSocket->GetIPString( ) + "] due to blacklist" ); - delete NewSocket; - } - } + CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] expired" ); + SendAllChat( m_GHost->m_Language->VoteKickExpired( m_KickVotePlayer ) ); + m_KickVotePlayer.clear( ); +} - if( m_Socket->HasError( ) ) - return true; - } +void CBaseGame::EventLobbyTimeout() +{ + if( m_GameLoading || m_GameLoaded || m_AutoStartPlayers != 0) + return; - return m_Exiting; + // check if we've hit the time limit + + CONSOLE_Print( "[GAME: " + m_GameName + "] is over (lobby time limit hit)" ); + deleteLater(); } -void CBaseGame :: UpdatePost( void *send_fd ) +void CBaseGame::EventNewConnection() { - // we need to manually call DoSend on each player now because CGamePlayer :: Update doesn't do it - // this is in case player 2 generates a packet for player 1 during the update but it doesn't get sent because player 1 already finished updating - // in reality since we're queueing actions it might not make a big difference but oh well + QTcpSocket *NewSocket = m_Socket->nextPendingConnection(); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetSocket( ) ) - (*i)->GetSocket( )->DoSend( (fd_set *)send_fd ); - } + if( !NewSocket ) + return; - for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + // check the IP blacklist + if( m_IPBlackList.find( NewSocket->localAddress().toString() ) != m_IPBlackList.end( ) ) { - if( (*i)->GetSocket( ) ) - (*i)->GetSocket( )->DoSend( (fd_set *)send_fd ); + CONSOLE_Print( "[GAME: " + m_GameName + "] rejected connection from [" + NewSocket->localAddress().toString() + "] due to blacklist" ); + NewSocket->deleteLater(); + return; } + + if( m_GHost->m_TCPNoDelay ) + NewSocket->setSocketOption(QAbstractSocket::LowDelayOption, true); + + new CPotentialPlayer( m_Protocol, this, NewSocket ); } void CBaseGame :: Send( CGamePlayer *player, QByteArray data ) @@ -1204,10 +969,7 @@ void CBaseGame :: SendLocalAdminChat( QString message ) void CBaseGame :: SendAllSlotInfo( ) { if( !m_GameLoading && !m_GameLoaded ) - { SendAll( m_Protocol->SEND_W3GS_SLOTINFO( m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); - m_SlotInfoChanged = false; - } } void CBaseGame :: SendVirtualHostPlayerInfo( CGamePlayer *player ) @@ -1276,6 +1038,7 @@ void CBaseGame :: SendAllActions( ) m_SyncCounter += m_GProxyEmptyActions; */ m_SyncCounter++; + CheckPlayersStartedLaggging(); // we aren't allowed to send more than 1460 bytes in a single packet but it's possible we might have more than that many bytes waiting in the queue @@ -1407,10 +1170,237 @@ void CBaseGame :: SendEndMessage( ) } } -void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) +void CBaseGame::CheckPlayersStartedLaggging() +{ + // check if anyone has started lagging + // we consider a player to have started lagging if they're more than m_SyncLimit keepalives behind + + if( m_Lagging ) + return; + + + bool UsingGProxy = false; + + m_WaitTime = 60; + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( (*i)->GetGProxy( ) ) + { + if( UsingGProxy ) + m_WaitTime = ( m_GProxyEmptyActions + 1 ) * 60; + + break; + } + } + + QString LaggingString; + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( m_SyncCounter - (*i)->GetSyncCounter( ) > m_SyncLimit ) + { + (*i)->SetLagging( true ); + (*i)->SetStartedLaggingTicks( GetTicks( ) ); + m_Lagging = true; + m_StartedLaggingTime = GetTime( ); + + m_DropLaggerTimer.start(m_WaitTime*1000); + + if( LaggingString.isEmpty( ) ) + LaggingString = (*i)->GetName( ); + else + LaggingString += ", " + (*i)->GetName( ); + } + } + + if( m_Lagging ) + { + // start the lag screen + + CONSOLE_Print( "[GAME: " + m_GameName + "] started lagging on [" + LaggingString + "]" ); + SendAll( m_Protocol->SEND_W3GS_START_LAG( m_Players ) ); + + // reset everyone's drop vote + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + (*i)->SetDropVote( false ); + + m_ResetLagscreenTimer.start(); + } +} + +void CBaseGame::EventDropLaggerTimeout() +{ + StopLaggers( m_GHost->m_Language->WasAutomaticallyDroppedAfterSeconds( UTIL_ToString(m_WaitTime) ) ); +} + +void CBaseGame::EventResetLagscreenTimeout() +{ + if (!m_Lagging) + { + m_ResetLagscreenTimer.stop(); + return; + } + + bool UsingGProxy = false; + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( (*i)->GetGProxy( ) ) + UsingGProxy = true; + } + + // we cannot allow the lag screen to stay up for more than ~65 seconds because Warcraft III disconnects if it doesn't receive an action packet at least this often + // one (easy) solution is to simply drop all the laggers if they lag for more than 60 seconds + // another solution is to reset the lag screen the same way we reset it when using load-in-game + // this is required in order to give GProxy++ clients more time to reconnect + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + // stop the lag screen + + for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + { + if( (*j)->GetLagging( ) ) + Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j ) ); + } + + // send an empty update + // this resets the lag screen timer + + if( UsingGProxy && !(*i)->GetGProxy( ) ) + { + // we must send additional empty actions to non-GProxy++ players + // GProxy++ will insert these itself so we don't need to send them to GProxy++ players + // empty actions are used to extend the time a player can use when reconnecting + + for( unsigned char j = 0; j < m_GProxyEmptyActions; j++ ) + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); + } + + Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( QQueue( ), 0 ) ); + + // start the lag screen + + Send( *i, m_Protocol->SEND_W3GS_START_LAG( m_Players ) ); + } + + // add actions to replay + + if( m_Replay ) + { + if( UsingGProxy ) + { + for( unsigned char i = 0; i < m_GProxyEmptyActions; i++ ) + m_Replay->AddTimeSlot( 0, QQueue( ) ); + } + + m_Replay->AddTimeSlot( 0, QQueue( ) ); + } + + // Warcraft III doesn't seem to respond to empty actions + + /* if( UsingGProxy ) + m_SyncCounter += m_GProxyEmptyActions; + + m_SyncCounter++; */ +} + +void CBaseGame::EventPlayerStoppedLagging() +{ + if( !m_Lagging ) + return; + + // check if anyone has stopped lagging normally + // we consider a player to have stopped lagging if they're less than half m_SyncLimit keepalives behind + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( (*i)->GetLagging( ) && m_SyncCounter - (*i)->GetSyncCounter( ) < m_SyncLimit / 2 ) + { + // stop the lag screen for this player + + CONSOLE_Print( "[GAME: " + m_GameName + "] stopped lagging on [" + (*i)->GetName( ) + "]" ); + SendAll( m_Protocol->SEND_W3GS_STOP_LAG( *i ) ); + (*i)->SetLagging( false ); + (*i)->SetStartedLaggingTicks( 0 ); + } + } + + // check if everyone has stopped lagging + + bool Lagging = false; + + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( (*i)->GetLagging( ) ) + Lagging = true; + } + + m_Lagging = Lagging; + + if (!m_Lagging) + { + m_DropLaggerTimer.stop(); + m_SendActionTimer.start(); + } + + // reset m_LastActionSentTicks because we want the game to stop running while the lag screen is up + + m_LastActionSentTicks = GetTicks( ); + + // keep track of the last lag screen time so we can avoid timing out players + + m_LastLagScreenTime = GetTime( ); +} + +void CBaseGame :: EventPlayerDeleted() { + CGamePlayer *player = (CGamePlayer*)QObject::sender(); CONSOLE_Print( "[GAME: " + m_GameName + "] deleting player [" + player->GetName( ) + "]: " + player->GetLeftReason( ) ); + m_Players.remove(m_Players.indexOf(player)); + + // create the virtual host player if there is room + if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < 12 ) + CreateVirtualHost( ); + + bool res = false; + // check if there's another player with reserved status in the game + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + if( (*i)->GetReserved( ) ) + res = true; + + if (res) + m_LobbyTimeoutTimer.start(); + + // unlock the game if the owner leaves + if( m_Locked && player->GetName() == m_OwnerName ) + { + SendAllChat( m_GHost->m_Language->GameUnlocked( ) ); + m_Locked = false; + } + + // start the gameover timer if there's only one player left + if( ( m_GameLoading || m_GameLoaded ) && m_Players.size( ) == 1 && m_FakePlayerPID == 255 && !m_GameOverTimer.isActive() ) + { + CONSOLE_Print( "[GAME: " + m_GameName + "] gameover timer started (one player left)" ); + m_GameOverTimer.start(); + } + + // end the game if there aren't any players left + if( m_Players.isEmpty( ) && m_GameLoading || m_GameLoaded ) + { + if( !m_Saving ) + { + CONSOLE_Print( "[GAME: " + m_GameName + "] is over (no players left)" ); + SaveGameData( ); + m_Saving = true; + } + else if( IsGameDataSaved( ) ) + deleteLater(); + } + // remove any queued spoofcheck messages for this player if( player->GetWhoisSent( ) && !player->GetJoinedRealm( ).isEmpty( ) && player->GetSpoofedRealm( ).isEmpty( ) ) @@ -1516,7 +1506,7 @@ void CBaseGame :: EventPlayerDeleted( CGamePlayer *player ) SendAllChat( m_GHost->m_Language->VoteKickCancelled( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); - m_StartedKickVoteTime = 0; + m_VotekickTimer.stop(); } void CBaseGame :: EventPlayerDisconnectTimedOut( CGamePlayer *player ) @@ -1529,33 +1519,25 @@ void CBaseGame :: EventPlayerDisconnectTimedOut( CGamePlayer *player ) player->SetGProxyDisconnectNoticeSent( true ); } - if( GetTime( ) - player->GetLastGProxyWaitNoticeSentTime( ) >= 20 ) - { - uint32_t TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60 - ( GetTime( ) - m_StartedLaggingTime ); - - if( TimeRemaining > ( (uint32_t)m_GProxyEmptyActions + 1 ) * 60 ) - TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; - - SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); - player->SetLastGProxyWaitNoticeSentTime( GetTime( ) ); - } - + player->m_SendGProxyMessageTimer.start(); return; } - // not only do we not do any timeouts if the game is lagging, we allow for an additional grace period of 10 seconds + // not only do we not do any timeouts if the game is lagging, we allow for an additional grace period of 5 seconds // this is because Warcraft 3 stops sending packets during the lag screen // so when the lag screen finishes we would immediately disconnect everyone if we didn't give them some extra time - if( GetTime( ) - m_LastLagScreenTime >= 10 ) - { - player->SetDeleteMe( true ); - player->SetLeftReason( m_GHost->m_Language->HasLostConnectionTimedOut( ) ); - player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); + QTimer::singleShot(5000, this, SLOT(EventPlayerLaggedOut(player))); +} - if( !m_GameLoading && !m_GameLoaded ) - OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); - } +void CBaseGame::EventPlayerLaggedOut(CGamePlayer *player) +{ + player->SetDeleteMe( true ); + player->SetLeftReason( m_GHost->m_Language->HasLostConnectionTimedOut( ) ); + player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); + + if( !m_GameLoading && !m_GameLoaded ) + OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); } void CBaseGame :: EventPlayerDisconnectPlayerError( CGamePlayer *player ) @@ -1577,7 +1559,7 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) { if( !player->GetGProxyDisconnectNoticeSent( ) ) { - SendAllChat( player->GetName( ) + " " + m_GHost->m_Language->HasLostConnectionSocketErrorGProxy( player->GetSocket( )->GetErrorString( ) ) + "." ); + SendAllChat( player->GetName( ) + " " + m_GHost->m_Language->HasLostConnectionSocketErrorGProxy( player->GetSocket( )->errorString() ) + "." ); player->SetGProxyDisconnectNoticeSent( true ); } @@ -1596,7 +1578,7 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) } player->SetDeleteMe( true ); - player->SetLeftReason( m_GHost->m_Language->HasLostConnectionSocketError( player->GetSocket( )->GetErrorString( ) ) ); + player->SetLeftReason( m_GHost->m_Language->HasLostConnectionSocketError( player->GetSocket( )->errorString( ) ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); if( !m_GameLoading && !m_GameLoaded ) @@ -1716,7 +1698,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, potential->GetSocket( )->GetPort( ), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateQByteArray((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; } @@ -1744,7 +1726,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, potential->GetSocket( )->GetPort( ), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateQByteArray((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; } @@ -1780,6 +1762,10 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP bool Reserved = IsReserved( joinPlayer->GetName( ) ) || ( m_GHost->m_ReserveAdmins && AnyAdminCheck ) || IsOwner( joinPlayer->GetName( ) ); + // stop some timers + if (Reserved) + m_LobbyTimeoutTimer.stop(); + // try to find a slot unsigned char SID = 255; @@ -1987,7 +1973,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), Player->GetSocket( )->GetPort( ), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateQByteArray((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2148,6 +2134,12 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco } } + bool Reserved = IsReserved( joinPlayer->GetName( ) ) || ( m_GHost->m_ReserveAdmins && AnyAdminCheck ) || IsOwner( joinPlayer->GetName( ) ); + + // stop some timers + if (Reserved) + m_LobbyTimeoutTimer.stop(); + if( SID == 255 ) { // no empty slot found, time to do some matchmaking! @@ -2360,7 +2352,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), Player->GetSocket( )->GetPort( ), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateQByteArray((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2524,8 +2516,9 @@ void CBaseGame :: EventPlayerLeft( CGamePlayer *player, uint32_t reason ) OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); } -void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) +void CBaseGame :: EventPlayerLoaded() { + CGamePlayer *player = (CGamePlayer*)QObject::sender(); CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] finished loading in " + UTIL_ToString( (float)( player->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) + " seconds" ); if( m_LoadInGame ) @@ -2575,6 +2568,8 @@ void CBaseGame :: EventPlayerLoaded( CGamePlayer *player ) } else SendAll( m_Protocol->SEND_W3GS_GAMELOADED_OTHERS( player->GetPID( ) ) ); + + CheckGameLoaded(); } void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *action ) @@ -3101,8 +3096,34 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map // if we send a new slot update for every percentage change in their download status it adds up to a lot of data // instead, we mark the slot info as "out of date" and update it only once in awhile (once per second when this comment was made) - m_SlotInfoChanged = true; + if (!m_SlotInfoTimer.isActive()) + m_SlotInfoTimer.start(); + } + } +} + +void CBaseGame::EventCallableUpdateTimeout() +{ + // update callables + + for( QVector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); ) + { + if( (*i)->GetReady( ) ) + { + double Score = (*i)->GetResult( ); + + for( QVector :: iterator j = m_Potentials.begin( ); j != m_Potentials.end( ); j++ ) + { + if( (*j)->GetJoinPlayer( ) && (*j)->GetJoinPlayer( )->GetName( ) == (*i)->GetName( ) ) + EventPlayerJoinedWithScore( *j, (*j)->GetJoinPlayer( ), Score ); + } + + m_GHost->m_DB->RecoverCallable( *i ); + delete *i; + i = m_ScoreChecks.erase( i ); } + else + i++; } } @@ -3204,11 +3225,11 @@ void CBaseGame :: EventGameStarted( ) // this is because we only permit slot info updates to be flagged when it's just a change in download status, all others are sent immediately // it might not be necessary but let's clean up the mess anyway - if( m_SlotInfoChanged ) + //if( m_SlotInfoChanged ) SendAllSlotInfo( ); m_StartedLoadingTicks = GetTicks( ); - m_LastLagScreenResetTime = GetTime( ); + m_LoadInGameTimer.start(); m_GameLoading = true; // since we use a fake countdown to deal with leavers during countdown the COUNTDOWN_START and COUNTDOWN_END packets are sent in quick succession @@ -4298,6 +4319,7 @@ void CBaseGame :: StartCountDown( bool force ) if( force ) { m_CountDownStarted = true; + m_CountdownTimer.start(); m_CountDownCounter = 5; } else @@ -4379,6 +4401,7 @@ void CBaseGame :: StartCountDown( bool force ) { m_CountDownStarted = true; m_CountDownCounter = 5; + m_CountdownTimer.start(); } } } @@ -4470,6 +4493,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( StillDownloading.isEmpty( ) && NotSpoofChecked.isEmpty( ) && NotPinged.isEmpty( ) ) { m_CountDownStarted = true; + m_CountdownTimer.start(); m_CountDownCounter = 10; } } diff --git a/ghost/game_base.h b/ghost/game_base.h index 268dc49..68e14d4 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -40,14 +40,52 @@ class CIncomingAction; class CIncomingChatPlayer; class CIncomingMapSize; class CCallableScoreCheck; +class CGHost; -class CBaseGame +#include +#include + +class CBaseGame : public QObject { + Q_OBJECT + public: CGHost *m_GHost; +public slots: + void EventNewConnection(); + void EventBroadcastTimeout(); + void EventRefreshTimeout(); + void EventRefreshError(); + void EventMapDataTimeout(); + void EventCountdownTimeout(); + void EventAutostartTimeout(); + void EventGameOverTimeout(); + void EventVotekickTimeout(); + virtual void EventCallableUpdateTimeout(); + void EventResetDownloadCounter(); + void EventAnnounceTimeout(); + void EventLobbyTimeout(); + void EventPlayerStoppedLagging(); + void CheckPlayersStartedLaggging(); + void EventLoadInGameTimeout(); + void EventResetLagscreenTimeout(); + void EventDropLaggerTimeout(); + void EventPlayerLaggedOut(CGamePlayer *player); + void EventSendActions(); + virtual void SendAllSlotInfo(); + virtual void EventPlayerLoaded(); + virtual void EventPlayerDeleted(); + protected: - CTCPServer *m_Socket; // listening socket + QTimer m_BroadcastTimer, m_RefreshTimer, m_MapDataTimer, m_CountdownTimer, m_AutostartTimer, m_GameOverTimer, m_VotekickTimer, + m_SlotInfoTimer, m_DownloadCounterTimer, m_CallableUpdateTimer, m_AnnounceTimer, m_LobbyTimeoutTimer, + m_DropLaggerTimer, m_LoadInGameTimer, m_ResetLagscreenTimer, m_SendActionTimer; + + void CheckGameLoaded(); + +protected: + QTcpServer *m_Socket; // listening socket CGameProtocol *m_Protocol; // game protocol QVector m_Slots; // vector of slots QVector m_Potentials; // vector of potential players (connections that haven't sent a W3GS_REQJOIN packet yet) @@ -79,6 +117,7 @@ class CBaseGame QString m_StatString; // the stat QString when the game started (used when saving replays) QString m_KickVotePlayer; // the player to be kicked with the currently running kick vote QString m_HCLCommandString; // the "HostBot Command Library" command QString, used to pass a limited amount of data to specially designed maps + uint32_t m_WaitTime; uint32_t m_RandomSeed; // the random seed sent to the Warcraft III clients uint32_t m_HostCounter; // a unique game number uint32_t m_Latency; // the number of ms to wait between sending action packets (we queue any received during this time) @@ -86,31 +125,19 @@ class CBaseGame uint32_t m_SyncCounter; // the number of actions sent so far (for determining if anyone is lagging) uint32_t m_GameTicks; // ingame ticks uint32_t m_CreationTime; // GetTime when the game was created - uint32_t m_LastPingTime; // GetTime when the last ping was sent - uint32_t m_LastRefreshTime; // GetTime when the last game refresh was sent uint32_t m_LastDownloadTicks; // GetTicks when the last map download cycle was performed uint32_t m_DownloadCounter; // # of map bytes downloaded in the last second - uint32_t m_LastDownloadCounterResetTicks; // GetTicks when the download counter was last reset - uint32_t m_LastAnnounceTime; // GetTime when the last announce message was sent - uint32_t m_AnnounceInterval; // how many seconds to wait between sending the m_AnnounceMessage - uint32_t m_LastAutoStartTime; // the last time we tried to auto start the game uint32_t m_AutoStartPlayers; // auto start the game when there are this many players or more - uint32_t m_LastCountDownTicks; // GetTicks when the last countdown message was sent uint32_t m_CountDownCounter; // the countdown is finished when this reaches zero uint32_t m_StartedLoadingTicks; // GetTicks when the game started loading uint32_t m_StartPlayers; // number of players when the game started - uint32_t m_LastLagScreenResetTime; // GetTime when the "lag" screen was last reset uint32_t m_LastActionSentTicks; // GetTicks when the last action packet was sent uint32_t m_LastActionLateBy; // the number of ticks we were late sending the last action packet by uint32_t m_StartedLaggingTime; // GetTime when the last lag screen started uint32_t m_LastLagScreenTime; // GetTime when the last lag screen was active (continuously updated) - uint32_t m_LastReservedSeen; // GetTime when the last reserved player was seen in the lobby - uint32_t m_StartedKickVoteTime; // GetTime when the kick vote was started - uint32_t m_GameOverTime; // GetTime when the game was over uint32_t m_LastPlayerLeaveTicks; // GetTicks when the most recent player left the game double m_MinimumScore; // the minimum allowed score for matchmaking mode double m_MaximumScore; // the maximum allowed score for matchmaking mode - bool m_SlotInfoChanged; // if the slot info has changed and hasn't been sent to the players yet (optimization) bool m_Locked; // if the game owner is the only one allowed to run game commands or not bool m_RefreshMessages; // if we should display "game refreshed..." messages or not bool m_RefreshError; // if there was an error refreshing the game @@ -144,6 +171,8 @@ class CBaseGame virtual QString GetCreatorServer( ) { return m_CreatorServer; } virtual uint32_t GetHostCounter( ) { return m_HostCounter; } virtual uint32_t GetLastLagScreenTime( ) { return m_LastLagScreenTime; } + virtual uint32_t GetStartedLaggingTime( ) { return m_StartedLaggingTime; } + virtual uint32_t GetAutoStartPlayers( ) { return m_AutoStartPlayers; } virtual bool GetLocked( ) { return m_Locked; } virtual bool GetRefreshMessages( ) { return m_RefreshMessages; } virtual bool GetCountDownStarted( ) { return m_CountDownStarted; } @@ -151,13 +180,13 @@ class CBaseGame virtual bool GetGameLoaded( ) { return m_GameLoaded; } virtual bool GetLagging( ) { return m_Lagging; } + virtual void SetEnforceSlots( QVector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } virtual void SetEnforcePlayers( QVector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } virtual void SetExiting( bool nExiting ) { m_Exiting = nExiting; } virtual void SetAutoStartPlayers( uint32_t nAutoStartPlayers ) { m_AutoStartPlayers = nAutoStartPlayers; } virtual void SetMinimumScore( double nMinimumScore ) { m_MinimumScore = nMinimumScore; } virtual void SetMaximumScore( double nMaximumScore ) { m_MaximumScore = nMaximumScore; } - virtual void SetRefreshError( bool nRefreshError ) { m_RefreshError = nRefreshError; } virtual void SetMatchMaking( bool nMatchMaking ) { m_MatchMaking = nMatchMaking; } virtual uint32_t GetNextTimedActionTicks( ); @@ -171,9 +200,7 @@ class CBaseGame // processing functions - virtual unsigned int SetFD( void *fd, void *send_fd, int *nfds ); virtual bool Update( void *fd, void *send_fd ); - virtual void UpdatePost( void *send_fd ); // generic functions to send packets to players @@ -191,7 +218,6 @@ class CBaseGame virtual void SendAllChat( unsigned char fromPID, QString message ); virtual void SendAllChat( QString message ); virtual void SendLocalAdminChat( QString message ); - virtual void SendAllSlotInfo( ); virtual void SendVirtualHostPlayerInfo( CGamePlayer *player ); virtual void SendFakePlayerInfo( CGamePlayer *player ); virtual void SendAllActions( ); @@ -202,7 +228,6 @@ class CBaseGame // note: these are only called while iterating through the m_Potentials or m_Players vectors // therefore you can't modify those vectors and must use the player's m_DeleteMe member to flag for deletion - virtual void EventPlayerDeleted( CGamePlayer *player ); virtual void EventPlayerDisconnectTimedOut( CGamePlayer *player ); virtual void EventPlayerDisconnectPlayerError( CGamePlayer *player ); virtual void EventPlayerDisconnectSocketError( CGamePlayer *player ); @@ -210,7 +235,6 @@ class CBaseGame virtual void EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer ); virtual void EventPlayerJoinedWithScore( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer, double score ); virtual void EventPlayerLeft( CGamePlayer *player, uint32_t reason ); - virtual void EventPlayerLoaded( CGamePlayer *player ); virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); virtual void EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ); virtual void EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlayer *chatPlayer ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index b6fac76..6fbb593 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -34,14 +34,22 @@ // CPotentialPlayer // -CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket ) +#include + +CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket ) + : QObject(NULL) { m_Protocol = nProtocol; m_Game = nGame; m_Socket = nSocket; + m_DeleteMe = false; m_Error = false; m_IncomingJoinPlayer = NULL; + + QObject::connect(nSocket, SIGNAL(readyRead()), this, SLOT(EventDataReady())); + QObject::connect(nSocket, SIGNAL(disconnected()), this, SLOT(EventConnectionClosed())); + QObject::connect(nSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(EventConnectionError(QAbstractSocket::SocketError))); } CPotentialPlayer :: ~CPotentialPlayer( ) @@ -58,40 +66,104 @@ CPotentialPlayer :: ~CPotentialPlayer( ) delete m_IncomingJoinPlayer; } -QByteArray CPotentialPlayer :: GetExternalIP( ) +void CPotentialPlayer::EventDataReady() { - unsigned char Zeros[] = { 0, 0, 0, 0 }; + m_TimeoutTimer.start(); - if( m_Socket ) - return m_Socket->GetIP( ); + ExtractPackets( ); + ProcessPackets( ); +} - return QByteArray( (char*)Zeros, 4 ); +void CPotentialPlayer::EventConnectionError(QAbstractSocket::SocketError /*error*/) +{ + this->deleteLater(); } -QString CPotentialPlayer :: GetExternalIPString( ) +void CPotentialPlayer::EventConnectionClosed() { + this->deleteLater(); +} + +void CGamePlayer::EventPingTimeout() +{ + Send(m_Protocol->SEND_W3GS_PING_FROM_HOST( ) ); +} + +void CGamePlayer::EventACKTimeout() +{ + // GProxy++ acks + if( m_Socket ) - return m_Socket->GetIPString( ); + m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) ); +} + +void CGamePlayer::EventWhoisTimeout() +{ + // wait 4 seconds after joining before sending the /whois or /w + // if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results + + if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.isEmpty( ) ) + { + // todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking + + for( QVector :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ ) + { + if( (*i)->GetServer( ) == m_JoinedRealm ) + { + if( m_Game->GetGameState( ) == GAME_PUBLIC ) + { + if( (*i)->GetPasswordHashType( ) == "pvpgn" ) + (*i)->QueueChatCommand( "/whereis " + m_Name ); + else + (*i)->QueueChatCommand( "/whois " + m_Name ); + } + else if( m_Game->GetGameState( ) == GAME_PRIVATE ) + (*i)->QueueChatCommand( m_Game->m_GHost->m_Language->SpoofCheckByReplying( ), m_Name, true ); + } + } + + m_WhoisSent = true; + } - return QString( ); } -bool CPotentialPlayer :: Update( void *fd ) +void CGamePlayer::EventConnectionError(QAbstractSocket::SocketError /*error*/) { - if( m_DeleteMe ) - return true; + m_Game->EventPlayerDisconnectSocketError( this ); + this->deleteLater(); +} - if( !m_Socket ) - return false; +void CGamePlayer::EventConnectionTimeout() +{ + // check for socket timeouts + // if we don't receive anything from a player for 30 seconds we can assume they've dropped + // this works because in the lobby we send pings every 5 seconds and expect a response to each one + // and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like) + m_Game->EventPlayerDisconnectTimedOut( this ); + this->deleteLater(); +} - m_Socket->DoRecv( (fd_set *)fd ); - ExtractPackets( ); - ProcessPackets( ); +void CGamePlayer::EventConnectionClosed() +{ + m_Game->EventPlayerDisconnectConnectionClosed( this ); + this->deleteLater(); +} + +QByteArray CPotentialPlayer :: GetExternalIP( ) +{ + if( m_Socket ) + return UTIL_CreateQByteArray(m_Socket->localAddress().toIPv4Address()); - // don't call DoSend here because some other players may not have updated yet and may generate a packet for this player - // also m_Socket may have been set to NULL during ProcessPackets but we're banking on the fact that m_DeleteMe has been set to true as well so it'll short circuit before dereferencing + unsigned char Zeros[] = { 0, 0, 0, 0 }; + return QByteArray( (char*)Zeros, 4 ); +} + +QString CPotentialPlayer :: GetExternalIPString( ) +{ + if( m_Socket ) + return m_Socket->localAddress().toString(); - return m_DeleteMe || m_Error || m_Socket->HasError( ) || !m_Socket->GetConnected( ); + return QString( ); } void CPotentialPlayer :: ExtractPackets( ) @@ -100,44 +172,40 @@ void CPotentialPlayer :: ExtractPackets( ) return; // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue - - QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = RecvBuffer->toUtf8(); - // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes - while( Bytes.size( ) >= 4 ) + while( m_Socket->bytesAvailable() >= 4 ) { - if( Bytes[0] == W3GS_HEADER_CONSTANT || Bytes[0] == GPS_HEADER_CONSTANT ) + char header = m_Socket->peek(1).at(0); + if (header != W3GS_HEADER_CONSTANT && header != GPS_HEADER_CONSTANT ) { - // bytes 2 and 3 contain the length of the packet + m_Error = true; + m_ErrorString = "received invalid packet from player (bad header constant)"; + m_Socket->abort(); + m_Socket->deleteLater(); + m_Socket = NULL; + return; + } - uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); + // bytes 2 and 3 contain the length of the packet - if( Length >= 4 ) - { - if( Bytes.size( ) >= Length ) - { - m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], Bytes.mid(0, Length) ) ); - *RecvBuffer = RecvBuffer->mid( Length ); - Bytes = Bytes.mid(Length); - } - else - return; - } - else - { - m_Error = true; - m_ErrorString = "received invalid packet from player (bad length)"; - return; - } - } - else + uint16_t Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); + + if( Length < 4 ) { m_Error = true; - m_ErrorString = "received invalid packet from player (bad header constant)"; + m_ErrorString = "received invalid packet from player (bad length)"; + m_Socket->abort(); + m_Socket->deleteLater(); + m_Socket = NULL; return; } + + if( m_Socket->bytesAvailable() < Length ) + return; + + QByteArray Bytes = m_Socket->read(Length); + m_Packets.enqueue( new CCommandPacket( header, Bytes.at(1), Bytes ) ); } } @@ -182,14 +250,15 @@ void CPotentialPlayer :: ProcessPackets( ) void CPotentialPlayer :: Send( QByteArray data ) { if( m_Socket ) - m_Socket->PutBytes( data ); + m_Socket->write(data); } // // CGamePlayer // - -CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) : CPotentialPlayer( nProtocol, nGame, nSocket ) +#include +CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) + : CPotentialPlayer( nProtocol, nGame, nSocket ) { m_PID = nPID; m_Name = nName; @@ -231,7 +300,8 @@ CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSock m_LastGProxyAckTime = 0; } -CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) : CPotentialPlayer( potential->m_Protocol, potential->m_Game, potential->GetSocket( ) ) +CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) + : CPotentialPlayer( potential->m_Protocol, potential->m_Game, potential->GetSocket( ) ) { // todotodo: properly copy queued packets to the new player, this just discards them // this isn't a big problem because official Warcraft III clients don't send any packets after the join request until they receive a response @@ -281,11 +351,63 @@ CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QSt m_GProxyDisconnectNoticeSent = false; m_GProxyReconnectKey = GetTicks( ); m_LastGProxyAckTime = 0; + init(); +} + +void CGamePlayer::EventSpoofCheckTimeout() +{ + // kick players who don't spoof check within 20 seconds when spoof checks are required and the game is autohosted + + if (GetSpoofed()) + return; + + if (m_Game->GetCountDownStarted() || !m_Game->m_GHost->m_RequireSpoofChecks || + m_Game->GetGameState() != GAME_PUBLIC || !m_Game->m_GHost->m_AutoHostGameName.isEmpty() || + m_Game->m_GHost->m_AutoHostMaximumGames == 0 || m_Game->m_GHost->m_AutoHostAutoStartPlayers == 0 || + m_Game->GetAutoStartPlayers() == 0) + return; + + deleteLater(); + SetLeftReason( m_Game->m_GHost->m_Language->WasKickedForNotSpoofChecking( ) ); + SetLeftCode( PLAYERLEAVE_LOBBY ); + m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false ); +} + +void CGamePlayer::init() +{ + QObject::connect(&m_TimeoutTimer, SIGNAL(timeout()), this, SLOT(EventConnectionTimeout())); + QObject::connect(&m_ACKTimer, SIGNAL(timeout()), this, SLOT(EventACKTimeout())); + QObject::connect(&m_PingTimer, SIGNAL(timeout()), this, SLOT(EventPingTimeout())); + QTimer::singleShot(4000, this, SLOT(EventWhoisTimeout())); + + QObject::connect(this, SIGNAL(finishedLoading()), m_Game, SLOT(EventPlayerLoaded())); + QObject::connect(this, SIGNAL(destroyed()), m_Game, SLOT(EventPlayerDeleted())); + m_SendGProxyMessageTimer.setInterval(20000); + QObject::connect(&m_SendGProxyMessageTimer, SIGNAL(timeout()), this, SLOT(EventSendGProxyMessage())); + + QTimer::singleShot(20000, this, SLOT(EventSpoofCheckTimeout())); + + if (m_GProxy) + m_ACKTimer.start(10000); + + m_PingTimer.start(5000); + m_TimeoutTimer.start(30000); + m_TimeoutTimer.setSingleShot(true); } CGamePlayer :: ~CGamePlayer( ) { +} + +void CGamePlayer::EventSendGProxyMessage() +{ + uint32_t TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60 - ( GetTime( ) - m_Game->GetStartedLaggingTime() ); + if( TimeRemaining > ( (uint32_t)m_Game->GetGProxyEmptyActions() + 1 ) * 60 ) + TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60; + + m_Game->SendAllChat( GetPID( ), m_Game->m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); + SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } QString CGamePlayer :: GetNameTerminated( ) @@ -323,128 +445,51 @@ uint32_t CGamePlayer :: GetPing( bool LCPing ) return AvgPing; } -bool CGamePlayer :: Update( void *fd ) -{ - // wait 4 seconds after joining before sending the /whois or /w - // if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results - - if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.isEmpty( ) && GetTime( ) - m_JoinTime >= 4 ) - { - // todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking - - for( QVector :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ ) - { - if( (*i)->GetServer( ) == m_JoinedRealm ) - { - if( m_Game->GetGameState( ) == GAME_PUBLIC ) - { - if( (*i)->GetPasswordHashType( ) == "pvpgn" ) - (*i)->QueueChatCommand( "/whereis " + m_Name ); - else - (*i)->QueueChatCommand( "/whois " + m_Name ); - } - else if( m_Game->GetGameState( ) == GAME_PRIVATE ) - (*i)->QueueChatCommand( m_Game->m_GHost->m_Language->SpoofCheckByReplying( ), m_Name, true ); - } - } - - m_WhoisSent = true; - } - - // check for socket timeouts - // if we don't receive anything from a player for 30 seconds we can assume they've dropped - // this works because in the lobby we send pings every 5 seconds and expect a response to each one - // and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like) - - if( m_Socket && GetTime( ) - m_Socket->GetLastRecv( ) >= 30 ) - m_Game->EventPlayerDisconnectTimedOut( this ); - - // GProxy++ acks - - if( m_GProxy && GetTime( ) - m_LastGProxyAckTime >= 10 ) - { - if( m_Socket ) - m_Socket->PutBytes( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) ); - - m_LastGProxyAckTime = GetTime( ); - } - - // base class update - - CPotentialPlayer :: Update( fd ); - bool Deleting; - - if( m_GProxy && m_Game->GetGameLoaded( ) ) - Deleting = m_DeleteMe || m_Error; - else - Deleting = m_DeleteMe || m_Error || m_Socket->HasError( ) || !m_Socket->GetConnected( ); - - // try to find out why we're requesting deletion - // in cases other than the ones covered here m_LeftReason should have been set when m_DeleteMe was set - - if( m_Error ) - m_Game->EventPlayerDisconnectPlayerError( this ); - - if( m_Socket ) - { - if( m_Socket->HasError( ) ) - m_Game->EventPlayerDisconnectSocketError( this ); - - if( !m_Socket->GetConnected( ) ) - m_Game->EventPlayerDisconnectConnectionClosed( this ); - } - - return Deleting; -} - void CGamePlayer :: ExtractPackets( ) { if( !m_Socket ) return; // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue - - QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = RecvBuffer->toUtf8(); - // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes - while( Bytes.size( ) >= 4 ) + while( m_Socket->bytesAvailable() >= 4 ) { - if( Bytes[0] == W3GS_HEADER_CONSTANT || Bytes[0] == GPS_HEADER_CONSTANT ) + char header = m_Socket->peek(1).at(0); + if (header != W3GS_HEADER_CONSTANT && header != GPS_HEADER_CONSTANT ) { - // bytes 2 and 3 contain the length of the packet - - uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); + m_Error = true; + m_ErrorString = "received invalid packet from player (bad header constant)"; + m_Game->EventPlayerDisconnectPlayerError( this ); + m_Socket->abort(); + m_Socket->deleteLater(); + m_Socket = NULL; + this->deleteLater(); + return; + } - if( Length >= 4 ) - { - if( Bytes.size( ) >= Length ) - { - m_Packets.enqueue( new CCommandPacket( Bytes[0], Bytes[1], Bytes.mid(0, Length) ) ); + // bytes 2 and 3 contain the length of the packet - if( Bytes[0] == W3GS_HEADER_CONSTANT ) - m_TotalPacketsReceived++; + uint16_t Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); - *RecvBuffer = RecvBuffer->mid( Length ); - Bytes.remove(0, Length); - } - else - return; - } - else - { - m_Error = true; - m_ErrorString = "received invalid packet from player (bad length)"; - return; - } - } - else + if( Length < 4 ) { m_Error = true; - m_ErrorString = "received invalid packet from player (bad header constant)"; + m_ErrorString = "received invalid packet from player (bad length)"; + m_Socket->abort(); + m_Socket->deleteLater(); + m_Socket = NULL; return; } + + if( m_Socket->bytesAvailable() < Length ) + return; + + QByteArray Bytes = m_Socket->read(Length); + m_Packets.enqueue( new CCommandPacket( header, Bytes.at(1), Bytes ) ); + + if( header == W3GS_HEADER_CONSTANT ) + m_TotalPacketsReceived++; } } @@ -482,7 +527,7 @@ void CGamePlayer :: ProcessPackets( ) { m_FinishedLoading = true; m_FinishedLoadingTicks = GetTicks( ); - m_Game->EventPlayerLoaded( this ); + emit finishedLoading(); } else { @@ -578,7 +623,7 @@ void CGamePlayer :: ProcessPackets( ) if( m_Game->m_GHost->m_Reconnect ) { m_GProxy = true; - m_Socket->PutBytes( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_INIT( m_Game->m_GHost->m_ReconnectPort, m_PID, m_GProxyReconnectKey, m_Game->GetGProxyEmptyActions( ) ) ); + m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_INIT( m_Game->m_GHost->m_ReconnectPort, m_PID, m_GProxyReconnectKey, m_Game->GetGProxyEmptyActions( ) ) ); CONSOLE_Print( "[GAME: " + m_Game->GetGameName( ) + "] player [" + m_Name + "] is using GProxy++" ); } else @@ -631,11 +676,11 @@ void CGamePlayer :: Send( QByteArray data ) CPotentialPlayer :: Send( data ); } -void CGamePlayer :: EventGProxyReconnect( CTCPSocket *NewSocket, uint32_t LastPacket ) +void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, uint32_t LastPacket ) { delete m_Socket; m_Socket = NewSocket; - m_Socket->PutBytes( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_RECONNECT( m_TotalPacketsReceived ) ); + m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_RECONNECT( m_TotalPacketsReceived ) ); uint32_t PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); @@ -659,7 +704,7 @@ void CGamePlayer :: EventGProxyReconnect( CTCPSocket *NewSocket, uint32_t LastPa while( !m_GProxyBuffer.isEmpty( ) ) { - m_Socket->PutBytes( m_GProxyBuffer.front( ) ); + m_Socket->write( m_GProxyBuffer.front( ) ); TempBuffer.enqueue( m_GProxyBuffer.front( ) ); m_GProxyBuffer.dequeue( ); } diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index 49c43db..d4ac236 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -28,22 +28,34 @@ class CGame; class CIncomingJoinPlayer; #include "includes.h" - +class CBaseGame; // // CPotentialPlayer // +#include +#include + class CPotentialPlayer + : public QObject { + Q_OBJECT + +public slots: + void EventDataReady(); + virtual void EventConnectionError(QAbstractSocket::SocketError); + virtual void EventConnectionClosed(); + public: CGameProtocol *m_Protocol; CBaseGame *m_Game; + QTimer m_TimeoutTimer, m_SendGProxyMessageTimer; protected: // note: we permit m_Socket to be NULL in this class to allow for the virtual host player which doesn't really exist // it also allows us to convert CPotentialPlayers to CGamePlayers without the CPotentialPlayer's destructor closing the socket - CTCPSocket *m_Socket; + QTcpSocket *m_Socket; QQueue m_Packets; bool m_DeleteMe; bool m_Error; @@ -51,10 +63,10 @@ class CPotentialPlayer CIncomingJoinPlayer *m_IncomingJoinPlayer; public: - CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket ); + CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket ); virtual ~CPotentialPlayer( ); - virtual CTCPSocket *GetSocket( ) { return m_Socket; } + virtual QTcpSocket *GetSocket( ) { return m_Socket; } virtual QByteArray GetExternalIP( ); virtual QString GetExternalIPString( ); virtual QQueue GetPackets( ) { return m_Packets; } @@ -63,12 +75,11 @@ class CPotentialPlayer virtual QString GetErrorString( ) { return m_ErrorString; } virtual CIncomingJoinPlayer *GetJoinPlayer( ) { return m_IncomingJoinPlayer; } - virtual void SetSocket( CTCPSocket *nSocket ) { m_Socket = nSocket; } + virtual void SetSocket( QTcpSocket *nSocket ) { m_Socket = nSocket; } virtual void SetDeleteMe( bool nDeleteMe ) { m_DeleteMe = nDeleteMe; } // processing functions - virtual bool Update( void *fd ); virtual void ExtractPackets( ); virtual void ProcessPackets( ); @@ -77,12 +88,33 @@ class CPotentialPlayer virtual void Send( QByteArray data ); }; + // // CGamePlayer // - class CGamePlayer : public CPotentialPlayer { + Q_OBJECT + +public slots: + virtual void EventConnectionError(QAbstractSocket::SocketError); + virtual void EventConnectionClosed(); + void EventConnectionTimeout(); + void EventWhoisTimeout(); + void EventACKTimeout(); + void EventPingTimeout(); + void EventSendGProxyMessage(); + void EventSpoofCheckTimeout(); + +signals: + void finishedLoading(); + void stoppedLagging(); + +private: + QTimer m_ACKTimer; + QTimer m_PingTimer; + void init(); + private: unsigned char m_PID; QString m_Name; // the player's name @@ -130,7 +162,7 @@ class CGamePlayer : public CPotentialPlayer uint32_t m_LastGProxyAckTime; public: - CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, CTCPSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); + CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); virtual ~CGamePlayer( ); @@ -211,14 +243,13 @@ class CGamePlayer : public CPotentialPlayer // processing functions - virtual bool Update( void *fd ); virtual void ExtractPackets( ); virtual void ProcessPackets( ); // other functions virtual void Send( QByteArray data ); - virtual void EventGProxyReconnect( CTCPSocket *NewSocket, uint32_t LastPacket ); + virtual void EventGProxyReconnect( QTcpSocket *NewSocket, uint32_t LastPacket ); }; #endif diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 14bfe43..f411e38 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -60,9 +60,9 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) : m_ConfigFile(configFile) { - m_UDPSocket = new CUDPSocket( ); - m_UDPSocket->SetBroadcastTarget( CFG->GetString( "udp_broadcasttarget", QString( ) ) ); - m_UDPSocket->SetDontRoute( CFG->GetInt( "udp_dontroute", 0 ) == 0 ? false : true ); + m_UDPSocket = new QUdpSocket(this); + m_UDPSocket->setProperty("target", CFG->GetString( "udp_broadcasttarget", QString( ) ) ); + m_UDPSocket->setProperty("dontroute", CFG->GetInt( "udp_dontroute", 0 ) == 0 ? false : true ); m_ReconnectSocket = NULL; m_GPSProtocol = new CGPSProtocol( ); m_CRC = new CCRC32( ); @@ -70,6 +70,9 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_SHA = new CSHA1( ); m_CurrentGame = NULL; QString DBType = CFG->GetString( "db_type", "sqlite3" ); + + // create connections + CONSOLE_Print( "[GHOST] opening primary database" ); if( DBType == "mysql" ) @@ -359,12 +362,6 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CGHost :: ~CGHost( ) { - delete m_UDPSocket; - delete m_ReconnectSocket; - - for( QVector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); i++ ) - delete *i; - delete m_GPSProtocol; delete m_CRC; delete m_SHA; @@ -395,6 +392,91 @@ CGHost :: ~CGHost( ) delete m_SaveGame; } +void CGHost::EventIncomingReconnection() +{ + QTcpSocket *con = m_ReconnectSocket->nextPendingConnection(); + if (con == NULL) + return; + + QObject::connect(con, SIGNAL(readyRead()), this, SLOT(EventReconnectionSocketReadyRead())); +} + +void CGHost::EventReconnectionSocketReadyRead() +{ + QTcpSocket* con = (QTcpSocket*)QObject::sender(); + + // a packet is at least 4 bytes + if (con->bytesAvailable() < 4) + return; + + if( con->peek(1).at(0) == GPS_HEADER_CONSTANT ) + { + // bytes 2 and 3 contain the length of the packet + + uint16_t Length = UTIL_QByteArrayToUInt16( con->peek(4), false, 2 ); + + if( Length < 4 ) + { + con->write( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_INVALID ) ); + con->deleteLater(); + return; + } + + if( con->bytesAvailable() < Length ) + return; + + QByteArray Bytes = con->read(Length); + if( Bytes.at(0) == CGPSProtocol :: GPS_RECONNECT && Length == 13 ) + { + unsigned char PID = Bytes.at(4); + uint32_t ReconnectKey = UTIL_QByteArrayToUInt32( Bytes, false, 5 ); + uint32_t LastPacket = UTIL_QByteArrayToUInt32( Bytes, false, 9 ); + + // look for a matching player in a running game + + CGamePlayer *Match = NULL; + + for( QVector :: iterator j = m_Games.begin( ); j != m_Games.end( ); j++ ) + { + if( (*j)->GetGameLoaded( ) ) + { + CGamePlayer *Player = (*j)->GetPlayerFromPID( PID ); + + if( Player && Player->GetGProxy( ) && Player->GetGProxyReconnectKey( ) == ReconnectKey ) + { + Match = Player; + break; + } + } + } + + if( Match ) + { + // reconnect successful! + Match->EventGProxyReconnect( con, LastPacket ); + return; + } + else + { + con->write( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_NOTFOUND ) ); + con->deleteLater(); + return; + } + } + else + { + con->write( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_INVALID ) ); + con->deleteLater(); + return; + } + } +} + +void CGHost::UpdateEvent() +{ + Update(50000); +} + bool CGHost :: Update( long usecBlock ) { // todotodo: do we really want to shutdown if there's a database error? is there any way to recover from this? @@ -485,9 +567,10 @@ bool CGHost :: Update( long usecBlock ) { if( !m_ReconnectSocket ) { - m_ReconnectSocket = new CTCPServer( ); + m_ReconnectSocket = new QTcpServer( this ); + QObject::connect(m_ReconnectSocket, SIGNAL(newConnection()), this, SLOT(EventIncomingReconnection())); - if( m_ReconnectSocket->Listen( m_BindAddress, m_ReconnectPort ) ) + if( m_ReconnectSocket->listen( QHostAddress(m_BindAddress), m_ReconnectPort ) ) CONSOLE_Print( "[GHOST] listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); else { @@ -497,9 +580,9 @@ bool CGHost :: Update( long usecBlock ) m_Reconnect = false; } } - else if( m_ReconnectSocket->HasError( ) ) + else if( !m_ReconnectSocket->isListening() ) { - CONSOLE_Print( "[GHOST] GProxy++ reconnect listener error (" + m_ReconnectSocket->GetErrorString( ) + ")" ); + CONSOLE_Print( "[GHOST] GProxy++ reconnect listener error (" + m_ReconnectSocket->errorString() + ")" ); delete m_ReconnectSocket; m_ReconnectSocket = NULL; m_Reconnect = false; @@ -521,35 +604,6 @@ bool CGHost :: Update( long usecBlock ) for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) NumFDs += (*i)->SetFD( &fd, &send_fd, &nfds ); - // 2. the current game's server and player sockets - - if( m_CurrentGame ) - NumFDs += m_CurrentGame->SetFD( &fd, &send_fd, &nfds ); - - // 3. the admin game's server and player sockets - - if( m_AdminGame ) - NumFDs += m_AdminGame->SetFD( &fd, &send_fd, &nfds ); - - // 4. all running games' player sockets - - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) - NumFDs += (*i)->SetFD( &fd, &send_fd, &nfds ); - - // 5. the GProxy++ reconnect socket(s) - - if( m_Reconnect && m_ReconnectSocket ) - { - m_ReconnectSocket->SetFD( &fd, &send_fd, &nfds ); - NumFDs++; - } - - for( QVector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); i++ ) - { - (*i)->SetFD( &fd, &send_fd, &nfds ); - NumFDs++; - } - // before we call select we need to determine how long to block for // previously we just blocked for a maximum of the passed usecBlock microseconds // however, in an effort to make game updates happen closer to the desired latency setting we now use a dynamic block interval @@ -612,8 +666,6 @@ bool CGHost :: Update( long usecBlock ) (*i)->QueueEnterChat( ); } } - else if( m_CurrentGame ) - m_CurrentGame->UpdatePost( &send_fd ); } // update admin game @@ -627,8 +679,6 @@ bool CGHost :: Update( long usecBlock ) m_AdminGame = NULL; AdminExit = true; } - else if( m_AdminGame ) - m_AdminGame->UpdatePost( &send_fd ); } // update running games @@ -642,11 +692,6 @@ bool CGHost :: Update( long usecBlock ) delete *i; i = m_Games.erase( i ); } - else - { - (*i)->UpdatePost( &send_fd ); - i++; - } } // update battle.net connections @@ -657,117 +702,6 @@ bool CGHost :: Update( long usecBlock ) BNETExit = true; } - // update GProxy++ reliable reconnect sockets - - if( m_Reconnect && m_ReconnectSocket ) - { - CTCPSocket *NewSocket = m_ReconnectSocket->Accept( &fd ); - - if( NewSocket ) - m_ReconnectSockets.push_back( NewSocket ); - } - - for( QVector :: iterator i = m_ReconnectSockets.begin( ); i != m_ReconnectSockets.end( ); ) - { - if( (*i)->HasError( ) || !(*i)->GetConnected( ) || GetTime( ) - (*i)->GetLastRecv( ) >= 10 ) - { - delete *i; - i = m_ReconnectSockets.erase( i ); - continue; - } - - (*i)->DoRecv( &fd ); - QString *RecvBuffer = (*i)->GetBytes( ); - QByteArray Bytes = RecvBuffer->toUtf8(); - - // a packet is at least 4 bytes - - if( Bytes.size( ) >= 4 ) - { - if( Bytes[0] == GPS_HEADER_CONSTANT ) - { - // bytes 2 and 3 contain the length of the packet - - uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); - - if( Length >= 4 ) - { - if( Bytes.size( ) >= Length ) - { - if( Bytes[1] == CGPSProtocol :: GPS_RECONNECT && Length == 13 ) - { - unsigned char PID = Bytes[4]; - uint32_t ReconnectKey = UTIL_QByteArrayToUInt32( Bytes, false, 5 ); - uint32_t LastPacket = UTIL_QByteArrayToUInt32( Bytes, false, 9 ); - - // look for a matching player in a running game - - CGamePlayer *Match = NULL; - - for( QVector :: iterator j = m_Games.begin( ); j != m_Games.end( ); j++ ) - { - if( (*j)->GetGameLoaded( ) ) - { - CGamePlayer *Player = (*j)->GetPlayerFromPID( PID ); - - if( Player && Player->GetGProxy( ) && Player->GetGProxyReconnectKey( ) == ReconnectKey ) - { - Match = Player; - break; - } - } - } - - if( Match ) - { - // reconnect successful! - - *RecvBuffer = RecvBuffer->mid( Length ); - Match->EventGProxyReconnect( *i, LastPacket ); - i = m_ReconnectSockets.erase( i ); - continue; - } - else - { - (*i)->PutBytes( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_NOTFOUND ) ); - (*i)->DoSend( &send_fd ); - delete *i; - i = m_ReconnectSockets.erase( i ); - continue; - } - } - else - { - (*i)->PutBytes( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_INVALID ) ); - (*i)->DoSend( &send_fd ); - delete *i; - i = m_ReconnectSockets.erase( i ); - continue; - } - } - } - else - { - (*i)->PutBytes( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_INVALID ) ); - (*i)->DoSend( &send_fd ); - delete *i; - i = m_ReconnectSockets.erase( i ); - continue; - } - } - else - { - (*i)->PutBytes( m_GPSProtocol->SEND_GPSS_REJECT( REJECTGPS_INVALID ) ); - (*i)->DoSend( &send_fd ); - delete *i; - i = m_ReconnectSockets.erase( i ); - continue; - } - } - - (*i)->DoSend( &send_fd ); - i++; - } // autohost @@ -912,7 +846,7 @@ void CGHost :: EventBNETGameRefreshFailed( CBNET *bnet ) if( m_CurrentGame->GetNumHumanPlayers( ) == 0 ) m_CurrentGame->SetExiting( true ); - m_CurrentGame->SetRefreshError( true ); + m_CurrentGame->EventRefreshError(); } } diff --git a/ghost/ghost.h b/ghost/ghost.h index 2949111..622f18d 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -23,6 +23,7 @@ #include "includes.h" #include +#include // // CGHost @@ -47,10 +48,15 @@ class CConfig; class CGHost : public QObject { Q_OBJECT + +public slots: + void EventIncomingReconnection(); + void EventReconnectionSocketReadyRead(); + void UpdateEvent(); + public: - CUDPSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) - CTCPServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects - QVector m_ReconnectSockets;// vector of sockets attempting to reconnect (connected but not identified yet) + QUdpSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) + QTcpServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects CGPSProtocol *m_GPSProtocol; CCRC32 *m_CRC; // for calculating CRC's CSHA1 *m_SHA; // for calculating SHA1's diff --git a/ghost/ghost.pro b/ghost/ghost.pro index 593feb2..fd78b00 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -2,90 +2,86 @@ # Project created by QtCreator 2010-04-19T13:31:03 # ------------------------------------------------- QT += network \ - sql + sql QT -= gui TARGET = ghost CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += util.cpp \ - statsw3mmd.cpp \ - statsdota.cpp \ - stats.cpp \ - sqlite3.c \ - sha1.cpp \ - savegame.cpp \ - replay.cpp \ - packed.cpp \ - map.cpp \ - language.cpp \ - gpsprotocol.cpp \ - ghostdbsqlite.cpp \ - ghostdbmysql.cpp \ - ghostdb.cpp \ - ghost.cpp \ - gameslot.cpp \ - gameprotocol.cpp \ - gameplayer.cpp \ - game_base.cpp \ - game_admin.cpp \ - game.cpp \ - csvparser.cpp \ - crc32.cpp \ - config.cpp \ - commandpacket.cpp \ - bnlsprotocol.cpp \ - bnlsclient.cpp \ - bnetprotocol.cpp \ - bnet.cpp \ - bncsutilinterface.cpp \ - main.cpp + statsw3mmd.cpp \ + statsdota.cpp \ + stats.cpp \ + sqlite3.c \ + sha1.cpp \ + savegame.cpp \ + replay.cpp \ + packed.cpp \ + map.cpp \ + language.cpp \ + gpsprotocol.cpp \ + ghostdbsqlite.cpp \ + ghostdbmysql.cpp \ + ghostdb.cpp \ + ghost.cpp \ + gameslot.cpp \ + gameprotocol.cpp \ + gameplayer.cpp \ + game_base.cpp \ + game_admin.cpp \ + game.cpp \ + csvparser.cpp \ + crc32.cpp \ + config.cpp \ + commandpacket.cpp \ + bnlsprotocol.cpp \ + bnlsclient.cpp \ + bnetprotocol.cpp \ + bnet.cpp \ + bncsutilinterface.cpp \ + main.cpp OTHER_FILES += w3g_format.txt \ - w3g_actions.txt \ - ghost.vcproj + w3g_actions.txt \ + ghost.vcproj INCLUDEPATH += ../StormLib \ - ../bncsutil/src + ../bncsutil/src LIBS += -L../StormLib/stormlib \ - -L../bncsutil/src/bncsutil \ - -lbncsutil \ - -lStorm \ - -lboost_date_time-mt \ - -lboost_thread-mt \ - -lboost_system-mt \ - -lboost_filesystem-mt + -L../bncsutil/src/bncsutil \ + -lbncsutil \ + -lStorm HEADERS += util.h \ - statsw3mmd.h \ - statsdota.h \ - stats.h \ - sqlite3ext.h \ - sqlite3.h \ - socket.h \ - sha1.h \ - savegame.h \ - replay.h \ - packed.h \ - next_combination.h \ - ms_stdint.h \ - map.h \ - language.h \ - includes.h \ - gpsprotocol.h \ - ghostdbsqlite.h \ - ghostdbmysql.h \ - ghostdb.h \ - ghost.h \ - gameslot.h \ - gameprotocol.h \ - gameplayer.h \ - game_base.h \ - game_admin.h \ - game.h \ - csvparser.h \ - crc32.h \ - config.h \ - commandpacket.h \ - bnlsprotocol.h \ - bnlsclient.h \ - bnetprotocol.h \ - bnet.h \ - bncsutilinterface.h + statsw3mmd.h \ + statsdota.h \ + stats.h \ + sqlite3ext.h \ + sqlite3.h \ + socket.h \ + sha1.h \ + savegame.h \ + replay.h \ + packed.h \ + next_combination.h \ + ms_stdint.h \ + map.h \ + language.h \ + includes.h \ + gpsprotocol.h \ + ghostdbsqlite.h \ + ghostdbmysql.h \ + ghostdb.h \ + ghost.h \ + gameslot.h \ + gameprotocol.h \ + gameplayer.h \ + game_base.h \ + game_admin.h \ + game.h \ + csvparser.h \ + crc32.h \ + config.h \ + commandpacket.h \ + bnlsprotocol.h \ + bnlsclient.h \ + bnetprotocol.h \ + bnet.h \ + bncsutilinterface.h From 1671afc0059973002f16da5ecd5f474d0b79e158 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 00:16:45 +0000 Subject: [PATCH 07/69] this Makefile shouldn't be in here --- ghost/Makefile | 615 ------------------------------------------------- 1 file changed, 615 deletions(-) delete mode 100644 ghost/Makefile diff --git a/ghost/Makefile b/ghost/Makefile deleted file mode 100644 index 05fbd17..0000000 --- a/ghost/Makefile +++ /dev/null @@ -1,615 +0,0 @@ -############################################################################# -# Makefile for building: ghost -# Generated by qmake (2.01a) (Qt 4.6.2) on: Tue Apr 20 01:52:45 2010 -# Project: ghost.pro -# Template: app -# Command: /usr/bin/qmake -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro -############################################################################# - -####### Compiler, tools and options - -CC = gcc -CXX = g++ -DEFINES = -DQT_SQL_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -CFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES) -CXXFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES) -INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtNetwork -I/usr/include/qt4/QtSql -I/usr/include/qt4 -I../StormLib -I../bncsutil/src -I. -LINK = g++ -LFLAGS = -Wl,-rpath,/usr/lib/qt4 -LIBS = $(SUBLIBS) -L/usr/lib/qt4 -L../StormLib/stormlib -L../bncsutil/src/bncsutil -lbncsutil -lStorm -lQtSql -L/usr/lib/mysql -L/usr/lib/qt4 -lQtNetwork -lQtCore -lgthread-2.0 -lrt -lglib-2.0 -lpthread -AR = ar cqs -RANLIB = -QMAKE = /usr/bin/qmake -TAR = tar -cf -COMPRESS = gzip -9f -COPY = cp -f -SED = sed -COPY_FILE = $(COPY) -COPY_DIR = $(COPY) -r -STRIP = strip -INSTALL_FILE = install -m 644 -p -INSTALL_DIR = $(COPY_DIR) -INSTALL_PROGRAM = install -m 755 -p -DEL_FILE = rm -f -SYMLINK = ln -f -s -DEL_DIR = rmdir -MOVE = mv -f -CHK_DIR_EXISTS= test -d -MKDIR = mkdir -p - -####### Output directory - -OBJECTS_DIR = ./ - -####### Files - -SOURCES = util.cpp \ - statsw3mmd.cpp \ - statsdota.cpp \ - stats.cpp \ - sqlite3.c \ - sha1.cpp \ - savegame.cpp \ - replay.cpp \ - packed.cpp \ - map.cpp \ - language.cpp \ - gpsprotocol.cpp \ - ghostdbsqlite.cpp \ - ghostdbmysql.cpp \ - ghostdb.cpp \ - ghost.cpp \ - gameslot.cpp \ - gameprotocol.cpp \ - gameplayer.cpp \ - game_base.cpp \ - game_admin.cpp \ - game.cpp \ - csvparser.cpp \ - crc32.cpp \ - config.cpp \ - commandpacket.cpp \ - bnlsprotocol.cpp \ - bnlsclient.cpp \ - bnetprotocol.cpp \ - bnet.cpp \ - bncsutilinterface.cpp \ - main.cpp moc_ghost.cpp \ - moc_gameplayer.cpp \ - moc_game_base.cpp -OBJECTS = util.o \ - statsw3mmd.o \ - statsdota.o \ - stats.o \ - sqlite3.o \ - sha1.o \ - savegame.o \ - replay.o \ - packed.o \ - map.o \ - language.o \ - gpsprotocol.o \ - ghostdbsqlite.o \ - ghostdbmysql.o \ - ghostdb.o \ - ghost.o \ - gameslot.o \ - gameprotocol.o \ - gameplayer.o \ - game_base.o \ - game_admin.o \ - game.o \ - csvparser.o \ - crc32.o \ - config.o \ - commandpacket.o \ - bnlsprotocol.o \ - bnlsclient.o \ - bnetprotocol.o \ - bnet.o \ - bncsutilinterface.o \ - main.o \ - moc_ghost.o \ - moc_gameplayer.o \ - moc_game_base.o -DIST = /usr/share/qt4/mkspecs/common/g++.conf \ - /usr/share/qt4/mkspecs/common/unix.conf \ - /usr/share/qt4/mkspecs/common/linux.conf \ - /usr/share/qt4/mkspecs/qconfig.pri \ - /usr/share/qt4/mkspecs/features/qt_functions.prf \ - /usr/share/qt4/mkspecs/features/qt_config.prf \ - /usr/share/qt4/mkspecs/features/exclusive_builds.prf \ - /usr/share/qt4/mkspecs/features/default_pre.prf \ - /usr/share/qt4/mkspecs/features/debug.prf \ - /usr/share/qt4/mkspecs/features/default_post.prf \ - /usr/share/qt4/mkspecs/features/warn_on.prf \ - /usr/share/qt4/mkspecs/features/qt.prf \ - /usr/share/qt4/mkspecs/features/unix/thread.prf \ - /usr/share/qt4/mkspecs/features/moc.prf \ - /usr/share/qt4/mkspecs/features/resources.prf \ - /usr/share/qt4/mkspecs/features/uic.prf \ - /usr/share/qt4/mkspecs/features/yacc.prf \ - /usr/share/qt4/mkspecs/features/lex.prf \ - /usr/share/qt4/mkspecs/features/include_source_dir.prf \ - ghost.pro -QMAKE_TARGET = ghost -DESTDIR = -TARGET = ghost - -first: all -####### Implicit rules - -.SUFFIXES: .o .c .cpp .cc .cxx .C - -.cpp.o: - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" - -.cc.o: - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" - -.cxx.o: - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" - -.C.o: - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" - -.c.o: - $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" - -####### Build rules - -all: Makefile $(TARGET) - -$(TARGET): $(OBJECTS) - $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) - -Makefile: ghost.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/g++.conf \ - /usr/share/qt4/mkspecs/common/unix.conf \ - /usr/share/qt4/mkspecs/common/linux.conf \ - /usr/share/qt4/mkspecs/qconfig.pri \ - /usr/share/qt4/mkspecs/features/qt_functions.prf \ - /usr/share/qt4/mkspecs/features/qt_config.prf \ - /usr/share/qt4/mkspecs/features/exclusive_builds.prf \ - /usr/share/qt4/mkspecs/features/default_pre.prf \ - /usr/share/qt4/mkspecs/features/debug.prf \ - /usr/share/qt4/mkspecs/features/default_post.prf \ - /usr/share/qt4/mkspecs/features/warn_on.prf \ - /usr/share/qt4/mkspecs/features/qt.prf \ - /usr/share/qt4/mkspecs/features/unix/thread.prf \ - /usr/share/qt4/mkspecs/features/moc.prf \ - /usr/share/qt4/mkspecs/features/resources.prf \ - /usr/share/qt4/mkspecs/features/uic.prf \ - /usr/share/qt4/mkspecs/features/yacc.prf \ - /usr/share/qt4/mkspecs/features/lex.prf \ - /usr/share/qt4/mkspecs/features/include_source_dir.prf \ - /usr/lib/qt4/libQtSql.prl \ - /usr/lib/qt4/libQtCore.prl \ - /usr/lib/qt4/libQtNetwork.prl - $(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro -/usr/share/qt4/mkspecs/common/g++.conf: -/usr/share/qt4/mkspecs/common/unix.conf: -/usr/share/qt4/mkspecs/common/linux.conf: -/usr/share/qt4/mkspecs/qconfig.pri: -/usr/share/qt4/mkspecs/features/qt_functions.prf: -/usr/share/qt4/mkspecs/features/qt_config.prf: -/usr/share/qt4/mkspecs/features/exclusive_builds.prf: -/usr/share/qt4/mkspecs/features/default_pre.prf: -/usr/share/qt4/mkspecs/features/debug.prf: -/usr/share/qt4/mkspecs/features/default_post.prf: -/usr/share/qt4/mkspecs/features/warn_on.prf: -/usr/share/qt4/mkspecs/features/qt.prf: -/usr/share/qt4/mkspecs/features/unix/thread.prf: -/usr/share/qt4/mkspecs/features/moc.prf: -/usr/share/qt4/mkspecs/features/resources.prf: -/usr/share/qt4/mkspecs/features/uic.prf: -/usr/share/qt4/mkspecs/features/yacc.prf: -/usr/share/qt4/mkspecs/features/lex.prf: -/usr/share/qt4/mkspecs/features/include_source_dir.prf: -/usr/lib/qt4/libQtSql.prl: -/usr/lib/qt4/libQtCore.prl: -/usr/lib/qt4/libQtNetwork.prl: -qmake: FORCE - @$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ -unix CONFIG+=debug -o Makefile ghost.pro - -dist: - @$(CHK_DIR_EXISTS) .tmp/ghost1.0.0 || $(MKDIR) .tmp/ghost1.0.0 - $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/ghost1.0.0/ && $(COPY_FILE) --parents util.h statsw3mmd.h statsdota.h stats.h sqlite3ext.h sqlite3.h socket.h sha1.h savegame.h replay.h packed.h next_combination.h ms_stdint.h map.h language.h includes.h gpsprotocol.h ghostdbsqlite.h ghostdbmysql.h ghostdb.h ghost.h gameslot.h gameprotocol.h gameplayer.h game_base.h game_admin.h game.h csvparser.h crc32.h config.h commandpacket.h bnlsprotocol.h bnlsclient.h bnetprotocol.h bnet.h bncsutilinterface.h .tmp/ghost1.0.0/ && $(COPY_FILE) --parents util.cpp statsw3mmd.cpp statsdota.cpp stats.cpp sqlite3.c sha1.cpp savegame.cpp replay.cpp packed.cpp map.cpp language.cpp gpsprotocol.cpp ghostdbsqlite.cpp ghostdbmysql.cpp ghostdb.cpp ghost.cpp gameslot.cpp gameprotocol.cpp gameplayer.cpp game_base.cpp game_admin.cpp game.cpp csvparser.cpp crc32.cpp config.cpp commandpacket.cpp bnlsprotocol.cpp bnlsclient.cpp bnetprotocol.cpp bnet.cpp bncsutilinterface.cpp main.cpp .tmp/ghost1.0.0/ && (cd `dirname .tmp/ghost1.0.0` && $(TAR) ghost1.0.0.tar ghost1.0.0 && $(COMPRESS) ghost1.0.0.tar) && $(MOVE) `dirname .tmp/ghost1.0.0`/ghost1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/ghost1.0.0 - - -clean:compiler_clean - -$(DEL_FILE) $(OBJECTS) - -$(DEL_FILE) *~ core *.core - - -####### Sub-libraries - -distclean: clean - -$(DEL_FILE) $(TARGET) - -$(DEL_FILE) Makefile - - -mocclean: compiler_moc_header_clean compiler_moc_source_clean - -mocables: compiler_moc_header_make_all compiler_moc_source_make_all - -compiler_moc_header_make_all: moc_ghost.cpp moc_gameplayer.cpp moc_game_base.cpp -compiler_moc_header_clean: - -$(DEL_FILE) moc_ghost.cpp moc_gameplayer.cpp moc_game_base.cpp -moc_ghost.cpp: includes.h \ - ms_stdint.h \ - ghost.h - /usr/bin/moc $(DEFINES) $(INCPATH) ghost.h -o moc_ghost.cpp - -moc_gameplayer.cpp: includes.h \ - ms_stdint.h \ - gameplayer.h - /usr/bin/moc $(DEFINES) $(INCPATH) gameplayer.h -o moc_gameplayer.cpp - -moc_game_base.cpp: includes.h \ - ms_stdint.h \ - gameslot.h \ - game_base.h - /usr/bin/moc $(DEFINES) $(INCPATH) game_base.h -o moc_game_base.cpp - -compiler_rcc_make_all: -compiler_rcc_clean: -compiler_image_collection_make_all: qmake_image_collection.cpp -compiler_image_collection_clean: - -$(DEL_FILE) qmake_image_collection.cpp -compiler_moc_source_make_all: -compiler_moc_source_clean: -compiler_uic_make_all: -compiler_uic_clean: -compiler_yacc_decl_make_all: -compiler_yacc_decl_clean: -compiler_yacc_impl_make_all: -compiler_yacc_impl_clean: -compiler_lex_make_all: -compiler_lex_clean: -compiler_clean: compiler_moc_header_clean - -####### Compile - -util.o: util.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o util.o util.cpp - -statsw3mmd.o: statsw3mmd.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - ghostdb.h \ - gameprotocol.h \ - gameslot.h \ - game_base.h \ - stats.h \ - statsw3mmd.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o statsw3mmd.o statsw3mmd.cpp - -statsdota.o: statsdota.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - ghostdb.h \ - gameplayer.h \ - gameprotocol.h \ - gameslot.h \ - game_base.h \ - stats.h \ - statsdota.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o statsdota.o statsdota.cpp - -stats.o: stats.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - stats.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o stats.o stats.cpp - -sqlite3.o: sqlite3.c config.h - $(CC) -c $(CFLAGS) $(INCPATH) -o sqlite3.o sqlite3.c - -sha1.o: sha1.cpp sha1.h \ - ms_stdint.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o sha1.o sha1.cpp - -savegame.o: savegame.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - packed.h \ - savegame.h \ - gameslot.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o savegame.o savegame.cpp - -replay.o: replay.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - packed.h \ - replay.h \ - gameslot.h \ - gameprotocol.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o replay.o replay.cpp - -packed.o: packed.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - crc32.h \ - packed.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o packed.o packed.cpp - -map.o: map.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - crc32.h \ - sha1.h \ - config.h \ - map.h \ - gameslot.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o map.o map.cpp - -language.o: language.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - language.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o language.o language.cpp - -gpsprotocol.o: gpsprotocol.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - gpsprotocol.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gpsprotocol.o gpsprotocol.cpp - -ghostdbsqlite.o: ghostdbsqlite.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - ghostdb.h \ - ghostdbsqlite.h \ - sqlite3.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghostdbsqlite.o ghostdbsqlite.cpp - -ghostdbmysql.o: ghostdbmysql.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - ghostdb.h \ - ghostdbmysql.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghostdbmysql.o ghostdbmysql.cpp - -ghostdb.o: ghostdb.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - ghostdb.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghostdb.o ghostdb.cpp - -ghost.o: ghost.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - crc32.h \ - sha1.h \ - csvparser.h \ - config.h \ - language.h \ - socket.h \ - ghostdb.h \ - ghostdbsqlite.h \ - ghostdbmysql.h \ - bnet.h \ - map.h \ - gameslot.h \ - packed.h \ - savegame.h \ - gameplayer.h \ - gameprotocol.h \ - gpsprotocol.h \ - game_base.h \ - game.h \ - game_admin.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o ghost.o ghost.cpp - -gameslot.o: gameslot.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - gameslot.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gameslot.o gameslot.cpp - -gameprotocol.o: gameprotocol.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - crc32.h \ - gameplayer.h \ - gameprotocol.h \ - gameslot.h \ - game_base.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gameprotocol.o gameprotocol.cpp - -gameplayer.o: gameplayer.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - language.h \ - socket.h \ - commandpacket.h \ - bnet.h \ - map.h \ - gameslot.h \ - gameplayer.h \ - gameprotocol.h \ - gpsprotocol.h \ - game_base.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o gameplayer.o gameplayer.cpp - -game_base.o: game_base.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - language.h \ - socket.h \ - ghostdb.h \ - bnet.h \ - map.h \ - gameslot.h \ - packed.h \ - savegame.h \ - replay.h \ - gameplayer.h \ - gameprotocol.h \ - game_base.h \ - next_combination.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o game_base.o game_base.cpp - -game_admin.o: game_admin.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - language.h \ - socket.h \ - ghostdb.h \ - bnet.h \ - map.h \ - gameslot.h \ - packed.h \ - savegame.h \ - replay.h \ - gameplayer.h \ - gameprotocol.h \ - game_base.h \ - game_admin.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o game_admin.o game_admin.cpp - -game.o: game.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - language.h \ - socket.h \ - ghostdb.h \ - bnet.h \ - map.h \ - gameslot.h \ - packed.h \ - savegame.h \ - gameplayer.h \ - gameprotocol.h \ - game_base.h \ - game.h \ - stats.h \ - statsdota.h \ - statsw3mmd.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o game.o game.cpp - -csvparser.o: csvparser.cpp csvparser.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o csvparser.o csvparser.cpp - -crc32.o: crc32.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - crc32.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o crc32.o crc32.cpp - -config.o: config.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - config.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o config.o config.cpp - -commandpacket.o: commandpacket.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - commandpacket.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o commandpacket.o commandpacket.cpp - -bnlsprotocol.o: bnlsprotocol.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - bnlsprotocol.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnlsprotocol.o bnlsprotocol.cpp - -bnlsclient.o: bnlsclient.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - socket.h \ - commandpacket.h \ - bnlsprotocol.h \ - bnlsclient.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnlsclient.o bnlsclient.cpp - -bnetprotocol.o: bnetprotocol.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - bnetprotocol.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnetprotocol.o bnetprotocol.cpp - -bnet.o: bnet.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h \ - language.h \ - socket.h \ - commandpacket.h \ - ghostdb.h \ - bncsutilinterface.h \ - bnlsclient.h \ - bnetprotocol.h \ - bnet.h \ - map.h \ - gameslot.h \ - packed.h \ - savegame.h \ - replay.h \ - gameprotocol.h \ - game_base.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bnet.o bnet.cpp - -bncsutilinterface.o: bncsutilinterface.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - bncsutilinterface.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o bncsutilinterface.o bncsutilinterface.cpp - -main.o: main.cpp ghost.h \ - includes.h \ - ms_stdint.h \ - util.h \ - config.h - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp - -moc_ghost.o: moc_ghost.cpp - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_ghost.o moc_ghost.cpp - -moc_gameplayer.o: moc_gameplayer.cpp - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_gameplayer.o moc_gameplayer.cpp - -moc_game_base.o: moc_game_base.cpp - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_game_base.o moc_game_base.cpp - -####### Install - -install: FORCE - -uninstall: FORCE - -FORCE: - From d0ee388078241d0e2898e40bcaf8db1465fbcd50 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 01:16:18 +0000 Subject: [PATCH 08/69] nearly there --- ghost/bnet.cpp | 461 +++++++++++++++++++++---------------------- ghost/bnet.h | 39 +++- ghost/bnlsclient.cpp | 18 +- ghost/bnlsclient.h | 4 +- ghost/game.h | 6 +- ghost/game_admin.h | 1 - ghost/game_base.h | 4 - ghost/ghost.cpp | 132 ++----------- ghost/ghost.h | 5 +- 9 files changed, 290 insertions(+), 380 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index e26fd87..651b4a1 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -46,11 +46,31 @@ // CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ) + : QObject(NULL) { // todotodo: append path seperator to Warcraft3Path if needed - + m_Retries = 0; m_GHost = nGHost; - m_Socket = new CTCPClient( ); + m_Socket = new QTcpSocket( ); + + QObject::connect(m_Socket, SIGNAL(connected()), this, SLOT(socketConnected())); + QObject::connect(m_Socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); + QObject::connect(m_Socket, SIGNAL(readyRead()), this, SLOT(socketDataReady())); + QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); + + m_CallableUpdateTimer.setInterval(200); + m_CallableUpdateTimer.start(); + m_AdminListUpdateTimer.setInterval(60000); + m_AdminListUpdateTimer.start(); + m_BanListRefreshTimer.setInterval(3600000); + m_BanListRefreshTimer.start(); + m_NULLTimer.setInterval(60000); + QObject::connect(&m_NULLTimer, SIGNAL(timeout()), this, SLOT(timeout_NULL())); + + QObject::connect(&m_CallableUpdateTimer, SIGNAL(timeout()), this, SLOT(EventCallableUpdateTimeout())); + QObject::connect(&m_AdminListUpdateTimer, SIGNAL(timeout()), this, SLOT(EventUpdateAdminList())); + QObject::connect(&m_BanListRefreshTimer, SIGNAL(timeout()), this, SLOT(EventRefreshBanList())); + m_Protocol = new CBNETProtocol( ); m_BNLSClient = NULL; m_BNCSUtil = new CBNCSUtilInterface( nUserName, nUserPassword ); @@ -117,13 +137,11 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_HostCounterID = nHostCounterID; m_LastDisconnectedTime = 0; m_LastConnectionAttemptTime = 0; - m_LastNullTime = 0; m_LastOutPacketTicks = 0; m_LastOutPacketSize = 0; m_LastAdminRefreshTime = GetTime( ); m_LastBanRefreshTime = GetTime( ); m_FirstConnect = true; - m_WaitingToConnect = true; m_LoggedIn = false; m_InChat = false; m_HoldFriends = nHoldFriends; @@ -185,26 +203,172 @@ CBNET :: ~CBNET( ) delete *i; } -QByteArray CBNET :: GetUniqueName( ) +void CBNET::socketConnect() { - return m_Protocol->GetUniqueName( ); + // attempt to connect to battle.net + + m_FirstConnect = false; + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connecting to server [" + m_Server + "] on port 6112" ); + m_GHost->EventBNETConnecting( this ); + + if( m_ServerIP.isEmpty( ) ) + m_Socket->connectToHost( m_Server, 6112 ); + + else + { + // use cached server IP address since resolving takes time and is blocking + + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using cached server IP address " + m_ServerIP ); + m_Socket->connectToHost( m_ServerIP, 6112 ); + } + + if (m_Socket->waitForConnected(15000)) + { + m_ServerIP = m_Socket->peerAddress().toString(); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] resolved and cached server IP address " + m_ServerIP ); + } + + else + { + // the connection attempt timed out (15 seconds) + + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connect timed out" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); + m_GHost->EventBNETConnectTimedOut( this ); + m_Socket->abort(); + m_Socket->reset(); + m_Socket->deleteLater(); + m_Socket = NULL; + m_LastDisconnectedTime = GetTime( ); + QTimer::singleShot(90000, this, SLOT(socketConnect())); + m_NULLTimer.stop(); + } + + m_LastConnectionAttemptTime = GetTime( ); + m_Retries++; +} + +void CBNET::timeout_NULL() +{ + m_Socket->write( m_Protocol->SEND_SID_NULL( ) ); +} + +void CBNET::socketConnected() +{ + // the connection attempt completed + + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connected" ); + m_GHost->EventBNETConnected( this ); + m_Socket->write( m_Protocol->SEND_PROTOCOL_INITIALIZE_SELECTOR( ) ); + m_Socket->write( m_Protocol->SEND_SID_AUTH_INFO( m_War3Version, m_GHost->m_TFT, m_LocaleID, m_CountryAbbrev, m_Country ) ); + m_NULLTimer.start(); + + while( !m_OutPackets.isEmpty( ) ) + m_OutPackets.dequeue( ); +} + +void CBNET::socketDisconnected() +{ + // the socket was disconnected + + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] disconnected from battle.net" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); + m_GHost->EventBNETDisconnected( this ); + delete m_BNLSClient; + m_BNLSClient = NULL; + m_BNCSUtil->Reset( m_UserName, m_UserPassword ); + m_Socket->abort(); + m_Socket->deleteLater(); + m_Socket = NULL; + m_LastDisconnectedTime = GetTime( ); + m_LoggedIn = false; + m_InChat = false; + m_NULLTimer.stop(); + + if (m_Retries > 6) + { + CONSOLE_Print("[BNET: " + m_ServerAlias + "] giving up after 5 failed retries, waiting for 10 minutes to reconnect" ); + QTimer::singleShot(600000, this, SLOT(socketConnect())); + m_Retries = 0; + return; + } + + QTimer::singleShot(90000, this, SLOT(socketConnect())); + } -unsigned int CBNET :: SetFD( void *fd, void *send_fd, int *nfds ) +void CBNET::sendWardenResponse(const QByteArray & response) { - unsigned int NumFDs = 0; + if (m_Socket->state() != QAbstractSocket::ConnectedState) + return; + + m_Socket->write( m_Protocol->SEND_SID_WARDEN( response ) ); +} + +void CBNET::socketDataReady() +{ + // the socket is connected and everything appears to be working properly + + ExtractPackets( ); + ProcessPackets( ); + + // check if at least one packet is waiting to be sent and if we've waited long enough to prevent flooding + // this formula has changed many times but currently we wait 1 second if the last packet was "small", 3.5 seconds if it was "medium", and 4 seconds if it was "big" + + uint32_t WaitTicks = 0; + + if( m_LastOutPacketSize < 10 ) + WaitTicks = 1000; + else if( m_LastOutPacketSize < 100 ) + WaitTicks = 3500; + else + WaitTicks = 4000; - if( !m_Socket->HasError( ) && m_Socket->GetConnected( ) ) + if( !m_OutPackets.isEmpty( ) && GetTicks( ) - m_LastOutPacketTicks >= WaitTicks ) { - m_Socket->SetFD( (fd_set *)fd, (fd_set *)send_fd, nfds ); - NumFDs++; + if( m_OutPackets.size( ) > 7 ) + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); + + m_Socket->write( m_OutPackets.front( ) ); + m_LastOutPacketSize = m_OutPackets.front( ).size( ); + m_OutPackets.dequeue( ); + m_LastOutPacketTicks = GetTicks( ); } +} + +void CBNET::socketError() +{ + // the socket has an error + + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] disconnected from battle.net due to socket error: " + m_Socket->errorString() ); + + if( m_Socket->error() == QAbstractSocket::RemoteHostClosedError && GetTime( ) - m_LastConnectionAttemptTime <= 15 ) + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] warning - you are probably temporarily IP banned from battle.net" ); + + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); + m_GHost->EventBNETDisconnected( this ); + delete m_BNLSClient; + m_BNLSClient = NULL; + m_BNCSUtil->Reset( m_UserName, m_UserPassword ); + m_Socket->abort(); + m_Socket->deleteLater(); + m_Socket = NULL; + m_LastDisconnectedTime = GetTime( ); + m_LoggedIn = false; + m_InChat = false; + m_NULLTimer.stop(); - return NumFDs; + QTimer::singleShot(90000, this, SLOT(socketConnect())); } -bool CBNET :: Update( void *fd, void *send_fd ) +QByteArray CBNET :: GetUniqueName( ) { + return m_Protocol->GetUniqueName( ); +} + +void CBNET::EventCallableUpdateTimeout() +{ + // // update callables // @@ -394,11 +558,6 @@ bool CBNET :: Update( void *fd, void *send_fd ) i++; } - // refresh the admin list every 5 minutes - - if( !m_CallableAdminList && GetTime( ) - m_LastAdminRefreshTime >= 300 ) - m_CallableAdminList = m_GHost->m_DB->ThreadedAdminList( m_Server ); - if( m_CallableAdminList && m_CallableAdminList->GetReady( ) ) { // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed admin list (" + UTIL_ToString( m_Admins.size( ) ) + " -> " + UTIL_ToString( m_CallableAdminList->GetResult( ).size( ) ) + " admins)" ); @@ -409,11 +568,6 @@ bool CBNET :: Update( void *fd, void *send_fd ) m_LastAdminRefreshTime = GetTime( ); } - // refresh the ban list every 60 minutes - - if( !m_CallableBanList && GetTime( ) - m_LastBanRefreshTime >= 3600 ) - m_CallableBanList = m_GHost->m_DB->ThreadedBanList( m_Server ); - if( m_CallableBanList && m_CallableBanList->GetReady( ) ) { // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed ban list (" + UTIL_ToString( m_Bans.size( ) ) + " -> " + UTIL_ToString( m_CallableBanList->GetResult( ).size( ) ) + " bans)" ); @@ -427,219 +581,56 @@ bool CBNET :: Update( void *fd, void *send_fd ) m_CallableBanList = NULL; m_LastBanRefreshTime = GetTime( ); } +} - // we return at the end of each if statement so we don't have to deal with errors related to the order of the if statements - // that means it might take a few ms longer to complete a task involving multiple steps (in this case, reconnecting) due to blocking or sleeping - // but it's not a big deal at all, maybe 100ms in the worst possible case (based on a 50ms blocking time) - - if( m_Socket->HasError( ) ) - { - // the socket has an error - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] disconnected from battle.net due to socket error" ); - - if( m_Socket->GetError( ) == ECONNRESET && GetTime( ) - m_LastConnectionAttemptTime <= 15 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] warning - you are probably temporarily IP banned from battle.net" ); - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); - m_GHost->EventBNETDisconnected( this ); - delete m_BNLSClient; - m_BNLSClient = NULL; - m_BNCSUtil->Reset( m_UserName, m_UserPassword ); - m_Socket->Reset( ); - m_LastDisconnectedTime = GetTime( ); - m_LoggedIn = false; - m_InChat = false; - m_WaitingToConnect = true; - return m_Exiting; - } - - if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && !m_WaitingToConnect ) - { - // the socket was disconnected - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] disconnected from battle.net" ); - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); - m_GHost->EventBNETDisconnected( this ); - delete m_BNLSClient; - m_BNLSClient = NULL; - m_BNCSUtil->Reset( m_UserName, m_UserPassword ); - m_Socket->Reset( ); - m_LastDisconnectedTime = GetTime( ); - m_LoggedIn = false; - m_InChat = false; - m_WaitingToConnect = true; - return m_Exiting; - } - - if( m_Socket->GetConnected( ) ) - { - // the socket is connected and everything appears to be working properly - - m_Socket->DoRecv( (fd_set *)fd ); - ExtractPackets( ); - ProcessPackets( ); - - // update the BNLS client - - if( m_BNLSClient ) - { - QByteArray WardenResponse = m_BNLSClient->GetWardenResponse( ); - - if( !WardenResponse.isEmpty( ) ) - m_Socket->PutBytes( m_Protocol->SEND_SID_WARDEN( WardenResponse ) ); - } - - // check if at least one packet is waiting to be sent and if we've waited long enough to prevent flooding - // this formula has changed many times but currently we wait 1 second if the last packet was "small", 3.5 seconds if it was "medium", and 4 seconds if it was "big" - - uint32_t WaitTicks = 0; - - if( m_LastOutPacketSize < 10 ) - WaitTicks = 1000; - else if( m_LastOutPacketSize < 100 ) - WaitTicks = 3500; - else - WaitTicks = 4000; - - if( !m_OutPackets.isEmpty( ) && GetTicks( ) - m_LastOutPacketTicks >= WaitTicks ) - { - if( m_OutPackets.size( ) > 7 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); - - m_Socket->PutBytes( m_OutPackets.front( ) ); - m_LastOutPacketSize = m_OutPackets.front( ).size( ); - m_OutPackets.dequeue( ); - m_LastOutPacketTicks = GetTicks( ); - } - - // send a null packet every 60 seconds to detect disconnects - - if( GetTime( ) - m_LastNullTime >= 60 && GetTicks( ) - m_LastOutPacketTicks >= 60000 ) - { - m_Socket->PutBytes( m_Protocol->SEND_SID_NULL( ) ); - m_LastNullTime = GetTime( ); - } - - m_Socket->DoSend( (fd_set *)send_fd ); - return m_Exiting; - } - - if( m_Socket->GetConnecting( ) ) - { - // we are currently attempting to connect to battle.net - - if( m_Socket->CheckConnect( ) ) - { - // the connection attempt completed - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connected" ); - m_GHost->EventBNETConnected( this ); - m_Socket->PutBytes( m_Protocol->SEND_PROTOCOL_INITIALIZE_SELECTOR( ) ); - m_Socket->PutBytes( m_Protocol->SEND_SID_AUTH_INFO( m_War3Version, m_GHost->m_TFT, m_LocaleID, m_CountryAbbrev, m_Country ) ); - m_Socket->DoSend( (fd_set *)send_fd ); - m_LastNullTime = GetTime( ); - m_LastOutPacketTicks = GetTicks( ); - - while( !m_OutPackets.isEmpty( ) ) - m_OutPackets.dequeue( ); - - return m_Exiting; - } - else if( GetTime( ) - m_LastConnectionAttemptTime >= 15 ) - { - // the connection attempt timed out (15 seconds) - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connect timed out" ); - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); - m_GHost->EventBNETConnectTimedOut( this ); - m_Socket->Reset( ); - m_LastDisconnectedTime = GetTime( ); - m_WaitingToConnect = true; - return m_Exiting; - } - } - - if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && ( m_FirstConnect || GetTime( ) - m_LastDisconnectedTime >= 90 ) ) - { - // attempt to connect to battle.net - - m_FirstConnect = false; - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connecting to server [" + m_Server + "] on port 6112" ); - m_GHost->EventBNETConnecting( this ); - - if( !m_GHost->m_BindAddress.isEmpty( ) ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to bind to address [" + m_GHost->m_BindAddress + "]" ); - - if( m_ServerIP.isEmpty( ) ) - { - m_Socket->Connect( m_GHost->m_BindAddress, m_Server, 6112 ); - - if( !m_Socket->HasError( ) ) - { - m_ServerIP = m_Socket->GetIPString( ); - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] resolved and cached server IP address " + m_ServerIP ); - } - } - else - { - // use cached server IP address since resolving takes time and is blocking +void CBNET::EventUpdateAdminList() +{ + // refresh the admin list every 5 minutes - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using cached server IP address " + m_ServerIP ); - m_Socket->Connect( m_GHost->m_BindAddress, m_ServerIP, 6112 ); - } + if( !m_CallableAdminList ) + m_CallableAdminList = m_GHost->m_DB->ThreadedAdminList( m_Server ); +} - m_WaitingToConnect = false; - m_LastConnectionAttemptTime = GetTime( ); - return m_Exiting; - } +void CBNET::EventRefreshBanList() +{ + // refresh the ban list every 60 minutes - return m_Exiting; + if( !m_CallableBanList ) + m_CallableBanList = m_GHost->m_DB->ThreadedBanList( m_Server ); } void CBNET :: ExtractPackets( ) { - // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue - - QString *RecvBuffer = m_Socket->GetBytes( ); - QByteArray Bytes = RecvBuffer->toUtf8(); - // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes - while( Bytes.size( ) >= 4 ) + while( m_Socket->bytesAvailable() >= 4 ) { // byte 0 is always 255 + QByteArray header = m_Socket->peek(4); - if( Bytes[0] == BNET_HEADER_CONSTANT ) + if( header.at(0) != BNET_HEADER_CONSTANT ) { - // bytes 2 and 3 contain the length of the packet + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad header constant), disconnecting" ); + m_Socket->abort(); + return; + } - uint16_t Length = UTIL_QByteArrayToUInt16( Bytes, false, 2 ); + // bytes 2 and 3 contain the length of the packet - if( Length >= 4 ) - { - if( Bytes.size( ) >= Length ) - { - m_Packets.enqueue( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes[1], Bytes.left(Length) ) ); - *RecvBuffer = RecvBuffer->mid( Length ); - Bytes.remove(0, Length); - } - else - return; - } - else - { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad length), disconnecting" ); - m_Socket->Disconnect( ); - return; - } - } - else + uint16_t Length = UTIL_QByteArrayToUInt16( header, false, 2 ); + + if( Length < 4 ) { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad header constant), disconnecting" ); - m_Socket->Disconnect( ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad length), disconnecting" ); + m_Socket->abort(); return; } + + if( m_Socket->bytesAvailable() < Length ) + return; + + QByteArray Bytes = m_Socket->read(Length); + m_Packets.enqueue( new CCommandPacket( BNET_HEADER_CONSTANT, Bytes.at(1), Bytes ) ); } } @@ -686,7 +677,7 @@ void CBNET :: ProcessPackets( ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] joining channel [" + m_FirstChannel + "]" ); m_InChat = true; - m_Socket->PutBytes( m_Protocol->SEND_SID_JOINCHANNEL( m_FirstChannel ) ); + m_Socket->write( m_Protocol->SEND_SID_JOINCHANNEL( m_FirstChannel ) ); } break; @@ -720,7 +711,7 @@ void CBNET :: ProcessPackets( ) break; case CBNETProtocol :: SID_PING: - m_Socket->PutBytes( m_Protocol->SEND_SID_PING( m_Protocol->RECEIVE_SID_PING( Packet->GetData( ) ) ) ); + m_Socket->write( m_Protocol->SEND_SID_PING( m_Protocol->RECEIVE_SID_PING( Packet->GetData( ) ) ) ); break; case CBNETProtocol :: SID_AUTH_INFO: @@ -748,7 +739,7 @@ void CBNET :: ProcessPackets( ) else CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: Reign of Chaos" ); - m_Socket->PutBytes( m_Protocol->SEND_SID_AUTH_CHECK( m_GHost->m_TFT, m_Protocol->GetClientToken( ), m_BNCSUtil->GetEXEVersion( ), m_BNCSUtil->GetEXEVersionHash( ), m_BNCSUtil->GetKeyInfoROC( ), m_BNCSUtil->GetKeyInfoTFT( ), m_BNCSUtil->GetEXEInfo( ), "GHost" ) ); + m_Socket->write( m_Protocol->SEND_SID_AUTH_CHECK( m_GHost->m_TFT, m_Protocol->GetClientToken( ), m_BNCSUtil->GetEXEVersion( ), m_BNCSUtil->GetEXEVersionHash( ), m_BNCSUtil->GetKeyInfoROC( ), m_BNCSUtil->GetKeyInfoTFT( ), m_BNCSUtil->GetEXEInfo( ), "GHost" ) ); // the Warden seed is the first 4 bytes of the ROC key hash // initialize the Warden handler @@ -759,12 +750,14 @@ void CBNET :: ProcessPackets( ) delete m_BNLSClient; m_BNLSClient = new CBNLSClient( m_BNLSServer, m_BNLSPort, m_BNLSWardenCookie ); m_BNLSClient->QueueWardenSeed( UTIL_QByteArrayToUInt32( m_BNCSUtil->GetKeyInfoROC( ), false, 16 ) ); + + QObject::connect(m_BNLSClient, SIGNAL(newWardenResponse(QByteArray)), this, SLOT(sendWardenResponse(QByteArray))); } } else { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - bncsutil key hash failed (check your Warcraft 3 path and cd keys), disconnecting" ); - m_Socket->Disconnect( ); + m_Socket->abort(); delete Packet; return; } @@ -779,7 +772,7 @@ void CBNET :: ProcessPackets( ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] cd keys accepted" ); m_BNCSUtil->HELP_SID_AUTH_ACCOUNTLOGON( ); - m_Socket->PutBytes( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGON( m_BNCSUtil->GetClientKey( ), m_UserName ) ); + m_Socket->write( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGON( m_BNCSUtil->GetClientKey( ), m_UserName ) ); } else { @@ -804,7 +797,7 @@ void CBNET :: ProcessPackets( ) break; } - m_Socket->Disconnect( ); + m_Socket->abort(); delete Packet; return; } @@ -822,7 +815,7 @@ void CBNET :: ProcessPackets( ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using pvpgn logon type (for pvpgn servers only)" ); m_BNCSUtil->HELP_PvPGNPasswordHash( m_UserPassword ); - m_Socket->PutBytes( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGONPROOF( m_BNCSUtil->GetPvPGNPasswordHash( ) ) ); + m_Socket->write( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGONPROOF( m_BNCSUtil->GetPvPGNPasswordHash( ) ) ); } else { @@ -830,13 +823,13 @@ void CBNET :: ProcessPackets( ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using battle.net logon type (for official battle.net servers only)" ); m_BNCSUtil->HELP_SID_AUTH_ACCOUNTLOGONPROOF( m_Protocol->GetSalt( ), m_Protocol->GetServerPublicKey( ) ); - m_Socket->PutBytes( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGONPROOF( m_BNCSUtil->GetM1( ) ) ); + m_Socket->write( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGONPROOF( m_BNCSUtil->GetM1( ) ) ); } } else { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - invalid username, disconnecting" ); - m_Socket->Disconnect( ); + m_Socket->abort( ); delete Packet; return; } @@ -851,10 +844,10 @@ void CBNET :: ProcessPackets( ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon successful" ); m_LoggedIn = true; m_GHost->EventBNETLoggedIn( this ); - m_Socket->PutBytes( m_Protocol->SEND_SID_NETGAMEPORT( m_GHost->m_HostPort ) ); - m_Socket->PutBytes( m_Protocol->SEND_SID_ENTERCHAT( ) ); - m_Socket->PutBytes( m_Protocol->SEND_SID_FRIENDSLIST( ) ); - m_Socket->PutBytes( m_Protocol->SEND_SID_CLANMEMBERLIST( ) ); + m_Socket->write( m_Protocol->SEND_SID_NETGAMEPORT( m_GHost->m_HostPort ) ); + m_Socket->write( m_Protocol->SEND_SID_ENTERCHAT( ) ); + m_Socket->write( m_Protocol->SEND_SID_FRIENDSLIST( ) ); + m_Socket->write( m_Protocol->SEND_SID_CLANMEMBERLIST( ) ); } else { @@ -870,7 +863,7 @@ void CBNET :: ProcessPackets( ) else if( m_PasswordHashType != "pvpgn" && ( Server != "useast.battle.net" && Server != "uswest.battle.net" && Server != "asia.battle.net" && Server != "europe.battle.net" ) ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] it looks like you're trying to connect to a pvpgn server using a battle.net logon type, check your config file's \"battle.net custom data\" section" ); - m_Socket->Disconnect( ); + m_Socket->abort( ); delete Packet; return; } @@ -2184,19 +2177,19 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) void CBNET :: SendJoinChannel( QString channel ) { if( m_LoggedIn && m_InChat ) - m_Socket->PutBytes( m_Protocol->SEND_SID_JOINCHANNEL( channel ) ); + m_Socket->write( m_Protocol->SEND_SID_JOINCHANNEL( channel ) ); } void CBNET :: SendGetFriendsList( ) { if( m_LoggedIn ) - m_Socket->PutBytes( m_Protocol->SEND_SID_FRIENDSLIST( ) ); + m_Socket->write( m_Protocol->SEND_SID_FRIENDSLIST( ) ); } void CBNET :: SendGetClanList( ) { if( m_LoggedIn ) - m_Socket->PutBytes( m_Protocol->SEND_SID_CLANMEMBERLIST( ) ); + m_Socket->write( m_Protocol->SEND_SID_CLANMEMBERLIST( ) ); } void CBNET :: QueueEnterChat( ) diff --git a/ghost/bnet.h b/ghost/bnet.h index 427e05b..14feb11 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -25,7 +25,6 @@ // CBNET // -class CTCPClient; class CCommandPacket; class CBNCSUtilInterface; class CBNETProtocol; @@ -44,6 +43,14 @@ class CCallableBanList; class CCallableGamePlayerSummaryCheck; class CCallableDotAPlayerSummaryCheck; class CDBBan; +class CGHost; +class CSaveGame; +class CBaseGame; +class CMap; + +#include "includes.h" +#include +#include typedef pair PairedAdminCount; typedef pair PairedAdminAdd; @@ -54,12 +61,33 @@ typedef pair PairedBanRemove; typedef pair PairedGPSCheck; typedef pair PairedDPSCheck; -class CBNET + +class CBNET : public QObject { + Q_OBJECT +public slots: + void socketConnected(); + void socketDisconnected(); + void socketDataReady(); + void socketConnect(); + void socketError(); + void sendWardenResponse(const QByteArray & response); + void timeout_NULL(); + + void EventCallableUpdateTimeout(); + void EventUpdateAdminList(); + void EventRefreshBanList(); + +private: + QTimer m_NULLTimer; + QTimer m_CallableUpdateTimer, m_AdminListUpdateTimer, m_BanListRefreshTimer; + public: CGHost *m_GHost; + private: - CTCPClient *m_Socket; // the connection to battle.net + int m_Retries; + QTcpSocket *m_Socket; // the connection to battle.net CBNETProtocol *m_Protocol; // battle.net protocol CBNLSClient *m_BNLSClient; // the BNLS client (for external warden handling) QQueue m_Packets; // queue of incoming packets @@ -112,7 +140,6 @@ class CBNET uint32_t m_LastAdminRefreshTime; // GetTime when the admin list was last refreshed from the database uint32_t m_LastBanRefreshTime; // GetTime when the ban list was last refreshed from the database bool m_FirstConnect; // if we haven't tried to connect to battle.net yet - bool m_WaitingToConnect; // if we're waiting to reconnect to battle.net after being disconnected bool m_LoggedIn; // if we've logged into battle.net or not bool m_InChat; // if we've entered chat or not (but we're not necessarily in a chat channel yet) bool m_HoldFriends; // whether to auto hold friends when creating a game or not @@ -121,7 +148,7 @@ class CBNET public: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ); - ~CBNET( ); + virtual ~CBNET( ); bool GetExiting( ) { return m_Exiting; } QString GetServer( ) { return m_Server; } @@ -149,8 +176,6 @@ class CBNET // processing functions - unsigned int SetFD( void *fd, void *send_fd, int *nfds ); - bool Update( void *fd, void *send_fd ); void ExtractPackets( ); void ProcessPackets( ); void ProcessChatEvent( CIncomingChatEvent *chatEvent ); diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index a278aa5..8aab8bc 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -39,7 +39,7 @@ CBNLSClient :: CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCoo QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); QObject::connect(&m_NULLTimer, SIGNAL(timeout()), this, SLOT(timeout_NULL())); - m_NULLTimer.setInterval(50); + m_NULLTimer.setInterval(50000); m_Protocol = new CBNLSProtocol( ); m_WasConnected = false; @@ -116,20 +116,6 @@ CBNLSClient :: ~CBNLSClient( ) } } -QByteArray CBNLSClient :: GetWardenResponse( ) -{ - QByteArray WardenResponse; - - if( !m_WardenResponses.isEmpty( ) ) - { - WardenResponse = m_WardenResponses.front( ); - m_WardenResponses.dequeue( ); - m_TotalWardenOut++; - } - - return WardenResponse; -} - void CBNLSClient :: ExtractPackets( ) { while( m_Socket->bytesAvailable() >= 3 ) @@ -164,7 +150,7 @@ void CBNLSClient :: ProcessPackets( ) QByteArray WardenResponse = m_Protocol->RECEIVE_BNLS_WARDEN( Packet->GetData( ) ); if( !WardenResponse.isEmpty( ) ) - m_WardenResponses.enqueue( WardenResponse ); + emit newWardenResponse(WardenResponse); } delete Packet; diff --git a/ghost/bnlsclient.h b/ghost/bnlsclient.h index a9545b7..19c2c96 100644 --- a/ghost/bnlsclient.h +++ b/ghost/bnlsclient.h @@ -43,6 +43,9 @@ public slots: void socketError(); void timeout_NULL(); +signals: + emit void newWardenResponse(const QByteArray &data); + private: QTimer m_NULLTimer; QTcpSocket *m_Socket; // the connection to the BNLS server @@ -54,7 +57,6 @@ public slots: uint32_t m_LastNullTime; uint32_t m_WardenCookie; // the warden cookie QQueue m_OutPackets; // queue of outgoing packets to be sent - QQueue m_WardenResponses; // the warden responses to be sent to battle.net uint32_t m_TotalWardenIn; uint32_t m_TotalWardenOut; int m_Retries; diff --git a/ghost/game.h b/ghost/game.h index 57cffc4..f5d1420 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -25,6 +25,8 @@ // CGame // +#include "includes.h" + class CDBBan; class CDBGame; class CDBGamePlayer; @@ -40,6 +42,9 @@ typedef pair PairedBanAdd; typedef pair PairedGPSCheck; typedef pair PairedDPSCheck; +#include +#include "game_base.h" + class CGame : public CBaseGame { Q_OBJECT @@ -64,7 +69,6 @@ public slots: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CGame( ); - virtual bool Update( void *fd, void *send_fd ); virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); virtual void EventGameStarted( ); diff --git a/ghost/game_admin.h b/ghost/game_admin.h index 95bf297..505103f 100644 --- a/ghost/game_admin.h +++ b/ghost/game_admin.h @@ -50,7 +50,6 @@ class CAdminGame : public CBaseGame Q_OBJECT public slots: - void EventCallableReady(); void EventCallableUpdateTimeout(); protected: diff --git a/ghost/game_base.h b/ghost/game_base.h index 68e14d4..21d899b 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -198,10 +198,6 @@ public slots: virtual void SetAnnounce( uint32_t interval, QString message ); - // processing functions - - virtual bool Update( void *fd, void *send_fd ); - // generic functions to send packets to players virtual void Send( CGamePlayer *player, QByteArray data ); diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index f411e38..ff5224f 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -71,6 +71,9 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_CurrentGame = NULL; QString DBType = CFG->GetString( "db_type", "sqlite3" ); + m_CallableUpdateTimer.setInterval(200); + QObject::connect(&m_CallableUpdateTimer, SIGNAL(timeout()), this, SLOT(EventCallableUpdateTimeout())); + // create connections CONSOLE_Print( "[GHOST] opening primary database" ); @@ -472,9 +475,21 @@ void CGHost::EventReconnectionSocketReadyRead() } } -void CGHost::UpdateEvent() +void CGHost::EventCallableUpdateTimeout() { - Update(50000); + // update callables + + for( QVector :: iterator i = m_Callables.begin( ); i != m_Callables.end( ); ) + { + if( (*i)->GetReady( ) ) + { + m_DB->RecoverCallable( *i ); + delete *i; + i = m_Callables.erase( i ); + } + else + i++; + } } bool CGHost :: Update( long usecBlock ) @@ -547,20 +562,6 @@ bool CGHost :: Update( long usecBlock ) } } - // update callables - - for( QVector :: iterator i = m_Callables.begin( ); i != m_Callables.end( ); ) - { - if( (*i)->GetReady( ) ) - { - m_DB->RecoverCallable( *i ); - delete *i; - i = m_Callables.erase( i ); - } - else - i++; - } - // create the GProxy++ reconnect listener if( m_Reconnect ) @@ -589,21 +590,6 @@ bool CGHost :: Update( long usecBlock ) } } - unsigned int NumFDs = 0; - - // take every socket we own and throw it in one giant select statement so we can block on all sockets - - int nfds = 0; - fd_set fd; - fd_set send_fd; - FD_ZERO( &fd ); - FD_ZERO( &send_fd ); - - // 1. all battle.net sockets - - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - NumFDs += (*i)->SetFD( &fd, &send_fd, &nfds ); - // before we call select we need to determine how long to block for // previously we just blocked for a maximum of the passed usecBlock microseconds // however, in an effort to make game updates happen closer to the desired latency setting we now use a dynamic block interval @@ -615,94 +601,10 @@ bool CGHost :: Update( long usecBlock ) usecBlock = (*i)->GetNextTimedActionTicks( ) * 1000; } - // always block for at least 1ms just in case something goes wrong - // this prevents the bot from sucking up all the available CPU if a game keeps asking for immediate updates - // it's a bit ridiculous to include this check since, in theory, the bot is programmed well enough to never make this mistake - // however, considering who programmed it, it's worthwhile to do it anyway - - if( usecBlock < 1000 ) - usecBlock = 1000; - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = usecBlock; - - struct timeval send_tv; - send_tv.tv_sec = 0; - send_tv.tv_usec = 0; - -#ifdef WIN32 - select( 1, &fd, NULL, NULL, &tv ); - select( 1, NULL, &send_fd, NULL, &send_tv ); -#else - select( nfds + 1, &fd, NULL, NULL, &tv ); - select( nfds + 1, NULL, &send_fd, NULL, &send_tv ); -#endif - - if( NumFDs == 0 ) - { - // we don't have any sockets (i.e. we aren't connected to battle.net maybe due to a lost connection and there aren't any games running) - // select will return immediately and we'll chew up the CPU if we let it loop so just sleep for 50ms to kill some time - - MILLISLEEP( 50 ); - } bool AdminExit = false; bool BNETExit = false; - // update current game - - if( m_CurrentGame ) - { - if( m_CurrentGame->Update( &fd, &send_fd ) ) - { - CONSOLE_Print( "[GHOST] deleting current game [" + m_CurrentGame->GetGameName( ) + "]" ); - delete m_CurrentGame; - m_CurrentGame = NULL; - - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - { - (*i)->QueueGameUncreate( ); - (*i)->QueueEnterChat( ); - } - } - } - - // update admin game - - if( m_AdminGame ) - { - if( m_AdminGame->Update( &fd, &send_fd ) ) - { - CONSOLE_Print( "[GHOST] deleting admin game" ); - delete m_AdminGame; - m_AdminGame = NULL; - AdminExit = true; - } - } - - // update running games - - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); ) - { - if( (*i)->Update( &fd, &send_fd ) ) - { - CONSOLE_Print( "[GHOST] deleting game [" + (*i)->GetGameName( ) + "]" ); - EventGameDeleted( *i ); - delete *i; - i = m_Games.erase( i ); - } - } - - // update battle.net connections - - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - { - if( (*i)->Update( &fd, &send_fd ) ) - BNETExit = true; - } - - // autohost if( !m_AutoHostGameName.isEmpty( ) && m_AutoHostMaximumGames != 0 && m_AutoHostAutoStartPlayers != 0 && GetTime( ) - m_LastAutoHostTime >= 30 ) diff --git a/ghost/ghost.h b/ghost/ghost.h index 622f18d..6a7a315 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -45,6 +45,8 @@ class CMap; class CSaveGame; class CConfig; +#include + class CGHost : public QObject { Q_OBJECT @@ -52,9 +54,10 @@ class CGHost : public QObject public slots: void EventIncomingReconnection(); void EventReconnectionSocketReadyRead(); - void UpdateEvent(); + void EventCallableUpdateTimeout(); public: + QTimer m_CallableUpdateTimer; QUdpSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) QTcpServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects CGPSProtocol *m_GPSProtocol; From 1e3ad428fc97901ec4276beca8f6eccaaa1ce6d4 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 01:19:16 +0000 Subject: [PATCH 09/69] socket.\* no longer needed --- ghost/ghost.pro | 145 +++++---- ghost/socket.cpp | 785 ----------------------------------------------- ghost/socket.h | 231 -------------- 3 files changed, 72 insertions(+), 1089 deletions(-) delete mode 100644 ghost/socket.cpp delete mode 100644 ghost/socket.h diff --git a/ghost/ghost.pro b/ghost/ghost.pro index fd78b00..b7e3eab 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -2,86 +2,85 @@ # Project created by QtCreator 2010-04-19T13:31:03 # ------------------------------------------------- QT += network \ - sql + sql QT -= gui TARGET = ghost CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += util.cpp \ - statsw3mmd.cpp \ - statsdota.cpp \ - stats.cpp \ - sqlite3.c \ - sha1.cpp \ - savegame.cpp \ - replay.cpp \ - packed.cpp \ - map.cpp \ - language.cpp \ - gpsprotocol.cpp \ - ghostdbsqlite.cpp \ - ghostdbmysql.cpp \ - ghostdb.cpp \ - ghost.cpp \ - gameslot.cpp \ - gameprotocol.cpp \ - gameplayer.cpp \ - game_base.cpp \ - game_admin.cpp \ - game.cpp \ - csvparser.cpp \ - crc32.cpp \ - config.cpp \ - commandpacket.cpp \ - bnlsprotocol.cpp \ - bnlsclient.cpp \ - bnetprotocol.cpp \ - bnet.cpp \ - bncsutilinterface.cpp \ - main.cpp + statsw3mmd.cpp \ + statsdota.cpp \ + stats.cpp \ + sqlite3.c \ + sha1.cpp \ + savegame.cpp \ + replay.cpp \ + packed.cpp \ + map.cpp \ + language.cpp \ + gpsprotocol.cpp \ + ghostdbsqlite.cpp \ + ghostdbmysql.cpp \ + ghostdb.cpp \ + ghost.cpp \ + gameslot.cpp \ + gameprotocol.cpp \ + gameplayer.cpp \ + game_base.cpp \ + game_admin.cpp \ + game.cpp \ + csvparser.cpp \ + crc32.cpp \ + config.cpp \ + commandpacket.cpp \ + bnlsprotocol.cpp \ + bnlsclient.cpp \ + bnetprotocol.cpp \ + bnet.cpp \ + bncsutilinterface.cpp \ + main.cpp OTHER_FILES += w3g_format.txt \ - w3g_actions.txt \ - ghost.vcproj + w3g_actions.txt \ + ghost.vcproj INCLUDEPATH += ../StormLib \ - ../bncsutil/src + ../bncsutil/src LIBS += -L../StormLib/stormlib \ - -L../bncsutil/src/bncsutil \ - -lbncsutil \ - -lStorm + -L../bncsutil/src/bncsutil \ + -lbncsutil \ + -lStorm HEADERS += util.h \ - statsw3mmd.h \ - statsdota.h \ - stats.h \ - sqlite3ext.h \ - sqlite3.h \ - socket.h \ - sha1.h \ - savegame.h \ - replay.h \ - packed.h \ - next_combination.h \ - ms_stdint.h \ - map.h \ - language.h \ - includes.h \ - gpsprotocol.h \ - ghostdbsqlite.h \ - ghostdbmysql.h \ - ghostdb.h \ - ghost.h \ - gameslot.h \ - gameprotocol.h \ - gameplayer.h \ - game_base.h \ - game_admin.h \ - game.h \ - csvparser.h \ - crc32.h \ - config.h \ - commandpacket.h \ - bnlsprotocol.h \ - bnlsclient.h \ - bnetprotocol.h \ - bnet.h \ - bncsutilinterface.h + statsw3mmd.h \ + statsdota.h \ + stats.h \ + sqlite3ext.h \ + sqlite3.h \ + sha1.h \ + savegame.h \ + replay.h \ + packed.h \ + next_combination.h \ + ms_stdint.h \ + map.h \ + language.h \ + includes.h \ + gpsprotocol.h \ + ghostdbsqlite.h \ + ghostdbmysql.h \ + ghostdb.h \ + ghost.h \ + gameslot.h \ + gameprotocol.h \ + gameplayer.h \ + game_base.h \ + game_admin.h \ + game.h \ + csvparser.h \ + crc32.h \ + config.h \ + commandpacket.h \ + bnlsprotocol.h \ + bnlsclient.h \ + bnetprotocol.h \ + bnet.h \ + bncsutilinterface.h diff --git a/ghost/socket.cpp b/ghost/socket.cpp deleted file mode 100644 index f859005..0000000 --- a/ghost/socket.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* - - Copyright [2008] [Trevor Hogan] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/ - -*/ - -#include "ghost.h" -#include "util.h" -#include "socket.h" - -#include - -#ifndef WIN32 - int GetLastError( ) { return errno; } -#endif - -// -// CSocket -// - -CSocket :: CSocket( ) -{ - m_Socket = INVALID_SOCKET; - memset( &m_SIN, 0, sizeof( m_SIN ) ); - m_HasError = false; - m_Error = 0; -} - -CSocket :: CSocket( SOCKET nSocket, struct sockaddr_in nSIN ) -{ - m_Socket = nSocket; - m_SIN = nSIN; - m_HasError = false; - m_Error = 0; -} - -CSocket :: ~CSocket( ) -{ - if( m_Socket != INVALID_SOCKET ) - closesocket( m_Socket ); -} - -QByteArray CSocket :: GetPort( ) -{ - return UTIL_CreateQByteArray( m_SIN.sin_port, false ); -} - -QByteArray CSocket :: GetIP( ) -{ - return UTIL_CreateQByteArray( (uint32_t)m_SIN.sin_addr.s_addr, false ); -} - -QString CSocket :: GetIPString( ) -{ - return inet_ntoa( m_SIN.sin_addr ); -} - -QString CSocket :: GetErrorString( ) -{ - if( !m_HasError ) - return "NO ERROR"; - - switch( m_Error ) - { - case EWOULDBLOCK: return "EWOULDBLOCK"; - case EINPROGRESS: return "EINPROGRESS"; - case EALREADY: return "EALREADY"; - case ENOTSOCK: return "ENOTSOCK"; - case EDESTADDRREQ: return "EDESTADDRREQ"; - case EMSGSIZE: return "EMSGSIZE"; - case EPROTOTYPE: return "EPROTOTYPE"; - case ENOPROTOOPT: return "ENOPROTOOPT"; - case EPROTONOSUPPORT: return "EPROTONOSUPPORT"; - case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT"; - case EOPNOTSUPP: return "EOPNOTSUPP"; - case EPFNOSUPPORT: return "EPFNOSUPPORT"; - case EAFNOSUPPORT: return "EAFNOSUPPORT"; - case EADDRINUSE: return "EADDRINUSE"; - case EADDRNOTAVAIL: return "EADDRNOTAVAIL"; - case ENETDOWN: return "ENETDOWN"; - case ENETUNREACH: return "ENETUNREACH"; - case ENETRESET: return "ENETRESET"; - case ECONNABORTED: return "ECONNABORTED"; - case ECONNRESET: return "ECONNRESET"; - case ENOBUFS: return "ENOBUFS"; - case EISCONN: return "EISCONN"; - case ENOTCONN: return "ENOTCONN"; - case ESHUTDOWN: return "ESHUTDOWN"; - case ETOOMANYREFS: return "ETOOMANYREFS"; - case ETIMEDOUT: return "ETIMEDOUT"; - case ECONNREFUSED: return "ECONNREFUSED"; - case ELOOP: return "ELOOP"; - case ENAMETOOLONG: return "ENAMETOOLONG"; - case EHOSTDOWN: return "EHOSTDOWN"; - case EHOSTUNREACH: return "EHOSTUNREACH"; - case ENOTEMPTY: return "ENOTEMPTY"; - case EUSERS: return "EUSERS"; - case EDQUOT: return "EDQUOT"; - case ESTALE: return "ESTALE"; - case EREMOTE: return "EREMOTE"; - } - - return "UNKNOWN ERROR (" + UTIL_ToString( m_Error ) + ")"; -} - -void CSocket :: SetFD( fd_set *fd, fd_set *send_fd, int *nfds ) -{ - if( m_Socket == INVALID_SOCKET ) - return; - - FD_SET( m_Socket, fd ); - FD_SET( m_Socket, send_fd ); - -#ifndef WIN32 - if( m_Socket > *nfds ) - *nfds = m_Socket; -#endif -} - -void CSocket :: Allocate( int type ) -{ - m_Socket = socket( AF_INET, type, 0 ); - - if( m_Socket == INVALID_SOCKET ) - { - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[SOCKET] error (socket) - " + GetErrorString( ) ); - return; - } -} - -void CSocket :: Reset( ) -{ - if( m_Socket != INVALID_SOCKET ) - closesocket( m_Socket ); - - m_Socket = INVALID_SOCKET; - memset( &m_SIN, 0, sizeof( m_SIN ) ); - m_HasError = false; - m_Error = 0; -} - -// -// CTCPSocket -// - -CTCPSocket :: CTCPSocket( ) : CSocket( ) -{ - Allocate( SOCK_STREAM ); - m_Connected = false; - m_LastRecv = GetTime( ); - m_LastSend = GetTime( ); - - // make socket non blocking - -#ifdef WIN32 - int iMode = 1; - ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode ); -#else - fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK ); -#endif -} - -CTCPSocket :: CTCPSocket( SOCKET nSocket, struct sockaddr_in nSIN ) : CSocket( nSocket, nSIN ) -{ - m_Connected = true; - m_LastRecv = GetTime( ); - m_LastSend = GetTime( ); - - // make socket non blocking - -#ifdef WIN32 - int iMode = 1; - ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode ); -#else - fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK ); -#endif -} - -CTCPSocket :: ~CTCPSocket( ) -{ - -} - -void CTCPSocket :: Reset( ) -{ - CSocket :: Reset( ); - - Allocate( SOCK_STREAM ); - m_Connected = false; - m_RecvBuffer.clear( ); - m_SendBuffer.clear( ); - m_LastRecv = GetTime( ); - m_LastSend = GetTime( ); - - // make socket non blocking - -#ifdef WIN32 - int iMode = 1; - ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode ); -#else - fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK ); -#endif -} - -void CTCPSocket :: PutBytes( QString bytes ) -{ - m_SendBuffer.append(bytes); -} - -void CTCPSocket :: PutBytes( QByteArray bytes ) -{ - m_SendBuffer.append(bytes); -} - -void CTCPSocket :: DoRecv( fd_set *fd ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected ) - return; - - if( FD_ISSET( m_Socket, fd ) ) - { - // data is waiting, receive it - - char buffer[1024]; - int c = recv( m_Socket, buffer, 1024, 0 ); - - if( c == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK ) - { - // receive error - - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[TCPSOCKET] error (recv) - " + GetErrorString( ) ); - return; - } - else if( c == 0 ) - { - // the other end closed the connection - - CONSOLE_Print( "[TCPSOCKET] closed by remote host" ); - m_Connected = false; - } - else if( c > 0 ) - { - // success! add the received data to the buffer - - if( !m_LogFile.isEmpty( ) ) - { - ofstream Log; - Log.open( m_LogFile.c_str( ), ios :: app ); - - if( !Log.fail( ) ) - { - Log << " RECEIVE <<< " << UTIL_QByteArrayToHexString( UTIL_CreateQByteArray( (unsigned char *)buffer, c ) ) << endl; - Log.close( ); - } - } - - m_RecvBuffer += QString( buffer, c ); - m_LastRecv = GetTime( ); - } - } -} - -void CTCPSocket :: DoSend( fd_set *send_fd ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected || m_SendBuffer.isEmpty( ) ) - return; - - if( FD_ISSET( m_Socket, send_fd ) ) - { - // socket is ready, send it - - int s = send( m_Socket, m_SendBuffer.c_str( ), (int)m_SendBuffer.size( ), MSG_NOSIGNAL ); - - if( s == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK ) - { - // send error - - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[TCPSOCKET] error (send) - " + GetErrorString( ) ); - return; - } - else if( s > 0 ) - { - // success! only some of the data may have been sent, remove it from the buffer - - if( !m_LogFile.isEmpty( ) ) - { - ofstream Log; - Log.open( m_LogFile.c_str( ), ios :: app ); - - if( !Log.fail( ) ) - { - Log << "SEND >>> " << UTIL_QByteArrayToHexString( QByteArray( m_SendBuffer.begin( ), m_SendBuffer.begin( ) + s ) ) << endl; - Log.close( ); - } - } - - m_SendBuffer = m_SendBuffer.mid( s ); - m_LastSend = GetTime( ); - } - } -} - -void CTCPSocket :: Disconnect( ) -{ - if( m_Socket != INVALID_SOCKET ) - shutdown( m_Socket, SHUT_RDWR ); - - m_Connected = false; -} - -void CTCPSocket :: SetNoDelay( bool noDelay ) -{ - int OptVal = 0; - - if( noDelay ) - OptVal = 1; - - setsockopt( m_Socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&OptVal, sizeof( int ) ); -} - -// -// CTCPClient -// - -CTCPClient :: CTCPClient( ) : CTCPSocket( ) -{ - m_Connecting = false; -} - -CTCPClient :: ~CTCPClient( ) -{ - -} - -void CTCPClient :: Reset( ) -{ - CTCPSocket :: Reset( ); - m_Connecting = false; -} - -void CTCPClient :: Disconnect( ) -{ - CTCPSocket :: Disconnect( ); - m_Connecting = false; -} - -void CTCPClient :: Connect( QString localaddress, QString address, uint16_t port ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError || m_Connecting || m_Connected ) - return; - - if( !localaddress.isEmpty( ) ) - { - struct sockaddr_in LocalSIN; - memset( &LocalSIN, 0, sizeof( LocalSIN ) ); - LocalSIN.sin_family = AF_INET; - - if( ( LocalSIN.sin_addr.s_addr = inet_addr( localaddress.c_str( ) ) ) == INADDR_NONE ) - LocalSIN.sin_addr.s_addr = INADDR_ANY; - - LocalSIN.sin_port = htons( 0 ); - - if( bind( m_Socket, (struct sockaddr *)&LocalSIN, sizeof( LocalSIN ) ) == SOCKET_ERROR ) - { - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[TCPCLIENT] error (bind) - " + GetErrorString( ) ); - return; - } - } - - // get IP address - - struct hostent *HostInfo; - uint32_t HostAddress; - HostInfo = gethostbyname( address.c_str( ) ); - - if( !HostInfo ) - { - m_HasError = true; - // m_Error = h_error; - CONSOLE_Print( "[TCPCLIENT] error (gethostbyname)" ); - return; - } - - memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length ); - - // connect - - m_SIN.sin_family = AF_INET; - m_SIN.sin_addr.s_addr = HostAddress; - m_SIN.sin_port = htons( port ); - - if( connect( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR ) - { - if( GetLastError( ) != EINPROGRESS && GetLastError( ) != EWOULDBLOCK ) - { - // connect error - - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[TCPCLIENT] error (connect) - " + GetErrorString( ) ); - return; - } - } - - m_Connecting = true; -} - -bool CTCPClient :: CheckConnect( ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connecting ) - return false; - - fd_set fd; - FD_ZERO( &fd ); - FD_SET( m_Socket, &fd ); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - - // check if the socket is connected - -#ifdef WIN32 - if( select( 1, NULL, &fd, NULL, &tv ) == SOCKET_ERROR ) -#else - if( select( m_Socket + 1, NULL, &fd, NULL, &tv ) == SOCKET_ERROR ) -#endif - { - m_HasError = true; - m_Error = GetLastError( ); - return false; - } - - if( FD_ISSET( m_Socket, &fd ) ) - { - m_Connecting = false; - m_Connected = true; - return true; - } - - return false; -} - -// -// CTCPServer -// - -CTCPServer :: CTCPServer( ) : CTCPSocket( ) -{ - // set the socket to reuse the address in case it hasn't been released yet - - int optval = 1; - -#ifdef WIN32 - setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) ); -#else - setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) ); -#endif -} - -CTCPServer :: ~CTCPServer( ) -{ - -} - -bool CTCPServer :: Listen( QString address, uint16_t port ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return false; - - m_SIN.sin_family = AF_INET; - - if( !address.isEmpty( ) ) - { - if( ( m_SIN.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE ) - m_SIN.sin_addr.s_addr = INADDR_ANY; - } - else - m_SIN.sin_addr.s_addr = INADDR_ANY; - - m_SIN.sin_port = htons( port ); - - if( bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR ) - { - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[TCPSERVER] error (bind) - " + GetErrorString( ) ); - return false; - } - - // listen, queue length 8 - - if( listen( m_Socket, 8 ) == SOCKET_ERROR ) - { - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[TCPSERVER] error (listen) - " + GetErrorString( ) ); - return false; - } - - return true; -} - -CTCPSocket *CTCPServer :: Accept( fd_set *fd ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return NULL; - - if( FD_ISSET( m_Socket, fd ) ) - { - // a connection is waiting, accept it - - struct sockaddr_in Addr; - int AddrLen = sizeof( Addr ); - SOCKET NewSocket; - -#ifdef WIN32 - if( ( NewSocket = accept( m_Socket, (struct sockaddr *)&Addr, &AddrLen ) ) == INVALID_SOCKET ) -#else - if( ( NewSocket = accept( m_Socket, (struct sockaddr *)&Addr, (socklen_t *)&AddrLen ) ) == INVALID_SOCKET ) -#endif - { - // accept error, ignore it - } - else - { - // success! return the new socket - - return new CTCPSocket( NewSocket, Addr ); - } - } - - return NULL; -} - -// -// CUDPSocket -// - -CUDPSocket :: CUDPSocket( ) : CSocket( ) -{ - Allocate( SOCK_DGRAM ); - - // enable broadcast support - - int OptVal = 1; - setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (const char *)&OptVal, sizeof( int ) ); - - // set default broadcast target - m_BroadcastTarget.s_addr = INADDR_BROADCAST; -} - -CUDPSocket :: ~CUDPSocket( ) -{ - -} - -bool CUDPSocket :: SendTo( struct sockaddr_in sin, QByteArray message ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return false; - - QString MessageString = QString( message.begin( ), message.end( ) ); - - if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 ) - return false; - - return true; -} - -bool CUDPSocket :: SendTo( QString address, uint16_t port, QByteArray message ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return false; - - // get IP address - - struct hostent *HostInfo; - uint32_t HostAddress; - HostInfo = gethostbyname( address.c_str( ) ); - - if( !HostInfo ) - { - m_HasError = true; - // m_Error = h_error; - CONSOLE_Print( "[UDPSOCKET] error (gethostbyname)" ); - return false; - } - - memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length ); - struct sockaddr_in sin; - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = HostAddress; - sin.sin_port = htons( port ); - - return SendTo( sin, message ); -} - -bool CUDPSocket :: Broadcast( uint16_t port, QByteArray message ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return false; - - struct sockaddr_in sin; - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = m_BroadcastTarget.s_addr; - sin.sin_port = htons( port ); - - QString MessageString = QString( message.begin( ), message.end( ) ); - - if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 ) - { - CONSOLE_Print( "[UDPSOCKET] failed to broadcast packet (port " + UTIL_ToString( port ) + ", size " + UTIL_ToString( MessageString.size( ) ) + " bytes)" ); - return false; - } - - return true; -} - -void CUDPSocket :: SetBroadcastTarget( QString subnet ) -{ - if( subnet.isEmpty( ) ) - { - CONSOLE_Print( "[UDPSOCKET] using default broadcast target" ); - m_BroadcastTarget.s_addr = INADDR_BROADCAST; - } - else - { - // this function does not check whether the given subnet is a valid subnet the user is on - // convert QString representation of ip/subnet to in_addr - - CONSOLE_Print( "[UDPSOCKET] using broadcast target [" + subnet + "]" ); - m_BroadcastTarget.s_addr = inet_addr( subnet.c_str( ) ); - - // if conversion fails, inet_addr( ) returns INADDR_NONE - - if( m_BroadcastTarget.s_addr == INADDR_NONE ) - { - CONSOLE_Print( "[UDPSOCKET] invalid broadcast target, using default broadcast target" ); - m_BroadcastTarget.s_addr = INADDR_BROADCAST; - } - } -} - -void CUDPSocket :: SetDontRoute( bool dontRoute ) -{ - int OptVal = 0; - - if( dontRoute ) - OptVal = 1; - - // don't route packets; make them ignore routes set by routing table and send them to the interface - // belonging to the target address directly - - setsockopt( m_Socket, SOL_SOCKET, SO_DONTROUTE, (const char *)&OptVal, sizeof( int ) ); -} - -// -// CUDPServer -// - -CUDPServer :: CUDPServer( ) : CUDPSocket( ) -{ - // make socket non blocking - -#ifdef WIN32 - int iMode = 1; - ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode ); -#else - fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK ); -#endif - - // set the socket to reuse the address - // with UDP sockets this allows more than one program to listen on the same port - - int optval = 1; - -#ifdef WIN32 - setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) ); -#else - setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) ); -#endif -} - -CUDPServer :: ~CUDPServer( ) -{ - -} - -bool CUDPServer :: Bind( struct sockaddr_in sin ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return false; - - m_SIN = sin; - - if( bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR ) - { - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[UDPSERVER] error (bind) - " + GetErrorString( ) ); - return false; - } - - return true; -} - -bool CUDPServer :: Bind( QString address, uint16_t port ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError ) - return false; - - struct sockaddr_in sin; - sin.sin_family = AF_INET; - - if( !address.isEmpty( ) ) - { - if( ( sin.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE ) - sin.sin_addr.s_addr = INADDR_ANY; - } - else - sin.sin_addr.s_addr = INADDR_ANY; - - sin.sin_port = htons( port ); - - return Bind( sin ); -} - -void CUDPServer :: RecvFrom( fd_set *fd, struct sockaddr_in *sin, QString *message ) -{ - if( m_Socket == INVALID_SOCKET || m_HasError || !sin || !message ) - return; - - int AddrLen = sizeof( *sin ); - - if( FD_ISSET( m_Socket, fd ) ) - { - // data is waiting, receive it - - char buffer[1024]; - -#ifdef WIN32 - int c = recvfrom( m_Socket, buffer, 1024, 0, (struct sockaddr *)sin, &AddrLen ); -#else - int c = recvfrom( m_Socket, buffer, 1024, 0, (struct sockaddr *)sin, (socklen_t *)&AddrLen ); -#endif - - if( c == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK ) - { - // receive error - - m_HasError = true; - m_Error = GetLastError( ); - CONSOLE_Print( "[UDPSERVER] error (recvfrom) - " + GetErrorString( ) ); - } - else if( c > 0 ) - { - // success! - - *message = QString( buffer, c ); - } - } -} diff --git a/ghost/socket.h b/ghost/socket.h deleted file mode 100644 index 86b1502..0000000 --- a/ghost/socket.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - - Copyright [2008] [Trevor Hogan] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/ - -*/ - -#ifndef SOCKET_H -#define SOCKET_H - -#ifdef WIN32 - #include - #include - - #define EADDRINUSE WSAEADDRINUSE - #define EADDRNOTAVAIL WSAEADDRNOTAVAIL - #define EAFNOSUPPORT WSAEAFNOSUPPORT - #define EALREADY WSAEALREADY - #define ECONNABORTED WSAECONNABORTED - #define ECONNREFUSED WSAECONNREFUSED - #define ECONNRESET WSAECONNRESET - #define EDESTADDRREQ WSAEDESTADDRREQ - #define EDQUOT WSAEDQUOT - #define EHOSTDOWN WSAEHOSTDOWN - #define EHOSTUNREACH WSAEHOSTUNREACH - #define EINPROGRESS WSAEINPROGRESS - #define EISCONN WSAEISCONN - #define ELOOP WSAELOOP - #define EMSGSIZE WSAEMSGSIZE - // #define ENAMETOOLONG WSAENAMETOOLONG - #define ENETDOWN WSAENETDOWN - #define ENETRESET WSAENETRESET - #define ENETUNREACH WSAENETUNREACH - #define ENOBUFS WSAENOBUFS - #define ENOPROTOOPT WSAENOPROTOOPT - #define ENOTCONN WSAENOTCONN - // #define ENOTEMPTY WSAENOTEMPTY - #define ENOTSOCK WSAENOTSOCK - #define EOPNOTSUPP WSAEOPNOTSUPP - #define EPFNOSUPPORT WSAEPFNOSUPPORT - #define EPROTONOSUPPORT WSAEPROTONOSUPPORT - #define EPROTOTYPE WSAEPROTOTYPE - #define EREMOTE WSAEREMOTE - #define ESHUTDOWN WSAESHUTDOWN - #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT - #define ESTALE WSAESTALE - #define ETIMEDOUT WSAETIMEDOUT - #define ETOOMANYREFS WSAETOOMANYREFS - #define EUSERS WSAEUSERS - #define EWOULDBLOCK WSAEWOULDBLOCK -#else - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - typedef int SOCKET; - - #define INVALID_SOCKET -1 - #define SOCKET_ERROR -1 - - #define closesocket close - - extern int GetLastError( ); -#endif - -#ifndef INADDR_NONE - #define INADDR_NONE -1 -#endif - -#ifndef MSG_NOSIGNAL - #define MSG_NOSIGNAL 0 -#endif - -#ifdef WIN32 - #define SHUT_RDWR 2 -#endif - -// -// CSocket -// - -class CSocket -{ -protected: - SOCKET m_Socket; - struct sockaddr_in m_SIN; - bool m_HasError; - int m_Error; - -public: - CSocket( ); - CSocket( SOCKET nSocket, struct sockaddr_in nSIN ); - ~CSocket( ); - - virtual QByteArray GetPort( ); - virtual QByteArray GetIP( ); - virtual QString GetIPString( ); - virtual bool HasError( ) { return m_HasError; } - virtual int GetError( ) { return m_Error; } - virtual QString GetErrorString( ); - virtual void SetFD( fd_set *fd, fd_set *send_fd, int *nfds ); - virtual void Allocate( int type ); - virtual void Reset( ); -}; - -// -// CTCPSocket -// - -class CTCPSocket : public CSocket -{ -protected: - bool m_Connected; - QString m_LogFile; - -private: - QString m_RecvBuffer; - QString m_SendBuffer; - uint32_t m_LastRecv; - uint32_t m_LastSend; - -public: - CTCPSocket( ); - CTCPSocket( SOCKET nSocket, struct sockaddr_in nSIN ); - virtual ~CTCPSocket( ); - - virtual void Reset( ); - virtual bool GetConnected( ) { return m_Connected; } - virtual QString *GetBytes( ) { return &m_RecvBuffer; } - virtual void PutBytes( QString bytes ); - virtual void PutBytes( QByteArray bytes ); - virtual void ClearRecvBuffer( ) { m_RecvBuffer.clear( ); } - virtual void ClearSendBuffer( ) { m_SendBuffer.clear( ); } - virtual uint32_t GetLastRecv( ) { return m_LastRecv; } - virtual uint32_t GetLastSend( ) { return m_LastSend; } - virtual void DoRecv( fd_set *fd ); - virtual void DoSend( fd_set *send_fd ); - virtual void Disconnect( ); - virtual void SetNoDelay( bool noDelay ); - virtual void SetLogFile( QString nLogFile ) { m_LogFile = nLogFile; } -}; - -// -// CTCPClient -// - -class CTCPClient : public CTCPSocket -{ -protected: - bool m_Connecting; - -public: - CTCPClient( ); - virtual ~CTCPClient( ); - - virtual void Reset( ); - virtual void Disconnect( ); - virtual bool GetConnecting( ) { return m_Connecting; } - virtual void Connect( QString localaddress, QString address, uint16_t port ); - virtual bool CheckConnect( ); -}; - -// -// CTCPServer -// - -class CTCPServer : public CTCPSocket -{ -public: - CTCPServer( ); - virtual ~CTCPServer( ); - - virtual bool Listen( QString address, uint16_t port ); - virtual CTCPSocket *Accept( fd_set *fd ); -}; - -// -// CUDPSocket -// - -class CUDPSocket : public CSocket -{ -protected: - struct in_addr m_BroadcastTarget; -public: - CUDPSocket( ); - virtual ~CUDPSocket( ); - - virtual bool SendTo( struct sockaddr_in sin, QByteArray message ); - virtual bool SendTo( QString address, uint16_t port, QByteArray message ); - virtual bool Broadcast( uint16_t port, QByteArray message ); - virtual void SetBroadcastTarget( QString subnet ); - virtual void SetDontRoute( bool dontRoute ); -}; - -// -// CUDPServer -// - -class CUDPServer : public CUDPSocket -{ -public: - CUDPServer( ); - virtual ~CUDPServer( ); - - virtual bool Bind( struct sockaddr_in sin ); - virtual bool Bind( QString address, uint16_t port ); - virtual void RecvFrom( fd_set *fd, struct sockaddr_in *sin, QString *message ); -}; - -#endif From e9192901c2543fe987b0eb3ff1e3e030c9dc2d81 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 01:50:47 +0000 Subject: [PATCH 10/69] socket.\* no longer needed --- ghost/bnet.cpp | 34 +++++++--------- ghost/bnlsclient.cpp | 1 - ghost/game.cpp | 49 ++++++++++++----------- ghost/game_admin.cpp | 29 +++++++------- ghost/game_base.cpp | 1 - ghost/gameplayer.cpp | 1 - ghost/gameplayer.h | 1 - ghost/ghost.cpp | 60 ++++------------------------- ghost/ghost.h | 3 -- ghost/util.cpp | 92 ++++++++------------------------------------ 10 files changed, 76 insertions(+), 195 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 651b4a1..60f8fda 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -22,7 +22,6 @@ #include "util.h" #include "config.h" #include "language.h" -#include "socket.h" #include "commandpacket.h" #include "ghostdb.h" #include "bncsutilinterface.h" @@ -1012,8 +1011,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString Victim; QString Reason; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); SS >> Victim; if( !SS.atEnd( ) ) @@ -1049,8 +1047,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t Interval; QString Message; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); SS >> Interval; if( SS.status() != QTextStream::Ok || Interval == 0 ) @@ -1103,8 +1100,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t MaximumGames; uint32_t AutoStartPlayers; QString GameName; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); SS >> MaximumGames; if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) @@ -1179,8 +1175,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) double MinimumScore; double MaximumScore; QString GameName; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); SS >> MaximumGames; if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) @@ -1309,8 +1304,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); while( !SS.atEnd( ) ) { @@ -1582,8 +1576,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); while( !SS.atEnd( ) ) { @@ -1771,8 +1764,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // open as many slots as specified, e.g. "5 10" opens slots 5 and 10 - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); while( !SS.atEnd( ) ) { @@ -1895,8 +1887,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) uint32_t GameNumber; QString Message; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> GameNumber; if( SS.status() != QTextStream::Ok ) @@ -1987,8 +1979,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { uint32_t SID1; uint32_t SID2; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> SID1; if( SS.status() != QTextStream::Ok ) @@ -2403,9 +2395,9 @@ bool CBNET :: IsRootAdmin( QString name ) // note: this function gets called frequently so it would be better to parse the root admins just once and store them in a list somewhere // however, it's hardly worth optimizing at this point since the code's already written - QTextStream SS; + QTextStream SS(&m_RootAdmin); + QString s; - SS << m_RootAdmin; while( !SS.atEnd( ) ) { diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index 8aab8bc..c3699ab 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -20,7 +20,6 @@ #include "ghost.h" #include "util.h" -#include "socket.h" #include "commandpacket.h" #include "bnlsprotocol.h" #include "bnlsclient.h" diff --git a/ghost/game.cpp b/ghost/game.cpp index ff50e9d..eaf6cb1 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -22,7 +22,6 @@ #include "util.h" #include "config.h" #include "language.h" -#include "socket.h" #include "ghostdb.h" #include "bnet.h" #include "map.h" @@ -414,8 +413,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString Victim; QString Reason; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Victim; if( !SS.atEnd( ) ) @@ -494,8 +493,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Interval; QString Message; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Interval; if( SS.status() != QTextStream::Ok || Interval == 0 ) @@ -641,8 +640,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + while( !SS.atEnd( ) ) { @@ -677,8 +676,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Skill = 1; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Slot; if( SS.status() != QTextStream::Ok ) @@ -706,8 +705,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Colour; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Slot; if( SS.status() != QTextStream::Ok ) @@ -747,8 +746,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Handicap; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Slot; if( SS.status() != QTextStream::Ok ) @@ -791,8 +790,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; QString Race; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Slot; if( SS.status() != QTextStream::Ok ) @@ -859,8 +858,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri uint32_t Slot; uint32_t Team; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Slot; if( SS.status() != QTextStream::Ok ) @@ -1054,8 +1053,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + while( !SS.atEnd( ) ) { @@ -1196,8 +1195,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // open as many slots as specified, e.g. "5 10" opens slots 5 and 10 - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + while( !SS.atEnd( ) ) { @@ -1415,8 +1414,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QString IP; uint32_t Port = 6112; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> IP; if( !SS.atEnd( ) ) @@ -1499,8 +1498,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { uint32_t SID1; uint32_t SID2; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> SID1; if( SS.status() != QTextStream::Ok ) diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index f07f5a0..65931fc 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -22,7 +22,6 @@ #include "util.h" #include "config.h" #include "language.h" -#include "socket.h" #include "ghostdb.h" #include "bnet.h" #include "map.h" @@ -344,8 +343,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Name; if( SS.atEnd( ) ) @@ -415,8 +414,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, uint32_t MaximumGames; uint32_t AutoStartPlayers; QString GameName; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> MaximumGames; if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) @@ -486,8 +485,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, double MinimumScore; double MaximumScore; QString GameName; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> MaximumGames; if( SS.status() != QTextStream::Ok || MaximumGames == 0 ) @@ -553,8 +552,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Name; if( SS.atEnd( ) ) @@ -608,8 +607,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Name; if( SS.atEnd( ) ) @@ -694,8 +693,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Name; QString Server; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> Name; if( SS.atEnd( ) ) @@ -1128,8 +1127,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, uint32_t GameNumber; QString Message; - QTextStream SS; - SS << Payload; + QTextStream SS(&Payload); + SS >> GameNumber; if( SS.status() != QTextStream::Ok ) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 3d9bbd3..bd45bd8 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -22,7 +22,6 @@ #include "util.h" #include "config.h" #include "language.h" -#include "socket.h" #include "ghostdb.h" #include "bnet.h" #include "map.h" diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 6fbb593..2e1c1e9 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -21,7 +21,6 @@ #include "ghost.h" #include "util.h" #include "language.h" -#include "socket.h" #include "commandpacket.h" #include "bnet.h" #include "map.h" diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index d4ac236..727e68a 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -21,7 +21,6 @@ #ifndef GAMEPLAYER_H #define GAMEPLAYER_H -class CTCPSocket; class CCommandPacket; class CGameProtocol; class CGame; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index ff5224f..e5abd29 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -25,7 +25,6 @@ #include "csvparser.h" #include "config.h" #include "language.h" -#include "socket.h" #include "ghostdb.h" #include "ghostdbsqlite.h" #include "ghostdbmysql.h" @@ -52,6 +51,8 @@ #define __STORMLIB_SELF__ #include +#include + // // CGHost @@ -98,62 +99,17 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CONSOLE_Print( "[GHOST] attempting to find local IP addresses" ); -#ifdef WIN32 - // use a more reliable Windows specific method since the portable method doesn't always work properly on Windows - // code stolen from: http://tangentsoft.net/wskfaq/examples/getifaces.html - - SOCKET sd = WSASocket( AF_INET, SOCK_DGRAM, 0, 0, 0, 0 ); - - if( sd == SOCKET_ERROR ) - CONSOLE_Print( "[GHOST] error finding local IP addresses - failed to create socket (error code " + UTIL_ToString( WSAGetLastError( ) ) + ")" ); - else - { - INTERFACE_INFO InterfaceList[20]; - unsigned long nBytesReturned; + QString HostName = QHostInfo::localHostName(); - if( WSAIoctl( sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0 ) == SOCKET_ERROR ) - CONSOLE_Print( "[GHOST] error finding local IP addresses - WSAIoctl failed (error code " + UTIL_ToString( WSAGetLastError( ) ) + ")" ); - else - { - int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); + CONSOLE_Print( "[GHOST] local hostname is [" + HostName + "]" ); - for( int i = 0; i < nNumInterfaces; i++ ) - { - sockaddr_in *pAddress; - pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress); - CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + QString( inet_ntoa( pAddress->sin_addr ) ) + "]" ); - m_LocalAddresses.push_back( UTIL_CreateQByteArray( (uint32_t)pAddress->sin_addr.s_addr, false ) ); - } - } + QHostInfo info = QHostInfo::fromName(HostName); - closesocket( sd ); - } -#else - // use a portable method - - char HostName[255]; - - if( gethostname( HostName, 255 ) == SOCKET_ERROR ) - CONSOLE_Print( "[GHOST] error finding local IP addresses - failed to get local hostname" ); - else + for (int i = 0; i < info.addresses().size(); i++) { - CONSOLE_Print( "[GHOST] local hostname is [" + QString( HostName ) + "]" ); - struct hostent *HostEnt = gethostbyname( HostName ); - - if( !HostEnt ) - CONSOLE_Print( "[GHOST] error finding local IP addresses - gethostbyname failed" ); - else - { - for( int i = 0; HostEnt->h_addr_list[i] != NULL; i++ ) - { - struct in_addr Address; - memcpy( &Address, HostEnt->h_addr_list[i], sizeof(struct in_addr) ); - CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + QString( inet_ntoa( Address ) ) + "]" ); - m_LocalAddresses.push_back( UTIL_CreateQByteArray( (uint32_t)Address.s_addr, false ) ); - } - } + CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + info.addresses().at(i).toString() + "]" ); + m_LocalAddresses.push_back( UTIL_CreateQByteArray( (uint32_t)info.addresses().at(i).toIPv4Address() ) ); } -#endif m_Language = NULL; m_Exiting = false; diff --git a/ghost/ghost.h b/ghost/ghost.h index 6a7a315..2dbfc3a 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -29,9 +29,6 @@ // CGHost // -class CUDPSocket; -class CTCPServer; -class CTCPSocket; class CGPSProtocol; class CCRC32; class CSHA1; diff --git a/ghost/util.cpp b/ghost/util.cpp index 22cafb9..2e54d57 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -174,8 +174,7 @@ QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ) QByteArray result; unsigned int c; - QTextStream SS; - SS << s; + QTextStream SS(&s); for( unsigned int i = 0; i < count; i++ ) { @@ -198,8 +197,8 @@ QByteArray UTIL_ExtractHexNumbers( QString s ) QByteArray result; unsigned int c; - QTextStream SS; - SS << s; + QTextStream SS(&s); + while( !SS.atEnd() ) { @@ -215,131 +214,74 @@ QByteArray UTIL_ExtractHexNumbers( QString s ) QString UTIL_ToString( unsigned long i ) { - QString result; - QTextStream SS; - SS << i; - SS >> result; - return result; + return QString::number(i); } QString UTIL_ToString( unsigned short i ) { - QString result; - QTextStream SS; - SS << i; - SS >> result; - return result; + return QString::number(i); } QString UTIL_ToString( unsigned int i ) { - QString result; - QTextStream SS; - SS << i; - SS >> result; - return result; + return QString::number(i); } QString UTIL_ToString( long i ) { - QString result; - QTextStream SS; - SS << i; - SS >> result; - return result; + return QString::number(i); } QString UTIL_ToString( short i ) { - QString result; - QTextStream SS; - SS << i; - SS >> result; - return result; + return QString::number(i); } QString UTIL_ToString( int i ) { - QString result; - QTextStream SS; - SS << i; - SS >> result; - return result; + return QString::number(i); } QString UTIL_ToString( float f, int digits ) { - QString result; - QTextStream SS; - SS.setRealNumberPrecision( digits ); - SS << QTextStream::FixedNotation << f; - SS >> result; - return result; + return QString::number(f, 'g', digits); } QString UTIL_ToString( double d, int digits ) { - QString result; - QTextStream SS; - SS << fixed << qSetRealNumberPrecision( digits ) << d; - SS >> result; - return result; + return QString::number(d, 'g', digits); } QString UTIL_ToHexString( uint32_t i ) { - QString result; - QTextStream SS; - SS << hex << i; - SS >> result; - return result; + return QString::number(i); } // todotodo: these UTIL_ToXXX functions don't fail gracefully, they just return garbage (in the uint case usually just -1 casted to an unsigned type it looks like) uint16_t UTIL_ToUInt16( QString &s ) { - uint16_t result; - QTextStream SS; - SS << s; - SS >> result; - return result; + return s.toUShort(); } uint32_t UTIL_ToUInt32( QString &s ) { - uint32_t result; - QTextStream SS; - SS << s; - SS >> result; - return result; + return s.toUInt(); } int16_t UTIL_ToInt16( QString &s ) { - int16_t result; - QTextStream SS; - SS << s; - SS >> result; - return result; + return s.toShort(); } int32_t UTIL_ToInt32( QString &s ) { - int32_t result; - QTextStream SS; - SS << s; - SS >> result; - return result; + return s.toInt(); } double UTIL_ToDouble( QString &s ) { - double result; - QTextStream SS; - SS << s; - SS >> result; - return result; + s.toDouble(); } QString UTIL_MSToString( uint32_t ms ) From cbbe6adcb078c3d8c59f440350b1b0a83c88a6fe Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 01:53:38 +0000 Subject: [PATCH 11/69] loads of bugs --- ghost/config.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ghost/config.cpp b/ghost/config.cpp index ccdecd2..fd8f854 100644 --- a/ghost/config.cpp +++ b/ghost/config.cpp @@ -65,7 +65,8 @@ void CConfig :: Read( QString file ) QStringList parts = Line.split('='); - m_CFG[parts.at(0).trimmed()] = parts.at(1).trimmed(); + if (parts.size() == 2) + m_CFG[parts.at(0).trimmed()] = parts.at(1).trimmed(); } f.close( ); From cc0de2a023a49d8573ecf2a6e874ec24aba5691d Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 02:53:10 +0000 Subject: [PATCH 12/69] charset corrections --- ghost/ghost.cpp | 2 +- ghost/ghostdbsqlite.cpp | 114 ++++++++++++++++++++-------------------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index e5abd29..dea5443 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -850,7 +850,7 @@ void CGHost :: ExtractScripts( ) QString PatchMPQFileName = m_Warcraft3Path + "War3Patch.mpq"; HANDLE PatchMPQ; - if( SFileOpenArchive( (char*)PatchMPQFileName.data( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &PatchMPQ ) ) + if( SFileOpenArchive( PatchMPQFileName.toUtf8().data( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &PatchMPQ ) ) { CONSOLE_Print( "[GHOST] loading MPQ file [" + PatchMPQFileName + "]" ); HANDLE SubFile; diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index 2b0a871..1457f47 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -33,7 +33,7 @@ CSQLITE3 :: CSQLITE3( QString filename ) { m_Ready = true; - if( sqlite3_open_v2( (char*)filename.data(), (sqlite3 **)&m_DB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL ) != SQLITE_OK ) + if( sqlite3_open_v2( filename.toUtf8().data(), (sqlite3 **)&m_DB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL ) != SQLITE_OK ) m_Ready = false; } @@ -49,7 +49,7 @@ QString CSQLITE3 :: GetError( ) int CSQLITE3 :: Prepare( QString query, void **Statement ) { - return sqlite3_prepare_v2( (sqlite3 *)m_DB, (char*)query.data( ), -1, (sqlite3_stmt **)Statement, NULL ); + return sqlite3_prepare_v2( (sqlite3 *)m_DB, query.toUtf8().data( ), -1, (sqlite3_stmt **)Statement, NULL ); } int CSQLITE3 :: Step( void *Statement ) @@ -91,7 +91,7 @@ int CSQLITE3 :: ClearBindings( void *Statement ) int CSQLITE3 :: Exec( QString query ) { - return sqlite3_exec( (sqlite3 *)m_DB, (char*)query.data( ), NULL, NULL, NULL ); + return sqlite3_exec( (sqlite3 *)m_DB, query.toUtf8().data( ), NULL, NULL, NULL ); } uint32_t CSQLITE3 :: LastRowID( ) @@ -215,7 +215,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)SchemaNumber.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, SchemaNumber.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ERROR ) @@ -563,7 +563,7 @@ uint32_t CGHostDBSQLite :: AdminCount( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -588,8 +588,8 @@ bool CGHostDBSQLite :: AdminCheck( QString server, QString user ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); // we're just checking to see if the query returned a row, we don't need to check the row data itself @@ -616,8 +616,8 @@ bool CGHostDBSQLite :: AdminAdd( QString server, QString user ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -642,8 +642,8 @@ bool CGHostDBSQLite :: AdminRemove( QString server, QString user ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -667,7 +667,7 @@ QVector CGHostDBSQLite :: AdminList( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); while( RC == SQLITE_ROW ) @@ -699,7 +699,7 @@ uint32_t CGHostDBSQLite :: BanCount( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -728,11 +728,11 @@ CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); if( !ip.isEmpty( ) ) - sqlite3_bind_text( Statement, 3, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, ip.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -765,12 +765,12 @@ bool CGHostDBSQLite :: BanAdd( QString server, QString user, QString ip, QString if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 3, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, (char*)gamename.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 5, (char*)admin.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 6, (char*)reason.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, ip.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, gamename.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 5, admin.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 6, reason.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -796,8 +796,8 @@ bool CGHostDBSQLite :: BanRemove( QString server, QString user ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -822,7 +822,7 @@ bool CGHostDBSQLite :: BanRemove( QString user ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)user.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, user.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_DONE ) @@ -846,7 +846,7 @@ QVector CGHostDBSQLite :: BanList( QString server ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); while( RC == SQLITE_ROW ) @@ -878,14 +878,14 @@ uint32_t CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamenam if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)server.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 2, (char*)map.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 3, (char*)gamename.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, (char*)ownername.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, server.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, map.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, gamename.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, ownername.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 5, duration ); sqlite3_bind_int( Statement, 6, gamestate ); - sqlite3_bind_text( Statement, 7, (char*)creatorname.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 8, (char*)creatorserver.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 7, creatorname.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 8, creatorserver.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -912,16 +912,16 @@ uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString if( Statement ) { sqlite3_bind_int( Statement, 1, gameid ); - sqlite3_bind_text( Statement, 2, (char*)name.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 3, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 2, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, ip.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 4, spoofed ); sqlite3_bind_int( Statement, 5, reserved ); sqlite3_bind_int( Statement, 6, loadingtime ); sqlite3_bind_int( Statement, 7, left ); - sqlite3_bind_text( Statement, 8, (char*)leftreason.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 8, leftreason.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 9, team ); sqlite3_bind_int( Statement, 10, colour ); - sqlite3_bind_text( Statement, 11, (char*)spoofedrealm.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 11, spoofedrealm.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); @@ -947,7 +947,7 @@ uint32_t CGHostDBSQLite :: GamePlayerCount( QString name ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -975,7 +975,7 @@ CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( QString name ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -1064,13 +1064,13 @@ uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint sqlite3_bind_int( Statement, 7, assists ); sqlite3_bind_int( Statement, 8, gold ); sqlite3_bind_int( Statement, 9, neutralkills ); - sqlite3_bind_text( Statement, 10, (char*)item1.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 11, (char*)item2.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 12, (char*)item3.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 13, (char*)item4.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 14, (char*)item5.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 15, (char*)item6.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 16, (char*)hero.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 10, item1.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 11, item2.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 12, item3.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 13, item4.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 14, item5.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 15, item6.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 16, hero.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 17, newcolour ); sqlite3_bind_int( Statement, 18, towerkills ); sqlite3_bind_int( Statement, 19, raxkills ); @@ -1100,7 +1100,7 @@ uint32_t CGHostDBSQLite :: DotAPlayerCount( QString name ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -1128,7 +1128,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( Statement ); if( RC == SQLITE_ROW ) @@ -1155,7 +1155,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) if( Statement2 ) { - sqlite3_bind_text( Statement2, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement2, 1, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC2 = m_DB->Step( Statement2 ); if( RC2 == SQLITE_ROW ) @@ -1175,7 +1175,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) if( Statement3 ) { - sqlite3_bind_text( Statement3, 1, (char*)name.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement3, 1, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC3 = m_DB->Step( Statement3 ); if( RC3 == SQLITE_ROW ) @@ -1257,7 +1257,7 @@ bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) sqlite3_bind_int64( (sqlite3_stmt *)FromAddStmt, 1, ip1 ); sqlite3_bind_int64( (sqlite3_stmt *)FromAddStmt, 2, ip2 ); - sqlite3_bind_text( (sqlite3_stmt *)FromAddStmt, 3, (char*)country.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( (sqlite3_stmt *)FromAddStmt, 3, country.toUtf8().data( ), -1, SQLITE_TRANSIENT ); int RC = m_DB->Step( FromAddStmt ); @@ -1282,12 +1282,12 @@ bool CGHostDBSQLite :: DownloadAdd( QString map, uint32_t mapsize, QString name, if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)map.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, map.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 2, mapsize ); - sqlite3_bind_text( Statement, 3, (char*)name.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 4, (char*)ip.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 3, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, ip.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 5, spoofed ); - sqlite3_bind_text( Statement, 6, (char*)spoofedrealm.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 6, spoofedrealm.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 7, downloadtime ); int RC = m_DB->Step( Statement ); @@ -1313,11 +1313,11 @@ uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( QString category, uint32_t gameid, ui if( Statement ) { - sqlite3_bind_text( Statement, 1, (char*)category.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 1, category.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 2, gameid ); sqlite3_bind_int( Statement, 3, pid ); - sqlite3_bind_text( Statement, 4, (char*)name.data( ), -1, SQLITE_TRANSIENT ); - sqlite3_bind_text( Statement, 5, (char*)flag.data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 4, name.toUtf8().data( ), -1, SQLITE_TRANSIENT ); + sqlite3_bind_text( Statement, 5, flag.toUtf8().data( ), -1, SQLITE_TRANSIENT ); sqlite3_bind_int( Statement, 6, leaver ); sqlite3_bind_int( Statement, 7, practicing ); From a7ff4f8f823af5e70892fed8211a82e329237c90 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 03:00:19 +0000 Subject: [PATCH 13/69] broadcast packets are invalid, probably because of stat encoding --- ghost/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ghost/util.cpp b/ghost/util.cpp index 2e54d57..ace99f1 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -335,7 +335,7 @@ QByteArray UTIL_FileRead( QString file ) bool UTIL_FileWrite( QString file, const QByteArray &data ) { QFile f(file); - f.open(QFile::Truncate); + f.open(QFile::Truncate | QFile::WriteOnly); if (f.error() != QFile::NoError || !f.isWritable()) { From efde271807be95120a8c7a11b10cad57ddd1ef72 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 05:01:45 +0000 Subject: [PATCH 14/69] warnings removed --- ghost/bnet.cpp | 14 +- ghost/bnet.h | 2 +- ghost/bnetprotocol.cpp | 8 +- ghost/bnlsprotocol.cpp | 8 +- ghost/commandpacket.cpp | 2 +- ghost/game.cpp | 3 +- ghost/game_admin.cpp | 10 +- ghost/game_base.cpp | 26 ++-- ghost/game_base.h | 8 +- ghost/gameplayer.cpp | 15 +- ghost/gameprotocol.cpp | 16 +- ghost/ghost.cpp | 319 +++++++++++++++++++++------------------- ghost/ghost.h | 17 ++- ghost/ghost.pro | 144 +++++++++--------- ghost/ghostdb.cpp | 109 +++++++------- ghost/ghostdb.h | 19 ++- ghost/ghostdbmysql.cpp | 6 +- ghost/ghostdbsqlite.cpp | 3 +- ghost/gpsprotocol.cpp | 2 +- ghost/includes.h | 21 +-- ghost/main.cpp | 36 +---- ghost/map.cpp | 3 + ghost/packed.cpp | 2 +- ghost/replay.cpp | 2 +- ghost/sha1.cpp | 2 +- ghost/stats.cpp | 6 +- ghost/statsdota.cpp | 10 +- ghost/statsw3mmd.cpp | 36 ++--- ghost/statsw3mmd.h | 3 +- ghost/util.cpp | 20 +-- 30 files changed, 432 insertions(+), 440 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 60f8fda..1f6a518 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -607,7 +607,7 @@ void CBNET :: ExtractPackets( ) // byte 0 is always 255 QByteArray header = m_Socket->peek(4); - if( header.at(0) != BNET_HEADER_CONSTANT ) + if( (unsigned char)header.at(0) != BNET_HEADER_CONSTANT ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad header constant), disconnecting" ); m_Socket->abort(); @@ -1087,7 +1087,6 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_GHost->m_AutoHostServer.clear( ); m_GHost->m_AutoHostMaximumGames = 0; m_GHost->m_AutoHostAutoStartPlayers = 0; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = false; m_GHost->m_AutoHostMinimumScore = 0.0; m_GHost->m_AutoHostMaximumScore = 0.0; @@ -1131,7 +1130,6 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_GHost->m_AutoHostServer = m_Server; m_GHost->m_AutoHostMaximumGames = MaximumGames; m_GHost->m_AutoHostAutoStartPlayers = AutoStartPlayers; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = false; m_GHost->m_AutoHostMinimumScore = 0.0; m_GHost->m_AutoHostMaximumScore = 0.0; @@ -1160,7 +1158,6 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_GHost->m_AutoHostServer.clear( ); m_GHost->m_AutoHostMaximumGames = 0; m_GHost->m_AutoHostAutoStartPlayers = 0; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = false; m_GHost->m_AutoHostMinimumScore = 0.0; m_GHost->m_AutoHostMaximumScore = 0.0; @@ -1218,7 +1215,6 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_GHost->m_AutoHostServer = m_Server; m_GHost->m_AutoHostMaximumGames = MaximumGames; m_GHost->m_AutoHostAutoStartPlayers = AutoStartPlayers; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = true; m_GHost->m_AutoHostMinimumScore = MinimumScore; m_GHost->m_AutoHostMaximumScore = MaximumScore; @@ -1450,7 +1446,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // todotodo: what if a game ends just as you're typing this command and the numbering changes? - uint32_t GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = UTIL_ToUInt32( Payload ) - 1; if( GameNumber < m_GHost->m_Games.size( ) ) { @@ -1548,7 +1544,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "getgame" && !Payload.isEmpty( ) ) { - uint32_t GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = UTIL_ToUInt32( Payload ) - 1; if( GameNumber < m_GHost->m_Games.size( ) ) QueueChatCommand( m_GHost->m_Language->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ), User, Whisper ); @@ -1885,7 +1881,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the game number and the message // e.g. "3 hello everyone" -> game number: "3", message: "hello everyone" - uint32_t GameNumber; + int GameNumber; QString Message; QTextStream SS(&Payload); @@ -2326,7 +2322,7 @@ void CBNET :: UnqueuePackets( unsigned char type ) QByteArray Packet = m_OutPackets.front( ); m_OutPackets.dequeue( ); - if( Packet.size( ) >= 2 && Packet[1] == type ) + if( Packet.size( ) >= 2 && Packet.at(1) == type ) Unqueued++; else Packets.enqueue( Packet ); diff --git a/ghost/bnet.h b/ghost/bnet.h index 14feb11..04701bb 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -130,7 +130,7 @@ public slots: QByteArray m_EXEVersionHash; // custom exe version hash for PvPGN users QString m_PasswordHashType; // password hash type for PvPGN users QString m_PVPGNRealmName; // realm name for PvPGN users (for mutual friend spoofchecks) - uint32_t m_MaxMessageLength; // maximum message length for PvPGN users + int m_MaxMessageLength; // maximum message length for PvPGN users uint32_t m_HostCounterID; // the host counter ID to identify players from this realm uint32_t m_LastDisconnectedTime; // GetTime when we were last disconnected from battle.net uint32_t m_LastConnectionAttemptTime; // GetTime when we last attempted to connect to battle.net diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index db4e298..58cce96 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -362,13 +362,13 @@ QVector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteAr { Total--; - if( data.size( ) < i + 1 ) + if( (unsigned int)data.size( ) < i + 1 ) break; QByteArray Account = UTIL_ExtractCString( data, i ); i += Account.size( ) + 1; - if( data.size( ) < i + 7 ) + if( (unsigned int)data.size( ) < i + 7 ) break; unsigned char Status = data[i]; @@ -412,13 +412,13 @@ QVector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteA { Total--; - if( data.size( ) < i + 1 ) + if( (unsigned int)data.size( ) < i + 1 ) break; QByteArray Name = UTIL_ExtractCString( data, i ); i += Name.size( ) + 1; - if( data.size( ) < i + 3 ) + if( (unsigned int)data.size( ) < i + 3 ) break; unsigned char Rank = data[i]; diff --git a/ghost/bnlsprotocol.cpp b/ghost/bnlsprotocol.cpp index 6f9486e..1c60693 100644 --- a/ghost/bnlsprotocol.cpp +++ b/ghost/bnlsprotocol.cpp @@ -48,10 +48,10 @@ QByteArray CBNLSProtocol :: RECEIVE_BNLS_WARDEN( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 11 ) { - unsigned char Usage = data[3]; - uint32_t Cookie = UTIL_QByteArrayToUInt32( data, false, 4 ); + //unsigned char Usage = data[3]; + //uint32_t Cookie = UTIL_QByteArrayToUInt32( data, false, 4 ); unsigned char Result = data[8]; - uint16_t Length = UTIL_QByteArrayToUInt16( data, false, 10 ); + //uint16_t Length = UTIL_QByteArrayToUInt16( data, false, 10 ); if( Result == 0x00 ) return data.mid(11); @@ -110,7 +110,7 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray ra return packet; } -QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RUNMODULE( uint32_t cookie ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RUNMODULE( uint32_t /*cookie*/ ) { return QByteArray( ); } diff --git a/ghost/commandpacket.cpp b/ghost/commandpacket.cpp index d51d99c..cbecd0e 100644 --- a/ghost/commandpacket.cpp +++ b/ghost/commandpacket.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ghost/game.cpp b/ghost/game.cpp index eaf6cb1..7057798 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -1261,7 +1262,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // copy the m_Players vector so we can sort by descending ping so it's easier to find players with high pings QVector SortedPlayers = m_Players; - sort( SortedPlayers.begin( ), SortedPlayers.end( ), CGamePlayerSortDescByPing( ) ); + qSort(SortedPlayers); QString Pings; for( QVector :: iterator i = SortedPlayers.begin( ); i != SortedPlayers.end( ); i++ ) diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 65931fc..bf2fa13 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -401,7 +401,6 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, m_GHost->m_AutoHostServer.clear( ); m_GHost->m_AutoHostMaximumGames = 0; m_GHost->m_AutoHostAutoStartPlayers = 0; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = false; m_GHost->m_AutoHostMinimumScore = 0.0; m_GHost->m_AutoHostMaximumScore = 0.0; @@ -446,7 +445,6 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, m_GHost->m_AutoHostServer.clear( ); m_GHost->m_AutoHostMaximumGames = MaximumGames; m_GHost->m_AutoHostAutoStartPlayers = AutoStartPlayers; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = false; m_GHost->m_AutoHostMinimumScore = 0.0; m_GHost->m_AutoHostMaximumScore = 0.0; @@ -470,7 +468,6 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, m_GHost->m_AutoHostServer.clear( ); m_GHost->m_AutoHostMaximumGames = 0; m_GHost->m_AutoHostAutoStartPlayers = 0; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = false; m_GHost->m_AutoHostMinimumScore = 0.0; m_GHost->m_AutoHostMaximumScore = 0.0; @@ -529,7 +526,6 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, m_GHost->m_AutoHostServer.clear( ); m_GHost->m_AutoHostMaximumGames = MaximumGames; m_GHost->m_AutoHostAutoStartPlayers = AutoStartPlayers; - m_GHost->m_LastAutoHostTime = GetTime( ); m_GHost->m_AutoHostMatchMaking = true; m_GHost->m_AutoHostMinimumScore = MinimumScore; m_GHost->m_AutoHostMaximumScore = MaximumScore; @@ -798,7 +794,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { // todotodo: what if a game ends just as you're typing this command and the numbering changes? - uint32_t GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = UTIL_ToUInt32( Payload ) - 1; if( GameNumber < m_GHost->m_Games.size( ) ) { @@ -864,7 +860,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "getgame" && !Payload.isEmpty( ) ) { - uint32_t GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = UTIL_ToUInt32( Payload ) - 1; if( GameNumber < m_GHost->m_Games.size( ) ) SendChat( player, m_GHost->m_Language->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ) ); @@ -1125,7 +1121,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // extract the game number and the message // e.g. "3 hello everyone" -> game number: "3", message: "hello everyone" - uint32_t GameNumber; + int GameNumber; QString Message; QTextStream SS(&Payload); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index bd45bd8..7a33e7d 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -234,7 +234,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 // ignore lines that don't look like IP addresses - if( Line.indexOf( QRegExp("[^0-9\.]") ) != -1 ) + if( Line.indexOf( QRegExp("[^0-9\\.]") ) != -1 ) continue; m_IPBlackList.insert( Line ); @@ -850,7 +850,7 @@ void CBaseGame :: Send( unsigned char PID, QByteArray data ) void CBaseGame :: Send( QByteArray PIDs, QByteArray data ) { - for( unsigned int i = 0; i < PIDs.size( ); i++ ) + for( int i = 0; i < PIDs.size( ); i++ ) Send( PIDs[i], data ); } @@ -1388,7 +1388,7 @@ void CBaseGame :: EventPlayerDeleted() } // end the game if there aren't any players left - if( m_Players.isEmpty( ) && m_GameLoading || m_GameLoaded ) + if( m_Players.isEmpty( ) && (m_GameLoading || m_GameLoaded) ) { if( !m_Saving ) { @@ -2577,14 +2577,14 @@ void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *actio // check for players saving the game and notify everyone - if( !action->GetAction( )->isEmpty( ) && (*action->GetAction( ))[0] == 6 ) + if( !action->GetAction( )->isEmpty( ) && (*action->GetAction( )).at(0) == 6 ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] is saving the game" ); SendAllChat( m_GHost->m_Language->PlayerIsSavingTheGame( player->GetName( ) ) ); } } -void CBaseGame :: EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ) +void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, uint32_t /*checkSum*/ ) { // check for desyncs // however, it's possible that not every player has sent a checksum for this frame yet @@ -2753,7 +2753,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye if( !ExtraFlags.isEmpty( ) ) { - if( ExtraFlags[0] == 0 ) + if( ExtraFlags.at(0) == 0 ) { // this is an ingame [All] message, print it to the console @@ -2765,7 +2765,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye if( m_MuteAll ) Relay = false; } - else if( ExtraFlags[0] == 2 ) + else if( ExtraFlags.at(0) == 2 ) { // this is an ingame [Obs/Ref] message, print it to the console @@ -2837,7 +2837,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye } } -bool CBaseGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ) +bool CBaseGame :: EventPlayerBotCommand( CGamePlayer */*player*/, QString /*command*/, QString /*payload*/ ) { // return true if the command itself should be hidden from other players @@ -3126,7 +3126,7 @@ void CBaseGame::EventCallableUpdateTimeout() } } -void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, uint32_t pong ) +void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, uint32_t /*pong*/ ) { // autokick players with excessive pings but only if they're not reserved and we've received at least 3 pings from them // also don't kick anyone if the game is loading or loaded - this could happen because we send pings during loading but we stop sending them after the game is loaded @@ -3144,7 +3144,7 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, uint32_t pong ) } } -void CBaseGame :: EventGameRefreshed( QString server ) +void CBaseGame :: EventGameRefreshed( QString /*server*/ ) { if( m_RefreshRehosted ) { @@ -3177,7 +3177,7 @@ void CBaseGame :: EventGameStarted( ) if( !m_HCLCommandString.isEmpty( ) ) { - if( m_HCLCommandString.size( ) <= GetSlotsOccupied( ) ) + if( m_HCLCommandString.size( ) <= (int)GetSlotsOccupied( ) ) { QString HCLChars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."; @@ -3345,7 +3345,7 @@ void CBaseGame :: EventGameStarted( ) // move the game to the games in progress vector - m_GHost->m_CurrentGame = NULL; + emit gameStarted(); m_GHost->m_Games.push_back( this ); // and finally reenter battle.net chat @@ -4325,7 +4325,7 @@ void CBaseGame :: StartCountDown( bool force ) { // check if the HCL command QString is short enough - if( m_HCLCommandString.size( ) > GetSlotsOccupied( ) ) + if( m_HCLCommandString.size( ) > (int)GetSlotsOccupied( ) ) { SendAllChat( m_GHost->m_Language->TheHCLIsTooLongUseForceToStart( ) ); return; diff --git a/ghost/game_base.h b/ghost/game_base.h index 21d899b..e5debef 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -44,11 +44,15 @@ class CGHost; #include #include +#include class CBaseGame : public QObject { Q_OBJECT +signals: + void gameStarted(); + public: CGHost *m_GHost; @@ -93,8 +97,8 @@ public slots: QVector m_ScoreChecks; QQueue m_Actions; // queue of actions to be sent QVector m_Reserved; // vector of player names with reserved slots (from the !hold command) - set m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed - set m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) + QSet m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed + QSet m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) QVector m_EnforceSlots; // vector of slots to force players to use (used with saved games) QVector m_EnforcePlayers; // vector of pids to force players to use (used with saved games) CMap *m_Map; // map data diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 2e1c1e9..f696039 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -175,7 +175,7 @@ void CPotentialPlayer :: ExtractPackets( ) while( m_Socket->bytesAvailable() >= 4 ) { - char header = m_Socket->peek(1).at(0); + unsigned char header = m_Socket->peek(1).at(0); if (header != W3GS_HEADER_CONSTANT && header != GPS_HEADER_CONSTANT ) { m_Error = true; @@ -433,7 +433,7 @@ uint32_t CGamePlayer :: GetPing( bool LCPing ) uint32_t AvgPing = 0; - for( unsigned int i = 0; i < m_Pings.size( ); i++ ) + for( int i = 0; i < m_Pings.size( ); i++ ) AvgPing += m_Pings[i]; AvgPing /= m_Pings.size( ); @@ -454,7 +454,7 @@ void CGamePlayer :: ExtractPackets( ) while( m_Socket->bytesAvailable() >= 4 ) { - char header = m_Socket->peek(1).at(0); + unsigned char header = m_Socket->peek(1).at(0); if (header != W3GS_HEADER_CONSTANT && header != GPS_HEADER_CONSTANT ) { m_Error = true; @@ -500,7 +500,6 @@ void CGamePlayer :: ProcessPackets( ) CIncomingAction *Action = NULL; CIncomingChatPlayer *ChatPlayer = NULL; CIncomingMapSize *MapSize = NULL; - bool HasMap = false; uint32_t CheckSum = 0; uint32_t Pong = 0; @@ -638,12 +637,12 @@ void CGamePlayer :: ProcessPackets( ) } else if( Packet->GetID( ) == CGPSProtocol :: GPS_ACK && Data.size( ) == 8 ) { - uint32_t LastPacket = UTIL_QByteArrayToUInt32( Data, false, 4 ); - uint32_t PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); + int LastPacket = UTIL_QByteArrayToUInt32( Data, false, 4 ); + int PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); if( LastPacket > PacketsAlreadyUnqueued ) { - uint32_t PacketsToUnqueue = LastPacket - PacketsAlreadyUnqueued; + int PacketsToUnqueue = LastPacket - PacketsAlreadyUnqueued; if( PacketsToUnqueue > m_GProxyBuffer.size( ) ) PacketsToUnqueue = m_GProxyBuffer.size( ); @@ -685,7 +684,7 @@ void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, uint32_t LastPa if( LastPacket > PacketsAlreadyUnqueued ) { - uint32_t PacketsToUnqueue = LastPacket - PacketsAlreadyUnqueued; + int PacketsToUnqueue = LastPacket - PacketsAlreadyUnqueued; if( PacketsToUnqueue > m_GProxyBuffer.size( ) ) PacketsToUnqueue = m_GProxyBuffer.size( ); diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 6b43f3e..dba2d72 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -172,7 +172,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data unsigned int i = 5; unsigned char Total = data[4]; - if( Total > 0 && data.size( ) >= i + Total ) + if( Total > 0 && (unsigned int)data.size( ) >= i + Total ) { QByteArray ToPIDs = data.mid(i, Total ); i += Total; @@ -180,21 +180,21 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data unsigned char Flag = data[i + 1]; i += 2; - if( Flag == 16 && data.size( ) >= i + 1 ) + if( Flag == 16 && (unsigned int)data.size( ) >= i + 1 ) { // chat message QByteArray Message = UTIL_ExtractCString( data, i ); return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, QString::fromUtf8(Message) ); } - else if( ( Flag >= 17 && Flag <= 20 ) && data.size( ) >= i + 1 ) + else if( ( Flag >= 17 && Flag <= 20 ) && (unsigned int)data.size( ) >= i + 1 ) { // team/colour/race/handicap change request unsigned char Byte = data[i]; return new CIncomingChatPlayer( FromPID, ToPIDs, Flag, Byte ); } - else if( Flag == 32 && data.size( ) >= i + 5 ) + else if( Flag == 32 && (unsigned int)data.size( ) >= i + 5 ) { // chat message with extra flags @@ -237,7 +237,7 @@ bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char wa return false; } -CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray mapSize ) +CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray /*mapSize*/ ) { // DEBUG_Print( "RECEIVED W3GS_MAPSIZE" ); // DEBUG_Print( data ); @@ -824,7 +824,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c QByteArray packet; - if( start < mapData->size( ) ) + if( start < (unsigned int)mapData->size( ) ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_MAPPART ); // W3GS_MAPPART @@ -839,7 +839,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c uint32_t End = start + 1442; - if( End > mapData->size( ) ) + if( End > (unsigned int)mapData->size( ) ) End = mapData->size( ); // calculate crc @@ -949,7 +949,7 @@ QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, uint32_t QByteArray SlotInfo; SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots - for( unsigned int i = 0; i < lslots.size( ); i++ ) + for( int i = 0; i < lslots.size( ); i++ ) UTIL_AppendQByteArray( SlotInfo, lslots[i].GetQByteArray( ) ); UTIL_AppendQByteArray( SlotInfo, randomSeed, false ); // random seed diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index dea5443..1ad4beb 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -94,6 +94,22 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CONSOLE_Print( "[GHOST] opening secondary (local) database" ); m_DBLocal = new CGHostDBSQLite( CFG ); + if (m_DB->HasError() ) + { + CONSOLE_Print( "[GHOST] database initialization error - " + m_DB->GetError() ); + deleteLater(); + return; + } + if (m_DBLocal->HasError() ) + { + CONSOLE_Print( "[GHOST] local database initialization error - " + m_DB->GetError() ); + deleteLater(); + return; + } + + QObject::connect(m_DBLocal, SIGNAL(error(QString)), this, SLOT(EventDatabaseError(QString))); + QObject::connect(m_DB, SIGNAL(error(QString)), this, SLOT(EventDatabaseError(QString))); + // get a list of local IP addresses // this list is used elsewhere to determine if a player connecting to the bot is local or not @@ -121,7 +137,6 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_AutoHostAutoStartPlayers = CFG->GetInt( "autohost_startplayers", 0 ); m_AutoHostGameName = CFG->GetString( "autohost_gamename", QString( ) ); m_AutoHostOwner = CFG->GetString( "autohost_owner", QString( ) ); - m_LastAutoHostTime = GetTime( ); m_AutoHostMatchMaking = false; m_AutoHostMinimumScore = 0.0; m_AutoHostMaximumScore = 0.0; @@ -147,6 +162,9 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_ReplayBuildNumber = CFG->GetInt( "replay_buildnumber", 6059 ); SetConfigs( CFG ); + if (m_Reconnect) + CreateReconnectServer(); + // load the battle.net connections // we're just loading the config data and creating the CBNET classes here, the connections are established later (in the Update function) @@ -317,6 +335,8 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) #else CONSOLE_Print( "[GHOST] GHost++ Version " + m_Version + " (without MySQL support)" ); #endif + + EventAutoHost(); } CGHost :: ~CGHost( ) @@ -351,6 +371,19 @@ CGHost :: ~CGHost( ) delete m_SaveGame; } +void CGHost::EventGameStarted() +{ + m_CurrentGame = NULL; + + if (m_LastAutoHostTime.elapsed() > 30) + { + EventAutoHost(); + return; + } + + QTimer::singleShot(30 - m_LastAutoHostTime.elapsed(), this, SLOT(EventAutoHost())); +} + void CGHost::EventIncomingReconnection() { QTcpSocket *con = m_ReconnectSocket->nextPendingConnection(); @@ -368,7 +401,7 @@ void CGHost::EventReconnectionSocketReadyRead() if (con->bytesAvailable() < 4) return; - if( con->peek(1).at(0) == GPS_HEADER_CONSTANT ) + if( (unsigned char)con->peek(1).at(0) == GPS_HEADER_CONSTANT ) { // bytes 2 and 3 contain the length of the packet @@ -448,191 +481,173 @@ void CGHost::EventCallableUpdateTimeout() } } -bool CGHost :: Update( long usecBlock ) +void CGHost::EventDatabaseError(const QString &error) { // todotodo: do we really want to shutdown if there's a database error? is there any way to recover from this? + if( QObject::sender() == m_DB ) + CONSOLE_Print( "[GHOST] database error - " + error ); - if( m_DB->HasError( ) ) + else if (QObject::sender() == m_DBLocal) + CONSOLE_Print( "[GHOST] local database error - " + error ); + + deleteLater(); +} + +void CGHost::EventExitNice() +{ + m_ExitingNice = true; + + if( !m_BNETs.isEmpty( ) ) { - CONSOLE_Print( "[GHOST] database error - " + m_DB->GetError( ) ); - return true; + CONSOLE_Print( "[GHOST] deleting all battle.net connections in preparation for exiting nicely" ); + + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + delete *i; + + m_BNETs.clear( ); } - if( m_DBLocal->HasError( ) ) + if( m_CurrentGame ) { - CONSOLE_Print( "[GHOST] local database error - " + m_DBLocal->GetError( ) ); - return true; + CONSOLE_Print( "[GHOST] deleting current game in preparation for exiting nicely" ); + delete m_CurrentGame; + m_CurrentGame = NULL; } - // try to exit nicely if requested to do so + if( m_AdminGame ) + { + CONSOLE_Print( "[GHOST] deleting admin game in preparation for exiting nicely" ); + delete m_AdminGame; + m_AdminGame = NULL; + } - if( m_ExitingNice ) + if( m_Games.isEmpty( ) ) { - if( !m_BNETs.isEmpty( ) ) + if( !m_AllGamesFinished ) { - CONSOLE_Print( "[GHOST] deleting all battle.net connections in preparation for exiting nicely" ); - - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - delete *i; - - m_BNETs.clear( ); + CONSOLE_Print( "[GHOST] all games finished, waiting 60 seconds for threads to finish" ); + CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads in progress" ); + m_AllGamesFinished = true; + m_AllGamesFinishedTime = GetTime( ); + QTimer::singleShot(60000, this, SLOT(EventWaitForNiceExitTimeout())); } - - if( m_CurrentGame ) + else if( m_Callables.isEmpty( ) ) { - CONSOLE_Print( "[GHOST] deleting current game in preparation for exiting nicely" ); - delete m_CurrentGame; - m_CurrentGame = NULL; + CONSOLE_Print( "[GHOST] all threads finished, exiting nicely" ); + deleteLater(); + return; } + } - if( m_AdminGame ) - { - CONSOLE_Print( "[GHOST] deleting admin game in preparation for exiting nicely" ); - delete m_AdminGame; - m_AdminGame = NULL; - } + // try again in 2 seconds + QTimer::singleShot(2000, this, SLOT(EventExitNice())); +} - if( m_Games.isEmpty( ) ) - { - if( !m_AllGamesFinished ) - { - CONSOLE_Print( "[GHOST] all games finished, waiting 60 seconds for threads to finish" ); - CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads in progress" ); - m_AllGamesFinished = true; - m_AllGamesFinishedTime = GetTime( ); - } - else - { - if( m_Callables.isEmpty( ) ) - { - CONSOLE_Print( "[GHOST] all threads finished, exiting nicely" ); - m_Exiting = true; - } - else if( GetTime( ) - m_AllGamesFinishedTime >= 60 ) - { - CONSOLE_Print( "[GHOST] waited 60 seconds for threads to finish, exiting anyway" ); - CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads still in progress which will be terminated" ); - m_Exiting = true; - } - } - } - } +void CGHost::EventWaitForNiceExitTimeout() +{ + CONSOLE_Print( "[GHOST] waited 60 seconds for threads to finish, exiting anyway" ); + CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads still in progress which will be terminated" ); + deleteLater(); +} - // create the GProxy++ reconnect listener +void CGHost::EventAutoHost() +{ + // autohost - if( m_Reconnect ) - { - if( !m_ReconnectSocket ) - { - m_ReconnectSocket = new QTcpServer( this ); - QObject::connect(m_ReconnectSocket, SIGNAL(newConnection()), this, SLOT(EventIncomingReconnection())); + if( m_AutoHostGameName.isEmpty( ) || m_AutoHostMaximumGames == 0 || m_AutoHostAutoStartPlayers == 0 ) + return; - if( m_ReconnectSocket->listen( QHostAddress(m_BindAddress), m_ReconnectPort ) ) - CONSOLE_Print( "[GHOST] listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); - else - { - CONSOLE_Print( "[GHOST] error listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); - delete m_ReconnectSocket; - m_ReconnectSocket = NULL; - m_Reconnect = false; - } - } - else if( !m_ReconnectSocket->isListening() ) - { - CONSOLE_Print( "[GHOST] GProxy++ reconnect listener error (" + m_ReconnectSocket->errorString() + ")" ); - delete m_ReconnectSocket; - m_ReconnectSocket = NULL; - m_Reconnect = false; - } + // copy all the checks from CGHost :: CreateGame here because we don't want to spam the chat when there's an error + // instead we fail silently and try again soon + + if( m_ExitingNice || !m_Enabled || m_CurrentGame || m_Games.size( ) >= m_MaxGames || m_Games.size( ) >= m_AutoHostMaximumGames ) + return; + + if( !m_AutoHostMap->GetValid( ) ) + { + CONSOLE_Print( "[GHOST] stopped auto hosting, map config file [" + m_AutoHostMap->GetCFGFile( ) + "] is invalid" ); + m_AutoHostGameName.clear( ); + m_AutoHostOwner.clear( ); + m_AutoHostServer.clear( ); + m_AutoHostMaximumGames = 0; + m_AutoHostAutoStartPlayers = 0; + m_AutoHostMatchMaking = false; + m_AutoHostMinimumScore = 0.0; + m_AutoHostMaximumScore = 0.0; + return; } - // before we call select we need to determine how long to block for - // previously we just blocked for a maximum of the passed usecBlock microseconds - // however, in an effort to make game updates happen closer to the desired latency setting we now use a dynamic block interval - // note: we still use the passed usecBlock as a hard maximum + QString GameName = m_AutoHostGameName + " #" + UTIL_ToString( m_HostCounter ); - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + if( GameName.size( ) >= 31 ) { - if( (*i)->GetNextTimedActionTicks( ) * 1000 < usecBlock ) - usecBlock = (*i)->GetNextTimedActionTicks( ) * 1000; + CONSOLE_Print( "[GHOST] stopped auto hosting, next game name [" + GameName + "] is too long (the maximum is 31 characters)" ); + m_AutoHostGameName.clear( ); + m_AutoHostOwner.clear( ); + m_AutoHostServer.clear( ); + m_AutoHostMaximumGames = 0; + m_AutoHostAutoStartPlayers = 0; + m_AutoHostMatchMaking = false; + m_AutoHostMinimumScore = 0.0; + m_AutoHostMaximumScore = 0.0; + return; } + CreateGame( m_AutoHostMap, GAME_PUBLIC, false, GameName, m_AutoHostOwner, m_AutoHostOwner, m_AutoHostServer, false ); + + if( !m_CurrentGame ) + return; - bool AdminExit = false; - bool BNETExit = false; + m_LastAutoHostTime.restart(); + m_CurrentGame->SetAutoStartPlayers( m_AutoHostAutoStartPlayers ); - // autohost + if( !m_AutoHostMatchMaking ) + return; - if( !m_AutoHostGameName.isEmpty( ) && m_AutoHostMaximumGames != 0 && m_AutoHostAutoStartPlayers != 0 && GetTime( ) - m_LastAutoHostTime >= 30 ) + if( m_Map->GetMapMatchMakingCategory( ).isEmpty( ) ) { - // copy all the checks from CGHost :: CreateGame here because we don't want to spam the chat when there's an error - // instead we fail silently and try again soon + CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory not found, matchmaking disabled" ); + return; + } - if( !m_ExitingNice && m_Enabled && !m_CurrentGame && m_Games.size( ) < m_MaxGames && m_Games.size( ) < m_AutoHostMaximumGames ) - { - if( m_AutoHostMap->GetValid( ) ) - { - QString GameName = m_AutoHostGameName + " #" + UTIL_ToString( m_HostCounter ); + if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) ) + { + CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory [" + m_Map->GetMapMatchMakingCategory( ) + "] found but matchmaking can only be used with fixed player settings, matchmaking disabled" ); + return; + } - if( GameName.size( ) <= 31 ) - { - CreateGame( m_AutoHostMap, GAME_PUBLIC, false, GameName, m_AutoHostOwner, m_AutoHostOwner, m_AutoHostServer, false ); + CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory [" + m_Map->GetMapMatchMakingCategory( ) + "] found, matchmaking enabled" ); - if( m_CurrentGame ) - { - m_CurrentGame->SetAutoStartPlayers( m_AutoHostAutoStartPlayers ); - - if( m_AutoHostMatchMaking ) - { - if( !m_Map->GetMapMatchMakingCategory( ).isEmpty( ) ) - { - if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) ) - CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory [" + m_Map->GetMapMatchMakingCategory( ) + "] found but matchmaking can only be used with fixed player settings, matchmaking disabled" ); - else - { - CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory [" + m_Map->GetMapMatchMakingCategory( ) + "] found, matchmaking enabled" ); - - m_CurrentGame->SetMatchMaking( true ); - m_CurrentGame->SetMinimumScore( m_AutoHostMinimumScore ); - m_CurrentGame->SetMaximumScore( m_AutoHostMaximumScore ); - } - } - else - CONSOLE_Print( "[GHOST] autohostmm - map_matchmakingcategory not found, matchmaking disabled" ); - } - } - } - else - { - CONSOLE_Print( "[GHOST] stopped auto hosting, next game name [" + GameName + "] is too long (the maximum is 31 characters)" ); - m_AutoHostGameName.clear( ); - m_AutoHostOwner.clear( ); - m_AutoHostServer.clear( ); - m_AutoHostMaximumGames = 0; - m_AutoHostAutoStartPlayers = 0; - m_AutoHostMatchMaking = false; - m_AutoHostMinimumScore = 0.0; - m_AutoHostMaximumScore = 0.0; - } - } - else - { - CONSOLE_Print( "[GHOST] stopped auto hosting, map config file [" + m_AutoHostMap->GetCFGFile( ) + "] is invalid" ); - m_AutoHostGameName.clear( ); - m_AutoHostOwner.clear( ); - m_AutoHostServer.clear( ); - m_AutoHostMaximumGames = 0; - m_AutoHostAutoStartPlayers = 0; - m_AutoHostMatchMaking = false; - m_AutoHostMinimumScore = 0.0; - m_AutoHostMaximumScore = 0.0; - } - } + m_CurrentGame->SetMatchMaking( true ); + m_CurrentGame->SetMinimumScore( m_AutoHostMinimumScore ); + m_CurrentGame->SetMaximumScore( m_AutoHostMaximumScore ); +} - m_LastAutoHostTime = GetTime( ); - } +void CGHost::CreateReconnectServer() +{ + // create the GProxy++ reconnect listener + if( !m_ReconnectSocket ) + { + m_ReconnectSocket = new QTcpServer( this ); + QObject::connect(m_ReconnectSocket, SIGNAL(newConnection()), this, SLOT(EventIncomingReconnection())); - return m_Exiting || AdminExit || BNETExit; + if( m_ReconnectSocket->listen( QHostAddress(m_BindAddress), m_ReconnectPort ) ) + CONSOLE_Print( "[GHOST] listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); + else + { + CONSOLE_Print( "[GHOST] error listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); + delete m_ReconnectSocket; + m_ReconnectSocket = NULL; + m_Reconnect = false; + } + } + else if( !m_ReconnectSocket->isListening() ) + { + CONSOLE_Print( "[GHOST] GProxy++ reconnect listener error (" + m_ReconnectSocket->errorString() + ")" ); + delete m_ReconnectSocket; + m_ReconnectSocket = NULL; + m_Reconnect = false; + } } void CGHost :: EventBNETConnecting( CBNET *bnet ) diff --git a/ghost/ghost.h b/ghost/ghost.h index 2dbfc3a..24a050c 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -43,6 +43,7 @@ class CSaveGame; class CConfig; #include +#include class CGHost : public QObject { @@ -52,8 +53,15 @@ public slots: void EventIncomingReconnection(); void EventReconnectionSocketReadyRead(); void EventCallableUpdateTimeout(); + void EventDatabaseError(const QString &error); + void EventExitNice(); + void EventWaitForNiceExitTimeout(); + void EventAutoHost(); + void EventGameStarted(); + void CreateReconnectServer(); public: + QTime m_LastAutoHostTime; QTimer m_CallableUpdateTimer; QUdpSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) QTcpServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects @@ -82,9 +90,8 @@ public slots: QString m_AutoHostGameName; // the base game name to auto host with QString m_AutoHostOwner; QString m_AutoHostServer; - uint32_t m_AutoHostMaximumGames; // maximum number of games to auto host + int m_AutoHostMaximumGames; // maximum number of games to auto host uint32_t m_AutoHostAutoStartPlayers; // when using auto hosting auto start the game when this many players have joined - uint32_t m_LastAutoHostTime; // GetTime when the last auto host was attempted bool m_AutoHostMatchMaking; double m_AutoHostMinimumScore; double m_AutoHostMaximumScore; @@ -98,7 +105,7 @@ public slots: bool m_Reconnect; // config value: GProxy++ reliable reconnects enabled or not uint16_t m_ReconnectPort; // config value: the port to listen for GProxy++ reliable reconnects on uint32_t m_ReconnectWaitTime; // config value: the maximum number of minutes to wait for a GProxy++ reliable reconnect - uint32_t m_MaxGames; // config value: maximum number of games in progress + int m_MaxGames; // config value: maximum number of games in progress char m_CommandTrigger; // config value: the command trigger inside games QString m_MapCFGPath; // config value: map cfg path QString m_SaveGamePath; // config value: savegame path @@ -146,10 +153,6 @@ public slots: CGHost( CConfig *CFG, QString configFile ); ~CGHost( ); - // processing functions - - bool Update( long usecBlock ); - // events void EventBNETConnecting( CBNET *bnet ); diff --git a/ghost/ghost.pro b/ghost/ghost.pro index b7e3eab..262961f 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -2,85 +2,85 @@ # Project created by QtCreator 2010-04-19T13:31:03 # ------------------------------------------------- QT += network \ - sql + sql QT -= gui TARGET = ghost CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += util.cpp \ - statsw3mmd.cpp \ - statsdota.cpp \ - stats.cpp \ - sqlite3.c \ - sha1.cpp \ - savegame.cpp \ - replay.cpp \ - packed.cpp \ - map.cpp \ - language.cpp \ - gpsprotocol.cpp \ - ghostdbsqlite.cpp \ - ghostdbmysql.cpp \ - ghostdb.cpp \ - ghost.cpp \ - gameslot.cpp \ - gameprotocol.cpp \ - gameplayer.cpp \ - game_base.cpp \ - game_admin.cpp \ - game.cpp \ - csvparser.cpp \ - crc32.cpp \ - config.cpp \ - commandpacket.cpp \ - bnlsprotocol.cpp \ - bnlsclient.cpp \ - bnetprotocol.cpp \ - bnet.cpp \ - bncsutilinterface.cpp \ - main.cpp + statsw3mmd.cpp \ + statsdota.cpp \ + stats.cpp \ + sqlite3.c \ + sha1.cpp \ + savegame.cpp \ + replay.cpp \ + packed.cpp \ + map.cpp \ + language.cpp \ + gpsprotocol.cpp \ + ghostdbsqlite.cpp \ + ghostdbmysql.cpp \ + ghostdb.cpp \ + ghost.cpp \ + gameslot.cpp \ + gameprotocol.cpp \ + gameplayer.cpp \ + game_base.cpp \ + game_admin.cpp \ + game.cpp \ + csvparser.cpp \ + crc32.cpp \ + config.cpp \ + commandpacket.cpp \ + bnlsprotocol.cpp \ + bnlsclient.cpp \ + bnetprotocol.cpp \ + bnet.cpp \ + bncsutilinterface.cpp \ + main.cpp OTHER_FILES += w3g_format.txt \ - w3g_actions.txt \ - ghost.vcproj + w3g_actions.txt \ + ghost.vcproj INCLUDEPATH += ../StormLib \ - ../bncsutil/src + ../bncsutil/src LIBS += -L../StormLib/stormlib \ - -L../bncsutil/src/bncsutil \ - -lbncsutil \ - -lStorm + -L../bncsutil/src/bncsutil \ + -lbncsutil \ + -lStorm HEADERS += util.h \ - statsw3mmd.h \ - statsdota.h \ - stats.h \ - sqlite3ext.h \ - sqlite3.h \ - sha1.h \ - savegame.h \ - replay.h \ - packed.h \ - next_combination.h \ - ms_stdint.h \ - map.h \ - language.h \ - includes.h \ - gpsprotocol.h \ - ghostdbsqlite.h \ - ghostdbmysql.h \ - ghostdb.h \ - ghost.h \ - gameslot.h \ - gameprotocol.h \ - gameplayer.h \ - game_base.h \ - game_admin.h \ - game.h \ - csvparser.h \ - crc32.h \ - config.h \ - commandpacket.h \ - bnlsprotocol.h \ - bnlsclient.h \ - bnetprotocol.h \ - bnet.h \ - bncsutilinterface.h + statsw3mmd.h \ + statsdota.h \ + stats.h \ + sqlite3ext.h \ + sqlite3.h \ + sha1.h \ + savegame.h \ + replay.h \ + packed.h \ + next_combination.h \ + ms_stdint.h \ + map.h \ + language.h \ + includes.h \ + gpsprotocol.h \ + ghostdbsqlite.h \ + ghostdbmysql.h \ + ghostdb.h \ + ghost.h \ + gameslot.h \ + gameprotocol.h \ + gameplayer.h \ + game_base.h \ + game_admin.h \ + game.h \ + csvparser.h \ + crc32.h \ + config.h \ + commandpacket.h \ + bnlsprotocol.h \ + bnlsclient.h \ + bnetprotocol.h \ + bnet.h \ + bncsutilinterface.h diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index fcb9f33..27c307a 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -27,7 +27,7 @@ // CGHostDB // -CGHostDB :: CGHostDB( CConfig *CFG ) +CGHostDB :: CGHostDB( CConfig */*CFG*/ ) { m_HasError = false; } @@ -37,7 +37,14 @@ CGHostDB :: ~CGHostDB( ) } -void CGHostDB :: RecoverCallable( CBaseCallable *callable ) +void CGHostDB::SetError(const QString &sError) +{ + m_Error = sError; + m_HasError = true; + emit error(m_Error); +} + +void CGHostDB :: RecoverCallable( CBaseCallable */*callable*/ ) { } @@ -52,132 +59,132 @@ bool CGHostDB :: Commit( ) return true; } -uint32_t CGHostDB :: AdminCount( QString server ) +uint32_t CGHostDB :: AdminCount( QString /*server*/ ) { return 0; } -bool CGHostDB :: AdminCheck( QString server, QString user ) +bool CGHostDB :: AdminCheck( QString /*server*/, QString /*user*/ ) { return false; } -bool CGHostDB :: AdminAdd( QString server, QString user ) +bool CGHostDB :: AdminAdd( QString /*server*/, QString /*user*/ ) { return false; } -bool CGHostDB :: AdminRemove( QString server, QString user ) +bool CGHostDB :: AdminRemove( QString /*server*/, QString /*user*/ ) { return false; } -QVector CGHostDB :: AdminList( QString server ) +QVector CGHostDB :: AdminList( QString /*server*/ ) { return QVector( ); } -uint32_t CGHostDB :: BanCount( QString server ) +uint32_t CGHostDB :: BanCount( QString /*server*/ ) { return 0; } -CDBBan *CGHostDB :: BanCheck( QString server, QString user, QString ip ) +CDBBan *CGHostDB :: BanCheck( QString /*server*/, QString /*user*/, QString /*ip*/ ) { return NULL; } -bool CGHostDB :: BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) +bool CGHostDB :: BanAdd( QString /*server*/, QString /*user*/, QString /*ip*/, QString /*gamename*/, QString /*admin*/, QString /*reason*/ ) { return false; } -bool CGHostDB :: BanRemove( QString server, QString user ) +bool CGHostDB :: BanRemove( QString /*server*/, QString /*user*/ ) { return false; } -bool CGHostDB :: BanRemove( QString user ) +bool CGHostDB :: BanRemove( QString /*user*/ ) { return false; } -QVector CGHostDB :: BanList( QString server ) +QVector CGHostDB :: BanList( QString /*server*/ ) { return QVector( ); } -uint32_t CGHostDB :: GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) +uint32_t CGHostDB :: GameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, uint32_t /*duration*/, uint32_t /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) { return 0; } -uint32_t CGHostDB :: GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) +uint32_t CGHostDB :: GamePlayerAdd( uint32_t /*gameid*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*reserved*/, uint32_t /*loadingtime*/, uint32_t /*left*/, QString /*leftreason*/, uint32_t /*team*/, uint32_t /*colour*/ ) { return 0; } -uint32_t CGHostDB :: GamePlayerCount( QString name ) +uint32_t CGHostDB :: GamePlayerCount( QString /*name*/ ) { return 0; } -CDBGamePlayerSummary *CGHostDB :: GamePlayerSummaryCheck( QString name ) +CDBGamePlayerSummary *CGHostDB :: GamePlayerSummaryCheck( QString /*name*/ ) { return NULL; } -uint32_t CGHostDB :: DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +uint32_t CGHostDB :: DotAGameAdd( uint32_t /*gameid*/, uint32_t /*winner*/, uint32_t /*min*/, uint32_t /*sec*/ ) { return 0; } -uint32_t CGHostDB :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +uint32_t CGHostDB :: DotAPlayerAdd( uint32_t /*gameid*/, uint32_t /*colour*/, uint32_t /*kills*/, uint32_t /*deaths*/, uint32_t /*creepkills*/, uint32_t /*creepdenies*/, uint32_t /*assists*/, uint32_t /*gold*/, uint32_t /*neutralkills*/, QString /*item1*/, QString /*item2*/, QString /*item3*/, QString /*item4*/, QString /*item5*/, QString /*item6*/, QString /*hero*/, uint32_t /*newcolour*/, uint32_t /*towerkills*/, uint32_t /*raxkills*/, uint32_t /*courierkills*/ ) { return 0; } -uint32_t CGHostDB :: DotAPlayerCount( QString name ) +uint32_t CGHostDB :: DotAPlayerCount( QString /*name*/ ) { return 0; } -CDBDotAPlayerSummary *CGHostDB :: DotAPlayerSummaryCheck( QString name ) +CDBDotAPlayerSummary *CGHostDB :: DotAPlayerSummaryCheck( QString /*name*/ ) { return NULL; } -QString CGHostDB :: FromCheck( uint32_t ip ) +QString CGHostDB :: FromCheck( uint32_t /*ip*/ ) { return "??"; } -bool CGHostDB :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) +bool CGHostDB :: FromAdd( uint32_t /*ip1*/, uint32_t /*ip2*/, QString /*country*/ ) { return false; } -bool CGHostDB :: DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) +bool CGHostDB :: DownloadAdd( QString /*map*/, uint32_t /*mapsize*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*downloadtime*/ ) { return false; } -uint32_t CGHostDB :: W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) +uint32_t CGHostDB :: W3MMDPlayerAdd( QString /*category*/, uint32_t /*gameid*/, uint32_t /*pid*/, QString /*name*/, QString /*flag*/, uint32_t /*leaver*/, uint32_t /*practicing*/ ) { return 0; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, QMap var_ints ) +bool CGHostDB :: W3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_ints*/ ) { return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, QMap var_reals ) +bool CGHostDB :: W3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_reals*/ ) { return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t gameid, QMap var_strings ) +bool CGHostDB :: W3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_strings*/ ) { return false; } @@ -187,117 +194,117 @@ void CGHostDB :: CreateThread( CBaseCallable *callable ) callable->SetReady( true ); } -CCallableAdminCount *CGHostDB :: ThreadedAdminCount( QString server ) +CCallableAdminCount *CGHostDB :: ThreadedAdminCount( QString /*server*/ ) { return NULL; } -CCallableAdminCheck *CGHostDB :: ThreadedAdminCheck( QString server, QString user ) +CCallableAdminCheck *CGHostDB :: ThreadedAdminCheck( QString /*server*/, QString /*user*/ ) { return NULL; } -CCallableAdminAdd *CGHostDB :: ThreadedAdminAdd( QString server, QString user ) +CCallableAdminAdd *CGHostDB :: ThreadedAdminAdd( QString /*server*/, QString /*user*/ ) { return NULL; } -CCallableAdminRemove *CGHostDB :: ThreadedAdminRemove( QString server, QString user ) +CCallableAdminRemove *CGHostDB :: ThreadedAdminRemove( QString /*server*/, QString /*user*/ ) { return NULL; } -CCallableAdminList *CGHostDB :: ThreadedAdminList( QString server ) +CCallableAdminList *CGHostDB :: ThreadedAdminList( QString /*server*/ ) { return NULL; } -CCallableBanCount *CGHostDB :: ThreadedBanCount( QString server ) +CCallableBanCount *CGHostDB :: ThreadedBanCount( QString /*server*/ ) { return NULL; } -CCallableBanCheck *CGHostDB :: ThreadedBanCheck( QString server, QString user, QString ip ) +CCallableBanCheck *CGHostDB :: ThreadedBanCheck( QString /*server*/, QString /*user*/, QString /*ip*/ ) { return NULL; } -CCallableBanAdd *CGHostDB :: ThreadedBanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) +CCallableBanAdd *CGHostDB :: ThreadedBanAdd( QString /*server*/, QString /*user*/, QString /*ip*/, QString /*gamename*/, QString /*admin*/, QString /*reason*/ ) { return NULL; } -CCallableBanRemove *CGHostDB :: ThreadedBanRemove( QString server, QString user ) +CCallableBanRemove *CGHostDB :: ThreadedBanRemove( QString /*server*/, QString /*user*/ ) { return NULL; } -CCallableBanRemove *CGHostDB :: ThreadedBanRemove( QString user ) +CCallableBanRemove *CGHostDB :: ThreadedBanRemove( QString /*user*/ ) { return NULL; } -CCallableBanList *CGHostDB :: ThreadedBanList( QString server ) +CCallableBanList *CGHostDB :: ThreadedBanList( QString /*server*/ ) { return NULL; } -CCallableGameAdd *CGHostDB :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) +CCallableGameAdd *CGHostDB :: ThreadedGameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, uint32_t /*duration*/, uint32_t /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) { return NULL; } -CCallableGamePlayerAdd *CGHostDB :: ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) +CCallableGamePlayerAdd *CGHostDB :: ThreadedGamePlayerAdd( uint32_t /*gameid*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*reserved*/, uint32_t /*loadingtime*/, uint32_t /*left*/, QString /*leftreason*/, uint32_t /*team*/, uint32_t /*colour*/ ) { return NULL; } -CCallableGamePlayerSummaryCheck *CGHostDB :: ThreadedGamePlayerSummaryCheck( QString name ) +CCallableGamePlayerSummaryCheck *CGHostDB :: ThreadedGamePlayerSummaryCheck( QString /*name*/ ) { return NULL; } -CCallableDotAGameAdd *CGHostDB :: ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +CCallableDotAGameAdd *CGHostDB :: ThreadedDotAGameAdd( uint32_t /*gameid*/, uint32_t /*winner*/, uint32_t /*min*/, uint32_t /*sec*/ ) { return NULL; } -CCallableDotAPlayerAdd *CGHostDB :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +CCallableDotAPlayerAdd *CGHostDB :: ThreadedDotAPlayerAdd( uint32_t /*gameid*/, uint32_t /*colour*/, uint32_t /*kills*/, uint32_t /*deaths*/, uint32_t /*creepkills*/, uint32_t /*creepdenies*/, uint32_t /*assists*/, uint32_t /*gold*/, uint32_t /*neutralkills*/, QString /*item1*/, QString /*item2*/, QString /*item3*/, QString /*item4*/, QString /*item5*/, QString /*item6*/, QString /*hero*/, uint32_t /*newcolour*/, uint32_t /*towerkills*/, uint32_t /*raxkills*/, uint32_t /*courierkills*/ ) { return NULL; } -CCallableDotAPlayerSummaryCheck *CGHostDB :: ThreadedDotAPlayerSummaryCheck( QString name ) +CCallableDotAPlayerSummaryCheck *CGHostDB :: ThreadedDotAPlayerSummaryCheck( QString /*name*/ ) { return NULL; } -CCallableDownloadAdd *CGHostDB :: ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) +CCallableDownloadAdd *CGHostDB :: ThreadedDownloadAdd( QString /*map*/, uint32_t /*mapsize*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*downloadtime*/ ) { return NULL; } -CCallableScoreCheck *CGHostDB :: ThreadedScoreCheck( QString category, QString name, QString server ) +CCallableScoreCheck *CGHostDB :: ThreadedScoreCheck( QString /*category*/, QString /*name*/, QString /*server*/ ) { return NULL; } -CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) +CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString /*category*/, uint32_t /*gameid*/, uint32_t /*pid*/, QString /*name*/, QString /*flag*/, uint32_t /*leaver*/, uint32_t /*practicing*/ ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_ints*/ ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_reals*/ ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_strings*/ ) { return NULL; } diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index 4bfe051..02e9c87 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -25,6 +25,7 @@ // CGHostDB // + class CBaseCallable; class CCallableAdminCount; class CCallableAdminCheck; @@ -51,15 +52,27 @@ class CDBGame; class CDBGamePlayer; class CDBGamePlayerSummary; class CDBDotAPlayerSummary; +class CConfig; + +#include "includes.h" +#include -typedef pair VarP; +typedef QPair VarP; -class CGHostDB +class CGHostDB : public QObject { -protected: + Q_OBJECT + +signals: + void error(const QString& message); + +private: bool m_HasError; QString m_Error; +protected: + void SetError(const QString& error); + public: CGHostDB( CConfig *CFG ); virtual ~CGHostDB( ); diff --git a/ghost/ghostdbmysql.cpp b/ghost/ghostdbmysql.cpp index 9ec6434..bcc2534 100644 --- a/ghost/ghostdbmysql.cpp +++ b/ghost/ghostdbmysql.cpp @@ -60,8 +60,7 @@ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) if( !( Connection = mysql_init( NULL ) ) ) { CONSOLE_Print( QString( "[MYSQL] " ) + mysql_error( Connection ) ); - m_HasError = true; - m_Error = "error initializing MySQL connection"; + SetError("error initializing MySQL connection"); return; } @@ -71,8 +70,7 @@ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) if( !( mysql_real_connect( Connection, m_Server.c_str( ), m_User.c_str( ), m_Password.c_str( ), m_Database.c_str( ), m_Port, NULL, 0 ) ) ) { CONSOLE_Print( QString( "[MYSQL] " ) + mysql_error( Connection ) ); - m_HasError = true; - m_Error = "error connecting to MySQL server"; + SetError("error connecting to MySQL server"); return; } diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index 1457f47..f1c20cd 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -116,8 +116,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) // this is okay here because we're in the constructor so we're not dropping any games or players CONSOLE_Print( QString( "[SQLITE3] error opening database [" + m_File + "] - " ) + m_DB->GetError( ) ); - m_HasError = true; - m_Error = "error opening database"; + SetError("error opening database"); return; } diff --git a/ghost/gpsprotocol.cpp b/ghost/gpsprotocol.cpp index ca2a6de..eb36a90 100644 --- a/ghost/gpsprotocol.cpp +++ b/ghost/gpsprotocol.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/ghost/includes.h b/ghost/includes.h index e90426a..5e075e5 100644 --- a/ghost/includes.h +++ b/ghost/includes.h @@ -31,39 +31,24 @@ // STL -#include #include -#include -#include -#include -#include -#include #include #include #include #include +#include +#include using namespace std; -typedef pair PIDPlayer; +typedef QPair PIDPlayer; // time uint32_t GetTime( ); // seconds uint32_t GetTicks( ); // milliseconds -#ifdef WIN32 - #define MILLISLEEP( x ) Sleep( x ) -#else - #define MILLISLEEP( x ) usleep( ( x ) * 1000 ) -#endif - -// network - -#undef FD_SETSIZE -#define FD_SETSIZE 512 - // output void CONSOLE_Print( QString message ); diff --git a/ghost/main.cpp b/ghost/main.cpp index 7dcaa7a..d9dd66b 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -50,7 +50,7 @@ void SignalCatcher( int s ) CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting nicely" ); if( gGHost ) - gGHost->m_ExitingNice = true; + gGHost->EventExitNice(); else exit( 1 ); } @@ -87,7 +87,7 @@ void DEBUG_Print( QByteArray b ) { cout << "{ "; - for( unsigned int i = 0; i < b.size( ); i++ ) + for( int i = 0; i < b.size( ); i++ ) cout << hex << (int)b[i] << " "; cout << "}" << endl; @@ -160,17 +160,6 @@ int main( int argc, char **argv ) #endif #ifdef WIN32 - // initialize winsock - - CONSOLE_Print( "[GHOST] starting winsock" ); - WSADATA wsadata; - - if( WSAStartup( MAKEWORD( 2, 2 ), &wsadata ) != 0 ) - { - CONSOLE_Print( "[GHOST] error starting winsock" ); - return 1; - } - // increase process priority CONSOLE_Print( "[GHOST] setting process priority to \"above normal\"" ); @@ -181,24 +170,7 @@ int main( int argc, char **argv ) gGHost = new CGHost( &CFG, gCFGFile ); - int ret = a.exec(); - - // shutdown ghost - - CONSOLE_Print( "[GHOST] shutting down" ); - delete gGHost; - gGHost = NULL; - -#ifdef WIN32 - // shutdown winsock - - CONSOLE_Print( "[GHOST] shutting down winsock" ); - WSACleanup( ); - - // shutdown timer - - timeEndPeriod( TimerResolution ); -#endif + QObject::connect(gGHost, SIGNAL(destroyed()), &a, SLOT(quit())); - return ret; + return a.exec(); } diff --git a/ghost/map.cpp b/ghost/map.cpp index fdcef2c..9bffa56 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -18,6 +18,9 @@ */ +#include +using std::istringstream; + #include "ghost.h" #include "util.h" #include "crc32.h" diff --git a/ghost/packed.cpp b/ghost/packed.cpp index 587f5b7..1654643 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -135,7 +135,7 @@ bool CPacked :: Pack( bool TFT, QString inFileName, QString outFileName ) return false; } -void CPacked :: Decompress( bool allBlocks ) +void CPacked :: Decompress( bool /*allBlocks*/ ) { /*CONSOLE_Print( "[PACKED] decompressing data" ); diff --git a/ghost/replay.cpp b/ghost/replay.cpp index 3d8c0cd..a73bc87 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -220,7 +220,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 #define READB( x, y, z ) (x).read( (char *)(y), (z) ) #define READSTR( x, y ) getline( (x), (y), '\0' ) -void CReplay :: ParseReplay( bool parseBlocks ) +void CReplay :: ParseReplay( bool /*parseBlocks*/ ) { /* m_HostPID = 0; diff --git a/ghost/sha1.cpp b/ghost/sha1.cpp index a73517e..29c2f6f 100644 --- a/ghost/sha1.cpp +++ b/ghost/sha1.cpp @@ -153,7 +153,7 @@ void CSHA1::Final() } // Get the final hash as a pre-formatted QString -void CSHA1::ReportHash(char *szReport, unsigned char uReportType) +void CSHA1::ReportHash(char */*szReport*/, unsigned char /*uReportType*/) { /* diff --git a/ghost/stats.cpp b/ghost/stats.cpp index 9dec048..7bd6a23 100644 --- a/ghost/stats.cpp +++ b/ghost/stats.cpp @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -35,12 +35,12 @@ CStats :: ~CStats( ) } -bool CStats :: ProcessAction( CIncomingAction *Action ) +bool CStats :: ProcessAction( CIncomingAction */*Action*/ ) { return false; } -void CStats :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) +void CStats :: Save( CGHost */*GHost*/, CGHostDB */*DB*/, uint32_t /*GameID*/ ) { } diff --git a/ghost/statsdota.cpp b/ghost/statsdota.cpp index 58bcd8e..23a98f9 100644 --- a/ghost/statsdota.cpp +++ b/ghost/statsdota.cpp @@ -68,26 +68,26 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) // parsing the actions would be more correct but would be a lot more difficult to write for relatively little gain // so we take the easy route (which isn't always guaranteed to work) and search the data for the sequence "6b 64 72 2e 78 00" and hope it identifies an action - while( ActionData->size( ) >= i + 6 ) + while( (unsigned int)ActionData->size( ) >= i + 6 ) { - if( (*ActionData)[i] == 0x6b && (*ActionData)[i + 1] == 0x64 && (*ActionData)[i + 2] == 0x72 && (*ActionData)[i + 3] == 0x2e && (*ActionData)[i + 4] == 0x78 && (*ActionData)[i + 5] == 0x00 ) + if( (*ActionData).at(i) == 0x6b && (*ActionData).at(i + 1) == 0x64 && (*ActionData).at(i + 2) == 0x72 && (*ActionData).at(i + 3) == 0x2e && (*ActionData).at(i + 4) == 0x78 && (*ActionData).at(i + 5) == 0x00 ) { // we think we've found an action with real time replay data (but we can't be 100% sure) // next we parse out two null terminated strings and a 4 byte integer - if( ActionData->size( ) >= i + 7 ) + if( (unsigned int)ActionData->size( ) >= i + 7 ) { // the first null terminated QString should either be the strings "Data" or "Global" or a player id in ASCII representation, e.g. "1" or "2" Data = UTIL_ExtractCString( *ActionData, i + 6 ); - if( ActionData->size( ) >= i + 8 + Data.size( ) ) + if( (unsigned int)ActionData->size( ) >= i + 8 + Data.size( ) ) { // the second null terminated QString should be the key Key = UTIL_ExtractCString( *ActionData, i + 7 + Data.size( ) ); - if( ActionData->size( ) >= i + 12 + Data.size( ) + Key.size( ) ) + if( (unsigned int)ActionData->size( ) >= i + 12 + Data.size( ) + Key.size( ) ) { // the 4 byte integer should be the value diff --git a/ghost/statsw3mmd.cpp b/ghost/statsw3mmd.cpp index 0ecf0bb..9d11d92 100644 --- a/ghost/statsw3mmd.cpp +++ b/ghost/statsw3mmd.cpp @@ -54,39 +54,39 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) QByteArray Key; QByteArray Value; - while( ActionData->size( ) >= i + 9 ) + while( (unsigned int)ActionData->size( ) >= i + 9 ) { - if( (*ActionData)[i] == 'k' && - (*ActionData)[i + 1] == 'M' && - (*ActionData)[i + 2] == 'M' && - (*ActionData)[i + 3] == 'D' && - (*ActionData)[i + 4] == '.' && - (*ActionData)[i + 5] == 'D' && - (*ActionData)[i + 6] == 'a' && - (*ActionData)[i + 7] == 't' && - (*ActionData)[i + 8] == 0x00 ) + if( (*ActionData).at(i) == 'k' && + (*ActionData).at(i + 1) == 'M' && + (*ActionData).at(i + 2) == 'M' && + (*ActionData).at(i + 3) == 'D' && + (*ActionData).at(i + 4) == '.' && + (*ActionData).at(i + 5) == 'D' && + (*ActionData).at(i + 6) == 'a' && + (*ActionData).at(i + 7) == 't' && + (*ActionData).at(i + 8) == 0x00 ) { - if( ActionData->size( ) >= i + 10 ) + if( (unsigned int)ActionData->size( ) >= i + 10 ) { MissionKey = UTIL_ExtractCString( *ActionData, i + 9 ); - if( ActionData->size( ) >= i + 11 + MissionKey.size( ) ) + if( (unsigned int)ActionData->size( ) >= i + 11 + MissionKey.size( ) ) { Key = UTIL_ExtractCString( *ActionData, i + 10 + MissionKey.size( ) ); - if( ActionData->size( ) >= i + 15 + MissionKey.size( ) + Key.size( ) ) + if( (unsigned int)ActionData->size( ) >= i + 15 + MissionKey.size( ) + Key.size( ) ) { Value = ActionData->mid(i + 11 + MissionKey.size( ) + Key.size( ), 4 ); QString MissionKeyString = MissionKey; QString KeyString = Key; - uint32_t ValueInt = UTIL_QByteArrayToUInt32( Value, false ); + //uint32_t ValueInt = UTIL_QByteArrayToUInt32( Value, false ); // CONSOLE_Print( "[STATSW3MMD] DEBUG: mkey [" + MissionKeyString + "], key [" + KeyString + "], value [" + UTIL_ToString( ValueInt ) + "]" ); if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "val:" ) { QString ValueIDString = MissionKeyString.mid( 4 ); - uint32_t ValueID = UTIL_ToUInt32( ValueIDString ); + //uint32_t ValueID = UTIL_ToUInt32( ValueIDString ); QVector Tokens = TokenizeKey( KeyString ); if( !Tokens.isEmpty( ) ) @@ -253,7 +253,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { uint32_t Arguments = UTIL_ToUInt32( Tokens[2] ); - if( Tokens.size( ) == Arguments + 4 ) + if( (unsigned int)Tokens.size( ) == Arguments + 4 ) m_DefEvents[Tokens[1]] = Tokens.mid(3); } } @@ -278,7 +278,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { // replace the markers in the format QString with the arguments - for( uint32_t i = 0; i < Tokens.size( ) - 2; i++ ) + for( int i = 0; i < Tokens.size( ) - 2; i++ ) { // check if the marker is a PID marker @@ -321,7 +321,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) else if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "chk:" ) { QString CheckIDString = MissionKeyString.mid( 4 ); - uint32_t CheckID = UTIL_ToUInt32( CheckIDString ); + //uint32_t CheckID = UTIL_ToUInt32( CheckIDString ); // todotodo: cheat detection diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index e3d48a2..f18d1f4 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -25,7 +25,8 @@ // CStatsW3MMD // -typedef pair VarP; +#include +typedef QPair VarP; class CStatsW3MMD : public CStats { diff --git a/ghost/util.cpp b/ghost/util.cpp index ace99f1..2533a21 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -71,7 +71,7 @@ QByteArray UTIL_CreateQByteArray( uint32_t i, bool reverse ) uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start ) { - if( b.size( ) < start + 2 ) + if( (unsigned int)b.size( ) < start + 2 ) return 0; QByteArray temp = b.mid(start, 2); @@ -81,7 +81,7 @@ uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start ) { - if( b.size( ) < start + 4 ) + if( (unsigned int)b.size( ) < start + 4 ) return 0; QByteArray temp = b.mid(start, 4); @@ -281,7 +281,7 @@ int32_t UTIL_ToInt32( QString &s ) double UTIL_ToDouble( QString &s ) { - s.toDouble(); + return s.toDouble(); } QString UTIL_MSToString( uint32_t ms ) @@ -374,7 +374,7 @@ QByteArray UTIL_EncodeStatString( QByteArray &data ) unsigned char Mask = 1; QByteArray Result; - for( unsigned int i = 0; i < data.size( ); i++ ) + for( int i = 0; i < data.size( ); i++ ) { if( ( data[i] % 2 ) == 0 ) Result.push_back( data[i] + 1 ); @@ -409,7 +409,7 @@ QByteArray UTIL_DecodeStatString( QByteArray &data ) unsigned char Mask; QByteArray Result; - for( unsigned int i = 0; i < data.size( ); i++ ) + for( int i = 0; i < data.size( ); i++ ) { if( ( i % 8 ) == 0 ) Mask = data[i]; @@ -433,23 +433,23 @@ bool UTIL_IsLanIP( QByteArray ip ) // thanks to LuCasn for this function // 127.0.0.1 - if( ip[0] == 127 && ip[1] == 0 && ip[2] == 0 && ip[3] == 1 ) + if( ip.at(0) == 127 && ip.at(1) == 0 && ip.at(2) == 0 && ip.at(3) == 1 ) return true; // 10.x.x.x - if( ip[0] == 10 ) + if( ip.at(0) == 10 ) return true; // 172.16.0.0-172.31.255.255 - if( ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31 ) + if( (unsigned char)ip.at(0) == 172 && ip.at(1) >= 16 && ip.at(1) <= 31 ) return true; // 192.168.x.x - if( ip[0] == 192 && ip[1] == 168 ) + if( (unsigned char)ip.at(0) == 192 && (unsigned char)ip.at(1) == 168 ) return true; // RFC 3330 and RFC 3927 automatic address range - if( ip[0] == 169 && ip[1] == 254 ) + if( (unsigned char)ip.at(0) == 169 && (unsigned char)ip.at(1) == 254 ) return true; return false; From 87244e374053ea003d008abcbb44fd8980689fb9 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 05:06:46 +0000 Subject: [PATCH 15/69] warnings removed --- ghost/map.cpp | 2 +- ghost/next_combination.h | 72 ++++++++++++++++++++-------------------- ghost/util.cpp | 3 ++ 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/ghost/map.cpp b/ghost/map.cpp index 9bffa56..b055164 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -902,7 +902,7 @@ void CMap :: CheckValid( ) m_Valid = false; CONSOLE_Print( "[MAP] invalid map_size detected" ); } - else if( !m_MapData.isEmpty( ) && m_MapData.size( ) != UTIL_QByteArrayToUInt32( m_MapSize, false ) ) + else if( !m_MapData.isEmpty( ) && (unsigned int)m_MapData.size( ) != UTIL_QByteArrayToUInt32( m_MapSize, false ) ) { m_Valid = false; CONSOLE_Print( "[MAP] invalid map_size detected - size mismatch with actual map data" ); diff --git a/ghost/next_combination.h b/ghost/next_combination.h index ba8b785..42ae347 100644 --- a/ghost/next_combination.h +++ b/ghost/next_combination.h @@ -7,34 +7,34 @@ #include template -void disjoint_rotate(Iterator begin1, Iterator end1, size_t size1, - Iterator begin2, Iterator end2, size_t size2, - Value *type) { +void disjoint_rotate(Iterator begin1, Iterator /*end1*/, size_t size1, + Iterator begin2, Iterator /*end2*/, size_t size2, + Value */*type*/) { const size_t total = size1 + size2; size_t gcd = total; for (size_t div = size1; div != 0; ) { - gcd %= div; - std::swap(gcd, div); + gcd %= div; + std::swap(gcd, div); } const size_t skip = total / gcd - 1; for (size_t i = 0; i < gcd; ++i) { - Iterator curr((i < size1) ? begin1 + i : begin2 + (i - size1)); - size_t ctr = i; - const Value v(*curr); - for (size_t j = 0; j < skip; ++j) { - ctr = (ctr + size1) % total; - Iterator next((ctr < size1) ? begin1 + ctr : begin2 + (ctr - size1)); - *curr = *next; - curr = next; - } - *curr = v; + Iterator curr((i < size1) ? begin1 + i : begin2 + (i - size1)); + size_t ctr = i; + const Value v(*curr); + for (size_t j = 0; j < skip; ++j) { + ctr = (ctr + size1) % total; + Iterator next((ctr < size1) ? begin1 + ctr : begin2 + (ctr - size1)); + *curr = *next; + curr = next; + } + *curr = v; } } template bool next_combination(Iterator begin, Iterator mid, Iterator end) { if (begin == mid || mid == end) { - return false; + return false; } // Starting from mid backwards, find first char that is // less than last char. Call it head_pos. This is the one @@ -45,27 +45,27 @@ bool next_combination(Iterator begin, Iterator mid, Iterator end) { --head_pos; size_t head_len = 1; while (head_pos != begin && !(*head_pos < *tail_pos)) { - --head_pos; - ++head_len; + --head_pos; + ++head_len; } if (head_pos == begin && !(*head_pos < *tail_pos)) { - // Last combination. We know that the smallest elements are - // in tail (in order) and largest elements are in head (also - // in order). rotate everything back into order and return false. - std::rotate(begin, mid, end); - return false; + // Last combination. We know that the smallest elements are + // in tail (in order) and largest elements are in head (also + // in order). rotate everything back into order and return false. + std::rotate(begin, mid, end); + return false; } // Now decrement tail_pos as long as it is larger than *head_pos. // This way we'll find the two positions to swap. size_t tail_len = 1; while (tail_pos > mid) { - --tail_pos; - ++tail_len; - if (!(*tail_pos > *head_pos)) { - ++tail_pos; - --tail_len; - break; - } + --tail_pos; + ++tail_len; + if (!(*tail_pos > *head_pos)) { + ++tail_pos; + --tail_len; + break; + } } // Now we have head_pos and tail_pos. Lets call // - 'h': the element at head_pos @@ -88,22 +88,22 @@ bool next_combination(Iterator begin, Iterator mid, Iterator end) { // Same is true if tail_len == 1 (T == ''). Proof: h H ; t -> t H ; h, // so this time H will stay in place and swap will suffice. if (head_len == 1 || tail_len == 1) { - std::iter_swap(head_pos, tail_pos); - return true; + std::iter_swap(head_pos, tail_pos); + return true; } // If head_len == tail_len, this operation reduces to a swap_ranges. // Proof: since len(H) == len(T), the swap is h H ; t T -> t T ; h H if (head_len == tail_len) { - std::swap_ranges(head_pos, mid, tail_pos); - return true; + std::swap_ranges(head_pos, mid, tail_pos); + return true; } // Finally we have to do the full reorder. Simply swap h and t, then // do what std::rotate would do with the sequence H T with the // constraint that the elements are not stored in consecutive locations. std::iter_swap(head_pos, tail_pos); disjoint_rotate(head_pos + 1, mid, head_len - 1, - tail_pos + 1, end, tail_len - 1, - &*head_pos); + tail_pos + 1, end, tail_len - 1, + &*head_pos); return true; } diff --git a/ghost/util.cpp b/ghost/util.cpp index 2533a21..adef36b 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -165,6 +165,9 @@ unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ) // consider the byte array to contain a 2 character ASCII encoded hex value at b[start] and b[start + 1] e.g. "FF" // extract it as a single decoded byte + if (reverse) + return (unsigned char)(b.mid(start + 1, 1) + b.mid(start, 1)).toUShort(NULL, 16); + return (unsigned char)b.mid(start, 2).toUShort(NULL, 16); } From d5625461643641a59bcbfd831814ff8e2d337010 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 05:55:29 +0000 Subject: [PATCH 16/69] broadcasting game information works --- ghost/game_base.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 7a33e7d..c70f1f3 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -535,6 +535,8 @@ void CBaseGame::EventBroadcastTimeout() // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused uint32_t FixedHostCounter = m_HostCounter & 0x0FFFFFFF; + QString target = m_GHost->m_UDPSocket->property("target").toString(); + QHostAddress hostAddr = target == "" ? QHostAddress::LocalHost : QHostAddress(m_GHost->m_UDPSocket->property("target").toString()); if( m_SaveGame ) { @@ -564,7 +566,7 @@ void CBaseGame::EventBroadcastTimeout() 12, m_HostPort, FixedHostCounter ), - QHostAddress(m_GHost->m_UDPSocket->property("target").toString()), + hostAddr, 6112); } else @@ -574,7 +576,7 @@ void CBaseGame::EventBroadcastTimeout() uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ), - QHostAddress(m_GHost->m_UDPSocket->property("target").toString()), + hostAddr, 6112 ); } } From 013b37e33792fc2d95202a45853cd6a8b7a50c93 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 06:39:58 +0000 Subject: [PATCH 17/69] renamend UTIL functions back --- ghost/bncsutilinterface.cpp | 14 +-- ghost/bnet.cpp | 8 +- ghost/bnetprotocol.cpp | 128 +++++++++++++-------------- ghost/bnlsprotocol.cpp | 18 ++-- ghost/game.cpp | 4 +- ghost/game_base.cpp | 43 ++++----- ghost/gameplayer.cpp | 2 +- ghost/gameprotocol.cpp | 170 ++++++++++++++++++------------------ ghost/ghost.cpp | 2 +- ghost/gpsprotocol.cpp | 20 ++--- ghost/map.cpp | 12 +-- ghost/packed.cpp | 32 +++---- ghost/replay.cpp | 84 +++++++++--------- ghost/util.cpp | 24 ++--- ghost/util.h | 18 ++-- mapcfgs/wormwar.cfg | 2 +- 16 files changed, 293 insertions(+), 288 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index a563b84..2632712 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -71,10 +71,10 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr uint32_t EXEVersion; getExeInfo( FileWar3EXE.toStdString().c_str( ), (char *)&buf, 1024, (uint32_t *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); m_EXEInfo = buf; - m_EXEVersion = UTIL_CreateQByteArray( EXEVersion, false ); + m_EXEVersion = UTIL_CreateBYTEARRAY( EXEVersion, false ); uint32_t EXEVersionHash; checkRevisionFlat( valueStringFormula.toStdString().c_str( ), FileWar3EXE.toStdString().c_str( ), FileStormDLL.toStdString().c_str( ), FileGameDLL.toStdString().c_str( ), extractMPQNumber( mpqFileName.toStdString().c_str( ) ), (unsigned long *)&EXEVersionHash ); - m_EXEVersionHash = UTIL_CreateQByteArray( EXEVersionHash, false ); + m_EXEVersionHash = UTIL_CreateBYTEARRAY( EXEVersionHash, false ); m_KeyInfoROC = CreateKeyInfo( keyROC, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); if( TFT ) @@ -146,14 +146,14 @@ QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToke if( Decoder.isKeyValid( ) ) { - UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( (uint32_t)key.size( ), false ) ); - UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Decoder.getProduct( ), false ) ); - UTIL_AppendQByteArray( KeyInfo, UTIL_CreateQByteArray( Decoder.getVal1( ), false ) ); - UTIL_AppendQByteArray( KeyInfo, QByteArray( (char*)Zeros, 4 ) ); + UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( (uint32_t)key.size( ), false ) ); + UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( Decoder.getProduct( ), false ) ); + UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( Decoder.getVal1( ), false ) ); + UTIL_AppendBYTEARRAY( KeyInfo, QByteArray( (char*)Zeros, 4 ) ); size_t Length = Decoder.calculateHash( clientToken, serverToken ); char *buf = new char[Length]; Length = Decoder.getHash( buf ); - UTIL_AppendQByteArray( KeyInfo, QByteArray( buf, Length ) ); + UTIL_AppendBYTEARRAY( KeyInfo, QByteArray( buf, Length ) ); delete [] buf; } diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 1f6a518..27fe37e 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -2275,9 +2275,9 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateQByteArray( (uint16_t)0, false ), UTIL_CreateQByteArray( (uint16_t)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateBYTEARRAY( (uint16_t)0, false ), UTIL_CreateBYTEARRAY( (uint16_t)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); } else { @@ -2297,9 +2297,9 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateQByteArray( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); } } } diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 58cce96..debec4b 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -522,11 +522,11 @@ QByteArray CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) packet.push_back( SID_GETADVLISTEX ); // SID_GETADVLISTEX packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, MapFilter1, 4 ); // Map Filter - UTIL_AppendQByteArray( packet, MapFilter2, 4 ); // Map Filter - UTIL_AppendQByteArray( packet, MapFilter3, 4 ); // Map Filter - UTIL_AppendQByteArray( packet, NumGames, 4 ); // maximum number of games to list - UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendBYTEARRAY( packet, MapFilter1, 4 ); // Map Filter + UTIL_AppendBYTEARRAY( packet, MapFilter2, 4 ); // Map Filter + UTIL_AppendBYTEARRAY( packet, MapFilter3, 4 ); // Map Filter + UTIL_AppendBYTEARRAY( packet, NumGames, 4 ); // maximum number of games to list + UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name packet.push_back( (char)0 ); // Game Password is NULL packet.push_back( (char)0 ); // Game Stats is NULL AssignLength( packet ); @@ -562,11 +562,11 @@ QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) packet.push_back( (char)0 ); // packet length will be assigned later if( channel.size( ) > 0 ) - UTIL_AppendQByteArray( packet, NoCreateJoin, 4 ); // flags for no create join + UTIL_AppendBYTEARRAY( packet, NoCreateJoin, 4 ); // flags for no create join else - UTIL_AppendQByteArray( packet, FirstJoin, 4 ); // flags for first join + UTIL_AppendBYTEARRAY( packet, FirstJoin, 4 ); // flags for first join - UTIL_AppendQByteArrayFast( packet, channel ); + UTIL_AppendBYTEARRAYFast( packet, channel ); AssignLength( packet ); // DEBUG_Print( "SENT SID_JOINCHANNEL" ); // DEBUG_Print( packet ); @@ -580,7 +580,7 @@ QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) packet.push_back( SID_CHATCOMMAND ); // SID_CHATCOMMAND packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, command ); // Message + UTIL_AppendBYTEARRAYFast( packet, command ); // Message AssignLength( packet ); // DEBUG_Print( "SENT SID_CHATCOMMAND" ); // DEBUG_Print( packet ); @@ -596,10 +596,10 @@ QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) packet.push_back( SID_CHECKAD ); // SID_CHECKAD packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? AssignLength( packet ); // DEBUG_Print( "SENT SID_CHECKAD" ); // DEBUG_Print( packet ); @@ -652,15 +652,15 @@ Observers: (mask 0x00700000) cant be combined // make the stat QString QByteArray StatString; - UTIL_AppendQByteArrayFast( StatString, mapFlags ); + UTIL_AppendBYTEARRAYFast( StatString, mapFlags ); StatString.push_back( (char)0 ); - UTIL_AppendQByteArrayFast( StatString, mapWidth ); - UTIL_AppendQByteArrayFast( StatString, mapHeight ); - UTIL_AppendQByteArrayFast( StatString, mapCRC ); - UTIL_AppendQByteArrayFast( StatString, mapPath ); - UTIL_AppendQByteArrayFast( StatString, hostName ); + UTIL_AppendBYTEARRAYFast( StatString, mapWidth ); + UTIL_AppendBYTEARRAYFast( StatString, mapHeight ); + UTIL_AppendBYTEARRAYFast( StatString, mapCRC ); + UTIL_AppendBYTEARRAYFast( StatString, mapPath ); + UTIL_AppendBYTEARRAYFast( StatString, hostName ); StatString.push_back( (char)0 ); - UTIL_AppendQByteArrayFast( StatString, mapSHA1 ); + UTIL_AppendBYTEARRAYFast( StatString, mapSHA1 ); StatString = UTIL_EncodeStatString( StatString ); if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.isEmpty( ) && !hostName.isEmpty( ) && !mapPath.isEmpty( ) && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 && StatString.size( ) < 128 && HostCounterString.size( ) == 8 ) @@ -675,15 +675,15 @@ Observers: (mask 0x00700000) cant be combined packet.push_back( (char)0 ); // State continued... packet.push_back( (char)0 ); // State continued... packet.push_back( (char)0 ); // State continued... - UTIL_AppendQByteArray( packet, upTime, false ); // time since creation - UTIL_AppendQByteArrayFast( packet, mapGameType ); // Game Type, Parameter - UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? - UTIL_AppendQByteArray( packet, CustomGame, 4 ); // Custom Game - UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendBYTEARRAY( packet, upTime, false ); // time since creation + UTIL_AppendBYTEARRAYFast( packet, mapGameType ); // Game Type, Parameter + UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, CustomGame, 4 ); // Custom Game + UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name packet.push_back( (char)0 ); // Game Password is NULL packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate - UTIL_AppendQByteArrayFast( packet, HostCounterString, false ); // Host Counter - UTIL_AppendQByteArrayFast( packet, StatString ); // Stat String + UTIL_AppendBYTEARRAYFast( packet, HostCounterString, false ); // Host Counter + UTIL_AppendBYTEARRAYFast( packet, StatString ); // Stat String packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) AssignLength( packet ); } @@ -705,9 +705,9 @@ QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) packet.push_back( SID_NOTIFYJOIN ); // SID_NOTIFYJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, ProductID, 4 ); // Product ID - UTIL_AppendQByteArray( packet, ProductVersion, 4 ); // Product Version - UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendBYTEARRAY( packet, ProductID, 4 ); // Product ID + UTIL_AppendBYTEARRAY( packet, ProductVersion, 4 ); // Product Version + UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name packet.push_back( (char)0 ); // Game Password is NULL AssignLength( packet ); // DEBUG_Print( "SENT SID_NOTIFYJOIN" ); @@ -725,7 +725,7 @@ QByteArray CBNETProtocol :: SEND_SID_PING( QByteArray pingValue ) packet.push_back( SID_PING ); // SID_PING packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, pingValue ); // Ping Value + UTIL_AppendBYTEARRAYFast( packet, pingValue ); // Ping Value AssignLength( packet ); } else @@ -745,10 +745,10 @@ QByteArray CBNETProtocol :: SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByt packet.push_back( SID_LOGONRESPONSE ); // SID_LOGONRESPONSE packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, clientToken ); // Client Token - UTIL_AppendQByteArrayFast( packet, serverToken ); // Server Token - UTIL_AppendQByteArrayFast( packet, passwordHash ); // Password Hash - UTIL_AppendQByteArrayFast( packet, accountName ); // Account Name + UTIL_AppendBYTEARRAYFast( packet, clientToken ); // Client Token + UTIL_AppendBYTEARRAYFast( packet, serverToken ); // Server Token + UTIL_AppendBYTEARRAYFast( packet, passwordHash ); // Password Hash + UTIL_AppendBYTEARRAYFast( packet, accountName ); // Account Name AssignLength( packet ); // DEBUG_Print( "SENT SID_LOGONRESPONSE" ); // DEBUG_Print( packet ); @@ -762,7 +762,7 @@ QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) packet.push_back( SID_NETGAMEPORT ); // SID_NETGAMEPORT packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, serverPort, false ); // local game server port + UTIL_AppendBYTEARRAY( packet, serverPort, false ); // local game server port AssignLength( packet ); // DEBUG_Print( "SENT SID_NETGAMEPORT" ); // DEBUG_Print( packet ); @@ -785,22 +785,22 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uin packet.push_back( SID_AUTH_INFO ); // SID_AUTH_INFO packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, ProtocolID, 4 ); // Protocol ID - UTIL_AppendQByteArray( packet, PlatformID, 4 ); // Platform ID + UTIL_AppendBYTEARRAY( packet, ProtocolID, 4 ); // Protocol ID + UTIL_AppendBYTEARRAY( packet, PlatformID, 4 ); // Platform ID if( TFT ) - UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) - - UTIL_AppendQByteArray( packet, Version, 4 ); // Version - UTIL_AppendQByteArray( packet, Language, 4 ); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English) - UTIL_AppendQByteArray( packet, LocalIP, 4 ); // Local IP for NAT compatibility - UTIL_AppendQByteArray( packet, TimeZoneBias, 4 ); // Time Zone Bias - UTIL_AppendQByteArray( packet, localeID, false ); // Locale ID - UTIL_AppendQByteArray( packet, localeID, false ); // Language ID (copying the locale ID should be sufficient since we don't care about sublanguages) - UTIL_AppendQByteArrayFast( packet, countryAbbrev ); // Country Abbreviation - UTIL_AppendQByteArrayFast( packet, country ); // Country + UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) + + UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version + UTIL_AppendBYTEARRAY( packet, Language, 4 ); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English) + UTIL_AppendBYTEARRAY( packet, LocalIP, 4 ); // Local IP for NAT compatibility + UTIL_AppendBYTEARRAY( packet, TimeZoneBias, 4 ); // Time Zone Bias + UTIL_AppendBYTEARRAY( packet, localeID, false ); // Locale ID + UTIL_AppendBYTEARRAY( packet, localeID, false ); // Language ID (copying the locale ID should be sufficient since we don't care about sublanguages) + UTIL_AppendBYTEARRAYFast( packet, countryAbbrev ); // Country Abbreviation + UTIL_AppendBYTEARRAYFast( packet, country ); // Country AssignLength( packet ); // DEBUG_Print( "SENT SID_AUTH_INFO" ); // DEBUG_Print( packet ); @@ -824,18 +824,18 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToke packet.push_back( SID_AUTH_CHECK ); // SID_AUTH_CHECK packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, clientToken ); // Client Token - UTIL_AppendQByteArrayFast( packet, exeVersion ); // EXE Version - UTIL_AppendQByteArrayFast( packet, exeVersionHash ); // EXE Version Hash - UTIL_AppendQByteArray( packet, NumKeys, false ); // number of keys in this packet - UTIL_AppendQByteArray( packet, (uint32_t)0, false ); // boolean Using Spawn (32 bit) - UTIL_AppendQByteArrayFast( packet, keyInfoROC ); // ROC Key Info + UTIL_AppendBYTEARRAYFast( packet, clientToken ); // Client Token + UTIL_AppendBYTEARRAYFast( packet, exeVersion ); // EXE Version + UTIL_AppendBYTEARRAYFast( packet, exeVersionHash ); // EXE Version Hash + UTIL_AppendBYTEARRAY( packet, NumKeys, false ); // number of keys in this packet + UTIL_AppendBYTEARRAY( packet, (uint32_t)0, false ); // boolean Using Spawn (32 bit) + UTIL_AppendBYTEARRAYFast( packet, keyInfoROC ); // ROC Key Info if( TFT ) - UTIL_AppendQByteArrayFast( packet, keyInfoTFT ); // TFT Key Info + UTIL_AppendBYTEARRAYFast( packet, keyInfoTFT ); // TFT Key Info - UTIL_AppendQByteArrayFast( packet, exeInfo ); // EXE Info - UTIL_AppendQByteArrayFast( packet, keyOwnerName ); // CD Key Owner Name + UTIL_AppendBYTEARRAYFast( packet, exeInfo ); // EXE Info + UTIL_AppendBYTEARRAYFast( packet, keyOwnerName ); // CD Key Owner Name AssignLength( packet ); } else @@ -856,8 +856,8 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicK packet.push_back( SID_AUTH_ACCOUNTLOGON ); // SID_AUTH_ACCOUNTLOGON packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, clientPublicKey ); // Client Key - UTIL_AppendQByteArrayFast( packet, accountName ); // Account Name + UTIL_AppendBYTEARRAYFast( packet, clientPublicKey ); // Client Key + UTIL_AppendBYTEARRAYFast( packet, accountName ); // Account Name AssignLength( packet ); } else @@ -878,7 +878,7 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPa packet.push_back( SID_AUTH_ACCOUNTLOGONPROOF ); // SID_AUTH_ACCOUNTLOGONPROOF packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, clientPasswordProof ); // Client Password Proof + UTIL_AppendBYTEARRAYFast( packet, clientPasswordProof ); // Client Password Proof AssignLength( packet ); } else @@ -896,7 +896,7 @@ QByteArray CBNETProtocol :: SEND_SID_WARDEN( QByteArray wardenResponse ) packet.push_back( SID_WARDEN ); // SID_WARDEN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArrayFast( packet, wardenResponse ); // warden response + UTIL_AppendBYTEARRAYFast( packet, wardenResponse ); // warden response AssignLength( packet ); // DEBUG_Print( "SENT SID_WARDEN" ); // DEBUG_Print( packet ); @@ -925,7 +925,7 @@ QByteArray CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) packet.push_back( SID_CLANMEMBERLIST ); // SID_CLANMEMBERLIST packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, Cookie, 4 ); // cookie + UTIL_AppendBYTEARRAY( packet, Cookie, 4 ); // cookie AssignLength( packet ); // DEBUG_Print( "SENT SID_CLANMEMBERLIST" ); // DEBUG_Print( packet ); @@ -944,7 +944,7 @@ bool CBNETProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; diff --git a/ghost/bnlsprotocol.cpp b/ghost/bnlsprotocol.cpp index 1c60693..c0ede70 100644 --- a/ghost/bnlsprotocol.cpp +++ b/ghost/bnlsprotocol.cpp @@ -85,12 +85,12 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t see packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( (char)0 ); // BNLS_WARDEN_SEED - UTIL_AppendQByteArray( packet, cookie, false ); // cookie - UTIL_AppendQByteArray( packet, Client, 4 ); // Client - UTIL_AppendQByteArray( packet, (uint16_t)4, false ); // length of seed - UTIL_AppendQByteArray( packet, seed, false ); // seed + UTIL_AppendBYTEARRAY( packet, cookie, false ); // cookie + UTIL_AppendBYTEARRAY( packet, Client, 4 ); // Client + UTIL_AppendBYTEARRAY( packet, (uint16_t)4, false ); // length of seed + UTIL_AppendBYTEARRAY( packet, seed, false ); // seed packet.push_back( (char)0 ); // username is blank - UTIL_AppendQByteArray( packet, (uint16_t)0, false ); // password length + UTIL_AppendBYTEARRAY( packet, (uint16_t)0, false ); // password length // password AssignLength( packet ); return packet; @@ -103,9 +103,9 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray ra packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( 1 ); // BNLS_WARDEN_RAW - UTIL_AppendQByteArray( packet, cookie, false ); // cookie - UTIL_AppendQByteArray( packet, (uint16_t)raw.size( ), false ); // raw length - UTIL_AppendQByteArray( packet, raw ); // raw + UTIL_AppendBYTEARRAY( packet, cookie, false ); // cookie + UTIL_AppendBYTEARRAY( packet, (uint16_t)raw.size( ), false ); // raw length + UTIL_AppendBYTEARRAY( packet, raw ); // raw AssignLength( packet ); return packet; } @@ -127,7 +127,7 @@ bool CBNLSProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 2 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); content[0] = LengthBytes[0]; content[1] = LengthBytes[1]; return true; diff --git a/ghost/game.cpp b/ghost/game.cpp index 7057798..05fd5d2 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -1446,7 +1446,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QByteArray MapHeight; MapHeight.push_back( (char)0 ); MapHeight.push_back( (char)0 ); - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), QHostAddress(IP), Port); } else @@ -1455,7 +1455,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), QHostAddress(IP), Port); } } diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index c70f1f3..259db68 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -253,12 +253,13 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16 else CONSOLE_Print( "[GAME: " + m_GameName + "] attempting to bind to all available addresses" ); - if( m_Socket->listen( QHostAddress(m_GHost->m_BindAddress), m_HostPort ) ) - CONSOLE_Print( "[GAME: " + m_GameName + "] listening on port " + UTIL_ToString( m_Socket->serverPort() ) ); + QHostAddress hostAddr = m_GHost->m_BindAddress == "" ? QHostAddress::Any : QHostAddress(m_GHost->m_BindAddress); + if( m_Socket->listen( hostAddr, m_HostPort ) ) + CONSOLE_Print( "[GAME: " + m_GameName + "] listening on " + hostAddr.toString() + ":" + UTIL_ToString( m_Socket->serverPort() ) ); else { - CONSOLE_Print( "[GAME: " + m_GameName + "] error listening on port " + UTIL_ToString( m_HostPort ) ); - m_Exiting = true; + CONSOLE_Print( "[GAME: " + m_GameName + "] error listening on " + hostAddr.toString() + ":" + UTIL_ToString( m_HostPort ) ); + deleteLater(); } } @@ -553,7 +554,7 @@ void CBaseGame::EventBroadcastTimeout() m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, - UTIL_CreateQByteArray( MapGameType, false ), + UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, @@ -575,7 +576,7 @@ void CBaseGame::EventBroadcastTimeout() // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateQByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ), + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ), hostAddr, 6112 ); } @@ -825,6 +826,8 @@ void CBaseGame::EventNewConnection() if( !NewSocket ) return; + CONSOLE_Print("New socket connected"); + // check the IP blacklist if( m_IPBlackList.find( NewSocket->localAddress().toString() ) != m_IPBlackList.end( ) ) { @@ -873,7 +876,7 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString if( message.size( ) > 254 ) message = message.mid( 0, 254 ); - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateQByteArray( player->GetPID( ) ), 16, QByteArray( ), message ) ); + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateBYTEARRAY( player->GetPID( ) ), 16, QByteArray( ), message ) ); } else { @@ -929,7 +932,7 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) if( message.size( ) > 127 ) message = message.mid( 0, 127 ); - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateQByteArray( (uint32_t)0, false ), message ) ); + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateBYTEARRAY( (uint32_t)0, false ), message ) ); if( m_Replay ) m_Replay->AddChatMessage( fromPID, 32, 0, message ); @@ -1444,7 +1447,7 @@ void CBaseGame :: EventPlayerDeleted() QByteArray CRC; QByteArray Action; Action.push_back( 6 ); - UTIL_AppendQByteArray( Action, SaveGameName ); + UTIL_AppendBYTEARRAY( Action, SaveGameName ); m_Actions.enqueue( new CIncomingAction( player->GetPID( ), CRC, Action ) ); // todotodo: with the new latency system there needs to be a way to send a 0-time action @@ -1699,7 +1702,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateQByteArray((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; } @@ -1727,7 +1730,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateQByteArray((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; } @@ -1974,7 +1977,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateQByteArray((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2353,7 +2356,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateQByteArray((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -3315,15 +3318,15 @@ void CBaseGame :: EventGameStarted( ) // we have to build this now because the map data is going to be deleted QByteArray StatString; - UTIL_AppendQByteArray( StatString, m_Map->GetMapGameFlags( ) ); + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapGameFlags( ) ); StatString.push_back( (char)0 ); - UTIL_AppendQByteArray( StatString, m_Map->GetMapWidth( ) ); - UTIL_AppendQByteArray( StatString, m_Map->GetMapHeight( ) ); - UTIL_AppendQByteArray( StatString, m_Map->GetMapCRC( ) ); - UTIL_AppendQByteArray( StatString, m_Map->GetMapPath( ) ); - UTIL_AppendQByteArray( StatString, "GHost++" ); + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapWidth( ) ); + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapHeight( ) ); + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapCRC( ) ); + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapPath( ) ); + UTIL_AppendBYTEARRAY( StatString, "GHost++" ); StatString.push_back( (char)0 ); - UTIL_AppendQByteArray( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing StatString = UTIL_EncodeStatString( StatString ); m_StatString = StatString; diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index f696039..574cdbc 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -151,7 +151,7 @@ void CGamePlayer::EventConnectionClosed() QByteArray CPotentialPlayer :: GetExternalIP( ) { if( m_Socket ) - return UTIL_CreateQByteArray(m_Socket->localAddress().toIPv4Address()); + return UTIL_CreateBYTEARRAY((uint32_t)m_Socket->localAddress().toIPv4Address()); unsigned char Zeros[] = { 0, 0, 0, 0 }; return QByteArray( (char*)Zeros, 4 ); diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index dba2d72..07bcb01 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -302,7 +302,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) packet.push_back( W3GS_PING_FROM_HOST ); // W3GS_PING_FROM_HOST packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, GetTicks( ), false ); // ping value + UTIL_AppendBYTEARRAY( packet, GetTicks( ), false ); // ping value AssignLength( packet ); // DEBUG_Print( "SENT W3GS_PING_FROM_HOST" ); // DEBUG_Print( packet ); @@ -322,19 +322,21 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArra packet.push_back( W3GS_SLOTINFOJOIN ); // W3GS_SLOTINFOJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length - UTIL_AppendQByteArrayFast( packet, SlotInfo ); // SlotInfo + UTIL_AppendBYTEARRAY( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length + UTIL_AppendBYTEARRAYFast( packet, SlotInfo ); // SlotInfo packet.push_back( PID ); // PID packet.push_back( 2 ); // AF_INET packet.push_back( (char)0 ); // AF_INET continued... - UTIL_AppendQByteArray( packet, port ); // port - UTIL_AppendQByteArrayFast( packet, externalIP ); // external IP - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, port ); // port + UTIL_AppendBYTEARRAYFast( packet, externalIP ); // external IP + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? AssignLength( packet ); } else - CONSOLE_Print( "[GAMEPROTO] invalid parameters passed to SEND_W3GS_SLOTINFOJOIN" ); + CONSOLE_Print( "[GAMEPROTO] invalid parameters passed to SEND_W3GS_SLOTINFOJOIN (" + + QString::number(port.size()) + ": " + port.toHex() + ", " + + QString::number(externalIP.size()) + ": " + externalIP.toHex() + ")"); // DEBUG_Print( "SENT W3GS_SLOTINFOJOIN" ); // DEBUG_Print( packet ); @@ -348,7 +350,7 @@ QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( uint32_t reason ) packet.push_back( W3GS_REJECTJOIN ); // W3GS_REJECTJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, reason, false ); // reason + UTIL_AppendBYTEARRAY( packet, reason, false ); // reason AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REJECTJOIN" ); // DEBUG_Print( packet ); @@ -368,25 +370,25 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString nam packet.push_back( W3GS_PLAYERINFO ); // W3GS_PLAYERINFO packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, PlayerJoinCounter, 4 ); // player join counter + UTIL_AppendBYTEARRAY( packet, PlayerJoinCounter, 4 ); // player join counter packet.push_back( PID ); // PID - UTIL_AppendQByteArrayFast( packet, name ); // player name + UTIL_AppendBYTEARRAYFast( packet, name ); // player name packet.push_back( 1 ); // ??? packet.push_back( (char)0 ); // ??? packet.push_back( 2 ); // AF_INET packet.push_back( (char)0 ); // AF_INET continued... packet.push_back( (char)0 ); // port packet.push_back( (char)0 ); // port continued... - UTIL_AppendQByteArrayFast( packet, externalIP ); // external IP - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAYFast( packet, externalIP ); // external IP + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? packet.push_back( 2 ); // AF_INET packet.push_back( (char)0 ); // AF_INET continued... packet.push_back( (char)0 ); // port packet.push_back( (char)0 ); // port continued... - UTIL_AppendQByteArrayFast( packet, internalIP ); // internal IP - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? - UTIL_AppendQByteArray( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAYFast( packet, internalIP ); // internal IP + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? AssignLength( packet ); } else @@ -408,7 +410,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uin packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( PID ); // PID - UTIL_AppendQByteArray( packet, leftCode, false ); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) + UTIL_AppendBYTEARRAY( packet, leftCode, false ); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) AssignLength( packet ); } else @@ -448,8 +450,8 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, uint packet.push_back( W3GS_SLOTINFO ); // W3GS_SLOTINFO packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length - UTIL_AppendQByteArrayFast( packet, SlotInfo ); // SlotInfo + UTIL_AppendBYTEARRAY( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length + UTIL_AppendBYTEARRAYFast( packet, SlotInfo ); // SlotInfo AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SLOTINFO" ); // DEBUG_Print( packet ); @@ -489,7 +491,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue packet.push_back( W3GS_INCOMING_ACTION ); // W3GS_INCOMING_ACTION packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, sendInterval, false ); // send interval + UTIL_AppendBYTEARRAY( packet, sendInterval, false ); // send interval // create subpacket @@ -502,19 +504,19 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue CIncomingAction *Action = actions.front( ); actions.dequeue( ); subpacket.push_back( Action->GetPID( ) ); - UTIL_AppendQByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendQByteArrayFast( subpacket, *Action->GetAction( ) ); + UTIL_AppendBYTEARRAY( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); } // calculate crc (we only care about the first 2 bytes though) - QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( subpacket ), false ); + QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC( subpacket ), false ); crc32.resize( 2 ); // finish subpacket - UTIL_AppendQByteArrayFast( packet, crc32 ); // crc - UTIL_AppendQByteArrayFast( packet, subpacket ); // subpacket + UTIL_AppendBYTEARRAYFast( packet, crc32 ); // crc + UTIL_AppendBYTEARRAYFast( packet, subpacket ); // subpacket } AssignLength( packet ); @@ -534,11 +536,11 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( toPIDs.size( ) ); // number of receivers - UTIL_AppendQByteArrayFast( packet, toPIDs ); // receivers + UTIL_AppendBYTEARRAYFast( packet, toPIDs ); // receivers packet.push_back( fromPID ); // sender packet.push_back( flag ); // flag - UTIL_AppendQByteArrayFast( packet, flagExtra ); // extra flag - UTIL_AppendQByteArrayFast( packet, message ); // message + UTIL_AppendBYTEARRAYFast( packet, flagExtra ); // extra flag + UTIL_AppendBYTEARRAYFast( packet, message ); // message AssignLength( packet ); } else @@ -584,7 +586,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, if( !(*i)->GetFinishedLoading( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendQByteArray( packet, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( packet, (uint32_t)0, false ); } } else @@ -592,7 +594,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, if( (*i)->GetLagging( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendQByteArray( packet, GetTicks( ) - (*i)->GetStartedLaggingTicks( ), false ); + UTIL_AppendBYTEARRAY( packet, GetTicks( ) - (*i)->GetStartedLaggingTicks( ), false ); } } } @@ -617,9 +619,9 @@ QByteArray CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadIn packet.push_back( player->GetPID( ) ); if( loadInGame ) - UTIL_AppendQByteArray( packet, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( packet, (uint32_t)0, false ); else - UTIL_AppendQByteArray( packet, GetTicks( ) - player->GetStartedLaggingTicks( ), false ); + UTIL_AppendBYTEARRAY( packet, GetTicks( ) - player->GetStartedLaggingTicks( ), false ); AssignLength( packet ); // DEBUG_Print( "SENT W3GS_STOP_LAG" ); @@ -641,12 +643,12 @@ QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Ve packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) - UTIL_AppendQByteArray( packet, Version, 4 ); // Version - UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version + UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SEARCHGAME" ); // DEBUG_Print( packet ); @@ -668,13 +670,13 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers // make the stat QString QByteArray StatString; - UTIL_AppendQByteArrayFast( StatString, mapFlags ); + UTIL_AppendBYTEARRAYFast( StatString, mapFlags ); StatString.push_back( (char)0 ); - UTIL_AppendQByteArrayFast( StatString, mapWidth ); - UTIL_AppendQByteArrayFast( StatString, mapHeight ); - UTIL_AppendQByteArrayFast( StatString, mapCRC ); - UTIL_AppendQByteArrayFast( StatString, mapPath ); - UTIL_AppendQByteArrayFast( StatString, hostName ); + UTIL_AppendBYTEARRAYFast( StatString, mapWidth ); + UTIL_AppendBYTEARRAYFast( StatString, mapHeight ); + UTIL_AppendBYTEARRAYFast( StatString, mapCRC ); + UTIL_AppendBYTEARRAYFast( StatString, mapPath ); + UTIL_AppendBYTEARRAYFast( StatString, hostName ); StatString.push_back( (char)0 ); StatString = UTIL_EncodeStatString( StatString ); @@ -686,23 +688,23 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) - UTIL_AppendQByteArray( packet, Version, 4 ); // Version - UTIL_AppendQByteArray( packet, hostCounter, false ); // Host Counter - UTIL_AppendQByteArray( packet, Unknown1, 4 ); // ??? (this varies wildly even between two identical games created one after another) - UTIL_AppendQByteArrayFast( packet, gameName ); // Game Name + UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version + UTIL_AppendBYTEARRAY( packet, hostCounter, false ); // Host Counter + UTIL_AppendBYTEARRAY( packet, Unknown1, 4 ); // ??? (this varies wildly even between two identical games created one after another) + UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name packet.push_back( (char)0 ); // ??? (maybe game password) - UTIL_AppendQByteArrayFast( packet, StatString ); // Stat String + UTIL_AppendBYTEARRAYFast( packet, StatString ); // Stat String packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) - UTIL_AppendQByteArray( packet, slotsTotal, false ); // Slots Total - UTIL_AppendQByteArrayFast( packet, mapGameType ); // Game Type - UTIL_AppendQByteArray( packet, Unknown2, 4 ); // ??? - UTIL_AppendQByteArray( packet, slotsOpen, false ); // Slots Open - UTIL_AppendQByteArray( packet, upTime, false ); // time since creation - UTIL_AppendQByteArray( packet, port, false ); // port + UTIL_AppendBYTEARRAY( packet, slotsTotal, false ); // Slots Total + UTIL_AppendBYTEARRAYFast( packet, mapGameType ); // Game Type + UTIL_AppendBYTEARRAY( packet, Unknown2, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, slotsOpen, false ); // Slots Open + UTIL_AppendBYTEARRAY( packet, upTime, false ); // time since creation + UTIL_AppendBYTEARRAY( packet, port, false ); // port AssignLength( packet ); } else @@ -727,12 +729,12 @@ QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Ve packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendQByteArray( packet, ProductID_TFT, 4 ); // Product ID (TFT) + UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) else - UTIL_AppendQByteArray( packet, ProductID_ROC, 4 ); // Product ID (ROC) + UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) - UTIL_AppendQByteArray( packet, Version, 4 ); // Version - UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter + UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version + UTIL_AppendBYTEARRAY( packet, HostCounter, 4 ); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_CREATEGAME" ); // DEBUG_Print( packet ); @@ -748,9 +750,9 @@ QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t pl packet.push_back( W3GS_REFRESHGAME ); // W3GS_REFRESHGAME packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter - UTIL_AppendQByteArray( packet, players, false ); // Players - UTIL_AppendQByteArray( packet, playerSlots, false ); // Player Slots + UTIL_AppendBYTEARRAY( packet, HostCounter, 4 ); // Host Counter + UTIL_AppendBYTEARRAY( packet, players, false ); // Players + UTIL_AppendBYTEARRAY( packet, playerSlots, false ); // Player Slots AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REFRESHGAME" ); // DEBUG_Print( packet ); @@ -766,7 +768,7 @@ QByteArray CGameProtocol :: SEND_W3GS_DECREATEGAME( ) packet.push_back( W3GS_DECREATEGAME ); // W3GS_DECREATEGAME packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, HostCounter, 4 ); // Host Counter + UTIL_AppendBYTEARRAY( packet, HostCounter, 4 ); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_DECREATEGAME" ); // DEBUG_Print( packet ); @@ -785,12 +787,12 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapS packet.push_back( W3GS_MAPCHECK ); // W3GS_MAPCHECK packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? - UTIL_AppendQByteArrayFast( packet, mapPath ); // map path - UTIL_AppendQByteArrayFast( packet, mapSize ); // map size - UTIL_AppendQByteArrayFast( packet, mapInfo ); // map info - UTIL_AppendQByteArrayFast( packet, mapCRC ); // map crc - UTIL_AppendQByteArrayFast( packet, mapSHA1 ); // map sha1 + UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? + UTIL_AppendBYTEARRAYFast( packet, mapPath ); // map path + UTIL_AppendBYTEARRAYFast( packet, mapSize ); // map size + UTIL_AppendBYTEARRAYFast( packet, mapInfo ); // map info + UTIL_AppendBYTEARRAYFast( packet, mapCRC ); // map crc + UTIL_AppendBYTEARRAYFast( packet, mapSHA1 ); // map sha1 AssignLength( packet ); } else @@ -810,7 +812,7 @@ QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) packet.push_back( W3GS_STARTDOWNLOAD ); // W3GS_STARTDOWNLOAD packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? packet.push_back( fromPID ); // from PID AssignLength( packet ); // DEBUG_Print( "SENT W3GS_STARTDOWNLOAD" ); @@ -832,8 +834,8 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( toPID ); // to PID packet.push_back( fromPID ); // from PID - UTIL_AppendQByteArray( packet, Unknown, 4 ); // ??? - UTIL_AppendQByteArray( packet, start, false ); // start position + UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? + UTIL_AppendBYTEARRAY( packet, start, false ); // start position // calculate end position (don't send more than 1442 map bytes in one packet) @@ -844,13 +846,13 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c // calculate crc - QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC( mapData->mid(start, End - start) ), false ); - UTIL_AppendQByteArrayFast( packet, crc32 ); + QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC( mapData->mid(start, End - start) ), false ); + UTIL_AppendBYTEARRAYFast( packet, crc32 ); // map data QByteArray Data = mapData->mid(start, End - start).toUtf8(); - UTIL_AppendQByteArrayFast( packet, Data ); + UTIL_AppendBYTEARRAYFast( packet, Data ); AssignLength( packet ); } else @@ -882,19 +884,19 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueueGetPID( ) ); - UTIL_AppendQByteArray( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendQByteArrayFast( subpacket, *Action->GetAction( ) ); + UTIL_AppendBYTEARRAY( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); } // calculate crc (we only care about the first 2 bytes though) - QByteArray crc32 = UTIL_CreateQByteArray( m_GHost->m_CRC->FullCRC(subpacket), false ); + QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC(subpacket), false ); crc32.resize( 2 ); // finish subpacket - UTIL_AppendQByteArrayFast( packet, crc32 ); // crc - UTIL_AppendQByteArrayFast( packet, subpacket ); // subpacket + UTIL_AppendBYTEARRAYFast( packet, crc32 ); // crc + UTIL_AppendBYTEARRAYFast( packet, subpacket ); // subpacket } AssignLength( packet ); @@ -915,7 +917,7 @@ bool CGameProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -950,9 +952,9 @@ QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, uint32_t SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots for( int i = 0; i < lslots.size( ); i++ ) - UTIL_AppendQByteArray( SlotInfo, lslots[i].GetQByteArray( ) ); + UTIL_AppendBYTEARRAY( SlotInfo, lslots[i].GetQByteArray( ) ); - UTIL_AppendQByteArray( SlotInfo, randomSeed, false ); // random seed + UTIL_AppendBYTEARRAY( SlotInfo, randomSeed, false ); // random seed SlotInfo.push_back( layoutStyle ); // LayoutStyle (0 = melee, 1 = custom forces, 3 = custom forces + fixed player settings) SlotInfo.push_back( playerSlots ); // number of player slots (non observer) return SlotInfo; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 1ad4beb..fba57c9 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -124,7 +124,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) for (int i = 0; i < info.addresses().size(); i++) { CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + info.addresses().at(i).toString() + "]" ); - m_LocalAddresses.push_back( UTIL_CreateQByteArray( (uint32_t)info.addresses().at(i).toIPv4Address() ) ); + m_LocalAddresses.push_back( UTIL_CreateBYTEARRAY( (uint32_t)info.addresses().at(i).toIPv4Address() ) ); } m_Language = NULL; diff --git a/ghost/gpsprotocol.cpp b/ghost/gpsprotocol.cpp index eb36a90..cea454f 100644 --- a/ghost/gpsprotocol.cpp +++ b/ghost/gpsprotocol.cpp @@ -49,7 +49,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_INIT( uint32_t version ) packet.push_back( GPS_INIT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendQByteArray( packet, version, false ); + UTIL_AppendBYTEARRAY( packet, version, false ); AssignLength( packet ); return packet; } @@ -62,8 +62,8 @@ QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reco packet.push_back( (char)0 ); packet.push_back( (char)0 ); packet.push_back( PID ); - UTIL_AppendQByteArray( packet, reconnectKey, false ); - UTIL_AppendQByteArray( packet, lastPacket, false ); + UTIL_AppendBYTEARRAY( packet, reconnectKey, false ); + UTIL_AppendBYTEARRAY( packet, lastPacket, false ); AssignLength( packet ); return packet; } @@ -75,7 +75,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_ACK( uint32_t lastPacket ) packet.push_back( GPS_ACK ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendQByteArray( packet, lastPacket, false ); + UTIL_AppendBYTEARRAY( packet, lastPacket, false ); AssignLength( packet ); return packet; } @@ -87,9 +87,9 @@ QByteArray CGPSProtocol :: SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char packet.push_back( GPS_INIT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendQByteArray( packet, reconnectPort, false ); + UTIL_AppendBYTEARRAY( packet, reconnectPort, false ); packet.push_back( PID ); - UTIL_AppendQByteArray( packet, reconnectKey, false ); + UTIL_AppendBYTEARRAY( packet, reconnectKey, false ); packet.push_back( numEmptyActions ); AssignLength( packet ); return packet; @@ -102,7 +102,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( uint32_t lastPacket ) packet.push_back( GPS_RECONNECT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendQByteArray( packet, lastPacket, false ); + UTIL_AppendBYTEARRAY( packet, lastPacket, false ); AssignLength( packet ); return packet; } @@ -114,7 +114,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_ACK( uint32_t lastPacket ) packet.push_back( GPS_ACK ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendQByteArray( packet, lastPacket, false ); + UTIL_AppendBYTEARRAY( packet, lastPacket, false ); AssignLength( packet ); return packet; } @@ -126,7 +126,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_REJECT( uint32_t reason ) packet.push_back( GPS_REJECT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendQByteArray( packet, reason, false ); + UTIL_AppendBYTEARRAY( packet, reason, false ); AssignLength( packet ); return packet; } @@ -143,7 +143,7 @@ bool CGPSProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateQByteArray( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; diff --git a/ghost/map.cpp b/ghost/map.cpp index b055164..6fd101e 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -158,7 +158,7 @@ QByteArray CMap :: GetMapGameFlags( ) if( m_MapFlags & MAPFLAG_RANDOMRACES ) GameFlags |= 0x04000000; - return UTIL_CreateQByteArray( GameFlags, false ); + return UTIL_CreateBYTEARRAY( GameFlags, false ); } uint32_t CMap :: GetMapGameType( ) @@ -292,12 +292,12 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // calculate map_size - MapSize = UTIL_CreateQByteArray( (uint32_t)m_MapData.size( ), false ); + MapSize = UTIL_CreateBYTEARRAY( (uint32_t)m_MapData.size( ), false ); CONSOLE_Print( "[MAP] calculated map_size = " + UTIL_QByteArrayToDecString( MapSize ) ); // calculate map_info (this is actually the CRC) - MapInfo = UTIL_CreateQByteArray( (uint32_t)m_GHost->m_CRC->FullCRC( m_MapData ), false ); + MapInfo = UTIL_CreateBYTEARRAY( (uint32_t)m_GHost->m_CRC->FullCRC( m_MapData ), false ); CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_QByteArrayToDecString( MapInfo ) ); // calculate map_crc (this is not the CRC) and map_sha1 @@ -456,7 +456,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( !FoundScript ) CONSOLE_Print( "[MAP] couldn't find war3map.j or scripts\\war3map.j in MPQ file, calculated map_crc/sha1 is probably wrong" ); - MapCRC = UTIL_CreateQByteArray( Val, false ); + MapCRC = UTIL_CreateBYTEARRAY( Val, false ); CONSOLE_Print( "[MAP] calculated map_crc = " + UTIL_QByteArrayToDecString( MapCRC ) ); m_GHost->m_SHA->Final( ); @@ -656,9 +656,9 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) MapOptions = RawMapFlags & ( MAPOPT_MELEE | MAPOPT_FIXEDPLAYERSETTINGS | MAPOPT_CUSTOMFORCES ); CONSOLE_Print( "[MAP] calculated map_options = " + UTIL_ToString( MapOptions ) ); - MapWidth = UTIL_CreateQByteArray( (uint16_t)RawMapWidth, false ); + MapWidth = UTIL_CreateBYTEARRAY( (uint16_t)RawMapWidth, false ); CONSOLE_Print( "[MAP] calculated map_width = " + UTIL_QByteArrayToDecString( MapWidth ) ); - MapHeight = UTIL_CreateQByteArray( (uint16_t)RawMapHeight, false ); + MapHeight = UTIL_CreateBYTEARRAY( (uint16_t)RawMapHeight, false ); CONSOLE_Print( "[MAP] calculated map_height = " + UTIL_QByteArrayToDecString( MapHeight ) ); MapNumPlayers = RawMapNumPlayers - ClosedSlots; CONSOLE_Print( "[MAP] calculated map_numplayers = " + UTIL_ToString( MapNumPlayers ) ); diff --git a/ghost/packed.cpp b/ghost/packed.cpp index 1654643..e32dbcf 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -325,12 +325,12 @@ void CPacked :: Compress( bool TFT ) uint32_t HeaderCompressedSize = HeaderSize + CompressedSize + CompressedBlocks.size( ) * 8; uint32_t HeaderVersion = 1; QByteArray Header; - UTIL_AppendQByteArray( Header, "Warcraft III recorded game\x01A" ); - UTIL_AppendQByteArray( Header, HeaderSize, false ); - UTIL_AppendQByteArray( Header, HeaderCompressedSize, false ); - UTIL_AppendQByteArray( Header, HeaderVersion, false ); - UTIL_AppendQByteArray( Header, (uint32_t)m_Decompressed.size( ), false ); - UTIL_AppendQByteArray( Header, (uint32_t)CompressedBlocks.size( ), false ); + UTIL_AppendBYTEARRAY( Header, "Warcraft III recorded game\x01A" ); + UTIL_AppendBYTEARRAY( Header, HeaderSize, false ); + UTIL_AppendBYTEARRAY( Header, HeaderCompressedSize, false ); + UTIL_AppendBYTEARRAY( Header, HeaderVersion, false ); + UTIL_AppendBYTEARRAY( Header, (uint32_t)m_Decompressed.size( ), false ); + UTIL_AppendBYTEARRAY( Header, (uint32_t)CompressedBlocks.size( ), false ); if( TFT ) { @@ -347,16 +347,16 @@ void CPacked :: Compress( bool TFT ) Header.push_back( 'W' ); } - UTIL_AppendQByteArray( Header, m_War3Version, false ); - UTIL_AppendQByteArray( Header, m_BuildNumber, false ); - UTIL_AppendQByteArray( Header, m_Flags, false ); - UTIL_AppendQByteArray( Header, m_ReplayLength, false ); + UTIL_AppendBYTEARRAY( Header, m_War3Version, false ); + UTIL_AppendBYTEARRAY( Header, m_BuildNumber, false ); + UTIL_AppendBYTEARRAY( Header, m_Flags, false ); + UTIL_AppendBYTEARRAY( Header, m_ReplayLength, false ); // append zero header CRC // the header CRC is calculated over the entire header with itself set to zero // we'll overwrite the zero header CRC after we calculate it - UTIL_AppendQByteArray( Header, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( Header, (uint32_t)0, false ); // calculate header CRC @@ -366,7 +366,7 @@ void CPacked :: Compress( bool TFT ) // overwrite the (currently zero) header CRC with the calculated CRC Header.remove(Header.size() - 4, 4); - UTIL_AppendQByteArray( Header, CRC, false ); + UTIL_AppendBYTEARRAY( Header, CRC, false ); // append header @@ -377,12 +377,12 @@ void CPacked :: Compress( bool TFT ) for( QVector :: const_iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { QByteArray BlockHeader; - UTIL_AppendQByteArray( BlockHeader, (uint16_t)(*i).size( ), false ); - UTIL_AppendQByteArray( BlockHeader, (uint16_t)8192, false ); + UTIL_AppendBYTEARRAY( BlockHeader, (uint16_t)(*i).size( ), false ); + UTIL_AppendBYTEARRAY( BlockHeader, (uint16_t)8192, false ); // append zero block header CRC - UTIL_AppendQByteArray( BlockHeader, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( BlockHeader, (uint32_t)0, false ); // calculate block header CRC @@ -395,7 +395,7 @@ void CPacked :: Compress( bool TFT ) // overwrite the block header CRC with the calculated CRC BlockHeader.remove( BlockHeader.size() - 4, 4 ); - UTIL_AppendQByteArray( BlockHeader, BlockCRC, false ); + UTIL_AppendBYTEARRAY( BlockHeader, BlockCRC, false ); // append block header and data diff --git a/ghost/replay.cpp b/ghost/replay.cpp index a73bc87..579e54f 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -48,10 +48,10 @@ void CReplay :: AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t resul { QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); - UTIL_AppendQByteArray( Block, reason, false ); + UTIL_AppendBYTEARRAY( Block, reason, false ); Block.push_back( PID ); - UTIL_AppendQByteArray( Block, result, false ); - UTIL_AppendQByteArray( Block, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Block, result, false ); + UTIL_AppendBYTEARRAY( Block, (uint32_t)1, false ); m_CompiledBlocks += Block; } @@ -59,10 +59,10 @@ void CReplay :: AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, u { QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); - UTIL_AppendQByteArray( Block, reason, false ); + UTIL_AppendBYTEARRAY( Block, reason, false ); Block.push_back( PID ); - UTIL_AppendQByteArray( Block, result, false ); - UTIL_AppendQByteArray( Block, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Block, result, false ); + UTIL_AppendBYTEARRAY( Block, (uint32_t)1, false ); m_LoadingBlocks.enqueue( Block ); } @@ -70,21 +70,21 @@ void CReplay :: AddTimeSlot2( QQueue actions ) { QByteArray Block; Block.push_back( REPLAY_TIMESLOT2 ); - UTIL_AppendQByteArray( Block, (uint16_t)0, false ); - UTIL_AppendQByteArray( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendQByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendQByteArrayFast( Block, *Action->GetAction( ) ); + UTIL_AppendBYTEARRAY( Block, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAYFast( Block, *Action->GetAction( ) ); } // assign length - QByteArray LengthBytes = UTIL_CreateQByteArray( (uint16_t)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = UTIL_CreateBYTEARRAY((uint16_t)( Block.size( ) - 3 ), false ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -94,21 +94,21 @@ void CReplay :: AddTimeSlot( uint16_t timeIncrement, QQueue a { QByteArray Block; Block.push_back( REPLAY_TIMESLOT ); - UTIL_AppendQByteArray( Block, (uint16_t)0, false ); - UTIL_AppendQByteArray( Block, timeIncrement, false ); + UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, timeIncrement, false ); while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendQByteArray( Block, (uint16_t)Action->GetAction( )->size( ), false ); - UTIL_AppendQByteArrayFast( Block, *Action->GetAction( ) ); + UTIL_AppendBYTEARRAY( Block, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAYFast( Block, *Action->GetAction( ) ); } // assign length - QByteArray LengthBytes = UTIL_CreateQByteArray( (uint16_t)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = UTIL_CreateBYTEARRAY((uint16_t)( Block.size( ) - 3 ), false ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -120,14 +120,14 @@ void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, uint32_t QByteArray Block; Block.push_back( REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendQByteArray( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); Block.push_back( flags ); - UTIL_AppendQByteArray( Block, chatMode, false ); - UTIL_AppendQByteArrayFast( Block, message ); + UTIL_AppendBYTEARRAY( Block, chatMode, false ); + UTIL_AppendBYTEARRAYFast( Block, message ); // assign length - QByteArray LengthBytes = UTIL_CreateQByteArray( (uint16_t)( Block.size( ) - 4 ), false ); + QByteArray LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)( Block.size( ) - 4 ), false ); Block[2] = LengthBytes[0]; Block[3] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -155,15 +155,15 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 Replay.push_back( (char)0 ); // Unknown (4.0) Replay.push_back( (char)0 ); // Host RecordID (4.1) Replay.push_back( (char)m_HostPID ); // Host PlayerID (4.1) - UTIL_AppendQByteArrayFast( Replay, m_HostName ); // Host PlayerName (4.1) + UTIL_AppendBYTEARRAYFast( Replay, m_HostName ); // Host PlayerName (4.1) Replay.push_back( (char)1 ); // Host AdditionalSize (4.1) Replay.push_back( (char)0 ); // Host AdditionalData (4.1) - UTIL_AppendQByteArrayFast( Replay, gameName ); // GameName (4.2) + UTIL_AppendBYTEARRAYFast( Replay, gameName ); // GameName (4.2) Replay.push_back( (char)0 ); // Null (4.0) - UTIL_AppendQByteArrayFast( Replay, statString ); // StatString (4.3) - UTIL_AppendQByteArray( Replay, (uint32_t)m_Slots.size( ), false ); // PlayerCount (4.6) - UTIL_AppendQByteArray( Replay, m_MapGameType, false ); // GameType (4.7) - UTIL_AppendQByteArray( Replay, LanguageID, false ); // LanguageID (4.8) + UTIL_AppendBYTEARRAYFast( Replay, statString ); // StatString (4.3) + UTIL_AppendBYTEARRAY( Replay, (uint32_t)m_Slots.size( ), false ); // PlayerCount (4.6) + UTIL_AppendBYTEARRAY( Replay, m_MapGameType, false ); // GameType (4.7) + UTIL_AppendBYTEARRAY( Replay, LanguageID, false ); // LanguageID (4.8) // PlayerList (4.9) @@ -173,43 +173,43 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 { Replay.push_back( 22 ); // Player RecordID (4.1) Replay.push_back( (*i).first ); // Player PlayerID (4.1) - UTIL_AppendQByteArrayFast( Replay, (*i).second ); // Player PlayerName (4.1) + UTIL_AppendBYTEARRAYFast( Replay, (*i).second ); // Player PlayerName (4.1) Replay.push_back( 1 ); // Player AdditionalSize (4.1) Replay.push_back( (char)0 ); // Player AdditionalData (4.1) - UTIL_AppendQByteArray( Replay, (uint32_t)0, false ); // Unknown + UTIL_AppendBYTEARRAY( Replay, (uint32_t)0, false ); // Unknown } } // GameStartRecord (4.10) Replay.push_back( 25 ); // RecordID (4.10) - UTIL_AppendQByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) + UTIL_AppendBYTEARRAY( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) Replay.push_back( m_Slots.size( ) ); // NumSlots (4.10) for( unsigned char i = 0; i < m_Slots.size( ); i++ ) - UTIL_AppendQByteArray( Replay, m_Slots[i].GetQByteArray( ) ); + UTIL_AppendBYTEARRAY( Replay, m_Slots[i].GetQByteArray( ) ); - UTIL_AppendQByteArray( Replay, m_RandomSeed, false ); // RandomSeed (4.10) + UTIL_AppendBYTEARRAY( Replay, m_RandomSeed, false ); // RandomSeed (4.10) Replay.push_back( m_SelectMode ); // SelectMode (4.10) Replay.push_back( m_StartSpotCount ); // StartSpotCount (4.10) // ReplayData (5.0) Replay.push_back( REPLAY_FIRSTSTARTBLOCK ); - UTIL_AppendQByteArray( Replay, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Replay, (uint32_t)1, false ); Replay.push_back( REPLAY_SECONDSTARTBLOCK ); - UTIL_AppendQByteArray( Replay, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Replay, (uint32_t)1, false ); // leavers during loading need to be stored between the second and third start blocks while( !m_LoadingBlocks.isEmpty( ) ) { - UTIL_AppendQByteArray( Replay, m_LoadingBlocks.front( ) ); + UTIL_AppendBYTEARRAY( Replay, m_LoadingBlocks.front( ) ); m_LoadingBlocks.dequeue( ); } Replay.push_back( REPLAY_THIRDSTARTBLOCK ); - UTIL_AppendQByteArray( Replay, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Replay, (uint32_t)1, false ); // done @@ -394,7 +394,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) { unsigned char SlotData[9]; READB( ISS, SlotData, 9 ); - QByteArray SlotDataBA = UTIL_CreateQByteArray( SlotData, 9 ); + QByteArray SlotDataBA = UTIL_CreateBYTEARRAY( SlotData, 9 ); m_Slots.push_back( CGameSlot( SlotDataBA ) ); } @@ -463,7 +463,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) READB( ISS, GarbageData, 13 ); QByteArray LoadingBlock; LoadingBlock.push_back( Garbage1 ); - UTIL_AppendQByteArray( LoadingBlock, GarbageData, 13 ); + UTIL_AppendBYTEARRAY( LoadingBlock, GarbageData, 13 ); m_LoadingBlocks.enqueue( LoadingBlock ); } else if( Garbage1 == CReplay :: REPLAY_THIRDSTARTBLOCK ) @@ -508,7 +508,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) QByteArray Block; Block.push_back( CReplay :: REPLAY_LEAVEGAME ); - UTIL_AppendQByteArray( Block, GarbageData, 13 ); + UTIL_AppendBYTEARRAY( Block, GarbageData, 13 ); m_Blocks.enqueue( Block ); } else if( Garbage1 == CReplay :: REPLAY_TIMESLOT ) @@ -524,8 +524,8 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) QByteArray Block; Block.push_back( CReplay :: REPLAY_TIMESLOT ); - UTIL_AppendQByteArray( Block, BlockSize, false ); - UTIL_AppendQByteArray( Block, GarbageData, BlockSize ); + UTIL_AppendBYTEARRAY( Block, BlockSize, false ); + UTIL_AppendBYTEARRAY( Block, GarbageData, BlockSize ); m_Blocks.enqueue( Block ); } else if( Garbage1 == CReplay :: REPLAY_CHATMESSAGE ) @@ -549,8 +549,8 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) QByteArray Block; Block.push_back( CReplay :: REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendQByteArray( Block, BlockSize, false ); - UTIL_AppendQByteArray( Block, GarbageData, BlockSize ); + UTIL_AppendBYTEARRAY( Block, BlockSize, false ); + UTIL_AppendBYTEARRAY( Block, GarbageData, BlockSize ); m_Blocks.enqueue( Block ); } else if( Garbage1 == CReplay :: REPLAY_CHECKSUM ) diff --git a/ghost/util.cpp b/ghost/util.cpp index adef36b..c3a94e5 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -24,14 +24,14 @@ #include #include -QByteArray UTIL_CreateQByteArray( unsigned char c ) +QByteArray UTIL_CreateBYTEARRAY( unsigned char c ) { QByteArray result; result.push_back( c ); return result; } -QByteArray UTIL_CreateQByteArray( uint16_t i, bool reverse ) +QByteArray UTIL_CreateBYTEARRAY( quint16 i, bool reverse ) { QByteArray result; @@ -46,7 +46,7 @@ QByteArray UTIL_CreateQByteArray( uint16_t i, bool reverse ) return result; } -QByteArray UTIL_CreateQByteArray( uint32_t i, bool reverse ) +QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ) { QByteArray result; @@ -110,22 +110,22 @@ QString UTIL_QByteArrayToHexString( QByteArray b ) return QString::fromAscii(b.toHex()); } -void UTIL_AppendQByteArray( QByteArray &b, QByteArray append ) +void UTIL_AppendBYTEARRAY( QByteArray &b, QByteArray append ) { b.append(append); } -void UTIL_AppendQByteArrayFast( QByteArray &b, QByteArray &append ) +void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ) { b.append(append); } -void UTIL_AppendQByteArray( QByteArray &b, unsigned char *a, int size ) +void UTIL_AppendBYTEARRAY( QByteArray &b, unsigned char *a, int size ) { b.append((char*)a, size); } -void UTIL_AppendQByteArray( QByteArray &b, QString append, bool terminator ) +void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator ) { b.append(append); @@ -133,7 +133,7 @@ void UTIL_AppendQByteArray( QByteArray &b, QString append, bool terminator ) b.push_back( (char)0 ); } -void UTIL_AppendQByteArrayFast( QByteArray &b, QString &append, bool terminator ) +void UTIL_AppendBYTEARRAYFast( QByteArray &b, QString &append, bool terminator ) { b.append(append); @@ -141,14 +141,14 @@ void UTIL_AppendQByteArrayFast( QByteArray &b, QString &append, bool terminator b.push_back( (char)0 ); } -void UTIL_AppendQByteArray( QByteArray &b, uint16_t i, bool reverse ) +void UTIL_AppendBYTEARRAY( QByteArray &b, quint16 i, bool reverse ) { - b.append( UTIL_CreateQByteArray( i, reverse ) ); + b.append( UTIL_CreateBYTEARRAY( i, reverse ) ); } -void UTIL_AppendQByteArray( QByteArray &b, uint32_t i, bool reverse ) +void UTIL_AppendBYTEARRAY( QByteArray &b, quint32 i, bool reverse ) { - b.append( UTIL_CreateQByteArray( i, reverse ) ); + b.append( UTIL_CreateBYTEARRAY( i, reverse ) ); } QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ) diff --git a/ghost/util.h b/ghost/util.h index eec1f78..e0c3893 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -27,19 +27,19 @@ // byte arrays -QByteArray UTIL_CreateQByteArray( unsigned char c ); -QByteArray UTIL_CreateQByteArray( uint16_t i, bool reverse ); -QByteArray UTIL_CreateQByteArray( uint32_t i, bool reverse ); +QByteArray UTIL_CreateBYTEARRAY( unsigned char c ); +QByteArray UTIL_CreateBYTEARRAY( quint16 i, bool reverse ); +QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ); uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start = 0 ); uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start = 0 ); QString UTIL_QByteArrayToDecString( QByteArray b ); QString UTIL_QByteArrayToHexString( QByteArray b ); -void UTIL_AppendQByteArrayFast( QByteArray &b, QByteArray &append ); -void UTIL_AppendQByteArray( QByteArray &b, unsigned char *a, int size ); -void UTIL_AppendQByteArray( QByteArray &b, QString append, bool terminator = true ); -void UTIL_AppendQByteArrayFast( QByteArray &b, QString &append, bool terminator = true ); -void UTIL_AppendQByteArray( QByteArray &b, uint16_t i, bool reverse ); -void UTIL_AppendQByteArray( QByteArray &b, uint32_t i, bool reverse ); +void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ); +void UTIL_AppendBYTEARRAY( QByteArray &b, unsigned char *a, int size ); +void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator = true ); +void UTIL_AppendBYTEARRAYFast( QByteArray &b, QString &append, bool terminator = true ); +void UTIL_AppendBYTEARRAY( QByteArray &b, quint16 i, bool reverse ); +void UTIL_AppendBYTEARRAY( QByteArray &b, quint32 i, bool reverse ); QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ); unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ); QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ); diff --git a/mapcfgs/wormwar.cfg b/mapcfgs/wormwar.cfg index ac77c84..e2ffc31 100644 --- a/mapcfgs/wormwar.cfg +++ b/mapcfgs/wormwar.cfg @@ -88,7 +88,7 @@ map_height = 84 0 # map information (if incorrect it will force downloading for players and kick from the game lobby) -map_size = 201 213 5 0 +//map_size = 201 213 5 0 map_info = 206 105 219 80 map_crc = 15 15 71 22 map_sha1 = 91 92 122 144 89 127 250 70 133 235 247 76 193 31 109 105 36 250 36 16 From 9ccf4a8f23eb2e319cff4b8a864052ccb7bbc9eb Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 06:58:40 +0000 Subject: [PATCH 18/69] change uintXX_t to quintXX and repaired some bug with a missing argument --- ghost/bncsutilinterface.cpp | 10 +- ghost/bncsutilinterface.h | 2 +- ghost/bnet.cpp | 52 ++--- ghost/bnet.h | 32 +-- ghost/bnetprotocol.cpp | 18 +- ghost/bnetprotocol.h | 18 +- ghost/bnlsclient.cpp | 6 +- ghost/bnlsclient.h | 18 +- ghost/bnlsprotocol.cpp | 20 +- ghost/bnlsprotocol.h | 6 +- ghost/crc32.cpp | 10 +- ghost/crc32.h | 8 +- ghost/game.cpp | 64 +++--- ghost/game.h | 2 +- ghost/game_admin.cpp | 24 +- ghost/game_admin.h | 4 +- ghost/game_base.cpp | 110 ++++----- ghost/game_base.h | 74 +++--- ghost/gameplayer.cpp | 22 +- ghost/gameplayer.h | 94 ++++---- ghost/gameprotocol.cpp | 54 ++--- ghost/gameprotocol.h | 43 ++-- ghost/ghost.cpp | 22 +- ghost/ghost.h | 40 ++-- ghost/ghostdb.cpp | 62 +++--- ghost/ghostdb.h | 432 ++++++++++++++++++------------------ ghost/ghostdbmysql.cpp | 122 +++++----- ghost/ghostdbmysql.h | 122 +++++----- ghost/ghostdbsqlite.cpp | 114 +++++----- ghost/ghostdbsqlite.h | 50 ++--- ghost/gpsprotocol.cpp | 18 +- ghost/gpsprotocol.h | 16 +- ghost/includes.h | 12 +- ghost/main.cpp | 6 +- ghost/map.cpp | 72 +++--- ghost/map.h | 20 +- ghost/ms_stdint.h | 12 +- ghost/packed.cpp | 34 +-- ghost/packed.h | 50 ++--- ghost/replay.cpp | 60 ++--- ghost/replay.h | 30 +-- ghost/savegame.cpp | 6 +- ghost/savegame.h | 4 +- ghost/sha1.cpp | 8 +- ghost/sha1.h | 15 +- ghost/stats.cpp | 2 +- ghost/stats.h | 2 +- ghost/statsdota.cpp | 12 +- ghost/statsdota.h | 8 +- ghost/statsw3mmd.cpp | 22 +- ghost/statsw3mmd.h | 16 +- ghost/util.cpp | 26 +-- ghost/util.h | 16 +- 53 files changed, 1057 insertions(+), 1065 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index 2632712..e1a4beb 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -68,11 +68,11 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr // todotodo: check getExeInfo return value to ensure 1024 bytes was enough char buf[1024]; - uint32_t EXEVersion; - getExeInfo( FileWar3EXE.toStdString().c_str( ), (char *)&buf, 1024, (uint32_t *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); + quint32 EXEVersion; + getExeInfo( FileWar3EXE.toStdString().c_str( ), (char *)&buf, 1024, (quint32 *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); m_EXEInfo = buf; m_EXEVersion = UTIL_CreateBYTEARRAY( EXEVersion, false ); - uint32_t EXEVersionHash; + quint32 EXEVersionHash; checkRevisionFlat( valueStringFormula.toStdString().c_str( ), FileWar3EXE.toStdString().c_str( ), FileStormDLL.toStdString().c_str( ), FileGameDLL.toStdString().c_str( ), extractMPQNumber( mpqFileName.toStdString().c_str( ) ), (unsigned long *)&EXEVersionHash ); m_EXEVersionHash = UTIL_CreateBYTEARRAY( EXEVersionHash, false ); m_KeyInfoROC = CreateKeyInfo( keyROC, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); @@ -138,7 +138,7 @@ bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( QString userPassword ) return true; } -QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ) +QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, quint32 clientToken, quint32 serverToken ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; QByteArray KeyInfo; @@ -146,7 +146,7 @@ QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, uint32_t clientToke if( Decoder.isKeyValid( ) ) { - UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( (uint32_t)key.size( ), false ) ); + UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( (quint32)key.size( ), false ) ); UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( Decoder.getProduct( ), false ) ); UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( Decoder.getVal1( ), false ) ); UTIL_AppendBYTEARRAY( KeyInfo, QByteArray( (char*)Zeros, 4 ) ); diff --git a/ghost/bncsutilinterface.h b/ghost/bncsutilinterface.h index d47c1af..eefadde 100644 --- a/ghost/bncsutilinterface.h +++ b/ghost/bncsutilinterface.h @@ -62,7 +62,7 @@ class CBNCSUtilInterface bool HELP_PvPGNPasswordHash( QString userPassword ); private: - QByteArray CreateKeyInfo( QString key, uint32_t clientToken, uint32_t serverToken ); + QByteArray CreateKeyInfo( QString key, quint32 clientToken, quint32 serverToken ); }; #endif diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 27fe37e..015f4ea 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -44,7 +44,7 @@ // CBNET // -CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ) +CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, quint32 nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ) : QObject(NULL) { // todotodo: append path seperator to Warcraft3Path if needed @@ -314,7 +314,7 @@ void CBNET::socketDataReady() // check if at least one packet is waiting to be sent and if we've waited long enough to prevent flooding // this formula has changed many times but currently we wait 1 second if the last packet was "small", 3.5 seconds if it was "medium", and 4 seconds if it was "big" - uint32_t WaitTicks = 0; + quint32 WaitTicks = 0; if( m_LastOutPacketSize < 10 ) WaitTicks = 1000; @@ -376,7 +376,7 @@ void CBNET::EventCallableUpdateTimeout() { if( i->second->GetReady( ) ) { - uint32_t Count = i->second->GetResult( ); + quint32 Count = i->second->GetResult( ); if( Count == 0 ) QueueChatCommand( m_GHost->m_Language->ThereAreNoAdmins( m_Server ), i->first, !i->first.isEmpty( ) ); @@ -437,7 +437,7 @@ void CBNET::EventCallableUpdateTimeout() { if( i->second->GetReady( ) ) { - uint32_t Count = i->second->GetResult( ); + quint32 Count = i->second->GetResult( ); if( Count == 0 ) QueueChatCommand( m_GHost->m_Language->ThereAreNoBannedUsers( m_Server ), i->first, !i->first.isEmpty( ) ); @@ -616,7 +616,7 @@ void CBNET :: ExtractPackets( ) // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_QByteArrayToUInt16( header, false, 2 ); + quint16 Length = UTIL_QByteArrayToUInt16( header, false, 2 ); if( Length < 4 ) { @@ -1045,7 +1045,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the interval and the message // e.g. "30 hello everyone" -> interval: "30", message: "hello everyone" - uint32_t Interval; + quint32 Interval; QString Message; QTextStream SS(&Payload); SS >> Interval; @@ -1096,8 +1096,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the maximum games, auto start players, and the game name // e.g. "5 10 BattleShips Pro" -> maximum games: "5", auto start players: "10", game name: "BattleShips Pro" - uint32_t MaximumGames; - uint32_t AutoStartPlayers; + quint32 MaximumGames; + quint32 AutoStartPlayers; QString GameName; QTextStream SS(&Payload); SS >> MaximumGames; @@ -1167,8 +1167,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // extract the maximum games, auto start players, minimum score, maximum score, and the game name // e.g. "5 10 800 1200 BattleShips Pro" -> maximum games: "5", auto start players: "10", minimum score: "800", maximum score: "1200", game name: "BattleShips Pro" - uint32_t MaximumGames; - uint32_t AutoStartPlayers; + quint32 MaximumGames; + quint32 AutoStartPlayers; double MinimumScore; double MaximumScore; QString GameName; @@ -1242,7 +1242,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } else { - uint32_t AutoStartPlayers = UTIL_ToUInt32( Payload ); + quint32 AutoStartPlayers = UTIL_ToUInt32( Payload ); if( AutoStartPlayers != 0 ) { @@ -1304,7 +1304,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) while( !SS.atEnd( ) ) { - uint32_t SID; + quint32 SID; SS >> SID; if( SS.status() != QTextStream::Ok ) @@ -1404,7 +1404,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "downloads" && !Payload.isEmpty( ) ) { - uint32_t Downloads = UTIL_ToUInt32( Payload ); + quint32 Downloads = UTIL_ToUInt32( Payload ); if( Downloads == 0 ) { @@ -1622,7 +1622,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { QStringList files = MapCFGPath.entryList(QStringList("*" + Pattern + "*"), QDir::Files, QDir::Name); - uint32_t Matches = files.size(); + quint32 Matches = files.size(); if( Matches == 0 ) QueueChatCommand( m_GHost->m_Language->NoMapConfigsFound( ), User, Whisper ); @@ -1711,7 +1711,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { QStringList files = MapPath.entryList(QStringList("*"+Pattern+"*"), QDir::Files, QDir::Name); - uint32_t Matches = files.size(); + quint32 Matches = files.size(); if( Matches == 0 ) QueueChatCommand( m_GHost->m_Language->NoMapsFound( ), User, Whisper ); @@ -1764,7 +1764,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) while( !SS.atEnd( ) ) { - uint32_t SID; + quint32 SID; SS >> SID; if( SS.status() != QTextStream::Ok ) @@ -1973,8 +1973,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( !m_GHost->m_CurrentGame->GetLocked( ) ) { - uint32_t SID1; - uint32_t SID2; + quint32 SID1; + quint32 SID2; QTextStream SS(&Payload); SS >> SID1; @@ -2222,7 +2222,7 @@ void CBNET :: QueueChatCommand( QString chatCommand, QString user, bool whisper QueueChatCommand( chatCommand ); } -void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *savegame, uint32_t hostCounter ) +void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *savegame, quint32 hostCounter ) { if( m_LoggedIn && map ) { @@ -2237,7 +2237,7 @@ void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString ho } } -void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ) +void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, quint32 upTime, quint32 hostCounter ) { if( hostName.isEmpty( ) ) { @@ -2254,11 +2254,11 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h // when a player joins a game we can obtain the ID from the received host counter // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused - uint32_t FixedHostCounter = ( hostCounter & 0x0FFFFFFF ) | ( m_HostCounterID << 28 ); + quint32 FixedHostCounter = ( hostCounter & 0x0FFFFFFF ) | ( m_HostCounterID << 28 ); if( saveGame ) { - uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; + quint32 MapGameType = MAPGAMETYPE_SAVEDGAME; // the state should always be private when creating a saved game @@ -2277,11 +2277,11 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h if( m_GHost->m_Reconnect ) m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateBYTEARRAY( (uint16_t)0, false ), UTIL_CreateBYTEARRAY( (uint16_t)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateBYTEARRAY( (quint16)0, false ), UTIL_CreateBYTEARRAY( (quint16)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); } else { - uint32_t MapGameType = map->GetMapGameType( ); + quint32 MapGameType = map->GetMapGameType( ); MapGameType |= MAPGAMETYPE_UNKNOWN0; if( state == GAME_PRIVATE ) @@ -2313,7 +2313,7 @@ void CBNET :: QueueGameUncreate( ) void CBNET :: UnqueuePackets( unsigned char type ) { QQueue Packets; - uint32_t Unqueued = 0; + quint32 Unqueued = 0; while( !m_OutPackets.isEmpty( ) ) { @@ -2342,7 +2342,7 @@ void CBNET :: UnqueueChatCommand( QString chatCommand ) QByteArray PacketToUnqueue = m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ); QQueue Packets; - uint32_t Unqueued = 0; + quint32 Unqueued = 0; while( !m_OutPackets.isEmpty( ) ) { diff --git a/ghost/bnet.h b/ghost/bnet.h index 04701bb..9fdb8c8 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -112,13 +112,13 @@ public slots: QString m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) QString m_ServerAlias; // battle.net server alias (short name, e.g. "USEast") QString m_BNLSServer; // BNLS server to connect to (for warden handling) - uint16_t m_BNLSPort; // BNLS port - uint32_t m_BNLSWardenCookie; // BNLS warden cookie + quint16 m_BNLSPort; // BNLS port + quint32 m_BNLSWardenCookie; // BNLS warden cookie QString m_CDKeyROC; // ROC CD key QString m_CDKeyTFT; // TFT CD key QString m_CountryAbbrev; // country abbreviation QString m_Country; // country - uint32_t m_LocaleID; // see: http://msdn.microsoft.com/en-us/library/0h88fahh%28VS.85%29.aspx + quint32 m_LocaleID; // see: http://msdn.microsoft.com/en-us/library/0h88fahh%28VS.85%29.aspx QString m_UserName; // battle.net username QString m_UserPassword; // battle.net password QString m_FirstChannel; // the first chat channel to join upon entering chat (note: we hijack this to store the last channel when entering a game) @@ -131,14 +131,14 @@ public slots: QString m_PasswordHashType; // password hash type for PvPGN users QString m_PVPGNRealmName; // realm name for PvPGN users (for mutual friend spoofchecks) int m_MaxMessageLength; // maximum message length for PvPGN users - uint32_t m_HostCounterID; // the host counter ID to identify players from this realm - uint32_t m_LastDisconnectedTime; // GetTime when we were last disconnected from battle.net - uint32_t m_LastConnectionAttemptTime; // GetTime when we last attempted to connect to battle.net - uint32_t m_LastNullTime; // GetTime when the last null packet was sent for detecting disconnects - uint32_t m_LastOutPacketTicks; // GetTicks when the last packet was sent for the m_OutPackets queue - uint32_t m_LastOutPacketSize; - uint32_t m_LastAdminRefreshTime; // GetTime when the admin list was last refreshed from the database - uint32_t m_LastBanRefreshTime; // GetTime when the ban list was last refreshed from the database + quint32 m_HostCounterID; // the host counter ID to identify players from this realm + quint32 m_LastDisconnectedTime; // GetTime when we were last disconnected from battle.net + quint32 m_LastConnectionAttemptTime; // GetTime when we last attempted to connect to battle.net + quint32 m_LastNullTime; // GetTime when the last null packet was sent for detecting disconnects + quint32 m_LastOutPacketTicks; // GetTicks when the last packet was sent for the m_OutPackets queue + quint32 m_LastOutPacketSize; + quint32 m_LastAdminRefreshTime; // GetTime when the admin list was last refreshed from the database + quint32 m_LastBanRefreshTime; // GetTime when the ban list was last refreshed from the database bool m_FirstConnect; // if we haven't tried to connect to battle.net yet bool m_LoggedIn; // if we've logged into battle.net or not bool m_InChat; // if we've entered chat or not (but we're not necessarily in a chat channel yet) @@ -147,7 +147,7 @@ public slots: bool m_PublicCommands; // whether to allow public commands or not public: - CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, uint16_t nBNLSPort, uint32_t nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, uint32_t nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, uint32_t nMaxMessageLength, uint32_t nHostCounterID ); + CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, quint32 nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); virtual ~CBNET( ); bool GetExiting( ) { return m_Exiting; } @@ -165,13 +165,13 @@ public slots: QByteArray GetEXEVersionHash( ) { return m_EXEVersionHash; } QString GetPasswordHashType( ) { return m_PasswordHashType; } QString GetPVPGNRealmName( ) { return m_PVPGNRealmName; } - uint32_t GetHostCounterID( ) { return m_HostCounterID; } + quint32 GetHostCounterID( ) { return m_HostCounterID; } bool GetLoggedIn( ) { return m_LoggedIn; } bool GetInChat( ) { return m_InChat; } bool GetHoldFriends( ) { return m_HoldFriends; } bool GetHoldClan( ) { return m_HoldClan; } bool GetPublicCommands( ) { return m_PublicCommands; } - uint32_t GetOutPacketsQueued( ) { return m_OutPackets.size( ); } + quint32 GetOutPacketsQueued( ) { return m_OutPackets.size( ); } QByteArray GetUniqueName( ); // processing functions @@ -188,8 +188,8 @@ public slots: void QueueEnterChat( ); void QueueChatCommand( QString chatCommand ); void QueueChatCommand( QString chatCommand, QString user, bool whisper ); - void QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t hostCounter ); - void QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, uint32_t upTime, uint32_t hostCounter ); + void QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, quint32 hostCounter ); + void QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, quint32 upTime, quint32 hostCounter ); void QueueGameUncreate( ); void UnqueuePackets( unsigned char type ); diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index debec4b..cbc2753 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -606,7 +606,7 @@ QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, uint32_t hostCounter ) +QByteArray CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, quint32 hostCounter ) { // todotodo: sort out how GameType works, the documentation is horrendous @@ -755,7 +755,7 @@ QByteArray CBNETProtocol :: SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByt return packet; } -QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) +QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( quint16 serverPort ) { QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant @@ -769,7 +769,7 @@ QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( uint16_t serverPort ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, QString countryAbbrev, QString country ) +QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, quint32 localeID, QString countryAbbrev, QString country ) { unsigned char ProtocolID[] = { 0, 0, 0, 0 }; unsigned char PlatformID[] = { 54, 56, 88, 73 }; // "IX86" @@ -809,7 +809,7 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uin QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToken, QByteArray exeVersion, QByteArray exeVersionHash, QByteArray keyInfoROC, QByteArray keyInfoTFT, QString exeInfo, QString keyOwnerName ) { - uint32_t NumKeys = 0; + quint32 NumKeys = 0; if( TFT ) NumKeys = 2; @@ -828,7 +828,7 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToke UTIL_AppendBYTEARRAYFast( packet, exeVersion ); // EXE Version UTIL_AppendBYTEARRAYFast( packet, exeVersionHash ); // EXE Version Hash UTIL_AppendBYTEARRAY( packet, NumKeys, false ); // number of keys in this packet - UTIL_AppendBYTEARRAY( packet, (uint32_t)0, false ); // boolean Using Spawn (32 bit) + UTIL_AppendBYTEARRAY( packet, (quint32)0, false ); // boolean Using Spawn (32 bit) UTIL_AppendBYTEARRAYFast( packet, keyInfoROC ); // ROC Key Info if( TFT ) @@ -944,7 +944,7 @@ bool CBNETProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -957,7 +957,7 @@ bool CBNETProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length - uint16_t Length; + quint16 Length; QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) @@ -977,7 +977,7 @@ bool CBNETProtocol :: ValidateLength( QByteArray &content ) // CIncomingGameHost // -CIncomingGameHost :: CIncomingGameHost( QByteArray &nIP, uint16_t nPort, QString nGameName, QByteArray &nHostCounter ) +CIncomingGameHost :: CIncomingGameHost( QByteArray &nIP, quint16 nPort, QString nGameName, QByteArray &nHostCounter ) { m_IP = nIP; m_Port = nPort; @@ -1012,7 +1012,7 @@ QString CIncomingGameHost :: GetIPString( ) // CIncomingChatEvent // -CIncomingChatEvent :: CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, uint32_t nPing, QString nUser, QString nMessage ) +CIncomingChatEvent :: CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, quint32 nPing, QString nUser, QString nMessage ) { m_ChatEvent = nChatEvent; m_Ping = nPing; diff --git a/ghost/bnetprotocol.h b/ghost/bnetprotocol.h index 31d60dd..575871b 100644 --- a/ghost/bnetprotocol.h +++ b/ghost/bnetprotocol.h @@ -148,12 +148,12 @@ class CBNETProtocol QByteArray SEND_SID_JOINCHANNEL( QString channel ); QByteArray SEND_SID_CHATCOMMAND( QString command ); QByteArray SEND_SID_CHECKAD( ); - QByteArray SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, uint32_t hostCounter ); + QByteArray SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, quint32 hostCounter ); QByteArray SEND_SID_NOTIFYJOIN( QString gameName ); QByteArray SEND_SID_PING( QByteArray pingValue ); QByteArray SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByteArray serverToken, QByteArray passwordHash, QString accountName ); - QByteArray SEND_SID_NETGAMEPORT( uint16_t serverPort ); - QByteArray SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, uint32_t localeID, QString countryAbbrev, QString country ); + QByteArray SEND_SID_NETGAMEPORT( quint16 serverPort ); + QByteArray SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, quint32 localeID, QString countryAbbrev, QString country ); QByteArray SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToken, QByteArray exeVersion, QByteArray exeVersionHash, QByteArray keyInfoROC, QByteArray keyInfoTFT, QString exeInfo, QString keyOwnerName ); QByteArray SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicKey, QString accountName ); QByteArray SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPasswordProof ); @@ -176,17 +176,17 @@ class CIncomingGameHost { private: QByteArray m_IP; - uint16_t m_Port; + quint16 m_Port; QString m_GameName; QByteArray m_HostCounter; public: - CIncomingGameHost( QByteArray &nIP, uint16_t nPort, QString nGameName, QByteArray &nHostCounter ); + CIncomingGameHost( QByteArray &nIP, quint16 nPort, QString nGameName, QByteArray &nHostCounter ); ~CIncomingGameHost( ); QByteArray GetIP( ) { return m_IP; } QString GetIPString( ); - uint16_t GetPort( ) { return m_Port; } + quint16 GetPort( ) { return m_Port; } QString GetGameName( ) { return m_GameName; } QByteArray GetHostCounter( ) { return m_HostCounter; } }; @@ -199,16 +199,16 @@ class CIncomingChatEvent { private: CBNETProtocol :: IncomingChatEvent m_ChatEvent; - uint32_t m_Ping; + quint32 m_Ping; QString m_User; QString m_Message; public: - CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, uint32_t nPing, QString nUser, QString nMessage ); + CIncomingChatEvent( CBNETProtocol :: IncomingChatEvent nChatEvent, quint32 nPing, QString nUser, QString nMessage ); ~CIncomingChatEvent( ); CBNETProtocol :: IncomingChatEvent GetChatEvent( ) { return m_ChatEvent; } - uint32_t GetPing( ) { return m_Ping; } + quint32 GetPing( ) { return m_Ping; } QString GetUser( ) { return m_User; } QString GetMessage( ) { return m_Message; } }; diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index c3699ab..7fde607 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -28,7 +28,7 @@ // CBNLSClient // -CBNLSClient :: CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCookie ) +CBNLSClient :: CBNLSClient( QString nServer, quint16 nPort, quint32 nWardenCookie ) { m_Socket = new QTcpSocket( ); @@ -119,7 +119,7 @@ void CBNLSClient :: ExtractPackets( ) { while( m_Socket->bytesAvailable() >= 3 ) { - uint16_t Length = UTIL_QByteArrayToUInt16( m_Socket->peek(2), false ); + quint16 Length = UTIL_QByteArrayToUInt16( m_Socket->peek(2), false ); if( Length < 3 ) { @@ -156,7 +156,7 @@ void CBNLSClient :: ProcessPackets( ) } } -void CBNLSClient :: QueueWardenSeed( uint32_t seed ) +void CBNLSClient :: QueueWardenSeed( quint32 seed ) { m_OutPackets.enqueue( m_Protocol->SEND_BNLS_WARDEN_SEED( m_WardenCookie, seed ) ); } diff --git a/ghost/bnlsclient.h b/ghost/bnlsclient.h index 19c2c96..e729894 100644 --- a/ghost/bnlsclient.h +++ b/ghost/bnlsclient.h @@ -53,21 +53,21 @@ public slots: QQueue m_Packets; // queue of incoming packets bool m_WasConnected; QString m_Server; - uint16_t m_Port; - uint32_t m_LastNullTime; - uint32_t m_WardenCookie; // the warden cookie + quint16 m_Port; + quint32 m_LastNullTime; + quint32 m_WardenCookie; // the warden cookie QQueue m_OutPackets; // queue of outgoing packets to be sent - uint32_t m_TotalWardenIn; - uint32_t m_TotalWardenOut; + quint32 m_TotalWardenIn; + quint32 m_TotalWardenOut; int m_Retries; public: - CBNLSClient( QString nServer, uint16_t nPort, uint32_t nWardenCookie ); + CBNLSClient( QString nServer, quint16 nPort, quint32 nWardenCookie ); ~CBNLSClient( ); QByteArray GetWardenResponse( ); - uint32_t GetTotalWardenIn( ) { return m_TotalWardenIn; } - uint32_t GetTotalWardenOut( ) { return m_TotalWardenOut; } + quint32 GetTotalWardenIn( ) { return m_TotalWardenIn; } + quint32 GetTotalWardenOut( ) { return m_TotalWardenOut; } // processing functions @@ -76,7 +76,7 @@ public slots: // other functions - void QueueWardenSeed( uint32_t seed ); + void QueueWardenSeed( quint32 seed ); void QueueWardenRaw( QByteArray wardenRaw ); }; diff --git a/ghost/bnlsprotocol.cpp b/ghost/bnlsprotocol.cpp index c0ede70..8ce2247 100644 --- a/ghost/bnlsprotocol.cpp +++ b/ghost/bnlsprotocol.cpp @@ -49,9 +49,9 @@ QByteArray CBNLSProtocol :: RECEIVE_BNLS_WARDEN( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 11 ) { //unsigned char Usage = data[3]; - //uint32_t Cookie = UTIL_QByteArrayToUInt32( data, false, 4 ); + //quint32 Cookie = UTIL_QByteArrayToUInt32( data, false, 4 ); unsigned char Result = data[8]; - //uint16_t Length = UTIL_QByteArrayToUInt16( data, false, 10 ); + //quint16 Length = UTIL_QByteArrayToUInt16( data, false, 10 ); if( Result == 0x00 ) return data.mid(11); @@ -76,7 +76,7 @@ QByteArray CBNLSProtocol :: SEND_BNLS_NULL( ) return packet; } -QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t seed ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( quint32 cookie, quint32 seed ) { unsigned char Client[] = { 80, 88, 51, 87 }; // "W3XP" @@ -87,16 +87,16 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t see packet.push_back( (char)0 ); // BNLS_WARDEN_SEED UTIL_AppendBYTEARRAY( packet, cookie, false ); // cookie UTIL_AppendBYTEARRAY( packet, Client, 4 ); // Client - UTIL_AppendBYTEARRAY( packet, (uint16_t)4, false ); // length of seed + UTIL_AppendBYTEARRAY( packet, (quint16)4, false ); // length of seed UTIL_AppendBYTEARRAY( packet, seed, false ); // seed packet.push_back( (char)0 ); // username is blank - UTIL_AppendBYTEARRAY( packet, (uint16_t)0, false ); // password length + UTIL_AppendBYTEARRAY( packet, (quint16)0, false ); // password length // password AssignLength( packet ); return packet; } -QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray raw ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( quint32 cookie, QByteArray raw ) { QByteArray packet; packet.push_back( (char)0 ); // packet length will be assigned later @@ -104,13 +104,13 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray ra packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( 1 ); // BNLS_WARDEN_RAW UTIL_AppendBYTEARRAY( packet, cookie, false ); // cookie - UTIL_AppendBYTEARRAY( packet, (uint16_t)raw.size( ), false ); // raw length + UTIL_AppendBYTEARRAY( packet, (quint16)raw.size( ), false ); // raw length UTIL_AppendBYTEARRAY( packet, raw ); // raw AssignLength( packet ); return packet; } -QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RUNMODULE( uint32_t /*cookie*/ ) +QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RUNMODULE( quint32 /*cookie*/ ) { return QByteArray( ); } @@ -127,7 +127,7 @@ bool CBNLSProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 2 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); content[0] = LengthBytes[0]; content[1] = LengthBytes[1]; return true; @@ -140,7 +140,7 @@ bool CBNLSProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 1 and 2 (indices 0 and 1) of the content array describe the length - uint16_t Length; + quint16 Length; QByteArray LengthBytes; if( content.size( ) >= 2 && content.size( ) <= 65535 ) diff --git a/ghost/bnlsprotocol.h b/ghost/bnlsprotocol.h index 5ef3cac..67681b4 100644 --- a/ghost/bnlsprotocol.h +++ b/ghost/bnlsprotocol.h @@ -70,9 +70,9 @@ class CBNLSProtocol // send functions QByteArray SEND_BNLS_NULL( ); - QByteArray SEND_BNLS_WARDEN_SEED( uint32_t cookie, uint32_t seed ); - QByteArray SEND_BNLS_WARDEN_RAW( uint32_t cookie, QByteArray raw ); - QByteArray SEND_BNLS_WARDEN_RUNMODULE( uint32_t cookie ); + QByteArray SEND_BNLS_WARDEN_SEED( quint32 cookie, quint32 seed ); + QByteArray SEND_BNLS_WARDEN_RAW( quint32 cookie, QByteArray raw ); + QByteArray SEND_BNLS_WARDEN_RUNMODULE( quint32 cookie ); // other functions diff --git a/ghost/crc32.cpp b/ghost/crc32.cpp index df314d2..f30f07f 100644 --- a/ghost/crc32.cpp +++ b/ghost/crc32.cpp @@ -14,9 +14,9 @@ void CCRC32 :: Initialize( ) } } -uint32_t CCRC32 :: Reflect( uint32_t ulReflect, char cChar ) +quint32 CCRC32 :: Reflect( quint32 ulReflect, char cChar ) { - uint32_t ulValue = 0; + quint32 ulValue = 0; for( int iPos = 1; iPos < ( cChar + 1 ); iPos++ ) { @@ -29,14 +29,14 @@ uint32_t CCRC32 :: Reflect( uint32_t ulReflect, char cChar ) return ulValue; } -uint32_t CCRC32 :: FullCRC( QString data ) +quint32 CCRC32 :: FullCRC( QString data ) { - uint32_t ulCRC = 0xFFFFFFFF; + quint32 ulCRC = 0xFFFFFFFF; PartialCRC( &ulCRC, (const unsigned char*)data.toStdString().c_str(), data.toStdString().size() ); return ulCRC ^ 0xFFFFFFFF; } -void CCRC32 :: PartialCRC( uint32_t *ulInCRC, const unsigned char *sData, uint32_t ulLength ) +void CCRC32 :: PartialCRC( quint32 *ulInCRC, const unsigned char *sData, quint32 ulLength ) { while( ulLength-- ) *ulInCRC = ( *ulInCRC >> 8 ) ^ ulTable[( *ulInCRC & 0xFF ) ^ *sData++]; diff --git a/ghost/crc32.h b/ghost/crc32.h index a171a7d..97df039 100644 --- a/ghost/crc32.h +++ b/ghost/crc32.h @@ -7,12 +7,12 @@ class CCRC32 { public: void Initialize( ); - uint32_t FullCRC( QString data ); - void PartialCRC( uint32_t *ulInCRC, const unsigned char *sData, uint32_t ulLength ); + quint32 FullCRC( QString data ); + void PartialCRC( quint32 *ulInCRC, const unsigned char *sData, quint32 ulLength ); private: - uint32_t Reflect( uint32_t ulReflect, char cChar ); - uint32_t ulTable[256]; + quint32 Reflect( quint32 ulReflect, char cChar ); + quint32 ulTable[256]; }; #endif diff --git a/ghost/game.cpp b/ghost/game.cpp index 05fd5d2..2165814 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -71,7 +71,7 @@ class CGamePlayerSortDescByPing // CGame // -CGame :: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, nOwnerName, nCreatorName, nCreatorServer ) +CGame :: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, nOwnerName, nCreatorName, nCreatorServer ) { m_DBBanLast = NULL; m_DBGame = new CDBGame( 0, QString( ), m_Map->GetMapPath( ), QString( ), QString( ), QString( ), 0 ); @@ -430,7 +430,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( m_GameLoaded ) { QString VictimLower = Victim.toLower(); - uint32_t Matches = 0; + quint32 Matches = 0; CDBBan *LastMatch = NULL; // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") @@ -465,7 +465,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri else { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Victim, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Victim, &LastMatch ); if( Matches == 0 ) SendAllChat( m_GHost->m_Language->UnableToBanNoMatchesFound( Victim ) ); @@ -492,7 +492,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // extract the interval and the message // e.g. "30 hello everyone" -> interval: "30", message: "hello everyone" - uint32_t Interval; + quint32 Interval; QString Message; QTextStream SS(&Payload); @@ -550,7 +550,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } else { - uint32_t AutoStartPlayers = UTIL_ToUInt32( Payload ); + quint32 AutoStartPlayers = UTIL_ToUInt32( Payload ); if( AutoStartPlayers != 0 ) { @@ -576,7 +576,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( !Payload.isEmpty( ) ) { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) SendAllChat( m_GHost->m_Language->UnableToCheckPlayerNoMatchesFound( Payload ) ); @@ -646,7 +646,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri while( !SS.atEnd( ) ) { - uint32_t SID; + quint32 SID; SS >> SID; if( SS.status() != QTextStream::Ok ) @@ -675,8 +675,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // extract the slot and the skill // e.g. "1 2" -> slot: "1", skill: "2" - uint32_t Slot; - uint32_t Skill = 1; + quint32 Slot; + quint32 Skill = 1; QTextStream SS(&Payload); SS >> Slot; @@ -704,8 +704,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // extract the slot and the colour // e.g. "1 2" -> slot: "1", colour: "2" - uint32_t Slot; - uint32_t Colour; + quint32 Slot; + quint32 Colour; QTextStream SS(&Payload); SS >> Slot; @@ -745,8 +745,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // extract the slot and the handicap // e.g. "1 50" -> slot: "1", handicap: "50" - uint32_t Slot; - uint32_t Handicap; + quint32 Slot; + quint32 Handicap; QTextStream SS(&Payload); SS >> Slot; @@ -789,7 +789,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // extract the slot and the race // e.g. "1 human" -> slot: "1", race: "human" - uint32_t Slot; + quint32 Slot; QString Race; QTextStream SS(&Payload); @@ -857,8 +857,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // extract the slot and the team // e.g. "1 2" -> slot: "1", team: "2" - uint32_t Slot; - uint32_t Team; + quint32 Slot; + quint32 Team; QTextStream SS(&Payload); SS >> Slot; @@ -907,7 +907,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( ( Command == "download" || Command == "dl" ) && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) SendAllChat( m_GHost->m_Language->UnableToStartDownloadNoMatchesFound( Payload ) ); @@ -1082,7 +1082,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "kick" && !Payload.isEmpty( ) ) { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) SendAllChat( m_GHost->m_Language->UnableToKickNoMatchesFound( Payload ) ); @@ -1165,7 +1165,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "mute" ) { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) SendAllChat( m_GHost->m_Language->UnableToMuteNoMatchesFound( Payload ) ); @@ -1201,7 +1201,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri while( !SS.atEnd( ) ) { - uint32_t SID; + quint32 SID; SS >> SID; if( SS.status() != QTextStream::Ok ) @@ -1253,8 +1253,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // kick players with ping higher than payload if payload isn't empty // we only do this if the game hasn't started since we don't want to kick players from a game in progress - uint32_t Kicked = 0; - uint32_t KickPing = 0; + quint32 Kicked = 0; + quint32 KickPing = 0; if( !m_GameLoading && !m_GameLoaded && !Payload.isEmpty( ) ) KickPing = UTIL_ToUInt32( Payload ); @@ -1414,7 +1414,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // e.g. "1.2.3.4 6112" -> ip: "1.2.3.4", port: "6112" QString IP; - uint32_t Port = 6112; + quint32 Port = 6112; QTextStream SS(&Payload); SS >> IP; @@ -1439,7 +1439,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) - uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; + quint32 MapGameType = MAPGAMETYPE_SAVEDGAME; QByteArray MapWidth; MapWidth.push_back( (char)0 ); MapWidth.push_back( (char)0 ); @@ -1454,7 +1454,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) - uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; + quint32 MapGameType = MAPGAMETYPE_UNKNOWN0; m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), QHostAddress(IP), Port); } @@ -1497,8 +1497,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "swap" && !Payload.isEmpty( ) && !m_GameLoading && !m_GameLoaded ) { - uint32_t SID1; - uint32_t SID2; + quint32 SID1; + quint32 SID2; QTextStream SS(&Payload); SS >> SID1; @@ -1572,7 +1572,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "unmute" ) { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) SendAllChat( m_GHost->m_Language->UnableToMuteNoMatchesFound( Payload ) ); @@ -1729,7 +1729,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri else { CGamePlayer *LastMatch = NULL; - uint32_t Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); + quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) SendChat( player, m_GHost->m_Language->UnableToVoteKickNoMatchesFound( Payload ) ); @@ -1747,7 +1747,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri player->SetKickVote( true ); CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] started by player [" + User + "]" ); - SendAllChat( m_GHost->m_Language->StartedVoteKick( LastMatch->GetName( ), User, UTIL_ToString( (uint32_t)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); + SendAllChat( m_GHost->m_Language->StartedVoteKick( LastMatch->GetName( ), User, UTIL_ToString( (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); SendAllChat( m_GHost->m_Language->TypeYesToVote( QString( 1, m_GHost->m_CommandTrigger ) ) ); } } @@ -1763,8 +1763,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "yes" && !m_KickVotePlayer.isEmpty( ) && player->GetName( ) != m_KickVotePlayer && !player->GetKickVote( ) ) { player->SetKickVote( true ); - uint32_t VotesNeeded = (uint32_t)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ); - uint32_t Votes = 0; + quint32 VotesNeeded = (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ); + quint32 Votes = 0; for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { diff --git a/ghost/game.h b/ghost/game.h index f5d1420..a048d44 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -66,7 +66,7 @@ public slots: QVector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress public: - CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); + CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CGame( ); virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index bf2fa13..9f7aabf 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -43,7 +43,7 @@ // CAdminGame // -CAdminGame :: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, QString( ), QString( ), QString( ) ) +CAdminGame :: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, QString( ), QString( ), QString( ) ) { m_VirtualHostName = "|cFFC04040Admin"; m_MuteLobby = true; @@ -89,7 +89,7 @@ void CAdminGame::EventCallableUpdateTimeout() if( Player ) { - uint32_t Count = i->second->GetResult( ); + quint32 Count = i->second->GetResult( ); if( Count == 0 ) SendChat( Player, m_GHost->m_Language->ThereAreNoAdmins( i->second->GetServer( ) ) ); @@ -177,7 +177,7 @@ void CAdminGame::EventCallableUpdateTimeout() if( Player ) { - uint32_t Count = i->second->GetResult( ); + quint32 Count = i->second->GetResult( ); if( Count == 0 ) SendChat( Player, m_GHost->m_Language->ThereAreNoBannedUsers( i->second->GetServer( ) ) ); @@ -287,7 +287,7 @@ void CAdminGame :: SendWelcomeMessage( CGamePlayer *player ) void CAdminGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer ) { - uint32_t Time = GetTime( ); + quint32 Time = GetTime( ); for( QVector :: iterator i = m_TempBans.begin( ); i != m_TempBans.end( ); ) { @@ -410,8 +410,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // extract the maximum games, auto start players, and the game name // e.g. "5 10 BattleShips Pro" -> maximum games: "5", auto start players: "10", game name: "BattleShips Pro" - uint32_t MaximumGames; - uint32_t AutoStartPlayers; + quint32 MaximumGames; + quint32 AutoStartPlayers; QString GameName; QTextStream SS(&Payload); @@ -477,8 +477,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // extract the maximum games, auto start players, and the game name // e.g. "5 10 800 1200 BattleShips Pro" -> maximum games: "5", auto start players: "10", minimum score: "800", maximum score: "1200", game name: "BattleShips Pro" - uint32_t MaximumGames; - uint32_t AutoStartPlayers; + quint32 MaximumGames; + quint32 AutoStartPlayers; double MinimumScore; double MaximumScore; QString GameName; @@ -757,7 +757,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "downloads" && !Payload.isEmpty( ) ) { - uint32_t Downloads = UTIL_ToUInt32( Payload ); + quint32 Downloads = UTIL_ToUInt32( Payload ); if( Downloads == 0 ) { @@ -910,7 +910,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else { QStringList files = MapCFGPath.entryList(QStringList("*" + Pattern + "*"), QDir::Files, QDir::Name); - uint32_t Matches = files.size(); + quint32 Matches = files.size(); if( Matches == 0 ) SendChat( player, m_GHost->m_Language->NoMapConfigsFound( ) ); @@ -997,7 +997,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else { QStringList files = MapPath.entryList(QStringList("*"+Pattern+"*"), QDir::Files, QDir::Name); - uint32_t Matches = files.size(); + quint32 Matches = files.size(); if( Matches == 0 ) SendChat( player, m_GHost->m_Language->NoMapsFound( ) ); @@ -1226,7 +1226,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, } else { - uint32_t LoginAttempts = player->GetLoginAttempts( ) + 1; + quint32 LoginAttempts = player->GetLoginAttempts( ) + 1; player->SetLoginAttempts( LoginAttempts ); CONSOLE_Print( "[ADMINGAME] user [" + User + "] login attempt failed" ); SendChat( player, m_GHost->m_Language->AdminInvalidPassword( UTIL_ToString( LoginAttempts ) ) ); diff --git a/ghost/game_admin.h b/ghost/game_admin.h index 505103f..bfcf543 100644 --- a/ghost/game_admin.h +++ b/ghost/game_admin.h @@ -43,7 +43,7 @@ typedef pair PairedBanCount; // typedef pair PairedBanAdd; typedef pair PairedBanRemove; -typedef pair TempBan; +typedef pair TempBan; class CAdminGame : public CBaseGame { @@ -63,7 +63,7 @@ public slots: QVector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress public: - CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ); + CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ); virtual ~CAdminGame( ); virtual void SendAdminChat( QString message ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 259db68..8d30831 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -46,7 +46,7 @@ // CBaseGame // -CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) +CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) { m_GHost = nGHost; m_Socket = new QTcpServer(this); @@ -308,7 +308,7 @@ CBaseGame :: ~CBaseGame( ) } } -uint32_t CBaseGame :: GetNextTimedActionTicks( ) +quint32 CBaseGame :: GetNextTimedActionTicks( ) { // return the number of ticks (ms) until the next "timed action", which for our purposes is the next game update // the main GHost++ loop will make sure the next loop update happens at or before this value @@ -318,7 +318,7 @@ uint32_t CBaseGame :: GetNextTimedActionTicks( ) if( !m_GameLoaded || m_Lagging ) return 50; - uint32_t TicksSinceLastUpdate = GetTicks( ) - m_LastActionSentTicks; + quint32 TicksSinceLastUpdate = GetTicks( ) - m_LastActionSentTicks; if( TicksSinceLastUpdate > m_Latency - m_LastActionLateBy ) return 0; @@ -326,9 +326,9 @@ uint32_t CBaseGame :: GetNextTimedActionTicks( ) return m_Latency - m_LastActionLateBy - TicksSinceLastUpdate; } -uint32_t CBaseGame :: GetSlotsOccupied( ) +quint32 CBaseGame :: GetSlotsOccupied( ) { - uint32_t NumSlotsOccupied = 0; + quint32 NumSlotsOccupied = 0; for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { @@ -339,9 +339,9 @@ uint32_t CBaseGame :: GetSlotsOccupied( ) return NumSlotsOccupied; } -uint32_t CBaseGame :: GetSlotsOpen( ) +quint32 CBaseGame :: GetSlotsOpen( ) { - uint32_t NumSlotsOpen = 0; + quint32 NumSlotsOpen = 0; for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { @@ -352,9 +352,9 @@ uint32_t CBaseGame :: GetSlotsOpen( ) return NumSlotsOpen; } -uint32_t CBaseGame :: GetNumPlayers( ) +quint32 CBaseGame :: GetNumPlayers( ) { - uint32_t NumPlayers = GetNumHumanPlayers( ); + quint32 NumPlayers = GetNumHumanPlayers( ); if( m_FakePlayerPID != 255 ) NumPlayers++; @@ -362,9 +362,9 @@ uint32_t CBaseGame :: GetNumPlayers( ) return NumPlayers; } -uint32_t CBaseGame :: GetNumHumanPlayers( ) +quint32 CBaseGame :: GetNumHumanPlayers( ) { - uint32_t NumHumanPlayers = 0; + quint32 NumHumanPlayers = 0; for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -387,7 +387,7 @@ QString CBaseGame :: GetDescription( ) return Description; } -void CBaseGame :: SetAnnounce( uint32_t interval, QString message ) +void CBaseGame :: SetAnnounce( quint32 interval, QString message ) { m_AnnounceTimer.start(1000 * interval); m_AnnounceMessage = message; @@ -535,7 +535,7 @@ void CBaseGame::EventBroadcastTimeout() // when a player joins a game we can obtain the ID from the received host counter // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused - uint32_t FixedHostCounter = m_HostCounter & 0x0FFFFFFF; + quint32 FixedHostCounter = m_HostCounter & 0x0FFFFFFF; QString target = m_GHost->m_UDPSocket->property("target").toString(); QHostAddress hostAddr = target == "" ? QHostAddress::LocalHost : QHostAddress(m_GHost->m_UDPSocket->property("target").toString()); @@ -543,7 +543,7 @@ void CBaseGame::EventBroadcastTimeout() { // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) - uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; + quint32 MapGameType = MAPGAMETYPE_SAVEDGAME; QByteArray MapWidth; MapWidth.push_back( (char)0 ); MapWidth.push_back( (char)0 ); @@ -575,7 +575,7 @@ void CBaseGame::EventBroadcastTimeout() // note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect) // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) - uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0; + quint32 MapGameType = MAPGAMETYPE_UNKNOWN0; m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ), hostAddr, 6112 ); @@ -694,7 +694,7 @@ void CBaseGame::EventMapDataTimeout() return; } - uint32_t Downloaders = 0; + quint32 Downloaders = 0; for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -719,7 +719,7 @@ void CBaseGame::EventMapDataTimeout() // in addition to this, the throughput is limited by the configuration value bot_maxdownloadspeed // in summary: the actual throughput is MIN( 140 * 1000 / ping, 1400, bot_maxdownloadspeed ) in KB/sec assuming only one player is downloading the map - uint32_t MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); + quint32 MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); while( (*i)->GetLastMapPartSent( ) < (*i)->GetLastMapPartAcked( ) + 1442 * 100 && (*i)->GetLastMapPartSent( ) < MapSize ) { @@ -932,7 +932,7 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) if( message.size( ) > 127 ) message = message.mid( 0, 127 ); - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateBYTEARRAY( (uint32_t)0, false ), message ) ); + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateBYTEARRAY( (quint32)0, false ), message ) ); if( m_Replay ) m_Replay->AddChatMessage( fromPID, 32, 0, message ); @@ -1055,7 +1055,7 @@ void CBaseGame :: SendAllActions( ) CIncomingAction *Action = m_Actions.front( ); m_Actions.dequeue( ); SubActions.enqueue( Action ); - uint32_t SubActionsLength = Action->GetLength( ); + quint32 SubActionsLength = Action->GetLength( ); while( !m_Actions.isEmpty( ) ) { @@ -1107,8 +1107,8 @@ void CBaseGame :: SendAllActions( ) m_Replay->AddTimeSlot( m_Latency, m_Actions ); } - uint32_t ActualSendInterval = GetTicks( ) - m_LastActionSentTicks; - uint32_t ExpectedSendInterval = m_Latency - m_LastActionLateBy; + quint32 ActualSendInterval = GetTicks( ) - m_LastActionSentTicks; + quint32 ExpectedSendInterval = m_Latency - m_LastActionLateBy; m_LastActionLateBy = ActualSendInterval - ExpectedSendInterval; if( m_LastActionLateBy > m_Latency ) @@ -1569,9 +1569,9 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) if( GetTime( ) - player->GetLastGProxyWaitNoticeSentTime( ) >= 20 ) { - uint32_t TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60 - ( GetTime( ) - m_StartedLaggingTime ); + quint32 TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60 - ( GetTime( ) - m_StartedLaggingTime ); - if( TimeRemaining > ( (uint32_t)m_GProxyEmptyActions + 1 ) * 60 ) + if( TimeRemaining > ( (quint32)m_GProxyEmptyActions + 1 ) * 60 ) TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); @@ -1601,9 +1601,9 @@ void CBaseGame :: EventPlayerDisconnectConnectionClosed( CGamePlayer *player ) if( GetTime( ) - player->GetLastGProxyWaitNoticeSentTime( ) >= 20 ) { - uint32_t TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60 - ( GetTime( ) - m_StartedLaggingTime ); + quint32 TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60 - ( GetTime( ) - m_StartedLaggingTime ); - if( TimeRemaining > ( (uint32_t)m_GProxyEmptyActions + 1 ) * 60 ) + if( TimeRemaining > ( (quint32)m_GProxyEmptyActions + 1 ) * 60 ) TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); @@ -1659,7 +1659,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // the client sends the host counter when it joins so we can extract the ID value here // note: this is not a replacement for spoof checking since it doesn't verify the player's name and it can be spoofed anyway - uint32_t HostCounterID = joinPlayer->GetHostCounter( ) >> 28; + quint32 HostCounterID = joinPlayer->GetHostCounter( ) >> 28; QString JoinedRealm; // we use an ID value of 0 to denote joining via LAN @@ -1702,7 +1702,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((quint16)potential->GetSocket( )->localPort(), false), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; } @@ -1730,7 +1730,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((uint16_t)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((quint16)potential->GetSocket( )->localPort(), false), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->SetDeleteMe( true ); return; } @@ -1977,7 +1977,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((quint16)Player->GetSocket( )->localPort(), false), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2162,7 +2162,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // this ensures that the players' scores will tend to converge as players join the game double AverageScore = 0.0; - uint32_t PlayersScored = 0; + quint32 PlayersScored = 0; if( score > -99999.0 ) { @@ -2319,7 +2319,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // the client sends the host counter when it joins so we can extract the ID value here // note: this is not a replacement for spoof checking since it doesn't verify the player's name and it can be spoofed anyway - uint32_t HostCounterID = joinPlayer->GetHostCounter( ) >> 28; + quint32 HostCounterID = joinPlayer->GetHostCounter( ) >> 28; QString JoinedRealm; // we use an ID value of 0 to denote joining via LAN @@ -2356,7 +2356,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((uint16_t)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((quint16)Player->GetSocket( )->localPort(), false), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2428,8 +2428,8 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco else SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), UTIL_ToString( score, 2 ) ) ); - uint32_t PlayersScored = 0; - uint32_t PlayersNotScored = 0; + quint32 PlayersScored = 0; + quint32 PlayersNotScored = 0; double AverageScore = 0.0; double MinScore = 0.0; double MaxScore = 0.0; @@ -2458,7 +2458,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco } double Spread = MaxScore - MinScore; - SendAllChat( m_GHost->m_Language->RatedPlayersSpread( UTIL_ToString( PlayersScored ), UTIL_ToString( PlayersScored + PlayersNotScored ), UTIL_ToString( (uint32_t)Spread ) ) ); + SendAllChat( m_GHost->m_Language->RatedPlayersSpread( UTIL_ToString( PlayersScored ), UTIL_ToString( PlayersScored + PlayersNotScored ), UTIL_ToString( (quint32)Spread ) ) ); // check for multiple IP usage @@ -2503,7 +2503,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco BalanceSlots( ); } -void CBaseGame :: EventPlayerLeft( CGamePlayer *player, uint32_t reason ) +void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) { // this function is only called when a player leave packet is received, not when there's a socket error, kick, etc... @@ -2589,7 +2589,7 @@ void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *actio } } -void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, uint32_t /*checkSum*/ ) +void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*checkSum*/ ) { // check for desyncs // however, it's possible that not every player has sent a checksum for this frame yet @@ -2604,7 +2604,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, uint32_t /*chec // now we check for desyncs since we know that every player has at least one checksum waiting bool FoundPlayer = false; - uint32_t FirstCheckSum = 0; + quint32 FirstCheckSum = 0; for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -2632,7 +2632,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, uint32_t /*chec // this is complicated by the fact that we don't know what the correct game state is so we let the players vote // put the players into bins based on their game state - QMap > Bins; + QMap > Bins; for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { @@ -2640,11 +2640,11 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, uint32_t /*chec Bins[(*j)->GetCheckSums( )->front( )].push_back( (*j)->GetPID( ) ); } - uint32_t StateNumber = 1; - QMap > :: iterator LargestBin = Bins.begin( ); + quint32 StateNumber = 1; + QMap > :: iterator LargestBin = Bins.begin( ); bool Tied = false; - for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) + for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { if( j.value().size( ) > LargestBin.value().size( ) ) { @@ -2692,7 +2692,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, uint32_t /*chec { CONSOLE_Print( "[GAME: " + m_GameName + "] kicking desynced players" ); - for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) + for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { // kick players who are NOT in the largest bin // examples: suppose there are 10 players @@ -2999,7 +2999,7 @@ void CBaseGame :: EventPlayerDropRequest( CGamePlayer *player ) // check if at least half the players voted to drop - uint32_t Votes = 0; + quint32 Votes = 0; for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -3019,7 +3019,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map // todotodo: the variable names here are confusing due to extremely poor design on my part - uint32_t MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); + quint32 MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); if( mapSize->GetSizeFlag( ) != 1 || mapSize->GetMapSize( ) != MapSize ) { @@ -3131,7 +3131,7 @@ void CBaseGame::EventCallableUpdateTimeout() } } -void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, uint32_t /*pong*/ ) +void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, quint32 /*pong*/ ) { // autokick players with excessive pings but only if they're not reserved and we've received at least 3 pings from them // also don't kick anyone if the game is loading or loaded - this could happen because we send pings during loading but we stop sending them after the game is loaded @@ -3191,7 +3191,7 @@ void CBaseGame :: EventGameStarted( ) unsigned char EncodingMap[256]; unsigned char j = 0; - for( uint32_t i = 0; i < 256; i++ ) + for( quint32 i = 0; i < 256; i++ ) { // the following 7 handicap values are forbidden @@ -3287,7 +3287,7 @@ void CBaseGame :: EventGameStarted( ) if( m_SaveGame ) { - uint32_t MapGameType = MAPGAMETYPE_SAVEDGAME; + quint32 MapGameType = MAPGAMETYPE_SAVEDGAME; if( m_GameState == GAME_PRIVATE ) MapGameType |= MAPGAMETYPE_PRIVATEGAME; @@ -3296,7 +3296,7 @@ void CBaseGame :: EventGameStarted( ) } else { - uint32_t MapGameType = m_Map->GetMapGameType( ); + quint32 MapGameType = m_Map->GetMapGameType( ); MapGameType |= MAPGAMETYPE_UNKNOWN0; if( m_GameState == GAME_PRIVATE ) @@ -3458,10 +3458,10 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) return NULL; } -uint32_t CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **player ) +quint32 CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **player ) { name = name.toLower(); - uint32_t Matches = 0; + quint32 Matches = 0; *player = NULL; // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") @@ -4135,8 +4135,8 @@ void CBaseGame :: BalanceSlots( ) // 4 teams of 2 = 2520 ~ 30ms *** ok // 4 teams of 3 = 369600 ~ 3500ms *** unacceptable - uint32_t AlgorithmCost = 0; - uint32_t PlayersLeft = PlayerIDs.size( ); + quint32 AlgorithmCost = 0; + quint32 PlayersLeft = PlayerIDs.size( ); for( unsigned char i = 0; i < 12; i++ ) { @@ -4162,9 +4162,9 @@ void CBaseGame :: BalanceSlots( ) return; } - uint32_t StartTicks = GetTicks( ); + quint32 StartTicks = GetTicks( ); QVector BestOrdering = BalanceSlotsRecursive( PlayerIDs, TeamSizes, PlayerScores, 0 ); - uint32_t EndTicks = GetTicks( ); + quint32 EndTicks = GetTicks( ); // the BestOrdering assumes the teams are in slot order although this may not be the case // so put the players on the correct teams regardless of slot order diff --git a/ghost/game_base.h b/ghost/game_base.h index e5debef..75e5732 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -106,7 +106,7 @@ public slots: CReplay *m_Replay; // replay bool m_Exiting; // set to true and this class will be deleted next update bool m_Saving; // if we're currently saving game data to the database - uint16_t m_HostPort; // the port to host games on + quint16 m_HostPort; // the port to host games on unsigned char m_GameState; // game state, public or private unsigned char m_VirtualHostPID; // virtual host's PID unsigned char m_FakePlayerPID; // the fake player's PID (if present) @@ -121,25 +121,25 @@ public slots: QString m_StatString; // the stat QString when the game started (used when saving replays) QString m_KickVotePlayer; // the player to be kicked with the currently running kick vote QString m_HCLCommandString; // the "HostBot Command Library" command QString, used to pass a limited amount of data to specially designed maps - uint32_t m_WaitTime; - uint32_t m_RandomSeed; // the random seed sent to the Warcraft III clients - uint32_t m_HostCounter; // a unique game number - uint32_t m_Latency; // the number of ms to wait between sending action packets (we queue any received during this time) - uint32_t m_SyncLimit; // the maximum number of packets a player can fall out of sync before starting the lag screen - uint32_t m_SyncCounter; // the number of actions sent so far (for determining if anyone is lagging) - uint32_t m_GameTicks; // ingame ticks - uint32_t m_CreationTime; // GetTime when the game was created - uint32_t m_LastDownloadTicks; // GetTicks when the last map download cycle was performed - uint32_t m_DownloadCounter; // # of map bytes downloaded in the last second - uint32_t m_AutoStartPlayers; // auto start the game when there are this many players or more - uint32_t m_CountDownCounter; // the countdown is finished when this reaches zero - uint32_t m_StartedLoadingTicks; // GetTicks when the game started loading - uint32_t m_StartPlayers; // number of players when the game started - uint32_t m_LastActionSentTicks; // GetTicks when the last action packet was sent - uint32_t m_LastActionLateBy; // the number of ticks we were late sending the last action packet by - uint32_t m_StartedLaggingTime; // GetTime when the last lag screen started - uint32_t m_LastLagScreenTime; // GetTime when the last lag screen was active (continuously updated) - uint32_t m_LastPlayerLeaveTicks; // GetTicks when the most recent player left the game + quint32 m_WaitTime; + quint32 m_RandomSeed; // the random seed sent to the Warcraft III clients + quint32 m_HostCounter; // a unique game number + quint32 m_Latency; // the number of ms to wait between sending action packets (we queue any received during this time) + quint32 m_SyncLimit; // the maximum number of packets a player can fall out of sync before starting the lag screen + quint32 m_SyncCounter; // the number of actions sent so far (for determining if anyone is lagging) + quint32 m_GameTicks; // ingame ticks + quint32 m_CreationTime; // GetTime when the game was created + quint32 m_LastDownloadTicks; // GetTicks when the last map download cycle was performed + quint32 m_DownloadCounter; // # of map bytes downloaded in the last second + quint32 m_AutoStartPlayers; // auto start the game when there are this many players or more + quint32 m_CountDownCounter; // the countdown is finished when this reaches zero + quint32 m_StartedLoadingTicks; // GetTicks when the game started loading + quint32 m_StartPlayers; // number of players when the game started + quint32 m_LastActionSentTicks; // GetTicks when the last action packet was sent + quint32 m_LastActionLateBy; // the number of ticks we were late sending the last action packet by + quint32 m_StartedLaggingTime; // GetTime when the last lag screen started + quint32 m_LastLagScreenTime; // GetTime when the last lag screen was active (continuously updated) + quint32 m_LastPlayerLeaveTicks; // GetTicks when the most recent player left the game double m_MinimumScore; // the minimum allowed score for matchmaking mode double m_MaximumScore; // the maximum allowed score for matchmaking mode bool m_Locked; // if the game owner is the only one allowed to run game commands or not @@ -158,13 +158,13 @@ public slots: bool m_LocalAdminMessages; // if local admin messages should be relayed or not public: - CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); + CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CBaseGame( ); virtual QVector GetEnforceSlots( ) { return m_EnforceSlots; } virtual QVector GetEnforcePlayers( ) { return m_EnforcePlayers; } virtual CSaveGame *GetSaveGame( ) { return m_SaveGame; } - virtual uint16_t GetHostPort( ) { return m_HostPort; } + virtual quint16 GetHostPort( ) { return m_HostPort; } virtual unsigned char GetGameState( ) { return m_GameState; } virtual unsigned char GetGProxyEmptyActions( ) { return m_GProxyEmptyActions; } virtual QString GetGameName( ) { return m_GameName; } @@ -173,10 +173,10 @@ public slots: virtual QString GetOwnerName( ) { return m_OwnerName; } virtual QString GetCreatorName( ) { return m_CreatorName; } virtual QString GetCreatorServer( ) { return m_CreatorServer; } - virtual uint32_t GetHostCounter( ) { return m_HostCounter; } - virtual uint32_t GetLastLagScreenTime( ) { return m_LastLagScreenTime; } - virtual uint32_t GetStartedLaggingTime( ) { return m_StartedLaggingTime; } - virtual uint32_t GetAutoStartPlayers( ) { return m_AutoStartPlayers; } + virtual quint32 GetHostCounter( ) { return m_HostCounter; } + virtual quint32 GetLastLagScreenTime( ) { return m_LastLagScreenTime; } + virtual quint32 GetStartedLaggingTime( ) { return m_StartedLaggingTime; } + virtual quint32 GetAutoStartPlayers( ) { return m_AutoStartPlayers; } virtual bool GetLocked( ) { return m_Locked; } virtual bool GetRefreshMessages( ) { return m_RefreshMessages; } virtual bool GetCountDownStarted( ) { return m_CountDownStarted; } @@ -188,19 +188,19 @@ public slots: virtual void SetEnforceSlots( QVector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } virtual void SetEnforcePlayers( QVector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } virtual void SetExiting( bool nExiting ) { m_Exiting = nExiting; } - virtual void SetAutoStartPlayers( uint32_t nAutoStartPlayers ) { m_AutoStartPlayers = nAutoStartPlayers; } + virtual void SetAutoStartPlayers( quint32 nAutoStartPlayers ) { m_AutoStartPlayers = nAutoStartPlayers; } virtual void SetMinimumScore( double nMinimumScore ) { m_MinimumScore = nMinimumScore; } virtual void SetMaximumScore( double nMaximumScore ) { m_MaximumScore = nMaximumScore; } virtual void SetMatchMaking( bool nMatchMaking ) { m_MatchMaking = nMatchMaking; } - virtual uint32_t GetNextTimedActionTicks( ); - virtual uint32_t GetSlotsOccupied( ); - virtual uint32_t GetSlotsOpen( ); - virtual uint32_t GetNumPlayers( ); - virtual uint32_t GetNumHumanPlayers( ); + virtual quint32 GetNextTimedActionTicks( ); + virtual quint32 GetSlotsOccupied( ); + virtual quint32 GetSlotsOpen( ); + virtual quint32 GetNumPlayers( ); + virtual quint32 GetNumHumanPlayers( ); virtual QString GetDescription( ); - virtual void SetAnnounce( uint32_t interval, QString message ); + virtual void SetAnnounce( quint32 interval, QString message ); // generic functions to send packets to players @@ -234,9 +234,9 @@ public slots: virtual void EventPlayerDisconnectConnectionClosed( CGamePlayer *player ); virtual void EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer ); virtual void EventPlayerJoinedWithScore( CPotentialPlayer *potential, CIncomingJoinPlayer *joinPlayer, double score ); - virtual void EventPlayerLeft( CGamePlayer *player, uint32_t reason ); + virtual void EventPlayerLeft( CGamePlayer *player, quint32 reason ); virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); - virtual void EventPlayerKeepAlive( CGamePlayer *player, uint32_t checkSum ); + virtual void EventPlayerKeepAlive( CGamePlayer *player, quint32 checkSum ); virtual void EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlayer *chatPlayer ); virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); virtual void EventPlayerChangeTeam( CGamePlayer *player, unsigned char team ); @@ -245,7 +245,7 @@ public slots: virtual void EventPlayerChangeHandicap( CGamePlayer *player, unsigned char handicap ); virtual void EventPlayerDropRequest( CGamePlayer *player ); virtual void EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *mapSize ); - virtual void EventPlayerPongToHost( CGamePlayer *player, uint32_t pong ); + virtual void EventPlayerPongToHost( CGamePlayer *player, quint32 pong ); // these events are called outside of any iterations @@ -259,7 +259,7 @@ public slots: virtual CGamePlayer *GetPlayerFromPID( unsigned char PID ); virtual CGamePlayer *GetPlayerFromSID( unsigned char SID ); virtual CGamePlayer *GetPlayerFromName( QString name, bool sensitive ); - virtual uint32_t GetPlayerFromNamePartial( QString name, CGamePlayer **player ); + virtual quint32 GetPlayerFromNamePartial( QString name, CGamePlayer **player ); virtual CGamePlayer *GetPlayerFromColour( unsigned char colour ); virtual unsigned char GetNewPID( ); virtual unsigned char GetNewColour( ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 574cdbc..3a7fc23 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -151,7 +151,7 @@ void CGamePlayer::EventConnectionClosed() QByteArray CPotentialPlayer :: GetExternalIP( ) { if( m_Socket ) - return UTIL_CreateBYTEARRAY((uint32_t)m_Socket->localAddress().toIPv4Address()); + return UTIL_CreateBYTEARRAY((quint32)m_Socket->localAddress().toIPv4Address(), false); unsigned char Zeros[] = { 0, 0, 0, 0 }; return QByteArray( (char*)Zeros, 4 ); @@ -188,7 +188,7 @@ void CPotentialPlayer :: ExtractPackets( ) // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); + quint16 Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); if( Length < 4 ) { @@ -400,9 +400,9 @@ CGamePlayer :: ~CGamePlayer( ) void CGamePlayer::EventSendGProxyMessage() { - uint32_t TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60 - ( GetTime( ) - m_Game->GetStartedLaggingTime() ); + quint32 TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60 - ( GetTime( ) - m_Game->GetStartedLaggingTime() ); - if( TimeRemaining > ( (uint32_t)m_Game->GetGProxyEmptyActions() + 1 ) * 60 ) + if( TimeRemaining > ( (quint32)m_Game->GetGProxyEmptyActions() + 1 ) * 60 ) TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60; m_Game->SendAllChat( GetPID( ), m_Game->m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); @@ -424,14 +424,14 @@ QString CGamePlayer :: GetNameTerminated( ) return m_Name; } -uint32_t CGamePlayer :: GetPing( bool LCPing ) +quint32 CGamePlayer :: GetPing( bool LCPing ) { // just average all the pings in the vector, nothing fancy if( m_Pings.isEmpty( ) ) return 0; - uint32_t AvgPing = 0; + quint32 AvgPing = 0; for( int i = 0; i < m_Pings.size( ); i++ ) AvgPing += m_Pings[i]; @@ -469,7 +469,7 @@ void CGamePlayer :: ExtractPackets( ) // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); + quint16 Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); if( Length < 4 ) { @@ -500,8 +500,8 @@ void CGamePlayer :: ProcessPackets( ) CIncomingAction *Action = NULL; CIncomingChatPlayer *ChatPlayer = NULL; CIncomingMapSize *MapSize = NULL; - uint32_t CheckSum = 0; - uint32_t Pong = 0; + quint32 CheckSum = 0; + quint32 Pong = 0; // process all the received packets in the m_Packets queue @@ -674,13 +674,13 @@ void CGamePlayer :: Send( QByteArray data ) CPotentialPlayer :: Send( data ); } -void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, uint32_t LastPacket ) +void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPacket ) { delete m_Socket; m_Socket = NewSocket; m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_RECONNECT( m_TotalPacketsReceived ) ); - uint32_t PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); + quint32 PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); if( LastPacket > PacketsAlreadyUnqueued ) { diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index 727e68a..3b414b6 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -118,26 +118,26 @@ public slots: unsigned char m_PID; QString m_Name; // the player's name QByteArray m_InternalIP; // the player's internal IP address as reported by the player when connecting - QVector m_Pings; // store the last few (20) pings received so we can take an average - QQueue m_CheckSums; // the last few checksums the player has sent (for detecting desyncs) + QVector m_Pings; // store the last few (20) pings received so we can take an average + QQueue m_CheckSums; // the last few checksums the player has sent (for detecting desyncs) QString m_LeftReason; // the reason the player left the game QString m_SpoofedRealm; // the realm the player last spoof checked on QString m_JoinedRealm; // the realm the player joined on (probable, can be spoofed) - uint32_t m_TotalPacketsSent; - uint32_t m_TotalPacketsReceived; - uint32_t m_LeftCode; // the code to be sent in W3GS_PLAYERLEAVE_OTHERS for why this player left the game - uint32_t m_LoginAttempts; // the number of attempts to login (used with CAdminGame only) - uint32_t m_SyncCounter; // the number of keepalive packets received from this player - uint32_t m_JoinTime; // GetTime when the player joined the game (used to delay sending the /whois a few seconds to allow for some lag) - uint32_t m_LastMapPartSent; // the last mappart sent to the player (for sending more than one part at a time) - uint32_t m_LastMapPartAcked; // the last mappart acknowledged by the player - uint32_t m_StartedDownloadingTicks; // GetTicks when the player started downloading the map - uint32_t m_FinishedDownloadingTime; // GetTime when the player finished downloading the map - uint32_t m_FinishedLoadingTicks; // GetTicks when the player finished loading the game - uint32_t m_StartedLaggingTicks; // GetTicks when the player started lagging - uint32_t m_StatsSentTime; // GetTime when we sent this player's stats to the chat (to prevent players from spamming !stats) - uint32_t m_StatsDotASentTime; // GetTime when we sent this player's dota stats to the chat (to prevent players from spamming !statsdota) - uint32_t m_LastGProxyWaitNoticeSentTime; + quint32 m_TotalPacketsSent; + quint32 m_TotalPacketsReceived; + quint32 m_LeftCode; // the code to be sent in W3GS_PLAYERLEAVE_OTHERS for why this player left the game + quint32 m_LoginAttempts; // the number of attempts to login (used with CAdminGame only) + quint32 m_SyncCounter; // the number of keepalive packets received from this player + quint32 m_JoinTime; // GetTime when the player joined the game (used to delay sending the /whois a few seconds to allow for some lag) + quint32 m_LastMapPartSent; // the last mappart sent to the player (for sending more than one part at a time) + quint32 m_LastMapPartAcked; // the last mappart acknowledged by the player + quint32 m_StartedDownloadingTicks; // GetTicks when the player started downloading the map + quint32 m_FinishedDownloadingTime; // GetTime when the player finished downloading the map + quint32 m_FinishedLoadingTicks; // GetTicks when the player finished loading the game + quint32 m_StartedLaggingTicks; // GetTicks when the player started lagging + quint32 m_StatsSentTime; // GetTime when we sent this player's stats to the chat (to prevent players from spamming !stats) + quint32 m_StatsDotASentTime; // GetTime when we sent this player's dota stats to the chat (to prevent players from spamming !statsdota) + quint32 m_LastGProxyWaitNoticeSentTime; QQueue m_LoadInGameData; // queued data to be sent when the player finishes loading when using "load in game" double m_Score; // the player's generic "score" for the matchmaking algorithm bool m_LoggedIn; // if the player has logged in or not (used with CAdminGame only) @@ -157,8 +157,8 @@ public slots: bool m_GProxy; // if the player is using GProxy++ bool m_GProxyDisconnectNoticeSent; // if a disconnection notice has been sent or not when using GProxy++ QQueue m_GProxyBuffer; - uint32_t m_GProxyReconnectKey; - uint32_t m_LastGProxyAckTime; + quint32 m_GProxyReconnectKey; + quint32 m_LastGProxyAckTime; public: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); @@ -170,23 +170,23 @@ public slots: QByteArray GetInternalIP( ) { return m_InternalIP; } unsigned int GetNumPings( ) { return m_Pings.size( ); } unsigned int GetNumCheckSums( ) { return m_CheckSums.size( ); } - QQueue *GetCheckSums( ) { return &m_CheckSums; } + QQueue *GetCheckSums( ) { return &m_CheckSums; } QString GetLeftReason( ) { return m_LeftReason; } QString GetSpoofedRealm( ) { return m_SpoofedRealm; } QString GetJoinedRealm( ) { return m_JoinedRealm; } - uint32_t GetLeftCode( ) { return m_LeftCode; } - uint32_t GetLoginAttempts( ) { return m_LoginAttempts; } - uint32_t GetSyncCounter( ) { return m_SyncCounter; } - uint32_t GetJoinTime( ) { return m_JoinTime; } - uint32_t GetLastMapPartSent( ) { return m_LastMapPartSent; } - uint32_t GetLastMapPartAcked( ) { return m_LastMapPartAcked; } - uint32_t GetStartedDownloadingTicks( ) { return m_StartedDownloadingTicks; } - uint32_t GetFinishedDownloadingTime( ) { return m_FinishedDownloadingTime; } - uint32_t GetFinishedLoadingTicks( ) { return m_FinishedLoadingTicks; } - uint32_t GetStartedLaggingTicks( ) { return m_StartedLaggingTicks; } - uint32_t GetStatsSentTime( ) { return m_StatsSentTime; } - uint32_t GetStatsDotASentTime( ) { return m_StatsDotASentTime; } - uint32_t GetLastGProxyWaitNoticeSentTime( ) { return m_LastGProxyWaitNoticeSentTime; } + quint32 GetLeftCode( ) { return m_LeftCode; } + quint32 GetLoginAttempts( ) { return m_LoginAttempts; } + quint32 GetSyncCounter( ) { return m_SyncCounter; } + quint32 GetJoinTime( ) { return m_JoinTime; } + quint32 GetLastMapPartSent( ) { return m_LastMapPartSent; } + quint32 GetLastMapPartAcked( ) { return m_LastMapPartAcked; } + quint32 GetStartedDownloadingTicks( ) { return m_StartedDownloadingTicks; } + quint32 GetFinishedDownloadingTime( ) { return m_FinishedDownloadingTime; } + quint32 GetFinishedLoadingTicks( ) { return m_FinishedLoadingTicks; } + quint32 GetStartedLaggingTicks( ) { return m_StartedLaggingTicks; } + quint32 GetStatsSentTime( ) { return m_StatsSentTime; } + quint32 GetStatsDotASentTime( ) { return m_StatsDotASentTime; } + quint32 GetLastGProxyWaitNoticeSentTime( ) { return m_LastGProxyWaitNoticeSentTime; } QQueue *GetLoadInGameData( ) { return &m_LoadInGameData; } double GetScore( ) { return m_Score; } bool GetLoggedIn( ) { return m_LoggedIn; } @@ -205,21 +205,21 @@ public slots: bool GetLeftMessageSent( ) { return m_LeftMessageSent; } bool GetGProxy( ) { return m_GProxy; } bool GetGProxyDisconnectNoticeSent( ) { return m_GProxyDisconnectNoticeSent; } - uint32_t GetGProxyReconnectKey( ) { return m_GProxyReconnectKey; } + quint32 GetGProxyReconnectKey( ) { return m_GProxyReconnectKey; } void SetLeftReason( QString nLeftReason ) { m_LeftReason = nLeftReason; } void SetSpoofedRealm( QString nSpoofedRealm ) { m_SpoofedRealm = nSpoofedRealm; } - void SetLeftCode( uint32_t nLeftCode ) { m_LeftCode = nLeftCode; } - void SetLoginAttempts( uint32_t nLoginAttempts ) { m_LoginAttempts = nLoginAttempts; } - void SetSyncCounter( uint32_t nSyncCounter ) { m_SyncCounter = nSyncCounter; } - void SetLastMapPartSent( uint32_t nLastMapPartSent ) { m_LastMapPartSent = nLastMapPartSent; } - void SetLastMapPartAcked( uint32_t nLastMapPartAcked ) { m_LastMapPartAcked = nLastMapPartAcked; } - void SetStartedDownloadingTicks( uint32_t nStartedDownloadingTicks ) { m_StartedDownloadingTicks = nStartedDownloadingTicks; } - void SetFinishedDownloadingTime( uint32_t nFinishedDownloadingTime ) { m_FinishedDownloadingTime = nFinishedDownloadingTime; } - void SetStartedLaggingTicks( uint32_t nStartedLaggingTicks ) { m_StartedLaggingTicks = nStartedLaggingTicks; } - void SetStatsSentTime( uint32_t nStatsSentTime ) { m_StatsSentTime = nStatsSentTime; } - void SetStatsDotASentTime( uint32_t nStatsDotASentTime ) { m_StatsDotASentTime = nStatsDotASentTime; } - void SetLastGProxyWaitNoticeSentTime( uint32_t nLastGProxyWaitNoticeSentTime ) { m_LastGProxyWaitNoticeSentTime = nLastGProxyWaitNoticeSentTime; } + void SetLeftCode( quint32 nLeftCode ) { m_LeftCode = nLeftCode; } + void SetLoginAttempts( quint32 nLoginAttempts ) { m_LoginAttempts = nLoginAttempts; } + void SetSyncCounter( quint32 nSyncCounter ) { m_SyncCounter = nSyncCounter; } + void SetLastMapPartSent( quint32 nLastMapPartSent ) { m_LastMapPartSent = nLastMapPartSent; } + void SetLastMapPartAcked( quint32 nLastMapPartAcked ) { m_LastMapPartAcked = nLastMapPartAcked; } + void SetStartedDownloadingTicks( quint32 nStartedDownloadingTicks ) { m_StartedDownloadingTicks = nStartedDownloadingTicks; } + void SetFinishedDownloadingTime( quint32 nFinishedDownloadingTime ) { m_FinishedDownloadingTime = nFinishedDownloadingTime; } + void SetStartedLaggingTicks( quint32 nStartedLaggingTicks ) { m_StartedLaggingTicks = nStartedLaggingTicks; } + void SetStatsSentTime( quint32 nStatsSentTime ) { m_StatsSentTime = nStatsSentTime; } + void SetStatsDotASentTime( quint32 nStatsDotASentTime ) { m_StatsDotASentTime = nStatsDotASentTime; } + void SetLastGProxyWaitNoticeSentTime( quint32 nLastGProxyWaitNoticeSentTime ) { m_LastGProxyWaitNoticeSentTime = nLastGProxyWaitNoticeSentTime; } void SetScore( double nScore ) { m_Score = nScore; } void SetLoggedIn( bool nLoggedIn ) { m_LoggedIn = nLoggedIn; } void SetSpoofed( bool nSpoofed ) { m_Spoofed = nSpoofed; } @@ -236,7 +236,7 @@ public slots: void SetGProxyDisconnectNoticeSent( bool nGProxyDisconnectNoticeSent ) { m_GProxyDisconnectNoticeSent = nGProxyDisconnectNoticeSent; } QString GetNameTerminated( ); - uint32_t GetPing( bool LCPing ); + quint32 GetPing( bool LCPing ); void AddLoadInGameData( QByteArray nLoadInGameData ) { m_LoadInGameData.enqueue( nLoadInGameData ); } @@ -248,7 +248,7 @@ public slots: // other functions virtual void Send( QByteArray data ); - virtual void EventGProxyReconnect( QTcpSocket *NewSocket, uint32_t LastPacket ); + virtual void EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPacket ); }; #endif diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 07bcb01..4bb6853 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -63,7 +63,7 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 20 ) { - uint32_t HostCounter = UTIL_QByteArrayToUInt32( data, false, 4 ); + quint32 HostCounter = UTIL_QByteArrayToUInt32( data, false, 4 ); QByteArray Name = UTIL_ExtractCString( data, 19 ); if( !Name.isEmpty( ) && data.size( ) >= Name.size( ) + 30 ) @@ -76,7 +76,7 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) return NULL; } -uint32_t CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_LEAVEGAME" ); // DEBUG_Print( data ); @@ -125,7 +125,7 @@ CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, return NULL; } -uint32_t CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_OUTGOING_KEEPALIVE" ); // DEBUG_Print( data ); @@ -210,8 +210,8 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char war3Version ) { - uint32_t ProductID = 1462982736; // "W3XP" - uint32_t Version = war3Version; + quint32 ProductID = 1462982736; // "W3XP" + quint32 Version = war3Version; // DEBUG_Print( "RECEIVED W3GS_SEARCHGAME" ); // DEBUG_Print( data ); @@ -254,7 +254,7 @@ CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteA return NULL; } -uint32_t CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_MAPPARTOK" ); // DEBUG_Print( data ); @@ -272,7 +272,7 @@ uint32_t CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) return 0; } -uint32_t CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ) { // DEBUG_Print( "RECEIVED W3GS_PONG_TO_HOST" ); // DEBUG_Print( data ); @@ -309,7 +309,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; @@ -322,7 +322,7 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArra packet.push_back( W3GS_SLOTINFOJOIN ); // W3GS_SLOTINFOJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length + UTIL_AppendBYTEARRAY( packet, (quint16)SlotInfo.size( ), false ); // SlotInfo length UTIL_AppendBYTEARRAYFast( packet, SlotInfo ); // SlotInfo packet.push_back( PID ); // PID packet.push_back( 2 ); // AF_INET @@ -343,7 +343,7 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArra return packet; } -QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( uint32_t reason ) +QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( quint32 reason ) { QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -399,7 +399,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString nam return packet; } -QByteArray CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ) +QByteArray CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, quint32 leftCode ) { QByteArray packet; @@ -442,7 +442,7 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; @@ -450,7 +450,7 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, uint packet.push_back( W3GS_SLOTINFO ); // W3GS_SLOTINFO packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, (uint16_t)SlotInfo.size( ), false ); // SlotInfo length + UTIL_AppendBYTEARRAY( packet, (quint16)SlotInfo.size( ), false ); // SlotInfo length UTIL_AppendBYTEARRAYFast( packet, SlotInfo ); // SlotInfo AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SLOTINFO" ); @@ -484,7 +484,7 @@ QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue actions, uint16_t sendInterval ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue actions, quint16 sendInterval ) { QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -504,7 +504,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue CIncomingAction *Action = actions.front( ); actions.dequeue( ); subpacket.push_back( Action->GetPID( ) ); - UTIL_AppendBYTEARRAY( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAY( subpacket, (quint16)Action->GetAction( )->size( ), false ); UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); } @@ -586,7 +586,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, if( !(*i)->GetFinishedLoading( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendBYTEARRAY( packet, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( packet, (quint32)0, false ); } } else @@ -619,7 +619,7 @@ QByteArray CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadIn packet.push_back( player->GetPID( ) ); if( loadInGame ) - UTIL_AppendBYTEARRAY( packet, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( packet, (quint32)0, false ); else UTIL_AppendBYTEARRAY( packet, GetTicks( ) - player->GetStartedLaggingTicks( ), false ); @@ -655,7 +655,7 @@ QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Ve return packet; } -QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ) +QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ) { unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" @@ -741,7 +741,7 @@ QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Ve return packet; } -QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( quint32 players, quint32 playerSlots ) { unsigned char HostCounter[] = { 1, 0, 0, 0 }; @@ -820,7 +820,7 @@ QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, QString *mapData ) +QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QString *mapData ) { unsigned char Unknown[] = { 1, 0, 0, 0 }; @@ -839,7 +839,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c // calculate end position (don't send more than 1442 map bytes in one packet) - uint32_t End = start + 1442; + quint32 End = start + 1442; if( End > (unsigned int)mapData->size( ) ) End = mapData->size( ); @@ -884,7 +884,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueueGetPID( ) ); - UTIL_AppendBYTEARRAY( subpacket, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAY( subpacket, (quint16)Action->GetAction( )->size( ), false ); UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); } @@ -917,7 +917,7 @@ bool CGameProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -930,7 +930,7 @@ bool CGameProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length - uint16_t Length; + quint16 Length; QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) @@ -946,7 +946,7 @@ bool CGameProtocol :: ValidateLength( QByteArray &content ) return false; } -QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo; SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots @@ -964,7 +964,7 @@ QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, uint32_t // CIncomingJoinPlayer // -CIncomingJoinPlayer :: CIncomingJoinPlayer( uint32_t nHostCounter, QString nName, QByteArray &nInternalIP ) +CIncomingJoinPlayer :: CIncomingJoinPlayer( quint32 nHostCounter, QString nName, QByteArray &nInternalIP ) { m_HostCounter = nHostCounter; m_Name = nName; @@ -1041,7 +1041,7 @@ CIncomingChatPlayer :: ~CIncomingChatPlayer( ) // CIncomingMapSize // -CIncomingMapSize :: CIncomingMapSize( unsigned char nSizeFlag, uint32_t nMapSize ) +CIncomingMapSize :: CIncomingMapSize( unsigned char nSizeFlag, quint32 nMapSize ) { m_SizeFlag = nSizeFlag; m_MapSize = nMapSize; diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index d0d0909..7525aef 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -48,8 +48,11 @@ #define REJECTJOIN_STARTED 10 #define REJECTJOIN_WRONGPASSWORD 27 +#include +#include "includes.h" #include "gameslot.h" +class CGHost; class CGamePlayer; class CIncomingJoinPlayer; class CIncomingAction; @@ -107,39 +110,39 @@ class CGameProtocol // receive functions CIncomingJoinPlayer *RECEIVE_W3GS_REQJOIN( QByteArray data ); - uint32_t RECEIVE_W3GS_LEAVEGAME( QByteArray data ); + quint32 RECEIVE_W3GS_LEAVEGAME( QByteArray data ); bool RECEIVE_W3GS_GAMELOADED_SELF( QByteArray data ); CIncomingAction *RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, unsigned char PID ); - uint32_t RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ); + quint32 RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ); CIncomingChatPlayer *RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data ); bool RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char war3Version ); CIncomingMapSize *RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray mapSize ); - uint32_t RECEIVE_W3GS_MAPPARTOK( QByteArray data ); - uint32_t RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ); + quint32 RECEIVE_W3GS_MAPPARTOK( QByteArray data ); + quint32 RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ); // send functions QByteArray SEND_W3GS_PING_FROM_HOST( ); - QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); - QByteArray SEND_W3GS_REJECTJOIN( uint32_t reason ); + QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_REJECTJOIN( quint32 reason ); QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ); - QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, uint32_t leftCode ); + QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, quint32 leftCode ); QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); - QByteArray SEND_W3GS_SLOTINFO( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFO( QVector &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_COUNTDOWN_START( ); QByteArray SEND_W3GS_COUNTDOWN_END( ); - QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, uint16_t sendInterval ); + QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, quint16 sendInterval ); QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, QString message ); QByteArray SEND_W3GS_START_LAG( QVector players, bool loadInGame = false ); QByteArray SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); QByteArray SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); - QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, uint32_t upTime, QString mapPath, QByteArray mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter ); + QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ); QByteArray SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ); - QByteArray SEND_W3GS_REFRESHGAME( uint32_t players, uint32_t playerSlots ); + QByteArray SEND_W3GS_REFRESHGAME( quint32 players, quint32 playerSlots ); QByteArray SEND_W3GS_DECREATEGAME( ); QByteArray SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); QByteArray SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); - QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, uint32_t start, QString *mapData ); + QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QString *mapData ); QByteArray SEND_W3GS_INCOMING_ACTION2( QQueue actions ); // other functions @@ -147,7 +150,7 @@ class CGameProtocol private: bool AssignLength( QByteArray &content ); bool ValidateLength( QByteArray &content ); - QByteArray EncodeSlotInfo( QVector &slots, uint32_t randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray EncodeSlotInfo( QVector &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); }; // @@ -157,15 +160,15 @@ class CGameProtocol class CIncomingJoinPlayer { private: - uint32_t m_HostCounter; + quint32 m_HostCounter; QString m_Name; QByteArray m_InternalIP; public: - CIncomingJoinPlayer( uint32_t nHostCounter, QString nName, QByteArray &nInternalIP ); + CIncomingJoinPlayer( quint32 nHostCounter, QString nName, QByteArray &nInternalIP ); ~CIncomingJoinPlayer( ); - uint32_t GetHostCounter( ) { return m_HostCounter; } + quint32 GetHostCounter( ) { return m_HostCounter; } QString GetName( ) { return m_Name; } QByteArray GetInternalIP( ) { return m_InternalIP; } }; @@ -188,7 +191,7 @@ class CIncomingAction unsigned char GetPID( ) { return m_PID; } QByteArray GetCRC( ) { return m_CRC; } QByteArray *GetAction( ) { return &m_Action; } - uint32_t GetLength( ) { return m_Action.size( ) + 3; } + quint32 GetLength( ) { return m_Action.size( ) + 3; } }; // @@ -236,14 +239,14 @@ class CIncomingMapSize { private: unsigned char m_SizeFlag; - uint32_t m_MapSize; + quint32 m_MapSize; public: - CIncomingMapSize( unsigned char nSizeFlag, uint32_t nMapSize ); + CIncomingMapSize( unsigned char nSizeFlag, quint32 nMapSize ); ~CIncomingMapSize( ); unsigned char GetSizeFlag( ) { return m_SizeFlag; } - uint32_t GetMapSize( ) { return m_MapSize; } + quint32 GetMapSize( ) { return m_MapSize; } }; #endif diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index fba57c9..c14b428 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -124,7 +124,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) for (int i = 0; i < info.addresses().size(); i++) { CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + info.addresses().at(i).toString() + "]" ); - m_LocalAddresses.push_back( UTIL_CreateBYTEARRAY( (uint32_t)info.addresses().at(i).toIPv4Address() ) ); + m_LocalAddresses.push_back( UTIL_CreateBYTEARRAY( (quint32)info.addresses().at(i).toIPv4Address(), false ) ); } m_Language = NULL; @@ -168,7 +168,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) // load the battle.net connections // we're just loading the config data and creating the CBNET classes here, the connections are established later (in the Update function) - for( uint32_t i = 1; i < 10; i++ ) + for( quint32 i = 1; i < 10; i++ ) { QString Prefix; @@ -184,7 +184,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) QString CountryAbbrev = CFG->GetString( Prefix + "countryabbrev", "USA" ); QString Country = CFG->GetString( Prefix + "country", "United States" ); QString Locale = CFG->GetString( Prefix + "locale", "system" ); - uint32_t LocaleID; + quint32 LocaleID; if( Locale == "system" ) { @@ -217,7 +217,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) QByteArray EXEVersionHash = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversionhash", QString( ) ), 4 ); QString PasswordHashType = CFG->GetString( Prefix + "custom_passwordhashtype", QString( ) ); QString PVPGNRealmName = CFG->GetString( Prefix + "custom_pvpgnrealmname", "PvPGN Realm" ); - uint32_t MaxMessageLength = CFG->GetInt( Prefix + "custom_maxmessagelength", 200 ); + quint32 MaxMessageLength = CFG->GetInt( Prefix + "custom_maxmessagelength", 200 ); if( Server.isEmpty( ) ) break; @@ -257,7 +257,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) #endif } - m_BNETs.push_back( new CBNET( this, Server, ServerAlias, BNLSServer, (uint16_t)BNLSPort, (uint32_t)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger.at(0).toAscii(), HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ) ); + m_BNETs.push_back( new CBNET( this, Server, ServerAlias, BNLSServer, (quint16)BNLSPort, (quint32)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger.at(0).toAscii(), HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ) ); } if( m_BNETs.isEmpty( ) ) @@ -405,7 +405,7 @@ void CGHost::EventReconnectionSocketReadyRead() { // bytes 2 and 3 contain the length of the packet - uint16_t Length = UTIL_QByteArrayToUInt16( con->peek(4), false, 2 ); + quint16 Length = UTIL_QByteArrayToUInt16( con->peek(4), false, 2 ); if( Length < 4 ) { @@ -421,8 +421,8 @@ void CGHost::EventReconnectionSocketReadyRead() if( Bytes.at(0) == CGPSProtocol :: GPS_RECONNECT && Length == 13 ) { unsigned char PID = Bytes.at(4); - uint32_t ReconnectKey = UTIL_QByteArrayToUInt32( Bytes, false, 5 ); - uint32_t LastPacket = UTIL_QByteArrayToUInt32( Bytes, false, 9 ); + quint32 ReconnectKey = UTIL_QByteArrayToUInt32( Bytes, false, 5 ); + quint32 LastPacket = UTIL_QByteArrayToUInt32( Bytes, false, 9 ); // look for a matching player in a running game @@ -874,7 +874,7 @@ void CGHost :: ExtractScripts( ) if( SFileOpenFileEx( PatchMPQ, "Scripts\\common.j", 0, &SubFile ) ) { - uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); + quint32 FileLength = SFileGetFileSize( SubFile, NULL ); if( FileLength > 0 && FileLength != 0xFFFFFFFF ) { @@ -901,7 +901,7 @@ void CGHost :: ExtractScripts( ) if( SFileOpenFileEx( PatchMPQ, "Scripts\\blizzard.j", 0, &SubFile ) ) { - uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); + quint32 FileLength = SFileGetFileSize( SubFile, NULL ); if( FileLength > 0 && FileLength != 0xFFFFFFFF ) { @@ -959,7 +959,7 @@ void CGHost :: LoadIPToCountryData( ) // get length of file for the progress meter - uint32_t FileLength = f.size(); + quint32 FileLength = f.size(); while( !in.atEnd( ) ) { diff --git a/ghost/ghost.h b/ghost/ghost.h index 24a050c..c19efb0 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -86,25 +86,25 @@ public slots: bool m_ExitingNice; // set to true to force ghost to disconnect from all battle.net connections and wait for all games to finish before shutting down bool m_Enabled; // set to false to prevent new games from being created QString m_Version; // GHost++ version QString - uint32_t m_HostCounter; // the current host counter (a unique number to identify a game, incremented each time a game is created) + quint32 m_HostCounter; // the current host counter (a unique number to identify a game, incremented each time a game is created) QString m_AutoHostGameName; // the base game name to auto host with QString m_AutoHostOwner; QString m_AutoHostServer; int m_AutoHostMaximumGames; // maximum number of games to auto host - uint32_t m_AutoHostAutoStartPlayers; // when using auto hosting auto start the game when this many players have joined + quint32 m_AutoHostAutoStartPlayers; // when using auto hosting auto start the game when this many players have joined bool m_AutoHostMatchMaking; double m_AutoHostMinimumScore; double m_AutoHostMaximumScore; bool m_AllGamesFinished; // if all games finished (used when exiting nicely) - uint32_t m_AllGamesFinishedTime; // GetTime when all games finished (used when exiting nicely) + quint32 m_AllGamesFinishedTime; // GetTime when all games finished (used when exiting nicely) QString m_LanguageFile; // config value: language file QString m_Warcraft3Path; // config value: Warcraft 3 path bool m_TFT; // config value: TFT enabled or not QString m_BindAddress; // config value: the address to host games on - uint16_t m_HostPort; // config value: the port to host games on + quint16 m_HostPort; // config value: the port to host games on bool m_Reconnect; // config value: GProxy++ reliable reconnects enabled or not - uint16_t m_ReconnectPort; // config value: the port to listen for GProxy++ reliable reconnects on - uint32_t m_ReconnectWaitTime; // config value: the maximum number of minutes to wait for a GProxy++ reliable reconnect + quint16 m_ReconnectPort; // config value: the port to listen for GProxy++ reliable reconnects on + quint32 m_ReconnectWaitTime; // config value: the maximum number of minutes to wait for a GProxy++ reliable reconnect int m_MaxGames; // config value: maximum number of games in progress char m_CommandTrigger; // config value: the command trigger inside games QString m_MapCFGPath; // config value: map cfg path @@ -115,39 +115,39 @@ public slots: QString m_VirtualHostName; // config value: virtual host name bool m_HideIPAddresses; // config value: hide IP addresses from players bool m_CheckMultipleIPUsage; // config value: check for multiple IP address usage - uint32_t m_SpoofChecks; // config value: do automatic spoof checks or not + quint32 m_SpoofChecks; // config value: do automatic spoof checks or not bool m_RequireSpoofChecks; // config value: require spoof checks or not bool m_ReserveAdmins; // config value: consider admins to be reserved players or not bool m_RefreshMessages; // config value: display refresh messages or not (by default) bool m_AutoLock; // config value: auto lock games when the owner is present bool m_AutoSave; // config value: auto save before someone disconnects - uint32_t m_AllowDownloads; // config value: allow map downloads or not + quint32 m_AllowDownloads; // config value: allow map downloads or not bool m_PingDuringDownloads; // config value: ping during map downloads or not - uint32_t m_MaxDownloaders; // config value: maximum number of map downloaders at the same time - uint32_t m_MaxDownloadSpeed; // config value: maximum total map download speed in KB/sec + quint32 m_MaxDownloaders; // config value: maximum number of map downloaders at the same time + quint32 m_MaxDownloadSpeed; // config value: maximum total map download speed in KB/sec bool m_LCPings; // config value: use LC style pings (divide actual pings by two) - uint32_t m_AutoKickPing; // config value: auto kick players with ping higher than this - uint32_t m_BanMethod; // config value: ban method (ban by name/ip/both) + quint32 m_AutoKickPing; // config value: auto kick players with ping higher than this + quint32 m_BanMethod; // config value: ban method (ban by name/ip/both) QString m_IPBlackListFile; // config value: IP blacklist file (ipblacklist.txt) - uint32_t m_LobbyTimeLimit; // config value: auto close the game lobby after this many minutes without any reserved players - uint32_t m_Latency; // config value: the latency (by default) - uint32_t m_SyncLimit; // config value: the maximum number of packets a player can fall out of sync before starting the lag screen (by default) + quint32 m_LobbyTimeLimit; // config value: auto close the game lobby after this many minutes without any reserved players + quint32 m_Latency; // config value: the latency (by default) + quint32 m_SyncLimit; // config value: the maximum number of packets a player can fall out of sync before starting the lag screen (by default) bool m_VoteKickAllowed; // config value: if votekicks are allowed or not - uint32_t m_VoteKickPercentage; // config value: percentage of players required to vote yes for a votekick to pass + quint32 m_VoteKickPercentage; // config value: percentage of players required to vote yes for a votekick to pass QString m_DefaultMap; // config value: default map (map.cfg) QString m_MOTDFile; // config value: motd.txt QString m_GameLoadedFile; // config value: gameloaded.txt QString m_GameOverFile; // config value: gameover.txt bool m_LocalAdminMessages; // config value: send local admin messages or not bool m_AdminGameCreate; // config value: create the admin game or not - uint16_t m_AdminGamePort; // config value: the port to host the admin game on + quint16 m_AdminGamePort; // config value: the port to host the admin game on QString m_AdminGamePassword; // config value: the admin game password QString m_AdminGameMap; // config value: the admin game map config to use unsigned char m_LANWar3Version; // config value: LAN warcraft 3 version - uint32_t m_ReplayWar3Version; // config value: replay warcraft 3 version (for saving replays) - uint32_t m_ReplayBuildNumber; // config value: replay build number (for saving replays) + quint32 m_ReplayWar3Version; // config value: replay warcraft 3 version (for saving replays) + quint32 m_ReplayBuildNumber; // config value: replay build number (for saving replays) bool m_TCPNoDelay; // config value: use Nagle's algorithm or not - uint32_t m_MatchMakingMethod; // config value: the matchmaking method + quint32 m_MatchMakingMethod; // config value: the matchmaking method QString m_ConfigFile; CGHost( CConfig *CFG, QString configFile ); diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index 27c307a..668e67f 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -23,6 +23,8 @@ #include "config.h" #include "ghostdb.h" +#include + // // CGHostDB // @@ -59,7 +61,7 @@ bool CGHostDB :: Commit( ) return true; } -uint32_t CGHostDB :: AdminCount( QString /*server*/ ) +quint32 CGHostDB :: AdminCount( QString /*server*/ ) { return 0; } @@ -84,7 +86,7 @@ QVector CGHostDB :: AdminList( QString /*server*/ ) return QVector( ); } -uint32_t CGHostDB :: BanCount( QString /*server*/ ) +quint32 CGHostDB :: BanCount( QString /*server*/ ) { return 0; } @@ -114,17 +116,17 @@ QVector CGHostDB :: BanList( QString /*server*/ ) return QVector( ); } -uint32_t CGHostDB :: GameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, uint32_t /*duration*/, uint32_t /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) +quint32 CGHostDB :: GameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, quint32 /*duration*/, quint32 /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) { return 0; } -uint32_t CGHostDB :: GamePlayerAdd( uint32_t /*gameid*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*reserved*/, uint32_t /*loadingtime*/, uint32_t /*left*/, QString /*leftreason*/, uint32_t /*team*/, uint32_t /*colour*/ ) +quint32 CGHostDB :: GamePlayerAdd( quint32 /*gameid*/, QString /*name*/, QString /*ip*/, quint32 /*spoofed*/, QString /*spoofedrealm*/, quint32 /*reserved*/, quint32 /*loadingtime*/, quint32 /*left*/, QString /*leftreason*/, quint32 /*team*/, quint32 /*colour*/ ) { return 0; } -uint32_t CGHostDB :: GamePlayerCount( QString /*name*/ ) +quint32 CGHostDB :: GamePlayerCount( QString /*name*/ ) { return 0; } @@ -134,17 +136,17 @@ CDBGamePlayerSummary *CGHostDB :: GamePlayerSummaryCheck( QString /*name*/ ) return NULL; } -uint32_t CGHostDB :: DotAGameAdd( uint32_t /*gameid*/, uint32_t /*winner*/, uint32_t /*min*/, uint32_t /*sec*/ ) +quint32 CGHostDB :: DotAGameAdd( quint32 /*gameid*/, quint32 /*winner*/, quint32 /*min*/, quint32 /*sec*/ ) { return 0; } -uint32_t CGHostDB :: DotAPlayerAdd( uint32_t /*gameid*/, uint32_t /*colour*/, uint32_t /*kills*/, uint32_t /*deaths*/, uint32_t /*creepkills*/, uint32_t /*creepdenies*/, uint32_t /*assists*/, uint32_t /*gold*/, uint32_t /*neutralkills*/, QString /*item1*/, QString /*item2*/, QString /*item3*/, QString /*item4*/, QString /*item5*/, QString /*item6*/, QString /*hero*/, uint32_t /*newcolour*/, uint32_t /*towerkills*/, uint32_t /*raxkills*/, uint32_t /*courierkills*/ ) +quint32 CGHostDB :: DotAPlayerAdd( quint32 /*gameid*/, quint32 /*colour*/, quint32 /*kills*/, quint32 /*deaths*/, quint32 /*creepkills*/, quint32 /*creepdenies*/, quint32 /*assists*/, quint32 /*gold*/, quint32 /*neutralkills*/, QString /*item1*/, QString /*item2*/, QString /*item3*/, QString /*item4*/, QString /*item5*/, QString /*item6*/, QString /*hero*/, quint32 /*newcolour*/, quint32 /*towerkills*/, quint32 /*raxkills*/, quint32 /*courierkills*/ ) { return 0; } -uint32_t CGHostDB :: DotAPlayerCount( QString /*name*/ ) +quint32 CGHostDB :: DotAPlayerCount( QString /*name*/ ) { return 0; } @@ -154,37 +156,37 @@ CDBDotAPlayerSummary *CGHostDB :: DotAPlayerSummaryCheck( QString /*name*/ ) return NULL; } -QString CGHostDB :: FromCheck( uint32_t /*ip*/ ) +QString CGHostDB :: FromCheck( quint32 /*ip*/ ) { return "??"; } -bool CGHostDB :: FromAdd( uint32_t /*ip1*/, uint32_t /*ip2*/, QString /*country*/ ) +bool CGHostDB :: FromAdd( quint32 /*ip1*/, quint32 /*ip2*/, QString /*country*/ ) { return false; } -bool CGHostDB :: DownloadAdd( QString /*map*/, uint32_t /*mapsize*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*downloadtime*/ ) +bool CGHostDB :: DownloadAdd( QString /*map*/, quint32 /*mapsize*/, QString /*name*/, QString /*ip*/, quint32 /*spoofed*/, QString /*spoofedrealm*/, quint32 /*downloadtime*/ ) { return false; } -uint32_t CGHostDB :: W3MMDPlayerAdd( QString /*category*/, uint32_t /*gameid*/, uint32_t /*pid*/, QString /*name*/, QString /*flag*/, uint32_t /*leaver*/, uint32_t /*practicing*/ ) +quint32 CGHostDB :: W3MMDPlayerAdd( QString /*category*/, quint32 /*gameid*/, quint32 /*pid*/, QString /*name*/, QString /*flag*/, quint32 /*leaver*/, quint32 /*practicing*/ ) { return 0; } -bool CGHostDB :: W3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_ints*/ ) +bool CGHostDB :: W3MMDVarAdd( quint32 /*gameid*/, QMap /*var_ints*/ ) { return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_reals*/ ) +bool CGHostDB :: W3MMDVarAdd( quint32 /*gameid*/, QMap /*var_reals*/ ) { return false; } -bool CGHostDB :: W3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_strings*/ ) +bool CGHostDB :: W3MMDVarAdd( quint32 /*gameid*/, QMap /*var_strings*/ ) { return false; } @@ -249,12 +251,12 @@ CCallableBanList *CGHostDB :: ThreadedBanList( QString /*server*/ ) return NULL; } -CCallableGameAdd *CGHostDB :: ThreadedGameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, uint32_t /*duration*/, uint32_t /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) +CCallableGameAdd *CGHostDB :: ThreadedGameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, quint32 /*duration*/, quint32 /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) { return NULL; } -CCallableGamePlayerAdd *CGHostDB :: ThreadedGamePlayerAdd( uint32_t /*gameid*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*reserved*/, uint32_t /*loadingtime*/, uint32_t /*left*/, QString /*leftreason*/, uint32_t /*team*/, uint32_t /*colour*/ ) +CCallableGamePlayerAdd *CGHostDB :: ThreadedGamePlayerAdd( quint32 /*gameid*/, QString /*name*/, QString /*ip*/, quint32 /*spoofed*/, QString /*spoofedrealm*/, quint32 /*reserved*/, quint32 /*loadingtime*/, quint32 /*left*/, QString /*leftreason*/, quint32 /*team*/, quint32 /*colour*/ ) { return NULL; } @@ -264,12 +266,12 @@ CCallableGamePlayerSummaryCheck *CGHostDB :: ThreadedGamePlayerSummaryCheck( QSt return NULL; } -CCallableDotAGameAdd *CGHostDB :: ThreadedDotAGameAdd( uint32_t /*gameid*/, uint32_t /*winner*/, uint32_t /*min*/, uint32_t /*sec*/ ) +CCallableDotAGameAdd *CGHostDB :: ThreadedDotAGameAdd( quint32 /*gameid*/, quint32 /*winner*/, quint32 /*min*/, quint32 /*sec*/ ) { return NULL; } -CCallableDotAPlayerAdd *CGHostDB :: ThreadedDotAPlayerAdd( uint32_t /*gameid*/, uint32_t /*colour*/, uint32_t /*kills*/, uint32_t /*deaths*/, uint32_t /*creepkills*/, uint32_t /*creepdenies*/, uint32_t /*assists*/, uint32_t /*gold*/, uint32_t /*neutralkills*/, QString /*item1*/, QString /*item2*/, QString /*item3*/, QString /*item4*/, QString /*item5*/, QString /*item6*/, QString /*hero*/, uint32_t /*newcolour*/, uint32_t /*towerkills*/, uint32_t /*raxkills*/, uint32_t /*courierkills*/ ) +CCallableDotAPlayerAdd *CGHostDB :: ThreadedDotAPlayerAdd( quint32 /*gameid*/, quint32 /*colour*/, quint32 /*kills*/, quint32 /*deaths*/, quint32 /*creepkills*/, quint32 /*creepdenies*/, quint32 /*assists*/, quint32 /*gold*/, quint32 /*neutralkills*/, QString /*item1*/, QString /*item2*/, QString /*item3*/, QString /*item4*/, QString /*item5*/, QString /*item6*/, QString /*hero*/, quint32 /*newcolour*/, quint32 /*towerkills*/, quint32 /*raxkills*/, quint32 /*courierkills*/ ) { return NULL; } @@ -279,7 +281,7 @@ CCallableDotAPlayerSummaryCheck *CGHostDB :: ThreadedDotAPlayerSummaryCheck( QSt return NULL; } -CCallableDownloadAdd *CGHostDB :: ThreadedDownloadAdd( QString /*map*/, uint32_t /*mapsize*/, QString /*name*/, QString /*ip*/, uint32_t /*spoofed*/, QString /*spoofedrealm*/, uint32_t /*downloadtime*/ ) +CCallableDownloadAdd *CGHostDB :: ThreadedDownloadAdd( QString /*map*/, quint32 /*mapsize*/, QString /*name*/, QString /*ip*/, quint32 /*spoofed*/, QString /*spoofedrealm*/, quint32 /*downloadtime*/ ) { return NULL; } @@ -289,22 +291,22 @@ CCallableScoreCheck *CGHostDB :: ThreadedScoreCheck( QString /*category*/, QStri return NULL; } -CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString /*category*/, uint32_t /*gameid*/, uint32_t /*pid*/, QString /*name*/, QString /*flag*/, uint32_t /*leaver*/, uint32_t /*practicing*/ ) +CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString /*category*/, quint32 /*gameid*/, quint32 /*pid*/, QString /*name*/, QString /*flag*/, quint32 /*leaver*/, quint32 /*practicing*/ ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_ints*/ ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_ints*/ ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_reals*/ ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_reals*/ ) { return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( uint32_t /*gameid*/, QMap /*var_strings*/ ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_strings*/ ) { return NULL; } @@ -448,7 +450,7 @@ CDBBan :: ~CDBBan( ) // CDBGame // -CDBGame :: CDBGame( uint32_t nID, QString nServer, QString nMap, QString nDateTime, QString nGameName, QString nOwnerName, uint32_t nDuration ) +CDBGame :: CDBGame( quint32 nID, QString nServer, QString nMap, QString nDateTime, QString nGameName, QString nOwnerName, quint32 nDuration ) { m_ID = nID; m_Server = nServer; @@ -468,7 +470,7 @@ CDBGame :: ~CDBGame( ) // CDBGamePlayer // -CDBGamePlayer :: CDBGamePlayer( uint32_t nID, uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour ) +CDBGamePlayer :: CDBGamePlayer( quint32 nID, quint32 nGameID, QString nName, QString nIP, quint32 nSpoofed, QString nSpoofedRealm, quint32 nReserved, quint32 nLoadingTime, quint32 nLeft, QString nLeftReason, quint32 nTeam, quint32 nColour ) { m_ID = nID; m_GameID = nGameID; @@ -493,7 +495,7 @@ CDBGamePlayer :: ~CDBGamePlayer( ) // CDBGamePlayerSummary // -CDBGamePlayerSummary :: CDBGamePlayerSummary( QString nServer, QString nName, QString nFirstGameDateTime, QString nLastGameDateTime, uint32_t nTotalGames, uint32_t nMinLoadingTime, uint32_t nAvgLoadingTime, uint32_t nMaxLoadingTime, uint32_t nMinLeftPercent, uint32_t nAvgLeftPercent, uint32_t nMaxLeftPercent, uint32_t nMinDuration, uint32_t nAvgDuration, uint32_t nMaxDuration ) +CDBGamePlayerSummary :: CDBGamePlayerSummary( QString nServer, QString nName, QString nFirstGameDateTime, QString nLastGameDateTime, quint32 nTotalGames, quint32 nMinLoadingTime, quint32 nAvgLoadingTime, quint32 nMaxLoadingTime, quint32 nMinLeftPercent, quint32 nAvgLeftPercent, quint32 nMaxLeftPercent, quint32 nMinDuration, quint32 nAvgDuration, quint32 nMaxDuration ) { m_Server = nServer; m_Name = nName; @@ -520,7 +522,7 @@ CDBGamePlayerSummary :: ~CDBGamePlayerSummary( ) // CDBDotAGame // -CDBDotAGame :: CDBDotAGame( uint32_t nID, uint32_t nGameID, uint32_t nWinner, uint32_t nMin, uint32_t nSec ) +CDBDotAGame :: CDBDotAGame( quint32 nID, quint32 nGameID, quint32 nWinner, quint32 nMin, quint32 nSec ) { m_ID = nID; m_GameID = nGameID; @@ -556,7 +558,7 @@ CDBDotAPlayer :: CDBDotAPlayer( ) m_CourierKills = 0; } -CDBDotAPlayer :: CDBDotAPlayer( uint32_t nID, uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ) +CDBDotAPlayer :: CDBDotAPlayer( quint32 nID, quint32 nGameID, quint32 nColour, quint32 nKills, quint32 nDeaths, quint32 nCreepKills, quint32 nCreepDenies, quint32 nAssists, quint32 nGold, quint32 nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, quint32 nNewColour, quint32 nTowerKills, quint32 nRaxKills, quint32 nCourierKills ) { m_ID = nID; m_GameID = nGameID; @@ -604,7 +606,7 @@ void CDBDotAPlayer :: SetItem( unsigned int i, QString item ) // CDBDotAPlayerSummary // -CDBDotAPlayerSummary :: CDBDotAPlayerSummary( QString nServer, QString nName, uint32_t nTotalGames, uint32_t nTotalWins, uint32_t nTotalLosses, uint32_t nTotalKills, uint32_t nTotalDeaths, uint32_t nTotalCreepKills, uint32_t nTotalCreepDenies, uint32_t nTotalAssists, uint32_t nTotalNeutralKills, uint32_t nTotalTowerKills, uint32_t nTotalRaxKills, uint32_t nTotalCourierKills ) +CDBDotAPlayerSummary :: CDBDotAPlayerSummary( QString nServer, QString nName, quint32 nTotalGames, quint32 nTotalWins, quint32 nTotalLosses, quint32 nTotalKills, quint32 nTotalDeaths, quint32 nTotalCreepKills, quint32 nTotalCreepDenies, quint32 nTotalAssists, quint32 nTotalNeutralKills, quint32 nTotalTowerKills, quint32 nTotalRaxKills, quint32 nTotalCourierKills ) { m_Server = nServer; m_Name = nName; diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index 02e9c87..7bb58ee 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -57,7 +57,7 @@ class CConfig; #include "includes.h" #include -typedef QPair VarP; +typedef QPair VarP; class CGHostDB : public QObject { @@ -87,32 +87,32 @@ class CGHostDB : public QObject virtual bool Begin( ); virtual bool Commit( ); - virtual uint32_t AdminCount( QString server ); + virtual quint32 AdminCount( QString server ); virtual bool AdminCheck( QString server, QString user ); virtual bool AdminAdd( QString server, QString user ); virtual bool AdminRemove( QString server, QString user ); virtual QVector AdminList( QString server ); - virtual uint32_t BanCount( QString server ); + virtual quint32 BanCount( QString server ); virtual CDBBan *BanCheck( QString server, QString user, QString ip ); virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); virtual bool BanRemove( QString server, QString user ); virtual bool BanRemove( QString user ); virtual QVector BanList( QString server ); - virtual uint32_t GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); - virtual uint32_t GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); - virtual uint32_t GamePlayerCount( QString name ); + virtual quint32 GameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); + virtual quint32 GamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); + virtual quint32 GamePlayerCount( QString name ); virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( QString name ); - virtual uint32_t DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual uint32_t DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual uint32_t DotAPlayerCount( QString name ); + virtual quint32 DotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ); + virtual quint32 DotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ); + virtual quint32 DotAPlayerCount( QString name ); virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( QString name ); - virtual QString FromCheck( uint32_t ip ); - virtual bool FromAdd( uint32_t ip1, uint32_t ip2, QString country ); - virtual bool DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); - virtual uint32_t W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_ints ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual QString FromCheck( quint32 ip ); + virtual bool FromAdd( quint32 ip1, quint32 ip2, QString country ); + virtual bool DownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); + virtual quint32 W3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_reals ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_strings ); // threaded database functions @@ -128,18 +128,18 @@ class CGHostDB : public QObject virtual CCallableBanRemove *ThreadedBanRemove( QString server, QString user ); virtual CCallableBanRemove *ThreadedBanRemove( QString user ); virtual CCallableBanList *ThreadedBanList( QString server ); - virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); - virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); + virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( QString name ); - virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ); + virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ); virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); - virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); virtual CCallableScoreCheck *ThreadedScoreCheck( QString category, QString name, QString server ); - virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); }; // @@ -170,8 +170,8 @@ class CBaseCallable protected: QString m_Error; volatile bool m_Ready; - uint32_t m_StartTicks; - uint32_t m_EndTicks; + quint32 m_StartTicks; + quint32 m_EndTicks; public: CBaseCallable( ) : m_Error( ), m_Ready( false ), m_StartTicks( 0 ), m_EndTicks( 0 ) { } @@ -185,22 +185,22 @@ class CBaseCallable virtual QString GetError( ) { return m_Error; } virtual bool GetReady( ) { return m_Ready; } virtual void SetReady( bool nReady ) { m_Ready = nReady; } - virtual uint32_t GetElapsed( ) { return m_Ready ? m_EndTicks - m_StartTicks : 0; } + virtual quint32 GetElapsed( ) { return m_Ready ? m_EndTicks - m_StartTicks : 0; } }; class CCallableAdminCount : virtual public CBaseCallable { protected: QString m_Server; - uint32_t m_Result; + quint32 m_Result; public: CCallableAdminCount( QString nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } virtual ~CCallableAdminCount( ); virtual QString GetServer( ) { return m_Server; } - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableAdminCheck : virtual public CBaseCallable @@ -272,15 +272,15 @@ class CCallableBanCount : virtual public CBaseCallable { protected: QString m_Server; - uint32_t m_Result; + quint32 m_Result; public: CCallableBanCount( QString nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } virtual ~CCallableBanCount( ); virtual QString GetServer( ) { return m_Server; } - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableBanCheck : virtual public CBaseCallable @@ -365,42 +365,42 @@ class CCallableGameAdd : virtual public CBaseCallable QString m_Map; QString m_GameName; QString m_OwnerName; - uint32_t m_Duration; - uint32_t m_GameState; + quint32 m_Duration; + quint32 m_GameState; QString m_CreatorName; QString m_CreatorServer; - uint32_t m_Result; + quint32 m_Result; public: - CCallableGameAdd( QString nServer, QString nMap, QString nGameName, QString nOwnerName, uint32_t nDuration, uint32_t nGameState, QString nCreatorName, QString nCreatorServer ) : CBaseCallable( ), m_Server( nServer ), m_Map( nMap ), m_GameName( nGameName ), m_OwnerName( nOwnerName ), m_Duration( nDuration ), m_GameState( nGameState ), m_CreatorName( nCreatorName ), m_CreatorServer( nCreatorServer ), m_Result( 0 ) { } + CCallableGameAdd( QString nServer, QString nMap, QString nGameName, QString nOwnerName, quint32 nDuration, quint32 nGameState, QString nCreatorName, QString nCreatorServer ) : CBaseCallable( ), m_Server( nServer ), m_Map( nMap ), m_GameName( nGameName ), m_OwnerName( nOwnerName ), m_Duration( nDuration ), m_GameState( nGameState ), m_CreatorName( nCreatorName ), m_CreatorServer( nCreatorServer ), m_Result( 0 ) { } virtual ~CCallableGameAdd( ); - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableGamePlayerAdd : virtual public CBaseCallable { protected: - uint32_t m_GameID; + quint32 m_GameID; QString m_Name; QString m_IP; - uint32_t m_Spoofed; + quint32 m_Spoofed; QString m_SpoofedRealm; - uint32_t m_Reserved; - uint32_t m_LoadingTime; - uint32_t m_Left; + quint32 m_Reserved; + quint32 m_LoadingTime; + quint32 m_Left; QString m_LeftReason; - uint32_t m_Team; - uint32_t m_Colour; - uint32_t m_Result; + quint32 m_Team; + quint32 m_Colour; + quint32 m_Result; public: - CCallableGamePlayerAdd( uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour ) : CBaseCallable( ), m_GameID( nGameID ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_Reserved( nReserved ), m_LoadingTime( nLoadingTime ), m_Left( nLeft ), m_LeftReason( nLeftReason ), m_Team( nTeam ), m_Colour( nColour ), m_Result( 0 ) { } + CCallableGamePlayerAdd( quint32 nGameID, QString nName, QString nIP, quint32 nSpoofed, QString nSpoofedRealm, quint32 nReserved, quint32 nLoadingTime, quint32 nLeft, QString nLeftReason, quint32 nTeam, quint32 nColour ) : CBaseCallable( ), m_GameID( nGameID ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_Reserved( nReserved ), m_LoadingTime( nLoadingTime ), m_Left( nLeft ), m_LeftReason( nLeftReason ), m_Team( nTeam ), m_Colour( nColour ), m_Result( 0 ) { } virtual ~CCallableGamePlayerAdd( ); - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableGamePlayerSummaryCheck : virtual public CBaseCallable @@ -421,32 +421,32 @@ class CCallableGamePlayerSummaryCheck : virtual public CBaseCallable class CCallableDotAGameAdd : virtual public CBaseCallable { protected: - uint32_t m_GameID; - uint32_t m_Winner; - uint32_t m_Min; - uint32_t m_Sec; - uint32_t m_Result; + quint32 m_GameID; + quint32 m_Winner; + quint32 m_Min; + quint32 m_Sec; + quint32 m_Result; public: - CCallableDotAGameAdd( uint32_t nGameID, uint32_t nWinner, uint32_t nMin, uint32_t nSec ) : CBaseCallable( ), m_GameID( nGameID ), m_Winner( nWinner ), m_Min( nMin ), m_Sec( nSec ), m_Result( 0 ) { } + CCallableDotAGameAdd( quint32 nGameID, quint32 nWinner, quint32 nMin, quint32 nSec ) : CBaseCallable( ), m_GameID( nGameID ), m_Winner( nWinner ), m_Min( nMin ), m_Sec( nSec ), m_Result( 0 ) { } virtual ~CCallableDotAGameAdd( ); - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableDotAPlayerAdd : virtual public CBaseCallable { protected: - uint32_t m_GameID; - uint32_t m_Colour; - uint32_t m_Kills; - uint32_t m_Deaths; - uint32_t m_CreepKills; - uint32_t m_CreepDenies; - uint32_t m_Assists; - uint32_t m_Gold; - uint32_t m_NeutralKills; + quint32 m_GameID; + quint32 m_Colour; + quint32 m_Kills; + quint32 m_Deaths; + quint32 m_CreepKills; + quint32 m_CreepDenies; + quint32 m_Assists; + quint32 m_Gold; + quint32 m_NeutralKills; QString m_Item1; QString m_Item2; QString m_Item3; @@ -454,18 +454,18 @@ class CCallableDotAPlayerAdd : virtual public CBaseCallable QString m_Item5; QString m_Item6; QString m_Hero; - uint32_t m_NewColour; - uint32_t m_TowerKills; - uint32_t m_RaxKills; - uint32_t m_CourierKills; - uint32_t m_Result; + quint32 m_NewColour; + quint32 m_TowerKills; + quint32 m_RaxKills; + quint32 m_CourierKills; + quint32 m_Result; public: - CCallableDotAPlayerAdd( uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ) : CBaseCallable( ), m_GameID( nGameID ), m_Colour( nColour ), m_Kills( nKills ), m_Deaths( nDeaths ), m_CreepKills( nCreepKills ), m_CreepDenies( nCreepDenies ), m_Assists( nAssists ), m_Gold( nGold ), m_NeutralKills( nNeutralKills ), m_Item1( nItem1 ), m_Item2( nItem2 ), m_Item3( nItem3 ), m_Item4( nItem4 ), m_Item5( nItem5 ), m_Item6( nItem6 ), m_Hero( nHero ), m_NewColour( nNewColour ), m_TowerKills( nTowerKills ), m_RaxKills( nRaxKills ), m_CourierKills( nCourierKills ), m_Result( 0 ) { } + CCallableDotAPlayerAdd( quint32 nGameID, quint32 nColour, quint32 nKills, quint32 nDeaths, quint32 nCreepKills, quint32 nCreepDenies, quint32 nAssists, quint32 nGold, quint32 nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, quint32 nNewColour, quint32 nTowerKills, quint32 nRaxKills, quint32 nCourierKills ) : CBaseCallable( ), m_GameID( nGameID ), m_Colour( nColour ), m_Kills( nKills ), m_Deaths( nDeaths ), m_CreepKills( nCreepKills ), m_CreepDenies( nCreepDenies ), m_Assists( nAssists ), m_Gold( nGold ), m_NeutralKills( nNeutralKills ), m_Item1( nItem1 ), m_Item2( nItem2 ), m_Item3( nItem3 ), m_Item4( nItem4 ), m_Item5( nItem5 ), m_Item6( nItem6 ), m_Hero( nHero ), m_NewColour( nNewColour ), m_TowerKills( nTowerKills ), m_RaxKills( nRaxKills ), m_CourierKills( nCourierKills ), m_Result( 0 ) { } virtual ~CCallableDotAPlayerAdd( ); - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableDotAPlayerSummaryCheck : virtual public CBaseCallable @@ -487,16 +487,16 @@ class CCallableDownloadAdd : virtual public CBaseCallable { protected: QString m_Map; - uint32_t m_MapSize; + quint32 m_MapSize; QString m_Name; QString m_IP; - uint32_t m_Spoofed; + quint32 m_Spoofed; QString m_SpoofedRealm; - uint32_t m_DownloadTime; + quint32 m_DownloadTime; bool m_Result; public: - CCallableDownloadAdd( QString nMap, uint32_t nMapSize, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nDownloadTime ) : CBaseCallable( ), m_Map( nMap ), m_MapSize( nMapSize ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_DownloadTime( nDownloadTime ), m_Result( false ) { } + CCallableDownloadAdd( QString nMap, quint32 nMapSize, QString nName, QString nIP, quint32 nSpoofed, QString nSpoofedRealm, quint32 nDownloadTime ) : CBaseCallable( ), m_Map( nMap ), m_MapSize( nMapSize ), m_Name( nName ), m_IP( nIP ), m_Spoofed( nSpoofed ), m_SpoofedRealm( nSpoofedRealm ), m_DownloadTime( nDownloadTime ), m_Result( false ) { } virtual ~CCallableDownloadAdd( ); virtual bool GetResult( ) { return m_Result; } @@ -524,26 +524,26 @@ class CCallableW3MMDPlayerAdd : virtual public CBaseCallable { protected: QString m_Category; - uint32_t m_GameID; - uint32_t m_PID; + quint32 m_GameID; + quint32 m_PID; QString m_Name; QString m_Flag; - uint32_t m_Leaver; - uint32_t m_Practicing; - uint32_t m_Result; + quint32 m_Leaver; + quint32 m_Practicing; + quint32 m_Result; public: - CCallableW3MMDPlayerAdd( QString nCategory, uint32_t nGameID, uint32_t nPID, QString nName, QString nFlag, uint32_t nLeaver, uint32_t nPracticing ) : CBaseCallable( ), m_Category( nCategory ), m_GameID( nGameID ), m_PID( nPID ), m_Name( nName ), m_Flag( nFlag ), m_Leaver( nLeaver ), m_Practicing( nPracticing ), m_Result( 0 ) { } + CCallableW3MMDPlayerAdd( QString nCategory, quint32 nGameID, quint32 nPID, QString nName, QString nFlag, quint32 nLeaver, quint32 nPracticing ) : CBaseCallable( ), m_Category( nCategory ), m_GameID( nGameID ), m_PID( nPID ), m_Name( nName ), m_Flag( nFlag ), m_Leaver( nLeaver ), m_Practicing( nPracticing ), m_Result( 0 ) { } virtual ~CCallableW3MMDPlayerAdd( ); - virtual uint32_t GetResult( ) { return m_Result; } - virtual void SetResult( uint32_t nResult ) { m_Result = nResult; } + virtual quint32 GetResult( ) { return m_Result; } + virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; class CCallableW3MMDVarAdd : virtual public CBaseCallable { protected: - uint32_t m_GameID; + quint32 m_GameID; QMap m_VarInts; QMap m_VarReals; QMap m_VarStrings; @@ -558,9 +558,9 @@ class CCallableW3MMDVarAdd : virtual public CBaseCallable bool m_Result; public: - CCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } - CCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarReals ) : CBaseCallable( ), m_GameID( nGameID ), m_VarReals( nVarReals ), m_ValueType( VALUETYPE_REAL ), m_Result( false ) { } - CCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } + CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } + CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarReals ) : CBaseCallable( ), m_GameID( nGameID ), m_VarReals( nVarReals ), m_ValueType( VALUETYPE_REAL ), m_Result( false ) { } + CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } virtual ~CCallableW3MMDVarAdd( ); virtual bool GetResult( ) { return m_Result; } @@ -602,27 +602,27 @@ class CDBBan class CDBGame { private: - uint32_t m_ID; + quint32 m_ID; QString m_Server; QString m_Map; QString m_DateTime; QString m_GameName; QString m_OwnerName; - uint32_t m_Duration; + quint32 m_Duration; public: - CDBGame( uint32_t nID, QString nServer, QString nMap, QString nDateTime, QString nGameName, QString nOwnerName, uint32_t nDuration ); + CDBGame( quint32 nID, QString nServer, QString nMap, QString nDateTime, QString nGameName, QString nOwnerName, quint32 nDuration ); ~CDBGame( ); - uint32_t GetID( ) { return m_ID; } + quint32 GetID( ) { return m_ID; } QString GetServer( ) { return m_Server; } QString GetMap( ) { return m_Map; } QString GetDateTime( ) { return m_DateTime; } QString GetGameName( ) { return m_GameName; } QString GetOwnerName( ) { return m_OwnerName; } - uint32_t GetDuration( ) { return m_Duration; } + quint32 GetDuration( ) { return m_Duration; } - void SetDuration( uint32_t nDuration ) { m_Duration = nDuration; } + void SetDuration( quint32 nDuration ) { m_Duration = nDuration; } }; // @@ -632,38 +632,38 @@ class CDBGame class CDBGamePlayer { private: - uint32_t m_ID; - uint32_t m_GameID; + quint32 m_ID; + quint32 m_GameID; QString m_Name; QString m_IP; - uint32_t m_Spoofed; + quint32 m_Spoofed; QString m_SpoofedRealm; - uint32_t m_Reserved; - uint32_t m_LoadingTime; - uint32_t m_Left; + quint32 m_Reserved; + quint32 m_LoadingTime; + quint32 m_Left; QString m_LeftReason; - uint32_t m_Team; - uint32_t m_Colour; + quint32 m_Team; + quint32 m_Colour; public: - CDBGamePlayer( uint32_t nID, uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour ); + CDBGamePlayer( quint32 nID, quint32 nGameID, QString nName, QString nIP, quint32 nSpoofed, QString nSpoofedRealm, quint32 nReserved, quint32 nLoadingTime, quint32 nLeft, QString nLeftReason, quint32 nTeam, quint32 nColour ); ~CDBGamePlayer( ); - uint32_t GetID( ) { return m_ID; } - uint32_t GetGameID( ) { return m_GameID; } + quint32 GetID( ) { return m_ID; } + quint32 GetGameID( ) { return m_GameID; } QString GetName( ) { return m_Name; } QString GetIP( ) { return m_IP; } - uint32_t GetSpoofed( ) { return m_Spoofed; } + quint32 GetSpoofed( ) { return m_Spoofed; } QString GetSpoofedRealm( ) { return m_SpoofedRealm; } - uint32_t GetReserved( ) { return m_Reserved; } - uint32_t GetLoadingTime( ) { return m_LoadingTime; } - uint32_t GetLeft( ) { return m_Left; } + quint32 GetReserved( ) { return m_Reserved; } + quint32 GetLoadingTime( ) { return m_LoadingTime; } + quint32 GetLeft( ) { return m_Left; } QString GetLeftReason( ) { return m_LeftReason; } - uint32_t GetTeam( ) { return m_Team; } - uint32_t GetColour( ) { return m_Colour; } + quint32 GetTeam( ) { return m_Team; } + quint32 GetColour( ) { return m_Colour; } - void SetLoadingTime( uint32_t nLoadingTime ) { m_LoadingTime = nLoadingTime; } - void SetLeft( uint32_t nLeft ) { m_Left = nLeft; } + void SetLoadingTime( quint32 nLoadingTime ) { m_LoadingTime = nLoadingTime; } + void SetLeft( quint32 nLeft ) { m_Left = nLeft; } void SetLeftReason( QString nLeftReason ) { m_LeftReason = nLeftReason; } }; @@ -678,35 +678,35 @@ class CDBGamePlayerSummary QString m_Name; QString m_FirstGameDateTime; // datetime of first game played QString m_LastGameDateTime; // datetime of last game played - uint32_t m_TotalGames; // total number of games played - uint32_t m_MinLoadingTime; // minimum loading time in milliseconds (this could be skewed because different maps have different load times) - uint32_t m_AvgLoadingTime; // average loading time in milliseconds (this could be skewed because different maps have different load times) - uint32_t m_MaxLoadingTime; // maximum loading time in milliseconds (this could be skewed because different maps have different load times) - uint32_t m_MinLeftPercent; // minimum time at which the player left the game expressed as a percentage of the game duration (0-100) - uint32_t m_AvgLeftPercent; // average time at which the player left the game expressed as a percentage of the game duration (0-100) - uint32_t m_MaxLeftPercent; // maximum time at which the player left the game expressed as a percentage of the game duration (0-100) - uint32_t m_MinDuration; // minimum game duration in seconds - uint32_t m_AvgDuration; // average game duration in seconds - uint32_t m_MaxDuration; // maximum game duration in seconds + quint32 m_TotalGames; // total number of games played + quint32 m_MinLoadingTime; // minimum loading time in milliseconds (this could be skewed because different maps have different load times) + quint32 m_AvgLoadingTime; // average loading time in milliseconds (this could be skewed because different maps have different load times) + quint32 m_MaxLoadingTime; // maximum loading time in milliseconds (this could be skewed because different maps have different load times) + quint32 m_MinLeftPercent; // minimum time at which the player left the game expressed as a percentage of the game duration (0-100) + quint32 m_AvgLeftPercent; // average time at which the player left the game expressed as a percentage of the game duration (0-100) + quint32 m_MaxLeftPercent; // maximum time at which the player left the game expressed as a percentage of the game duration (0-100) + quint32 m_MinDuration; // minimum game duration in seconds + quint32 m_AvgDuration; // average game duration in seconds + quint32 m_MaxDuration; // maximum game duration in seconds public: - CDBGamePlayerSummary( QString nServer, QString nName, QString nFirstGameDateTime, QString nLastGameDateTime, uint32_t nTotalGames, uint32_t nMinLoadingTime, uint32_t nAvgLoadingTime, uint32_t nMaxLoadingTime, uint32_t nMinLeftPercent, uint32_t nAvgLeftPercent, uint32_t nMaxLeftPercent, uint32_t nMinDuration, uint32_t nAvgDuration, uint32_t nMaxDuration ); + CDBGamePlayerSummary( QString nServer, QString nName, QString nFirstGameDateTime, QString nLastGameDateTime, quint32 nTotalGames, quint32 nMinLoadingTime, quint32 nAvgLoadingTime, quint32 nMaxLoadingTime, quint32 nMinLeftPercent, quint32 nAvgLeftPercent, quint32 nMaxLeftPercent, quint32 nMinDuration, quint32 nAvgDuration, quint32 nMaxDuration ); ~CDBGamePlayerSummary( ); QString GetServer( ) { return m_Server; } QString GetName( ) { return m_Name; } QString GetFirstGameDateTime( ) { return m_FirstGameDateTime; } QString GetLastGameDateTime( ) { return m_LastGameDateTime; } - uint32_t GetTotalGames( ) { return m_TotalGames; } - uint32_t GetMinLoadingTime( ) { return m_MinLoadingTime; } - uint32_t GetAvgLoadingTime( ) { return m_AvgLoadingTime; } - uint32_t GetMaxLoadingTime( ) { return m_MaxLoadingTime; } - uint32_t GetMinLeftPercent( ) { return m_MinLeftPercent; } - uint32_t GetAvgLeftPercent( ) { return m_AvgLeftPercent; } - uint32_t GetMaxLeftPercent( ) { return m_MaxLeftPercent; } - uint32_t GetMinDuration( ) { return m_MinDuration; } - uint32_t GetAvgDuration( ) { return m_AvgDuration; } - uint32_t GetMaxDuration( ) { return m_MaxDuration; } + quint32 GetTotalGames( ) { return m_TotalGames; } + quint32 GetMinLoadingTime( ) { return m_MinLoadingTime; } + quint32 GetAvgLoadingTime( ) { return m_AvgLoadingTime; } + quint32 GetMaxLoadingTime( ) { return m_MaxLoadingTime; } + quint32 GetMinLeftPercent( ) { return m_MinLeftPercent; } + quint32 GetAvgLeftPercent( ) { return m_AvgLeftPercent; } + quint32 GetMaxLeftPercent( ) { return m_MaxLeftPercent; } + quint32 GetMinDuration( ) { return m_MinDuration; } + quint32 GetAvgDuration( ) { return m_AvgDuration; } + quint32 GetMaxDuration( ) { return m_MaxDuration; } }; // @@ -716,21 +716,21 @@ class CDBGamePlayerSummary class CDBDotAGame { private: - uint32_t m_ID; - uint32_t m_GameID; - uint32_t m_Winner; - uint32_t m_Min; - uint32_t m_Sec; + quint32 m_ID; + quint32 m_GameID; + quint32 m_Winner; + quint32 m_Min; + quint32 m_Sec; public: - CDBDotAGame( uint32_t nID, uint32_t nGameID, uint32_t nWinner, uint32_t nMin, uint32_t nSec ); + CDBDotAGame( quint32 nID, quint32 nGameID, quint32 nWinner, quint32 nMin, quint32 nSec ); ~CDBDotAGame( ); - uint32_t GetID( ) { return m_ID; } - uint32_t GetGameID( ) { return m_GameID; } - uint32_t GetWinner( ) { return m_Winner; } - uint32_t GetMin( ) { return m_Min; } - uint32_t GetSec( ) { return m_Sec; } + quint32 GetID( ) { return m_ID; } + quint32 GetGameID( ) { return m_GameID; } + quint32 GetWinner( ) { return m_Winner; } + quint32 GetMin( ) { return m_Min; } + quint32 GetSec( ) { return m_Sec; } }; // @@ -740,59 +740,59 @@ class CDBDotAGame class CDBDotAPlayer { private: - uint32_t m_ID; - uint32_t m_GameID; - uint32_t m_Colour; - uint32_t m_Kills; - uint32_t m_Deaths; - uint32_t m_CreepKills; - uint32_t m_CreepDenies; - uint32_t m_Assists; - uint32_t m_Gold; - uint32_t m_NeutralKills; + quint32 m_ID; + quint32 m_GameID; + quint32 m_Colour; + quint32 m_Kills; + quint32 m_Deaths; + quint32 m_CreepKills; + quint32 m_CreepDenies; + quint32 m_Assists; + quint32 m_Gold; + quint32 m_NeutralKills; QString m_Items[6]; QString m_Hero; - uint32_t m_NewColour; - uint32_t m_TowerKills; - uint32_t m_RaxKills; - uint32_t m_CourierKills; + quint32 m_NewColour; + quint32 m_TowerKills; + quint32 m_RaxKills; + quint32 m_CourierKills; public: CDBDotAPlayer( ); - CDBDotAPlayer( uint32_t nID, uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills ); + CDBDotAPlayer( quint32 nID, quint32 nGameID, quint32 nColour, quint32 nKills, quint32 nDeaths, quint32 nCreepKills, quint32 nCreepDenies, quint32 nAssists, quint32 nGold, quint32 nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, quint32 nNewColour, quint32 nTowerKills, quint32 nRaxKills, quint32 nCourierKills ); ~CDBDotAPlayer( ); - uint32_t GetID( ) { return m_ID; } - uint32_t GetGameID( ) { return m_GameID; } - uint32_t GetColour( ) { return m_Colour; } - uint32_t GetKills( ) { return m_Kills; } - uint32_t GetDeaths( ) { return m_Deaths; } - uint32_t GetCreepKills( ) { return m_CreepKills; } - uint32_t GetCreepDenies( ) { return m_CreepDenies; } - uint32_t GetAssists( ) { return m_Assists; } - uint32_t GetGold( ) { return m_Gold; } - uint32_t GetNeutralKills( ) { return m_NeutralKills; } + quint32 GetID( ) { return m_ID; } + quint32 GetGameID( ) { return m_GameID; } + quint32 GetColour( ) { return m_Colour; } + quint32 GetKills( ) { return m_Kills; } + quint32 GetDeaths( ) { return m_Deaths; } + quint32 GetCreepKills( ) { return m_CreepKills; } + quint32 GetCreepDenies( ) { return m_CreepDenies; } + quint32 GetAssists( ) { return m_Assists; } + quint32 GetGold( ) { return m_Gold; } + quint32 GetNeutralKills( ) { return m_NeutralKills; } QString GetItem( unsigned int i ); QString GetHero( ) { return m_Hero; } - uint32_t GetNewColour( ) { return m_NewColour; } - uint32_t GetTowerKills( ) { return m_TowerKills; } - uint32_t GetRaxKills( ) { return m_RaxKills; } - uint32_t GetCourierKills( ) { return m_CourierKills; } - - void SetColour( uint32_t nColour ) { m_Colour = nColour; } - void SetKills( uint32_t nKills ) { m_Kills = nKills; } - void SetDeaths( uint32_t nDeaths ) { m_Deaths = nDeaths; } - void SetCreepKills( uint32_t nCreepKills ) { m_CreepKills = nCreepKills; } - void SetCreepDenies( uint32_t nCreepDenies ) { m_CreepDenies = nCreepDenies; } - void SetAssists( uint32_t nAssists ) { m_Assists = nAssists; } - void SetGold( uint32_t nGold ) { m_Gold = nGold; } - void SetNeutralKills( uint32_t nNeutralKills ) { m_NeutralKills = nNeutralKills; } + quint32 GetNewColour( ) { return m_NewColour; } + quint32 GetTowerKills( ) { return m_TowerKills; } + quint32 GetRaxKills( ) { return m_RaxKills; } + quint32 GetCourierKills( ) { return m_CourierKills; } + + void SetColour( quint32 nColour ) { m_Colour = nColour; } + void SetKills( quint32 nKills ) { m_Kills = nKills; } + void SetDeaths( quint32 nDeaths ) { m_Deaths = nDeaths; } + void SetCreepKills( quint32 nCreepKills ) { m_CreepKills = nCreepKills; } + void SetCreepDenies( quint32 nCreepDenies ) { m_CreepDenies = nCreepDenies; } + void SetAssists( quint32 nAssists ) { m_Assists = nAssists; } + void SetGold( quint32 nGold ) { m_Gold = nGold; } + void SetNeutralKills( quint32 nNeutralKills ) { m_NeutralKills = nNeutralKills; } void SetItem( unsigned int i, QString item ); void SetHero( QString nHero ) { m_Hero = nHero; } - void SetNewColour( uint32_t nNewColour ) { m_NewColour = nNewColour; } - void SetTowerKills( uint32_t nTowerKills ) { m_TowerKills = nTowerKills; } - void SetRaxKills( uint32_t nRaxKills ) { m_RaxKills = nRaxKills; } - void SetCourierKills( uint32_t nCourierKills ) { m_CourierKills = nCourierKills; } + void SetNewColour( quint32 nNewColour ) { m_NewColour = nNewColour; } + void SetTowerKills( quint32 nTowerKills ) { m_TowerKills = nTowerKills; } + void SetRaxKills( quint32 nRaxKills ) { m_RaxKills = nRaxKills; } + void SetCourierKills( quint32 nCourierKills ) { m_CourierKills = nCourierKills; } }; // @@ -804,37 +804,37 @@ class CDBDotAPlayerSummary private: QString m_Server; QString m_Name; - uint32_t m_TotalGames; // total number of dota games played - uint32_t m_TotalWins; // total number of dota games won - uint32_t m_TotalLosses; // total number of dota games lost - uint32_t m_TotalKills; // total number of hero kills - uint32_t m_TotalDeaths; // total number of deaths - uint32_t m_TotalCreepKills; // total number of creep kills - uint32_t m_TotalCreepDenies; // total number of creep denies - uint32_t m_TotalAssists; // total number of assists - uint32_t m_TotalNeutralKills; // total number of neutral kills - uint32_t m_TotalTowerKills; // total number of tower kills - uint32_t m_TotalRaxKills; // total number of rax kills - uint32_t m_TotalCourierKills; // total number of courier kills + quint32 m_TotalGames; // total number of dota games played + quint32 m_TotalWins; // total number of dota games won + quint32 m_TotalLosses; // total number of dota games lost + quint32 m_TotalKills; // total number of hero kills + quint32 m_TotalDeaths; // total number of deaths + quint32 m_TotalCreepKills; // total number of creep kills + quint32 m_TotalCreepDenies; // total number of creep denies + quint32 m_TotalAssists; // total number of assists + quint32 m_TotalNeutralKills; // total number of neutral kills + quint32 m_TotalTowerKills; // total number of tower kills + quint32 m_TotalRaxKills; // total number of rax kills + quint32 m_TotalCourierKills; // total number of courier kills public: - CDBDotAPlayerSummary( QString nServer, QString nName, uint32_t nTotalGames, uint32_t nTotalWins, uint32_t nTotalLosses, uint32_t nTotalKills, uint32_t nTotalDeaths, uint32_t nTotalCreepKills, uint32_t nTotalCreepDenies, uint32_t nTotalAssists, uint32_t nTotalNeutralKills, uint32_t nTotalTowerKills, uint32_t nTotalRaxKills, uint32_t nTotalCourierKills ); + CDBDotAPlayerSummary( QString nServer, QString nName, quint32 nTotalGames, quint32 nTotalWins, quint32 nTotalLosses, quint32 nTotalKills, quint32 nTotalDeaths, quint32 nTotalCreepKills, quint32 nTotalCreepDenies, quint32 nTotalAssists, quint32 nTotalNeutralKills, quint32 nTotalTowerKills, quint32 nTotalRaxKills, quint32 nTotalCourierKills ); ~CDBDotAPlayerSummary( ); QString GetServer( ) { return m_Server; } QString GetName( ) { return m_Name; } - uint32_t GetTotalGames( ) { return m_TotalGames; } - uint32_t GetTotalWins( ) { return m_TotalWins; } - uint32_t GetTotalLosses( ) { return m_TotalLosses; } - uint32_t GetTotalKills( ) { return m_TotalKills; } - uint32_t GetTotalDeaths( ) { return m_TotalDeaths; } - uint32_t GetTotalCreepKills( ) { return m_TotalCreepKills; } - uint32_t GetTotalCreepDenies( ) { return m_TotalCreepDenies; } - uint32_t GetTotalAssists( ) { return m_TotalAssists; } - uint32_t GetTotalNeutralKills( ) { return m_TotalNeutralKills; } - uint32_t GetTotalTowerKills( ) { return m_TotalTowerKills; } - uint32_t GetTotalRaxKills( ) { return m_TotalRaxKills; } - uint32_t GetTotalCourierKills( ) { return m_TotalCourierKills; } + quint32 GetTotalGames( ) { return m_TotalGames; } + quint32 GetTotalWins( ) { return m_TotalWins; } + quint32 GetTotalLosses( ) { return m_TotalLosses; } + quint32 GetTotalKills( ) { return m_TotalKills; } + quint32 GetTotalDeaths( ) { return m_TotalDeaths; } + quint32 GetTotalCreepKills( ) { return m_TotalCreepKills; } + quint32 GetTotalCreepDenies( ) { return m_TotalCreepDenies; } + quint32 GetTotalAssists( ) { return m_TotalAssists; } + quint32 GetTotalNeutralKills( ) { return m_TotalNeutralKills; } + quint32 GetTotalTowerKills( ) { return m_TotalTowerKills; } + quint32 GetTotalRaxKills( ) { return m_TotalRaxKills; } + quint32 GetTotalCourierKills( ) { return m_TotalCourierKills; } float GetAvgKills( ) { return m_TotalGames > 0 ? (float)m_TotalKills / m_TotalGames : 0; } float GetAvgDeaths( ) { return m_TotalGames > 0 ? (float)m_TotalDeaths / m_TotalGames : 0; } diff --git a/ghost/ghostdbmysql.cpp b/ghost/ghostdbmysql.cpp index bcc2534..342c131 100644 --- a/ghost/ghostdbmysql.cpp +++ b/ghost/ghostdbmysql.cpp @@ -290,7 +290,7 @@ CCallableBanList *CGHostDBMySQL :: ThreadedBanList( QString server ) return Callable; } -CCallableGameAdd *CGHostDBMySQL :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) +CCallableGameAdd *CGHostDBMySQL :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ) { void *Connection = GetIdleConnection( ); @@ -303,7 +303,7 @@ CCallableGameAdd *CGHostDBMySQL :: ThreadedGameAdd( QString server, QString map, return Callable; } -CCallableGamePlayerAdd *CGHostDBMySQL :: ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) +CCallableGamePlayerAdd *CGHostDBMySQL :: ThreadedGamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ) { void *Connection = GetIdleConnection( ); @@ -329,7 +329,7 @@ CCallableGamePlayerSummaryCheck *CGHostDBMySQL :: ThreadedGamePlayerSummaryCheck return Callable; } -CCallableDotAGameAdd *CGHostDBMySQL :: ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +CCallableDotAGameAdd *CGHostDBMySQL :: ThreadedDotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ) { void *Connection = GetIdleConnection( ); @@ -342,7 +342,7 @@ CCallableDotAGameAdd *CGHostDBMySQL :: ThreadedDotAGameAdd( uint32_t gameid, uin return Callable; } -CCallableDotAPlayerAdd *CGHostDBMySQL :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +CCallableDotAPlayerAdd *CGHostDBMySQL :: ThreadedDotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ) { void *Connection = GetIdleConnection( ); @@ -368,7 +368,7 @@ CCallableDotAPlayerSummaryCheck *CGHostDBMySQL :: ThreadedDotAPlayerSummaryCheck return Callable; } -CCallableDownloadAdd *CGHostDBMySQL :: ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) +CCallableDownloadAdd *CGHostDBMySQL :: ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ) { void *Connection = GetIdleConnection( ); @@ -394,7 +394,7 @@ CCallableScoreCheck *CGHostDBMySQL :: ThreadedScoreCheck( QString category, QStr return Callable; } -CCallableW3MMDPlayerAdd *CGHostDBMySQL :: ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) +CCallableW3MMDPlayerAdd *CGHostDBMySQL :: ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ) { void *Connection = GetIdleConnection( ); @@ -407,7 +407,7 @@ CCallableW3MMDPlayerAdd *CGHostDBMySQL :: ThreadedW3MMDPlayerAdd( QString catego return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ) { void *Connection = GetIdleConnection( ); @@ -420,7 +420,7 @@ CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMa return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ) { void *Connection = GetIdleConnection( ); @@ -433,7 +433,7 @@ CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMa return Callable; } -CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ) +CCallableW3MMDVarAdd *CGHostDBMySQL :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ) { void *Connection = GetIdleConnection( ); @@ -499,10 +499,10 @@ QVector MySQLFetchRow( MYSQL_RES *res ) // global helper functions // -uint32_t MySQLAdminCount( void *conn, QString *error, uint32_t botid, QString server ) +quint32 MySQLAdminCount( void *conn, QString *error, quint32 botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); - uint32_t Count = 0; + quint32 Count = 0; QString Query = "SELECT COUNT(*) FROM admins WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -529,7 +529,7 @@ uint32_t MySQLAdminCount( void *conn, QString *error, uint32_t botid, QString se return Count; } -bool MySQLAdminCheck( void *conn, QString *error, uint32_t botid, QString server, QString user ) +bool MySQLAdminCheck( void *conn, QString *error, quint32 botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscServer = MySQLEscapeString( conn, server ); @@ -559,7 +559,7 @@ bool MySQLAdminCheck( void *conn, QString *error, uint32_t botid, QString server return IsAdmin; } -bool MySQLAdminAdd( void *conn, QString *error, uint32_t botid, QString server, QString user ) +bool MySQLAdminAdd( void *conn, QString *error, quint32 botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscServer = MySQLEscapeString( conn, server ); @@ -575,7 +575,7 @@ bool MySQLAdminAdd( void *conn, QString *error, uint32_t botid, QString server, return Success; } -bool MySQLAdminRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ) +bool MySQLAdminRemove( void *conn, QString *error, quint32 botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscServer = MySQLEscapeString( conn, server ); @@ -591,7 +591,7 @@ bool MySQLAdminRemove( void *conn, QString *error, uint32_t botid, QString serve return Success; } -QVector MySQLAdminList( void *conn, QString *error, uint32_t botid, QString server ) +QVector MySQLAdminList( void *conn, QString *error, quint32 botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); QVector AdminList; @@ -622,10 +622,10 @@ QVector MySQLAdminList( void *conn, QString *error, uint32_t botid, QSt return AdminList; } -uint32_t MySQLBanCount( void *conn, QString *error, uint32_t botid, QString server ) +quint32 MySQLBanCount( void *conn, QString *error, quint32 botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); - uint32_t Count = 0; + quint32 Count = 0; QString Query = "SELECT COUNT(*) FROM bans WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -652,7 +652,7 @@ uint32_t MySQLBanCount( void *conn, QString *error, uint32_t botid, QString serv return Count; } -CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip ) +CDBBan *MySQLBanCheck( void *conn, QString *error, quint32 botid, QString server, QString user, QString ip ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscServer = MySQLEscapeString( conn, server ); @@ -690,7 +690,7 @@ CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString serve return Ban; } -bool MySQLBanAdd( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) +bool MySQLBanAdd( void *conn, QString *error, quint32 botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscServer = MySQLEscapeString( conn, server ); @@ -710,7 +710,7 @@ bool MySQLBanAdd( void *conn, QString *error, uint32_t botid, QString server, QS return Success; } -bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ) +bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString server, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscServer = MySQLEscapeString( conn, server ); @@ -726,7 +726,7 @@ bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString server, return Success; } -bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString user ) +bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString user ) { transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); QString EscUser = MySQLEscapeString( conn, user ); @@ -741,7 +741,7 @@ bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString user ) return Success; } -QVector MySQLBanList( void *conn, QString *error, uint32_t botid, QString server ) +QVector MySQLBanList( void *conn, QString *error, quint32 botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); QVector BanList; @@ -772,9 +772,9 @@ QVector MySQLBanList( void *conn, QString *error, uint32_t botid, QStr return BanList; } -uint32_t MySQLGameAdd( void *conn, QString *error, uint32_t botid, QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) +quint32 MySQLGameAdd( void *conn, QString *error, quint32 botid, QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ) { - uint32_t RowID = 0; + quint32 RowID = 0; QString EscServer = MySQLEscapeString( conn, server ); QString EscMap = MySQLEscapeString( conn, map ); QString EscGameName = MySQLEscapeString( conn, gamename ); @@ -791,10 +791,10 @@ uint32_t MySQLGameAdd( void *conn, QString *error, uint32_t botid, QString serve return RowID; } -uint32_t MySQLGamePlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) +quint32 MySQLGamePlayerAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - uint32_t RowID = 0; + quint32 RowID = 0; QString EscName = MySQLEscapeString( conn, name ); QString EscIP = MySQLEscapeString( conn, ip ); QString EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm ); @@ -809,7 +809,7 @@ uint32_t MySQLGamePlayerAdd( void *conn, QString *error, uint32_t botid, uint32_ return RowID; } -CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ) +CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, quint32 botid, QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); QString EscName = MySQLEscapeString( conn, name ); @@ -830,16 +830,16 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, u { QString FirstGameDateTime = Row[0]; QString LastGameDateTime = Row[1]; - uint32_t TotalGames = UTIL_ToUInt32( Row[2] ); - uint32_t MinLoadingTime = UTIL_ToUInt32( Row[3] ); - uint32_t AvgLoadingTime = UTIL_ToUInt32( Row[4] ); - uint32_t MaxLoadingTime = UTIL_ToUInt32( Row[5] ); - uint32_t MinLeftPercent = UTIL_ToUInt32( Row[6] ); - uint32_t AvgLeftPercent = UTIL_ToUInt32( Row[7] ); - uint32_t MaxLeftPercent = UTIL_ToUInt32( Row[8] ); - uint32_t MinDuration = UTIL_ToUInt32( Row[9] ); - uint32_t AvgDuration = UTIL_ToUInt32( Row[10] ); - uint32_t MaxDuration = UTIL_ToUInt32( Row[11] ); + quint32 TotalGames = UTIL_ToUInt32( Row[2] ); + quint32 MinLoadingTime = UTIL_ToUInt32( Row[3] ); + quint32 AvgLoadingTime = UTIL_ToUInt32( Row[4] ); + quint32 MaxLoadingTime = UTIL_ToUInt32( Row[5] ); + quint32 MinLeftPercent = UTIL_ToUInt32( Row[6] ); + quint32 AvgLeftPercent = UTIL_ToUInt32( Row[7] ); + quint32 MaxLeftPercent = UTIL_ToUInt32( Row[8] ); + quint32 MinDuration = UTIL_ToUInt32( Row[9] ); + quint32 AvgDuration = UTIL_ToUInt32( Row[10] ); + quint32 MaxDuration = UTIL_ToUInt32( Row[11] ); GamePlayerSummary = new CDBGamePlayerSummary( QString( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); } else @@ -854,9 +854,9 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, u return GamePlayerSummary; } -uint32_t MySQLDotAGameAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +quint32 MySQLDotAGameAdd( void *conn, QString *error, quint32 botid, quint32 gameid, quint32 winner, quint32 min, quint32 sec ) { - uint32_t RowID = 0; + quint32 RowID = 0; QString Query = "INSERT INTO dotagames ( botid, gameid, winner, min, sec ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( winner ) + ", " + UTIL_ToString( min ) + ", " + UTIL_ToString( sec ) + " )"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -867,9 +867,9 @@ uint32_t MySQLDotAGameAdd( void *conn, QString *error, uint32_t botid, uint32_t return RowID; } -uint32_t MySQLDotAPlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +quint32 MySQLDotAPlayerAdd( void *conn, QString *error, quint32 botid, quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ) { - uint32_t RowID = 0; + quint32 RowID = 0; QString EscItem1 = MySQLEscapeString( conn, item1 ); QString EscItem2 = MySQLEscapeString( conn, item2 ); QString EscItem3 = MySQLEscapeString( conn, item3 ); @@ -887,7 +887,7 @@ uint32_t MySQLDotAPlayerAdd( void *conn, QString *error, uint32_t botid, uint32_ return RowID; } -CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ) +CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, quint32 botid, QString name ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); QString EscName = MySQLEscapeString( conn, name ); @@ -906,21 +906,21 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, u if( Row.size( ) == 10 ) { - uint32_t TotalGames = UTIL_ToUInt32( Row[0] ); + quint32 TotalGames = UTIL_ToUInt32( Row[0] ); if( TotalGames > 0 ) { - uint32_t TotalWins = 0; - uint32_t TotalLosses = 0; - uint32_t TotalKills = UTIL_ToUInt32( Row[1] ); - uint32_t TotalDeaths = UTIL_ToUInt32( Row[2] ); - uint32_t TotalCreepKills = UTIL_ToUInt32( Row[3] ); - uint32_t TotalCreepDenies = UTIL_ToUInt32( Row[4] ); - uint32_t TotalAssists = UTIL_ToUInt32( Row[5] ); - uint32_t TotalNeutralKills = UTIL_ToUInt32( Row[6] ); - uint32_t TotalTowerKills = UTIL_ToUInt32( Row[7] ); - uint32_t TotalRaxKills = UTIL_ToUInt32( Row[8] ); - uint32_t TotalCourierKills = UTIL_ToUInt32( Row[9] ); + quint32 TotalWins = 0; + quint32 TotalLosses = 0; + quint32 TotalKills = UTIL_ToUInt32( Row[1] ); + quint32 TotalDeaths = UTIL_ToUInt32( Row[2] ); + quint32 TotalCreepKills = UTIL_ToUInt32( Row[3] ); + quint32 TotalCreepDenies = UTIL_ToUInt32( Row[4] ); + quint32 TotalAssists = UTIL_ToUInt32( Row[5] ); + quint32 TotalNeutralKills = UTIL_ToUInt32( Row[6] ); + quint32 TotalTowerKills = UTIL_ToUInt32( Row[7] ); + quint32 TotalRaxKills = UTIL_ToUInt32( Row[8] ); + quint32 TotalCourierKills = UTIL_ToUInt32( Row[9] ); // calculate total wins @@ -989,7 +989,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, u return DotAPlayerSummary; } -bool MySQLDownloadAdd( void *conn, QString *error, uint32_t botid, QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) +bool MySQLDownloadAdd( void *conn, QString *error, quint32 botid, QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ) { bool Success = false; QString EscMap = MySQLEscapeString( conn, map ); @@ -1006,7 +1006,7 @@ bool MySQLDownloadAdd( void *conn, QString *error, uint32_t botid, QString map, return Success; } -double MySQLScoreCheck( void *conn, QString *error, uint32_t botid, QString category, QString name, QString server ) +double MySQLScoreCheck( void *conn, QString *error, quint32 botid, QString category, QString name, QString server ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); QString EscCategory = MySQLEscapeString( conn, category ); @@ -1039,10 +1039,10 @@ double MySQLScoreCheck( void *conn, QString *error, uint32_t botid, QString cate return Score; } -uint32_t MySQLW3MMDPlayerAdd( void *conn, QString *error, uint32_t botid, QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) +quint32 MySQLW3MMDPlayerAdd( void *conn, QString *error, quint32 botid, QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ) { transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); - uint32_t RowID = 0; + quint32 RowID = 0; QString EscCategory = MySQLEscapeString( conn, category ); QString EscName = MySQLEscapeString( conn, name ); QString EscFlag = MySQLEscapeString( conn, flag ); @@ -1056,7 +1056,7 @@ uint32_t MySQLW3MMDPlayerAdd( void *conn, QString *error, uint32_t botid, QStrin return RowID; } -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_ints ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QMap var_ints ) { if( var_ints.isEmpty( ) ) return false; @@ -1082,7 +1082,7 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t game return Success; } -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_reals ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QMap var_reals ) { if( var_reals.isEmpty( ) ) return false; @@ -1108,7 +1108,7 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t game return Success; } -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_strings ) +bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QMap var_strings ) { if( var_strings.isEmpty( ) ) return false; diff --git a/ghost/ghostdbmysql.h b/ghost/ghostdbmysql.h index 41307b9..38cf669 100644 --- a/ghost/ghostdbmysql.h +++ b/ghost/ghostdbmysql.h @@ -171,11 +171,11 @@ class CGHostDBMySQL : public CGHostDB QString m_Database; QString m_User; QString m_Password; - uint16_t m_Port; - uint32_t m_BotID; + quint16 m_Port; + quint32 m_BotID; QQueue m_IdleConnections; - uint32_t m_NumConnections; - uint32_t m_OutstandingCallables; + quint32 m_NumConnections; + quint32 m_OutstandingCallables; public: CGHostDBMySQL( CConfig *CFG ); @@ -199,18 +199,18 @@ class CGHostDBMySQL : public CGHostDB virtual CCallableBanRemove *ThreadedBanRemove( QString server, QString user ); virtual CCallableBanRemove *ThreadedBanRemove( QString user ); virtual CCallableBanList *ThreadedBanList( QString server ); - virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); - virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); + virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( QString name ); - virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ); + virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ); virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); - virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); + virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); virtual CCallableScoreCheck *ThreadedScoreCheck( QString category, QString name, QString server ); - virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); // other database functions @@ -221,29 +221,29 @@ class CGHostDBMySQL : public CGHostDB // global helper functions // -uint32_t MySQLAdminCount( void *conn, QString *error, uint32_t botid, QString server ); -bool MySQLAdminCheck( void *conn, QString *error, uint32_t botid, QString server, QString user ); -bool MySQLAdminAdd( void *conn, QString *error, uint32_t botid, QString server, QString user ); -bool MySQLAdminRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ); -QVector MySQLAdminList( void *conn, QString *error, uint32_t botid, QString server ); -uint32_t MySQLBanCount( void *conn, QString *error, uint32_t botid, QString server ); -CDBBan *MySQLBanCheck( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip ); -bool MySQLBanAdd( void *conn, QString *error, uint32_t botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); -bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString server, QString user ); -bool MySQLBanRemove( void *conn, QString *error, uint32_t botid, QString user ); -QVector MySQLBanList( void *conn, QString *error, uint32_t botid, QString server ); -uint32_t MySQLGameAdd( void *conn, QString *error, uint32_t botid, QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); -uint32_t MySQLGamePlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); -CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ); -uint32_t MySQLDotAGameAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); -uint32_t MySQLDotAPlayerAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); -CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, uint32_t botid, QString name ); -bool MySQLDownloadAdd( void *conn, QString *error, uint32_t botid, QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); -double MySQLScoreCheck( void *conn, QString *error, uint32_t botid, QString category, QString name, QString server ); -uint32_t MySQLW3MMDPlayerAdd( void *conn, QString *error, uint32_t botid, QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_ints ); -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_reals ); -bool MySQLW3MMDVarAdd( void *conn, QString *error, uint32_t botid, uint32_t gameid, QMap var_strings ); +quint32 MySQLAdminCount( void *conn, QString *error, quint32 botid, QString server ); +bool MySQLAdminCheck( void *conn, QString *error, quint32 botid, QString server, QString user ); +bool MySQLAdminAdd( void *conn, QString *error, quint32 botid, QString server, QString user ); +bool MySQLAdminRemove( void *conn, QString *error, quint32 botid, QString server, QString user ); +QVector MySQLAdminList( void *conn, QString *error, quint32 botid, QString server ); +quint32 MySQLBanCount( void *conn, QString *error, quint32 botid, QString server ); +CDBBan *MySQLBanCheck( void *conn, QString *error, quint32 botid, QString server, QString user, QString ip ); +bool MySQLBanAdd( void *conn, QString *error, quint32 botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); +bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString server, QString user ); +bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString user ); +QVector MySQLBanList( void *conn, QString *error, quint32 botid, QString server ); +quint32 MySQLGameAdd( void *conn, QString *error, quint32 botid, QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); +quint32 MySQLGamePlayerAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); +CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, quint32 botid, QString name ); +quint32 MySQLDotAGameAdd( void *conn, QString *error, quint32 botid, quint32 gameid, quint32 winner, quint32 min, quint32 sec ); +quint32 MySQLDotAPlayerAdd( void *conn, QString *error, quint32 botid, quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ); +CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, quint32 botid, QString name ); +bool MySQLDownloadAdd( void *conn, QString *error, quint32 botid, QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); +double MySQLScoreCheck( void *conn, QString *error, quint32 botid, QString category, QString name, QString server ); +quint32 MySQLW3MMDPlayerAdd( void *conn, QString *error, quint32 botid, QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); +bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QMap var_ints ); +bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QMap var_reals ); +bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QMap var_strings ); // // MySQL Callables @@ -257,11 +257,11 @@ class CMySQLCallable : virtual public CBaseCallable QString m_SQLDatabase; QString m_SQLUser; QString m_SQLPassword; - uint16_t m_SQLPort; - uint32_t m_SQLBotID; + quint16 m_SQLPort; + quint32 m_SQLBotID; public: - CMySQLCallable( void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), m_Connection( nConnection ), m_SQLBotID( nSQLBotID ), m_SQLServer( nSQLServer ), m_SQLDatabase( nSQLDatabase ), m_SQLUser( nSQLUser ), m_SQLPassword( nSQLPassword ), m_SQLPort( nSQLPort ) { } + CMySQLCallable( void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), m_Connection( nConnection ), m_SQLBotID( nSQLBotID ), m_SQLServer( nSQLServer ), m_SQLDatabase( nSQLDatabase ), m_SQLUser( nSQLUser ), m_SQLPassword( nSQLPassword ), m_SQLPort( nSQLPort ) { } virtual ~CMySQLCallable( ) { } virtual void *GetConnection( ) { return m_Connection; } @@ -273,7 +273,7 @@ class CMySQLCallable : virtual public CBaseCallable class CMySQLCallableAdminCount : public CCallableAdminCount, public CMySQLCallable { public: - CMySQLCallableAdminCount( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminCount( QString nServer, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableAdminCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminCount( ) { } virtual void operator( )( ); @@ -284,7 +284,7 @@ class CMySQLCallableAdminCount : public CCallableAdminCount, public CMySQLCallab class CMySQLCallableAdminCheck : public CCallableAdminCheck, public CMySQLCallable { public: - CMySQLCallableAdminCheck( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminCheck( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminCheck( QString nServer, QString nUser, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableAdminCheck( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminCheck( ) { } virtual void operator( )( ); @@ -295,7 +295,7 @@ class CMySQLCallableAdminCheck : public CCallableAdminCheck, public CMySQLCallab class CMySQLCallableAdminAdd : public CCallableAdminAdd, public CMySQLCallable { public: - CMySQLCallableAdminAdd( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminAdd( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminAdd( QString nServer, QString nUser, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableAdminAdd( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminAdd( ) { } virtual void operator( )( ); @@ -306,7 +306,7 @@ class CMySQLCallableAdminAdd : public CCallableAdminAdd, public CMySQLCallable class CMySQLCallableAdminRemove : public CCallableAdminRemove, public CMySQLCallable { public: - CMySQLCallableAdminRemove( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminRemove( QString nServer, QString nUser, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableAdminRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminRemove( ) { } virtual void operator( )( ); @@ -317,7 +317,7 @@ class CMySQLCallableAdminRemove : public CCallableAdminRemove, public CMySQLCall class CMySQLCallableAdminList : public CCallableAdminList, public CMySQLCallable { public: - CMySQLCallableAdminList( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableAdminList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableAdminList( QString nServer, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableAdminList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableAdminList( ) { } virtual void operator( )( ); @@ -328,7 +328,7 @@ class CMySQLCallableAdminList : public CCallableAdminList, public CMySQLCallable class CMySQLCallableBanCount : public CCallableBanCount, public CMySQLCallable { public: - CMySQLCallableBanCount( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanCount( QString nServer, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableBanCount( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanCount( ) { } virtual void operator( )( ); @@ -339,7 +339,7 @@ class CMySQLCallableBanCount : public CCallableBanCount, public CMySQLCallable class CMySQLCallableBanCheck : public CCallableBanCheck, public CMySQLCallable { public: - CMySQLCallableBanCheck( QString nServer, QString nUser, QString nIP, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanCheck( nServer, nUser, nIP ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanCheck( QString nServer, QString nUser, QString nIP, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableBanCheck( nServer, nUser, nIP ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanCheck( ) { } virtual void operator( )( ); @@ -350,7 +350,7 @@ class CMySQLCallableBanCheck : public CCallableBanCheck, public CMySQLCallable class CMySQLCallableBanAdd : public CCallableBanAdd, public CMySQLCallable { public: - CMySQLCallableBanAdd( QString nServer, QString nUser, QString nIP, QString nGameName, QString nAdmin, QString nReason, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanAdd( nServer, nUser, nIP, nGameName, nAdmin, nReason ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanAdd( QString nServer, QString nUser, QString nIP, QString nGameName, QString nAdmin, QString nReason, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableBanAdd( nServer, nUser, nIP, nGameName, nAdmin, nReason ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanAdd( ) { } virtual void operator( )( ); @@ -361,7 +361,7 @@ class CMySQLCallableBanAdd : public CCallableBanAdd, public CMySQLCallable class CMySQLCallableBanRemove : public CCallableBanRemove, public CMySQLCallable { public: - CMySQLCallableBanRemove( QString nServer, QString nUser, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanRemove( QString nServer, QString nUser, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableBanRemove( nServer, nUser ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanRemove( ) { } virtual void operator( )( ); @@ -372,7 +372,7 @@ class CMySQLCallableBanRemove : public CCallableBanRemove, public CMySQLCallable class CMySQLCallableBanList : public CCallableBanList, public CMySQLCallable { public: - CMySQLCallableBanList( QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableBanList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableBanList( QString nServer, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableBanList( nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableBanList( ) { } virtual void operator( )( ); @@ -383,7 +383,7 @@ class CMySQLCallableBanList : public CCallableBanList, public CMySQLCallable class CMySQLCallableGameAdd : public CCallableGameAdd, public CMySQLCallable { public: - CMySQLCallableGameAdd( QString nServer, QString nMap, QString nGameName, QString nOwnerName, uint32_t nDuration, uint32_t nGameState, QString nCreatorName, QString nCreatorServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGameAdd( nServer, nMap, nGameName, nOwnerName, nDuration, nGameState, nCreatorName, nCreatorServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableGameAdd( QString nServer, QString nMap, QString nGameName, QString nOwnerName, quint32 nDuration, quint32 nGameState, QString nCreatorName, QString nCreatorServer, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableGameAdd( nServer, nMap, nGameName, nOwnerName, nDuration, nGameState, nCreatorName, nCreatorServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableGameAdd( ) { } virtual void operator( )( ); @@ -394,7 +394,7 @@ class CMySQLCallableGameAdd : public CCallableGameAdd, public CMySQLCallable class CMySQLCallableGamePlayerAdd : public CCallableGamePlayerAdd, public CMySQLCallable { public: - CMySQLCallableGamePlayerAdd( uint32_t nGameID, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nReserved, uint32_t nLoadingTime, uint32_t nLeft, QString nLeftReason, uint32_t nTeam, uint32_t nColour, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGamePlayerAdd( nGameID, nName, nIP, nSpoofed, nSpoofedRealm, nReserved, nLoadingTime, nLeft, nLeftReason, nTeam, nColour ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableGamePlayerAdd( quint32 nGameID, QString nName, QString nIP, quint32 nSpoofed, QString nSpoofedRealm, quint32 nReserved, quint32 nLoadingTime, quint32 nLeft, QString nLeftReason, quint32 nTeam, quint32 nColour, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableGamePlayerAdd( nGameID, nName, nIP, nSpoofed, nSpoofedRealm, nReserved, nLoadingTime, nLeft, nLeftReason, nTeam, nColour ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableGamePlayerAdd( ) { } virtual void operator( )( ); @@ -405,7 +405,7 @@ class CMySQLCallableGamePlayerAdd : public CCallableGamePlayerAdd, public CMySQL class CMySQLCallableGamePlayerSummaryCheck : public CCallableGamePlayerSummaryCheck, public CMySQLCallable { public: - CMySQLCallableGamePlayerSummaryCheck( QString nName, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableGamePlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableGamePlayerSummaryCheck( QString nName, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableGamePlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableGamePlayerSummaryCheck( ) { } virtual void operator( )( ); @@ -416,7 +416,7 @@ class CMySQLCallableGamePlayerSummaryCheck : public CCallableGamePlayerSummaryCh class CMySQLCallableDotAGameAdd : public CCallableDotAGameAdd, public CMySQLCallable { public: - CMySQLCallableDotAGameAdd( uint32_t nGameID, uint32_t nWinner, uint32_t nMin, uint32_t nSec, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAGameAdd( nGameID, nWinner, nMin, nSec ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDotAGameAdd( quint32 nGameID, quint32 nWinner, quint32 nMin, quint32 nSec, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableDotAGameAdd( nGameID, nWinner, nMin, nSec ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDotAGameAdd( ) { } virtual void operator( )( ); @@ -427,7 +427,7 @@ class CMySQLCallableDotAGameAdd : public CCallableDotAGameAdd, public CMySQLCall class CMySQLCallableDotAPlayerAdd : public CCallableDotAPlayerAdd, public CMySQLCallable { public: - CMySQLCallableDotAPlayerAdd( uint32_t nGameID, uint32_t nColour, uint32_t nKills, uint32_t nDeaths, uint32_t nCreepKills, uint32_t nCreepDenies, uint32_t nAssists, uint32_t nGold, uint32_t nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, uint32_t nNewColour, uint32_t nTowerKills, uint32_t nRaxKills, uint32_t nCourierKills, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerAdd( nGameID, nColour, nKills, nDeaths, nCreepKills, nCreepDenies, nAssists, nGold, nNeutralKills, nItem1, nItem2, nItem3, nItem4, nItem5, nItem6, nHero, nNewColour, nTowerKills, nRaxKills, nCourierKills ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDotAPlayerAdd( quint32 nGameID, quint32 nColour, quint32 nKills, quint32 nDeaths, quint32 nCreepKills, quint32 nCreepDenies, quint32 nAssists, quint32 nGold, quint32 nNeutralKills, QString nItem1, QString nItem2, QString nItem3, QString nItem4, QString nItem5, QString nItem6, QString nHero, quint32 nNewColour, quint32 nTowerKills, quint32 nRaxKills, quint32 nCourierKills, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerAdd( nGameID, nColour, nKills, nDeaths, nCreepKills, nCreepDenies, nAssists, nGold, nNeutralKills, nItem1, nItem2, nItem3, nItem4, nItem5, nItem6, nHero, nNewColour, nTowerKills, nRaxKills, nCourierKills ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDotAPlayerAdd( ) { } virtual void operator( )( ); @@ -438,7 +438,7 @@ class CMySQLCallableDotAPlayerAdd : public CCallableDotAPlayerAdd, public CMySQL class CMySQLCallableDotAPlayerSummaryCheck : public CCallableDotAPlayerSummaryCheck, public CMySQLCallable { public: - CMySQLCallableDotAPlayerSummaryCheck( QString nName, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDotAPlayerSummaryCheck( QString nName, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableDotAPlayerSummaryCheck( nName ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDotAPlayerSummaryCheck( ) { } virtual void operator( )( ); @@ -449,7 +449,7 @@ class CMySQLCallableDotAPlayerSummaryCheck : public CCallableDotAPlayerSummaryCh class CMySQLCallableDownloadAdd : public CCallableDownloadAdd, public CMySQLCallable { public: - CMySQLCallableDownloadAdd( QString nMap, uint32_t nMapSize, QString nName, QString nIP, uint32_t nSpoofed, QString nSpoofedRealm, uint32_t nDownloadTime, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableDownloadAdd( nMap, nMapSize, nName, nIP, nSpoofed, nSpoofedRealm, nDownloadTime ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableDownloadAdd( QString nMap, quint32 nMapSize, QString nName, QString nIP, quint32 nSpoofed, QString nSpoofedRealm, quint32 nDownloadTime, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableDownloadAdd( nMap, nMapSize, nName, nIP, nSpoofed, nSpoofedRealm, nDownloadTime ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableDownloadAdd( ) { } virtual void operator( )( ); @@ -460,7 +460,7 @@ class CMySQLCallableDownloadAdd : public CCallableDownloadAdd, public CMySQLCall class CMySQLCallableScoreCheck : public CCallableScoreCheck, public CMySQLCallable { public: - CMySQLCallableScoreCheck( QString nCategory, QString nName, QString nServer, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableScoreCheck( nCategory, nName, nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableScoreCheck( QString nCategory, QString nName, QString nServer, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableScoreCheck( nCategory, nName, nServer ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableScoreCheck( ) { } virtual void operator( )( ); @@ -471,7 +471,7 @@ class CMySQLCallableScoreCheck : public CCallableScoreCheck, public CMySQLCallab class CMySQLCallableW3MMDPlayerAdd : public CCallableW3MMDPlayerAdd, public CMySQLCallable { public: - CMySQLCallableW3MMDPlayerAdd( QString nCategory, uint32_t nGameID, uint32_t nPID, QString nName, QString nFlag, uint32_t nLeaver, uint32_t nPracticing, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDPlayerAdd( nCategory, nGameID, nPID, nName, nFlag, nLeaver, nPracticing ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDPlayerAdd( QString nCategory, quint32 nGameID, quint32 nPID, QString nName, QString nFlag, quint32 nLeaver, quint32 nPracticing, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableW3MMDPlayerAdd( nCategory, nGameID, nPID, nName, nFlag, nLeaver, nPracticing ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableW3MMDPlayerAdd( ) { } virtual void operator( )( ); @@ -482,9 +482,9 @@ class CMySQLCallableW3MMDPlayerAdd : public CCallableW3MMDPlayerAdd, public CMyS class CMySQLCallableW3MMDVarAdd : public CCallableW3MMDVarAdd, public CMySQLCallable { public: - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarInts, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarInts ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarReals, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarReals ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } - CMySQLCallableW3MMDVarAdd( uint32_t nGameID, QMap nVarStrings, void *nConnection, uint32_t nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, uint16_t nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarStrings ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( quint32 nGameID, QMap nVarInts, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarInts ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( quint32 nGameID, QMap nVarReals, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarReals ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } + CMySQLCallableW3MMDVarAdd( quint32 nGameID, QMap nVarStrings, void *nConnection, quint32 nSQLBotID, QString nSQLServer, QString nSQLDatabase, QString nSQLUser, QString nSQLPassword, quint16 nSQLPort ) : CBaseCallable( ), CCallableW3MMDVarAdd( nGameID, nVarStrings ), CMySQLCallable( nConnection, nSQLBotID, nSQLServer, nSQLDatabase, nSQLUser, nSQLPassword, nSQLPort ) { } virtual ~CMySQLCallableW3MMDVarAdd( ) { } virtual void operator( )( ); diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index f1c20cd..dad8b61 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -94,9 +94,9 @@ int CSQLITE3 :: Exec( QString query ) return sqlite3_exec( (sqlite3 *)m_DB, query.toUtf8().data( ), NULL, NULL, NULL ); } -uint32_t CSQLITE3 :: LastRowID( ) +quint32 CSQLITE3 :: LastRowID( ) { - return (uint32_t)sqlite3_last_insert_rowid( (sqlite3 *)m_DB ); + return (quint32)sqlite3_last_insert_rowid( (sqlite3 *)m_DB ); } // @@ -554,9 +554,9 @@ bool CGHostDBSQLite :: Commit( ) return m_DB->Exec( "COMMIT TRANSACTION" ) == SQLITE_OK; } -uint32_t CGHostDBSQLite :: AdminCount( QString server ) +quint32 CGHostDBSQLite :: AdminCount( QString server ) { - uint32_t Count = 0; + quint32 Count = 0; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(*) FROM admins WHERE server=?", (void **)&Statement ); @@ -690,9 +690,9 @@ QVector CGHostDBSQLite :: AdminList( QString server ) return AdminList; } -uint32_t CGHostDBSQLite :: BanCount( QString server ) +quint32 CGHostDBSQLite :: BanCount( QString server ) { - uint32_t Count = 0; + quint32 Count = 0; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(*) FROM bans WHERE server=?", (void **)&Statement ); @@ -869,9 +869,9 @@ QVector CGHostDBSQLite :: BanList( QString server ) return BanList; } -uint32_t CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) +quint32 CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ) { - uint32_t RowID = 0; + quint32 RowID = 0; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO games ( server, map, datetime, gamename, ownername, duration, gamestate, creatorname, creatorserver ) VALUES ( ?, ?, datetime('now'), ?, ?, ?, ?, ?, ? )", (void **)&Statement ); @@ -901,10 +901,10 @@ uint32_t CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamenam return RowID; } -uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) +quint32 CGHostDBSQLite :: GamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ) { name = name.toLower(); - uint32_t RowID = 0; + quint32 RowID = 0; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO gameplayers ( gameid, name, ip, spoofed, reserved, loadingtime, left, leftreason, team, colour, spoofedrealm ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )", (void **)&Statement ); @@ -937,10 +937,10 @@ uint32_t CGHostDBSQLite :: GamePlayerAdd( uint32_t gameid, QString name, QString return RowID; } -uint32_t CGHostDBSQLite :: GamePlayerCount( QString name ) +quint32 CGHostDBSQLite :: GamePlayerCount( QString name ) { name = name.toLower(); - uint32_t Count = 0; + quint32 Count = 0; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE name=?", (void **)&Statement ); @@ -992,16 +992,16 @@ CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( QString name ) if( Last ) LastGameDateTime = Last; - uint32_t TotalGames = sqlite3_column_int( (sqlite3_stmt *)Statement, 2 ); - uint32_t MinLoadingTime = sqlite3_column_int( (sqlite3_stmt *)Statement, 3 ); - uint32_t AvgLoadingTime = sqlite3_column_int( (sqlite3_stmt *)Statement, 4 ); - uint32_t MaxLoadingTime = sqlite3_column_int( (sqlite3_stmt *)Statement, 5 ); - uint32_t MinLeftPercent = sqlite3_column_int( (sqlite3_stmt *)Statement, 6 ); - uint32_t AvgLeftPercent = sqlite3_column_int( (sqlite3_stmt *)Statement, 7 ); - uint32_t MaxLeftPercent = sqlite3_column_int( (sqlite3_stmt *)Statement, 8 ); - uint32_t MinDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 9 ); - uint32_t AvgDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 10 ); - uint32_t MaxDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 11 ); + quint32 TotalGames = sqlite3_column_int( (sqlite3_stmt *)Statement, 2 ); + quint32 MinLoadingTime = sqlite3_column_int( (sqlite3_stmt *)Statement, 3 ); + quint32 AvgLoadingTime = sqlite3_column_int( (sqlite3_stmt *)Statement, 4 ); + quint32 MaxLoadingTime = sqlite3_column_int( (sqlite3_stmt *)Statement, 5 ); + quint32 MinLeftPercent = sqlite3_column_int( (sqlite3_stmt *)Statement, 6 ); + quint32 AvgLeftPercent = sqlite3_column_int( (sqlite3_stmt *)Statement, 7 ); + quint32 MaxLeftPercent = sqlite3_column_int( (sqlite3_stmt *)Statement, 8 ); + quint32 MinDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 9 ); + quint32 AvgDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 10 ); + quint32 MaxDuration = sqlite3_column_int( (sqlite3_stmt *)Statement, 11 ); GamePlayerSummary = new CDBGamePlayerSummary( QString( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); } else @@ -1018,9 +1018,9 @@ CDBGamePlayerSummary *CGHostDBSQLite :: GamePlayerSummaryCheck( QString name ) return GamePlayerSummary; } -uint32_t CGHostDBSQLite :: DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +quint32 CGHostDBSQLite :: DotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ) { - uint32_t RowID = 0; + quint32 RowID = 0; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO dotagames ( gameid, winner, min, sec ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1046,9 +1046,9 @@ uint32_t CGHostDBSQLite :: DotAGameAdd( uint32_t gameid, uint32_t winner, uint32 return RowID; } -uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +quint32 CGHostDBSQLite :: DotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ) { - uint32_t RowID = 0; + quint32 RowID = 0; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO dotaplayers ( gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )", (void **)&Statement ); @@ -1090,10 +1090,10 @@ uint32_t CGHostDBSQLite :: DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint return RowID; } -uint32_t CGHostDBSQLite :: DotAPlayerCount( QString name ) +quint32 CGHostDBSQLite :: DotAPlayerCount( QString name ) { name = name.toLower(); - uint32_t Count = 0; + quint32 Count = 0; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT COUNT(dotaplayers.id) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE name=?", (void **)&Statement ); @@ -1134,18 +1134,18 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) { if( sqlite3_column_count( (sqlite3_stmt *)Statement ) == 10 ) { - uint32_t TotalGames = sqlite3_column_int( (sqlite3_stmt *)Statement, 0 ); - uint32_t TotalWins = 0; - uint32_t TotalLosses = 0; - uint32_t TotalKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 1 ); - uint32_t TotalDeaths = sqlite3_column_int( (sqlite3_stmt *)Statement, 2 ); - uint32_t TotalCreepKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 3 ); - uint32_t TotalCreepDenies = sqlite3_column_int( (sqlite3_stmt *)Statement, 4 ); - uint32_t TotalAssists = sqlite3_column_int( (sqlite3_stmt *)Statement, 5 ); - uint32_t TotalNeutralKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 6 ); - uint32_t TotalTowerKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 7 ); - uint32_t TotalRaxKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 8 ); - uint32_t TotalCourierKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 9 ); + quint32 TotalGames = sqlite3_column_int( (sqlite3_stmt *)Statement, 0 ); + quint32 TotalWins = 0; + quint32 TotalLosses = 0; + quint32 TotalKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 1 ); + quint32 TotalDeaths = sqlite3_column_int( (sqlite3_stmt *)Statement, 2 ); + quint32 TotalCreepKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 3 ); + quint32 TotalCreepDenies = sqlite3_column_int( (sqlite3_stmt *)Statement, 4 ); + quint32 TotalAssists = sqlite3_column_int( (sqlite3_stmt *)Statement, 5 ); + quint32 TotalNeutralKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 6 ); + quint32 TotalTowerKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 7 ); + quint32 TotalRaxKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 8 ); + quint32 TotalCourierKills = sqlite3_column_int( (sqlite3_stmt *)Statement, 9 ); // calculate total wins @@ -1205,7 +1205,7 @@ CDBDotAPlayerSummary *CGHostDBSQLite :: DotAPlayerSummaryCheck( QString name ) return DotAPlayerSummary; } -QString CGHostDBSQLite :: FromCheck( uint32_t ip ) +QString CGHostDBSQLite :: FromCheck( quint32 ip ) { // a big thank you to tjado for help with the iptocountry feature @@ -1241,7 +1241,7 @@ QString CGHostDBSQLite :: FromCheck( uint32_t ip ) return From; } -bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) +bool CGHostDBSQLite :: FromAdd( quint32 ip1, quint32 ip2, QString country ) { // a big thank you to tjado for help with the iptocountry feature @@ -1273,7 +1273,7 @@ bool CGHostDBSQLite :: FromAdd( uint32_t ip1, uint32_t ip2, QString country ) return Success; } -bool CGHostDBSQLite :: DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) +bool CGHostDBSQLite :: DownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ) { bool Success = false; sqlite3_stmt *Statement; @@ -1304,9 +1304,9 @@ bool CGHostDBSQLite :: DownloadAdd( QString map, uint32_t mapsize, QString name, return Success; } -uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) +quint32 CGHostDBSQLite :: W3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ) { - uint32_t RowID = 0; + quint32 RowID = 0; sqlite3_stmt *Statement; m_DB->Prepare( "INSERT INTO w3mmdplayers ( category, gameid, pid, name, flag, leaver, practicing ) VALUES ( ?, ?, ?, ?, ?, ?, ? )", (void **)&Statement ); @@ -1335,7 +1335,7 @@ uint32_t CGHostDBSQLite :: W3MMDPlayerAdd( QString category, uint32_t gameid, ui return RowID; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_ints ) +bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints ) { if( var_ints.isEmpty( ) ) return false; @@ -1380,7 +1380,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_ints return Success; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_reals ) +bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_reals ) { if( var_reals.isEmpty( ) ) return false; @@ -1425,7 +1425,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_reals return Success; } -bool CGHostDBSQLite :: W3MMDVarAdd( uint32_t gameid, QMap var_strings ) +bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_strings ) { if( var_strings.isEmpty( ) ) return false; @@ -1558,7 +1558,7 @@ CCallableBanList *CGHostDBSQLite :: ThreadedBanList( QString server ) return Callable; } -CCallableGameAdd *CGHostDBSQLite :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ) +CCallableGameAdd *CGHostDBSQLite :: ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ) { CCallableGameAdd *Callable = new CCallableGameAdd( server, map, gamename, ownername, duration, gamestate, creatorname, creatorserver ); Callable->SetResult( GameAdd( server, map, gamename, ownername, duration, gamestate, creatorname, creatorserver ) ); @@ -1566,7 +1566,7 @@ CCallableGameAdd *CGHostDBSQLite :: ThreadedGameAdd( QString server, QString map return Callable; } -CCallableGamePlayerAdd *CGHostDBSQLite :: ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ) +CCallableGamePlayerAdd *CGHostDBSQLite :: ThreadedGamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ) { CCallableGamePlayerAdd *Callable = new CCallableGamePlayerAdd( gameid, name, ip, spoofed, spoofedrealm, reserved, loadingtime, left, leftreason, team, colour ); Callable->SetResult( GamePlayerAdd( gameid, name, ip, spoofed, spoofedrealm, reserved, loadingtime, left, leftreason, team, colour ) ); @@ -1582,7 +1582,7 @@ CCallableGamePlayerSummaryCheck *CGHostDBSQLite :: ThreadedGamePlayerSummaryChec return Callable; } -CCallableDotAGameAdd *CGHostDBSQLite :: ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) +CCallableDotAGameAdd *CGHostDBSQLite :: ThreadedDotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ) { CCallableDotAGameAdd *Callable = new CCallableDotAGameAdd( gameid, winner, min, sec ); Callable->SetResult( DotAGameAdd( gameid, winner, min, sec ) ); @@ -1590,7 +1590,7 @@ CCallableDotAGameAdd *CGHostDBSQLite :: ThreadedDotAGameAdd( uint32_t gameid, ui return Callable; } -CCallableDotAPlayerAdd *CGHostDBSQLite :: ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ) +CCallableDotAPlayerAdd *CGHostDBSQLite :: ThreadedDotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ) { CCallableDotAPlayerAdd *Callable = new CCallableDotAPlayerAdd( gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ); Callable->SetResult( DotAPlayerAdd( gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) ); @@ -1606,7 +1606,7 @@ CCallableDotAPlayerSummaryCheck *CGHostDBSQLite :: ThreadedDotAPlayerSummaryChec return Callable; } -CCallableDownloadAdd *CGHostDBSQLite :: ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ) +CCallableDownloadAdd *CGHostDBSQLite :: ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ) { CCallableDownloadAdd *Callable = new CCallableDownloadAdd( map, mapsize, name, ip, spoofed, spoofedrealm, downloadtime ); Callable->SetResult( DownloadAdd( map, mapsize, name, ip, spoofed, spoofedrealm, downloadtime ) ); @@ -1614,7 +1614,7 @@ CCallableDownloadAdd *CGHostDBSQLite :: ThreadedDownloadAdd( QString map, uint32 return Callable; } -CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ) +CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ) { CCallableW3MMDPlayerAdd *Callable = new CCallableW3MMDPlayerAdd( category, gameid, pid, name, flag, leaver, practicing ); Callable->SetResult( W3MMDPlayerAdd( category, gameid, pid, name, flag, leaver, practicing ) ); @@ -1622,7 +1622,7 @@ CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( QString categ return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_ints ); Callable->SetResult( W3MMDVarAdd( gameid, var_ints ) ); @@ -1630,7 +1630,7 @@ CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QM return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_reals ); Callable->SetResult( W3MMDVarAdd( gameid, var_reals ) ); @@ -1638,7 +1638,7 @@ CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QM return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_strings ); Callable->SetResult( W3MMDVarAdd( gameid, var_strings ) ); diff --git a/ghost/ghostdbsqlite.h b/ghost/ghostdbsqlite.h index c110849..6f14280 100644 --- a/ghost/ghostdbsqlite.h +++ b/ghost/ghostdbsqlite.h @@ -179,7 +179,7 @@ class CSQLITE3 int Reset( void *Statement ); int ClearBindings( void *Statement ); int Exec( QString query ); - uint32_t LastRowID( ); + quint32 LastRowID( ); }; // @@ -214,32 +214,32 @@ class CGHostDBSQLite : public CGHostDB virtual bool Begin( ); virtual bool Commit( ); - virtual uint32_t AdminCount( QString server ); + virtual quint32 AdminCount( QString server ); virtual bool AdminCheck( QString server, QString user ); virtual bool AdminAdd( QString server, QString user ); virtual bool AdminRemove( QString server, QString user ); virtual QVector AdminList( QString server ); - virtual uint32_t BanCount( QString server ); + virtual quint32 BanCount( QString server ); virtual CDBBan *BanCheck( QString server, QString user, QString ip ); virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); virtual bool BanRemove( QString server, QString user ); virtual bool BanRemove( QString user ); virtual QVector BanList( QString server ); - virtual uint32_t GameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); - virtual uint32_t GamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); - virtual uint32_t GamePlayerCount( QString name ); + virtual quint32 GameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); + virtual quint32 GamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); + virtual quint32 GamePlayerCount( QString name ); virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( QString name ); - virtual uint32_t DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual uint32_t DotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); - virtual uint32_t DotAPlayerCount( QString name ); + virtual quint32 DotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ); + virtual quint32 DotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ); + virtual quint32 DotAPlayerCount( QString name ); virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( QString name ); - virtual QString FromCheck( uint32_t ip ); - virtual bool FromAdd( uint32_t ip1, uint32_t ip2, QString country ); - virtual bool DownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); - virtual uint32_t W3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_ints ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual bool W3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual QString FromCheck( quint32 ip ); + virtual bool FromAdd( quint32 ip1, quint32 ip2, QString country ); + virtual bool DownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); + virtual quint32 W3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_reals ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_strings ); // threaded database functions // note: these are not actually implemented with threads at the moment, they WILL block until the query is complete @@ -256,17 +256,17 @@ class CGHostDBSQLite : public CGHostDB virtual CCallableBanRemove *ThreadedBanRemove( QString server, QString user ); virtual CCallableBanRemove *ThreadedBanRemove( QString user ); virtual CCallableBanList *ThreadedBanList( QString server ); - virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, uint32_t duration, uint32_t gamestate, QString creatorname, QString creatorserver ); - virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( uint32_t gameid, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, QString leftreason, uint32_t team, uint32_t colour ); + virtual CCallableGameAdd *ThreadedGameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); + virtual CCallableGamePlayerAdd *ThreadedGamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); virtual CCallableGamePlayerSummaryCheck *ThreadedGamePlayerSummaryCheck( QString name ); - virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); - virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills ); + virtual CCallableDotAGameAdd *ThreadedDotAGameAdd( quint32 gameid, quint32 winner, quint32 min, quint32 sec ); + virtual CCallableDotAPlayerAdd *ThreadedDotAPlayerAdd( quint32 gameid, quint32 colour, quint32 kills, quint32 deaths, quint32 creepkills, quint32 creepdenies, quint32 assists, quint32 gold, quint32 neutralkills, QString item1, QString item2, QString item3, QString item4, QString item5, QString item6, QString hero, quint32 newcolour, quint32 towerkills, quint32 raxkills, quint32 courierkills ); virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); - virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, uint32_t mapsize, QString name, QString ip, uint32_t spoofed, QString spoofedrealm, uint32_t downloadtime ); - virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, uint32_t gameid, uint32_t pid, QString name, QString flag, uint32_t leaver, uint32_t practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_ints ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( uint32_t gameid, QMap var_strings ); + virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); + virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); }; #endif diff --git a/ghost/gpsprotocol.cpp b/ghost/gpsprotocol.cpp index cea454f..8bba5cd 100644 --- a/ghost/gpsprotocol.cpp +++ b/ghost/gpsprotocol.cpp @@ -42,7 +42,7 @@ CGPSProtocol :: ~CGPSProtocol( ) // SEND FUNCTIONS // //////////////////// -QByteArray CGPSProtocol :: SEND_GPSC_INIT( uint32_t version ) +QByteArray CGPSProtocol :: SEND_GPSC_INIT( quint32 version ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -54,7 +54,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_INIT( uint32_t version ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reconnectKey, uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, quint32 reconnectKey, quint32 lastPacket ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -68,7 +68,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reco return packet; } -QByteArray CGPSProtocol :: SEND_GPSC_ACK( uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSC_ACK( quint32 lastPacket ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -80,7 +80,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_ACK( uint32_t lastPacket ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char PID, uint32_t reconnectKey, unsigned char numEmptyActions ) +QByteArray CGPSProtocol :: SEND_GPSS_INIT( quint16 reconnectPort, unsigned char PID, quint32 reconnectKey, unsigned char numEmptyActions ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -95,7 +95,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( quint32 lastPacket ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -107,7 +107,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( uint32_t lastPacket ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_ACK( uint32_t lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSS_ACK( quint32 lastPacket ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -119,7 +119,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_ACK( uint32_t lastPacket ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_REJECT( uint32_t reason ) +QByteArray CGPSProtocol :: SEND_GPSS_REJECT( quint32 reason ) { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -143,7 +143,7 @@ bool CGPSProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)content.size( ), false ); + LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -156,7 +156,7 @@ bool CGPSProtocol :: ValidateLength( QByteArray &content ) { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length - uint16_t Length; + quint16 Length; QByteArray LengthBytes; if( content.size( ) >= 4 && content.size( ) <= 65535 ) diff --git a/ghost/gpsprotocol.h b/ghost/gpsprotocol.h index 9f46b38..9f4a2dc 100644 --- a/ghost/gpsprotocol.h +++ b/ghost/gpsprotocol.h @@ -45,14 +45,14 @@ class CGPSProtocol // send functions - QByteArray SEND_GPSC_INIT( uint32_t version ); - QByteArray SEND_GPSC_RECONNECT( unsigned char PID, uint32_t reconnectKey, uint32_t lastPacket ); - QByteArray SEND_GPSC_ACK( uint32_t lastPacket ); - - QByteArray SEND_GPSS_INIT( uint16_t reconnectPort, unsigned char PID, uint32_t reconnectKey, unsigned char numEmptyActions ); - QByteArray SEND_GPSS_RECONNECT( uint32_t lastPacket ); - QByteArray SEND_GPSS_ACK( uint32_t lastPacket ); - QByteArray SEND_GPSS_REJECT( uint32_t reason ); + QByteArray SEND_GPSC_INIT( quint32 version ); + QByteArray SEND_GPSC_RECONNECT( unsigned char PID, quint32 reconnectKey, quint32 lastPacket ); + QByteArray SEND_GPSC_ACK( quint32 lastPacket ); + + QByteArray SEND_GPSS_INIT( quint16 reconnectPort, unsigned char PID, quint32 reconnectKey, unsigned char numEmptyActions ); + QByteArray SEND_GPSS_RECONNECT( quint32 lastPacket ); + QByteArray SEND_GPSS_ACK( quint32 lastPacket ); + QByteArray SEND_GPSS_REJECT( quint32 reason ); // other functions diff --git a/ghost/includes.h b/ghost/includes.h index 5e075e5..ba11f8b 100644 --- a/ghost/includes.h +++ b/ghost/includes.h @@ -21,14 +21,6 @@ #ifndef INCLUDES_H #define INCLUDES_H -// standard integer sizes for 64 bit compatibility - -#ifdef WIN32 - #include "ms_stdint.h" -#else - #include -#endif - // STL #include @@ -46,8 +38,8 @@ typedef QPair PIDPlayer; // time -uint32_t GetTime( ); // seconds -uint32_t GetTicks( ); // milliseconds +quint32 GetTime( ); // seconds +quint32 GetTicks( ); // milliseconds // output diff --git a/ghost/main.cpp b/ghost/main.cpp index d9dd66b..c760639 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -14,15 +14,15 @@ QFile gLogFile; QTextStream gLogStream(&gLogFile); QString gCFGFile; -uint32_t gLogMethod; +quint32 gLogMethod; CGHost *gGHost = NULL; -uint32_t GetTime() +quint32 GetTime() { return GetTicks( ) / 1000; } -uint32_t GetTicks() +quint32 GetTicks() { return gBasicTime.msec(); } diff --git a/ghost/map.cpp b/ghost/map.cpp index 6fd101e..359cd9f 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -114,7 +114,7 @@ QByteArray CMap :: GetMapGameFlags( ) */ - uint32_t GameFlags = 0; + quint32 GameFlags = 0; // speed @@ -161,7 +161,7 @@ QByteArray CMap :: GetMapGameFlags( ) return UTIL_CreateBYTEARRAY( GameFlags, false ); } -uint32_t CMap :: GetMapGameType( ) +quint32 CMap :: GetMapGameType( ) { /* spec stolen from Strilanc as follows: @@ -199,7 +199,7 @@ uint32_t CMap :: GetMapGameType( ) // note: we allow "conflicting" flags to be set at the same time (who knows if this is a good idea) // we also don't set any flags this class is unaware of such as Unknown0, SavedGame, and PrivateGame - uint32_t GameType = 0; + quint32 GameType = 0; // maker @@ -292,12 +292,12 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // calculate map_size - MapSize = UTIL_CreateBYTEARRAY( (uint32_t)m_MapData.size( ), false ); + MapSize = UTIL_CreateBYTEARRAY( (quint32)m_MapData.size( ), false ); CONSOLE_Print( "[MAP] calculated map_size = " + UTIL_QByteArrayToDecString( MapSize ) ); // calculate map_info (this is actually the CRC) - MapInfo = UTIL_CreateBYTEARRAY( (uint32_t)m_GHost->m_CRC->FullCRC( m_MapData ), false ); + MapInfo = UTIL_CreateBYTEARRAY( (quint32)m_GHost->m_CRC->FullCRC( m_MapData ), false ); CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_QByteArrayToDecString( MapInfo ) ); // calculate map_crc (this is not the CRC) and map_sha1 @@ -315,7 +315,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "blizzard.j]" ); else { - uint32_t Val = 0; + quint32 Val = 0; // update: it's possible for maps to include their own copies of common.j and/or blizzard.j // this code now overrides the default copies if required @@ -331,7 +331,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( SFileOpenFileEx( MapMPQ, "Scripts\\common.j", 0, &SubFile ) ) { - uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); + quint32 FileLength = SFileGetFileSize( SubFile, NULL ); if( FileLength > 0 && FileLength != 0xFFFFFFFF ) { @@ -367,7 +367,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( SFileOpenFileEx( MapMPQ, "Scripts\\blizzard.j", 0, &SubFile ) ) { - uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); + quint32 FileLength = SFileGetFileSize( SubFile, NULL ); if( FileLength > 0 && FileLength != 0xFFFFFFFF ) { @@ -425,7 +425,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( SFileOpenFileEx( MapMPQ, (*i).toStdString().c_str( ), 0, &SubFile ) ) { - uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); + quint32 FileLength = SFileGetFileSize( SubFile, NULL ); if( FileLength > 0 && FileLength != 0xFFFFFFFF ) { @@ -476,11 +476,11 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // try to calculate map_width, map_height, map_slot, map_numplayers, map_numteams - uint32_t MapOptions = 0; + quint32 MapOptions = 0; QByteArray MapWidth; QByteArray MapHeight; - uint32_t MapNumPlayers = 0; - uint32_t MapNumTeams = 0; + quint32 MapNumPlayers = 0; + quint32 MapNumTeams = 0; QVector Slots; if( !m_MapData.isEmpty( ) ) @@ -491,7 +491,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( SFileOpenFileEx( MapMPQ, "war3map.w3i", 0, &SubFile ) ) { - uint32_t FileLength = SFileGetFileSize( SubFile, NULL ); + quint32 FileLength = SFileGetFileSize( SubFile, NULL ); if( FileLength > 0 && FileLength != 0xFFFFFFFF ) { @@ -505,12 +505,12 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // war3map.w3i format found at http://www.wc3campaigns.net/tools/specs/index.html by Zepir/PitzerMike string GarbageString; - uint32_t FileFormat; - uint32_t RawMapWidth; - uint32_t RawMapHeight; - uint32_t RawMapFlags; - uint32_t RawMapNumPlayers; - uint32_t RawMapNumTeams; + quint32 FileFormat; + quint32 RawMapWidth; + quint32 RawMapHeight; + quint32 RawMapFlags; + quint32 RawMapNumPlayers; + quint32 RawMapNumTeams; ISS.read( (char *)&FileFormat, 4 ); // file format (18 = ROC, 25 = TFT) @@ -573,14 +573,14 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) } ISS.read( (char *)&RawMapNumPlayers, 4 ); // number of players - uint32_t ClosedSlots = 0; + quint32 ClosedSlots = 0; - for( uint32_t i = 0; i < RawMapNumPlayers; i++ ) + for( quint32 i = 0; i < RawMapNumPlayers; i++ ) { CGameSlot Slot( 0, 255, SLOTSTATUS_OPEN, 0, 0, 1, SLOTRACE_RANDOM ); - uint32_t Colour; - uint32_t Status; - uint32_t Race; + quint32 Colour; + quint32 Status; + quint32 Race; ISS.read( (char *)&Colour, 4 ); // colour Slot.SetColour( Colour ); @@ -626,10 +626,10 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) ISS.read( (char *)&RawMapNumTeams, 4 ); // number of teams - for( uint32_t i = 0; i < RawMapNumTeams; i++ ) + for( quint32 i = 0; i < RawMapNumTeams; i++ ) { - uint32_t Flags; - uint32_t PlayerMask; + quint32 Flags; + quint32 PlayerMask; ISS.read( (char *)&Flags, 4 ); // flags ISS.read( (char *)&PlayerMask, 4 ); // player mask @@ -656,16 +656,16 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) MapOptions = RawMapFlags & ( MAPOPT_MELEE | MAPOPT_FIXEDPLAYERSETTINGS | MAPOPT_CUSTOMFORCES ); CONSOLE_Print( "[MAP] calculated map_options = " + UTIL_ToString( MapOptions ) ); - MapWidth = UTIL_CreateBYTEARRAY( (uint16_t)RawMapWidth, false ); + MapWidth = UTIL_CreateBYTEARRAY( (quint16)RawMapWidth, false ); CONSOLE_Print( "[MAP] calculated map_width = " + UTIL_QByteArrayToDecString( MapWidth ) ); - MapHeight = UTIL_CreateBYTEARRAY( (uint16_t)RawMapHeight, false ); + MapHeight = UTIL_CreateBYTEARRAY( (quint16)RawMapHeight, false ); CONSOLE_Print( "[MAP] calculated map_height = " + UTIL_QByteArrayToDecString( MapHeight ) ); MapNumPlayers = RawMapNumPlayers - ClosedSlots; CONSOLE_Print( "[MAP] calculated map_numplayers = " + UTIL_ToString( MapNumPlayers ) ); MapNumTeams = RawMapNumTeams; CONSOLE_Print( "[MAP] calculated map_numteams = " + UTIL_ToString( MapNumTeams ) ); - uint32_t SlotNum = 1; + quint32 SlotNum = 1; for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) { @@ -829,7 +829,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( Slots.isEmpty( ) ) { - for( uint32_t Slot = 1; Slot <= 12; Slot++ ) + for( quint32 Slot = 1; Slot <= 12; Slot++ ) { QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); @@ -845,7 +845,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) CONSOLE_Print( "[MAP] overriding slots" ); Slots.clear( ); - for( uint32_t Slot = 1; Slot <= 12; Slot++ ) + for( quint32 Slot = 1; Slot <= 12; Slot++ ) { QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); @@ -978,18 +978,18 @@ void CMap :: CheckValid( ) } } -uint32_t CMap :: XORRotateLeft( unsigned char *data, uint32_t length ) +quint32 CMap :: XORRotateLeft( unsigned char *data, quint32 length ) { // a big thank you to Strilanc for figuring this out - uint32_t i = 0; - uint32_t Val = 0; + quint32 i = 0; + quint32 Val = 0; if( length > 3 ) { while( i < length - 3 ) { - Val = ROTL( Val ^ ( (uint32_t)data[i] + (uint32_t)( data[i + 1] << 8 ) + (uint32_t)( data[i + 2] << 16 ) + (uint32_t)( data[i + 3] << 24 ) ), 3 ); + Val = ROTL( Val ^ ( (quint32)data[i] + (quint32)( data[i + 1] << 8 ) + (quint32)( data[i + 2] << 16 ) + (quint32)( data[i + 3] << 24 ) ), 3 ); i += 4; } } diff --git a/ghost/map.h b/ghost/map.h index 319b8ce..385259a 100644 --- a/ghost/map.h +++ b/ghost/map.h @@ -110,19 +110,19 @@ class CMap unsigned char m_MapFilterType; unsigned char m_MapFilterSize; unsigned char m_MapFilterObs; - uint32_t m_MapOptions; + quint32 m_MapOptions; QByteArray m_MapWidth; // config value: map width (2 bytes) QByteArray m_MapHeight; // config value: map height (2 bytes) QString m_MapType; // config value: map type (for stats class) QString m_MapMatchMakingCategory; // config value: map matchmaking category (for matchmaking) QString m_MapStatsW3MMDCategory; // config value: map stats w3mmd category (for saving w3mmd stats) QString m_MapDefaultHCL; // config value: map default HCL to use (this should really be specified elsewhere and not part of the map config) - uint32_t m_MapDefaultPlayerScore; // config value: map default player score (for matchmaking) + quint32 m_MapDefaultPlayerScore; // config value: map default player score (for matchmaking) QString m_MapLocalPath; // config value: map local path bool m_MapLoadInGame; QString m_MapData; // the map data itself, for sending the map to players - uint32_t m_MapNumPlayers; - uint32_t m_MapNumTeams; + quint32 m_MapNumPlayers; + quint32 m_MapNumTeams; QVector m_Slots; public: @@ -142,8 +142,8 @@ class CMap unsigned char GetMapObservers( ) { return m_MapObservers; } unsigned char GetMapFlags( ) { return m_MapFlags; } QByteArray GetMapGameFlags( ); - uint32_t GetMapGameType( ); - uint32_t GetMapOptions( ) { return m_MapOptions; } + quint32 GetMapGameType( ); + quint32 GetMapOptions( ) { return m_MapOptions; } unsigned char GetMapLayoutStyle( ); QByteArray GetMapWidth( ) { return m_MapWidth; } QByteArray GetMapHeight( ) { return m_MapHeight; } @@ -151,17 +151,17 @@ class CMap QString GetMapMatchMakingCategory( ) { return m_MapMatchMakingCategory; } QString GetMapStatsW3MMDCategory( ) { return m_MapStatsW3MMDCategory; } QString GetMapDefaultHCL( ) { return m_MapDefaultHCL; } - uint32_t GetMapDefaultPlayerScore( ) { return m_MapDefaultPlayerScore; } + quint32 GetMapDefaultPlayerScore( ) { return m_MapDefaultPlayerScore; } QString GetMapLocalPath( ) { return m_MapLocalPath; } bool GetMapLoadInGame( ) { return m_MapLoadInGame; } QString *GetMapData( ) { return &m_MapData; } - uint32_t GetMapNumPlayers( ) { return m_MapNumPlayers; } - uint32_t GetMapNumTeams( ) { return m_MapNumTeams; } + quint32 GetMapNumPlayers( ) { return m_MapNumPlayers; } + quint32 GetMapNumTeams( ) { return m_MapNumTeams; } QVector GetSlots( ) { return m_Slots; } void Load( CConfig *CFG, QString nCFGFile ); void CheckValid( ); - uint32_t XORRotateLeft( unsigned char *data, uint32_t length ); + quint32 XORRotateLeft( unsigned char *data, quint32 length ); }; #endif diff --git a/ghost/ms_stdint.h b/ghost/ms_stdint.h index e032ff1..b7dc00c 100644 --- a/ghost/ms_stdint.h +++ b/ghost/ms_stdint.h @@ -71,8 +71,8 @@ typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; +typedef unsigned __int16 quint16; +typedef unsigned __int32 quint32; typedef unsigned __int64 uint64_t; // 7.18.1.2 Minimum-width integer types @@ -81,8 +81,8 @@ typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; +typedef quint16 uint_least16_t; +typedef quint32 uint_least32_t; typedef uint64_t uint_least64_t; // 7.18.1.3 Fastest minimum-width integer types @@ -91,8 +91,8 @@ typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; +typedef quint16 uint_fast16_t; +typedef quint32 uint_fast32_t; typedef uint64_t uint_fast64_t; // 7.18.1.4 Integer types capable of holding object pointers diff --git a/ghost/packed.cpp b/ghost/packed.cpp index e32dbcf..d6faee0 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -196,10 +196,10 @@ void CPacked :: Decompress( bool /*allBlocks*/ ) // read blocks - for( uint32_t i = 0; i < m_NumBlocks; i++ ) + for( quint32 i = 0; i < m_NumBlocks; i++ ) { - uint16_t BlockCompressed; - uint16_t BlockDecompressed; + quint16 BlockCompressed; + quint16 BlockDecompressed; // read block header @@ -292,7 +292,7 @@ void CPacked :: Compress( bool TFT ) // compress data into blocks of size 8192 bytes // use a buffer of size 8213 bytes because in the worst case zlib will grow the data 0.1% plus 12 bytes - uint32_t CompressedSize = 0; + quint32 CompressedSize = 0; string Padded = QString(m_Decompressed).toStdString(); Padded.append( 8192 - ( Padded.size( ) % 8192 ), 0 ); QVector CompressedBlocks; @@ -321,16 +321,16 @@ void CPacked :: Compress( bool TFT ) // build header - uint32_t HeaderSize = 68; - uint32_t HeaderCompressedSize = HeaderSize + CompressedSize + CompressedBlocks.size( ) * 8; - uint32_t HeaderVersion = 1; + quint32 HeaderSize = 68; + quint32 HeaderCompressedSize = HeaderSize + CompressedSize + CompressedBlocks.size( ) * 8; + quint32 HeaderVersion = 1; QByteArray Header; UTIL_AppendBYTEARRAY( Header, "Warcraft III recorded game\x01A" ); UTIL_AppendBYTEARRAY( Header, HeaderSize, false ); UTIL_AppendBYTEARRAY( Header, HeaderCompressedSize, false ); UTIL_AppendBYTEARRAY( Header, HeaderVersion, false ); - UTIL_AppendBYTEARRAY( Header, (uint32_t)m_Decompressed.size( ), false ); - UTIL_AppendBYTEARRAY( Header, (uint32_t)CompressedBlocks.size( ), false ); + UTIL_AppendBYTEARRAY( Header, (quint32)m_Decompressed.size( ), false ); + UTIL_AppendBYTEARRAY( Header, (quint32)CompressedBlocks.size( ), false ); if( TFT ) { @@ -356,12 +356,12 @@ void CPacked :: Compress( bool TFT ) // the header CRC is calculated over the entire header with itself set to zero // we'll overwrite the zero header CRC after we calculate it - UTIL_AppendBYTEARRAY( Header, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( Header, (quint32)0, false ); // calculate header CRC QString HeaderString = Header; - uint32_t CRC = m_CRC->FullCRC( HeaderString ); + quint32 CRC = m_CRC->FullCRC( HeaderString ); // overwrite the (currently zero) header CRC with the calculated CRC @@ -377,20 +377,20 @@ void CPacked :: Compress( bool TFT ) for( QVector :: const_iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { QByteArray BlockHeader; - UTIL_AppendBYTEARRAY( BlockHeader, (uint16_t)(*i).size( ), false ); - UTIL_AppendBYTEARRAY( BlockHeader, (uint16_t)8192, false ); + UTIL_AppendBYTEARRAY( BlockHeader, (quint16)(*i).size( ), false ); + UTIL_AppendBYTEARRAY( BlockHeader, (quint16)8192, false ); // append zero block header CRC - UTIL_AppendBYTEARRAY( BlockHeader, (uint32_t)0, false ); + UTIL_AppendBYTEARRAY( BlockHeader, (quint32)0, false ); // calculate block header CRC - uint32_t CRC1 = m_CRC->FullCRC( BlockHeader ); + quint32 CRC1 = m_CRC->FullCRC( BlockHeader ); CRC1 = CRC1 ^ ( CRC1 >> 16 ); - uint32_t CRC2 = m_CRC->FullCRC( QString::fromStdString(*i) ); + quint32 CRC2 = m_CRC->FullCRC( QString::fromStdString(*i) ); CRC2 = CRC2 ^ ( CRC2 >> 16 ); - uint32_t BlockCRC = ( CRC1 & 0xFFFF ) | ( CRC2 << 16 ); + quint32 BlockCRC = ( CRC1 & 0xFFFF ) | ( CRC2 << 16 ); // overwrite the block header CRC with the calculated CRC diff --git a/ghost/packed.h b/ghost/packed.h index 6289a21..58bcede 100644 --- a/ghost/packed.h +++ b/ghost/packed.h @@ -36,37 +36,37 @@ class CPacked bool m_Valid; QByteArray m_Compressed; QByteArray m_Decompressed; - uint32_t m_HeaderSize; - uint32_t m_CompressedSize; - uint32_t m_HeaderVersion; - uint32_t m_DecompressedSize; - uint32_t m_NumBlocks; - uint32_t m_War3Identifier; - uint32_t m_War3Version; - uint16_t m_BuildNumber; - uint16_t m_Flags; - uint32_t m_ReplayLength; + quint32 m_HeaderSize; + quint32 m_CompressedSize; + quint32 m_HeaderVersion; + quint32 m_DecompressedSize; + quint32 m_NumBlocks; + quint32 m_War3Identifier; + quint32 m_War3Version; + quint16 m_BuildNumber; + quint16 m_Flags; + quint32 m_ReplayLength; public: CPacked( ); virtual ~CPacked( ); virtual bool GetValid( ) { return m_Valid; } - virtual uint32_t GetHeaderSize( ) { return m_HeaderSize; } - virtual uint32_t GetCompressedSize( ) { return m_CompressedSize; } - virtual uint32_t GetHeaderVersion( ) { return m_HeaderVersion; } - virtual uint32_t GetDecompressedSize( ) { return m_DecompressedSize; } - virtual uint32_t GetNumBlocks( ) { return m_NumBlocks; } - virtual uint32_t GetWar3Identifier( ) { return m_War3Identifier; } - virtual uint32_t GetWar3Version( ) { return m_War3Version; } - virtual uint16_t GetBuildNumber( ) { return m_BuildNumber; } - virtual uint16_t GetFlags( ) { return m_Flags; } - virtual uint32_t GetReplayLength( ) { return m_ReplayLength; } - - virtual void SetWar3Version( uint32_t nWar3Version ) { m_War3Version = nWar3Version; } - virtual void SetBuildNumber( uint16_t nBuildNumber ) { m_BuildNumber = nBuildNumber; } - virtual void SetFlags( uint16_t nFlags ) { m_Flags = nFlags; } - virtual void SetReplayLength( uint32_t nReplayLength ) { m_ReplayLength = nReplayLength; } + virtual quint32 GetHeaderSize( ) { return m_HeaderSize; } + virtual quint32 GetCompressedSize( ) { return m_CompressedSize; } + virtual quint32 GetHeaderVersion( ) { return m_HeaderVersion; } + virtual quint32 GetDecompressedSize( ) { return m_DecompressedSize; } + virtual quint32 GetNumBlocks( ) { return m_NumBlocks; } + virtual quint32 GetWar3Identifier( ) { return m_War3Identifier; } + virtual quint32 GetWar3Version( ) { return m_War3Version; } + virtual quint16 GetBuildNumber( ) { return m_BuildNumber; } + virtual quint16 GetFlags( ) { return m_Flags; } + virtual quint32 GetReplayLength( ) { return m_ReplayLength; } + + virtual void SetWar3Version( quint32 nWar3Version ) { m_War3Version = nWar3Version; } + virtual void SetBuildNumber( quint16 nBuildNumber ) { m_BuildNumber = nBuildNumber; } + virtual void SetFlags( quint16 nFlags ) { m_Flags = nFlags; } + virtual void SetReplayLength( quint32 nReplayLength ) { m_ReplayLength = nReplayLength; } virtual void Load( QString fileName, bool allBlocks ); virtual bool Save( bool TFT, QString fileName ); diff --git a/ghost/replay.cpp b/ghost/replay.cpp index 579e54f..d2a7284 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -44,25 +44,25 @@ CReplay :: ~CReplay( ) } -void CReplay :: AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t result ) +void CReplay :: AddLeaveGame( quint32 reason, unsigned char PID, quint32 result ) { QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); UTIL_AppendBYTEARRAY( Block, reason, false ); Block.push_back( PID ); UTIL_AppendBYTEARRAY( Block, result, false ); - UTIL_AppendBYTEARRAY( Block, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Block, (quint32)1, false ); m_CompiledBlocks += Block; } -void CReplay :: AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, uint32_t result ) +void CReplay :: AddLeaveGameDuringLoading( quint32 reason, unsigned char PID, quint32 result ) { QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); UTIL_AppendBYTEARRAY( Block, reason, false ); Block.push_back( PID ); UTIL_AppendBYTEARRAY( Block, result, false ); - UTIL_AppendBYTEARRAY( Block, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Block, (quint32)1, false ); m_LoadingBlocks.enqueue( Block ); } @@ -70,31 +70,31 @@ void CReplay :: AddTimeSlot2( QQueue actions ) { QByteArray Block; Block.push_back( REPLAY_TIMESLOT2 ); - UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); - UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); + UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendBYTEARRAY( Block, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAY( Block, (quint16)Action->GetAction( )->size( ), false ); UTIL_AppendBYTEARRAYFast( Block, *Action->GetAction( ) ); } // assign length - QByteArray LengthBytes = UTIL_CreateBYTEARRAY((uint16_t)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = UTIL_CreateBYTEARRAY((quint16)( Block.size( ) - 3 ), false ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; m_CompiledBlocks += Block; } -void CReplay :: AddTimeSlot( uint16_t timeIncrement, QQueue actions ) +void CReplay :: AddTimeSlot( quint16 timeIncrement, QQueue actions ) { QByteArray Block; Block.push_back( REPLAY_TIMESLOT ); - UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); UTIL_AppendBYTEARRAY( Block, timeIncrement, false ); while( !actions.isEmpty( ) ) @@ -102,32 +102,32 @@ void CReplay :: AddTimeSlot( uint16_t timeIncrement, QQueue a CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendBYTEARRAY( Block, (uint16_t)Action->GetAction( )->size( ), false ); + UTIL_AppendBYTEARRAY( Block, (quint16)Action->GetAction( )->size( ), false ); UTIL_AppendBYTEARRAYFast( Block, *Action->GetAction( ) ); } // assign length - QByteArray LengthBytes = UTIL_CreateBYTEARRAY((uint16_t)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = UTIL_CreateBYTEARRAY((quint16)( Block.size( ) - 3 ), false ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; m_CompiledBlocks += Block; m_ReplayLength += timeIncrement; } -void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, QString message ) +void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, quint32 chatMode, QString message ) { QByteArray Block; Block.push_back( REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendBYTEARRAY( Block, (uint16_t)0, false ); + UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); Block.push_back( flags ); UTIL_AppendBYTEARRAY( Block, chatMode, false ); UTIL_AppendBYTEARRAYFast( Block, message ); // assign length - QByteArray LengthBytes = UTIL_CreateBYTEARRAY( (uint16_t)( Block.size( ) - 4 ), false ); + QByteArray LengthBytes = UTIL_CreateBYTEARRAY( (quint16)( Block.size( ) - 4 ), false ); Block[2] = LengthBytes[0]; Block[3] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -138,7 +138,7 @@ void CReplay :: AddLoadingBlock( QByteArray &loadingBlock ) m_LoadingBlocks.enqueue( loadingBlock ); } -void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3Version, uint16_t buildNumber ) +void CReplay :: BuildReplay( QString gameName, QString statString, quint32 war3Version, quint16 buildNumber ) { m_War3Version = war3Version; m_BuildNumber = buildNumber; @@ -146,7 +146,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 CONSOLE_Print( "[REPLAY] building replay" ); - uint32_t LanguageID = 0x0012F8B0; + quint32 LanguageID = 0x0012F8B0; QByteArray Replay; Replay.push_back( (char)16 ); // Unknown (4.0) @@ -161,7 +161,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 UTIL_AppendBYTEARRAYFast( Replay, gameName ); // GameName (4.2) Replay.push_back( (char)0 ); // Null (4.0) UTIL_AppendBYTEARRAYFast( Replay, statString ); // StatString (4.3) - UTIL_AppendBYTEARRAY( Replay, (uint32_t)m_Slots.size( ), false ); // PlayerCount (4.6) + UTIL_AppendBYTEARRAY( Replay, (quint32)m_Slots.size( ), false ); // PlayerCount (4.6) UTIL_AppendBYTEARRAY( Replay, m_MapGameType, false ); // GameType (4.7) UTIL_AppendBYTEARRAY( Replay, LanguageID, false ); // LanguageID (4.8) @@ -176,14 +176,14 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 UTIL_AppendBYTEARRAYFast( Replay, (*i).second ); // Player PlayerName (4.1) Replay.push_back( 1 ); // Player AdditionalSize (4.1) Replay.push_back( (char)0 ); // Player AdditionalData (4.1) - UTIL_AppendBYTEARRAY( Replay, (uint32_t)0, false ); // Unknown + UTIL_AppendBYTEARRAY( Replay, (quint32)0, false ); // Unknown } } // GameStartRecord (4.10) Replay.push_back( 25 ); // RecordID (4.10) - UTIL_AppendBYTEARRAY( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) + UTIL_AppendBYTEARRAY( Replay, (quint16)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) Replay.push_back( m_Slots.size( ) ); // NumSlots (4.10) for( unsigned char i = 0; i < m_Slots.size( ); i++ ) @@ -196,9 +196,9 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 // ReplayData (5.0) Replay.push_back( REPLAY_FIRSTSTARTBLOCK ); - UTIL_AppendBYTEARRAY( Replay, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Replay, (quint32)1, false ); Replay.push_back( REPLAY_SECONDSTARTBLOCK ); - UTIL_AppendBYTEARRAY( Replay, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Replay, (quint32)1, false ); // leavers during loading need to be stored between the second and third start blocks @@ -209,7 +209,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, uint32_t war3 } Replay.push_back( REPLAY_THIRDSTARTBLOCK ); - UTIL_AppendBYTEARRAY( Replay, (uint32_t)1, false ); + UTIL_AppendBYTEARRAY( Replay, (quint32)1, false ); // done @@ -236,7 +236,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) m_StartSpotCount = 0; m_LoadingBlocks = QQueue( ); m_Blocks = QQueue( ); - m_CheckSums = QQueue( ); + m_CheckSums = QQueue( ); if( m_Flags != 32768 ) { @@ -248,7 +248,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) istringstream ISS( m_Decompressed ); unsigned char Garbage1; - uint32_t Garbage4; + quint32 Garbage4; QString GarbageString; unsigned char GarbageData[65535]; @@ -371,7 +371,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) } } - uint16_t Size; + quint16 Size; unsigned char NumSlots; READB( ISS, &Size, 2 ); // Size (4.10) READB( ISS, &NumSlots, 1 ); // NumSlots (4.10) @@ -492,7 +492,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) return; } - uint32_t ActualReplayLength = 0; + quint32 ActualReplayLength = 0; while( 1 ) { @@ -513,7 +513,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) } else if( Garbage1 == CReplay :: REPLAY_TIMESLOT ) { - uint16_t BlockSize; + quint16 BlockSize; READB( ISS, &BlockSize, 2 ); READB( ISS, GarbageData, BlockSize ); @@ -531,7 +531,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) else if( Garbage1 == CReplay :: REPLAY_CHATMESSAGE ) { unsigned char PID; - uint16_t BlockSize; + quint16 BlockSize; READB( ISS, &PID, 1 ); if( PID > 15 ) @@ -564,7 +564,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) return; } - uint32_t CheckSum; + quint32 CheckSum; READB( ISS, &CheckSum, 4 ); m_CheckSums.enqueue( CheckSum ); } diff --git a/ghost/replay.h b/ghost/replay.h index ed419c6..781dae7 100644 --- a/ghost/replay.h +++ b/ghost/replay.h @@ -50,16 +50,16 @@ class CReplay : public CPacked QString m_HostName; QString m_GameName; QString m_StatString; - uint32_t m_PlayerCount; - uint32_t m_MapGameType; + quint32 m_PlayerCount; + quint32 m_MapGameType; QVector m_Players; QVector m_Slots; - uint32_t m_RandomSeed; + quint32 m_RandomSeed; unsigned char m_SelectMode; // also known as the "layout style" elsewhere in this project unsigned char m_StartSpotCount; QQueue m_LoadingBlocks; QQueue m_Blocks; - QQueue m_CheckSums; + QQueue m_CheckSums; QString m_CompiledBlocks; public: @@ -70,33 +70,33 @@ class CReplay : public CPacked QString GetHostName( ) { return m_HostName; } QString GetGameName( ) { return m_GameName; } QString GetStatString( ) { return m_StatString; } - uint32_t GetPlayerCount( ) { return m_PlayerCount; } - uint32_t GetMapGameType( ) { return m_MapGameType; } + quint32 GetPlayerCount( ) { return m_PlayerCount; } + quint32 GetMapGameType( ) { return m_MapGameType; } QVector GetPlayers( ) { return m_Players; } QVector GetSlots( ) { return m_Slots; } - uint32_t GetRandomSeed( ) { return m_RandomSeed; } + quint32 GetRandomSeed( ) { return m_RandomSeed; } unsigned char GetSelectMode( ) { return m_SelectMode; } unsigned char GetStartSpotCount( ) { return m_StartSpotCount; } QQueue *GetLoadingBlocks( ) { return &m_LoadingBlocks; } QQueue *GetBlocks( ) { return &m_Blocks; } - QQueue *GetCheckSums( ) { return &m_CheckSums; } + QQueue *GetCheckSums( ) { return &m_CheckSums; } void AddPlayer( unsigned char nPID, QString nName ) { m_Players.push_back( PIDPlayer( nPID, nName ) ); } void SetSlots( QVector nSlots ) { m_Slots = nSlots; } - void SetRandomSeed( uint32_t nRandomSeed ) { m_RandomSeed = nRandomSeed; } + void SetRandomSeed( quint32 nRandomSeed ) { m_RandomSeed = nRandomSeed; } void SetSelectMode( unsigned char nSelectMode ) { m_SelectMode = nSelectMode; } void SetStartSpotCount( unsigned char nStartSpotCount ) { m_StartSpotCount = nStartSpotCount; } - void SetMapGameType( uint32_t nMapGameType ) { m_MapGameType = nMapGameType; } + void SetMapGameType( quint32 nMapGameType ) { m_MapGameType = nMapGameType; } void SetHostPID( unsigned char nHostPID ) { m_HostPID = nHostPID; } void SetHostName( QString nHostName ) { m_HostName = nHostName; } - void AddLeaveGame( uint32_t reason, unsigned char PID, uint32_t result ); - void AddLeaveGameDuringLoading( uint32_t reason, unsigned char PID, uint32_t result ); + void AddLeaveGame( quint32 reason, unsigned char PID, quint32 result ); + void AddLeaveGameDuringLoading( quint32 reason, unsigned char PID, quint32 result ); void AddTimeSlot2( QQueue actions ); - void AddTimeSlot( uint16_t timeIncrement, QQueue actions ); - void AddChatMessage( unsigned char PID, unsigned char flags, uint32_t chatMode, QString message ); + void AddTimeSlot( quint16 timeIncrement, QQueue actions ); + void AddChatMessage( unsigned char PID, unsigned char flags, quint32 chatMode, QString message ); void AddLoadingBlock( QByteArray &loadingBlock ); - void BuildReplay( QString gameName, QString statString, uint32_t war3Version, uint16_t buildNumber ); + void BuildReplay( QString gameName, QString statString, quint32 war3Version, quint16 buildNumber ); void ParseReplay( bool parseBlocks ); }; diff --git a/ghost/savegame.cpp b/ghost/savegame.cpp index 23dcb91..fdbb721 100644 --- a/ghost/savegame.cpp +++ b/ghost/savegame.cpp @@ -72,10 +72,10 @@ void CSaveGame :: ParseSaveGame( ) // 4 bytes -> magic number unsigned char Garbage1; - uint16_t Garbage2; - uint32_t Garbage4; + quint16 Garbage2; + quint32 Garbage4; QString GarbageString; - uint32_t MagicNumber; + quint32 MagicNumber; READSTR( ISS, m_MapPath ); // map path READSTR( ISS, GarbageString ); // ??? diff --git a/ghost/savegame.h b/ghost/savegame.h index a9520c5..9671103 100644 --- a/ghost/savegame.h +++ b/ghost/savegame.h @@ -36,7 +36,7 @@ class CSaveGame : public CPacked QString m_GameName; unsigned char m_NumSlots; QVector m_Slots; - uint32_t m_RandomSeed; + quint32 m_RandomSeed; QByteArray m_MagicNumber; public: @@ -49,7 +49,7 @@ class CSaveGame : public CPacked QString GetGameName( ) { return m_GameName; } unsigned char GetNumSlots( ) { return m_NumSlots; } QVector GetSlots( ) { return m_Slots; } - uint32_t GetRandomSeed( ) { return m_RandomSeed; } + quint32 GetRandomSeed( ) { return m_RandomSeed; } QByteArray GetMagicNumber( ) { return m_MagicNumber; } void SetFileName( QString nFileName ) { m_FileName = nFileName; } diff --git a/ghost/sha1.cpp b/ghost/sha1.cpp index 29c2f6f..9832d4c 100644 --- a/ghost/sha1.cpp +++ b/ghost/sha1.cpp @@ -44,9 +44,9 @@ void CSHA1::Reset() m_count[1] = 0; } -void CSHA1::Transform(uint32_t state[5], unsigned char buffer[64]) +void CSHA1::Transform(quint32 state[5], unsigned char buffer[64]) { - uint32_t a = 0, b = 0, c = 0, d = 0, e = 0; + quint32 a = 0, b = 0, c = 0, d = 0, e = 0; SHA1_WORKSPACE_BLOCK* block; static unsigned char workspace[64]; @@ -96,7 +96,7 @@ void CSHA1::Transform(uint32_t state[5], unsigned char buffer[64]) // Use this function to hash in binary data and strings void CSHA1::Update(unsigned char* data, unsigned int len) { - uint32_t i = 0, j = 0; + quint32 i = 0, j = 0; j = (m_count[0] >> 3) & 63; @@ -123,7 +123,7 @@ void CSHA1::Update(unsigned char* data, unsigned int len) void CSHA1::Final() { - uint32_t i = 0, j = 0; + quint32 i = 0, j = 0; unsigned char finalcount[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; for (i = 0; i < 8; i++) diff --git a/ghost/sha1.h b/ghost/sha1.h index dc04677..b93364f 100644 --- a/ghost/sha1.h +++ b/ghost/sha1.h @@ -24,12 +24,7 @@ #include // Needed for strcat and strcpy // standard integer sizes for 64 bit compatibility - -#ifdef WIN32 - #include "ms_stdint.h" -#else - #include -#endif +#include #define MAX_FILE_READ_BUFFER 8000 @@ -58,7 +53,7 @@ class CSHA1 typedef union { unsigned char c[64]; - uint32_t l[16]; + quint32 l[16]; } SHA1_WORKSPACE_BLOCK; // Two different formats for ReportHash(...) @@ -68,8 +63,8 @@ class CSHA1 CSHA1(); virtual ~CSHA1(); - uint32_t m_state[5]; - uint32_t m_count[2]; + quint32 m_state[5]; + quint32 m_count[2]; unsigned char m_buffer[64]; unsigned char m_digest[20]; @@ -85,7 +80,7 @@ class CSHA1 private: // Private SHA-1 transformation - void Transform(uint32_t state[5], unsigned char buffer[64]); + void Transform(quint32 state[5], unsigned char buffer[64]); }; #endif // ___SHA1_H___ diff --git a/ghost/stats.cpp b/ghost/stats.cpp index 7bd6a23..98dd1d2 100644 --- a/ghost/stats.cpp +++ b/ghost/stats.cpp @@ -40,7 +40,7 @@ bool CStats :: ProcessAction( CIncomingAction */*Action*/ ) return false; } -void CStats :: Save( CGHost */*GHost*/, CGHostDB */*DB*/, uint32_t /*GameID*/ ) +void CStats :: Save( CGHost */*GHost*/, CGHostDB */*DB*/, quint32 /*GameID*/ ) { } diff --git a/ghost/stats.h b/ghost/stats.h index bc02812..24eea8b 100644 --- a/ghost/stats.h +++ b/ghost/stats.h @@ -45,7 +45,7 @@ class CStats virtual ~CStats( ); virtual bool ProcessAction( CIncomingAction *Action ); - virtual void Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ); + virtual void Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ); }; #endif diff --git a/ghost/statsdota.cpp b/ghost/statsdota.cpp index 23a98f9..e8bc006 100644 --- a/ghost/statsdota.cpp +++ b/ghost/statsdota.cpp @@ -94,7 +94,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) Value = ActionData->mid(i + 8 + Data.size( ) + Key.size( ), 4 ); QString DataString = Data; QString KeyString = Key; - uint32_t ValueInt = UTIL_QByteArrayToUInt32( Value, false ); + quint32 ValueInt = UTIL_QByteArrayToUInt32( Value, false ); // CONSOLE_Print( "[STATS] " + DataString + ", " + KeyString + ", " + UTIL_ToString( ValueInt ) ); @@ -109,7 +109,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) // a hero died QString VictimColourString = KeyString.mid( 4 ); - uint32_t VictimColour = UTIL_ToUInt32( VictimColourString ); + quint32 VictimColour = UTIL_ToUInt32( VictimColourString ); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); CGamePlayer *Victim = m_Game->GetPlayerFromColour( VictimColour ); @@ -136,7 +136,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) } QString VictimColourString = KeyString.mid( 7 ); - uint32_t VictimColour = UTIL_ToUInt32( VictimColourString ); + quint32 VictimColour = UTIL_ToUInt32( VictimColourString ); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); CGamePlayer *Victim = m_Game->GetPlayerFromColour( VictimColour ); @@ -292,7 +292,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { // these are only received at the end of the game - uint32_t ID = UTIL_ToUInt32( DataString ); + quint32 ID = UTIL_ToUInt32( DataString ); if( ( ID >= 1 && ID <= 5 ) || ( ID >= 7 && ID <= 11 ) ) { @@ -376,7 +376,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) return m_Winner != 0; } -void CStatsDOTA :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) +void CStatsDOTA :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) { if( DB->Begin( ) ) { @@ -398,7 +398,7 @@ void CStatsDOTA :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) { if( m_Players[i] ) { - uint32_t Colour = m_Players[i]->GetNewColour( ); + quint32 Colour = m_Players[i]->GetNewColour( ); if( !( ( Colour >= 1 && Colour <= 5 ) || ( Colour >= 7 && Colour <= 11 ) ) ) { diff --git a/ghost/statsdota.h b/ghost/statsdota.h index 8a4ce50..f8d3cb7 100644 --- a/ghost/statsdota.h +++ b/ghost/statsdota.h @@ -31,16 +31,16 @@ class CStatsDOTA : public CStats { private: CDBDotAPlayer *m_Players[12]; - uint32_t m_Winner; - uint32_t m_Min; - uint32_t m_Sec; + quint32 m_Winner; + quint32 m_Min; + quint32 m_Sec; public: CStatsDOTA( CBaseGame *nGame ); virtual ~CStatsDOTA( ); virtual bool ProcessAction( CIncomingAction *Action ); - virtual void Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ); + virtual void Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ); }; #endif diff --git a/ghost/statsw3mmd.cpp b/ghost/statsw3mmd.cpp index 9d11d92..a223788 100644 --- a/ghost/statsw3mmd.cpp +++ b/ghost/statsw3mmd.cpp @@ -79,14 +79,14 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) Value = ActionData->mid(i + 11 + MissionKey.size( ) + Key.size( ), 4 ); QString MissionKeyString = MissionKey; QString KeyString = Key; - //uint32_t ValueInt = UTIL_QByteArrayToUInt32( Value, false ); + //quint32 ValueInt = UTIL_QByteArrayToUInt32( Value, false ); // CONSOLE_Print( "[STATSW3MMD] DEBUG: mkey [" + MissionKeyString + "], key [" + KeyString + "], value [" + UTIL_ToString( ValueInt ) + "]" ); if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "val:" ) { QString ValueIDString = MissionKeyString.mid( 4 ); - //uint32_t ValueID = UTIL_ToUInt32( ValueIDString ); + //quint32 ValueID = UTIL_ToUInt32( ValueIDString ); QVector Tokens = TokenizeKey( KeyString ); if( !Tokens.isEmpty( ) ) @@ -108,7 +108,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) // Tokens[2] = pid // Tokens[3] = name - uint32_t PID = UTIL_ToUInt32( Tokens[2] ); + quint32 PID = UTIL_ToUInt32( Tokens[2] ); if( m_PIDToName.find( PID ) != m_PIDToName.end( ) ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] overwriting previous name [" + m_PIDToName[PID] + "] with new name [" + Tokens[3] + "] for PID [" + Tokens[2] + "]" ); @@ -223,7 +223,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) if( Tokens[2] == "winner" || Tokens[2] == "loser" || Tokens[2] == "drawer" || Tokens[2] == "leaver" || Tokens[2] == "practicing" ) { - uint32_t PID = UTIL_ToUInt32( Tokens[1] ); + quint32 PID = UTIL_ToUInt32( Tokens[1] ); if( Tokens[2] == "leaver" ) m_FlagsLeaver[PID] = true; @@ -251,7 +251,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] duplicate DefEvent [" + KeyString + "] found, ignoring" ); else { - uint32_t Arguments = UTIL_ToUInt32( Tokens[2] ); + quint32 Arguments = UTIL_ToUInt32( Tokens[2] ); if( (unsigned int)Tokens.size( ) == Arguments + 4 ) m_DefEvents[Tokens[1]] = Tokens.mid(3); @@ -286,7 +286,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { // replace it with the player's name rather than their PID - uint32_t PID = UTIL_ToUInt32( Tokens[i + 2] ); + quint32 PID = UTIL_ToUInt32( Tokens[i + 2] ); if( m_PIDToName.find( PID ) == m_PIDToName.end( ) ) UTIL_Replace( Format, "{" + UTIL_ToString( i ) + "}", "PID:" + Tokens[i + 2] ); @@ -321,7 +321,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) else if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "chk:" ) { QString CheckIDString = MissionKeyString.mid( 4 ); - //uint32_t CheckID = UTIL_ToUInt32( CheckIDString ); + //quint32 CheckID = UTIL_ToUInt32( CheckIDString ); // todotodo: cheat detection @@ -348,7 +348,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) return false; } -void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) +void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] received " + UTIL_ToString( m_NextValueID ) + "/" + UTIL_ToString( m_NextCheckID ) + " value/check messages" ); @@ -357,11 +357,11 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ) // todotodo: there's no reason to create a new callable for each entry in this map // rewrite ThreadedW3MMDPlayerAdd to act more like ThreadedW3MMDVarAdd - for( QMap :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) + for( QMap :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) { QString Flags = m_Flags[i.key()]; - uint32_t Leaver = 0; - uint32_t Practicing = 0; + quint32 Leaver = 0; + quint32 Practicing = 0; if( m_FlagsLeaver.find( i.key() ) != m_FlagsLeaver.end( ) && m_FlagsLeaver[i.key()] ) { diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index f18d1f4..ecb5b47 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -26,18 +26,18 @@ // #include -typedef QPair VarP; +typedef QPair VarP; class CStatsW3MMD : public CStats { private: QString m_Category; - uint32_t m_NextValueID; - uint32_t m_NextCheckID; - QMap m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case - QMap m_Flags; // pid -> flag (e.g. 0 -> "winner") - QMap m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true - QMap m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true + quint32 m_NextValueID; + quint32 m_NextCheckID; + QMap m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case + QMap m_Flags; // pid -> flag (e.g. 0 -> "winner") + QMap m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true + QMap m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true QMap m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") QMap m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) QMap m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) @@ -49,7 +49,7 @@ class CStatsW3MMD : public CStats virtual ~CStatsW3MMD( ); virtual bool ProcessAction( CIncomingAction *Action ); - virtual void Save( CGHost *GHost, CGHostDB *DB, uint32_t GameID ); + virtual void Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ); virtual QVector TokenizeKey( QString key ); }; diff --git a/ghost/util.cpp b/ghost/util.cpp index c3a94e5..0757f1b 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -69,17 +69,17 @@ QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ) return result; } -uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start ) +quint16 UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start ) { if( (unsigned int)b.size( ) < start + 2 ) return 0; QByteArray temp = b.mid(start, 2); - return (uint16_t)( reverse ? (temp[0] << 8 | temp[1]) : (temp[1] << 8 | temp[0]) ); + return (quint16)( reverse ? (temp[0] << 8 | temp[1]) : (temp[1] << 8 | temp[0]) ); } -uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start ) +quint32 UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start ) { if( (unsigned int)b.size( ) < start + 4 ) return 0; @@ -87,9 +87,9 @@ uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start QByteArray temp = b.mid(start, 4); if (reverse) - return (uint32_t)( temp[0] << 24 | temp[1] << 16 | temp[2] << 8 | temp[3] ); + return (quint32)( temp[0] << 24 | temp[1] << 16 | temp[2] << 8 | temp[3] ); - return (uint32_t)( temp[3] << 24 | temp[2] << 16 | temp[1] << 8 | temp[0] ); + return (quint32)( temp[3] << 24 | temp[2] << 16 | temp[1] << 8 | temp[0] ); } QString UTIL_QByteArrayToDecString( QByteArray b ) @@ -255,19 +255,19 @@ QString UTIL_ToString( double d, int digits ) return QString::number(d, 'g', digits); } -QString UTIL_ToHexString( uint32_t i ) +QString UTIL_ToHexString( quint32 i ) { return QString::number(i); } // todotodo: these UTIL_ToXXX functions don't fail gracefully, they just return garbage (in the uint case usually just -1 casted to an unsigned type it looks like) -uint16_t UTIL_ToUInt16( QString &s ) +quint16 UTIL_ToUInt16( QString &s ) { return s.toUShort(); } -uint32_t UTIL_ToUInt32( QString &s ) +quint32 UTIL_ToUInt32( QString &s ) { return s.toUInt(); } @@ -287,7 +287,7 @@ double UTIL_ToDouble( QString &s ) return s.toDouble(); } -QString UTIL_MSToString( uint32_t ms ) +QString UTIL_MSToString( quint32 ms ) { QString MinString = UTIL_ToString( ( ms / 1000 ) / 60 ); QString SecString = UTIL_ToString( ( ms / 1000 ) % 60 ); @@ -306,7 +306,7 @@ bool UTIL_FileExists( QString file ) return QFile::exists(file); } -QByteArray UTIL_FileRead( QString file, uint32_t start, uint32_t length ) +QByteArray UTIL_FileRead( QString file, quint32 start, quint32 length ) { QFile f(file); f.open(QFile::ReadOnly); @@ -505,11 +505,11 @@ QVector UTIL_Tokenize( QString s, char delim ) return Tokens; } -uint32_t UTIL_Factorial( uint32_t x ) +quint32 UTIL_Factorial( quint32 x ) { - uint32_t Factorial = 1; + quint32 Factorial = 1; - for( uint32_t i = 2; i <= x; i++ ) + for( quint32 i = 2; i <= x; i++ ) Factorial *= i; return Factorial; diff --git a/ghost/util.h b/ghost/util.h index e0c3893..49288a6 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -30,8 +30,8 @@ QByteArray UTIL_CreateBYTEARRAY( unsigned char c ); QByteArray UTIL_CreateBYTEARRAY( quint16 i, bool reverse ); QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ); -uint16_t UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start = 0 ); -uint32_t UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start = 0 ); +quint16 UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start = 0 ); +quint32 UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start = 0 ); QString UTIL_QByteArrayToDecString( QByteArray b ); QString UTIL_QByteArrayToHexString( QByteArray b ); void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ); @@ -56,18 +56,18 @@ QString UTIL_ToString( short i ); QString UTIL_ToString( int i ); QString UTIL_ToString( float f, int digits ); QString UTIL_ToString( double d, int digits ); -QString UTIL_ToHexString( uint32_t i ); -uint16_t UTIL_ToUInt16( QString &s ); -uint32_t UTIL_ToUInt32( QString &s ); +QString UTIL_ToHexString( quint32 i ); +quint16 UTIL_ToUInt16( QString &s ); +quint32 UTIL_ToUInt32( QString &s ); int16_t UTIL_ToInt16( QString &s ); int32_t UTIL_ToInt32( QString &s ); double UTIL_ToDouble( QString &s ); -QString UTIL_MSToString( uint32_t ms ); +QString UTIL_MSToString( quint32 ms ); // files bool UTIL_FileExists( QString file ); -QByteArray UTIL_FileRead( QString file, uint32_t start, uint32_t length ); +QByteArray UTIL_FileRead( QString file, quint32 start, quint32 length ); QByteArray UTIL_FileRead( QString file ); bool UTIL_FileWrite( QString file, const QByteArray &data ); QString UTIL_FileSafeName( QString fileName ); @@ -87,7 +87,7 @@ QVector UTIL_Tokenize( QString s, char delim ); // math -uint32_t UTIL_Factorial( uint32_t x ); +quint32 UTIL_Factorial( quint32 x ); #define nCr(n, r) (UTIL_Factorial(n) / UTIL_Factorial((n)-(r)) / UTIL_Factorial(r)) #define nPr(n, r) (UTIL_Factorial(n) / UTIL_Factorial((n)-(r))) From f0ba30c0a89512de8b7596d27660ecb6a0417dd4 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 09:38:12 +0000 Subject: [PATCH 19/69] fixed mess up with UTIL_AppendBYTEARRAY overloads --- ghost/game_base.cpp | 27 +++++++++++++++++---------- ghost/gameplayer.cpp | 39 +++++++++++++++++++++++++++------------ ghost/gameprotocol.cpp | 3 +++ ghost/gameprotocol.h | 4 ++-- ghost/includes.h | 1 - ghost/main.cpp | 11 +---------- ghost/util.cpp | 2 +- ghost/util.h | 3 ++- 8 files changed, 53 insertions(+), 37 deletions(-) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 8d30831..9e56995 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -826,7 +826,7 @@ void CBaseGame::EventNewConnection() if( !NewSocket ) return; - CONSOLE_Print("New socket connected"); + CONSOLE_Print("New socket connected: " + QString::number((int)NewSocket)); // check the IP blacklist if( m_IPBlackList.find( NewSocket->localAddress().toString() ) != m_IPBlackList.end( ) ) @@ -1447,7 +1447,7 @@ void CBaseGame :: EventPlayerDeleted() QByteArray CRC; QByteArray Action; Action.push_back( 6 ); - UTIL_AppendBYTEARRAY( Action, SaveGameName ); + UTIL_AppendBYTEARRAY( Action, SaveGameName.toUtf8() ); m_Actions.enqueue( new CIncomingAction( player->GetPID( ), CRC, Action ) ); // todotodo: with the new latency system there needs to be a way to send a 0-time action @@ -1629,7 +1629,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game with an invalid name of length " + UTIL_ToString( joinPlayer->GetName( ).size( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1639,7 +1639,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game with the virtual host name" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1650,7 +1650,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but that name is already taken" ); // SendAllChat( m_GHost->m_Language->TryingToJoinTheGameButTaken( joinPlayer->GetName( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1703,7 +1703,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP QVector Slots = m_Map->GetSlots( ); potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((quint16)potential->GetSocket( )->localPort(), false), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1731,7 +1731,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP QVector Slots = m_Map->GetSlots( ); potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((quint16)potential->GetSocket( )->localPort(), false), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1877,7 +1877,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( SID >= m_Slots.size( ) ) { potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1936,7 +1936,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP Player->SetWhoisShouldBeSent( m_GHost->m_SpoofChecks == 1 || ( m_GHost->m_SpoofChecks == 2 && AnyAdminCheck ) ); m_Players.push_back( Player ); potential->SetSocket( NULL ); - potential->SetDeleteMe( true ); + potential->deleteLater(); if( m_SaveGame ) m_Slots[SID] = EnforceSlot; @@ -1977,11 +1977,14 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful +DEBUG_Print("sent SEND_W3GS_SLOTINFOJOIN"); Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((quint16)Player->GetSocket( )->localPort(), false), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player +DEBUG_Print("sent SendVirtualHostPlayerInfo"); SendVirtualHostPlayerInfo( Player ); +DEBUG_Print("sent SendFakePlayerInfo"); SendFakePlayerInfo( Player ); QByteArray BlankIP; @@ -2015,15 +2018,19 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send a map check packet to the new player +DEBUG_Print("sent SEND_W3GS_MAPCHECK"); Player->Send( m_Protocol->SEND_W3GS_MAPCHECK( m_Map->GetMapPath( ), m_Map->GetMapSize( ), m_Map->GetMapInfo( ), m_Map->GetMapCRC( ), m_Map->GetMapSHA1( ) ) ); // send slot info to everyone, so the new player gets this info twice but everyone else still needs to know the new slot layout +DEBUG_Print("sent SendAllSlotInfo"); SendAllSlotInfo( ); // send a welcome message +DEBUG_Print("sent SendWelcomeMessage"); SendWelcomeMessage( Player ); +DEBUG_Print("sent done"); // if spoof checks are required and we won't automatically spoof check this player then tell them how to spoof check // e.g. if automatic spoof checks are disabled, or if automatic spoof checks are done on admins only and this player isn't an admin @@ -3323,7 +3330,7 @@ void CBaseGame :: EventGameStarted( ) UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapWidth( ) ); UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapHeight( ) ); UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapCRC( ) ); - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapPath( ) ); + UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapPath( ).toUtf8() ); UTIL_AppendBYTEARRAY( StatString, "GHost++" ); StatString.push_back( (char)0 ); UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 3a7fc23..6704ea7 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -41,6 +41,7 @@ CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame m_Protocol = nProtocol; m_Game = nGame; m_Socket = nSocket; + m_Socket->setParent(this); m_DeleteMe = false; m_Error = false; @@ -75,12 +76,12 @@ void CPotentialPlayer::EventDataReady() void CPotentialPlayer::EventConnectionError(QAbstractSocket::SocketError /*error*/) { - this->deleteLater(); + deleteLater(); } void CPotentialPlayer::EventConnectionClosed() { - this->deleteLater(); + deleteLater(); } void CGamePlayer::EventPingTimeout() @@ -129,7 +130,7 @@ void CGamePlayer::EventWhoisTimeout() void CGamePlayer::EventConnectionError(QAbstractSocket::SocketError /*error*/) { m_Game->EventPlayerDisconnectSocketError( this ); - this->deleteLater(); + deleteLater(); } void CGamePlayer::EventConnectionTimeout() @@ -139,13 +140,13 @@ void CGamePlayer::EventConnectionTimeout() // this works because in the lobby we send pings every 5 seconds and expect a response to each one // and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like) m_Game->EventPlayerDisconnectTimedOut( this ); - this->deleteLater(); + deleteLater(); } void CGamePlayer::EventConnectionClosed() { m_Game->EventPlayerDisconnectConnectionClosed( this ); - this->deleteLater(); + deleteLater(); } QByteArray CPotentialPlayer :: GetExternalIP( ) @@ -167,7 +168,7 @@ QString CPotentialPlayer :: GetExternalIPString( ) void CPotentialPlayer :: ExtractPackets( ) { - if( !m_Socket ) + if( !m_Socket || !m_Socket->isValid() ) return; // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue @@ -210,7 +211,7 @@ void CPotentialPlayer :: ExtractPackets( ) void CPotentialPlayer :: ProcessPackets( ) { - if( !m_Socket ) + if( !m_Socket || !m_Socket->isValid()) return; // process all the received packets in the m_Packets queue @@ -248,7 +249,7 @@ void CPotentialPlayer :: ProcessPackets( ) void CPotentialPlayer :: Send( QByteArray data ) { - if( m_Socket ) + if( m_Socket && m_Socket->isValid() ) m_Socket->write(data); } @@ -305,6 +306,12 @@ CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QSt // todotodo: properly copy queued packets to the new player, this just discards them // this isn't a big problem because official Warcraft III clients don't send any packets after the join request until they receive a response + QTcpSocket *s = potential->GetSocket(); + + s->disconnect(potential, SLOT(EventConnectionClosed())); + s->disconnect(potential, SLOT(EventConnectionError(QAbstractSocket::SocketError))); + s->disconnect(potential, SLOT(EventDataReady())); + // m_Packets = potential->GetPackets( ); m_PID = nPID; m_Name = nName; @@ -446,12 +453,13 @@ quint32 CGamePlayer :: GetPing( bool LCPing ) void CGamePlayer :: ExtractPackets( ) { - if( !m_Socket ) + if( !m_Socket || !m_Socket->isValid() ) return; // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes + DEBUG_Print("Receiving as normal player with socket " + QString::number((int)m_Socket)); while( m_Socket->bytesAvailable() >= 4 ) { unsigned char header = m_Socket->peek(1).at(0); @@ -463,7 +471,7 @@ void CGamePlayer :: ExtractPackets( ) m_Socket->abort(); m_Socket->deleteLater(); m_Socket = NULL; - this->deleteLater(); + deleteLater(); return; } @@ -494,7 +502,7 @@ void CGamePlayer :: ExtractPackets( ) void CGamePlayer :: ProcessPackets( ) { - if( !m_Socket ) + if( !m_Socket || !m_Socket->isValid() ) return; CIncomingAction *Action = NULL; @@ -666,6 +674,8 @@ void CGamePlayer :: Send( QByteArray data ) // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients + DEBUG_Print("CGamePlayer::Send(" + data.toHex() + ");"); + m_TotalPacketsSent++; if( m_GProxy && m_Game->GetGameLoaded( ) ) @@ -676,8 +686,13 @@ void CGamePlayer :: Send( QByteArray data ) void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPacket ) { - delete m_Socket; + m_Socket->deleteLater(); m_Socket = NewSocket; + + QObject::connect(m_Socket, SIGNAL(readyRead()), this, SLOT(EventDataReady())); + QObject::connect(m_Socket, SIGNAL(disconnected()), this, SLOT(EventConnectionClosed())); + QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(EventConnectionError(QAbstractSocket::SocketError))); + m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_RECONNECT( m_TotalPacketsReceived ) ); quint32 PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 4bb6853..8bb0ff4 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -446,6 +446,9 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, quin { QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; + + // f709 1900 1300 0c00 0000 0000 0000 0000 0000 0000 0000 0000 0c + // f709 1c00 1600 0c01 ff02 0000 0000 0000 0000 0000 0000 0000 0000 000c packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_SLOTINFO ); // W3GS_SLOTINFO packet.push_back( (char)0 ); // packet length will be assigned later diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index 7525aef..047eafb 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -123,12 +123,12 @@ class CGameProtocol // send functions QByteArray SEND_W3GS_PING_FROM_HOST( ); - QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_REJECTJOIN( quint32 reason ); QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ); QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, quint32 leftCode ); QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); - QByteArray SEND_W3GS_SLOTINFO( QVector &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFO( QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_COUNTDOWN_START( ); QByteArray SEND_W3GS_COUNTDOWN_END( ); QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, quint16 sendInterval ); diff --git a/ghost/includes.h b/ghost/includes.h index ba11f8b..08a4c35 100644 --- a/ghost/includes.h +++ b/ghost/includes.h @@ -45,6 +45,5 @@ quint32 GetTicks( ); // milliseconds void CONSOLE_Print( QString message ); void DEBUG_Print( QString message ); -void DEBUG_Print( QByteArray b ); #endif diff --git a/ghost/main.cpp b/ghost/main.cpp index c760639..7e7d6c2 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -83,20 +83,11 @@ void DEBUG_Print( QString message ) cout << message.toStdString() << endl; } -void DEBUG_Print( QByteArray b ) -{ - cout << "{ "; - - for( int i = 0; i < b.size( ); i++ ) - cout << hex << (int)b[i] << " "; - - cout << "}" << endl; -} - // // main // +#include "gameslot.h" int main( int argc, char **argv ) { QCoreApplication a(argc, argv); diff --git a/ghost/util.cpp b/ghost/util.cpp index 0757f1b..4d076e4 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -110,7 +110,7 @@ QString UTIL_QByteArrayToHexString( QByteArray b ) return QString::fromAscii(b.toHex()); } -void UTIL_AppendBYTEARRAY( QByteArray &b, QByteArray append ) +void UTIL_AppendBYTEARRAY( QByteArray &b, const QByteArray &append ) { b.append(append); } diff --git a/ghost/util.h b/ghost/util.h index 49288a6..4f86da4 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -35,8 +35,9 @@ quint32 UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start QString UTIL_QByteArrayToDecString( QByteArray b ); QString UTIL_QByteArrayToHexString( QByteArray b ); void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ); +void UTIL_AppendBYTEARRAY( QByteArray &b, const QByteArray &append ); void UTIL_AppendBYTEARRAY( QByteArray &b, unsigned char *a, int size ); -void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator = true ); +void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator ); void UTIL_AppendBYTEARRAYFast( QByteArray &b, QString &append, bool terminator = true ); void UTIL_AppendBYTEARRAY( QByteArray &b, quint16 i, bool reverse ); void UTIL_AppendBYTEARRAY( QByteArray &b, quint32 i, bool reverse ); From cfb7c5fae46fc9c8e55a2adb35860c4861e8e6be Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 09:49:10 +0000 Subject: [PATCH 20/69] you can now chat in a game... if u leave, it will crash --- ghost/game_base.cpp | 8 +------- ghost/game_base.h | 1 - ghost/gameplayer.cpp | 3 --- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 9e56995..e40ff2b 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -74,6 +74,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 QObject::connect(&m_VotekickTimer, SIGNAL(timeout()), this, SLOT(EventVotekickTimeout())); m_SlotInfoTimer.setInterval(500); + m_SlotInfoTimer.setSingleShot(true); QObject::connect(&m_SlotInfoTimer, SIGNAL(timeout()), this, SLOT(SendAllSlotInfo())); m_CallableUpdateTimer.setInterval(200); @@ -1977,14 +1978,11 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful -DEBUG_Print("sent SEND_W3GS_SLOTINFOJOIN"); Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((quint16)Player->GetSocket( )->localPort(), false), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player -DEBUG_Print("sent SendVirtualHostPlayerInfo"); SendVirtualHostPlayerInfo( Player ); -DEBUG_Print("sent SendFakePlayerInfo"); SendFakePlayerInfo( Player ); QByteArray BlankIP; @@ -2018,19 +2016,15 @@ DEBUG_Print("sent SendFakePlayerInfo"); // send a map check packet to the new player -DEBUG_Print("sent SEND_W3GS_MAPCHECK"); Player->Send( m_Protocol->SEND_W3GS_MAPCHECK( m_Map->GetMapPath( ), m_Map->GetMapSize( ), m_Map->GetMapInfo( ), m_Map->GetMapCRC( ), m_Map->GetMapSHA1( ) ) ); // send slot info to everyone, so the new player gets this info twice but everyone else still needs to know the new slot layout -DEBUG_Print("sent SendAllSlotInfo"); SendAllSlotInfo( ); // send a welcome message -DEBUG_Print("sent SendWelcomeMessage"); SendWelcomeMessage( Player ); -DEBUG_Print("sent done"); // if spoof checks are required and we won't automatically spoof check this player then tell them how to spoof check // e.g. if automatic spoof checks are disabled, or if automatic spoof checks are done on admins only and this player isn't an admin diff --git a/ghost/game_base.h b/ghost/game_base.h index 75e5732..5c08146 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -184,7 +184,6 @@ public slots: virtual bool GetGameLoaded( ) { return m_GameLoaded; } virtual bool GetLagging( ) { return m_Lagging; } - virtual void SetEnforceSlots( QVector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } virtual void SetEnforcePlayers( QVector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } virtual void SetExiting( bool nExiting ) { m_Exiting = nExiting; } diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 6704ea7..719981e 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -459,7 +459,6 @@ void CGamePlayer :: ExtractPackets( ) // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes - DEBUG_Print("Receiving as normal player with socket " + QString::number((int)m_Socket)); while( m_Socket->bytesAvailable() >= 4 ) { unsigned char header = m_Socket->peek(1).at(0); @@ -674,8 +673,6 @@ void CGamePlayer :: Send( QByteArray data ) // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients - DEBUG_Print("CGamePlayer::Send(" + data.toHex() + ");"); - m_TotalPacketsSent++; if( m_GProxy && m_Game->GetGameLoaded( ) ) From 7be8adf81115d7dd2215b4c6b358c9d68ba0f52e Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 19:13:19 +0000 Subject: [PATCH 21/69] player deletion fixed --- ghost/game.cpp | 6 +-- ghost/game_admin.cpp | 4 +- ghost/game_base.cpp | 107 ++++++++++++++++++------------------------- ghost/gameplayer.cpp | 26 ++++++----- ghost/gameplayer.h | 7 +-- ghost/ghost.pro | 2 +- ghost/main.cpp | 4 +- 7 files changed, 71 insertions(+), 85 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index 2165814..dedc8f7 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -1088,7 +1088,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( m_GHost->m_Language->UnableToKickNoMatchesFound( Payload ) ); else if( Matches == 1 ) { - LastMatch->SetDeleteMe( true ); + LastMatch->deleteLater(); LastMatch->SetLeftReason( m_GHost->m_Language->WasKickedByPlayer( User ) ); if( !m_GameLoading && !m_GameLoaded ) @@ -1276,7 +1276,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( !m_GameLoading && !m_GameLoaded && !(*i)->GetReserved( ) && KickPing > 0 && (*i)->GetPing( m_GHost->m_LCPings ) > KickPing ) { - (*i)->SetDeleteMe( true ); + (*i)->deleteLater(); (*i)->SetLeftReason( "was kicked for excessive ping " + UTIL_ToString( (*i)->GetPing( m_GHost->m_LCPings ) ) + " > " + UTIL_ToString( KickPing ) ); (*i)->SetLeftCode( PLAYERLEAVE_LOBBY ); OpenSlot( GetSIDFromPID( (*i)->GetPID( ) ), false ); @@ -1778,7 +1778,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Victim ) { - Victim->SetDeleteMe( true ); + Victim->deleteLater(); Victim->SetLeftReason( m_GHost->m_Language->WasKickedByVote( ) ); if( !m_GameLoading && !m_GameLoaded ) diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 9f7aabf..c6f0c73 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -302,7 +302,7 @@ void CAdminGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoin // tempbanned, goodbye potential->GetSocket( )->write( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_WRONGPASSWORD ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); CONSOLE_Print( "[ADMINGAME] player [" + joinPlayer->GetName( ) + "] at ip [" + (*i).first + "] is trying to join the game but is tempbanned" ); return; } @@ -1233,7 +1233,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( LoginAttempts >= 1 ) { - player->SetDeleteMe( true ); + player->deleteLater(); player->SetLeftReason( "was kicked for too many failed login attempts" ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index e40ff2b..8257141 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -528,6 +528,7 @@ void CBaseGame::EventBroadcastTimeout() m_BroadcastTimer.stop(); return; } + DEBUG_Print("EventBroadcastTimeout"); // construct a fixed host counter which will be used to identify players from this "realm" (i.e. LAN) // the fixed host counter's 4 most significant bits will contain a 4 bit ID (0-15) @@ -593,6 +594,7 @@ void CBaseGame::EventRefreshError() if (m_CountDownStarted) return; + DEBUG_Print("EventRefreshError"); // auto rehost if there was a refresh error in autohosted games m_RefreshError = true; @@ -633,6 +635,7 @@ void CBaseGame::EventRefreshTimeout() m_RefreshTimer.stop(); return; } + DEBUG_Print("EventRefreshTimeout"); // refresh every 3 seconds if( !m_RefreshError && m_GameState == GAME_PUBLIC && GetSlotsOpen( ) > 0) @@ -779,22 +782,11 @@ void CBaseGame::EventAutostartTimeout() void CBaseGame::EventGameOverTimeout() { - bool AlreadyStopped = true; - - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( !(*i)->GetDeleteMe( ) ) - { - AlreadyStopped = false; - break; - } - } + if( m_Players.size() == 0 ) + return; - if( !AlreadyStopped ) - { - CONSOLE_Print( "[GAME: " + m_GameName + "] is over (gameover timer finished)" ); - StopPlayers( "was disconnected (gameover timer finished)" ); - } + CONSOLE_Print( "[GAME: " + m_GameName + "] is over (gameover timer finished)" ); + StopPlayers( "was disconnected (gameover timer finished)" ); } void CBaseGame::EventVotekickTimeout() @@ -827,8 +819,6 @@ void CBaseGame::EventNewConnection() if( !NewSocket ) return; - CONSOLE_Print("New socket connected: " + QString::number((int)NewSocket)); - // check the IP blacklist if( m_IPBlackList.find( NewSocket->localAddress().toString() ) != m_IPBlackList.end( ) ) { @@ -1364,7 +1354,10 @@ void CBaseGame :: EventPlayerDeleted() CGamePlayer *player = (CGamePlayer*)QObject::sender(); CONSOLE_Print( "[GAME: " + m_GameName + "] deleting player [" + player->GetName( ) + "]: " + player->GetLeftReason( ) ); - m_Players.remove(m_Players.indexOf(player)); + int ind = m_Players.indexOf(player); + + if (ind != -1) + m_Players.remove(ind); // create the virtual host player if there is room if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < 12 ) @@ -1537,7 +1530,6 @@ void CBaseGame :: EventPlayerDisconnectTimedOut( CGamePlayer *player ) void CBaseGame::EventPlayerLaggedOut(CGamePlayer *player) { - player->SetDeleteMe( true ); player->SetLeftReason( m_GHost->m_Language->HasLostConnectionTimedOut( ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); @@ -1550,7 +1542,6 @@ void CBaseGame :: EventPlayerDisconnectPlayerError( CGamePlayer *player ) // at the time of this comment there's only one player error and that's when we receive a bad packet from the player // since TCP has checks and balances for data corruption the chances of this are pretty slim - player->SetDeleteMe( true ); player->SetLeftReason( m_GHost->m_Language->HasLostConnectionPlayerError( player->GetErrorString( ) ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); @@ -1582,7 +1573,6 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) return; } - player->SetDeleteMe( true ); player->SetLeftReason( m_GHost->m_Language->HasLostConnectionSocketError( player->GetSocket( )->errorString( ) ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); @@ -1614,7 +1604,6 @@ void CBaseGame :: EventPlayerDisconnectConnectionClosed( CGamePlayer *player ) return; } - player->SetDeleteMe( true ); player->SetLeftReason( m_GHost->m_Language->HasLostConnectionClosedByRemoteHost( ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); @@ -1805,7 +1794,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but isn't in the enforced list" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -1829,7 +1818,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( KickedPlayer ) { - KickedPlayer->SetDeleteMe( true ); + KickedPlayer->deleteLater(); KickedPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForReservedPlayer( joinPlayer->GetName( ) ) ); KickedPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -1862,7 +1851,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( KickedPlayer ) { - KickedPlayer->SetDeleteMe( true ); + KickedPlayer->deleteLater(); KickedPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForOwnerPlayer( joinPlayer->GetName( ) ) ); KickedPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2096,7 +2085,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game with the virtual host name" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -2107,7 +2096,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but that name is already taken" ); // SendAllChat( m_GHost->m_Language->TryingToJoinTheGameButTaken( joinPlayer->GetName( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -2117,7 +2106,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has a rating [" + UTIL_ToString( score, 2 ) + "] outside the limits [" + UTIL_ToString( m_MinimumScore, 2 ) + "] to [" + UTIL_ToString( m_MaximumScore, 2 ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -2199,7 +2188,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but no furthest player was found (this should be impossible)" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -2213,14 +2202,14 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [" + UTIL_ToString( score, 2 ) + "] from the average [" + UTIL_ToString( AverageScore, 2 ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } // kick the furthest player SID = GetSIDFromPID( FurthestPlayer->GetPID( ) ); - FurthestPlayer->SetDeleteMe( true ); + FurthestPlayer->deleteLater(); if( FurthestPlayer->GetScore( ) < -99999.0 ) FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", UTIL_ToString( AverageScore, 2 ) ) ); @@ -2259,7 +2248,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but no lowest player was found (this should be impossible)" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -2273,14 +2262,14 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [" + UTIL_ToString( score, 2 ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } // kick the lowest player SID = GetSIDFromPID( LowestPlayer->GetPID( ) ); - LowestPlayer->SetDeleteMe( true ); + LowestPlayer->deleteLater(); if( LowestPlayer->GetScore( ) < -99999.0 ) LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( "N/A" ) ); @@ -2305,7 +2294,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( SID >= m_Slots.size( ) ) { potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); - potential->SetDeleteMe( true ); + potential->deleteLater(); return; } @@ -2351,7 +2340,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco Player->SetScore( score ); m_Players.push_back( Player ); potential->SetSocket( NULL ); - potential->SetDeleteMe( true ); + potential->deleteLater(); m_Slots[SID] = CGameSlot( Player->GetPID( ), 255, SLOTSTATUS_OCCUPIED, 0, m_Slots[SID].GetTeam( ), m_Slots[SID].GetColour( ), m_Slots[SID].GetRace( ) ); // send slot info to the new player @@ -2507,8 +2496,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) { // this function is only called when a player leave packet is received, not when there's a socket error, kick, etc... + DEBUG_Print("EventPlayerLeft"); - player->SetDeleteMe( true ); + player->deleteLater(); if( reason == PLAYERLEAVE_GPROXY ) player->SetLeftReason( m_GHost->m_Language->WasUnrecoverablyDroppedFromGProxy( ) ); @@ -2598,7 +2588,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - if( !(*i)->GetDeleteMe( ) && (*i)->GetCheckSums( )->empty( ) ) + if( (*i)->GetCheckSums( )->empty( ) ) return; } @@ -2609,12 +2599,9 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - if( !(*i)->GetDeleteMe( ) ) - { - FoundPlayer = true; - FirstCheckSum = (*i)->GetCheckSums( )->front( ); - break; - } + FoundPlayer = true; + FirstCheckSum = (*i)->GetCheckSums( )->front( ); + break; } if( !FoundPlayer ) @@ -2624,7 +2611,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - if( !(*i)->GetDeleteMe( ) && (*i)->GetCheckSums( )->front( ) != FirstCheckSum ) + if( (*i)->GetCheckSums( )->front( ) != FirstCheckSum ) { CONSOLE_Print( "[GAME: " + m_GameName + "] desync detected" ); SendAllChat( m_GHost->m_Language->DesyncDetected( ) ); @@ -2636,10 +2623,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check QMap > Bins; for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) - { - if( !(*j)->GetDeleteMe( ) ) - Bins[(*j)->GetCheckSums( )->front( )].push_back( (*j)->GetPID( ) ); - } + Bins[(*j)->GetCheckSums( )->front( )].push_back( (*j)->GetPID( ) ); quint32 StateNumber = 1; QMap > :: iterator LargestBin = Bins.begin( ); @@ -2708,7 +2692,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check if( Player ) { - Player->SetDeleteMe( true ); + Player->deleteLater(); Player->SetLeftReason( m_GHost->m_Language->WasDroppedDesync( ) ); Player->SetLeftCode( PLAYERLEAVE_LOST ); } @@ -2724,10 +2708,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check } for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( !(*i)->GetDeleteMe( ) ) - (*i)->GetCheckSums( )->dequeue( ); - } + (*i)->GetCheckSums( )->dequeue( ); // add checksum to replay @@ -3049,7 +3030,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map } else { - player->SetDeleteMe( true ); + player->deleteLater(); player->SetLeftReason( "doesn't have the map and there is no local copy of the map to send" ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); @@ -3057,7 +3038,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map } else { - player->SetDeleteMe( true ); + player->deleteLater(); player->SetLeftReason( "doesn't have the map and map downloads are disabled" ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); @@ -3138,12 +3119,12 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, quint32 /*pong*/ ) // also don't kick anyone if the game is loading or loaded - this could happen because we send pings during loading but we stop sending them after the game is loaded // see the Update function for where we send pings - if( !m_GameLoading && !m_GameLoaded && !player->GetDeleteMe( ) && !player->GetReserved( ) && player->GetNumPings( ) >= 3 && player->GetPing( m_GHost->m_LCPings ) > m_GHost->m_AutoKickPing ) + if( !m_GameLoading && !m_GameLoaded && !player->GetReserved( ) && player->GetNumPings( ) >= 3 && player->GetPing( m_GHost->m_LCPings ) > m_GHost->m_AutoKickPing ) { // send a chat message because we don't normally do so when a player leaves the lobby SendAllChat( m_GHost->m_Language->AutokickingPlayerForExcessivePing( player->GetName( ), UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) ) ); - player->SetDeleteMe( true ); + player->deleteLater(); player->SetLeftReason( "was autokicked for excessive ping of " + UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); @@ -3787,7 +3768,7 @@ void CBaseGame :: OpenSlot( unsigned char SID, bool kick ) if( Player ) { - Player->SetDeleteMe( true ); + Player->deleteLater(); Player->SetLeftReason( "was kicked when opening a slot" ); Player->SetLeftCode( PLAYERLEAVE_LOBBY ); } @@ -3809,7 +3790,7 @@ void CBaseGame :: CloseSlot( unsigned char SID, bool kick ) if( Player ) { - Player->SetDeleteMe( true ); + Player->deleteLater(); Player->SetLeftReason( "was kicked when closing a slot" ); Player->SetLeftCode( PLAYERLEAVE_LOBBY ); } @@ -3831,7 +3812,7 @@ void CBaseGame :: ComputerSlot( unsigned char SID, unsigned char skill, bool kic if( Player ) { - Player->SetDeleteMe( true ); + Player->deleteLater(); Player->SetLeftReason( "was kicked when creating a computer in a slot" ); Player->SetLeftCode( PLAYERLEAVE_LOBBY ); } @@ -4513,7 +4494,7 @@ void CBaseGame :: StopPlayers( QString reason ) for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - (*i)->SetDeleteMe( true ); + (*i)->deleteLater(); (*i)->SetLeftReason( reason ); (*i)->SetLeftCode( PLAYERLEAVE_LOST ); } @@ -4525,7 +4506,7 @@ void CBaseGame :: StopLaggers( QString reason ) { if( (*i)->GetLagging( ) ) { - (*i)->SetDeleteMe( true ); + (*i)->deleteLater(); (*i)->SetLeftReason( reason ); (*i)->SetLeftCode( PLAYERLEAVE_DISCONNECT ); } diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 719981e..412344b 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -43,7 +43,6 @@ CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame m_Socket = nSocket; m_Socket->setParent(this); - m_DeleteMe = false; m_Error = false; m_IncomingJoinPlayer = NULL; @@ -52,18 +51,19 @@ CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame QObject::connect(nSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(EventConnectionError(QAbstractSocket::SocketError))); } -CPotentialPlayer :: ~CPotentialPlayer( ) +void CPotentialPlayer::deleteLater() { - if( m_Socket ) - delete m_Socket; + emit aboutToDelete(); + QObject::deleteLater(); +} +CPotentialPlayer :: ~CPotentialPlayer( ) +{ while( !m_Packets.isEmpty( ) ) - { - delete m_Packets.front( ); - m_Packets.dequeue( ); - } + delete m_Packets.dequeue( ); delete m_IncomingJoinPlayer; + m_IncomingJoinPlayer = NULL; } void CPotentialPlayer::EventDataReady() @@ -76,25 +76,28 @@ void CPotentialPlayer::EventDataReady() void CPotentialPlayer::EventConnectionError(QAbstractSocket::SocketError /*error*/) { + DEBUG_Print("CPotentialPlayer::EventConnectionError()"); deleteLater(); } void CPotentialPlayer::EventConnectionClosed() { + DEBUG_Print("CPotentialPlayer::EventConnectionClosed()"); deleteLater(); } void CGamePlayer::EventPingTimeout() { + DEBUG_Print("EventPingTimeout()"); Send(m_Protocol->SEND_W3GS_PING_FROM_HOST( ) ); } void CGamePlayer::EventACKTimeout() { + DEBUG_Print("EventACKTimeout()"); // GProxy++ acks - if( m_Socket ) - m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) ); + Send( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) ); } void CGamePlayer::EventWhoisTimeout() @@ -387,7 +390,7 @@ void CGamePlayer::init() QTimer::singleShot(4000, this, SLOT(EventWhoisTimeout())); QObject::connect(this, SIGNAL(finishedLoading()), m_Game, SLOT(EventPlayerLoaded())); - QObject::connect(this, SIGNAL(destroyed()), m_Game, SLOT(EventPlayerDeleted())); + QObject::connect(this, SIGNAL(aboutToDelete()), m_Game, SLOT(EventPlayerDeleted())); m_SendGProxyMessageTimer.setInterval(20000); QObject::connect(&m_SendGProxyMessageTimer, SIGNAL(timeout()), this, SLOT(EventSendGProxyMessage())); @@ -672,6 +675,7 @@ void CGamePlayer :: Send( QByteArray data ) // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients + DEBUG_Print("Sending " + data.toHex()); m_TotalPacketsSent++; diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index 3b414b6..d2c9f57 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -40,10 +40,14 @@ class CPotentialPlayer { Q_OBJECT +signals: + void aboutToDelete(); + public slots: void EventDataReady(); virtual void EventConnectionError(QAbstractSocket::SocketError); virtual void EventConnectionClosed(); + virtual void deleteLater(); public: CGameProtocol *m_Protocol; @@ -56,7 +60,6 @@ public slots: QTcpSocket *m_Socket; QQueue m_Packets; - bool m_DeleteMe; bool m_Error; QString m_ErrorString; CIncomingJoinPlayer *m_IncomingJoinPlayer; @@ -69,13 +72,11 @@ public slots: virtual QByteArray GetExternalIP( ); virtual QString GetExternalIPString( ); virtual QQueue GetPackets( ) { return m_Packets; } - virtual bool GetDeleteMe( ) { return m_DeleteMe; } virtual bool GetError( ) { return m_Error; } virtual QString GetErrorString( ) { return m_ErrorString; } virtual CIncomingJoinPlayer *GetJoinPlayer( ) { return m_IncomingJoinPlayer; } virtual void SetSocket( QTcpSocket *nSocket ) { m_Socket = nSocket; } - virtual void SetDeleteMe( bool nDeleteMe ) { m_DeleteMe = nDeleteMe; } // processing functions diff --git a/ghost/ghost.pro b/ghost/ghost.pro index 262961f..ae6c996 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -5,7 +5,7 @@ QT += network \ sql QT -= gui TARGET = ghost -CONFIG += console +CONFIG += console debug CONFIG -= app_bundle TEMPLATE = app SOURCES += util.cpp \ diff --git a/ghost/main.cpp b/ghost/main.cpp index 7e7d6c2..8b6fadd 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -61,7 +61,7 @@ void CONSOLE_Print( QString message ) // logging - if (!gLogFile.fileName().isEmpty()) + /*if (!gLogFile.fileName().isEmpty()) { if( gLogMethod == 1 ) { @@ -75,7 +75,7 @@ void CONSOLE_Print( QString message ) } else if( gLogMethod == 2 && gLogFile.isWritable() ) gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; - } + }*/ } void DEBUG_Print( QString message ) From ea55766b2ee415bf46c93f508a11d6f7013bd10e Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 22:05:48 +0000 Subject: [PATCH 22/69] --- ghost/game.cpp | 38 ++++++++++++++++++++------------- ghost/game.h | 1 + ghost/game_base.cpp | 22 +++++++++---------- ghost/ghost.cpp | 1 + ghost/ghostdb.cpp | 2 +- ghost/ghostdb.h | 51 ++++++++++++++++++++++++++------------------- ghost/main.cpp | 3 ++- 7 files changed, 68 insertions(+), 50 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index dedc8f7..60bb3bf 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -86,28 +86,35 @@ CGame :: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostP m_CallableGameAdd = NULL; } -CGame :: ~CGame( ) +void CGame::EventGameDataSaved() { - if( m_CallableGameAdd && m_CallableGameAdd->GetReady( ) ) + if( m_CallableGameAdd->GetResult( ) > 0 ) { - if( m_CallableGameAdd->GetResult( ) > 0 ) - { - CONSOLE_Print( "[GAME: " + m_GameName + "] saving player/stats data to database" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] saving player/stats data to database" ); - // store the CDBGamePlayers in the database + // store the CDBGamePlayers in the database - for( QVector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) - m_GHost->m_Callables.push_back( m_GHost->m_DB->ThreadedGamePlayerAdd( m_CallableGameAdd->GetResult( ), (*i)->GetName( ), (*i)->GetIP( ), (*i)->GetSpoofed( ), (*i)->GetSpoofedRealm( ), (*i)->GetReserved( ), (*i)->GetLoadingTime( ), (*i)->GetLeft( ), (*i)->GetLeftReason( ), (*i)->GetTeam( ), (*i)->GetColour( ) ) ); + for( QVector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) + m_GHost->m_Callables.push_back( m_GHost->m_DB->ThreadedGamePlayerAdd( m_CallableGameAdd->GetResult( ), (*i)->GetName( ), (*i)->GetIP( ), (*i)->GetSpoofed( ), (*i)->GetSpoofedRealm( ), (*i)->GetReserved( ), (*i)->GetLoadingTime( ), (*i)->GetLeft( ), (*i)->GetLeftReason( ), (*i)->GetTeam( ), (*i)->GetColour( ) ) ); - // store the stats in the database + // store the stats in the database - if( m_Stats ) - m_Stats->Save( m_GHost, m_GHost->m_DB, m_CallableGameAdd->GetResult( ) ); - } - else - CONSOLE_Print( "[GAME: " + m_GameName + "] unable to save player/stats data to database" ); + if( m_Stats ) + m_Stats->Save( m_GHost, m_GHost->m_DB, m_CallableGameAdd->GetResult( ) ); + } + else + CONSOLE_Print( "[GAME: " + m_GameName + "] unable to save player/stats data to database" ); - m_GHost->m_DB->RecoverCallable( m_CallableGameAdd ); + m_GHost->m_DB->RecoverCallable( m_CallableGameAdd ); + delete m_CallableGameAdd; + m_CallableGameAdd = NULL; + deleteLater(); +} + +CGame :: ~CGame( ) +{ + if (m_CallableGameAdd != NULL) + { delete m_CallableGameAdd; m_CallableGameAdd = NULL; } @@ -1827,4 +1834,5 @@ void CGame :: SaveGameData( ) { CONSOLE_Print( "[GAME: " + m_GameName + "] saving game data to database" ); m_CallableGameAdd = m_GHost->m_DB->ThreadedGameAdd( m_GHost->m_BNETs.size( ) == 1 ? m_GHost->m_BNETs[0]->GetServer( ) : QString( ), m_DBGame->GetMap( ), m_GameName, m_OwnerName, m_GameTicks / 1000, m_GameState, m_CreatorName, m_CreatorServer ); + QObject::connect(m_CallableGameAdd, SIGNAL(finished()), this, SLOT(EventGameDataSaved())); } diff --git a/ghost/game.h b/ghost/game.h index a048d44..974ae7c 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -52,6 +52,7 @@ class CGame : public CBaseGame public slots: virtual void EventPlayerDeleted(); void EventCallableUpdateTimeout(); + void EventGameDataSaved(); protected: CDBBan *m_DBBanLast; // last ban for the !banlast command - this is a pointer to one of the items in m_DBBans diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 8257141..b452eb7 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -247,6 +247,8 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 } } + CreateVirtualHost( ); + // start listening for connections if( !m_GHost->m_BindAddress.isEmpty( ) ) @@ -528,7 +530,6 @@ void CBaseGame::EventBroadcastTimeout() m_BroadcastTimer.stop(); return; } - DEBUG_Print("EventBroadcastTimeout"); // construct a fixed host counter which will be used to identify players from this "realm" (i.e. LAN) // the fixed host counter's 4 most significant bits will contain a 4 bit ID (0-15) @@ -635,7 +636,6 @@ void CBaseGame::EventRefreshTimeout() m_RefreshTimer.stop(); return; } - DEBUG_Print("EventRefreshTimeout"); // refresh every 3 seconds if( !m_RefreshError && m_GameState == GAME_PUBLIC && GetSlotsOpen( ) > 0) @@ -787,6 +787,7 @@ void CBaseGame::EventGameOverTimeout() CONSOLE_Print( "[GAME: " + m_GameName + "] is over (gameover timer finished)" ); StopPlayers( "was disconnected (gameover timer finished)" ); + deleteLater(); } void CBaseGame::EventVotekickTimeout() @@ -819,6 +820,8 @@ void CBaseGame::EventNewConnection() if( !NewSocket ) return; + DEBUG_Print("New connection incomming"); + // check the IP blacklist if( m_IPBlackList.find( NewSocket->localAddress().toString() ) != m_IPBlackList.end( ) ) { @@ -883,7 +886,7 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString if( message.size( ) > 127 ) message = message.mid( 0, 127 ); - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray( (char*)player->GetPID( ) ), 32, QByteArray( (char*)ExtraFlags, 4 ), message ) ); + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray( 1, player->GetPID( ) ), 32, QByteArray( (char*)ExtraFlags, 4 ), message ) ); } } } @@ -1389,14 +1392,8 @@ void CBaseGame :: EventPlayerDeleted() // end the game if there aren't any players left if( m_Players.isEmpty( ) && (m_GameLoading || m_GameLoaded) ) { - if( !m_Saving ) - { - CONSOLE_Print( "[GAME: " + m_GameName + "] is over (no players left)" ); - SaveGameData( ); - m_Saving = true; - } - else if( IsGameDataSaved( ) ) - deleteLater(); + CONSOLE_Print( "[GAME: " + m_GameName + "] is over (no players left)" ); + SaveGameData( ); } // remove any queued spoofcheck messages for this player @@ -3362,6 +3359,9 @@ void CBaseGame :: EventGameLoaded( ) Longest = *i; } + // start sending actions + m_SendActionTimer.start(); + if( Shortest && Longest ) { SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), UTIL_ToString( (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index c14b428..9eab293 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -553,6 +553,7 @@ void CGHost::EventWaitForNiceExitTimeout() void CGHost::EventAutoHost() { // autohost + DEBUG_Print("EventAutoHost"); if( m_AutoHostGameName.isEmpty( ) || m_AutoHostMaximumGames == 0 || m_AutoHostAutoStartPlayers == 0 ) return; diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index 668e67f..8f89b2e 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -323,7 +323,7 @@ void CBaseCallable :: Init( ) void CBaseCallable :: Close( ) { m_EndTicks = GetTicks( ); - m_Ready = true; + SetReady(true); } CCallableAdminCount :: ~CCallableAdminCount( ) diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index 7bb58ee..e865199 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -165,10 +165,17 @@ class CGHostDB : public QObject // - you should deliver any to-be-orphaned callables to the main vector in CGHost so they can be properly deleted when ready even if you don't care about the result anymore // - e.g. if a player does a stats check immediately before a game is deleted you can't just delete the callable on game deletion unless it's ready -class CBaseCallable +class CBaseCallable : public QObject { + Q_OBJECT + +signals: + void finished(); + protected: QString m_Error; + +private: volatile bool m_Ready; quint32 m_StartTicks; quint32 m_EndTicks; @@ -184,11 +191,11 @@ class CBaseCallable virtual QString GetError( ) { return m_Error; } virtual bool GetReady( ) { return m_Ready; } - virtual void SetReady( bool nReady ) { m_Ready = nReady; } + virtual void SetReady( bool nReady ) { m_Ready = nReady; if (nReady) emit finished(); } virtual quint32 GetElapsed( ) { return m_Ready ? m_EndTicks - m_StartTicks : 0; } }; -class CCallableAdminCount : virtual public CBaseCallable +class CCallableAdminCount : public CBaseCallable { protected: QString m_Server; @@ -203,7 +210,7 @@ class CCallableAdminCount : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableAdminCheck : virtual public CBaseCallable +class CCallableAdminCheck : public CBaseCallable { protected: QString m_Server; @@ -220,7 +227,7 @@ class CCallableAdminCheck : virtual public CBaseCallable virtual void SetResult( bool nResult ) { m_Result = nResult; } }; -class CCallableAdminAdd : virtual public CBaseCallable +class CCallableAdminAdd : public CBaseCallable { protected: QString m_Server; @@ -237,7 +244,7 @@ class CCallableAdminAdd : virtual public CBaseCallable virtual void SetResult( bool nResult ) { m_Result = nResult; } }; -class CCallableAdminRemove : virtual public CBaseCallable +class CCallableAdminRemove : public CBaseCallable { protected: QString m_Server; @@ -254,7 +261,7 @@ class CCallableAdminRemove : virtual public CBaseCallable virtual void SetResult( bool nResult ) { m_Result = nResult; } }; -class CCallableAdminList : virtual public CBaseCallable +class CCallableAdminList : public CBaseCallable { protected: QString m_Server; @@ -268,7 +275,7 @@ class CCallableAdminList : virtual public CBaseCallable virtual void SetResult( QVector nResult ) { m_Result = nResult; } }; -class CCallableBanCount : virtual public CBaseCallable +class CCallableBanCount : public CBaseCallable { protected: QString m_Server; @@ -283,7 +290,7 @@ class CCallableBanCount : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableBanCheck : virtual public CBaseCallable +class CCallableBanCheck : public CBaseCallable { protected: QString m_Server; @@ -302,7 +309,7 @@ class CCallableBanCheck : virtual public CBaseCallable virtual void SetResult( CDBBan *nResult ) { m_Result = nResult; } }; -class CCallableBanAdd : virtual public CBaseCallable +class CCallableBanAdd : public CBaseCallable { protected: QString m_Server; @@ -327,7 +334,7 @@ class CCallableBanAdd : virtual public CBaseCallable virtual void SetResult( bool nResult ) { m_Result = nResult; } }; -class CCallableBanRemove : virtual public CBaseCallable +class CCallableBanRemove : public CBaseCallable { protected: QString m_Server; @@ -344,7 +351,7 @@ class CCallableBanRemove : virtual public CBaseCallable virtual void SetResult( bool nResult ) { m_Result = nResult; } }; -class CCallableBanList : virtual public CBaseCallable +class CCallableBanList : public CBaseCallable { protected: QString m_Server; @@ -358,7 +365,7 @@ class CCallableBanList : virtual public CBaseCallable virtual void SetResult( QVector nResult ) { m_Result = nResult; } }; -class CCallableGameAdd : virtual public CBaseCallable +class CCallableGameAdd : public CBaseCallable { protected: QString m_Server; @@ -379,7 +386,7 @@ class CCallableGameAdd : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableGamePlayerAdd : virtual public CBaseCallable +class CCallableGamePlayerAdd : public CBaseCallable { protected: quint32 m_GameID; @@ -403,7 +410,7 @@ class CCallableGamePlayerAdd : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableGamePlayerSummaryCheck : virtual public CBaseCallable +class CCallableGamePlayerSummaryCheck : public CBaseCallable { protected: QString m_Name; @@ -418,7 +425,7 @@ class CCallableGamePlayerSummaryCheck : virtual public CBaseCallable virtual void SetResult( CDBGamePlayerSummary *nResult ) { m_Result = nResult; } }; -class CCallableDotAGameAdd : virtual public CBaseCallable +class CCallableDotAGameAdd : public CBaseCallable { protected: quint32 m_GameID; @@ -435,7 +442,7 @@ class CCallableDotAGameAdd : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableDotAPlayerAdd : virtual public CBaseCallable +class CCallableDotAPlayerAdd : public CBaseCallable { protected: quint32 m_GameID; @@ -468,7 +475,7 @@ class CCallableDotAPlayerAdd : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableDotAPlayerSummaryCheck : virtual public CBaseCallable +class CCallableDotAPlayerSummaryCheck : public CBaseCallable { protected: QString m_Name; @@ -483,7 +490,7 @@ class CCallableDotAPlayerSummaryCheck : virtual public CBaseCallable virtual void SetResult( CDBDotAPlayerSummary *nResult ) { m_Result = nResult; } }; -class CCallableDownloadAdd : virtual public CBaseCallable +class CCallableDownloadAdd : public CBaseCallable { protected: QString m_Map; @@ -503,7 +510,7 @@ class CCallableDownloadAdd : virtual public CBaseCallable virtual void SetResult( bool nResult ) { m_Result = nResult; } }; -class CCallableScoreCheck : virtual public CBaseCallable +class CCallableScoreCheck : public CBaseCallable { protected: QString m_Category; @@ -520,7 +527,7 @@ class CCallableScoreCheck : virtual public CBaseCallable virtual void SetResult( double nResult ) { m_Result = nResult; } }; -class CCallableW3MMDPlayerAdd : virtual public CBaseCallable +class CCallableW3MMDPlayerAdd : public CBaseCallable { protected: QString m_Category; @@ -540,7 +547,7 @@ class CCallableW3MMDPlayerAdd : virtual public CBaseCallable virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; -class CCallableW3MMDVarAdd : virtual public CBaseCallable +class CCallableW3MMDVarAdd : public CBaseCallable { protected: quint32 m_GameID; diff --git a/ghost/main.cpp b/ghost/main.cpp index 8b6fadd..d6f95a9 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -24,7 +24,7 @@ quint32 GetTime() quint32 GetTicks() { - return gBasicTime.msec(); + return gBasicTime.elapsed(); } void SignalCatcher2( int s ) @@ -99,6 +99,7 @@ int main( int argc, char **argv ) // read config file + gBasicTime.start(); CConfig CFG; CFG.Read( "default.cfg" ); CFG.Read( gCFGFile ); From c6439308e76d1cd484ba4fddd95042751abb9d29 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 23:14:59 +0000 Subject: [PATCH 23/69] playable --- ghost/crc32.cpp | 4 ++-- ghost/crc32.h | 2 +- ghost/game_base.cpp | 2 +- ghost/gameprotocol.cpp | 10 +++++----- ghost/gameprotocol.h | 2 +- ghost/main.cpp | 16 +++++++++++++++- ghost/map.cpp | 4 +++- ghost/map.h | 6 +++--- ghost/packed.cpp | 6 ++---- ghost/util.cpp | 25 ++++++++++++++++++------- ghost/util.h | 4 ++-- 11 files changed, 53 insertions(+), 28 deletions(-) diff --git a/ghost/crc32.cpp b/ghost/crc32.cpp index f30f07f..c710395 100644 --- a/ghost/crc32.cpp +++ b/ghost/crc32.cpp @@ -29,10 +29,10 @@ quint32 CCRC32 :: Reflect( quint32 ulReflect, char cChar ) return ulValue; } -quint32 CCRC32 :: FullCRC( QString data ) +quint32 CCRC32 :: FullCRC( const QByteArray& data ) { quint32 ulCRC = 0xFFFFFFFF; - PartialCRC( &ulCRC, (const unsigned char*)data.toStdString().c_str(), data.toStdString().size() ); + PartialCRC( &ulCRC, (const unsigned char*)data.data(), data.size() ); return ulCRC ^ 0xFFFFFFFF; } diff --git a/ghost/crc32.h b/ghost/crc32.h index 97df039..28d75cf 100644 --- a/ghost/crc32.h +++ b/ghost/crc32.h @@ -7,7 +7,7 @@ class CCRC32 { public: void Initialize( ); - quint32 FullCRC( QString data ); + quint32 FullCRC( const QByteArray& data ); void PartialCRC( quint32 *ulInCRC, const unsigned char *sData, quint32 ulLength ); private: diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index b452eb7..abbae5f 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -3006,7 +3006,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map if( m_GHost->m_AllowDownloads != 0 ) { - QString *MapData = m_Map->GetMapData( ); + QByteArray *MapData = m_Map->GetMapData( ); if( !MapData->isEmpty( ) ) { diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 8bb0ff4..685dc6c 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -504,8 +504,8 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue while( !actions.isEmpty( ) ) { - CIncomingAction *Action = actions.front( ); - actions.dequeue( ); + CIncomingAction *Action = actions.dequeue( ); + subpacket.push_back( Action->GetPID( ) ); UTIL_AppendBYTEARRAY( subpacket, (quint16)Action->GetAction( )->size( ), false ); UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); @@ -515,6 +515,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC( subpacket ), false ); crc32.resize( 2 ); + DEBUG_Print("Calculating CRC for " + subpacket.toHex() + ": " + crc32.toHex()); // finish subpacket @@ -823,7 +824,7 @@ QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QString *mapData ) +QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QByteArray *mapData ) { unsigned char Unknown[] = { 1, 0, 0, 0 }; @@ -854,8 +855,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c // map data - QByteArray Data = mapData->mid(start, End - start).toUtf8(); - UTIL_AppendBYTEARRAYFast( packet, Data ); + packet.append( mapData->mid(start, End - start) ); AssignLength( packet ); } else diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index 047eafb..09dbac0 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -142,7 +142,7 @@ class CGameProtocol QByteArray SEND_W3GS_DECREATEGAME( ); QByteArray SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); QByteArray SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); - QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QString *mapData ); + QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QByteArray *mapData ); QByteArray SEND_W3GS_INCOMING_ACTION2( QQueue actions ); // other functions diff --git a/ghost/main.cpp b/ghost/main.cpp index d6f95a9..ac678a8 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -87,10 +87,24 @@ void DEBUG_Print( QString message ) // main // -#include "gameslot.h" +#include "crc32.h" int main( int argc, char **argv ) { QCoreApplication a(argc, argv); +/* + QByteArray data = QByteArray::fromHex("0224001b019a0700009a070000160101009a0700009a0700001a19303030559a0700009a070000"); + CCRC32 *crc = new CCRC32(); + crc->Initialize(); + DEBUG_Print("Expected: 868c6fa1"); + QByteArray crc32 = UTIL_CreateBYTEARRAY( crc->FullCRC( data ), false ); + // expected: bb76fe69 + DEBUG_Print(crc32.toHex()); + crc32.resize( 2 ); + DEBUG_Print(crc32.toHex()); + + quint16 crc16 = qChecksum("ABCDEF", 6); + DEBUG_Print(UTIL_CreateBYTEARRAY(crc16, false).toHex()); // 5e6f + return 0;*/ gCFGFile = "ghost.cfg"; diff --git a/ghost/map.cpp b/ghost/map.cpp index 359cd9f..9707618 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -905,7 +905,9 @@ void CMap :: CheckValid( ) else if( !m_MapData.isEmpty( ) && (unsigned int)m_MapData.size( ) != UTIL_QByteArrayToUInt32( m_MapSize, false ) ) { m_Valid = false; - CONSOLE_Print( "[MAP] invalid map_size detected - size mismatch with actual map data" ); + DEBUG_Print(m_MapSize.toHex()); + DEBUG_Print("(" + QString::number(m_MapData.size( )) + " vs. " + QString::number(UTIL_QByteArrayToUInt32( m_MapSize, false ))); + CONSOLE_Print( "[MAP] invalid map_size detected - size mismatch with actual map data "); } if( m_MapInfo.size( ) != 4 ) diff --git a/ghost/map.h b/ghost/map.h index 385259a..a0a1835 100644 --- a/ghost/map.h +++ b/ghost/map.h @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -120,7 +120,7 @@ class CMap quint32 m_MapDefaultPlayerScore; // config value: map default player score (for matchmaking) QString m_MapLocalPath; // config value: map local path bool m_MapLoadInGame; - QString m_MapData; // the map data itself, for sending the map to players + QByteArray m_MapData; // the map data itself, for sending the map to players quint32 m_MapNumPlayers; quint32 m_MapNumTeams; QVector m_Slots; @@ -154,7 +154,7 @@ class CMap quint32 GetMapDefaultPlayerScore( ) { return m_MapDefaultPlayerScore; } QString GetMapLocalPath( ) { return m_MapLocalPath; } bool GetMapLoadInGame( ) { return m_MapLoadInGame; } - QString *GetMapData( ) { return &m_MapData; } + QByteArray *GetMapData( ) { return &m_MapData; } quint32 GetMapNumPlayers( ) { return m_MapNumPlayers; } quint32 GetMapNumTeams( ) { return m_MapNumTeams; } QVector GetSlots( ) { return m_Slots; } diff --git a/ghost/packed.cpp b/ghost/packed.cpp index d6faee0..ad2fb74 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -359,9 +359,7 @@ void CPacked :: Compress( bool TFT ) UTIL_AppendBYTEARRAY( Header, (quint32)0, false ); // calculate header CRC - - QString HeaderString = Header; - quint32 CRC = m_CRC->FullCRC( HeaderString ); + quint32 CRC = m_CRC->FullCRC( Header ); // overwrite the (currently zero) header CRC with the calculated CRC @@ -388,7 +386,7 @@ void CPacked :: Compress( bool TFT ) quint32 CRC1 = m_CRC->FullCRC( BlockHeader ); CRC1 = CRC1 ^ ( CRC1 >> 16 ); - quint32 CRC2 = m_CRC->FullCRC( QString::fromStdString(*i) ); + quint32 CRC2 = m_CRC->FullCRC( QString::fromStdString(*i).toUtf8() ); CRC2 = CRC2 ^ ( CRC2 >> 16 ); quint32 BlockCRC = ( CRC1 & 0xFFFF ) | ( CRC2 << 16 ); diff --git a/ghost/util.cpp b/ghost/util.cpp index 4d076e4..0f71696 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -69,17 +69,22 @@ QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ) return result; } -quint16 UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start ) +quint16 UTIL_QByteArrayToUInt16( const QByteArray& b, bool reverse, unsigned int start ) { if( (unsigned int)b.size( ) < start + 2 ) return 0; QByteArray temp = b.mid(start, 2); - return (quint16)( reverse ? (temp[0] << 8 | temp[1]) : (temp[1] << 8 | temp[0]) ); + if (reverse) + return (quint32)( (unsigned char)temp.at(0) << 8 | + (unsigned char)temp.at(1) << 0 ); + + return (quint32)( (unsigned char)temp.at(1) << 8 | + (unsigned char)temp.at(0) << 0 ); } -quint32 UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start ) +quint32 UTIL_QByteArrayToUInt32( const QByteArray& b, bool reverse, unsigned int start ) { if( (unsigned int)b.size( ) < start + 4 ) return 0; @@ -87,9 +92,15 @@ quint32 UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start QByteArray temp = b.mid(start, 4); if (reverse) - return (quint32)( temp[0] << 24 | temp[1] << 16 | temp[2] << 8 | temp[3] ); + return (quint32)( (unsigned char)temp.at(0) << 24 | + (unsigned char)temp.at(1) << 16 | + (unsigned char)temp.at(2) << 8 | + (unsigned char)temp.at(3) << 0 ); - return (quint32)( temp[3] << 24 | temp[2] << 16 | temp[1] << 8 | temp[0] ); + return (quint32)( (unsigned char)temp.at(3) << 24 | + (unsigned char)temp.at(2) << 16 | + (unsigned char)temp.at(1) << 8 | + (unsigned char)temp.at(0) << 0 ); } QString UTIL_QByteArrayToDecString( QByteArray b ) @@ -97,10 +108,10 @@ QString UTIL_QByteArrayToDecString( QByteArray b ) if( b.isEmpty( ) ) return QString( ); - QString result = QString::number( b[0] ); + QString result = QString::number( (unsigned char)b[0] ); for( QByteArray :: iterator i = b.begin( ) + 1; i != b.end( ); i++ ) - result += " " + QString::number( *i ); + result += " " + QString::number( (unsigned char)*i ); return result; } diff --git a/ghost/util.h b/ghost/util.h index 4f86da4..4d551c1 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -30,8 +30,8 @@ QByteArray UTIL_CreateBYTEARRAY( unsigned char c ); QByteArray UTIL_CreateBYTEARRAY( quint16 i, bool reverse ); QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ); -quint16 UTIL_QByteArrayToUInt16( QByteArray b, bool reverse, unsigned int start = 0 ); -quint32 UTIL_QByteArrayToUInt32( QByteArray b, bool reverse, unsigned int start = 0 ); +quint16 UTIL_QByteArrayToUInt16( const QByteArray& b, bool reverse, unsigned int start = 0 ); +quint32 UTIL_QByteArrayToUInt32( const QByteArray& b, bool reverse, unsigned int start = 0 ); QString UTIL_QByteArrayToDecString( QByteArray b ); QString UTIL_QByteArrayToHexString( QByteArray b ); void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ); From c0d2d2350e6f95d28d3f90a93835ecff933a8bc5 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Tue, 20 Apr 2010 23:45:03 +0000 Subject: [PATCH 24/69] removed some comments, changed some event patsh --- ghost/game.cpp | 7 ++++++- ghost/game_base.cpp | 12 +++++------- ghost/game_base.h | 7 ++++--- ghost/ghost.cpp | 2 ++ ghost/map.cpp | 2 -- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index 60bb3bf..7ff507a 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -1834,5 +1834,10 @@ void CGame :: SaveGameData( ) { CONSOLE_Print( "[GAME: " + m_GameName + "] saving game data to database" ); m_CallableGameAdd = m_GHost->m_DB->ThreadedGameAdd( m_GHost->m_BNETs.size( ) == 1 ? m_GHost->m_BNETs[0]->GetServer( ) : QString( ), m_DBGame->GetMap( ), m_GameName, m_OwnerName, m_GameTicks / 1000, m_GameState, m_CreatorName, m_CreatorServer ); - QObject::connect(m_CallableGameAdd, SIGNAL(finished()), this, SLOT(EventGameDataSaved())); + + if (!m_CallableGameAdd->GetReady()) + QObject::connect(m_CallableGameAdd, SIGNAL(finished()), this, SLOT(EventGameDataSaved())); + + else + EventGameDataSaved(); } diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index abbae5f..ffd2cdd 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -103,8 +103,9 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 m_SendActionTimer.setInterval(m_Latency); QObject::connect(&m_SendActionTimer, SIGNAL(timeout()), this, SLOT(EventSendActions())); - - + QObject::connect(this, SIGNAL(finishedLoading()), &m_SendActionTimer, SLOT(start())); + QObject::connect(this, SIGNAL(startedLoading()), this, SLOT(EventGameStarted())); + QObject::connect(this, SIGNAL(finishedLoading()), this, SLOT(EventGameLoaded())); @@ -413,7 +414,7 @@ void CBaseGame::CheckGameLoaded() m_LastActionSentTicks = GetTicks( ); m_GameLoading = false; m_GameLoaded = true; - EventGameLoaded( ); + emit finishedLoading(); return; } } @@ -3329,7 +3330,7 @@ void CBaseGame :: EventGameStarted( ) // move the game to the games in progress vector - emit gameStarted(); + emit startedLoading(); m_GHost->m_Games.push_back( this ); // and finally reenter battle.net chat @@ -3359,9 +3360,6 @@ void CBaseGame :: EventGameLoaded( ) Longest = *i; } - // start sending actions - m_SendActionTimer.start(); - if( Shortest && Longest ) { SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), UTIL_ToString( (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); diff --git a/ghost/game_base.h b/ghost/game_base.h index 5c08146..e23eb91 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -51,12 +51,15 @@ class CBaseGame : public QObject Q_OBJECT signals: - void gameStarted(); + void startedLoading(); + void finishedLoading(); public: CGHost *m_GHost; public slots: + virtual void EventGameStarted( ); + virtual void EventGameLoaded( ); void EventNewConnection(); void EventBroadcastTimeout(); void EventRefreshTimeout(); @@ -249,8 +252,6 @@ public slots: // these events are called outside of any iterations virtual void EventGameRefreshed( QString server ); - virtual void EventGameStarted( ); - virtual void EventGameLoaded( ); // other functions diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 9eab293..c3066d1 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -1127,6 +1127,8 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS else m_CurrentGame = new CGame( this, map, NULL, m_HostPort, gameState, gameName, ownerName, creatorName, creatorServer ); + QObject::connect(m_CurrentGame, SIGNAL(startedLoading()), this, SLOT(EventGameStarted())); + // todotodo: check if listening failed and report the error to the user if( m_SaveGame ) diff --git a/ghost/map.cpp b/ghost/map.cpp index 9707618..bc1347d 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -905,8 +905,6 @@ void CMap :: CheckValid( ) else if( !m_MapData.isEmpty( ) && (unsigned int)m_MapData.size( ) != UTIL_QByteArrayToUInt32( m_MapSize, false ) ) { m_Valid = false; - DEBUG_Print(m_MapSize.toHex()); - DEBUG_Print("(" + QString::number(m_MapData.size( )) + " vs. " + QString::number(UTIL_QByteArrayToUInt32( m_MapSize, false ))); CONSOLE_Print( "[MAP] invalid map_size detected - size mismatch with actual map data "); } From da0c71a35f8ad6bfea473801016c484d3e67778e Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:13:38 +0000 Subject: [PATCH 25/69] --- ghost/game_base.cpp | 202 ++++++++++++++++++++----------------------- ghost/game_base.h | 1 + ghost/gameplayer.cpp | 3 +- ghost/ghost.cpp | 63 +++++++++----- ghost/ghost.h | 5 +- 5 files changed, 141 insertions(+), 133 deletions(-) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index ffd2cdd..633d24a 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -586,6 +586,30 @@ void CBaseGame::EventBroadcastTimeout() } } +void CBaseGame::EventTryAutoRehost() +{ + // there's a slim chance that this isn't actually an autohosted game since there is no explicit autohost flag + // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted + // so rehost it using the current autohost game name + + QString GameName = m_GHost->m_AutoHostGameName + " #" + UTIL_ToString( m_GHost->m_HostCounter ); + CONSOLE_Print( "[GAME: " + m_GameName + "] automatically trying to rehost as public game [" + GameName + "] due to refresh failure" ); + m_LastGameName = m_GameName; + m_GameName = GameName; + m_HostCounter = m_GHost->m_HostCounter++; + m_RefreshError = false; + + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + { + (*i)->QueueGameUncreate( ); + (*i)->QueueEnterChat( ); + + // the game creation message will be sent on the next refresh + } + + m_CreationTime = GetTime( ); +} + void CBaseGame::EventRefreshError() { if (m_GameLoading || m_GameLoaded) @@ -606,28 +630,7 @@ void CBaseGame::EventRefreshError() m_GHost->m_AutoHostMaximumGames != 0 && m_GHost->m_AutoHostAutoStartPlayers != 0 && m_AutoStartPlayers != 0 ) - { - // there's a slim chance that this isn't actually an autohosted game since there is no explicit autohost flag - // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted - // so rehost it using the current autohost game name - - QString GameName = m_GHost->m_AutoHostGameName + " #" + UTIL_ToString( m_GHost->m_HostCounter ); - CONSOLE_Print( "[GAME: " + m_GameName + "] automatically trying to rehost as public game [" + GameName + "] due to refresh failure" ); - m_LastGameName = m_GameName; - m_GameName = GameName; - m_HostCounter = m_GHost->m_HostCounter++; - m_RefreshError = false; - - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) - { - (*i)->QueueGameUncreate( ); - (*i)->QueueEnterChat( ); - - // the game creation message will be sent on the next refresh - } - - m_CreationTime = GetTime( ); - } + QTimer::singleShot(5000, this, SLOT(EventTryAutoRehost())); } void CBaseGame::EventRefreshTimeout() @@ -752,17 +755,15 @@ void CBaseGame::EventMapDataTimeout() void CBaseGame::EventCountdownTimeout() { - if( m_CountDownCounter > 0 ) + if( m_CountDownCounter <= 0 ) { - // we use a countdown counter rather than a "finish countdown time" here because it might alternately round up or down the count - // this sometimes resulted in a countdown of e.g. "6 5 3 2 1" during my testing which looks pretty dumb - // doing it this way ensures it's always "5 4 3 2 1" but each interval might not be *exactly* the same length - - SendAllChat( UTIL_ToString( m_CountDownCounter ) + ". . ." ); - m_CountDownCounter--; + emit startedLoading(); + m_CountdownTimer.stop(); + return; } - else if( !m_GameLoading && !m_GameLoaded ) - EventGameStarted( ); + + SendAllChat( UTIL_ToString( m_CountDownCounter ) + ". . ." ); + m_CountDownCounter--; } void CBaseGame::EventAutostartTimeout() @@ -3327,19 +3328,6 @@ void CBaseGame :: EventGameStarted( ) (*j)->AddLoadInGameData( m_Protocol->SEND_W3GS_GAMELOADED_OTHERS( (*i)->GetPID( ) ) ); } } - - // move the game to the games in progress vector - - emit startedLoading(); - m_GHost->m_Games.push_back( this ); - - // and finally reenter battle.net chat - - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) - { - (*i)->QueueGameUncreate( ); - (*i)->QueueEnterChat( ); - } } void CBaseGame :: EventGameLoaded( ) @@ -4393,94 +4381,94 @@ void CBaseGame :: StartCountDown( bool force ) void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) { - if( !m_CountDownStarted ) - { - // check if enough players are present + if( m_CountDownStarted ) + return; - if( GetNumHumanPlayers( ) < m_AutoStartPlayers ) - { - SendAllChat( m_GHost->m_Language->WaitingForPlayersBeforeAutoStart( UTIL_ToString( m_AutoStartPlayers ), UTIL_ToString( m_AutoStartPlayers - GetNumHumanPlayers( ) ) ) ); - return; - } + // check if enough players are present - // check if everyone has the map + if( GetNumHumanPlayers( ) < m_AutoStartPlayers ) + { + SendAllChat( m_GHost->m_Language->WaitingForPlayersBeforeAutoStart( UTIL_ToString( m_AutoStartPlayers ), UTIL_ToString( m_AutoStartPlayers - GetNumHumanPlayers( ) ) ) ); + return; + } - QString StillDownloading; + // check if everyone has the map - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) - { - if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetDownloadStatus( ) != 100 ) - { - CGamePlayer *Player = GetPlayerFromPID( (*i).GetPID( ) ); - - if( Player ) - { - if( StillDownloading.isEmpty( ) ) - StillDownloading = Player->GetName( ); - else - StillDownloading += ", " + Player->GetName( ); - } - } - } + QString StillDownloading; - if( !StillDownloading.isEmpty( ) ) + for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + { + if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetDownloadStatus( ) != 100 ) { - SendAllChat( m_GHost->m_Language->PlayersStillDownloading( StillDownloading ) ); - return; - } - - // check if everyone is spoof checked + CGamePlayer *Player = GetPlayerFromPID( (*i).GetPID( ) ); - QString NotSpoofChecked; - - if( requireSpoofChecks ) - { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + if( Player ) { - if( !(*i)->GetSpoofed( ) ) - { - if( NotSpoofChecked.isEmpty( ) ) - NotSpoofChecked = (*i)->GetName( ); - else - NotSpoofChecked += ", " + (*i)->GetName( ); - } + if( StillDownloading.isEmpty( ) ) + StillDownloading = Player->GetName( ); + else + StillDownloading += ", " + Player->GetName( ); } - - if( !NotSpoofChecked.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); } + } - // check if everyone has been pinged enough (3 times) that the autokicker would have kicked them by now - // see function EventPlayerPongToHost for the autokicker code + if( !StillDownloading.isEmpty( ) ) + { + SendAllChat( m_GHost->m_Language->PlayersStillDownloading( StillDownloading ) ); + return; + } + + // check if everyone is spoof checked - QString NotPinged; + QString NotSpoofChecked; + if( requireSpoofChecks ) + { for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - if( !(*i)->GetReserved( ) && (*i)->GetNumPings( ) < 3 ) + if( !(*i)->GetSpoofed( ) ) { - if( NotPinged.isEmpty( ) ) - NotPinged = (*i)->GetName( ); + if( NotSpoofChecked.isEmpty( ) ) + NotSpoofChecked = (*i)->GetName( ); else - NotPinged += ", " + (*i)->GetName( ); + NotSpoofChecked += ", " + (*i)->GetName( ); } } - if( !NotPinged.isEmpty( ) ) - { - SendAllChat( m_GHost->m_Language->PlayersNotYetPingedAutoStart( NotPinged ) ); - return; - } + if( !NotSpoofChecked.isEmpty( ) ) + SendAllChat( m_GHost->m_Language->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); + } + + // check if everyone has been pinged enough (3 times) that the autokicker would have kicked them by now + // see function EventPlayerPongToHost for the autokicker code - // if no problems found start the game + QString NotPinged; - if( StillDownloading.isEmpty( ) && NotSpoofChecked.isEmpty( ) && NotPinged.isEmpty( ) ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + { + if( !(*i)->GetReserved( ) && (*i)->GetNumPings( ) < 3 ) { - m_CountDownStarted = true; - m_CountdownTimer.start(); - m_CountDownCounter = 10; + if( NotPinged.isEmpty( ) ) + NotPinged = (*i)->GetName( ); + else + NotPinged += ", " + (*i)->GetName( ); } } + + if( !NotPinged.isEmpty( ) ) + { + SendAllChat( m_GHost->m_Language->PlayersNotYetPingedAutoStart( NotPinged ) ); + return; + } + + // if no problems found start the game + + if( StillDownloading.isEmpty( ) && NotSpoofChecked.isEmpty( ) && NotPinged.isEmpty( ) ) + { + m_CountDownStarted = true; + m_CountdownTimer.start(); + m_CountDownCounter = 10; + } } void CBaseGame :: StopPlayers( QString reason ) diff --git a/ghost/game_base.h b/ghost/game_base.h index e23eb91..81e5b83 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -64,6 +64,7 @@ public slots: void EventBroadcastTimeout(); void EventRefreshTimeout(); void EventRefreshError(); + void EventTryAutoRehost(); void EventMapDataTimeout(); void EventCountdownTimeout(); void EventAutostartTimeout(); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 412344b..870e563 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -675,7 +675,8 @@ void CGamePlayer :: Send( QByteArray data ) // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients - DEBUG_Print("Sending " + data.toHex()); + if (data.toHex() != "f70c06006400") + DEBUG_Print("Sending " + data.toHex()); m_TotalPacketsSent++; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index c3066d1..943a22e 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -75,6 +75,10 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_CallableUpdateTimer.setInterval(200); QObject::connect(&m_CallableUpdateTimer, SIGNAL(timeout()), this, SLOT(EventCallableUpdateTimeout())); + m_AutoHostTimer.setSingleShot(true); + m_AutoHostTimer.setInterval(500); + QObject::connect(&m_AutoHostTimer, SIGNAL(timeout()), this, SLOT(EventAutoHost())); + // create connections CONSOLE_Print( "[GHOST] opening primary database" ); @@ -336,7 +340,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CONSOLE_Print( "[GHOST] GHost++ Version " + m_Version + " (without MySQL support)" ); #endif - EventAutoHost(); + m_AutoHostTimer.start(0); } CGHost :: ~CGHost( ) @@ -373,15 +377,20 @@ CGHost :: ~CGHost( ) void CGHost::EventGameStarted() { + DEBUG_Print("EventGameStarted"); + // move the game to the games in progress vector + m_Games.push_back( m_CurrentGame ); m_CurrentGame = NULL; - if (m_LastAutoHostTime.elapsed() > 30) + // and finally reenter battle.net chat + + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { - EventAutoHost(); - return; + (*i)->QueueGameUncreate( ); + (*i)->QueueEnterChat( ); } - QTimer::singleShot(30 - m_LastAutoHostTime.elapsed(), this, SLOT(EventAutoHost())); + m_AutoHostTimer.start(); } void CGHost::EventIncomingReconnection() @@ -560,6 +569,7 @@ void CGHost::EventAutoHost() // copy all the checks from CGHost :: CreateGame here because we don't want to spam the chat when there's an error // instead we fail silently and try again soon + DEBUG_Print(QString::number( m_Games.size( ) )); if( m_ExitingNice || !m_Enabled || m_CurrentGame || m_Games.size( ) >= m_MaxGames || m_Games.size( ) >= m_AutoHostMaximumGames ) return; @@ -698,30 +708,30 @@ void CGHost :: EventBNETGameRefreshed( CBNET *bnet ) void CGHost :: EventBNETGameRefreshFailed( CBNET *bnet ) { - if( m_CurrentGame ) + if( !m_CurrentGame ) + return; + + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - { - (*i)->QueueChatCommand( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); + (*i)->QueueChatCommand( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); - if( (*i)->GetServer( ) == m_CurrentGame->GetCreatorServer( ) ) - (*i)->QueueChatCommand( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ), m_CurrentGame->GetCreatorName( ), true ); - } + if( (*i)->GetServer( ) == m_CurrentGame->GetCreatorServer( ) ) + (*i)->QueueChatCommand( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ), m_CurrentGame->GetCreatorName( ), true ); + } - if( m_AdminGame ) - m_AdminGame->SendAllChat( m_Language->BNETGameHostingFailed( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); + if( m_AdminGame ) + m_AdminGame->SendAllChat( m_Language->BNETGameHostingFailed( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); - m_CurrentGame->SendAllChat( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); + m_CurrentGame->SendAllChat( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); - // we take the easy route and simply close the lobby if a refresh fails - // it's possible at least one refresh succeeded and therefore the game is still joinable on at least one battle.net (plus on the local network) but we don't keep track of that - // we only close the game if it has no players since we support game rehosting (via !priv and !pub in the lobby) + // we take the easy route and simply close the lobby if a refresh fails + // it's possible at least one refresh succeeded and therefore the game is still joinable on at least one battle.net (plus on the local network) but we don't keep track of that + // we only close the game if it has no players since we support game rehosting (via !priv and !pub in the lobby) - if( m_CurrentGame->GetNumHumanPlayers( ) == 0 ) - m_CurrentGame->SetExiting( true ); + if( m_CurrentGame->GetNumHumanPlayers( ) == 0 ) + m_CurrentGame->SetExiting( true ); - m_CurrentGame->EventRefreshError(); - } + m_CurrentGame->EventRefreshError(); } void CGHost :: EventBNETConnectTimedOut( CBNET *bnet ) @@ -775,8 +785,10 @@ void CGHost :: EventBNETEmote( CBNET *bnet, QString user, QString message ) } } -void CGHost :: EventGameDeleted( CBaseGame *game ) +void CGHost::EventGameDeleted() { + CBaseGame *game = (CBaseGame *)QObject::sender(); + for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { (*i)->QueueChatCommand( m_Language->GameIsOver( game->GetDescription( ) ) ); @@ -784,6 +796,10 @@ void CGHost :: EventGameDeleted( CBaseGame *game ) if( (*i)->GetServer( ) == game->GetCreatorServer( ) ) (*i)->QueueChatCommand( m_Language->GameIsOver( game->GetDescription( ) ), game->GetCreatorName( ), true ); } + + int ind = m_Games.indexOf(game); + if (ind != -1) + m_Games.remove(ind); } void CGHost :: ReloadConfigs( ) @@ -1128,6 +1144,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS m_CurrentGame = new CGame( this, map, NULL, m_HostPort, gameState, gameName, ownerName, creatorName, creatorServer ); QObject::connect(m_CurrentGame, SIGNAL(startedLoading()), this, SLOT(EventGameStarted())); + QObject::connect(m_CurrentGame, SIGNAL(destroyed()), this, SLOT(EventGameDeleted())); // todotodo: check if listening failed and report the error to the user diff --git a/ghost/ghost.h b/ghost/ghost.h index c19efb0..481a094 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -58,11 +58,12 @@ public slots: void EventWaitForNiceExitTimeout(); void EventAutoHost(); void EventGameStarted(); + void EventGameDeleted(); void CreateReconnectServer(); public: QTime m_LastAutoHostTime; - QTimer m_CallableUpdateTimer; + QTimer m_CallableUpdateTimer, m_AutoHostTimer; QUdpSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) QTcpServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects CGPSProtocol *m_GPSProtocol; @@ -165,7 +166,7 @@ public slots: void EventBNETWhisper( CBNET *bnet, QString user, QString message ); void EventBNETChat( CBNET *bnet, QString user, QString message ); void EventBNETEmote( CBNET *bnet, QString user, QString message ); - void EventGameDeleted( CBaseGame *game ); +// void EventGameDeleted( CBaseGame *game ); // other functions From 8f93e0d56d2de0078d12000caecadb0dc968f170 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:15:10 +0000 Subject: [PATCH 26/69] --- ghost/ghost.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 943a22e..fe2fb9f 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -800,6 +800,8 @@ void CGHost::EventGameDeleted() int ind = m_Games.indexOf(game); if (ind != -1) m_Games.remove(ind); + + m_AutoHostTimer.start(); } void CGHost :: ReloadConfigs( ) From fcfbf4466c0190fbdf0585512edbfcfab41a87b4 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:15:48 +0000 Subject: [PATCH 27/69] --- ghost/ghost.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index fe2fb9f..6c03808 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -562,14 +562,10 @@ void CGHost::EventWaitForNiceExitTimeout() void CGHost::EventAutoHost() { // autohost - DEBUG_Print("EventAutoHost"); - if( m_AutoHostGameName.isEmpty( ) || m_AutoHostMaximumGames == 0 || m_AutoHostAutoStartPlayers == 0 ) return; // copy all the checks from CGHost :: CreateGame here because we don't want to spam the chat when there's an error - // instead we fail silently and try again soon - DEBUG_Print(QString::number( m_Games.size( ) )); if( m_ExitingNice || !m_Enabled || m_CurrentGame || m_Games.size( ) >= m_MaxGames || m_Games.size( ) >= m_AutoHostMaximumGames ) return; From 40b645d73cbb5151979c3e07da07c64346b73b38 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:26:06 +0000 Subject: [PATCH 28/69] --- ghost/bnet.cpp | 7 +++---- ghost/bnet.h | 2 -- ghost/game.cpp | 2 +- ghost/game_admin.cpp | 6 +++--- ghost/game_base.cpp | 1 - ghost/game_base.h | 2 -- ghost/ghost.cpp | 9 ++++++++- ghost/ghost.h | 1 + 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 015f4ea..5a697c8 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -75,7 +75,6 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_BNCSUtil = new CBNCSUtilInterface( nUserName, nUserPassword ); m_CallableAdminList = m_GHost->m_DB->ThreadedAdminList( nServer ); m_CallableBanList = m_GHost->m_DB->ThreadedBanList( nServer ); - m_Exiting = false; m_Server = nServer; QString LowerServer = m_Server; LowerServer = LowerServer.toLower(); @@ -1505,13 +1504,13 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Payload == "nice" ) m_GHost->m_ExitingNice = true; else if( Payload == "force" ) - m_Exiting = true; + m_GHost->deleteLater(); else { if( m_GHost->m_CurrentGame || !m_GHost->m_Games.isEmpty( ) ) QueueChatCommand( m_GHost->m_Language->AtLeastOneGameActiveUseForceToShutdown( ), User, Whisper ); else - m_Exiting = true; + m_GHost->deleteLater(); } } else @@ -2018,7 +2017,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { QueueChatCommand( m_GHost->m_Language->UnhostingGame( m_GHost->m_CurrentGame->GetDescription( ) ), User, Whisper ); - m_GHost->m_CurrentGame->SetExiting( true ); + m_GHost->m_CurrentGame->deleteLater(); } } else diff --git a/ghost/bnet.h b/ghost/bnet.h index 9fdb8c8..6d8bc22 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -107,7 +107,6 @@ public slots: CCallableBanList *m_CallableBanList; // threaded database ban list in progress QVector m_Admins; // vector of cached admins QVector m_Bans; // vector of cached bans - bool m_Exiting; // set to true and this class will be deleted next update QString m_Server; // battle.net server to connect to QString m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) QString m_ServerAlias; // battle.net server alias (short name, e.g. "USEast") @@ -150,7 +149,6 @@ public slots: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, quint32 nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); virtual ~CBNET( ); - bool GetExiting( ) { return m_Exiting; } QString GetServer( ) { return m_Server; } QString GetServerAlias( ) { return m_ServerAlias; } QString GetCDKeyROC( ) { return m_CDKeyROC; } diff --git a/ghost/game.cpp b/ghost/game.cpp index 7ff507a..2b556aa 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -1560,7 +1560,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // if( Command == "unhost" && !m_CountDownStarted ) - m_Exiting = true; + deleteLater(); // // !UNLOCK diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index c6f0c73..54ecf04 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -844,13 +844,13 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Payload == "nice" ) m_GHost->m_ExitingNice = true; else if( Payload == "force" ) - m_Exiting = true; + deleteLater(); else { if( m_GHost->m_CurrentGame || !m_GHost->m_Games.isEmpty( ) ) SendChat( player, m_GHost->m_Language->AtLeastOneGameActiveUseForceToShutdown( ) ); else - m_Exiting = true; + deleteLater(); } } @@ -1175,7 +1175,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else { SendChat( player, m_GHost->m_Language->UnhostingGame( m_GHost->m_CurrentGame->GetDescription( ) ) ); - m_GHost->m_CurrentGame->SetExiting( true ); + m_GHost->m_CurrentGame->deleteLater(); } } else diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 633d24a..34f1b35 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -123,7 +123,6 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 else m_Replay = NULL; - m_Exiting = false; m_Saving = false; m_HostPort = nHostPort; m_GameState = nGameState; diff --git a/ghost/game_base.h b/ghost/game_base.h index 81e5b83..761b561 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -108,7 +108,6 @@ public slots: CMap *m_Map; // map data CSaveGame *m_SaveGame; // savegame data (this is a pointer to global data) CReplay *m_Replay; // replay - bool m_Exiting; // set to true and this class will be deleted next update bool m_Saving; // if we're currently saving game data to the database quint16 m_HostPort; // the port to host games on unsigned char m_GameState; // game state, public or private @@ -190,7 +189,6 @@ public slots: virtual void SetEnforceSlots( QVector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } virtual void SetEnforcePlayers( QVector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } - virtual void SetExiting( bool nExiting ) { m_Exiting = nExiting; } virtual void SetAutoStartPlayers( quint32 nAutoStartPlayers ) { m_AutoStartPlayers = nAutoStartPlayers; } virtual void SetMinimumScore( double nMinimumScore ) { m_MinimumScore = nMinimumScore; } virtual void SetMaximumScore( double nMaximumScore ) { m_MaximumScore = nMaximumScore; } diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 6c03808..d43fdfb 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -324,6 +324,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) { CONSOLE_Print( "[GHOST] creating admin game" ); m_AdminGame = new CAdminGame( this, m_AdminMap, NULL, m_AdminGamePort, 0, "GHost++ Admin Game", m_AdminGamePassword ); + QObject::connect(m_AdminGame, SIGNAL(destroyed()), this, SLOT(EventAdminGameDeleted())); if( m_AdminGamePort == m_HostPort ) CONSOLE_Print( "[GHOST] warning - admingame_port and bot_hostport are set to the same value, you won't be able to host any games" ); @@ -343,6 +344,12 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_AutoHostTimer.start(0); } +void CGHost::EventAdminGameDeleted() +{ + m_AdminGame = NULL; + deleteLater(); +} + CGHost :: ~CGHost( ) { delete m_GPSProtocol; @@ -725,7 +732,7 @@ void CGHost :: EventBNETGameRefreshFailed( CBNET *bnet ) // we only close the game if it has no players since we support game rehosting (via !priv and !pub in the lobby) if( m_CurrentGame->GetNumHumanPlayers( ) == 0 ) - m_CurrentGame->SetExiting( true ); + m_CurrentGame->deleteLater(); m_CurrentGame->EventRefreshError(); } diff --git a/ghost/ghost.h b/ghost/ghost.h index 481a094..c7082cc 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -59,6 +59,7 @@ public slots: void EventAutoHost(); void EventGameStarted(); void EventGameDeleted(); + void EventAdminGameDeleted(); void CreateReconnectServer(); public: From 8203b7ff50d31ac5657a89d6d045e261bcc17c48 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:27:54 +0000 Subject: [PATCH 29/69] --- ghost/ghost.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index d43fdfb..889c7d3 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -346,6 +346,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) void CGHost::EventAdminGameDeleted() { + CONSOLE_Print("[GHOST] Admin Game has been deleted, quitting."); m_AdminGame = NULL; deleteLater(); } @@ -800,6 +801,9 @@ void CGHost::EventGameDeleted() (*i)->QueueChatCommand( m_Language->GameIsOver( game->GetDescription( ) ), game->GetCreatorName( ), true ); } + if (game == m_CurrentGame) + m_CurrentGame = NULL; + int ind = m_Games.indexOf(game); if (ind != -1) m_Games.remove(ind); From a083bd8fec9244e46ef6611cae89cb8538f21945 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:38:31 +0000 Subject: [PATCH 30/69] --- ghost/gameplayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 870e563..cf92be4 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -675,8 +675,8 @@ void CGamePlayer :: Send( QByteArray data ) // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients - if (data.toHex() != "f70c06006400") - DEBUG_Print("Sending " + data.toHex()); + //if (data.toHex() != "f70c06006400") + // DEBUG_Print("Sending " + data.toHex()); m_TotalPacketsSent++; From 769010a03b1099a45ec5a81ee368717b163c396d Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 01:47:39 +0000 Subject: [PATCH 31/69] --- ghost/game.cpp | 1 + ghost/gameplayer.cpp | 4 ++-- ghost/ghost.cpp | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index 2b556aa..1b8b6c1 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -406,6 +406,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( ( Command == "abort" || Command == "a" ) && m_CountDownStarted && !m_GameLoading && !m_GameLoaded ) { SendAllChat( m_GHost->m_Language->CountDownAborted( ) ); + m_CountdownTimer.stop(); m_CountDownStarted = false; } diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index cf92be4..870e563 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -675,8 +675,8 @@ void CGamePlayer :: Send( QByteArray data ) // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients - //if (data.toHex() != "f70c06006400") - // DEBUG_Print("Sending " + data.toHex()); + if (data.toHex() != "f70c06006400") + DEBUG_Print("Sending " + data.toHex()); m_TotalPacketsSent++; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 889c7d3..2f3c497 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -575,6 +575,12 @@ void CGHost::EventAutoHost() // copy all the checks from CGHost :: CreateGame here because we don't want to spam the chat when there's an error + if (m_CurrentGame) + DEBUG_Print("Not autohosting because a game is still open"); + + if (m_Games.size( ) >= m_MaxGames) + DEBUG_Print("Not autohosting because m_Games.size( ) >= m_MaxGames"); + if( m_ExitingNice || !m_Enabled || m_CurrentGame || m_Games.size( ) >= m_MaxGames || m_Games.size( ) >= m_AutoHostMaximumGames ) return; From 3a3dbf52153568f3ec4d705ea7f9c7b51442ab21 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 02:19:29 +0000 Subject: [PATCH 32/69] --- ghost/game.cpp | 13 +++++++------ ghost/game_base.cpp | 41 ++++++++++------------------------------- ghost/game_base.h | 3 +-- 3 files changed, 18 insertions(+), 39 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index 1b8b6c1..9f9d069 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -1121,17 +1121,17 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( m_GHost->m_Language->LatencyIs( UTIL_ToString( m_Latency ) ) ); else { - m_Latency = UTIL_ToUInt32( Payload ); + m_RequestedLatency = UTIL_ToUInt32( Payload ); - if( m_Latency <= 20 ) + if( m_RequestedLatency <= 20 ) { - m_Latency = 20; + m_RequestedLatency = 20; SendAllChat( m_GHost->m_Language->SettingLatencyToMinimum( "20" ) ); } - else if( m_Latency >= 500 ) + else if( m_RequestedLatency >= 2000 ) { - m_Latency = 500; - SendAllChat( m_GHost->m_Language->SettingLatencyToMaximum( "500" ) ); + m_RequestedLatency = 2000; + SendAllChat( m_GHost->m_Language->SettingLatencyToMaximum( "2000" ) ); } else SendAllChat( m_GHost->m_Language->SettingLatencyTo( UTIL_ToString( m_Latency ) ) ); @@ -1611,6 +1611,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { DeleteVirtualHost( ); m_VirtualHostName = Payload; + CreateVirtualHost(); } // diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 34f1b35..e442a4b 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -109,11 +109,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 - - - - - + m_RequestedLatency = 0; m_Protocol = new CGameProtocol( m_GHost ); m_Map = new CMap( *nMap ); m_SaveGame = nSaveGame; @@ -165,7 +161,6 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 m_StartedLoadingTicks = 0; m_StartPlayers = 0; m_LastActionSentTicks = 0; - m_LastActionLateBy = 0; m_StartedLaggingTime = 0; m_LastLagScreenTime = 0; m_LastPlayerLeaveTicks = 0; @@ -311,24 +306,6 @@ CBaseGame :: ~CBaseGame( ) } } -quint32 CBaseGame :: GetNextTimedActionTicks( ) -{ - // return the number of ticks (ms) until the next "timed action", which for our purposes is the next game update - // the main GHost++ loop will make sure the next loop update happens at or before this value - // note: there's no reason this function couldn't take into account the game's other timers too but they're far less critical - // warning: this function must take into account when actions are not being sent (e.g. during loading or lagging) - - if( !m_GameLoaded || m_Lagging ) - return 50; - - quint32 TicksSinceLastUpdate = GetTicks( ) - m_LastActionSentTicks; - - if( TicksSinceLastUpdate > m_Latency - m_LastActionLateBy ) - return 0; - else - return m_Latency - m_LastActionLateBy - TicksSinceLastUpdate; -} - quint32 CBaseGame :: GetSlotsOccupied( ) { quint32 NumSlotsOccupied = 0; @@ -1102,18 +1079,20 @@ void CBaseGame :: SendAllActions( ) m_Replay->AddTimeSlot( m_Latency, m_Actions ); } - quint32 ActualSendInterval = GetTicks( ) - m_LastActionSentTicks; - quint32 ExpectedSendInterval = m_Latency - m_LastActionLateBy; - m_LastActionLateBy = ActualSendInterval - ExpectedSendInterval; - - if( m_LastActionLateBy > m_Latency ) + if( GetTicks() - m_LastActionSentTicks > m_Latency ) { // something is going terribly wrong - GHost++ is probably starved of resources // print a message because even though this will take more resources it should provide some information to the administrator for future reference // other solutions - dynamically modify the latency, request higher priority, terminate other games, ??? - CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but the last update was late by " + UTIL_ToString( m_LastActionLateBy ) + "ms" ); - m_LastActionLateBy = m_Latency; + CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but GHost needed " + QString::number(GetTicks() - m_LastActionSentTicks) + "ms, your machine is probably overloaded" ); + } + + if (m_RequestedLatency != 0) + { + m_Latency = m_RequestedLatency; + m_SendActionTimer.setInterval(m_RequestedLatency); + m_RequestedLatency = 0; } m_LastActionSentTicks = GetTicks( ); diff --git a/ghost/game_base.h b/ghost/game_base.h index 761b561..510e92d 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -128,6 +128,7 @@ public slots: quint32 m_RandomSeed; // the random seed sent to the Warcraft III clients quint32 m_HostCounter; // a unique game number quint32 m_Latency; // the number of ms to wait between sending action packets (we queue any received during this time) + quint32 m_RequestedLatency; quint32 m_SyncLimit; // the maximum number of packets a player can fall out of sync before starting the lag screen quint32 m_SyncCounter; // the number of actions sent so far (for determining if anyone is lagging) quint32 m_GameTicks; // ingame ticks @@ -139,7 +140,6 @@ public slots: quint32 m_StartedLoadingTicks; // GetTicks when the game started loading quint32 m_StartPlayers; // number of players when the game started quint32 m_LastActionSentTicks; // GetTicks when the last action packet was sent - quint32 m_LastActionLateBy; // the number of ticks we were late sending the last action packet by quint32 m_StartedLaggingTime; // GetTime when the last lag screen started quint32 m_LastLagScreenTime; // GetTime when the last lag screen was active (continuously updated) quint32 m_LastPlayerLeaveTicks; // GetTicks when the most recent player left the game @@ -194,7 +194,6 @@ public slots: virtual void SetMaximumScore( double nMaximumScore ) { m_MaximumScore = nMaximumScore; } virtual void SetMatchMaking( bool nMatchMaking ) { m_MatchMaking = nMatchMaking; } - virtual quint32 GetNextTimedActionTicks( ); virtual quint32 GetSlotsOccupied( ); virtual quint32 GetSlotsOpen( ); virtual quint32 GetNumPlayers( ); From 4c9bd3036bbcd8ea3f458104931a5e72603ee5a2 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 02:29:06 +0000 Subject: [PATCH 33/69] --- ghost/game.cpp | 16 +++++++++------- ghost/game_base.cpp | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index 9f9d069..d3c51fe 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -1123,18 +1123,20 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { m_RequestedLatency = UTIL_ToUInt32( Payload ); - if( m_RequestedLatency <= 20 ) + quint32 min = 20, max = 2000; + + if( m_RequestedLatency <= min ) { - m_RequestedLatency = 20; - SendAllChat( m_GHost->m_Language->SettingLatencyToMinimum( "20" ) ); + m_RequestedLatency = min; + SendAllChat( m_GHost->m_Language->SettingLatencyToMinimum( QString::number(m_RequestedLatency) ) ); } - else if( m_RequestedLatency >= 2000 ) + else if( m_RequestedLatency >= max ) { - m_RequestedLatency = 2000; - SendAllChat( m_GHost->m_Language->SettingLatencyToMaximum( "2000" ) ); + m_RequestedLatency = max; + SendAllChat( m_GHost->m_Language->SettingLatencyToMaximum( QString::number(m_RequestedLatency) ) ); } else - SendAllChat( m_GHost->m_Language->SettingLatencyTo( UTIL_ToString( m_Latency ) ) ); + SendAllChat( m_GHost->m_Language->SettingLatencyTo( UTIL_ToString( m_RequestedLatency ) ) ); } } diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index e442a4b..8390906 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -1079,13 +1079,13 @@ void CBaseGame :: SendAllActions( ) m_Replay->AddTimeSlot( m_Latency, m_Actions ); } - if( GetTicks() - m_LastActionSentTicks > m_Latency ) + if( GetTicks() - m_LastActionSentTicks > 1.5 * m_Latency ) { // something is going terribly wrong - GHost++ is probably starved of resources // print a message because even though this will take more resources it should provide some information to the administrator for future reference // other solutions - dynamically modify the latency, request higher priority, terminate other games, ??? - CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but GHost needed " + QString::number(GetTicks() - m_LastActionSentTicks) + "ms, your machine is probably overloaded" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but GHost needed " + QString::number(GetTicks() - m_LastActionSentTicks) + "ms , your machine is probably overloaded" ); } if (m_RequestedLatency != 0) From 5097968255facc1ec722023c82833646327a7997 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 03:07:05 +0000 Subject: [PATCH 34/69] --- ghost/game_base.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 8390906..184a533 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -984,6 +984,14 @@ void CBaseGame :: SendAllActions( ) UsingGProxy = true; } + if (m_RequestedLatency != 0) + { + m_Latency = m_RequestedLatency; + m_SendActionTimer.setInterval(m_RequestedLatency); + m_SendActionTimer.start(); + m_RequestedLatency = 0; + } + m_GameTicks += m_Latency; if( UsingGProxy ) @@ -1088,13 +1096,6 @@ void CBaseGame :: SendAllActions( ) CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but GHost needed " + QString::number(GetTicks() - m_LastActionSentTicks) + "ms , your machine is probably overloaded" ); } - if (m_RequestedLatency != 0) - { - m_Latency = m_RequestedLatency; - m_SendActionTimer.setInterval(m_RequestedLatency); - m_RequestedLatency = 0; - } - m_LastActionSentTicks = GetTicks( ); } @@ -4456,11 +4457,14 @@ void CBaseGame :: StopPlayers( QString reason ) // therefore calling this function when m_GameLoading || m_GameLoaded is roughly equivalent to setting m_Exiting = true // the only difference is whether the code in the Update function is executed or not - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); ) { - (*i)->deleteLater(); - (*i)->SetLeftReason( reason ); - (*i)->SetLeftCode( PLAYERLEAVE_LOST ); + CGamePlayer *p = *i; + i = m_Players.erase(i); + + p->SetLeftReason( reason ); + p->SetLeftCode( PLAYERLEAVE_LOST ); + p->deleteLater(); } } @@ -4470,9 +4474,12 @@ void CBaseGame :: StopLaggers( QString reason ) { if( (*i)->GetLagging( ) ) { - (*i)->deleteLater(); - (*i)->SetLeftReason( reason ); - (*i)->SetLeftCode( PLAYERLEAVE_DISCONNECT ); + CGamePlayer *p = *i; + i = m_Players.erase(i); + + p->SetLeftReason( reason ); + p->SetLeftCode( PLAYERLEAVE_LOST ); + p->deleteLater(); } } } From 3d11458e8fe6d3e7df033cb4f196d47618dd473d Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 03:09:20 +0000 Subject: [PATCH 35/69] --- ghost/game_base.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 184a533..434cb1a 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -1340,8 +1340,10 @@ void CBaseGame :: EventPlayerDeleted() int ind = m_Players.indexOf(player); - if (ind != -1) - m_Players.remove(ind); + if (ind == -1) + return; + + m_Players.remove(ind); // create the virtual host player if there is room if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < 12 ) From b88b33d30edbcbb08458624804832dffb6e5e519 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 03:19:19 +0000 Subject: [PATCH 36/69] --- ghost/game.cpp | 8 +++++--- ghost/game_admin.cpp | 2 +- ghost/game_base.cpp | 24 ++++++++++++------------ ghost/ghost.cpp | 4 ++++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/ghost/game.cpp b/ghost/game.cpp index d3c51fe..57f86e8 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -956,6 +956,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { CONSOLE_Print( "[GAME: " + m_GameName + "] is over (admin ended game)" ); StopPlayers( "was disconnected (admin ended game)" ); + deleteLater(); } // @@ -1096,7 +1097,6 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( m_GHost->m_Language->UnableToKickNoMatchesFound( Payload ) ); else if( Matches == 1 ) { - LastMatch->deleteLater(); LastMatch->SetLeftReason( m_GHost->m_Language->WasKickedByPlayer( User ) ); if( !m_GameLoading && !m_GameLoaded ) @@ -1104,6 +1104,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri else LastMatch->SetLeftCode( PLAYERLEAVE_LOST ); + LastMatch->deleteLater(); if( !m_GameLoading && !m_GameLoaded ) OpenSlot( GetSIDFromPID( LastMatch->GetPID( ) ), false ); } @@ -1286,9 +1287,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( !m_GameLoading && !m_GameLoaded && !(*i)->GetReserved( ) && KickPing > 0 && (*i)->GetPing( m_GHost->m_LCPings ) > KickPing ) { - (*i)->deleteLater(); (*i)->SetLeftReason( "was kicked for excessive ping " + UTIL_ToString( (*i)->GetPing( m_GHost->m_LCPings ) ) + " > " + UTIL_ToString( KickPing ) ); (*i)->SetLeftCode( PLAYERLEAVE_LOBBY ); + (*i)->deleteLater(); OpenSlot( GetSIDFromPID( (*i)->GetPID( ) ), false ); Kicked++; } @@ -1789,7 +1790,6 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Victim ) { - Victim->deleteLater(); Victim->SetLeftReason( m_GHost->m_Language->WasKickedByVote( ) ); if( !m_GameLoading && !m_GameLoaded ) @@ -1797,6 +1797,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri else Victim->SetLeftCode( PLAYERLEAVE_LOST ); + Victim->deleteLater(); + if( !m_GameLoading && !m_GameLoaded ) OpenSlot( GetSIDFromPID( Victim->GetPID( ) ), false ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 54ecf04..3e07573 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -1233,9 +1233,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( LoginAttempts >= 1 ) { - player->deleteLater(); player->SetLeftReason( "was kicked for too many failed login attempts" ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); + player->deleteLater(); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); // tempban for 5 seconds to prevent bruteforcing diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 434cb1a..089fb47 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -1798,7 +1798,6 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( KickedPlayer ) { - KickedPlayer->deleteLater(); KickedPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForReservedPlayer( joinPlayer->GetName( ) ) ); KickedPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -1807,6 +1806,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP SendAll( m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( KickedPlayer->GetPID( ), KickedPlayer->GetLeftCode( ) ) ); KickedPlayer->SetLeftMessageSent( true ); + KickedPlayer->deleteLater(); } } } @@ -1831,7 +1831,6 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( KickedPlayer ) { - KickedPlayer->deleteLater(); KickedPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForOwnerPlayer( joinPlayer->GetName( ) ) ); KickedPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -1840,6 +1839,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP SendAll( m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( KickedPlayer->GetPID( ), KickedPlayer->GetLeftCode( ) ) ); KickedPlayer->SetLeftMessageSent( true ); + KickedPlayer->deleteLater(); } } } @@ -2189,7 +2189,6 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // kick the furthest player SID = GetSIDFromPID( FurthestPlayer->GetPID( ) ); - FurthestPlayer->deleteLater(); if( FurthestPlayer->GetScore( ) < -99999.0 ) FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", UTIL_ToString( AverageScore, 2 ) ) ); @@ -2203,6 +2202,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SendAll( m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( FurthestPlayer->GetPID( ), FurthestPlayer->GetLeftCode( ) ) ); FurthestPlayer->SetLeftMessageSent( true ); + FurthestPlayer->deleteLater(); if( FurthestPlayer->GetScore( ) < -99999.0 ) SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", UTIL_ToString( AverageScore, 2 ) ) ); @@ -2249,7 +2249,6 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // kick the lowest player SID = GetSIDFromPID( LowestPlayer->GetPID( ) ); - LowestPlayer->deleteLater(); if( LowestPlayer->GetScore( ) < -99999.0 ) LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( "N/A" ) ); @@ -2263,6 +2262,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SendAll( m_Protocol->SEND_W3GS_PLAYERLEAVE_OTHERS( LowestPlayer->GetPID( ), LowestPlayer->GetLeftCode( ) ) ); LowestPlayer->SetLeftMessageSent( true ); + LowestPlayer->deleteLater(); if( LowestPlayer->GetScore( ) < -99999.0 ) SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), "N/A" ) ); @@ -2478,7 +2478,6 @@ void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) // this function is only called when a player leave packet is received, not when there's a socket error, kick, etc... DEBUG_Print("EventPlayerLeft"); - player->deleteLater(); if( reason == PLAYERLEAVE_GPROXY ) player->SetLeftReason( m_GHost->m_Language->WasUnrecoverablyDroppedFromGProxy( ) ); @@ -2486,6 +2485,7 @@ void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) player->SetLeftReason( m_GHost->m_Language->HasLeftVoluntarily( ) ); player->SetLeftCode( PLAYERLEAVE_LOST ); + player->deleteLater(); if( !m_GameLoading && !m_GameLoaded ) OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); @@ -2672,9 +2672,9 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check if( Player ) { - Player->deleteLater(); Player->SetLeftReason( m_GHost->m_Language->WasDroppedDesync( ) ); Player->SetLeftCode( PLAYERLEAVE_LOST ); + Player->deleteLater(); } } } @@ -3010,17 +3010,17 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map } else { - player->deleteLater(); player->SetLeftReason( "doesn't have the map and there is no local copy of the map to send" ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); + player->deleteLater(); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); } } else { - player->deleteLater(); player->SetLeftReason( "doesn't have the map and map downloads are disabled" ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); + player->deleteLater(); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); } } @@ -3104,9 +3104,9 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, quint32 /*pong*/ ) // send a chat message because we don't normally do so when a player leaves the lobby SendAllChat( m_GHost->m_Language->AutokickingPlayerForExcessivePing( player->GetName( ), UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) ) ); - player->deleteLater(); player->SetLeftReason( "was autokicked for excessive ping of " + UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); + player->deleteLater(); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); } } @@ -3735,9 +3735,9 @@ void CBaseGame :: OpenSlot( unsigned char SID, bool kick ) if( Player ) { - Player->deleteLater(); Player->SetLeftReason( "was kicked when opening a slot" ); Player->SetLeftCode( PLAYERLEAVE_LOBBY ); + Player->deleteLater(); } } @@ -3757,9 +3757,9 @@ void CBaseGame :: CloseSlot( unsigned char SID, bool kick ) if( Player ) { - Player->deleteLater(); Player->SetLeftReason( "was kicked when closing a slot" ); Player->SetLeftCode( PLAYERLEAVE_LOBBY ); + Player->deleteLater(); } } @@ -3779,9 +3779,9 @@ void CBaseGame :: ComputerSlot( unsigned char SID, unsigned char skill, bool kic if( Player ) { - Player->deleteLater(); Player->SetLeftReason( "was kicked when creating a computer in a slot" ); Player->SetLeftCode( PLAYERLEAVE_LOBBY ); + Player->deleteLater(); } } diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 2f3c497..7da0846 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -569,6 +569,7 @@ void CGHost::EventWaitForNiceExitTimeout() void CGHost::EventAutoHost() { + DEBUG_Print("EventAutoHost"); // autohost if( m_AutoHostGameName.isEmpty( ) || m_AutoHostMaximumGames == 0 || m_AutoHostAutoStartPlayers == 0 ) return; @@ -581,6 +582,9 @@ void CGHost::EventAutoHost() if (m_Games.size( ) >= m_MaxGames) DEBUG_Print("Not autohosting because m_Games.size( ) >= m_MaxGames"); + if (m_Games.size( ) >= m_AutoHostMaximumGames) + DEBUG_Print("Not autohosting because m_Games.size( ) >= m_AutoHostMaximumGames"); + if( m_ExitingNice || !m_Enabled || m_CurrentGame || m_Games.size( ) >= m_MaxGames || m_Games.size( ) >= m_AutoHostMaximumGames ) return; From 3500211b88c23a8948de326f108d7b878e61e809 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 03:23:31 +0000 Subject: [PATCH 37/69] --- ghost/gameplayer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 870e563..3e4ddca 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -148,6 +148,12 @@ void CGamePlayer::EventConnectionTimeout() void CGamePlayer::EventConnectionClosed() { + if (m_Socket->error() != QAbstractSocket::UnknownSocketError) + { + DEBUG_Print("Error is " + QString::number((int)m_Socket->error())); + return; + } + m_Game->EventPlayerDisconnectConnectionClosed( this ); deleteLater(); } From d5cc234d7ea876096c4b1e74a78cbf6777b85117 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 04:16:41 +0000 Subject: [PATCH 38/69] --- ghost/bnet.cpp | 76 +++++++++++++++++++++++++++++++----------- ghost/bnet.h | 19 ++++++++++- ghost/bnetprotocol.cpp | 29 ++++++++++------ ghost/game_base.cpp | 8 +++++ ghost/gameplayer.cpp | 5 ++- ghost/ghost.cpp | 19 +++++------ ghost/main.cpp | 2 +- ghost/util.cpp | 8 ++--- ghost/util.h | 4 +-- 9 files changed, 119 insertions(+), 51 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 5a697c8..a3546e1 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -263,6 +263,8 @@ void CBNET::socketConnected() while( !m_OutPackets.isEmpty( ) ) m_OutPackets.dequeue( ); + + QTimer::singleShot(500, m_GHost, SLOT(EventAutoHost())); } void CBNET::socketDisconnected() @@ -309,29 +311,39 @@ void CBNET::socketDataReady() ExtractPackets( ); ProcessPackets( ); +} - // check if at least one packet is waiting to be sent and if we've waited long enough to prevent flooding - // this formula has changed many times but currently we wait 1 second if the last packet was "small", 3.5 seconds if it was "medium", and 4 seconds if it was "big" +void CBNET::EnqueuePacket(const QByteArray &pkg) +{ + int ticks = getWaitTicks(); + int pkgs = m_OutPackets.empty(); - quint32 WaitTicks = 0; + m_OutPackets.enqueue(pkg); - if( m_LastOutPacketSize < 10 ) - WaitTicks = 1000; - else if( m_LastOutPacketSize < 100 ) - WaitTicks = 3500; - else - WaitTicks = 4000; + if (pkgs > 0) + return; - if( !m_OutPackets.isEmpty( ) && GetTicks( ) - m_LastOutPacketTicks >= WaitTicks ) + if (m_LastPacketSent.elapsed() >= ticks) { - if( m_OutPackets.size( ) > 7 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); - - m_Socket->write( m_OutPackets.front( ) ); - m_LastOutPacketSize = m_OutPackets.front( ).size( ); - m_OutPackets.dequeue( ); - m_LastOutPacketTicks = GetTicks( ); + SendPacket(); + return; } + + QTimer::singleShot(getWaitTicks() - m_LastPacketSent.elapsed(), this, SLOT(SendPacket())); +} + +void CBNET::SendPacket() +{ + if( m_OutPackets.size( ) > 7 ) + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); + + m_Socket->write( m_OutPackets.front() ); + m_LastOutPacketSize = m_OutPackets.front( ).size( ); + m_OutPackets.dequeue( ); + m_LastPacketSent.restart(); + + if (m_OutPackets.size() > 0) + QTimer::singleShot(getWaitTicks(), this, SLOT(SendPacket())); } void CBNET::socketError() @@ -643,6 +655,8 @@ void CBNET :: ProcessPackets( ) // process all the received packets in the m_Packets queue // this normally means sending some kind of response + DEBUG_Print("Received " + QString::number(m_Packets.size())); + while( !m_Packets.isEmpty( ) ) { CCommandPacket *Packet = m_Packets.front( ); @@ -2274,9 +2288,33 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( + state, + UTIL_CreateBYTEARRAY( MapGameType, false ), + map->GetMapGameFlags( ), + MapWidth, + MapHeight, + gameName, + hostName, + upTime, + "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), + saveGame->GetMagicNumber( ), + map->GetMapSHA1( ), + FixedHostCounter ) ); else - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), UTIL_CreateBYTEARRAY( (quint16)0, false ), UTIL_CreateBYTEARRAY( (quint16)0, false ), gameName, hostName, upTime, "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), saveGame->GetMagicNumber( ), map->GetMapSHA1( ), FixedHostCounter ) ); + m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( + state, + UTIL_CreateBYTEARRAY( MapGameType, false ), + map->GetMapGameFlags( ), + UTIL_CreateBYTEARRAY( (quint16)0, false ), + UTIL_CreateBYTEARRAY( (quint16)0, false ), + gameName, + hostName, + upTime, + "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), + saveGame->GetMagicNumber( ), + map->GetMapSHA1( ), + FixedHostCounter ) ); } else { diff --git a/ghost/bnet.h b/ghost/bnet.h index 6d8bc22..9673945 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -134,7 +134,6 @@ public slots: quint32 m_LastDisconnectedTime; // GetTime when we were last disconnected from battle.net quint32 m_LastConnectionAttemptTime; // GetTime when we last attempted to connect to battle.net quint32 m_LastNullTime; // GetTime when the last null packet was sent for detecting disconnects - quint32 m_LastOutPacketTicks; // GetTicks when the last packet was sent for the m_OutPackets queue quint32 m_LastOutPacketSize; quint32 m_LastAdminRefreshTime; // GetTime when the admin list was last refreshed from the database quint32 m_LastBanRefreshTime; // GetTime when the ban list was last refreshed from the database @@ -145,6 +144,24 @@ public slots: bool m_HoldClan; // whether to auto hold clan members when creating a game or not bool m_PublicCommands; // whether to allow public commands or not + inline int getWaitTicks() + { + // this formula has changed many times but currently we wait 1 second if the last packet was "small", 3.5 seconds if it was "medium", and 4 seconds if it was "big" + if( m_LastOutPacketSize < 10 ) + return 1000; + + else if( m_LastOutPacketSize < 100 ) + return 3500; + + return 4000; + } + + QTime m_LastPacketSent; + +public slots: + void EnqueuePacket(const QByteArray &pkg); + void SendPacket(); + public: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, quint32 nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); virtual ~CBNET( ); diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index cbc2753..8008bc8 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -606,7 +606,19 @@ QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, quint32 hostCounter ) +QByteArray CBNETProtocol :: SEND_SID_STARTADVEX3( + unsigned char state, + QByteArray mapGameType, + QByteArray mapFlags, + QByteArray mapWidth, + QByteArray mapHeight, + QString gameName, + QString hostName, + quint32 upTime, + QString mapPath, + QByteArray mapCRC, + QByteArray mapSHA1, + quint32 hostCounter ) { // todotodo: sort out how GameType works, the documentation is horrendous @@ -637,15 +649,8 @@ Observers: (mask 0x00700000) cant be combined unsigned char Unknown[] = { 255, 3, 0, 0 }; unsigned char CustomGame[] = { 0, 0, 0, 0 }; - QString HostCounterString = UTIL_ToHexString( hostCounter ); - - QString fi; - fi.fill('0', 8 - HostCounterString.size( ) ); - - if( HostCounterString.size( ) < 8 ) - HostCounterString += fi; - - HostCounterString = UTIL_QByteArrayReverse( HostCounterString.toUtf8() ); + QString HostCounterString = QString::number(hostCounter, 16); + HostCounterString.prepend(QString(8 - HostCounterString.size(), '0')); QByteArray packet; @@ -663,7 +668,9 @@ Observers: (mask 0x00700000) cant be combined UTIL_AppendBYTEARRAYFast( StatString, mapSHA1 ); StatString = UTIL_EncodeStatString( StatString ); - if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && !gameName.isEmpty( ) && !hostName.isEmpty( ) && !mapPath.isEmpty( ) && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 && StatString.size( ) < 128 && HostCounterString.size( ) == 8 ) + if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && + !gameName.isEmpty( ) && !hostName.isEmpty( ) && !mapPath.isEmpty( ) && mapCRC.size( ) == 4 && mapSHA1.size( ) == 20 && + StatString.size( ) < 128 && HostCounterString.size( ) == 8 ) { // make the rest of the packet diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 089fb47..68991b5 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -263,6 +263,14 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 CBaseGame :: ~CBaseGame( ) { + for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + { + (*i)->QueueChatCommand( m_GHost->m_Language->GameIsOver( GetDescription( ) ) ); + + if( (*i)->GetServer( ) == GetCreatorServer( ) ) + (*i)->QueueChatCommand( m_GHost->m_Language->GameIsOver( GetDescription( ) ), GetCreatorName( ), true ); + } + // save replay // todotodo: put this in a thread diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 3e4ddca..f76e363 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -88,7 +88,6 @@ void CPotentialPlayer::EventConnectionClosed() void CGamePlayer::EventPingTimeout() { - DEBUG_Print("EventPingTimeout()"); Send(m_Protocol->SEND_W3GS_PING_FROM_HOST( ) ); } @@ -681,8 +680,8 @@ void CGamePlayer :: Send( QByteArray data ) // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts // this prevents us from buffering packets for non-GProxy++ clients - if (data.toHex() != "f70c06006400") - DEBUG_Print("Sending " + data.toHex()); + //if (data.toHex() != "f70c06006400") + // DEBUG_Print("Sending " + data.toHex()); m_TotalPacketsSent++; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 7da0846..b980169 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -341,7 +341,14 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CONSOLE_Print( "[GHOST] GHost++ Version " + m_Version + " (without MySQL support)" ); #endif - m_AutoHostTimer.start(0); + if( m_BNETs.isEmpty( ) ) + m_AutoHostTimer.start(0); + + else + { + for (int i = 0; i < m_BNETs.size(); i++) + m_BNETs.at(i)->socketConnect(); + } } void CGHost::EventAdminGameDeleted() @@ -540,7 +547,7 @@ void CGHost::EventExitNice() if( m_Games.isEmpty( ) ) { - if( !m_AllGamesFinished ) + if( !m_AllGamesFinished && m_Callables.size( ) > 0 ) { CONSOLE_Print( "[GHOST] all games finished, waiting 60 seconds for threads to finish" ); CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads in progress" ); @@ -803,14 +810,6 @@ void CGHost::EventGameDeleted() { CBaseGame *game = (CBaseGame *)QObject::sender(); - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - { - (*i)->QueueChatCommand( m_Language->GameIsOver( game->GetDescription( ) ) ); - - if( (*i)->GetServer( ) == game->GetCreatorServer( ) ) - (*i)->QueueChatCommand( m_Language->GameIsOver( game->GetDescription( ) ), game->GetCreatorName( ), true ); - } - if (game == m_CurrentGame) m_CurrentGame = NULL; diff --git a/ghost/main.cpp b/ghost/main.cpp index ac678a8..2255a93 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -176,7 +176,7 @@ int main( int argc, char **argv ) gGHost = new CGHost( &CFG, gCFGFile ); - QObject::connect(gGHost, SIGNAL(destroyed()), &a, SLOT(quit())); + QObject::connect(gGHost, SIGNAL(destroyed()), &a, SLOT(deleteLater())); return a.exec(); } diff --git a/ghost/util.cpp b/ghost/util.cpp index 0f71696..4338e95 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -126,7 +126,7 @@ void UTIL_AppendBYTEARRAY( QByteArray &b, const QByteArray &append ) b.append(append); } -void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ) +void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QByteArray &append ) { b.append(append); } @@ -144,9 +144,9 @@ void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator ) b.push_back( (char)0 ); } -void UTIL_AppendBYTEARRAYFast( QByteArray &b, QString &append, bool terminator ) +void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QString &append, bool terminator ) { - b.append(append); + b.append(append.toUtf8()); if( terminator ) b.push_back( (char)0 ); @@ -268,7 +268,7 @@ QString UTIL_ToString( double d, int digits ) QString UTIL_ToHexString( quint32 i ) { - return QString::number(i); + return QString::number(i, 16); } // todotodo: these UTIL_ToXXX functions don't fail gracefully, they just return garbage (in the uint case usually just -1 casted to an unsigned type it looks like) diff --git a/ghost/util.h b/ghost/util.h index 4d551c1..cc4d527 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -34,11 +34,11 @@ quint16 UTIL_QByteArrayToUInt16( const QByteArray& b, bool reverse, unsigned int quint32 UTIL_QByteArrayToUInt32( const QByteArray& b, bool reverse, unsigned int start = 0 ); QString UTIL_QByteArrayToDecString( QByteArray b ); QString UTIL_QByteArrayToHexString( QByteArray b ); -void UTIL_AppendBYTEARRAYFast( QByteArray &b, QByteArray &append ); +void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QByteArray &append ); void UTIL_AppendBYTEARRAY( QByteArray &b, const QByteArray &append ); void UTIL_AppendBYTEARRAY( QByteArray &b, unsigned char *a, int size ); void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator ); -void UTIL_AppendBYTEARRAYFast( QByteArray &b, QString &append, bool terminator = true ); +void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QString &append, bool terminator = true ); void UTIL_AppendBYTEARRAY( QByteArray &b, quint16 i, bool reverse ); void UTIL_AppendBYTEARRAY( QByteArray &b, quint32 i, bool reverse ); QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ); From c957a547fe04c83503e5f0385591afcd3bf2317d Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 04:17:33 +0000 Subject: [PATCH 39/69] woopsy, compiler error, bad me --- ghost/bnet.cpp | 1 - ghost/bnet.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index a3546e1..3e78024 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -135,7 +135,6 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_HostCounterID = nHostCounterID; m_LastDisconnectedTime = 0; m_LastConnectionAttemptTime = 0; - m_LastOutPacketTicks = 0; m_LastOutPacketSize = 0; m_LastAdminRefreshTime = GetTime( ); m_LastBanRefreshTime = GetTime( ); diff --git a/ghost/bnet.h b/ghost/bnet.h index 9673945..7fca80c 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -62,6 +62,8 @@ typedef pair PairedGPSCheck; typedef pair PairedDPSCheck; +#include + class CBNET : public QObject { Q_OBJECT From 58fa0a69103a1ebd4ca1aa825d31c82467726548 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 04:19:35 +0000 Subject: [PATCH 40/69] we should use the new methods, not just put them in the code, right, eh? --- ghost/bnet.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 3e78024..6dbc67b 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -2195,7 +2195,7 @@ void CBNET :: SendGetClanList( ) void CBNET :: QueueEnterChat( ) { if( m_LoggedIn ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_ENTERCHAT( ) ); + EnqueuePacket( m_Protocol->SEND_SID_ENTERCHAT( ) ); } void CBNET :: QueueChatCommand( QString chatCommand ) @@ -2216,7 +2216,7 @@ void CBNET :: QueueChatCommand( QString chatCommand ) else { CONSOLE_Print( "[QUEUED: " + m_ServerAlias + "] " + chatCommand ); - m_OutPackets.enqueue( m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ) ); + EnqueuePacket( m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ) ); } } } @@ -2287,7 +2287,7 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), @@ -2301,7 +2301,7 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), @@ -2333,9 +2333,9 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - m_OutPackets.enqueue( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); } } } @@ -2343,7 +2343,7 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h void CBNET :: QueueGameUncreate( ) { if( m_LoggedIn ) - m_OutPackets.enqueue( m_Protocol->SEND_SID_STOPADV( ) ); + EnqueuePacket( m_Protocol->SEND_SID_STOPADV( ) ); } void CBNET :: UnqueuePackets( unsigned char type ) From 904783739d18ba8fc302237be870ef47eed1f2e4 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 04:21:31 +0000 Subject: [PATCH 41/69] --- ghost/bnet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 6dbc67b..f29b013 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -340,6 +340,7 @@ void CBNET::SendPacket() m_LastOutPacketSize = m_OutPackets.front( ).size( ); m_OutPackets.dequeue( ); m_LastPacketSent.restart(); + CONSOLE_Print(QString::number(m_OutPackets.size( ) - 1) + " left in queue."); if (m_OutPackets.size() > 0) QTimer::singleShot(getWaitTicks(), this, SLOT(SendPacket())); From 4aab187349efe8fe9052a4c37e550fe7d0ba3045 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 04:27:01 +0000 Subject: [PATCH 42/69] --- ghost/bnet.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index f29b013..0240bc1 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -333,6 +333,12 @@ void CBNET::EnqueuePacket(const QByteArray &pkg) void CBNET::SendPacket() { + if (m_OutPackets.size() == 0) + { + DEBUG_Print("Nice, empty query... but actually, this shouldn't happen..."); + return; + } + if( m_OutPackets.size( ) > 7 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); From 6ef65350cf748d230d271511f8cb0f3825050b81 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 04:30:39 +0000 Subject: [PATCH 43/69] --- ghost/bnet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 0240bc1..73b9aa4 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -346,7 +346,7 @@ void CBNET::SendPacket() m_LastOutPacketSize = m_OutPackets.front( ).size( ); m_OutPackets.dequeue( ); m_LastPacketSent.restart(); - CONSOLE_Print(QString::number(m_OutPackets.size( ) - 1) + " left in queue."); + CONSOLE_Print(QString::number(m_OutPackets.size( )) + " left in queue."); if (m_OutPackets.size() > 0) QTimer::singleShot(getWaitTicks(), this, SLOT(SendPacket())); From 2c16f7cc26ea286b78213b024126389e7fe00000 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Wed, 21 Apr 2010 05:16:04 +0000 Subject: [PATCH 44/69] removed some of the debug output --- ghost/bnet.cpp | 3 --- ghost/gameprotocol.cpp | 1 - 2 files changed, 4 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 73b9aa4..65a7554 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -346,7 +346,6 @@ void CBNET::SendPacket() m_LastOutPacketSize = m_OutPackets.front( ).size( ); m_OutPackets.dequeue( ); m_LastPacketSent.restart(); - CONSOLE_Print(QString::number(m_OutPackets.size( )) + " left in queue."); if (m_OutPackets.size() > 0) QTimer::singleShot(getWaitTicks(), this, SLOT(SendPacket())); @@ -661,8 +660,6 @@ void CBNET :: ProcessPackets( ) // process all the received packets in the m_Packets queue // this normally means sending some kind of response - DEBUG_Print("Received " + QString::number(m_Packets.size())); - while( !m_Packets.isEmpty( ) ) { CCommandPacket *Packet = m_Packets.front( ); diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 685dc6c..edd5d35 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -515,7 +515,6 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC( subpacket ), false ); crc32.resize( 2 ); - DEBUG_Print("Calculating CRC for " + subpacket.toHex() + ": " + crc32.toHex()); // finish subpacket From 670a5538522396ab8e4db9e2076f1f001293358b Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Thu, 22 Apr 2010 23:45:52 +0000 Subject: [PATCH 45/69] removed most of util.h --- ghost/bncsutilinterface.cpp | 27 +- ghost/bnet.cpp | 104 ++++---- ghost/bnetprotocol.cpp | 245 +++++++++--------- ghost/bnlsclient.cpp | 14 +- ghost/bnlsprotocol.cpp | 24 +- ghost/game.cpp | 88 +++---- ghost/game_admin.cpp | 22 +- ghost/game_base.cpp | 148 ++++++----- ghost/gameplayer.cpp | 10 +- ghost/gameprotocol.cpp | 270 ++++++++++---------- ghost/ghost.cpp | 44 ++-- ghost/ghostdb.cpp | 2 +- ghost/ghostdb.h | 4 +- ghost/ghostdbsqlite.cpp | 46 ++-- ghost/gpsprotocol.cpp | 22 +- ghost/language.cpp | 486 ++++++++++++++++++------------------ ghost/main.cpp | 8 +- ghost/map.cpp | 28 +-- ghost/packed.cpp | 34 +-- ghost/replay.cpp | 94 +++---- ghost/statsdota.cpp | 34 ++- ghost/statsw3mmd.cpp | 114 ++++----- ghost/statsw3mmd.h | 14 +- ghost/util.cpp | 292 ++-------------------- ghost/util.h | 50 +--- 25 files changed, 996 insertions(+), 1228 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index e1a4beb..45ee376 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -23,6 +23,7 @@ #include "bncsutilinterface.h" #include +#include // // CBNCSUtilInterface @@ -55,13 +56,13 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr QString FileWar3EXE = war3Path + "war3.exe"; QString FileStormDLL = war3Path + "Storm.dll"; - if( !UTIL_FileExists( FileStormDLL ) ) + if( !QFile::exists( FileStormDLL ) ) FileStormDLL = war3Path + "storm.dll"; QString FileGameDLL = war3Path + "game.dll"; - bool ExistsWar3EXE = UTIL_FileExists( FileWar3EXE ); - bool ExistsStormDLL = UTIL_FileExists( FileStormDLL ); - bool ExistsGameDLL = UTIL_FileExists( FileGameDLL ); + bool ExistsWar3EXE = QFile::exists( FileWar3EXE ); + bool ExistsStormDLL = QFile::exists( FileStormDLL ); + bool ExistsGameDLL = QFile::exists( FileGameDLL ); if( ExistsWar3EXE && ExistsStormDLL && ExistsGameDLL ) { @@ -71,14 +72,14 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr quint32 EXEVersion; getExeInfo( FileWar3EXE.toStdString().c_str( ), (char *)&buf, 1024, (quint32 *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); m_EXEInfo = buf; - m_EXEVersion = UTIL_CreateBYTEARRAY( EXEVersion, false ); + m_EXEVersion = Util::fromUInt32( EXEVersion); quint32 EXEVersionHash; checkRevisionFlat( valueStringFormula.toStdString().c_str( ), FileWar3EXE.toStdString().c_str( ), FileStormDLL.toStdString().c_str( ), FileGameDLL.toStdString().c_str( ), extractMPQNumber( mpqFileName.toStdString().c_str( ) ), (unsigned long *)&EXEVersionHash ); - m_EXEVersionHash = UTIL_CreateBYTEARRAY( EXEVersionHash, false ); - m_KeyInfoROC = CreateKeyInfo( keyROC, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); + m_EXEVersionHash = Util::fromUInt32( EXEVersionHash); + m_KeyInfoROC = CreateKeyInfo( keyROC, Util::extractUInt32(clientToken), Util::extractUInt32(serverToken) ); if( TFT ) - m_KeyInfoTFT = CreateKeyInfo( keyTFT, UTIL_QByteArrayToUInt32( clientToken, false ), UTIL_QByteArrayToUInt32( serverToken, false ) ); + m_KeyInfoTFT = CreateKeyInfo( keyTFT, Util::extractUInt32(clientToken), Util::extractUInt32(serverToken) ); if( m_KeyInfoROC.size( ) == 36 && ( !TFT || m_KeyInfoTFT.size( ) == 36 ) ) return true; @@ -146,14 +147,14 @@ QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, quint32 clientToken if( Decoder.isKeyValid( ) ) { - UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( (quint32)key.size( ), false ) ); - UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( Decoder.getProduct( ), false ) ); - UTIL_AppendBYTEARRAY( KeyInfo, UTIL_CreateBYTEARRAY( Decoder.getVal1( ), false ) ); - UTIL_AppendBYTEARRAY( KeyInfo, QByteArray( (char*)Zeros, 4 ) ); + KeyInfo.append(Util::fromUInt32( key.size( ))); + KeyInfo.append(Util::fromUInt32( Decoder.getProduct( ))); + KeyInfo.append(Util::fromUInt32( Decoder.getVal1( ))); + KeyInfo.append(QByteArray( (char*)Zeros, 4 ) ); size_t Length = Decoder.calculateHash( clientToken, serverToken ); char *buf = new char[Length]; Length = Decoder.getHash( buf ); - UTIL_AppendBYTEARRAY( KeyInfo, QByteArray( buf, Length ) ); + KeyInfo.append(QByteArray( buf, Length ) ); delete [] buf; } diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 65a7554..4ee4b34 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -340,7 +340,7 @@ void CBNET::SendPacket() } if( m_OutPackets.size( ) > 7 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + UTIL_ToString( m_OutPackets.size( ) ) + " packets waiting to be sent" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + QString::number( m_OutPackets.size( ) ) + " packets waiting to be sent" ); m_Socket->write( m_OutPackets.front() ); m_LastOutPacketSize = m_OutPackets.front( ).size( ); @@ -399,7 +399,7 @@ void CBNET::EventCallableUpdateTimeout() else if( Count == 1 ) QueueChatCommand( m_GHost->m_Language->ThereIsAdmin( m_Server ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->ThereAreAdmins( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereAreAdmins( m_Server, QString::number( Count ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -460,7 +460,7 @@ void CBNET::EventCallableUpdateTimeout() else if( Count == 1 ) QueueChatCommand( m_GHost->m_Language->ThereIsBannedUser( m_Server ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->ThereAreBannedUsers( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->m_Language->ThereAreBannedUsers( m_Server, QString::number( Count ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -517,7 +517,7 @@ void CBNET::EventCallableUpdateTimeout() CDBGamePlayerSummary *GamePlayerSummary = i->second->GetResult( ); if( GamePlayerSummary ) - QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), UTIL_ToString( GamePlayerSummary->GetTotalGames( ) ), UTIL_ToString( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 2 ), UTIL_ToString( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( 2, (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); else QueueChatCommand( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); @@ -538,27 +538,27 @@ void CBNET::EventCallableUpdateTimeout() if( DotAPlayerSummary ) { QString Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), - UTIL_ToString( DotAPlayerSummary->GetTotalGames( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalWins( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalLosses( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalDeaths( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalCreepKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalCreepDenies( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalAssists( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalNeutralKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalTowerKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalRaxKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalCourierKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetAvgKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgDeaths( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgCreepKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgCreepDenies( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgAssists( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgNeutralKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgTowerKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgRaxKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgCourierKills( ), 2 ) ); + QString::number( DotAPlayerSummary->GetTotalGames( ) ), + QString::number( DotAPlayerSummary->GetTotalWins( ) ), + QString::number( DotAPlayerSummary->GetTotalLosses( ) ), + QString::number( DotAPlayerSummary->GetTotalKills( ) ), + QString::number( DotAPlayerSummary->GetTotalDeaths( ) ), + QString::number( DotAPlayerSummary->GetTotalCreepKills( ) ), + QString::number( DotAPlayerSummary->GetTotalCreepDenies( ) ), + QString::number( DotAPlayerSummary->GetTotalAssists( ) ), + QString::number( DotAPlayerSummary->GetTotalNeutralKills( ) ), + QString::number( DotAPlayerSummary->GetTotalTowerKills( ) ), + QString::number( DotAPlayerSummary->GetTotalRaxKills( ) ), + QString::number( DotAPlayerSummary->GetTotalCourierKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgDeaths( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgCreepKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgCreepDenies( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgAssists( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgNeutralKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgTowerKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgRaxKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgCourierKills( ) ) ); QueueChatCommand( Summary, i->first, !i->first.isEmpty( ) ); } @@ -575,7 +575,7 @@ void CBNET::EventCallableUpdateTimeout() if( m_CallableAdminList && m_CallableAdminList->GetReady( ) ) { - // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed admin list (" + UTIL_ToString( m_Admins.size( ) ) + " -> " + UTIL_ToString( m_CallableAdminList->GetResult( ).size( ) ) + " admins)" ); + // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed admin list (" + QString::number( m_Admins.size( ) ) + " -> " + QString::number( m_CallableAdminList->GetResult( ).size( ) ) + " admins)" ); m_Admins = m_CallableAdminList->GetResult( ); m_GHost->m_DB->RecoverCallable( m_CallableAdminList ); delete m_CallableAdminList; @@ -585,7 +585,7 @@ void CBNET::EventCallableUpdateTimeout() if( m_CallableBanList && m_CallableBanList->GetReady( ) ) { - // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed ban list (" + UTIL_ToString( m_Bans.size( ) ) + " -> " + UTIL_ToString( m_CallableBanList->GetResult( ).size( ) ) + " bans)" ); + // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed ban list (" + QString::number( m_Bans.size( ) ) + " -> " + QString::number( m_CallableBanList->GetResult( ).size( ) ) + " bans)" ); for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) delete *i; @@ -632,7 +632,7 @@ void CBNET :: ExtractPackets( ) // bytes 2 and 3 contain the length of the packet - quint16 Length = UTIL_QByteArrayToUInt16( header, false, 2 ); + quint16 Length = Util::extractUInt16(header, 2); if( Length < 4 ) { @@ -739,13 +739,13 @@ void CBNET :: ProcessPackets( ) if( m_EXEVersion.size( ) == 4 ) { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using custom exe version bnet_custom_exeversion = " + UTIL_ToString( m_EXEVersion[0] ) + " " + UTIL_ToString( m_EXEVersion[1] ) + " " + UTIL_ToString( m_EXEVersion[2] ) + " " + UTIL_ToString( m_EXEVersion[3] ) ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using custom exe version bnet_custom_exeversion = " + QString::number( m_EXEVersion[0] ) + " " + QString::number( m_EXEVersion[1] ) + " " + QString::number( m_EXEVersion[2] ) + " " + QString::number( m_EXEVersion[3] ) ); m_BNCSUtil->SetEXEVersion( m_EXEVersion ); } if( m_EXEVersionHash.size( ) == 4 ) { - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using custom exe version hash bnet_custom_exeversionhash = " + UTIL_ToString( m_EXEVersionHash[0] ) + " " + UTIL_ToString( m_EXEVersionHash[1] ) + " " + UTIL_ToString( m_EXEVersionHash[2] ) + " " + UTIL_ToString( m_EXEVersionHash[3] ) ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using custom exe version hash bnet_custom_exeversionhash = " + QString::number( m_EXEVersionHash[0] ) + " " + QString::number( m_EXEVersionHash[1] ) + " " + QString::number( m_EXEVersionHash[2] ) + " " + QString::number( m_EXEVersionHash[3] ) ); m_BNCSUtil->SetEXEVersionHash( m_EXEVersionHash ); } @@ -764,7 +764,7 @@ void CBNET :: ProcessPackets( ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] creating BNLS client" ); delete m_BNLSClient; m_BNLSClient = new CBNLSClient( m_BNLSServer, m_BNLSPort, m_BNLSWardenCookie ); - m_BNLSClient->QueueWardenSeed( UTIL_QByteArrayToUInt32( m_BNCSUtil->GetKeyInfoROC( ), false, 16 ) ); + m_BNLSClient->QueueWardenSeed( Util::extractUInt32(m_BNCSUtil->GetKeyInfoROC( ), 16) ); QObject::connect(m_BNLSClient, SIGNAL(newWardenResponse(QByteArray)), this, SLOT(sendWardenResponse(QByteArray))); } @@ -793,7 +793,7 @@ void CBNET :: ProcessPackets( ) { // cd keys not accepted - switch( UTIL_QByteArrayToUInt32( m_Protocol->GetKeyState( ), false ) ) + switch( Util::extractUInt32(m_Protocol->GetKeyState( )) ) { case CBNETProtocol :: KR_ROC_KEY_IN_USE: CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - ROC CD key in use by user [" + m_Protocol->GetKeyStateDescription( ) + "], disconnecting" ); @@ -1258,11 +1258,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } else { - quint32 AutoStartPlayers = UTIL_ToUInt32( Payload ); + quint32 AutoStartPlayers = Payload.toUInt(); if( AutoStartPlayers != 0 ) { - QueueChatCommand( m_GHost->m_Language->AutoStartEnabled( UTIL_ToString( AutoStartPlayers ) ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->AutoStartEnabled( QString::number( AutoStartPlayers ) ), User, Whisper ); m_GHost->m_CurrentGame->SetAutoStartPlayers( AutoStartPlayers ); } } @@ -1420,7 +1420,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "downloads" && !Payload.isEmpty( ) ) { - quint32 Downloads = UTIL_ToUInt32( Payload ); + quint32 Downloads = Payload.toUInt(); if( Downloads == 0 ) { @@ -1462,7 +1462,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // todotodo: what if a game ends just as you're typing this command and the numbering changes? - int GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = Payload.toUInt() - 1; if( GameNumber < m_GHost->m_Games.size( ) ) { @@ -1495,7 +1495,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { QString File = m_GHost->m_ReplayPath + Payload + ".w3g"; - if( UTIL_FileExists( File ) ) + if( QFile::exists( File ) ) { QueueChatCommand( m_GHost->m_Language->LoadingReplay( File ), User, Whisper ); CReplay *Replay = new CReplay( ); @@ -1560,7 +1560,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "getgame" && !Payload.isEmpty( ) ) { - int GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = Payload.toUInt() - 1; if( GameNumber < m_GHost->m_Games.size( ) ) QueueChatCommand( m_GHost->m_Language->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ), User, Whisper ); @@ -1575,9 +1575,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "getgames" ) { if( m_GHost->m_CurrentGame ) - QueueChatCommand( m_GHost->m_Language->GameIsInTheLobby( m_GHost->m_CurrentGame->GetDescription( ), UTIL_ToString( m_GHost->m_Games.size( ) ), UTIL_ToString( m_GHost->m_MaxGames ) ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->GameIsInTheLobby( m_GHost->m_CurrentGame->GetDescription( ), QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ), User, Whisper ); else - QueueChatCommand( m_GHost->m_Language->ThereIsNoGameInTheLobby( UTIL_ToString( m_GHost->m_Games.size( ) ), UTIL_ToString( m_GHost->m_MaxGames ) ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->ThereIsNoGameInTheLobby( QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ), User, Whisper ); } // @@ -1684,7 +1684,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; QString FileNoPath = Payload + ".w3z"; - if( UTIL_FileExists( File ) ) + if( QFile::exists( File ) ) { if( m_GHost->m_CurrentGame ) QueueChatCommand( m_GHost->m_Language->UnableToLoadSaveGameGameInLobby( ), User, Whisper ); @@ -1920,7 +1920,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( GameNumber - 1 < m_GHost->m_Games.size( ) ) m_GHost->m_Games[GameNumber - 1]->SendAllChat( "ADMIN: " + Message ); else - QueueChatCommand( m_GHost->m_Language->GameNumberDoesntExist( UTIL_ToString( GameNumber ) ), User, Whisper ); + QueueChatCommand( m_GHost->m_Language->GameNumberDoesntExist( QString::number( GameNumber ) ), User, Whisper ); } } } @@ -2048,7 +2048,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "wardenstatus" ) { if( m_BNLSClient ) - QueueChatCommand( "WARDEN STATUS --- " + UTIL_ToString( m_BNLSClient->GetTotalWardenIn( ) ) + " requests received, " + UTIL_ToString( m_BNLSClient->GetTotalWardenOut( ) ) + " responses sent.", User, Whisper ); + QueueChatCommand( "WARDEN STATUS --- " + QString::number( m_BNLSClient->GetTotalWardenIn( ) ) + " requests received, " + QString::number( m_BNLSClient->GetTotalWardenOut( ) ) + " responses sent.", User, Whisper ); else QueueChatCommand( "WARDEN STATUS --- Not connected to BNLS server.", User, Whisper ); } @@ -2216,7 +2216,7 @@ void CBNET :: QueueChatCommand( QString chatCommand ) chatCommand = chatCommand.mid( 0, 255 ); if( m_OutPackets.size( ) > 10 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + UTIL_ToString( m_OutPackets.size( ) ) + ") packets queued, discarding" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + QString::number( m_OutPackets.size( ) ) + ") packets queued, discarding" ); else { CONSOLE_Print( "[QUEUED: " + m_ServerAlias + "] " + chatCommand ); @@ -2293,7 +2293,7 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h if( m_GHost->m_Reconnect ) EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, - UTIL_CreateBYTEARRAY( MapGameType, false ), + Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), MapWidth, MapHeight, @@ -2307,10 +2307,10 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h else EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, - UTIL_CreateBYTEARRAY( MapGameType, false ), + Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), - UTIL_CreateBYTEARRAY( (quint16)0, false ), - UTIL_CreateBYTEARRAY( (quint16)0, false ), + Util::fromUInt16( (quint16)0), + Util::fromUInt16( (quint16)0), gameName, hostName, upTime, @@ -2337,9 +2337,9 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h MapHeight.push_back( 7 ); if( m_GHost->m_Reconnect ) - EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, UTIL_CreateBYTEARRAY( MapGameType, false ), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); } } } @@ -2371,7 +2371,7 @@ void CBNET :: UnqueuePackets( unsigned char type ) m_OutPackets = Packets; if( Unqueued > 0 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] unqueued " + UTIL_ToString( Unqueued ) + " packets of type " + UTIL_ToString( type ) ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] unqueued " + QString::number( Unqueued ) + " packets of type " + QString::number( type ) ); } void CBNET :: UnqueueChatCommand( QString chatCommand ) @@ -2400,7 +2400,7 @@ void CBNET :: UnqueueChatCommand( QString chatCommand ) m_OutPackets = Packets; if( Unqueued > 0 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] unqueued " + UTIL_ToString( Unqueued ) + " chat command packets" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] unqueued " + QString::number( Unqueued ) + " chat command packets" ); } void CBNET :: UnqueueGameRefreshes( ) diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 8008bc8..7b2963d 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -24,7 +24,7 @@ CBNETProtocol :: CBNETProtocol( ) { - unsigned char ClientToken[] = { 220, 1, 203, 7 }; + char ClientToken[] = { 220, 1, 203, 7 }; m_ClientToken = QByteArray( (char*)ClientToken, 4 ); } @@ -68,7 +68,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) { QByteArray GamesFound = data.mid(4, 4); - if( UTIL_QByteArrayToUInt32( GamesFound, false ) > 0 && data.size( ) >= 25 ) + if( Util::extractUInt32(GamesFound) > 0 && data.size( ) >= 25 ) { QByteArray Port = data.mid(18, 2); QByteArray IP = data.mid(20, 4); @@ -82,7 +82,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 31, true ) ); HostCounter.push_back( UTIL_ExtractHex( data, GameName.size( ) + 33, true ) ); return new CIncomingGameHost( IP, - UTIL_QByteArrayToUInt16( Port, false ), + Util::extractUInt16(Port), GameName, HostCounter ); } @@ -131,7 +131,7 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) QByteArray User = UTIL_ExtractCString( data, 28 ); QByteArray Message = UTIL_ExtractCString( data, User.size( ) + 29 ); - switch( UTIL_QByteArrayToUInt32( EventID, false ) ) + switch( Util::extractUInt32(EventID) ) { case CBNETProtocol :: EID_SHOWUSER: case CBNETProtocol :: EID_JOIN: @@ -148,8 +148,8 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) case CBNETProtocol :: EID_INFO: case CBNETProtocol :: EID_ERROR: case CBNETProtocol :: EID_EMOTE: - return new CIncomingChatEvent( (CBNETProtocol :: IncomingChatEvent)UTIL_QByteArrayToUInt32( EventID, false ), - UTIL_QByteArrayToUInt32( Ping, false ), + return new CIncomingChatEvent( (CBNETProtocol :: IncomingChatEvent)Util::extractUInt32(EventID), + Util::extractUInt32(Ping), User, Message ); } @@ -183,7 +183,7 @@ bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( QByteArray data ) { QByteArray Status = data.mid(4, 8 - 4); - if( UTIL_QByteArrayToUInt32( Status, false ) == 0 ) + if( Util::extractUInt32(Status) == 0 ) return true; } @@ -218,7 +218,7 @@ bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( QByteArray data ) { QByteArray Status = data.mid(4, 8 - 4); - if( UTIL_QByteArrayToUInt32( Status, false ) == 1 ) + if( Util::extractUInt32(Status) == 1 ) return true; } @@ -267,7 +267,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( QByteArray data ) m_KeyState = data.mid(4, 8 - 4); m_KeyStateDescription = UTIL_ExtractCString( data, 8 ); - if( UTIL_QByteArrayToUInt32( m_KeyState, false ) == KR_GOOD ) + if( Util::extractUInt32(m_KeyState) == KR_GOOD ) return true; } @@ -290,7 +290,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ) { QByteArray status = data.mid(4, 8 - 4); - if( UTIL_QByteArrayToUInt32( status, false ) == 0 && data.size( ) >= 72 ) + if( Util::extractUInt32(status) == 0 && data.size( ) >= 72 ) { m_Salt = data.mid(8, 40 - 8); m_ServerPublicKey = data.mid(40, 72 - 40); @@ -314,7 +314,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ) { QByteArray Status = data.mid(4, 8 - 4); - if( UTIL_QByteArrayToUInt32( Status, false ) == 0 ) + if( Util::extractUInt32(Status) == 0 ) return true; } @@ -512,21 +512,22 @@ QByteArray CBNETProtocol :: SEND_SID_STOPADV( ) QByteArray CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) { - unsigned char MapFilter1[] = { 255, 3, 0, 0 }; - unsigned char MapFilter2[] = { 255, 3, 0, 0 }; - unsigned char MapFilter3[] = { 0, 0, 0, 0 }; - unsigned char NumGames[] = { 1, 0, 0, 0 }; + char MapFilter1[] = { 255, 3, 0, 0 }; + char MapFilter2[] = { 255, 3, 0, 0 }; + char MapFilter3[] = { 0, 0, 0, 0 }; + char NumGames[] = { 1, 0, 0, 0 }; QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_GETADVLISTEX ); // SID_GETADVLISTEX packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, MapFilter1, 4 ); // Map Filter - UTIL_AppendBYTEARRAY( packet, MapFilter2, 4 ); // Map Filter - UTIL_AppendBYTEARRAY( packet, MapFilter3, 4 ); // Map Filter - UTIL_AppendBYTEARRAY( packet, NumGames, 4 ); // maximum number of games to list - UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name + packet.append(QByteArray(MapFilter1, 4)); // Map Filter + packet.append(QByteArray(MapFilter2, 4)); // Map Filter + packet.append(QByteArray(MapFilter3, 4)); // Map Filter + packet.append(QByteArray(NumGames, 4)); // maximum number of games to list + packet.append(gameName); // Game Name + packet.push_back( (char)0 ); // 0 term packet.push_back( (char)0 ); // Game Password is NULL packet.push_back( (char)0 ); // Game Stats is NULL AssignLength( packet ); @@ -552,8 +553,8 @@ QByteArray CBNETProtocol :: SEND_SID_ENTERCHAT( ) QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) { - unsigned char NoCreateJoin[] = { 2, 0, 0, 0 }; - unsigned char FirstJoin[] = { 1, 0, 0, 0 }; + char NoCreateJoin[] = { 2, 0, 0, 0 }; + char FirstJoin[] = { 1, 0, 0, 0 }; QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant @@ -562,11 +563,12 @@ QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) packet.push_back( (char)0 ); // packet length will be assigned later if( channel.size( ) > 0 ) - UTIL_AppendBYTEARRAY( packet, NoCreateJoin, 4 ); // flags for no create join + packet.append(QByteArray(NoCreateJoin, 4)); // flags for no create join else - UTIL_AppendBYTEARRAY( packet, FirstJoin, 4 ); // flags for first join + packet.append(QByteArray(FirstJoin, 4)); // flags for first join - UTIL_AppendBYTEARRAYFast( packet, channel ); + packet.append(channel); + packet.push_back( (char)0 ); // 0 term AssignLength( packet ); // DEBUG_Print( "SENT SID_JOINCHANNEL" ); // DEBUG_Print( packet ); @@ -580,7 +582,8 @@ QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) packet.push_back( SID_CHATCOMMAND ); // SID_CHATCOMMAND packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, command ); // Message + packet.append(command); // Message + packet.push_back( (char)0 ); // 0 term AssignLength( packet ); // DEBUG_Print( "SENT SID_CHATCOMMAND" ); // DEBUG_Print( packet ); @@ -589,17 +592,17 @@ QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) { - unsigned char Zeros[] = { 0, 0, 0, 0 }; + char Zeros[] = { 0, 0, 0, 0 }; QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CHECKAD ); // SID_CHECKAD packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + packet.append(QByteArray(Zeros, 4)); // ??? + packet.append(QByteArray(Zeros, 4)); // ??? + packet.append(QByteArray(Zeros, 4)); // ??? + packet.append(QByteArray(Zeros, 4)); // ??? AssignLength( packet ); // DEBUG_Print( "SENT SID_CHECKAD" ); // DEBUG_Print( packet ); @@ -646,8 +649,8 @@ Observers: (mask 0x00700000) cant be combined */ - unsigned char Unknown[] = { 255, 3, 0, 0 }; - unsigned char CustomGame[] = { 0, 0, 0, 0 }; + char Unknown[] = { 255, 3, 0, 0 }; + char CustomGame[] = { 0, 0, 0, 0 }; QString HostCounterString = QString::number(hostCounter, 16); HostCounterString.prepend(QString(8 - HostCounterString.size(), '0')); @@ -657,15 +660,17 @@ Observers: (mask 0x00700000) cant be combined // make the stat QString QByteArray StatString; - UTIL_AppendBYTEARRAYFast( StatString, mapFlags ); + StatString.append(mapFlags); StatString.push_back( (char)0 ); - UTIL_AppendBYTEARRAYFast( StatString, mapWidth ); - UTIL_AppendBYTEARRAYFast( StatString, mapHeight ); - UTIL_AppendBYTEARRAYFast( StatString, mapCRC ); - UTIL_AppendBYTEARRAYFast( StatString, mapPath ); - UTIL_AppendBYTEARRAYFast( StatString, hostName ); + StatString.append(mapWidth); + StatString.append(mapHeight); + StatString.append(mapCRC); + StatString.append(mapPath); + StatString.push_back( (char)0 ); // 0 term + StatString.append(hostName); + StatString.push_back( (char)0 ); // 0 term StatString.push_back( (char)0 ); - UTIL_AppendBYTEARRAYFast( StatString, mapSHA1 ); + StatString.append(mapSHA1); StatString = UTIL_EncodeStatString( StatString ); if( mapGameType.size( ) == 4 && mapFlags.size( ) == 4 && mapWidth.size( ) == 2 && mapHeight.size( ) == 2 && @@ -674,24 +679,25 @@ Observers: (mask 0x00700000) cant be combined { // make the rest of the packet - packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant - packet.push_back( SID_STARTADVEX3 ); // SID_STARTADVEX3 - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( state ); // State (16 = public, 17 = private, 18 = close) - packet.push_back( (char)0 ); // State continued... - packet.push_back( (char)0 ); // State continued... - packet.push_back( (char)0 ); // State continued... - UTIL_AppendBYTEARRAY( packet, upTime, false ); // time since creation - UTIL_AppendBYTEARRAYFast( packet, mapGameType ); // Game Type, Parameter - UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, CustomGame, 4 ); // Custom Game - UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name - packet.push_back( (char)0 ); // Game Password is NULL - packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate - UTIL_AppendBYTEARRAYFast( packet, HostCounterString, false ); // Host Counter - UTIL_AppendBYTEARRAYFast( packet, StatString ); // Stat String - packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) + packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant + packet.push_back( SID_STARTADVEX3 ); // SID_STARTADVEX3 + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( state ); // State (16 = public, 17 = private, 18 = close) + packet.push_back( (char)0 ); // State continued... + packet.push_back( (char)0 ); // State continued... + packet.push_back( (char)0 ); // State continued... + packet.append(Util::fromUInt32(upTime)); // time since creation + packet.append(mapGameType); // Game Type, Parameter + packet.append(QByteArray(Unknown, 4)); // ??? + packet.append(QByteArray(CustomGame, 4)); // Custom Game + packet.append(gameName); // Game Name + packet.push_back( (char)0 ); // 0 term + packet.push_back( (char)0 ); // Game Password is NULL + packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate + packet.append(HostCounterString); // Host Counter + packet.append(StatString); // Stat String + packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) AssignLength( packet ); } else @@ -704,17 +710,18 @@ Observers: (mask 0x00700000) cant be combined QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) { - unsigned char ProductID[] = { 0, 0, 0, 0 }; - unsigned char ProductVersion[] = { 14, 0, 0, 0 }; // Warcraft III is 14 + char ProductID[] = { 0, 0, 0, 0 }; + char ProductVersion[] = { 14, 0, 0, 0 }; // Warcraft III is 14 QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_NOTIFYJOIN ); // SID_NOTIFYJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, ProductID, 4 ); // Product ID - UTIL_AppendBYTEARRAY( packet, ProductVersion, 4 ); // Product Version - UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name + packet.append(QByteArray(ProductID, 4)); // Product ID + packet.append(QByteArray(ProductVersion, 4)); // Product Version + packet.append(gameName); // Game Name + packet.push_back( (char)0 ); // 0 term packet.push_back( (char)0 ); // Game Password is NULL AssignLength( packet ); // DEBUG_Print( "SENT SID_NOTIFYJOIN" ); @@ -732,7 +739,7 @@ QByteArray CBNETProtocol :: SEND_SID_PING( QByteArray pingValue ) packet.push_back( SID_PING ); // SID_PING packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, pingValue ); // Ping Value + packet.append(pingValue); // Ping Value AssignLength( packet ); } else @@ -752,10 +759,11 @@ QByteArray CBNETProtocol :: SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByt packet.push_back( SID_LOGONRESPONSE ); // SID_LOGONRESPONSE packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, clientToken ); // Client Token - UTIL_AppendBYTEARRAYFast( packet, serverToken ); // Server Token - UTIL_AppendBYTEARRAYFast( packet, passwordHash ); // Password Hash - UTIL_AppendBYTEARRAYFast( packet, accountName ); // Account Name + packet.append(clientToken); // Client Token + packet.append(serverToken); // Server Token + packet.append(passwordHash); // Password Hash + packet.append(accountName); // Account Name + packet.push_back( (char)0 ); // 0 term AssignLength( packet ); // DEBUG_Print( "SENT SID_LOGONRESPONSE" ); // DEBUG_Print( packet ); @@ -769,7 +777,7 @@ QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( quint16 serverPort ) packet.push_back( SID_NETGAMEPORT ); // SID_NETGAMEPORT packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, serverPort, false ); // local game server port + packet.append(Util::fromUInt16(serverPort)); // local game server port AssignLength( packet ); // DEBUG_Print( "SENT SID_NETGAMEPORT" ); // DEBUG_Print( packet ); @@ -778,36 +786,38 @@ QByteArray CBNETProtocol :: SEND_SID_NETGAMEPORT( quint16 serverPort ) QByteArray CBNETProtocol :: SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, quint32 localeID, QString countryAbbrev, QString country ) { - unsigned char ProtocolID[] = { 0, 0, 0, 0 }; - unsigned char PlatformID[] = { 54, 56, 88, 73 }; // "IX86" - unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" - unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" - unsigned char Version[] = { ver, 0, 0, 0 }; - unsigned char Language[] = { 83, 85, 110, 101 }; // "enUS" - unsigned char LocalIP[] = { 127, 0, 0, 1 }; - unsigned char TimeZoneBias[] = { 44, 1, 0, 0 }; // 300 minutes (GMT -0500) + char ProtocolID[] = { 0, 0, 0, 0 }; + char PlatformID[] = { 54, 56, 88, 73 }; // "IX86" + char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" + char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" + char Version[] = { ver, 0, 0, 0 }; + char Language[] = { 83, 85, 110, 101 }; // "enUS" + char LocalIP[] = { 127, 0, 0, 1 }; + char TimeZoneBias[] = { 44, 1, 0, 0 }; // 300 minutes (GMT -0500) QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_INFO ); // SID_AUTH_INFO packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, ProtocolID, 4 ); // Protocol ID - UTIL_AppendBYTEARRAY( packet, PlatformID, 4 ); // Platform ID + packet.append(QByteArray(ProtocolID, 4)); // Protocol ID + packet.append(QByteArray(PlatformID, 4)); // Platform ID if( TFT ) - UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) + packet.append(QByteArray(ProductID_TFT, 4)); // Product ID (TFT) else - UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) - - UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version - UTIL_AppendBYTEARRAY( packet, Language, 4 ); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English) - UTIL_AppendBYTEARRAY( packet, LocalIP, 4 ); // Local IP for NAT compatibility - UTIL_AppendBYTEARRAY( packet, TimeZoneBias, 4 ); // Time Zone Bias - UTIL_AppendBYTEARRAY( packet, localeID, false ); // Locale ID - UTIL_AppendBYTEARRAY( packet, localeID, false ); // Language ID (copying the locale ID should be sufficient since we don't care about sublanguages) - UTIL_AppendBYTEARRAYFast( packet, countryAbbrev ); // Country Abbreviation - UTIL_AppendBYTEARRAYFast( packet, country ); // Country + packet.append(QByteArray(ProductID_ROC, 4)); // Product ID (ROC) + + packet.append(QByteArray(Version, 4)); // Version + packet.append(QByteArray(Language, 4)); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English) + packet.append(QByteArray(LocalIP, 4)); // Local IP for NAT compatibility + packet.append(QByteArray(TimeZoneBias, 4)); // Time Zone Bias + packet.append(Util::fromUInt32(localeID)); // Locale ID + packet.append(Util::fromUInt32(localeID)); // Language ID (copying the locale ID should be sufficient since we don't care about sublanguages) + packet.append(countryAbbrev); // Country Abbreviation + packet.push_back( (char)0 ); // 0 term + packet.append(country); // Country + packet.push_back( (char)0 ); // 0 term AssignLength( packet ); // DEBUG_Print( "SENT SID_AUTH_INFO" ); // DEBUG_Print( packet ); @@ -829,20 +839,22 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToke { packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_CHECK ); // SID_AUTH_CHECK - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, clientToken ); // Client Token - UTIL_AppendBYTEARRAYFast( packet, exeVersion ); // EXE Version - UTIL_AppendBYTEARRAYFast( packet, exeVersionHash ); // EXE Version Hash - UTIL_AppendBYTEARRAY( packet, NumKeys, false ); // number of keys in this packet - UTIL_AppendBYTEARRAY( packet, (quint32)0, false ); // boolean Using Spawn (32 bit) - UTIL_AppendBYTEARRAYFast( packet, keyInfoROC ); // ROC Key Info + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.append(clientToken); // Client Token + packet.append(exeVersion); // EXE Version + packet.append(exeVersionHash); // EXE Version Hash + packet.append(Util::fromUInt32(NumKeys)); // number of keys in this packet + packet.append(Util::fromUInt16(0)); // boolean Using Spawn (32 bit) + packet.append(keyInfoROC); // ROC Key Info if( TFT ) - UTIL_AppendBYTEARRAYFast( packet, keyInfoTFT ); // TFT Key Info + packet.append(keyInfoTFT); // TFT Key Info - UTIL_AppendBYTEARRAYFast( packet, exeInfo ); // EXE Info - UTIL_AppendBYTEARRAYFast( packet, keyOwnerName ); // CD Key Owner Name + packet.append(exeInfo); // EXE Info + packet.push_back( (char)0 ); // 0 term + packet.append(keyOwnerName); // CD Key Owner Name + packet.push_back( (char)0 ); // 0 term AssignLength( packet ); } else @@ -861,10 +873,11 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGON( QByteArray clientPublicK { packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_AUTH_ACCOUNTLOGON ); // SID_AUTH_ACCOUNTLOGON - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, clientPublicKey ); // Client Key - UTIL_AppendBYTEARRAYFast( packet, accountName ); // Account Name + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.append(clientPublicKey); // Client Key + packet.append(accountName); // Account Name + packet.push_back( (char)0 ); // 0 term AssignLength( packet ); } else @@ -881,11 +894,11 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray clientPa if( clientPasswordProof.size( ) == 20 ) { - packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant - packet.push_back( SID_AUTH_ACCOUNTLOGONPROOF ); // SID_AUTH_ACCOUNTLOGONPROOF - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, clientPasswordProof ); // Client Password Proof + packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant + packet.push_back( SID_AUTH_ACCOUNTLOGONPROOF ); // SID_AUTH_ACCOUNTLOGONPROOF + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.append(clientPasswordProof); // Client Password Proof AssignLength( packet ); } else @@ -903,7 +916,7 @@ QByteArray CBNETProtocol :: SEND_SID_WARDEN( QByteArray wardenResponse ) packet.push_back( SID_WARDEN ); // SID_WARDEN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAYFast( packet, wardenResponse ); // warden response + packet.append(wardenResponse); // warden response AssignLength( packet ); // DEBUG_Print( "SENT SID_WARDEN" ); // DEBUG_Print( packet ); @@ -925,14 +938,14 @@ QByteArray CBNETProtocol :: SEND_SID_FRIENDSLIST( ) QByteArray CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) { - unsigned char Cookie[] = { 0, 0, 0, 0 }; + char Cookie[] = { 0, 0, 0, 0 }; QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant packet.push_back( SID_CLANMEMBERLIST ); // SID_CLANMEMBERLIST packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, Cookie, 4 ); // cookie + packet.append(QByteArray(Cookie, 4)); // cookie AssignLength( packet ); // DEBUG_Print( "SENT SID_CLANMEMBERLIST" ); // DEBUG_Print( packet ); @@ -951,7 +964,7 @@ bool CBNETProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); + LengthBytes = Util::fromUInt16(content.size( )); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -971,7 +984,7 @@ bool CBNETProtocol :: ValidateLength( QByteArray &content ) { LengthBytes.push_back( content[2] ); LengthBytes.push_back( content[3] ); - Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); + Length = Util::extractUInt16(LengthBytes); if( Length == content.size( ) ) return true; @@ -1005,7 +1018,7 @@ QString CIncomingGameHost :: GetIPString( ) { for( unsigned int i = 0; i < 4; i++ ) { - Result += UTIL_ToString( (unsigned int)m_IP[i] ); + Result += QString::number( (unsigned int)m_IP[i] ); if( i < 3 ) Result += "."; diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index 7fde607..43c2e57 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -53,27 +53,27 @@ CBNLSClient :: CBNLSClient( QString nServer, quint16 nPort, quint32 nWardenCooki void CBNLSClient::socketConnect() { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connecting to server [" + m_Server + "] on port " + UTIL_ToString( m_Port ) ); + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + QString::number( m_Port ) + ":C" + QString::number( m_WardenCookie ) + "] connecting to server [" + m_Server + "] on port " + QString::number( m_Port ) ); m_Socket->connectToHost( QHostAddress(m_Server), m_Port ); m_Retries++; } void CBNLSClient::socketConnected() { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] connected" ); + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + QString::number( m_Port ) + ":C" + QString::number( m_WardenCookie ) + "] connected" ); m_WasConnected = true; m_NULLTimer.start(); } void CBNLSClient::socketDisconnected() { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] disconnected from BNLS server" ); + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + QString::number( m_Port ) + ":C" + QString::number( m_WardenCookie ) + "] disconnected from BNLS server" ); m_Socket->deleteLater(); m_Socket = new QTcpSocket(); if (m_Retries > 6) { - CONSOLE_Print("[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] giving up after 5 failed retries." ); + CONSOLE_Print("[BNLSC: " + m_Server + ":" + QString::number( m_Port ) + ":C" + QString::number( m_WardenCookie ) + "] giving up after 5 failed retries." ); deleteLater(); return; } @@ -98,7 +98,7 @@ void CBNLSClient::socketDataReady() void CBNLSClient::socketError() { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] disconnected from BNLS server due to socket error" ); + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + QString::number( m_Port ) + ":C" + QString::number( m_WardenCookie ) + "] disconnected from BNLS server due to socket error" ); m_Socket->deleteLater(); m_Socket = NULL; } @@ -119,11 +119,11 @@ void CBNLSClient :: ExtractPackets( ) { while( m_Socket->bytesAvailable() >= 3 ) { - quint16 Length = UTIL_QByteArrayToUInt16( m_Socket->peek(2), false ); + quint16 Length = Util::extractUInt16( m_Socket->peek(2) ); if( Length < 3 ) { - CONSOLE_Print( "[BNLSC: " + m_Server + ":" + UTIL_ToString( m_Port ) + ":C" + UTIL_ToString( m_WardenCookie ) + "] error - received invalid packet from BNLS server (bad length), disconnecting" ); + CONSOLE_Print( "[BNLSC: " + m_Server + ":" + QString::number( m_Port ) + ":C" + QString::number( m_WardenCookie ) + "] error - received invalid packet from BNLS server (bad length), disconnecting" ); m_Socket->abort(); m_Socket->deleteLater(); return; diff --git a/ghost/bnlsprotocol.cpp b/ghost/bnlsprotocol.cpp index 8ce2247..eef5ca1 100644 --- a/ghost/bnlsprotocol.cpp +++ b/ghost/bnlsprotocol.cpp @@ -56,7 +56,7 @@ QByteArray CBNLSProtocol :: RECEIVE_BNLS_WARDEN( QByteArray data ) if( Result == 0x00 ) return data.mid(11); else - CONSOLE_Print( "[BNLSPROTO] received error code " + UTIL_ToString( data[8] ) ); + CONSOLE_Print( "[BNLSPROTO] received error code " + QString::number( data[8] ) ); } return QByteArray( ); @@ -78,19 +78,19 @@ QByteArray CBNLSProtocol :: SEND_BNLS_NULL( ) QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_SEED( quint32 cookie, quint32 seed ) { - unsigned char Client[] = { 80, 88, 51, 87 }; // "W3XP" + char Client[] = { 80, 88, 51, 87 }; // "W3XP" QByteArray packet; packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( (char)0 ); // BNLS_WARDEN_SEED - UTIL_AppendBYTEARRAY( packet, cookie, false ); // cookie - UTIL_AppendBYTEARRAY( packet, Client, 4 ); // Client - UTIL_AppendBYTEARRAY( packet, (quint16)4, false ); // length of seed - UTIL_AppendBYTEARRAY( packet, seed, false ); // seed + packet.append(Util::fromUInt32(cookie)); // cookie + packet.append(QByteArray(Client, 4)); // Client + packet.append(Util::fromUInt16(4)); // length of seed + packet.append(Util::fromUInt32(seed)); // seed packet.push_back( (char)0 ); // username is blank - UTIL_AppendBYTEARRAY( packet, (quint16)0, false ); // password length + packet.append(Util::fromUInt16(0)); // password length // password AssignLength( packet ); return packet; @@ -103,9 +103,9 @@ QByteArray CBNLSProtocol :: SEND_BNLS_WARDEN_RAW( quint32 cookie, QByteArray raw packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( BNLS_WARDEN ); // BNLS_WARDEN packet.push_back( 1 ); // BNLS_WARDEN_RAW - UTIL_AppendBYTEARRAY( packet, cookie, false ); // cookie - UTIL_AppendBYTEARRAY( packet, (quint16)raw.size( ), false ); // raw length - UTIL_AppendBYTEARRAY( packet, raw ); // raw + packet.append(Util::fromUInt32(cookie)); // cookie + packet.append(Util::fromUInt16(raw.size( ))); // raw length + packet.append(raw); // raw AssignLength( packet ); return packet; } @@ -127,7 +127,7 @@ bool CBNLSProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 2 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); + LengthBytes = Util::fromUInt16(content.size( )); content[0] = LengthBytes[0]; content[1] = LengthBytes[1]; return true; @@ -147,7 +147,7 @@ bool CBNLSProtocol :: ValidateLength( QByteArray &content ) { LengthBytes.push_back( content[0] ); LengthBytes.push_back( content[1] ); - Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); + Length = Util::extractUInt16( LengthBytes ); if( Length == content.size( ) ) return true; diff --git a/ghost/game.cpp b/ghost/game.cpp index 57f86e8..eb342dd 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -208,13 +208,13 @@ void CGame::EventCallableUpdateTimeout() if( GamePlayerSummary ) { if( i->first.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), UTIL_ToString( GamePlayerSummary->GetTotalGames( ) ), UTIL_ToString( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 2 ), UTIL_ToString( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); + SendAllChat( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( 2, (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); else { CGamePlayer *Player = GetPlayerFromName( i->first, true ); if( Player ) - SendChat( Player, m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), UTIL_ToString( GamePlayerSummary->GetTotalGames( ) ), UTIL_ToString( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 2 ), UTIL_ToString( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); + SendChat( Player, m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( 2, (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); } } else @@ -247,27 +247,27 @@ void CGame::EventCallableUpdateTimeout() if( DotAPlayerSummary ) { QString Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), - UTIL_ToString( DotAPlayerSummary->GetTotalGames( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalWins( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalLosses( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalDeaths( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalCreepKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalCreepDenies( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalAssists( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalNeutralKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalTowerKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalRaxKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetTotalCourierKills( ) ), - UTIL_ToString( DotAPlayerSummary->GetAvgKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgDeaths( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgCreepKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgCreepDenies( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgAssists( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgNeutralKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgTowerKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgRaxKills( ), 2 ), - UTIL_ToString( DotAPlayerSummary->GetAvgCourierKills( ), 2 ) ); + QString::number( DotAPlayerSummary->GetTotalGames( ) ), + QString::number( DotAPlayerSummary->GetTotalWins( ) ), + QString::number( DotAPlayerSummary->GetTotalLosses( ) ), + QString::number( DotAPlayerSummary->GetTotalKills( ) ), + QString::number( DotAPlayerSummary->GetTotalDeaths( ) ), + QString::number( DotAPlayerSummary->GetTotalCreepKills( ) ), + QString::number( DotAPlayerSummary->GetTotalCreepDenies( ) ), + QString::number( DotAPlayerSummary->GetTotalAssists( ) ), + QString::number( DotAPlayerSummary->GetTotalNeutralKills( ) ), + QString::number( DotAPlayerSummary->GetTotalTowerKills( ) ), + QString::number( DotAPlayerSummary->GetTotalRaxKills( ) ), + QString::number( DotAPlayerSummary->GetTotalCourierKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgDeaths( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgCreepKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgCreepDenies( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgAssists( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgNeutralKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgTowerKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgRaxKills( ) ), + QString::number( 2, DotAPlayerSummary->GetAvgCourierKills( ) ) ); if( i->first.isEmpty( ) ) SendAllChat( Summary ); @@ -558,11 +558,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } else { - quint32 AutoStartPlayers = UTIL_ToUInt32( Payload ); + quint32 AutoStartPlayers = Payload.toUInt(); if( AutoStartPlayers != 0 ) { - SendAllChat( m_GHost->m_Language->AutoStartEnabled( UTIL_ToString( AutoStartPlayers ) ) ); + SendAllChat( m_GHost->m_Language->AutoStartEnabled( QString::number( AutoStartPlayers ) ) ); m_AutoStartPlayers = AutoStartPlayers; } } @@ -612,13 +612,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } } - SendAllChat( m_GHost->m_Language->CheckedPlayer( LastMatch->GetName( ), LastMatch->GetNumPings( ) > 0 ? UTIL_ToString( LastMatch->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( LastMatch->GetExternalIP( ), true ) ), LastMatchAdminCheck || LastMatchRootAdminCheck ? "Yes" : "No", IsOwner( LastMatch->GetName( ) ) ? "Yes" : "No", LastMatch->GetSpoofed( ) ? "Yes" : "No", LastMatch->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : LastMatch->GetSpoofedRealm( ), LastMatch->GetReserved( ) ? "Yes" : "No" ) ); + SendAllChat( m_GHost->m_Language->CheckedPlayer( LastMatch->GetName( ), LastMatch->GetNumPings( ) > 0 ? QString::number( LastMatch->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32( Util::reverse(LastMatch->GetExternalIP( )) ) ), LastMatchAdminCheck || LastMatchRootAdminCheck ? "Yes" : "No", IsOwner( LastMatch->GetName( ) ) ? "Yes" : "No", LastMatch->GetSpoofed( ) ? "Yes" : "No", LastMatch->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : LastMatch->GetSpoofedRealm( ), LastMatch->GetReserved( ) ? "Yes" : "No" ) ); } else SendAllChat( m_GHost->m_Language->UnableToCheckPlayerFoundMoreThanOneMatch( Payload ) ); } else - SendAllChat( m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( player->GetExternalIP( ), true ) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); + SendAllChat( m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? QString::number( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse(player->GetExternalIP( ))) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); } // @@ -1009,7 +1009,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri Froms += (*i)->GetNameTerminated( ); Froms += ": ("; - Froms += m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( (*i)->GetExternalIP( ), true ) ); + Froms += m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse((*i)->GetExternalIP( ))) ); Froms += ")"; if( i != m_Players.end( ) - 1 ) @@ -1119,10 +1119,10 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "latency" ) { if( Payload.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->LatencyIs( UTIL_ToString( m_Latency ) ) ); + SendAllChat( m_GHost->m_Language->LatencyIs( QString::number( m_Latency ) ) ); else { - m_RequestedLatency = UTIL_ToUInt32( Payload ); + m_RequestedLatency = Payload.toUInt(); quint32 min = 20, max = 2000; @@ -1137,7 +1137,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( m_GHost->m_Language->SettingLatencyToMaximum( QString::number(m_RequestedLatency) ) ); } else - SendAllChat( m_GHost->m_Language->SettingLatencyTo( UTIL_ToString( m_RequestedLatency ) ) ); + SendAllChat( m_GHost->m_Language->SettingLatencyTo( QString::number( m_RequestedLatency ) ) ); } } @@ -1268,7 +1268,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 KickPing = 0; if( !m_GameLoading && !m_GameLoaded && !Payload.isEmpty( ) ) - KickPing = UTIL_ToUInt32( Payload ); + KickPing = Payload.toUInt(); // copy the m_Players vector so we can sort by descending ping so it's easier to find players with high pings @@ -1283,11 +1283,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( (*i)->GetNumPings( ) > 0 ) { - Pings += UTIL_ToString( (*i)->GetPing( m_GHost->m_LCPings ) ); + Pings += QString::number( (*i)->GetPing( m_GHost->m_LCPings ) ); if( !m_GameLoading && !m_GameLoaded && !(*i)->GetReserved( ) && KickPing > 0 && (*i)->GetPing( m_GHost->m_LCPings ) > KickPing ) { - (*i)->SetLeftReason( "was kicked for excessive ping " + UTIL_ToString( (*i)->GetPing( m_GHost->m_LCPings ) ) + " > " + UTIL_ToString( KickPing ) ); + (*i)->SetLeftReason( "was kicked for excessive ping " + QString::number( (*i)->GetPing( m_GHost->m_LCPings ) ) + " > " + QString::number( KickPing ) ); (*i)->SetLeftCode( PLAYERLEAVE_LOBBY ); (*i)->deleteLater(); OpenSlot( GetSIDFromPID( (*i)->GetPID( ) ), false ); @@ -1315,7 +1315,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( Pings ); if( Kicked > 0 ) - SendAllChat( m_GHost->m_Language->KickingPlayersWithPingsGreaterThan( UTIL_ToString( Kicked ), UTIL_ToString( KickPing ) ) ); + SendAllChat( m_GHost->m_Language->KickingPlayersWithPingsGreaterThan( QString::number( Kicked ), QString::number( KickPing ) ) ); } // @@ -1457,7 +1457,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QByteArray MapHeight; MapHeight.push_back( (char)0 ); MapHeight.push_back( (char)0 ); - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), QHostAddress(IP), Port); } else @@ -1466,7 +1466,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) quint32 MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), + m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), QHostAddress(IP), Port); } } @@ -1539,10 +1539,10 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "synclimit" ) { if( Payload.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->SyncLimitIs( UTIL_ToString( m_SyncLimit ) ) ); + SendAllChat( m_GHost->m_Language->SyncLimitIs( QString::number( m_SyncLimit ) ) ); else { - m_SyncLimit = UTIL_ToUInt32( Payload ); + m_SyncLimit = Payload.toUInt(); if( m_SyncLimit <= 10 ) { @@ -1555,7 +1555,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( m_GHost->m_Language->SettingSyncLimitToMaximum( "10000" ) ); } else - SendAllChat( m_GHost->m_Language->SettingSyncLimitTo( UTIL_ToString( m_SyncLimit ) ) ); + SendAllChat( m_GHost->m_Language->SettingSyncLimitTo( QString::number( m_SyncLimit ) ) ); } } @@ -1676,7 +1676,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // if( Command == "checkme" ) - SendChat( player, m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( UTIL_QByteArrayToUInt32( player->GetExternalIP( ), true ) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); + SendChat( player, m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? QString::number( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse(player->GetExternalIP( ))) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); // // !STATS @@ -1759,7 +1759,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri player->SetKickVote( true ); CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] started by player [" + User + "]" ); - SendAllChat( m_GHost->m_Language->StartedVoteKick( LastMatch->GetName( ), User, UTIL_ToString( (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); + SendAllChat( m_GHost->m_Language->StartedVoteKick( LastMatch->GetName( ), User, QString::number( (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); SendAllChat( m_GHost->m_Language->TypeYesToVote( QString( 1, m_GHost->m_CommandTrigger ) ) ); } } @@ -1802,7 +1802,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( !m_GameLoading && !m_GameLoaded ) OpenSlot( GetSIDFromPID( Victim->GetPID( ) ), false ); - CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] passed with " + UTIL_ToString( Votes ) + "/" + UTIL_ToString( GetNumHumanPlayers( ) ) + " votes" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] passed with " + QString::number( Votes ) + "/" + QString::number( GetNumHumanPlayers( ) ) + " votes" ); SendAllChat( m_GHost->m_Language->VoteKickPassed( m_KickVotePlayer ) ); } else @@ -1812,7 +1812,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_VotekickTimer.stop(); } else - SendAllChat( m_GHost->m_Language->VoteKickAcceptedNeedMoreVotes( m_KickVotePlayer, User, UTIL_ToString( VotesNeeded - Votes ) ) ); + SendAllChat( m_GHost->m_Language->VoteKickAcceptedNeedMoreVotes( m_KickVotePlayer, User, QString::number( VotesNeeded - Votes ) ) ); } return HideCommand; diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 3e07573..5213ed5 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -96,7 +96,7 @@ void CAdminGame::EventCallableUpdateTimeout() else if( Count == 1 ) SendChat( Player, m_GHost->m_Language->ThereIsAdmin( i->second->GetServer( ) ) ); else - SendChat( Player, m_GHost->m_Language->ThereAreAdmins( i->second->GetServer( ), UTIL_ToString( Count ) ) ); + SendChat( Player, m_GHost->m_Language->ThereAreAdmins( i->second->GetServer( ), QString::number( Count ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -184,7 +184,7 @@ void CAdminGame::EventCallableUpdateTimeout() else if( Count == 1 ) SendChat( Player, m_GHost->m_Language->ThereIsBannedUser( i->second->GetServer( ) ) ); else - SendChat( Player, m_GHost->m_Language->ThereAreBannedUsers( i->second->GetServer( ), UTIL_ToString( Count ) ) ); + SendChat( Player, m_GHost->m_Language->ThereAreBannedUsers( i->second->GetServer( ), QString::number( Count ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -757,7 +757,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "downloads" && !Payload.isEmpty( ) ) { - quint32 Downloads = UTIL_ToUInt32( Payload ); + quint32 Downloads = Payload.toUInt(); if( Downloads == 0 ) { @@ -794,7 +794,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { // todotodo: what if a game ends just as you're typing this command and the numbering changes? - int GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = Payload.toUInt() - 1; if( GameNumber < m_GHost->m_Games.size( ) ) { @@ -820,7 +820,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { QString File = m_GHost->m_ReplayPath + Payload + ".w3g"; - if( UTIL_FileExists( File ) ) + if( QFile::exists( File ) ) { SendChat( player, m_GHost->m_Language->LoadingReplay( File ) ); CReplay *Replay = new CReplay( ); @@ -860,7 +860,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "getgame" && !Payload.isEmpty( ) ) { - int GameNumber = UTIL_ToUInt32( Payload ) - 1; + int GameNumber = Payload.toUInt() - 1; if( GameNumber < m_GHost->m_Games.size( ) ) SendChat( player, m_GHost->m_Language->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ) ); @@ -875,9 +875,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "getgames" ) { if( m_GHost->m_CurrentGame ) - SendChat( player, m_GHost->m_Language->GameIsInTheLobby( m_GHost->m_CurrentGame->GetDescription( ), UTIL_ToString( m_GHost->m_Games.size( ) ), UTIL_ToString( m_GHost->m_MaxGames ) ) ); + SendChat( player, m_GHost->m_Language->GameIsInTheLobby( m_GHost->m_CurrentGame->GetDescription( ), QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ) ); else - SendChat( player, m_GHost->m_Language->ThereIsNoGameInTheLobby( UTIL_ToString( m_GHost->m_Games.size( ) ), UTIL_ToString( m_GHost->m_MaxGames ) ) ); + SendChat( player, m_GHost->m_Language->ThereIsNoGameInTheLobby( QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ) ); } // @@ -956,7 +956,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; QString FileNoPath = Payload + ".w3z"; - if( UTIL_FileExists( File ) ) + if( QFile::exists( File ) ) { if( m_GHost->m_CurrentGame ) SendChat( player, m_GHost->m_Language->UnableToLoadSaveGameGameInLobby( ) ); @@ -1144,7 +1144,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( GameNumber - 1 < m_GHost->m_Games.size( ) ) m_GHost->m_Games[GameNumber - 1]->SendAllChat( "ADMIN: " + Message ); else - SendChat( player, m_GHost->m_Language->GameNumberDoesntExist( UTIL_ToString( GameNumber ) ) ); + SendChat( player, m_GHost->m_Language->GameNumberDoesntExist( QString::number( GameNumber ) ) ); } } } @@ -1229,7 +1229,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, quint32 LoginAttempts = player->GetLoginAttempts( ) + 1; player->SetLoginAttempts( LoginAttempts ); CONSOLE_Print( "[ADMINGAME] user [" + User + "] login attempt failed" ); - SendChat( player, m_GHost->m_Language->AdminInvalidPassword( UTIL_ToString( LoginAttempts ) ) ); + SendChat( player, m_GHost->m_Language->AdminInvalidPassword( QString::number( LoginAttempts ) ) ); if( LoginAttempts >= 1 ) { diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 68991b5..89a5a93 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -238,7 +238,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 f.close( ); - CONSOLE_Print( "[GAME: " + m_GameName + "] loaded " + UTIL_ToString( m_IPBlackList.size( ) ) + " lines from IP blacklist file" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] loaded " + QString::number( m_IPBlackList.size( ) ) + " lines from IP blacklist file" ); } } @@ -253,10 +253,10 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 QHostAddress hostAddr = m_GHost->m_BindAddress == "" ? QHostAddress::Any : QHostAddress(m_GHost->m_BindAddress); if( m_Socket->listen( hostAddr, m_HostPort ) ) - CONSOLE_Print( "[GAME: " + m_GameName + "] listening on " + hostAddr.toString() + ":" + UTIL_ToString( m_Socket->serverPort() ) ); + CONSOLE_Print( "[GAME: " + m_GameName + "] listening on " + hostAddr.toString() + ":" + QString::number( m_Socket->serverPort() ) ); else { - CONSOLE_Print( "[GAME: " + m_GameName + "] error listening on " + hostAddr.toString() + ":" + UTIL_ToString( m_HostPort ) ); + CONSOLE_Print( "[GAME: " + m_GameName + "] error listening on " + hostAddr.toString() + ":" + QString::number( m_HostPort ) ); deleteLater(); } } @@ -280,8 +280,8 @@ CBaseGame :: ~CBaseGame( ) char Time[17]; memset( Time, 0, sizeof( char ) * 17 ); strftime( Time, sizeof( char ) * 17, "%Y-%m-%d %H-%M", localtime( &Now ) ); - QString MinString = UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ); - QString SecString = UTIL_ToString( ( m_GameTicks / 1000 ) % 60 ); + QString MinString = QString::number( ( m_GameTicks / 1000 ) / 60 ); + QString SecString = QString::number( ( m_GameTicks / 1000 ) % 60 ); if( MinString.size( ) == 1 ) MinString.insert( 0, "0" ); @@ -365,12 +365,12 @@ quint32 CBaseGame :: GetNumHumanPlayers( ) QString CBaseGame :: GetDescription( ) { - QString Description = m_GameName + " : " + m_OwnerName + " : " + UTIL_ToString( GetNumHumanPlayers( ) ) + "/" + UTIL_ToString( m_GameLoading || m_GameLoaded ? m_StartPlayers : m_Slots.size( ) ); + QString Description = m_GameName + " : " + m_OwnerName + " : " + QString::number( GetNumHumanPlayers( ) ) + "/" + QString::number( m_GameLoading || m_GameLoaded ? m_StartPlayers : m_Slots.size( ) ); if( m_GameLoading || m_GameLoaded ) - Description += " : " + UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ) + "m"; + Description += " : " + QString::number( ( m_GameTicks / 1000 ) / 60 ) + "m"; else - Description += " : " + UTIL_ToString( ( GetTime( ) - m_CreationTime ) / 60 ) + "m"; + Description += " : " + QString::number( ( GetTime( ) - m_CreationTime ) / 60 ) + "m"; return Description; } @@ -542,7 +542,7 @@ void CBaseGame::EventBroadcastTimeout() m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, - UTIL_CreateBYTEARRAY( MapGameType, false ), + Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, @@ -564,7 +564,23 @@ void CBaseGame::EventBroadcastTimeout() // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) quint32 MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateBYTEARRAY( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter ), + m_GHost->m_UDPSocket->writeDatagram( + m_Protocol->SEND_W3GS_GAMEINFO( + m_GHost->m_TFT, + m_GHost->m_LANWar3Version, + Util::fromUInt32( MapGameType), + m_Map->GetMapGameFlags( ), + m_Map->GetMapWidth( ), + m_Map->GetMapHeight( ), + m_GameName, + "Varlock", + GetTime( ) - m_CreationTime, + m_Map->GetMapPath( ), + m_Map->GetMapCRC( ), + 12, + 12, + m_HostPort, + FixedHostCounter ), hostAddr, 6112 ); } @@ -576,7 +592,7 @@ void CBaseGame::EventTryAutoRehost() // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted // so rehost it using the current autohost game name - QString GameName = m_GHost->m_AutoHostGameName + " #" + UTIL_ToString( m_GHost->m_HostCounter ); + QString GameName = m_GHost->m_AutoHostGameName + " #" + QString::number( m_GHost->m_HostCounter ); CONSOLE_Print( "[GAME: " + m_GameName + "] automatically trying to rehost as public game [" + GameName + "] due to refresh failure" ); m_LastGameName = m_GameName; m_GameName = GameName; @@ -711,7 +727,7 @@ void CBaseGame::EventMapDataTimeout() // in addition to this, the throughput is limited by the configuration value bot_maxdownloadspeed // in summary: the actual throughput is MIN( 140 * 1000 / ping, 1400, bot_maxdownloadspeed ) in KB/sec assuming only one player is downloading the map - quint32 MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); + quint32 MapSize = Util::extractUInt32(m_Map->GetMapSize( )); while( (*i)->GetLastMapPartSent( ) < (*i)->GetLastMapPartAcked( ) + 1442 * 100 && (*i)->GetLastMapPartSent( ) < MapSize ) { @@ -746,7 +762,7 @@ void CBaseGame::EventCountdownTimeout() return; } - SendAllChat( UTIL_ToString( m_CountDownCounter ) + ". . ." ); + SendAllChat( QString::number( m_CountDownCounter ) + ". . ." ); m_CountDownCounter--; } @@ -856,7 +872,7 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString if( message.size( ) > 254 ) message = message.mid( 0, 254 ); - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, UTIL_CreateBYTEARRAY( player->GetPID( ) ), 16, QByteArray( ), message ) ); + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray(1, player->GetPID( ) ), 16, QByteArray( ), message ) ); } else { @@ -912,7 +928,7 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) if( message.size( ) > 127 ) message = message.mid( 0, 127 ); - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, UTIL_CreateBYTEARRAY( (quint32)0, false ), message ) ); + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, Util::fromUInt32( 0), message ) ); if( m_Replay ) m_Replay->AddChatMessage( fromPID, 32, 0, message ); @@ -1101,7 +1117,7 @@ void CBaseGame :: SendAllActions( ) // print a message because even though this will take more resources it should provide some information to the administrator for future reference // other solutions - dynamically modify the latency, request higher priority, terminate other games, ??? - CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but GHost needed " + QString::number(GetTicks() - m_LastActionSentTicks) + "ms , your machine is probably overloaded" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + QString::number( m_Latency ) + "ms but GHost needed " + QString::number(GetTicks() - m_LastActionSentTicks) + "ms , your machine is probably overloaded" ); } m_LastActionSentTicks = GetTicks( ); @@ -1218,7 +1234,7 @@ void CBaseGame::CheckPlayersStartedLaggging() void CBaseGame::EventDropLaggerTimeout() { - StopLaggers( m_GHost->m_Language->WasAutomaticallyDroppedAfterSeconds( UTIL_ToString(m_WaitTime) ) ); + StopLaggers( m_GHost->m_Language->WasAutomaticallyDroppedAfterSeconds( QString::number(m_WaitTime) ) ); } void CBaseGame::EventResetLagscreenTimeout() @@ -1425,11 +1441,11 @@ void CBaseGame :: EventPlayerDeleted() if( m_GameLoaded && player->GetLeftCode( ) == PLAYERLEAVE_DISCONNECT && m_AutoSave ) { QString SaveGameName = UTIL_FileSafeName( "GHost++ AutoSave " + m_GameName + " (" + player->GetName( ) + ").w3z" ); - CONSOLE_Print( "[GAME: " + m_GameName + "] auto saving [" + SaveGameName + "] before player drop, shortened send interval = " + UTIL_ToString( GetTicks( ) - m_LastActionSentTicks ) ); + CONSOLE_Print( "[GAME: " + m_GameName + "] auto saving [" + SaveGameName + "] before player drop, shortened send interval = " + QString::number( GetTicks( ) - m_LastActionSentTicks ) ); QByteArray CRC; QByteArray Action; Action.push_back( 6 ); - UTIL_AppendBYTEARRAY( Action, SaveGameName.toUtf8() ); + Action.append(SaveGameName.toUtf8()); m_Actions.enqueue( new CIncomingAction( player->GetPID( ), CRC, Action ) ); // todotodo: with the new latency system there needs to be a way to send a 0-time action @@ -1554,7 +1570,7 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) if( TimeRemaining > ( (quint32)m_GProxyEmptyActions + 1 ) * 60 ) TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; - SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); + SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); player->SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } @@ -1585,7 +1601,7 @@ void CBaseGame :: EventPlayerDisconnectConnectionClosed( CGamePlayer *player ) if( TimeRemaining > ( (quint32)m_GProxyEmptyActions + 1 ) * 60 ) TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; - SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); + SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); player->SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } @@ -1605,7 +1621,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( joinPlayer->GetName( ).isEmpty( ) || joinPlayer->GetName( ).size( ) > 15 ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game with an invalid name of length " + UTIL_ToString( joinPlayer->GetName( ).size( ) ) ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game with an invalid name of length " + QString::number( joinPlayer->GetName( ).size( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); return; @@ -1680,7 +1696,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((quint16)potential->GetSocket( )->localPort(), false), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, Util::fromUInt16(potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->deleteLater(); return; } @@ -1708,7 +1724,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // this causes them to be kicked back to the chat channel on battle.net QVector Slots = m_Map->GetSlots( ); - potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, UTIL_CreateBYTEARRAY((quint16)potential->GetSocket( )->localPort(), false), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, Util::fromUInt16((quint16)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->deleteLater(); return; } @@ -1955,7 +1971,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((quint16)Player->GetSocket( )->localPort(), false), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), Util::fromUInt16(Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2092,7 +2108,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score > -99999.0 && ( score < m_MinimumScore || score > m_MaximumScore ) ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has a rating [" + UTIL_ToString( score, 2 ) + "] outside the limits [" + UTIL_ToString( m_MinimumScore, 2 ) + "] to [" + UTIL_ToString( m_MaximumScore, 2 ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has a rating [" + QString::number( 2, score ) + "] outside the limits [" + QString::number( 2, m_MinimumScore ) + "] to [" + QString::number( 2, m_MaximumScore ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); return; @@ -2185,9 +2201,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score < -99999.0 || abs( score - AverageScore ) > abs( FurthestPlayer->GetScore( ) - AverageScore ) ) { if( score < -99999.0 ) - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [N/A] from the average [" + UTIL_ToString( AverageScore, 2 ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [N/A] from the average [" + QString::number( 2, AverageScore ) + "]" ); else - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [" + UTIL_ToString( score, 2 ) + "] from the average [" + UTIL_ToString( AverageScore, 2 ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [" + QString::number( 2, score ) + "] from the average [" + QString::number( 2, AverageScore ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); @@ -2199,9 +2215,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SID = GetSIDFromPID( FurthestPlayer->GetPID( ) ); if( FurthestPlayer->GetScore( ) < -99999.0 ) - FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", UTIL_ToString( AverageScore, 2 ) ) ); + FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", QString::number( 2, AverageScore ) ) ); else - FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( UTIL_ToString( FurthestPlayer->GetScore( ), 2 ), UTIL_ToString( AverageScore, 2 ) ) ); + FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( QString::number( 2, FurthestPlayer->GetScore( ) ), QString::number( 2, AverageScore ) ) ); FurthestPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2213,9 +2229,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco FurthestPlayer->deleteLater(); if( FurthestPlayer->GetScore( ) < -99999.0 ) - SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", UTIL_ToString( AverageScore, 2 ) ) ); + SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", QString::number( 2, AverageScore ) ) ); else - SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), UTIL_ToString( FurthestPlayer->GetScore( ), 2 ), UTIL_ToString( AverageScore, 2 ) ) ); + SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), QString::number( 2, FurthestPlayer->GetScore( ) ), QString::number( 2, AverageScore ) ) ); } else if( m_GHost->m_MatchMakingMethod == 2 ) { @@ -2247,7 +2263,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score < -99999.0 ) CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [N/A]" ); else - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [" + UTIL_ToString( score, 2 ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [" + QString::number( 2, score ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); @@ -2261,7 +2277,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( LowestPlayer->GetScore( ) < -99999.0 ) LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( "N/A" ) ); else - LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( UTIL_ToString( LowestPlayer->GetScore( ), 2 ) ) ); + LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( QString::number( 2, LowestPlayer->GetScore( ) ) ) ); LowestPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2275,7 +2291,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( LowestPlayer->GetScore( ) < -99999.0 ) SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), "N/A" ) ); else - SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), UTIL_ToString( LowestPlayer->GetScore( ), 2 ) ) ); + SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), QString::number( 2, LowestPlayer->GetScore( ) ) ) ); } } @@ -2334,7 +2350,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco // send slot info to the new player // the SLOTINFOJOIN packet also tells the client their assigned PID and that the join was successful - Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), UTIL_CreateBYTEARRAY((quint16)Player->GetSocket( )->localPort(), false), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); + Player->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( Player->GetPID( ), Util::fromUInt16((quint16)Player->GetSocket( )->localPort()), Player->GetExternalIP( ), m_Slots, m_RandomSeed, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); // send virtual host info and fake player info (if present) to the new player @@ -2404,7 +2420,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score < -99999.0 ) SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), "N/A" ) ); else - SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), UTIL_ToString( score, 2 ) ) ); + SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), QString::number( 2, score ) ) ); quint32 PlayersScored = 0; quint32 PlayersNotScored = 0; @@ -2436,7 +2452,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco } double Spread = MaxScore - MinScore; - SendAllChat( m_GHost->m_Language->RatedPlayersSpread( UTIL_ToString( PlayersScored ), UTIL_ToString( PlayersScored + PlayersNotScored ), UTIL_ToString( (quint32)Spread ) ) ); + SendAllChat( m_GHost->m_Language->RatedPlayersSpread( QString::number( PlayersScored ), QString::number( PlayersScored + PlayersNotScored ), QString::number( (quint32)Spread ) ) ); // check for multiple IP usage @@ -2502,7 +2518,7 @@ void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) void CBaseGame :: EventPlayerLoaded() { CGamePlayer *player = (CGamePlayer*)QObject::sender(); - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] finished loading in " + UTIL_ToString( (float)( player->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) + " seconds" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] finished loading in " + QString::number( 2, (float)( player->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) + " seconds" ); if( m_LoadInGame ) { @@ -2642,7 +2658,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check } } - SendAllChat( m_GHost->m_Language->PlayersInGameState( UTIL_ToString( StateNumber ), Players ) ); + SendAllChat( m_GHost->m_Language->PlayersInGameState( QString::number( StateNumber ), Players ) ); StateNumber++; } @@ -2717,8 +2733,8 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye // calculate timestamp - QString MinString = UTIL_ToString( ( m_GameTicks / 1000 ) / 60 ); - QString SecString = UTIL_ToString( ( m_GameTicks / 1000 ) % 60 ); + QString MinString = QString::number( ( m_GameTicks / 1000 ) / 60 ); + QString SecString = QString::number( ( m_GameTicks / 1000 ) % 60 ); if( MinString.size( ) == 1 ) MinString.insert( 0, "0" ); @@ -2753,7 +2769,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye // this includes allied chat and private chat from both teams as long as it was relayed if( m_Replay ) - m_Replay->AddChatMessage( chatPlayer->GetFromPID( ), chatPlayer->GetFlag( ), UTIL_QByteArrayToUInt32( chatPlayer->GetExtraFlags( ), false ), chatPlayer->GetMessage( ) ); + m_Replay->AddChatMessage( chatPlayer->GetFromPID( ), chatPlayer->GetFlag( ), Util::extractUInt32(chatPlayer->GetExtraFlags( )), chatPlayer->GetMessage( ) ); } } else @@ -2989,7 +3005,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map // todotodo: the variable names here are confusing due to extremely poor design on my part - quint32 MapSize = UTIL_QByteArrayToUInt32( m_Map->GetMapSize( ), false ); + quint32 MapSize = Util::extractUInt32(m_Map->GetMapSize( )); if( mapSize->GetSizeFlag( ) != 1 || mapSize->GetMapSize( ) != MapSize ) { @@ -3040,8 +3056,8 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map float Seconds = (float)( GetTicks( ) - player->GetStartedDownloadingTicks( ) ) / 1000; float Rate = (float)MapSize / 1024 / Seconds; - CONSOLE_Print( "[GAME: " + m_GameName + "] map download finished for player [" + player->GetName( ) + "] in " + UTIL_ToString( Seconds, 1 ) + " seconds" ); - SendAllChat( m_GHost->m_Language->PlayerDownloadedTheMap( player->GetName( ), UTIL_ToString( Seconds, 1 ), UTIL_ToString( Rate, 1 ) ) ); + CONSOLE_Print( "[GAME: " + m_GameName + "] map download finished for player [" + player->GetName( ) + "] in " + QString::number( 1, Seconds ) + " seconds" ); + SendAllChat( m_GHost->m_Language->PlayerDownloadedTheMap( player->GetName( ), QString::number( 1, Seconds ), QString::number( 1, Rate ) ) ); player->SetDownloadFinished( true ); player->SetFinishedDownloadingTime( GetTime( ) ); @@ -3111,8 +3127,8 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, quint32 /*pong*/ ) { // send a chat message because we don't normally do so when a player leaves the lobby - SendAllChat( m_GHost->m_Language->AutokickingPlayerForExcessivePing( player->GetName( ), UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) ) ); - player->SetLeftReason( "was autokicked for excessive ping of " + UTIL_ToString( player->GetPing( m_GHost->m_LCPings ) ) ); + SendAllChat( m_GHost->m_Language->AutokickingPlayerForExcessivePing( player->GetName( ), QString::number( player->GetPing( m_GHost->m_LCPings ) ) ) ); + player->SetLeftReason( "was autokicked for excessive ping of " + QString::number( player->GetPing( m_GHost->m_LCPings ) ) ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); player->deleteLater(); OpenSlot( GetSIDFromPID( player->GetPID( ) ), false ); @@ -3134,7 +3150,7 @@ void CBaseGame :: EventGameRefreshed( QString /*server*/ ) void CBaseGame :: EventGameStarted( ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] started loading with " + UTIL_ToString( GetNumHumanPlayers( ) ) + " players" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] started loading with " + QString::number( GetNumHumanPlayers( ) ) + " players" ); // encode the HCL command QString in the slot handicaps // here's how it works: @@ -3203,7 +3219,6 @@ void CBaseGame :: EventGameStarted( ) SendAllSlotInfo( ); m_StartedLoadingTicks = GetTicks( ); - m_LoadInGameTimer.start(); m_GameLoading = true; // since we use a fake countdown to deal with leavers during countdown the COUNTDOWN_START and COUNTDOWN_END packets are sent in quick succession @@ -3288,15 +3303,15 @@ void CBaseGame :: EventGameStarted( ) // we have to build this now because the map data is going to be deleted QByteArray StatString; - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapGameFlags( ) ); + StatString.append(m_Map->GetMapGameFlags( )); StatString.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapWidth( ) ); - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapHeight( ) ); - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapCRC( ) ); - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapPath( ).toUtf8() ); - UTIL_AppendBYTEARRAY( StatString, "GHost++" ); + StatString.append(m_Map->GetMapWidth( )); + StatString.append(m_Map->GetMapHeight( )); + StatString.append(m_Map->GetMapCRC( )); + StatString.append(m_Map->GetMapPath( ).toUtf8()); + StatString.append("GHost++"); StatString.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( StatString, m_Map->GetMapSHA1( ) ); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing + StatString.append(m_Map->GetMapSHA1( )); // note: in replays generated by Warcraft III it stores 20 zeros for the SHA1 instead of the real thing StatString = UTIL_EncodeStatString( StatString ); m_StatString = StatString; @@ -3307,6 +3322,8 @@ void CBaseGame :: EventGameStarted( ) if( m_LoadInGame ) { + m_LoadInGameTimer.start(); + // buffer all the player loaded messages // this ensures that every player receives the same set of player loaded messages in the same order, even if someone leaves during loading // if someone leaves during loading we buffer the leave message to ensure it gets sent in the correct position but the player loaded message wouldn't get sent if we didn't buffer it now @@ -3321,12 +3338,13 @@ void CBaseGame :: EventGameStarted( ) void CBaseGame :: EventGameLoaded( ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] finished loading with " + UTIL_ToString( GetNumHumanPlayers( ) ) + " players" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] finished loading with " + QString::number( GetNumHumanPlayers( ) ) + " players" ); // send shortest, longest, and personal load times to each player CGamePlayer *Shortest = NULL; CGamePlayer *Longest = NULL; + m_LoadInGameTimer.stop(); for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { @@ -3339,12 +3357,12 @@ void CBaseGame :: EventGameLoaded( ) if( Shortest && Longest ) { - SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), UTIL_ToString( (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); - SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), UTIL_ToString( (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); + SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), QString::number( 2, (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) ) ); + SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), QString::number( 2, (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) ) ); } for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( UTIL_ToString( (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 2 ) ) ); + SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( QString::number( 2, (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) ) ); // read from gameloaded.txt if available @@ -4113,7 +4131,7 @@ void CBaseGame :: BalanceSlots( ) // the cost is too high, don't run the algorithm // a possible alternative: stop after enough iterations and/or time has passed - CONSOLE_Print( "[GAME: " + m_GameName + "] shuffling slots instead of balancing - the algorithm is too slow (with a cost of " + UTIL_ToString( AlgorithmCost ) + ") for this team configuration" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] shuffling slots instead of balancing - the algorithm is too slow (with a cost of " + QString::number( AlgorithmCost ) + ") for this team configuration" ); SendAllChat( m_GHost->m_Language->ShufflingPlayers( ) ); ShuffleSlots( ); return; @@ -4162,7 +4180,7 @@ void CBaseGame :: BalanceSlots( ) } } - CONSOLE_Print( "[GAME: " + m_GameName + "] balancing slots completed in " + UTIL_ToString( EndTicks - StartTicks ) + "ms (with a cost of " + UTIL_ToString( AlgorithmCost ) + ")" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] balancing slots completed in " + QString::number( EndTicks - StartTicks ) + "ms (with a cost of " + QString::number( AlgorithmCost ) + ")" ); SendAllChat( m_GHost->m_Language->BalancingSlotsCompleted( ) ); SendAllSlotInfo( ); @@ -4188,7 +4206,7 @@ void CBaseGame :: BalanceSlots( ) } if( TeamHasPlayers ) - SendAllChat( m_GHost->m_Language->TeamCombinedScore( UTIL_ToString( i + 1 ), UTIL_ToString( TeamScore, 2 ) ) ); + SendAllChat( m_GHost->m_Language->TeamCombinedScore( QString::number( i + 1 ), QString::number( 2, TeamScore ) ) ); } } @@ -4377,7 +4395,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( GetNumHumanPlayers( ) < m_AutoStartPlayers ) { - SendAllChat( m_GHost->m_Language->WaitingForPlayersBeforeAutoStart( UTIL_ToString( m_AutoStartPlayers ), UTIL_ToString( m_AutoStartPlayers - GetNumHumanPlayers( ) ) ) ); + SendAllChat( m_GHost->m_Language->WaitingForPlayersBeforeAutoStart( QString::number( m_AutoStartPlayers ), QString::number( m_AutoStartPlayers - GetNumHumanPlayers( ) ) ) ); return; } diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index f76e363..b3a98e7 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -160,7 +160,7 @@ void CGamePlayer::EventConnectionClosed() QByteArray CPotentialPlayer :: GetExternalIP( ) { if( m_Socket ) - return UTIL_CreateBYTEARRAY((quint32)m_Socket->localAddress().toIPv4Address(), false); + return Util::fromUInt32(m_Socket->localAddress().toIPv4Address()); unsigned char Zeros[] = { 0, 0, 0, 0 }; return QByteArray( (char*)Zeros, 4 ); @@ -197,7 +197,7 @@ void CPotentialPlayer :: ExtractPackets( ) // bytes 2 and 3 contain the length of the packet - quint16 Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); + quint16 Length = Util::extractUInt16( m_Socket->peek(4), 2 ); if( Length < 4 ) { @@ -420,7 +420,7 @@ void CGamePlayer::EventSendGProxyMessage() if( TimeRemaining > ( (quint32)m_Game->GetGProxyEmptyActions() + 1 ) * 60 ) TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60; - m_Game->SendAllChat( GetPID( ), m_Game->m_GHost->m_Language->WaitForReconnectSecondsRemain( UTIL_ToString( TimeRemaining ) ) ); + m_Game->SendAllChat( GetPID( ), m_Game->m_GHost->m_Language->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } @@ -484,7 +484,7 @@ void CGamePlayer :: ExtractPackets( ) // bytes 2 and 3 contain the length of the packet - quint16 Length = UTIL_QByteArrayToUInt16( m_Socket->peek(4), false, 2 ); + quint16 Length = Util::extractUInt16( m_Socket->peek(4), 2 ); if( Length < 4 ) { @@ -652,7 +652,7 @@ void CGamePlayer :: ProcessPackets( ) } else if( Packet->GetID( ) == CGPSProtocol :: GPS_ACK && Data.size( ) == 8 ) { - int LastPacket = UTIL_QByteArrayToUInt32( Data, false, 4 ); + int LastPacket = Util::extractUInt32( Data, 4 ); int PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); if( LastPacket > PacketsAlreadyUnqueued ) diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index edd5d35..35a4540 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -63,7 +63,7 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) if( ValidateLength( data ) && data.size( ) >= 20 ) { - quint32 HostCounter = UTIL_QByteArrayToUInt32( data, false, 4 ); + quint32 HostCounter = Util::extractUInt32( data, 4 ); QByteArray Name = UTIL_ExtractCString( data, 19 ); if( !Name.isEmpty( ) && data.size( ) >= Name.size( ) + 30 ) @@ -86,7 +86,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( QByteArray data ) // 4 bytes -> Reason if( ValidateLength( data ) && data.size( ) >= 8 ) - return UTIL_QByteArrayToUInt32( data, false, 4 ); + return Util::extractUInt32( data, 4 ); return 0; } @@ -136,7 +136,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ) // 4 bytes -> CheckSum??? (used in replays) if( ValidateLength( data ) && data.size( ) == 9 ) - return UTIL_QByteArrayToUInt32( data, false, 5 ); + return Util::extractUInt32(data, 5); return 0; } @@ -224,11 +224,11 @@ bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char wa if( ValidateLength( data ) && data.size( ) >= 16 ) { - if( UTIL_QByteArrayToUInt32( data, false, 4 ) == ProductID ) + if( Util::extractUInt32(data, 4) == ProductID ) { - if( UTIL_QByteArrayToUInt32( data, false, 8 ) == Version ) + if( Util::extractUInt32(data, 8) == Version ) { - if( UTIL_QByteArrayToUInt32( data, false, 12 ) == 0 ) + if( Util::extractUInt32(data, 12) == 0 ) return true; } } @@ -249,7 +249,7 @@ CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteA // 4 bytes -> MapSize if( ValidateLength( data ) && data.size( ) >= 13 ) - return new CIncomingMapSize( data[8], UTIL_QByteArrayToUInt32( data, false, 9 ) ); + return new CIncomingMapSize( data[8], Util::extractUInt32(data, 9) ); return NULL; } @@ -267,7 +267,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) // 4 bytes -> MapSize if( ValidateLength( data ) && data.size( ) >= 14 ) - return UTIL_QByteArrayToUInt32( data, false, 10 ); + return Util::extractUInt32(data, 10); return 0; } @@ -286,7 +286,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ) // (the subtraction is done elsewhere because the very first pong value seems to be 1 and we want to discard that one) if( ValidateLength( data ) && data.size( ) >= 8 ) - return UTIL_QByteArrayToUInt32( data, false, 4 ); + return Util::extractUInt32(data, 4); return 1; } @@ -302,7 +302,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) packet.push_back( W3GS_PING_FROM_HOST ); // W3GS_PING_FROM_HOST packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, GetTicks( ), false ); // ping value + packet.append(Util::fromUInt32(GetTicks( ))); // ping value AssignLength( packet ); // DEBUG_Print( "SENT W3GS_PING_FROM_HOST" ); // DEBUG_Print( packet ); @@ -311,7 +311,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { - unsigned char Zeros[] = { 0, 0, 0, 0 }; + char Zeros[] = { 0, 0, 0, 0 }; QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; @@ -322,15 +322,15 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArra packet.push_back( W3GS_SLOTINFOJOIN ); // W3GS_SLOTINFOJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, (quint16)SlotInfo.size( ), false ); // SlotInfo length - UTIL_AppendBYTEARRAYFast( packet, SlotInfo ); // SlotInfo + packet.append(Util::fromUInt16(SlotInfo.size( ))); // SlotInfo length + packet.append(SlotInfo); // SlotInfo packet.push_back( PID ); // PID packet.push_back( 2 ); // AF_INET packet.push_back( (char)0 ); // AF_INET continued... - UTIL_AppendBYTEARRAY( packet, port ); // port - UTIL_AppendBYTEARRAYFast( packet, externalIP ); // external IP - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + packet.append(port); // port + packet.append(externalIP); // external IP + packet.append(QByteArray(Zeros, 4 )); // ??? + packet.append(QByteArray(Zeros, 4 )); // ??? AssignLength( packet ); } else @@ -350,7 +350,7 @@ QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( quint32 reason ) packet.push_back( W3GS_REJECTJOIN ); // W3GS_REJECTJOIN packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, reason, false ); // reason + packet.append(Util::fromUInt32(reason)); // reason AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REJECTJOIN" ); // DEBUG_Print( packet ); @@ -359,36 +359,37 @@ QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( quint32 reason ) QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ) { - unsigned char PlayerJoinCounter[] = { 2, 0, 0, 0 }; - unsigned char Zeros[] = { 0, 0, 0, 0 }; + char PlayerJoinCounter[] = { 2, 0, 0, 0 }; + char Zeros[] = { 0, 0, 0, 0 }; QByteArray packet; if( !name.isEmpty( ) && name.size( ) <= 15 && externalIP.size( ) == 4 && internalIP.size( ) == 4 ) { - packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant - packet.push_back( W3GS_PLAYERINFO ); // W3GS_PLAYERINFO - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, PlayerJoinCounter, 4 ); // player join counter - packet.push_back( PID ); // PID - UTIL_AppendBYTEARRAYFast( packet, name ); // player name - packet.push_back( 1 ); // ??? - packet.push_back( (char)0 ); // ??? - packet.push_back( 2 ); // AF_INET - packet.push_back( (char)0 ); // AF_INET continued... - packet.push_back( (char)0 ); // port - packet.push_back( (char)0 ); // port continued... - UTIL_AppendBYTEARRAYFast( packet, externalIP ); // external IP - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - packet.push_back( 2 ); // AF_INET - packet.push_back( (char)0 ); // AF_INET continued... - packet.push_back( (char)0 ); // port - packet.push_back( (char)0 ); // port continued... - UTIL_AppendBYTEARRAYFast( packet, internalIP ); // internal IP - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, Zeros, 4 ); // ??? + packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant + packet.push_back( W3GS_PLAYERINFO ); // W3GS_PLAYERINFO + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.append( QByteArray(PlayerJoinCounter, 4) ); // player join counter + packet.push_back( PID ); // PID + packet.append(name); // player name + packet.push_back( (char)0 ); // 0 term + packet.push_back( 1 ); // ??? + packet.push_back( (char)0 ); // ??? + packet.push_back( 2 ); // AF_INET + packet.push_back( (char)0 ); // AF_INET continued... + packet.push_back( (char)0 ); // port + packet.push_back( (char)0 ); // port continued... + packet.append(externalIP); // external IP + packet.append( QByteArray(Zeros, 4) ); // ??? + packet.append( QByteArray(Zeros, 4) ); // ??? + packet.push_back( 2 ); // AF_INET + packet.push_back( (char)0 ); // AF_INET continued... + packet.push_back( (char)0 ); // port + packet.push_back( (char)0 ); // port continued... + packet.append(internalIP); // internal IP + packet.append( QByteArray(Zeros, 4) ); // ??? + packet.append( QByteArray(Zeros, 4) ); // ??? AssignLength( packet ); } else @@ -410,7 +411,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, qui packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( PID ); // PID - UTIL_AppendBYTEARRAY( packet, leftCode, false ); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) + packet.append(Util::fromUInt32(leftCode)); // left code (see PLAYERLEAVE_ constants in gameprotocol.h) AssignLength( packet ); } else @@ -453,8 +454,8 @@ QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, quin packet.push_back( W3GS_SLOTINFO ); // W3GS_SLOTINFO packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, (quint16)SlotInfo.size( ), false ); // SlotInfo length - UTIL_AppendBYTEARRAYFast( packet, SlotInfo ); // SlotInfo + packet.append(Util::fromUInt16(SlotInfo.size( ))); // SlotInfo length + packet.append(SlotInfo); // SlotInfo AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SLOTINFO" ); // DEBUG_Print( packet ); @@ -494,7 +495,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue packet.push_back( W3GS_INCOMING_ACTION ); // W3GS_INCOMING_ACTION packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, sendInterval, false ); // send interval + packet.append(Util::fromUInt16(sendInterval)); // send interval // create subpacket @@ -507,19 +508,19 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue CIncomingAction *Action = actions.dequeue( ); subpacket.push_back( Action->GetPID( ) ); - UTIL_AppendBYTEARRAY( subpacket, (quint16)Action->GetAction( )->size( ), false ); - UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); + subpacket.append(Util::fromUInt16(Action->GetAction( )->size( ))); + subpacket.append(*Action->GetAction( )); } // calculate crc (we only care about the first 2 bytes though) - QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC( subpacket ), false ); + QByteArray crc32 = Util::fromUInt32(m_GHost->m_CRC->FullCRC( subpacket )); crc32.resize( 2 ); // finish subpacket - UTIL_AppendBYTEARRAYFast( packet, crc32 ); // crc - UTIL_AppendBYTEARRAYFast( packet, subpacket ); // subpacket + packet.append(crc32); // crc + packet.append(subpacket); // subpacket } AssignLength( packet ); @@ -536,14 +537,15 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_CHAT_FROM_HOST ); // W3GS_CHAT_FROM_HOST - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( toPIDs.size( ) ); // number of receivers - UTIL_AppendBYTEARRAYFast( packet, toPIDs ); // receivers + packet.append(toPIDs); // receivers packet.push_back( fromPID ); // sender packet.push_back( flag ); // flag - UTIL_AppendBYTEARRAYFast( packet, flagExtra ); // extra flag - UTIL_AppendBYTEARRAYFast( packet, message ); // message + packet.append(flagExtra); // extra flag + packet.append(message); // message + packet.push_back( (char)0 ); // ??? AssignLength( packet ); } else @@ -589,7 +591,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, if( !(*i)->GetFinishedLoading( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendBYTEARRAY( packet, (quint32)0, false ); + packet.append(Util::fromUInt32(0)); } } else @@ -597,7 +599,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, if( (*i)->GetLagging( ) ) { packet.push_back( (*i)->GetPID( ) ); - UTIL_AppendBYTEARRAY( packet, GetTicks( ) - (*i)->GetStartedLaggingTicks( ), false ); + packet.append(Util::fromUInt32(GetTicks( ) - (*i)->GetStartedLaggingTicks( ))); } } } @@ -622,9 +624,9 @@ QByteArray CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadIn packet.push_back( player->GetPID( ) ); if( loadInGame ) - UTIL_AppendBYTEARRAY( packet, (quint32)0, false ); + packet.append(Util::fromUInt32(0)); else - UTIL_AppendBYTEARRAY( packet, GetTicks( ) - player->GetStartedLaggingTicks( ), false ); + packet.append(Util::fromUInt32(GetTicks( ) - player->GetStartedLaggingTicks( ))); AssignLength( packet ); // DEBUG_Print( "SENT W3GS_STOP_LAG" ); @@ -634,10 +636,10 @@ QByteArray CGameProtocol :: SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadIn QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ) { - unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" - unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" - unsigned char Version[] = { war3Version, 0, 0, 0 }; - unsigned char Unknown[] = { 0, 0, 0, 0 }; + char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" + char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" + char Version[] = { war3Version, 0, 0, 0 }; + char Unknown[] = { 0, 0, 0, 0 }; QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -646,12 +648,12 @@ QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Ve packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) + packet.append(QByteArray(ProductID_TFT, 4)); // Product ID (TFT) else - UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) + packet.append(QByteArray(ProductID_ROC, 4)); // Product ID (ROC) - UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version - UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? + packet.append(QByteArray(Version, 4)); // Version + packet.append(QByteArray(Unknown, 4)); // ??? AssignLength( packet ); // DEBUG_Print( "SENT W3GS_SEARCHGAME" ); // DEBUG_Print( packet ); @@ -660,11 +662,11 @@ QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Ve QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ) { - unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" - unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" - unsigned char Version[] = { war3Version, 0, 0, 0 }; - unsigned char Unknown1[] = { 1, 2, 3, 4 }; - unsigned char Unknown2[] = { 1, 0, 0, 0 }; + char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" + char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" + char Version[] = { war3Version, 0, 0, 0 }; + char Unknown1[] = { 1, 2, 3, 4 }; + char Unknown2[] = { 1, 0, 0, 0 }; QByteArray packet; @@ -673,13 +675,15 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers // make the stat QString QByteArray StatString; - UTIL_AppendBYTEARRAYFast( StatString, mapFlags ); + StatString.append(mapFlags); + StatString.push_back( (char)0 ); + StatString.append(mapWidth); + StatString.append(mapHeight); + StatString.append(mapCRC); + StatString.append(mapPath); + StatString.push_back( (char)0 ); + StatString.append(hostName); StatString.push_back( (char)0 ); - UTIL_AppendBYTEARRAYFast( StatString, mapWidth ); - UTIL_AppendBYTEARRAYFast( StatString, mapHeight ); - UTIL_AppendBYTEARRAYFast( StatString, mapCRC ); - UTIL_AppendBYTEARRAYFast( StatString, mapPath ); - UTIL_AppendBYTEARRAYFast( StatString, hostName ); StatString.push_back( (char)0 ); StatString = UTIL_EncodeStatString( StatString ); @@ -691,23 +695,24 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) + packet.append(QByteArray(ProductID_TFT, 4)); // Product ID (TFT) else - UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) + packet.append(QByteArray(ProductID_ROC, 4)); // Product ID (ROC) - UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version - UTIL_AppendBYTEARRAY( packet, hostCounter, false ); // Host Counter - UTIL_AppendBYTEARRAY( packet, Unknown1, 4 ); // ??? (this varies wildly even between two identical games created one after another) - UTIL_AppendBYTEARRAYFast( packet, gameName ); // Game Name + packet.append(QByteArray(Version, 4)); // Version + packet.append(Util::fromUInt32(hostCounter)); // Host Counter + packet.append(QByteArray(Unknown1, 4)); // ??? (this varies wildly even between two identical games created one after another) + packet.append(gameName); // Game Name + packet.push_back( (char)0 ); // 0term for gamename packet.push_back( (char)0 ); // ??? (maybe game password) - UTIL_AppendBYTEARRAYFast( packet, StatString ); // Stat String + packet.append(StatString); // Stat String packet.push_back( (char)0 ); // Stat String null terminator (the stat QString is encoded to remove all even numbers i.e. zeros) - UTIL_AppendBYTEARRAY( packet, slotsTotal, false ); // Slots Total - UTIL_AppendBYTEARRAYFast( packet, mapGameType ); // Game Type - UTIL_AppendBYTEARRAY( packet, Unknown2, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, slotsOpen, false ); // Slots Open - UTIL_AppendBYTEARRAY( packet, upTime, false ); // time since creation - UTIL_AppendBYTEARRAY( packet, port, false ); // port + packet.append(Util::fromUInt32(slotsTotal)); // Slots Total + packet.append(mapGameType); // Game Type + packet.append(QByteArray(Unknown2, 4)); // ??? + packet.append(Util::fromUInt32(slotsOpen)); // Slots Open + packet.append(Util::fromUInt32(upTime)); // time since creation + packet.append(Util::fromUInt16(port)); // port AssignLength( packet ); } else @@ -720,10 +725,10 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Vers QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ) { - unsigned char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" - unsigned char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" - unsigned char Version[] = { war3Version, 0, 0, 0 }; - unsigned char HostCounter[] = { 1, 0, 0, 0 }; + char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" + char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" + char Version[] = { war3Version, 0, 0, 0 }; + char HostCounter[] = { 1, 0, 0, 0 }; QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -732,12 +737,12 @@ QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Ve packet.push_back( (char)0 ); // packet length will be assigned later if( TFT ) - UTIL_AppendBYTEARRAY( packet, ProductID_TFT, 4 ); // Product ID (TFT) + packet.append(QByteArray(ProductID_TFT, 4)); // Product ID (TFT) else - UTIL_AppendBYTEARRAY( packet, ProductID_ROC, 4 ); // Product ID (ROC) + packet.append(QByteArray(ProductID_ROC, 4)); // Product ID (ROC) - UTIL_AppendBYTEARRAY( packet, Version, 4 ); // Version - UTIL_AppendBYTEARRAY( packet, HostCounter, 4 ); // Host Counter + packet.append(QByteArray(Version, 4)); // Version + packet.append(QByteArray(HostCounter, 4)); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_CREATEGAME" ); // DEBUG_Print( packet ); @@ -746,16 +751,16 @@ QByteArray CGameProtocol :: SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Ve QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( quint32 players, quint32 playerSlots ) { - unsigned char HostCounter[] = { 1, 0, 0, 0 }; + char HostCounter[] = { 1, 0, 0, 0 }; QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_REFRESHGAME ); // W3GS_REFRESHGAME packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, HostCounter, 4 ); // Host Counter - UTIL_AppendBYTEARRAY( packet, players, false ); // Players - UTIL_AppendBYTEARRAY( packet, playerSlots, false ); // Player Slots + packet.append(QByteArray(HostCounter, 4)); // Host Counter + packet.append(Util::fromUInt32(players)); // Players + packet.append(Util::fromUInt32(playerSlots)); // Player Slots AssignLength( packet ); // DEBUG_Print( "SENT W3GS_REFRESHGAME" ); // DEBUG_Print( packet ); @@ -764,14 +769,14 @@ QByteArray CGameProtocol :: SEND_W3GS_REFRESHGAME( quint32 players, quint32 play QByteArray CGameProtocol :: SEND_W3GS_DECREATEGAME( ) { - unsigned char HostCounter[] = { 1, 0, 0, 0 }; + char HostCounter[] = { 1, 0, 0, 0 }; QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_DECREATEGAME ); // W3GS_DECREATEGAME packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, HostCounter, 4 ); // Host Counter + packet.append(QByteArray(HostCounter, 4)); // Host Counter AssignLength( packet ); // DEBUG_Print( "SENT W3GS_DECREATEGAME" ); // DEBUG_Print( packet ); @@ -780,7 +785,7 @@ QByteArray CGameProtocol :: SEND_W3GS_DECREATEGAME( ) QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ) { - unsigned char Unknown[] = { 1, 0, 0, 0 }; + char Unknown[] = { 1, 0, 0, 0 }; QByteArray packet; @@ -788,14 +793,15 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapS { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_MAPCHECK ); // W3GS_MAPCHECK - packet.push_back( (char)0 ); // packet length will be assigned later - packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? - UTIL_AppendBYTEARRAYFast( packet, mapPath ); // map path - UTIL_AppendBYTEARRAYFast( packet, mapSize ); // map size - UTIL_AppendBYTEARRAYFast( packet, mapInfo ); // map info - UTIL_AppendBYTEARRAYFast( packet, mapCRC ); // map crc - UTIL_AppendBYTEARRAYFast( packet, mapSHA1 ); // map sha1 + packet.push_back( (char)0 ); // packet length will be assigned later + packet.push_back( (char)0 ); // packet length will be assigned later + packet.append(QByteArray(Unknown, 4)); // ??? + packet.append(mapPath); // map path + packet.push_back( (char)0 ); // 0 term + packet.append(mapSize); // map size + packet.append(mapInfo); // map info + packet.append(mapCRC); // map crc + packet.append(mapSHA1); // map sha1 AssignLength( packet ); } else @@ -808,14 +814,14 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapS QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) { - unsigned char Unknown[] = { 1, 0, 0, 0 }; + char Unknown[] = { 1, 0, 0, 0 }; QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_STARTDOWNLOAD ); // W3GS_STARTDOWNLOAD packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( (char)0 ); // packet length will be assigned later - UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? + packet.append(QByteArray(Unknown, 4)); // ??? packet.push_back( fromPID ); // from PID AssignLength( packet ); // DEBUG_Print( "SENT W3GS_STARTDOWNLOAD" ); @@ -825,7 +831,7 @@ QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QByteArray *mapData ) { - unsigned char Unknown[] = { 1, 0, 0, 0 }; + char Unknown[] = { 1, 0, 0, 0 }; QByteArray packet; @@ -837,8 +843,8 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( toPID ); // to PID packet.push_back( fromPID ); // from PID - UTIL_AppendBYTEARRAY( packet, Unknown, 4 ); // ??? - UTIL_AppendBYTEARRAY( packet, start, false ); // start position + packet.append(QByteArray(Unknown, 4)); // ??? + packet.append(Util::fromUInt32(start)); // start position // calculate end position (don't send more than 1442 map bytes in one packet) @@ -849,8 +855,8 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c // calculate crc - QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC( mapData->mid(start, End - start) ), false ); - UTIL_AppendBYTEARRAYFast( packet, crc32 ); + QByteArray crc32 = Util::fromUInt32( m_GHost->m_CRC->FullCRC( mapData->mid(start, End - start) ) ); + packet.append(crc32); // map data @@ -886,19 +892,19 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueueGetPID( ) ); - UTIL_AppendBYTEARRAY( subpacket, (quint16)Action->GetAction( )->size( ), false ); - UTIL_AppendBYTEARRAYFast( subpacket, *Action->GetAction( ) ); + subpacket.append(Util::fromUInt16(Action->GetAction( )->size( ))); + subpacket.append(*Action->GetAction( )); } // calculate crc (we only care about the first 2 bytes though) - QByteArray crc32 = UTIL_CreateBYTEARRAY( m_GHost->m_CRC->FullCRC(subpacket), false ); + QByteArray crc32 = Util::fromUInt32( m_GHost->m_CRC->FullCRC(subpacket) ); crc32.resize( 2 ); // finish subpacket - UTIL_AppendBYTEARRAYFast( packet, crc32 ); // crc - UTIL_AppendBYTEARRAYFast( packet, subpacket ); // subpacket + packet.append(crc32); // crc + packet.append(subpacket); // subpacket } AssignLength( packet ); @@ -919,7 +925,7 @@ bool CGameProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); + LengthBytes = Util::fromUInt16( content.size( ) ); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -939,7 +945,7 @@ bool CGameProtocol :: ValidateLength( QByteArray &content ) { LengthBytes.push_back( content[2] ); LengthBytes.push_back( content[3] ); - Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); + Length = Util::extractUInt16( LengthBytes ); if( Length == content.size( ) ) return true; @@ -954,9 +960,9 @@ QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, quint32 SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots for( int i = 0; i < lslots.size( ); i++ ) - UTIL_AppendBYTEARRAY( SlotInfo, lslots[i].GetQByteArray( ) ); + SlotInfo.append(lslots[i].GetQByteArray( )); - UTIL_AppendBYTEARRAY( SlotInfo, randomSeed, false ); // random seed + SlotInfo.append(Util::fromUInt32(randomSeed)); // random seed SlotInfo.push_back( layoutStyle ); // LayoutStyle (0 = melee, 1 = custom forces, 3 = custom forces + fixed player settings) SlotInfo.push_back( playerSlots ); // number of player slots (non observer) return SlotInfo; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index b980169..8d8087a 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -52,6 +52,7 @@ #include #include +#include // @@ -127,8 +128,8 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) for (int i = 0; i < info.addresses().size(); i++) { - CONSOLE_Print( "[GHOST] local IP address #" + UTIL_ToString( i + 1 ) + " is [" + info.addresses().at(i).toString() + "]" ); - m_LocalAddresses.push_back( UTIL_CreateBYTEARRAY( (quint32)info.addresses().at(i).toIPv4Address(), false ) ); + CONSOLE_Print( "[GHOST] local IP address #" + QString::number( i + 1 ) + " is [" + info.addresses().at(i).toString() + "]" ); + m_LocalAddresses.push_back( Util::fromUInt32(info.addresses().at(i).toIPv4Address() ) ); } m_Language = NULL; @@ -179,7 +180,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) if( i == 1 ) Prefix = "bnet_"; else - Prefix = "bnet" + UTIL_ToString( i ) + "_"; + Prefix = "bnet" + QString::number( i ) + "_"; QString Server = CFG->GetString( Prefix + "server", QString( ) ); QString ServerAlias = CFG->GetString( Prefix + "serveralias", QString( ) ); @@ -199,7 +200,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) #endif } else - LocaleID = UTIL_ToUInt32( Locale ); + LocaleID = Locale.toUInt(); QString UserName = CFG->GetString( Prefix + "username", QString( ) ); QString UserPassword = CFG->GetString( Prefix + "password", QString( ) ); @@ -250,12 +251,12 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) continue; } - CONSOLE_Print( "[GHOST] found battle.net connection #" + UTIL_ToString( i ) + " for server [" + Server + "]" ); + CONSOLE_Print( "[GHOST] found battle.net connection #" + QString::number( i ) + " for server [" + Server + "]" ); if( Locale == "system" ) { #ifdef WIN32 - CONSOLE_Print( "[GHOST] using system locale of " + UTIL_ToString( LocaleID ) ); + CONSOLE_Print( "[GHOST] using system locale of " + QString::number( LocaleID ) ); #else CONSOLE_Print( "[GHOST] unable to get system locale, using default locale of 1033" ); #endif @@ -381,13 +382,15 @@ CGHost :: ~CGHost( ) // but if you try to recreate the CGHost object within a single session you will probably leak resources! if( !m_Callables.isEmpty( ) ) - CONSOLE_Print( "[GHOST] warning - " + UTIL_ToString( m_Callables.size( ) ) + " orphaned callables were leaked (this is not an error)" ); + CONSOLE_Print( "[GHOST] warning - " + QString::number( m_Callables.size( ) ) + " orphaned callables were leaked (this is not an error)" ); delete m_Language; delete m_Map; delete m_AdminMap; delete m_AutoHostMap; delete m_SaveGame; + + DEBUG_Print("[GHOST] good bye"); } void CGHost::EventGameStarted() @@ -429,7 +432,7 @@ void CGHost::EventReconnectionSocketReadyRead() { // bytes 2 and 3 contain the length of the packet - quint16 Length = UTIL_QByteArrayToUInt16( con->peek(4), false, 2 ); + quint16 Length = Util::extractUInt16( con->peek(4), 2 ); if( Length < 4 ) { @@ -445,8 +448,8 @@ void CGHost::EventReconnectionSocketReadyRead() if( Bytes.at(0) == CGPSProtocol :: GPS_RECONNECT && Length == 13 ) { unsigned char PID = Bytes.at(4); - quint32 ReconnectKey = UTIL_QByteArrayToUInt32( Bytes, false, 5 ); - quint32 LastPacket = UTIL_QByteArrayToUInt32( Bytes, false, 9 ); + quint32 ReconnectKey = Util::extractUInt32( Bytes, 5 ); + quint32 LastPacket = Util::extractUInt32( Bytes, 9 ); // look for a matching player in a running game @@ -550,7 +553,7 @@ void CGHost::EventExitNice() if( !m_AllGamesFinished && m_Callables.size( ) > 0 ) { CONSOLE_Print( "[GHOST] all games finished, waiting 60 seconds for threads to finish" ); - CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads in progress" ); + CONSOLE_Print( "[GHOST] there are " + QString::number( m_Callables.size( ) ) + " threads in progress" ); m_AllGamesFinished = true; m_AllGamesFinishedTime = GetTime( ); QTimer::singleShot(60000, this, SLOT(EventWaitForNiceExitTimeout())); @@ -559,6 +562,7 @@ void CGHost::EventExitNice() { CONSOLE_Print( "[GHOST] all threads finished, exiting nicely" ); deleteLater(); + QCoreApplication::instance()->quit(); return; } } @@ -570,7 +574,7 @@ void CGHost::EventExitNice() void CGHost::EventWaitForNiceExitTimeout() { CONSOLE_Print( "[GHOST] waited 60 seconds for threads to finish, exiting anyway" ); - CONSOLE_Print( "[GHOST] there are " + UTIL_ToString( m_Callables.size( ) ) + " threads still in progress which will be terminated" ); + CONSOLE_Print( "[GHOST] there are " + QString::number( m_Callables.size( ) ) + " threads still in progress which will be terminated" ); deleteLater(); } @@ -609,7 +613,7 @@ void CGHost::EventAutoHost() return; } - QString GameName = m_AutoHostGameName + " #" + UTIL_ToString( m_HostCounter ); + QString GameName = m_AutoHostGameName + " #" + QString::number( m_HostCounter ); if( GameName.size( ) >= 31 ) { @@ -664,10 +668,10 @@ void CGHost::CreateReconnectServer() QObject::connect(m_ReconnectSocket, SIGNAL(newConnection()), this, SLOT(EventIncomingReconnection())); if( m_ReconnectSocket->listen( QHostAddress(m_BindAddress), m_ReconnectPort ) ) - CONSOLE_Print( "[GHOST] listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); + CONSOLE_Print( "[GHOST] listening for GProxy++ reconnects on port " + QString::number( m_ReconnectPort ) ); else { - CONSOLE_Print( "[GHOST] error listening for GProxy++ reconnects on port " + UTIL_ToString( m_ReconnectPort ) ); + CONSOLE_Print( "[GHOST] error listening for GProxy++ reconnects on port " + QString::number( m_ReconnectPort ) ); delete m_ReconnectSocket; m_ReconnectSocket = NULL; m_Reconnect = false; @@ -962,7 +966,7 @@ void CGHost :: ExtractScripts( ) SFileCloseArchive( PatchMPQ ); } else - CONSOLE_Print( "[GHOST] warning - unable to load MPQ file [" + PatchMPQFileName + "] - error code " + UTIL_ToString( GetLastError( ) ) ); + CONSOLE_Print( "[GHOST] warning - unable to load MPQ file [" + PatchMPQFileName + "] - error code " + QString::number( GetLastError( ) ) ); } void CGHost :: LoadIPToCountryData( ) @@ -1007,7 +1011,7 @@ void CGHost :: LoadIPToCountryData( ) parser >> IP1; parser >> IP2; parser >> Country; - m_DBLocal->FromAdd( UTIL_ToUInt32( IP1 ), UTIL_ToUInt32( IP2 ), Country ); + m_DBLocal->FromAdd( IP1.toUInt(), IP2.toUInt(), Country ); // it's probably going to take awhile to load the iptocountry data (~10 seconds on my 3.2 GHz P4 when using SQLite3) // so let's print a progress meter just to keep the user from getting worried @@ -1017,7 +1021,7 @@ void CGHost :: LoadIPToCountryData( ) if( NewPercent != Percent && NewPercent % 10 == 0 ) { Percent = NewPercent; - CONSOLE_Print( "[GHOST] iptocountry data: " + UTIL_ToString( Percent ) + "% loaded" ); + CONSOLE_Print( "[GHOST] iptocountry data: " + QString::number( Percent ) + "% loaded" ); } } @@ -1145,11 +1149,11 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) - (*i)->QueueChatCommand( m_Language->UnableToCreateGameMaxGamesReached( gameName, UTIL_ToString( m_MaxGames ) ), creatorName, whisper ); + (*i)->QueueChatCommand( m_Language->UnableToCreateGameMaxGamesReached( gameName, QString::number( m_MaxGames ) ), creatorName, whisper ); } if( m_AdminGame ) - m_AdminGame->SendAllChat( m_Language->UnableToCreateGameMaxGamesReached( gameName, UTIL_ToString( m_MaxGames ) ) ); + m_AdminGame->SendAllChat( m_Language->UnableToCreateGameMaxGamesReached( gameName, QString::number( m_MaxGames ) ) ); return; } diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index 8f89b2e..fb6dd6e 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -306,7 +306,7 @@ CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap< return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_strings*/ ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_strings*/ ) { return NULL; } diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index e865199..74ec111 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -57,7 +57,7 @@ class CConfig; #include "includes.h" #include -typedef QPair VarP; +typedef QPair VarP; class CGHostDB : public QObject { @@ -139,7 +139,7 @@ class CGHostDB : public QObject virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); }; // diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index dad8b61..b479140 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -891,12 +891,12 @@ quint32 CGHostDBSQLite :: GameAdd( QString server, QString map, QString gamename if( RC == SQLITE_DONE ) RowID = m_DB->LastRowID( ); else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding game [" + server + " : " + map + " : " + gamename + " : " + ownername + " : " + UTIL_ToString( duration ) + " : " + UTIL_ToString( gamestate ) + " : " + creatorname + " : " + creatorserver + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding game [" + server + " : " + map + " : " + gamename + " : " + ownername + " : " + QString::number( duration ) + " : " + QString::number( gamestate ) + " : " + creatorname + " : " + creatorserver + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding game [" + server + " : " + map + " : " + gamename + " : " + ownername + " : " + UTIL_ToString( duration ) + " : " + UTIL_ToString( gamestate ) + " : " + creatorname + " : " + creatorserver + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding game [" + server + " : " + map + " : " + gamename + " : " + ownername + " : " + QString::number( duration ) + " : " + QString::number( gamestate ) + " : " + creatorname + " : " + creatorserver + "] - " + m_DB->GetError( ) ); return RowID; } @@ -927,12 +927,12 @@ quint32 CGHostDBSQLite :: GamePlayerAdd( quint32 gameid, QString name, QString i if( RC == SQLITE_DONE ) RowID = m_DB->LastRowID( ); else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding gameplayer [" + UTIL_ToString( gameid ) + " : " + name + " : " + ip + " : " + UTIL_ToString( spoofed ) + " : " + spoofedrealm + " : " + UTIL_ToString( reserved ) + " : " + UTIL_ToString( loadingtime ) + " : " + UTIL_ToString( left ) + " : " + leftreason + " : " + UTIL_ToString( team ) + " : " + UTIL_ToString( colour ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding gameplayer [" + QString::number( gameid ) + " : " + name + " : " + ip + " : " + QString::number( spoofed ) + " : " + spoofedrealm + " : " + QString::number( reserved ) + " : " + QString::number( loadingtime ) + " : " + QString::number( left ) + " : " + leftreason + " : " + QString::number( team ) + " : " + QString::number( colour ) + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding gameplayer [" + UTIL_ToString( gameid ) + " : " + name + " : " + ip + " : " + UTIL_ToString( spoofed ) + " : " + spoofedrealm + " : " + UTIL_ToString( reserved ) + " : " + UTIL_ToString( loadingtime ) + " : " + UTIL_ToString( left ) + " : " + leftreason + " : " + UTIL_ToString( team ) + " : " + UTIL_ToString( colour ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding gameplayer [" + QString::number( gameid ) + " : " + name + " : " + ip + " : " + QString::number( spoofed ) + " : " + spoofedrealm + " : " + QString::number( reserved ) + " : " + QString::number( loadingtime ) + " : " + QString::number( left ) + " : " + leftreason + " : " + QString::number( team ) + " : " + QString::number( colour ) + "] - " + m_DB->GetError( ) ); return RowID; } @@ -1036,12 +1036,12 @@ quint32 CGHostDBSQLite :: DotAGameAdd( quint32 gameid, quint32 winner, quint32 m if( RC == SQLITE_DONE ) RowID = m_DB->LastRowID( ); else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding dotagame [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( winner ) + " : " + UTIL_ToString( min ) + " : " + UTIL_ToString( sec ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding dotagame [" + QString::number( gameid ) + " : " + QString::number( winner ) + " : " + QString::number( min ) + " : " + QString::number( sec ) + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding dotagame [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( winner ) + " : " + UTIL_ToString( min ) + " : " + UTIL_ToString( sec ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding dotagame [" + QString::number( gameid ) + " : " + QString::number( winner ) + " : " + QString::number( min ) + " : " + QString::number( sec ) + "] - " + m_DB->GetError( ) ); return RowID; } @@ -1080,12 +1080,12 @@ quint32 CGHostDBSQLite :: DotAPlayerAdd( quint32 gameid, quint32 colour, quint32 if( RC == SQLITE_DONE ) RowID = m_DB->LastRowID( ); else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding dotaplayer [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( colour ) + " : " + UTIL_ToString( kills ) + " : " + UTIL_ToString( deaths ) + " : " + UTIL_ToString( creepkills ) + " : " + UTIL_ToString( creepdenies ) + " : " + UTIL_ToString( assists ) + " : " + UTIL_ToString( gold ) + " : " + UTIL_ToString( neutralkills ) + " : " + item1 + " : " + item2 + " : " + item3 + " : " + item4 + " : " + item5 + " : " + item6 + " : " + hero + " : " + UTIL_ToString( newcolour ) + " : " + UTIL_ToString( towerkills ) + " : " + UTIL_ToString( raxkills ) + " : " + UTIL_ToString( courierkills ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding dotaplayer [" + QString::number( gameid ) + " : " + QString::number( colour ) + " : " + QString::number( kills ) + " : " + QString::number( deaths ) + " : " + QString::number( creepkills ) + " : " + QString::number( creepdenies ) + " : " + QString::number( assists ) + " : " + QString::number( gold ) + " : " + QString::number( neutralkills ) + " : " + item1 + " : " + item2 + " : " + item3 + " : " + item4 + " : " + item5 + " : " + item6 + " : " + hero + " : " + QString::number( newcolour ) + " : " + QString::number( towerkills ) + " : " + QString::number( raxkills ) + " : " + QString::number( courierkills ) + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding dotaplayer [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( colour ) + " : " + UTIL_ToString( kills ) + " : " + UTIL_ToString( deaths ) + " : " + UTIL_ToString( creepkills ) + " : " + UTIL_ToString( creepdenies ) + " : " + UTIL_ToString( assists ) + " : " + UTIL_ToString( gold ) + " : " + UTIL_ToString( neutralkills ) + " : " + item1 + " : " + item2 + " : " + item3 + " : " + item4 + " : " + item5 + " : " + item6 + " : " + hero + " : " + UTIL_ToString( newcolour ) + " : " + UTIL_ToString( towerkills ) + " : " + UTIL_ToString( raxkills ) + " : " + UTIL_ToString( courierkills ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding dotaplayer [" + QString::number( gameid ) + " : " + QString::number( colour ) + " : " + QString::number( kills ) + " : " + QString::number( deaths ) + " : " + QString::number( creepkills ) + " : " + QString::number( creepdenies ) + " : " + QString::number( assists ) + " : " + QString::number( gold ) + " : " + QString::number( neutralkills ) + " : " + item1 + " : " + item2 + " : " + item3 + " : " + item4 + " : " + item5 + " : " + item6 + " : " + hero + " : " + QString::number( newcolour ) + " : " + QString::number( towerkills ) + " : " + QString::number( raxkills ) + " : " + QString::number( courierkills ) + "] - " + m_DB->GetError( ) ); return RowID; } @@ -1228,15 +1228,15 @@ QString CGHostDBSQLite :: FromCheck( quint32 ip ) if( Row->size( ) == 1 ) From = (*Row)[0]; else - CONSOLE_Print( "[SQLITE3] error checking iptocountry [" + UTIL_ToString( ip ) + "] - row doesn't have 1 column" ); + CONSOLE_Print( "[SQLITE3] error checking iptocountry [" + QString::number( ip ) + "] - row doesn't have 1 column" ); } else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error checking iptocountry [" + UTIL_ToString( ip ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error checking iptocountry [" + QString::number( ip ) + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error checking iptocountry [" + UTIL_ToString( ip ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error checking iptocountry [" + QString::number( ip ) + "] - " + m_DB->GetError( ) ); return From; } @@ -1263,12 +1263,12 @@ bool CGHostDBSQLite :: FromAdd( quint32 ip1, quint32 ip2, QString country ) if( RC == SQLITE_DONE ) Success = true; else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding iptocountry [" + UTIL_ToString( ip1 ) + " : " + UTIL_ToString( ip2 ) + " : " + country + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding iptocountry [" + QString::number( ip1 ) + " : " + QString::number( ip2 ) + " : " + country + "] - " + m_DB->GetError( ) ); m_DB->Reset( FromAddStmt ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding iptocountry [" + UTIL_ToString( ip1 ) + " : " + UTIL_ToString( ip2 ) + " : " + country + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding iptocountry [" + QString::number( ip1 ) + " : " + QString::number( ip2 ) + " : " + country + "] - " + m_DB->GetError( ) ); return Success; } @@ -1294,12 +1294,12 @@ bool CGHostDBSQLite :: DownloadAdd( QString map, quint32 mapsize, QString name, if( RC == SQLITE_DONE ) Success = true; else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding download [" + map + " : " + UTIL_ToString( mapsize ) + " : " + name + " : " + ip + " : " + UTIL_ToString( spoofed ) + " : " + spoofedrealm + " : " + UTIL_ToString( downloadtime ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding download [" + map + " : " + QString::number( mapsize ) + " : " + name + " : " + ip + " : " + QString::number( spoofed ) + " : " + spoofedrealm + " : " + QString::number( downloadtime ) + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding download [" + map + " : " + UTIL_ToString( mapsize ) + " : " + name + " : " + ip + " : " + UTIL_ToString( spoofed ) + " : " + spoofedrealm + " : " + UTIL_ToString( downloadtime ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding download [" + map + " : " + QString::number( mapsize ) + " : " + name + " : " + ip + " : " + QString::number( spoofed ) + " : " + spoofedrealm + " : " + QString::number( downloadtime ) + "] - " + m_DB->GetError( ) ); return Success; } @@ -1325,12 +1325,12 @@ quint32 CGHostDBSQLite :: W3MMDPlayerAdd( QString category, quint32 gameid, quin if( RC == SQLITE_DONE ) RowID = m_DB->LastRowID( ); else if( RC == SQLITE_ERROR ) - CONSOLE_Print( "[SQLITE3] error adding w3mmdplayer [" + category + " : " + UTIL_ToString( gameid ) + " : " + UTIL_ToString( pid ) + " : " + name + " : " + flag + " : " + UTIL_ToString( leaver ) + " : " + UTIL_ToString( practicing ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdplayer [" + category + " : " + QString::number( gameid ) + " : " + QString::number( pid ) + " : " + name + " : " + flag + " : " + QString::number( leaver ) + " : " + QString::number( practicing ) + "] - " + m_DB->GetError( ) ); m_DB->Finalize( Statement ); } else - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdplayer [" + category + " : " + UTIL_ToString( gameid ) + " : " + UTIL_ToString( pid ) + " : " + name + " : " + flag + " : " + UTIL_ToString( leaver ) + " : " + UTIL_ToString( practicing ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdplayer [" + category + " : " + QString::number( gameid ) + " : " + QString::number( pid ) + " : " + name + " : " + flag + " : " + QString::number( leaver ) + " : " + QString::number( practicing ) + "] - " + m_DB->GetError( ) ); return RowID; } @@ -1360,7 +1360,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-int [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value() ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-int [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( i.value() ) + "] - " + m_DB->GetError( ) ); break; } @@ -1369,7 +1369,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-int [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value() ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-int [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( i.value() ) + "] - " + m_DB->GetError( ) ); break; } } @@ -1405,7 +1405,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_reals if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-real [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value(), 10 ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-real [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( 10, i.value() ) + "] - " + m_DB->GetError( ) ); break; } @@ -1414,7 +1414,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_reals else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-real [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + UTIL_ToString( i.value(), 10 ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-real [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( 10, i.value() ) + "] - " + m_DB->GetError( ) ); break; } } @@ -1450,7 +1450,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_strin if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + i.value() + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-QString [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + i.value() + "] - " + m_DB->GetError( ) ); break; } @@ -1459,7 +1459,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_strin else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-QString [" + UTIL_ToString( gameid ) + " : " + UTIL_ToString( i.key().first ) + " : " + i.key().second + " : " + i.value() + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-QString [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + i.value() + "] - " + m_DB->GetError( ) ); break; } } diff --git a/ghost/gpsprotocol.cpp b/ghost/gpsprotocol.cpp index 8bba5cd..929ac89 100644 --- a/ghost/gpsprotocol.cpp +++ b/ghost/gpsprotocol.cpp @@ -49,7 +49,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_INIT( quint32 version ) packet.push_back( GPS_INIT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( packet, version, false ); + packet.append(Util::fromUInt32(version)); AssignLength( packet ); return packet; } @@ -62,8 +62,8 @@ QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, quint32 recon packet.push_back( (char)0 ); packet.push_back( (char)0 ); packet.push_back( PID ); - UTIL_AppendBYTEARRAY( packet, reconnectKey, false ); - UTIL_AppendBYTEARRAY( packet, lastPacket, false ); + packet.append(Util::fromUInt32(reconnectKey)); + packet.append(Util::fromUInt32(lastPacket)); AssignLength( packet ); return packet; } @@ -75,7 +75,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_ACK( quint32 lastPacket ) packet.push_back( GPS_ACK ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( packet, lastPacket, false ); + packet.append(Util::fromUInt32(lastPacket)); AssignLength( packet ); return packet; } @@ -87,9 +87,9 @@ QByteArray CGPSProtocol :: SEND_GPSS_INIT( quint16 reconnectPort, unsigned char packet.push_back( GPS_INIT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( packet, reconnectPort, false ); + packet.append(Util::fromUInt16(reconnectPort)); packet.push_back( PID ); - UTIL_AppendBYTEARRAY( packet, reconnectKey, false ); + packet.append(Util::fromUInt32(reconnectKey)); packet.push_back( numEmptyActions ); AssignLength( packet ); return packet; @@ -102,7 +102,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( quint32 lastPacket ) packet.push_back( GPS_RECONNECT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( packet, lastPacket, false ); + packet.append(Util::fromUInt32(lastPacket)); AssignLength( packet ); return packet; } @@ -114,7 +114,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_ACK( quint32 lastPacket ) packet.push_back( GPS_ACK ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( packet, lastPacket, false ); + packet.append(Util::fromUInt32(lastPacket)); AssignLength( packet ); return packet; } @@ -126,7 +126,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_REJECT( quint32 reason ) packet.push_back( GPS_REJECT ); packet.push_back( (char)0 ); packet.push_back( (char)0 ); - UTIL_AppendBYTEARRAY( packet, reason, false ); + packet.append(Util::fromUInt32(reason)); AssignLength( packet ); return packet; } @@ -143,7 +143,7 @@ bool CGPSProtocol :: AssignLength( QByteArray &content ) if( content.size( ) >= 4 && content.size( ) <= 65535 ) { - LengthBytes = UTIL_CreateBYTEARRAY( (quint16)content.size( ), false ); + LengthBytes = Util::fromUInt16(content.size( )); content[2] = LengthBytes[0]; content[3] = LengthBytes[1]; return true; @@ -163,7 +163,7 @@ bool CGPSProtocol :: ValidateLength( QByteArray &content ) { LengthBytes.push_back( content[2] ); LengthBytes.push_back( content[3] ); - Length = UTIL_QByteArrayToUInt16( LengthBytes, false ); + Length = LengthBytes.toUShort(); if( Length == content.size( ) ) return true; diff --git a/ghost/language.cpp b/ghost/language.cpp index 1a3c2a5..46b9f4b 100644 --- a/ghost/language.cpp +++ b/ghost/language.cpp @@ -41,32 +41,32 @@ CLanguage :: ~CLanguage( ) QString CLanguage :: UnableToCreateGameTryAnotherName( QString server, QString gamename ) { QString Out = m_CFG->GetString( "lang_0001", "lang_0001" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$SERVER$", server); + Out.replace("$GAMENAME$", gamename); return Out; } QString CLanguage :: UserIsAlreadyAnAdmin( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0002", "lang_0002" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: AddedUserToAdminDatabase( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0003", "lang_0003" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: ErrorAddingUserToAdminDatabase( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0004", "lang_0004" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } @@ -78,103 +78,103 @@ QString CLanguage :: YouDontHaveAccessToThatCommand( ) QString CLanguage :: UserIsAlreadyBanned( QString server, QString victim ) { QString Out = m_CFG->GetString( "lang_0006", "lang_0006" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$SERVER$", server); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: BannedUser( QString server, QString victim ) { QString Out = m_CFG->GetString( "lang_0007", "lang_0007" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$SERVER$", server); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: ErrorBanningUser( QString server, QString victim ) { QString Out = m_CFG->GetString( "lang_0008", "lang_0008" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$SERVER$", server); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: UserIsAnAdmin( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0009", "lang_0009" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UserIsNotAnAdmin( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0010", "lang_0010" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UserWasBannedOnByBecause( QString server, QString victim, QString date, QString admin, QString reason ) { QString Out = m_CFG->GetString( "lang_0011", "lang_0011" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$DATE$", date ); - UTIL_Replace( Out, "$ADMIN$", admin ); - UTIL_Replace( Out, "$REASON$", reason ); + Out.replace("$SERVER$", server); + Out.replace("$VICTIM$", victim); + Out.replace("$DATE$", date); + Out.replace("$ADMIN$", admin); + Out.replace("$REASON$", reason); return Out; } QString CLanguage :: UserIsNotBanned( QString server, QString victim ) { QString Out = m_CFG->GetString( "lang_0012", "lang_0012" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$SERVER$", server); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: ThereAreNoAdmins( QString server ) { QString Out = m_CFG->GetString( "lang_0013", "lang_0013" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: ThereIsAdmin( QString server ) { QString Out = m_CFG->GetString( "lang_0014", "lang_0014" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: ThereAreAdmins( QString server, QString count ) { QString Out = m_CFG->GetString( "lang_0015", "lang_0015" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$COUNT$", count ); + Out.replace("$SERVER$", server); + Out.replace("$COUNT$", count); return Out; } QString CLanguage :: ThereAreNoBannedUsers( QString server ) { QString Out = m_CFG->GetString( "lang_0016", "lang_0016" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: ThereIsBannedUser( QString server ) { QString Out = m_CFG->GetString( "lang_0017", "lang_0017" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: ThereAreBannedUsers( QString server, QString count ) { QString Out = m_CFG->GetString( "lang_0018", "lang_0018" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$COUNT$", count ); + Out.replace("$SERVER$", server); + Out.replace("$COUNT$", count); return Out; } @@ -186,62 +186,62 @@ QString CLanguage :: YouCantDeleteTheRootAdmin( ) QString CLanguage :: DeletedUserFromAdminDatabase( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0020", "lang_0020" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: ErrorDeletingUserFromAdminDatabase( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0021", "lang_0021" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UnbannedUser( QString victim ) { QString Out = m_CFG->GetString( "lang_0022", "lang_0022" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: ErrorUnbanningUser( QString victim ) { QString Out = m_CFG->GetString( "lang_0023", "lang_0023" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: GameNumberIs( QString number, QString description ) { QString Out = m_CFG->GetString( "lang_0024", "lang_0024" ); - UTIL_Replace( Out, "$NUMBER$", number ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); + Out.replace("$NUMBER$", number); + Out.replace("$DESCRIPTION$", description); return Out; } QString CLanguage :: GameNumberDoesntExist( QString number ) { QString Out = m_CFG->GetString( "lang_0025", "lang_0025" ); - UTIL_Replace( Out, "$NUMBER$", number ); + Out.replace("$NUMBER$", number); return Out; } QString CLanguage :: GameIsInTheLobby( QString description, QString current, QString max ) { QString Out = m_CFG->GetString( "lang_0026", "lang_0026" ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); - UTIL_Replace( Out, "$CURRENT$", current ); - UTIL_Replace( Out, "$MAX$", max ); + Out.replace("$DESCRIPTION$", description); + Out.replace("$CURRENT$", current); + Out.replace("$MAX$", max); return Out; } QString CLanguage :: ThereIsNoGameInTheLobby( QString current, QString max ) { QString Out = m_CFG->GetString( "lang_0027", "lang_0027" ); - UTIL_Replace( Out, "$CURRENT$", current ); - UTIL_Replace( Out, "$MAX$", max ); + Out.replace("$CURRENT$", current); + Out.replace("$MAX$", max); return Out; } @@ -253,44 +253,44 @@ QString CLanguage :: UnableToLoadConfigFilesOutside( ) QString CLanguage :: LoadingConfigFile( QString file ) { QString Out = m_CFG->GetString( "lang_0029", "lang_0029" ); - UTIL_Replace( Out, "$FILE$", file ); + Out.replace("$FILE$", file); return Out; } QString CLanguage :: UnableToLoadConfigFileDoesntExist( QString file ) { QString Out = m_CFG->GetString( "lang_0030", "lang_0030" ); - UTIL_Replace( Out, "$FILE$", file ); + Out.replace("$FILE$", file); return Out; } QString CLanguage :: CreatingPrivateGame( QString gamename, QString user ) { QString Out = m_CFG->GetString( "lang_0031", "lang_0031" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$GAMENAME$", gamename); + Out.replace("$USER$", user); return Out; } QString CLanguage :: CreatingPublicGame( QString gamename, QString user ) { QString Out = m_CFG->GetString( "lang_0032", "lang_0032" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$GAMENAME$", gamename); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UnableToUnhostGameCountdownStarted( QString description ) { QString Out = m_CFG->GetString( "lang_0033", "lang_0033" ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); + Out.replace("$DESCRIPTION$", description); return Out; } QString CLanguage :: UnhostingGame( QString description ) { QString Out = m_CFG->GetString( "lang_0034", "lang_0034" ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); + Out.replace("$DESCRIPTION$", description); return Out; } @@ -302,37 +302,37 @@ QString CLanguage :: UnableToUnhostGameNoGameInLobby( ) QString CLanguage :: VersionAdmin( QString version ) { QString Out = m_CFG->GetString( "lang_0036", "lang_0036" ); - UTIL_Replace( Out, "$VERSION$", version ); + Out.replace("$VERSION$", version); return Out; } QString CLanguage :: VersionNotAdmin( QString version ) { QString Out = m_CFG->GetString( "lang_0037", "lang_0037" ); - UTIL_Replace( Out, "$VERSION$", version ); + Out.replace("$VERSION$", version); return Out; } QString CLanguage :: UnableToCreateGameAnotherGameInLobby( QString gamename, QString description ) { QString Out = m_CFG->GetString( "lang_0038", "lang_0038" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); + Out.replace("$GAMENAME$", gamename); + Out.replace("$DESCRIPTION$", description); return Out; } QString CLanguage :: UnableToCreateGameMaxGamesReached( QString gamename, QString max ) { QString Out = m_CFG->GetString( "lang_0039", "lang_0039" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); - UTIL_Replace( Out, "$MAX$", max ); + Out.replace("$GAMENAME$", gamename); + Out.replace("$MAX$", max); return Out; } QString CLanguage :: GameIsOver( QString description ) { QString Out = m_CFG->GetString( "lang_0040", "lang_0040" ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); + Out.replace("$DESCRIPTION$", description); return Out; } @@ -349,42 +349,42 @@ QString CLanguage :: GameRefreshed( ) QString CLanguage :: SpoofPossibleIsAway( QString user ) { QString Out = m_CFG->GetString( "lang_0043", "lang_0043" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: SpoofPossibleIsUnavailable( QString user ) { QString Out = m_CFG->GetString( "lang_0044", "lang_0044" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: SpoofPossibleIsRefusingMessages( QString user ) { QString Out = m_CFG->GetString( "lang_0045", "lang_0045" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: SpoofDetectedIsNotInGame( QString user ) { QString Out = m_CFG->GetString( "lang_0046", "lang_0046" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: SpoofDetectedIsInPrivateChannel( QString user ) { QString Out = m_CFG->GetString( "lang_0047", "lang_0047" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: SpoofDetectedIsInAnotherGame( QString user ) { QString Out = m_CFG->GetString( "lang_0048", "lang_0048" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } @@ -396,136 +396,136 @@ QString CLanguage :: CountDownAborted( ) QString CLanguage :: TryingToJoinTheGameButBanned( QString victim ) { QString Out = m_CFG->GetString( "lang_0050", "lang_0050" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: UnableToBanNoMatchesFound( QString victim ) { QString Out = m_CFG->GetString( "lang_0051", "lang_0051" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: PlayerWasBannedByPlayer( QString server, QString victim, QString user ) { QString Out = m_CFG->GetString( "lang_0052", "lang_0052" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$VICTIM$", victim); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UnableToBanFoundMoreThanOneMatch( QString victim ) { QString Out = m_CFG->GetString( "lang_0053", "lang_0053" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: AddedPlayerToTheHoldList( QString user ) { QString Out = m_CFG->GetString( "lang_0054", "lang_0054" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UnableToKickNoMatchesFound( QString victim ) { QString Out = m_CFG->GetString( "lang_0055", "lang_0055" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: UnableToKickFoundMoreThanOneMatch( QString victim ) { QString Out = m_CFG->GetString( "lang_0056", "lang_0056" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: SettingLatencyToMinimum( QString min ) { QString Out = m_CFG->GetString( "lang_0057", "lang_0057" ); - UTIL_Replace( Out, "$MIN$", min ); + Out.replace("$MIN$", min); return Out; } QString CLanguage :: SettingLatencyToMaximum( QString max ) { QString Out = m_CFG->GetString( "lang_0058", "lang_0058" ); - UTIL_Replace( Out, "$MAX$", max ); + Out.replace("$MAX$", max); return Out; } QString CLanguage :: SettingLatencyTo( QString latency ) { QString Out = m_CFG->GetString( "lang_0059", "lang_0059" ); - UTIL_Replace( Out, "$LATENCY$", latency ); + Out.replace("$LATENCY$", latency); return Out; } QString CLanguage :: KickingPlayersWithPingsGreaterThan( QString total, QString ping ) { QString Out = m_CFG->GetString( "lang_0060", "lang_0060" ); - UTIL_Replace( Out, "$TOTAL$", total ); - UTIL_Replace( Out, "$PING$", ping ); + Out.replace("$TOTAL$", total); + Out.replace("$PING$", ping); return Out; } QString CLanguage :: HasPlayedGamesWithThisBot( QString user, QString firstgame, QString lastgame, QString totalgames, QString avgloadingtime, QString avgstay ) { QString Out = m_CFG->GetString( "lang_0061", "lang_0061" ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$FIRSTGAME$", firstgame ); - UTIL_Replace( Out, "$LASTGAME$", lastgame ); - UTIL_Replace( Out, "$TOTALGAMES$", totalgames ); - UTIL_Replace( Out, "$AVGLOADINGTIME$", avgloadingtime ); - UTIL_Replace( Out, "$AVGSTAY$", avgstay ); + Out.replace("$USER$", user); + Out.replace("$FIRSTGAME$", firstgame); + Out.replace("$LASTGAME$", lastgame); + Out.replace("$TOTALGAMES$", totalgames); + Out.replace("$AVGLOADINGTIME$", avgloadingtime); + Out.replace("$AVGSTAY$", avgstay); return Out; } QString CLanguage :: HasntPlayedGamesWithThisBot( QString user ) { QString Out = m_CFG->GetString( "lang_0062", "lang_0062" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: AutokickingPlayerForExcessivePing( QString victim, QString ping ) { QString Out = m_CFG->GetString( "lang_0063", "lang_0063" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$PING$", ping ); + Out.replace("$VICTIM$", victim); + Out.replace("$PING$", ping); return Out; } QString CLanguage :: SpoofCheckAcceptedFor( QString server, QString user ) { QString Out = m_CFG->GetString( "lang_0064", "lang_0064" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$SERVER$", server); + Out.replace("$USER$", user); return Out; } QString CLanguage :: PlayersNotYetSpoofChecked( QString notspoofchecked ) { QString Out = m_CFG->GetString( "lang_0065", "lang_0065" ); - UTIL_Replace( Out, "$NOTSPOOFCHECKED$", notspoofchecked ); + Out.replace("$NOTSPOOFCHECKED$", notspoofchecked); return Out; } QString CLanguage :: ManuallySpoofCheckByWhispering( QString hostname ) { QString Out = m_CFG->GetString( "lang_0066", "lang_0066" ); - UTIL_Replace( Out, "$HOSTNAME$", hostname ); + Out.replace("$HOSTNAME$", hostname); return Out; } QString CLanguage :: SpoofCheckByWhispering( QString hostname ) { QString Out = m_CFG->GetString( "lang_0067", "lang_0067" ); - UTIL_Replace( Out, "$HOSTNAME$", hostname ); + Out.replace("$HOSTNAME$", hostname); return Out; } @@ -537,7 +537,7 @@ QString CLanguage :: EveryoneHasBeenSpoofChecked( ) QString CLanguage :: PlayersNotYetPinged( QString notpinged ) { QString Out = m_CFG->GetString( "lang_0069", "lang_0069" ); - UTIL_Replace( Out, "$NOTPINGED$", notpinged ); + Out.replace("$NOTPINGED$", notpinged); return Out; } @@ -549,93 +549,93 @@ QString CLanguage :: EveryoneHasBeenPinged( ) QString CLanguage :: ShortestLoadByPlayer( QString user, QString loadingtime ) { QString Out = m_CFG->GetString( "lang_0071", "lang_0071" ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$LOADINGTIME$", loadingtime ); + Out.replace("$USER$", user); + Out.replace("$LOADINGTIME$", loadingtime); return Out; } QString CLanguage :: LongestLoadByPlayer( QString user, QString loadingtime ) { QString Out = m_CFG->GetString( "lang_0072", "lang_0072" ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$LOADINGTIME$", loadingtime ); + Out.replace("$USER$", user); + Out.replace("$LOADINGTIME$", loadingtime); return Out; } QString CLanguage :: YourLoadingTimeWas( QString loadingtime ) { QString Out = m_CFG->GetString( "lang_0073", "lang_0073" ); - UTIL_Replace( Out, "$LOADINGTIME$", loadingtime ); + Out.replace("$LOADINGTIME$", loadingtime); return Out; } QString CLanguage :: HasPlayedDotAGamesWithThisBot( QString user, QString totalgames, QString totalwins, QString totallosses, QString totalkills, QString totaldeaths, QString totalcreepkills, QString totalcreepdenies, QString totalassists, QString totalneutralkills, QString totaltowerkills, QString totalraxkills, QString totalcourierkills, QString avgkills, QString avgdeaths, QString avgcreepkills, QString avgcreepdenies, QString avgassists, QString avgneutralkills, QString avgtowerkills, QString avgraxkills, QString avgcourierkills ) { QString Out = m_CFG->GetString( "lang_0074", "lang_0074" ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$TOTALGAMES$", totalgames ); - UTIL_Replace( Out, "$TOTALWINS$", totalwins ); - UTIL_Replace( Out, "$TOTALLOSSES$", totallosses ); - UTIL_Replace( Out, "$TOTALKILLS$", totalkills ); - UTIL_Replace( Out, "$TOTALDEATHS$", totaldeaths ); - UTIL_Replace( Out, "$TOTALCREEPKILLS$", totalcreepkills ); - UTIL_Replace( Out, "$TOTALCREEPDENIES$", totalcreepdenies ); - UTIL_Replace( Out, "$TOTALASSISTS$", totalassists ); - UTIL_Replace( Out, "$TOTALNEUTRALKILLS$", totalneutralkills ); - UTIL_Replace( Out, "$TOTALTOWERKILLS$", totaltowerkills ); - UTIL_Replace( Out, "$TOTALRAXKILLS$", totalraxkills ); - UTIL_Replace( Out, "$TOTALCOURIERKILLS$", totalcourierkills ); - UTIL_Replace( Out, "$AVGKILLS$", avgkills ); - UTIL_Replace( Out, "$AVGDEATHS$", avgdeaths ); - UTIL_Replace( Out, "$AVGCREEPKILLS$", avgcreepkills ); - UTIL_Replace( Out, "$AVGCREEPDENIES$", avgcreepdenies ); - UTIL_Replace( Out, "$AVGASSISTS$", avgassists ); - UTIL_Replace( Out, "$AVGNEUTRALKILLS$", avgneutralkills ); - UTIL_Replace( Out, "$AVGTOWERKILLS$", avgtowerkills ); - UTIL_Replace( Out, "$AVGRAXKILLS$", avgraxkills ); - UTIL_Replace( Out, "$AVGCOURIERKILLS$", avgcourierkills ); + Out.replace("$USER$", user); + Out.replace("$TOTALGAMES$", totalgames); + Out.replace("$TOTALWINS$", totalwins); + Out.replace("$TOTALLOSSES$", totallosses); + Out.replace("$TOTALKILLS$", totalkills); + Out.replace("$TOTALDEATHS$", totaldeaths); + Out.replace("$TOTALCREEPKILLS$", totalcreepkills); + Out.replace("$TOTALCREEPDENIES$", totalcreepdenies); + Out.replace("$TOTALASSISTS$", totalassists); + Out.replace("$TOTALNEUTRALKILLS$", totalneutralkills); + Out.replace("$TOTALTOWERKILLS$", totaltowerkills); + Out.replace("$TOTALRAXKILLS$", totalraxkills); + Out.replace("$TOTALCOURIERKILLS$", totalcourierkills); + Out.replace("$AVGKILLS$", avgkills); + Out.replace("$AVGDEATHS$", avgdeaths); + Out.replace("$AVGCREEPKILLS$", avgcreepkills); + Out.replace("$AVGCREEPDENIES$", avgcreepdenies); + Out.replace("$AVGASSISTS$", avgassists); + Out.replace("$AVGNEUTRALKILLS$", avgneutralkills); + Out.replace("$AVGTOWERKILLS$", avgtowerkills); + Out.replace("$AVGRAXKILLS$", avgraxkills); + Out.replace("$AVGCOURIERKILLS$", avgcourierkills); return Out; } QString CLanguage :: HasntPlayedDotAGamesWithThisBot( QString user ) { QString Out = m_CFG->GetString( "lang_0075", "lang_0075" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: WasKickedForReservedPlayer( QString reserved ) { QString Out = m_CFG->GetString( "lang_0076", "lang_0076" ); - UTIL_Replace( Out, "$RESERVED$", reserved ); + Out.replace("$RESERVED$", reserved); return Out; } QString CLanguage :: WasKickedForOwnerPlayer( QString owner ) { QString Out = m_CFG->GetString( "lang_0077", "lang_0077" ); - UTIL_Replace( Out, "$OWNER$", owner ); + Out.replace("$OWNER$", owner); return Out; } QString CLanguage :: WasKickedByPlayer( QString user ) { QString Out = m_CFG->GetString( "lang_0078", "lang_0078" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: HasLostConnectionPlayerError( QString error ) { QString Out = m_CFG->GetString( "lang_0079", "lang_0079" ); - UTIL_Replace( Out, "$ERROR$", error ); + Out.replace("$ERROR$", error); return Out; } QString CLanguage :: HasLostConnectionSocketError( QString error ) { QString Out = m_CFG->GetString( "lang_0080", "lang_0080" ); - UTIL_Replace( Out, "$ERROR$", error ); + Out.replace("$ERROR$", error); return Out; } @@ -652,7 +652,7 @@ QString CLanguage :: HasLeftVoluntarily( ) QString CLanguage :: EndingGame( QString description ) { QString Out = m_CFG->GetString( "lang_0083", "lang_0083" ); - UTIL_Replace( Out, "$DESCRIPTION$", description ); + Out.replace("$DESCRIPTION$", description); return Out; } @@ -684,7 +684,7 @@ QString CLanguage :: UnableToLoadConfigFileGameInLobby( ) QString CLanguage :: PlayersStillDownloading( QString stilldownloading ) { QString Out = m_CFG->GetString( "lang_0089", "lang_0089" ); - UTIL_Replace( Out, "$STILLDOWNLOADING$", stilldownloading ); + Out.replace("$STILLDOWNLOADING$", stilldownloading); return Out; } @@ -706,7 +706,7 @@ QString CLanguage :: AtLeastOneGameActiveUseForceToShutdown( ) QString CLanguage :: CurrentlyLoadedMapCFGIs( QString mapcfg ) { QString Out = m_CFG->GetString( "lang_0093", "lang_0093" ); - UTIL_Replace( Out, "$MAPCFG$", mapcfg ); + Out.replace("$MAPCFG$", mapcfg); return Out; } @@ -723,49 +723,49 @@ QString CLanguage :: LaggedOutDroppedByVote( ) QString CLanguage :: PlayerVotedToDropLaggers( QString user ) { QString Out = m_CFG->GetString( "lang_0096", "lang_0096" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } QString CLanguage :: LatencyIs( QString latency ) { QString Out = m_CFG->GetString( "lang_0097", "lang_0097" ); - UTIL_Replace( Out, "$LATENCY$", latency ); + Out.replace("$LATENCY$", latency); return Out; } QString CLanguage :: SyncLimitIs( QString synclimit ) { QString Out = m_CFG->GetString( "lang_0098", "lang_0098" ); - UTIL_Replace( Out, "$SYNCLIMIT$", synclimit ); + Out.replace("$SYNCLIMIT$", synclimit); return Out; } QString CLanguage :: SettingSyncLimitToMinimum( QString min ) { QString Out = m_CFG->GetString( "lang_0099", "lang_0099" ); - UTIL_Replace( Out, "$MIN$", min ); + Out.replace("$MIN$", min); return Out; } QString CLanguage :: SettingSyncLimitToMaximum( QString max ) { QString Out = m_CFG->GetString( "lang_0100", "lang_0100" ); - UTIL_Replace( Out, "$MAX$", max ); + Out.replace("$MAX$", max); return Out; } QString CLanguage :: SettingSyncLimitTo( QString synclimit ) { QString Out = m_CFG->GetString( "lang_0101", "lang_0101" ); - UTIL_Replace( Out, "$SYNCLIMIT$", synclimit ); + Out.replace("$SYNCLIMIT$", synclimit); return Out; } QString CLanguage :: UnableToCreateGameNotLoggedIn( QString gamename ) { QString Out = m_CFG->GetString( "lang_0102", "lang_0102" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } @@ -777,80 +777,80 @@ QString CLanguage :: AdminLoggedIn( ) QString CLanguage :: AdminInvalidPassword( QString attempt ) { QString Out = m_CFG->GetString( "lang_0104", "lang_0104" ); - UTIL_Replace( Out, "$ATTEMPT$", attempt ); + Out.replace("$ATTEMPT$", attempt); return Out; } QString CLanguage :: ConnectingToBNET( QString server ) { QString Out = m_CFG->GetString( "lang_0105", "lang_0105" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: ConnectedToBNET( QString server ) { QString Out = m_CFG->GetString( "lang_0106", "lang_0106" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: DisconnectedFromBNET( QString server ) { QString Out = m_CFG->GetString( "lang_0107", "lang_0107" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: LoggedInToBNET( QString server ) { QString Out = m_CFG->GetString( "lang_0108", "lang_0108" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: BNETGameHostingSucceeded( QString server ) { QString Out = m_CFG->GetString( "lang_0109", "lang_0109" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: BNETGameHostingFailed( QString server, QString gamename ) { QString Out = m_CFG->GetString( "lang_0110", "lang_0110" ); - UTIL_Replace( Out, "$SERVER$", server ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$SERVER$", server); + Out.replace("$GAMENAME$", gamename); return Out; } QString CLanguage :: ConnectingToBNETTimedOut( QString server ) { QString Out = m_CFG->GetString( "lang_0111", "lang_0111" ); - UTIL_Replace( Out, "$SERVER$", server ); + Out.replace("$SERVER$", server); return Out; } QString CLanguage :: PlayerDownloadedTheMap( QString user, QString seconds, QString rate ) { QString Out = m_CFG->GetString( "lang_0112", "lang_0112" ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$SECONDS$", seconds ); - UTIL_Replace( Out, "$RATE$", rate ); + Out.replace("$USER$", user); + Out.replace("$SECONDS$", seconds); + Out.replace("$RATE$", rate); return Out; } QString CLanguage :: UnableToCreateGameNameTooLong( QString gamename ) { QString Out = m_CFG->GetString( "lang_0113", "lang_0113" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } QString CLanguage :: SettingGameOwnerTo( QString owner ) { QString Out = m_CFG->GetString( "lang_0114", "lang_0114" ); - UTIL_Replace( Out, "$OWNER$", owner ); + Out.replace("$OWNER$", owner); return Out; } @@ -872,49 +872,49 @@ QString CLanguage :: GameUnlocked( ) QString CLanguage :: UnableToStartDownloadNoMatchesFound( QString victim ) { QString Out = m_CFG->GetString( "lang_0118", "lang_0118" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( QString victim ) { QString Out = m_CFG->GetString( "lang_0119", "lang_0119" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: UnableToSetGameOwner( QString owner ) { QString Out = m_CFG->GetString( "lang_0120", "lang_0120" ); - UTIL_Replace( Out, "$OWNER$", owner ); + Out.replace("$OWNER$", owner); return Out; } QString CLanguage :: UnableToCheckPlayerNoMatchesFound( QString victim ) { QString Out = m_CFG->GetString( "lang_0121", "lang_0121" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: CheckedPlayer( QString victim, QString ping, QString from, QString admin, QString owner, QString spoofed, QString spoofedrealm, QString reserved ) { QString Out = m_CFG->GetString( "lang_0122", "lang_0122" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$PING$", ping ); - UTIL_Replace( Out, "$FROM$", from ); - UTIL_Replace( Out, "$ADMIN$", admin ); - UTIL_Replace( Out, "$OWNER$", owner ); - UTIL_Replace( Out, "$SPOOFED$", spoofed ); - UTIL_Replace( Out, "$SPOOFEDREALM$", spoofedrealm ); - UTIL_Replace( Out, "$RESERVED$", reserved ); + Out.replace("$VICTIM$", victim); + Out.replace("$PING$", ping); + Out.replace("$FROM$", from); + Out.replace("$ADMIN$", admin); + Out.replace("$OWNER$", owner); + Out.replace("$SPOOFED$", spoofed); + Out.replace("$SPOOFEDREALM$", spoofedrealm); + Out.replace("$RESERVED$", reserved); return Out; } QString CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( QString victim ) { QString Out = m_CFG->GetString( "lang_0123", "lang_0123" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } @@ -926,7 +926,7 @@ QString CLanguage :: TheGameIsLockedBNET( ) QString CLanguage :: UnableToCreateGameDisabled( QString gamename ) { QString Out = m_CFG->GetString( "lang_0125", "lang_0125" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } @@ -943,15 +943,15 @@ QString CLanguage :: BotEnabled( ) QString CLanguage :: UnableToCreateGameInvalidMap( QString gamename ) { QString Out = m_CFG->GetString( "lang_0128", "lang_0128" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } QString CLanguage :: WaitingForPlayersBeforeAutoStart( QString players, QString playersleft ) { QString Out = m_CFG->GetString( "lang_0129", "lang_0129" ); - UTIL_Replace( Out, "$PLAYERS$", players ); - UTIL_Replace( Out, "$PLAYERSLEFT$", playersleft ); + Out.replace("$PLAYERS$", players); + Out.replace("$PLAYERSLEFT$", playersleft); return Out; } @@ -963,7 +963,7 @@ QString CLanguage :: AutoStartDisabled( ) QString CLanguage :: AutoStartEnabled( QString players ) { QString Out = m_CFG->GetString( "lang_0131", "lang_0131" ); - UTIL_Replace( Out, "$PLAYERS$", players ); + Out.replace("$PLAYERS$", players); return Out; } @@ -1000,28 +1000,28 @@ QString CLanguage :: UnableToLoadSaveGameGameInLobby( ) QString CLanguage :: LoadingSaveGame( QString file ) { QString Out = m_CFG->GetString( "lang_0138", "lang_0138" ); - UTIL_Replace( Out, "$FILE$", file ); + Out.replace("$FILE$", file); return Out; } QString CLanguage :: UnableToLoadSaveGameDoesntExist( QString file ) { QString Out = m_CFG->GetString( "lang_0139", "lang_0139" ); - UTIL_Replace( Out, "$FILE$", file ); + Out.replace("$FILE$", file); return Out; } QString CLanguage :: UnableToCreateGameInvalidSaveGame( QString gamename ) { QString Out = m_CFG->GetString( "lang_0140", "lang_0140" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } QString CLanguage :: UnableToCreateGameSaveGameMapMismatch( QString gamename ) { QString Out = m_CFG->GetString( "lang_0141", "lang_0141" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } @@ -1043,37 +1043,37 @@ QString CLanguage :: DesyncDetected( ) QString CLanguage :: UnableToMuteNoMatchesFound( QString victim ) { QString Out = m_CFG->GetString( "lang_0145", "lang_0145" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: MutedPlayer( QString victim, QString user ) { QString Out = m_CFG->GetString( "lang_0146", "lang_0146" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$VICTIM$", victim); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UnmutedPlayer( QString victim, QString user ) { QString Out = m_CFG->GetString( "lang_0147", "lang_0147" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$VICTIM$", victim); + Out.replace("$USER$", user); return Out; } QString CLanguage :: UnableToMuteFoundMoreThanOneMatch( QString victim ) { QString Out = m_CFG->GetString( "lang_0148", "lang_0148" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: PlayerIsSavingTheGame( QString player ) { QString Out = m_CFG->GetString( "lang_0149", "lang_0149" ); - UTIL_Replace( Out, "$PLAYER$", player ); + Out.replace("$PLAYER$", player); return Out; } @@ -1090,8 +1090,8 @@ QString CLanguage :: UpdatingFriendsList( ) QString CLanguage :: MultipleIPAddressUsageDetected( QString player, QString others ) { QString Out = m_CFG->GetString( "lang_0152", "lang_0152" ); - UTIL_Replace( Out, "$PLAYER$", player ); - UTIL_Replace( Out, "$OTHERS$", others ); + Out.replace("$PLAYER$", player); + Out.replace("$OTHERS$", others); return Out; } @@ -1108,67 +1108,67 @@ QString CLanguage :: UnableToVoteKickNotEnoughPlayers( ) QString CLanguage :: UnableToVoteKickNoMatchesFound( QString victim ) { QString Out = m_CFG->GetString( "lang_0155", "lang_0155" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: UnableToVoteKickPlayerIsReserved( QString victim ) { QString Out = m_CFG->GetString( "lang_0156", "lang_0156" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: StartedVoteKick( QString victim, QString user, QString votesneeded ) { QString Out = m_CFG->GetString( "lang_0157", "lang_0157" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$VOTESNEEDED$", votesneeded ); + Out.replace("$VICTIM$", victim); + Out.replace("$USER$", user); + Out.replace("$VOTESNEEDED$", votesneeded); return Out; } QString CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( QString victim ) { QString Out = m_CFG->GetString( "lang_0158", "lang_0158" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: VoteKickPassed( QString victim ) { QString Out = m_CFG->GetString( "lang_0159", "lang_0159" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: ErrorVoteKickingPlayer( QString victim ) { QString Out = m_CFG->GetString( "lang_0160", "lang_0160" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: VoteKickAcceptedNeedMoreVotes( QString victim, QString user, QString votes ) { QString Out = m_CFG->GetString( "lang_0161", "lang_0161" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$USER$", user ); - UTIL_Replace( Out, "$VOTES$", votes ); + Out.replace("$VICTIM$", victim); + Out.replace("$USER$", user); + Out.replace("$VOTES$", votes); return Out; } QString CLanguage :: VoteKickCancelled( QString victim ) { QString Out = m_CFG->GetString( "lang_0162", "lang_0162" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: VoteKickExpired( QString victim ) { QString Out = m_CFG->GetString( "lang_0163", "lang_0163" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } @@ -1180,14 +1180,14 @@ QString CLanguage :: WasKickedByVote( ) QString CLanguage :: TypeYesToVote( QString commandtrigger ) { QString Out = m_CFG->GetString( "lang_0165", "lang_0165" ); - UTIL_Replace( Out, "$COMMANDTRIGGER$", commandtrigger ); + Out.replace("$COMMANDTRIGGER$", commandtrigger); return Out; } QString CLanguage :: PlayersNotYetPingedAutoStart( QString notpinged ) { QString Out = m_CFG->GetString( "lang_0166", "lang_0166" ); - UTIL_Replace( Out, "$NOTPINGED$", notpinged ); + Out.replace("$NOTPINGED$", notpinged); return Out; } @@ -1199,25 +1199,25 @@ QString CLanguage :: WasKickedForNotSpoofChecking( ) QString CLanguage :: WasKickedForHavingFurthestScore( QString score, QString average ) { QString Out = m_CFG->GetString( "lang_0168", "lang_0168" ); - UTIL_Replace( Out, "$SCORE$", score ); - UTIL_Replace( Out, "$AVERAGE$", average ); + Out.replace("$SCORE$", score); + Out.replace("$AVERAGE$", average); return Out; } QString CLanguage :: PlayerHasScore( QString player, QString score ) { QString Out = m_CFG->GetString( "lang_0169", "lang_0169" ); - UTIL_Replace( Out, "$PLAYER$", player ); - UTIL_Replace( Out, "$SCORE$", score ); + Out.replace("$PLAYER$", player); + Out.replace("$SCORE$", score); return Out; } QString CLanguage :: RatedPlayersSpread( QString rated, QString total, QString spread ) { QString Out = m_CFG->GetString( "lang_0170", "lang_0170" ); - UTIL_Replace( Out, "$RATED$", rated ); - UTIL_Replace( Out, "$TOTAL$", total ); - UTIL_Replace( Out, "$SPREAD$", spread ); + Out.replace("$RATED$", rated); + Out.replace("$TOTAL$", total); + Out.replace("$SPREAD$", spread); return Out; } @@ -1229,7 +1229,7 @@ QString CLanguage :: ErrorListingMaps( ) QString CLanguage :: FoundMaps( QString maps ) { QString Out = m_CFG->GetString( "lang_0172", "lang_0172" ); - UTIL_Replace( Out, "$MAPS$", maps ); + Out.replace("$MAPS$", maps); return Out; } @@ -1246,7 +1246,7 @@ QString CLanguage :: ErrorListingMapConfigs( ) QString CLanguage :: FoundMapConfigs( QString mapconfigs ) { QString Out = m_CFG->GetString( "lang_0175", "lang_0175" ); - UTIL_Replace( Out, "$MAPCONFIGS$", mapconfigs ); + Out.replace("$MAPCONFIGS$", mapconfigs); return Out; } @@ -1258,7 +1258,7 @@ QString CLanguage :: NoMapConfigsFound( ) QString CLanguage :: PlayerFinishedLoading( QString user ) { QString Out = m_CFG->GetString( "lang_0177", "lang_0177" ); - UTIL_Replace( Out, "$USER$", user ); + Out.replace("$USER$", user); return Out; } @@ -1285,7 +1285,7 @@ QString CLanguage :: MapDownloadsConditional( ) QString CLanguage :: SettingHCL( QString HCL ) { QString Out = m_CFG->GetString( "lang_0182", "lang_0182" ); - UTIL_Replace( Out, "$HCL$", HCL ); + Out.replace("$HCL$", HCL); return Out; } @@ -1302,7 +1302,7 @@ QString CLanguage :: UnableToSetHCLTooLong( ) QString CLanguage :: TheHCLIs( QString HCL ) { QString Out = m_CFG->GetString( "lang_0185", "lang_0185" ); - UTIL_Replace( Out, "$HCL$", HCL ); + Out.replace("$HCL$", HCL); return Out; } @@ -1319,14 +1319,14 @@ QString CLanguage :: ClearingHCL( ) QString CLanguage :: TryingToRehostAsPrivateGame( QString gamename ) { QString Out = m_CFG->GetString( "lang_0188", "lang_0188" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } QString CLanguage :: TryingToRehostAsPublicGame( QString gamename ) { QString Out = m_CFG->GetString( "lang_0189", "lang_0189" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } @@ -1338,55 +1338,55 @@ QString CLanguage :: RehostWasSuccessful( ) QString CLanguage :: TryingToJoinTheGameButBannedByName( QString victim ) { QString Out = m_CFG->GetString( "lang_0191", "lang_0191" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: TryingToJoinTheGameButBannedByIP( QString victim, QString ip, QString bannedname ) { QString Out = m_CFG->GetString( "lang_0192", "lang_0192" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$IP$", ip ); - UTIL_Replace( Out, "$BANNEDNAME$", bannedname ); + Out.replace("$VICTIM$", victim); + Out.replace("$IP$", ip); + Out.replace("$BANNEDNAME$", bannedname); return Out; } QString CLanguage :: HasBannedName( QString victim ) { QString Out = m_CFG->GetString( "lang_0193", "lang_0193" ); - UTIL_Replace( Out, "$VICTIM$", victim ); + Out.replace("$VICTIM$", victim); return Out; } QString CLanguage :: HasBannedIP( QString victim, QString ip, QString bannedname ) { QString Out = m_CFG->GetString( "lang_0194", "lang_0194" ); - UTIL_Replace( Out, "$VICTIM$", victim ); - UTIL_Replace( Out, "$IP$", ip ); - UTIL_Replace( Out, "$BANNEDNAME$", bannedname ); + Out.replace("$VICTIM$", victim); + Out.replace("$IP$", ip); + Out.replace("$BANNEDNAME$", bannedname); return Out; } QString CLanguage :: PlayersInGameState( QString number, QString players ) { QString Out = m_CFG->GetString( "lang_0195", "lang_0195" ); - UTIL_Replace( Out, "$NUMBER$", number ); - UTIL_Replace( Out, "$PLAYERS$", players ); + Out.replace("$NUMBER$", number); + Out.replace("$PLAYERS$", players); return Out; } QString CLanguage :: ValidServers( QString servers ) { QString Out = m_CFG->GetString( "lang_0196", "lang_0196" ); - UTIL_Replace( Out, "$SERVERS$", servers ); + Out.replace("$SERVERS$", servers); return Out; } QString CLanguage :: TeamCombinedScore( QString team, QString score ) { QString Out = m_CFG->GetString( "lang_0197", "lang_0197" ); - UTIL_Replace( Out, "$TEAM$", team ); - UTIL_Replace( Out, "$SCORE$", score ); + Out.replace("$TEAM$", team); + Out.replace("$SCORE$", score); return Out; } @@ -1398,9 +1398,9 @@ QString CLanguage :: BalancingSlotsCompleted( ) QString CLanguage :: PlayerWasKickedForFurthestScore( QString name, QString score, QString average ) { QString Out = m_CFG->GetString( "lang_0199", "lang_0199" ); - UTIL_Replace( Out, "$NAME$", name ); - UTIL_Replace( Out, "$SCORE$", score ); - UTIL_Replace( Out, "$AVERAGE$", average ); + Out.replace("$NAME$", name); + Out.replace("$SCORE$", score); + Out.replace("$AVERAGE$", average); return Out; } @@ -1422,15 +1422,15 @@ QString CLanguage :: WasDroppedDesync( ) QString CLanguage :: WasKickedForHavingLowestScore( QString score ) { QString Out = m_CFG->GetString( "lang_0203", "lang_0203" ); - UTIL_Replace( Out, "$SCORE$", score ); + Out.replace("$SCORE$", score); return Out; } QString CLanguage :: PlayerWasKickedForLowestScore( QString name, QString score ) { QString Out = m_CFG->GetString( "lang_0204", "lang_0204" ); - UTIL_Replace( Out, "$NAME$", name ); - UTIL_Replace( Out, "$SCORE$", score ); + Out.replace("$NAME$", name); + Out.replace("$SCORE$", score); return Out; } @@ -1447,7 +1447,7 @@ QString CLanguage :: CountDownAbortedSomeoneLeftRecently( ) QString CLanguage :: UnableToCreateGameMustEnforceFirst( QString gamename ) { QString Out = m_CFG->GetString( "lang_0207", "lang_0207" ); - UTIL_Replace( Out, "$GAMENAME$", gamename ); + Out.replace("$GAMENAME$", gamename); return Out; } @@ -1459,42 +1459,42 @@ QString CLanguage :: UnableToLoadReplaysOutside( ) QString CLanguage :: LoadingReplay( QString file ) { QString Out = m_CFG->GetString( "lang_0209", "lang_0209" ); - UTIL_Replace( Out, "$FILE$", file ); + Out.replace("$FILE$", file); return Out; } QString CLanguage :: UnableToLoadReplayDoesntExist( QString file ) { QString Out = m_CFG->GetString( "lang_0210", "lang_0210" ); - UTIL_Replace( Out, "$FILE$", file ); + Out.replace("$FILE$", file); return Out; } QString CLanguage :: CommandTrigger( QString trigger ) { QString Out = m_CFG->GetString( "lang_0211", "lang_0211" ); - UTIL_Replace( Out, "$TRIGGER$", trigger ); + Out.replace("$TRIGGER$", trigger); return Out; } QString CLanguage :: CantEndGameOwnerIsStillPlaying( QString owner ) { QString Out = m_CFG->GetString( "lang_0212", "lang_0212" ); - UTIL_Replace( Out, "$OWNER$", owner ); + Out.replace("$OWNER$", owner); return Out; } QString CLanguage :: CantUnhostGameOwnerIsPresent( QString owner ) { QString Out = m_CFG->GetString( "lang_0213", "lang_0213" ); - UTIL_Replace( Out, "$OWNER$", owner ); + Out.replace("$OWNER$", owner); return Out; } QString CLanguage :: WasAutomaticallyDroppedAfterSeconds( QString seconds ) { QString Out = m_CFG->GetString( "lang_0214", "lang_0214" ); - UTIL_Replace( Out, "$SECONDS$", seconds ); + Out.replace("$SECONDS$", seconds); return Out; } @@ -1506,7 +1506,7 @@ QString CLanguage :: HasLostConnectionTimedOutGProxy( ) QString CLanguage :: HasLostConnectionSocketErrorGProxy( QString error ) { QString Out = m_CFG->GetString( "lang_0216", "lang_0216" ); - UTIL_Replace( Out, "$ERROR$", error ); + Out.replace("$ERROR$", error); return Out; } @@ -1518,7 +1518,7 @@ QString CLanguage :: HasLostConnectionClosedByRemoteHostGProxy( ) QString CLanguage :: WaitForReconnectSecondsRemain( QString seconds ) { QString Out = m_CFG->GetString( "lang_0218", "lang_0218" ); - UTIL_Replace( Out, "$SECONDS$", seconds ); + Out.replace("$SECONDS$", seconds); return Out; } @@ -1530,6 +1530,6 @@ QString CLanguage :: WasUnrecoverablyDroppedFromGProxy( ) QString CLanguage :: PlayerReconnectedWithGProxy( QString name ) { QString Out = m_CFG->GetString( "lang_0220", "lang_0220" ); - UTIL_Replace( Out, "$NAME$", name ); + Out.replace("$NAME$", name); return Out; } diff --git a/ghost/main.cpp b/ghost/main.cpp index 2255a93..a27088a 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -29,7 +29,7 @@ quint32 GetTicks() void SignalCatcher2( int s ) { - CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting NOW" ); + CONSOLE_Print( "[!!!] caught signal " + QString::number( s ) + ", exiting NOW" ); if( gGHost ) { @@ -47,7 +47,7 @@ void SignalCatcher( int s ) // signal( SIGABRT, SignalCatcher2 ); signal( SIGINT, SignalCatcher2 ); - CONSOLE_Print( "[!!!] caught signal " + UTIL_ToString( s ) + ", exiting nicely" ); + CONSOLE_Print( "[!!!] caught signal " + QString::number( s ) + ", exiting nicely" ); if( gGHost ) gGHost->EventExitNice(); @@ -91,6 +91,10 @@ void DEBUG_Print( QString message ) int main( int argc, char **argv ) { QCoreApplication a(argc, argv); + + /*DEBUG_Print(Util::fromUInt32(1111).toHex()); + return 0;*/ + /* QByteArray data = QByteArray::fromHex("0224001b019a0700009a070000160101009a0700009a0700001a19303030559a0700009a070000"); CCRC32 *crc = new CCRC32(); diff --git a/ghost/map.cpp b/ghost/map.cpp index bc1347d..c173010 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -158,7 +158,7 @@ QByteArray CMap :: GetMapGameFlags( ) if( m_MapFlags & MAPFLAG_RANDOMRACES ) GameFlags |= 0x04000000; - return UTIL_CreateBYTEARRAY( GameFlags, false ); + return Util::fromUInt32(GameFlags); } quint32 CMap :: GetMapGameType( ) @@ -292,12 +292,12 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // calculate map_size - MapSize = UTIL_CreateBYTEARRAY( (quint32)m_MapData.size( ), false ); + MapSize = Util::fromUInt32(m_MapData.size( )); CONSOLE_Print( "[MAP] calculated map_size = " + UTIL_QByteArrayToDecString( MapSize ) ); // calculate map_info (this is actually the CRC) - MapInfo = UTIL_CreateBYTEARRAY( (quint32)m_GHost->m_CRC->FullCRC( m_MapData ), false ); + MapInfo = Util::fromUInt32(m_GHost->m_CRC->FullCRC( m_MapData )); CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_QByteArrayToDecString( MapInfo ) ); // calculate map_crc (this is not the CRC) and map_sha1 @@ -456,7 +456,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( !FoundScript ) CONSOLE_Print( "[MAP] couldn't find war3map.j or scripts\\war3map.j in MPQ file, calculated map_crc/sha1 is probably wrong" ); - MapCRC = UTIL_CreateBYTEARRAY( Val, false ); + MapCRC = Util::fromUInt32( Val ); CONSOLE_Print( "[MAP] calculated map_crc = " + UTIL_QByteArrayToDecString( MapCRC ) ); m_GHost->m_SHA->Final( ); @@ -655,21 +655,21 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) // let's not confuse the user by displaying erroneous map options so zero them out now MapOptions = RawMapFlags & ( MAPOPT_MELEE | MAPOPT_FIXEDPLAYERSETTINGS | MAPOPT_CUSTOMFORCES ); - CONSOLE_Print( "[MAP] calculated map_options = " + UTIL_ToString( MapOptions ) ); - MapWidth = UTIL_CreateBYTEARRAY( (quint16)RawMapWidth, false ); + CONSOLE_Print( "[MAP] calculated map_options = " + QString::number( MapOptions ) ); + MapWidth = Util::fromUInt16(RawMapWidth); CONSOLE_Print( "[MAP] calculated map_width = " + UTIL_QByteArrayToDecString( MapWidth ) ); - MapHeight = UTIL_CreateBYTEARRAY( (quint16)RawMapHeight, false ); + MapHeight = Util::fromUInt16(RawMapHeight); CONSOLE_Print( "[MAP] calculated map_height = " + UTIL_QByteArrayToDecString( MapHeight ) ); MapNumPlayers = RawMapNumPlayers - ClosedSlots; - CONSOLE_Print( "[MAP] calculated map_numplayers = " + UTIL_ToString( MapNumPlayers ) ); + CONSOLE_Print( "[MAP] calculated map_numplayers = " + QString::number( MapNumPlayers ) ); MapNumTeams = RawMapNumTeams; - CONSOLE_Print( "[MAP] calculated map_numteams = " + UTIL_ToString( MapNumTeams ) ); + CONSOLE_Print( "[MAP] calculated map_numteams = " + QString::number( MapNumTeams ) ); quint32 SlotNum = 1; for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) { - CONSOLE_Print( "[MAP] calculated map_slot" + UTIL_ToString( SlotNum ) + " = " + UTIL_QByteArrayToDecString( (*i).GetQByteArray( ) ) ); + CONSOLE_Print( "[MAP] calculated map_slot" + QString::number( SlotNum ) + " = " + UTIL_QByteArrayToDecString( (*i).GetQByteArray( ) ) ); SlotNum++; } @@ -831,7 +831,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { for( quint32 Slot = 1; Slot <= 12; Slot++ ) { - QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); + QString SlotString = CFG->GetString( "map_slot" + QString::number( Slot ), QString( ) ); if( SlotString.isEmpty( ) ) break; @@ -847,7 +847,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) for( quint32 Slot = 1; Slot <= 12; Slot++ ) { - QString SlotString = CFG->GetString( "map_slot" + UTIL_ToString( Slot ), QString( ) ); + QString SlotString = CFG->GetString( "map_slot" + QString::number( Slot ), QString( ) ); if( SlotString.isEmpty( ) ) break; @@ -873,7 +873,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( m_MapObservers == MAPOBS_ALLOWED || m_MapObservers == MAPOBS_REFEREES ) { - CONSOLE_Print( "[MAP] adding " + UTIL_ToString( 12 - m_Slots.size( ) ) + " observer slots" ); + CONSOLE_Print( "[MAP] adding " + QString::number( 12 - m_Slots.size( ) ) + " observer slots" ); while( m_Slots.size( ) < 12 ) m_Slots.push_back( CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, 12, 12, SLOTRACE_RANDOM ) ); @@ -902,7 +902,7 @@ void CMap :: CheckValid( ) m_Valid = false; CONSOLE_Print( "[MAP] invalid map_size detected" ); } - else if( !m_MapData.isEmpty( ) && (unsigned int)m_MapData.size( ) != UTIL_QByteArrayToUInt32( m_MapSize, false ) ) + else if( !m_MapData.isEmpty( ) && (unsigned int)m_MapData.size( ) != Util::extractUInt32(m_MapSize) ) { m_Valid = false; CONSOLE_Print( "[MAP] invalid map_size detected - size mismatch with actual map data "); diff --git a/ghost/packed.cpp b/ghost/packed.cpp index ad2fb74..c5b86fb 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -306,7 +306,7 @@ void CPacked :: Compress( bool TFT ) if( Result != Z_OK ) { - CONSOLE_Print( "[PACKED] compress error " + UTIL_ToString( Result ) ); + CONSOLE_Print( "[PACKED] compress error " + QString::number( Result ) ); delete [] CompressedData; m_Valid = false; return; @@ -325,12 +325,12 @@ void CPacked :: Compress( bool TFT ) quint32 HeaderCompressedSize = HeaderSize + CompressedSize + CompressedBlocks.size( ) * 8; quint32 HeaderVersion = 1; QByteArray Header; - UTIL_AppendBYTEARRAY( Header, "Warcraft III recorded game\x01A" ); - UTIL_AppendBYTEARRAY( Header, HeaderSize, false ); - UTIL_AppendBYTEARRAY( Header, HeaderCompressedSize, false ); - UTIL_AppendBYTEARRAY( Header, HeaderVersion, false ); - UTIL_AppendBYTEARRAY( Header, (quint32)m_Decompressed.size( ), false ); - UTIL_AppendBYTEARRAY( Header, (quint32)CompressedBlocks.size( ), false ); + Header.append("Warcraft III recorded game\x01A"); + Header.append(Util::fromUInt32(HeaderSize)); + Header.append(Util::fromUInt32(HeaderCompressedSize)); + Header.append(Util::fromUInt32(HeaderVersion)); + Header.append(Util::fromUInt32(m_Decompressed.size( ))); + Header.append(Util::fromUInt32(CompressedBlocks.size( ))); if( TFT ) { @@ -347,16 +347,16 @@ void CPacked :: Compress( bool TFT ) Header.push_back( 'W' ); } - UTIL_AppendBYTEARRAY( Header, m_War3Version, false ); - UTIL_AppendBYTEARRAY( Header, m_BuildNumber, false ); - UTIL_AppendBYTEARRAY( Header, m_Flags, false ); - UTIL_AppendBYTEARRAY( Header, m_ReplayLength, false ); + Header.append(Util::fromUInt32(m_War3Version)); + Header.append(Util::fromUInt16(m_BuildNumber)); + Header.append(Util::fromUInt16(m_Flags)); + Header.append(Util::fromUInt32(m_ReplayLength)); // append zero header CRC // the header CRC is calculated over the entire header with itself set to zero // we'll overwrite the zero header CRC after we calculate it - UTIL_AppendBYTEARRAY( Header, (quint32)0, false ); + Header.append(Util::fromUInt32(0)); // calculate header CRC quint32 CRC = m_CRC->FullCRC( Header ); @@ -364,7 +364,7 @@ void CPacked :: Compress( bool TFT ) // overwrite the (currently zero) header CRC with the calculated CRC Header.remove(Header.size() - 4, 4); - UTIL_AppendBYTEARRAY( Header, CRC, false ); + Header.append(Util::fromUInt32(CRC)); // append header @@ -375,12 +375,12 @@ void CPacked :: Compress( bool TFT ) for( QVector :: const_iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { QByteArray BlockHeader; - UTIL_AppendBYTEARRAY( BlockHeader, (quint16)(*i).size( ), false ); - UTIL_AppendBYTEARRAY( BlockHeader, (quint16)8192, false ); + BlockHeader.append(Util::fromUInt16((*i).size( ))); + BlockHeader.append(Util::fromUInt16(8192)); // append zero block header CRC - UTIL_AppendBYTEARRAY( BlockHeader, (quint32)0, false ); + BlockHeader.append(Util::fromUInt32(0)); // calculate block header CRC @@ -393,7 +393,7 @@ void CPacked :: Compress( bool TFT ) // overwrite the block header CRC with the calculated CRC BlockHeader.remove( BlockHeader.size() - 4, 4 ); - UTIL_AppendBYTEARRAY( BlockHeader, BlockCRC, false ); + BlockHeader.append(Util::fromUInt32(BlockCRC)); // append block header and data diff --git a/ghost/replay.cpp b/ghost/replay.cpp index d2a7284..6b84562 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -48,10 +48,10 @@ void CReplay :: AddLeaveGame( quint32 reason, unsigned char PID, quint32 result { QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); - UTIL_AppendBYTEARRAY( Block, reason, false ); + Block.append(Util::fromUInt32(reason)); Block.push_back( PID ); - UTIL_AppendBYTEARRAY( Block, result, false ); - UTIL_AppendBYTEARRAY( Block, (quint32)1, false ); + Block.append(Util::fromUInt32(result)); + Block.append(Util::fromUInt32(1)); m_CompiledBlocks += Block; } @@ -59,10 +59,10 @@ void CReplay :: AddLeaveGameDuringLoading( quint32 reason, unsigned char PID, qu { QByteArray Block; Block.push_back( REPLAY_LEAVEGAME ); - UTIL_AppendBYTEARRAY( Block, reason, false ); + Block.append(Util::fromUInt32(reason)); Block.push_back( PID ); - UTIL_AppendBYTEARRAY( Block, result, false ); - UTIL_AppendBYTEARRAY( Block, (quint32)1, false ); + Block.append(Util::fromUInt32(result)); + Block.append(Util::fromUInt32(1)); m_LoadingBlocks.enqueue( Block ); } @@ -70,21 +70,21 @@ void CReplay :: AddTimeSlot2( QQueue actions ) { QByteArray Block; Block.push_back( REPLAY_TIMESLOT2 ); - UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); - UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); + Block.append(Util::fromUInt16(0)); + Block.append(Util::fromUInt16(0)); while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendBYTEARRAY( Block, (quint16)Action->GetAction( )->size( ), false ); - UTIL_AppendBYTEARRAYFast( Block, *Action->GetAction( ) ); + Block.append(Util::fromUInt16(Action->GetAction( )->size( ))); + Block.append(*Action->GetAction( )); } // assign length - QByteArray LengthBytes = UTIL_CreateBYTEARRAY((quint16)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = Util::fromUInt16( Block.size( ) - 3 ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -94,21 +94,21 @@ void CReplay :: AddTimeSlot( quint16 timeIncrement, QQueue ac { QByteArray Block; Block.push_back( REPLAY_TIMESLOT ); - UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); - UTIL_AppendBYTEARRAY( Block, timeIncrement, false ); + Block.append(Util::fromUInt16(0)); + Block.append(Util::fromUInt16(timeIncrement)); while( !actions.isEmpty( ) ) { CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - UTIL_AppendBYTEARRAY( Block, (quint16)Action->GetAction( )->size( ), false ); - UTIL_AppendBYTEARRAYFast( Block, *Action->GetAction( ) ); + Block.append(Util::fromUInt16(Action->GetAction( )->size( ))); + Block.append(*Action->GetAction( )); } // assign length - QByteArray LengthBytes = UTIL_CreateBYTEARRAY((quint16)( Block.size( ) - 3 ), false ); + QByteArray LengthBytes = Util::fromUInt16( Block.size( ) - 3 ); Block[1] = LengthBytes[0]; Block[2] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -120,14 +120,14 @@ void CReplay :: AddChatMessage( unsigned char PID, unsigned char flags, quint32 QByteArray Block; Block.push_back( REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendBYTEARRAY( Block, (quint16)0, false ); + Block.append(Util::fromUInt16(0)); Block.push_back( flags ); - UTIL_AppendBYTEARRAY( Block, chatMode, false ); - UTIL_AppendBYTEARRAYFast( Block, message ); + Block.append(Util::fromUInt32(chatMode)); + Block.append(message); // assign length - QByteArray LengthBytes = UTIL_CreateBYTEARRAY( (quint16)( Block.size( ) - 4 ), false ); + QByteArray LengthBytes = Util::fromUInt16( Block.size( ) - 4 ); Block[2] = LengthBytes[0]; Block[3] = LengthBytes[1]; m_CompiledBlocks += Block; @@ -149,21 +149,21 @@ void CReplay :: BuildReplay( QString gameName, QString statString, quint32 war3V quint32 LanguageID = 0x0012F8B0; QByteArray Replay; - Replay.push_back( (char)16 ); // Unknown (4.0) - Replay.push_back( (char)1 ); // Unknown (4.0) - Replay.push_back( (char)0 ); // Unknown (4.0) - Replay.push_back( (char)0 ); // Unknown (4.0) - Replay.push_back( (char)0 ); // Host RecordID (4.1) - Replay.push_back( (char)m_HostPID ); // Host PlayerID (4.1) - UTIL_AppendBYTEARRAYFast( Replay, m_HostName ); // Host PlayerName (4.1) - Replay.push_back( (char)1 ); // Host AdditionalSize (4.1) - Replay.push_back( (char)0 ); // Host AdditionalData (4.1) - UTIL_AppendBYTEARRAYFast( Replay, gameName ); // GameName (4.2) - Replay.push_back( (char)0 ); // Null (4.0) - UTIL_AppendBYTEARRAYFast( Replay, statString ); // StatString (4.3) - UTIL_AppendBYTEARRAY( Replay, (quint32)m_Slots.size( ), false ); // PlayerCount (4.6) - UTIL_AppendBYTEARRAY( Replay, m_MapGameType, false ); // GameType (4.7) - UTIL_AppendBYTEARRAY( Replay, LanguageID, false ); // LanguageID (4.8) + Replay.push_back( (char)16 ); // Unknown (4.0) + Replay.push_back( (char)1 ); // Unknown (4.0) + Replay.push_back( (char)0 ); // Unknown (4.0) + Replay.push_back( (char)0 ); // Unknown (4.0) + Replay.push_back( (char)0 ); // Host RecordID (4.1) + Replay.push_back( (char)m_HostPID ); // Host PlayerID (4.1) + Replay.append(m_HostName); // Host PlayerName (4.1) + Replay.push_back( (char)1 ); // Host AdditionalSize (4.1) + Replay.push_back( (char)0 ); // Host AdditionalData (4.1) + Replay.append(gameName); // GameName (4.2) + Replay.push_back( (char)0 ); // Null (4.0) + Replay.append(statString); // StatString (4.3) + Replay.append(Util::fromUInt32(m_Slots.size( ))); // PlayerCount (4.6) + Replay.append(Util::fromUInt32(m_MapGameType)); // GameType (4.7) + Replay.append(Util::fromUInt32(LanguageID)); // LanguageID (4.8) // PlayerList (4.9) @@ -173,43 +173,43 @@ void CReplay :: BuildReplay( QString gameName, QString statString, quint32 war3V { Replay.push_back( 22 ); // Player RecordID (4.1) Replay.push_back( (*i).first ); // Player PlayerID (4.1) - UTIL_AppendBYTEARRAYFast( Replay, (*i).second ); // Player PlayerName (4.1) + Replay.append((*i).second); // Player PlayerName (4.1) Replay.push_back( 1 ); // Player AdditionalSize (4.1) - Replay.push_back( (char)0 ); // Player AdditionalData (4.1) - UTIL_AppendBYTEARRAY( Replay, (quint32)0, false ); // Unknown + Replay.push_back( (char)0 ); // Player AdditionalData (4.1) + Replay.append(Util::fromUInt32(0)); // Unknown } } // GameStartRecord (4.10) Replay.push_back( 25 ); // RecordID (4.10) - UTIL_AppendBYTEARRAY( Replay, (quint16)( 7 + m_Slots.size( ) * 9 ), false ); // Size (4.10) + Replay.append(Util::fromUInt16( 7 + m_Slots.size( ) * 9 )); // Size (4.10) Replay.push_back( m_Slots.size( ) ); // NumSlots (4.10) for( unsigned char i = 0; i < m_Slots.size( ); i++ ) - UTIL_AppendBYTEARRAY( Replay, m_Slots[i].GetQByteArray( ) ); + Replay.append(m_Slots[i].GetQByteArray( )); - UTIL_AppendBYTEARRAY( Replay, m_RandomSeed, false ); // RandomSeed (4.10) + Replay.append(Util::fromUInt32(m_RandomSeed)); // RandomSeed (4.10) Replay.push_back( m_SelectMode ); // SelectMode (4.10) Replay.push_back( m_StartSpotCount ); // StartSpotCount (4.10) // ReplayData (5.0) Replay.push_back( REPLAY_FIRSTSTARTBLOCK ); - UTIL_AppendBYTEARRAY( Replay, (quint32)1, false ); + Replay.append(Util::fromUInt32(1)); Replay.push_back( REPLAY_SECONDSTARTBLOCK ); - UTIL_AppendBYTEARRAY( Replay, (quint32)1, false ); + Replay.append(Util::fromUInt32(1)); // leavers during loading need to be stored between the second and third start blocks while( !m_LoadingBlocks.isEmpty( ) ) { - UTIL_AppendBYTEARRAY( Replay, m_LoadingBlocks.front( ) ); + Replay.append(m_LoadingBlocks.front( )); m_LoadingBlocks.dequeue( ); } Replay.push_back( REPLAY_THIRDSTARTBLOCK ); - UTIL_AppendBYTEARRAY( Replay, (quint32)1, false ); + Replay.append(Util::fromUInt32(1)); // done @@ -524,7 +524,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) QByteArray Block; Block.push_back( CReplay :: REPLAY_TIMESLOT ); - UTIL_AppendBYTEARRAY( Block, BlockSize, false ); + Block.append(Util::fromUInt32(BlockSize)); UTIL_AppendBYTEARRAY( Block, GarbageData, BlockSize ); m_Blocks.enqueue( Block ); } @@ -549,7 +549,7 @@ void CReplay :: ParseReplay( bool /*parseBlocks*/ ) QByteArray Block; Block.push_back( CReplay :: REPLAY_CHATMESSAGE ); Block.push_back( PID ); - UTIL_AppendBYTEARRAY( Block, BlockSize, false ); + Block.append(Util::fromUInt32(BlockSize)); UTIL_AppendBYTEARRAY( Block, GarbageData, BlockSize ); m_Blocks.enqueue( Block ); } diff --git a/ghost/statsdota.cpp b/ghost/statsdota.cpp index e8bc006..9d154d4 100644 --- a/ghost/statsdota.cpp +++ b/ghost/statsdota.cpp @@ -94,9 +94,9 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) Value = ActionData->mid(i + 8 + Data.size( ) + Key.size( ), 4 ); QString DataString = Data; QString KeyString = Key; - quint32 ValueInt = UTIL_QByteArrayToUInt32( Value, false ); + quint32 ValueInt = Util::extractUInt32( Value ); - // CONSOLE_Print( "[STATS] " + DataString + ", " + KeyString + ", " + UTIL_ToString( ValueInt ) ); + // CONSOLE_Print( "[STATS] " + DataString + ", " + KeyString + ", " + QString::number( ValueInt ) ); if( DataString == "Data" ) { @@ -108,8 +108,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { // a hero died - QString VictimColourString = KeyString.mid( 4 ); - quint32 VictimColour = UTIL_ToUInt32( VictimColourString ); + quint32 VictimColour = KeyString.mid( 4 ).toUInt(); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); CGamePlayer *Victim = m_Game->GetPlayerFromColour( VictimColour ); @@ -135,8 +134,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) m_Players[ValueInt]->SetCourierKills( m_Players[ValueInt]->GetCourierKills( ) + 1 ); } - QString VictimColourString = KeyString.mid( 7 ); - quint32 VictimColour = UTIL_ToUInt32( VictimColourString ); + quint32 VictimColour = KeyString.mid( 7 ).toUInt(); CGamePlayer *Killer = m_Game->GetPlayerFromColour( ValueInt ); CGamePlayer *Victim = m_Game->GetPlayerFromColour( VictimColour ); @@ -252,13 +250,13 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { // the frozen throne got hurt - CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Frozen Throne is now at " + UTIL_ToString( ValueInt ) + "% HP" ); + CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the Frozen Throne is now at " + QString::number( ValueInt ) + "% HP" ); } else if( KeyString.size( ) >= 4 && KeyString.mid( 0, 4 ) == "Tree" ) { // the world tree got hurt - CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the World Tree is now at " + UTIL_ToString( ValueInt ) + "% HP" ); + CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] the World Tree is now at " + QString::number( ValueInt ) + "% HP" ); } else if( KeyString.size( ) >= 2 && KeyString.mid( 0, 2 ) == "CK" ) { @@ -281,7 +279,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) else if( m_Winner == 2 ) CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] detected winner: Scourge" ); else - CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] detected winner: " + UTIL_ToString( ValueInt ) ); + CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] detected winner: " + QString::number( ValueInt ) ); } else if( KeyString == "m" ) m_Min = ValueInt; @@ -292,7 +290,7 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { // these are only received at the end of the game - quint32 ID = UTIL_ToUInt32( DataString ); + quint32 ID = DataString.toUInt(); if( ( ID >= 1 && ID <= 5 ) || ( ID >= 7 && ID <= 11 ) ) { @@ -332,19 +330,19 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) else if( KeyString == "7" ) m_Players[ID]->SetNeutralKills( ValueInt ); else if( KeyString == "8_0" ) - m_Players[ID]->SetItem( 0, QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetItem( 0, QString( Util::reverse(Value) ) ); else if( KeyString == "8_1" ) - m_Players[ID]->SetItem( 1, QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetItem( 1, QString( Util::reverse(Value) ) ); else if( KeyString == "8_2" ) - m_Players[ID]->SetItem( 2, QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetItem( 2, QString( Util::reverse(Value) ) ); else if( KeyString == "8_3" ) - m_Players[ID]->SetItem( 3, QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetItem( 3, QString( Util::reverse(Value) ) ); else if( KeyString == "8_4" ) - m_Players[ID]->SetItem( 4, QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetItem( 4, QString( Util::reverse(Value) ) ); else if( KeyString == "8_5" ) - m_Players[ID]->SetItem( 5, QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetItem( 5, QString( Util::reverse(Value) ) ); else if( KeyString == "9" ) - m_Players[ID]->SetHero( QString( UTIL_QByteArrayReverse(Value) ) ); + m_Players[ID]->SetHero( QString( Util::reverse(Value) ) ); else if( KeyString == "id" ) { // DotA sends id values from 1-10 with 1-5 being sentinel players and 6-10 being scourge players @@ -431,7 +429,7 @@ void CStatsDOTA :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) } if( DB->Commit( ) ) - CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] saving " + UTIL_ToString( Players ) + " players" ); + CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] saving " + QString::number( Players ) + " players" ); else CONSOLE_Print( "[STATSDOTA: " + m_Game->GetGameName( ) + "] unable to commit database transaction, data not saved" ); } diff --git a/ghost/statsw3mmd.cpp b/ghost/statsw3mmd.cpp index a223788..47d034a 100644 --- a/ghost/statsw3mmd.cpp +++ b/ghost/statsw3mmd.cpp @@ -77,17 +77,15 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) if( (unsigned int)ActionData->size( ) >= i + 15 + MissionKey.size( ) + Key.size( ) ) { Value = ActionData->mid(i + 11 + MissionKey.size( ) + Key.size( ), 4 ); - QString MissionKeyString = MissionKey; - QString KeyString = Key; //quint32 ValueInt = UTIL_QByteArrayToUInt32( Value, false ); - // CONSOLE_Print( "[STATSW3MMD] DEBUG: mkey [" + MissionKeyString + "], key [" + KeyString + "], value [" + UTIL_ToString( ValueInt ) + "]" ); + // CONSOLE_Print( "[STATSW3MMD] DEBUG: mkey [" + MissionKey + "], key [" + Key + "], value [" + QString::number(ValueInt) + "]" ); - if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "val:" ) + if( MissionKey.size( ) > 4 && MissionKey.mid( 0, 4 ) == "val:" ) { - QString ValueIDString = MissionKeyString.mid( 4 ); + //QByteArray ValueIDString = MissionKey.mid( 4 ); //quint32 ValueID = UTIL_ToUInt32( ValueIDString ); - QVector Tokens = TokenizeKey( KeyString ); + QVector Tokens = TokenizeKey( Key ); if( !Tokens.isEmpty( ) ) { @@ -100,7 +98,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] map is using Warcraft 3 Map Meta Data library version [" + Tokens[3] + "]" ); - if( UTIL_ToUInt32( Tokens[2] ) > 1 ) + if( Tokens[2].toUInt() > 1 ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] warning - parser version 1 is not compatible with this map, minimum version [" + Tokens[2] + "]" ); } else if( Tokens[1] == "pid" && Tokens.size( ) == 4 ) @@ -108,7 +106,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) // Tokens[2] = pid // Tokens[3] = name - quint32 PID = UTIL_ToUInt32( Tokens[2] ); + quint32 PID = Tokens[2].toUInt(); if( m_PIDToName.find( PID ) != m_PIDToName.end( ) ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] overwriting previous name [" + m_PIDToName[PID] + "] with new name [" + Tokens[3] + "] for PID [" + Tokens[2] + "]" ); @@ -124,13 +122,13 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) // Tokens[4] = suggestion (ignored here) if( m_DefVarPs.find( Tokens[1] ) != m_DefVarPs.end( ) ) - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] duplicate DefVarP [" + KeyString + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] duplicate DefVarP [" + Key + "] found, ignoring" ); else { if( Tokens[2] == "int" || Tokens[2] == "real" || Tokens[2] == "QString" ) m_DefVarPs[Tokens[1]] = Tokens[2]; else - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown DefVarP [" + KeyString + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown DefVarP [" + Key + "] found, ignoring" ); } } @@ -142,77 +140,77 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) // Tokens[4] = value if( m_DefVarPs.find( Tokens[2] ) == m_DefVarPs.end( ) ) - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] VarP [" + KeyString + "] found without a corresponding DefVarP, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] VarP [" + Key + "] found without a corresponding DefVarP, ignoring" ); else { QString ValueType = m_DefVarPs[Tokens[2]]; if( ValueType == "int" ) { - VarP VP = VarP( UTIL_ToUInt32( Tokens[1] ), Tokens[2] ); + VarP VP = VarP( Tokens[1].toUInt(), Tokens[2] ); if( Tokens[3] == "=" ) - m_VarPInts[VP] = UTIL_ToInt32( Tokens[4] ); + m_VarPInts[VP] = Tokens[4].toInt(); else if( Tokens[3] == "+=" ) { if( m_VarPInts.find( VP ) != m_VarPInts.end( ) ) - m_VarPInts[VP] += UTIL_ToInt32( Tokens[4] ); + m_VarPInts[VP] += Tokens[4].toInt(); else { - // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] int VarP [" + KeyString + "] found with relative operation [+=] without a previously assigned value, ignoring" ); - m_VarPInts[VP] = UTIL_ToInt32( Tokens[4] ); + // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] int VarP [" + Key + "] found with relative operation [+=] without a previously assigned value, ignoring" ); + m_VarPInts[VP] = Tokens[4].toInt(); } } else if( Tokens[3] == "-=" ) { if( m_VarPInts.find( VP ) != m_VarPInts.end( ) ) - m_VarPInts[VP] -= UTIL_ToInt32( Tokens[4] ); + m_VarPInts[VP] -= Tokens[4].toInt(); else { - // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] int VarP [" + KeyString + "] found with relative operation [-=] without a previously assigned value, ignoring" ); - m_VarPInts[VP] = -UTIL_ToInt32( Tokens[4] ); + // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] int VarP [" + Key + "] found with relative operation [-=] without a previously assigned value, ignoring" ); + m_VarPInts[VP] = -Tokens[4].toInt(); } } else - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown int VarP [" + KeyString + "] operation [" + Tokens[3] + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown int VarP [" + Key + "] operation [" + Tokens[3] + "] found, ignoring" ); } else if( ValueType == "real" ) { - VarP VP = VarP( UTIL_ToUInt32( Tokens[1] ), Tokens[2] ); + VarP VP = VarP( Tokens[1].toUInt(), Tokens[2] ); if( Tokens[3] == "=" ) - m_VarPReals[VP] = UTIL_ToDouble( Tokens[4] ); + m_VarPReals[VP] = Tokens[4].toDouble(); else if( Tokens[3] == "+=" ) { if( m_VarPReals.find( VP ) != m_VarPReals.end( ) ) - m_VarPReals[VP] += UTIL_ToDouble( Tokens[4] ); + m_VarPReals[VP] += Tokens[4].toDouble(); else { - // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] real VarP [" + KeyString + "] found with relative operation [+=] without a previously assigned value, ignoring" ); - m_VarPReals[VP] = UTIL_ToDouble( Tokens[4] ); + // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] real VarP [" + Key + "] found with relative operation [+=] without a previously assigned value, ignoring" ); + m_VarPReals[VP] = Tokens[4].toDouble(); } } else if( Tokens[3] == "-=" ) { if( m_VarPReals.find( VP ) != m_VarPReals.end( ) ) - m_VarPReals[VP] -= UTIL_ToDouble( Tokens[4] ); + m_VarPReals[VP] -= Tokens[4].toDouble(); else { - // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] real VarP [" + KeyString + "] found with relative operation [-=] without a previously assigned value, ignoring" ); - m_VarPReals[VP] = -UTIL_ToDouble( Tokens[4] ); + // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] real VarP [" + Key + "] found with relative operation [-=] without a previously assigned value, ignoring" ); + m_VarPReals[VP] = -Tokens[4].toDouble(); } } else - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown real VarP [" + KeyString + "] operation [" + Tokens[3] + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown real VarP [" + Key + "] operation [" + Tokens[3] + "] found, ignoring" ); } else { - VarP VP = VarP( UTIL_ToUInt32( Tokens[1] ), Tokens[2] ); + VarP VP = VarP( Tokens[1].toUInt(), Tokens[2]); if( Tokens[3] == "=" ) m_VarPStrings[VP] = Tokens[4]; else - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown QString VarP [" + KeyString + "] operation [" + Tokens[3] + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown QString VarP [" + Key + "] operation [" + Tokens[3] + "] found, ignoring" ); } } } @@ -223,7 +221,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) if( Tokens[2] == "winner" || Tokens[2] == "loser" || Tokens[2] == "drawer" || Tokens[2] == "leaver" || Tokens[2] == "practicing" ) { - quint32 PID = UTIL_ToUInt32( Tokens[1] ); + quint32 PID = Tokens[1].toUInt(); if( Tokens[2] == "leaver" ) m_FlagsLeaver[PID] = true; @@ -248,10 +246,10 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) // Tokens[n+3] = format if( m_DefEvents.find( Tokens[1] ) != m_DefEvents.end( ) ) - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] duplicate DefEvent [" + KeyString + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] duplicate DefEvent [" + Key + "] found, ignoring" ); else { - quint32 Arguments = UTIL_ToUInt32( Tokens[2] ); + quint32 Arguments = Tokens[2].toUInt(); if( (unsigned int)Tokens.size( ) == Arguments + 4 ) m_DefEvents[Tokens[1]] = Tokens.mid(3); @@ -263,17 +261,17 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) // Tokens[2..n+2] = arguments (where n is the # of arguments in the corresponding DefEvent) if( m_DefEvents.find( Tokens[1] ) == m_DefEvents.end( ) ) - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + KeyString + "] found without a corresponding DefEvent, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + Key + "] found without a corresponding DefEvent, ignoring" ); else { - QVector DefEvent = m_DefEvents[Tokens[1]]; + QVector DefEvent = m_DefEvents[Tokens[1]]; if( !DefEvent.isEmpty( ) ) { QString Format = DefEvent[DefEvent.size( ) - 1]; if( Tokens.size( ) - 2 != DefEvent.size( ) - 1 ) - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + KeyString + "] found with " + UTIL_ToString( Tokens.size( ) - 2 ) + " arguments but expected " + UTIL_ToString( DefEvent.size( ) - 1 ) + " arguments, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + Key + "] found with " + QString::number( Tokens.size( ) - 2 ) + " arguments but expected " + QString::number(DefEvent.size() - 1 ) + " arguments, ignoring" ); else { // replace the markers in the format QString with the arguments @@ -282,19 +280,19 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { // check if the marker is a PID marker - if( DefEvent[i].midRef( 0, 4 ) == "pid:" ) + if( DefEvent[i].mid( 0, 4 ) == "pid:" ) { // replace it with the player's name rather than their PID - quint32 PID = UTIL_ToUInt32( Tokens[i + 2] ); + quint32 PID = Tokens[i + 2].toUInt(); if( m_PIDToName.find( PID ) == m_PIDToName.end( ) ) - UTIL_Replace( Format, "{" + UTIL_ToString( i ) + "}", "PID:" + Tokens[i + 2] ); + Format.replace( "{" + QString::number(i) + "}", "PID:" + Tokens[i + 2] ); else - UTIL_Replace( Format, "{" + UTIL_ToString( i ) + "}", m_PIDToName[PID] ); + Format.replace( "{" + QString::number(i) + "}", m_PIDToName[PID] ); } else - UTIL_Replace( Format, "{" + UTIL_ToString( i ) + "}", Tokens[i + 2] ); + Format.replace( "{" + QString::number(i) + "}", Tokens[i + 2] ); } CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] " + Format ); @@ -302,7 +300,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) } } - // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] event [" + KeyString + "]" ); + // CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] event [" + Key + "]" ); } else if( Tokens[0] == "Blank" ) { @@ -310,7 +308,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) } else if( Tokens[0] == "Custom" ) { - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] custom [" + KeyString + "]" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] custom [" + Key + "]" ); } else CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown message type [" + Tokens[0] + "] found, ignoring" ); @@ -318,9 +316,9 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) m_NextValueID++; } - else if( MissionKeyString.size( ) > 4 && MissionKeyString.midRef( 0, 4 ) == "chk:" ) + else if( MissionKey.size( ) > 4 && MissionKey.mid( 0, 4 ) == "chk:" ) { - QString CheckIDString = MissionKeyString.mid( 4 ); + QString CheckIDString = MissionKey.mid( 4 ); //quint32 CheckID = UTIL_ToUInt32( CheckIDString ); // todotodo: cheat detection @@ -328,7 +326,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) m_NextCheckID++; } else - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown mission key [" + MissionKeyString + "] found, ignoring" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unknown mission key [" + MissionKey + "] found, ignoring" ); i += 15 + MissionKey.size( ) + Key.size( ); } @@ -350,14 +348,14 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) { - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] received " + UTIL_ToString( m_NextValueID ) + "/" + UTIL_ToString( m_NextCheckID ) + " value/check messages" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] received " + QString::number(m_NextValueID) + "/" + QString::number(m_NextCheckID) + " value/check messages" ); if( DB->Begin( ) ) { // todotodo: there's no reason to create a new callable for each entry in this map // rewrite ThreadedW3MMDPlayerAdd to act more like ThreadedW3MMDVarAdd - for( QMap :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) + for( QMap :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) { QString Flags = m_Flags[i.key()]; quint32 Leaver = 0; @@ -383,7 +381,7 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) Flags += "practicing"; } - CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] recorded flags [" + Flags + "] for player [" + i.value() + "] with PID [" + UTIL_ToString( i.key() ) + "]" ); + CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] recorded flags [" + Flags + "] for player [" + i.value() + "] with PID [" + QString::number( i.key() ) + "]" ); GHost->m_Callables.push_back( DB->ThreadedW3MMDPlayerAdd( m_Category, GameID, i.key(), i.value(), m_Flags[i.key()], Leaver, Practicing ) ); } @@ -405,13 +403,15 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unable to begin database transaction, data not saved" ); } -QVector CStatsW3MMD :: TokenizeKey( QString key ) +QVector CStatsW3MMD :: TokenizeKey( const QByteArray& key ) { - QVector Tokens; - QString Token; + QVector Tokens; + QByteArray Token; bool Escaping = false; - for( QString :: iterator i = key.begin( ); i != key.end( ); i++ ) + for( QByteArray::const_iterator i = key.begin(); + i != key.end(); + i++ ) { if( Escaping ) { @@ -422,7 +422,7 @@ QVector CStatsW3MMD :: TokenizeKey( QString key ) else { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], invalid escape sequence found, ignoring" ); - return QVector( ); + return QVector( ); } Escaping = false; @@ -434,7 +434,7 @@ QVector CStatsW3MMD :: TokenizeKey( QString key ) if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return QVector( ); + return QVector( ); } Tokens.push_back( Token ); @@ -450,7 +450,7 @@ QVector CStatsW3MMD :: TokenizeKey( QString key ) if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return QVector( ); + return QVector( ); } Tokens.push_back( Token ); diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index ecb5b47..abfe7b2 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -26,7 +26,7 @@ // #include -typedef QPair VarP; +typedef QPair VarP; class CStatsW3MMD : public CStats { @@ -34,15 +34,15 @@ class CStatsW3MMD : public CStats QString m_Category; quint32 m_NextValueID; quint32 m_NextCheckID; - QMap m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case - QMap m_Flags; // pid -> flag (e.g. 0 -> "winner") + QMap m_PIDToName; // pid -> player name (e.g. 0 -> "Varlock") --- note: will not be automatically converted to lower case + QMap m_Flags; // pid -> flag (e.g. 0 -> "winner") QMap m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true QMap m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true - QMap m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") + QMap m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") QMap m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) QMap m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) - QMap m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") - QMap > m_DefEvents; // event -> vector of arguments + format + QMap m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") + QMap > m_DefEvents; // event -> vector of arguments + format public: CStatsW3MMD( CBaseGame *nGame, QString nCategory ); @@ -50,7 +50,7 @@ class CStatsW3MMD : public CStats virtual bool ProcessAction( CIncomingAction *Action ); virtual void Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ); - virtual QVector TokenizeKey( QString key ); + virtual QVector TokenizeKey( const QByteArray& key ); }; #endif diff --git a/ghost/util.cpp b/ghost/util.cpp index 4338e95..9929a85 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -23,84 +23,40 @@ #include #include +#include -QByteArray UTIL_CreateBYTEARRAY( unsigned char c ) +quint16 Util::extractUInt16(const QByteArray& data, int offset) { - QByteArray result; - result.push_back( c ); - return result; + return qFromLittleEndian((uchar*)data.mid(offset, 2).data()); } -QByteArray UTIL_CreateBYTEARRAY( quint16 i, bool reverse ) +quint32 Util::extractUInt32(const QByteArray& data, int offset) { - QByteArray result; - - if (!reverse) - result.push_back( (unsigned char)i ); - - result.push_back( (unsigned char)( i >> 8 ) ); - - if (reverse) - result.push_back( (unsigned char)i ); - - return result; + return qFromLittleEndian((uchar*)data.mid(offset, 4).data()); } -QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ) +QByteArray Util::fromUInt16(const quint16 &value) { - QByteArray result; - - if( reverse ) - { - result.push_back( (unsigned char)( i >> 24 ) ); - result.push_back( (unsigned char)( i >> 16 ) ); - result.push_back( (unsigned char)( i >> 8 ) ); - result.push_back( (unsigned char)i ); - } - - else - { - result.push_back( (unsigned char)i ); - result.push_back( (unsigned char)( i >> 8 ) ); - result.push_back( (unsigned char)( i >> 16 ) ); - result.push_back( (unsigned char)( i >> 24 ) ); - } - - return result; + uchar dest[2]; + qToLittleEndian(value, dest); + return QByteArray((char*)dest, 2); } -quint16 UTIL_QByteArrayToUInt16( const QByteArray& b, bool reverse, unsigned int start ) +QByteArray Util::fromUInt32(const quint32 &value) { - if( (unsigned int)b.size( ) < start + 2 ) - return 0; - - QByteArray temp = b.mid(start, 2); - - if (reverse) - return (quint32)( (unsigned char)temp.at(0) << 8 | - (unsigned char)temp.at(1) << 0 ); - - return (quint32)( (unsigned char)temp.at(1) << 8 | - (unsigned char)temp.at(0) << 0 ); + uchar dest[4]; + qToLittleEndian(value, dest); + return QByteArray((char*)dest, 4); } -quint32 UTIL_QByteArrayToUInt32( const QByteArray& b, bool reverse, unsigned int start ) +QByteArray Util::reverse(const QByteArray &b) { - if( (unsigned int)b.size( ) < start + 4 ) - return 0; - - QByteArray temp = b.mid(start, 4); + QByteArray res; + QByteArray::const_iterator it; + for (it = b.end(); it != b.begin(); it--) + res.push_back(*it); - if (reverse) - return (quint32)( (unsigned char)temp.at(0) << 24 | - (unsigned char)temp.at(1) << 16 | - (unsigned char)temp.at(2) << 8 | - (unsigned char)temp.at(3) << 0 ); - - return (quint32)( (unsigned char)temp.at(3) << 24 | - (unsigned char)temp.at(2) << 16 | - (unsigned char)temp.at(1) << 8 | - (unsigned char)temp.at(0) << 0 ); + return res; } QString UTIL_QByteArrayToDecString( QByteArray b ) @@ -116,52 +72,6 @@ QString UTIL_QByteArrayToDecString( QByteArray b ) return result; } -QString UTIL_QByteArrayToHexString( QByteArray b ) -{ - return QString::fromAscii(b.toHex()); -} - -void UTIL_AppendBYTEARRAY( QByteArray &b, const QByteArray &append ) -{ - b.append(append); -} - -void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QByteArray &append ) -{ - b.append(append); -} - -void UTIL_AppendBYTEARRAY( QByteArray &b, unsigned char *a, int size ) -{ - b.append((char*)a, size); -} - -void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator ) -{ - b.append(append); - - if( terminator ) - b.push_back( (char)0 ); -} - -void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QString &append, bool terminator ) -{ - b.append(append.toUtf8()); - - if( terminator ) - b.push_back( (char)0 ); -} - -void UTIL_AppendBYTEARRAY( QByteArray &b, quint16 i, bool reverse ) -{ - b.append( UTIL_CreateBYTEARRAY( i, reverse ) ); -} - -void UTIL_AppendBYTEARRAY( QByteArray &b, quint32 i, bool reverse ) -{ - b.append( UTIL_CreateBYTEARRAY( i, reverse ) ); -} - QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ) { // start searching the byte array at position 'start' for the first null value @@ -205,133 +115,6 @@ QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ) return result; } -QByteArray UTIL_ExtractHexNumbers( QString s ) -{ - // consider the QString to contain a QByteArray in hex-text form, e.g. "4e 17 b7 e6" - - QByteArray result; - unsigned int c; - QTextStream SS(&s); - - - while( !SS.atEnd() ) - { - SS >> hex >> c; - - // todotodo: if c > 255 handle the error instead of truncating - - result.push_back( (unsigned char)c ); - } - - return result; -} - -QString UTIL_ToString( unsigned long i ) -{ - return QString::number(i); -} - -QString UTIL_ToString( unsigned short i ) -{ - return QString::number(i); -} - -QString UTIL_ToString( unsigned int i ) -{ - return QString::number(i); -} - -QString UTIL_ToString( long i ) -{ - return QString::number(i); -} - -QString UTIL_ToString( short i ) -{ - return QString::number(i); -} - -QString UTIL_ToString( int i ) -{ - return QString::number(i); -} - -QString UTIL_ToString( float f, int digits ) -{ - return QString::number(f, 'g', digits); -} - -QString UTIL_ToString( double d, int digits ) -{ - return QString::number(d, 'g', digits); -} - -QString UTIL_ToHexString( quint32 i ) -{ - return QString::number(i, 16); -} - -// todotodo: these UTIL_ToXXX functions don't fail gracefully, they just return garbage (in the uint case usually just -1 casted to an unsigned type it looks like) - -quint16 UTIL_ToUInt16( QString &s ) -{ - return s.toUShort(); -} - -quint32 UTIL_ToUInt32( QString &s ) -{ - return s.toUInt(); -} - -int16_t UTIL_ToInt16( QString &s ) -{ - return s.toShort(); -} - -int32_t UTIL_ToInt32( QString &s ) -{ - return s.toInt(); -} - -double UTIL_ToDouble( QString &s ) -{ - return s.toDouble(); -} - -QString UTIL_MSToString( quint32 ms ) -{ - QString MinString = UTIL_ToString( ( ms / 1000 ) / 60 ); - QString SecString = UTIL_ToString( ( ms / 1000 ) % 60 ); - - if( MinString.size( ) == 1 ) - MinString.insert( 0, "0" ); - - if( SecString.size( ) == 1 ) - SecString.insert( 0, "0" ); - - return MinString + "m" + SecString + "s"; -} - -bool UTIL_FileExists( QString file ) -{ - return QFile::exists(file); -} - -QByteArray UTIL_FileRead( QString file, quint32 start, quint32 length ) -{ - QFile f(file); - f.open(QFile::ReadOnly); - - if (f.error() != QFile::NoError) - { - CONSOLE_Print( "[UTIL] warning - unable to read file part [" + file + "]" ); - return QByteArray(); - } - - f.seek(start); - return f.read(length); -} - QByteArray UTIL_FileRead( QString file ) { QFile f(file); @@ -408,37 +191,6 @@ QByteArray UTIL_EncodeStatString( QByteArray &data ) return Result; } -QByteArray UTIL_QByteArrayReverse(const QByteArray &b) -{ - QByteArray res; - QByteArray::const_iterator it; - for (it = b.end(); it != b.begin(); it--) - res.push_back(*it); - - return res; -} - -QByteArray UTIL_DecodeStatString( QByteArray &data ) -{ - unsigned char Mask; - QByteArray Result; - - for( int i = 0; i < data.size( ); i++ ) - { - if( ( i % 8 ) == 0 ) - Mask = data[i]; - else - { - if( ( Mask & ( 1 << ( i % 8 ) ) ) == 0 ) - Result.push_back( data[i] - 1 ); - else - Result.push_back( data[i] ); - } - } - - return Result; -} - bool UTIL_IsLanIP( QByteArray ip ) { if( ip.size( ) != 4 ) @@ -486,11 +238,6 @@ bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ) return false; } -void UTIL_Replace( QString &Text, QString Key, QString Value ) -{ - Text.replace(Key, Value); -} - QVector UTIL_Tokenize( QString s, char delim ) { QVector Tokens; @@ -525,3 +272,4 @@ quint32 UTIL_Factorial( quint32 x ) return Factorial; } + diff --git a/ghost/util.h b/ghost/util.h index cc4d527..cb04b74 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -24,51 +24,29 @@ #include #include #include +#include + +class Util +{ +public: + static quint16 extractUInt16(const QByteArray& data, int offset = 0); + static quint32 extractUInt32(const QByteArray& data, int offset = 0); + + static QByteArray fromUInt16(const quint16 &value); + static QByteArray fromUInt32(const quint32 &value); + + static QByteArray reverse(const QByteArray &b); +}; // byte arrays -QByteArray UTIL_CreateBYTEARRAY( unsigned char c ); -QByteArray UTIL_CreateBYTEARRAY( quint16 i, bool reverse ); -QByteArray UTIL_CreateBYTEARRAY( quint32 i, bool reverse ); -quint16 UTIL_QByteArrayToUInt16( const QByteArray& b, bool reverse, unsigned int start = 0 ); -quint32 UTIL_QByteArrayToUInt32( const QByteArray& b, bool reverse, unsigned int start = 0 ); QString UTIL_QByteArrayToDecString( QByteArray b ); -QString UTIL_QByteArrayToHexString( QByteArray b ); -void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QByteArray &append ); -void UTIL_AppendBYTEARRAY( QByteArray &b, const QByteArray &append ); -void UTIL_AppendBYTEARRAY( QByteArray &b, unsigned char *a, int size ); -void UTIL_AppendBYTEARRAY( QByteArray &b, QString append, bool terminator ); -void UTIL_AppendBYTEARRAYFast( QByteArray &b, const QString &append, bool terminator = true ); -void UTIL_AppendBYTEARRAY( QByteArray &b, quint16 i, bool reverse ); -void UTIL_AppendBYTEARRAY( QByteArray &b, quint32 i, bool reverse ); QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ); unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ); QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ); -QByteArray UTIL_ExtractHexNumbers( QString s ); -QByteArray UTIL_QByteArrayReverse(const QByteArray &b); - -// conversions - -QString UTIL_ToString( unsigned long i ); -QString UTIL_ToString( unsigned short i ); -QString UTIL_ToString( unsigned int i ); -QString UTIL_ToString( long i ); -QString UTIL_ToString( short i ); -QString UTIL_ToString( int i ); -QString UTIL_ToString( float f, int digits ); -QString UTIL_ToString( double d, int digits ); -QString UTIL_ToHexString( quint32 i ); -quint16 UTIL_ToUInt16( QString &s ); -quint32 UTIL_ToUInt32( QString &s ); -int16_t UTIL_ToInt16( QString &s ); -int32_t UTIL_ToInt32( QString &s ); -double UTIL_ToDouble( QString &s ); -QString UTIL_MSToString( quint32 ms ); // files -bool UTIL_FileExists( QString file ); -QByteArray UTIL_FileRead( QString file, quint32 start, quint32 length ); QByteArray UTIL_FileRead( QString file ); bool UTIL_FileWrite( QString file, const QByteArray &data ); QString UTIL_FileSafeName( QString fileName ); @@ -77,13 +55,11 @@ QString UTIL_AddPathSeperator( QString path ); // stat strings QByteArray UTIL_EncodeStatString( QByteArray &data ); -QByteArray UTIL_DecodeStatString( QByteArray &data ); // other bool UTIL_IsLanIP( QByteArray ip ); bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ); -void UTIL_Replace( QString &Text, QString Key, QString Value ); QVector UTIL_Tokenize( QString s, char delim ); // math From b59e77ce173fa08e3ecf10611985dceb3af441ce Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Fri, 23 Apr 2010 00:14:52 +0000 Subject: [PATCH 46/69] bugfix --- ghost/bncsutilinterface.cpp | 27 ++++++++++++++------------- ghost/bncsutilinterface.h | 10 ++++++---- ghost/bnet.cpp | 18 +++++++++++------- ghost/bnet.h | 4 ++-- ghost/bnetprotocol.cpp | 2 +- ghost/bnetprotocol.h | 20 ++++++++++---------- ghost/ghost.cpp | 2 +- ghost/ghost.h | 2 +- 8 files changed, 46 insertions(+), 39 deletions(-) diff --git a/ghost/bncsutilinterface.cpp b/ghost/bncsutilinterface.cpp index 45ee376..7376a01 100644 --- a/ghost/bncsutilinterface.cpp +++ b/ghost/bncsutilinterface.cpp @@ -49,17 +49,19 @@ void CBNCSUtilInterface :: Reset( QString userName, QString userPassword ) m_NLS = new NLS( userName.toStdString(), userPassword.toStdString() ); } -bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, QByteArray clientToken, QByteArray serverToken ) +bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, const QByteArray& war3Path, const QByteArray & keyROC, + const QByteArray & keyTFT, const QByteArray & valueStringFormula, const QByteArray & mpqFileName, + const QByteArray & clientToken, const QByteArray & serverToken ) { // set m_EXEVersion, m_EXEVersionHash, m_EXEInfo, m_InfoROC, m_InfoTFT - QString FileWar3EXE = war3Path + "war3.exe"; - QString FileStormDLL = war3Path + "Storm.dll"; + QByteArray FileWar3EXE = war3Path + "war3.exe"; + QByteArray FileStormDLL = war3Path + "Storm.dll"; if( !QFile::exists( FileStormDLL ) ) FileStormDLL = war3Path + "storm.dll"; - QString FileGameDLL = war3Path + "game.dll"; + QByteArray FileGameDLL = war3Path + "game.dll"; bool ExistsWar3EXE = QFile::exists( FileWar3EXE ); bool ExistsStormDLL = QFile::exists( FileStormDLL ); bool ExistsGameDLL = QFile::exists( FileGameDLL ); @@ -67,14 +69,13 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QStr if( ExistsWar3EXE && ExistsStormDLL && ExistsGameDLL ) { // todotodo: check getExeInfo return value to ensure 1024 bytes was enough - char buf[1024]; quint32 EXEVersion; - getExeInfo( FileWar3EXE.toStdString().c_str( ), (char *)&buf, 1024, (quint32 *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); + getExeInfo( FileWar3EXE.data( ), (char *)&buf, 1024, (quint32 *)&EXEVersion, BNCSUTIL_PLATFORM_X86 ); m_EXEInfo = buf; m_EXEVersion = Util::fromUInt32( EXEVersion); quint32 EXEVersionHash; - checkRevisionFlat( valueStringFormula.toStdString().c_str( ), FileWar3EXE.toStdString().c_str( ), FileStormDLL.toStdString().c_str( ), FileGameDLL.toStdString().c_str( ), extractMPQNumber( mpqFileName.toStdString().c_str( ) ), (unsigned long *)&EXEVersionHash ); + checkRevisionFlat( valueStringFormula.data( ), FileWar3EXE.data( ), FileStormDLL.data( ), FileGameDLL.data( ), extractMPQNumber( mpqFileName.data( ) ), (unsigned long *)&EXEVersionHash ); m_EXEVersionHash = Util::fromUInt32( EXEVersionHash); m_KeyInfoROC = CreateKeyInfo( keyROC, Util::extractUInt32(clientToken), Util::extractUInt32(serverToken) ); @@ -118,32 +119,32 @@ bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGON( ) return true; } -bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray salt, QByteArray serverKey ) +bool CBNCSUtilInterface :: HELP_SID_AUTH_ACCOUNTLOGONPROOF( const QByteArray & salt, const QByteArray & serverKey ) { // set m_M1 char buf[20]; - // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).toStdString().c_str( ), QString( salt.begin( ), salt.end( ) ).toStdString().c_str( ) ); + // nls_get_M1( (nls_t *)m_nls, buf, QString( serverKey.begin( ), serverKey.end( ) ).data( ), QString( salt.begin( ), salt.end( ) ).data( ) ); ( (NLS *)m_NLS )->getClientSessionKey( buf, salt.data(), serverKey.data() ); m_M1 = QByteArray( (char *)buf, 20 ); return true; } -bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( QString userPassword ) +bool CBNCSUtilInterface :: HELP_PvPGNPasswordHash( const QByteArray &userPassword ) { // set m_PvPGNPasswordHash char buf[20]; - hashPassword( userPassword.toStdString().c_str( ), buf ); + hashPassword( userPassword.data( ), buf ); m_PvPGNPasswordHash = QByteArray( (char *)buf, 20 ); return true; } -QByteArray CBNCSUtilInterface :: CreateKeyInfo( QString key, quint32 clientToken, quint32 serverToken ) +QByteArray CBNCSUtilInterface :: CreateKeyInfo( const QByteArray & key, quint32 clientToken, quint32 serverToken ) { unsigned char Zeros[] = { 0, 0, 0, 0 }; QByteArray KeyInfo; - CDKeyDecoder Decoder( key.toStdString().c_str( ), key.size( ) ); + CDKeyDecoder Decoder( key.data(), key.size( ) ); if( Decoder.isKeyValid( ) ) { diff --git a/ghost/bncsutilinterface.h b/ghost/bncsutilinterface.h index eefadde..fe72cbb 100644 --- a/ghost/bncsutilinterface.h +++ b/ghost/bncsutilinterface.h @@ -24,6 +24,7 @@ // // CBNCSUtilInterface // +#include "includes.h" class CBNCSUtilInterface { @@ -56,13 +57,14 @@ class CBNCSUtilInterface void Reset( QString userName, QString userPassword ); - bool HELP_SID_AUTH_CHECK( bool TFT, QString war3Path, QString keyROC, QString keyTFT, QString valueStringFormula, QString mpqFileName, QByteArray clientToken, QByteArray serverToken ); + bool HELP_SID_AUTH_CHECK( bool TFT, const QByteArray & war3Path, const QByteArray & keyROC, const QByteArray & keyTFT, + const QByteArray & valueStringFormula, const QByteArray & mpqFileName, const QByteArray & clientToken, const QByteArray & serverToken ); bool HELP_SID_AUTH_ACCOUNTLOGON( ); - bool HELP_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray salt, QByteArray serverKey ); - bool HELP_PvPGNPasswordHash( QString userPassword ); + bool HELP_SID_AUTH_ACCOUNTLOGONPROOF( const QByteArray & salt, const QByteArray & serverKey ); + bool HELP_PvPGNPasswordHash( const QByteArray & userPassword ); private: - QByteArray CreateKeyInfo( QString key, quint32 clientToken, quint32 serverToken ); + QByteArray CreateKeyInfo( const QByteArray & key, quint32 clientToken, quint32 serverToken ); }; #endif diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 4ee4b34..8dff302 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -103,8 +103,8 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_BNLSServer = nBNLSServer; m_BNLSPort = nBNLSPort; m_BNLSWardenCookie = nBNLSWardenCookie; - m_CDKeyROC = nCDKeyROC; - m_CDKeyTFT = nCDKeyTFT; + m_CDKeyROC = nCDKeyROC.toAscii(); + m_CDKeyTFT = nCDKeyTFT.toAscii(); // remove dashes from CD keys and convert to uppercase @@ -328,7 +328,7 @@ void CBNET::EnqueuePacket(const QByteArray &pkg) return; } - QTimer::singleShot(getWaitTicks() - m_LastPacketSent.elapsed(), this, SLOT(SendPacket())); + QTimer::singleShot(ticks - m_LastPacketSent.elapsed(), this, SLOT(SendPacket())); } void CBNET::SendPacket() @@ -732,7 +732,9 @@ void CBNET :: ProcessPackets( ) case CBNETProtocol :: SID_AUTH_INFO: if( m_Protocol->RECEIVE_SID_AUTH_INFO( Packet->GetData( ) ) ) { - if( m_BNCSUtil->HELP_SID_AUTH_CHECK( m_GHost->m_TFT, m_GHost->m_Warcraft3Path, m_CDKeyROC, m_CDKeyTFT, m_Protocol->GetValueStringFormulaString( ), m_Protocol->GetIX86VerFileNameString( ), m_Protocol->GetClientToken( ), m_Protocol->GetServerToken( ) ) ) + if( m_BNCSUtil->HELP_SID_AUTH_CHECK( m_GHost->m_TFT, m_GHost->m_Warcraft3Path, m_CDKeyROC, m_CDKeyTFT, + m_Protocol->GetValueStringFormulaString( ), m_Protocol->GetIX86VerFileNameString( ), + m_Protocol->GetClientToken( ), m_Protocol->GetServerToken( ) ) ) { // override the exe information generated by bncsutil if specified in the config file // apparently this is useful for pvpgn users @@ -754,7 +756,9 @@ void CBNET :: ProcessPackets( ) else CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: Reign of Chaos" ); - m_Socket->write( m_Protocol->SEND_SID_AUTH_CHECK( m_GHost->m_TFT, m_Protocol->GetClientToken( ), m_BNCSUtil->GetEXEVersion( ), m_BNCSUtil->GetEXEVersionHash( ), m_BNCSUtil->GetKeyInfoROC( ), m_BNCSUtil->GetKeyInfoTFT( ), m_BNCSUtil->GetEXEInfo( ), "GHost" ) ); + m_Socket->write( m_Protocol->SEND_SID_AUTH_CHECK( m_GHost->m_TFT, m_Protocol->GetClientToken( ), m_BNCSUtil->GetEXEVersion( ), + m_BNCSUtil->GetEXEVersionHash( ), m_BNCSUtil->GetKeyInfoROC( ), m_BNCSUtil->GetKeyInfoTFT( ), + m_BNCSUtil->GetEXEInfo( ), "GHost" ) ); // the Warden seed is the first 4 bytes of the ROC key hash // initialize the Warden handler @@ -808,7 +812,7 @@ void CBNET :: ProcessPackets( ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - game version is invalid, disconnecting" ); break; default: - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - cd keys not accepted, disconnecting" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - cd keys not accepted ("+QString::number(Util::extractUInt32(m_Protocol->GetKeyState( )))+"), disconnecting" ); break; } @@ -829,7 +833,7 @@ void CBNET :: ProcessPackets( ) // pvpgn logon CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using pvpgn logon type (for pvpgn servers only)" ); - m_BNCSUtil->HELP_PvPGNPasswordHash( m_UserPassword ); + m_BNCSUtil->HELP_PvPGNPasswordHash( m_UserPassword.toAscii() ); m_Socket->write( m_Protocol->SEND_SID_AUTH_ACCOUNTLOGONPROOF( m_BNCSUtil->GetPvPGNPasswordHash( ) ) ); } else diff --git a/ghost/bnet.h b/ghost/bnet.h index 7fca80c..8d5296d 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -115,8 +115,8 @@ public slots: QString m_BNLSServer; // BNLS server to connect to (for warden handling) quint16 m_BNLSPort; // BNLS port quint32 m_BNLSWardenCookie; // BNLS warden cookie - QString m_CDKeyROC; // ROC CD key - QString m_CDKeyTFT; // TFT CD key + QByteArray m_CDKeyROC; // ROC CD key + QByteArray m_CDKeyTFT; // TFT CD key QString m_CountryAbbrev; // country abbreviation QString m_Country; // country quint32 m_LocaleID; // see: http://msdn.microsoft.com/en-us/library/0h88fahh%28VS.85%29.aspx diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index 7b2963d..ead25ed 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -845,7 +845,7 @@ QByteArray CBNETProtocol :: SEND_SID_AUTH_CHECK( bool TFT, QByteArray clientToke packet.append(exeVersion); // EXE Version packet.append(exeVersionHash); // EXE Version Hash packet.append(Util::fromUInt32(NumKeys)); // number of keys in this packet - packet.append(Util::fromUInt16(0)); // boolean Using Spawn (32 bit) + packet.append(Util::fromUInt32(0)); // boolean Using Spawn (32 bit) packet.append(keyInfoROC); // ROC Key Info if( TFT ) diff --git a/ghost/bnetprotocol.h b/ghost/bnetprotocol.h index 575871b..400219c 100644 --- a/ghost/bnetprotocol.h +++ b/ghost/bnetprotocol.h @@ -94,30 +94,30 @@ class CBNETProtocol QByteArray m_ServerToken; // set in RECEIVE_SID_AUTH_INFO QByteArray m_MPQFileTime; // set in RECEIVE_SID_AUTH_INFO QByteArray m_IX86VerFileName; // set in RECEIVE_SID_AUTH_INFO - QByteArray m_ValueStringFormula; // set in RECEIVE_SID_AUTH_INFO + QByteArray m_ValueStringFormula; // set in RECEIVE_SID_AUTH_INFO QByteArray m_KeyState; // set in RECEIVE_SID_AUTH_CHECK QByteArray m_KeyStateDescription; // set in RECEIVE_SID_AUTH_CHECK QByteArray m_Salt; // set in RECEIVE_SID_AUTH_ACCOUNTLOGON QByteArray m_ServerPublicKey; // set in RECEIVE_SID_AUTH_ACCOUNTLOGON - QByteArray m_UniqueName; // set in RECEIVE_SID_ENTERCHAT + QByteArray m_UniqueName; // set in RECEIVE_SID_ENTERCHAT public: CBNETProtocol( ); ~CBNETProtocol( ); QByteArray GetClientToken( ) { return m_ClientToken; } - QByteArray GetLogonType( ) { return m_LogonType; } + QByteArray GetLogonType( ) { return m_LogonType; } QByteArray GetServerToken( ) { return m_ServerToken; } QByteArray GetMPQFileTime( ) { return m_MPQFileTime; } QByteArray GetIX86VerFileName( ) { return m_IX86VerFileName; } - QString GetIX86VerFileNameString( ) { return m_IX86VerFileName; } - QByteArray GetValueStringFormula( ) { return m_ValueStringFormula; } - QString GetValueStringFormulaString( ) { return m_ValueStringFormula; } - QByteArray GetKeyState( ) { return m_KeyState; } - QString GetKeyStateDescription( ) { return m_KeyStateDescription; } - QByteArray GetSalt( ) { return m_Salt; } + QByteArray GetIX86VerFileNameString( ) { return m_IX86VerFileName; } + QByteArray GetValueStringFormula( ) { return m_ValueStringFormula; } + QByteArray GetValueStringFormulaString( ) { return m_ValueStringFormula; } + QByteArray GetKeyState( ) { return m_KeyState; } + QByteArray GetKeyStateDescription( ) { return m_KeyStateDescription; } + QByteArray GetSalt( ) { return m_Salt; } QByteArray GetServerPublicKey( ) { return m_ServerPublicKey; } - QByteArray GetUniqueName( ) { return m_UniqueName; } + QByteArray GetUniqueName( ) { return m_UniqueName; } // receive functions diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 8d8087a..d3e1479 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -840,7 +840,7 @@ void CGHost :: SetConfigs( CConfig *CFG ) m_LanguageFile = CFG->GetString( "bot_language", "language.cfg" ); delete m_Language; m_Language = new CLanguage( m_LanguageFile ); - m_Warcraft3Path = UTIL_AddPathSeperator( CFG->GetString( "bot_war3path", "C:\\Program Files\\Warcraft III\\" ) ); + m_Warcraft3Path = UTIL_AddPathSeperator( CFG->GetString( "bot_war3path", "C:\\Program Files\\Warcraft III\\" ) ).toAscii(); m_BindAddress = CFG->GetString( "bot_bindaddress", QString( ) ); m_ReconnectWaitTime = CFG->GetInt( "bot_reconnectwaittime", 3 ); m_MaxGames = CFG->GetInt( "bot_maxgames", 5 ); diff --git a/ghost/ghost.h b/ghost/ghost.h index c7082cc..0a0e96c 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -100,7 +100,7 @@ public slots: bool m_AllGamesFinished; // if all games finished (used when exiting nicely) quint32 m_AllGamesFinishedTime; // GetTime when all games finished (used when exiting nicely) QString m_LanguageFile; // config value: language file - QString m_Warcraft3Path; // config value: Warcraft 3 path + QByteArray m_Warcraft3Path; // config value: Warcraft 3 path bool m_TFT; // config value: TFT enabled or not QString m_BindAddress; // config value: the address to host games on quint16 m_HostPort; // config value: the port to host games on From b5b9dcdb53b783dd95442fbfeba867ed2a432a38 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Fri, 23 Apr 2010 00:22:05 +0000 Subject: [PATCH 47/69] localAddress \-\> peerAddress --- ghost/gameplayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index b3a98e7..6abec21 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -160,7 +160,7 @@ void CGamePlayer::EventConnectionClosed() QByteArray CPotentialPlayer :: GetExternalIP( ) { if( m_Socket ) - return Util::fromUInt32(m_Socket->localAddress().toIPv4Address()); + return Util::fromUInt32(m_Socket->peerAddress().toIPv4Address()); unsigned char Zeros[] = { 0, 0, 0, 0 }; return QByteArray( (char*)Zeros, 4 ); @@ -169,7 +169,7 @@ QByteArray CPotentialPlayer :: GetExternalIP( ) QString CPotentialPlayer :: GetExternalIPString( ) { if( m_Socket ) - return m_Socket->localAddress().toString(); + return m_Socket->peerAddress().toString(); return QString( ); } From 864c735da727ce097f977f095e695bbe6f7ffad0 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Fri, 23 Apr 2010 00:52:31 +0000 Subject: [PATCH 48/69] bugfixes in lagging --- ghost/bnet.cpp | 20 ++++++------ ghost/game.cpp | 22 ++++++------- ghost/game_base.cpp | 68 +++++++++++++++++------------------------ ghost/game_base.h | 4 +-- ghost/gameplayer.cpp | 9 ++++++ ghost/ghostdbsqlite.cpp | 4 +-- 6 files changed, 62 insertions(+), 65 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 8dff302..deba459 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -517,7 +517,7 @@ void CBNET::EventCallableUpdateTimeout() CDBGamePlayerSummary *GamePlayerSummary = i->second->GetResult( ); if( GamePlayerSummary ) - QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( 2, (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); else QueueChatCommand( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); @@ -550,15 +550,15 @@ void CBNET::EventCallableUpdateTimeout() QString::number( DotAPlayerSummary->GetTotalTowerKills( ) ), QString::number( DotAPlayerSummary->GetTotalRaxKills( ) ), QString::number( DotAPlayerSummary->GetTotalCourierKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgDeaths( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgCreepKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgCreepDenies( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgAssists( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgNeutralKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgTowerKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgRaxKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgCourierKills( ) ) ); + QString::number( DotAPlayerSummary->GetAvgKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgDeaths( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgCreepKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgCreepDenies( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgAssists( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgNeutralKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgTowerKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgRaxKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgCourierKills( ), 'g', 2 ) ); QueueChatCommand( Summary, i->first, !i->first.isEmpty( ) ); } diff --git a/ghost/game.cpp b/ghost/game.cpp index eb342dd..30afd59 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -208,13 +208,13 @@ void CGame::EventCallableUpdateTimeout() if( GamePlayerSummary ) { if( i->first.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( 2, (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); + SendAllChat( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); else { CGamePlayer *Player = GetPlayerFromName( i->first, true ); if( Player ) - SendChat( Player, m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( 2, (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); + SendChat( Player, m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); } } else @@ -259,15 +259,15 @@ void CGame::EventCallableUpdateTimeout() QString::number( DotAPlayerSummary->GetTotalTowerKills( ) ), QString::number( DotAPlayerSummary->GetTotalRaxKills( ) ), QString::number( DotAPlayerSummary->GetTotalCourierKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgDeaths( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgCreepKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgCreepDenies( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgAssists( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgNeutralKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgTowerKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgRaxKills( ) ), - QString::number( 2, DotAPlayerSummary->GetAvgCourierKills( ) ) ); + QString::number( DotAPlayerSummary->GetAvgKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgDeaths( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgCreepKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgCreepDenies( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgAssists( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgNeutralKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgTowerKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgRaxKills( ), 'g', 2 ), + QString::number( DotAPlayerSummary->GetAvgCourierKills( ), 'g', 2 ) ); if( i->first.isEmpty( ) ) SendAllChat( Summary ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 89a5a93..c3a3239 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -162,7 +162,6 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 m_StartPlayers = 0; m_LastActionSentTicks = 0; m_StartedLaggingTime = 0; - m_LastLagScreenTime = 0; m_LastPlayerLeaveTicks = 0; m_MinimumScore = 0.0; m_MaximumScore = 0.0; @@ -1229,6 +1228,7 @@ void CBaseGame::CheckPlayersStartedLaggging() (*i)->SetDropVote( false ); m_ResetLagscreenTimer.start(); + m_SendActionTimer.stop(); } } @@ -1314,21 +1314,15 @@ void CBaseGame::EventPlayerStoppedLagging() if( !m_Lagging ) return; - // check if anyone has stopped lagging normally - // we consider a player to have stopped lagging if they're less than half m_SyncLimit keepalives behind + CGamePlayer *player = (CGamePlayer*)QObject::sender(); + if (player == NULL) + return; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - { - if( (*i)->GetLagging( ) && m_SyncCounter - (*i)->GetSyncCounter( ) < m_SyncLimit / 2 ) - { - // stop the lag screen for this player + // we consider a player to have stopped lagging if they're less than half m_SyncLimit keepalives behind - CONSOLE_Print( "[GAME: " + m_GameName + "] stopped lagging on [" + (*i)->GetName( ) + "]" ); - SendAll( m_Protocol->SEND_W3GS_STOP_LAG( *i ) ); - (*i)->SetLagging( false ); - (*i)->SetStartedLaggingTicks( 0 ); - } - } + CONSOLE_Print( "[GAME: " + m_GameName + "] stopped lagging on [" + player->GetName( ) + "]" ); + SendAll( m_Protocol->SEND_W3GS_STOP_LAG( player ) ); + player->SetStartedLaggingTicks( 0 ); // check if everyone has stopped lagging @@ -1345,16 +1339,10 @@ void CBaseGame::EventPlayerStoppedLagging() if (!m_Lagging) { m_DropLaggerTimer.stop(); + + // we continue to send actions m_SendActionTimer.start(); } - - // reset m_LastActionSentTicks because we want the game to stop running while the lag screen is up - - m_LastActionSentTicks = GetTicks( ); - - // keep track of the last lag screen time so we can avoid timing out players - - m_LastLagScreenTime = GetTime( ); } void CBaseGame :: EventPlayerDeleted() @@ -2108,7 +2096,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score > -99999.0 && ( score < m_MinimumScore || score > m_MaximumScore ) ) { - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has a rating [" + QString::number( 2, score ) + "] outside the limits [" + QString::number( 2, m_MinimumScore ) + "] to [" + QString::number( 2, m_MaximumScore ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has a rating [" + QString::number( score, 'g', 2 ) + "] outside the limits [" + QString::number( m_MinimumScore, 'g', 2 ) + "] to [" + QString::number( m_MaximumScore, 'g', 2 ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); return; @@ -2201,9 +2189,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score < -99999.0 || abs( score - AverageScore ) > abs( FurthestPlayer->GetScore( ) - AverageScore ) ) { if( score < -99999.0 ) - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [N/A] from the average [" + QString::number( 2, AverageScore ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [N/A] from the average [" + QString::number( AverageScore, 'g', 2 ) + "]" ); else - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [" + QString::number( 2, score ) + "] from the average [" + QString::number( 2, AverageScore ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the furthest rating [" + QString::number( score, 'g', 2 ) + "] from the average [" + QString::number( AverageScore, 'g', 2 ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); @@ -2215,9 +2203,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SID = GetSIDFromPID( FurthestPlayer->GetPID( ) ); if( FurthestPlayer->GetScore( ) < -99999.0 ) - FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", QString::number( 2, AverageScore ) ) ); + FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", QString::number( AverageScore, 'g', 2 ) ) ); else - FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( QString::number( 2, FurthestPlayer->GetScore( ) ), QString::number( 2, AverageScore ) ) ); + FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( QString::number( FurthestPlayer->GetScore( ), 'g', 2 ), QString::number( AverageScore, 'g', 2 ) ) ); FurthestPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2229,9 +2217,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco FurthestPlayer->deleteLater(); if( FurthestPlayer->GetScore( ) < -99999.0 ) - SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", QString::number( 2, AverageScore ) ) ); + SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", QString::number( AverageScore, 'g', 2 ) ) ); else - SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), QString::number( 2, FurthestPlayer->GetScore( ) ), QString::number( 2, AverageScore ) ) ); + SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), QString::number( FurthestPlayer->GetScore( ), 'g', 2 ), QString::number( AverageScore, 'g', 2 ) ) ); } else if( m_GHost->m_MatchMakingMethod == 2 ) { @@ -2263,7 +2251,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score < -99999.0 ) CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [N/A]" ); else - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [" + QString::number( 2, score ) + "]" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but has the lowest rating [" + QString::number( score, 'g', 2 ) + "]" ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); @@ -2277,7 +2265,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( LowestPlayer->GetScore( ) < -99999.0 ) LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( "N/A" ) ); else - LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( QString::number( 2, LowestPlayer->GetScore( ) ) ) ); + LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( QString::number( LowestPlayer->GetScore( ), 'g', 2 ) ) ); LowestPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2291,7 +2279,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( LowestPlayer->GetScore( ) < -99999.0 ) SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), "N/A" ) ); else - SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), QString::number( 2, LowestPlayer->GetScore( ) ) ) ); + SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), QString::number( LowestPlayer->GetScore( ), 'g', 2 ) ) ); } } @@ -2420,7 +2408,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( score < -99999.0 ) SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), "N/A" ) ); else - SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), QString::number( 2, score ) ) ); + SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), QString::number( score, 'g', 2 ) ) ); quint32 PlayersScored = 0; quint32 PlayersNotScored = 0; @@ -2518,7 +2506,7 @@ void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) void CBaseGame :: EventPlayerLoaded() { CGamePlayer *player = (CGamePlayer*)QObject::sender(); - CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] finished loading in " + QString::number( 2, (float)( player->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) + " seconds" ); + CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] finished loading in " + QString::number( (float)( player->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g' ) + " seconds" ); if( m_LoadInGame ) { @@ -3056,8 +3044,8 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map float Seconds = (float)( GetTicks( ) - player->GetStartedDownloadingTicks( ) ) / 1000; float Rate = (float)MapSize / 1024 / Seconds; - CONSOLE_Print( "[GAME: " + m_GameName + "] map download finished for player [" + player->GetName( ) + "] in " + QString::number( 1, Seconds ) + " seconds" ); - SendAllChat( m_GHost->m_Language->PlayerDownloadedTheMap( player->GetName( ), QString::number( 1, Seconds ), QString::number( 1, Rate ) ) ); + CONSOLE_Print( "[GAME: " + m_GameName + "] map download finished for player [" + player->GetName( ) + "] in " + QString::number( Seconds, 'g', 1 ) + " seconds" ); + SendAllChat( m_GHost->m_Language->PlayerDownloadedTheMap( player->GetName( ), QString::number( Seconds, 'g', 1 ), QString::number( Rate, 'g', 1 ) ) ); player->SetDownloadFinished( true ); player->SetFinishedDownloadingTime( GetTime( ) ); @@ -3357,12 +3345,12 @@ void CBaseGame :: EventGameLoaded( ) if( Shortest && Longest ) { - SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), QString::number( 2, (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) ) ); - SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), QString::number( 2, (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) ) ); + SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), QString::number( (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); + SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), QString::number( (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); } for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( QString::number( 2, (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000 ) ) ); + SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( QString::number( (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); // read from gameloaded.txt if available @@ -4206,7 +4194,7 @@ void CBaseGame :: BalanceSlots( ) } if( TeamHasPlayers ) - SendAllChat( m_GHost->m_Language->TeamCombinedScore( QString::number( i + 1 ), QString::number( 2, TeamScore ) ) ); + SendAllChat( m_GHost->m_Language->TeamCombinedScore( QString::number( i + 1 ), QString::number( TeamScore, 'g', 2 ) ) ); } } diff --git a/ghost/game_base.h b/ghost/game_base.h index 510e92d..c248cb8 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -141,7 +141,6 @@ public slots: quint32 m_StartPlayers; // number of players when the game started quint32 m_LastActionSentTicks; // GetTicks when the last action packet was sent quint32 m_StartedLaggingTime; // GetTime when the last lag screen started - quint32 m_LastLagScreenTime; // GetTime when the last lag screen was active (continuously updated) quint32 m_LastPlayerLeaveTicks; // GetTicks when the most recent player left the game double m_MinimumScore; // the minimum allowed score for matchmaking mode double m_MaximumScore; // the maximum allowed score for matchmaking mode @@ -177,7 +176,6 @@ public slots: virtual QString GetCreatorName( ) { return m_CreatorName; } virtual QString GetCreatorServer( ) { return m_CreatorServer; } virtual quint32 GetHostCounter( ) { return m_HostCounter; } - virtual quint32 GetLastLagScreenTime( ) { return m_LastLagScreenTime; } virtual quint32 GetStartedLaggingTime( ) { return m_StartedLaggingTime; } virtual quint32 GetAutoStartPlayers( ) { return m_AutoStartPlayers; } virtual bool GetLocked( ) { return m_Locked; } @@ -199,6 +197,8 @@ public slots: virtual quint32 GetNumPlayers( ); virtual quint32 GetNumHumanPlayers( ); virtual QString GetDescription( ); + quint32 GetSyncCounter() { return m_SyncCounter; } + quint32 GetSyncLimit() { return m_SyncLimit; } virtual void SetAnnounce( quint32 interval, QString message ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 6abec21..abc3c07 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -396,6 +396,7 @@ void CGamePlayer::init() QObject::connect(this, SIGNAL(finishedLoading()), m_Game, SLOT(EventPlayerLoaded())); QObject::connect(this, SIGNAL(aboutToDelete()), m_Game, SLOT(EventPlayerDeleted())); + QObject::connect(this, SIGNAL(stoppedLagging()), m_Game, SLOT(EventPlayerStoppedLagging())); m_SendGProxyMessageTimer.setInterval(20000); QObject::connect(&m_SendGProxyMessageTimer, SIGNAL(timeout()), this, SLOT(EventSendGProxyMessage())); @@ -411,6 +412,7 @@ void CGamePlayer::init() CGamePlayer :: ~CGamePlayer( ) { + emit stoppedLagging(); } void CGamePlayer::EventSendGProxyMessage() @@ -518,6 +520,13 @@ void CGamePlayer :: ProcessPackets( ) quint32 CheckSum = 0; quint32 Pong = 0; + if( m_Lagging && m_Game->GetSyncCounter() - m_SyncCounter < m_Game->GetSyncLimit() / 2 ) + { + // stop the lag screen for this player + m_Lagging = false; + emit stoppedLagging(); + } + // process all the received packets in the m_Packets queue while( !m_Packets.isEmpty( ) ) diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index b479140..ea6e943 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -1405,7 +1405,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_reals if( RC == SQLITE_ERROR ) { Success = false; - CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-real [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( 10, i.value() ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] error adding w3mmdvar-real [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( i.value(), 'g', 10 ) + "] - " + m_DB->GetError( ) ); break; } @@ -1414,7 +1414,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_reals else { Success = false; - CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-real [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( 10, i.value() ) + "] - " + m_DB->GetError( ) ); + CONSOLE_Print( "[SQLITE3] prepare error adding w3mmdvar-real [" + QString::number( gameid ) + " : " + QString::number( i.key().first ) + " : " + i.key().second + " : " + QString::number( i.value(), 'g', 10 ) + "] - " + m_DB->GetError( ) ); break; } } From 462aee41e8b9c257101417384aa114fb9ece74c1 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sat, 24 Apr 2010 00:10:27 +0000 Subject: [PATCH 49/69] fixed some win32 issues --- StormLib/StormLibDll.sln | 4 +- StormLib/StormLibDll.vcproj | 111 ++++++++++++++++++------------------ ghost/bncsutilinterface.cpp | 2 + ghost/ghost.pro | 18 ++++-- ghost/main.cpp | 3 + ghost/util.cpp | 2 +- 6 files changed, 77 insertions(+), 63 deletions(-) diff --git a/StormLib/StormLibDll.sln b/StormLib/StormLibDll.sln index 61fdb2a..a84df24 100644 --- a/StormLib/StormLibDll.sln +++ b/StormLib/StormLibDll.sln @@ -1,6 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLibDll", "StormLibDll.vcproj", "{A22DEC27-4BA6-479F-AF9C-0229ACFD7E3A}" EndProject Global diff --git a/StormLib/StormLibDll.vcproj b/StormLib/StormLibDll.vcproj index b4ec7eb..6bb65ca 100644 --- a/StormLib/StormLibDll.vcproj +++ b/StormLib/StormLibDll.vcproj @@ -1,10 +1,11 @@ @@ -100,15 +103,12 @@ - - #include diff --git a/ghost/ghost.pro b/ghost/ghost.pro index ae6c996..18028b8 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -44,11 +44,21 @@ OTHER_FILES += w3g_format.txt \ w3g_actions.txt \ ghost.vcproj INCLUDEPATH += ../StormLib \ - ../bncsutil/src + ../bncsutil/src \ + ../zlib/include LIBS += -L../StormLib/stormlib \ - -L../bncsutil/src/bncsutil \ - -lbncsutil \ - -lStorm + -L../bncsutil/src/bncsutil \ + -L. \ + -L"../bncsutil/vc8_build/Release MySQL" \ + -lbncsutil + win32 { + LIBS += -lStormLibRAS +} + +!win32 { + LIBS += -lStorm +} + HEADERS += util.h \ statsw3mmd.h \ statsdota.h \ diff --git a/ghost/main.cpp b/ghost/main.cpp index a27088a..aa6b1ab 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -8,6 +8,9 @@ #include "ghost.h" #include "util.h" #include "config.h" +#ifdef WIN32 +#include "windows.h" +#endif QTime gBasicTime; QFile gLogFile; diff --git a/ghost/util.cpp b/ghost/util.cpp index 9929a85..9329bb2 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -53,7 +53,7 @@ QByteArray Util::reverse(const QByteArray &b) { QByteArray res; QByteArray::const_iterator it; - for (it = b.end(); it != b.begin(); it--) + for (it = b.end() - 1; it == b.begin(); it--) res.push_back(*it); return res; From b6ae31547e1ffbdf0612cd9b7ceb1aa05be6fd53 Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 7 May 2010 00:15:56 +0000 Subject: [PATCH 50/69] ghost.qt: added frameworks and libs necessary for compiling on mac os x. --- ghost/ghost.pro | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ghost/ghost.pro b/ghost/ghost.pro index 18028b8..946acde 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -59,6 +59,11 @@ LIBS += -L../StormLib/stormlib \ LIBS += -lStorm } +macx { + LIBS += -framework CoreFoundation -framework CoreServices + LIBS += -L/usr/lib -lbz2 -lz +} + HEADERS += util.h \ statsw3mmd.h \ statsdota.h \ From f0f097a2154ee01988d67608952b492d1383bb13 Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 7 May 2010 00:31:14 +0000 Subject: [PATCH 51/69] ghost.qt: fixed typo in function name and dumped macro for QDir functionality --- ghost/ghost.cpp | 10 +++++----- ghost/util.cpp | 13 ++++--------- ghost/util.h | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index d3e1479..3f1ba0a 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -840,7 +840,7 @@ void CGHost :: SetConfigs( CConfig *CFG ) m_LanguageFile = CFG->GetString( "bot_language", "language.cfg" ); delete m_Language; m_Language = new CLanguage( m_LanguageFile ); - m_Warcraft3Path = UTIL_AddPathSeperator( CFG->GetString( "bot_war3path", "C:\\Program Files\\Warcraft III\\" ) ).toAscii(); + m_Warcraft3Path = UTIL_AddPathSeparator( CFG->GetString( "bot_war3path", "C:\\Program Files\\Warcraft III\\" ) ).toAscii(); m_BindAddress = CFG->GetString( "bot_bindaddress", QString( ) ); m_ReconnectWaitTime = CFG->GetInt( "bot_reconnectwaittime", 3 ); m_MaxGames = CFG->GetInt( "bot_maxgames", 5 ); @@ -850,11 +850,11 @@ void CGHost :: SetConfigs( CConfig *CFG ) BotCommandTrigger = "!"; m_CommandTrigger = BotCommandTrigger[0].toAscii(); - m_MapCFGPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mapcfgpath", QString( ) ) ); - m_SaveGamePath = UTIL_AddPathSeperator( CFG->GetString( "bot_savegamepath", QString( ) ) ); - m_MapPath = UTIL_AddPathSeperator( CFG->GetString( "bot_mappath", QString( ) ) ); + m_MapCFGPath = UTIL_AddPathSeparator( CFG->GetString( "bot_mapcfgpath", QString( ) ) ); + m_SaveGamePath = UTIL_AddPathSeparator( CFG->GetString( "bot_savegamepath", QString( ) ) ); + m_MapPath = UTIL_AddPathSeparator( CFG->GetString( "bot_mappath", QString( ) ) ); m_SaveReplays = CFG->GetInt( "bot_savereplays", 0 ) == 0 ? false : true; - m_ReplayPath = UTIL_AddPathSeperator( CFG->GetString( "bot_replaypath", QString( ) ) ); + m_ReplayPath = UTIL_AddPathSeparator( CFG->GetString( "bot_replaypath", QString( ) ) ); m_VirtualHostName = CFG->GetString( "bot_virtualhostname", "|cFF4080C0GHost" ); m_HideIPAddresses = CFG->GetInt( "bot_hideipaddresses", 0 ) == 0 ? false : true; m_CheckMultipleIPUsage = CFG->GetInt( "bot_checkmultipleipusage", 1 ) == 0 ? false : true; diff --git a/ghost/util.cpp b/ghost/util.cpp index 9329bb2..599c4bb 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -24,6 +24,7 @@ #include #include #include +#include quint16 Util::extractUInt16(const QByteArray& data, int offset) { @@ -149,21 +150,15 @@ QString UTIL_FileSafeName( QString fileName ) return fileName.replace(QRegExp("\\\\\\/\\:\\*\\?\\<\\>\\|"), "_"); } -QString UTIL_AddPathSeperator( QString path ) +QString UTIL_AddPathSeparator( QString path ) { if( path.isEmpty( ) ) return path; -#ifdef WIN32 - QString Seperator = "\\"; -#else - QString Seperator = "/"; -#endif - - if( path.right(1) == Seperator ) + if( path.right(1) == QDir::separator() ) return path; else - return path + Seperator; + return path + QDir::separator(); } QByteArray UTIL_EncodeStatString( QByteArray &data ) diff --git a/ghost/util.h b/ghost/util.h index cb04b74..0adcdbb 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -50,7 +50,7 @@ QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ); QByteArray UTIL_FileRead( QString file ); bool UTIL_FileWrite( QString file, const QByteArray &data ); QString UTIL_FileSafeName( QString fileName ); -QString UTIL_AddPathSeperator( QString path ); +QString UTIL_AddPathSeparator( QString path ); // stat strings From 27b5a3aa860cf9ba4e4329c3354be18b8a50a1e1 Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 7 May 2010 11:20:37 +0000 Subject: [PATCH 52/69] ghost.qt: replaced QVector with QList for performance reasons (see http://doc.trolltech.com/4.6/qlist.html , section "Detailed Description") changed iterator to const_iterator where applicable (performance) --- ghost/bnet.cpp | 68 ++++++------ ghost/bnet.h | 24 ++--- ghost/bnetprotocol.cpp | 8 +- ghost/bnetprotocol.h | 4 +- ghost/game.cpp | 58 +++++----- ghost/game.h | 12 +-- ghost/game_admin.cpp | 50 ++++----- ghost/game_admin.h | 14 +-- ghost/game_base.cpp | 232 ++++++++++++++++++++-------------------- ghost/game_base.h | 24 ++--- ghost/gameplayer.cpp | 2 +- ghost/gameplayer.h | 2 +- ghost/gameprotocol.cpp | 12 +-- ghost/gameprotocol.h | 8 +- ghost/ghost.cpp | 55 +++++----- ghost/ghost.h | 11 +- ghost/ghostdb.cpp | 8 +- ghost/ghostdb.h | 16 +-- ghost/ghostdbmysql.cpp | 40 +++---- ghost/ghostdbmysql.h | 4 +- ghost/ghostdbsqlite.cpp | 24 ++--- ghost/ghostdbsqlite.h | 8 +- ghost/includes.h | 2 +- ghost/map.cpp | 16 +-- ghost/map.h | 4 +- ghost/packed.cpp | 4 +- ghost/replay.cpp | 2 +- ghost/replay.h | 10 +- ghost/savegame.h | 4 +- ghost/statsw3mmd.cpp | 16 +-- ghost/statsw3mmd.h | 4 +- ghost/util.cpp | 12 +-- ghost/util.h | 6 +- 33 files changed, 379 insertions(+), 385 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index deba459..6ff238f 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -160,34 +160,34 @@ CBNET :: ~CBNET( ) delete m_BNCSUtil; - for( QVector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) + for( QList :: const_iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) delete *i; - for( QVector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) + for( QList :: const_iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) delete *i; - for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) + for( QList :: const_iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) + for( QList :: const_iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) + for( QList :: const_iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) + for( QList :: const_iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) + for( QList :: const_iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); if( m_CallableAdminList ) @@ -196,7 +196,7 @@ CBNET :: ~CBNET( ) if( m_CallableBanList ) m_GHost->m_Callables.push_back( m_CallableBanList ); - for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QList :: const_iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) delete *i; } @@ -388,7 +388,7 @@ void CBNET::EventCallableUpdateTimeout() // update callables // - for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) + for( QList :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) { if( i->second->GetReady( ) ) { @@ -409,7 +409,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) + for( QList :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) { if( i->second->GetReady( ) ) { @@ -429,7 +429,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) + for( QList :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) { if( i->second->GetReady( ) ) { @@ -449,7 +449,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) + for( QList :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) { if( i->second->GetReady( ) ) { @@ -470,7 +470,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) + for( QList :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) { if( i->second->GetReady( ) ) { @@ -490,7 +490,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) + for( QList :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) { if( i->second->GetReady( ) ) { @@ -510,7 +510,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) + for( QList :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -529,7 +529,7 @@ void CBNET::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) + for( QList :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -587,7 +587,7 @@ void CBNET::EventCallableUpdateTimeout() { // CONSOLE_Print( "[BNET: " + m_ServerAlias + "] refreshed ban list (" + QString::number( m_Bans.size( ) ) + " -> " + QString::number( m_CallableBanList->GetResult( ).size( ) ) + " bans)" ); - for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QList :: const_iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) delete *i; m_Bans = m_CallableBanList->GetResult( ); @@ -654,8 +654,8 @@ void CBNET :: ProcessPackets( ) CIncomingGameHost *GameHost = NULL; CIncomingChatEvent *ChatEvent = NULL; QByteArray WardenData; - QVector Friends; - QVector Clans; + QList Friends; + QList Clans; // process all the received packets in the m_Packets queue // this normally means sending some kind of response @@ -902,16 +902,16 @@ void CBNET :: ProcessPackets( ) case CBNETProtocol :: SID_FRIENDSLIST: Friends = m_Protocol->RECEIVE_SID_FRIENDSLIST( Packet->GetData( ) ); - for( QVector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) + for( QList :: const_iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) delete *i; m_Friends = Friends; break; case CBNETProtocol :: SID_CLANMEMBERLIST: - QVector Clans = m_Protocol->RECEIVE_SID_CLANMEMBERLIST( Packet->GetData( ) ); + QList Clans = m_Protocol->RECEIVE_SID_CLANMEMBERLIST( Packet->GetData( ) ); - for( QVector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) + for( QList :: const_iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) delete *i; m_Clans = Clans; @@ -961,7 +961,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { // the equivalent pvpgn message is: [PvPGN Realm] Your friend abc has entered a Warcraft III Frozen Throne game named "xyz". - QVector Tokens = UTIL_Tokenize( Message, ' ' ); + QList Tokens = UTIL_Tokenize( Message, ' ' ); if( Tokens.size( ) >= 3 ) m_GHost->m_CurrentGame->AddToSpoofed( m_Server, Tokens[2], false ); @@ -1943,7 +1943,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( m_GHost->m_CurrentGame ) m_GHost->m_CurrentGame->SendAllChat( Payload ); - for( QVector :: iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) (*i)->SendAllChat( "ADMIN: " + Payload ); } else @@ -2416,7 +2416,7 @@ bool CBNET :: IsAdmin( QString name ) { name = name.toLower(); - for( QVector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) + for( QList :: const_iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) { if( *i == name ) return true; @@ -2456,7 +2456,7 @@ CDBBan *CBNET :: IsBannedName( QString name ) // todotodo: optimize this - maybe use a map? - for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QList :: const_iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) { if( (*i)->GetName( ) == name ) return *i; @@ -2469,7 +2469,7 @@ CDBBan *CBNET :: IsBannedIP( QString ip ) { // todotodo: optimize this - maybe use a map? - for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) + for( QList :: const_iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) { if( (*i)->GetIP( ) == ip ) return *i; @@ -2494,7 +2494,7 @@ void CBNET :: RemoveAdmin( QString name ) { name = name.toLower(); - for( QVector :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) + for( QList :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) { if( *i == name ) i = m_Admins.erase( i ); @@ -2507,7 +2507,7 @@ void CBNET :: RemoveBan( QString name ) { name = name.toLower(); - for( QVector :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); ) + for( QList :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); ) { if( (*i)->GetName( ) == name ) i = m_Bans.erase( i ); @@ -2520,7 +2520,7 @@ void CBNET :: HoldFriends( CBaseGame *game ) { if( game ) { - for( QVector :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) + for( QList :: const_iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ ) game->AddToReserved( (*i)->GetAccount( ) ); } } @@ -2529,7 +2529,7 @@ void CBNET :: HoldClan( CBaseGame *game ) { if( game ) { - for( QVector :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) + for( QList :: const_iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ ) game->AddToReserved( (*i)->GetName( ) ); } } diff --git a/ghost/bnet.h b/ghost/bnet.h index 8d5296d..c785a52 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -95,20 +95,20 @@ public slots: QQueue m_Packets; // queue of incoming packets CBNCSUtilInterface *m_BNCSUtil; // the interface to the bncsutil library (used for logging into battle.net) QQueue m_OutPackets; // queue of outgoing packets to be sent (to prevent getting kicked for flooding) - QVector m_Friends; // vector of friends - QVector m_Clans; // vector of clan members - QVector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress - QVector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress - QVector m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress - QVector m_PairedBanCounts; // vector of paired threaded database ban counts in progress - QVector m_PairedBanAdds; // vector of paired threaded database ban adds in progress - QVector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress - QVector m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress - QVector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress + QList m_Friends; // vector of friends + QList m_Clans; // vector of clan members + QList m_PairedAdminCounts; // vector of paired threaded database admin counts in progress + QList m_PairedAdminAdds; // vector of paired threaded database admin adds in progress + QList m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress + QList m_PairedBanCounts; // vector of paired threaded database ban counts in progress + QList m_PairedBanAdds; // vector of paired threaded database ban adds in progress + QList m_PairedBanRemoves; // vector of paired threaded database ban removes in progress + QList m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress + QList m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress CCallableAdminList *m_CallableAdminList; // threaded database admin list in progress CCallableBanList *m_CallableBanList; // threaded database ban list in progress - QVector m_Admins; // vector of cached admins - QVector m_Bans; // vector of cached bans + QList m_Admins; // vector of cached admins + QList m_Bans; // vector of cached bans QString m_Server; // battle.net server to connect to QString m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) QString m_ServerAlias; // battle.net server alias (short name, e.g. "USEast") diff --git a/ghost/bnetprotocol.cpp b/ghost/bnetprotocol.cpp index ead25ed..45c4c69 100644 --- a/ghost/bnetprotocol.cpp +++ b/ghost/bnetprotocol.cpp @@ -336,7 +336,7 @@ QByteArray CBNETProtocol :: RECEIVE_SID_WARDEN( QByteArray data ) return QByteArray( ); } -QVector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteArray data ) +QList CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_FRIENDSLIST" ); // DEBUG_Print( data ); @@ -351,7 +351,7 @@ QVector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteAr // 4 bytes -> ??? // null term QString -> Location - QVector Friends; + QList Friends; if( ValidateLength( data ) && data.size( ) >= 5 ) { @@ -386,7 +386,7 @@ QVector CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteAr return Friends; } -QVector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteArray data ) +QList CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteArray data ) { // DEBUG_Print( "RECEIVED SID_CLANMEMBERLIST" ); // DEBUG_Print( data ); @@ -401,7 +401,7 @@ QVector CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteA // 1 byte -> Status // null term QString -> Location - QVector ClanList; + QList ClanList; if( ValidateLength( data ) && data.size( ) >= 9 ) { diff --git a/ghost/bnetprotocol.h b/ghost/bnetprotocol.h index 400219c..1f4c798 100644 --- a/ghost/bnetprotocol.h +++ b/ghost/bnetprotocol.h @@ -134,8 +134,8 @@ class CBNETProtocol bool RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ); bool RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ); QByteArray RECEIVE_SID_WARDEN( QByteArray data ); - QVector RECEIVE_SID_FRIENDSLIST( QByteArray data ); - QVector RECEIVE_SID_CLANMEMBERLIST( QByteArray data ); + QList RECEIVE_SID_FRIENDSLIST( QByteArray data ); + QList RECEIVE_SID_CLANMEMBERLIST( QByteArray data ); CIncomingClanList *RECEIVE_SID_CLANMEMBERSTATUSCHANGE( QByteArray data ); // send functions diff --git a/ghost/game.cpp b/ghost/game.cpp index 30afd59..1aa61bd 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -94,7 +94,7 @@ void CGame::EventGameDataSaved() // store the CDBGamePlayers in the database - for( QVector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) + for( QList :: const_iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) m_GHost->m_Callables.push_back( m_GHost->m_DB->ThreadedGamePlayerAdd( m_CallableGameAdd->GetResult( ), (*i)->GetName( ), (*i)->GetIP( ), (*i)->GetSpoofed( ), (*i)->GetSpoofedRealm( ), (*i)->GetReserved( ), (*i)->GetLoadingTime( ), (*i)->GetLeft( ), (*i)->GetLeftReason( ), (*i)->GetTeam( ), (*i)->GetColour( ) ) ); // store the stats in the database @@ -119,24 +119,24 @@ CGame :: ~CGame( ) m_CallableGameAdd = NULL; } - for( QVector :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) + for( QList :: const_iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) + for( QList :: const_iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) + for( QList :: const_iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) delete *i; delete m_DBGame; - for( QVector :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) + for( QList :: const_iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) delete *i; delete m_Stats; @@ -157,7 +157,7 @@ void CGame::EventCallableUpdateTimeout() { // update callables - for( QVector :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); ) + for( QList :: iterator i = m_PairedBanChecks.begin( ); i != m_PairedBanChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -176,13 +176,13 @@ void CGame::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) + for( QList :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QList :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); @@ -199,7 +199,7 @@ void CGame::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) + for( QList :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -238,7 +238,7 @@ void CGame::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) + for( QList :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); ) { if( i->second->GetReady( ) ) { @@ -332,7 +332,7 @@ void CGame :: EventPlayerDeleted() // also keep track of the last player to leave for the !banlast command - for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) + for( QList :: const_iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) { if( (*i)->GetName( ) == player->GetName( ) ) m_DBBanLast = *i; @@ -366,7 +366,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri bool AdminCheck = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == player->GetSpoofedRealm( ) && (*i)->IsAdmin( User ) ) { @@ -377,7 +377,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri bool RootAdminCheck = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == player->GetSpoofedRealm( ) && (*i)->IsRootAdmin( User ) ) { @@ -444,7 +444,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") // we use the m_DBBans vector for this in case the player already left and thus isn't in the m_Players vector anymore - for( QVector :: iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) + for( QList :: const_iterator i = m_DBBans.begin( ); i != m_DBBans.end( ); i++ ) { QString TestName = (*i)->GetName( ).toLower(); @@ -592,7 +592,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { bool LastMatchAdminCheck = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == LastMatch->GetSpoofedRealm( ) && (*i)->IsAdmin( LastMatch->GetName( ) ) ) { @@ -603,7 +603,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri bool LastMatchRootAdminCheck = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == LastMatch->GetSpoofedRealm( ) && (*i)->IsRootAdmin( LastMatch->GetName( ) ) ) { @@ -627,7 +627,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "checkban" && !Payload.isEmpty( ) && !m_GHost->m_BNETs.isEmpty( ) ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) m_PairedBanChecks.push_back( PairedBanCheck( User, m_GHost->m_DB->ThreadedBanCheck( (*i)->GetServer( ), Payload, QString( ) ) ) ); } @@ -1003,7 +1003,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { QString Froms; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { // we reverse the byte order on the IP because it's stored in network byte order @@ -1272,11 +1272,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // copy the m_Players vector so we can sort by descending ping so it's easier to find players with high pings - QVector SortedPlayers = m_Players; + QList SortedPlayers = m_Players; qSort(SortedPlayers); QString Pings; - for( QVector :: iterator i = SortedPlayers.begin( ); i != SortedPlayers.end( ); i++ ) + for( QList :: const_iterator i = SortedPlayers.begin( ); i != SortedPlayers.end( ); i++ ) { Pings += (*i)->GetNameTerminated( ); Pings += ": "; @@ -1333,7 +1333,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_RefreshError = false; m_RefreshRehosted = true; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // unqueue any existing game refreshes because we're going to assume the next successful game refresh indicates that the rehost worked // this ignores the fact that it's possible a game refresh was just sent and no response has been received yet @@ -1369,7 +1369,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_RefreshError = false; m_RefreshRehosted = true; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // unqueue any existing game refreshes because we're going to assume the next successful game refresh indicates that the rehost worked // this ignores the fact that it's possible a game refresh was just sent and no response has been received yet @@ -1409,7 +1409,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "say" && !Payload.isEmpty( ) ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Payload ); HideCommand = true; @@ -1646,7 +1646,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri Name = Payload.mid( 0, MessageStart ); Message = Payload.mid( MessageStart + 1 ); - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Message, Name, true ); } @@ -1754,7 +1754,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_KickVotePlayer = LastMatch->GetName( ); m_VotekickTimer.start(); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->SetKickVote( false ); player->SetKickVote( true ); @@ -1778,7 +1778,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 VotesNeeded = (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ); quint32 Votes = 0; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetKickVote( ) ) Votes++; @@ -1827,7 +1827,7 @@ void CGame :: EventGameStarted( ) // but since the player has already left the game we don't have access to their information anymore // so we create a "potential ban" for each player and only store it in the database if requested to by an admin - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) m_DBBans.push_back( new CDBBan( (*i)->GetJoinedRealm( ), (*i)->GetName( ), (*i)->GetExternalIPString( ), QString( ), QString( ), QString( ), QString( ) ) ); } diff --git a/ghost/game.h b/ghost/game.h index 974ae7c..a55336e 100644 --- a/ghost/game.h +++ b/ghost/game.h @@ -56,15 +56,15 @@ public slots: protected: CDBBan *m_DBBanLast; // last ban for the !banlast command - this is a pointer to one of the items in m_DBBans - QVector m_DBBans; // vector of potential ban data for the database (see the Update function for more info, it's not as straightforward as you might think) + QList m_DBBans; // vector of potential ban data for the database (see the Update function for more info, it's not as straightforward as you might think) CDBGame *m_DBGame; // potential game data for the database - QVector m_DBGamePlayers; // vector of potential gameplayer data for the database + QList m_DBGamePlayers; // vector of potential gameplayer data for the database CStats *m_Stats; // class to keep track of game stats such as kills/deaths/assists in dota CCallableGameAdd *m_CallableGameAdd; // threaded database game addition in progress - QVector m_PairedBanChecks; // vector of paired threaded database ban checks in progress - QVector m_PairedBanAdds; // vector of paired threaded database ban adds in progress - QVector m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress - QVector m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress + QList m_PairedBanChecks; // vector of paired threaded database ban checks in progress + QList m_PairedBanAdds; // vector of paired threaded database ban adds in progress + QList m_PairedGPSChecks; // vector of paired threaded database game player summary checks in progress + QList m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress public: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); diff --git a/ghost/game_admin.cpp b/ghost/game_admin.cpp index 5213ed5..88d703d 100644 --- a/ghost/game_admin.cpp +++ b/ghost/game_admin.cpp @@ -52,26 +52,26 @@ CAdminGame :: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quin CAdminGame :: ~CAdminGame( ) { - for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) + for( QList :: const_iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) + for( QList :: const_iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) + for( QList :: const_iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); - for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); /* - for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); */ - for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) + for( QList :: const_iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ ) m_GHost->m_Callables.push_back( i->second ); } @@ -81,7 +81,7 @@ void CAdminGame::EventCallableUpdateTimeout() // update callables // - for( QVector :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) + for( QList :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); ) { if( i->second->GetReady( ) ) { @@ -107,13 +107,13 @@ void CAdminGame::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) + for( QList :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QList :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->AddAdmin( i->second->GetUser( ) ); @@ -138,13 +138,13 @@ void CAdminGame::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) + for( QList :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QList :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->RemoveAdmin( i->second->GetUser( ) ); @@ -169,7 +169,7 @@ void CAdminGame::EventCallableUpdateTimeout() i++; } - for( QVector :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) + for( QList :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); ) { if( i->second->GetReady( ) ) { @@ -197,13 +197,13 @@ void CAdminGame::EventCallableUpdateTimeout() /* - for( QVector :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) + for( QList :: const_iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QList :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); @@ -230,13 +230,13 @@ void CAdminGame::EventCallableUpdateTimeout() */ - for( QVector :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) + for( QList :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); ) { if( i->second->GetReady( ) ) { if( i->second->GetResult( ) ) { - for( QVector :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) + for( QList :: iterator j = m_GHost->m_BNETs.begin( ); j != m_GHost->m_BNETs.end( ); j++ ) { if( (*j)->GetServer( ) == i->second->GetServer( ) ) (*j)->RemoveBan( i->second->GetUser( ) ); @@ -266,7 +266,7 @@ void CAdminGame::EventCallableUpdateTimeout() void CAdminGame :: SendAdminChat( QString message ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLoggedIn( ) ) SendChat( *i, message ); @@ -289,7 +289,7 @@ void CAdminGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoin { quint32 Time = GetTime( ); - for( QVector :: iterator i = m_TempBans.begin( ); i != m_TempBans.end( ); ) + for( QList :: iterator i = m_TempBans.begin( ); i != m_TempBans.end( ); ) { // remove old tempbans (after 5 seconds) @@ -362,7 +362,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Servers; bool FoundServer = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); @@ -567,7 +567,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Servers; bool FoundServer = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); @@ -622,7 +622,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Servers; bool FoundServer = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); @@ -708,7 +708,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QString Servers; bool FoundServer = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( Servers.isEmpty( ) ) Servers = (*i)->GetServer( ); @@ -1108,7 +1108,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "say" && !Payload.isEmpty( ) ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Payload ); } @@ -1158,7 +1158,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( m_GHost->m_CurrentGame ) m_GHost->m_CurrentGame->SendAllChat( Payload ); - for( QVector :: iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) (*i)->SendAllChat( "ADMIN: " + Payload ); } @@ -1200,7 +1200,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, Name = Payload.mid( 0, MessageStart ); Message = Payload.mid( MessageStart + 1 ); - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) (*i)->QueueChatCommand( Message, Name, true ); } } diff --git a/ghost/game_admin.h b/ghost/game_admin.h index bfcf543..ade601d 100644 --- a/ghost/game_admin.h +++ b/ghost/game_admin.h @@ -54,13 +54,13 @@ public slots: protected: QString m_Password; - QVector m_TempBans; - QVector m_PairedAdminCounts; // vector of paired threaded database admin counts in progress - QVector m_PairedAdminAdds; // vector of paired threaded database admin adds in progress - QVector m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress - QVector m_PairedBanCounts; // vector of paired threaded database ban counts in progress - // QVector m_PairedBanAdds; // vector of paired threaded database ban adds in progress - QVector m_PairedBanRemoves; // vector of paired threaded database ban removes in progress + QList m_TempBans; + QList m_PairedAdminCounts; // vector of paired threaded database admin counts in progress + QList m_PairedAdminAdds; // vector of paired threaded database admin adds in progress + QList m_PairedAdminRemoves; // vector of paired threaded database admin removes in progress + QList m_PairedBanCounts; // vector of paired threaded database ban counts in progress + // QList m_PairedBanAdds; // vector of paired threaded database ban adds in progress + QList m_PairedBanRemoves; // vector of paired threaded database ban removes in progress public: CAdminGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nPassword ); diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index c3a3239..9c6a214 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -189,7 +189,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 // we really just want the open/closed/computer entries // so open all the player slots - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 ) { @@ -262,7 +262,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 CBaseGame :: ~CBaseGame( ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { (*i)->QueueChatCommand( m_GHost->m_Language->GameIsOver( GetDescription( ) ) ); @@ -297,13 +297,13 @@ CBaseGame :: ~CBaseGame( ) delete m_Map; delete m_Replay; - for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + for( QList :: const_iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) delete *i; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) delete *i; - for( QVector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); i++ ) + for( QList :: const_iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); i++ ) m_GHost->m_Callables.push_back( *i ); while( !m_Actions.isEmpty( ) ) @@ -317,7 +317,7 @@ quint32 CBaseGame :: GetSlotsOccupied( ) { quint32 NumSlotsOccupied = 0; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED ) NumSlotsOccupied++; @@ -330,7 +330,7 @@ quint32 CBaseGame :: GetSlotsOpen( ) { quint32 NumSlotsOpen = 0; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OPEN ) NumSlotsOpen++; @@ -353,7 +353,7 @@ quint32 CBaseGame :: GetNumHumanPlayers( ) { quint32 NumHumanPlayers = 0; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) NumHumanPlayers++; @@ -384,7 +384,7 @@ void CBaseGame::CheckGameLoaded() { bool FinishedLoading = true; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { FinishedLoading = (*i)->GetFinishedLoading( ); @@ -408,19 +408,19 @@ void CBaseGame::EventLoadInGameTimeout() bool UsingGProxy = false; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) UsingGProxy = true; } - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetFinishedLoading( ) ) { // stop the lag screen - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QList :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { if( !(*j)->GetFinishedLoading( ) ) Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j, true ) ); @@ -598,7 +598,7 @@ void CBaseGame::EventTryAutoRehost() m_HostCounter = m_GHost->m_HostCounter++; m_RefreshError = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { (*i)->QueueGameUncreate( ); (*i)->QueueEnterChat( ); @@ -647,7 +647,7 @@ void CBaseGame::EventRefreshTimeout() bool Refreshed = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // don't queue a game refresh message if the queue contains more than 1 packet because they're very low priority @@ -703,7 +703,7 @@ void CBaseGame::EventMapDataTimeout() quint32 Downloaders = 0; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetDownloadStarted( ) && !(*i)->GetDownloadFinished( ) ) { @@ -856,7 +856,7 @@ void CBaseGame :: Send( QByteArray PIDs, QByteArray data ) void CBaseGame :: SendAll( QByteArray data ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->Send( data ); } @@ -949,7 +949,7 @@ void CBaseGame :: SendLocalAdminChat( QString message ) // at the time of this writing it is only possible for the game owner to meet this criteria because being an admin requires spoof checking // this is mainly used for relaying battle.net whispers, chat messages, and emotes to these players - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetSpoofed( ) && IsOwner( (*i)->GetName( ) ) && ( UTIL_IsLanIP( (*i)->GetExternalIP( ) ) || UTIL_IsLocalIP( (*i)->GetExternalIP( ), m_GHost->m_LocalAddresses ) ) ) { @@ -1001,7 +1001,7 @@ void CBaseGame :: SendAllActions( ) { bool UsingGProxy = false; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) UsingGProxy = true; @@ -1023,7 +1023,7 @@ void CBaseGame :: SendAllActions( ) // GProxy++ will insert these itself so we don't need to send them to GProxy++ players // empty actions are used to extend the time a player can use when reconnecting - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetGProxy( ) ) { @@ -1185,7 +1185,7 @@ void CBaseGame::CheckPlayersStartedLaggging() m_WaitTime = 60; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) { @@ -1197,7 +1197,7 @@ void CBaseGame::CheckPlayersStartedLaggging() } QString LaggingString; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( m_SyncCounter - (*i)->GetSyncCounter( ) > m_SyncLimit ) { @@ -1224,7 +1224,7 @@ void CBaseGame::CheckPlayersStartedLaggging() // reset everyone's drop vote - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->SetDropVote( false ); m_ResetLagscreenTimer.start(); @@ -1247,7 +1247,7 @@ void CBaseGame::EventResetLagscreenTimeout() bool UsingGProxy = false; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetGProxy( ) ) UsingGProxy = true; @@ -1258,11 +1258,11 @@ void CBaseGame::EventResetLagscreenTimeout() // another solution is to reset the lag screen the same way we reset it when using load-in-game // this is required in order to give GProxy++ clients more time to reconnect - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { // stop the lag screen - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QList :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { if( (*j)->GetLagging( ) ) Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( *j ) ); @@ -1328,7 +1328,7 @@ void CBaseGame::EventPlayerStoppedLagging() bool Lagging = false; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLagging( ) ) Lagging = true; @@ -1350,20 +1350,16 @@ void CBaseGame :: EventPlayerDeleted() CGamePlayer *player = (CGamePlayer*)QObject::sender(); CONSOLE_Print( "[GAME: " + m_GameName + "] deleting player [" + player->GetName( ) + "]: " + player->GetLeftReason( ) ); - int ind = m_Players.indexOf(player); - - if (ind == -1) + if( !m_Players.removeOne(player) ) return; - m_Players.remove(ind); - // create the virtual host player if there is room if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < 12 ) CreateVirtualHost( ); bool res = false; // check if there's another player with reserved status in the game - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) if( (*i)->GetReserved( ) ) res = true; @@ -1395,7 +1391,7 @@ void CBaseGame :: EventPlayerDeleted() if( player->GetWhoisSent( ) && !player->GetJoinedRealm( ).isEmpty( ) && player->GetSpoofedRealm( ).isEmpty( ) ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == player->GetJoinedRealm( ) ) { @@ -1446,7 +1442,7 @@ void CBaseGame :: EventPlayerDeleted() // we must buffer player leave messages when using "load in game" to prevent desyncs // this ensures the player leave messages are correctly interleaved with the empty updates sent to each player - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetFinishedLoading( ) ) { @@ -1648,7 +1644,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( HostCounterID != 0 ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetHostCounterID( ) == HostCounterID ) JoinedRealm = (*i)->GetServer( ); @@ -1661,7 +1657,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_BanMethod != 0 ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == JoinedRealm ) { @@ -1683,7 +1679,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // let banned players "join" the game with an arbitrary PID then immediately close the connection // this causes them to be kicked back to the chat channel on battle.net - QVector Slots = m_Map->GetSlots( ); + QList Slots = m_Map->GetSlots( ); potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, Util::fromUInt16(potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->deleteLater(); return; @@ -1711,7 +1707,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // let banned players "join" the game with an arbitrary PID then immediately close the connection // this causes them to be kicked back to the chat channel on battle.net - QVector Slots = m_Map->GetSlots( ); + QList Slots = m_Map->GetSlots( ); potential->Send( m_Protocol->SEND_W3GS_SLOTINFOJOIN( 1, Util::fromUInt16((quint16)potential->GetSocket( )->localPort()), potential->GetExternalIP( ), Slots, 0, m_Map->GetMapLayoutStyle( ), m_Map->GetMapNumPlayers( ) ) ); potential->deleteLater(); return; @@ -1737,7 +1733,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP bool AnyAdminCheck = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->IsAdmin( joinPlayer->GetName( ) ) || (*i)->IsRootAdmin( joinPlayer->GetName( ) ) ) { @@ -1765,13 +1761,13 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP // unfortunately we don't know how to extract the player layout from the saved game so we use the data from a replay instead // the !enforcesg command defines the player layout by parsing a replay - for( QVector :: iterator i = m_EnforcePlayers.begin( ); i != m_EnforcePlayers.end( ); i++ ) + for( QList :: const_iterator i = m_EnforcePlayers.begin( ); i != m_EnforcePlayers.end( ); i++ ) { if( (*i).second == joinPlayer->GetName( ) ) EnforcePID = (*i).first; } - for( QVector :: iterator i = m_EnforceSlots.begin( ); i != m_EnforceSlots.end( ); i++ ) + for( QList :: iterator i = m_EnforceSlots.begin( ); i != m_EnforceSlots.end( ); i++ ) { if( (*i).GetPID( ) == EnforcePID ) { @@ -1869,7 +1865,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_BanMethod == 0 ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == JoinedRealm ) { @@ -1972,7 +1968,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP BlankIP.push_back( (char)0 ); BlankIP.push_back( (char)0 ); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && *i != Player ) { @@ -2012,7 +2008,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_RequireSpoofChecks && !Player->GetWhoisShouldBeSent( ) ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // note: the following (commented out) line of code will crash because calling GetUniqueName( ) twice will result in two different return values // and unfortunately iterators are not valid if compared against different containers @@ -2032,7 +2028,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP { QString Others; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( Player != *i && Player->GetExternalIPString( ) == (*i)->GetExternalIPString( ) ) { @@ -2111,7 +2107,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco bool AnyAdminCheck = false; - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->IsAdmin( joinPlayer->GetName( ) ) || (*i)->IsRootAdmin( joinPlayer->GetName( ) ) ) { @@ -2152,7 +2148,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco PlayersScored = 1; } - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetScore( ) > -99999.0 ) { @@ -2168,7 +2164,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CGamePlayer *FurthestPlayer = NULL; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !FurthestPlayer || (*i)->GetScore( ) < -99999.0 || abs( (*i)->GetScore( ) - AverageScore ) > abs( FurthestPlayer->GetScore( ) - AverageScore ) ) FurthestPlayer = *i; @@ -2228,7 +2224,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco CGamePlayer *LowestPlayer = NULL; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !LowestPlayer || (*i)->GetScore( ) < -99999.0 || (*i)->GetScore( ) < LowestPlayer->GetScore( ) ) LowestPlayer = *i; @@ -2308,7 +2304,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( HostCounterID != 0 ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetHostCounterID( ) == HostCounterID ) JoinedRealm = (*i)->GetServer( ); @@ -2351,7 +2347,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco BlankIP.push_back( (char)0 ); BlankIP.push_back( (char)0 ); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && *i != Player ) { @@ -2391,7 +2387,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( m_GHost->m_RequireSpoofChecks && !Player->GetWhoisShouldBeSent( ) ) { - for( QVector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { // note: the following (commented out) line of code will crash because calling GetUniqueName( ) twice will result in two different return values // and unfortunately iterators are not valid if compared against different containers @@ -2417,7 +2413,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco double MaxScore = 0.0; bool Found = false; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { @@ -2448,7 +2444,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco { QString Others; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( Player != *i && Player->GetExternalIPString( ) == (*i)->GetExternalIPString( ) ) { @@ -2523,7 +2519,7 @@ void CBaseGame :: EventPlayerLoaded() bool FinishedLoading = true; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { FinishedLoading = (*i)->GetFinishedLoading( ); @@ -2536,7 +2532,7 @@ void CBaseGame :: EventPlayerLoaded() // remove the new player from previously loaded players' lag screens - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( *i != player && (*i)->GetFinishedLoading( ) ) Send( *i, m_Protocol->SEND_W3GS_STOP_LAG( player ) ); @@ -2544,7 +2540,7 @@ void CBaseGame :: EventPlayerLoaded() // send a chat message to previously loaded players - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( *i != player && (*i)->GetFinishedLoading( ) ) SendChat( *i, m_GHost->m_Language->PlayerFinishedLoading( player->GetName( ) ) ); @@ -2578,7 +2574,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check // however, it's possible that not every player has sent a checksum for this frame yet // first we verify that we have enough checksums to work with otherwise we won't know exactly who desynced - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetCheckSums( )->empty( ) ) return; @@ -2589,7 +2585,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check bool FoundPlayer = false; quint32 FirstCheckSum = 0; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { FoundPlayer = true; FirstCheckSum = (*i)->GetCheckSums( )->front( ); @@ -2601,7 +2597,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check bool AddToReplay = true; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetCheckSums( )->front( ) != FirstCheckSum ) { @@ -2612,16 +2608,16 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check // this is complicated by the fact that we don't know what the correct game state is so we let the players vote // put the players into bins based on their game state - QMap > Bins; + QMap > Bins; - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QList :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) Bins[(*j)->GetCheckSums( )->front( )].push_back( (*j)->GetPID( ) ); quint32 StateNumber = 1; - QMap > :: iterator LargestBin = Bins.begin( ); + QMap > :: iterator LargestBin = Bins.begin( ); bool Tied = false; - for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) + for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { if( j.value().size( ) > LargestBin.value().size( ) ) { @@ -2633,7 +2629,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check QString Players; - for( QVector :: iterator k = j.value().begin( ); k != j.value().end( ); k++ ) + for( QList :: iterator k = j.value().begin( ); k != j.value().end( ); k++ ) { CGamePlayer *Player = GetPlayerFromPID( *k ); @@ -2669,7 +2665,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check { CONSOLE_Print( "[GAME: " + m_GameName + "] kicking desynced players" ); - for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) + for( QMap > :: iterator j = Bins.begin( ); j != Bins.end( ); j++ ) { // kick players who are NOT in the largest bin // examples: suppose there are 10 players @@ -2678,7 +2674,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check if( j.key() != LargestBin.key() ) { - for( QVector :: iterator k = j.value().begin( ); k != j.value().end( ); k++ ) + for( QList :: iterator k = j.value().begin( ); k != j.value().end( ); k++ ) { CGamePlayer *Player = GetPlayerFromPID( *k ); @@ -2699,7 +2695,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check } } - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->GetCheckSums( )->dequeue( ); // add checksum to replay @@ -2975,7 +2971,7 @@ void CBaseGame :: EventPlayerDropRequest( CGamePlayer *player ) quint32 Votes = 0; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetDropVote( ) ) Votes++; @@ -3084,13 +3080,13 @@ void CBaseGame::EventCallableUpdateTimeout() { // update callables - for( QVector :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); ) + for( QList :: iterator i = m_ScoreChecks.begin( ); i != m_ScoreChecks.end( ); ) { if( (*i)->GetReady( ) ) { double Score = (*i)->GetResult( ); - for( QVector :: iterator j = m_Potentials.begin( ); j != m_Potentials.end( ); j++ ) + for( QList :: iterator j = m_Potentials.begin( ); j != m_Potentials.end( ); j++ ) { if( (*j)->GetJoinPlayer( ) && (*j)->GetJoinPlayer( )->GetName( ) == (*i)->GetName( ) ) EventPlayerJoinedWithScore( *j, (*j)->GetJoinPlayer( ), Score ); @@ -3238,7 +3234,7 @@ void CBaseGame :: EventGameStarted( ) // delete any potential players that are still hanging around - for( QVector :: iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) + for( QList :: const_iterator i = m_Potentials.begin( ); i != m_Potentials.end( ); i++ ) delete *i; m_Potentials.clear( ); @@ -3247,7 +3243,7 @@ void CBaseGame :: EventGameStarted( ) if( m_Replay ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) m_Replay->AddPlayer( (*i)->GetPID( ), (*i)->GetName( ) ); if( m_FakePlayerPID != 255 ) @@ -3316,9 +3312,9 @@ void CBaseGame :: EventGameStarted( ) // this ensures that every player receives the same set of player loaded messages in the same order, even if someone leaves during loading // if someone leaves during loading we buffer the leave message to ensure it gets sent in the correct position but the player loaded message wouldn't get sent if we didn't buffer it now - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QList :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) (*j)->AddLoadInGameData( m_Protocol->SEND_W3GS_GAMELOADED_OTHERS( (*i)->GetPID( ) ) ); } } @@ -3334,7 +3330,7 @@ void CBaseGame :: EventGameLoaded( ) CGamePlayer *Longest = NULL; m_LoadInGameTimer.stop(); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !Shortest || (*i)->GetFinishedLoadingTicks( ) < Shortest->GetFinishedLoadingTicks( ) ) Shortest = *i; @@ -3349,7 +3345,7 @@ void CBaseGame :: EventGameLoaded( ) SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), QString::number( (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); } - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( QString::number( (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); // read from gameloaded.txt if available @@ -3382,7 +3378,7 @@ unsigned char CBaseGame :: GetSIDFromPID( unsigned char PID ) CGamePlayer *CBaseGame :: GetPlayerFromPID( unsigned char PID ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && (*i)->GetPID( ) == PID ) return *i; @@ -3404,7 +3400,7 @@ CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) if( !sensitive ) name = name.toLower(); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { @@ -3429,7 +3425,7 @@ quint32 CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **playe // try to match each player with the passed QString (e.g. "Varlock" would be matched with "lock") - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { @@ -3476,7 +3472,7 @@ unsigned char CBaseGame :: GetNewPID( ) bool InUse = false; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && (*i)->GetPID( ) == TestPID ) { @@ -3524,7 +3520,7 @@ QByteArray CBaseGame :: GetPIDs( ) { QByteArray result; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) result.push_back( (*i)->GetPID( ) ); @@ -3537,7 +3533,7 @@ QByteArray CBaseGame :: GetPIDs( unsigned char excludePID ) { QByteArray result; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && (*i)->GetPID( ) != excludePID ) result.push_back( (*i)->GetPID( ) ); @@ -3561,7 +3557,7 @@ unsigned char CBaseGame :: GetHostPID( ) // try to find the owner player next - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) && IsOwner( (*i)->GetName( ) ) ) return (*i)->GetPID( ); @@ -3569,7 +3565,7 @@ unsigned char CBaseGame :: GetHostPID( ) // okay then, just use the first available player - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) return (*i)->GetPID( ); @@ -3588,7 +3584,7 @@ unsigned char CBaseGame :: GetEmptySlot( bool reserved ) // unfortunately we don't know which slot each player was assigned in the savegame // but we do know which slots were occupied and which weren't so let's at least force players to use previously occupied slots - QVector SaveGameSlots = m_SaveGame->GetSlots( ); + QList SaveGameSlots = m_SaveGame->GetSlots( ); for( unsigned char i = 0; i < m_Slots.size( ); i++ ) { @@ -3675,7 +3671,7 @@ unsigned char CBaseGame :: GetEmptySlot( unsigned char team, unsigned char PID ) if( m_SaveGame ) { - QVector SaveGameSlots = m_SaveGame->GetSlots( ); + QList SaveGameSlots = m_SaveGame->GetSlots( ); for( unsigned char i = StartSlot; i < m_Slots.size( ); i++ ) { @@ -3848,7 +3844,7 @@ void CBaseGame :: OpenAllSlots( ) { bool Changed = false; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_CLOSED ) { @@ -3865,7 +3861,7 @@ void CBaseGame :: CloseAllSlots( ) { bool Changed = false; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OPEN ) { @@ -3884,9 +3880,9 @@ void CBaseGame :: ShuffleSlots( ) // that means we need to prevent this function from shuffling the open/closed/computer slots too // so we start by copying the player slots to a temporary vector - QVector PlayerSlots; + QList PlayerSlots; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != 12 ) PlayerSlots.push_back( *i ); @@ -3901,7 +3897,7 @@ void CBaseGame :: ShuffleSlots( ) // unfortunately we can't just use PlayerSlots because the team/colour/race shouldn't be modified // so make a vector we can use - QVector SIDs; + QList SIDs; for( unsigned char i = 0; i < PlayerSlots.size( ); i++ ) SIDs.push_back( i ); @@ -3910,7 +3906,7 @@ void CBaseGame :: ShuffleSlots( ) // now put the PlayerSlots vector in the same order as the SIDs vector - QVector Slots; + QList Slots; // as usual don't modify the team/colour/race @@ -3929,10 +3925,10 @@ void CBaseGame :: ShuffleSlots( ) // now we put m_Slots back together again - QVector :: iterator CurrentPlayer = PlayerSlots.begin( ); - QVector Slots; + QList :: iterator CurrentPlayer = PlayerSlots.begin( ); + QList Slots; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != 12 ) { @@ -3950,7 +3946,7 @@ void CBaseGame :: ShuffleSlots( ) SendAllSlotInfo( ); } -QVector CBaseGame :: BalanceSlotsRecursive( QVector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ) +QList CBaseGame :: BalanceSlotsRecursive( QList PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ) { // take a brute force approach to finding the best balance by iterating through every possible combination of players // 1.) since the number of teams is arbitrary this algorithm must be recursive @@ -3959,7 +3955,7 @@ QVector CBaseGame :: BalanceSlotsRecursive( QVector BestOrdering = PlayerIDs; + QList BestOrdering = PlayerIDs; double BestDifference = -1.0; for( unsigned char i = StartTeam; i < 12; i++ ) @@ -3978,18 +3974,18 @@ QVector CBaseGame :: BalanceSlotsRecursive( QVector BestSubOrdering = BalanceSlotsRecursive( PlayerIDs.mid(Mid), TeamSizes, PlayerScores, i + 1 ); + QList BestSubOrdering = BalanceSlotsRecursive( PlayerIDs.mid(Mid), TeamSizes, PlayerScores, i + 1 ); // BestSubOrdering now contains the best ordering of all the remaining players (the "right team") given this particular combination of players into two "teams" // in order to calculate the largest difference in total scores we need to recombine the subordering with the first team - QVector TestOrdering = PlayerIDs.mid(0, Mid); + QList TestOrdering = PlayerIDs.mid(0, Mid); for (int k = 0; k < BestSubOrdering.size(); k++) TestOrdering.push_back(BestSubOrdering.at(k)); // now calculate the team scores for all the teams that we know about (e.g. on subsequent recursion steps this will NOT be every possible team) - QVector :: iterator CurrentPID = TestOrdering.begin( ); + QList :: iterator CurrentPID = TestOrdering.begin( ); double TeamScores[12]; for( unsigned char j = StartTeam; j < 12; j++ ) @@ -4049,12 +4045,12 @@ void CBaseGame :: BalanceSlots( ) // setup the necessary variables for the balancing algorithm // use an array of 13 elements for 12 players because GHost++ allocates PID's from 1-12 (i.e. excluding 0) and we use the PID to index the array - QVector PlayerIDs; + QList PlayerIDs; unsigned char TeamSizes[12]; double PlayerScores[13]; memset( TeamSizes, 0, sizeof( unsigned char ) * 12 ); - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { unsigned char PID = (*i)->GetPID( ); @@ -4126,13 +4122,13 @@ void CBaseGame :: BalanceSlots( ) } quint32 StartTicks = GetTicks( ); - QVector BestOrdering = BalanceSlotsRecursive( PlayerIDs, TeamSizes, PlayerScores, 0 ); + QList BestOrdering = BalanceSlotsRecursive( PlayerIDs, TeamSizes, PlayerScores, 0 ); quint32 EndTicks = GetTicks( ); // the BestOrdering assumes the teams are in slot order although this may not be the case // so put the players on the correct teams regardless of slot order - QVector :: iterator CurrentPID = BestOrdering.begin( ); + QList :: iterator CurrentPID = BestOrdering.begin( ); for( unsigned char i = 0; i < 12; i++ ) { @@ -4177,7 +4173,7 @@ void CBaseGame :: BalanceSlots( ) bool TeamHasPlayers = false; double TeamScore = 0.0; - for( QVector :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) + for( QList :: iterator j = m_Players.begin( ); j != m_Players.end( ); j++ ) { unsigned char SID = GetSIDFromPID( (*j)->GetPID( ) ); @@ -4218,7 +4214,7 @@ void CBaseGame :: AddToReserved( QString name ) // check that the user is not already reserved - for( QVector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) + for( QList :: const_iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { if( *i == name ) return; @@ -4228,7 +4224,7 @@ void CBaseGame :: AddToReserved( QString name ) // upgrade the user if they're already in the game - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { QString NameLower = (*i)->GetName( ).toLower(); @@ -4247,7 +4243,7 @@ bool CBaseGame :: IsReserved( QString name ) { name = name.toLower(); - for( QVector :: iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) + for( QList :: const_iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) { if( *i == name ) return true; @@ -4260,7 +4256,7 @@ bool CBaseGame :: IsDownloading( ) { // returns true if at least one player is downloading the map - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetDownloadStarted( ) && !(*i)->GetDownloadFinished( ) ) return true; @@ -4303,7 +4299,7 @@ void CBaseGame :: StartCountDown( bool force ) QString StillDownloading; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetDownloadStatus( ) != 100 ) { @@ -4328,7 +4324,7 @@ void CBaseGame :: StartCountDown( bool force ) if( m_GHost->m_RequireSpoofChecks ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetSpoofed( ) ) { @@ -4348,7 +4344,7 @@ void CBaseGame :: StartCountDown( bool force ) QString NotPinged; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetReserved( ) && (*i)->GetNumPings( ) < 3 ) { @@ -4391,7 +4387,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) QString StillDownloading; - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetDownloadStatus( ) != 100 ) { @@ -4419,7 +4415,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( requireSpoofChecks ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetSpoofed( ) ) { @@ -4439,7 +4435,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) QString NotPinged; - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetReserved( ) && (*i)->GetNumPings( ) < 3 ) { @@ -4473,7 +4469,7 @@ void CBaseGame :: StopPlayers( QString reason ) // therefore calling this function when m_GameLoading || m_GameLoaded is roughly equivalent to setting m_Exiting = true // the only difference is whether the code in the Update function is executed or not - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); ) + for( QList :: iterator i = m_Players.begin( ); i != m_Players.end( ); ) { CGamePlayer *p = *i; i = m_Players.erase(i); @@ -4486,7 +4482,7 @@ void CBaseGame :: StopPlayers( QString reason ) void CBaseGame :: StopLaggers( QString reason ) { - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i)->GetLagging( ) ) { diff --git a/ghost/game_base.h b/ghost/game_base.h index c248cb8..fdc5275 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -95,16 +95,16 @@ public slots: protected: QTcpServer *m_Socket; // listening socket CGameProtocol *m_Protocol; // game protocol - QVector m_Slots; // vector of slots - QVector m_Potentials; // vector of potential players (connections that haven't sent a W3GS_REQJOIN packet yet) - QVector m_Players; // vector of players - QVector m_ScoreChecks; + QList m_Slots; // vector of slots + QList m_Potentials; // vector of potential players (connections that haven't sent a W3GS_REQJOIN packet yet) + QList m_Players; // vector of players + QList m_ScoreChecks; QQueue m_Actions; // queue of actions to be sent - QVector m_Reserved; // vector of player names with reserved slots (from the !hold command) + QList m_Reserved; // vector of player names with reserved slots (from the !hold command) QSet m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed QSet m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) - QVector m_EnforceSlots; // vector of slots to force players to use (used with saved games) - QVector m_EnforcePlayers; // vector of pids to force players to use (used with saved games) + QList m_EnforceSlots; // vector of slots to force players to use (used with saved games) + QList m_EnforcePlayers; // vector of pids to force players to use (used with saved games) CMap *m_Map; // map data CSaveGame *m_SaveGame; // savegame data (this is a pointer to global data) CReplay *m_Replay; // replay @@ -163,8 +163,8 @@ public slots: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CBaseGame( ); - virtual QVector GetEnforceSlots( ) { return m_EnforceSlots; } - virtual QVector GetEnforcePlayers( ) { return m_EnforcePlayers; } + virtual QList GetEnforceSlots( ) { return m_EnforceSlots; } + virtual QList GetEnforcePlayers( ) { return m_EnforcePlayers; } virtual CSaveGame *GetSaveGame( ) { return m_SaveGame; } virtual quint16 GetHostPort( ) { return m_HostPort; } virtual unsigned char GetGameState( ) { return m_GameState; } @@ -185,8 +185,8 @@ public slots: virtual bool GetGameLoaded( ) { return m_GameLoaded; } virtual bool GetLagging( ) { return m_Lagging; } - virtual void SetEnforceSlots( QVector nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } - virtual void SetEnforcePlayers( QVector nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } + virtual void SetEnforceSlots( QList nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } + virtual void SetEnforcePlayers( QList nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } virtual void SetAutoStartPlayers( quint32 nAutoStartPlayers ) { m_AutoStartPlayers = nAutoStartPlayers; } virtual void SetMinimumScore( double nMinimumScore ) { m_MinimumScore = nMinimumScore; } virtual void SetMaximumScore( double nMaximumScore ) { m_MaximumScore = nMaximumScore; } @@ -274,7 +274,7 @@ public slots: virtual void OpenAllSlots( ); virtual void CloseAllSlots( ); virtual void ShuffleSlots( ); - virtual QVector BalanceSlotsRecursive( QVector PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ); + virtual QList BalanceSlotsRecursive( QList PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ); virtual void BalanceSlots( ); virtual void AddToSpoofed( QString server, QString name, bool sendMessage ); virtual void AddToReserved( QString name ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index abc3c07..1c7d9e9 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -108,7 +108,7 @@ void CGamePlayer::EventWhoisTimeout() { // todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking - for( QVector :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == m_JoinedRealm ) { diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index d2c9f57..fa5a396 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -119,7 +119,7 @@ public slots: unsigned char m_PID; QString m_Name; // the player's name QByteArray m_InternalIP; // the player's internal IP address as reported by the player when connecting - QVector m_Pings; // store the last few (20) pings received so we can take an average + QList m_Pings; // store the last few (20) pings received so we can take an average QQueue m_CheckSums; // the last few checksums the player has sent (for detecting desyncs) QString m_LeftReason; // the reason the player left the game QString m_SpoofedRealm; // the realm the player last spoof checked on diff --git a/ghost/gameprotocol.cpp b/ghost/gameprotocol.cpp index 35a4540..5b48646 100644 --- a/ghost/gameprotocol.cpp +++ b/ghost/gameprotocol.cpp @@ -309,7 +309,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { char Zeros[] = { 0, 0, 0, 0 }; @@ -443,7 +443,7 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; @@ -556,13 +556,13 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy return packet; } -QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, bool loadInGame ) +QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QList players, bool loadInGame ) { QByteArray packet; unsigned char NumLaggers = 0; - for( QVector :: iterator i = players.begin( ); i != players.end( ); i++ ) + for( QList :: const_iterator i = players.begin( ); i != players.end( ); i++ ) { if( loadInGame ) { @@ -584,7 +584,7 @@ QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QVector players, packet.push_back( (char)0 ); // packet length will be assigned later packet.push_back( NumLaggers ); - for( QVector :: iterator i = players.begin( ); i != players.end( ); i++ ) + for( QList :: const_iterator i = players.begin( ); i != players.end( ); i++ ) { if( loadInGame ) { @@ -954,7 +954,7 @@ bool CGameProtocol :: ValidateLength( QByteArray &content ) return false; } -QByteArray CGameProtocol :: EncodeSlotInfo( QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: EncodeSlotInfo( QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo; SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots diff --git a/ghost/gameprotocol.h b/ghost/gameprotocol.h index 09dbac0..d049fa0 100644 --- a/ghost/gameprotocol.h +++ b/ghost/gameprotocol.h @@ -123,17 +123,17 @@ class CGameProtocol // send functions QByteArray SEND_W3GS_PING_FROM_HOST( ); - QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_REJECTJOIN( quint32 reason ); QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ); QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, quint32 leftCode ); QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); - QByteArray SEND_W3GS_SLOTINFO( QVector &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFO( QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_COUNTDOWN_START( ); QByteArray SEND_W3GS_COUNTDOWN_END( ); QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, quint16 sendInterval ); QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, QString message ); - QByteArray SEND_W3GS_START_LAG( QVector players, bool loadInGame = false ); + QByteArray SEND_W3GS_START_LAG( QList players, bool loadInGame = false ); QByteArray SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); QByteArray SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ); @@ -150,7 +150,7 @@ class CGameProtocol private: bool AssignLength( QByteArray &content ); bool ValidateLength( QByteArray &content ); - QByteArray EncodeSlotInfo( QVector &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray EncodeSlotInfo( QList &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); }; // diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 3f1ba0a..0fa3520 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -344,11 +344,10 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) if( m_BNETs.isEmpty( ) ) m_AutoHostTimer.start(0); - else { - for (int i = 0; i < m_BNETs.size(); i++) - m_BNETs.at(i)->socketConnect(); + for (QList::const_iterator i = m_BNETs.begin(); i != m_BNETs.end(); ++i) + (*i)->socketConnect(); } } @@ -365,14 +364,14 @@ CGHost :: ~CGHost( ) delete m_CRC; delete m_SHA; - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) - delete *i; + qDeleteAll( m_BNETs ); + m_BNETs.clear( ); delete m_CurrentGame; delete m_AdminGame; - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) - delete *i; + qDeleteAll( m_Games ); + m_Games.clear( ); delete m_DB; delete m_DBLocal; @@ -402,7 +401,7 @@ void CGHost::EventGameStarted() // and finally reenter battle.net chat - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { (*i)->QueueGameUncreate( ); (*i)->QueueEnterChat( ); @@ -455,7 +454,7 @@ void CGHost::EventReconnectionSocketReadyRead() CGamePlayer *Match = NULL; - for( QVector :: iterator j = m_Games.begin( ); j != m_Games.end( ); j++ ) + for( QList :: iterator j = m_Games.begin( ); j != m_Games.end( ); j++ ) { if( (*j)->GetGameLoaded( ) ) { @@ -495,7 +494,7 @@ void CGHost::EventCallableUpdateTimeout() { // update callables - for( QVector :: iterator i = m_Callables.begin( ); i != m_Callables.end( ); ) + for( QList :: iterator i = m_Callables.begin( ); i != m_Callables.end( ); ) { if( (*i)->GetReady( ) ) { @@ -528,7 +527,7 @@ void CGHost::EventExitNice() { CONSOLE_Print( "[GHOST] deleting all battle.net connections in preparation for exiting nicely" ); - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) delete *i; m_BNETs.clear( ); @@ -736,7 +735,7 @@ void CGHost :: EventBNETGameRefreshFailed( CBNET *bnet ) if( !m_CurrentGame ) return; - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { (*i)->QueueChatCommand( m_Language->UnableToCreateGameTryAnotherName( bnet->GetServer( ), m_CurrentGame->GetGameName( ) ) ); @@ -777,7 +776,7 @@ void CGHost :: EventBNETWhisper( CBNET *bnet, QString user, QString message ) if( m_CurrentGame ) m_CurrentGame->SendLocalAdminChat( "[W: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QList :: const_iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) (*i)->SendLocalAdminChat( "[W: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); } } @@ -791,7 +790,7 @@ void CGHost :: EventBNETChat( CBNET *bnet, QString user, QString message ) if( m_CurrentGame ) m_CurrentGame->SendLocalAdminChat( "[L: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QList :: const_iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) (*i)->SendLocalAdminChat( "[L: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); } } @@ -805,7 +804,7 @@ void CGHost :: EventBNETEmote( CBNET *bnet, QString user, QString message ) if( m_CurrentGame ) m_CurrentGame->SendLocalAdminChat( "[E: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); - for( QVector :: iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) + for( QList :: const_iterator i = m_Games.begin( ); i != m_Games.end( ); i++ ) (*i)->SendLocalAdminChat( "[E: " + bnet->GetServerAlias( ) + "] [" + user + "] " + message ); } } @@ -817,9 +816,7 @@ void CGHost::EventGameDeleted() if (game == m_CurrentGame) m_CurrentGame = NULL; - int ind = m_Games.indexOf(game); - if (ind != -1) - m_Games.remove(ind); + m_Games.removeOne(game); m_AutoHostTimer.start(); } @@ -1039,7 +1036,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS { if( !m_Enabled ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameDisabled( gameName ), creatorName, whisper ); @@ -1053,7 +1050,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( gameName.size( ) > 31 ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameNameTooLong( gameName ), creatorName, whisper ); @@ -1067,7 +1064,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( !map->GetValid( ) ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameInvalidMap( gameName ), creatorName, whisper ); @@ -1083,7 +1080,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS { if( !m_SaveGame->GetValid( ) ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameInvalidSaveGame( gameName ), creatorName, whisper ); @@ -1103,7 +1100,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS { CONSOLE_Print( "[GHOST] path mismatch, saved game path is [" + MapPath1 + "] but map path is [" + MapPath2 + "]" ); - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameSaveGameMapMismatch( gameName ), creatorName, whisper ); @@ -1117,7 +1114,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( m_EnforcePlayers.isEmpty( ) ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameMustEnforceFirst( gameName ), creatorName, whisper ); @@ -1132,7 +1129,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( m_CurrentGame ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameAnotherGameInLobby( gameName, m_CurrentGame->GetDescription( ) ), creatorName, whisper ); @@ -1146,7 +1143,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( m_Games.size( ) >= m_MaxGames ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetServer( ) == creatorServer ) (*i)->QueueChatCommand( m_Language->UnableToCreateGameMaxGamesReached( gameName, QString::number( m_MaxGames ) ), creatorName, whisper ); @@ -1176,7 +1173,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS m_EnforcePlayers.clear( ); } - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( whisper && (*i)->GetServer( ) == creatorServer ) { @@ -1217,7 +1214,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS if( gameState == GAME_PRIVATE ) { - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetPasswordHashType( ) != "pvpgn" ) (*i)->QueueEnterChat( ); @@ -1226,7 +1223,7 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QS // hold friends and/or clan members - for( QVector :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) + for( QList :: const_iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); i++ ) { if( (*i)->GetHoldFriends( ) ) (*i)->HoldFriends( m_CurrentGame ); diff --git a/ghost/ghost.h b/ghost/ghost.h index 0a0e96c..7e40b16 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -44,6 +44,7 @@ class CConfig; #include #include +#include class CGHost : public QObject { @@ -70,20 +71,20 @@ public slots: CGPSProtocol *m_GPSProtocol; CCRC32 *m_CRC; // for calculating CRC's CSHA1 *m_SHA; // for calculating SHA1's - QVector m_BNETs; // all our battle.net connections (there can be more than one) + QList m_BNETs; // all our battle.net connections (there can be more than one) CBaseGame *m_CurrentGame; // this game is still in the lobby state CAdminGame *m_AdminGame; // this "fake game" allows an admin who knows the password to control the bot from the local network - QVector m_Games; // these games are in progress + QList m_Games; // these games are in progress CGHostDB *m_DB; // database CGHostDB *m_DBLocal; // local database (for temporary data) - QVector m_Callables; // vector of orphaned callables waiting to die - QVector m_LocalAddresses; // vector of local IP addresses + QList m_Callables; // vector of orphaned callables waiting to die + QList m_LocalAddresses; // vector of local IP addresses CLanguage *m_Language; // language CMap *m_Map; // the currently loaded map CMap *m_AdminMap; // the map to use in the admin game CMap *m_AutoHostMap; // the map to use when autohosting CSaveGame *m_SaveGame; // the save game to use - QVector m_EnforcePlayers; // vector of pids to force players to use in the next game (used with saved games) + QList m_EnforcePlayers; // vector of pids to force players to use in the next game (used with saved games) bool m_Exiting; // set to true to force ghost to shutdown next update (used by SignalCatcher) bool m_ExitingNice; // set to true to force ghost to disconnect from all battle.net connections and wait for all games to finish before shutting down bool m_Enabled; // set to false to prevent new games from being created diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index fb6dd6e..7ffd2d8 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -81,9 +81,9 @@ bool CGHostDB :: AdminRemove( QString /*server*/, QString /*user*/ ) return false; } -QVector CGHostDB :: AdminList( QString /*server*/ ) +QList CGHostDB :: AdminList( QString /*server*/ ) { - return QVector( ); + return QList( ); } quint32 CGHostDB :: BanCount( QString /*server*/ ) @@ -111,9 +111,9 @@ bool CGHostDB :: BanRemove( QString /*user*/ ) return false; } -QVector CGHostDB :: BanList( QString /*server*/ ) +QList CGHostDB :: BanList( QString /*server*/ ) { - return QVector( ); + return QList( ); } quint32 CGHostDB :: GameAdd( QString /*server*/, QString /*map*/, QString /*gamename*/, QString /*ownername*/, quint32 /*duration*/, quint32 /*gamestate*/, QString /*creatorname*/, QString /*creatorserver*/ ) diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index 74ec111..b27cc5e 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -91,13 +91,13 @@ class CGHostDB : public QObject virtual bool AdminCheck( QString server, QString user ); virtual bool AdminAdd( QString server, QString user ); virtual bool AdminRemove( QString server, QString user ); - virtual QVector AdminList( QString server ); + virtual QList AdminList( QString server ); virtual quint32 BanCount( QString server ); virtual CDBBan *BanCheck( QString server, QString user, QString ip ); virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); virtual bool BanRemove( QString server, QString user ); virtual bool BanRemove( QString user ); - virtual QVector BanList( QString server ); + virtual QList BanList( QString server ); virtual quint32 GameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); virtual quint32 GamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); virtual quint32 GamePlayerCount( QString name ); @@ -265,14 +265,14 @@ class CCallableAdminList : public CBaseCallable { protected: QString m_Server; - QVector m_Result; + QList m_Result; public: CCallableAdminList( QString nServer ) : CBaseCallable( ), m_Server( nServer ) { } virtual ~CCallableAdminList( ); - virtual QVector GetResult( ) { return m_Result; } - virtual void SetResult( QVector nResult ) { m_Result = nResult; } + virtual QList GetResult( ) { return m_Result; } + virtual void SetResult( QList nResult ) { m_Result = nResult; } }; class CCallableBanCount : public CBaseCallable @@ -355,14 +355,14 @@ class CCallableBanList : public CBaseCallable { protected: QString m_Server; - QVector m_Result; + QList m_Result; public: CCallableBanList( QString nServer ) : CBaseCallable( ), m_Server( nServer ) { } virtual ~CCallableBanList( ); - virtual QVector GetResult( ) { return m_Result; } - virtual void SetResult( QVector nResult ) { m_Result = nResult; } + virtual QList GetResult( ) { return m_Result; } + virtual void SetResult( QList nResult ) { m_Result = nResult; } }; class CCallableGameAdd : public CBaseCallable diff --git a/ghost/ghostdbmysql.cpp b/ghost/ghostdbmysql.cpp index 342c131..3a03ce6 100644 --- a/ghost/ghostdbmysql.cpp +++ b/ghost/ghostdbmysql.cpp @@ -472,9 +472,9 @@ QString MySQLEscapeString( void *conn, QString str ) return result; } -QVector MySQLFetchRow( MYSQL_RES *res ) +QList MySQLFetchRow( MYSQL_RES *res ) { - QVector Result; + QList Result; MYSQL_ROW Row = mysql_fetch_row( res ); @@ -513,7 +513,7 @@ quint32 MySQLAdminCount( void *conn, QString *error, quint32 botid, QString serv if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Count = UTIL_ToUInt32( Row[0] ); @@ -545,7 +545,7 @@ bool MySQLAdminCheck( void *conn, QString *error, quint32 botid, QString server, if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( !Row.isEmpty( ) ) IsAdmin = true; @@ -591,10 +591,10 @@ bool MySQLAdminRemove( void *conn, QString *error, quint32 botid, QString server return Success; } -QVector MySQLAdminList( void *conn, QString *error, quint32 botid, QString server ) +QList MySQLAdminList( void *conn, QString *error, quint32 botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); - QVector AdminList; + QList AdminList; QString Query = "SELECT name FROM admins WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -605,7 +605,7 @@ QVector MySQLAdminList( void *conn, QString *error, quint32 botid, QStr if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); while( !Row.isEmpty( ) ) { @@ -636,7 +636,7 @@ quint32 MySQLBanCount( void *conn, QString *error, quint32 botid, QString server if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Count = UTIL_ToUInt32( Row[0] ); @@ -674,7 +674,7 @@ CDBBan *MySQLBanCheck( void *conn, QString *error, quint32 botid, QString server if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( Row.size( ) == 6 ) Ban = new CDBBan( server, Row[0], Row[1], Row[2], Row[3], Row[4], Row[5] ); @@ -741,10 +741,10 @@ bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString user ) return Success; } -QVector MySQLBanList( void *conn, QString *error, quint32 botid, QString server ) +QList MySQLBanList( void *conn, QString *error, quint32 botid, QString server ) { QString EscServer = MySQLEscapeString( conn, server ); - QVector BanList; + QList BanList; QString Query = "SELECT name, ip, DATE(date), gamename, admin, reason FROM bans WHERE server='" + EscServer + "'"; if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 ) @@ -755,7 +755,7 @@ QVector MySQLBanList( void *conn, QString *error, quint32 botid, QStri if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); while( Row.size( ) == 6 ) { @@ -824,7 +824,7 @@ CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, q if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( Row.size( ) == 12 ) { @@ -902,7 +902,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, q if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( Row.size( ) == 10 ) { @@ -934,7 +934,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, q if( Result2 ) { - QVector Row2 = MySQLFetchRow( Result2 ); + QList Row2 = MySQLFetchRow( Result2 ); if( Row2.size( ) == 1 ) TotalWins = UTIL_ToUInt32( Row2[0] ); @@ -959,7 +959,7 @@ CDBDotAPlayerSummary *MySQLDotAPlayerSummaryCheck( void *conn, QString *error, q if( Result3 ) { - QVector Row3 = MySQLFetchRow( Result3 ); + QList Row3 = MySQLFetchRow( Result3 ); if( Row3.size( ) == 1 ) TotalLosses = UTIL_ToUInt32( Row3[0] ); @@ -1023,7 +1023,7 @@ double MySQLScoreCheck( void *conn, QString *error, quint32 botid, QString categ if( Result ) { - QVector Row = MySQLFetchRow( Result ); + QList Row = MySQLFetchRow( Result ); if( Row.size( ) == 1 ) Score = UTIL_ToDouble( Row[0] ); @@ -1064,7 +1064,7 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid bool Success = false; QString Query; - for( QMap :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) + for( QMap :: const_iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) { QString EscVarName = MySQLEscapeString( conn, i->first.second ); @@ -1090,7 +1090,7 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid bool Success = false; QString Query; - for( QMap :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) + for( QMap :: const_iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) { QString EscVarName = MySQLEscapeString( conn, i->first.second ); @@ -1116,7 +1116,7 @@ bool MySQLW3MMDVarAdd( void *conn, QString *error, quint32 botid, quint32 gameid bool Success = false; QString Query; - for( QMap :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) + for( QMap :: const_iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) { QString EscVarName = MySQLEscapeString( conn, i->first.second ); QString EscValueString = MySQLEscapeString( conn, i->second ); diff --git a/ghost/ghostdbmysql.h b/ghost/ghostdbmysql.h index 38cf669..d798545 100644 --- a/ghost/ghostdbmysql.h +++ b/ghost/ghostdbmysql.h @@ -225,13 +225,13 @@ quint32 MySQLAdminCount( void *conn, QString *error, quint32 botid, QString serv bool MySQLAdminCheck( void *conn, QString *error, quint32 botid, QString server, QString user ); bool MySQLAdminAdd( void *conn, QString *error, quint32 botid, QString server, QString user ); bool MySQLAdminRemove( void *conn, QString *error, quint32 botid, QString server, QString user ); -QVector MySQLAdminList( void *conn, QString *error, quint32 botid, QString server ); +QList MySQLAdminList( void *conn, QString *error, quint32 botid, QString server ); quint32 MySQLBanCount( void *conn, QString *error, quint32 botid, QString server ); CDBBan *MySQLBanCheck( void *conn, QString *error, quint32 botid, QString server, QString user, QString ip ); bool MySQLBanAdd( void *conn, QString *error, quint32 botid, QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString server, QString user ); bool MySQLBanRemove( void *conn, QString *error, quint32 botid, QString user ); -QVector MySQLBanList( void *conn, QString *error, quint32 botid, QString server ); +QList MySQLBanList( void *conn, QString *error, quint32 botid, QString server ); quint32 MySQLGameAdd( void *conn, QString *error, quint32 botid, QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); quint32 MySQLGamePlayerAdd( void *conn, QString *error, quint32 botid, quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); CDBGamePlayerSummary *MySQLGamePlayerSummaryCheck( void *conn, QString *error, quint32 botid, QString name ); diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index ea6e943..a1d3a85 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -132,7 +132,7 @@ CGHostDBSQLite :: CGHostDBSQLite( CConfig *CFG ) : CGHostDB( CFG ) if( RC == SQLITE_ROW ) { - QVector *Row = m_DB->GetRow( ); + QList *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) SchemaNumber = (*Row)[0]; @@ -658,9 +658,9 @@ bool CGHostDBSQLite :: AdminRemove( QString server, QString user ) return Success; } -QVector CGHostDBSQLite :: AdminList( QString server ) +QList CGHostDBSQLite :: AdminList( QString server ) { - QVector AdminList; + QList AdminList; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT name FROM admins WHERE server=?", (void **)&Statement ); @@ -671,7 +671,7 @@ QVector CGHostDBSQLite :: AdminList( QString server ) while( RC == SQLITE_ROW ) { - QVector *Row = m_DB->GetRow( ); + QList *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) AdminList.push_back( (*Row)[0] ); @@ -737,7 +737,7 @@ CDBBan *CGHostDBSQLite :: BanCheck( QString server, QString user, QString ip ) if( RC == SQLITE_ROW ) { - QVector *Row = m_DB->GetRow( ); + QList *Row = m_DB->GetRow( ); if( Row->size( ) == 6 ) Ban = new CDBBan( server, (*Row)[0], (*Row)[1], (*Row)[2], (*Row)[3], (*Row)[4], (*Row)[5] ); @@ -837,9 +837,9 @@ bool CGHostDBSQLite :: BanRemove( QString user ) return Success; } -QVector CGHostDBSQLite :: BanList( QString server ) +QList CGHostDBSQLite :: BanList( QString server ) { - QVector BanList; + QList BanList; sqlite3_stmt *Statement; m_DB->Prepare( "SELECT name, ip, date, gamename, admin, reason FROM bans WHERE server=?", (void **)&Statement ); @@ -850,7 +850,7 @@ QVector CGHostDBSQLite :: BanList( QString server ) while( RC == SQLITE_ROW ) { - QVector *Row = m_DB->GetRow( ); + QList *Row = m_DB->GetRow( ); if( Row->size( ) == 6 ) BanList.push_back( new CDBBan( server, (*Row)[0], (*Row)[1], (*Row)[2], (*Row)[3], (*Row)[4], (*Row)[5] ) ); @@ -1223,7 +1223,7 @@ QString CGHostDBSQLite :: FromCheck( quint32 ip ) if( RC == SQLITE_ROW ) { - QVector *Row = m_DB->GetRow( ); + QList *Row = m_DB->GetRow( ); if( Row->size( ) == 1 ) From = (*Row)[0]; @@ -1343,7 +1343,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints bool Success = true; sqlite3_stmt *Statement = NULL; - for( QMap :: iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) + for( QMap :: const_iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_int ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1388,7 +1388,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_reals bool Success = true; sqlite3_stmt *Statement = NULL; - for( QMap :: iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) + for( QMap :: const_iterator i = var_reals.begin( ); i != var_reals.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_real ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1433,7 +1433,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_strin bool Success = true; sqlite3_stmt *Statement = NULL; - for( QMap :: iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) + for( QMap :: const_iterator i = var_strings.begin( ); i != var_strings.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_QString ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); diff --git a/ghost/ghostdbsqlite.h b/ghost/ghostdbsqlite.h index 6f14280..4d1f3e9 100644 --- a/ghost/ghostdbsqlite.h +++ b/ghost/ghostdbsqlite.h @@ -163,14 +163,14 @@ class CSQLITE3 private: void *m_DB; bool m_Ready; - QVector m_Row; + QList m_Row; public: CSQLITE3( QString filename ); ~CSQLITE3( ); bool GetReady( ) { return m_Ready; } - QVector *GetRow( ) { return &m_Row; } + QList *GetRow( ) { return &m_Row; } QString GetError( ); int Prepare( QString query, void **Statement ); @@ -218,13 +218,13 @@ class CGHostDBSQLite : public CGHostDB virtual bool AdminCheck( QString server, QString user ); virtual bool AdminAdd( QString server, QString user ); virtual bool AdminRemove( QString server, QString user ); - virtual QVector AdminList( QString server ); + virtual QList AdminList( QString server ); virtual quint32 BanCount( QString server ); virtual CDBBan *BanCheck( QString server, QString user, QString ip ); virtual bool BanAdd( QString server, QString user, QString ip, QString gamename, QString admin, QString reason ); virtual bool BanRemove( QString server, QString user ); virtual bool BanRemove( QString user ); - virtual QVector BanList( QString server ); + virtual QList BanList( QString server ); virtual quint32 GameAdd( QString server, QString map, QString gamename, QString ownername, quint32 duration, quint32 gamestate, QString creatorname, QString creatorserver ); virtual quint32 GamePlayerAdd( quint32 gameid, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 reserved, quint32 loadingtime, quint32 left, QString leftreason, quint32 team, quint32 colour ); virtual quint32 GamePlayerCount( QString name ); diff --git a/ghost/includes.h b/ghost/includes.h index 08a4c35..6def9e4 100644 --- a/ghost/includes.h +++ b/ghost/includes.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include using namespace std; diff --git a/ghost/map.cpp b/ghost/map.cpp index c173010..b9fcd34 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -401,7 +401,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) if( MapMPQReady ) { - QVector FileList; + QList FileList; FileList.push_back( "war3map.j" ); FileList.push_back( "scripts\\war3map.j" ); FileList.push_back( "war3map.w3e" ); @@ -414,7 +414,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) FileList.push_back( "war3map.w3q" ); bool FoundScript = false; - for( QVector :: iterator i = FileList.begin( ); i != FileList.end( ); i++ ) + for( QList :: const_iterator i = FileList.begin( ); i != FileList.end( ); i++ ) { // don't use scripts\war3map.j if we've already used war3map.j (yes, some maps have both but only war3map.j is used) @@ -481,7 +481,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) QByteArray MapHeight; quint32 MapNumPlayers = 0; quint32 MapNumTeams = 0; - QVector Slots; + QList Slots; if( !m_MapData.isEmpty( ) ) { @@ -638,7 +638,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { if( PlayerMask & 1 ) { - for( QVector :: iterator k = Slots.begin( ); k != Slots.end( ); k++ ) + for( QList :: iterator k = Slots.begin( ); k != Slots.end( ); k++ ) { if( (*k).GetColour( ) == j ) (*k).SetTeam( i ); @@ -667,7 +667,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) quint32 SlotNum = 1; - for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) + for( QList :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) { CONSOLE_Print( "[MAP] calculated map_slot" + QString::number( SlotNum ) + " = " + UTIL_QByteArrayToDecString( (*i).GetQByteArray( ) ) ); SlotNum++; @@ -681,7 +681,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) unsigned char Team = 0; - for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) + for( QList :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) { (*i).SetTeam( Team++ ); (*i).SetRace( SLOTRACE_RANDOM ); @@ -692,7 +692,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { // make races selectable - for( QVector :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) + for( QList :: iterator i = Slots.begin( ); i != Slots.end( ); i++ ) (*i).SetRace( (*i).GetRace( ) | SLOTRACE_SELECTABLE ); } } @@ -865,7 +865,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) { CONSOLE_Print( "[MAP] forcing races to random" ); - for( QVector :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) (*i).SetRace( SLOTRACE_RANDOM ); } diff --git a/ghost/map.h b/ghost/map.h index a0a1835..fbe82c9 100644 --- a/ghost/map.h +++ b/ghost/map.h @@ -123,7 +123,7 @@ class CMap QByteArray m_MapData; // the map data itself, for sending the map to players quint32 m_MapNumPlayers; quint32 m_MapNumTeams; - QVector m_Slots; + QList m_Slots; public: CMap( CGHost *nGHost ); @@ -157,7 +157,7 @@ class CMap QByteArray *GetMapData( ) { return &m_MapData; } quint32 GetMapNumPlayers( ) { return m_MapNumPlayers; } quint32 GetMapNumTeams( ) { return m_MapNumTeams; } - QVector GetSlots( ) { return m_Slots; } + QList GetSlots( ) { return m_Slots; } void Load( CConfig *CFG, QString nCFGFile ); void CheckValid( ); diff --git a/ghost/packed.cpp b/ghost/packed.cpp index c5b86fb..cf59a3e 100644 --- a/ghost/packed.cpp +++ b/ghost/packed.cpp @@ -295,7 +295,7 @@ void CPacked :: Compress( bool TFT ) quint32 CompressedSize = 0; string Padded = QString(m_Decompressed).toStdString(); Padded.append( 8192 - ( Padded.size( ) % 8192 ), 0 ); - QVector CompressedBlocks; + QList CompressedBlocks; string :: size_type Position = 0; unsigned char *CompressedData = new unsigned char[8213]; @@ -372,7 +372,7 @@ void CPacked :: Compress( bool TFT ) // append blocks - for( QVector :: const_iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) + for( QList :: const_iterator i = CompressedBlocks.begin( ); i != CompressedBlocks.end( ); i++ ) { QByteArray BlockHeader; BlockHeader.append(Util::fromUInt16((*i).size( ))); diff --git a/ghost/replay.cpp b/ghost/replay.cpp index 6b84562..647565e 100644 --- a/ghost/replay.cpp +++ b/ghost/replay.cpp @@ -167,7 +167,7 @@ void CReplay :: BuildReplay( QString gameName, QString statString, quint32 war3V // PlayerList (4.9) - for( QVector :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) + for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( (*i).first != m_HostPID ) { diff --git a/ghost/replay.h b/ghost/replay.h index 781dae7..3ce2d35 100644 --- a/ghost/replay.h +++ b/ghost/replay.h @@ -52,8 +52,8 @@ class CReplay : public CPacked QString m_StatString; quint32 m_PlayerCount; quint32 m_MapGameType; - QVector m_Players; - QVector m_Slots; + QList m_Players; + QList m_Slots; quint32 m_RandomSeed; unsigned char m_SelectMode; // also known as the "layout style" elsewhere in this project unsigned char m_StartSpotCount; @@ -72,8 +72,8 @@ class CReplay : public CPacked QString GetStatString( ) { return m_StatString; } quint32 GetPlayerCount( ) { return m_PlayerCount; } quint32 GetMapGameType( ) { return m_MapGameType; } - QVector GetPlayers( ) { return m_Players; } - QVector GetSlots( ) { return m_Slots; } + QList GetPlayers( ) { return m_Players; } + QList GetSlots( ) { return m_Slots; } quint32 GetRandomSeed( ) { return m_RandomSeed; } unsigned char GetSelectMode( ) { return m_SelectMode; } unsigned char GetStartSpotCount( ) { return m_StartSpotCount; } @@ -82,7 +82,7 @@ class CReplay : public CPacked QQueue *GetCheckSums( ) { return &m_CheckSums; } void AddPlayer( unsigned char nPID, QString nName ) { m_Players.push_back( PIDPlayer( nPID, nName ) ); } - void SetSlots( QVector nSlots ) { m_Slots = nSlots; } + void SetSlots( QList nSlots ) { m_Slots = nSlots; } void SetRandomSeed( quint32 nRandomSeed ) { m_RandomSeed = nRandomSeed; } void SetSelectMode( unsigned char nSelectMode ) { m_SelectMode = nSelectMode; } void SetStartSpotCount( unsigned char nStartSpotCount ) { m_StartSpotCount = nStartSpotCount; } diff --git a/ghost/savegame.h b/ghost/savegame.h index 9671103..7c58cfc 100644 --- a/ghost/savegame.h +++ b/ghost/savegame.h @@ -35,7 +35,7 @@ class CSaveGame : public CPacked QString m_MapPath; QString m_GameName; unsigned char m_NumSlots; - QVector m_Slots; + QList m_Slots; quint32 m_RandomSeed; QByteArray m_MagicNumber; @@ -48,7 +48,7 @@ class CSaveGame : public CPacked QString GetMapPath( ) { return m_MapPath; } QString GetGameName( ) { return m_GameName; } unsigned char GetNumSlots( ) { return m_NumSlots; } - QVector GetSlots( ) { return m_Slots; } + QList GetSlots( ) { return m_Slots; } quint32 GetRandomSeed( ) { return m_RandomSeed; } QByteArray GetMagicNumber( ) { return m_MagicNumber; } diff --git a/ghost/statsw3mmd.cpp b/ghost/statsw3mmd.cpp index 47d034a..008fc91 100644 --- a/ghost/statsw3mmd.cpp +++ b/ghost/statsw3mmd.cpp @@ -85,7 +85,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { //QByteArray ValueIDString = MissionKey.mid( 4 ); //quint32 ValueID = UTIL_ToUInt32( ValueIDString ); - QVector Tokens = TokenizeKey( Key ); + QList Tokens = TokenizeKey( Key ); if( !Tokens.isEmpty( ) ) { @@ -264,7 +264,7 @@ bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] Event [" + Key + "] found without a corresponding DefEvent, ignoring" ); else { - QVector DefEvent = m_DefEvents[Tokens[1]]; + QList DefEvent = m_DefEvents[Tokens[1]]; if( !DefEvent.isEmpty( ) ) { @@ -355,7 +355,7 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) // todotodo: there's no reason to create a new callable for each entry in this map // rewrite ThreadedW3MMDPlayerAdd to act more like ThreadedW3MMDVarAdd - for( QMap :: iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) + for( QMap :: const_iterator i = m_PIDToName.begin( ); i != m_PIDToName.end( ); i++ ) { QString Flags = m_Flags[i.key()]; quint32 Leaver = 0; @@ -403,9 +403,9 @@ void CStatsW3MMD :: Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ) CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] unable to begin database transaction, data not saved" ); } -QVector CStatsW3MMD :: TokenizeKey( const QByteArray& key ) +QList CStatsW3MMD :: TokenizeKey( const QByteArray& key ) { - QVector Tokens; + QList Tokens; QByteArray Token; bool Escaping = false; @@ -422,7 +422,7 @@ QVector CStatsW3MMD :: TokenizeKey( const QByteArray& key ) else { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], invalid escape sequence found, ignoring" ); - return QVector( ); + return QList( ); } Escaping = false; @@ -434,7 +434,7 @@ QVector CStatsW3MMD :: TokenizeKey( const QByteArray& key ) if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return QVector( ); + return QList( ); } Tokens.push_back( Token ); @@ -450,7 +450,7 @@ QVector CStatsW3MMD :: TokenizeKey( const QByteArray& key ) if( Token.isEmpty( ) ) { CONSOLE_Print( "[STATSW3MMD: " + m_Game->GetGameName( ) + "] error tokenizing key [" + key + "], empty token found, ignoring" ); - return QVector( ); + return QList( ); } Tokens.push_back( Token ); diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index abfe7b2..02154ee 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -42,7 +42,7 @@ class CStatsW3MMD : public CStats QMap m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) QMap m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) QMap m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") - QMap > m_DefEvents; // event -> vector of arguments + format + QMap > m_DefEvents; // event -> vector of arguments + format public: CStatsW3MMD( CBaseGame *nGame, QString nCategory ); @@ -50,7 +50,7 @@ class CStatsW3MMD : public CStats virtual bool ProcessAction( CIncomingAction *Action ); virtual void Save( CGHost *GHost, CGHostDB *DB, quint32 GameID ); - virtual QVector TokenizeKey( const QByteArray& key ); + virtual QList TokenizeKey( const QByteArray& key ); }; #endif diff --git a/ghost/util.cpp b/ghost/util.cpp index 599c4bb..5d0bb0c 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -67,7 +67,7 @@ QString UTIL_QByteArrayToDecString( QByteArray b ) QString result = QString::number( (unsigned char)b[0] ); - for( QByteArray :: iterator i = b.begin( ) + 1; i != b.end( ); i++ ) + for( QByteArray :: const_iterator i = b.begin( ) + 1; i != b.end( ); i++ ) result += " " + QString::number( (unsigned char)*i ); return result; @@ -216,12 +216,12 @@ bool UTIL_IsLanIP( QByteArray ip ) return false; } -bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ) +bool UTIL_IsLocalIP( QByteArray ip, QList &localIPs ) { if( ip.size( ) != 4 ) return false; - for( QVector :: iterator i = localIPs.begin( ); i != localIPs.end( ); i++ ) + for( QList :: const_iterator i = localIPs.begin( ); i != localIPs.end( ); i++ ) { if( (*i).size( ) != 4 ) continue; @@ -233,12 +233,12 @@ bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ) return false; } -QVector UTIL_Tokenize( QString s, char delim ) +QList UTIL_Tokenize( QString s, char delim ) { - QVector Tokens; + QList Tokens; QString Token; - for( QString :: iterator i = s.begin( ); i != s.end( ); i++ ) + for( QString :: const_iterator i = s.begin( ); i != s.end( ); i++ ) { if( *i == delim ) { diff --git a/ghost/util.h b/ghost/util.h index 0adcdbb..32e3744 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include class Util @@ -59,8 +59,8 @@ QByteArray UTIL_EncodeStatString( QByteArray &data ); // other bool UTIL_IsLanIP( QByteArray ip ); -bool UTIL_IsLocalIP( QByteArray ip, QVector &localIPs ); -QVector UTIL_Tokenize( QString s, char delim ); +bool UTIL_IsLocalIP( QByteArray ip, QList &localIPs ); +QList UTIL_Tokenize( QString s, char delim ); // math From cae9de2ee871f3f4c9f06888038d4f42f69624c9 Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 7 May 2010 14:28:18 +0000 Subject: [PATCH 53/69] ghost.qt: changed many function definitions to "const QString &foo" in order to avoid useless copying changed some QList vars to QStringList to leverage string comparing capabilities added m_RootAdmins to CBNET to avoid parsing a string everytime a player joins added empty bytearray definitions to util.h for usage where --- ghost/bnet.cpp | 194 ++++++++++++++++--------------------------- ghost/bnet.h | 34 ++++---- ghost/game_base.cpp | 114 ++++++++++--------------- ghost/game_base.h | 47 ++++++----- ghost/gameplayer.cpp | 4 +- ghost/gameplayer.h | 6 +- ghost/ghost.cpp | 12 +-- ghost/ghost.h | 8 +- ghost/util.cpp | 25 +++--- ghost/util.h | 25 +++--- 10 files changed, 201 insertions(+), 268 deletions(-) diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 6ff238f..7db60ad 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -44,7 +44,11 @@ // CBNET // -CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, quint32 nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ) +CBNET :: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAlias, const QString &nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, + const QString &nCDKeyROC, const QString &nCDKeyTFT, const QString &nCountryAbbrev, const QString &nCountry, quint32 nLocaleID, const QString &nUserName, const QString &nUserPassword, + const QString &nFirstChannel, const QString &nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, + unsigned char nWar3Version, const QByteArray &nEXEVersion, const QByteArray &nEXEVersionHash, const QString &nPasswordHashType, const QString &nPVPGNRealmName, + quint32 nMaxMessageLength, quint32 nHostCounterID ) : QObject(NULL) { // todotodo: append path seperator to Warcraft3Path if needed @@ -95,12 +99,12 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n if( nPasswordHashType == "pvpgn" && !nBNLSServer.isEmpty( ) ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] pvpgn connection found with a configured BNLS server, ignoring BNLS server" ); - nBNLSServer.clear( ); nBNLSPort = 0; nBNLSWardenCookie = 0; } - - m_BNLSServer = nBNLSServer; + else + m_BNLSServer = nBNLSServer; + m_BNLSPort = nBNLSPort; m_BNLSWardenCookie = nBNLSWardenCookie; m_CDKeyROC = nCDKeyROC.toAscii(); @@ -124,6 +128,7 @@ CBNET :: CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString n m_UserPassword = nUserPassword; m_FirstChannel = nFirstChannel; m_RootAdmin = nRootAdmin; + m_RootAdmins = nRootAdmin.split( QRegExp("\\s+") ); m_RootAdmin = m_RootAdmin.toLower(); m_CommandTrigger = nCommandTrigger; m_War3Version = nWar3Version; @@ -2182,7 +2187,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } } -void CBNET :: SendJoinChannel( QString channel ) +void CBNET :: SendJoinChannel( const QString &channel ) { if( m_LoggedIn && m_InChat ) m_Socket->write( m_Protocol->SEND_SID_JOINCHANNEL( channel ) ); @@ -2206,30 +2211,29 @@ void CBNET :: QueueEnterChat( ) EnqueuePacket( m_Protocol->SEND_SID_ENTERCHAT( ) ); } -void CBNET :: QueueChatCommand( QString chatCommand ) +void CBNET :: QueueChatCommand( const QString &chatCommand ) { if( chatCommand.isEmpty( ) ) return; if( m_LoggedIn ) { - if( m_PasswordHashType == "pvpgn" && chatCommand.size( ) > m_MaxMessageLength ) - chatCommand = chatCommand.mid( 0, m_MaxMessageLength ); - - if( chatCommand.size( ) > 255 ) - chatCommand = chatCommand.mid( 0, 255 ); + int maxTextLen = 255; + if( m_PasswordHashType == "pvpgn" ) + maxTextLen = m_MaxMessageLength; + QString cutCommand = chatCommand.mid( 0, maxTextLen ); if( m_OutPackets.size( ) > 10 ) - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + QString::number( m_OutPackets.size( ) ) + ") packets queued, discarding" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + cutCommand + "] but there are too many (" + QString::number( m_OutPackets.size( ) ) + ") packets queued, discarding" ); else { - CONSOLE_Print( "[QUEUED: " + m_ServerAlias + "] " + chatCommand ); - EnqueuePacket( m_Protocol->SEND_SID_CHATCOMMAND( chatCommand ) ); + CONSOLE_Print( "[QUEUED: " + m_ServerAlias + "] " + cutCommand ); + EnqueuePacket( m_Protocol->SEND_SID_CHATCOMMAND( cutCommand ) ); } } } -void CBNET :: QueueChatCommand( QString chatCommand, QString user, bool whisper ) +void CBNET :: QueueChatCommand( const QString &chatCommand, const QString &user, bool whisper ) { if( chatCommand.isEmpty( ) ) return; @@ -2242,7 +2246,7 @@ void CBNET :: QueueChatCommand( QString chatCommand, QString user, bool whisper QueueChatCommand( chatCommand ); } -void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *savegame, quint32 hostCounter ) +void CBNET :: QueueGameCreate( unsigned char state, const QString &gameName, const QString &hostName, CMap *map, CSaveGame *savegame, quint32 hostCounter ) { if( m_LoggedIn && map ) { @@ -2257,13 +2261,15 @@ void CBNET :: QueueGameCreate( unsigned char state, QString gameName, QString ho } } -void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, quint32 upTime, quint32 hostCounter ) +void CBNET :: QueueGameRefresh( unsigned char state, const QString &gameName, const QString &hostName, CMap *map, CSaveGame *saveGame, quint32 upTime, quint32 hostCounter ) { + QString newHostName; + if( hostName.isEmpty( ) ) - { - QByteArray UniqueName = m_Protocol->GetUniqueName( ); - hostName = UniqueName; - } + newHostName = m_Protocol->GetUniqueName( ); + else + newHostName = hostName; + if( m_LoggedIn && map ) { @@ -2275,6 +2281,15 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused quint32 FixedHostCounter = ( hostCounter & 0x0FFFFFFF ) | ( m_HostCounterID << 28 ); + + // use an invalid map width/height to indicate reconnectable games + + QByteArray FakeMapWidth; + FakeMapWidth.push_back( 192 ); + FakeMapWidth.push_back( 7 ); + QByteArray FakeMapHeight; + FakeMapHeight.push_back( 192 ); + FakeMapHeight.push_back( 7 ); if( saveGame ) { @@ -2285,43 +2300,21 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h if( state == GAME_PRIVATE ) MapGameType |= MAPGAMETYPE_PRIVATEGAME; - // use an invalid map width/height to indicate reconnectable games - - QByteArray MapWidth; - MapWidth.push_back( 192 ); - MapWidth.push_back( 7 ); - QByteArray MapHeight; - MapHeight.push_back( 192 ); - MapHeight.push_back( 7 ); - - if( m_GHost->m_Reconnect ) - EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( - state, - Util::fromUInt32( MapGameType), - map->GetMapGameFlags( ), - MapWidth, - MapHeight, - gameName, - hostName, - upTime, - "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), - saveGame->GetMagicNumber( ), - map->GetMapSHA1( ), - FixedHostCounter ) ); - else - EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( - state, - Util::fromUInt32( MapGameType), - map->GetMapGameFlags( ), - Util::fromUInt16( (quint16)0), - Util::fromUInt16( (quint16)0), - gameName, - hostName, - upTime, - "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), - saveGame->GetMagicNumber( ), - map->GetMapSHA1( ), - FixedHostCounter ) ); + + + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( + state, + Util::fromUInt32( MapGameType), + map->GetMapGameFlags( ), + m_GHost->m_Reconnect ? FakeMapWidth : Util::EmptyData16(), + m_GHost->m_Reconnect ? FakeMapHeight : Util::EmptyData16(), + gameName, + newHostName, + upTime, + "Save\\Multiplayer\\" + saveGame->GetFileNameNoPath( ), + saveGame->GetMagicNumber( ), + map->GetMapSHA1( ), + FixedHostCounter ) ); } else { @@ -2331,19 +2324,10 @@ void CBNET :: QueueGameRefresh( unsigned char state, QString gameName, QString h if( state == GAME_PRIVATE ) MapGameType |= MAPGAMETYPE_PRIVATEGAME; - // use an invalid map width/height to indicate reconnectable games - - QByteArray MapWidth; - MapWidth.push_back( 192 ); - MapWidth.push_back( 7 ); - QByteArray MapHeight; - MapHeight.push_back( 192 ); - MapHeight.push_back( 7 ); - if( m_GHost->m_Reconnect ) - EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), MapWidth, MapHeight, gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), FakeMapWidth, FakeMapHeight, gameName, newHostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); else - EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, hostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); + EnqueuePacket( m_Protocol->SEND_SID_STARTADVEX3( state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), map->GetMapWidth( ), map->GetMapHeight( ), gameName, newHostName, upTime, map->GetMapPath( ), map->GetMapCRC( ), map->GetMapSHA1( ), FixedHostCounter ) ); } } } @@ -2378,7 +2362,7 @@ void CBNET :: UnqueuePackets( unsigned char type ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] unqueued " + QString::number( Unqueued ) + " packets of type " + QString::number( type ) ); } -void CBNET :: UnqueueChatCommand( QString chatCommand ) +void CBNET :: UnqueueChatCommand( const QString &chatCommand ) { // hackhack: this is ugly code // generate the packet that would be sent for this chat command @@ -2412,60 +2396,36 @@ void CBNET :: UnqueueGameRefreshes( ) UnqueuePackets( CBNETProtocol :: SID_STARTADVEX3 ); } -bool CBNET :: IsAdmin( QString name ) +bool CBNET :: IsAdmin( const QString &name ) { - name = name.toLower(); - - for( QList :: const_iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ ) - { - if( *i == name ) - return true; - } - + if( m_Admins.contains( name, Qt :: CaseInsensitive ) ) + return true; return false; } -bool CBNET :: IsRootAdmin( QString name ) +bool CBNET :: IsRootAdmin( const QString &name ) { - // m_RootAdmin was already transformed to lower case in the constructor - - name = name.toLower(); - - // updated to permit multiple root admins seperated by a space, e.g. "Varlock Kilranin Instinct121" - // note: this function gets called frequently so it would be better to parse the root admins just once and store them in a list somewhere - // however, it's hardly worth optimizing at this point since the code's already written - - QTextStream SS(&m_RootAdmin); - - QString s; - - while( !SS.atEnd( ) ) - { - SS >> s; - - if( name == s ) - return true; + if ( m_RootAdmins.contains(name, Qt :: CaseInsensitive ) ) { + return true; } return false; } -CDBBan *CBNET :: IsBannedName( QString name ) +CDBBan *CBNET :: IsBannedName( const QString &name ) { - name = name.toLower(); - // todotodo: optimize this - maybe use a map? for( QList :: const_iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ ) { - if( (*i)->GetName( ) == name ) + if( name.compare( (*i)->GetName( ), Qt :: CaseInsensitive ) == 0) return *i; } return NULL; } -CDBBan *CBNET :: IsBannedIP( QString ip ) +CDBBan *CBNET :: IsBannedIP( const QString &ip ) { // todotodo: optimize this - maybe use a map? @@ -2478,38 +2438,26 @@ CDBBan *CBNET :: IsBannedIP( QString ip ) return NULL; } -void CBNET :: AddAdmin( QString name ) +void CBNET :: AddAdmin( const QString &name ) { - name = name.toLower(); - m_Admins.push_back( name ); + m_Admins.push_back( name.toLower() ); } -void CBNET :: AddBan( QString name, QString ip, QString gamename, QString admin, QString reason ) +void CBNET :: AddBan( const QString &name, const QString &ip, const QString &gamename, const QString &admin, const QString &reason ) { - name = name.toLower(); - m_Bans.push_back( new CDBBan( m_Server, name, ip, "N/A", gamename, admin, reason ) ); + m_Bans.push_back( new CDBBan( m_Server, name.toLower(), ip, "N/A", gamename, admin, reason ) ); } -void CBNET :: RemoveAdmin( QString name ) +void CBNET :: RemoveAdmin( const QString &name ) { - name = name.toLower(); - - for( QList :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); ) - { - if( *i == name ) - i = m_Admins.erase( i ); - else - i++; - } + m_Admins.removeOne( name.toLower( ) ); } -void CBNET :: RemoveBan( QString name ) +void CBNET :: RemoveBan( const QString &name ) { - name = name.toLower(); - for( QList :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); ) { - if( (*i)->GetName( ) == name ) + if( name.compare( (*i)->GetName( ), Qt :: CaseInsensitive ) == 0 ) i = m_Bans.erase( i ); else i++; diff --git a/ghost/bnet.h b/ghost/bnet.h index c785a52..7d398cd 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -51,6 +51,7 @@ class CMap; #include "includes.h" #include #include +#include typedef pair PairedAdminCount; typedef pair PairedAdminAdd; @@ -107,7 +108,8 @@ public slots: QList m_PairedDPSChecks; // vector of paired threaded database DotA player summary checks in progress CCallableAdminList *m_CallableAdminList; // threaded database admin list in progress CCallableBanList *m_CallableBanList; // threaded database ban list in progress - QList m_Admins; // vector of cached admins + QStringList m_Admins; // vector of cached admins + QStringList m_RootAdmins; // vector of rootadmins QList m_Bans; // vector of cached bans QString m_Server; // battle.net server to connect to QString m_ServerIP; // battle.net server to connect to (the IP address so we don't have to resolve it every time we connect) @@ -165,7 +167,7 @@ public slots: void SendPacket(); public: - CBNET( CGHost *nGHost, QString nServer, QString nServerAlias, QString nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, QString nCDKeyROC, QString nCDKeyTFT, QString nCountryAbbrev, QString nCountry, quint32 nLocaleID, QString nUserName, QString nUserPassword, QString nFirstChannel, QString nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, QByteArray nEXEVersion, QByteArray nEXEVersionHash, QString nPasswordHashType, QString nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); + CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAlias, const QString &nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, const QString &nCDKeyROC, const QString &nCDKeyTFT, const QString &nCountryAbbrev, const QString &nCountry, quint32 nLocaleID, const QString &nUserName, const QString &nUserPassword, const QString &nFirstChannel, const QString &nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, const QByteArray &nEXEVersion, const QByteArray &nEXEVersionHash, const QString &nPasswordHashType, const QString &nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); virtual ~CBNET( ); QString GetServer( ) { return m_Server; } @@ -199,30 +201,30 @@ public slots: // functions to send packets to battle.net - void SendJoinChannel( QString channel ); + void SendJoinChannel( const QString &channel ); void SendGetFriendsList( ); void SendGetClanList( ); void QueueEnterChat( ); - void QueueChatCommand( QString chatCommand ); - void QueueChatCommand( QString chatCommand, QString user, bool whisper ); - void QueueGameCreate( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, quint32 hostCounter ); - void QueueGameRefresh( unsigned char state, QString gameName, QString hostName, CMap *map, CSaveGame *saveGame, quint32 upTime, quint32 hostCounter ); + void QueueChatCommand( const QString &chatCommand ); + void QueueChatCommand( const QString &chatCommand, const QString &user, bool whisper ); + void QueueGameCreate( unsigned char state, const QString &gameName, const QString &hostName, CMap *map, CSaveGame *saveGame, quint32 hostCounter ); + void QueueGameRefresh( unsigned char state, const QString &gameName, const QString &hostName, CMap *map, CSaveGame *saveGame, quint32 upTime, quint32 hostCounter ); void QueueGameUncreate( ); void UnqueuePackets( unsigned char type ); - void UnqueueChatCommand( QString chatCommand ); + void UnqueueChatCommand( const QString &chatCommand ); void UnqueueGameRefreshes( ); // other functions - bool IsAdmin( QString name ); - bool IsRootAdmin( QString name ); - CDBBan *IsBannedName( QString name ); - CDBBan *IsBannedIP( QString ip ); - void AddAdmin( QString name ); - void AddBan( QString name, QString ip, QString gamename, QString admin, QString reason ); - void RemoveAdmin( QString name ); - void RemoveBan( QString name ); + bool IsAdmin( const QString &name ); + bool IsRootAdmin( const QString &name ); + CDBBan *IsBannedName( const QString &name ); + CDBBan *IsBannedIP( const QString &ip ); + void AddAdmin( const QString &name ); + void AddBan( const QString &name, const QString &ip, const QString &gamename, const QString &admin, const QString &reason ); + void RemoveAdmin( const QString &name ); + void RemoveBan( const QString &name ); void HoldFriends( CBaseGame *game ); void HoldClan( CBaseGame *game ); }; diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 9c6a214..093d632 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -374,7 +374,7 @@ QString CBaseGame :: GetDescription( ) return Description; } -void CBaseGame :: SetAnnounce( quint32 interval, QString message ) +void CBaseGame :: SetAnnounce( quint32 interval, const QString &message ) { m_AnnounceTimer.start(1000 * interval); m_AnnounceMessage = message; @@ -837,30 +837,30 @@ void CBaseGame::EventNewConnection() new CPotentialPlayer( m_Protocol, this, NewSocket ); } -void CBaseGame :: Send( CGamePlayer *player, QByteArray data ) +void CBaseGame :: Send( CGamePlayer *player, const QByteArray &data ) { if( player ) player->Send( data ); } -void CBaseGame :: Send( unsigned char PID, QByteArray data ) +void CBaseGame :: Send( unsigned char PID, const QByteArray &data ) { Send( GetPlayerFromPID( PID ), data ); } -void CBaseGame :: Send( QByteArray PIDs, QByteArray data ) +void CBaseGame :: Send( const QByteArray &PIDs, const QByteArray &data ) { for( int i = 0; i < PIDs.size( ); i++ ) Send( PIDs[i], data ); } -void CBaseGame :: SendAll( QByteArray data ) +void CBaseGame :: SendAll( const QByteArray &data ) { for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) (*i)->Send( data ); } -void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString message ) +void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, const QString &message ) { // send a private message to one player - it'll be marked [Private] in Warcraft 3 @@ -868,10 +868,8 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString { if( !m_GameLoading && !m_GameLoaded ) { - if( message.size( ) > 254 ) - message = message.mid( 0, 254 ); - - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray(1, player->GetPID( ) ), 16, QByteArray( ), message ) ); + // limit text length to 254 + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray(1, player->GetPID( ) ), 16, QByteArray( ), message.mid( 0, 254 ) ) ); } else { @@ -883,31 +881,29 @@ void CBaseGame :: SendChat( unsigned char fromPID, CGamePlayer *player, QString if( SID < m_Slots.size( ) ) ExtraFlags[0] = 3 + m_Slots[SID].GetColour( ); - - if( message.size( ) > 127 ) - message = message.mid( 0, 127 ); - - Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray( 1, player->GetPID( ) ), 32, QByteArray( (char*)ExtraFlags, 4 ), message ) ); + + // limit text length to 127 + Send( player, m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, QByteArray( 1, player->GetPID( ) ), 32, QByteArray( (char*)ExtraFlags, 4 ), message.mid( 0, 127 ) ) ); } } } -void CBaseGame :: SendChat( unsigned char fromPID, unsigned char toPID, QString message ) +void CBaseGame :: SendChat( unsigned char fromPID, unsigned char toPID, const QString &message ) { SendChat( fromPID, GetPlayerFromPID( toPID ), message ); } -void CBaseGame :: SendChat( CGamePlayer *player, QString message ) +void CBaseGame :: SendChat( CGamePlayer *player, const QString &message ) { SendChat( GetHostPID( ), player, message ); } -void CBaseGame :: SendChat( unsigned char toPID, QString message ) +void CBaseGame :: SendChat( unsigned char toPID, const QString &message ) { SendChat( GetHostPID( ), toPID, message ); } -void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) +void CBaseGame :: SendAllChat( unsigned char fromPID, const QString &message ) { // send a public message to all players - it'll be marked [All] in Warcraft 3 @@ -917,17 +913,13 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) if( !m_GameLoading && !m_GameLoaded ) { - if( message.size( ) > 254 ) - message = message.mid( 0, 254 ); - - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 16, QByteArray( ), message ) ); + // limit text length to 254 + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 16, QByteArray( ), message.mid( 0, 254 ) ) ); } else { - if( message.size( ) > 127 ) - message = message.mid( 0, 127 ); - - SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, Util::fromUInt32( 0), message ) ); + // limit text length to 127 + SendAll( m_Protocol->SEND_W3GS_CHAT_FROM_HOST( fromPID, GetPIDs( ), 32, Util::fromUInt32( 0), message.mid( 0, 127 ) ) ); if( m_Replay ) m_Replay->AddChatMessage( fromPID, 32, 0, message ); @@ -935,12 +927,12 @@ void CBaseGame :: SendAllChat( unsigned char fromPID, QString message ) } } -void CBaseGame :: SendAllChat( QString message ) +void CBaseGame :: SendAllChat( const QString &message ) { SendAllChat( GetHostPID( ), message ); } -void CBaseGame :: SendLocalAdminChat( QString message ) +void CBaseGame :: SendLocalAdminChat( const QString &message ) { if( !m_LocalAdminMessages ) return; @@ -2812,7 +2804,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye } } -bool CBaseGame :: EventPlayerBotCommand( CGamePlayer */*player*/, QString /*command*/, QString /*payload*/ ) +bool CBaseGame :: EventPlayerBotCommand( CGamePlayer */*player*/, const QString &/*command*/, const QString &/*payload*/ ) { // return true if the command itself should be hidden from other players @@ -3119,7 +3111,7 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, quint32 /*pong*/ ) } } -void CBaseGame :: EventGameRefreshed( QString /*server*/ ) +void CBaseGame :: EventGameRefreshed( const QString &/*server*/ ) { if( m_RefreshRehosted ) { @@ -3395,31 +3387,22 @@ CGamePlayer *CBaseGame :: GetPlayerFromSID( unsigned char SID ) return NULL; } -CGamePlayer *CBaseGame :: GetPlayerFromName( QString name, bool sensitive ) +CGamePlayer *CBaseGame :: GetPlayerFromName( const QString &name, bool sensitive ) { - if( !sensitive ) - name = name.toLower(); - for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( !(*i)->GetLeftMessageSent( ) ) { - QString TestName = (*i)->GetName( ); - - if( !sensitive ) - TestName = TestName.toLower(); - - if( TestName == name ) - return *i; + if( name.compare( (*i)->GetName( ), sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive ) == 0 ) + return *i; } } return NULL; } -quint32 CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **player ) +quint32 CBaseGame :: GetPlayerFromNamePartial( const QString &name, CGamePlayer **player ) { - name = name.toLower(); quint32 Matches = 0; *player = NULL; @@ -3429,16 +3412,16 @@ quint32 CBaseGame :: GetPlayerFromNamePartial( QString name, CGamePlayer **playe { if( !(*i)->GetLeftMessageSent( ) ) { - QString TestName = (*i)->GetName( ).toLower(); + QString TestName = (*i)->GetName( ); - if( TestName.indexOf( name ) != -1 ) + if( TestName.contains( name, Qt::CaseInsensitive ) ) { Matches++; *player = *i; // if the name matches exactly stop any further matching - if( TestName == name ) + if( TestName.compare( name, Qt::CaseInsensitive ) == 0 ) { Matches = 1; break; @@ -4194,7 +4177,7 @@ void CBaseGame :: BalanceSlots( ) } } -void CBaseGame :: AddToSpoofed( QString server, QString name, bool sendMessage ) +void CBaseGame :: AddToSpoofed( const QString &server, const QString &name, bool sendMessage ) { CGamePlayer *Player = GetPlayerFromName( name, true ); @@ -4208,47 +4191,38 @@ void CBaseGame :: AddToSpoofed( QString server, QString name, bool sendMessage ) } } -void CBaseGame :: AddToReserved( QString name ) +void CBaseGame :: AddToReserved( const QString &name ) { - name = name.toLower(); + QString nameLower = name.toLower(); // check that the user is not already reserved - for( QList :: const_iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) - { - if( *i == name ) - return; - } + if ( m_Reserved.contains( nameLower ) ) + return; - m_Reserved.push_back( name ); + m_Reserved.push_back( nameLower ); // upgrade the user if they're already in the game for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { - QString NameLower = (*i)->GetName( ).toLower(); - - if( NameLower == name ) + if( name.compare( (*i)->GetName( ), Qt::CaseInsensitive ) == 0 ) (*i)->SetReserved( true ); } } -bool CBaseGame :: IsOwner( QString name ) +bool CBaseGame :: IsOwner( const QString &name ) { QString OwnerLower = m_OwnerName.toLower(); return name.toLower() == OwnerLower; } -bool CBaseGame :: IsReserved( QString name ) +bool CBaseGame :: IsReserved( const QString &name ) { - name = name.toLower(); - - for( QList :: const_iterator i = m_Reserved.begin( ); i != m_Reserved.end( ); i++ ) - { - if( *i == name ) - return true; + if( m_Reserved.contains( name, Qt::CaseInsensitive ) ) { + return true; } - + return false; } @@ -4462,7 +4436,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) } } -void CBaseGame :: StopPlayers( QString reason ) +void CBaseGame :: StopPlayers( const QString &reason ) { // disconnect every player and set their left reason to the passed QString // we use this function when we want the code in the Update function to run before the destructor (e.g. saving players to the database) @@ -4480,7 +4454,7 @@ void CBaseGame :: StopPlayers( QString reason ) } } -void CBaseGame :: StopLaggers( QString reason ) +void CBaseGame :: StopLaggers( const QString &reason ) { for( QList :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { diff --git a/ghost/game_base.h b/ghost/game_base.h index fdc5275..c046e71 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -45,6 +45,7 @@ class CGHost; #include #include #include +#include class CBaseGame : public QObject { @@ -100,7 +101,7 @@ public slots: QList m_Players; // vector of players QList m_ScoreChecks; QQueue m_Actions; // queue of actions to be sent - QList m_Reserved; // vector of player names with reserved slots (from the !hold command) + QStringList m_Reserved; // vector of player names with reserved slots (from the !hold command) QSet m_IgnoredNames; // set of player names to NOT print ban messages for when joining because they've already been printed QSet m_IPBlackList; // set of IP addresses to blacklist from joining (todotodo: convert to uint32's for efficiency) QList m_EnforceSlots; // vector of slots to force players to use (used with saved games) @@ -200,24 +201,24 @@ public slots: quint32 GetSyncCounter() { return m_SyncCounter; } quint32 GetSyncLimit() { return m_SyncLimit; } - virtual void SetAnnounce( quint32 interval, QString message ); + virtual void SetAnnounce( quint32 interval, const QString &message ); // generic functions to send packets to players - virtual void Send( CGamePlayer *player, QByteArray data ); - virtual void Send( unsigned char PID, QByteArray data ); - virtual void Send( QByteArray PIDs, QByteArray data ); - virtual void SendAll( QByteArray data ); + virtual void Send( CGamePlayer *player, const QByteArray &data ); + virtual void Send( unsigned char PID, const QByteArray &data ); + virtual void Send( const QByteArray &PIDs, const QByteArray &data ); + virtual void SendAll( const QByteArray &data ); // functions to send packets to players - virtual void SendChat( unsigned char fromPID, CGamePlayer *player, QString message ); - virtual void SendChat( unsigned char fromPID, unsigned char toPID, QString message ); - virtual void SendChat( CGamePlayer *player, QString message ); - virtual void SendChat( unsigned char toPID, QString message ); - virtual void SendAllChat( unsigned char fromPID, QString message ); - virtual void SendAllChat( QString message ); - virtual void SendLocalAdminChat( QString message ); + virtual void SendChat( unsigned char fromPID, CGamePlayer *player, const QString &message ); + virtual void SendChat( unsigned char fromPID, unsigned char toPID, const QString &message ); + virtual void SendChat( CGamePlayer *player, const QString &message ); + virtual void SendChat( unsigned char toPID, const QString &message ); + virtual void SendAllChat( unsigned char fromPID, const QString &message ); + virtual void SendAllChat( const QString &message ); + virtual void SendLocalAdminChat( const QString &message ); virtual void SendVirtualHostPlayerInfo( CGamePlayer *player ); virtual void SendFakePlayerInfo( CGamePlayer *player ); virtual void SendAllActions( ); @@ -238,7 +239,7 @@ public slots: virtual void EventPlayerAction( CGamePlayer *player, CIncomingAction *action ); virtual void EventPlayerKeepAlive( CGamePlayer *player, quint32 checkSum ); virtual void EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlayer *chatPlayer ); - virtual bool EventPlayerBotCommand( CGamePlayer *player, QString command, QString payload ); + virtual bool EventPlayerBotCommand( CGamePlayer *player, const QString &command, const QString &payload ); virtual void EventPlayerChangeTeam( CGamePlayer *player, unsigned char team ); virtual void EventPlayerChangeColour( CGamePlayer *player, unsigned char colour ); virtual void EventPlayerChangeRace( CGamePlayer *player, unsigned char race ); @@ -249,15 +250,15 @@ public slots: // these events are called outside of any iterations - virtual void EventGameRefreshed( QString server ); + virtual void EventGameRefreshed( const QString &server ); // other functions virtual unsigned char GetSIDFromPID( unsigned char PID ); virtual CGamePlayer *GetPlayerFromPID( unsigned char PID ); virtual CGamePlayer *GetPlayerFromSID( unsigned char SID ); - virtual CGamePlayer *GetPlayerFromName( QString name, bool sensitive ); - virtual quint32 GetPlayerFromNamePartial( QString name, CGamePlayer **player ); + virtual CGamePlayer *GetPlayerFromName( const QString &name, bool sensitive ); + virtual quint32 GetPlayerFromNamePartial( const QString &name, CGamePlayer **player ); virtual CGamePlayer *GetPlayerFromColour( unsigned char colour ); virtual unsigned char GetNewPID( ); virtual unsigned char GetNewColour( ); @@ -276,17 +277,17 @@ public slots: virtual void ShuffleSlots( ); virtual QList BalanceSlotsRecursive( QList PlayerIDs, unsigned char *TeamSizes, double *PlayerScores, unsigned char StartTeam ); virtual void BalanceSlots( ); - virtual void AddToSpoofed( QString server, QString name, bool sendMessage ); - virtual void AddToReserved( QString name ); - virtual bool IsOwner( QString name ); - virtual bool IsReserved( QString name ); + virtual void AddToSpoofed( const QString &server, const QString &name, bool sendMessage ); + virtual void AddToReserved( const QString &name ); + virtual bool IsOwner( const QString &name ); + virtual bool IsReserved( const QString &name ); virtual bool IsDownloading( ); virtual bool IsGameDataSaved( ); virtual void SaveGameData( ); virtual void StartCountDown( bool force ); virtual void StartCountDownAuto( bool requireSpoofChecks ); - virtual void StopPlayers( QString reason ); - virtual void StopLaggers( QString reason ); + virtual void StopPlayers( const QString &reason ); + virtual void StopLaggers( const QString &reason ); virtual void CreateVirtualHost( ); virtual void DeleteVirtualHost( ); virtual void CreateFakePlayer( ); diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 1c7d9e9..9e48404 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -255,7 +255,7 @@ void CPotentialPlayer :: ProcessPackets( ) } } -void CPotentialPlayer :: Send( QByteArray data ) +void CPotentialPlayer :: Send( const QByteArray &data ) { if( m_Socket && m_Socket->isValid() ) m_Socket->write(data); @@ -684,7 +684,7 @@ void CGamePlayer :: ProcessPackets( ) } } -void CGamePlayer :: Send( QByteArray data ) +void CGamePlayer :: Send( const QByteArray &data ) { // must start counting packet total from beginning of connection // but we can avoid buffering packets until we know the client is using GProxy++ since that'll be determined before the game starts diff --git a/ghost/gameplayer.h b/ghost/gameplayer.h index fa5a396..f3cfac3 100644 --- a/ghost/gameplayer.h +++ b/ghost/gameplayer.h @@ -85,7 +85,7 @@ public slots: // other functions - virtual void Send( QByteArray data ); + virtual void Send( const QByteArray &data ); }; @@ -239,7 +239,7 @@ public slots: QString GetNameTerminated( ); quint32 GetPing( bool LCPing ); - void AddLoadInGameData( QByteArray nLoadInGameData ) { m_LoadInGameData.enqueue( nLoadInGameData ); } + void AddLoadInGameData( const QByteArray &nLoadInGameData ) { m_LoadInGameData.enqueue( nLoadInGameData ); } // processing functions @@ -248,7 +248,7 @@ public slots: // other functions - virtual void Send( QByteArray data ); + virtual void Send( const QByteArray &data ); virtual void EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPacket ); }; diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 0fa3520..fab37d8 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -364,13 +364,13 @@ CGHost :: ~CGHost( ) delete m_CRC; delete m_SHA; - qDeleteAll( m_BNETs ); + //qDeleteAll( m_BNETs ); m_BNETs.clear( ); delete m_CurrentGame; delete m_AdminGame; - qDeleteAll( m_Games ); + //qDeleteAll( m_Games ); m_Games.clear( ); delete m_DB; @@ -767,7 +767,7 @@ void CGHost :: EventBNETConnectTimedOut( CBNET *bnet ) m_CurrentGame->SendAllChat( m_Language->ConnectingToBNETTimedOut( bnet->GetServer( ) ) ); } -void CGHost :: EventBNETWhisper( CBNET *bnet, QString user, QString message ) +void CGHost :: EventBNETWhisper( CBNET *bnet, const QString &user, const QString &message ) { if( m_AdminGame ) { @@ -781,7 +781,7 @@ void CGHost :: EventBNETWhisper( CBNET *bnet, QString user, QString message ) } } -void CGHost :: EventBNETChat( CBNET *bnet, QString user, QString message ) +void CGHost :: EventBNETChat( CBNET *bnet, const QString &user, const QString &message ) { if( m_AdminGame ) { @@ -795,7 +795,7 @@ void CGHost :: EventBNETChat( CBNET *bnet, QString user, QString message ) } } -void CGHost :: EventBNETEmote( CBNET *bnet, QString user, QString message ) +void CGHost :: EventBNETEmote( CBNET *bnet, const QString &user, const QString &message ) { if( m_AdminGame ) { @@ -1032,7 +1032,7 @@ void CGHost :: LoadIPToCountryData( ) } } -void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, QString gameName, QString ownerName, QString creatorName, QString creatorServer, bool whisper ) +void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, const QString &gameName, const QString &ownerName, const QString &creatorName, const QString &creatorServer, bool whisper ) { if( !m_Enabled ) { diff --git a/ghost/ghost.h b/ghost/ghost.h index 7e40b16..210a224 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -165,9 +165,9 @@ public slots: void EventBNETGameRefreshed( CBNET *bnet ); void EventBNETGameRefreshFailed( CBNET *bnet ); void EventBNETConnectTimedOut( CBNET *bnet ); - void EventBNETWhisper( CBNET *bnet, QString user, QString message ); - void EventBNETChat( CBNET *bnet, QString user, QString message ); - void EventBNETEmote( CBNET *bnet, QString user, QString message ); + void EventBNETWhisper( CBNET *bnet, const QString &user, const QString &message ); + void EventBNETChat( CBNET *bnet, const QString &user, const QString &message ); + void EventBNETEmote( CBNET *bnet, const QString &user, const QString &message ); // void EventGameDeleted( CBaseGame *game ); // other functions @@ -176,7 +176,7 @@ public slots: void SetConfigs( CConfig *CFG ); void ExtractScripts( ); void LoadIPToCountryData( ); - void CreateGame( CMap *map, unsigned char gameState, bool saveGame, QString gameName, QString ownerName, QString creatorName, QString creatorServer, bool whisper ); + void CreateGame( CMap *map, unsigned char gameState, bool saveGame, const QString &gameName, const QString &ownerName, const QString &creatorName, const QString &creatorServer, bool whisper ); }; #endif diff --git a/ghost/util.cpp b/ghost/util.cpp index 5d0bb0c..08dbff8 100644 --- a/ghost/util.cpp +++ b/ghost/util.cpp @@ -26,6 +26,9 @@ #include #include +const QByteArray Util :: emptyByteArray16( 2, 0 ); +const QByteArray Util :: emptyByteArray32( 4, 0 ); + quint16 Util::extractUInt16(const QByteArray& data, int offset) { return qFromLittleEndian((uchar*)data.mid(offset, 2).data()); @@ -60,7 +63,7 @@ QByteArray Util::reverse(const QByteArray &b) return res; } -QString UTIL_QByteArrayToDecString( QByteArray b ) +QString UTIL_QByteArrayToDecString( const QByteArray &b ) { if( b.isEmpty( ) ) return QString( ); @@ -73,7 +76,7 @@ QString UTIL_QByteArrayToDecString( QByteArray b ) return result; } -QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ) +QByteArray UTIL_ExtractCString( const QByteArray &b, unsigned int start ) { // start searching the byte array at position 'start' for the first null value // if found, return the subarray from 'start' to the null value but not including the null value @@ -82,7 +85,7 @@ QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ) return s.toUtf8(); } -unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ) +unsigned char UTIL_ExtractHex( const QByteArray &b, unsigned int start, bool reverse ) { // consider the byte array to contain a 2 character ASCII encoded hex value at b[start] and b[start + 1] e.g. "FF" // extract it as a single decoded byte @@ -99,7 +102,7 @@ QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ) QByteArray result; unsigned int c; - QTextStream SS(&s); + QTextStream SS( &s, QIODevice::ReadOnly ); for( unsigned int i = 0; i < count; i++ ) { @@ -116,7 +119,7 @@ QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ) return result; } -QByteArray UTIL_FileRead( QString file ) +QByteArray UTIL_FileRead( const QString &file ) { QFile f(file); f.open(QFile::ReadOnly); @@ -130,7 +133,7 @@ QByteArray UTIL_FileRead( QString file ) return f.readAll(); } -bool UTIL_FileWrite( QString file, const QByteArray &data ) +bool UTIL_FileWrite( const QString &file, const QByteArray &data ) { QFile f(file); f.open(QFile::Truncate | QFile::WriteOnly); @@ -150,7 +153,7 @@ QString UTIL_FileSafeName( QString fileName ) return fileName.replace(QRegExp("\\\\\\/\\:\\*\\?\\<\\>\\|"), "_"); } -QString UTIL_AddPathSeparator( QString path ) +QString UTIL_AddPathSeparator( const QString &path ) { if( path.isEmpty( ) ) return path; @@ -161,7 +164,7 @@ QString UTIL_AddPathSeparator( QString path ) return path + QDir::separator(); } -QByteArray UTIL_EncodeStatString( QByteArray &data ) +QByteArray UTIL_EncodeStatString( const QByteArray &data ) { unsigned char Mask = 1; QByteArray Result; @@ -186,7 +189,7 @@ QByteArray UTIL_EncodeStatString( QByteArray &data ) return Result; } -bool UTIL_IsLanIP( QByteArray ip ) +bool UTIL_IsLanIP( const QByteArray &ip ) { if( ip.size( ) != 4 ) return false; @@ -216,7 +219,7 @@ bool UTIL_IsLanIP( QByteArray ip ) return false; } -bool UTIL_IsLocalIP( QByteArray ip, QList &localIPs ) +bool UTIL_IsLocalIP( const QByteArray &ip, QList &localIPs ) { if( ip.size( ) != 4 ) return false; @@ -233,7 +236,7 @@ bool UTIL_IsLocalIP( QByteArray ip, QList &localIPs ) return false; } -QList UTIL_Tokenize( QString s, char delim ) +QList UTIL_Tokenize( const QString &s, char delim ) { QList Tokens; QString Token; diff --git a/ghost/util.h b/ghost/util.h index 32e3744..0aa0d40 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -34,33 +34,38 @@ class Util static QByteArray fromUInt16(const quint16 &value); static QByteArray fromUInt32(const quint32 &value); + static const QByteArray &EmptyData16( ) { return emptyByteArray16; } + static const QByteArray &EmptyData32( ) { return emptyByteArray32; } static QByteArray reverse(const QByteArray &b); +private: + static const QByteArray emptyByteArray16; + static const QByteArray emptyByteArray32; }; // byte arrays -QString UTIL_QByteArrayToDecString( QByteArray b ); -QByteArray UTIL_ExtractCString( QByteArray &b, unsigned int start ); -unsigned char UTIL_ExtractHex( QByteArray &b, unsigned int start, bool reverse ); +QString UTIL_QByteArrayToDecString( const QByteArray &b ); +QByteArray UTIL_ExtractCString( const QByteArray &b, unsigned int start ); +unsigned char UTIL_ExtractHex( const QByteArray &b, unsigned int start, bool reverse ); QByteArray UTIL_ExtractNumbers( QString s, unsigned int count ); // files -QByteArray UTIL_FileRead( QString file ); -bool UTIL_FileWrite( QString file, const QByteArray &data ); +QByteArray UTIL_FileRead( const QString &file ); +bool UTIL_FileWrite( const QString &file, const QByteArray &data ); QString UTIL_FileSafeName( QString fileName ); -QString UTIL_AddPathSeparator( QString path ); +QString UTIL_AddPathSeparator( const QString &path ); // stat strings -QByteArray UTIL_EncodeStatString( QByteArray &data ); +QByteArray UTIL_EncodeStatString( const QByteArray &data ); // other -bool UTIL_IsLanIP( QByteArray ip ); -bool UTIL_IsLocalIP( QByteArray ip, QList &localIPs ); -QList UTIL_Tokenize( QString s, char delim ); +bool UTIL_IsLanIP( const QByteArray &ip ); +bool UTIL_IsLocalIP( const QByteArray &ip, QList &localIPs ); +QList UTIL_Tokenize( const QString &s, char delim ); // math From cb2d5d0685beb6d9faaa1b21f7a76fed65306267 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sat, 8 May 2010 14:59:24 +0000 Subject: [PATCH 54/69] --- ghost/mpqarchive.cpp | 479 +++++++++++++++++++++++++++++++++++++++++++ ghost/mpqarchive.h | 172 ++++++++++++++++ ghost/mpqfile.cpp | 239 +++++++++++++++++++++ ghost/mpqfile.h | 56 +++++ 4 files changed, 946 insertions(+) create mode 100644 ghost/mpqarchive.cpp create mode 100644 ghost/mpqarchive.h create mode 100644 ghost/mpqfile.cpp create mode 100644 ghost/mpqfile.h diff --git a/ghost/mpqarchive.cpp b/ghost/mpqarchive.cpp new file mode 100644 index 0000000..bc6880e --- /dev/null +++ b/ghost/mpqarchive.cpp @@ -0,0 +1,479 @@ +// rewritten using StormLib: +/*****************************************************************************/ +/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */ +/* */ +/* Author : Ladislav Zezula */ +/* E-mail : ladik@zezula.net */ +/* WWW : www.zezula.net */ +/*---------------------------------------------------------------------------*/ +/* Archive functions of Storm.dll */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */ +/* 19.11.03 1.01 Dan Big endian handling */ +/*****************************************************************************/ + +#include +#include "mpqarchive.h" +#include "mpqfile.h" +#include "includes.h" + +QByteArray m_ID; + + +bool MPQArchive::Header::readFrom(MPQArchive *parent) +{ + char buffer[32]; + if (parent->read(buffer, 32) != 32) + return false; +DEBUG_Print(QByteArray(buffer, 32).toHex()); + //<- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> + //4d50511a 20000000 98a46c00 00000f00 c8256c00 c8656c00 00040000 ed030000 + + m_ID = QByteArray(buffer, 4); + m_HeaderSize = qFromLittleEndian((unsigned char*)buffer + 4); + m_ArchiveSize = qFromLittleEndian((unsigned char*)buffer + 8); + m_FormatVersion = qFromLittleEndian((unsigned char*)buffer + 12); + m_BlockSize = qFromLittleEndian((unsigned char*)buffer + 14); + m_HashTablePos = qFromLittleEndian((unsigned char*)buffer + 16); + m_BlockTablePos = qFromLittleEndian((unsigned char*)buffer + 20); + m_HashTableSize = qFromLittleEndian((unsigned char*)buffer + 24); + m_BlockTableSize = qFromLittleEndian((unsigned char*)buffer + 28); + + return true; +} + +bool MPQArchive::Shunt::readFrom(MPQArchive *parent) +{ + char buffer[12]; + if (parent->read(buffer, 12) != 12) + return false; + + m_ID = QByteArray(buffer, 4); + m_HeaderPos = qFromLittleEndian((unsigned char*)buffer + 8); + + return true; +} + +bool MPQArchive::HashEntry::readFrom(MPQArchive *parent, quint32 &Seed1, quint32 &Seed2) +{ + char buffer[16]; + if (parent->read(buffer, 16) != 16) + return false; + + unsigned char buffer_out[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + for (int i = 0; i < 4; i++) + { + quint32 p = qFromLittleEndian((unsigned char*)buffer + i * 4); + Seed2 += parent->m_CryptBuffer[0x400 + (Seed1 & 0xFF)]; + quint32 ch = p ^ (Seed1 + Seed2); + + Seed1 = ((~Seed1 << 0x15) + 0x11111111) | (Seed1 >> 0x0B); + Seed2 = ch + Seed2 + (Seed2 << 5) + 3; + qToLittleEndian(ch, buffer_out + i * 4); + } + + m_Name1 = qFromLittleEndian(buffer_out + 0); + m_Name2 = qFromLittleEndian(buffer_out + 4); + m_Locale = qFromLittleEndian(buffer_out + 8); + m_Platform = qFromLittleEndian(buffer_out + 10); + m_BlockIndex = qFromLittleEndian(buffer_out + 12); + + return true; +} + +bool MPQArchive::BlockEntry::readFrom(MPQArchive *parent, quint32 &Seed1, quint32 &Seed2) +{ + m_Parent = parent; + char buffer[16]; + if (parent->read(buffer, 16) != 16) + return false; + + unsigned char buffer_out[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + for (int i = 0; i < 4; i++) + { + quint32 p = qFromLittleEndian((unsigned char*)buffer + i * 4); + Seed2 += parent->m_CryptBuffer[0x400 + (Seed1 & 0xFF)]; + quint32 ch = p ^ (Seed1 + Seed2); + + Seed1 = ((~Seed1 << 0x15) + 0x11111111) | (Seed1 >> 0x0B); + Seed2 = ch + Seed2 + (Seed2 << 5) + 3; + qToLittleEndian(ch, buffer_out + i * 4); + } + + m_FilePos = qFromLittleEndian(buffer_out + 0); + m_CSize = qFromLittleEndian(buffer_out + 4); + m_FSize = qFromLittleEndian(buffer_out + 8); + m_Flags = qFromLittleEndian(buffer_out + 12); + return true; +} + +bool MPQArchive::BlockEntry::encrypted() +{ + return (m_Flags & 0x00010000); +} + +bool MPQArchive::BlockEntry::fixSeed() +{ + return (m_Flags & 0x00020000); +} + +bool MPQArchive::BlockEntry::compressed() +{ + return (m_Flags & 0x0000FF00); +} + +bool MPQArchive::BlockEntry::exists() +{ + return (m_Flags & 0x80000000); +} + +bool MPQArchive::BlockEntry::singleUnit() +{ + return (m_Flags & 0x01000000); +} + +bool MPQArchive::BlockEntry::hasExtra() +{ + return (m_Flags & 0x04000000); +} + +bool MPQArchive::BlockEntry::usesImplode() +{ + return (m_Flags & 0x00000100); +} + +bool MPQArchive::BlockEntry::valid() +{ + return !(m_Flags & ~( 0x00000100 | 0x00000200 | 0x00010000 | 0x00020000 | 0x01000000 | 0x02000000 | 0x04000000 | 0x80000000 )); +} + +QByteArray MPQArchive::BlockEntry::readAll() +{ + //m_Parent->seek(m_FilePos + m_Parent->m_HeaderOffset); + //return m_Parent->read(m_CSize); + if (compressed()) + return "SINGLEUNIT"; + + return "-"; +} + +bool MPQArchive::FileNode::readFrom(MPQArchive *parent) +{ + char buffer[16]; + if (parent->read(buffer, 16) != 16) + return false; + + qint32 m_References; + QByteArray m_Filename; + int m_Size; + return true; +} + + +MPQArchive::MPQArchive(const QString &file) + : QFile(file) +{ + m_Error = NO_ERROR; + m_HashTable = NULL; + + m_FileList = NULL; + m_BlockTable = NULL; + m_HashTable = NULL; + m_ListFile = NULL; + + quint32 dwSeed = 0x00100001; + + // Initialize the decryption buffer. + for (int index1 = 0; index1 < 0x100; index1++) + { + for (int index2 = index1, i = 0; i < 5; i++, index2 += 0x100) + { + quint32 temp1, temp2; + + dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; + temp1 = (dwSeed & 0xFFFF) << 0x10; + + dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; + temp2 = (dwSeed & 0xFFFF); + + m_CryptBuffer[index2] = (temp1 | temp2); + } + } +} + +quint32 MPQArchive::getHash(const char *data, int offset) +{ + quint32 Seed1 = 0x7FED7FED; + quint32 Seed2 = 0xEEEEEEEE; + + while(*data != 0) + { + quint32 ch = toupper(*data++); + + Seed1 = m_CryptBuffer[offset + ch] ^ (Seed1 + Seed2); + Seed2 = ch + Seed1 + Seed2 + (Seed2 << 5) + 3; + } + + return Seed1; +} + +bool MPQArchive::open() +{ + if (!QFile::open(ReadOnly)) + { + m_Error = CANNOT_OPEN_FILE; + return false; + } + + m_HeaderOffset = 0; + + for(;;) + { + if (!m_Header.readFrom(this)) + { + m_Error = FILE_CORRUPT; + return false; + } + + // Special check : Some MPQs are actually AVI files, only with + // changed extension. + if (m_Header.m_ID == "FFIR" || + m_Header.m_ID == " IVA" || + m_Header.m_ID == "TSIL") + { + m_Error = FILE_IS_AVI; + return false; + } +/* +/ note: Ignore the MPQ shunt completely if the caller wants to open the MPQ as V1.0 + + // If there is the MPQ shunt signature, process it + if (m_Header.m_ID == "MPQ\x1B") + { + + //ha->ShuntPos = MpqPos; + + if (!m_CurrentShunt.readFrom(this)) + return false; + + // Set the MPQ pos and repeat the search + if (!seek(m_CurrentShunt.m_HeaderPos)) + return false; + + continue; + } +*/ + // There must be MPQ header signature + if (m_Header.m_ID != "MPQ\x1A") + { + m_HeaderOffset += 0x200; + if (!seek(m_HeaderOffset)) + { + m_Error = FILE_CORRUPT; + return false; + } + + continue; + } + + // If valid signature has been found, break the loop + if(m_Header.m_FormatVersion == 0) + break; + + m_Error = INVALID_HEADER; + return false; + } + + m_BlockSize = 0x200 << m_Header.m_BlockSize; + DEBUG_Print("Block size is " + QString::number(m_Header.m_BlockSize) + " bzw. " + QString::number(m_BlockSize)); + + // read hash table + if (m_Header.m_HashTableSize > 0) + { + m_HashTable = new HashEntry[m_Header.m_HashTableSize]; + seek(m_Header.m_HashTablePos + m_HeaderOffset); + + // Decrypt hash table on the fly + const char *key = "(HASH TABLE)"; + quint32 Seed1 = getHash(key, 0x300);//0x7FED7FED; + quint32 Seed2 = 0xEEEEEEEE; + + // Prepare seeds + /*for (uint i = 0; i < strlen(key); i++) + { + Seed1 = m_CryptBuffer[0x300 + key[i]] ^ (Seed1 + Seed2); + Seed2 = key[i] + Seed1 + Seed2 + (Seed2 << 5) + 3; + } + + Seed1 = getHash(key, 0x300); + Seed2 = 0xEEEEEEEE; + */ + + for (uint i = 0; i < m_Header.m_HashTableSize; i++) + if (!m_HashTable[i].readFrom(this, Seed1, Seed2)) + { + m_Error = FILE_CORRUPT; + return false; + } + + DEBUG_Print("Read "+ QString::number(m_Header.m_HashTableSize) + " hash entries"); + } + + // read block table + if (m_Header.m_BlockTableSize > 0) + { + m_BlockTable = new BlockEntry[m_Header.m_BlockTableSize]; + seek(m_Header.m_BlockTablePos + m_HeaderOffset); + + // Decrypt hash table on the fly + const char *key = "(BLOCK TABLE)"; + quint32 Seed1 = getHash(key, 0x300);//0x7FED7FED; + quint32 Seed2 = 0xEEEEEEEE; + + // Prepare seeds + /*for (uint i = 0; i < strlen(key); i++) + { + Seed1 = m_CryptBuffer[0x300 + key[i]] ^ (Seed1 + Seed2); + Seed2 = key[i] + Seed1 + Seed2 + (Seed2 << 5) + 3; + } + + Seed2 = 0xEEEEEEEE; + */ + + for (uint i = 0; i < m_Header.m_BlockTableSize; i++) + if (!m_BlockTable[i].readFrom(this, Seed1, Seed2)) + { + m_Error = FILE_CORRUPT; + return false; + } + + DEBUG_Print("Read "+ QString::number(m_Header.m_BlockTableSize) + " block entries"); + } + + // verify the block table + BlockEntry *pBlockEnd = m_BlockTable + m_Header.m_BlockTableSize + 1; + BlockEntry *pBlock = m_BlockTable; + + // we will check if all sizes in the block table is correct. + for(; pBlock < pBlockEnd; pBlock++) + if(pBlock->m_Flags & 0x80000000 /*MPQ_FILE_EXISTS*/ && pBlock->m_FilePos > size()) + { + m_Error = BLOCK_TABLE_CORRUPT; + return false; + } + + // Add the internal listfile + const char* listfilename = "(listfile)"; + HashEntry *pHash = GetHashEntry(listfilename); + + if (pHash == NULL || pHash->m_BlockIndex > m_Header.m_BlockTableSize) + { + m_Error = NO_FILE_LIST; + return false; + } + + // Get block and test if the file was not already deleted. + pBlock = m_BlockTable + pHash->m_BlockIndex; + + if (!pBlock->exists() || !pBlock->valid()) + { + m_Error = NO_FILE_LIST; + return false; + } + + DEBUG_Print("file list @block " + QString::number(pHash->m_BlockIndex)); + + m_ListFile = new MPQFile(this, listfilename, pBlock, pHash); + + // If the caller didn't specified otherwise, + // load the "(attributes)" file + // Ignore the result here. Attrobutes are not necessary, + // if they are not there, we will just ignore them +// SAttrFileLoad(ha); + + return true; +} + +MPQFile* MPQArchive::getFile(const QByteArray &filename) +{ + HashEntry *pHash = GetHashEntry(filename.data()); + + if (pHash == NULL || pHash->m_BlockIndex > m_Header.m_BlockTableSize) + { + m_Error = NO_FILE_LIST; + return false; + } + + // Get block and test if the file was not already deleted. + BlockEntry *pBlock = m_BlockTable + pHash->m_BlockIndex; + + if (!pBlock->exists() || !pBlock->valid()) + { + m_Error = NO_FILE_LIST; + return false; + } + + DEBUG_Print("file @block " + QString::number(pHash->m_BlockIndex)); + + return new MPQFile(this, filename.data(), pBlock, pHash); +} + +MPQArchive::~MPQArchive() +{ + delete[] m_CryptBuffer; + delete[] m_BlockTable; + delete[] m_HashTable; + delete[] m_FileList; + delete m_ListFile; +} + +MPQArchive::HashEntry *MPQArchive::GetHashEntry(const char * file, quint32 locale) +{ + HashEntry *pHashEnd = m_HashTable + m_Header.m_HashTableSize; + HashEntry *pHash0; // File hash entry (start) + HashEntry *pHash; // File hash entry (current) + HashEntry *pHashNeutral = NULL; + + // Decrypt name and block index + quint32 index = getHash(file) & (m_Header.m_HashTableSize - 1); + quint32 name1 = getHash(file, 0x100); + quint32 name2 = getHash(file, 0x200); + cout << file << " " << index << " " << m_Header.m_HashTableSize << " " << name2 << endl; + + pHash = pHash0 = m_HashTable + index; + + // Look for hash index + while(pHash->m_BlockIndex != 0xFFFFFFFF /*HASH_ENTRY_FREE*/) + { + if(pHash->m_Name1 == name1 && + pHash->m_Name2 == name2 && + pHash->m_BlockIndex != 0xFFFFFFFE /*HASH_ENTRY_DELETED*/) + { + if (locale == 0xFFFFFFFF) + return pHash; + + else + { + if (pHash->m_Locale == 0) + pHashNeutral = pHash; + + if (pHash->m_Locale == locale) + return pHash; + } + } + + // Move to the next hash entry + if(++pHash >= pHashEnd) + pHash = m_HashTable; + if(pHash == pHash0) + break; + } + + // File was not found + return pHashNeutral; +} + diff --git a/ghost/mpqarchive.h b/ghost/mpqarchive.h new file mode 100644 index 0000000..ae57263 --- /dev/null +++ b/ghost/mpqarchive.h @@ -0,0 +1,172 @@ +#ifndef MPQARCHIVE_H +#define MPQARCHIVE_H + +#include +class MPQFile; + +class MPQArchive : public QFile +{ + Q_OBJECT + +public: + MPQArchive(const QString & filename); + virtual ~MPQArchive(); + + bool open(); + MPQFile* getFile(const QByteArray &filename); + + enum Error + { + NO_ERROR, + FILE_CORRUPT, + INVALID_HEADER, + FILE_IS_AVI, + CANNOT_OPEN_FILE, + BLOCK_TABLE_CORRUPT, + NO_FILE_LIST, + } m_Error; + + class Header + { + public: + bool readFrom(MPQArchive* parent); + + // The ID_MPQ ('MPQ\x1A') signature + QByteArray m_ID; + + // Size of the archive header + quint32 m_HeaderSize; + + // Size of MPQ archive + // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive + // is calculated as the size from the beginning of the archive to the end of the hash table, + // block table, or extended block table (whichever is largest). + quint32 m_ArchiveSize; + + // 0 = Original format + // 1 = Extended format (The Burning Crusade and newer) + quint16 m_FormatVersion; + + // Power of two exponent specifying the number of 512-byte disk sectors in each logical sector + // in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. + // Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors). + quint16 m_BlockSize; + + // Offset to the beginning of the hash table, relative to the beginning of the archive. + quint32 m_HashTablePos; + + // Offset to the beginning of the block table, relative to the beginning of the archive. + quint32 m_BlockTablePos; + + // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for + // the original MoPaQ format, or less than 2^20 for the Burning Crusade format. + quint32 m_HashTableSize; + + // Number of entries in the block table + quint32 m_BlockTableSize; + }; + + class Shunt + { + public: + bool readFrom(MPQArchive* parent); + + // The ID_MPQ_SHUNT ('MPQ\x1B') signature + QByteArray m_ID; + + // Position of the MPQ header, relative to the begin of the shunt + qint32 m_HeaderPos; + }; + + class FileNode + { + public: + bool readFrom(MPQArchive* parent); + + qint32 m_References; + QByteArray m_Filename; + int m_Size; + }; + + class HashEntry + { + public: + bool readFrom(MPQArchive* parent, quint32 &Seed1, quint32& Seed2); + + // The hash of the file path, using method A. + quint32 m_Name1; + + // The hash of the file path, using method B. + quint32 m_Name2; + + // The language of the file. This is a Windows LANGID data type, and uses the same values. + // 0 indicates the default language (American English), or that the file is language-neutral. + quint16 m_Locale; + + // The platform the file is used for. 0 indicates the default platform. + // No other values have been observed. + quint16 m_Platform; + + // If the hash table entry is valid, this is the index into the block table of the file. + // Otherwise, one of the following two values: + // - FFFFFFFFh: Hash table entry is empty, and has always been empty. + // Terminates searches for a given file. + // - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file). + // Does not terminate searches for a given file. + quint32 m_BlockIndex; + }; + + class BlockEntry + { + public: + bool readFrom(MPQArchive* parent, quint32 &Seed1, quint32& Seed2); + + bool exists(); + bool valid(); + bool compressed(); + bool encrypted(); + bool fixSeed(); + bool singleUnit(); + bool hasExtra(); + bool usesImplode(); + + MPQArchive *m_Parent; + QByteArray readAll(); + + // Offset of the beginning of the block, relative to the beginning of the archive. + quint32 m_FilePos; + + // Compressed file size + quint32 m_CSize; + + // Only valid if the block is a file; otherwise meaningless, and should be 0. + // If the file is compressed, this is the size of the uncompressed file data. + quint32 m_FSize; + + // Flags for the file. See MPQ_FILE_XXXX constants + quint32 m_Flags; + }; + + int m_HeaderOffset; // offset where the header was found + int m_BlockSize; // Size of file block + quint32 getHash(const char *data, int offset = 0x000); + MPQFile *m_ListFile; + quint32 m_CryptBuffer[0x500]; + +private: + HashEntry *GetHashEntry(const char * file, quint32 locale = 0xFFFFFFFF); + + int m_ShuntPos; // MPQShunt offset (only valid if a shunt is present) + int m_HashTablePos; // Hash table offset (relative to the begin of the file) + int m_BlockTablePos; // Block table offset (relative to the begin of the file) + int m_ExtBlockTablePos; // Ext. block table offset (relative to the begin of the file) + int m_MpqSize; // Size of MPQ archive + + Header m_Header; // MPQ header + HashEntry *m_HashTable; + BlockEntry *m_BlockTable; + FileNode *m_FileList; + +}; + +#endif // MPGARCHIVE_H diff --git a/ghost/mpqfile.cpp b/ghost/mpqfile.cpp new file mode 100644 index 0000000..3c33bb2 --- /dev/null +++ b/ghost/mpqfile.cpp @@ -0,0 +1,239 @@ +#include "mpqfile.h" +#include "includes.h" +#include + +MPQFile::MPQFile(MPQArchive *archive, const QString &filename, MPQArchive::BlockEntry *block, MPQArchive::HashEntry *hash) +{ + m_Parent = archive; + m_BlockEntry = block; + m_HashEntry = hash; + m_Seed1 = 0; + m_Name = filename; + m_Size = block->m_FSize; + DEBUG_Print("Block size: " + QString::number(block->m_CSize)); + DEBUG_Print("File size: " + QString::number(block->m_FSize)); + m_Blocks = (block->m_FSize + archive->m_BlockSize - 1) / archive->m_BlockSize; + DEBUG_Print("Number of blocks: " + QString::number(m_Blocks)); + + m_PositionFromBegin = block->m_FilePos + archive->m_HeaderOffset; + m_PositionFromHeader = block->m_FilePos; + + if (block->compressed()) + { + } + + if (block->encrypted()) + { + QString name = filename.section('\\', -1); + + m_Seed1 = archive->getHash(name.toUtf8().data(), 0x300); + if (block->fixSeed()) + m_Seed1 = (m_Seed1 + block->m_FilePos) ^ block->m_FSize; + } +/* + // Resolve pointers to file's attributes + if(nError == ERROR_SUCCESS && ha->pAttributes != NULL) + { + if(ha->pAttributes->pCrc32 != NULL) + hf->pCrc32 = ha->pAttributes->pCrc32 + dwBlockIndex; + if(ha->pAttributes->pFileTime != NULL) + hf->pFileTime = ha->pAttributes->pFileTime + dwBlockIndex; + if(ha->pAttributes->pMd5 != NULL) + hf->pMd5 = ha->pAttributes->pMd5 + dwBlockIndex; + }*/ +} + +bool MPQFile::read() +{ + MPQArchive::BlockEntry *block = m_BlockEntry; + + if (block->compressed()) + { + m_BlockPosTableSize = m_Blocks + 1 + (block->hasExtra() ? 1 : 0); + m_BlockPosTable = new qint32[m_BlockPosTableSize]; + + m_Parent->seek(m_PositionFromBegin); + + char buffer[4]; + qint32 *pos = m_BlockPosTable, *posEnd = pos + m_BlockPosTableSize; + for (; pos != posEnd; pos++) + { + if (m_Parent->read(buffer, 4) != 4) + { + m_Error = POS_TABLE_CORRUPT; + return false; + } + + *pos = qFromLittleEndian((unsigned char*)buffer); + } + + // encryption check + qint32 bytes = m_BlockPosTableSize * 4; + if (m_BlockPosTable[0] != bytes) + m_BlockEntry->m_Flags |= 0x00010000; + + quint32 saveSeed1 = 0; + if (m_BlockEntry->encrypted()) + { + quint32 temp = (m_BlockPosTable[0] ^ bytes) - 0xEEEEEEEE; + + int i; + for(i = 0; i < 0x100; i++) // Try all 255 possibilities + { + quint32 seed1; + quint32 seed2 = 0xEEEEEEEE; + quint32 ch; + + // Try the first DWORD (We exactly know the value) + seed1 = temp - m_Parent->m_CryptBuffer[0x400 + i]; + seed2 += m_Parent->m_CryptBuffer[0x400 + (seed1 & 0xFF)]; + ch = m_BlockPosTable[0] ^ (seed1 + seed2); + + if(ch != (quint32)bytes) + continue; + + // Add 1 because we are decrypting block positions + saveSeed1 = seed1 + 1; + + // If OK, continue and test the second value. We don't know exactly the value, + // but we know that the second one has lower 16 bits set to zero + // (no compressed block is larger than 0xFFFF bytes) + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + + seed2 += m_Parent->m_CryptBuffer[0x400 + (seed1 & 0xFF)]; + ch = m_BlockPosTable[1] ^ (seed1 + seed2); + + if((ch & 0xFFFF0000) == 0) + break; + } + + if (i == 0x100) + { + m_Error = SEED_NOT_FOUND; + return false; + } + + decryptBlock((quint32*)m_BlockPosTable, m_BlockPosTableSize, saveSeed1 - 1); + } + + cout << m_BlockPosTableSize << ", " << m_BlockEntry->m_FilePos << ", " << m_BlockPosTable[0] << ", " << m_BlockPosTable[1] << endl; + + if (m_BlockPosTable[0] != bytes) + { + m_Error = DECRYPTION_FAILED; + return false; + } + + DEBUG_Print(QString::number(m_BlockPosTableSize) + " blockpos loaded"); + + for (int i = 0; i < m_Blocks - 1; i++) + readBlock(m_BlockPosTable[i + 1], m_BlockPosTable[i + 2], saveSeed1 + i); + + QFile out("test.out"); + if (out.open(QFile::WriteOnly | QFile::Truncate)) + { + out.write(m_Content); + out.close(); + } + + return true; + } + + DEBUG_Print("file not compressed"); + + + + return true; +} + +bool MPQFile::readBlock(quint32 from, quint32 to, quint32 seed) +{ + int len = to - from; + + if (len > m_Parent->m_BlockSize) + len = m_Parent->m_BlockSize; + + m_Parent->seek(m_PositionFromBegin + from); + QByteArray part; + + if (m_BlockEntry->encrypted()) + { + quint32 num = len >> 2; + + char buffer[4]; + quint32 data[num]; + + for (uint i = 0; i < num; i++) + { + if (m_Parent->read((char*)buffer, 4) != 4) + { + m_Error = FILE_CORRUPTED; + return false; + } + + data[i] = qFromLittleEndian((unsigned char*)buffer); + } + + decryptBlock(data, num, seed); + + for (uint i = 0; i < num; i++) + { + //qToLittleEndian(data[i], (unsigned char*)buffer); + //part.append(buffer, 4); + part.append((char*)&data[i], 4); + } + } + + else + { + QByteArray ba = m_Parent->read(len); + if (ba.size() != len) + { + m_Error = FILE_CORRUPTED; + return false; + } + + part.append(ba); + } + + if (m_BlockEntry->usesImplode()) + { + DEBUG_Print("Uses PKWARE"); + } + + m_Content.append(part); + + return true; +} + +void MPQFile::decryptBlock(quint32 *data, quint32 length, quint32 seed) +{ + quint32 seed2 = 0xEEEEEEEE; + quint32 ch; + + while(length-- > 0) + { + seed2 += m_Parent->m_CryptBuffer[0x400 + (seed & 0xFF)]; + ch = *data ^ (seed + seed2); + + seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + *data++ = ch; + } +} + + + + + + + + + + + + + + + diff --git a/ghost/mpqfile.h b/ghost/mpqfile.h new file mode 100644 index 0000000..e55a860 --- /dev/null +++ b/ghost/mpqfile.h @@ -0,0 +1,56 @@ +#ifndef MPQFILE_H +#define MPQFILE_H + +#include "mpqarchive.h" + +class MPQFile +{ +public: + MPQFile(MPQArchive* archive, const QString &filename, MPQArchive::BlockEntry *block, MPQArchive::HashEntry *hash); + + enum Error + { + NO_ERROR, + POS_TABLE_CORRUPT, + SEED_NOT_FOUND, + DECRYPTION_FAILED, + FILE_CORRUPTED, + } m_Error; + + bool read(); + bool readBlock(quint32 from, quint32 to, quint32 seed); + void decryptBlock(quint32 *data, quint32 length, quint32 seed); + + MPQArchive* m_Parent; + MPQArchive::BlockEntry *m_BlockEntry; + MPQArchive::HashEntry *m_HashEntry; + + quint32 m_Seed1; + quint32 m_PositionFromBegin; + quint32 m_PositionFromHeader; + quint32 m_Size; + + int m_BlockPosTableSize; + qint32 *m_BlockPosTable; + + int m_Blocks; + + QByteArray m_Content; + + QString m_Name; + +/* DWORD * pdwBlockPos; // Position of each file block (only for compressed files) + DWORD nBlocks; // Number of blocks in the file (incl. the last incomplete one) + BOOL bBlockPosLoaded; // TRUE if block positions loaded + BYTE * pbFileBuffer; // Decompressed file (for single unit files, size is the uncompressed file size) + + TMPQCRC32 * pCrc32; // Pointer to CRC32 (NULL if none) + TMPQFileTime * pFileTime; // Pointer to file's FILETIME (NULL if none) + TMPQMD5 * pMd5; // Pointer to file's MD5 (NULL if none) + + DWORD dwHashIndex; // Index to Hash table + DWORD dwBlockIndex; // Index to Block table + char szFileName[1]; // File name (variable length) */ +}; + +#endif // MPQFILE_H From 239718f714946bd68fa8c06304937db603d8fa15 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sat, 8 May 2010 15:06:31 +0000 Subject: [PATCH 55/69] --- ghost/mpqarchive.cpp | 479 ------------------------------------------- ghost/mpqarchive.h | 172 ---------------- ghost/mpqfile.cpp | 239 --------------------- ghost/mpqfile.h | 56 ----- 4 files changed, 946 deletions(-) delete mode 100644 ghost/mpqarchive.cpp delete mode 100644 ghost/mpqarchive.h delete mode 100644 ghost/mpqfile.cpp delete mode 100644 ghost/mpqfile.h diff --git a/ghost/mpqarchive.cpp b/ghost/mpqarchive.cpp deleted file mode 100644 index bc6880e..0000000 --- a/ghost/mpqarchive.cpp +++ /dev/null @@ -1,479 +0,0 @@ -// rewritten using StormLib: -/*****************************************************************************/ -/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */ -/* */ -/* Author : Ladislav Zezula */ -/* E-mail : ladik@zezula.net */ -/* WWW : www.zezula.net */ -/*---------------------------------------------------------------------------*/ -/* Archive functions of Storm.dll */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */ -/* 19.11.03 1.01 Dan Big endian handling */ -/*****************************************************************************/ - -#include -#include "mpqarchive.h" -#include "mpqfile.h" -#include "includes.h" - -QByteArray m_ID; - - -bool MPQArchive::Header::readFrom(MPQArchive *parent) -{ - char buffer[32]; - if (parent->read(buffer, 32) != 32) - return false; -DEBUG_Print(QByteArray(buffer, 32).toHex()); - //<- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> - //4d50511a 20000000 98a46c00 00000f00 c8256c00 c8656c00 00040000 ed030000 - - m_ID = QByteArray(buffer, 4); - m_HeaderSize = qFromLittleEndian((unsigned char*)buffer + 4); - m_ArchiveSize = qFromLittleEndian((unsigned char*)buffer + 8); - m_FormatVersion = qFromLittleEndian((unsigned char*)buffer + 12); - m_BlockSize = qFromLittleEndian((unsigned char*)buffer + 14); - m_HashTablePos = qFromLittleEndian((unsigned char*)buffer + 16); - m_BlockTablePos = qFromLittleEndian((unsigned char*)buffer + 20); - m_HashTableSize = qFromLittleEndian((unsigned char*)buffer + 24); - m_BlockTableSize = qFromLittleEndian((unsigned char*)buffer + 28); - - return true; -} - -bool MPQArchive::Shunt::readFrom(MPQArchive *parent) -{ - char buffer[12]; - if (parent->read(buffer, 12) != 12) - return false; - - m_ID = QByteArray(buffer, 4); - m_HeaderPos = qFromLittleEndian((unsigned char*)buffer + 8); - - return true; -} - -bool MPQArchive::HashEntry::readFrom(MPQArchive *parent, quint32 &Seed1, quint32 &Seed2) -{ - char buffer[16]; - if (parent->read(buffer, 16) != 16) - return false; - - unsigned char buffer_out[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 }; - - for (int i = 0; i < 4; i++) - { - quint32 p = qFromLittleEndian((unsigned char*)buffer + i * 4); - Seed2 += parent->m_CryptBuffer[0x400 + (Seed1 & 0xFF)]; - quint32 ch = p ^ (Seed1 + Seed2); - - Seed1 = ((~Seed1 << 0x15) + 0x11111111) | (Seed1 >> 0x0B); - Seed2 = ch + Seed2 + (Seed2 << 5) + 3; - qToLittleEndian(ch, buffer_out + i * 4); - } - - m_Name1 = qFromLittleEndian(buffer_out + 0); - m_Name2 = qFromLittleEndian(buffer_out + 4); - m_Locale = qFromLittleEndian(buffer_out + 8); - m_Platform = qFromLittleEndian(buffer_out + 10); - m_BlockIndex = qFromLittleEndian(buffer_out + 12); - - return true; -} - -bool MPQArchive::BlockEntry::readFrom(MPQArchive *parent, quint32 &Seed1, quint32 &Seed2) -{ - m_Parent = parent; - char buffer[16]; - if (parent->read(buffer, 16) != 16) - return false; - - unsigned char buffer_out[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 }; - - for (int i = 0; i < 4; i++) - { - quint32 p = qFromLittleEndian((unsigned char*)buffer + i * 4); - Seed2 += parent->m_CryptBuffer[0x400 + (Seed1 & 0xFF)]; - quint32 ch = p ^ (Seed1 + Seed2); - - Seed1 = ((~Seed1 << 0x15) + 0x11111111) | (Seed1 >> 0x0B); - Seed2 = ch + Seed2 + (Seed2 << 5) + 3; - qToLittleEndian(ch, buffer_out + i * 4); - } - - m_FilePos = qFromLittleEndian(buffer_out + 0); - m_CSize = qFromLittleEndian(buffer_out + 4); - m_FSize = qFromLittleEndian(buffer_out + 8); - m_Flags = qFromLittleEndian(buffer_out + 12); - return true; -} - -bool MPQArchive::BlockEntry::encrypted() -{ - return (m_Flags & 0x00010000); -} - -bool MPQArchive::BlockEntry::fixSeed() -{ - return (m_Flags & 0x00020000); -} - -bool MPQArchive::BlockEntry::compressed() -{ - return (m_Flags & 0x0000FF00); -} - -bool MPQArchive::BlockEntry::exists() -{ - return (m_Flags & 0x80000000); -} - -bool MPQArchive::BlockEntry::singleUnit() -{ - return (m_Flags & 0x01000000); -} - -bool MPQArchive::BlockEntry::hasExtra() -{ - return (m_Flags & 0x04000000); -} - -bool MPQArchive::BlockEntry::usesImplode() -{ - return (m_Flags & 0x00000100); -} - -bool MPQArchive::BlockEntry::valid() -{ - return !(m_Flags & ~( 0x00000100 | 0x00000200 | 0x00010000 | 0x00020000 | 0x01000000 | 0x02000000 | 0x04000000 | 0x80000000 )); -} - -QByteArray MPQArchive::BlockEntry::readAll() -{ - //m_Parent->seek(m_FilePos + m_Parent->m_HeaderOffset); - //return m_Parent->read(m_CSize); - if (compressed()) - return "SINGLEUNIT"; - - return "-"; -} - -bool MPQArchive::FileNode::readFrom(MPQArchive *parent) -{ - char buffer[16]; - if (parent->read(buffer, 16) != 16) - return false; - - qint32 m_References; - QByteArray m_Filename; - int m_Size; - return true; -} - - -MPQArchive::MPQArchive(const QString &file) - : QFile(file) -{ - m_Error = NO_ERROR; - m_HashTable = NULL; - - m_FileList = NULL; - m_BlockTable = NULL; - m_HashTable = NULL; - m_ListFile = NULL; - - quint32 dwSeed = 0x00100001; - - // Initialize the decryption buffer. - for (int index1 = 0; index1 < 0x100; index1++) - { - for (int index2 = index1, i = 0; i < 5; i++, index2 += 0x100) - { - quint32 temp1, temp2; - - dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; - temp1 = (dwSeed & 0xFFFF) << 0x10; - - dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; - temp2 = (dwSeed & 0xFFFF); - - m_CryptBuffer[index2] = (temp1 | temp2); - } - } -} - -quint32 MPQArchive::getHash(const char *data, int offset) -{ - quint32 Seed1 = 0x7FED7FED; - quint32 Seed2 = 0xEEEEEEEE; - - while(*data != 0) - { - quint32 ch = toupper(*data++); - - Seed1 = m_CryptBuffer[offset + ch] ^ (Seed1 + Seed2); - Seed2 = ch + Seed1 + Seed2 + (Seed2 << 5) + 3; - } - - return Seed1; -} - -bool MPQArchive::open() -{ - if (!QFile::open(ReadOnly)) - { - m_Error = CANNOT_OPEN_FILE; - return false; - } - - m_HeaderOffset = 0; - - for(;;) - { - if (!m_Header.readFrom(this)) - { - m_Error = FILE_CORRUPT; - return false; - } - - // Special check : Some MPQs are actually AVI files, only with - // changed extension. - if (m_Header.m_ID == "FFIR" || - m_Header.m_ID == " IVA" || - m_Header.m_ID == "TSIL") - { - m_Error = FILE_IS_AVI; - return false; - } -/* -/ note: Ignore the MPQ shunt completely if the caller wants to open the MPQ as V1.0 - - // If there is the MPQ shunt signature, process it - if (m_Header.m_ID == "MPQ\x1B") - { - - //ha->ShuntPos = MpqPos; - - if (!m_CurrentShunt.readFrom(this)) - return false; - - // Set the MPQ pos and repeat the search - if (!seek(m_CurrentShunt.m_HeaderPos)) - return false; - - continue; - } -*/ - // There must be MPQ header signature - if (m_Header.m_ID != "MPQ\x1A") - { - m_HeaderOffset += 0x200; - if (!seek(m_HeaderOffset)) - { - m_Error = FILE_CORRUPT; - return false; - } - - continue; - } - - // If valid signature has been found, break the loop - if(m_Header.m_FormatVersion == 0) - break; - - m_Error = INVALID_HEADER; - return false; - } - - m_BlockSize = 0x200 << m_Header.m_BlockSize; - DEBUG_Print("Block size is " + QString::number(m_Header.m_BlockSize) + " bzw. " + QString::number(m_BlockSize)); - - // read hash table - if (m_Header.m_HashTableSize > 0) - { - m_HashTable = new HashEntry[m_Header.m_HashTableSize]; - seek(m_Header.m_HashTablePos + m_HeaderOffset); - - // Decrypt hash table on the fly - const char *key = "(HASH TABLE)"; - quint32 Seed1 = getHash(key, 0x300);//0x7FED7FED; - quint32 Seed2 = 0xEEEEEEEE; - - // Prepare seeds - /*for (uint i = 0; i < strlen(key); i++) - { - Seed1 = m_CryptBuffer[0x300 + key[i]] ^ (Seed1 + Seed2); - Seed2 = key[i] + Seed1 + Seed2 + (Seed2 << 5) + 3; - } - - Seed1 = getHash(key, 0x300); - Seed2 = 0xEEEEEEEE; - */ - - for (uint i = 0; i < m_Header.m_HashTableSize; i++) - if (!m_HashTable[i].readFrom(this, Seed1, Seed2)) - { - m_Error = FILE_CORRUPT; - return false; - } - - DEBUG_Print("Read "+ QString::number(m_Header.m_HashTableSize) + " hash entries"); - } - - // read block table - if (m_Header.m_BlockTableSize > 0) - { - m_BlockTable = new BlockEntry[m_Header.m_BlockTableSize]; - seek(m_Header.m_BlockTablePos + m_HeaderOffset); - - // Decrypt hash table on the fly - const char *key = "(BLOCK TABLE)"; - quint32 Seed1 = getHash(key, 0x300);//0x7FED7FED; - quint32 Seed2 = 0xEEEEEEEE; - - // Prepare seeds - /*for (uint i = 0; i < strlen(key); i++) - { - Seed1 = m_CryptBuffer[0x300 + key[i]] ^ (Seed1 + Seed2); - Seed2 = key[i] + Seed1 + Seed2 + (Seed2 << 5) + 3; - } - - Seed2 = 0xEEEEEEEE; - */ - - for (uint i = 0; i < m_Header.m_BlockTableSize; i++) - if (!m_BlockTable[i].readFrom(this, Seed1, Seed2)) - { - m_Error = FILE_CORRUPT; - return false; - } - - DEBUG_Print("Read "+ QString::number(m_Header.m_BlockTableSize) + " block entries"); - } - - // verify the block table - BlockEntry *pBlockEnd = m_BlockTable + m_Header.m_BlockTableSize + 1; - BlockEntry *pBlock = m_BlockTable; - - // we will check if all sizes in the block table is correct. - for(; pBlock < pBlockEnd; pBlock++) - if(pBlock->m_Flags & 0x80000000 /*MPQ_FILE_EXISTS*/ && pBlock->m_FilePos > size()) - { - m_Error = BLOCK_TABLE_CORRUPT; - return false; - } - - // Add the internal listfile - const char* listfilename = "(listfile)"; - HashEntry *pHash = GetHashEntry(listfilename); - - if (pHash == NULL || pHash->m_BlockIndex > m_Header.m_BlockTableSize) - { - m_Error = NO_FILE_LIST; - return false; - } - - // Get block and test if the file was not already deleted. - pBlock = m_BlockTable + pHash->m_BlockIndex; - - if (!pBlock->exists() || !pBlock->valid()) - { - m_Error = NO_FILE_LIST; - return false; - } - - DEBUG_Print("file list @block " + QString::number(pHash->m_BlockIndex)); - - m_ListFile = new MPQFile(this, listfilename, pBlock, pHash); - - // If the caller didn't specified otherwise, - // load the "(attributes)" file - // Ignore the result here. Attrobutes are not necessary, - // if they are not there, we will just ignore them -// SAttrFileLoad(ha); - - return true; -} - -MPQFile* MPQArchive::getFile(const QByteArray &filename) -{ - HashEntry *pHash = GetHashEntry(filename.data()); - - if (pHash == NULL || pHash->m_BlockIndex > m_Header.m_BlockTableSize) - { - m_Error = NO_FILE_LIST; - return false; - } - - // Get block and test if the file was not already deleted. - BlockEntry *pBlock = m_BlockTable + pHash->m_BlockIndex; - - if (!pBlock->exists() || !pBlock->valid()) - { - m_Error = NO_FILE_LIST; - return false; - } - - DEBUG_Print("file @block " + QString::number(pHash->m_BlockIndex)); - - return new MPQFile(this, filename.data(), pBlock, pHash); -} - -MPQArchive::~MPQArchive() -{ - delete[] m_CryptBuffer; - delete[] m_BlockTable; - delete[] m_HashTable; - delete[] m_FileList; - delete m_ListFile; -} - -MPQArchive::HashEntry *MPQArchive::GetHashEntry(const char * file, quint32 locale) -{ - HashEntry *pHashEnd = m_HashTable + m_Header.m_HashTableSize; - HashEntry *pHash0; // File hash entry (start) - HashEntry *pHash; // File hash entry (current) - HashEntry *pHashNeutral = NULL; - - // Decrypt name and block index - quint32 index = getHash(file) & (m_Header.m_HashTableSize - 1); - quint32 name1 = getHash(file, 0x100); - quint32 name2 = getHash(file, 0x200); - cout << file << " " << index << " " << m_Header.m_HashTableSize << " " << name2 << endl; - - pHash = pHash0 = m_HashTable + index; - - // Look for hash index - while(pHash->m_BlockIndex != 0xFFFFFFFF /*HASH_ENTRY_FREE*/) - { - if(pHash->m_Name1 == name1 && - pHash->m_Name2 == name2 && - pHash->m_BlockIndex != 0xFFFFFFFE /*HASH_ENTRY_DELETED*/) - { - if (locale == 0xFFFFFFFF) - return pHash; - - else - { - if (pHash->m_Locale == 0) - pHashNeutral = pHash; - - if (pHash->m_Locale == locale) - return pHash; - } - } - - // Move to the next hash entry - if(++pHash >= pHashEnd) - pHash = m_HashTable; - if(pHash == pHash0) - break; - } - - // File was not found - return pHashNeutral; -} - diff --git a/ghost/mpqarchive.h b/ghost/mpqarchive.h deleted file mode 100644 index ae57263..0000000 --- a/ghost/mpqarchive.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef MPQARCHIVE_H -#define MPQARCHIVE_H - -#include -class MPQFile; - -class MPQArchive : public QFile -{ - Q_OBJECT - -public: - MPQArchive(const QString & filename); - virtual ~MPQArchive(); - - bool open(); - MPQFile* getFile(const QByteArray &filename); - - enum Error - { - NO_ERROR, - FILE_CORRUPT, - INVALID_HEADER, - FILE_IS_AVI, - CANNOT_OPEN_FILE, - BLOCK_TABLE_CORRUPT, - NO_FILE_LIST, - } m_Error; - - class Header - { - public: - bool readFrom(MPQArchive* parent); - - // The ID_MPQ ('MPQ\x1A') signature - QByteArray m_ID; - - // Size of the archive header - quint32 m_HeaderSize; - - // Size of MPQ archive - // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive - // is calculated as the size from the beginning of the archive to the end of the hash table, - // block table, or extended block table (whichever is largest). - quint32 m_ArchiveSize; - - // 0 = Original format - // 1 = Extended format (The Burning Crusade and newer) - quint16 m_FormatVersion; - - // Power of two exponent specifying the number of 512-byte disk sectors in each logical sector - // in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. - // Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors). - quint16 m_BlockSize; - - // Offset to the beginning of the hash table, relative to the beginning of the archive. - quint32 m_HashTablePos; - - // Offset to the beginning of the block table, relative to the beginning of the archive. - quint32 m_BlockTablePos; - - // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for - // the original MoPaQ format, or less than 2^20 for the Burning Crusade format. - quint32 m_HashTableSize; - - // Number of entries in the block table - quint32 m_BlockTableSize; - }; - - class Shunt - { - public: - bool readFrom(MPQArchive* parent); - - // The ID_MPQ_SHUNT ('MPQ\x1B') signature - QByteArray m_ID; - - // Position of the MPQ header, relative to the begin of the shunt - qint32 m_HeaderPos; - }; - - class FileNode - { - public: - bool readFrom(MPQArchive* parent); - - qint32 m_References; - QByteArray m_Filename; - int m_Size; - }; - - class HashEntry - { - public: - bool readFrom(MPQArchive* parent, quint32 &Seed1, quint32& Seed2); - - // The hash of the file path, using method A. - quint32 m_Name1; - - // The hash of the file path, using method B. - quint32 m_Name2; - - // The language of the file. This is a Windows LANGID data type, and uses the same values. - // 0 indicates the default language (American English), or that the file is language-neutral. - quint16 m_Locale; - - // The platform the file is used for. 0 indicates the default platform. - // No other values have been observed. - quint16 m_Platform; - - // If the hash table entry is valid, this is the index into the block table of the file. - // Otherwise, one of the following two values: - // - FFFFFFFFh: Hash table entry is empty, and has always been empty. - // Terminates searches for a given file. - // - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file). - // Does not terminate searches for a given file. - quint32 m_BlockIndex; - }; - - class BlockEntry - { - public: - bool readFrom(MPQArchive* parent, quint32 &Seed1, quint32& Seed2); - - bool exists(); - bool valid(); - bool compressed(); - bool encrypted(); - bool fixSeed(); - bool singleUnit(); - bool hasExtra(); - bool usesImplode(); - - MPQArchive *m_Parent; - QByteArray readAll(); - - // Offset of the beginning of the block, relative to the beginning of the archive. - quint32 m_FilePos; - - // Compressed file size - quint32 m_CSize; - - // Only valid if the block is a file; otherwise meaningless, and should be 0. - // If the file is compressed, this is the size of the uncompressed file data. - quint32 m_FSize; - - // Flags for the file. See MPQ_FILE_XXXX constants - quint32 m_Flags; - }; - - int m_HeaderOffset; // offset where the header was found - int m_BlockSize; // Size of file block - quint32 getHash(const char *data, int offset = 0x000); - MPQFile *m_ListFile; - quint32 m_CryptBuffer[0x500]; - -private: - HashEntry *GetHashEntry(const char * file, quint32 locale = 0xFFFFFFFF); - - int m_ShuntPos; // MPQShunt offset (only valid if a shunt is present) - int m_HashTablePos; // Hash table offset (relative to the begin of the file) - int m_BlockTablePos; // Block table offset (relative to the begin of the file) - int m_ExtBlockTablePos; // Ext. block table offset (relative to the begin of the file) - int m_MpqSize; // Size of MPQ archive - - Header m_Header; // MPQ header - HashEntry *m_HashTable; - BlockEntry *m_BlockTable; - FileNode *m_FileList; - -}; - -#endif // MPGARCHIVE_H diff --git a/ghost/mpqfile.cpp b/ghost/mpqfile.cpp deleted file mode 100644 index 3c33bb2..0000000 --- a/ghost/mpqfile.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include "mpqfile.h" -#include "includes.h" -#include - -MPQFile::MPQFile(MPQArchive *archive, const QString &filename, MPQArchive::BlockEntry *block, MPQArchive::HashEntry *hash) -{ - m_Parent = archive; - m_BlockEntry = block; - m_HashEntry = hash; - m_Seed1 = 0; - m_Name = filename; - m_Size = block->m_FSize; - DEBUG_Print("Block size: " + QString::number(block->m_CSize)); - DEBUG_Print("File size: " + QString::number(block->m_FSize)); - m_Blocks = (block->m_FSize + archive->m_BlockSize - 1) / archive->m_BlockSize; - DEBUG_Print("Number of blocks: " + QString::number(m_Blocks)); - - m_PositionFromBegin = block->m_FilePos + archive->m_HeaderOffset; - m_PositionFromHeader = block->m_FilePos; - - if (block->compressed()) - { - } - - if (block->encrypted()) - { - QString name = filename.section('\\', -1); - - m_Seed1 = archive->getHash(name.toUtf8().data(), 0x300); - if (block->fixSeed()) - m_Seed1 = (m_Seed1 + block->m_FilePos) ^ block->m_FSize; - } -/* - // Resolve pointers to file's attributes - if(nError == ERROR_SUCCESS && ha->pAttributes != NULL) - { - if(ha->pAttributes->pCrc32 != NULL) - hf->pCrc32 = ha->pAttributes->pCrc32 + dwBlockIndex; - if(ha->pAttributes->pFileTime != NULL) - hf->pFileTime = ha->pAttributes->pFileTime + dwBlockIndex; - if(ha->pAttributes->pMd5 != NULL) - hf->pMd5 = ha->pAttributes->pMd5 + dwBlockIndex; - }*/ -} - -bool MPQFile::read() -{ - MPQArchive::BlockEntry *block = m_BlockEntry; - - if (block->compressed()) - { - m_BlockPosTableSize = m_Blocks + 1 + (block->hasExtra() ? 1 : 0); - m_BlockPosTable = new qint32[m_BlockPosTableSize]; - - m_Parent->seek(m_PositionFromBegin); - - char buffer[4]; - qint32 *pos = m_BlockPosTable, *posEnd = pos + m_BlockPosTableSize; - for (; pos != posEnd; pos++) - { - if (m_Parent->read(buffer, 4) != 4) - { - m_Error = POS_TABLE_CORRUPT; - return false; - } - - *pos = qFromLittleEndian((unsigned char*)buffer); - } - - // encryption check - qint32 bytes = m_BlockPosTableSize * 4; - if (m_BlockPosTable[0] != bytes) - m_BlockEntry->m_Flags |= 0x00010000; - - quint32 saveSeed1 = 0; - if (m_BlockEntry->encrypted()) - { - quint32 temp = (m_BlockPosTable[0] ^ bytes) - 0xEEEEEEEE; - - int i; - for(i = 0; i < 0x100; i++) // Try all 255 possibilities - { - quint32 seed1; - quint32 seed2 = 0xEEEEEEEE; - quint32 ch; - - // Try the first DWORD (We exactly know the value) - seed1 = temp - m_Parent->m_CryptBuffer[0x400 + i]; - seed2 += m_Parent->m_CryptBuffer[0x400 + (seed1 & 0xFF)]; - ch = m_BlockPosTable[0] ^ (seed1 + seed2); - - if(ch != (quint32)bytes) - continue; - - // Add 1 because we are decrypting block positions - saveSeed1 = seed1 + 1; - - // If OK, continue and test the second value. We don't know exactly the value, - // but we know that the second one has lower 16 bits set to zero - // (no compressed block is larger than 0xFFFF bytes) - seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); - seed2 = ch + seed2 + (seed2 << 5) + 3; - - seed2 += m_Parent->m_CryptBuffer[0x400 + (seed1 & 0xFF)]; - ch = m_BlockPosTable[1] ^ (seed1 + seed2); - - if((ch & 0xFFFF0000) == 0) - break; - } - - if (i == 0x100) - { - m_Error = SEED_NOT_FOUND; - return false; - } - - decryptBlock((quint32*)m_BlockPosTable, m_BlockPosTableSize, saveSeed1 - 1); - } - - cout << m_BlockPosTableSize << ", " << m_BlockEntry->m_FilePos << ", " << m_BlockPosTable[0] << ", " << m_BlockPosTable[1] << endl; - - if (m_BlockPosTable[0] != bytes) - { - m_Error = DECRYPTION_FAILED; - return false; - } - - DEBUG_Print(QString::number(m_BlockPosTableSize) + " blockpos loaded"); - - for (int i = 0; i < m_Blocks - 1; i++) - readBlock(m_BlockPosTable[i + 1], m_BlockPosTable[i + 2], saveSeed1 + i); - - QFile out("test.out"); - if (out.open(QFile::WriteOnly | QFile::Truncate)) - { - out.write(m_Content); - out.close(); - } - - return true; - } - - DEBUG_Print("file not compressed"); - - - - return true; -} - -bool MPQFile::readBlock(quint32 from, quint32 to, quint32 seed) -{ - int len = to - from; - - if (len > m_Parent->m_BlockSize) - len = m_Parent->m_BlockSize; - - m_Parent->seek(m_PositionFromBegin + from); - QByteArray part; - - if (m_BlockEntry->encrypted()) - { - quint32 num = len >> 2; - - char buffer[4]; - quint32 data[num]; - - for (uint i = 0; i < num; i++) - { - if (m_Parent->read((char*)buffer, 4) != 4) - { - m_Error = FILE_CORRUPTED; - return false; - } - - data[i] = qFromLittleEndian((unsigned char*)buffer); - } - - decryptBlock(data, num, seed); - - for (uint i = 0; i < num; i++) - { - //qToLittleEndian(data[i], (unsigned char*)buffer); - //part.append(buffer, 4); - part.append((char*)&data[i], 4); - } - } - - else - { - QByteArray ba = m_Parent->read(len); - if (ba.size() != len) - { - m_Error = FILE_CORRUPTED; - return false; - } - - part.append(ba); - } - - if (m_BlockEntry->usesImplode()) - { - DEBUG_Print("Uses PKWARE"); - } - - m_Content.append(part); - - return true; -} - -void MPQFile::decryptBlock(quint32 *data, quint32 length, quint32 seed) -{ - quint32 seed2 = 0xEEEEEEEE; - quint32 ch; - - while(length-- > 0) - { - seed2 += m_Parent->m_CryptBuffer[0x400 + (seed & 0xFF)]; - ch = *data ^ (seed + seed2); - - seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B); - seed2 = ch + seed2 + (seed2 << 5) + 3; - *data++ = ch; - } -} - - - - - - - - - - - - - - - diff --git a/ghost/mpqfile.h b/ghost/mpqfile.h deleted file mode 100644 index e55a860..0000000 --- a/ghost/mpqfile.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef MPQFILE_H -#define MPQFILE_H - -#include "mpqarchive.h" - -class MPQFile -{ -public: - MPQFile(MPQArchive* archive, const QString &filename, MPQArchive::BlockEntry *block, MPQArchive::HashEntry *hash); - - enum Error - { - NO_ERROR, - POS_TABLE_CORRUPT, - SEED_NOT_FOUND, - DECRYPTION_FAILED, - FILE_CORRUPTED, - } m_Error; - - bool read(); - bool readBlock(quint32 from, quint32 to, quint32 seed); - void decryptBlock(quint32 *data, quint32 length, quint32 seed); - - MPQArchive* m_Parent; - MPQArchive::BlockEntry *m_BlockEntry; - MPQArchive::HashEntry *m_HashEntry; - - quint32 m_Seed1; - quint32 m_PositionFromBegin; - quint32 m_PositionFromHeader; - quint32 m_Size; - - int m_BlockPosTableSize; - qint32 *m_BlockPosTable; - - int m_Blocks; - - QByteArray m_Content; - - QString m_Name; - -/* DWORD * pdwBlockPos; // Position of each file block (only for compressed files) - DWORD nBlocks; // Number of blocks in the file (incl. the last incomplete one) - BOOL bBlockPosLoaded; // TRUE if block positions loaded - BYTE * pbFileBuffer; // Decompressed file (for single unit files, size is the uncompressed file size) - - TMPQCRC32 * pCrc32; // Pointer to CRC32 (NULL if none) - TMPQFileTime * pFileTime; // Pointer to file's FILETIME (NULL if none) - TMPQMD5 * pMd5; // Pointer to file's MD5 (NULL if none) - - DWORD dwHashIndex; // Index to Hash table - DWORD dwBlockIndex; // Index to Block table - char szFileName[1]; // File name (variable length) */ -}; - -#endif // MPQFILE_H From 5ec01a81d0341a873fe86abb09e7ead56c3c3499 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sat, 8 May 2010 15:06:36 +0000 Subject: [PATCH 56/69] --- ghost/mpqarchive.cpp | 479 +++++++++++++++++++++++++++++++++++++++++++ ghost/mpqfile.cpp | 239 +++++++++++++++++++++ 2 files changed, 718 insertions(+) create mode 100644 ghost/mpqarchive.cpp create mode 100644 ghost/mpqfile.cpp diff --git a/ghost/mpqarchive.cpp b/ghost/mpqarchive.cpp new file mode 100644 index 0000000..bc6880e --- /dev/null +++ b/ghost/mpqarchive.cpp @@ -0,0 +1,479 @@ +// rewritten using StormLib: +/*****************************************************************************/ +/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */ +/* */ +/* Author : Ladislav Zezula */ +/* E-mail : ladik@zezula.net */ +/* WWW : www.zezula.net */ +/*---------------------------------------------------------------------------*/ +/* Archive functions of Storm.dll */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */ +/* 19.11.03 1.01 Dan Big endian handling */ +/*****************************************************************************/ + +#include +#include "mpqarchive.h" +#include "mpqfile.h" +#include "includes.h" + +QByteArray m_ID; + + +bool MPQArchive::Header::readFrom(MPQArchive *parent) +{ + char buffer[32]; + if (parent->read(buffer, 32) != 32) + return false; +DEBUG_Print(QByteArray(buffer, 32).toHex()); + //<- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> <- 4b -> + //4d50511a 20000000 98a46c00 00000f00 c8256c00 c8656c00 00040000 ed030000 + + m_ID = QByteArray(buffer, 4); + m_HeaderSize = qFromLittleEndian((unsigned char*)buffer + 4); + m_ArchiveSize = qFromLittleEndian((unsigned char*)buffer + 8); + m_FormatVersion = qFromLittleEndian((unsigned char*)buffer + 12); + m_BlockSize = qFromLittleEndian((unsigned char*)buffer + 14); + m_HashTablePos = qFromLittleEndian((unsigned char*)buffer + 16); + m_BlockTablePos = qFromLittleEndian((unsigned char*)buffer + 20); + m_HashTableSize = qFromLittleEndian((unsigned char*)buffer + 24); + m_BlockTableSize = qFromLittleEndian((unsigned char*)buffer + 28); + + return true; +} + +bool MPQArchive::Shunt::readFrom(MPQArchive *parent) +{ + char buffer[12]; + if (parent->read(buffer, 12) != 12) + return false; + + m_ID = QByteArray(buffer, 4); + m_HeaderPos = qFromLittleEndian((unsigned char*)buffer + 8); + + return true; +} + +bool MPQArchive::HashEntry::readFrom(MPQArchive *parent, quint32 &Seed1, quint32 &Seed2) +{ + char buffer[16]; + if (parent->read(buffer, 16) != 16) + return false; + + unsigned char buffer_out[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + for (int i = 0; i < 4; i++) + { + quint32 p = qFromLittleEndian((unsigned char*)buffer + i * 4); + Seed2 += parent->m_CryptBuffer[0x400 + (Seed1 & 0xFF)]; + quint32 ch = p ^ (Seed1 + Seed2); + + Seed1 = ((~Seed1 << 0x15) + 0x11111111) | (Seed1 >> 0x0B); + Seed2 = ch + Seed2 + (Seed2 << 5) + 3; + qToLittleEndian(ch, buffer_out + i * 4); + } + + m_Name1 = qFromLittleEndian(buffer_out + 0); + m_Name2 = qFromLittleEndian(buffer_out + 4); + m_Locale = qFromLittleEndian(buffer_out + 8); + m_Platform = qFromLittleEndian(buffer_out + 10); + m_BlockIndex = qFromLittleEndian(buffer_out + 12); + + return true; +} + +bool MPQArchive::BlockEntry::readFrom(MPQArchive *parent, quint32 &Seed1, quint32 &Seed2) +{ + m_Parent = parent; + char buffer[16]; + if (parent->read(buffer, 16) != 16) + return false; + + unsigned char buffer_out[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + for (int i = 0; i < 4; i++) + { + quint32 p = qFromLittleEndian((unsigned char*)buffer + i * 4); + Seed2 += parent->m_CryptBuffer[0x400 + (Seed1 & 0xFF)]; + quint32 ch = p ^ (Seed1 + Seed2); + + Seed1 = ((~Seed1 << 0x15) + 0x11111111) | (Seed1 >> 0x0B); + Seed2 = ch + Seed2 + (Seed2 << 5) + 3; + qToLittleEndian(ch, buffer_out + i * 4); + } + + m_FilePos = qFromLittleEndian(buffer_out + 0); + m_CSize = qFromLittleEndian(buffer_out + 4); + m_FSize = qFromLittleEndian(buffer_out + 8); + m_Flags = qFromLittleEndian(buffer_out + 12); + return true; +} + +bool MPQArchive::BlockEntry::encrypted() +{ + return (m_Flags & 0x00010000); +} + +bool MPQArchive::BlockEntry::fixSeed() +{ + return (m_Flags & 0x00020000); +} + +bool MPQArchive::BlockEntry::compressed() +{ + return (m_Flags & 0x0000FF00); +} + +bool MPQArchive::BlockEntry::exists() +{ + return (m_Flags & 0x80000000); +} + +bool MPQArchive::BlockEntry::singleUnit() +{ + return (m_Flags & 0x01000000); +} + +bool MPQArchive::BlockEntry::hasExtra() +{ + return (m_Flags & 0x04000000); +} + +bool MPQArchive::BlockEntry::usesImplode() +{ + return (m_Flags & 0x00000100); +} + +bool MPQArchive::BlockEntry::valid() +{ + return !(m_Flags & ~( 0x00000100 | 0x00000200 | 0x00010000 | 0x00020000 | 0x01000000 | 0x02000000 | 0x04000000 | 0x80000000 )); +} + +QByteArray MPQArchive::BlockEntry::readAll() +{ + //m_Parent->seek(m_FilePos + m_Parent->m_HeaderOffset); + //return m_Parent->read(m_CSize); + if (compressed()) + return "SINGLEUNIT"; + + return "-"; +} + +bool MPQArchive::FileNode::readFrom(MPQArchive *parent) +{ + char buffer[16]; + if (parent->read(buffer, 16) != 16) + return false; + + qint32 m_References; + QByteArray m_Filename; + int m_Size; + return true; +} + + +MPQArchive::MPQArchive(const QString &file) + : QFile(file) +{ + m_Error = NO_ERROR; + m_HashTable = NULL; + + m_FileList = NULL; + m_BlockTable = NULL; + m_HashTable = NULL; + m_ListFile = NULL; + + quint32 dwSeed = 0x00100001; + + // Initialize the decryption buffer. + for (int index1 = 0; index1 < 0x100; index1++) + { + for (int index2 = index1, i = 0; i < 5; i++, index2 += 0x100) + { + quint32 temp1, temp2; + + dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; + temp1 = (dwSeed & 0xFFFF) << 0x10; + + dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB; + temp2 = (dwSeed & 0xFFFF); + + m_CryptBuffer[index2] = (temp1 | temp2); + } + } +} + +quint32 MPQArchive::getHash(const char *data, int offset) +{ + quint32 Seed1 = 0x7FED7FED; + quint32 Seed2 = 0xEEEEEEEE; + + while(*data != 0) + { + quint32 ch = toupper(*data++); + + Seed1 = m_CryptBuffer[offset + ch] ^ (Seed1 + Seed2); + Seed2 = ch + Seed1 + Seed2 + (Seed2 << 5) + 3; + } + + return Seed1; +} + +bool MPQArchive::open() +{ + if (!QFile::open(ReadOnly)) + { + m_Error = CANNOT_OPEN_FILE; + return false; + } + + m_HeaderOffset = 0; + + for(;;) + { + if (!m_Header.readFrom(this)) + { + m_Error = FILE_CORRUPT; + return false; + } + + // Special check : Some MPQs are actually AVI files, only with + // changed extension. + if (m_Header.m_ID == "FFIR" || + m_Header.m_ID == " IVA" || + m_Header.m_ID == "TSIL") + { + m_Error = FILE_IS_AVI; + return false; + } +/* +/ note: Ignore the MPQ shunt completely if the caller wants to open the MPQ as V1.0 + + // If there is the MPQ shunt signature, process it + if (m_Header.m_ID == "MPQ\x1B") + { + + //ha->ShuntPos = MpqPos; + + if (!m_CurrentShunt.readFrom(this)) + return false; + + // Set the MPQ pos and repeat the search + if (!seek(m_CurrentShunt.m_HeaderPos)) + return false; + + continue; + } +*/ + // There must be MPQ header signature + if (m_Header.m_ID != "MPQ\x1A") + { + m_HeaderOffset += 0x200; + if (!seek(m_HeaderOffset)) + { + m_Error = FILE_CORRUPT; + return false; + } + + continue; + } + + // If valid signature has been found, break the loop + if(m_Header.m_FormatVersion == 0) + break; + + m_Error = INVALID_HEADER; + return false; + } + + m_BlockSize = 0x200 << m_Header.m_BlockSize; + DEBUG_Print("Block size is " + QString::number(m_Header.m_BlockSize) + " bzw. " + QString::number(m_BlockSize)); + + // read hash table + if (m_Header.m_HashTableSize > 0) + { + m_HashTable = new HashEntry[m_Header.m_HashTableSize]; + seek(m_Header.m_HashTablePos + m_HeaderOffset); + + // Decrypt hash table on the fly + const char *key = "(HASH TABLE)"; + quint32 Seed1 = getHash(key, 0x300);//0x7FED7FED; + quint32 Seed2 = 0xEEEEEEEE; + + // Prepare seeds + /*for (uint i = 0; i < strlen(key); i++) + { + Seed1 = m_CryptBuffer[0x300 + key[i]] ^ (Seed1 + Seed2); + Seed2 = key[i] + Seed1 + Seed2 + (Seed2 << 5) + 3; + } + + Seed1 = getHash(key, 0x300); + Seed2 = 0xEEEEEEEE; + */ + + for (uint i = 0; i < m_Header.m_HashTableSize; i++) + if (!m_HashTable[i].readFrom(this, Seed1, Seed2)) + { + m_Error = FILE_CORRUPT; + return false; + } + + DEBUG_Print("Read "+ QString::number(m_Header.m_HashTableSize) + " hash entries"); + } + + // read block table + if (m_Header.m_BlockTableSize > 0) + { + m_BlockTable = new BlockEntry[m_Header.m_BlockTableSize]; + seek(m_Header.m_BlockTablePos + m_HeaderOffset); + + // Decrypt hash table on the fly + const char *key = "(BLOCK TABLE)"; + quint32 Seed1 = getHash(key, 0x300);//0x7FED7FED; + quint32 Seed2 = 0xEEEEEEEE; + + // Prepare seeds + /*for (uint i = 0; i < strlen(key); i++) + { + Seed1 = m_CryptBuffer[0x300 + key[i]] ^ (Seed1 + Seed2); + Seed2 = key[i] + Seed1 + Seed2 + (Seed2 << 5) + 3; + } + + Seed2 = 0xEEEEEEEE; + */ + + for (uint i = 0; i < m_Header.m_BlockTableSize; i++) + if (!m_BlockTable[i].readFrom(this, Seed1, Seed2)) + { + m_Error = FILE_CORRUPT; + return false; + } + + DEBUG_Print("Read "+ QString::number(m_Header.m_BlockTableSize) + " block entries"); + } + + // verify the block table + BlockEntry *pBlockEnd = m_BlockTable + m_Header.m_BlockTableSize + 1; + BlockEntry *pBlock = m_BlockTable; + + // we will check if all sizes in the block table is correct. + for(; pBlock < pBlockEnd; pBlock++) + if(pBlock->m_Flags & 0x80000000 /*MPQ_FILE_EXISTS*/ && pBlock->m_FilePos > size()) + { + m_Error = BLOCK_TABLE_CORRUPT; + return false; + } + + // Add the internal listfile + const char* listfilename = "(listfile)"; + HashEntry *pHash = GetHashEntry(listfilename); + + if (pHash == NULL || pHash->m_BlockIndex > m_Header.m_BlockTableSize) + { + m_Error = NO_FILE_LIST; + return false; + } + + // Get block and test if the file was not already deleted. + pBlock = m_BlockTable + pHash->m_BlockIndex; + + if (!pBlock->exists() || !pBlock->valid()) + { + m_Error = NO_FILE_LIST; + return false; + } + + DEBUG_Print("file list @block " + QString::number(pHash->m_BlockIndex)); + + m_ListFile = new MPQFile(this, listfilename, pBlock, pHash); + + // If the caller didn't specified otherwise, + // load the "(attributes)" file + // Ignore the result here. Attrobutes are not necessary, + // if they are not there, we will just ignore them +// SAttrFileLoad(ha); + + return true; +} + +MPQFile* MPQArchive::getFile(const QByteArray &filename) +{ + HashEntry *pHash = GetHashEntry(filename.data()); + + if (pHash == NULL || pHash->m_BlockIndex > m_Header.m_BlockTableSize) + { + m_Error = NO_FILE_LIST; + return false; + } + + // Get block and test if the file was not already deleted. + BlockEntry *pBlock = m_BlockTable + pHash->m_BlockIndex; + + if (!pBlock->exists() || !pBlock->valid()) + { + m_Error = NO_FILE_LIST; + return false; + } + + DEBUG_Print("file @block " + QString::number(pHash->m_BlockIndex)); + + return new MPQFile(this, filename.data(), pBlock, pHash); +} + +MPQArchive::~MPQArchive() +{ + delete[] m_CryptBuffer; + delete[] m_BlockTable; + delete[] m_HashTable; + delete[] m_FileList; + delete m_ListFile; +} + +MPQArchive::HashEntry *MPQArchive::GetHashEntry(const char * file, quint32 locale) +{ + HashEntry *pHashEnd = m_HashTable + m_Header.m_HashTableSize; + HashEntry *pHash0; // File hash entry (start) + HashEntry *pHash; // File hash entry (current) + HashEntry *pHashNeutral = NULL; + + // Decrypt name and block index + quint32 index = getHash(file) & (m_Header.m_HashTableSize - 1); + quint32 name1 = getHash(file, 0x100); + quint32 name2 = getHash(file, 0x200); + cout << file << " " << index << " " << m_Header.m_HashTableSize << " " << name2 << endl; + + pHash = pHash0 = m_HashTable + index; + + // Look for hash index + while(pHash->m_BlockIndex != 0xFFFFFFFF /*HASH_ENTRY_FREE*/) + { + if(pHash->m_Name1 == name1 && + pHash->m_Name2 == name2 && + pHash->m_BlockIndex != 0xFFFFFFFE /*HASH_ENTRY_DELETED*/) + { + if (locale == 0xFFFFFFFF) + return pHash; + + else + { + if (pHash->m_Locale == 0) + pHashNeutral = pHash; + + if (pHash->m_Locale == locale) + return pHash; + } + } + + // Move to the next hash entry + if(++pHash >= pHashEnd) + pHash = m_HashTable; + if(pHash == pHash0) + break; + } + + // File was not found + return pHashNeutral; +} + diff --git a/ghost/mpqfile.cpp b/ghost/mpqfile.cpp new file mode 100644 index 0000000..3c33bb2 --- /dev/null +++ b/ghost/mpqfile.cpp @@ -0,0 +1,239 @@ +#include "mpqfile.h" +#include "includes.h" +#include + +MPQFile::MPQFile(MPQArchive *archive, const QString &filename, MPQArchive::BlockEntry *block, MPQArchive::HashEntry *hash) +{ + m_Parent = archive; + m_BlockEntry = block; + m_HashEntry = hash; + m_Seed1 = 0; + m_Name = filename; + m_Size = block->m_FSize; + DEBUG_Print("Block size: " + QString::number(block->m_CSize)); + DEBUG_Print("File size: " + QString::number(block->m_FSize)); + m_Blocks = (block->m_FSize + archive->m_BlockSize - 1) / archive->m_BlockSize; + DEBUG_Print("Number of blocks: " + QString::number(m_Blocks)); + + m_PositionFromBegin = block->m_FilePos + archive->m_HeaderOffset; + m_PositionFromHeader = block->m_FilePos; + + if (block->compressed()) + { + } + + if (block->encrypted()) + { + QString name = filename.section('\\', -1); + + m_Seed1 = archive->getHash(name.toUtf8().data(), 0x300); + if (block->fixSeed()) + m_Seed1 = (m_Seed1 + block->m_FilePos) ^ block->m_FSize; + } +/* + // Resolve pointers to file's attributes + if(nError == ERROR_SUCCESS && ha->pAttributes != NULL) + { + if(ha->pAttributes->pCrc32 != NULL) + hf->pCrc32 = ha->pAttributes->pCrc32 + dwBlockIndex; + if(ha->pAttributes->pFileTime != NULL) + hf->pFileTime = ha->pAttributes->pFileTime + dwBlockIndex; + if(ha->pAttributes->pMd5 != NULL) + hf->pMd5 = ha->pAttributes->pMd5 + dwBlockIndex; + }*/ +} + +bool MPQFile::read() +{ + MPQArchive::BlockEntry *block = m_BlockEntry; + + if (block->compressed()) + { + m_BlockPosTableSize = m_Blocks + 1 + (block->hasExtra() ? 1 : 0); + m_BlockPosTable = new qint32[m_BlockPosTableSize]; + + m_Parent->seek(m_PositionFromBegin); + + char buffer[4]; + qint32 *pos = m_BlockPosTable, *posEnd = pos + m_BlockPosTableSize; + for (; pos != posEnd; pos++) + { + if (m_Parent->read(buffer, 4) != 4) + { + m_Error = POS_TABLE_CORRUPT; + return false; + } + + *pos = qFromLittleEndian((unsigned char*)buffer); + } + + // encryption check + qint32 bytes = m_BlockPosTableSize * 4; + if (m_BlockPosTable[0] != bytes) + m_BlockEntry->m_Flags |= 0x00010000; + + quint32 saveSeed1 = 0; + if (m_BlockEntry->encrypted()) + { + quint32 temp = (m_BlockPosTable[0] ^ bytes) - 0xEEEEEEEE; + + int i; + for(i = 0; i < 0x100; i++) // Try all 255 possibilities + { + quint32 seed1; + quint32 seed2 = 0xEEEEEEEE; + quint32 ch; + + // Try the first DWORD (We exactly know the value) + seed1 = temp - m_Parent->m_CryptBuffer[0x400 + i]; + seed2 += m_Parent->m_CryptBuffer[0x400 + (seed1 & 0xFF)]; + ch = m_BlockPosTable[0] ^ (seed1 + seed2); + + if(ch != (quint32)bytes) + continue; + + // Add 1 because we are decrypting block positions + saveSeed1 = seed1 + 1; + + // If OK, continue and test the second value. We don't know exactly the value, + // but we know that the second one has lower 16 bits set to zero + // (no compressed block is larger than 0xFFFF bytes) + seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + + seed2 += m_Parent->m_CryptBuffer[0x400 + (seed1 & 0xFF)]; + ch = m_BlockPosTable[1] ^ (seed1 + seed2); + + if((ch & 0xFFFF0000) == 0) + break; + } + + if (i == 0x100) + { + m_Error = SEED_NOT_FOUND; + return false; + } + + decryptBlock((quint32*)m_BlockPosTable, m_BlockPosTableSize, saveSeed1 - 1); + } + + cout << m_BlockPosTableSize << ", " << m_BlockEntry->m_FilePos << ", " << m_BlockPosTable[0] << ", " << m_BlockPosTable[1] << endl; + + if (m_BlockPosTable[0] != bytes) + { + m_Error = DECRYPTION_FAILED; + return false; + } + + DEBUG_Print(QString::number(m_BlockPosTableSize) + " blockpos loaded"); + + for (int i = 0; i < m_Blocks - 1; i++) + readBlock(m_BlockPosTable[i + 1], m_BlockPosTable[i + 2], saveSeed1 + i); + + QFile out("test.out"); + if (out.open(QFile::WriteOnly | QFile::Truncate)) + { + out.write(m_Content); + out.close(); + } + + return true; + } + + DEBUG_Print("file not compressed"); + + + + return true; +} + +bool MPQFile::readBlock(quint32 from, quint32 to, quint32 seed) +{ + int len = to - from; + + if (len > m_Parent->m_BlockSize) + len = m_Parent->m_BlockSize; + + m_Parent->seek(m_PositionFromBegin + from); + QByteArray part; + + if (m_BlockEntry->encrypted()) + { + quint32 num = len >> 2; + + char buffer[4]; + quint32 data[num]; + + for (uint i = 0; i < num; i++) + { + if (m_Parent->read((char*)buffer, 4) != 4) + { + m_Error = FILE_CORRUPTED; + return false; + } + + data[i] = qFromLittleEndian((unsigned char*)buffer); + } + + decryptBlock(data, num, seed); + + for (uint i = 0; i < num; i++) + { + //qToLittleEndian(data[i], (unsigned char*)buffer); + //part.append(buffer, 4); + part.append((char*)&data[i], 4); + } + } + + else + { + QByteArray ba = m_Parent->read(len); + if (ba.size() != len) + { + m_Error = FILE_CORRUPTED; + return false; + } + + part.append(ba); + } + + if (m_BlockEntry->usesImplode()) + { + DEBUG_Print("Uses PKWARE"); + } + + m_Content.append(part); + + return true; +} + +void MPQFile::decryptBlock(quint32 *data, quint32 length, quint32 seed) +{ + quint32 seed2 = 0xEEEEEEEE; + quint32 ch; + + while(length-- > 0) + { + seed2 += m_Parent->m_CryptBuffer[0x400 + (seed & 0xFF)]; + ch = *data ^ (seed + seed2); + + seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B); + seed2 = ch + seed2 + (seed2 << 5) + 3; + *data++ = ch; + } +} + + + + + + + + + + + + + + + From fe119524818b1f7e6be6e61aea9d456c77dee81d Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sat, 8 May 2010 16:02:14 +0000 Subject: [PATCH 57/69] --- ghost/ghost.cpp | 11 +-- ghost/ghost.pro | 34 +++---- ghost/main.cpp | 45 +++++---- ghost/map.cpp | 7 +- ghost/mpqarchive.h | 172 +++++++++++++++++++++++++++++++++ ghost/mpqfile.h | 56 +++++++++++ ghost/ms_stdint.h | 232 --------------------------------------------- 7 files changed, 273 insertions(+), 284 deletions(-) create mode 100644 ghost/mpqarchive.h create mode 100644 ghost/mpqfile.h delete mode 100644 ghost/ms_stdint.h diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index fab37d8..34a2624 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -44,13 +44,6 @@ #include #include -#ifdef WIN32 - #include // for WSAIoctl -#endif - -#define __STORMLIB_SELF__ -#include - #include #include @@ -897,7 +890,7 @@ void CGHost :: SetConfigs( CConfig *CFG ) } void CGHost :: ExtractScripts( ) -{ +{/* QString PatchMPQFileName = m_Warcraft3Path + "War3Patch.mpq"; HANDLE PatchMPQ; @@ -963,7 +956,7 @@ void CGHost :: ExtractScripts( ) SFileCloseArchive( PatchMPQ ); } else - CONSOLE_Print( "[GHOST] warning - unable to load MPQ file [" + PatchMPQFileName + "] - error code " + QString::number( GetLastError( ) ) ); + CONSOLE_Print( "[GHOST] warning - unable to load MPQ file [" + PatchMPQFileName + "] - error code " + QString::number( GetLastError( ) ) );*/ } void CGHost :: LoadIPToCountryData( ) diff --git a/ghost/ghost.pro b/ghost/ghost.pro index 946acde..fba544f 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -5,7 +5,8 @@ QT += network \ sql QT -= gui TARGET = ghost -CONFIG += console debug +CONFIG += console \ + debug CONFIG -= app_bundle TEMPLATE = app SOURCES += util.cpp \ @@ -39,26 +40,17 @@ SOURCES += util.cpp \ bnetprotocol.cpp \ bnet.cpp \ bncsutilinterface.cpp \ - main.cpp + main.cpp \ + mpqarchive.cpp \ + mpqfile.cpp OTHER_FILES += w3g_format.txt \ w3g_actions.txt \ ghost.vcproj -INCLUDEPATH += ../StormLib \ - ../bncsutil/src \ - ../zlib/include -LIBS += -L../StormLib/stormlib \ - -L../bncsutil/src/bncsutil \ - -L. \ - -L"../bncsutil/vc8_build/Release MySQL" \ - -lbncsutil - win32 { - LIBS += -lStormLibRAS -} - -!win32 { - LIBS += -lStorm -} - +INCLUDEPATH += ../bncsutil/src \ + ../zlib/include +LIBS += -L../bncsutil/src/bncsutil \ + -L"../bncsutil/vc8_build/Release MySQL" \ + -lbncsutil macx { LIBS += -framework CoreFoundation -framework CoreServices LIBS += -L/usr/lib -lbz2 -lz @@ -75,7 +67,6 @@ HEADERS += util.h \ replay.h \ packed.h \ next_combination.h \ - ms_stdint.h \ map.h \ language.h \ includes.h \ @@ -98,4 +89,7 @@ HEADERS += util.h \ bnlsclient.h \ bnetprotocol.h \ bnet.h \ - bncsutilinterface.h + bncsutilinterface.h \ + mpgarchive.h \ + mpqarchive.h \ + mpqfile.h diff --git a/ghost/main.cpp b/ghost/main.cpp index aa6b1ab..b432814 100644 --- a/ghost/main.cpp +++ b/ghost/main.cpp @@ -90,28 +90,37 @@ void DEBUG_Print( QString message ) // main // -#include "crc32.h" +#include "mpqarchive.h" +#include "mpqfile.h" + int main( int argc, char **argv ) { QCoreApplication a(argc, argv); - /*DEBUG_Print(Util::fromUInt32(1111).toHex()); - return 0;*/ - -/* - QByteArray data = QByteArray::fromHex("0224001b019a0700009a070000160101009a0700009a0700001a19303030559a0700009a070000"); - CCRC32 *crc = new CCRC32(); - crc->Initialize(); - DEBUG_Print("Expected: 868c6fa1"); - QByteArray crc32 = UTIL_CreateBYTEARRAY( crc->FullCRC( data ), false ); - // expected: bb76fe69 - DEBUG_Print(crc32.toHex()); - crc32.resize( 2 ); - DEBUG_Print(crc32.toHex()); - - quint16 crc16 = qChecksum("ABCDEF", 6); - DEBUG_Print(UTIL_CreateBYTEARRAY(crc16, false).toHex()); // 5e6f - return 0;*/ + MPQArchive arch("/mnt/disk/Programme/Warcraft III/War3Patch.mpq"); + if (!arch.open() && arch.m_Error != MPQArchive::NO_FILE_LIST) + { + DEBUG_Print("Failed to open, error " + QString::number(arch.m_Error)); + exit(1); + } + + + + /*if (!arch.m_ListFile->read()) + { + DEBUG_Print("Failed to read file list, error " + QString::number(arch.m_ListFile->m_Error)); + }*/ + + + DEBUG_Print("Successfully open MPQ file"); + + MPQFile* common_j = arch.getFile("Scripts\\common.j"); + + if (!common_j->read()) + { + DEBUG_Print("Failed to read common.j, error " + QString::number(common_j->m_Error)); + } + exit(0); gCFGFile = "ghost.cfg"; diff --git a/ghost/map.cpp b/ghost/map.cpp index b9fcd34..080296d 100644 --- a/ghost/map.cpp +++ b/ghost/map.cpp @@ -28,9 +28,6 @@ using std::istringstream; #include "config.h" #include "map.h" -#define __STORMLIB_SELF__ -#include - #define ROTL(x,n) ((x)<<(n))|((x)>>(32-(n))) // this won't work with signed types #define ROTR(x,n) ((x)>>(n))|((x)<<(32-(n))) // this won't work with signed types @@ -266,7 +263,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) m_MapData = UTIL_FileRead( m_GHost->m_MapPath + m_MapLocalPath ); // load the map MPQ - +/* QString MapMPQFileName = m_GHost->m_MapPath + m_MapLocalPath; HANDLE MapMPQ; bool MapMPQReady = false; @@ -877,7 +874,7 @@ void CMap :: Load( CConfig *CFG, QString nCFGFile ) while( m_Slots.size( ) < 12 ) m_Slots.push_back( CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, 12, 12, SLOTRACE_RANDOM ) ); - } + }*/ CheckValid( ); } diff --git a/ghost/mpqarchive.h b/ghost/mpqarchive.h new file mode 100644 index 0000000..ae57263 --- /dev/null +++ b/ghost/mpqarchive.h @@ -0,0 +1,172 @@ +#ifndef MPQARCHIVE_H +#define MPQARCHIVE_H + +#include +class MPQFile; + +class MPQArchive : public QFile +{ + Q_OBJECT + +public: + MPQArchive(const QString & filename); + virtual ~MPQArchive(); + + bool open(); + MPQFile* getFile(const QByteArray &filename); + + enum Error + { + NO_ERROR, + FILE_CORRUPT, + INVALID_HEADER, + FILE_IS_AVI, + CANNOT_OPEN_FILE, + BLOCK_TABLE_CORRUPT, + NO_FILE_LIST, + } m_Error; + + class Header + { + public: + bool readFrom(MPQArchive* parent); + + // The ID_MPQ ('MPQ\x1A') signature + QByteArray m_ID; + + // Size of the archive header + quint32 m_HeaderSize; + + // Size of MPQ archive + // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive + // is calculated as the size from the beginning of the archive to the end of the hash table, + // block table, or extended block table (whichever is largest). + quint32 m_ArchiveSize; + + // 0 = Original format + // 1 = Extended format (The Burning Crusade and newer) + quint16 m_FormatVersion; + + // Power of two exponent specifying the number of 512-byte disk sectors in each logical sector + // in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. + // Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors). + quint16 m_BlockSize; + + // Offset to the beginning of the hash table, relative to the beginning of the archive. + quint32 m_HashTablePos; + + // Offset to the beginning of the block table, relative to the beginning of the archive. + quint32 m_BlockTablePos; + + // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for + // the original MoPaQ format, or less than 2^20 for the Burning Crusade format. + quint32 m_HashTableSize; + + // Number of entries in the block table + quint32 m_BlockTableSize; + }; + + class Shunt + { + public: + bool readFrom(MPQArchive* parent); + + // The ID_MPQ_SHUNT ('MPQ\x1B') signature + QByteArray m_ID; + + // Position of the MPQ header, relative to the begin of the shunt + qint32 m_HeaderPos; + }; + + class FileNode + { + public: + bool readFrom(MPQArchive* parent); + + qint32 m_References; + QByteArray m_Filename; + int m_Size; + }; + + class HashEntry + { + public: + bool readFrom(MPQArchive* parent, quint32 &Seed1, quint32& Seed2); + + // The hash of the file path, using method A. + quint32 m_Name1; + + // The hash of the file path, using method B. + quint32 m_Name2; + + // The language of the file. This is a Windows LANGID data type, and uses the same values. + // 0 indicates the default language (American English), or that the file is language-neutral. + quint16 m_Locale; + + // The platform the file is used for. 0 indicates the default platform. + // No other values have been observed. + quint16 m_Platform; + + // If the hash table entry is valid, this is the index into the block table of the file. + // Otherwise, one of the following two values: + // - FFFFFFFFh: Hash table entry is empty, and has always been empty. + // Terminates searches for a given file. + // - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file). + // Does not terminate searches for a given file. + quint32 m_BlockIndex; + }; + + class BlockEntry + { + public: + bool readFrom(MPQArchive* parent, quint32 &Seed1, quint32& Seed2); + + bool exists(); + bool valid(); + bool compressed(); + bool encrypted(); + bool fixSeed(); + bool singleUnit(); + bool hasExtra(); + bool usesImplode(); + + MPQArchive *m_Parent; + QByteArray readAll(); + + // Offset of the beginning of the block, relative to the beginning of the archive. + quint32 m_FilePos; + + // Compressed file size + quint32 m_CSize; + + // Only valid if the block is a file; otherwise meaningless, and should be 0. + // If the file is compressed, this is the size of the uncompressed file data. + quint32 m_FSize; + + // Flags for the file. See MPQ_FILE_XXXX constants + quint32 m_Flags; + }; + + int m_HeaderOffset; // offset where the header was found + int m_BlockSize; // Size of file block + quint32 getHash(const char *data, int offset = 0x000); + MPQFile *m_ListFile; + quint32 m_CryptBuffer[0x500]; + +private: + HashEntry *GetHashEntry(const char * file, quint32 locale = 0xFFFFFFFF); + + int m_ShuntPos; // MPQShunt offset (only valid if a shunt is present) + int m_HashTablePos; // Hash table offset (relative to the begin of the file) + int m_BlockTablePos; // Block table offset (relative to the begin of the file) + int m_ExtBlockTablePos; // Ext. block table offset (relative to the begin of the file) + int m_MpqSize; // Size of MPQ archive + + Header m_Header; // MPQ header + HashEntry *m_HashTable; + BlockEntry *m_BlockTable; + FileNode *m_FileList; + +}; + +#endif // MPGARCHIVE_H diff --git a/ghost/mpqfile.h b/ghost/mpqfile.h new file mode 100644 index 0000000..e55a860 --- /dev/null +++ b/ghost/mpqfile.h @@ -0,0 +1,56 @@ +#ifndef MPQFILE_H +#define MPQFILE_H + +#include "mpqarchive.h" + +class MPQFile +{ +public: + MPQFile(MPQArchive* archive, const QString &filename, MPQArchive::BlockEntry *block, MPQArchive::HashEntry *hash); + + enum Error + { + NO_ERROR, + POS_TABLE_CORRUPT, + SEED_NOT_FOUND, + DECRYPTION_FAILED, + FILE_CORRUPTED, + } m_Error; + + bool read(); + bool readBlock(quint32 from, quint32 to, quint32 seed); + void decryptBlock(quint32 *data, quint32 length, quint32 seed); + + MPQArchive* m_Parent; + MPQArchive::BlockEntry *m_BlockEntry; + MPQArchive::HashEntry *m_HashEntry; + + quint32 m_Seed1; + quint32 m_PositionFromBegin; + quint32 m_PositionFromHeader; + quint32 m_Size; + + int m_BlockPosTableSize; + qint32 *m_BlockPosTable; + + int m_Blocks; + + QByteArray m_Content; + + QString m_Name; + +/* DWORD * pdwBlockPos; // Position of each file block (only for compressed files) + DWORD nBlocks; // Number of blocks in the file (incl. the last incomplete one) + BOOL bBlockPosLoaded; // TRUE if block positions loaded + BYTE * pbFileBuffer; // Decompressed file (for single unit files, size is the uncompressed file size) + + TMPQCRC32 * pCrc32; // Pointer to CRC32 (NULL if none) + TMPQFileTime * pFileTime; // Pointer to file's FILETIME (NULL if none) + TMPQMD5 * pMd5; // Pointer to file's MD5 (NULL if none) + + DWORD dwHashIndex; // Index to Hash table + DWORD dwBlockIndex; // Index to Block table + char szFileName[1]; // File name (variable length) */ +}; + +#endif // MPQFILE_H diff --git a/ghost/ms_stdint.h b/ghost/ms_stdint.h deleted file mode 100644 index b7dc00c..0000000 --- a/ghost/ms_stdint.h +++ /dev/null @@ -1,232 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#if (_MSC_VER < 1300) && defined(__cplusplus) - extern "C++" { -#endif -# include -#if (_MSC_VER < 1300) && defined(__cplusplus) - } -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 quint16; -typedef unsigned __int32 quint32; -typedef unsigned __int64 uint64_t; - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef quint16 uint_least16_t; -typedef quint32 uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef quint16 uint_fast16_t; -typedef quint32 uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] From ae751a5a1ca2ce27ca5c666f78ba714da23f03c7 Mon Sep 17 00:00:00 2001 From: luqasn Date: Sat, 8 May 2010 19:05:48 +0000 Subject: [PATCH 58/69] ghost.qt: changed all language related function parameters to be called by reference instead of value (avoiding copies) --- ghost/language.cpp | 308 ++++++++++++++++++++++---------------------- ghost/language.h | 312 +++++++++++++++++++++++---------------------- 2 files changed, 312 insertions(+), 308 deletions(-) diff --git a/ghost/language.cpp b/ghost/language.cpp index 46b9f4b..5f95a6b 100644 --- a/ghost/language.cpp +++ b/ghost/language.cpp @@ -27,7 +27,7 @@ // CLanguage // -CLanguage :: CLanguage( QString nCFGFile ) +CLanguage :: CLanguage( const QString &nCFGFile ) { m_CFG = new CConfig( ); m_CFG->Read( nCFGFile ); @@ -38,7 +38,7 @@ CLanguage :: ~CLanguage( ) delete m_CFG; } -QString CLanguage :: UnableToCreateGameTryAnotherName( QString server, QString gamename ) +QString CLanguage :: UnableToCreateGameTryAnotherName( const QString &server, const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0001", "lang_0001" ); Out.replace("$SERVER$", server); @@ -46,7 +46,7 @@ QString CLanguage :: UnableToCreateGameTryAnotherName( QString server, QString g return Out; } -QString CLanguage :: UserIsAlreadyAnAdmin( QString server, QString user ) +QString CLanguage :: UserIsAlreadyAnAdmin( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0002", "lang_0002" ); Out.replace("$SERVER$", server); @@ -54,7 +54,7 @@ QString CLanguage :: UserIsAlreadyAnAdmin( QString server, QString user ) return Out; } -QString CLanguage :: AddedUserToAdminDatabase( QString server, QString user ) +QString CLanguage :: AddedUserToAdminDatabase( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0003", "lang_0003" ); Out.replace("$SERVER$", server); @@ -62,7 +62,7 @@ QString CLanguage :: AddedUserToAdminDatabase( QString server, QString user ) return Out; } -QString CLanguage :: ErrorAddingUserToAdminDatabase( QString server, QString user ) +QString CLanguage :: ErrorAddingUserToAdminDatabase( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0004", "lang_0004" ); Out.replace("$SERVER$", server); @@ -75,7 +75,7 @@ QString CLanguage :: YouDontHaveAccessToThatCommand( ) return m_CFG->GetString( "lang_0005", "lang_0005" ); } -QString CLanguage :: UserIsAlreadyBanned( QString server, QString victim ) +QString CLanguage :: UserIsAlreadyBanned( const QString &server, const QString &victim ) { QString Out = m_CFG->GetString( "lang_0006", "lang_0006" ); Out.replace("$SERVER$", server); @@ -83,7 +83,7 @@ QString CLanguage :: UserIsAlreadyBanned( QString server, QString victim ) return Out; } -QString CLanguage :: BannedUser( QString server, QString victim ) +QString CLanguage :: BannedUser( const QString &server, const QString &victim ) { QString Out = m_CFG->GetString( "lang_0007", "lang_0007" ); Out.replace("$SERVER$", server); @@ -91,7 +91,7 @@ QString CLanguage :: BannedUser( QString server, QString victim ) return Out; } -QString CLanguage :: ErrorBanningUser( QString server, QString victim ) +QString CLanguage :: ErrorBanningUser( const QString &server, const QString &victim ) { QString Out = m_CFG->GetString( "lang_0008", "lang_0008" ); Out.replace("$SERVER$", server); @@ -99,7 +99,7 @@ QString CLanguage :: ErrorBanningUser( QString server, QString victim ) return Out; } -QString CLanguage :: UserIsAnAdmin( QString server, QString user ) +QString CLanguage :: UserIsAnAdmin( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0009", "lang_0009" ); Out.replace("$SERVER$", server); @@ -107,7 +107,7 @@ QString CLanguage :: UserIsAnAdmin( QString server, QString user ) return Out; } -QString CLanguage :: UserIsNotAnAdmin( QString server, QString user ) +QString CLanguage :: UserIsNotAnAdmin( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0010", "lang_0010" ); Out.replace("$SERVER$", server); @@ -115,7 +115,7 @@ QString CLanguage :: UserIsNotAnAdmin( QString server, QString user ) return Out; } -QString CLanguage :: UserWasBannedOnByBecause( QString server, QString victim, QString date, QString admin, QString reason ) +QString CLanguage :: UserWasBannedOnByBecause( const QString &server, const QString &victim, const QString &date, const QString &admin, const QString &reason ) { QString Out = m_CFG->GetString( "lang_0011", "lang_0011" ); Out.replace("$SERVER$", server); @@ -126,7 +126,7 @@ QString CLanguage :: UserWasBannedOnByBecause( QString server, QString victim, Q return Out; } -QString CLanguage :: UserIsNotBanned( QString server, QString victim ) +QString CLanguage :: UserIsNotBanned( const QString &server, const QString &victim ) { QString Out = m_CFG->GetString( "lang_0012", "lang_0012" ); Out.replace("$SERVER$", server); @@ -134,21 +134,21 @@ QString CLanguage :: UserIsNotBanned( QString server, QString victim ) return Out; } -QString CLanguage :: ThereAreNoAdmins( QString server ) +QString CLanguage :: ThereAreNoAdmins( const QString &server ) { QString Out = m_CFG->GetString( "lang_0013", "lang_0013" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereIsAdmin( QString server ) +QString CLanguage :: ThereIsAdmin( const QString &server ) { QString Out = m_CFG->GetString( "lang_0014", "lang_0014" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereAreAdmins( QString server, QString count ) +QString CLanguage :: ThereAreAdmins( const QString &server, const QString &count ) { QString Out = m_CFG->GetString( "lang_0015", "lang_0015" ); Out.replace("$SERVER$", server); @@ -156,21 +156,21 @@ QString CLanguage :: ThereAreAdmins( QString server, QString count ) return Out; } -QString CLanguage :: ThereAreNoBannedUsers( QString server ) +QString CLanguage :: ThereAreNoBannedUsers( const QString &server ) { QString Out = m_CFG->GetString( "lang_0016", "lang_0016" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereIsBannedUser( QString server ) +QString CLanguage :: ThereIsBannedUser( const QString &server ) { QString Out = m_CFG->GetString( "lang_0017", "lang_0017" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereAreBannedUsers( QString server, QString count ) +QString CLanguage :: ThereAreBannedUsers( const QString &server, const QString &count ) { QString Out = m_CFG->GetString( "lang_0018", "lang_0018" ); Out.replace("$SERVER$", server); @@ -183,7 +183,7 @@ QString CLanguage :: YouCantDeleteTheRootAdmin( ) return m_CFG->GetString( "lang_0019", "lang_0019" ); } -QString CLanguage :: DeletedUserFromAdminDatabase( QString server, QString user ) +QString CLanguage :: DeletedUserFromAdminDatabase( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0020", "lang_0020" ); Out.replace("$SERVER$", server); @@ -191,7 +191,7 @@ QString CLanguage :: DeletedUserFromAdminDatabase( QString server, QString user return Out; } -QString CLanguage :: ErrorDeletingUserFromAdminDatabase( QString server, QString user ) +QString CLanguage :: ErrorDeletingUserFromAdminDatabase( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0021", "lang_0021" ); Out.replace("$SERVER$", server); @@ -199,21 +199,21 @@ QString CLanguage :: ErrorDeletingUserFromAdminDatabase( QString server, QString return Out; } -QString CLanguage :: UnbannedUser( QString victim ) +QString CLanguage :: UnbannedUser( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0022", "lang_0022" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: ErrorUnbanningUser( QString victim ) +QString CLanguage :: ErrorUnbanningUser( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0023", "lang_0023" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: GameNumberIs( QString number, QString description ) +QString CLanguage :: GameNumberIs( const QString &number, const QString &description ) { QString Out = m_CFG->GetString( "lang_0024", "lang_0024" ); Out.replace("$NUMBER$", number); @@ -221,14 +221,14 @@ QString CLanguage :: GameNumberIs( QString number, QString description ) return Out; } -QString CLanguage :: GameNumberDoesntExist( QString number ) +QString CLanguage :: GameNumberDoesntExist( const QString &number ) { QString Out = m_CFG->GetString( "lang_0025", "lang_0025" ); Out.replace("$NUMBER$", number); return Out; } -QString CLanguage :: GameIsInTheLobby( QString description, QString current, QString max ) +QString CLanguage :: GameIsInTheLobby( const QString &description, const QString ¤t, const QString &max ) { QString Out = m_CFG->GetString( "lang_0026", "lang_0026" ); Out.replace("$DESCRIPTION$", description); @@ -237,7 +237,7 @@ QString CLanguage :: GameIsInTheLobby( QString description, QString current, QSt return Out; } -QString CLanguage :: ThereIsNoGameInTheLobby( QString current, QString max ) +QString CLanguage :: ThereIsNoGameInTheLobby( const QString ¤t, const QString &max ) { QString Out = m_CFG->GetString( "lang_0027", "lang_0027" ); Out.replace("$CURRENT$", current); @@ -250,21 +250,21 @@ QString CLanguage :: UnableToLoadConfigFilesOutside( ) return m_CFG->GetString( "lang_0028", "lang_0028" ); } -QString CLanguage :: LoadingConfigFile( QString file ) +QString CLanguage :: LoadingConfigFile( const QString &file ) { QString Out = m_CFG->GetString( "lang_0029", "lang_0029" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToLoadConfigFileDoesntExist( QString file ) +QString CLanguage :: UnableToLoadConfigFileDoesntExist( const QString &file ) { QString Out = m_CFG->GetString( "lang_0030", "lang_0030" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: CreatingPrivateGame( QString gamename, QString user ) +QString CLanguage :: CreatingPrivateGame( const QString &gamename, const QString &user ) { QString Out = m_CFG->GetString( "lang_0031", "lang_0031" ); Out.replace("$GAMENAME$", gamename); @@ -272,7 +272,7 @@ QString CLanguage :: CreatingPrivateGame( QString gamename, QString user ) return Out; } -QString CLanguage :: CreatingPublicGame( QString gamename, QString user ) +QString CLanguage :: CreatingPublicGame( const QString &gamename, const QString &user ) { QString Out = m_CFG->GetString( "lang_0032", "lang_0032" ); Out.replace("$GAMENAME$", gamename); @@ -280,14 +280,14 @@ QString CLanguage :: CreatingPublicGame( QString gamename, QString user ) return Out; } -QString CLanguage :: UnableToUnhostGameCountdownStarted( QString description ) +QString CLanguage :: UnableToUnhostGameCountdownStarted( const QString &description ) { QString Out = m_CFG->GetString( "lang_0033", "lang_0033" ); Out.replace("$DESCRIPTION$", description); return Out; } -QString CLanguage :: UnhostingGame( QString description ) +QString CLanguage :: UnhostingGame( const QString &description ) { QString Out = m_CFG->GetString( "lang_0034", "lang_0034" ); Out.replace("$DESCRIPTION$", description); @@ -299,21 +299,21 @@ QString CLanguage :: UnableToUnhostGameNoGameInLobby( ) return m_CFG->GetString( "lang_0035", "lang_0035" ); } -QString CLanguage :: VersionAdmin( QString version ) +QString CLanguage :: VersionAdmin( const QString &version ) { QString Out = m_CFG->GetString( "lang_0036", "lang_0036" ); Out.replace("$VERSION$", version); return Out; } -QString CLanguage :: VersionNotAdmin( QString version ) +QString CLanguage :: VersionNotAdmin( const QString &version ) { QString Out = m_CFG->GetString( "lang_0037", "lang_0037" ); Out.replace("$VERSION$", version); return Out; } -QString CLanguage :: UnableToCreateGameAnotherGameInLobby( QString gamename, QString description ) +QString CLanguage :: UnableToCreateGameAnotherGameInLobby( const QString &gamename, const QString &description ) { QString Out = m_CFG->GetString( "lang_0038", "lang_0038" ); Out.replace("$GAMENAME$", gamename); @@ -321,7 +321,7 @@ QString CLanguage :: UnableToCreateGameAnotherGameInLobby( QString gamename, QSt return Out; } -QString CLanguage :: UnableToCreateGameMaxGamesReached( QString gamename, QString max ) +QString CLanguage :: UnableToCreateGameMaxGamesReached( const QString &gamename, const QString &max ) { QString Out = m_CFG->GetString( "lang_0039", "lang_0039" ); Out.replace("$GAMENAME$", gamename); @@ -329,7 +329,7 @@ QString CLanguage :: UnableToCreateGameMaxGamesReached( QString gamename, QStrin return Out; } -QString CLanguage :: GameIsOver( QString description ) +QString CLanguage :: GameIsOver( const QString &description ) { QString Out = m_CFG->GetString( "lang_0040", "lang_0040" ); Out.replace("$DESCRIPTION$", description); @@ -346,42 +346,42 @@ QString CLanguage :: GameRefreshed( ) return m_CFG->GetString( "lang_0042", "lang_0042" ); } -QString CLanguage :: SpoofPossibleIsAway( QString user ) +QString CLanguage :: SpoofPossibleIsAway( const QString &user ) { QString Out = m_CFG->GetString( "lang_0043", "lang_0043" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofPossibleIsUnavailable( QString user ) +QString CLanguage :: SpoofPossibleIsUnavailable( const QString &user ) { QString Out = m_CFG->GetString( "lang_0044", "lang_0044" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofPossibleIsRefusingMessages( QString user ) +QString CLanguage :: SpoofPossibleIsRefusingMessages( const QString &user ) { QString Out = m_CFG->GetString( "lang_0045", "lang_0045" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofDetectedIsNotInGame( QString user ) +QString CLanguage :: SpoofDetectedIsNotInGame( const QString &user ) { QString Out = m_CFG->GetString( "lang_0046", "lang_0046" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofDetectedIsInPrivateChannel( QString user ) +QString CLanguage :: SpoofDetectedIsInPrivateChannel( const QString &user ) { QString Out = m_CFG->GetString( "lang_0047", "lang_0047" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofDetectedIsInAnotherGame( QString user ) +QString CLanguage :: SpoofDetectedIsInAnotherGame( const QString &user ) { QString Out = m_CFG->GetString( "lang_0048", "lang_0048" ); Out.replace("$USER$", user); @@ -393,21 +393,21 @@ QString CLanguage :: CountDownAborted( ) return m_CFG->GetString( "lang_0049", "lang_0049" ); } -QString CLanguage :: TryingToJoinTheGameButBanned( QString victim ) +QString CLanguage :: TryingToJoinTheGameButBanned( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0050", "lang_0050" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToBanNoMatchesFound( QString victim ) +QString CLanguage :: UnableToBanNoMatchesFound( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0051", "lang_0051" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: PlayerWasBannedByPlayer( QString server, QString victim, QString user ) +QString CLanguage :: PlayerWasBannedByPlayer( const QString &server, const QString &victim, const QString &user ) { QString Out = m_CFG->GetString( "lang_0052", "lang_0052" ); Out.replace("$SERVER$", server); @@ -416,56 +416,56 @@ QString CLanguage :: PlayerWasBannedByPlayer( QString server, QString victim, QS return Out; } -QString CLanguage :: UnableToBanFoundMoreThanOneMatch( QString victim ) +QString CLanguage :: UnableToBanFoundMoreThanOneMatch( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0053", "lang_0053" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: AddedPlayerToTheHoldList( QString user ) +QString CLanguage :: AddedPlayerToTheHoldList( const QString &user ) { QString Out = m_CFG->GetString( "lang_0054", "lang_0054" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: UnableToKickNoMatchesFound( QString victim ) +QString CLanguage :: UnableToKickNoMatchesFound( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0055", "lang_0055" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToKickFoundMoreThanOneMatch( QString victim ) +QString CLanguage :: UnableToKickFoundMoreThanOneMatch( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0056", "lang_0056" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: SettingLatencyToMinimum( QString min ) +QString CLanguage :: SettingLatencyToMinimum( const QString &min ) { QString Out = m_CFG->GetString( "lang_0057", "lang_0057" ); Out.replace("$MIN$", min); return Out; } -QString CLanguage :: SettingLatencyToMaximum( QString max ) +QString CLanguage :: SettingLatencyToMaximum( const QString &max ) { QString Out = m_CFG->GetString( "lang_0058", "lang_0058" ); Out.replace("$MAX$", max); return Out; } -QString CLanguage :: SettingLatencyTo( QString latency ) +QString CLanguage :: SettingLatencyTo( const QString &latency ) { QString Out = m_CFG->GetString( "lang_0059", "lang_0059" ); Out.replace("$LATENCY$", latency); return Out; } -QString CLanguage :: KickingPlayersWithPingsGreaterThan( QString total, QString ping ) +QString CLanguage :: KickingPlayersWithPingsGreaterThan( const QString &total, const QString &ping ) { QString Out = m_CFG->GetString( "lang_0060", "lang_0060" ); Out.replace("$TOTAL$", total); @@ -473,7 +473,7 @@ QString CLanguage :: KickingPlayersWithPingsGreaterThan( QString total, QString return Out; } -QString CLanguage :: HasPlayedGamesWithThisBot( QString user, QString firstgame, QString lastgame, QString totalgames, QString avgloadingtime, QString avgstay ) +QString CLanguage :: HasPlayedGamesWithThisBot( const QString &user, const QString &firstgame, const QString &lastgame, const QString &totalgames, const QString &avgloadingtime, const QString &avgstay ) { QString Out = m_CFG->GetString( "lang_0061", "lang_0061" ); Out.replace("$USER$", user); @@ -485,14 +485,14 @@ QString CLanguage :: HasPlayedGamesWithThisBot( QString user, QString firstgame, return Out; } -QString CLanguage :: HasntPlayedGamesWithThisBot( QString user ) +QString CLanguage :: HasntPlayedGamesWithThisBot( const QString &user ) { QString Out = m_CFG->GetString( "lang_0062", "lang_0062" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: AutokickingPlayerForExcessivePing( QString victim, QString ping ) +QString CLanguage :: AutokickingPlayerForExcessivePing( const QString &victim, const QString &ping ) { QString Out = m_CFG->GetString( "lang_0063", "lang_0063" ); Out.replace("$VICTIM$", victim); @@ -500,7 +500,7 @@ QString CLanguage :: AutokickingPlayerForExcessivePing( QString victim, QString return Out; } -QString CLanguage :: SpoofCheckAcceptedFor( QString server, QString user ) +QString CLanguage :: SpoofCheckAcceptedFor( const QString &server, const QString &user ) { QString Out = m_CFG->GetString( "lang_0064", "lang_0064" ); Out.replace("$SERVER$", server); @@ -508,21 +508,21 @@ QString CLanguage :: SpoofCheckAcceptedFor( QString server, QString user ) return Out; } -QString CLanguage :: PlayersNotYetSpoofChecked( QString notspoofchecked ) +QString CLanguage :: PlayersNotYetSpoofChecked( const QString ¬spoofchecked ) { QString Out = m_CFG->GetString( "lang_0065", "lang_0065" ); Out.replace("$NOTSPOOFCHECKED$", notspoofchecked); return Out; } -QString CLanguage :: ManuallySpoofCheckByWhispering( QString hostname ) +QString CLanguage :: ManuallySpoofCheckByWhispering( const QString &hostname ) { QString Out = m_CFG->GetString( "lang_0066", "lang_0066" ); Out.replace("$HOSTNAME$", hostname); return Out; } -QString CLanguage :: SpoofCheckByWhispering( QString hostname ) +QString CLanguage :: SpoofCheckByWhispering( const QString &hostname ) { QString Out = m_CFG->GetString( "lang_0067", "lang_0067" ); Out.replace("$HOSTNAME$", hostname); @@ -534,7 +534,7 @@ QString CLanguage :: EveryoneHasBeenSpoofChecked( ) return m_CFG->GetString( "lang_0068", "lang_0068" ); } -QString CLanguage :: PlayersNotYetPinged( QString notpinged ) +QString CLanguage :: PlayersNotYetPinged( const QString ¬pinged ) { QString Out = m_CFG->GetString( "lang_0069", "lang_0069" ); Out.replace("$NOTPINGED$", notpinged); @@ -546,7 +546,7 @@ QString CLanguage :: EveryoneHasBeenPinged( ) return m_CFG->GetString( "lang_0070", "lang_0070" ); } -QString CLanguage :: ShortestLoadByPlayer( QString user, QString loadingtime ) +QString CLanguage :: ShortestLoadByPlayer( const QString &user, const QString &loadingtime ) { QString Out = m_CFG->GetString( "lang_0071", "lang_0071" ); Out.replace("$USER$", user); @@ -554,7 +554,7 @@ QString CLanguage :: ShortestLoadByPlayer( QString user, QString loadingtime ) return Out; } -QString CLanguage :: LongestLoadByPlayer( QString user, QString loadingtime ) +QString CLanguage :: LongestLoadByPlayer( const QString &user, const QString &loadingtime ) { QString Out = m_CFG->GetString( "lang_0072", "lang_0072" ); Out.replace("$USER$", user); @@ -562,14 +562,14 @@ QString CLanguage :: LongestLoadByPlayer( QString user, QString loadingtime ) return Out; } -QString CLanguage :: YourLoadingTimeWas( QString loadingtime ) +QString CLanguage :: YourLoadingTimeWas( const QString &loadingtime ) { QString Out = m_CFG->GetString( "lang_0073", "lang_0073" ); Out.replace("$LOADINGTIME$", loadingtime); return Out; } -QString CLanguage :: HasPlayedDotAGamesWithThisBot( QString user, QString totalgames, QString totalwins, QString totallosses, QString totalkills, QString totaldeaths, QString totalcreepkills, QString totalcreepdenies, QString totalassists, QString totalneutralkills, QString totaltowerkills, QString totalraxkills, QString totalcourierkills, QString avgkills, QString avgdeaths, QString avgcreepkills, QString avgcreepdenies, QString avgassists, QString avgneutralkills, QString avgtowerkills, QString avgraxkills, QString avgcourierkills ) +QString CLanguage :: HasPlayedDotAGamesWithThisBot( const QString &user, const QString &totalgames, const QString &totalwins, const QString &totallosses, const QString &totalkills, const QString &totaldeaths, const QString &totalcreepkills, const QString &totalcreepdenies, const QString &totalassists, const QString &totalneutralkills, const QString &totaltowerkills, const QString &totalraxkills, const QString &totalcourierkills, const QString &avgkills, const QString &avgdeaths, const QString &avgcreepkills, const QString &avgcreepdenies, const QString &avgassists, const QString &avgneutralkills, const QString &avgtowerkills, const QString &avgraxkills, const QString &avgcourierkills ) { QString Out = m_CFG->GetString( "lang_0074", "lang_0074" ); Out.replace("$USER$", user); @@ -597,42 +597,42 @@ QString CLanguage :: HasPlayedDotAGamesWithThisBot( QString user, QString totalg return Out; } -QString CLanguage :: HasntPlayedDotAGamesWithThisBot( QString user ) +QString CLanguage :: HasntPlayedDotAGamesWithThisBot( const QString &user ) { QString Out = m_CFG->GetString( "lang_0075", "lang_0075" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: WasKickedForReservedPlayer( QString reserved ) +QString CLanguage :: WasKickedForReservedPlayer( const QString &reserved ) { QString Out = m_CFG->GetString( "lang_0076", "lang_0076" ); Out.replace("$RESERVED$", reserved); return Out; } -QString CLanguage :: WasKickedForOwnerPlayer( QString owner ) +QString CLanguage :: WasKickedForOwnerPlayer( const QString &owner ) { QString Out = m_CFG->GetString( "lang_0077", "lang_0077" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: WasKickedByPlayer( QString user ) +QString CLanguage :: WasKickedByPlayer( const QString &user ) { QString Out = m_CFG->GetString( "lang_0078", "lang_0078" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: HasLostConnectionPlayerError( QString error ) +QString CLanguage :: HasLostConnectionPlayerError( const QString &error ) { QString Out = m_CFG->GetString( "lang_0079", "lang_0079" ); Out.replace("$ERROR$", error); return Out; } -QString CLanguage :: HasLostConnectionSocketError( QString error ) +QString CLanguage :: HasLostConnectionSocketError( const QString &error ) { QString Out = m_CFG->GetString( "lang_0080", "lang_0080" ); Out.replace("$ERROR$", error); @@ -649,7 +649,7 @@ QString CLanguage :: HasLeftVoluntarily( ) return m_CFG->GetString( "lang_0082", "lang_0082" ); } -QString CLanguage :: EndingGame( QString description ) +QString CLanguage :: EndingGame( const QString &description ) { QString Out = m_CFG->GetString( "lang_0083", "lang_0083" ); Out.replace("$DESCRIPTION$", description); @@ -681,7 +681,7 @@ QString CLanguage :: UnableToLoadConfigFileGameInLobby( ) return m_CFG->GetString( "lang_0088", "lang_0088" ); } -QString CLanguage :: PlayersStillDownloading( QString stilldownloading ) +QString CLanguage :: PlayersStillDownloading( const QString &stilldownloading ) { QString Out = m_CFG->GetString( "lang_0089", "lang_0089" ); Out.replace("$STILLDOWNLOADING$", stilldownloading); @@ -703,7 +703,7 @@ QString CLanguage :: AtLeastOneGameActiveUseForceToShutdown( ) return m_CFG->GetString( "lang_0092", "lang_0092" ); } -QString CLanguage :: CurrentlyLoadedMapCFGIs( QString mapcfg ) +QString CLanguage :: CurrentlyLoadedMapCFGIs( const QString &mapcfg ) { QString Out = m_CFG->GetString( "lang_0093", "lang_0093" ); Out.replace("$MAPCFG$", mapcfg); @@ -720,49 +720,49 @@ QString CLanguage :: LaggedOutDroppedByVote( ) return m_CFG->GetString( "lang_0095", "lang_0095" ); } -QString CLanguage :: PlayerVotedToDropLaggers( QString user ) +QString CLanguage :: PlayerVotedToDropLaggers( const QString &user ) { QString Out = m_CFG->GetString( "lang_0096", "lang_0096" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: LatencyIs( QString latency ) +QString CLanguage :: LatencyIs( const QString &latency ) { QString Out = m_CFG->GetString( "lang_0097", "lang_0097" ); Out.replace("$LATENCY$", latency); return Out; } -QString CLanguage :: SyncLimitIs( QString synclimit ) +QString CLanguage :: SyncLimitIs( const QString &synclimit ) { QString Out = m_CFG->GetString( "lang_0098", "lang_0098" ); Out.replace("$SYNCLIMIT$", synclimit); return Out; } -QString CLanguage :: SettingSyncLimitToMinimum( QString min ) +QString CLanguage :: SettingSyncLimitToMinimum( const QString &min ) { QString Out = m_CFG->GetString( "lang_0099", "lang_0099" ); Out.replace("$MIN$", min); return Out; } -QString CLanguage :: SettingSyncLimitToMaximum( QString max ) +QString CLanguage :: SettingSyncLimitToMaximum( const QString &max ) { QString Out = m_CFG->GetString( "lang_0100", "lang_0100" ); Out.replace("$MAX$", max); return Out; } -QString CLanguage :: SettingSyncLimitTo( QString synclimit ) +QString CLanguage :: SettingSyncLimitTo( const QString &synclimit ) { QString Out = m_CFG->GetString( "lang_0101", "lang_0101" ); Out.replace("$SYNCLIMIT$", synclimit); return Out; } -QString CLanguage :: UnableToCreateGameNotLoggedIn( QString gamename ) +QString CLanguage :: UnableToCreateGameNotLoggedIn( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0102", "lang_0102" ); Out.replace("$GAMENAME$", gamename); @@ -774,49 +774,49 @@ QString CLanguage :: AdminLoggedIn( ) return m_CFG->GetString( "lang_0103", "lang_0103" ); } -QString CLanguage :: AdminInvalidPassword( QString attempt ) +QString CLanguage :: AdminInvalidPassword( const QString &attempt ) { QString Out = m_CFG->GetString( "lang_0104", "lang_0104" ); Out.replace("$ATTEMPT$", attempt); return Out; } -QString CLanguage :: ConnectingToBNET( QString server ) +QString CLanguage :: ConnectingToBNET( const QString &server ) { QString Out = m_CFG->GetString( "lang_0105", "lang_0105" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ConnectedToBNET( QString server ) +QString CLanguage :: ConnectedToBNET( const QString &server ) { QString Out = m_CFG->GetString( "lang_0106", "lang_0106" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: DisconnectedFromBNET( QString server ) +QString CLanguage :: DisconnectedFromBNET( const QString &server ) { QString Out = m_CFG->GetString( "lang_0107", "lang_0107" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: LoggedInToBNET( QString server ) +QString CLanguage :: LoggedInToBNET( const QString &server ) { QString Out = m_CFG->GetString( "lang_0108", "lang_0108" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: BNETGameHostingSucceeded( QString server ) +QString CLanguage :: BNETGameHostingSucceeded( const QString &server ) { QString Out = m_CFG->GetString( "lang_0109", "lang_0109" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: BNETGameHostingFailed( QString server, QString gamename ) +QString CLanguage :: BNETGameHostingFailed( const QString &server, const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0110", "lang_0110" ); Out.replace("$SERVER$", server); @@ -824,14 +824,14 @@ QString CLanguage :: BNETGameHostingFailed( QString server, QString gamename ) return Out; } -QString CLanguage :: ConnectingToBNETTimedOut( QString server ) +QString CLanguage :: ConnectingToBNETTimedOut( const QString &server ) { QString Out = m_CFG->GetString( "lang_0111", "lang_0111" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: PlayerDownloadedTheMap( QString user, QString seconds, QString rate ) +QString CLanguage :: PlayerDownloadedTheMap( const QString &user, const QString &seconds, const QString &rate ) { QString Out = m_CFG->GetString( "lang_0112", "lang_0112" ); Out.replace("$USER$", user); @@ -840,14 +840,14 @@ QString CLanguage :: PlayerDownloadedTheMap( QString user, QString seconds, QStr return Out; } -QString CLanguage :: UnableToCreateGameNameTooLong( QString gamename ) +QString CLanguage :: UnableToCreateGameNameTooLong( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0113", "lang_0113" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: SettingGameOwnerTo( QString owner ) +QString CLanguage :: SettingGameOwnerTo( const QString &owner ) { QString Out = m_CFG->GetString( "lang_0114", "lang_0114" ); Out.replace("$OWNER$", owner); @@ -869,35 +869,35 @@ QString CLanguage :: GameUnlocked( ) return m_CFG->GetString( "lang_0117", "lang_0117" ); } -QString CLanguage :: UnableToStartDownloadNoMatchesFound( QString victim ) +QString CLanguage :: UnableToStartDownloadNoMatchesFound( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0118", "lang_0118" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( QString victim ) +QString CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0119", "lang_0119" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToSetGameOwner( QString owner ) +QString CLanguage :: UnableToSetGameOwner( const QString &owner ) { QString Out = m_CFG->GetString( "lang_0120", "lang_0120" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: UnableToCheckPlayerNoMatchesFound( QString victim ) +QString CLanguage :: UnableToCheckPlayerNoMatchesFound( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0121", "lang_0121" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: CheckedPlayer( QString victim, QString ping, QString from, QString admin, QString owner, QString spoofed, QString spoofedrealm, QString reserved ) +QString CLanguage :: CheckedPlayer( const QString &victim, const QString &ping, const QString &from, const QString &admin, const QString &owner, const QString &spoofed, const QString &spoofedrealm, const QString &reserved ) { QString Out = m_CFG->GetString( "lang_0122", "lang_0122" ); Out.replace("$VICTIM$", victim); @@ -911,7 +911,7 @@ QString CLanguage :: CheckedPlayer( QString victim, QString ping, QString from, return Out; } -QString CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( QString victim ) +QString CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0123", "lang_0123" ); Out.replace("$VICTIM$", victim); @@ -923,7 +923,7 @@ QString CLanguage :: TheGameIsLockedBNET( ) return m_CFG->GetString( "lang_0124", "lang_0124" ); } -QString CLanguage :: UnableToCreateGameDisabled( QString gamename ) +QString CLanguage :: UnableToCreateGameDisabled( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0125", "lang_0125" ); Out.replace("$GAMENAME$", gamename); @@ -940,14 +940,14 @@ QString CLanguage :: BotEnabled( ) return m_CFG->GetString( "lang_0127", "lang_0127" ); } -QString CLanguage :: UnableToCreateGameInvalidMap( QString gamename ) +QString CLanguage :: UnableToCreateGameInvalidMap( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0128", "lang_0128" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: WaitingForPlayersBeforeAutoStart( QString players, QString playersleft ) +QString CLanguage :: WaitingForPlayersBeforeAutoStart( const QString &players, const QString &playersleft ) { QString Out = m_CFG->GetString( "lang_0129", "lang_0129" ); Out.replace("$PLAYERS$", players); @@ -960,7 +960,7 @@ QString CLanguage :: AutoStartDisabled( ) return m_CFG->GetString( "lang_0130", "lang_0130" ); } -QString CLanguage :: AutoStartEnabled( QString players ) +QString CLanguage :: AutoStartEnabled( const QString &players ) { QString Out = m_CFG->GetString( "lang_0131", "lang_0131" ); Out.replace("$PLAYERS$", players); @@ -997,28 +997,28 @@ QString CLanguage :: UnableToLoadSaveGameGameInLobby( ) return m_CFG->GetString( "lang_0137", "lang_0137" ); } -QString CLanguage :: LoadingSaveGame( QString file ) +QString CLanguage :: LoadingSaveGame( const QString &file ) { QString Out = m_CFG->GetString( "lang_0138", "lang_0138" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToLoadSaveGameDoesntExist( QString file ) +QString CLanguage :: UnableToLoadSaveGameDoesntExist( const QString &file ) { QString Out = m_CFG->GetString( "lang_0139", "lang_0139" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToCreateGameInvalidSaveGame( QString gamename ) +QString CLanguage :: UnableToCreateGameInvalidSaveGame( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0140", "lang_0140" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: UnableToCreateGameSaveGameMapMismatch( QString gamename ) +QString CLanguage :: UnableToCreateGameSaveGameMapMismatch( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0141", "lang_0141" ); Out.replace("$GAMENAME$", gamename); @@ -1040,14 +1040,14 @@ QString CLanguage :: DesyncDetected( ) return m_CFG->GetString( "lang_0144", "lang_0144" ); } -QString CLanguage :: UnableToMuteNoMatchesFound( QString victim ) +QString CLanguage :: UnableToMuteNoMatchesFound( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0145", "lang_0145" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: MutedPlayer( QString victim, QString user ) +QString CLanguage :: MutedPlayer( const QString &victim, const QString &user ) { QString Out = m_CFG->GetString( "lang_0146", "lang_0146" ); Out.replace("$VICTIM$", victim); @@ -1055,7 +1055,7 @@ QString CLanguage :: MutedPlayer( QString victim, QString user ) return Out; } -QString CLanguage :: UnmutedPlayer( QString victim, QString user ) +QString CLanguage :: UnmutedPlayer( const QString &victim, const QString &user ) { QString Out = m_CFG->GetString( "lang_0147", "lang_0147" ); Out.replace("$VICTIM$", victim); @@ -1063,14 +1063,14 @@ QString CLanguage :: UnmutedPlayer( QString victim, QString user ) return Out; } -QString CLanguage :: UnableToMuteFoundMoreThanOneMatch( QString victim ) +QString CLanguage :: UnableToMuteFoundMoreThanOneMatch( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0148", "lang_0148" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: PlayerIsSavingTheGame( QString player ) +QString CLanguage :: PlayerIsSavingTheGame( const QString &player ) { QString Out = m_CFG->GetString( "lang_0149", "lang_0149" ); Out.replace("$PLAYER$", player); @@ -1087,7 +1087,7 @@ QString CLanguage :: UpdatingFriendsList( ) return m_CFG->GetString( "lang_0151", "lang_0151" ); } -QString CLanguage :: MultipleIPAddressUsageDetected( QString player, QString others ) +QString CLanguage :: MultipleIPAddressUsageDetected( const QString &player, const QString &others ) { QString Out = m_CFG->GetString( "lang_0152", "lang_0152" ); Out.replace("$PLAYER$", player); @@ -1105,21 +1105,21 @@ QString CLanguage :: UnableToVoteKickNotEnoughPlayers( ) return m_CFG->GetString( "lang_0154", "lang_0154" ); } -QString CLanguage :: UnableToVoteKickNoMatchesFound( QString victim ) +QString CLanguage :: UnableToVoteKickNoMatchesFound( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0155", "lang_0155" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToVoteKickPlayerIsReserved( QString victim ) +QString CLanguage :: UnableToVoteKickPlayerIsReserved( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0156", "lang_0156" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: StartedVoteKick( QString victim, QString user, QString votesneeded ) +QString CLanguage :: StartedVoteKick( const QString &victim, const QString &user, const QString &votesneeded ) { QString Out = m_CFG->GetString( "lang_0157", "lang_0157" ); Out.replace("$VICTIM$", victim); @@ -1128,28 +1128,28 @@ QString CLanguage :: StartedVoteKick( QString victim, QString user, QString vote return Out; } -QString CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( QString victim ) +QString CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0158", "lang_0158" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: VoteKickPassed( QString victim ) +QString CLanguage :: VoteKickPassed( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0159", "lang_0159" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: ErrorVoteKickingPlayer( QString victim ) +QString CLanguage :: ErrorVoteKickingPlayer( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0160", "lang_0160" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: VoteKickAcceptedNeedMoreVotes( QString victim, QString user, QString votes ) +QString CLanguage :: VoteKickAcceptedNeedMoreVotes( const QString &victim, const QString &user, const QString &votes ) { QString Out = m_CFG->GetString( "lang_0161", "lang_0161" ); Out.replace("$VICTIM$", victim); @@ -1158,14 +1158,14 @@ QString CLanguage :: VoteKickAcceptedNeedMoreVotes( QString victim, QString user return Out; } -QString CLanguage :: VoteKickCancelled( QString victim ) +QString CLanguage :: VoteKickCancelled( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0162", "lang_0162" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: VoteKickExpired( QString victim ) +QString CLanguage :: VoteKickExpired( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0163", "lang_0163" ); Out.replace("$VICTIM$", victim); @@ -1177,14 +1177,14 @@ QString CLanguage :: WasKickedByVote( ) return m_CFG->GetString( "lang_0164", "lang_0164" ); } -QString CLanguage :: TypeYesToVote( QString commandtrigger ) +QString CLanguage :: TypeYesToVote( const QString &commandtrigger ) { QString Out = m_CFG->GetString( "lang_0165", "lang_0165" ); Out.replace("$COMMANDTRIGGER$", commandtrigger); return Out; } -QString CLanguage :: PlayersNotYetPingedAutoStart( QString notpinged ) +QString CLanguage :: PlayersNotYetPingedAutoStart( const QString ¬pinged ) { QString Out = m_CFG->GetString( "lang_0166", "lang_0166" ); Out.replace("$NOTPINGED$", notpinged); @@ -1196,7 +1196,7 @@ QString CLanguage :: WasKickedForNotSpoofChecking( ) return m_CFG->GetString( "lang_0167", "lang_0167" ); } -QString CLanguage :: WasKickedForHavingFurthestScore( QString score, QString average ) +QString CLanguage :: WasKickedForHavingFurthestScore( const QString &score, const QString &average ) { QString Out = m_CFG->GetString( "lang_0168", "lang_0168" ); Out.replace("$SCORE$", score); @@ -1204,7 +1204,7 @@ QString CLanguage :: WasKickedForHavingFurthestScore( QString score, QString ave return Out; } -QString CLanguage :: PlayerHasScore( QString player, QString score ) +QString CLanguage :: PlayerHasScore( const QString &player, const QString &score ) { QString Out = m_CFG->GetString( "lang_0169", "lang_0169" ); Out.replace("$PLAYER$", player); @@ -1212,7 +1212,7 @@ QString CLanguage :: PlayerHasScore( QString player, QString score ) return Out; } -QString CLanguage :: RatedPlayersSpread( QString rated, QString total, QString spread ) +QString CLanguage :: RatedPlayersSpread( const QString &rated, const QString &total, const QString &spread ) { QString Out = m_CFG->GetString( "lang_0170", "lang_0170" ); Out.replace("$RATED$", rated); @@ -1226,7 +1226,7 @@ QString CLanguage :: ErrorListingMaps( ) return m_CFG->GetString( "lang_0171", "lang_0171" ); } -QString CLanguage :: FoundMaps( QString maps ) +QString CLanguage :: FoundMaps( const QString &maps ) { QString Out = m_CFG->GetString( "lang_0172", "lang_0172" ); Out.replace("$MAPS$", maps); @@ -1243,7 +1243,7 @@ QString CLanguage :: ErrorListingMapConfigs( ) return m_CFG->GetString( "lang_0174", "lang_0174" ); } -QString CLanguage :: FoundMapConfigs( QString mapconfigs ) +QString CLanguage :: FoundMapConfigs( const QString &mapconfigs ) { QString Out = m_CFG->GetString( "lang_0175", "lang_0175" ); Out.replace("$MAPCONFIGS$", mapconfigs); @@ -1255,7 +1255,7 @@ QString CLanguage :: NoMapConfigsFound( ) return m_CFG->GetString( "lang_0176", "lang_0176" ); } -QString CLanguage :: PlayerFinishedLoading( QString user ) +QString CLanguage :: PlayerFinishedLoading( const QString &user ) { QString Out = m_CFG->GetString( "lang_0177", "lang_0177" ); Out.replace("$USER$", user); @@ -1282,7 +1282,7 @@ QString CLanguage :: MapDownloadsConditional( ) return m_CFG->GetString( "lang_0181", "lang_0181" ); } -QString CLanguage :: SettingHCL( QString HCL ) +QString CLanguage :: SettingHCL( const QString &HCL ) { QString Out = m_CFG->GetString( "lang_0182", "lang_0182" ); Out.replace("$HCL$", HCL); @@ -1299,7 +1299,7 @@ QString CLanguage :: UnableToSetHCLTooLong( ) return m_CFG->GetString( "lang_0184", "lang_0184" ); } -QString CLanguage :: TheHCLIs( QString HCL ) +QString CLanguage :: TheHCLIs( const QString &HCL ) { QString Out = m_CFG->GetString( "lang_0185", "lang_0185" ); Out.replace("$HCL$", HCL); @@ -1316,14 +1316,14 @@ QString CLanguage :: ClearingHCL( ) return m_CFG->GetString( "lang_0187", "lang_0187" ); } -QString CLanguage :: TryingToRehostAsPrivateGame( QString gamename ) +QString CLanguage :: TryingToRehostAsPrivateGame( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0188", "lang_0188" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: TryingToRehostAsPublicGame( QString gamename ) +QString CLanguage :: TryingToRehostAsPublicGame( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0189", "lang_0189" ); Out.replace("$GAMENAME$", gamename); @@ -1335,14 +1335,14 @@ QString CLanguage :: RehostWasSuccessful( ) return m_CFG->GetString( "lang_0190", "lang_0190" ); } -QString CLanguage :: TryingToJoinTheGameButBannedByName( QString victim ) +QString CLanguage :: TryingToJoinTheGameButBannedByName( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0191", "lang_0191" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: TryingToJoinTheGameButBannedByIP( QString victim, QString ip, QString bannedname ) +QString CLanguage :: TryingToJoinTheGameButBannedByIP( const QString &victim, const QString &ip, const QString &bannedname ) { QString Out = m_CFG->GetString( "lang_0192", "lang_0192" ); Out.replace("$VICTIM$", victim); @@ -1351,14 +1351,14 @@ QString CLanguage :: TryingToJoinTheGameButBannedByIP( QString victim, QString i return Out; } -QString CLanguage :: HasBannedName( QString victim ) +QString CLanguage :: HasBannedName( const QString &victim ) { QString Out = m_CFG->GetString( "lang_0193", "lang_0193" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: HasBannedIP( QString victim, QString ip, QString bannedname ) +QString CLanguage :: HasBannedIP( const QString &victim, const QString &ip, const QString &bannedname ) { QString Out = m_CFG->GetString( "lang_0194", "lang_0194" ); Out.replace("$VICTIM$", victim); @@ -1367,7 +1367,7 @@ QString CLanguage :: HasBannedIP( QString victim, QString ip, QString bannedname return Out; } -QString CLanguage :: PlayersInGameState( QString number, QString players ) +QString CLanguage :: PlayersInGameState( const QString &number, const QString &players ) { QString Out = m_CFG->GetString( "lang_0195", "lang_0195" ); Out.replace("$NUMBER$", number); @@ -1375,14 +1375,14 @@ QString CLanguage :: PlayersInGameState( QString number, QString players ) return Out; } -QString CLanguage :: ValidServers( QString servers ) +QString CLanguage :: ValidServers( const QString &servers ) { QString Out = m_CFG->GetString( "lang_0196", "lang_0196" ); Out.replace("$SERVERS$", servers); return Out; } -QString CLanguage :: TeamCombinedScore( QString team, QString score ) +QString CLanguage :: TeamCombinedScore( const QString &team, const QString &score ) { QString Out = m_CFG->GetString( "lang_0197", "lang_0197" ); Out.replace("$TEAM$", team); @@ -1395,7 +1395,7 @@ QString CLanguage :: BalancingSlotsCompleted( ) return m_CFG->GetString( "lang_0198", "lang_0198" ); } -QString CLanguage :: PlayerWasKickedForFurthestScore( QString name, QString score, QString average ) +QString CLanguage :: PlayerWasKickedForFurthestScore( const QString &name, const QString &score, const QString &average ) { QString Out = m_CFG->GetString( "lang_0199", "lang_0199" ); Out.replace("$NAME$", name); @@ -1419,14 +1419,14 @@ QString CLanguage :: WasDroppedDesync( ) return m_CFG->GetString( "lang_0202", "lang_0202" ); } -QString CLanguage :: WasKickedForHavingLowestScore( QString score ) +QString CLanguage :: WasKickedForHavingLowestScore( const QString &score ) { QString Out = m_CFG->GetString( "lang_0203", "lang_0203" ); Out.replace("$SCORE$", score); return Out; } -QString CLanguage :: PlayerWasKickedForLowestScore( QString name, QString score ) +QString CLanguage :: PlayerWasKickedForLowestScore( const QString &name, const QString &score ) { QString Out = m_CFG->GetString( "lang_0204", "lang_0204" ); Out.replace("$NAME$", name); @@ -1444,7 +1444,7 @@ QString CLanguage :: CountDownAbortedSomeoneLeftRecently( ) return m_CFG->GetString( "lang_0206", "lang_0206" ); } -QString CLanguage :: UnableToCreateGameMustEnforceFirst( QString gamename ) +QString CLanguage :: UnableToCreateGameMustEnforceFirst( const QString &gamename ) { QString Out = m_CFG->GetString( "lang_0207", "lang_0207" ); Out.replace("$GAMENAME$", gamename); @@ -1456,42 +1456,42 @@ QString CLanguage :: UnableToLoadReplaysOutside( ) return m_CFG->GetString( "lang_0208", "lang_0208" ); } -QString CLanguage :: LoadingReplay( QString file ) +QString CLanguage :: LoadingReplay( const QString &file ) { QString Out = m_CFG->GetString( "lang_0209", "lang_0209" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToLoadReplayDoesntExist( QString file ) +QString CLanguage :: UnableToLoadReplayDoesntExist( const QString &file ) { QString Out = m_CFG->GetString( "lang_0210", "lang_0210" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: CommandTrigger( QString trigger ) +QString CLanguage :: CommandTrigger( const QString &trigger ) { QString Out = m_CFG->GetString( "lang_0211", "lang_0211" ); Out.replace("$TRIGGER$", trigger); return Out; } -QString CLanguage :: CantEndGameOwnerIsStillPlaying( QString owner ) +QString CLanguage :: CantEndGameOwnerIsStillPlaying( const QString &owner ) { QString Out = m_CFG->GetString( "lang_0212", "lang_0212" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: CantUnhostGameOwnerIsPresent( QString owner ) +QString CLanguage :: CantUnhostGameOwnerIsPresent( const QString &owner ) { QString Out = m_CFG->GetString( "lang_0213", "lang_0213" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: WasAutomaticallyDroppedAfterSeconds( QString seconds ) +QString CLanguage :: WasAutomaticallyDroppedAfterSeconds( const QString &seconds ) { QString Out = m_CFG->GetString( "lang_0214", "lang_0214" ); Out.replace("$SECONDS$", seconds); @@ -1503,7 +1503,7 @@ QString CLanguage :: HasLostConnectionTimedOutGProxy( ) return m_CFG->GetString( "lang_0215", "lang_0215" ); } -QString CLanguage :: HasLostConnectionSocketErrorGProxy( QString error ) +QString CLanguage :: HasLostConnectionSocketErrorGProxy( const QString &error ) { QString Out = m_CFG->GetString( "lang_0216", "lang_0216" ); Out.replace("$ERROR$", error); @@ -1515,7 +1515,7 @@ QString CLanguage :: HasLostConnectionClosedByRemoteHostGProxy( ) return m_CFG->GetString( "lang_0217", "lang_0217" ); } -QString CLanguage :: WaitForReconnectSecondsRemain( QString seconds ) +QString CLanguage :: WaitForReconnectSecondsRemain( const QString &seconds ) { QString Out = m_CFG->GetString( "lang_0218", "lang_0218" ); Out.replace("$SECONDS$", seconds); @@ -1527,7 +1527,7 @@ QString CLanguage :: WasUnrecoverablyDroppedFromGProxy( ) return m_CFG->GetString( "lang_0219", "lang_0219" ); } -QString CLanguage :: PlayerReconnectedWithGProxy( QString name ) +QString CLanguage :: PlayerReconnectedWithGProxy( const QString &name ) { QString Out = m_CFG->GetString( "lang_0220", "lang_0220" ); Out.replace("$NAME$", name); diff --git a/ghost/language.h b/ghost/language.h index 8596d8b..07c060f 100644 --- a/ghost/language.h +++ b/ghost/language.h @@ -21,6 +21,10 @@ #ifndef LANGUAGE_H #define LANGUAGE_H +#include + +class CConfig; + // // CLanguage // @@ -31,229 +35,229 @@ class CLanguage CConfig *m_CFG; public: - CLanguage( QString nCFGFile ); + CLanguage( const QString &nCFGFile ); ~CLanguage( ); - QString UnableToCreateGameTryAnotherName( QString server, QString gamename ); - QString UserIsAlreadyAnAdmin( QString server, QString user ); - QString AddedUserToAdminDatabase( QString server, QString user ); - QString ErrorAddingUserToAdminDatabase( QString server, QString user ); + QString UnableToCreateGameTryAnotherName( const QString &server, const QString &gamename ); + QString UserIsAlreadyAnAdmin( const QString &server, const QString &user ); + QString AddedUserToAdminDatabase( const QString &server, const QString &user ); + QString ErrorAddingUserToAdminDatabase( const QString &server, const QString &user ); QString YouDontHaveAccessToThatCommand( ); - QString UserIsAlreadyBanned( QString server, QString victim ); - QString BannedUser( QString server, QString victim ); - QString ErrorBanningUser( QString server, QString victim ); - QString UserIsAnAdmin( QString server, QString user ); - QString UserIsNotAnAdmin( QString server, QString user ); - QString UserWasBannedOnByBecause( QString server, QString victim, QString date, QString admin, QString reason ); - QString UserIsNotBanned( QString server, QString victim ); - QString ThereAreNoAdmins( QString server ); - QString ThereIsAdmin( QString server ); - QString ThereAreAdmins( QString server, QString count ); - QString ThereAreNoBannedUsers( QString server ); - QString ThereIsBannedUser( QString server ); - QString ThereAreBannedUsers( QString server, QString count ); + QString UserIsAlreadyBanned( const QString &server, const QString &victim ); + QString BannedUser( const QString &server, const QString &victim ); + QString ErrorBanningUser( const QString &server, const QString &victim ); + QString UserIsAnAdmin( const QString &server, const QString &user ); + QString UserIsNotAnAdmin( const QString &server, const QString &user ); + QString UserWasBannedOnByBecause( const QString &server, const QString &victim, const QString &date, const QString &admin, const QString &reason ); + QString UserIsNotBanned( const QString &server, const QString &victim ); + QString ThereAreNoAdmins( const QString &server ); + QString ThereIsAdmin( const QString &server ); + QString ThereAreAdmins( const QString &server, const QString &count ); + QString ThereAreNoBannedUsers( const QString &server ); + QString ThereIsBannedUser( const QString &server ); + QString ThereAreBannedUsers( const QString &server, const QString &count ); QString YouCantDeleteTheRootAdmin( ); - QString DeletedUserFromAdminDatabase( QString server, QString user ); - QString ErrorDeletingUserFromAdminDatabase( QString server, QString user ); - QString UnbannedUser( QString victim ); - QString ErrorUnbanningUser( QString victim ); - QString GameNumberIs( QString number, QString description ); - QString GameNumberDoesntExist( QString number ); - QString GameIsInTheLobby( QString description, QString current, QString max ); - QString ThereIsNoGameInTheLobby( QString current, QString max ); + QString DeletedUserFromAdminDatabase( const QString &server, const QString &user ); + QString ErrorDeletingUserFromAdminDatabase( const QString &server, const QString &user ); + QString UnbannedUser( const QString &victim ); + QString ErrorUnbanningUser( const QString &victim ); + QString GameNumberIs( const QString &number, const QString &description ); + QString GameNumberDoesntExist( const QString &number ); + QString GameIsInTheLobby( const QString &description, const QString ¤t, const QString &max ); + QString ThereIsNoGameInTheLobby( const QString ¤t, const QString &max ); QString UnableToLoadConfigFilesOutside( ); - QString LoadingConfigFile( QString file ); - QString UnableToLoadConfigFileDoesntExist( QString file ); - QString CreatingPrivateGame( QString gamename, QString user ); - QString CreatingPublicGame( QString gamename, QString user ); - QString UnableToUnhostGameCountdownStarted( QString description ); - QString UnhostingGame( QString description ); + QString LoadingConfigFile( const QString &file ); + QString UnableToLoadConfigFileDoesntExist( const QString &file ); + QString CreatingPrivateGame( const QString &gamename, const QString &user ); + QString CreatingPublicGame( const QString &gamename, const QString &user ); + QString UnableToUnhostGameCountdownStarted( const QString &description ); + QString UnhostingGame( const QString &description ); QString UnableToUnhostGameNoGameInLobby( ); - QString VersionAdmin( QString version ); - QString VersionNotAdmin( QString version ); - QString UnableToCreateGameAnotherGameInLobby( QString gamename, QString description ); - QString UnableToCreateGameMaxGamesReached( QString gamename, QString max ); - QString GameIsOver( QString description ); + QString VersionAdmin( const QString &version ); + QString VersionNotAdmin( const QString &version ); + QString UnableToCreateGameAnotherGameInLobby( const QString &gamename, const QString &description ); + QString UnableToCreateGameMaxGamesReached( const QString &gamename, const QString &max ); + QString GameIsOver( const QString &description ); QString SpoofCheckByReplying( ); QString GameRefreshed( ); - QString SpoofPossibleIsAway( QString user ); - QString SpoofPossibleIsUnavailable( QString user ); - QString SpoofPossibleIsRefusingMessages( QString user ); - QString SpoofDetectedIsNotInGame( QString user ); - QString SpoofDetectedIsInPrivateChannel( QString user ); - QString SpoofDetectedIsInAnotherGame( QString user ); + QString SpoofPossibleIsAway( const QString &user ); + QString SpoofPossibleIsUnavailable( const QString &user ); + QString SpoofPossibleIsRefusingMessages( const QString &user ); + QString SpoofDetectedIsNotInGame( const QString &user ); + QString SpoofDetectedIsInPrivateChannel( const QString &user ); + QString SpoofDetectedIsInAnotherGame( const QString &user ); QString CountDownAborted( ); - QString TryingToJoinTheGameButBanned( QString victim ); - QString UnableToBanNoMatchesFound( QString victim ); - QString PlayerWasBannedByPlayer( QString server, QString victim, QString user ); - QString UnableToBanFoundMoreThanOneMatch( QString victim ); - QString AddedPlayerToTheHoldList( QString user ); - QString UnableToKickNoMatchesFound( QString victim ); - QString UnableToKickFoundMoreThanOneMatch( QString victim ); - QString SettingLatencyToMinimum( QString min ); - QString SettingLatencyToMaximum( QString max ); - QString SettingLatencyTo( QString latency ); - QString KickingPlayersWithPingsGreaterThan( QString total, QString ping ); - QString HasPlayedGamesWithThisBot( QString user, QString firstgame, QString lastgame, QString totalgames, QString avgloadingtime, QString avgstay ); - QString HasntPlayedGamesWithThisBot( QString user ); - QString AutokickingPlayerForExcessivePing( QString victim, QString ping ); - QString SpoofCheckAcceptedFor( QString server, QString user ); - QString PlayersNotYetSpoofChecked( QString notspoofchecked ); - QString ManuallySpoofCheckByWhispering( QString hostname ); - QString SpoofCheckByWhispering( QString hostname ); + QString TryingToJoinTheGameButBanned( const QString &victim ); + QString UnableToBanNoMatchesFound( const QString &victim ); + QString PlayerWasBannedByPlayer( const QString &server, const QString &victim, const QString &user ); + QString UnableToBanFoundMoreThanOneMatch( const QString &victim ); + QString AddedPlayerToTheHoldList( const QString &user ); + QString UnableToKickNoMatchesFound( const QString &victim ); + QString UnableToKickFoundMoreThanOneMatch( const QString &victim ); + QString SettingLatencyToMinimum( const QString &min ); + QString SettingLatencyToMaximum( const QString &max ); + QString SettingLatencyTo( const QString &latency ); + QString KickingPlayersWithPingsGreaterThan( const QString &total, const QString &ping ); + QString HasPlayedGamesWithThisBot( const QString &user, const QString &firstgame, const QString &lastgame, const QString &totalgames, const QString &avgloadingtime, const QString &avgstay ); + QString HasntPlayedGamesWithThisBot( const QString &user ); + QString AutokickingPlayerForExcessivePing( const QString &victim, const QString &ping ); + QString SpoofCheckAcceptedFor( const QString &server, const QString &user ); + QString PlayersNotYetSpoofChecked( const QString ¬spoofchecked ); + QString ManuallySpoofCheckByWhispering( const QString &hostname ); + QString SpoofCheckByWhispering( const QString &hostname ); QString EveryoneHasBeenSpoofChecked( ); - QString PlayersNotYetPinged( QString notpinged ); + QString PlayersNotYetPinged( const QString ¬pinged ); QString EveryoneHasBeenPinged( ); - QString ShortestLoadByPlayer( QString user, QString loadingtime ); - QString LongestLoadByPlayer( QString user, QString loadingtime ); - QString YourLoadingTimeWas( QString loadingtime ); - QString HasPlayedDotAGamesWithThisBot( QString user, QString totalgames, QString totalwins, QString totallosses, QString totalkills, QString totaldeaths, QString totalcreepkills, QString totalcreepdenies, QString totalassists, QString totalneutralkills, QString totaltowerkills, QString totalraxkills, QString totalcourierkills, QString avgkills, QString avgdeaths, QString avgcreepkills, QString avgcreepdenies, QString avgassists, QString avgneutralkills, QString avgtowerkills, QString avgraxkills, QString avgcourierkills ); - QString HasntPlayedDotAGamesWithThisBot( QString user ); - QString WasKickedForReservedPlayer( QString reserved ); - QString WasKickedForOwnerPlayer( QString owner ); - QString WasKickedByPlayer( QString user ); - QString HasLostConnectionPlayerError( QString error ); - QString HasLostConnectionSocketError( QString error ); + QString ShortestLoadByPlayer( const QString &user, const QString &loadingtime ); + QString LongestLoadByPlayer( const QString &user, const QString &loadingtime ); + QString YourLoadingTimeWas( const QString &loadingtime ); + QString HasPlayedDotAGamesWithThisBot( const QString &user, const QString &totalgames, const QString &totalwins, const QString &totallosses, const QString &totalkills, const QString &totaldeaths, const QString &totalcreepkills, const QString &totalcreepdenies, const QString &totalassists, const QString &totalneutralkills, const QString &totaltowerkills, const QString &totalraxkills, const QString &totalcourierkills, const QString &avgkills, const QString &avgdeaths, const QString &avgcreepkills, const QString &avgcreepdenies, const QString &avgassists, const QString &avgneutralkills, const QString &avgtowerkills, const QString &avgraxkills, const QString &avgcourierkills ); + QString HasntPlayedDotAGamesWithThisBot( const QString &user ); + QString WasKickedForReservedPlayer( const QString &reserved ); + QString WasKickedForOwnerPlayer( const QString &owner ); + QString WasKickedByPlayer( const QString &user ); + QString HasLostConnectionPlayerError( const QString &error ); + QString HasLostConnectionSocketError( const QString &error ); QString HasLostConnectionClosedByRemoteHost( ); QString HasLeftVoluntarily( ); - QString EndingGame( QString description ); + QString EndingGame( const QString &description ); QString HasLostConnectionTimedOut( ); QString GlobalChatMuted( ); QString GlobalChatUnmuted( ); QString ShufflingPlayers( ); QString UnableToLoadConfigFileGameInLobby( ); - QString PlayersStillDownloading( QString stilldownloading ); + QString PlayersStillDownloading( const QString &stilldownloading ); QString RefreshMessagesEnabled( ); QString RefreshMessagesDisabled( ); QString AtLeastOneGameActiveUseForceToShutdown( ); - QString CurrentlyLoadedMapCFGIs( QString mapcfg ); + QString CurrentlyLoadedMapCFGIs( const QString &mapcfg ); QString LaggedOutDroppedByAdmin( ); QString LaggedOutDroppedByVote( ); - QString PlayerVotedToDropLaggers( QString user ); - QString LatencyIs( QString latency ); - QString SyncLimitIs( QString synclimit ); - QString SettingSyncLimitToMinimum( QString min ); - QString SettingSyncLimitToMaximum( QString max ); - QString SettingSyncLimitTo( QString synclimit ); - QString UnableToCreateGameNotLoggedIn( QString gamename ); + QString PlayerVotedToDropLaggers( const QString &user ); + QString LatencyIs( const QString &latency ); + QString SyncLimitIs( const QString &synclimit ); + QString SettingSyncLimitToMinimum( const QString &min ); + QString SettingSyncLimitToMaximum( const QString &max ); + QString SettingSyncLimitTo( const QString &synclimit ); + QString UnableToCreateGameNotLoggedIn( const QString &gamename ); QString AdminLoggedIn( ); - QString AdminInvalidPassword( QString attempt ); - QString ConnectingToBNET( QString server ); - QString ConnectedToBNET( QString server ); - QString DisconnectedFromBNET( QString server ); - QString LoggedInToBNET( QString server ); - QString BNETGameHostingSucceeded( QString server ); - QString BNETGameHostingFailed( QString server, QString gamename ); - QString ConnectingToBNETTimedOut( QString server ); - QString PlayerDownloadedTheMap( QString user, QString seconds, QString rate ); - QString UnableToCreateGameNameTooLong( QString gamename ); - QString SettingGameOwnerTo( QString owner ); + QString AdminInvalidPassword( const QString &attempt ); + QString ConnectingToBNET( const QString &server ); + QString ConnectedToBNET( const QString &server ); + QString DisconnectedFromBNET( const QString &server ); + QString LoggedInToBNET( const QString &server ); + QString BNETGameHostingSucceeded( const QString &server ); + QString BNETGameHostingFailed( const QString &server, const QString &gamename ); + QString ConnectingToBNETTimedOut( const QString &server ); + QString PlayerDownloadedTheMap( const QString &user, const QString &seconds, const QString &rate ); + QString UnableToCreateGameNameTooLong( const QString &gamename ); + QString SettingGameOwnerTo( const QString &owner ); QString TheGameIsLocked( ); QString GameLocked( ); QString GameUnlocked( ); - QString UnableToStartDownloadNoMatchesFound( QString victim ); - QString UnableToStartDownloadFoundMoreThanOneMatch( QString victim ); - QString UnableToSetGameOwner( QString owner ); - QString UnableToCheckPlayerNoMatchesFound( QString victim ); - QString CheckedPlayer( QString victim, QString ping, QString from, QString admin, QString owner, QString spoofed, QString spoofedrealm, QString reserved ); - QString UnableToCheckPlayerFoundMoreThanOneMatch( QString victim ); + QString UnableToStartDownloadNoMatchesFound( const QString &victim ); + QString UnableToStartDownloadFoundMoreThanOneMatch( const QString &victim ); + QString UnableToSetGameOwner( const QString &owner ); + QString UnableToCheckPlayerNoMatchesFound( const QString &victim ); + QString CheckedPlayer( const QString &victim, const QString &ping, const QString &from, const QString &admin, const QString &owner, const QString &spoofed, const QString &spoofedrealm, const QString &reserved ); + QString UnableToCheckPlayerFoundMoreThanOneMatch( const QString &victim ); QString TheGameIsLockedBNET( ); - QString UnableToCreateGameDisabled( QString gamename ); + QString UnableToCreateGameDisabled( const QString &gamename ); QString BotDisabled( ); QString BotEnabled( ); - QString UnableToCreateGameInvalidMap( QString gamename ); - QString WaitingForPlayersBeforeAutoStart( QString players, QString playersleft ); + QString UnableToCreateGameInvalidMap( const QString &gamename ); + QString WaitingForPlayersBeforeAutoStart( const QString &players, const QString &playersleft ); QString AutoStartDisabled( ); - QString AutoStartEnabled( QString players ); + QString AutoStartEnabled( const QString &players ); QString AnnounceMessageEnabled( ); QString AnnounceMessageDisabled( ); QString AutoHostEnabled( ); QString AutoHostDisabled( ); QString UnableToLoadSaveGamesOutside( ); QString UnableToLoadSaveGameGameInLobby( ); - QString LoadingSaveGame( QString file ); - QString UnableToLoadSaveGameDoesntExist( QString file ); - QString UnableToCreateGameInvalidSaveGame( QString gamename ); - QString UnableToCreateGameSaveGameMapMismatch( QString gamename ); + QString LoadingSaveGame( const QString &file ); + QString UnableToLoadSaveGameDoesntExist( const QString &file ); + QString UnableToCreateGameInvalidSaveGame( const QString &gamename ); + QString UnableToCreateGameSaveGameMapMismatch( const QString &gamename ); QString AutoSaveEnabled( ); QString AutoSaveDisabled( ); QString DesyncDetected( ); - QString UnableToMuteNoMatchesFound( QString victim ); - QString MutedPlayer( QString victim, QString user ); - QString UnmutedPlayer( QString victim, QString user ); - QString UnableToMuteFoundMoreThanOneMatch( QString victim ); - QString PlayerIsSavingTheGame( QString player ); + QString UnableToMuteNoMatchesFound( const QString &victim ); + QString MutedPlayer( const QString &victim, const QString &user ); + QString UnmutedPlayer( const QString &victim, const QString &user ); + QString UnableToMuteFoundMoreThanOneMatch( const QString &victim ); + QString PlayerIsSavingTheGame( const QString &player ); QString UpdatingClanList( ); QString UpdatingFriendsList( ); - QString MultipleIPAddressUsageDetected( QString player, QString others ); + QString MultipleIPAddressUsageDetected( const QString &player, const QString &others ); QString UnableToVoteKickAlreadyInProgress( ); QString UnableToVoteKickNotEnoughPlayers( ); - QString UnableToVoteKickNoMatchesFound( QString victim ); - QString UnableToVoteKickPlayerIsReserved( QString victim ); - QString StartedVoteKick( QString victim, QString user, QString votesneeded ); - QString UnableToVoteKickFoundMoreThanOneMatch( QString victim ); - QString VoteKickPassed( QString victim ); - QString ErrorVoteKickingPlayer( QString victim ); - QString VoteKickAcceptedNeedMoreVotes( QString victim, QString user, QString votes ); - QString VoteKickCancelled( QString victim ); - QString VoteKickExpired( QString victim ); + QString UnableToVoteKickNoMatchesFound( const QString &victim ); + QString UnableToVoteKickPlayerIsReserved( const QString &victim ); + QString StartedVoteKick( const QString &victim, const QString &user, const QString &votesneeded ); + QString UnableToVoteKickFoundMoreThanOneMatch( const QString &victim ); + QString VoteKickPassed( const QString &victim ); + QString ErrorVoteKickingPlayer( const QString &victim ); + QString VoteKickAcceptedNeedMoreVotes( const QString &victim, const QString &user, const QString &votes ); + QString VoteKickCancelled( const QString &victim ); + QString VoteKickExpired( const QString &victim ); QString WasKickedByVote( ); - QString TypeYesToVote( QString commandtrigger ); - QString PlayersNotYetPingedAutoStart( QString notpinged ); + QString TypeYesToVote( const QString &commandtrigger ); + QString PlayersNotYetPingedAutoStart( const QString ¬pinged ); QString WasKickedForNotSpoofChecking( ); - QString WasKickedForHavingFurthestScore( QString score, QString average ); - QString PlayerHasScore( QString player, QString score ); - QString RatedPlayersSpread( QString rated, QString total, QString spread ); + QString WasKickedForHavingFurthestScore( const QString &score, const QString &average ); + QString PlayerHasScore( const QString &player, const QString &score ); + QString RatedPlayersSpread( const QString &rated, const QString &total, const QString &spread ); QString ErrorListingMaps( ); - QString FoundMaps( QString maps ); + QString FoundMaps( const QString &maps ); QString NoMapsFound( ); QString ErrorListingMapConfigs( ); - QString FoundMapConfigs( QString mapconfigs ); + QString FoundMapConfigs( const QString &mapconfigs ); QString NoMapConfigsFound( ); - QString PlayerFinishedLoading( QString user ); + QString PlayerFinishedLoading( const QString &user ); QString PleaseWaitPlayersStillLoading( ); QString MapDownloadsDisabled( ); QString MapDownloadsEnabled( ); QString MapDownloadsConditional( ); - QString SettingHCL( QString HCL ); + QString SettingHCL( const QString &HCL ); QString UnableToSetHCLInvalid( ); QString UnableToSetHCLTooLong( ); - QString TheHCLIs( QString HCL ); + QString TheHCLIs( const QString &HCL ); QString TheHCLIsTooLongUseForceToStart( ); QString ClearingHCL( ); - QString TryingToRehostAsPrivateGame( QString gamename ); - QString TryingToRehostAsPublicGame( QString gamename ); + QString TryingToRehostAsPrivateGame( const QString &gamename ); + QString TryingToRehostAsPublicGame( const QString &gamename ); QString RehostWasSuccessful( ); - QString TryingToJoinTheGameButBannedByName( QString victim ); - QString TryingToJoinTheGameButBannedByIP( QString victim, QString ip, QString bannedname ); - QString HasBannedName( QString victim ); - QString HasBannedIP( QString victim, QString ip, QString bannedname ); - QString PlayersInGameState( QString number, QString players ); - QString ValidServers( QString servers ); - QString TeamCombinedScore( QString team, QString score ); + QString TryingToJoinTheGameButBannedByName( const QString &victim ); + QString TryingToJoinTheGameButBannedByIP( const QString &victim, const QString &ip, const QString &bannedname ); + QString HasBannedName( const QString &victim ); + QString HasBannedIP( const QString &victim, const QString &ip, const QString &bannedname ); + QString PlayersInGameState( const QString &number, const QString &players ); + QString ValidServers( const QString &servers ); + QString TeamCombinedScore( const QString &team, const QString &score ); QString BalancingSlotsCompleted( ); - QString PlayerWasKickedForFurthestScore( QString name, QString score, QString average ); + QString PlayerWasKickedForFurthestScore( const QString &name, const QString &score, const QString &average ); QString LocalAdminMessagesEnabled( ); QString LocalAdminMessagesDisabled( ); QString WasDroppedDesync( ); - QString WasKickedForHavingLowestScore( QString score ); - QString PlayerWasKickedForLowestScore( QString name, QString score ); + QString WasKickedForHavingLowestScore( const QString &score ); + QString PlayerWasKickedForLowestScore( const QString &name, const QString &score ); QString ReloadingConfigurationFiles( ); QString CountDownAbortedSomeoneLeftRecently( ); - QString UnableToCreateGameMustEnforceFirst( QString gamename ); + QString UnableToCreateGameMustEnforceFirst( const QString &gamename ); QString UnableToLoadReplaysOutside( ); - QString LoadingReplay( QString file ); - QString UnableToLoadReplayDoesntExist( QString file ); - QString CommandTrigger( QString trigger ); - QString CantEndGameOwnerIsStillPlaying( QString owner ); - QString CantUnhostGameOwnerIsPresent( QString owner ); - QString WasAutomaticallyDroppedAfterSeconds( QString seconds ); + QString LoadingReplay( const QString &file ); + QString UnableToLoadReplayDoesntExist( const QString &file ); + QString CommandTrigger( const QString &trigger ); + QString CantEndGameOwnerIsStillPlaying( const QString &owner ); + QString CantUnhostGameOwnerIsPresent( const QString &owner ); + QString WasAutomaticallyDroppedAfterSeconds( const QString &seconds ); QString HasLostConnectionTimedOutGProxy( ); - QString HasLostConnectionSocketErrorGProxy( QString error ); + QString HasLostConnectionSocketErrorGProxy( const QString &error ); QString HasLostConnectionClosedByRemoteHostGProxy( ); - QString WaitForReconnectSecondsRemain( QString seconds ); + QString WaitForReconnectSecondsRemain( const QString &seconds ); QString WasUnrecoverablyDroppedFromGProxy( ); - QString PlayerReconnectedWithGProxy( QString name ); + QString PlayerReconnectedWithGProxy( const QString &name ); }; #endif From bfd0f981cfd3e158a0cd51917eb248d986f24146 Mon Sep 17 00:00:00 2001 From: luqasn Date: Sat, 8 May 2010 19:10:54 +0000 Subject: [PATCH 59/69] ghost.qt: removed unnecessary line in makefile (generated a warning) added local directory to library search path --- ghost/ghost.pro | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ghost/ghost.pro b/ghost/ghost.pro index fba544f..412e934 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -53,7 +53,7 @@ LIBS += -L../bncsutil/src/bncsutil \ -lbncsutil macx { LIBS += -framework CoreFoundation -framework CoreServices - LIBS += -L/usr/lib -lbz2 -lz + LIBS += -L. -L/usr/lib -lbz2 -lz } HEADERS += util.h \ @@ -90,6 +90,5 @@ HEADERS += util.h \ bnetprotocol.h \ bnet.h \ bncsutilinterface.h \ - mpgarchive.h \ mpqarchive.h \ mpqfile.h From 772147791027bee9e1c681d18c5fde64d8e348dd Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sun, 9 May 2010 01:22:05 +0000 Subject: [PATCH 60/69] --- StormLib/stormlib/Makefile | 201 +++++++++++++++++++++++++------------ 1 file changed, 136 insertions(+), 65 deletions(-) diff --git a/StormLib/stormlib/Makefile b/StormLib/stormlib/Makefile index 6c49337..92b79a2 100644 --- a/StormLib/stormlib/Makefile +++ b/StormLib/stormlib/Makefile @@ -1,73 +1,144 @@ -##################################################################### -### -# -# Makefile for compiling StormLib under linux -# -# Author: Marko Friedemann -# Created at: Mon Jan 29 18:26:01 CEST 2001 -# Computer: whiplash.flachland-chemnitz.de -# System: Linux 2.4.0 on i686 -# -# Copyright (c) 2001 BMX-Chemnitz.DE All rights reserved. -# -##################################################################### -### +############################################################################# +# Makefile for building: stormlib +# Generated by qmake (2.01a) (Qt 4.6.2) on: So 25. Apr 16:11:54 2010 +# Project: stormlib.pro +# Template: lib +# Command: c:\qt\2010.02.1\qt\bin\qmake.exe -spec c:\Qt\2010.02.1\qt\mkspecs\win32-g++ -win32 -o Makefile stormlib.pro +############################################################################# -############################################## -# updated on October 6, 2008 by Trevor Hogan # -############################################## +first: debug +install: debug-install +uninstall: debug-uninstall +MAKEFILE = Makefile +QMAKE = c:\qt\2010.02.1\qt\bin\qmake.exe +DEL_FILE = del +CHK_DIR_EXISTS= if not exist +MKDIR = mkdir +COPY = copy /y +COPY_FILE = $(COPY) +COPY_DIR = xcopy /s /q /y /i +INSTALL_FILE = $(COPY_FILE) +INSTALL_PROGRAM = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = del +SYMLINK = +DEL_DIR = rmdir +MOVE = move +CHK_DIR_EXISTS= if not exist +MKDIR = mkdir +SUBTARGETS = \ + debug \ + release -SHELL = /bin/sh -SYSTEM = $(shell uname) -C++ = g++ -CC = gcc -DFLAGS = -D__SYS_ZLIB -OFLAGS = -LFLAGS = -lbz2 -lz -CFLAGS = -fPIC -CFLAGS += $(OFLAGS) $(DFLAGS) +debug: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_default: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_first: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug first +debug-all: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug all +debug-clean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug clean +debug-distclean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug distclean +debug-install: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug install +debug-uninstall: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug uninstall +release: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_default: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_first: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release first +release-all: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release all +release-clean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release clean +release-distclean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release distclean +release-install: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release install +release-uninstall: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release uninstall -OBJS = SCommon.o SCompression.o SFileCompactArchive.o \ - SFileCreateArchiveEx.o SFileExtractFile.o SFileFindFile.o \ - SListFile.o SFileOpenArchive.o SFileOpenFileEx.o \ - SAttrFile.o SFileReadFile.o \ - wave/wave.o \ - huffman/huff.o \ - misc/crc32.o misc/md5.o +Makefile: stormlib.pro c:/Qt/2010.02.1/qt/mkspecs/win32-g++/qmake.conf c:/Qt/2010.02.1/qt/mkspecs/qconfig.pri \ + c:/Qt/2010.02.1/qt/mkspecs/features/qt_functions.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/qt_config.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/exclusive_builds.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/default_pre.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/default_pre.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/debug.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/debug_and_release.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/default_post.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/default_post.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/rtti.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/exceptions.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/stl.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/shared.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/dll.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/warn_on.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/qt.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/thread.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/moc.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/win32/windows.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/resources.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/uic.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/yacc.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/lex.prf \ + c:/Qt/2010.02.1/qt/mkspecs/features/include_source_dir.prf + $(QMAKE) -spec c:\Qt\2010.02.1\qt\mkspecs\win32-g++ -win32 -o Makefile stormlib.pro +c:\Qt\2010.02.1\qt\mkspecs\qconfig.pri: +c:\Qt\2010.02.1\qt\mkspecs\features\qt_functions.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\qt_config.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\exclusive_builds.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\default_pre.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\default_pre.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\debug.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\debug_and_release.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\default_post.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\default_post.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\rtti.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\exceptions.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\stl.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\shared.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\dll.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\warn_on.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\qt.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\thread.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\moc.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\win32\windows.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\resources.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\uic.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\yacc.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\lex.prf: +c:\Qt\2010.02.1\qt\mkspecs\features\include_source_dir.prf: +qmake: qmake_all FORCE + @$(QMAKE) -spec c:\Qt\2010.02.1\qt\mkspecs\win32-g++ -win32 -o Makefile stormlib.pro -COBJS = pklib/crc32.o pklib/explode.o pklib/implode.o +qmake_all: FORCE -ifeq ($(SYSTEM),Darwin) -OBJS += StormPortMac.o -LFLAGS += -dynamiclib -framework CoreServices -LIB = libStorm.dylib -else -OBJS += StormPortLinux.o -LFLAGS += -shared -LIB = libStorm.so -endif +make_default: debug-make_default release-make_default FORCE +make_first: debug-make_first release-make_first FORCE +all: debug-all release-all FORCE +clean: debug-clean release-clean FORCE + -$(DEL_FILE) libstormlib.a +distclean: debug-distclean release-distclean FORCE + -$(DEL_FILE) Makefile -all: $(OBJS) $(COBJS) $(LIB) +debug-mocclean: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocclean +release-mocclean: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocclean +mocclean: debug-mocclean release-mocclean -$(LIB): $(OBJS) $(COBJS) - $(C++) -o $(LIB) $(OBJS) $(COBJS) $(LFLAGS) +debug-mocables: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocables +release-mocables: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocables +mocables: debug-mocables release-mocables +FORCE: -clean: - rm -f $(OBJS) $(COBJS) $(LIB) - -$(OBJS): %.o: %.cpp - $(C++) -o $@ $(CFLAGS) -c $< - -$(COBJS): %.o: %.c - $(CC) -o $@ $(CFLAGS) -c $< - -$(LIB): $(OBJS) $(COBJS) - -all: $(LIB) - -install: $(LIB) - install $(LIB) /usr/local/lib - mkdir -p /usr/local/include/StormLib - cp StormLib.h /usr/local/include/StormLib - cp StormPort.h /usr/local/include/StormLib - ldconfig +$(MAKEFILE).Debug: Makefile +$(MAKEFILE).Release: Makefile From 9cab2e31ed6b3a5292eff6c0bbeb2f5e300a5638 Mon Sep 17 00:00:00 2001 From: "emmeran@gmx.net" Date: Sun, 9 May 2010 01:23:21 +0000 Subject: [PATCH 61/69] fixed build issues --- ghost/ghostdb.cpp | 4 ++-- ghost/ghostdb.h | 8 ++++---- ghost/ghostdbsqlite.cpp | 6 +++--- ghost/ghostdbsqlite.h | 4 ++-- ghost/statsw3mmd.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ghost/ghostdb.cpp b/ghost/ghostdb.cpp index 7ffd2d8..95b1dc5 100644 --- a/ghost/ghostdb.cpp +++ b/ghost/ghostdb.cpp @@ -176,7 +176,7 @@ quint32 CGHostDB :: W3MMDPlayerAdd( QString /*category*/, quint32 /*gameid*/, qu return 0; } -bool CGHostDB :: W3MMDVarAdd( quint32 /*gameid*/, QMap /*var_ints*/ ) +bool CGHostDB :: W3MMDVarAdd( quint32 /*gameid*/, QMap /*var_ints*/ ) { return false; } @@ -296,7 +296,7 @@ CCallableW3MMDPlayerAdd *CGHostDB :: ThreadedW3MMDPlayerAdd( QString /*category* return NULL; } -CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_ints*/ ) +CCallableW3MMDVarAdd *CGHostDB :: ThreadedW3MMDVarAdd( quint32 /*gameid*/, QMap /*var_ints*/ ) { return NULL; } diff --git a/ghost/ghostdb.h b/ghost/ghostdb.h index b27cc5e..ed328d8 100644 --- a/ghost/ghostdb.h +++ b/ghost/ghostdb.h @@ -110,7 +110,7 @@ class CGHostDB : public QObject virtual bool FromAdd( quint32 ip1, quint32 ip2, QString country ); virtual bool DownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); virtual quint32 W3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); - virtual bool W3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_ints ); virtual bool W3MMDVarAdd( quint32 gameid, QMap var_reals ); virtual bool W3MMDVarAdd( quint32 gameid, QMap var_strings ); @@ -137,7 +137,7 @@ class CGHostDB : public QObject virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); virtual CCallableScoreCheck *ThreadedScoreCheck( QString category, QString name, QString server ); virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); }; @@ -551,7 +551,7 @@ class CCallableW3MMDVarAdd : public CBaseCallable { protected: quint32 m_GameID; - QMap m_VarInts; + QMap m_VarInts; QMap m_VarReals; QMap m_VarStrings; @@ -565,7 +565,7 @@ class CCallableW3MMDVarAdd : public CBaseCallable bool m_Result; public: - CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } + CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarInts ) : CBaseCallable( ), m_GameID( nGameID ), m_VarInts( nVarInts ), m_ValueType( VALUETYPE_INT ), m_Result( false ) { } CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarReals ) : CBaseCallable( ), m_GameID( nGameID ), m_VarReals( nVarReals ), m_ValueType( VALUETYPE_REAL ), m_Result( false ) { } CCallableW3MMDVarAdd( quint32 nGameID, QMap nVarStrings ) : CBaseCallable( ), m_GameID( nGameID ), m_VarStrings( nVarStrings ), m_ValueType( VALUETYPE_STRING ), m_Result( false ) { } virtual ~CCallableW3MMDVarAdd( ); diff --git a/ghost/ghostdbsqlite.cpp b/ghost/ghostdbsqlite.cpp index a1d3a85..2c15190 100644 --- a/ghost/ghostdbsqlite.cpp +++ b/ghost/ghostdbsqlite.cpp @@ -1335,7 +1335,7 @@ quint32 CGHostDBSQLite :: W3MMDPlayerAdd( QString category, quint32 gameid, quin return RowID; } -bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints ) +bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints ) { if( var_ints.isEmpty( ) ) return false; @@ -1343,7 +1343,7 @@ bool CGHostDBSQLite :: W3MMDVarAdd( quint32 gameid, QMap var_ints bool Success = true; sqlite3_stmt *Statement = NULL; - for( QMap :: const_iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) + for( QMap :: const_iterator i = var_ints.begin( ); i != var_ints.end( ); i++ ) { if( !Statement ) m_DB->Prepare( "INSERT INTO w3mmdvars ( gameid, pid, varname, value_int ) VALUES ( ?, ?, ?, ? )", (void **)&Statement ); @@ -1622,7 +1622,7 @@ CCallableW3MMDPlayerAdd *CGHostDBSQLite :: ThreadedW3MMDPlayerAdd( QString categ return Callable; } -CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ) +CCallableW3MMDVarAdd *CGHostDBSQLite :: ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ) { CCallableW3MMDVarAdd *Callable = new CCallableW3MMDVarAdd( gameid, var_ints ); Callable->SetResult( W3MMDVarAdd( gameid, var_ints ) ); diff --git a/ghost/ghostdbsqlite.h b/ghost/ghostdbsqlite.h index 4d1f3e9..ecf2bf1 100644 --- a/ghost/ghostdbsqlite.h +++ b/ghost/ghostdbsqlite.h @@ -237,7 +237,7 @@ class CGHostDBSQLite : public CGHostDB virtual bool FromAdd( quint32 ip1, quint32 ip2, QString country ); virtual bool DownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); virtual quint32 W3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); - virtual bool W3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual bool W3MMDVarAdd( quint32 gameid, QMap var_ints ); virtual bool W3MMDVarAdd( quint32 gameid, QMap var_reals ); virtual bool W3MMDVarAdd( quint32 gameid, QMap var_strings ); @@ -264,7 +264,7 @@ class CGHostDBSQLite : public CGHostDB virtual CCallableDotAPlayerSummaryCheck *ThreadedDotAPlayerSummaryCheck( QString name ); virtual CCallableDownloadAdd *ThreadedDownloadAdd( QString map, quint32 mapsize, QString name, QString ip, quint32 spoofed, QString spoofedrealm, quint32 downloadtime ); virtual CCallableW3MMDPlayerAdd *ThreadedW3MMDPlayerAdd( QString category, quint32 gameid, quint32 pid, QString name, QString flag, quint32 leaver, quint32 practicing ); - virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); + virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_ints ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_reals ); virtual CCallableW3MMDVarAdd *ThreadedW3MMDVarAdd( quint32 gameid, QMap var_strings ); }; diff --git a/ghost/statsw3mmd.h b/ghost/statsw3mmd.h index 02154ee..2cfb8a8 100644 --- a/ghost/statsw3mmd.h +++ b/ghost/statsw3mmd.h @@ -39,7 +39,7 @@ class CStatsW3MMD : public CStats QMap m_FlagsLeaver; // pid -> leaver flag (e.g. 0 -> true) --- note: will only be present if true QMap m_FlagsPracticing; // pid -> practice flag (e.g. 0 -> true) --- note: will only be present if true QMap m_DefVarPs; // varname -> value type (e.g. "kills" -> "int") - QMap m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) + QMap m_VarPInts; // pid,varname -> value (e.g. 0,"kills" -> 5) QMap m_VarPReals; // pid,varname -> value (e.g. 0,"x" -> 0.8) QMap m_VarPStrings; // pid,varname -> value (e.g. 0,"hero" -> "heroname") QMap > m_DefEvents; // event -> vector of arguments + format From 8472daac05e55849655450fa7daaec520a21f5b1 Mon Sep 17 00:00:00 2001 From: luqasn Date: Sun, 9 May 2010 10:42:42 +0000 Subject: [PATCH 62/69] ghost.qt: partially implemented command plugin (loading works, not used yet & plugin itself does not compile) --- ghost/bnet.cpp | 5 +- ghost/bnet.h | 19 ++++--- ghost/bnlsclient.cpp | 2 + ghost/cmd_builtin/cmd_builtin.pro | 15 ++++++ ghost/cmd_builtin/commands.cpp | 65 ++++++++++++++++++++++ ghost/cmd_builtin/commands.h | 34 ++++++++++++ ghost/cmd_builtin/moc_commands.cpp | 73 +++++++++++++++++++++++++ ghost/game.cpp | 1 + ghost/game_base.cpp | 2 + ghost/game_base.h | 2 +- ghost/gameplayer.cpp | 2 + ghost/ghost.cpp | 55 +++++++++++++++++++ ghost/ghost.h | 19 ++++--- ghost/ghost.pro | 3 +- ghost/interfaces.h | 87 ++++++++++++++++++++++++++++++ ghost/util.cpp | 1 + ghost/util.h | 4 +- 17 files changed, 366 insertions(+), 23 deletions(-) create mode 100755 ghost/cmd_builtin/cmd_builtin.pro create mode 100644 ghost/cmd_builtin/commands.cpp create mode 100644 ghost/cmd_builtin/commands.h create mode 100644 ghost/cmd_builtin/moc_commands.cpp create mode 100644 ghost/interfaces.h diff --git a/ghost/bnet.cpp b/ghost/bnet.cpp index 7db60ad..21e25ac 100644 --- a/ghost/bnet.cpp +++ b/ghost/bnet.cpp @@ -39,6 +39,7 @@ #include #include #include +#include // // CBNET @@ -2306,8 +2307,8 @@ void CBNET :: QueueGameRefresh( unsigned char state, const QString &gameName, co state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), - m_GHost->m_Reconnect ? FakeMapWidth : Util::EmptyData16(), - m_GHost->m_Reconnect ? FakeMapHeight : Util::EmptyData16(), + m_GHost->m_Reconnect ? FakeMapWidth : *Util::EmptyData16(), + m_GHost->m_Reconnect ? FakeMapHeight : *Util::EmptyData16(), gameName, newHostName, upTime, diff --git a/ghost/bnet.h b/ghost/bnet.h index 7d398cd..aab16bf 100644 --- a/ghost/bnet.h +++ b/ghost/bnet.h @@ -21,9 +21,12 @@ #ifndef BNET_H #define BNET_H -// -// CBNET -// +#include "includes.h" +#include +#include +#include + +class QTcpSocket; class CCommandPacket; class CBNCSUtilInterface; @@ -48,11 +51,6 @@ class CSaveGame; class CBaseGame; class CMap; -#include "includes.h" -#include -#include -#include - typedef pair PairedAdminCount; typedef pair PairedAdminAdd; typedef pair PairedAdminRemove; @@ -62,8 +60,9 @@ typedef pair PairedBanRemove; typedef pair PairedGPSCheck; typedef pair PairedDPSCheck; - -#include +// +// CBNET +// class CBNET : public QObject { diff --git a/ghost/bnlsclient.cpp b/ghost/bnlsclient.cpp index 43c2e57..b26d453 100644 --- a/ghost/bnlsclient.cpp +++ b/ghost/bnlsclient.cpp @@ -24,6 +24,8 @@ #include "bnlsprotocol.h" #include "bnlsclient.h" +#include + // // CBNLSClient // diff --git a/ghost/cmd_builtin/cmd_builtin.pro b/ghost/cmd_builtin/cmd_builtin.pro new file mode 100755 index 0000000..2dd420e --- /dev/null +++ b/ghost/cmd_builtin/cmd_builtin.pro @@ -0,0 +1,15 @@ +TEMPLATE = lib +CONFIG += plugin dynamic #release +INCLUDEPATH += .. +HEADERS = commands.h +SOURCES = commands.cpp +TARGET = $$qtLibraryTarget(cmd_builtin) +DESTDIR = ../build/Debug/plugins + +# install +#target.path = $$[QT_INSTALL_EXAMPLES]/tools/plugandpaint/plugins +#sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS basictools.pro +#sources.path = $$[QT_INSTALL_EXAMPLES]/tools/plugandpaintplugins/basictools +#INSTALLS += target sources + +#symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/ghost/cmd_builtin/commands.cpp b/ghost/cmd_builtin/commands.cpp new file mode 100644 index 0000000..b211693 --- /dev/null +++ b/ghost/cmd_builtin/commands.cpp @@ -0,0 +1,65 @@ +/* + * commands.cpp + * ghost + * + * Created by Lucas on 08.05.10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ + +#include "commands.h" +#include "ghost.h" +#include "config.h" +#include "game_base.h" +#include "bnet.h" +#include "language.h" +#include + +QStringList CCommands :: GetCommands() const +{ + QStringList bla; + bla << "bla"; + return bla; +} + +void CCommands :: PluginLoaded( CGHost *ghost, CConfig *cfg ) +{ + m_GHost = ghost; +} + +void CCommands :: OnGameCommand( CGamePlayer *player, const CommandData &data ) +{ + +} + +void CCommands :: OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ) +{ + if( *data.GetCommand() == "close" && !data.GetCommand()->isEmpty( ) && m_GHost->m_CurrentGame ) + { + if( !m_GHost->m_CurrentGame->GetLocked( ) ) + { + // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 + + QTextStream SS; + SS << data.GetPayload(); + + while( !SS.atEnd() ) + { + quint32 SID; + SS >> SID; + + if( SS.status() != QTextStream::Ok ) + { + //CONSOLE_Print( "[BNET: " + bnet->GetServerAlias() + "] bad input to close command" ); + break; + } + else + m_GHost->m_CurrentGame->CloseSlot( (unsigned char)( SID - 1 ), true ); + } + } + else + bnet->QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), user, whisper ); + } +} + +Q_EXPORT_PLUGIN2(cmd_builtin, CCommands) \ No newline at end of file diff --git a/ghost/cmd_builtin/commands.h b/ghost/cmd_builtin/commands.h new file mode 100644 index 0000000..979ba5a --- /dev/null +++ b/ghost/cmd_builtin/commands.h @@ -0,0 +1,34 @@ +/* + * commands.h + * ghost + * + * Created by Lucas on 08.05.10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef COMMANDS_H +#define COMMANDS_H + +#include +#include "interfaces.h" + +class CGHost; +class CommandData; +class CGamePlayer; +class CBNET; + +class CCommands : public QObject, public ICommandProvider +{ + Q_OBJECT + Q_INTERFACES(ICommandProvider) +private: + CGHost *m_GHost; +public: + QStringList GetCommands() const; + void PluginLoaded( CGHost *ghost, CConfig *cfg ); + void OnGameCommand( CGamePlayer *player, const CommandData &data ); + void OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ); +}; + +#endif \ No newline at end of file diff --git a/ghost/cmd_builtin/moc_commands.cpp b/ghost/cmd_builtin/moc_commands.cpp new file mode 100644 index 0000000..e7378cd --- /dev/null +++ b/ghost/cmd_builtin/moc_commands.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'commands.h' +** +** Created: Sun May 9 03:02:38 2010 +** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "commands.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'commands.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.6.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_CCommands[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_CCommands[] = { + "CCommands\0" +}; + +const QMetaObject CCommands::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_CCommands, + qt_meta_data_CCommands, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &CCommands::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *CCommands::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *CCommands::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_CCommands)) + return static_cast(const_cast< CCommands*>(this)); + if (!strcmp(_clname, "ICommandProvider")) + return static_cast< ICommandProvider*>(const_cast< CCommands*>(this)); + if (!strcmp(_clname, "org.GHost.ICommandProvider/1.0")) + return static_cast< ICommandProvider*>(const_cast< CCommands*>(this)); + return QObject::qt_metacast(_clname); +} + +int CCommands::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/ghost/game.cpp b/ghost/game.cpp index 1aa61bd..a0c20bf 100644 --- a/ghost/game.cpp +++ b/ghost/game.cpp @@ -44,6 +44,7 @@ #include #include #include +#include // // sorting classes diff --git a/ghost/game_base.cpp b/ghost/game_base.cpp index 093d632..ec76da0 100644 --- a/ghost/game_base.cpp +++ b/ghost/game_base.cpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include "next_combination.h" diff --git a/ghost/game_base.h b/ghost/game_base.h index c046e71..cf1b2f1 100644 --- a/ghost/game_base.h +++ b/ghost/game_base.h @@ -41,8 +41,8 @@ class CIncomingChatPlayer; class CIncomingMapSize; class CCallableScoreCheck; class CGHost; +QT_FORWARD_DECLARE_CLASS(QTcpServer) -#include #include #include #include diff --git a/ghost/gameplayer.cpp b/ghost/gameplayer.cpp index 9e48404..3820819 100644 --- a/ghost/gameplayer.cpp +++ b/ghost/gameplayer.cpp @@ -33,6 +33,8 @@ // CPotentialPlayer // +#include +#include #include CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket ) diff --git a/ghost/ghost.cpp b/ghost/ghost.cpp index 34a2624..663240b 100644 --- a/ghost/ghost.cpp +++ b/ghost/ghost.cpp @@ -38,6 +38,7 @@ #include "game_base.h" #include "game.h" #include "game_admin.h" +#include "interfaces.h" #include #include @@ -46,6 +47,10 @@ #include #include +#include +#include +#include +#include // @@ -55,6 +60,16 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) : m_ConfigFile(configFile) { + foreach( QObject *plugin, QPluginLoader::staticInstances() ) + { + LoadPlugin( plugin ); + } + QDir pluginsDir = QDir( qApp->applicationDirPath() ); + QString cfgPluginDir = CFG->GetString( "bot_plugindir", "plugins" ); + + pluginsDir.cd( cfgPluginDir ); + LoadPlugins( pluginsDir ); + m_UDPSocket = new QUdpSocket(this); m_UDPSocket->setProperty("target", CFG->GetString( "udp_broadcasttarget", QString( ) ) ); m_UDPSocket->setProperty("dontroute", CFG->GetInt( "udp_dontroute", 0 ) == 0 ? false : true ); @@ -344,6 +359,46 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) } } +void CGHost :: LoadPlugin( QObject *plugin ) +{ + bool validPlugin = false; + + /*IGHostPlugin *iPlugin = qobject_cast( plugin ); + if( !iPlugin ) + { + CONSOLE_Print( "[PLUGIN] ERROR: Plugin does not implement IGHostPlugin" ); + return; + }*/ + + ICommandProvider *iCmd = qobject_cast( plugin ); + if( iCmd ) + { + CONSOLE_Print( "[PLUGIN] Found CommandProvider" ); + validPlugin = true; + m_Commands.append( iCmd ); + } + + if( !validPlugin ) + CONSOLE_Print( "[PLUGIN] WARNING: plugin did not contain valid interfaces!" ); +} + +void CGHost :: LoadPlugins( QDir path ) +{ + CONSOLE_Print( "[PLUGIN] Loading plugins from [" + path.absolutePath() + "]" ); + + foreach( QString fileName, path.entryList( QDir::Files ) ) { + QPluginLoader loader( path.absoluteFilePath( fileName ) ); + QObject *plugin = loader.instance(); + if( plugin ) + { + CONSOLE_Print( "[PLUGIN] Loading plugin [" + fileName + "]" ); + LoadPlugin( plugin ); + } + else + CONSOLE_Print( "[PLUGIN] Ignoring non-plugin file [" + fileName + "]" ); + } +} + void CGHost::EventAdminGameDeleted() { CONSOLE_Print("[GHOST] Admin Game has been deleted, quitting."); diff --git a/ghost/ghost.h b/ghost/ghost.h index 210a224..301fe05 100644 --- a/ghost/ghost.h +++ b/ghost/ghost.h @@ -22,8 +22,10 @@ #define GHOST_H #include "includes.h" -#include -#include + +#include +#include +#include // // CGHost @@ -41,10 +43,10 @@ class CLanguage; class CMap; class CSaveGame; class CConfig; - -#include -#include -#include +class ICommandProvider; +QT_FORWARD_DECLARE_CLASS(QDir) +QT_FORWARD_DECLARE_CLASS(QUdpSocket) +QT_FORWARD_DECLARE_CLASS(QTcpServer) class CGHost : public QObject { @@ -62,7 +64,9 @@ public slots: void EventGameDeleted(); void EventAdminGameDeleted(); void CreateReconnectServer(); - +private: + void LoadPlugin( QObject *plugin ); + void LoadPlugins( QDir path ); public: QTime m_LastAutoHostTime; QTimer m_CallableUpdateTimer, m_AutoHostTimer; @@ -71,6 +75,7 @@ public slots: CGPSProtocol *m_GPSProtocol; CCRC32 *m_CRC; // for calculating CRC's CSHA1 *m_SHA; // for calculating SHA1's + QList m_Commands; // list of plugins providing commands QList m_BNETs; // all our battle.net connections (there can be more than one) CBaseGame *m_CurrentGame; // this game is still in the lobby state CAdminGame *m_AdminGame; // this "fake game" allows an admin who knows the password to control the bot from the local network diff --git a/ghost/ghost.pro b/ghost/ghost.pro index 412e934..52d7e37 100644 --- a/ghost/ghost.pro +++ b/ghost/ghost.pro @@ -56,7 +56,8 @@ macx { LIBS += -L. -L/usr/lib -lbz2 -lz } -HEADERS += util.h \ +HEADERS += interfaces.h \ + util.h \ statsw3mmd.h \ statsdota.h \ stats.h \ diff --git a/ghost/interfaces.h b/ghost/interfaces.h new file mode 100644 index 0000000..6f027e3 --- /dev/null +++ b/ghost/interfaces.h @@ -0,0 +1,87 @@ +/* + + Copyright [2010] [Lucas ROmero] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/ + + */ + +#ifndef INTERFACES_H +#define INTERFACES_H + +#include +#include +#include +#include + +class CBNET; +class CGHost; +class CConfig; +class CGameBase; +class CGamePlayer; +class CCommandPacket; + +/*class IGHostPlugin : public QObject +{ + Q_OBJECT +public: + + //virtual QString GetName() const = 0; + virtual ~IGHostPlugin() {} +};*/ + +class IPacketHandler //: public IGHostPlugin +{ + virtual bool HandlePacket( CCommandPacket* packet, bool wasHandled ) = 0; +}; + +class ICommandProvider //: public IGHostPlugin +{ +protected: + //QHash #include #include +#include const QByteArray Util :: emptyByteArray16( 2, 0 ); const QByteArray Util :: emptyByteArray32( 4, 0 ); diff --git a/ghost/util.h b/ghost/util.h index 0aa0d40..0730209 100644 --- a/ghost/util.h +++ b/ghost/util.h @@ -34,8 +34,8 @@ class Util static QByteArray fromUInt16(const quint16 &value); static QByteArray fromUInt32(const quint32 &value); - static const QByteArray &EmptyData16( ) { return emptyByteArray16; } - static const QByteArray &EmptyData32( ) { return emptyByteArray32; } + static const QByteArray *EmptyData16( ) { return &emptyByteArray16; } + static const QByteArray *EmptyData32( ) { return &emptyByteArray32; } static QByteArray reverse(const QByteArray &b); private: From 07f80eee2ceab75411a477e10e0570ddbf767872 Mon Sep 17 00:00:00 2001 From: luqasn Date: Wed, 19 May 2010 22:09:55 +0000 Subject: [PATCH 63/69] ghost.qt: added basic commandprovider plugin (CGHost still needs better interfaces and instance variables made private) changed filesystem layout split ghost into lib and cli project added *.pro files for subprojects remarks: - as of now only tested on Mac OS - the old VS projects won't work anymore, generate new ones with qmake and delete old ones afterwards - cmd_builtin does not yet really handle any builtin commands, as the implementations of CGHost, CGame and CBNET are not suited for 'external' use yet. --- default.cfg => bin/default.cfg | 0 gameloaded.txt => bin/gameloaded.txt | 0 gameover.txt => bin/gameover.txt | 0 .../ghost dynamic configurator.exe | Bin ip-to-country.csv => bin/ip-to-country.csv | 0 ipblacklist.txt => bin/ipblacklist.txt | 0 language.cfg => bin/language.cfg | 0 .../language_german.cfg | 0 .../language_russian.cfg | 0 .../language_spanish.cfg | 0 .../language_turkish.cfg | 0 bin/license.txt | 13 + {mapcfgs => bin/mapcfgs}/wormwar.cfg | 0 .../mysql_create_tables_v1.sql | 0 .../mysql_create_tables_v2.sql | 0 .../mysql_upgrade_v1-v2.sql | 0 readme.txt => bin/readme.txt | 0 .../update_dota_elo.cfg | 0 .../update_dota_elo.exe | Bin .../update_w3mmd_elo.cfg | 0 .../update_w3mmd_elo.exe | Bin bncsutil/product_version | 1 - bncsutil/vc8_build/BNCSutil.vcproj | 626 -- bncsutil/vc8_build/bncsutil.def | 45 - bncsutil/vc8_build/gmp.lib | Bin 1659142 -> 0 bytes ghost.exe | Bin 1552896 -> 0 bytes ghost.pro | 14 + ghost/cmd_builtin/cmd_builtin.pro | 15 - ghost/cmd_builtin/moc_commands.cpp | 73 - ghost/language.h | 263 - {mysql/include => include}/mysql/config-win.h | 0 {mysql/include => include}/mysql/decimal.h | 0 {mysql/include => include}/mysql/errmsg.h | 0 {mysql/include => include}/mysql/keycache.h | 0 {mysql/include => include}/mysql/libmysql.def | 0 .../include => include}/mysql/libmysqld.def | 0 {mysql/include => include}/mysql/m_ctype.h | 0 {mysql/include => include}/mysql/m_string.h | 0 {mysql/include => include}/mysql/my_alloc.h | 0 .../include => include}/mysql/my_attribute.h | 0 {mysql/include => include}/mysql/my_dbug.h | 0 {mysql/include => include}/mysql/my_dir.h | 0 {mysql/include => include}/mysql/my_getopt.h | 0 {mysql/include => include}/mysql/my_global.h | 0 {mysql/include => include}/mysql/my_list.h | 0 {mysql/include => include}/mysql/my_net.h | 0 .../include => include}/mysql/my_no_pthread.h | 0 {mysql/include => include}/mysql/my_pthread.h | 0 {mysql/include => include}/mysql/my_sys.h | 0 {mysql/include => include}/mysql/my_xml.h | 0 {mysql/include => include}/mysql/mysql.h | 0 .../include => include}/mysql/mysql/plugin.h | 0 {mysql/include => include}/mysql/mysql_com.h | 0 .../include => include}/mysql/mysql_embed.h | 0 {mysql/include => include}/mysql/mysql_time.h | 0 .../include => include}/mysql/mysql_version.h | 0 .../include => include}/mysql/mysqld_ername.h | 0 .../include => include}/mysql/mysqld_error.h | 0 {mysql/include => include}/mysql/sql_common.h | 0 {mysql/include => include}/mysql/sql_state.h | 0 .../include => include}/mysql/sslopt-case.h | 0 .../mysql/sslopt-longopts.h | 0 .../include => include}/mysql/sslopt-vars.h | 0 {mysql/include => include}/mysql/typelib.h | 0 {zlib/include => include/zlib}/zconf.h | 0 {zlib/include => include/zlib}/zlib.h | 0 BNCSutil.dll => lib/BNCSutil.dll | Bin libmysql.dll => lib/libmysql.dll | Bin zlib1.dll => lib/zlib1.dll | Bin mysql/lib/opt/libmysql.lib | Bin 34876 -> 0 bytes {StormLib => src/StormLib}/Info.plist | 0 {StormLib => src/StormLib}/Storm.lib | Bin {StormLib => src/StormLib}/StormDll.bat | 0 {StormLib => src/StormLib}/StormDll.sln | 0 {StormLib => src/StormLib}/StormDll.vcproj | 0 .../StormLib}/StormLib-Info.plist | 0 {StormLib => src/StormLib}/StormLib.bat | 0 {StormLib => src/StormLib}/StormLib.sln | 0 {StormLib => src/StormLib}/StormLib.vcproj | 0 .../StormLib.xcodeproj/project.pbxproj | 0 .../StormLib}/StormLib64-Info.plist | 0 {StormLib => src/StormLib}/StormLibDll.sln | 0 {StormLib => src/StormLib}/StormLibDll.vcproj | 0 {StormLib => src/StormLib}/StormLibTest.sln | 0 .../StormLib}/StormLibTest.vcproj | 0 {StormLib => src/StormLib}/doc/History.txt | 0 .../doc/The MoPaQ File Format 0.9.txt | 0 .../doc/The MoPaQ File Format 1.0.txt | 0 {StormLib => src/StormLib}/storm.dll | Bin .../StormLib}/stormdll/StormDll.cpp | 0 .../StormLib}/stormdll/StormDll.def | 0 .../StormLib}/stormdll/StormDll.h | 0 .../StormLib}/stormlib/GfxDecode.cpp | 0 {StormLib => src/StormLib}/stormlib/Makefile | 0 .../StormLib}/stormlib/SAttrFile.cpp | 0 .../StormLib}/stormlib/SCommon.cpp | 0 {StormLib => src/StormLib}/stormlib/SCommon.h | 0 .../StormLib}/stormlib/SCompression.cpp | 0 .../StormLib}/stormlib/SCompression_new.cpp | 0 .../StormLib}/stormlib/SCompression_old.cpp | 0 .../stormlib/SFileCompactArchive.cpp | 0 .../stormlib/SFileCreateArchiveEx.cpp | 0 .../StormLib}/stormlib/SFileExtractFile.cpp | 0 .../StormLib}/stormlib/SFileFindFile.cpp | 0 .../StormLib}/stormlib/SFileOpenArchive.cpp | 0 .../StormLib}/stormlib/SFileOpenFileEx.cpp | 0 .../StormLib}/stormlib/SFileReadFile.cpp | 0 .../StormLib}/stormlib/SListFile.cpp | 0 .../StormLib}/stormlib/StormDll.h | 0 .../StormLib}/stormlib/StormLib.h | 0 .../StormLib}/stormlib/StormPort.h | 0 .../StormLib}/stormlib/StormPortLinux.cpp | 0 .../StormLib}/stormlib/StormPortMac.cpp | 0 .../StormLib}/stormlib/bzip2/CHANGES | 0 .../StormLib}/stormlib/bzip2/LICENSE | 0 .../StormLib}/stormlib/bzip2/Makefile | 0 .../stormlib/bzip2/Makefile-libbz2_so | 0 .../StormLib}/stormlib/bzip2/README | 0 .../bzip2/README.COMPILATION.PROBLEMS | 0 .../StormLib}/stormlib/bzip2/README.XML.STUFF | 0 .../StormLib}/stormlib/bzip2/Y2K_INFO | 0 .../StormLib}/stormlib/bzip2/blocksort.c | 0 .../StormLib}/stormlib/bzip2/bz-common.xsl | 0 .../StormLib}/stormlib/bzip2/bz-fo.xsl | 0 .../StormLib}/stormlib/bzip2/bz-html.xsl | 0 .../StormLib}/stormlib/bzip2/bzdiff | 0 .../StormLib}/stormlib/bzip2/bzdiff.1 | 0 .../StormLib}/stormlib/bzip2/bzgrep | 0 .../StormLib}/stormlib/bzip2/bzgrep.1 | 0 .../StormLib}/stormlib/bzip2/bzip.css | 0 .../StormLib}/stormlib/bzip2/bzip2.1 | 0 .../stormlib/bzip2/bzip2.1.preformatted | 0 .../StormLib}/stormlib/bzip2/bzip2.c | 0 .../StormLib}/stormlib/bzip2/bzip2.txt | 0 .../StormLib}/stormlib/bzip2/bzip2recover.c | 0 .../StormLib}/stormlib/bzip2/bzlib.c | 0 .../StormLib}/stormlib/bzip2/bzlib.h | 0 .../StormLib}/stormlib/bzip2/bzlib_private.h | 0 .../StormLib}/stormlib/bzip2/bzmore | 0 .../StormLib}/stormlib/bzip2/bzmore.1 | 0 .../StormLib}/stormlib/bzip2/compress.c | 0 .../StormLib}/stormlib/bzip2/crctable.c | 0 .../StormLib}/stormlib/bzip2/decompress.c | 0 .../StormLib}/stormlib/bzip2/dlltest.c | 0 .../StormLib}/stormlib/bzip2/dlltest.dsp | 0 .../StormLib}/stormlib/bzip2/entities.xml | 0 .../StormLib}/stormlib/bzip2/format.pl | 0 .../StormLib}/stormlib/bzip2/huffman.c | 0 .../StormLib}/stormlib/bzip2/libbz2.def | 0 .../StormLib}/stormlib/bzip2/libbz2.dsp | 0 .../StormLib}/stormlib/bzip2/makefile.msc | 0 .../StormLib}/stormlib/bzip2/manual.html | 0 .../StormLib}/stormlib/bzip2/manual.pdf | Bin .../StormLib}/stormlib/bzip2/manual.ps | Bin .../StormLib}/stormlib/bzip2/manual.xml | 0 .../StormLib}/stormlib/bzip2/mk251.c | 0 .../StormLib}/stormlib/bzip2/randtable.c | 0 .../StormLib}/stormlib/bzip2/sample1.bz2 | Bin .../StormLib}/stormlib/bzip2/sample1.ref | Bin .../StormLib}/stormlib/bzip2/sample2.bz2 | Bin .../StormLib}/stormlib/bzip2/sample2.ref | Bin .../StormLib}/stormlib/bzip2/sample3.bz2 | Bin .../StormLib}/stormlib/bzip2/sample3.ref | 0 .../StormLib}/stormlib/bzip2/spewG.c | 0 .../StormLib}/stormlib/bzip2/unzcrash.c | 0 .../StormLib}/stormlib/bzip2/words0 | 0 .../StormLib}/stormlib/bzip2/words1 | 0 .../StormLib}/stormlib/bzip2/words2 | 0 .../StormLib}/stormlib/bzip2/words3 | 0 .../StormLib}/stormlib/bzip2/xmlproc.sh | 0 .../StormLib}/stormlib/huffman/huff.cpp | 0 .../StormLib}/stormlib/huffman/huff.h | 0 .../StormLib}/stormlib/misc/crc32.cpp | 0 .../StormLib}/stormlib/misc/crc32.h | 0 .../StormLib}/stormlib/misc/md5.cpp | 0 .../StormLib}/stormlib/misc/md5.h | 0 .../StormLib}/stormlib/pklib/crc32.c | 0 .../StormLib}/stormlib/pklib/explode.c | 0 .../StormLib}/stormlib/pklib/implode.c | 0 .../StormLib}/stormlib/pklib/pklib.h | 0 .../StormLib}/stormlib/wave/wave.cpp | 0 .../StormLib}/stormlib/wave/wave.h | 0 .../StormLib}/stormlib/zlib/ChangeLog | 0 {StormLib => src/StormLib}/stormlib/zlib/FAQ | 0 .../StormLib}/stormlib/zlib/INDEX | 0 .../StormLib}/stormlib/zlib/Makefile | 0 .../StormLib}/stormlib/zlib/Makefile.in | 0 .../StormLib}/stormlib/zlib/README | 0 .../StormLib}/stormlib/zlib/adler32.c | 0 .../StormLib}/stormlib/zlib/algorithm.txt | 0 .../stormlib/zlib/amiga/Makefile.pup | 0 .../stormlib/zlib/amiga/Makefile.sas | 0 .../StormLib}/stormlib/zlib/as400/bndsrc | 0 .../StormLib}/stormlib/zlib/as400/compile.clp | 0 .../StormLib}/stormlib/zlib/as400/readme.txt | 0 .../StormLib}/stormlib/zlib/as400/zlib.inc | 0 .../StormLib}/stormlib/zlib/compress.c | 0 .../StormLib}/stormlib/zlib/configure | 0 .../stormlib/zlib/contrib/README.contrib | 0 .../stormlib/zlib/contrib/ada/buffer_demo.adb | 0 .../stormlib/zlib/contrib/ada/mtest.adb | 0 .../stormlib/zlib/contrib/ada/read.adb | 0 .../stormlib/zlib/contrib/ada/readme.txt | 0 .../stormlib/zlib/contrib/ada/test.adb | 0 .../zlib/contrib/ada/zlib-streams.adb | 0 .../zlib/contrib/ada/zlib-streams.ads | 0 .../stormlib/zlib/contrib/ada/zlib-thin.adb | 0 .../stormlib/zlib/contrib/ada/zlib-thin.ads | 0 .../stormlib/zlib/contrib/ada/zlib.adb | 0 .../stormlib/zlib/contrib/ada/zlib.ads | 0 .../stormlib/zlib/contrib/ada/zlib.gpr | 0 .../stormlib/zlib/contrib/asm586/README.586 | 0 .../stormlib/zlib/contrib/asm586/match.S | 0 .../stormlib/zlib/contrib/asm686/README.686 | 0 .../stormlib/zlib/contrib/asm686/match.S | 0 .../stormlib/zlib/contrib/blast/Makefile | 0 .../stormlib/zlib/contrib/blast/README | 0 .../stormlib/zlib/contrib/blast/blast.c | 0 .../stormlib/zlib/contrib/blast/blast.h | 0 .../stormlib/zlib/contrib/blast/test.pk | Bin .../stormlib/zlib/contrib/blast/test.txt | 0 .../stormlib/zlib/contrib/delphi/ZLib.pas | 0 .../zlib/contrib/delphi/ZLibConst.pas | 0 .../stormlib/zlib/contrib/delphi/readme.txt | 0 .../stormlib/zlib/contrib/delphi/zlibd32.mak | 0 .../zlib/contrib/dotzlib/DotZLib.build | 0 .../stormlib/zlib/contrib/dotzlib/DotZLib.chm | Bin .../stormlib/zlib/contrib/dotzlib/DotZLib.sln | 0 .../contrib/dotzlib/DotZLib/AssemblyInfo.cs | 0 .../contrib/dotzlib/DotZLib/ChecksumImpl.cs | 0 .../contrib/dotzlib/DotZLib/CircularBuffer.cs | 0 .../zlib/contrib/dotzlib/DotZLib/CodecBase.cs | 0 .../zlib/contrib/dotzlib/DotZLib/Deflater.cs | 0 .../zlib/contrib/dotzlib/DotZLib/DotZLib.cs | 0 .../contrib/dotzlib/DotZLib/DotZLib.csproj | 0 .../contrib/dotzlib/DotZLib/GZipStream.cs | 0 .../zlib/contrib/dotzlib/DotZLib/Inflater.cs | 0 .../zlib/contrib/dotzlib/DotZLib/UnitTests.cs | 0 .../zlib/contrib/dotzlib/LICENSE_1_0.txt | 0 .../stormlib/zlib/contrib/dotzlib/readme.txt | 0 .../stormlib/zlib/contrib/infback9/README | 0 .../stormlib/zlib/contrib/infback9/infback9.c | 0 .../stormlib/zlib/contrib/infback9/infback9.h | 0 .../stormlib/zlib/contrib/infback9/inffix9.h | 0 .../stormlib/zlib/contrib/infback9/inflate9.h | 0 .../stormlib/zlib/contrib/infback9/inftree9.c | 0 .../stormlib/zlib/contrib/infback9/inftree9.h | 0 .../zlib/contrib/inflate86/inffas86.c | 0 .../stormlib/zlib/contrib/inflate86/inffast.S | 0 .../stormlib/zlib/contrib/iostream/test.cpp | 0 .../zlib/contrib/iostream/zfstream.cpp | 0 .../stormlib/zlib/contrib/iostream/zfstream.h | 0 .../stormlib/zlib/contrib/iostream2/zstream.h | 0 .../zlib/contrib/iostream2/zstream_test.cpp | 0 .../stormlib/zlib/contrib/iostream3/README | 0 .../stormlib/zlib/contrib/iostream3/TODO | 0 .../stormlib/zlib/contrib/iostream3/test.cc | 0 .../zlib/contrib/iostream3/zfstream.cc | 0 .../zlib/contrib/iostream3/zfstream.h | 0 .../stormlib/zlib/contrib/masm686/match.asm | 0 .../zlib/contrib/masmx64/bld_ml64.bat | 0 .../stormlib/zlib/contrib/masmx64/gvmat64.asm | 0 .../zlib/contrib/masmx64/inffas8664.c | 0 .../zlib/contrib/masmx64/inffasx64.asm | 0 .../stormlib/zlib/contrib/masmx64/readme.txt | 0 .../zlib/contrib/masmx86/bld_ml32.bat | 0 .../stormlib/zlib/contrib/masmx86/gvmat32.asm | 0 .../stormlib/zlib/contrib/masmx86/gvmat32c.c | 0 .../zlib/contrib/masmx86/inffas32.asm | 0 .../stormlib/zlib/contrib/masmx86/mkasm.bat | 0 .../stormlib/zlib/contrib/masmx86/readme.txt | 0 .../zlib/contrib/minizip/ChangeLogUnzip | 0 .../stormlib/zlib/contrib/minizip/Makefile | 0 .../stormlib/zlib/contrib/minizip/crypt.h | 0 .../stormlib/zlib/contrib/minizip/ioapi.c | 0 .../stormlib/zlib/contrib/minizip/ioapi.h | 0 .../stormlib/zlib/contrib/minizip/iowin32.c | 0 .../stormlib/zlib/contrib/minizip/iowin32.h | 0 .../stormlib/zlib/contrib/minizip/miniunz.c | 0 .../stormlib/zlib/contrib/minizip/minizip.c | 0 .../stormlib/zlib/contrib/minizip/mztools.c | 0 .../stormlib/zlib/contrib/minizip/mztools.h | 0 .../stormlib/zlib/contrib/minizip/unzip.c | 0 .../stormlib/zlib/contrib/minizip/unzip.h | 0 .../stormlib/zlib/contrib/minizip/zip.c | 0 .../stormlib/zlib/contrib/minizip/zip.h | 0 .../stormlib/zlib/contrib/pascal/example.pas | 0 .../stormlib/zlib/contrib/pascal/readme.txt | 0 .../stormlib/zlib/contrib/pascal/zlibd32.mak | 0 .../stormlib/zlib/contrib/pascal/zlibpas.pas | 0 .../stormlib/zlib/contrib/puff/Makefile | 0 .../stormlib/zlib/contrib/puff/README | 0 .../stormlib/zlib/contrib/puff/puff.c | 0 .../stormlib/zlib/contrib/puff/puff.h | 0 .../stormlib/zlib/contrib/puff/zeros.raw | Bin .../stormlib/zlib/contrib/testzlib/testzlib.c | 0 .../zlib/contrib/testzlib/testzlib.txt | 0 .../stormlib/zlib/contrib/untgz/Makefile | 0 .../stormlib/zlib/contrib/untgz/Makefile.msc | 0 .../stormlib/zlib/contrib/untgz/untgz.c | 0 .../stormlib/zlib/contrib/vstudio/readme.txt | 0 .../zlib/contrib/vstudio/vc7/miniunz.vcproj | 0 .../zlib/contrib/vstudio/vc7/minizip.vcproj | 0 .../zlib/contrib/vstudio/vc7/testzlib.vcproj | 0 .../stormlib/zlib/contrib/vstudio/vc7/zlib.rc | 0 .../zlib/contrib/vstudio/vc7/zlibstat.vcproj | 0 .../zlib/contrib/vstudio/vc7/zlibvc.def | 0 .../zlib/contrib/vstudio/vc7/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc7/zlibvc.vcproj | 0 .../zlib/contrib/vstudio/vc8/miniunz.vcproj | 0 .../zlib/contrib/vstudio/vc8/minizip.vcproj | 0 .../zlib/contrib/vstudio/vc8/testzlib.vcproj | 0 .../contrib/vstudio/vc8/testzlibdll.vcproj | 0 .../stormlib/zlib/contrib/vstudio/vc8/zlib.rc | 0 .../zlib/contrib/vstudio/vc8/zlibstat.vcproj | 0 .../zlib/contrib/vstudio/vc8/zlibvc.def | 0 .../zlib/contrib/vstudio/vc8/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc8/zlibvc.vcproj | 0 .../StormLib}/stormlib/zlib/crc32.c | 0 .../StormLib}/stormlib/zlib/crc32.h | 0 .../StormLib}/stormlib/zlib/deflate.c | 0 .../StormLib}/stormlib/zlib/deflate.h | 0 .../StormLib}/stormlib/zlib/example.c | 0 .../stormlib/zlib/examples/README.examples | 0 .../StormLib}/stormlib/zlib/examples/fitblk.c | 0 .../StormLib}/stormlib/zlib/examples/gun.c | 0 .../stormlib/zlib/examples/gzappend.c | 0 .../StormLib}/stormlib/zlib/examples/gzjoin.c | 0 .../StormLib}/stormlib/zlib/examples/gzlog.c | 0 .../StormLib}/stormlib/zlib/examples/gzlog.h | 0 .../stormlib/zlib/examples/zlib_how.html | 0 .../StormLib}/stormlib/zlib/examples/zpipe.c | 0 .../StormLib}/stormlib/zlib/examples/zran.c | 0 .../StormLib}/stormlib/zlib/gzio.c | 0 .../StormLib}/stormlib/zlib/infback.c | 0 .../StormLib}/stormlib/zlib/inffast.c | 0 .../StormLib}/stormlib/zlib/inffast.h | 0 .../StormLib}/stormlib/zlib/inffixed.h | 0 .../StormLib}/stormlib/zlib/inflate.c | 0 .../StormLib}/stormlib/zlib/inflate.h | 0 .../StormLib}/stormlib/zlib/inftrees.c | 0 .../StormLib}/stormlib/zlib/inftrees.h | 0 .../StormLib}/stormlib/zlib/minigzip.c | 0 .../stormlib/zlib/msdos/Makefile.bor | 0 .../stormlib/zlib/msdos/Makefile.dj2 | 0 .../stormlib/zlib/msdos/Makefile.emx | 0 .../stormlib/zlib/msdos/Makefile.msc | 0 .../StormLib}/stormlib/zlib/msdos/Makefile.tc | 0 .../stormlib/zlib/old/Makefile.riscos | 0 .../StormLib}/stormlib/zlib/old/README | 0 .../StormLib}/stormlib/zlib/old/descrip.mms | 0 .../stormlib/zlib/old/os2/Makefile.os2 | 0 .../StormLib}/stormlib/zlib/old/os2/zlib.def | 0 .../stormlib/zlib/old/visual-basic.txt | 0 .../StormLib}/stormlib/zlib/old/zlib.html | 0 .../stormlib/zlib/projects/README.projects | 0 .../zlib/projects/visualc6/README.txt | 0 .../zlib/projects/visualc6/example.dsp | 0 .../zlib/projects/visualc6/minigzip.dsp | 0 .../stormlib/zlib/projects/visualc6/zlib.dsp | 0 .../stormlib/zlib/projects/visualc6/zlib.dsw | 0 .../StormLib}/stormlib/zlib/qnx/package.qpg | 0 .../StormLib}/stormlib/zlib/trees.c | 0 .../StormLib}/stormlib/zlib/trees.h | 0 .../StormLib}/stormlib/zlib/uncompr.c | 0 .../StormLib}/stormlib/zlib/win32/DLL_FAQ.txt | 0 .../stormlib/zlib/win32/Makefile.bor | 0 .../stormlib/zlib/win32/Makefile.emx | 0 .../stormlib/zlib/win32/Makefile.gcc | 0 .../stormlib/zlib/win32/Makefile.msc | 0 .../StormLib}/stormlib/zlib/win32/VisualC.txt | 0 .../StormLib}/stormlib/zlib/win32/zlib.def | 0 .../StormLib}/stormlib/zlib/win32/zlib1.rc | 0 .../StormLib}/stormlib/zlib/zconf.h | 0 .../StormLib}/stormlib/zlib/zconf.in.h | 0 .../StormLib}/stormlib/zlib/zlib.3 | 0 .../StormLib}/stormlib/zlib/zlib.h | 0 .../StormLib}/stormlib/zlib/zutil.c | 0 .../StormLib}/stormlib/zlib/zutil.h | 0 .../StormLib}/stormlibdll/DllMain.c | 0 .../StormLib}/stormlibdll/StormLib.def | 0 {StormLib => src/StormLib}/test/Test.cpp | 0 .../Makefile => src/bncsutil/Makefile.old | 0 {bncsutil/src => src}/bncsutil/bncsutil.h | 0 src/bncsutil/bncsutil.pro | 25 + {bncsutil/src => src}/bncsutil/bsha1.cpp | 0 {bncsutil/src => src}/bncsutil/bsha1.h | 0 {bncsutil/src => src}/bncsutil/buffer.h | 0 .../src => src}/bncsutil/cdkeydecoder.cpp | 0 {bncsutil/src => src}/bncsutil/cdkeydecoder.h | 0 .../src => src}/bncsutil/checkrevision.cpp | 0 .../src => src}/bncsutil/checkrevision.h | 0 {bncsutil/src => src}/bncsutil/debug.c | 0 {bncsutil/src => src}/bncsutil/debug.h | 0 {bncsutil/src => src}/bncsutil/decodekey.cpp | 0 {bncsutil/src => src}/bncsutil/decodekey.h | 0 {bncsutil/src => src}/bncsutil/file.cpp | 0 {bncsutil/src => src}/bncsutil/file.h | 0 {bncsutil/src => src}/bncsutil/gmp.h | 0 {bncsutil/src => src}/bncsutil/keytables.h | 0 {bncsutil/src => src}/bncsutil/libinfo.cpp | 0 {bncsutil/src => src}/bncsutil/libinfo.h | 0 {bncsutil/src => src}/bncsutil/ms_stdint.h | 0 {bncsutil/src => src}/bncsutil/mutil.h | 0 {bncsutil/src => src}/bncsutil/mutil_types.h | 0 {bncsutil/src => src}/bncsutil/nls.c | 0 {bncsutil/src => src}/bncsutil/nls.h | 0 {bncsutil/src => src}/bncsutil/oldauth.cpp | 0 {bncsutil/src => src}/bncsutil/oldauth.h | 0 {bncsutil/src => src}/bncsutil/pe.c | 0 {bncsutil/src => src}/bncsutil/pe.h | 0 {bncsutil/src => src}/bncsutil/sha1.c | 0 {bncsutil/src => src}/bncsutil/sha1.h | 0 {bncsutil/src => src}/bncsutil/stack.c | 0 {bncsutil/src => src}/bncsutil/stack.h | 0 src/cli/cli.pro | 22 + {ghost => src/cli}/main.cpp | 54 +- .../ghost configurator}/ReadMe.txt | 0 .../ghost configurator.sln | 0 .../ghost configurator/Form1.Designer.vb | 0 .../ghost configurator/Form1.resx | 0 .../ghost configurator/Form1.vb | 0 .../My Project/Application.Designer.vb | 0 .../My Project/Application.myapp | 0 .../My Project/AssemblyInfo.vb | 0 .../My Project/Resources.Designer.vb | 0 .../My Project/Resources.resx | 0 .../My Project/Settings.Designer.vb | 0 .../My Project/Settings.settings | 0 .../My Project/app.manifest | 0 .../Resources/parametres 3D.ico | Bin .../ghost configurator/bin/Debug/ghost.cfg | 0 .../ghost configurator.vbproj | 0 .../ghost configurator.vbproj.user | 0 src/lib.pri | 3 + {ghost => src/libghost}/StormLibRAS.lib | Bin {ghost => src/libghost}/bncsutilinterface.cpp | 0 {ghost => src/libghost}/bncsutilinterface.h | 0 {ghost => src/libghost}/bnet.cpp | 338 +- {ghost => src/libghost}/bnet.h | 50 +- {ghost => src/libghost}/bnetprotocol.cpp | 0 {ghost => src/libghost}/bnetprotocol.h | 0 {ghost => src/libghost}/bnlsclient.cpp | 0 {ghost => src/libghost}/bnlsclient.h | 0 {ghost => src/libghost}/bnlsprotocol.cpp | 0 {ghost => src/libghost}/bnlsprotocol.h | 0 {ghost => src/libghost}/commandpacket.cpp | 0 {ghost => src/libghost}/commandpacket.h | 0 {ghost => src/libghost}/config.cpp | 0 {ghost => src/libghost}/config.h | 0 {ghost => src/libghost}/crc32.cpp | 0 {ghost => src/libghost}/crc32.h | 0 {ghost => src/libghost}/csvparser.cpp | 0 {ghost => src/libghost}/csvparser.h | 0 {ghost => src/libghost}/game.cpp | 164 +- {ghost => src/libghost}/game.h | 0 {ghost => src/libghost}/game_admin.cpp | 180 +- {ghost => src/libghost}/game_admin.h | 0 {ghost => src/libghost}/game_base.cpp | 164 +- {ghost => src/libghost}/game_base.h | 1 + {ghost => src/libghost}/gameplayer.cpp | 10 +- {ghost => src/libghost}/gameplayer.h | 0 {ghost => src/libghost}/gameprotocol.cpp | 0 {ghost => src/libghost}/gameprotocol.h | 0 {ghost => src/libghost}/gameslot.cpp | 0 {ghost => src/libghost}/gameslot.h | 0 {ghost => src/libghost}/ghost.cpp | 153 +- {ghost => src/libghost}/ghost.h | 46 +- {ghost => src/libghost}/ghost.vcproj | 0 src/libghost/ghost_p.h | 30 + {ghost => src/libghost}/ghostdb.cpp | 0 {ghost => src/libghost}/ghostdb.h | 0 {ghost => src/libghost}/ghostdbmysql.cpp | 0 {ghost => src/libghost}/ghostdbmysql.h | 0 {ghost => src/libghost}/ghostdbsqlite.cpp | 0 {ghost => src/libghost}/ghostdbsqlite.h | 0 {ghost => src/libghost}/gpsprotocol.cpp | 0 {ghost => src/libghost}/gpsprotocol.h | 0 {ghost => src/libghost}/includes.h | 0 {ghost => src/libghost}/interfaces.h | 72 +- {ghost => src/libghost}/language.cpp | 440 +- src/libghost/language.h | 263 + ghost/ghost.pro => src/libghost/libghost.pro | 54 +- src/libghost/main.cpp | 158 + {ghost => src/libghost}/map.cpp | 0 {ghost => src/libghost}/map.h | 0 {ghost => src/libghost}/mpqarchive.cpp | 0 {ghost => src/libghost}/mpqarchive.h | 0 {ghost => src/libghost}/mpqfile.cpp | 0 {ghost => src/libghost}/mpqfile.h | 0 {ghost => src/libghost}/next_combination.h | 0 {ghost => src/libghost}/packed.cpp | 0 {ghost => src/libghost}/packed.h | 0 {ghost => src/libghost}/replay.cpp | 0 {ghost => src/libghost}/replay.h | 0 {ghost => src/libghost}/savegame.cpp | 0 {ghost => src/libghost}/savegame.h | 0 {ghost => src/libghost}/sha1.cpp | 0 {ghost => src/libghost}/sha1.h | 0 {ghost => src/libghost}/sqlite3.c | 0 {ghost => src/libghost}/sqlite3.h | 0 {ghost => src/libghost}/sqlite3ext.h | 0 {ghost => src/libghost}/stats.cpp | 0 {ghost => src/libghost}/stats.h | 0 {ghost => src/libghost}/statsdota.cpp | 0 {ghost => src/libghost}/statsdota.h | 0 {ghost => src/libghost}/statsw3mmd.cpp | 0 {ghost => src/libghost}/statsw3mmd.h | 0 src/libghost/ttmath/CHANGELOG | 498 ++ src/libghost/ttmath/COPYRIGHT | 28 + src/libghost/ttmath/README | 23 + src/libghost/ttmath/samples/Makefile | 46 + src/libghost/ttmath/samples/big.cpp | 100 + src/libghost/ttmath/samples/big2.cpp | 113 + src/libghost/ttmath/samples/int.cpp | 92 + src/libghost/ttmath/samples/parser.cpp | 39 + src/libghost/ttmath/samples/uint.cpp | 93 + src/libghost/ttmath/ttmath/ttmath.h | 2835 +++++++++ src/libghost/ttmath/ttmath/ttmathbig.h | 5236 +++++++++++++++++ src/libghost/ttmath/ttmath/ttmathint.h | 1547 +++++ src/libghost/ttmath/ttmath/ttmathmisc.h | 243 + src/libghost/ttmath/ttmath/ttmathobjects.h | 766 +++ src/libghost/ttmath/ttmath/ttmathparser.h | 2754 +++++++++ src/libghost/ttmath/ttmath/ttmaththreads.h | 250 + src/libghost/ttmath/ttmath/ttmathtypes.h | 646 ++ src/libghost/ttmath/ttmath/ttmathuint.h | 3520 +++++++++++ src/libghost/ttmath/ttmath/ttmathuint_noasm.h | 1013 ++++ src/libghost/ttmath/ttmath/ttmathuint_x86.h | 1602 +++++ .../ttmath/ttmath/ttmathuint_x86_64.h | 1222 ++++ .../ttmath/ttmath/ttmathuint_x86_64_msvc.asm | 548 ++ {ghost => src/libghost}/util.cpp | 0 {ghost => src/libghost}/util.h | 0 {ghost => src/libghost}/w3g_actions.txt | 0 {ghost => src/libghost}/w3g_format.txt | 0 src/plugins/cmd_builtin/cmd_builtin.pro | 12 + .../plugins}/cmd_builtin/commands.cpp | 23 +- {ghost => src/plugins}/cmd_builtin/commands.h | 8 +- src/plugins/plugin.pri | 11 + src/plugins/plugins.pro | 10 + .../update_dota_elo}/Makefile | 0 .../update_dota_elo}/elo.cpp | 0 .../update_dota_elo}/elo.h | 0 .../update_dota_elo}/update_dota_elo.cpp | 0 .../update_dota_elo}/update_dota_elo.vcproj | 0 .../update_w3mmd_elo}/Makefile | 0 .../update_w3mmd_elo}/elo.cpp | 0 .../update_w3mmd_elo}/elo.h | 0 .../update_w3mmd_elo}/update_w3mmd_elo.cpp | 0 .../update_w3mmd_elo}/update_w3mmd_elo.vcproj | 0 zlib/DLL_FAQ.txt | 397 -- zlib/README.txt | 53 - zlib/USAGE.txt | 94 - zlib/lib/zdll.exp | Bin 6109 -> 0 bytes zlib/lib/zdll.lib | Bin 10590 -> 0 bytes zlib/lib/zlib.def | 60 - zlib/test/example_d.exe | Bin 8704 -> 0 bytes zlib/test/minigzip_d.exe | Bin 4608 -> 0 bytes zlib/test/testzlib_d.exe | Bin 5120 -> 0 bytes zlib/test/untgz_d.exe | Bin 7168 -> 0 bytes 559 files changed, 24727 insertions(+), 2432 deletions(-) rename default.cfg => bin/default.cfg (100%) rename gameloaded.txt => bin/gameloaded.txt (100%) rename gameover.txt => bin/gameover.txt (100%) rename ghost dynamic configurator.exe => bin/ghost dynamic configurator.exe (100%) rename ip-to-country.csv => bin/ip-to-country.csv (100%) rename ipblacklist.txt => bin/ipblacklist.txt (100%) rename language.cfg => bin/language.cfg (100%) rename language_german.cfg => bin/language_german.cfg (100%) rename language_russian.cfg => bin/language_russian.cfg (100%) rename language_spanish.cfg => bin/language_spanish.cfg (100%) rename language_turkish.cfg => bin/language_turkish.cfg (100%) create mode 100644 bin/license.txt rename {mapcfgs => bin/mapcfgs}/wormwar.cfg (100%) rename mysql_create_tables_v1.sql => bin/mysql_create_tables_v1.sql (100%) rename mysql_create_tables_v2.sql => bin/mysql_create_tables_v2.sql (100%) rename mysql_upgrade_v1-v2.sql => bin/mysql_upgrade_v1-v2.sql (100%) rename readme.txt => bin/readme.txt (100%) rename update_dota_elo.cfg => bin/update_dota_elo.cfg (100%) rename update_dota_elo.exe => bin/update_dota_elo.exe (100%) rename update_w3mmd_elo.cfg => bin/update_w3mmd_elo.cfg (100%) rename update_w3mmd_elo.exe => bin/update_w3mmd_elo.exe (100%) delete mode 100644 bncsutil/product_version delete mode 100644 bncsutil/vc8_build/BNCSutil.vcproj delete mode 100644 bncsutil/vc8_build/bncsutil.def delete mode 100644 bncsutil/vc8_build/gmp.lib delete mode 100644 ghost.exe create mode 100644 ghost.pro delete mode 100755 ghost/cmd_builtin/cmd_builtin.pro delete mode 100644 ghost/cmd_builtin/moc_commands.cpp delete mode 100644 ghost/language.h rename {mysql/include => include}/mysql/config-win.h (100%) rename {mysql/include => include}/mysql/decimal.h (100%) rename {mysql/include => include}/mysql/errmsg.h (100%) rename {mysql/include => include}/mysql/keycache.h (100%) rename {mysql/include => include}/mysql/libmysql.def (100%) rename {mysql/include => include}/mysql/libmysqld.def (100%) rename {mysql/include => include}/mysql/m_ctype.h (100%) rename {mysql/include => include}/mysql/m_string.h (100%) rename {mysql/include => include}/mysql/my_alloc.h (100%) rename {mysql/include => include}/mysql/my_attribute.h (100%) rename {mysql/include => include}/mysql/my_dbug.h (100%) rename {mysql/include => include}/mysql/my_dir.h (100%) rename {mysql/include => include}/mysql/my_getopt.h (100%) rename {mysql/include => include}/mysql/my_global.h (100%) rename {mysql/include => include}/mysql/my_list.h (100%) rename {mysql/include => include}/mysql/my_net.h (100%) rename {mysql/include => include}/mysql/my_no_pthread.h (100%) rename {mysql/include => include}/mysql/my_pthread.h (100%) rename {mysql/include => include}/mysql/my_sys.h (100%) rename {mysql/include => include}/mysql/my_xml.h (100%) rename {mysql/include => include}/mysql/mysql.h (100%) rename {mysql/include => include}/mysql/mysql/plugin.h (100%) rename {mysql/include => include}/mysql/mysql_com.h (100%) rename {mysql/include => include}/mysql/mysql_embed.h (100%) rename {mysql/include => include}/mysql/mysql_time.h (100%) rename {mysql/include => include}/mysql/mysql_version.h (100%) rename {mysql/include => include}/mysql/mysqld_ername.h (100%) rename {mysql/include => include}/mysql/mysqld_error.h (100%) rename {mysql/include => include}/mysql/sql_common.h (100%) rename {mysql/include => include}/mysql/sql_state.h (100%) rename {mysql/include => include}/mysql/sslopt-case.h (100%) rename {mysql/include => include}/mysql/sslopt-longopts.h (100%) rename {mysql/include => include}/mysql/sslopt-vars.h (100%) rename {mysql/include => include}/mysql/typelib.h (100%) rename {zlib/include => include/zlib}/zconf.h (100%) rename {zlib/include => include/zlib}/zlib.h (100%) rename BNCSutil.dll => lib/BNCSutil.dll (100%) rename libmysql.dll => lib/libmysql.dll (100%) rename zlib1.dll => lib/zlib1.dll (100%) delete mode 100644 mysql/lib/opt/libmysql.lib rename {StormLib => src/StormLib}/Info.plist (100%) rename {StormLib => src/StormLib}/Storm.lib (100%) rename {StormLib => src/StormLib}/StormDll.bat (100%) rename {StormLib => src/StormLib}/StormDll.sln (100%) rename {StormLib => src/StormLib}/StormDll.vcproj (100%) rename {StormLib => src/StormLib}/StormLib-Info.plist (100%) rename {StormLib => src/StormLib}/StormLib.bat (100%) rename {StormLib => src/StormLib}/StormLib.sln (100%) rename {StormLib => src/StormLib}/StormLib.vcproj (100%) rename {StormLib => src/StormLib}/StormLib.xcodeproj/project.pbxproj (100%) rename {StormLib => src/StormLib}/StormLib64-Info.plist (100%) rename {StormLib => src/StormLib}/StormLibDll.sln (100%) rename {StormLib => src/StormLib}/StormLibDll.vcproj (100%) rename {StormLib => src/StormLib}/StormLibTest.sln (100%) rename {StormLib => src/StormLib}/StormLibTest.vcproj (100%) rename {StormLib => src/StormLib}/doc/History.txt (100%) rename {StormLib => src/StormLib}/doc/The MoPaQ File Format 0.9.txt (100%) rename {StormLib => src/StormLib}/doc/The MoPaQ File Format 1.0.txt (100%) rename {StormLib => src/StormLib}/storm.dll (100%) rename {StormLib => src/StormLib}/stormdll/StormDll.cpp (100%) rename {StormLib => src/StormLib}/stormdll/StormDll.def (100%) rename {StormLib => src/StormLib}/stormdll/StormDll.h (100%) rename {StormLib => src/StormLib}/stormlib/GfxDecode.cpp (100%) rename {StormLib => src/StormLib}/stormlib/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/SAttrFile.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SCommon.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SCommon.h (100%) rename {StormLib => src/StormLib}/stormlib/SCompression.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SCompression_new.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SCompression_old.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileCompactArchive.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileCreateArchiveEx.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileExtractFile.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileFindFile.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileOpenArchive.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileOpenFileEx.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SFileReadFile.cpp (100%) rename {StormLib => src/StormLib}/stormlib/SListFile.cpp (100%) rename {StormLib => src/StormLib}/stormlib/StormDll.h (100%) rename {StormLib => src/StormLib}/stormlib/StormLib.h (100%) rename {StormLib => src/StormLib}/stormlib/StormPort.h (100%) rename {StormLib => src/StormLib}/stormlib/StormPortLinux.cpp (100%) rename {StormLib => src/StormLib}/stormlib/StormPortMac.cpp (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/CHANGES (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/LICENSE (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/Makefile-libbz2_so (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/README (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/README.COMPILATION.PROBLEMS (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/README.XML.STUFF (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/Y2K_INFO (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/blocksort.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bz-common.xsl (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bz-fo.xsl (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bz-html.xsl (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzdiff (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzdiff.1 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzgrep (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzgrep.1 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzip.css (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzip2.1 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzip2.1.preformatted (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzip2.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzip2.txt (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzip2recover.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzlib.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzlib.h (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzlib_private.h (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzmore (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/bzmore.1 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/compress.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/crctable.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/decompress.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/dlltest.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/dlltest.dsp (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/entities.xml (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/format.pl (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/huffman.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/libbz2.def (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/libbz2.dsp (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/makefile.msc (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/manual.html (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/manual.pdf (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/manual.ps (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/manual.xml (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/mk251.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/randtable.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/sample1.bz2 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/sample1.ref (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/sample2.bz2 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/sample2.ref (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/sample3.bz2 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/sample3.ref (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/spewG.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/unzcrash.c (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/words0 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/words1 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/words2 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/words3 (100%) rename {StormLib => src/StormLib}/stormlib/bzip2/xmlproc.sh (100%) rename {StormLib => src/StormLib}/stormlib/huffman/huff.cpp (100%) rename {StormLib => src/StormLib}/stormlib/huffman/huff.h (100%) rename {StormLib => src/StormLib}/stormlib/misc/crc32.cpp (100%) rename {StormLib => src/StormLib}/stormlib/misc/crc32.h (100%) rename {StormLib => src/StormLib}/stormlib/misc/md5.cpp (100%) rename {StormLib => src/StormLib}/stormlib/misc/md5.h (100%) rename {StormLib => src/StormLib}/stormlib/pklib/crc32.c (100%) rename {StormLib => src/StormLib}/stormlib/pklib/explode.c (100%) rename {StormLib => src/StormLib}/stormlib/pklib/implode.c (100%) rename {StormLib => src/StormLib}/stormlib/pklib/pklib.h (100%) rename {StormLib => src/StormLib}/stormlib/wave/wave.cpp (100%) rename {StormLib => src/StormLib}/stormlib/wave/wave.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/ChangeLog (100%) rename {StormLib => src/StormLib}/stormlib/zlib/FAQ (100%) rename {StormLib => src/StormLib}/stormlib/zlib/INDEX (100%) rename {StormLib => src/StormLib}/stormlib/zlib/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/zlib/Makefile.in (100%) rename {StormLib => src/StormLib}/stormlib/zlib/README (100%) rename {StormLib => src/StormLib}/stormlib/zlib/adler32.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/algorithm.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/amiga/Makefile.pup (100%) rename {StormLib => src/StormLib}/stormlib/zlib/amiga/Makefile.sas (100%) rename {StormLib => src/StormLib}/stormlib/zlib/as400/bndsrc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/as400/compile.clp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/as400/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/as400/zlib.inc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/compress.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/configure (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/README.contrib (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/buffer_demo.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/mtest.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/read.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/test.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib-streams.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib-streams.ads (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib-thin.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib-thin.ads (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib.adb (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib.ads (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/ada/zlib.gpr (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/asm586/README.586 (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/asm586/match.S (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/asm686/README.686 (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/asm686/match.S (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/blast/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/blast/README (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/blast/blast.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/blast/blast.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/blast/test.pk (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/blast/test.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/delphi/ZLib.pas (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/delphi/ZLibConst.pas (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/delphi/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/delphi/zlibd32.mak (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib.build (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib.chm (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib.sln (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/Deflater.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/Inflater.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/LICENSE_1_0.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/dotzlib/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/README (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/infback9.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/infback9.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/inffix9.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/inflate9.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/inftree9.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/infback9/inftree9.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/inflate86/inffas86.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/inflate86/inffast.S (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream/test.cpp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream/zfstream.cpp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream/zfstream.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream2/zstream.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream2/zstream_test.cpp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream3/README (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream3/TODO (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream3/test.cc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream3/zfstream.cc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/iostream3/zfstream.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masm686/match.asm (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx64/bld_ml64.bat (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx64/gvmat64.asm (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx64/inffas8664.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx64/inffasx64.asm (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx64/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx86/bld_ml32.bat (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx86/gvmat32.asm (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx86/gvmat32c.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx86/inffas32.asm (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx86/mkasm.bat (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/masmx86/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/ChangeLogUnzip (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/crypt.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/ioapi.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/ioapi.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/iowin32.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/iowin32.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/miniunz.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/minizip.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/mztools.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/mztools.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/unzip.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/unzip.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/zip.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/minizip/zip.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/pascal/example.pas (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/pascal/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/pascal/zlibd32.mak (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/pascal/zlibpas.pas (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/puff/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/puff/README (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/puff/puff.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/puff/puff.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/puff/zeros.raw (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/testzlib/testzlib.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/testzlib/testzlib.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/untgz/Makefile (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/untgz/Makefile.msc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/untgz/untgz.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/readme.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/miniunz.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/minizip.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/testzlib.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/zlib.rc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/zlibstat.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/zlibvc.def (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/zlibvc.sln (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc7/zlibvc.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/miniunz.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/minizip.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/testzlib.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/testzlibdll.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/zlib.rc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/zlibstat.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/zlibvc.def (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/zlibvc.sln (100%) rename {StormLib => src/StormLib}/stormlib/zlib/contrib/vstudio/vc8/zlibvc.vcproj (100%) rename {StormLib => src/StormLib}/stormlib/zlib/crc32.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/crc32.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/deflate.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/deflate.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/example.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/README.examples (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/fitblk.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/gun.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/gzappend.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/gzjoin.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/gzlog.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/gzlog.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/zlib_how.html (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/zpipe.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/examples/zran.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/gzio.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/infback.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inffast.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inffast.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inffixed.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inflate.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inflate.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inftrees.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/inftrees.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/minigzip.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/msdos/Makefile.bor (100%) rename {StormLib => src/StormLib}/stormlib/zlib/msdos/Makefile.dj2 (100%) rename {StormLib => src/StormLib}/stormlib/zlib/msdos/Makefile.emx (100%) rename {StormLib => src/StormLib}/stormlib/zlib/msdos/Makefile.msc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/msdos/Makefile.tc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/Makefile.riscos (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/README (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/descrip.mms (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/os2/Makefile.os2 (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/os2/zlib.def (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/visual-basic.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/old/zlib.html (100%) rename {StormLib => src/StormLib}/stormlib/zlib/projects/README.projects (100%) rename {StormLib => src/StormLib}/stormlib/zlib/projects/visualc6/README.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/projects/visualc6/example.dsp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/projects/visualc6/minigzip.dsp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/projects/visualc6/zlib.dsp (100%) rename {StormLib => src/StormLib}/stormlib/zlib/projects/visualc6/zlib.dsw (100%) rename {StormLib => src/StormLib}/stormlib/zlib/qnx/package.qpg (100%) rename {StormLib => src/StormLib}/stormlib/zlib/trees.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/trees.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/uncompr.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/DLL_FAQ.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/Makefile.bor (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/Makefile.emx (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/Makefile.gcc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/Makefile.msc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/VisualC.txt (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/zlib.def (100%) rename {StormLib => src/StormLib}/stormlib/zlib/win32/zlib1.rc (100%) rename {StormLib => src/StormLib}/stormlib/zlib/zconf.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/zconf.in.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/zlib.3 (100%) rename {StormLib => src/StormLib}/stormlib/zlib/zlib.h (100%) rename {StormLib => src/StormLib}/stormlib/zlib/zutil.c (100%) rename {StormLib => src/StormLib}/stormlib/zlib/zutil.h (100%) rename {StormLib => src/StormLib}/stormlibdll/DllMain.c (100%) rename {StormLib => src/StormLib}/stormlibdll/StormLib.def (100%) rename {StormLib => src/StormLib}/test/Test.cpp (100%) rename bncsutil/src/bncsutil/Makefile => src/bncsutil/Makefile.old (100%) rename {bncsutil/src => src}/bncsutil/bncsutil.h (100%) create mode 100644 src/bncsutil/bncsutil.pro rename {bncsutil/src => src}/bncsutil/bsha1.cpp (100%) rename {bncsutil/src => src}/bncsutil/bsha1.h (100%) rename {bncsutil/src => src}/bncsutil/buffer.h (100%) rename {bncsutil/src => src}/bncsutil/cdkeydecoder.cpp (100%) rename {bncsutil/src => src}/bncsutil/cdkeydecoder.h (100%) rename {bncsutil/src => src}/bncsutil/checkrevision.cpp (100%) rename {bncsutil/src => src}/bncsutil/checkrevision.h (100%) rename {bncsutil/src => src}/bncsutil/debug.c (100%) rename {bncsutil/src => src}/bncsutil/debug.h (100%) rename {bncsutil/src => src}/bncsutil/decodekey.cpp (100%) rename {bncsutil/src => src}/bncsutil/decodekey.h (100%) rename {bncsutil/src => src}/bncsutil/file.cpp (100%) rename {bncsutil/src => src}/bncsutil/file.h (100%) rename {bncsutil/src => src}/bncsutil/gmp.h (100%) rename {bncsutil/src => src}/bncsutil/keytables.h (100%) rename {bncsutil/src => src}/bncsutil/libinfo.cpp (100%) rename {bncsutil/src => src}/bncsutil/libinfo.h (100%) rename {bncsutil/src => src}/bncsutil/ms_stdint.h (100%) rename {bncsutil/src => src}/bncsutil/mutil.h (100%) rename {bncsutil/src => src}/bncsutil/mutil_types.h (100%) rename {bncsutil/src => src}/bncsutil/nls.c (100%) rename {bncsutil/src => src}/bncsutil/nls.h (100%) rename {bncsutil/src => src}/bncsutil/oldauth.cpp (100%) rename {bncsutil/src => src}/bncsutil/oldauth.h (100%) rename {bncsutil/src => src}/bncsutil/pe.c (100%) rename {bncsutil/src => src}/bncsutil/pe.h (100%) rename {bncsutil/src => src}/bncsutil/sha1.c (100%) rename {bncsutil/src => src}/bncsutil/sha1.h (100%) rename {bncsutil/src => src}/bncsutil/stack.c (100%) rename {bncsutil/src => src}/bncsutil/stack.h (100%) create mode 100644 src/cli/cli.pro rename {ghost => src/cli}/main.cpp (80%) rename {ghost configurator => src/ghost configurator}/ReadMe.txt (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator.sln (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/Form1.Designer.vb (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/Form1.resx (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/Form1.vb (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/Application.Designer.vb (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/Application.myapp (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/AssemblyInfo.vb (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/Resources.Designer.vb (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/Resources.resx (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/Settings.Designer.vb (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/Settings.settings (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/My Project/app.manifest (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/Resources/parametres 3D.ico (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/bin/Debug/ghost.cfg (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/ghost configurator.vbproj (100%) rename {ghost configurator => src/ghost configurator}/ghost configurator/ghost configurator.vbproj.user (100%) create mode 100644 src/lib.pri rename {ghost => src/libghost}/StormLibRAS.lib (100%) rename {ghost => src/libghost}/bncsutilinterface.cpp (100%) rename {ghost => src/libghost}/bncsutilinterface.h (100%) rename {ghost => src/libghost}/bnet.cpp (78%) rename {ghost => src/libghost}/bnet.h (84%) rename {ghost => src/libghost}/bnetprotocol.cpp (100%) rename {ghost => src/libghost}/bnetprotocol.h (100%) rename {ghost => src/libghost}/bnlsclient.cpp (100%) rename {ghost => src/libghost}/bnlsclient.h (100%) rename {ghost => src/libghost}/bnlsprotocol.cpp (100%) rename {ghost => src/libghost}/bnlsprotocol.h (100%) rename {ghost => src/libghost}/commandpacket.cpp (100%) rename {ghost => src/libghost}/commandpacket.h (100%) rename {ghost => src/libghost}/config.cpp (100%) rename {ghost => src/libghost}/config.h (100%) rename {ghost => src/libghost}/crc32.cpp (100%) rename {ghost => src/libghost}/crc32.h (100%) rename {ghost => src/libghost}/csvparser.cpp (100%) rename {ghost => src/libghost}/csvparser.h (100%) rename {ghost => src/libghost}/game.cpp (81%) rename {ghost => src/libghost}/game.h (100%) rename {ghost => src/libghost}/game_admin.cpp (75%) rename {ghost => src/libghost}/game_admin.h (100%) rename {ghost => src/libghost}/game_base.cpp (91%) rename {ghost => src/libghost}/game_base.h (97%) rename {ghost => src/libghost}/gameplayer.cpp (94%) rename {ghost => src/libghost}/gameplayer.h (100%) rename {ghost => src/libghost}/gameprotocol.cpp (100%) rename {ghost => src/libghost}/gameprotocol.h (100%) rename {ghost => src/libghost}/gameslot.cpp (100%) rename {ghost => src/libghost}/gameslot.h (100%) rename {ghost => src/libghost}/ghost.cpp (88%) rename {ghost => src/libghost}/ghost.h (88%) rename {ghost => src/libghost}/ghost.vcproj (100%) create mode 100644 src/libghost/ghost_p.h rename {ghost => src/libghost}/ghostdb.cpp (100%) rename {ghost => src/libghost}/ghostdb.h (100%) rename {ghost => src/libghost}/ghostdbmysql.cpp (100%) rename {ghost => src/libghost}/ghostdbmysql.h (100%) rename {ghost => src/libghost}/ghostdbsqlite.cpp (100%) rename {ghost => src/libghost}/ghostdbsqlite.h (100%) rename {ghost => src/libghost}/gpsprotocol.cpp (100%) rename {ghost => src/libghost}/gpsprotocol.h (100%) rename {ghost => src/libghost}/includes.h (100%) rename {ghost => src/libghost}/interfaces.h (55%) rename {ghost => src/libghost}/language.cpp (77%) create mode 100644 src/libghost/language.h rename ghost/ghost.pro => src/libghost/libghost.pro (67%) create mode 100644 src/libghost/main.cpp rename {ghost => src/libghost}/map.cpp (100%) rename {ghost => src/libghost}/map.h (100%) rename {ghost => src/libghost}/mpqarchive.cpp (100%) rename {ghost => src/libghost}/mpqarchive.h (100%) rename {ghost => src/libghost}/mpqfile.cpp (100%) rename {ghost => src/libghost}/mpqfile.h (100%) rename {ghost => src/libghost}/next_combination.h (100%) rename {ghost => src/libghost}/packed.cpp (100%) rename {ghost => src/libghost}/packed.h (100%) rename {ghost => src/libghost}/replay.cpp (100%) rename {ghost => src/libghost}/replay.h (100%) rename {ghost => src/libghost}/savegame.cpp (100%) rename {ghost => src/libghost}/savegame.h (100%) rename {ghost => src/libghost}/sha1.cpp (100%) rename {ghost => src/libghost}/sha1.h (100%) rename {ghost => src/libghost}/sqlite3.c (100%) rename {ghost => src/libghost}/sqlite3.h (100%) rename {ghost => src/libghost}/sqlite3ext.h (100%) rename {ghost => src/libghost}/stats.cpp (100%) rename {ghost => src/libghost}/stats.h (100%) rename {ghost => src/libghost}/statsdota.cpp (100%) rename {ghost => src/libghost}/statsdota.h (100%) rename {ghost => src/libghost}/statsw3mmd.cpp (100%) rename {ghost => src/libghost}/statsw3mmd.h (100%) create mode 100644 src/libghost/ttmath/CHANGELOG create mode 100644 src/libghost/ttmath/COPYRIGHT create mode 100644 src/libghost/ttmath/README create mode 100644 src/libghost/ttmath/samples/Makefile create mode 100644 src/libghost/ttmath/samples/big.cpp create mode 100644 src/libghost/ttmath/samples/big2.cpp create mode 100644 src/libghost/ttmath/samples/int.cpp create mode 100644 src/libghost/ttmath/samples/parser.cpp create mode 100644 src/libghost/ttmath/samples/uint.cpp create mode 100644 src/libghost/ttmath/ttmath/ttmath.h create mode 100644 src/libghost/ttmath/ttmath/ttmathbig.h create mode 100644 src/libghost/ttmath/ttmath/ttmathint.h create mode 100644 src/libghost/ttmath/ttmath/ttmathmisc.h create mode 100644 src/libghost/ttmath/ttmath/ttmathobjects.h create mode 100644 src/libghost/ttmath/ttmath/ttmathparser.h create mode 100644 src/libghost/ttmath/ttmath/ttmaththreads.h create mode 100644 src/libghost/ttmath/ttmath/ttmathtypes.h create mode 100644 src/libghost/ttmath/ttmath/ttmathuint.h create mode 100644 src/libghost/ttmath/ttmath/ttmathuint_noasm.h create mode 100644 src/libghost/ttmath/ttmath/ttmathuint_x86.h create mode 100644 src/libghost/ttmath/ttmath/ttmathuint_x86_64.h create mode 100644 src/libghost/ttmath/ttmath/ttmathuint_x86_64_msvc.asm rename {ghost => src/libghost}/util.cpp (100%) rename {ghost => src/libghost}/util.h (100%) rename {ghost => src/libghost}/w3g_actions.txt (100%) rename {ghost => src/libghost}/w3g_format.txt (100%) create mode 100755 src/plugins/cmd_builtin/cmd_builtin.pro rename {ghost => src/plugins}/cmd_builtin/commands.cpp (67%) rename {ghost => src/plugins}/cmd_builtin/commands.h (59%) create mode 100644 src/plugins/plugin.pri create mode 100644 src/plugins/plugins.pro rename {update_dota_elo => src/update_dota_elo}/Makefile (100%) rename {update_dota_elo => src/update_dota_elo}/elo.cpp (100%) rename {update_dota_elo => src/update_dota_elo}/elo.h (100%) rename {update_dota_elo => src/update_dota_elo}/update_dota_elo.cpp (100%) rename {update_dota_elo => src/update_dota_elo}/update_dota_elo.vcproj (100%) rename {update_w3mmd_elo => src/update_w3mmd_elo}/Makefile (100%) rename {update_w3mmd_elo => src/update_w3mmd_elo}/elo.cpp (100%) rename {update_w3mmd_elo => src/update_w3mmd_elo}/elo.h (100%) rename {update_w3mmd_elo => src/update_w3mmd_elo}/update_w3mmd_elo.cpp (100%) rename {update_w3mmd_elo => src/update_w3mmd_elo}/update_w3mmd_elo.vcproj (100%) delete mode 100644 zlib/DLL_FAQ.txt delete mode 100644 zlib/README.txt delete mode 100644 zlib/USAGE.txt delete mode 100644 zlib/lib/zdll.exp delete mode 100644 zlib/lib/zdll.lib delete mode 100644 zlib/lib/zlib.def delete mode 100644 zlib/test/example_d.exe delete mode 100644 zlib/test/minigzip_d.exe delete mode 100644 zlib/test/testzlib_d.exe delete mode 100644 zlib/test/untgz_d.exe diff --git a/default.cfg b/bin/default.cfg similarity index 100% rename from default.cfg rename to bin/default.cfg diff --git a/gameloaded.txt b/bin/gameloaded.txt similarity index 100% rename from gameloaded.txt rename to bin/gameloaded.txt diff --git a/gameover.txt b/bin/gameover.txt similarity index 100% rename from gameover.txt rename to bin/gameover.txt diff --git a/ghost dynamic configurator.exe b/bin/ghost dynamic configurator.exe similarity index 100% rename from ghost dynamic configurator.exe rename to bin/ghost dynamic configurator.exe diff --git a/ip-to-country.csv b/bin/ip-to-country.csv similarity index 100% rename from ip-to-country.csv rename to bin/ip-to-country.csv diff --git a/ipblacklist.txt b/bin/ipblacklist.txt similarity index 100% rename from ipblacklist.txt rename to bin/ipblacklist.txt diff --git a/language.cfg b/bin/language.cfg similarity index 100% rename from language.cfg rename to bin/language.cfg diff --git a/language_german.cfg b/bin/language_german.cfg similarity index 100% rename from language_german.cfg rename to bin/language_german.cfg diff --git a/language_russian.cfg b/bin/language_russian.cfg similarity index 100% rename from language_russian.cfg rename to bin/language_russian.cfg diff --git a/language_spanish.cfg b/bin/language_spanish.cfg similarity index 100% rename from language_spanish.cfg rename to bin/language_spanish.cfg diff --git a/language_turkish.cfg b/bin/language_turkish.cfg similarity index 100% rename from language_turkish.cfg rename to bin/language_turkish.cfg diff --git a/bin/license.txt b/bin/license.txt new file mode 100644 index 0000000..0507f2e --- /dev/null +++ b/bin/license.txt @@ -0,0 +1,13 @@ + Copyright [2008] [Trevor Hogan] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/mapcfgs/wormwar.cfg b/bin/mapcfgs/wormwar.cfg similarity index 100% rename from mapcfgs/wormwar.cfg rename to bin/mapcfgs/wormwar.cfg diff --git a/mysql_create_tables_v1.sql b/bin/mysql_create_tables_v1.sql similarity index 100% rename from mysql_create_tables_v1.sql rename to bin/mysql_create_tables_v1.sql diff --git a/mysql_create_tables_v2.sql b/bin/mysql_create_tables_v2.sql similarity index 100% rename from mysql_create_tables_v2.sql rename to bin/mysql_create_tables_v2.sql diff --git a/mysql_upgrade_v1-v2.sql b/bin/mysql_upgrade_v1-v2.sql similarity index 100% rename from mysql_upgrade_v1-v2.sql rename to bin/mysql_upgrade_v1-v2.sql diff --git a/readme.txt b/bin/readme.txt similarity index 100% rename from readme.txt rename to bin/readme.txt diff --git a/update_dota_elo.cfg b/bin/update_dota_elo.cfg similarity index 100% rename from update_dota_elo.cfg rename to bin/update_dota_elo.cfg diff --git a/update_dota_elo.exe b/bin/update_dota_elo.exe similarity index 100% rename from update_dota_elo.exe rename to bin/update_dota_elo.exe diff --git a/update_w3mmd_elo.cfg b/bin/update_w3mmd_elo.cfg similarity index 100% rename from update_w3mmd_elo.cfg rename to bin/update_w3mmd_elo.cfg diff --git a/update_w3mmd_elo.exe b/bin/update_w3mmd_elo.exe similarity index 100% rename from update_w3mmd_elo.exe rename to bin/update_w3mmd_elo.exe diff --git a/bncsutil/product_version b/bncsutil/product_version deleted file mode 100644 index 1892b92..0000000 --- a/bncsutil/product_version +++ /dev/null @@ -1 +0,0 @@ -1.3.2 diff --git a/bncsutil/vc8_build/BNCSutil.vcproj b/bncsutil/vc8_build/BNCSutil.vcproj deleted file mode 100644 index 8c04042..0000000 --- a/bncsutil/vc8_build/BNCSutil.vcproj +++ /dev/null @@ -1,626 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bncsutil/vc8_build/bncsutil.def b/bncsutil/vc8_build/bncsutil.def deleted file mode 100644 index 32db61d..0000000 --- a/bncsutil/vc8_build/bncsutil.def +++ /dev/null @@ -1,45 +0,0 @@ -LIBRARY BNCSutil -VERSION 1.1 -EXPORTS - bncsutil_getVersion=_bncsutil_getVersion@0 @1 - bncsutil_getVersionString=_bncsutil_getVersionString@4 @2 - - calcHashBuf=_calcHashBuf@12 @3 - doubleHashPassword=_doubleHashPassword@16 @4 - hashPassword=_hashPassword@8 @5 - - kd_quick=_kd_quick@28 - kd_init=_kd_init@0 @6 - kd_create=_kd_create@8 @7 - kd_free=_kd_free@4 @8 - kd_val2Length=_kd_val2Length@4 @9 - kd_product=_kd_product@4 @10 - kd_val1=_kd_val1@4 @11 - kd_val2=_kd_val2@4 @12 - kd_longVal2=_kd_longVal2@8 @13 - kd_calculateHash=_kd_calculateHash@12 @14 - kd_getHash=_kd_getHash@8 @15 - kd_isValid=_kd_isValid@4 @16 - - checkRevision=_checkRevision@20 @17 - checkRevisionFlat=_checkRevisionFlat@24 @18 - getExeInfo=_getExeInfo@20 @19 - - extractMPQNumber=_extractMPQNumber@4 @20 - - nls_account_create=_nls_account_create@12 @21 - nls_account_logon=_nls_account_logon@12 @22 - nls_free=_nls_free@4 @23 - nls_get_A=_nls_get_A@8 @24 - nls_get_K=_nls_get_K@12 @25 - nls_get_M1=_nls_get_M1@16 @26 - nls_get_S=_nls_get_S@16 @27 - nls_get_v=_nls_get_v@12 @28 - nls_init=_nls_init@8 @29 - nls_init_l=_nls_init_l@16 @30 - nls_reinit=_nls_reinit@12 @31 - nls_reinit_l=_nls_reinit_l@20 @32 - nls_check_M2=_nls_check_M2@16 @33 - nls_check_signature=_nls_check_signature@8 @34 - nls_account_change_proof=_nls_account_change_proof@20 @35 - \ No newline at end of file diff --git a/bncsutil/vc8_build/gmp.lib b/bncsutil/vc8_build/gmp.lib deleted file mode 100644 index b5e2d63b077ec866153a8b4cdb5a72c92cf976b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1659142 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

~ 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�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≺7^S%4~K@nl1(N!Y+v=Fl3~g+)B+E3 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

cCkZ2d#gSE2iWGNZ=9uEDB-)6SPu-&ho9A!qi{x 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 diff --git a/ghost.exe b/ghost.exe deleted file mode 100644 index ceac20a62e6ab025571185906e4c4b561cfb992f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1552896 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ΞI2$5Ph)n$dL-O?Nw~n(94maQj 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�UsN zw@&%v(Lq5p(G%e_-cXxo{_!Ja&6$!N&9kr%ah({AaCy}ZwKiE8Shs=y`pxe*el!?1 z9~U5#Z~&JBXdP?vASUrT=OBRq$pKqY#D<9vl;zRWS2xavPfXOY_NekIwF|&3H2N%n zNgv3xKea^5-)h>M5A6=e-^wZ`{04yU>8o8O!RW-l+VTesEU>R8j=YQ$cyTxnPQN@W zRv?yOQyG1*Ib@zHH%GL780$w}&4fsP|3i#BvFK;e+%ui-Dru3IPoyrxzP~u$ZqI7J zKzPT-eAU{S(h$6nxf@IUbW6hjziIv#P0ab>mPAzD~XD(jLT9ZAA%7Fu} zPUYbYdX+_CTSe30#dgw#LnPpgm8Cpy%eGTjIa$~9*g^qh#WH1?$m zn28(FMPfqYW_$O73f4YR>!55-VyQC`b967LN-QA$y&wtq2$&SkhJ$YP|>OCR@;rKQJ*WC^H|i#kN_D`2zvi4-~-4nilp|C*R1l$8d@2k1+P za&>W3V)MI+&Hs-~7pnAm@HgXyy4vxSQwYW(s0=nNoco86i{RM=Gz%~BJsw4*gdqCJ zhdB@`_8CQV`!q;Kz9euKo7(Cu0l*W?#~)E_y;wor&V=&a5@xCGw+68|V7FZBe@}B5 z>b5vL+Oh{>BP7sqpsu0)rikMPcu@hF`Do?XZ}Db&3Vo(6s{PXY&1(Gue!=ofuk%io zoL=sM3-t}uEktABOp&mL9g6x*Zj6{$?J*c_W1soJVTEA4yc^LHc@0>1hoSmSxQ!|y=B&P}t6EMi?nLlhWqe#`{13l7 zVd2D!*VxtA3;s@^)@P4!{q8cFw`7d|z~&5iqaE9TC7=VpQcn zrG3Y?E{X5VB6t0mRMetVB>_`_fcX?#PrmqYC#eRAWpy+O0%m-M^ZLBV`r zL4}ZuUIrm{L#Ne7osaA8=pOech0J#lV=@f$HngFsG5Cxpl&v-MpCvd;b2E(q@6{;e zm=rfGVc^aQ++{KWqT1iJpT9)4zyA;XO}Gc|eqH|FCErr{LG!ci3U#C;Hyv;!$6)Xw zO}hu9=VL5=PT*myrH8GS?p7_0w_18wwUpOvdUZ=OD#+T!GPT&qxDoy4qq^yl=hO0s zU#Q|oESS1gldv>tR)3p?QTF1~somd&U0B;*svP|DlxIJ9ua{+H<{1vqA#?F$wda!Y zNvV%m$(As_(9mb0s<5iw_y-g5n;RQ6y%;hnL?t{Y0ISM2HgN_0EB2g}H1>wf_oTrU zsI`S<$?)o5FyH9Cei(x`cHF+)77BCf;ytp^7@8Z!ise;dW4$2y^At@MKt5G&I#BZ| zS#dL0%kjs@dvX^p;JOy|JCORkVm|#e((I7=>kmF6Ow?kUB+vn)aA>&k=tvDG=tvDN zVau=W4VmA6MZ?aOXbBb;_wX#esEtfe?2{y9pi|-u5aUekKUeU3)HTYzaJaO@-y6NW zT-g_mQeL*pfpa8iQ+R>Il{mNNtzB*H7~cO9jbVPTQBxi0&)hMq8&7kKc`F(lb(a7J zZ)B)GuqBZ?S_hkrqj1wGZ-omKfdYQ@d!kc0QGQ!Af7;6kp8tZ1fu-{rJI#B)&PU4S z^d+(b4_T1>kOj$I3X*dMlj=-7l!oM4x2rRuuEqV=1H^+F5lMEK`)HD-hm*8oP{4ZL zR6X?o@_=zIL!75#GSdsryhMsC#NHt*jc+rM#RtFnl3G4bx}@HrG|-w4tKvNv(T6sn&PXwY;Wz2eoGBLmM{;23#nP4_3!BRTItGn{>y!iQq3C zzoa@|WHqs-5VUbFku=UwrNg6?=H(^2G&m!3#p3%L^b&9_Hj19A2D;3{?4q%k5ln2Y z7S7~__Z0sL3wB~_HTaUZC6+-LCx?%om4XbgOFA?^A5&OP4QROBLDN%Y8 zGlU_!5u>3*vp~es1n$|A>akgHR2!5gHxcL~+GS!!L82L2q!PLISCxY?2K%cj%lQ31VRKFa|Dhn;H$W;w$O z%yP0ZN??`+3wy(6=_++9`276y@%=Jl6^nzsB|Xq`3Gi1)C@Kbm+CkEl`s9|7wm%el z*mfT*YqZQ*XfOWDGma_Z`&^q9*c+Sd+Bn&8t=;wqWE@D>c60E-ip}x9oSL;qPp4el zD{(rgU@_gs?)W=rb{sh~dhKHsv6jbtuFkcx<~uvy_IAAQh^}Ow1(ACAMDw@ztKkkg zJ;%3udR-gW-!zT}^Jp&q(b(0G$vMLhDMyCtS|4IzQx7tcl1=qx%{Ca4F`KUD1G^%w zt&-LosVN5X`O?8E)q!V32Wk8Yz50SPRNNCL@MVyAm&VEK#AAU{N^xDp6E&uQdu8r!gYvaB0dfH3T@f8yEa!1?G(b5T@p9%kr*)Af* zqA5mhm{DXm2^yI;SnPCm!CFLwpu2d1QFQzODP zpWw>zU*fn9H)TG(Qr3rNFeOPhleC(7RyQ+is2NP6AacS9N|2SFn@2XaR5dl+Os&<- zPMW!9NuqYB8PbL@8k+Go(#)+iBdGge^dv}I30I;ez+vH%_^fORp+LwS3G9Hhg=nc4 zF#3gwTy^<#%9_hDcTn|gIrwhuOC*3S6~ngFTL;D<)u)p8F?;mZvdONldAutNkuRWGJ~T_*?fmwI{Pq~lZaIubp}Pgy zDi)Y(@;z;0K__UDpwS;nPPLNwHmBq?gJG%NA124yI8+c1fy;zJgFlxmGS=HwVnv_d z_Cr-W7j#mNfCX*X5#WR)a)L4IL!93v^Bjwyn!iR+aS>9rN#>h3v4eD#sC4#=rW9UF zpj56=%ZvX~7O}VAs5}<)4YyJL=P(S1Gd*6{`i)W^>=!laJk%^yi4pox zQF3BT%Y;g0Hu*9eHJMk<-Lys7k{V_dh}he{#uvY9iy+tnX6G)gye8gP8u%6KTHsoL z3sXpoVe@;NA|0S6_Po^m?Y)W)WT2<~US1SMo)F~qw0bLoX;lD9k>4AR9N<-IEASIn z@v{LUpYRpA1ooBrOD;iUpL{aE_%oJhFJac@#Ln}(iEE*vt=HA_S|!V1|0QecoV!)B zDdSah=Z2$@Pr?s!S8e+~)%AM#u?|S)!w@w$DYwb3{|$#tj`Y^7D)XefDJCG!axncu zMj3(yoXy$)x)c+znC`%IIi%xLcJVMykka>}=U5q5r=X^oz385@W#lc*h^7ClMD%Wz zDwQ#$^Q4jo*~*hzVAK~$9LSphQi2&F20B3`>1bFb0clEB-fh{cNbK6XA6Ejbas4z# z4T)WQT&&7=ajL~_XJqVLK~q*kVn$!98p137xa#NY>X?ypatAZL9$FW%7=NK6>m%v3 zyxc+AlVbu<%Gp-dP1-OkUzv!#%H0v>Nfj-;G zvKE;OK@)!+>isLKHfuOrWr^S^oCXT;T`6Ebk9`s$%-85kX6}XuH_MoYqJX2 z8s&@V-3Oy*uM4Rh6Q^?^bZ&{sBhEwH2FWe4aDMMXfpJ90BmOmtqAibms*b=ODOv&! zS*a9)c7;HWnE~`f^jj6KjXA~)yAEYnq_K!k=z)ZE>9S+5A`Ef8>!BVesRoGp4<_fY#=ThI3lBf-(N{j7@-%ik|iAK1dh44&IG&_iplT}x5EO&6c zkSev`BH5;08}5<)&9&kSq+|d3*PO<|+x26X5!?u_5m7+}L%5XIhN8U^16UHQmve%X zp5k8f@_?StH@yeom2tS@#RF%2J7uf90fni_c6vkw6Zd-@{oBu*Epd(^ZX6G zE3ie&={LyNdZ7tk;}yh?ht$07YH5yHlGhczQPr(6m&VJoSnc*RWT!~dH#T;X-ldn6 z(p)gTLh?+*mz+L`_SALP!^p=-SZ3Z2=h1K0|5#BykFmG8F{E(prLruXOof|O{9hh` zUx`ots#!+yf%&u`%PwP+PB}lQwJVV&Hs*S14jh`_nZHvoA8Qx3Q?+0rIT;yHVQ%n?v@DEhJ3F8XKVm3nO0(MFR-z1F&3h5bj+4j7+RNj=E=xSZnLZ;l%D`{r?58KdjBo~G-7d8z z@T9zjtt4(&?_G+k9C(yRsnZ31$Wf>aowie*@BXm)=R0Mf z0$3%+wME?GugxHor|VuMBFbP59++vmr5yChER{z48B0V%b7Zg4)^O_&wzjh+A(~-J z(nkY(lDF@hY0LlWOxxVA&9vRhvG@&tALVBk&q}Qyc_xQc6vU2Z;}p4eC2#zOJ8bL% z;keC?FIp0W7+0&X8UB3^3e<<4iLhfyVqvZ*4N>$qmQlMPaTzdEe6SlOQpDNyT6<-3 zwiEP5ymA;^f_F8U#q;znKmwP;ffyB{bIVU;twYirc68e(*OFy9zJo~TQm?IFtALKd z#=_6})cvajs=C8$XWoKq`M6vboNX3zP6wsNDz9r}7U6Mdy`PN%Oav_}q%F*P{O}mT zF5_Ys0#GH!a)FNuj2=noQT!|~F`8&Hb_ibs4vCrn_<>qsxMe8~DxnXI$H>w-iOyf) zEuG7Y`U){?AZ;u71E^hB1!L(|Ol1|Ayj~VIHHi#tRXPJ(Tr#k^jlWSYU8q^ow3Vwg zZJCA2Nhd*{q3QG~rkkIYK9T*$dycU6T>V{lNy-G!pyOMhK@w#`2)uwuSmBvsDULHy zQz)$P%vAYq;Tc!w&jiJx$FXqDz<1<3qYwrh3$jqWe~chfZb);?f$vij6+sL4RX10V z>qQq5Yf-WIBs5Q^Z!)>5TQ!1XRTHx$_llE0-58h3Lf~gr)t56!Bfz=RM>kw~cJ0??XZ;RTUz zqeUQzIAA2!V3SMR7gMC#xK2EybABs!?1C*%qZpGZg;HN+d7Y*m=E?e%qq<9b$!F%j zp;t+!s#jLsD@j&Gwj7%es$?i1)Vt(^N;OlyS`P)) zEf6jzRgcE2MX>CmE--Cfv*HG)!VS(?WDIgYa&R3D*BFpN*_QsVn)0d_rM+wIk`-VgTDM zHkv8G{LIq`5Eft&;3>xK#Q$DBNjfaT zn@WgE2OXzQHf9jIbd51*t21feihtM~){K|j7w9S<>c>vc#kg{LJp!S?K7=A@>@kwG zOEGWi3Zud;o(xVTKox|qRJRAEBN`qcKoM+Ym?cboPNNxOFR6>pNUT@pEL=bjrvj!T zTJfM67egi3orKt2I91qahqfyd>pihAOK&&yv`ECQ*oMdrm7Onst;`!1vL~x8TkqQN zCl){eA*KDhyhczs20YwRv&#P<11oGax5DKclNplIjURS(-A6swleI<0tb&|gIn4Q6 zk$X;6s`0U?#w(uw5G_vgh?uHMFMi$VdT||3^~$trJa8a+bJm(mFd5ikwyYQOjD#w7 z79nC=2-fn@@06$%HTY)Ho)2rkoAW`IvTW5NgYr}bylR%~&*E6<15-4-JgkqhCxVO= zc5D&oM<3)g#>#TY9=p0$@~mTxq^c4ji&&8e=u7r^SJ(A?0_l|W)w#0-2zPEZbFs!k znkbt`n)$cMo&<=Pmm>Bc0Q7cy*@dnRlc`m_hrQ1ypA~s@$MMl8_NZ@5@6(xNbZqP3 zKri3cWtHC_b(BBo>Uvn-Az%`J!LRVywdG3JmTU7lZiDTo8CQFgA)m@8Q#MY{+qTj` zKj%$uP)>c$b{Y*YU<0#yf^jXnuGM2VDbUU{mI2z=8}>fPir*IV@W*S5c_U(pAgp74 zW2#s^b9H`!^%GZLsBEw)(k=Ju7nh6V&Z$ac=EQpGib05=dGBYHSWh4}*lKGr-$DEl z-!6LGd|9)a_%=`ALRkgZ`hNiKvICSY3cHDPKEpNtd!5^B-Mg(hpoN@GS`lkB* znEHK>{LX-XAFcZ7wE({IJW)I(+itSu49b7wMUGox;(T+(B6t%q6O!oq&M;RY^Xk0{ zzL*qzLBbo@haEj|7I+sPNzi41YlDRJr=4qz9)8&gbsbDS96#bsRYrTgrNSBksVc>Z&it23)L1&B9ysE*us;9AV%D z_Wok@2R@4BGWYz{k)wZuI+H8#V)N!}-rxNN=*?CY#~>)w(R> z)y|&i>8_2$`A&xrj$10CPYxj*o6oxDcYA~u`6`0p$R;+8ehbaEWeTK3gEC4g1|5do zWrblMO2tq&Pb%5ty9SL9*ue2Mfg43j78Hn;+k+s@QUJ_f8SnSRd%RYXddY9-r&om2 zWK$VT5x#hoKEEc+L*nFP`+WI&)u-^FYH2&aD<_mAz$l27Uu}F~?3H+&V>!;}Sn=ei zSn=d1r{l?I{g=|`D@A51FKD*wMp2&;Lo(J&bKc{s>hZXbty*P`2Y6+^rTvTsvnICN zrgi^mUV*=gM)>p@iSL&@$ra6pS9ukv6g~Mwh7maFksXos;irfn@hTJ^vz(s_eyaJY zmrUc6_)v(So(QkTP?PgLC*C(%Q5jZ5C=EV8I$kDnQCTGeS&jS`n%B|@q?MZg!L?ni zBk@@wM*eH5GC73!T(V@&t}X)UShS{m7!@g;q{PJ>E`mpsK69_JqtzCFYhQe4 zMROQW0`sQJl!iXOrh>yNZV8x`0YG__ln=2(PX&3HxY=p;vfpY%OIks%Ve`S4)ey?J0bWM0ENpGR)WTCC$aetXz^u#of1V0 zRErf~>#x;{Y1K`yzP1lf%BXXO7*{?yc;EgSH=P5Cm6B`JNyP802Nli6gn76)^cJlh zjG$N2L6yxfa&_G-SJ5`0;#G5Y?C4CC+?g?aKR1}!2)^Qos@+whQJb1sw!K;vkN&7mc?cO3MBWty@&vwqJ zDumP+RRXXPX@kn}4}WmFZh^3iEi0nF9-=z46KD(cbVXeWy&Q zP=ae^GRHL}O$?1i(g%NJcB;l8Fme_x?`nM;Q;}Z?XiVtGA$34n8FEZsXjaFK6Id|R z1Oo82&S8OmEZdWgFsl+Ko_hSSkJB2dVRHe@)Ly8BiI$hX(%-!FRke@9N+;`rq+K!b@f%lW}y&&q!k&6v=vk~iu4~-(|l1xdqoNDVT}tz_~l3j9Zm<(?KQ>+ zE?$i#G8cf2hJ9_=thrhp3M^Ny?Zp{)Uk1MsWLM^~GINY<1?h`IMl3&UltFBYFbCjI ziE*ogwlLX8`oi8w&Um3i;M!47^=^j1BOt@tDiMqE6RP3__mjgz9OL z?TS(G1ZuJx<&c<&mEs+fEB7%U_sohWTCHcCkzivV-cecI^ZYZ}-Gip{kiilDjtreI=bzUggL^0yMsNC!YWCJ`%0%q)!IFp_WVLdTqE z>@+G#mKZyPLp*8io0@~>6GS1VA@=xJEF?DQ{Qz^J`Ahl2c7>qv!rpy^;)JmY)sZxw zw^9B!0VYObF1wd*5AYFN{vh#C`pt#%N@QTdXTX1i8Y_aWeqPkdi~Ia?0X46aYEgCM zB#lI<$#Am_5xKntvB7Mj+>a^O7;I@WC;UNmzbd|cE?4zOWN@q+B|Xh(>sx7g|CjYG zFO#MAmj*TDsH8nk85CHyi{nB zO)Y9ngv4<>V$>9ZY?TzX&|Gxs5FF_ZmWU5KsKkyNwMB^;&=kXlgOfMl%Ljcrz`?nk`0#Q6%SZ?`LG3qSKGcE(ttA zHWM+)r`cI6Qt zMHF0Y)K@1Pvl79P2X@=tBTov&t(8^s)jr$D9@wG73c6*Ui|GR;w;yMTCJyU7!4Hc# zu=82x#r#CfLnT8CEld1a8SrZREu``?Ru`ZuJ=(*W4>pmlehzI#T7uS*6OruvLUR+< zN!$jIisp^hBjycrg*zbMr?N~Wz(9!U7A9E4`Cjt@c+_>G;(#~i3?^2~@k`7vO3W`Q z2dn)ZXf7W^hEF+;iaC_yD9oXC9Ff?VejO55h#DqZm$KOyDfF2a$OpDA+|r0n@JoVm z^=X8Kl;hZErZ!Nb)){VQMU;xSs8vK!c;49zjLgGFcPs0VM8idu1iLrYsf;g(#=L)EFD+Z7VCQ zb>gBF%E)2jP;1T+X$(CDn>}cr0vhQj%QJF#b~D~@kAIZiwp9V%bU8GO>G6jQL(Wt_ zIr-ivXbS~-awDCI=t3X?mA=S+@f^E`4)T>{>`(U$4q`%7WLd@*SeCIqL){T+ATsja znx>Rt^CZ=WU5cb1Y8D22S&obb78E@ku<0}Zo3O(^(qea zBBXQ{hw4=vY7qlRJ*Ze+kA+rB`)t*MFpp>Vq-?Dix0T{u7@XeJ*t!so@;Vx&nV>SV zX$ZD}r2E0BJSvR$XNMbcXqSE7VO}f+6~9*z-%gtE5oSAboJ6ZP%UOX1o1@A6N~@ee zu`JYyk-ds7zR6I4DXI#xBxS^AA664FejOZfB!4W8XP3^M5*?Q|a`PzbQ+h2#E4{j?PUcCJ{D9e!+DVPjqB(tLuI&7 zsSJrlvl@S4tul13bv*;?r6_?LX0;gfO^X8BUZkOoc=i$9w9(z&m^DIe_>EcIbEOu7 zgG8mfuQF>em7zA=FX#%p6k~Kq9!{9&iD&|%eVGMlN$fM~b`V`fUF6`0qlp}D%A z6CrJe>6{?y@@`UWN%ET!YN>%oq$vH)atK=`!K=PXBkExDbOopH7dOZ-Jp-#KdCz-K z&a?$K&a^%K3;pBdFr+V3Yxj4^f_3`UAs5*}1atM*!p8sjMS}xw!Z3-SxdK_{ELNPe zQb>$-u1i~k&69~Lnw(P-dQA!_X;=<%YL8s0Vmlz5RLhlrQo@0cZ zOA-y)6IfU*UOh5UnFs|6WD=bs|CFf$8X|J{CY`^eEt}a*q-ZHD-A)4kP~UGfVVx5A zpnXz&8&kMsR-&Z4QY7>*w*5_2t==N~ka>q-}}K)++DO273xnu}iTdUC^FJ_NR| zxl#)@IZh?U#KAj7xM`^0fji&gb3)Oj_B9FhEwxgmwG}X4yS;NTcXf&|+}N6&vx#L~l?#1UPVLTh*OZYo6m-*#!}x}OO6P*ySxC&| zwh8|h1bC_~dFCvq;dE@a(G<wWSuxfi^A^;;0v~CXJsIGQ&dt7yZ4bUoFNYJ&uh{2^Ch%?p$ zoWdCSjVJUl|3`J%j1z@d91!oSRVcO`&_z+;Tb8Kw#`36BJupSUX)@tpSC-?EOtYm% zU1>m8Jh-MZ8D5IISZpNZXHwu5KF@0#mz+~HSjMMzF^RACR>t2S*Y*bE3?@AnPurRZ zmt*dna>)auu0CgHa%om#cD*IeiYg)WJVm?zJ8t1najp6^A}!&K8KE$d0LV<>Iy$!a z;K1W-g$3GWt|z~yK>Ns=3$?ounA~qTG-xN3I>JzSp#vMhec@c$GjhOgOo)u)By0}Ob47@xQAkndhD6;c1(zna&{mHj!~$zLfzMnNDCUo@IN(Q->>fV0OGlT zrz$rtP`3KiVL)Uv%TX0KnipT1hQuHnS?)<>!6tO)kFCS-3m_9oSFr8gG~yNk&=U%* zBIZn#KMV5{*ZPe*FP?LUF9f`3m3ft2mybc|HdTbIB;Jtu8ZUXlBnyL-{qcYrU)jPU zSLZH(uzcFJ%7uMIx&z}(u82jPrlvs+58Sfh_m^y{&SKX(b>Wl z1TzTqoV6B9pqN<=of0^mal#OidP$|4%rv2fNDtHZlXUeX(m0Q)}hasaG zBG;5yXNYXDG`;e-2^K;G7nPZR=Sm?6b=gnZI>bkEtML*%<&wa*Xfd$ysk4|nE43QS zf`L_qiMa(<2bHRW*~dF!j^4q?=;r>jLU&*RkKXdcb%nA!f+FCGD&=+$4T^8ePK3lb zuKs7^y6^KdEn7kp{_b!3*UGnV`n&ZXxq^0!Lt=wJ%2jcb-QC1VBvgFQp7 z+T2dJbGB~h0%=E^pCK-@nnPmtF|*-H2Zf%?nX0CuztJLntp~zQ+}b+*f|)ViPImeq z;gcCuX`OtU1abF4FbQ)PKfE+{IZYJurJC{9i^xLCx4s*eMjquOe)U0Gxkp+VM=LDV zjTGnJNcCHY6bi7!4=;Chp1=p|7>fhVtkpyCRL&b)N-}UUzoA4Da$84kHhxrm0Fp)` zD-mw#tDHVdm0sihHVd_kY^t87$V+k2s7+a85}4bptDlz%*-YE>@yk36Z|%D7Qhi0I zR(V>?oIV-Hprl%>V+jUcsVWbPs?(UU@RQqM6-s5xmd8$DhH|=s1LH?7^Z(v{+%l(C zMwZTpp{AGlIJ}v$%n%W2UoG>!s!`5nx~aKCDA>6OD0Tc{XEA&n-EI|>;K{}o;Rykn>GY0yMC-Sx;-6l53t6npN~)j$0*)W|hu-Z7qm z!yveGrCN#M_C_dzMIJHgags$$9$VF)2EVl0`(vv%>8iu(XY2ek)I}Eh_@wneQCAn% zV2B_J16ir5>f$s88o>f)?BB~PtnELh{-->5_ob_+p~spyqfc+)@uRl{SK>I~{Hk3J zSc{VzS=yykh(Nh&7xlCvhZ0&y$e{wvK3kX2F1BMNdxc-E3e(PIzEZNDl@BF09GSLl zB3P3%K8I*$a);+n_kyfczV;vZTk1q*@5uP)Y=VLhn(u&F^mF;)J51omi|17Av_(Z$^HfZJ`VuSimu7lx%HR%ebqDvbBvI_q8$*WH2Mg?bqWz zk~%FlKKUqY7y>5jjTnEyCh`srnr97-Umf?~N7a58je_pQyN|&}`fQzwIS}u@;Zcel zQVSATVBs|KD+1F?@kX3pnz*KXSQuGIR8-m1XO^jakZ?6AU)IUd07%-&(x??6`-GRumO60yiQZ2B(Y z-nlQn-8)=kwa2J(5GgZ^P~Gg1n_;sv97^!4#z7h@(#>0OYTV4G%4vnF@e!(q@Od-b z1kMagA`o%47fJBYNS5Qt5jYerE4vb-3TOMpz@jnJjeI6(*e`FSL%N$N-EmE~E59Ik zQ+K@I6Uc?yIon=bxPUNDDuQBKQkuCw&0%b?F2>Y*O8YcCE^6Ft@yN!X5D~3vyvk~L zO53YeOvcO>^?FlX0%H{K355f{a&{=GtevQ>`W4>r7klshbWfD-u(>|NuPAo>X zz28PgW@0)NBT%W3fkKC(w5#>|#RTCxb`@=Tv-JeT*j{q9ae+Hu@!iL#2ow zoyYXxrUyAcyh+=uJKdo$LF#@hcIt>kRWD7fUuF+J>2$b<9;*it5=#%w)*NOq2W=03 zeESgff2)0@fokTJQg5a+Byzb*CyvnOMMF=J$K}h|ld?Ko>ZW5PQ^d{nQlebQ6&dH? zX&A1`N;6~J3DivS3KdM_N8I8ot!GxUYF#~RUbg_AjZDW!ECIp~0JKK;e%U;f63%44 zHVxmK^P2pRuXfwQ5|_R@;G-R^G_jmVO2bNs1-)1ic%rWOYL6{?($Jw(UvrnlugY4J zGJ=>ZlRP1s8*eYL#a@fADzwFZ6K^Nj)j0KZ6{h7omc+|!(JconacHu~ zWJBO|s+YRD!aRzv%13~FmmEJ;sY;&Fh^woNPfNImOycte>ho1uuCA$k`q`MyV6Lmn z%SWRgx9sS+j#c($t}apG;=mz62nlOSMeD3CYgiS z6W12dnlVd6wnfD~B8e^(V8<#%L>0AOqJbuAA(92=OC?%L%WGwmF{>aE!d}(US8HF^ zU#ln(@}bL?2?SGblt@6IsQqhGg|R4F781sXnRKqFv0G+n5%Oh{l$-FwNK^TRyHO> zgH2)cM{g+sB&8&9ppWT7KbWTOGe}ejM^@$wM ztk}l}QG`JfjPfb+q}bm3-ZQ2A35f|u{||C(Sy6u>KeB(A7Z+ub_<;^(M=`RSB(v*o z$UfaDCOm-xaiMs%w6&A!VToV!(+8z6I;i?F*p}6P~ zWZkfVW}-Ql^r*b)SskSh#NJzC1d;l}aV(kolEkKa$EX)S-PZ`L5PL=WnRS#s7$daO zQu}8AcuYfIFn`ma(*D>V&sxyC*{7dv<=LUVr}p@d+OvmDwBxG?c6^QDjuR%j3cwL8 z7rR_x-x8zVbFlI(x3Ue0og+gzlV!FWO+KT^esFq@FFJ8uMYi9KH;4p>JhXf2R*Yja zjK85rL~(_0>mdWm?Go(ca$~6nR>i|Uy=oSzK@ymH1+lDR`!PvkjXaU4Sc5)sjWCAk z1OdH?lQv6uJ}%OsCh}EPC|DSnUB1Al*|^SV^V_k$$*-IST-@jPrfVpIU%J7Gy%F; z8mPs2%L)}MV6zIo%Ym<2{}@0mDo4$s?Dx&wLXM$C{5wI6_nXbvzpMQh1Zc0rzaFzW zFsy6iouXiswVc|ggs{z#ZWbd!jMo`Hv++vQxK(zePTFNjPf+~OVZJL{FjunK-IT0? zqh#ET=6kEko#l>-4UIe8WUlCuBO;`*i%P=Jc~H)Y@zOle-L$~HID<{xc+BVRsw7>wg9HTs z2*3y7NX5mvVv!8bwPj+3go=`sx?Z*?-?jex@|x`u>ukoS9qx*Fh`YxjeO{!MDN;Y+H%3u3*cHKq zZq$`z_vV(UoLLJW^F^KPwG!|?RzbXL4k_yWzcIE&t_|a*u87#39Y*=Obz_tH>*#8h z>T0&Lqik7pI?Ev>$ZdX!#lW@&0t;)2+7LHP<954Pp|@=~z*jiqcTnl-QyuYrnjg4}rg*A?THGCc%Bc_ z7Mm)K*mG>@fS$xL!f6XVyewQ9ARH6Et_YSp%W}+u`yh(y$vW<09{kA2(2Edgs+OXd z6aD9n=7MuAJQbq*8=C}GT`WDLc2_g0nu7a>3?fHnGQpb3jBLRUlQoiiiNn73N(FuEJRM0;gGqWu zjHA#EVV?!enFg^hm5XX&nW7uaN-YYTBRU~PWxNl1y@mrDln5Hh>UH~N;8eTO$WqmMQfDV;XTh{wke-A~l=JW7cc8XN zU|YJARZQUFdoX&wAhp2bN=`B*@VJtbOg6d&MiUbTyA{MfF5gmlA@lQ7wNyloHm91Z zb70l#i5^%d<|uPq>u-=ye4Ktdun_9Fig<6S;MA>@kPBRcUS zCbCXG^cTw06#1r5+H0z$Ge_!#$m8-gpuP%wxQIy?RH&=@BG>xE;zFkIvnZuK=2wKB z;xdvr*|-Xj$03a3ovp$61xd3J)J9;k2ZaNe%Izh_=cdKvMLgOHNwUbNssVZ#`mw}l! zta(cV@3)D_3AvJrJ(Ip4dsO}ai9EafU>%)9IHtrRNnkA;><9ZEcx9$U1n^dTaJAq( zpZOl7jAe?qSJ+||;ya1b5ed$#z@@_jT*~tT_57?Pz!GkhR(jq%rj?)QR)+8EOkb3& zgbVOnrnu0IN>9#iA~1-}mDn?}nV$9tzrDoEWSU|fd9$Gr z=NYp+gIL}1I9dG@A!HCacL>qNd5;Vz^kcn|Zx$R7mU z2eId2{Bp(WuW*7%()E!x;1`ov~@dKuiFRzkFR={h1@6Yr7PA&-h+W+fs8)oKvd7kr}=RD^*=RD_POb(IVaHC=S z0_RCBc~M^|kC|v-Ox6Y`4}kK&BGljqy3VhVy|VWHi3Rp7tco%;SzS>rGjO87e9-fG z6m!tScPl`y0~69*!upNHkEY&F^cm7r5=6%A+SO(+K||zy<=M?N>w*s_94YTme`br{ z(;36FbP&`5Ls*F-03c~3bDk)*|M~+X>fn}*Hbks~jw+e)n6;5$zw%?M$FNy?ZkaWy z$u67*!#o6O)MM5~75LrIRN1p>xeS4HMX7uC6XKBNS1ZkA6`RQ_-#>KW*mGO?;rdN} zm_{>EV^fLs8yl@B{z~dfQ{{kCPa_`L*5ccOxr*BY57rmh-}x9r0!iSfp7h)tw$ul= z)fWt%$r(m}eZkv9LF2Ddd9Y+G`@b0TEzgRNg-Agv@x#fa~C1mE$R0_^GbJFpmG6ajgWl1=&e z*tV!(Xg1nm`*tb!P;qpj-uOY@BFJ-FHs?ygAs-ub`D2AOEs@a z!?^_=4=UA>dq#sr6Cc<~@h3*I9sQ*s{StGiybNb?nxdU&{7H(v4VO$UdwQsF$$5bm zI$F&QQv6@dbVbk=gLzU7?ChpP$Ah=TTJbhTo(a2a!A7zABeZlB5rSiugtbN6Qx)OR zRi9Qq(Y+rv4BpM?>8@MhxY*!$gE@B_p@wDG1GGZ#6-QPvUs(_qiiOIiSJIiaUhSVK zy~fRK8X4So*}KCd_T#O8{y7kG=;CX$%Bi#C=;6E>(pr+T_{aCUcH=SJHmrE`-A+K?d4g<-PfAYfad$naj{u`5t)J zR2giaIM85}Zv^QUy8)9Du7Xq}=lvS**8sCTcI) z%bUuU-Kaz=xA6#s>~Mvu8uA{f+L<8_VW~3k(B$~uKyD@%NAndSALnYH60Q|*TjeH zvzu)(573i3n`xf9HnV7=7YZ?<-h7s5`xsgTWh~dwHJ7bE+~YJc44@|_)rXH4_yDiZ z@)!r6qbywar2_v15 zEZ_3XCfU>vN%3x>zVfDt))eyju(MQKEg{CE`@FP*=ao@;Ih;6{T9esCewq1LS`S+L zFxqBU#IU3#A`8$PjtUYhv4WvTa?qL6XsM3gwhVA7oILKJ7J{?7V{$Vo` z_c|&L$6SG3o-PiheD>?#=WqZ*`!-fGP!`<2Xkz#8CMe3V#G0Y*l-kdJ=*)MADJP8~ z?Yu=3!3w$-0}y9QfdkfdygaP?o z`|B$V8;xZik?d5Ftw|W|wL((|blsK3#AARN%$$uxrV!wC6FbcPMz6F90xSTUGG${s0xV>7PfzC@gNyWR-l;H? zL7kT(c>RD=;(?UHG7HoN6?0pmEaBIxK`IPu^(#8~?(bo@v4j6cgO8LB{);Mt4`Tv6 z+bXiI!L-{oD@Tegb6$vTBRj2;<3NtFUPB~YrrWbA{N?iF@%Q`fl^{=(B2O{~Vpam( zc(OZ8)GwlUC%C*%S9)TPIUm9-zjiwx5;ytP=X^Zkd_1X-yPWrSnD^o*I5n8PfQ#F> zH#CV?^ab)zXwnLnoVrbBe`+q<%UfCcoSNl!m`2#!4nSo&3agYQd zC7n+j2uGIs7p58#=$XYHC%nzCWgy-3k!Wwq&abtf{8vbIhXDduG(x3cq@@jpR-al9 zx+OMe9uYrSJZ8UEte1pmFL}U5_Uk2A^E`&6)9lx88Yyt4BR!v|XIJ^G8XSWuV~9H@ zrIY!%HcMvBe#kv#U*F39$*)C?T;Iq=*r0ti7eTAwspaKdQqIIlYg*C6da;;@0j?}+ z1h}etv8nYu7~C?0wX&tf?4XwbVGuN>P#YvBP_EB=hc;3-8Kg-}II@v0z20p}tpsSL z%4wzCw9+Qs1KXgJW+XA1QgWja&PKCJ){kVBl&@=~ovfdizyj9O7{t7oYmMztFR_E@ zuAs5?vI10LYmBt3(ZDXU4t()g-kuha*yOe|t z>?j;2N0{6lOfK;(RfU~}4WtYUX9f$>uY%?%O-GZ~TXtCsR3!8{1r9f0J3za>a=RZ*$TI-Kh&u zCCA=ObE&30u+ykOow4;?iRy~GvsQaj9nLa>RJ(PZ`2f0*S(krW27cLsLE|P`bk%uM zV7P0OIl=q4$N-1ZgDSDnKQ?!&*46@(3-i~KQh%GgRnXR5ym zf-Z7YcZbHx59SsX;1)IpGmuy^xGh<*t?haPa3Q-=61{ajVp7sxg**tR7n9~fRATBB ze8OqC?4&#u*Yf(t^5^q@isPLu*IZAE+~-G?3iLWIqf{(#^8B#B<(P9$rTPh{Geh(_L%hxD;sbQy z1UD>$@yi?2nH#d>z9+EZ|fT&8j!yL`g$rd1uph$JsQGi35ua zCgzP`IpJU;x3uuIG}Yj*YLG;~c*|7#PUn5u{ufh#1Ed2|H>hFW`#qOk{(w1&5*5q@a$T;^4Nd+Ep4L~c%|vDVlNWkzq!$xVlUaookg{9@7nn$ zvpU~oRUp?4b&p;H^XvJw+^ zLtF|X_LcMy7tgWgdpYgcJQHuarWSUb74|uufe#4AGEAB z>`VC$8Lhxy_er|=$yMAEbCwWbcCQP$BFwi5Q2;Yyk7n-v*CZ!PuOB>L?+Ee6hH1Zh zgbeeCdY(_!$SJT;o7XgJfn-$_SnNaZPBwd(P{3aTB%Wo47UHC;`>le&7x!*k=+`l` zufO0P7`~a+)rn_NHB_+{UfXc zgDZf~ZRCcRq?-Cr4LR>!0*qJD)^+ZN*hp$07M;!^&T4d*tuf1wSOXVJz`l0;M&(!o zk%ed|Y5(qP-~#$~1O#ZN$^MJ2K9z%3E>_DK(K=sSb36D-7(#tI0X@|P+sq2I&_EsY zQxm9~@f9eQC_&y`nR%qr{(X=~J7bOPT3d8t*ofn@guRNK*Ku`!8c&*eC$h7R?#p?W zS>RILan5CZ6G7HwFa5gU!KFxMz?o3U_W&c$zS1xirX>-Ed`!YUd$|KO7ki4hn8jxl$D=hQ znCYS@ZiE}VFY<4tKqB7ILmR8Qf~f;|=_KvY#J7h#5;8JeQ0Rwl0j&TBt8HX1?Huf1EFJCJ*u_`&9&z z%i9h^qCKv~?5Ca+?5d44GdMbz>qx%2 zL~Q4R1*|2<%`vL+hq9Bq-}0uLHU3N=*!?5@(Jo5|f87so+#RvbXtKZI1zo69?yT-T zOP!N(iPwTj`&RDq4nJbqhJ63@5^S>n!MO#N&*Xi7=3#HMEgO~|A91N?xK$8!*N1q= zUqs>#*5}2{GIPpo$vMDzaUn07QEK3$9Ra#5(0yLQ*6ZYuIFUCZ#JbceA>>3F4QKJt zl|vgzv%p0 zeT{0Aj{VQ6M~oi?b*B`H-_njbdOfP)<}j%SnJ7$iCj9$b9)*9ODmoi8*G||~p z9XPC25&Pg27~*CfF;tu6Qq64br)=sp36URmXvx|fwg2JA?>ZG*e_%6&8_tdY;Lm*C zn6KDc=W#jF4;%-FR{J*RUFb#DbDfl~xn{K~?Zv4k*}E2S016iT(0{zHF?A)!V-Q1S z8|U9Q`fw@bV)`7b)oU&F+AqyDu8wC|19;&SQMfr`(+S8GB4R2*={dCtmXy!3%TCOPgA1O=_iW;xqQ;MOMdT{9WT)bagP+sfdFbc01J zV4Lh8bmjZixb8I(2zD{ZVMX4-BSAbi_x=g{lJzt=jM-;I;Si~_{F(k3DRlcTHuZI5 znaw3o#VV*ms}Qi8I&8uH4W4Fo56Y>Z4K&K^n}z*AV-hDx9RlavJiYP6|4z^>UecIXL(nMg>}p z@(xixbEXoI8;c; z(YpmHnS>|oo*-J0T>)cJOEbm2>U{S8^+F<0270fi)!lzv2#~xnVYhG5au3Ps_0+oQ z_CJk2cPY=YD_)YGG*A~jPi=zhhhluOKUrXs{}@_CdNd3fI?u!r#WuVb0p@ zXIPd%Q-a5tNV0aClqOC$ytI8DywhrG++K(EE!$4AwCFm?o6Ya;ZQIu1+qSIO{vEz8 zcth@t@*Cl0@wD?$cMv zW=I64-u8dI_0Fkz-emG&JZ#!guvW%2?@3QV-iy%Y3b2}&YchYXF!}A|pJUxCFxo9` zn@Z^)9=J^x^k1NN3xq63+?z$v_>&ijE&QzSXGaxuayDt!%3sEgI-LsUnLdA2Fy*Vu z^abOCR9(Pwn>AUxXAVsekvF2uSqbs(MyTd5))YvygqV^2sp*IqBQB47^Dd92y)Spx zWZo%AU16O84RDe|s%|Aq%{Ow^hcZQjCB_Q%&w-73ipFvV$EiHwg6ZWgOjG zHZl%L>`39uziqM{#I&ft!KGIFgPeQ;UDDde&~6Jk?-Sq51J&y9X0_ubzrK@$|RNGT%4l&|tR<*SCy zapEO1YN3z7^ z{)RaPdKagNmT*-|DE%tcW9)NzICp~=R`-hw!9!y$Zr#}xwfRmkb$?CNw_G_a2JGJv zeZcfMY2PYbxuJhZ~D2k@je`wl;Uo7jenrQ`*FT0gZtI{ z@J_t*R<-AoAN^<5R$S26>o1a*E?&Dzwo_c0;>T%CL3E>J&F0c} zd%7-RE9J_%f-E6{E#72Xwly?R=lP@nYeZBL8v$1^51wgm%hvg`OQQA_Z^I&Bpo%>~ z60GwM6*CuM`~CmM8!TS?aX44=Cr9Ce%3QavRCSKO{kDsY zYg>eiO({U+K8{fGGH7bfttoA>uhvx*>pJ-n0Q#CB4*=Y<(7>d1g8W_>j&6Cf4N?F} zdDv!8egiUCBAZ3FA)LhlW|iN*yAUu}Q4KtG0f_Y-7n^D+-0kUBjK;IpW1v}q8k4zs z_M2jNWH-)pq_NW9h`uFRg25QA%NfvfZ@B|%G6VXT8vz|B5x z*bI7K*C&eyV`j(-db3v;5#IV&yx#01E|y*GMXBy}r39bF6^<$wVz1dBa~| z9}XKKh*MMF-aleHIYZ)=)NSMWA13hTSBOdF2akW)luL(8wG%P)t(XxCnZPRu1EN19 zxb)>(l&Y>mrX?e+r!VEB!b7HUxvh1^U_8woC&bx{X6t?b(E03D#`H0?PcIwi8iGX_ za?;)c^jZsuvQ3d^BI%%_XyL($5StpQnorojWX0w8(_-t1@;bXhXe<@gP|kT(YEgA#jiNql!Gut#5aBf<{bf7BR+e6#?&xSNrW zW()ZWSb}ujY$4^(JBJ2t()ITwr!dD@s3J}SCd;(r+t^~7$tSwFXsidO$e`bIxyi*a z-f~Y4xV#JIYpJDjGQMhjvWvS5ti^ZZhIzL=S3_WfRMv>#%)0 z%qNe=DS8-04qavt8Qp`O-&57txS2$Bjm{GCBO}PRD;2thf^?$uLZe$rH9q}vx|q#= znpsE>&M}PPb?YVY@^ZWN3l`IMM}=Z-G%DUsmj<{beVka!cukn7z$ffl1tc`qX8LMz z6E4opCoYs>9hW*E#i){EuKMkV6j8d=9~@Iy+}J!Q9Gcp0yhgwRwgxn>Hw-ieK3x&YrAhc`igO zWGjW*FS1tC49G-L_GR|^oqBQ8Or}~q+dKcpa7Z~+*m*wpRlhLeYqOsO^uR-bT<9qV z0<-qcJCLpY)w50+AjHPJ{UiosB*j3Qbm8n|VkAM%Wbsxv$8RBy-=>$j>kw|5Kaj%R zfa*7KHymO7nU~U8{zm++)n|WrDoYw0=!uVG(Lu6#+`7|dSiwnJ?S6GWG#JEBLFl-yz?L zW|~!m7r)=WJZ*j(&QCJQ3*+02*l=Ean-Lq%wC<3gke%j6@R)d>!KrlAWPkIoMsgS& z2D-K;`#F?fAYs2j^YJ-o3WKJhi$~CegKLO`N{*;Z)W%0ni6%B)ojhqGLx9VHEEh9YtjPWS?df_2HHlK@v&Y-+vj3y5&gWD1qJZ`lb&5I%LAH%bai{N{b=+rH-pDD{D&_ zh5yxgLO_0ly+kXH)HUv*p=t;8duAGyA5XfCV+#f2?PKjVPKn46Zk&UWA;yOCI7^^f2}tf+x9|$bLac!^9)@Qlo6Vi?fyE!%hV?~lt%IxscKAFLrl==b+4D@~jdLK-S=pj`}0J4o4(gDIY;C<##g61mg+L9mE$0Dk#cSv{B zjaI&83$ zE@8w;cg)9EonPN@KECaIXiB*EZ_dYk&c~1WaPd$T#?9Nbm+{^OI2BVzEuoO z%DMj9I}GNOl>_&5D^i$qG9cSC4m*qX6YxsJq*W#zcVOq;>Sg>pi-R)d;LQxC9Ja9_v7l#v`u8L7ZFhiU=P_W;+nb6#u$;!wEzb6tL!i(DE1lm{ z% zkn>`Zvn7nBQBeXtuj?yrF(5XauO|UTCj-4d)15YIAE}Il<~XoZRHs81TvV(Jt0Mmq z$mO_#6R?+}5-+=aLZhd}(BQ3l+9ewS-z2Hgs=d{l?1*URO;0f9Xkb^6I1X@vXUS|f zZ9uHk=WP;X1GiS0?-FJMnGf(if5=Bw+kzjwz-7nzWbho_bC{KY7;b2^mWfh0B!}bc z7@hADa?Tb$x!dX|+jp)usEps${8eNd8a4P-@%)6j#4~PtpH^+p-b*#Xml623)D)a} zjh}8-{>yhi3m|Lbw<+Z5=1VMdj2s_Iy$^agMbQbfRdlU%i%u-hr{cez22Y)eKWy5! zn+TO3n*pN3$pE22o>W!B7T0X1y$%7^(rWux7kRR2YG3s5oBa`DDav+ut-JL*OWf8f zZ}tcJK2TTt&oBM-{aG{Q9+S^))N=760wS_y3>(StXj09Yrw|FTGdQ@bTr(r>?XUY( z0d!MBYH)2P?REpH?TsbKdS=WCPvzBErD|2;Q7<&EvXXQEhA#0lNOtEjM@(*M@y9EX3+z z(eX3``r+Jl@2o4JSR2aKk6)8SU#87DNZ6(`S`*a!(WnrXPxFmLJc_r|CD7;e!U1WA zi9=+Xw$ZO>V+?>B1k?tBU8)T2c`(=K!CY6^yl!2xDf?qH$M%d-06(p;O$U)mLA&SN z@c^3X$U7V7{hY@tV5}D0nP9@?#=sH2YcgYUUB(Taoey9!kR|d2lbmWeqLL!y78@IN z&~k`3znRw`5D0iB2>&lo>XZ`Q15&#>?2KU>uAzHsW?!ArJl%m&!SC z7+Y@w4}QiU#*+s2JY0|CY9rpu^i{jA9GW{ot7sEoB-Cuzrp$!mO6fh8@OP(LtL~Lv zkY1wqOf3LwX(Iq_6sV@Oz;p*FxnH|bZIn5o&T+rar(YhA4owFM2x%C87BRpnl%qrw zv~IG3fshaef1};pzem0kRXYsV!B4C~XD}OJyt67B!{o6w65!uVSfnYC>pWl-Htm50 z^r8G&^syl=!E-VFM5`iq26h@UNTJs`+^3E6?0b=zIcHYw2Os&l8Kd^FkXbJmoimmk z<)k+<2Z}IIv$@67j0ERI8^B#BYeJX}xXUTB4ZGPXUULKD$LktHuo2LakllDROY&?- zp>^Wx5{?t|UgybDP%$i#4po(r_fFOZ?d%i`emSTcsaH1QZ0^=8TO#Hc(li8m{$1E! z5;S%HE{m8UPeu@PSXmhe3^^mu_U#JT71eNqHU-`lz^LeKEbcM*=*|=$rWZRgZ6arQ|((uJ*5sqtkd;QFh z>`VKdrN{hK4h7$REU@dbZS^y)sP7M%A`wcrdMfPuF zDXntU%Je0a2{G$GOt%J`es(rS!`axzL#uxsfCRA#Ls{S|XAlIT?MK_b`rk>U6=k}*xuF46^M zPE77R46I~|pEU1RSz2jR(XM)h;}#7-xe2N;aX(UitctEVrwi;pDM%n;%uRST~+)ae{dN8h#bs72EW7g%)3!qZM3}ial3Q#RO63nJ^kFDdf!YJ zXWk^({i8g^q1)9bAuD4VPa9;pyd@vCt2A9OjYqM*2sb#sTB?P zkRV>>KvwKRHg^9u)&D9QbXhZhScK-QjoZ zXTs-7Qy*|&dLM0-nitJ02gkqiaJKU{y)tI{ZU`Cl&dVXL1q;bv>^^Z^AjTSgYXQAv2F)A%@v)Rl&6ow;MHH9O+?xpP>zA!rp(BC~|6=o0l~ zC!iJiR!J%;i$9&JB|{EqyWCZ0r`lhiVTM#{R*riNM6b6xJyLkhSx94~U{=v6(APSz zi=ZK98X2jM^nP~%o}^Vk%vB$iArI!ZTATrx>p4h=oa2qY^hZZnP#J+@@7NyGexNs^ zM_HJ8%xkfat{B+Qm_;-ASIEY5#_>6)lYg8Jk~reTkRZ{!%q+{% zO@V4&hR->~NJgd+`ExICMc{Lf6LU3qix$NQpObCLduyBYBH752_O4g*%xz`7Kea5s zNN&+|%pYNHWiU5C;EaG`_R5tbdu4t;49guEGgAWiVifc1;|n#{(ZCMewlwBidXkla zyGe6sw_N&UBOZoasZ8=jMP8khA^*zPS^E;&OH@=xO8Dk!0%uHtxKmMRo-`fv$5=s- zSTg!pOrJ4SSQ%T?XOy$T)OU?iBKl2@Ws-i=Vcr`BC=m@INs{tiV>s8z!tt0THY&`z zeQG_#T3U#5D^R!iP&pGRsjRvcS^ezwfr5URdp)U?DHGQTBgrbLx#Mi}Zw z=LmC&zu#j@9=}IAWMIqL#YPuPxzox#m+3i%i2T^{;`-PPE3bvGKW&|#7Xt>ci<~B% zwm>yO;Q98(vm^K?cfr_6wZ9=9Yk|~3SLaE60_ZnTQfgGo>uMM?ln$p~j_=I6ADJVb zkLH$7Ccyr@Q_qzS|Hdj;X)2P){$zHA=}xPoRf|Su{?x4*4Bs@Sfdgk4bc{A|T^_xs zZeYx-cc1(!lCwi~r+L-U2W26g<|_82A?^O9Xj&0kE2Q%Wdj0^xXC4$mc>=w^;@|GB z8GL(+Z(}+?)9L&Y(U*T0JaJ>ryUmy*3tA~U-0%6Qsz`4zj@%;&F_v7vt^k+ucQ6`Y z)umTuEl%HLeF|q6PO*w8flr(7AR3+dWJg>3!VRZ+G0a@=170t zxdr`obBeHwI45Z&r-U1_l#D%Vhhu%*s-w`sZ*e1O|LiGq>WH-*EHz@hz6eN9>j68~ zqAm~EEzaApl0Hz_jI^@(RydYpYXU6$;$MP}pBlpyN2XVEWct;|PjjGKjSt@??y>0w z@dstmzwunxt96pw@q?N``4w$_PE*KWV_q1{Ia=k%zp5DIBDB+e$!A+fd?=}`@#5CDtuctX08bbA_ii+{m zu|h=R_uIF&8lMH8^%LvTZy!7;(()@opTuIF&nfSu>9F$)I`|(c(*d-K0^*6%Hv1#Z z3=B(%_)pDk{tSn%nwG@1xolmwUJ(a2oB# z`!MMk^PQO_f$BiRwMFcH{;EYmw$U)Qo44#ulLgNhGjur^!o}D?mbcvyUg1^D#b@(S zu?ac>7cGwYCO<}*2;Q@thg5@1UoVxzea{?$G3E(*kG$# zlS8qFaV?1*yKOBP*Vx!(Dm6HV)WKz{jNv}m^~sUxC`AT)%kHED8X~%iatGqy&Xfq$ zTLrY!fnoco6`CM+0P;;Z$!C(|61O;g&5t`>b$*ff+B4yVh>pbV-{>b#9Lu5VM&Z5` zGuK=8u+QM$EmA0#m(o1qB^;AFo|8;$U;UoV4&qJ5pgiJLydrM(*W~PJrQ7bbErRTf0c)E+PKjVoLi;> z<2AroE|INbEdI55@KPA`P`sBMCwam^o!J=dPZW6i!G_t8p(V2+gIU)WH>UM>Cb_N8 zJGpf>+5DKtdHV>-E2-c9TeM~rJ8K^n;O{P>?%46vytw1UKi75QKl@Zp{H}vYi#`1@ zm(`66=v6$;D~z_-#ONtfMr(iFa56_+3S1+yP+SCZNlk6Dzy2?>#uJfq^*&(1TXIg7 zxR1BZPUAl0-Wkt8n~bx0kWiX@tBO$TzshYj(5u~)6IFk!eE^SO+Q^)^F3`K5t7di9_*Q|MvFqv4%)tsk8WKdw(k&5v*cA!rh@O ztU97XQ&B5%a$j{C&YAZ0e>BfO^o`leJwsU&3eCHRco+PH)NXo$wIzfz@i0EVIICgT zxlVB+Cc@RX^^M7X&JbqP)+DeJbz1AMpX1r1$ap;S*zif$=$X4WTX!A6i~^EBoTVF$ zx`&4x6t^>RLh;A(%6BHNk`6y$)mL7A$Ml;QrDk4!&v!2TM(T{qC*DF%;7PkVob(LM zbKs%Fx%Hu;a||sE&0-9G_&*NUW{&T~mxnLPS)Y!y+UGmhnJ%330b{TU9pyp6-DIt0uQKhcL!T(<;IKAeN zY=7c49P%W;!TAzUPjYTwb3L?wQn)$!rIky0J&Xr7wWQi=O|V-;rg};cg}72j>U9DH z;aKFV@v^a(TGIl%7EI-#irpKu+dqXJJg-H|e>gqUN^lZsh}oUj{)Wk_ zcM!NgLAWV_NdLUiM3=}q_$!u172u?2;hGrZUUu}Jf(N@dtK7v8`L=tT0oW!U#syT7 zklX9d>*?#95O}a}NXua8mbZtK1f$%@Clj{&-<)^;K%#1AaO-)eb$1_^ZHifOk*73h z9%XU1Otn5*D zf9!QRW$d=OOw{2O=7yl@=PJoGBSr`26koYc%TSM2<-YtJuBHKY~TK@^C06*cW|X5(^r@|q2Qp3&hKcWY9cS-<1dds zR6}Rs4Ex3uam{PI#5uO0H+<+LMpap3^&{P89*K^Sy{h2V z*Qx^1SXPN()k=&bHKw{N;f8hHn_)w5%(J)t4}0R3xh2!=<&QWn{DGb?fgs=rw&dyx z2!LD@Y_X?Rn*c}yoTUM3T_IN+LXUwV`#4rPoJ;fL82>8{vn@ih-W z%h27e>wk?u8!B$GSMD{tR{XcPdDPD-Sf@za#ws(|Ylh^&MPPSoGVq0)OuNKHRMyW) z%}N@M`ZO*r%(FPE;b~S^*t)59?g=>JWD1YunJA$Qd4$oTqyq_Xgc6Djh&8l#!P;P^ zJj4ZAdvz*o9L~9`ho}cJ^2oRiuoZrCLass$l?W~qtj{Fa4342M0ru>I4ljOKgop%_ z!xUZe4m4DPY)@uO!V~C`%7vd~)tc(A8ml2;dB3EMgV+Ag>Q%JQ;I1aVrn>WI)|SLI zG{7F2Dsk1MsH-N0U8kqnC#gy3M@JqqO~ANa1mRCg=8tL$x?~%u>fP%FN`kk5?`ivv zhneul%3o$Aus(nMsX*`la65jatKJOYd#4@1sp1@`Chax!E@abSU3|!?(Dwhejk8DF z00`c$1ceoD%Ais=Wl${d_BA%ra-g9a=snqG2`wq#zNG!kgCp>qd{Z=#UH@fo*8AmE zykTAtArN28ZWFZXJjWC4^*%~;^@DU0={Pm+sYTe?J~FE%(PaM< z`E!tXN7i7weWwooKPPmm!kIUFkNQ-P@rMIF@34huHdYr{m*5o~4(xbYTY4g4m0A7q zS555LjLKQ5iFYI_gXy>CIpvzHLt7se!>elb!;_yNNpu&EkOY>dJ#B1GO^!!4Q|T(=7A1d1o&I~ zX;m-NzV=9@HED17DSdoeJ{|;Io@Gt4hu>hwvdL+I@H!b;?A*7Fj9~r7I&ObK>2OD_ zeX+Mp&@EZsWkbxn{`7m!IE7&5y8VE8#ixT0!X;KQ#tqNX{}>;Wu<{7vH!JIT1a z4;ibPIc8&okx{GdxvqtByoGd3G@|QNvd?uY@pg|5@4S1MfwJR|cPe>rl*ILVPRHEoVqdP!8c zMdLWh?-0u|eKyb6ao$gXfC&g;Sw zV!*5ivAO)^v5V8JA5)9vDA*~rI;s(l69f#D?@yXcWw3c=KP<8T>uIKrz1~OGp((kV zNlt5#eE?pT!vm-}2X>R~;)S)@ogrwFV63LLVI{7{5M~m1WrioEKPd?5i{qO>uQHsq zbR<3vX|$?+jNSB*rNUTRPTLWIJ#d>E(|?Xc5xDiA%y-%U0vQt!=WH%B#zwXeN-?CF zFVdA5&e?D-VmL&R9Ig%|w5lcagt7}OGY^^`QaO!RuJvOb~yr(pwTOXpMu9Y zsIkAP2guKuEu`HNeA%Y$(L4kPFXx#SJG0yHep8x?(D@s9o#)CNyG<;x^J83)0zu6M zx(QqBeXJ^J!ynL-k5;bo5M~O!A;3|%>(M;H1$R#bjy-n(qV@XrX^lN3Zwc(WBCzY= z_Rkxi^m~j?`lR{wB%J?kBbLQ*U>A{|cQ_vD1%X}L^ljeb=_%XmCgO7cnd)fjQ^rv) z7})tk+BSmJo-ffsu43N*uO9r{Yv)a(i>Y)`ToYdz3wC~UsL6cUys&(K<>Gl0bJg>R zx5(_BmJWaD+AJ8=CxC zzj|xfX#3Ek)vp%Vzt4rx384*I&6G+fz8|89f-jG~Tk6qzcsDvn5DDarRwvEhv%fS8 zv$e%Ow#$6WH${W_dR^8|b6UE$<;y>rKwHP(qP$@u=go!qk+g1;`x%ngEJIqvr==(4 zY6`E}XWgy0%J=6&cVs7L7kaY`eOZnY7Y4J=8@HK8ck1nI^;W}K3(U2G20~`XD$Q-+ z+lh`f1vID&0VV&#h46j~Z&p~#5>_z=Ryu}>8`S*k5E#{&7|2s z{hXzClb8c15Mu=U)vJto!w6&Td;Dy+b|<=|bpj=7Lx+C1wA)E4GD0Gy3r;&tJbp)WQfJN2JnW4>hCGVSw93_S)>sd-W^&2ltRYp)`vu+2l3ixp1Ef3Tu`zp6 z=0Wv97wcobK+ipVm5y|;=(+2|?ZnGF1YZ3ms+D*z1n!CLMlZ}Xc!$xoW^+d3T&Rhg zmpY$j0BTaHGTy5eIAM3bv1$PxVrIn7Qd)&tu=__sItyp~4Fh$Pb-P+`X@!;-$9&nZ z>sR^9ZSnsQ$eY(%72l^USE8EUTib@8HLU)SRX}rGd4K$KHY2=YPW*G`JZqM9k4~`2 zY_C7HKm#E%I--6J)cd&WsUw8%^H~GLYBuMI4rf_q?Q`&o{p}Tp zTOcD7Eq}0UT9v^E7GdoqGNG|iPBbyI`#|c|RH{nhp~I8YEyF>os#3pm<8=PkKKz^k zJw3r*z*>K=0nW(dVut1W5%&cwn;V6#CR>j>j5xTjyYim&D^{X}(&#Ul%zb~bHdYcD z$R10+htw~j)0nj?oV26=#Y%vuVxCF$QBM`UfcPulb`$f(_MoltuaH%#5k9nLFad>| za1g_rX81tn5mFYUVkK=P>`4F6tQ#p=H%d)d61H!UG#f)RIoA@+w&2Z6{U#nyC~Ep|7r{>ud00JbvMoAh3w19l@~$RZfv^ty8%xhk z*4=L#`Ve0z?`sFGVQZ%c*5s_8_=TxOdE{F6n(NgjU$6Ztxo}`i7qr_a?lbfU!H_st ztz~c1gW1w;!?)=txgXh{X7w*X_#2Z-%Frj2;I~mFh6|`EPh>*o0ubP#aNhPG2IB2?)4vxa5B6q%yDhXkQ`tdR*SRK& zm9B|mdEP|fu0(T^JJdkw;u`bzheqDMh_~MhhshwEoiy(4V)99|A<^lg%%detZZ4py zhbGrp^COwPQ3$YI|0a94FZ<~TdCFGpBRn2gv!a9gA8MR^ zcS(^aM~!M?tnAcewvV5fA^4ms*a+rB7XtE`F1XWNaEk-??^M9ake~CCYB#RyvE5Gr z;PKz>eQAOc8j{|yU6AGckE?)8duTfhd3E;8ZB5g&w}b}fdqK`{-V9`DNB=Y_y|GzG zAyd74+ZstYWyq9x=bxj^1rz75gx8yN5^HX!e+OUCK@+yT7m&i30dqm^S%qdN39)53 z`8qzBnwsA~sQ7en-);yR1%B}39Yr3V&!5jz&lFXw9h2)6Jw|&@bZ*VJwuVmpi3RF@hq<_qQR3#S~~?Fo+LGm{h&B&S*WT;)lz ze*q9v(09B%Eu8_QZ@%rDf*d?z!{tv|ia%6!MVE3hPjvI+(zRd7O5hX;^#)f`j}6SZ zDt2Gdc?5(8r^qG)!{fGTe$8rFhenhiFG&o_54Ol)q9j^=a9&Y|MvRO=;FwTk_=3glzRAR^RfmC0_zUj*Tz ztZGhIspK>#`-q>CBVhMhr*kttxgCUR7-W1-=dYaxq}9k(X+y9W8=oMgg(!a{i#SD# z(`ZpXfDEUEhfU$k_p~SrTFlxI9@An8Etb;a#lU#cdtm%2<|0}wqeWA@aHK`_Q+yoo zy8H@HOyLR1q*Hi`>4{7^DhxD+n%bxQ+P*~({2F|7b%9cNDE^<0@VGI--%kNFhKT1J zk`$81{MW>61@3Po{T!%WJNNOH!2O4z$hB5e;T~OTT|4(cd*J?;?0sKD5>%cOuQI^Y z``Yav>dI0d$*VQvjUlT|8E~>m-OcjTZFu-y)9~6UPp!>17IIJB(bL)~PdFEtG_rvE zwo?(#n_cR!UUY-6bWug2chR_5FLR=SuidPKeYwV6yV-F(&%GG9 zzi;gJCi@#x62c#C>vgf%aDWkEjr(kb)uAvVl2nd%r|b>%K1xTbqTBmZzHrp5>`G;U`}g+t2YSBGC0<8i3-t8y{lRYjSsQ;k z(DNg{Sd$UhvG9rV7Lp0!n(fQ?&az(LwmcTFKMpoI6U*2iOHCt3L+Y&ZzV6Og;NyX> zkviP@{;|Maee4C;Uv*HZa~eCRIUv0!xJQ#e3kjsl8-FH{yO5;~3!7hcR{AKfaKF?F zZMS@OHR=%;=JK|&H#BAjlrKZsOHhjfy>CM-E;h^~%CaQX&@lwV<^N;3aRnHG_X?tQq zbwPS!hNGa=^y&l`0J*t3(bfd?mwX9s$=njf7p z?HseVuZ+!%52V6@2Z!R1rltiRe2I_Afd^|ZEg;ub`VX9jEC&(E?#@exhf`PaN~kh) zY5INqF7R-o3>_FUGv<>>Hm^=Prg+^&+?HkKx^?&)CVv5G~d)m*N$>%K1mu>2UyIvoE^D$t=PID4IO zo|}NuAOB6DXB{ef_p<3!Y*g_I3AaT+Sh;RN5;?IYyU3fpF*HyUmiU-$iDYl|WpDJ` z52(23jT{I1Gk+=ANPRP3TT7E&i}3ASy5(g?8|nV6PIZgvKnK?wNU-a-Hbss<3v|oz zp~>tYrf~f6UqZPIAOXX!1^y&=gMn>72G)`NXYUlO-QVO2wL*hEP@G9Dz*x)s_FSuB zyGdW{=I=?m)+DdsGQ+|J&7Zy5zelnqiM)cWCMJz(I3u?-nr-uD>q7(e&fu0tU?`m7 zTeH{IkYAJq$zP@Y3>jUiNuqHL6>OZX_(K*_3lWB`49vOAa4{+x@5jH-bcIM0pd!xE zt`(%lf%R&!#CRgAb9oM9>r;WuiG`iy@mku&KMfR|U`G{#fX)5^9Zosq?iSIK%=%cY zAT3Al((@?uaUKT6q0g$(aaTHyHB9%V*HY-$w6TshxKe0Dgq1jhG+=${rkAkQNV1#* z&QrDdo>m%;R2y4qdcZ|(ZRU-_6wY#a#18qmlRQuJ=4|q^?4k7yF|H)S#u3np6AO@10LPLR`qs&Qp-vGFQ@hG)ON$%S*$P5i3(EC2U zvMFTU7|Hy#K#V4^t&iu8e8qmyy>|LTgoMRXAJ%xS=`7}hU1!mDh_nV)m#?Zab;*3b z#vku|MLbDj0sJ^Qmx?4)9!|e+S*E|lu&?3GKXip4S4guTBrkwo8G1&nh;7CR9F3u8 z?a1DyXk&_c_1TY` zpO3{4k9pGDy>xnl27*Fyqu}FvZy#5po9_bMRK|OwkcCnb*zr7w7W4XnkW?cimG5^} zQB*H&tUp#iJplush3ln`<&rdl8|UBt3C7PdmreMDg`->0{>=A{&u0{U9yd1L9qoAY z1A0}y`X%H8(5p@pyW3xKA-cmWJ-n4Ij^xo5@eJFuX<0FwWC+|{!Q*+jp zQ4G;OCt|oB9H+mier>j8&Ol8m=rcR7RfZcB7wU?5jcHubEx=rJX>?w>!SK)4x^>+}0xHTz$AUyFFLcC>_5&~8=AjglWm_#nd; zTMiqeb+tA`cY7@Avnq;;4)GAVxkw7fnu)QoMD3ne4V$S%(POU#Y2xrDk`AwQvMC$Y z>2dHKe+-_yRAH2nCi`n-HQ<|^UxvzA1QDc^X8QtNWrB6}95L}pu*;eVsmS3P>;}Yl zgy>HlwM6t*TXVK1Y1dxMD6BbD74K^qg`h!A##jFIi77|7i1auKe~5#-S_cwohp#{<15 zG%HJe-BtG>qXS3@=ci5KY>O}O&{Y)I^5aj)5V_8@273<%dR}F{bbkbCY>+RRO+HWO z--$)Ep>H5k!Wc9+*3r~7u5A3OF$v@q%+3CFMQG07B$Foy6YrWJv0zEi1Qtbd-e(o> zwI)*J1b~!uFPiS_ubELWq?7&Ji(gE^Bl=Vkm~TjS3E~7yZkW`3hrP=mN}vAg{>qC_W{v` zL*eQLBp7BXA#*yZ6w|M3vUI>usp17C+6p3^7nR9VzXaOgre^X#g~d95_eNn+@xEF) zFq91;iri8|dv!ajuhQPdp64F7rl!cJjQ;z*LGTBAZnxWwWN%0a$V$_fkhHo|?+fkQ zYo`s9kYPAAvpQkUQH`8H1=#J~I{ACIZ<}#Hf$oAd1DrAIQs~j(oYpGsDmDxWhR$x# zW(Q`C>;@B;uFbZMARW$vbCYmhsg%$21@tJ=|63IX4P#5TH`8#fos>5p6DZt(4?`SH z_I9)mW*}x=mWKig`LC~yhryaT3d54IFihgrQfWu~?i$zob?SZ0l>b~Q|IC^x75&hk z2Y(iZt3}03K7*b>B3Q3=m8x@QYY%ue(=;yaGu(Z}-GScEnCbF9u;JsJ5H81;LbBIN zU91mgDp9DEWsE{~=)#z|1HJP{r?<>PYiCPoOR`|f>SsAbAxrXY2r9po~C zS0hYkF}OgG?|p}bkW4aH*L|7couG}F(%(9>W#9hQ@mTu%kb|ZD!~GL4J$ZSYh3)JE z?3jz&TkH?Bvz;=X{3YDH>MPn_eM57#y&8Em+vQ)|+o0|Bv9-lZ3(2OGZ422=cN&bF z74|yC^HAd%3{GRj8b}6DWRaf{#k0wEgnNHDauL|r(u64T;riRO7( zHW{@R#j=eG_>-VlTig;ZuHh_qWaD!cX6}!qCq63UBCe2Kvrx@*j(lA8!BqQL`{MCu z4HiT3lH&)hUvI9+rT*PhbgbwYfa3MR&W_hD6P2_xLrliNT#h@agwh{E5LOzQQ2fHq zpF6pW^Oj0`PfL+!=)35pM%o>FxC)G!KN~wA>qLw(spRY`dZtz9i$8-{E&qxrpCO1L z9N76PSYbg`#5Z{Zw=0($?}e=r95|tOb~Zvp!Z4rfP*Qi^KF)^>Zd31d`yDP zChz8$T!Je0SS>+iA}Go{O=-&#Ucq5DQe`c~VzCDo;UL$`pAS5=Boco*{V_}!w{X~u zWZ1@&_zo=am+y;{BB4uZC2(Z;0o}6G@Ez6}!t58Oz|v-w9GBmu0{W|k!D@_?vJV=* zM?D4v4BiP1O;lT(t9UfpPz62%JI;WsYQ$WsB|=J_5OAc^$`Cz9JI^v`1-&T!;e7%> z{#h^SUw=LHRQIN^ClzI=>9e_BrhXH~U9;By14cX3cS^=5V=*up_+`K>W*aB}$NX^m zqO~N?98S+w2@mRx->$RTt0kYnHN+xlne?C>3o6&ol| zu-UI-q8MJ4hfg~|*KCn6`g7F>9YdE(!$;ZTjqOq9{F{wA-}^L(t>&dj{AeJvQ|+z_ zkK}7S{1?aaSk*@UTNA@w3rhp>$Df^BA3c6x?$X%Yy3pJwWO%#MFf6~dRcfhqr<79I zQ4n?n`3HKUx_V3GaG!Nm=m_Y}d9#Q2=ez@a*W8xIPXsbQhB_PrLe;V$Me16q`ee2H zhn5*6mLIftB*`R4qfmQj@G?z3#9Xz^hZ_cVkDy8jED5O|>UBKT(O(-&)sUOAn`Q@U zV;h0MqpDyXpzg?F^1>cD#BSSY-;L`fv$5g@NqkGBOu$ck0@A%26_7{f2M_()OxGrP z7MEh01Lj*73yLMt%;tzEHRs4-EO196F?$BY%gZIS^TPha`)RrC@cz*j(lZY49}qaf zBUcBrpYa{JIy~fMjt@y0)m)@VRe3Ar!t!SlF2BnB*=z(dEhIw5IkKeuc}_}K%2Y}@ zhSqRqZ?LNAM0(<}g01O-n#|r3wAJ*>dH_^aIA;&&Bc;}*9MT>`k%wzd7DWfGtHSXm z;j}N2c{mjB?;MQxOTAgfnNhg?~lYw;q%+X3O58R*A zQBwSsEg!W0%c!KsP)TPE_rAbY%lsSfeUb0kFY0dB^;z?4Xf0Te=IVzpfA`(tErHLS zN1G!`>I8nAT1izX%kJAxt)Xhjumhu|zKoVyhwGRzSQ*v_2WgU6xM3eW`N*5S-cL{%m0aW!>ZedqR|4nR+%4V_ds*WN-YAPN3a4it^K1o) zjc;d{y`63MZue~qWCo<4lrG5hmBgDuod=Nz!eD)vW0?K!d5^?cyg?#U0uNmi$*z3V zL!#a7%P0G{Eq~O@!7ddoJD+#_elm}Q_TiLX<{Zxr%A>2iZ}5CkUuUeO+s-7Y z@JJ@Cm0|;kdMJ@!mt4=OT`P%C+ZI zZHgc%)!@LemAqSgT>& z;bys)BQ)4IVitGCc|Pw}Thop&U~UqgK+lhv->pkDPle8|U$XDWgcF@$5IOM3s$gbg zg(uMKErc7X(i;5VAdgPaD2mz`tDyLJ9*WdW19h-zkLOq-SeS|){)_X|OG^WF#u4|QLzp}>&| zjX+2{Me6))ckl1#qt=MKk{N!FK&ez zJ@h&HqDd~uHG}A+o}sxi6vIV8oUocTks;%9WB)V3wq`a{0n<*@Q-F>Y_6&VMuen=l z9}n>p{e>;{H+u!!&}`bMwtUCuo5@f494I`6N7&$bbA<9gt3+l&=1dJ_TZQQ%c7Gyr zAuQU+(?P;G7cSPN#-=vN-lEg(OJ^QC5ZJXh^P&$2`OITl!U?Osg5|)(7Aoc-&{OV3 zhHxZ1n;*e0H-}yQLAl*w_O*{|kg5cR2cm)h@|iCl-sX$d7=rv0Z%=h?Z=% zfBWD0$-9X|*`PDF0uQ09oo=C?vWeBS%R-h+7(WRjwioXRBQ zNM1@Uw+asT9oqYR!6=>n=CF}sKU-z(J#xqj9yxU2CAet`0F;cjM8-0`4`j}b5h_3Q z1`@Gt6(8<{pOhSa#JsjY55S>cI`Z>m$xcIO^62A-A3uZ;eduXNw04E(?k!=@k;A`v z9I~P7)NF>Bo_Tzq$3vCv$y=WQQ?h;qHS*k3qS$t*Lv+EvqJJ|tq4ssvxNx=F^}ll` zCeU+-9v-EikTWBN)FGw%2#=nfe>8Qz2-3M7gi^G;USMn@;}<%ec^KPJ`?{EE;MXta ziJ)Y(0gyi000Yt#{N`2DSQ&C89XZpc2|T=?W|OiWwLlThm;=2Msl+&p1ROqcNEW9A zDU3)84j;CAu#Ot?4)h#ggzS|QegZ?)T$dPhIqTCU4thyBSS%D45ATOAg0SL=>IAN9 zH9~x)m(x)9&C70}w$+VS5vW2HRYJ?DZN5eaKT%33zH#N|P+rpiW^Iw@__N0k&OJK! zrOZArXLHel^z&0*PoLr7up8PAiVL!?WikDVCW4|2FEj-Wxdpawi9nBD=?Q#klnsRAOVT5UaenQn=~FnWK1Im=L2j9bf#-I$G%k)wPg z@x%I5LFib+`N2R>Hv=Mk+t+T)gU*4GYW1`kcF#@wWw;ecKNN$XWV8gAd- zIQ`gOZ~6nK2%XQWJl0THkUF<}zjs^XbnJ}1`#YzjzgP)0(5z?qV>5Ez$5KzI_IHy! zcl~XM$XAjUf#OiD>&T>U|2-yGuoP>vpP*os;5EkIhW?k|QGW zl20}5SO}q3>yv&C_qR`MuU?qGlyQ_|jBjdgu_t{;<_|war~^R>G%<=3;&-4vO;8$l z_f}rq>6J%K!x!co{zsE7B%gGI{6NGqjcpm@m7uR$R3UF!yBU;m zNHSbgVex;|S8G$H^+EYG6!qEvmBqENMt<8}+Gh)_MHRWu$Bdqkos^dO9TE-Zass{s_}=Eev5h6nh)g?NqV(c^bleVlUkvKXw@R(sQD(x+|N8O>7Sbk zNuS97&j6T4QgpP9FiqFK6O8w#TEJPPfFh46b}+Qt?#(lOH_kz&YrVGWhM;k14`<$( z-1%x?SL@7d>Wkrb>t-^7lA*Ku7Ze*Olc69apron;_Vz~c9>Xy@{4f94R$4%44?v z`AdvaAr-G+WBi0)It8lC-ak&vr6!Wt!p8*;@s^gf=c=_Ydgi@hEj|&=b)N8Xj(uqF z(3xn)zb^py%Rzi8hR7sulrbNT_*!-2Ds;>#9Fh=^VoE$IsZu4-(hnIp&{d$4p`3By z8(iq_Dv_kSf+F=dtvuE+(??be=6=}Z?Zo>GZH-L2bfFwYi%r_V{SO-)UCdO4d3Le2 zIaGcSA~c5N&-HuCwk1h{X_m`Knx59{f&Qnl`+!F-VZK1mebNUw@~X554MN9&U(iD& z*HD-=)>VW6!OgX5`+|MOT$&lyTt*pKSOW{}kln*1tt2BC9De72@EfS);Z_S|Vf@#s zyuVIOt|9vN*x;ScU2y4>wUV6V*I2c8NRz9^%@$Wd%m0|pcA(z&WHUgluvg<6;4rFW zTuD>4DmE$z!_C7BI3-Zc{iL2ieJXdThNnv8w`(${CTVW5yC{qENovN>jiRjZQUh2~ zk6}oGofkQrFyf?D$CVKLmlz(k#OX;=}2<9 zaLy}Er=>Z6Av{h*?zX`k`m;`EB-$`+LNKw%sp4Sf#p9X2cO5RObCMDh9{R6+!bNJ5 zshd4?*+@5-AKh*$+?+=Jo`1-5squM?>PWEz4(TwNY$ajC3OK$n#08lN2j)kZNjzz~ zsxidGpq$#w0M5EzW+T=e_oTv@Nmv_>S5P&pE9X66KPUZlpAU!QEBos& zEXd*xh^Aa$MmM2&W2JQ{u=D?Mb}sNy6;}h_B%83nl3iet1tUgXHJYH&pn?Gnkc22n z%sU{DU_}}uT9jQt4H(=2SuU%zrD|IrRnb;H+ghcFFP})u(aL1c}lL zul7OYD|FeOv89Wm$zT~^tBmUX#zsFN_{wW*Dp+qbh(>#XjNh^R*z~{uQGruM8X4+i zwPy8P26qg~S+wpjViyHlvx#&g&&W981P+HhDE!&xUnoJ^l`@oBx^T9d!JETu38&r7 zpEIuD&xk_)oO!GM-gC^u;GPUD>Nw?fZRk@|?%Ggn|08=tJM@2S`X*Yb1XI1goINv{ z1Y14YyZXO2;iE+9U)_czq_uUNE2SL%puu+fu8QDaUkz@(i%pds`V*7^C?f2USwM8l zlj%UO*`gDRwE0CqkC^P#j>#OSZ!=)ZSeY=k#6NWGWdGotcgC+ifqdsxTUG(;=7X?~+9 zyFew>m=|p2q!Ok19r~{&Q30pm?0~qMKNSs<5|mOxZTYJ|za{cV{IK67sN*bF&!V8r zmaFWD)~MqwK_s^&(TvU6VooE%aqDq&A(VM{83g0M-1uF@Z9E~M#zOgR_BHWytMS>) z&lU2C;+;umv#vJ$voGM6u_23ML80(G(G~IehaUz$TY`U(z%k}p`;xwj1SFlr(0yXj zZIngSGJfe_S-$5rc+0ser;m7-PLNm1KuoaJtFlYhbjiwYeAjSPSw$YnYw)QB*x%oY zWks4dvRcU*>#7zK@>1h2>1nhe1r(Y7SZm1y%0`oHT6;%(9IiFnaz9khSqb})*>g0h z-5qipY&418JXp5P?_z^118ZnZR^hu6I{GTp;Y>UE>|ymgG~S&-Oc}E`Q+)2WKtE_v zv}Anj6AIUZk5Gn;AUPgNL%$VD{)Avpc+@ccKU@nUIGu$k6K>Y^`R62UZGP^KNGp$TLs zgD5m)DSazEqxJrxWYx%SV;~?viFKzNP{$c%bbR> z2QjqlQMnD3ROw|5S6J3{5rD*;V3*v(A~N3aWyx*u-*m{R81B!rE_8|OKH0(Ii?{#M zlGKKa7;Mk>yIxk>*kj5#y;bt2tzjNi$)>Bnyi)%p2`n6hu35w^m_skJJ5h$vcrByR z9Y_wo6*Z(;Iz*(OY&xfm+|YTsbmVruR5}tRCU^~{K#tgSY`C4~Jw@|?a0>KDM$zk# zJ%fsdi|Of~zW7bFMjt$Y!xiRGphpQHKO-;KY|1K3mO#pqj~jMzj}dYA*NJpTjw}wn zmGJoH2Gs}WTb9C+=vE5eW?8HOW8v{4V}U3V4-$yNJhLM-V7}x6NehgWE%Mhe`EG#07 z%W7xJWi{)57ov}x$p`3k^GyDLC`=#Tb5^rjj!?%~Z4sw+X@}oA%aGRC3@Jg&I3;j3 zuZwCNxEm?YF@!13na-z0S;0GF^F6wXL+sZ_TMYyiWzpxj*6m8(_DN;H`zQM%X4YLyZVo0 zZzI5)wPO~0mRzOazxX8Z4;5&&6a(JjUGSn4n~}TN)3}YnTm_9@xUy0`0B|;T{3p*c z?*HBH_K)M7)GH5eu-<+>|NR_E8UpZ&BW{^TV%N`i%pR@mQsw! zTdChDmyH0q=~A8ZuQ9iHmo$VYPG_9iYs2RLeK9xX#;^h_2;PIpi5>>~ZS8)wUk1dd zeA9G|k%gh)$ScUb#oPFFoi-VT*v3}bU9-t`v!_Va_E z9SJ`+TNv+dxKEm1wLnzI_>>J0XQdpZpa1VfMzoT{joT<+i%eJGbZvH^$H!SLWakZ) zdPAq_8`gglO*&pLr)M0^&e00I;m2m-K|7K8Vr*zh+8mB=^*>@|iPJ|+tDwH-T zKZJ7jbz)BrZk#WiEI(YEUXDq*_DRO&l3IBHvuMw#Vw--v1RAV%bIGJuzhj4B(i2>a z+?EMgbAn9e>?gQ&?-FHp7A<6KD!Zw$K^=Jh@PE|6A*q-Z6^k-rRD+{f)H(sjcrRXb zRR@QPe{7E?X%3bl>FW8v;S9*wM)n6IlWct_Ir`R$>MRPMAf#WE!h%~yiw2Vv)wofs z^T?f-!9-W0#eEafA8jRw`!394O^f7u&ojcWnbtS=MIRZ9n7hME(#f8O%a>wgPZB5k z+OiYFs|zgM;(AJM#nqs`HwUs^S#_J$fIOwjv(Y$<~9)wr{ILhXW?e!=HdKw z^{DXl_Z_aVQuAR0K&(ZjgsU9WnKZ{9nmDB2MkyEND<#g5r^>JHH}; zxJ4>%bS!S9I;}}lE$|QGc%c5{hm~=2bvA&$026__-X9jT?M!fAJq2Bird2kPg|#oq zS!F|=Op!gKd2C)`aQkRb4fd#&=e7560mky?P;fj6nfHW{B&;p$oQER>Z2W8 z`VWwabvb*e)`9u30<^L7q5WuHen+47NggIiSy~8Iw=1mnUvfT0vx~GtO3d5?2wK&i z^zcN`>}tLi5XZ|Uo&Jpn6{<^|OgYew)J38yJGTsGRFx<>yedTcZM5Zca+t8=ZU^bGwkXfG`JmT07dAE{xaPq^@D8BS}Sa zk|3<|B@`!OELDlHez}B}R#TsEl)N#hGIUIQ2GQJRMb0uJe{M#eCpjHZHA)$xXrWY_ z$^mbYk#4?9=hhA$hDktNW)%+^vDHQ?v@l=rRU{8uWkGRXZK`w3RQEj|?Wn%=*D~K* z56L6t58bqJ%WDVaM!n2wZfZUUdqQeaz_!qm)7U=< zZgX<=R@BNf&yx($R)}ZY~;= zGfUP0Y%CtrE1osbrR+R)T*%$9oLyqQ-ZDPNvqtQqSUb-#`3ST1F+1g0mgW(M2{Ak6 zXg-fx>e^J8fL6bL_V3i1NmkZOK%r7#5A^4!r8FV30T@kVRd%O_1oaq0ZQ{pE*ZQqSI*U(O?Ri*0yP}l za{Jh2)2`#uEI8A>0)MpwCAEc)nhO0R8T~>>3p`@e zU+hkBP%?nU#tr{N(*$=xj%RlHuU5z#qX?|Gk@x+-RoIJR4rM;UTt~NuAf3iTkQt9Vv5isuc4iKpkWw*fF7*Q!S24gz;OopekFOA;gzZUpX>`?WcT=H&KY zoDr_eLxaj&R-wJg`OeS&0ek2#_hHq{T?mqc+w*e2K&_9<+dcKsu|G|{K22QFh4vdn?Ip19dy~@^*+mcr& zrE{Rh)0h~PEIDYcg06FBZVNe9791Vx_1}!GJM$Q-gxg0lQT*rP1kWNt$f7%P0^?YY~vYh+dL3;VYoaorb^9EEoF zc=K|1F6pPPIdMe6QOXaTV}9TkVm!@kK^86e>914^Mj9;;h{O56wi!nbJagA@0!xv= zugWj#Q9d9P1^?|p=bA6q{R?GImh+zRva^;>gN^4-mg+!=m8PW!_?>^6_QU=BVx=i0 zDzTxZ;u9-PtLtSRu+w-NK13B%u7{nf@iaYit1?08*6Kf&_qB@!X@=GF!TOG0DrVHL z9XJS=$CKlptZuU{l}6Qfe@v-P_7Qxs6UQ`7j*c2tLABRFErTqx9JMpjW>e+#uwGerThrpB!^j-S8M6@SyHmUM8_+2|_4(7Pr({b4 zT8q6F3}?Mq8dK!xI8UDsfV_FYImVF_6h?d zilZ2J9)HqC7pXq=xWc>DT`#LgMrq}w@75y-b~Mx*Y{TM!C9W{-yTUKh5vyGr3ON$9 zL^AkUxR^O>yc5G!OhB>=fVnu=vboZk>^dFFv!}b3iP^HzQ&Ixg$Zj1Be7s4>*T@-; zAm+WN6k;wg8Y_4XR|yHPHlJeZg<>fPxyC9;ZLdo~VXGiDn&ZZTS&(tA9FMvbB_X+* zUj{}hP9HsWglpNa#Z%)z#A}jWs4QuUaLBD-5e|V()k)4GZRqIhNBH}^ynk*D9$qZia00tN!Vo5zhx81I5Rg*rfUOhcwJ1a#8=E^4!uBvHXSb&c{wcoZN}Be z2j+CIa_)Cjd3xNvud8m5dtbGQ8|i1P(d?1e1|3*E^2@!i^4W$MtL}Xn*Q%GqU8^os z*Q!fB`czCX12`6ll&$+Z5i85>NdrUKGiM-McDLtuV));?sXP47{^{f>i-&*7tnYyT zhc})Y{6D?kgdfVr#znQGPC?F?>j^v>Txd{WTXpHSSxgPVuPa^wgK0U`y=jC+#y^dU=6~h;cSlhe+dcr z63r0fH;EL9N%lm0A`wYR4u?J2k&G{qzljdg6J=ybarAN6Qyg~lHVgV zXvrrj+D>erg{v;%AfwS0zSh37LKMK(Gb*F0q+I+b?2F!TENbfiYwoRov)8y@^d~x( z9)Acfde2p^&GvvhyNW9eKlESX+VFPLwsC(>w%HasMz>^N$XjSvH}6_7tm)|Z`6E{T zsO8Ek8zyi)M&6aLFWKgL(H?m2vMSrm?XC^GGPee|j5l(B*0fP_j}QEr6b19x{Z->T zm=e`ec%a0w$h^NC2mQbp^oLj{M^m*F1%Lfo)@1ruO~;~blROD@3Rg`;^-cX-df;K< zrOm!y$d5xCGM$=47QAcl@o3}+#`k5z_`Z?vaDkm81Y(~g1lo?2 zN??h-9FwQ*`h8~L7zwPlSD^dXuHR_}`lP6W{aQ&YC2*QRQQ_*&T7B4GWR!R!c8MR_ zcJGJM1lcbM*ujq{azNzcl1`E{duD4c{&Ec9YTiS**pcCJ5WY-%tT0rGTQ4E|IFr}! z#sZx-ElXxK)|QPqTN?7@BEmemk}L;IRk)rTW@=N7@Ok>+4-$>df;o8oaJ_8UHQD_z zcear7fyGZuBd67(tqPUMN;aQKv#2fKcYT8X&2_Rj=~{M<0K^iYY0)B^AG_#&W-uSu z@Wt<1wt%kGmnJiD9U*(3sH1-=D_ZMOoTndA@&d~_B^<@hm(DVE6yp{1uDgw0v|UpC zm}}Dl&R5n?sj|KNDt|iqz0xY*Z}10D(zKSHRI3$;3VnL!*7Cfviu%38={xTbMk*Q( zS+Y*aP^Rbo$(G%DACtUH+S&taBtNM{1&==u$oQ=&lOxShm6+jlZ2ioxd0bedmm2@9 z=RtVH6*HxBYRW09{^uFY1I*PBl74oCSfFO}&*49pbfUec6_0i%wFmFyU~7=(uBgwO zs!BTamSU_V5?#XdhA6e!%j@S7tM>zX$`M^2&g`9K4QH}nwo88(6si?p8-WVz&G!rV zeu|LQZc&Xsi^X9%V_vV-)J(!=$^c4A7sHy7?@3~SYG3gezT{stFC$pwbQ>EG6OHI> zHl?-Ag4aM21gp6--`C#K-@lXcwhYkT42{o@43m^HHW&l7`l}tZnuIQ}vFGnHq`Z-1 z6t1nsH)^8Qvhuu6~?=eay ziCZ%mqHBY*U=QrwwZUHSHow{$b-s2%A{s$^m^3o~>3Xr+=GyG3F3OQqA0)l&deKuY zoPFunw=jBK;o(C>t;^Ni#>PLT%0~30(CC&DIYIQy5zEfVZ=rxERN@U)D?{N+TZMgZ z*EUNh%P_o!5sic!Jd)sARmbL8I}IYP`c;Z;!db4O<&K2_OTK{P@O$S3I{OFgk(ZU<-VVvgUBJjX!@u<(#vuq{kq50H zxfBO_qP9pgLF$E~$X)V<=9eupPrmxf*Btp`6=I7_=S!Ar7qn_6 zYl#A2sUlpxrXpOhzgF*eKoWT)0hOqec9p4joSrZx9yb=) zD#~i%`(u;!HRGgeyEYVVgJ}4lPmI|zoy@_-b{m#_3+yXPI$IF_5u*$Cizya*&L)+X z?AL~pXDfLKldg`ih~0F%H0cvr&N4R&w%2gmqmvCl!P8#8Tlrqkfk?qxsN}{!ON~D5 zV1#{6VX|pLY81U){}n5b;9>`=10roKa5p3{*efwJe@~q>-NCHP&ewK*58gwGx3mL3{OQureC?u?pyv068P! zY#{1-F=Y!8ry+~0Lp=0f!P!R9L z9KsW9O^aL-%cNDeqHIvIR%i_Ir<@tOU3aNuUi!#E!rmef{Ss!d zO6Ky!u{m*L>?4x$$s$36E5~h zi+HQ|1AMJM2J9Gv5zf|@UO4h5K z5)Rs1nG)dF4YG9eM0~2sR!u}Fx|R1JX@-ow{WaQ7fb!~50wRY{+r`ZDKE}7=QFKl9 zdLbFmxv5TdT;u~$?G*+lyo~|BAJrTikUnb0za;Sj3sV!^Q+kouCNuWu5(@+{0~w04 z9u{my?lHp&1j+YW!S$-L{YtoS=^xoG`lym{m&gf_O=~Q8oJtOda)MaFH8}Q0&No6u z76B+@>X0@^Qi*VFC=hd+A{-zUxOK7D6p`z-X5hx*^q`6vCo%66BjlX(kuZ$m;C_MV z2{8EVWr|_ErQbwAWtsM8gJHa-SE~fVXJvP*fUOoUpeO*ss7K!AH5It1ey1!b zpAflK<^mEslD08Y+(NjJi&_w>e1An;YTzBjjm;ACmcB%)U=NFPUO5l2hYP)B4< zpJE*-*y@fHlYpX4N~h06IoTE&Bf%J$W&nUf306$+Y=W^d>j$fx2t@`PQO-LAgv+D_)$zW6(9h}#Ja%r0KR=;8yid*JpDV>P}HY!6obsn5MuVOyfK z>V29z0a7DS*yE#Oq>h-En@BvTZ&_kw6(L-5N)*Z#jxO&wrHO#mY&P%~63EDx>6kcg z!z78FW5$+9ENqhmMr@J97MZaZtJu9Ae_?!oY0MY!(=Y?QoK$}^Q}tD;I>9d>z$zN1 zNo=bb+kuv?Oi!`c=@R?28T$uA2N!<2Ut#b~S%<*c1cTe;8%jcx74#Gs=qb4-h91Z; znYW!g2BT|wDcd4X2*w3%^hj{=URzJh4(iIP73_q)30W!LHc6nEq2}R@g;LL3`lm${ zCIizDF#Il=*53-%xOJ`Y+h|9sHltI!Lcdt5grrq<@=7qPWTPYB(x0RR8N+Z7nH=H? z_#+N$h4%^f^HbR(t1_rKi#dU#QsX{(-J2}RF2~~Q?3BzD*RJX2x2CDYYxH)GyWcZF*F9L$W-!_fQJKY(dmI#2tU6@;4L_k z1UkffC0?t8JXG|)^nl5x&j4pJgaMU;WC1)ia*gbNK_-H>9e@nlBA1zAGgw(wY+P;- zSBq7gNn8VEUNcL|q9h@&{gBrl5g;Kiv-6eoXz=r&9t7SJQxw_HVEIV}NzH*1;+tl; zBR?P&lE?>0A{E+C{H$k17!-MJ-MzK}?^J=#Mpc1iI-U!dtAEt5j&rL&O zYeSKJNu}iB1PC<-PKpTYA$QIt6cZ3Ljx0#4tlTK)dUU4)y3zJ2Sus3L6`)Ra5SplS za_>4by4BgQtIpID)_DXO$CxD|U+`%zU}e^MOYH?XA|Fa{yZ(!2grPV27J63<5)NLg zU+{p?jwiBS#aL69tZ{4g0cPAoDz0OMTKcJ}&4~ZkPmH{aBp%UJ81G)XxRtzbn{m^L z6NQh0y-A2GC7qdjpqA_~julQjgJY~dXR=I>j>sh{X|uLWs0H~1QFcG%vs1~&BGxi( z%vc)^tf`b$Q{E)WT_UkFpX=AhQY5Jqc9@YMzD(buN=L0N5)lb)1~K}_SSur79|0DJxg3%VOb|*3 z(pO1!+u8??U(Ej zZ*y1;)W~CI%3A$zKa>zhBrNIrv^5#W4r+&OD7Hi;>JFk5JP(AViT211W^P~!nn9%! zB%(`f%^O*vx;!$9m|Fc^Y|Xg&9O{D=hQs<8EFBpN@@nrA3pe5X(asj$0#Uo1#wO=H z^Zs;PLT$a;5!H{?;>0?ZZ+;H+{?JPaG&F*ZY;Ge zd#Tjc=ZR9=duvN=M{t9l;+MFQ{N~}RaP_!5aV@w9ac|%jJY8yg0=EhG7u**(_peHA z1E}{*+y%J98%k|s_`L=<9d{=#hzsLxe3r8KeHyn7_Yd4*+&Ppn5_bh|JZ>s(3GM;h zySRSOl-fMFAh1v3cNy+eTrU1g*Ol5P3O5J06!#-zTVzs@-z)#XZc4_voy&|r`Hw{D2%w4oj^3Hdi{_^{K{ z)}1lp%=EL)J}1@XJNLZvGcHKJFf(i9$W&MAc^65Vi?c7eG<9SS|3{9x>~dG?6{E+D zyfP&>WvnYTbzJIISLb;=<0nkaPc0~%be^ZkbqZrb!2GwWu}y5W0ubvMqwY0mfSZ*DOE-7@!S(VchQ-MDxOW$}ON_4hPU`_g;Q^8}llmn~n>5;9un@vK|7Qdt6!^y4)@dEmi^e(Gxa+0P$-Bz5Gvb&o#wi^rdMa_zcxPd)w1b?bh$ z?wMzvkppW^wB_{szn8?7)BZ=2Q`fsjr%P;Xz`87KVkcuU5FQz$t1_pW8YAi z@$QVAyzhcb1+f7eP0><=M`t&>^s7i1EtSW>B^>eJBPZ;|mpDUr+Cw*U9WbF~YGSC| z8JC9nUsjpra@bD8)!qwG`49{;^bsf~7>D`}5;<4CtF_Tu{qUd6M|-^6gVDsrDQZ6o z{eu3k4f(mq8p^P?YlC{15c`_;yrg$>w&k?{^rd@%|M1Zo*M{d8U5!Em@4sB?+VH@< zJZv()A2{9hqBEfLy>#o8aR{XCT)Haxo_aoLuxrDHBSwxp-&D1UI>YjP<4vsvL)Sq5 zvMUZ8%IHpb{NbA5k$`JODu*8cWos|BJ#UZtmOa!~ihpu~(t2-RT0aOSiqlMe4cCS$ zZ$jRodnGU-@Wssb0^1sZ=B2x)yAwtRE+k)~dise4&minyU>1c}el`@7Y1yuB=_PBm zWL4GhQXc-(diaO-@XM}9eEO;${+c*H@LU+Ubmip4=3V~GjUtDj;ITS*^uj<&(^&7t zemcV`dd2pQROwyIWF;lh3If$n zjeZ4Zd0cu)FttZ{!+OM*_3+P#^Sd_8H|Pa{(wqB5fIhEEO5lCG{&}tqe(C)~0X=y9 z{D4zxk`vt-dAuabLh4KtJlV6AFhOPWYN0O!M{`gSQ%2b}<7R&E3_2awMZ_ zGhGi;*ypDuIqhtpC+Z|V6clfe+d{K@EO)ZO!ID$tn2z;8?;ga8^JnlOg zD1tneZ3Ys7NKj^Qnezj)gv$^X6jaEdpuF>+cZmJ#;L-E_X$*9eBCL{Pz^Ma_{`}?#7B_yHgZc+1cQ-JKwqGr-G_B7O`Ps30j(M;7@ zmKi*9lON4~M;N>ABlHNn!)40sG^aX8_1AN01$USYZ1BPtImG%iS46#`gwR5{-AvHw zV;1HuIZY190+(tB_0AuE6K$X5q!wGwAr+dYJ-8aMG5`0_73$) z$d^`BTo$@tzVzJRsrH*G0-tb1f@$X^0~Ccx&kHnN_n4#xKL4>r?w*5zzz{zybS zBf~+`i(ah}?f*UU>{ur2Sn62GKL?mWT?tq5a45!cJ~b15VSs>HE@p}$GE?+5XNrKd zLSE@mvx&@Ku1)qUPB@>0C%hIsa*1ojQwl3Bqu*3m$>1j#O>r%|k6^9+ zI{qGvCaHwK7+)#HzhAA2KjXPR9j8n29ugKAWxT4Qo=fs4K9?BwU&Z{m#kJwxl@ITE zj+xQG2lp^h;fh1`h&R|{!JUiSzq{1-CtNk(KgZc@ObV>kd;GJdBuI$*laiQ{6c=re z`##a9to&0FzM||JNNNynCC-+Vkksv8VmDt>?|5U*tJUwK-*ck5?XG1P@l{#VkfFbS zF)T|>Du-RoYo%v6HfKjKCC)~@7^qj45Yt12J{j9QZc~`{Tyjg{h|m&u?k9mE$_NLq z@}v>eaf2zbt*kmTp`YhWfB#^6;?k(?^`GS~IZ&Om<+Vh{Ud^~I3D;uYSpVz>EG^FT zb@bE!#Mf(y{Y0b6-d>naEw<21PiTpEPUyC@w!$+L+X_b{>7SJzi_Ul0q=M=9zQ)^MYGBw(w*w}O8 zo2j)=Q!fnEZLiTEMZrl5ZJ()vrqylVIBQ^)%~FO3r5p49JhGc#FcTNwC21I6!Et-! zT|<9T&KAnQC_@l0V&kLas~wY^MkEhqMmtV#NQ@4df=_h7>>QH!tBnpZ-#!eE+b3mI zzb17B`sP5r8k@+i#=ep1r<`?5is9G=&wBPC(v zUkEU(s^?QG1~gHzd|c9k!hXEJ9)m))#I;PM+TggoB(MeUYM9<&tGC@&0}K+PKfg{L zW$Ej)+1ehrNF{RBJIAp#o~n!eN#^Ir{RC66#40jm?RCEX{Cu-jY1)8Ri5aqmzmLDl zAN_%Q(0dyx^|vRhihF=)LEjB+k4y71cRZUQ|kHj?QAp|p_{seN?M1c&5lbu zW`OttuKN1HRkjAZo{tm;s#Ot^cvF00n&7E>(i^K?L_Sd*LwmUH$&E&EXuxxPgodo= zuWEE$66qe*+*ehSEk+W7tG~b{-D|aB%mC?S;4(?zSy-zDmn7a4pEw4DDm+6Ko}~(} zQ=*@NtLO)Bvu}+{c&F4h0XGG=2KOTF3c6w$zo+4{O#c~#eaQDgTyT>NeQvPuZl8A4 z-*+Q>OSU>$xNZ7KBG7DDE=;3L|ItW8rij|_;mwF;A1&rNBdFw3PIfPPeB(Umr@aqW zXc#1k(LLH*uHWu1*Oy!f4eO7;DzS~$9I|7#kk0&f(vta_e5H}|fkRCjqxZr#O5($tLuHf;c1*Z{^RY52;CrhQ3v&cE21*77g5Cw&WOUj6$YA7k-jm->Up5@fyQl<$eb9q!zj z_QrP<#Dffo!;hwe6*>Es&DPag5+zi3ILz)?t<|S-`ONHw40FwqZY^25b;IELCR!R9 z2xlzQ*I!`H^gQ{pN!zjPUxD8nM*TerfuC#3o2gTd)~T#sw&Aq~M|iRO6*|DC^&zmY zcHNQk=pO0Pb}^I`i17N<`MGL{-*IN{Ztyi0dnljr)3%ak)SB=+SxfNBaLPvYy=SrD4<54ZG6C( zy7OP|3v<^&5uUoW*EvkROl4*Qp=mk25t6l%eyUsyJqmd|EQ6)^HF2T zzx-Jv!7w&e-0W;MVQL23`Vag{nxaTU_^Nr4)to|<9321nmWYq)@hy{o7W*8+p&Z6- zx!_Ufe79@E(%IZvVr^VCk=0r1ExTrKoJ}1|BlQd*47VrbeqFc3nfbQ1ZP}K4(1+v3 zaO%xlbRx^N@nhAvaws`z=60j(o-7S6E%q4Qq2;TD^6rz3lJ@0m1aJIDccZ706%WYEn1K;r7F`|9Bgvq~l6>fY9^L;!Y zw&z1M5JD{vQLHWxrJ-gb>jH(po^5PbZIiOwmrMJMuamZswZ61b>S=G1y+6sa{S9Nk z6a6HfBCBN^x|A2j;Mlpr#Xjsf1Q(~<0=c}%&EEOACNeC%NWU=uSah7M0pNemdq!w8 zJnU`-kJ$rfz9M@n9rcpcze8o+VNN^BYE1B0a$vGn;N!VQbfVJBDk>WiYEV_VQ#CXl z!g)_C@oClRS^)~PB~FY%HY7@dDX|2~in*`)Db>Do}1nEP(v zQrBko!UCDW%`HI0zJmYs`c^fI>8mCRTX2|DmV!$!S_OmQ_>+CshJ;FlRs&*e;2 zX298P^OJYSsxfEI{+&;ra;^5(&EYbATON-*Vr9MzTJ2#V$Lc$tX^mej(Fid&qD=S7 z{n7N;(+=r|w}N9~<2}*zrX?6%>NBn%b6`LeHTy6X@0g&P!Rpth;M101fGGc*Bi-p* z_UT+P!xtUY?kJtF9W&IDwA+Vh#!;X_d5Iyiqa4~QgG67iARN5EFf=)w{H)5;X~ zC!GY+-hf(SsEPeI-Z&XOY?4!G2tmD78d|;@U+6v+){|Lv@6?l)C&E@&c@L@bRM`Ks zykB%HZ>=g%h5bLvd#+n~>s5Iw?EhJwOj2F#m6chl04idtkXXPE}7hPB@^V*e?$>wm%b@G@GvCp z5BkF0j3M^VP_)Gs&SINZXV)uVJjNB6zC5`aoaBrKuoK3*BHQE&rdZK7sh=%)H>Rnb z(56=_u<0}2ITo$c+G5L@H_Fw9v&j2_p^w{{KDpIN1Q>2C z0R}%lRwWO7FFt9HwSWvwgvW8JURS)S4CIKz<0UP#bqOodf)ACeb)3O#z1Yd!FY z6JgjA6GT(Pf%M#G<1A{Qv0W=Lfg54~mudjlXJeBY-4me2BWyMPew!qB& z{JxN=@0kKHYPak~0x+tn-zEV4UZP=4tcYY7@f6rOhYHiud7bbo{Z?)Y&EbiNml8Oa zopa9CIV?e8qRAaMu`5VtBx`v^yk98$lC0^sH1=;AdnOw@lX8zN`A^O}vdT~!l}o=? zJC&*WxDr6%guvLXycpj`*{$r_szfMcx00PosU}IbNMqm+RN&X~%&Tphc56Nh1lg0b zBux5T&DX3)nU*uP@h09p2Hpl3cuP?e>~=8=!Bg1dz2}VgY*!P4#rAoROR-4lvy-z& zj8e+6CbPIdIe5$w=%-o=@;U~w0CTN64~h>SOLEVma@>|PHv|CxTaPY9U z>=NZ=$-SEg$jON{nn%u1czVkLu}Qpyu;ATJn}1PolQAo|`P1qhcgWgOKg1bX*Q_iL zQ#!Wmzia-6?e|K1@Nb86k+}j_FKv_64Hm4w&q6dj&;6P#w^kN*UO7>Y0py{uzFMid z>}oGml2@?J6Z}^~;6s6#F_o_1P7t^Un{X#-g~05;cqLU}j#(hi2V&m8lo?N^dZy{7 zzhjqMY@}uN`%oTqnPOLpyKVY7190Pobb%TPS#^nOg2-FE*B<=3@51xQj2#pnL(}pf zEMhBXaE&(VCwrjk+&7mbqO4#1VA0IF?aaVd&lyujIcSwf)N?+n4SDr9BhhH?cGt40 zw0z7NvPVd#9_l!YMCs4inqW)f9i;S^pAiu+kfL2CyNF9?`_ezN9go)U0fYMCq3|ai z(qti+r-FDc%KHo91f4ph>29@u$7OD-vXTfxK$U&uH1C2!|gAxDb{z7Z<(6AhK-| z^nCTy(h_GLO`{8aZ3SrwZ3SmVLo2S zX(*iwxU`GpXBg6BvSJO~6WyUVbKFi*k)MEPx!f?pUahbG8%p&hT*tJB#ydHb(eIG} zOks0ZzrfLMn=6o%IIuUKL}>d2w>oz#aJ1zOOCS^7C|gc6GBAM^{SG~yI<)`j*9=YMm`mK3K~KxMD)8uQ|wgjr{F6{6RE~PhXxS|z2@i93qghj81Hm%xWxS_wbL>{t zk?yWBD&tdLfRkmRQ$%;HAC#&7Lv4YjveHznWo5tErn|AMDd%hj(m!&}_5+V0C)jg2 zXM0R~0w(-_J!ebpcFs2aLHIR$}8BJlGfz_^xa;_hK-dDd^zwVIXN)5YFTLWCOUg{q*dEsZjkXNK_CzbH`AS8= z@qb-WoxFar2&x{EFl$%qx*GkKlY?+@lp2%&ClCz%0}#Lj!K4*;9!K>awW9m!rSzV8 zYFGj$Vt|1dkiy*#xnK@jw0)<#_4fdT%NRb%LN4Q!+c7QHe?4F~7DCR@@{Np&_T{hg zSN?_W+rr;o0_Umh-^jws*{;e{C8;w1dwJl??%I%-W{vm;>}5Mtcdn>~C9BO9UKs2t zS4%U?WxJ4bKW$PzGMdbEvZWW_?Q)!Q2w`$^CCiRwA1#@H9dRr@{=v|nS?RuVU|={V zOI!b8 z*BVpg__U3_jTWIlzj+CaO<&}oOf8U1&=yhD@5AFSlr&vx!sY+_ogEl?A$!-2Xe?b=c%=I zGpBAh!X;?4M8?AFT84<96v827#K7aHq6$Z^Nj_m8gnH{jL*zs+G(b-7B%G9w?`O8+ zsj1<0p#kzqFn0lEMmDlCFGvyS+*}1@HMrYwi*SFy-G_S`_Zn^&&e|Y21idBjxMh3F zB4%5E-x|GTxyWVM&zQN*ZhNCWLBhM}>C!C{+VyXnGv3Ghw8?uwNtyO0)MDq$79Fzw zERp$38ZkzqM#FahXd0CAur?rgBjrQ43N)XL4?hk}pq##ORSuCYYKf6*C z5k)Q13DHKQL($>GkE`o zr*1-pqe4qYhnDbIM;`ZHnXxT6>t-^0ZF3lqf_mKx^z?&+7Y}OmzRTj#FYtTc?}A^} zR&g!xnk|TM!@|>EU=v6|P`cnF9B{nC7M@MJN){ot`uEN~%yqeS&8qldn_W(c{!Sk0 zU!l1!@MJw?i5$j$El?y+tgw1*>4AE^@sj*C>mbn%ZIs?haUDdlUZ+;Fl<0ov^A@M1pN*|@H7#d z$ni|37!6Bt-Fw*u9P;eDBPBY->4P37p{nV<#kI^quy&n0JU=0GC)%JHxnFckl0DnC z?9&XA)RH7Ib5HJ<-J|co=%GYQ2}zkdd*;5#wd|KxZhPC^+ek~{moI-f|bGk zT{W!t%@+D!ldXzdWMq}0VRm+kKFlbhg(z*Gu1OJ-?b={5(O4mNa;fnb#OdV}!Syln zJw%Cpv{u+!wwM4Z)*s0FLR|&c!><6^DxaSO^=n}S*yM>0X@%2aR-l=kmCO+k$*aD# zl$U%*Q3J~oC^V1M736xD(C82wjM;=uDIII$B!B(0los5bP{u&_Mc;>zQ8^vhmhT&y zfbj}Z`B2FuKs`k%5Ym^2wkP;K!M`7;^w9*7In7}7O^qaUHBV+vd3>KtC_J5DKOroP z7s*;?_Do;>P9_rOd!G^>WMFp8^d2u#CF;o!~^^T17@@bclxu zj7h8ho4QJ_s;}}LAPuoC#17Cda}!%0eUAiY$*Iu1R~xsN)ofRwhoVu5L0DN~I=Gv5Gm>?cPo<+EMc!GKKRq!2ur8T!WpSr}o8yi#4Sis3(s2~m#n3y%hm z*cX<=oYI4hFFI_2oO;Dv4ylc z>dnN&wI@A}3Wa%?1Mdy8bQ^eQby1A@vEiU%t$nNDX45(HNk zm-Ja&GH%eG+nq(87f-yxkM;JcG2%5Fcy5gR;;7db3yh=QbGlLQ*?=RACzdjfdTG1K z1mf6hdMq#=y|KVJ_BtXKcmftV2b(T3znzFhe&7@qX*TTqxQ_ZR4w=!_QAKfRHaqHq z6R?X5PtGnf<1wySWc8F7#=nDITo7w=9KwMtj$NF8Vix&n|F|}1ono6ucD1>&cbhLd zL7Oi=d7HC)wfTnHQ)%->Cu%d0#kD!>JBaK%sU+|8ZY(nSge>y8E*5!7aJT)GSfpK8 z)ayh{S%s!9SgbD9Z8brXm$GbqUtH%Tg^R@)aH@+wjR-nj94c`Q)IS^dM) z5&z8LbA=_7I}oD#)Ncgi9p?d{N|?76d9ZteR!NXt{{}zQp;KjaNVDvpH2Z{=sIpNm zG~|4v%)OFj5~)=JDYLwLf_+w{DnaA#dR6*yw@O9cH7b?E*z@oqMi*(@^}8K1MbNM& zAQ>(AK{qgs#%!ct(E1Ywy^l{d4Om=yOxH*=rhzrSY(r+0Y2Zp@8mO>Xd9!bJS7fds zF`I(&L4cGRR4dhlyFrn zaE*aA>6me`z(rkwV`G8Sy8?4#ff-$aSH=SO(v@as(~0JMCS7e&fEifqD~eo3#Uih- zqM#TH&iBnWg#*!2>?Ryc?4k;XzpGy!>XJ}!IVniKc&wY~ayPPyu1bE<<+7M%!pU4d~}o)k+N*B^zk zz_^|(hy}*=alR2~_Rhq}YH*v;?dwjZQ{by6mB)3;b+N#>PAQEA#&t?bEHJK9ij6?CQzpZ|WT=`c zyH<@%6K2)YJTo=ZiWw-#G6OG*1;&Y%OkHNmI3bh?&kU5w#>{Rlw9^O2t-3&g2oT(2iQ6!%?Ij;bf1Fr8 zm=co@;yQ9_EKoRlH=*JB?(=s{Xiy3NtI&{6aWSDm=;1qs29@Buga(!1{~$CVsR+HD zsM0Fv3F*gJH`Sk@(&>`m1kz7T5LxeQqK}b9K990@YRMwgVpC3Y{KlP-L$_IHdKZH; zWRYUuTsl{#oEh=lP3^piBwy?lf2NMx-DTShGo;!JP~tv0OIpWU8{Zl4cnh zi^hl`(yZhkE8`7TMxh>+Q6?!X!j^f=E%%HCfyQe`Ab+#PP%L#RB8_;SI6CIDR-Q78u75>tca%BFjuOu!|qgh$V|# zl+%4CLyKD@PKyOLft|=zpiu-7^?;FViD+s&S1L1Qkw!kdQN^4ts%TV*UKKBdem|Zt z=-1f16(_~kcboQ%ZeHb+j?DaTZpy#vLU{ki+yEQu3M~J=9~wqlIw-J zC!Y3h?bXd67ImBUke$gM!*vnV-2^zd#4s4w_YJYYxW2zR78uv}^|8RXzW=@vXx1<% z@?(&$WRYk2h#Rfn)i1Yo^~*!O`{f6x&@c1;YrouXVfcjoa>q&fWxkcGd%yTk+%JJ% z{W4+Fsr1YI7-Hl4<&IcjT)*5N3ykZRd9lE_e))kBX!gr(uwogTv6OLRk~yfi@WGsA z2F8gg%x-3&Aki!ulLKa;Oa^8kGpHFDC#Ep(nt^dE8%s>NQ|vhyhgd0hjBQ9!hgdQQ zdPpkkArLANNo7HBH%~*K!e*~qj;lTg1u`mn2`gU_Si?4a7WmO0{~cg({B%&`gx+k- zLJsXL_9A^@vX@u+?8aUeb&+waB4Y+PMaZOcXODfRHOBb9E5^oqoj}~JXz5icr(6-I zekk8yh(+FvZ&X-0P>-jUOgcrw~|1Y)#*Z*X^BS9kF8qVRX)a5m4?oFxVReRHo) zhzuseIMhWtsUl0glQPx5i$ji*ha+N;YqiLd9%2;fshEv)oScD#7LI1;FOVN&?fJeU zb3im(1LB2Xj6WLZrw81S-osSatn_w9)u&N*$7C!5xRy1M>pKfucCx~jn}v;*Ca@DG z=X*fY5reE*?R}}1@_J*pao^HKid6y%2voCo zsNC8uGC<=*cdvZ_*{6J0BII6{jY7RmNnXgD>B4J~v=h8y6hM)q3bn5o>6 zPN21r)x_>;xBXW$l_&D1q%sFdGpV|5!kVePkzYwF6Rj;hcVf*{X_0&5YFu@a8q*_! zV5`Q}C#lgFxje2$KRwfJ!?_9)-@+JXA2VC;V6v5iKEiY>?3aXTmNE@Gc3LMiS`^cH z(LYo1uQ*V4olY-AWMa2qT10K#upqU~lLS)R;;!2EShbD$FSUs{pcPYFg8uL0)OLMb zZH*_YE!(Qi)m7VHtlD<>{qDB)w`xn&o20e_lF{tprW4inoK^DUlx$-1pcOXbztr}K zil=Q!`XH%oNnCBsC#o&aYFkcMZE~?tVfS;#cem|gt2Vp7_FHOm$JN$yqS~6Ql6O$D z**3Qow)DT$wpGQ`wq*TssqG24s)fl_J!>n2O3JK~YrASox55Vhm)a`L+RF87{wM|{ zt?^cNV-M;d!II>T{=&<&#*L1`4!OR;=S!G5hQ_ks-xt zA9N&76hYQdnG9E^u0OhNYDp(^oy+9jC8q1CH(*szR!! zhUynI&#NtVqO@M-)ZU7|BhpGCbDLJ0r`3!lxJke%*Gfn8zKWZdG_l+XO0%MSxKxzF zmxmXDkmJjF7$VV54=4)-?Q?nj&4U`TPd|Uamr-RfD%j>w_Xa0v%9==Q${K`KK-axF z&}J~&-?idGKD6DzW6t>_!Zmg+k-l*n_D6VQ48X^WS)`-RJ3gH#dc4O5+_4T~@CLWb z^Rrn>=NGFquIA6A7^M&>Eg<};f%SeYzP zoVrne;3#6xfi&n)Ha?PxRB1XxYkjLotS^YgKSX>A@pO)j%xisXB)%pVzn=I$!~>cU zuVkakWAS^4cM#8y5ibDir^VuhefHG`=WJ1hcS_{ZBZuVmnnhl%%%{yu*NW0YuljV! zzsSSaH|on>!9Wx;AjHX!w#bP|k{Yy^m9M~wekVjF1qD<^W zfF?$oC-cBGPslBMw@b#PYo+mAKx%q$^`+@o~`H_8;l4sLA%xO z;JNk8om-D4qD8E|m$_%_*NM4r&rgLRc|s{rc4(oyb zWFEB(LR9-+aq%VU_X2JgW$snb+PGIxCT$UD-CdNjX_Nsm2U6tjUN^u*77!}0zne$= zGM0ND@xLz0L9Xxo|Y0PS&n+|FPZmoogjfby!fn5(3=*%N_#$7+{47n>2 zeHUYR>WfRZnTOd|a{^O)fiO(08@LU7YLpO2BfFV5Ir^?D*OU9Ee*sAPf@^7GqwnTy z$(`q1m>7MxlxvyU(RXtfy6?c}+K@uoSTbWBS>B`m|`GHZouuZX9wlx~`?LUNCVZ zZ}#QG%6L~?+RDYB@DdDL`9>#bZ?&fs-!0dDl!8uSRvE!#6ZMYErCKsJSuukIyXc8SG0^5qRxZ+$BXSfnXdWlk^|rkXeT zX2C`*ZvS<*mDM9Cuy{$8FCQ@{cJB)NV?Mye(nN;(A!XbYAorWHW1SLg9ktE6h$Z)% zipUYW-*f>|xk#AC^|Ck0%k-a4QC(>EI`nTlxn>mW2yY+#VHIF?l{ZDtRRLCKdXx2^y(OKwisGcJ zymtNOe4!0R4c;Vun(`@1@h0l8O^~=Ol`=v9t@y-*8V~0goZYx~2lkv6_T+Myg^V7& zNxU)n_NFUiRKE1UJjAW8`&hD(65|P6t}}M!x3{3Swn zY*F{IiXgsnL~=Q{);l*7wnkmnvCb6}^iK$6QjlHfL~Wuwb0Sx=`nv8-yb%83_l?ax z7`s$8k!xAmT+8~y1w>7DhnL8;tVUm2?$K^ZMwhsjt&=2`B#~=bU-ydEtPfq8oin~s)Tne(2 z^tPi1qv*>OTgcV_lg3GPvrjliX0svOPIgPVRipb$!84@bs?q)AmEf{6O5V%+3uej1 z^rKm_U7y>tu zQJ%StdtENMcvV%7cqQkW+A&r@qxG+%Twr=wDNX3L{j8f;2S}h7#k^_a9n;-=Azp-) zB9^)P0HdOu;>27X7;ESst0`Y{-fz^gM!vu5Yt=W}mL^amhL+{Hif*meTd$U=Kmu%lhj07hPAoc*)LXl%Bsts%G;`N%6|eL8 zv{vc#i9^xi=g-V%IA4&T^nIhGr}T!`)yXSZ1W|YldTmK+Qs&-ht?bs)d0Gip+gR_p z=L%>rMQuPRO|VaExF)eC@{(;$&NmPLxp=q;q_3r1Il5}FP}_%>Mr*jKyfJ`y*Cveb z4Zg&es71DM=Kd@C2N|@tSJG^AKRuZy+EZa(=Y^H7WiY|EpE7PW=0~Sj;;(joDSF!% zPj!0_cfI3NTj#yIGySE(jo+qDb4z@ozGT3Bv$PmUSlBZhkQchTFY~^TIqeI!3nPSg z*3yBKNU}AesOCv?%>x9~;J=lgx<(WpDaJS~l97Qt%lm0bD}0v{TUahI8$b+23A5me z5h;)8s(Z81c8VqtEmYgvyBwE)-Uscl-A^5hjQO#KZFcfw4T(dnYIb~}$I4dWIPJ~8 z3t^D&5(s8`zbvxn%k-B7KmVo6UBqCD!=glh#tSGB%#W=SiV~Zn(`nfzM#u?Tgcw%S z6V2Ob&!K|^ufxz`(y(+GyvnA7@W%#djkz|fSzD`+rme{l7sWu=8lBDW{z^H0*#^=| z@SgD$%gh#@4=XcrW`hVGGP9C8xpimEb@H~k`_F`EbBu*mxraHKNAgN#NPSs$vr58< zw(o`B4cV<~5s~?on|b?bH5G64o7+Faj2JnfSD~Lv4!3zMIb_Lk0qNOCW)ExkTBMf{ zhwg8IO9eaJj6NdFvc}vkgf;r{6!SR(X)&6eywhaUpN)w-iUs;YHPm&48EV;TJk@N$ zoI8wk3p9YX42we6$rXnwfiDBtN!h@;!jz^T>o8s70MyLT*qp}buJ%ym2s&$4nVY{aqwkp_Wu@Y zYff(lQo{VVEh<=0vLL>}OiKd<=rF<*g404DpSp$So%0CJ03lktna>I{E?_M1she;j z<*mC9QbAUDsWHdNYiQ9&i5N`6^RR07jBYpU?H=bxtXe=)Y46+pE^v>C+!^X3Gs6&| zt$XBu`YEU}gRmVbkQl5+Fg1Py&QFTev|dXk&SKCqGWjM3R$|I4I22g=@x_T$nLJ6wEMLv@Nug^Di2}jJ08c*?-V1 zn6+rk9=uVcH+7AToq3?DkXGg?!RjS$=OYaHptt)cENgLSX}+MIKCPb`eKwR+KQUW? zldbOlXQ~TFob2;f6Jl==AP&V|L?anA zYDw5|t=k|9DD#__4x?q)3^9mRjzYP#3`|{GW+8I5Q|Jmyt-Y;Qm5T29Oi+TQsG9OB zTDg=`NuNZ-=JU*~q)!PmohwqXu+`PkDcE)9@!z^M!cwqap^&X$R}=}&H{=EL!`!p> z<4X{mZdtUGSFk^IfeW^^07xsDPejrXz^!}ae|l&s*;by2lFf0H>~Rt0r)U;Y-l9eM zpQaTm*?pp9*-DqVqWTvp%>EXN9QA_Pk1y%IKyY)^?DWZeSA%UV+O*V6;r1mLZjPEg zLF=MsiySo*r8h$wH^CDpF$vsIv+HaHF;9>tbJPgDTBTicyx>)-@k+x$r-u1)^}J`Z z$Mf1TdCu&z1MBaA^U`1d_vuvfEqb-0_vH?9G)Lt zW!vkUN91tK{HGHZRYY@Dgg!KEsTsoI=EyJ{w)dIlIh@~Q>f$h%4(0F+r_jY=Yqy-m z;Ts{g5YeeA+_RotWpi+FCK`vwgzc{Ql}-+cGSSFX9(H+y z?Ke}W*#t^%-JqE&2GPC{?3(*{Y%Uq{>?V2EFVAX*JiA1mc^>3h`H*LF@?*1Kp81A6 z`*$&XqZ_ZWlhl^5I)F(A%MlN@o?0_aq9+zbZ#B36>fDl1=avi`iaGDXVWi_$i$!_q z$ZvUdNk@Lms~WexH39nydGsi{1e6ly?Vnf5rYL5|qvht$e_6=U)I}->lG(G;{FY1# zAO#%L-~A5&RPNyHs%36;y|w{sHlD zZR+S0cYY^q!P-lYY=cmnPw{}iqOHaDS>|89xwnOz_{icuDzTg*jn zK!uitIufYO86m$jE<2-YbLsx4 zagfJh((X6Kd;~TsLeHqg*c*MrO);=yPnJ&x+hy%C^irn-$|}KG06^)N15xJER`Lnm zBj#6+pBPjZ5SjlxapY;MPkusG59b~};~LY{o0UK%Fez&!!u)Hr7*iEam>)7v40iug zMwcylvGGU`3dH6=WKYL%Zp)tOV7g?F)cKN#jTRV@6~hvnt z^wL~*l_G&WMPv@~>phALd+2SmwyQ{F?ih{8(B0xRN`n%a4uNK+QH}(M5gFbr5}7+3 z>2Qfmev`lQI1l^X9_LTsg3TK*I*s3)-(Vat_aA1m9b<0UgGTcgem%ieBSUFsDUq%v z!^jqa1H7Ma-UM6;MDs}*3(~?N%(S7|b6~kt>6zgm*A2!_1lwf3woWE8B|0(>J*3T$ z?4a&INf!-)ZbM~)qw|cs7Zy2qT)!vr0KG4_-cGvm13Rf^K{4mor>Sb+QMtIY*q*-AcF)$jcf<^Wh7I5iWa^az32N?@)FLSAKh? z%N^b6h@s0JEpZB6?kK;#vKJy-z0Gg06ed`O`R$dVeBmMorVP=$H_$z9qJSov!|pIP@e{BgDgD3jqRY!TzQ$Y zKu_`=3$)-0ZGoPUxW#JfP0X+HVI^`bzmoNk)rsaXXsgXk0XfpPnzzC8NholS`KfsK4$R2*R8f$yBg(jMJe%4wAdXR@7cfuV&$|xR?oqT-K{Id?{$0xeW z1XWZ=1)#*MoaAP&3$v%oi*UNv{D6(q<~&Xkt_e<`vh+!$l=a$qyd;|@c(JwJir@?J zYBmSI;NbPYxh2#9>vT$@K^WoGXTOMD#p zbP25`N5*hYO~zuk6M z+Dy?n^Vm<3Y#G1)MtW0@oLceYsh<@E0_}&TMg=v@*YnTp(Vwtq*EN5qNJT!e!%>@W6IO(wHm5BL%Xp~b;FvXv{lah z*m=Wr<$>Y40s_)Mt1D?}D^lUqblG@ofH8OrH(E2G;0+Oo^UWXpSVf?+ET{W%-Yr@< zWSMaQ&!>iEz?VP@3&4Z2aH!NBL8h#QL#{PLrFzZK?|>rGtA25T#<$KA(ZV3FQR&#h>}kw}|s59gV>TrpMe`JfSz z$n{0hgji)22?z_nu_3S9#X;mFZeFT!$Ct*q`G`>vwRD){lF0Q=p-ZVj(~?~m8?Ak~ z##X(0Pj57XA~ltI1s^-idZ7k=k+x)qS&-FxHBd^TA_t=7YNU?6!|VyQ^seVB2wBGN zvKqCwtPHuX>6vV>1w+8}oNutkb1s{wYFPV8%^F$%x%+(CUv`Eqb4FYA7=)kpw%#gs zeN?aeZBuJVWyjZXp7LSp59yZ~pc3yb;kz0n$sV)*EA)$-qjeO^f>e3T$5Q>FN265Y zMd_~d;&-hVx2olNvN=s2^UqJ<>;FjgfZx;E z!f=Sk@@FiJ%CYVT`D)(f)R6sHQlmr+v9-nGDXLhqZt~UfQAeoJ_0+uO(ucZb~#Bx#11G5NRP}3;IVwnZ}7!@@0#&q?@Q}TxOh#fp`4G~_S zhlbQNuM<41Vb=YnwuWryxrG65T7qAeFC60(&d3+~oI<8g?bq2wWxakpUua1=dLY!Y z8Y*#W9>^EwmBd3s7DHU?-lrO~Wyjzl8MTh}!>3#37=GiHD)b{FUcg`p=p5trDs*U( zz4^krs6w8y&~GL+gKcNVsN;Cs$MLD3v%!sJ{INtN4F%NA7Abc4?F*0vYD%DUGV4%b zE|{#Xq=c_}s$p8Eg(cW{ILtmwUU6ma;gup#{Hro<6~yL%U~RDdD?V3qAQG!{nrq5w ztI}xxXbK`KN923x!PpoJFjF>40HO~SGiUiyE3i9ZHXXL#>4sU@g(l;t=H{@+!(F+l z8}TioHF90abooq8QbGk&bZ4S6I*_z=K?&hX)W~e7zF}27S!yIX{;W`6Ok%SMfNUUykDD;gvDld|4D->OEI z$13sb60OjSP-C>FF%fK^L?;~kz_mmWquiy%YDA1AFK#ri2qH4p{-HU^}eqP_M zHVa#A<6XD%A`7H99^?~LrUTGFc!(WhOAw!`p5=z8`_wyX6c#p0yVb>ip6(~*{y$Im zm2zXHr+c;j_@R8r-C3pGe9Sfx zY)T{7ye?hC!m!P1Nzf2?f$E0M&&;LMACdtz%&CTA;qD`HZ|1kfU3*eZnci}Qw$|9I zR~ao#nCJiY6gyf&>_gvjgencPMI9oIg-B&Z8_&ytIU}QXo|lR@fAjr3_MkUAB!1R5a&4W; z%%zseIFl{b%F2Bk*WyXYCMH_8ES)+XNG!n=CB8Myhg<=N=N)YeP&49jiKHC8OLfcg zssiX2o(1|;3%cx+?b&8ynQM!#1gK?=H}h5F85s_eT3{rYUZesewe!^qjFz0XZB_@* z3sK#yniwK#Xx9Pi7DlrYmlDl>KBA*pb#oj0>BdfTMY0n73wT2yNpvsro_DAzdxAE)rTj2IIh%S1d##>^(dam&D#P2TIG#^7KV3 z%4xP!HQOiVQ!X#+{wQ4(cvqeqUa5jt)-q#huw7nTv2+-Czq0VVE)VZJA;zx!L;fXv}7k!#0*ET^Uv)b6bvAP&>pFSMOQ2rTl1 zP@L)0UgyH?4~XM8`eOT2ljU#$8S`fLmBmh_Pe_%7`He|Bi6X*-xt_tl8vfOqf6fD- zi8Oh-v;3FSXI>bdax{A>!mI6=Sn6rr`wBmH+k4Mtzcl{MoZ$Gk zOmB68J7WNA`Lfg8H@%44!B>`{Lw)UUIm7O|IkiBB%#rrjIXvNYdyE)kIG!peCR-4Q z9e7~s>br9bLJdU8#K(1*RFx7>)fo~sE=HhbxL$6L(D`1|v`|WAK}R`1mo(D!{pZtk z#8~CyNjb_tKc8r5e?5J*4$fn1obZ}`9M%_5Qj~1dGG`vNM0~PQN)l@S%p#SyXWrgEMIn_(Z!Xb5xMgee(ZGfV@44_=DYZ@ z6rz-I0pWY&M@aGG96w(BB`ay&{D2ow|6U}?V_w4=4L45~os%ck^n89H zPv*FIQpArBGkf=5`5_%t{0RSH`0*t-Kb99>FuTfO#~$-AQ>C!tbw_S0jax)+!d(9B zi@oK@4Wk^lW~>=bGnOIaY@d@DFtHeksgZcGO-Rn4c@?RdrlgFm%Gf23dFr6F#OxGi zREUBsV)RSov7Ysgd$3Hvf@AAkym>3lqD=`NW9cG&S>@tQX79>9#%Db}KhnA)|0AD= z^Y;a3dgm0$=Msw`OQS2%s%AN0WtOjH-8CNLbb6{We#^|dz?w0fEY;)Va1@U`Nc9?N z$A-KOrQUWZwH_OCo-salM_|pzrL&qKbY;1a!I&%*sFnP?wj7I_pj53CmNyvB(f?H? z=KKH^tBrMHG-@bXo)1CF1dxj+Z#y>RkvvUq6-`~@q6vzcKv9hwwGDwD6<0a-(|z2A z-=YMDkcK2e<$R3`z-Da1oDkS z$bILh!DpOazu>}0@pFpsa~gtgTqEM8#9uQtF!)2jM0I(L%qy%NC#=1~n4~xt5za*s zXfP{>RZ)+5tyzr0_TKogW1 zGTS;&48qh8T2{!daTRFXN?R=yqnkCOUxUf-jlbU^sVDq>#Xk~%^Zq7@`+xCD>W|v} zbE05i;qU41jq{ulxphIek0bNu`hr`#Hg$2%&4|zcR6mCvU(Va(5$sQHuA+Qcv2EOU zNgTZ>CMj?Gpm?z%vJ{Hsq_#rFk<7zoL_3kD#pz2_(7d7~X}oJbjAb*PgH0I5GLGZo z(G25yW4z8ysLpj^&?QkY1O2aw{agBaiGnk`0}x#95thjzN&bLDO_K)tfnuO*BF1E}3uH;Eztx>Q>D^I`urc0jI$&>*|<>e`4Mm1`Ad74=$PkV<7 zwk=OzEq>&dr}ZLiXOX9K%7-!OKPw+%Z|YHPp<#5wln z1?FN#l#kyz@*y_juXR-|AGf*XqrDisB_E$HE_dwBLIrEI@)6(Zl8+_KzZA+x!1QU< z^73(8p?n-4DyX)6JYW3CEgw&a@SH_HM&y{3ebdA8Ok|9jL||NgloI6y&8>>JJ{o>M;GWukl3_DkjwUrc{Md8-hII|egJ zP*-;OUGwY3kPynr$_egHjl-derN^lP;97~d>-C62xx5&RC3EKwEmw#EB$#OxVonzD zI5$^o+O0i8i;i16@it;cMa+;K7e3t(imbVXuQf)(-|`S+$ahnhP-8lWgeKVru%%dQ zm9xX^K2ZEXoE`Be=Vh!H;q%{_rBBX@gzrHCNNfE@T|k18*tlRua_YtlKvGh=u^5t;(nMhGd?hz>+J%HJ9&1IoFXE5u@Xt? zh54OgRS=03x|`dJpQw3pC6Zqiu^LGv&nAznM9f7VfBWtqLLLu)Z3KC2W>lo?<*eUZ z9-(;g_mp8EZ!UyP&AjqDb2UQK;kgq~ORXhKAnY>Ro>Rlw7uiN)@gQrg4Ma(nns z7B^#A+uMuFX#`pn z(BKB@8e7aN^z}Q3YMbrr|FZZIoNH1EI&-5)?^!&(9)O-r{+EkRDf#a|oBS_1(BQfE zZy<;#G2HkVLI_U`f2Pxyosh^aVD?d#@IZs|#@qs#X`mA_%c4q$1_o-KfHho}{KQvZ zcG?^E{9T4|u%QV3woju_R-Aw2J7WzVECE1cN|kEVdbT2KA@iO0Q<*U~O@<7H)stg~m>;@4ce}44*Ayy{I6qyDE==@% zN$TE{P2;fZ1v&xg&xGvf{PJs+Kkdyn`;B^E z%Y)UPT-;~;mLqY6j6`w1*tm4P(MZTs?MYwMac6bMUDc3xo^Ri*YN7LLU-x#Z#_sp0 z{fjw2y7{Zf%UoZ_l4?0izQMO|Hr3|(Sg*0ze1c~^4;qsctP6*O)$_5~^%~Bq5#SIY z6I@QrCit)Aq3b=MKATk_zHEbZHa6Rr9+REtW2sfb7b{Ksvg3NZ*?InKNtU%D3v>rb zXtl|Bn)=3Ug((Lt8bQdFmHS|p+UY)(Mp~jpUFR2SBMWUIH;$w~lr*jpD=UH%BUxzXfwO;6XQlD+CMb*+`a5$PJA}3{>ad~Kz~Ao`om1wS@dV-f3N<` zD|hQps8D~x|AqSVsr&BZddPF?&&9c6_2;IWiuC8#Kl}sf&y11vXNJZ^P-?RSE!D9W9u>3vh4+$K% z{)7tk2f-Oee-Q1_=#Qi(3iRha`JdbVd-dnfWt#SX!vEYdXAU=ho>PB*lpR)oPI3DY z9yx{gSi!P$9MH#K9;!egaX@Tgs9+v3`)PmA`$yq}lD?LQ>PFU~I;BH(9e34PI#f5D z4n?3ZhQiA0P}K-<3U%nV_pC#7uvmxcMx#RnT9*GI!R6MU zQTZQ4d#L_M;KnG(csOF*s;0)jUeZDMmA(Q;7*#`Tqd)k?E-7ncAk76JUdGL8s{G#x z?p`H)S2MjlT&xD}Dkqd*mvV-oHgOXJVLL{9*Zh=>WJZk8R9yB6f=>i2%)6LKxuP-} zyME2J5}K-YI1%FqjUmC(&C*Fc#uR~PnM7!+*bdU{;FwQRDhuU^ z4VgynM^c$7JWs70IzqZY&w#Pxb|xEm()ZGGh4Day3OXZESfMI?i%ga`__&6{OvE*=KxIU}k6BvkaZHA-B& z#TZPNd73{&G+Jd_f}cq=I#?KwRw-Lh)p1vqWeci?vjqpn^QOe3Rkkgln(a?{rfmVR zumwY5$FjLM%9KNjil6wfI2m!$#4`r9E#wHSasO`tCtWhpO*2N_`j0Iyz3cdDp!3_tW10GX4Fn7@z+l{hjI7-(9js>g@WP zjk?xX)D?~=?d44?qpKKEqQRG))uZc0a{i6OYVeg+T7y$;NK0~_y=ZVBM6kz`jKx>Q zOvaR})R^)H9`%&t&sTa<6S6GiU>I4!pt71lWm*j?n`KbB%CE*;7&m0R{ojWSDZ@&I z!yR{pEfr=5oyNb6tOWvn80cGQiSZ`9u5&4-bf<2zmX#*^2R zZ#?elr`uTGDeLAwBm9X~xLRtJCFD9WXEUgpKnAVdDqsamE3o zL?QoncAPS(OCmEr<4-@N>Yiup%iiMe`7A44%9*&5?;mFkJNRY&vA93&Gx~ZiQb?@Q zNMt|4HH835`Xy^97~K|``DwvumgEfUeKS7@QY9cY%Wouo*@Q1wUzO>sk_%8bU9>6G z5$TxtjglF6SLthH6+(59*n?yg&%?aUxQ7R4#LZ2JoldV+OS2@j#2hvgUN#yp?wecX zF=Y?EdUlN`*xoADOJ*#o!f!VCXWUhl`W%zp^7}&e+u}k9a1;Ax@mjrpZBtWKM?+P| zvMQ=c7aEKgiEd3%w{A(Yw>(IbQ`DPxR*~3OO-__|CkWTllXWxc_v=`wZMBuM9W|c8d-QKy@SC^et#;YsAF=d<&C*a6#syHrEkBSn-K2q=qWgGZUCg71O zu1IYVCIO6FYa_9FzVvtj=ZBrLOjBjA$7M_Hg6wR+{Z+I`?w$3s;XzO64-YRO@akLu z=lRo=`JFPL+mH29kFiK1qu{aop#;;nbv{OnWA{UU`Qgw1*jHOs!mTlZ#Hda)5rJ42TIu0^Ff2-OSoJ&8Okp3 zWyfZl{ML?&1)=O*HZ;j}4^q^z>>B2GhFsIhO~CcN4dzup(X&~vFI;GryuZ|Ce4yWG z?T@UzS2l=I$GL6LeGd$4gEE)nvyO-rVnS}W&nK0MAuOImSj^hWeRIPe^L%YXgl_58 zqTXT5j+mQp>KaJmweHa8qP1#@F|9F)QUCs1l#4kmPc6)U@Q8{=sL9H?8>g7S<238D54IZ? z_|$k6b1-a=^sGneBgFJ5z52a!sNw^3SjFeUZ3#U_QvQWL@_y?i{J6a~(^(7iLOT4A zb~+~Zlp04`9WdnYrP?XYczNrvog|Y#}%9HoasueZbH@DVfw%JC2;P+vf zMy)MLpN}%MtmBr*`!EBlWU_%c@e*%(%)hY>L2XAvEkH`NC6Ef{hj`ZWV9SFvGs)e| zXXPDi0j*52fnFxj9L-@3Y74EwY_SH@ENmtNKHvB&symySoVHa@q-j}NxbN255;i{| zGiA9ovX5#Ng&qdKvTtV<$Abj8@VY-$VSFwW`&}x?(G+^i?f$aZ@7Qw7c-oxB&3h1h zy|s=mke!Q*3>!B#nOE_IQsa997Yqlj{jIX#z#J#96`COSxf%NQG4`ruD`eIgYh}+U z>$qmQ9oM++j~a*k0qxI7@ZP)q`MiI$@k}iOGs|UvbUgF3>s=|V@CfmYHdU9<)Ckec z6;3o`YzSw^N*YAMnkK*b4CgF&EUWEUHfy*zhD{(6$K3P7d>k|LA}fx`e1svGT4u;j zu2&gjs(}VG6Mk+PSKpTnzIx9dgAEpho0lsMkpS90FPE{2C=G*_-+~JjYt>unGV2Ts z#;-AddIG?VL##AVHG3#j;Qo%{d-AcL#G}LG<5M`)X(TSuqoMQ!l@H2~joi&&DDBo2 zH~i+P+GG8V(|^7@{b!+t?mu6O`%gVr|EVxy|Ea0_Po>fIpGjW_AHF;IFmbK%;Y%?- z)N|oOg%R7U|5S1HpJ&7LpE{%KKa;3V|M~9ppGjcdf4&s=pL(wTQ(?sZQ&ab!O2hOY+sP8Q zkV=3U-?CZ#y~D)I9)CxZ+9 z@^xQ#34-~G59%2s^y`je_)@Lqu)@IHv%iWHa{pd8j@Uzc#OOK=J&tI z!0e^QM)OII=Myw^``hyE%Z6ZELyGc0CkQ-^`mk|#xv?RVjUUa{A5}{)WPht#x={I3 zB42$wM347nx!mDLT|Jk1f7CumwsS)-36llk${!4KeMC0i+s?J{FG%#hAT(^1Z{GIB z==qfgV&7Xc#(egnK2E&r_3mMjZ{`+x>G0tous_}_%%)1u81D<&`rg=q zHDhSQIMDw51Hly@^TLCQ!`Zmm<2S$g?GuB1+aDiLFD(e{iy!kC$zzR1vYdaRM&nR6 ze%xIB6ZQ=!%Q>b%J+D93KxUya!6PHi#+uC06C4~F%0DY70Gk`4QYev49yh1)I!!1w zeEbK&O%&&oqa+{^{G2&oHlD8nv&rm&*w~sC9?0<*6A;#TxlvzkcRc~>%=y(v%&)x; z26IDngWj1RrY&&K)#ygw^$vOmbH1R-4hbeqq?VWQDL+cUe~1j0c@C;&FDE$o=Td!s zLgrVTLX-+AgL91RpgxtT`yRDf7WqW|S$!L7{n_BJ1_xW8_mnftszWdBzXmRl-|vgk zqG!XnCiAl~u}^pI@pg%|2+CF&e%Y1z6#JJS95gI+`+|^_TUf7-*HH#U_fcAl2f9qZ6f+Y$)qG8gHu&Wjp>p$R z3e~_X#rDbB*he|!4<=(s%NhYy#lLF)O*i*g4+QTS4&Iz;?b^zvsP>=5|M<+|@vjnO zlYy=`HU5jh|026fA*V}Y?V^ZN^qWUqy?mR5PQI6Klj)XT%AW0lUjEp6aF$-endZDa zjC`I8QwP%qnc-ee5~u~XGZ($yI8gawW_M}qg*9jc^2sfRr*y6#(RFY*%jtg`R^P5 zLL&I=2{Qv2o>d`s0(%Dk$6BEmC`Op}Ams)pgkV!Ezzp9*b;$c4*%iT(OL z<&~X@w!HqIy_!lR%j;k08vi5mDso>St3D{q)Wds`Ra;6g(b{tkNzI>I9!V@jQjvxR z^PztnK~gU#Ip>npH~xs99D^KeWO1nBX;AA>5)I}%>}GXI>iAWbq{^{;Nb1Zzwu!El zllKz*Tg1O5X1RWVq`q#8rA{1adG#W%vIp7`;oK^3=AF_ZrOl;Uww=1j_PUa^ZDx?~ z;4?P{pQ-l*pPAbA3;*~NoW3cazvjQh_!H)rcO%d&twEX#PX=s}2YE?XomoklSYjnm zPiO=9gf@U&Xdwo0o>fC)_~8T{`M%U`k5}4<%`yX4Fm%%`TORuawi%0oe3Wrcm^37= z8SJ+4QQ4->s7!OXwwx!{{UFb@5sU4AK#bF7^*s2@#74}{z2o>ONm)vaeh_-&0${CY7-r-%rY39=k zsC`m2M*RHPQwpjbOUKRx+rC20_P2uVIX-OxrWwwiRlXqj%z1L$d!2ce##kmjs+#L& zF4R|T@{(8Gy({JS(w)teFu1Icr5_BhtPWadXp*Pbl(Wte#pPT+Oq;iM-z>w>xTkxK z{_J@JClkS_FK4NNwV{tgED4XwptGDEso0^%v>08@3~d-c+^NNd%T%Z;E^`~7d~DYr zPx4_#sATLDsoETEp&%cvaJ(alZq9amg-a+id)G;vhy46=wJXwkFY;3+_GM)G;lwzR zpMoAdtXlR_rh3q=?$J~Za(LPLFvmNLTDF#sTDE%pR(fU2dy+4;Jnlo{&f)f|!G9CC zA6i{H_-`#A4Xs&0*~eXFmb6992lLWa+q{(XUDaJVaOP~%Cif7CAUM+2vr+<Y3F$J?#ViAI%dtBanfJZ6Y&qZXEIms_n_r|XVdw!g!QR*~%oT(Vt; zt}JK4OMz@hhRU`j7j^{l@&BV`d#jR+#^GhVhDzs7V4QJ_eR)qxAt`phN`@~r{Hx{P9P?w=1447R-e&fOtwEU{U&yH<9P=kzA{4q| zH@b3=eYtU~bR#tL)_gbaVGD{JtP#5>f$RpYNtOr-9ko5jAwHw&;Btde1;A zJ;no}nGfWVye=nOoe`lqq@HBsCbM&5Ei1shtWlS%qs;lK;|4G&TgVd0BuiM$-(CEU z++(UB2)~!saWqfZc;c7 zgC993_EQc)FS1Z5%Qf^(vi0OHL2*MsV>lTMCwt7fU|39P9mU%C_=W6yh3pLp^VL2G zU+-sAidn{?LXh6!(XjRZmoQ4#?@WmKHu+&0 zlj&jLvOsKE9^Q?{8K8kx`eFxCGT{ADY>5QR`IzKQ6n0r22uL7pAtTK(FAEnpnSb&X z)Ow%AIBv%H0J5c{7`xd;yn!0>MkA)6$-KMZjkLeX?D^o^gZCKwY&AoF4qxZ^zDvlISnxXH>slI67V>f!(We zQ`5b{ZxyG+vy{aoZUbF`vD!Z%}Lm5f$Nx zPkar3gHvk7fb^lQ92Kh1x*nWTBV}ycy)ZvO7Pq;btDx;lI75NK4OUB~vIKf6KGt?) zMac>;)`Z(yPZHhaxa)_u#9}QGzb;4J6A>Pi)ZAV_NR>A>A6pcc0FpNj3A_V?QwDgv ziCra>%B92>^lF}hr@*5dQkb_^oA&gS-q2}mRtL+w%@#$+c!8+y%)gd!Vs{@uTnRkn z=?iXolJ!|d610ONM}m&>!#F+dZB(jUc&j#-EanoBT|6*9a@E^|3sv{4V1CpgK_?G| z1l2+U`H?3<`&(;o62HRadfQT8Rr+eGaYqI5v_%HIq)J*zYU?8_PYljgO~!t^`gtlv zJD!N{1m55ji#P(DHl&O~IhUPW;^wI8LzZ>V9?zY!f}?e>#KO>l{y+MhvskmWSM}eS z&*Bncs_D+NK=TQ8ftm3l9S_kz7GO#MyP|{#(tzr?tX`4ZN@-pAPZaYsKcw^JFiooI zhsT7OIMpV0T^zEcfuHo}DfP1Shx7$k+wjw7XdZ8E{r?B?H~$~U|M>so_&@On!~eVa z#mcR{+mN<}$$S=Hi>ylnM6;9zM9_e+)&K@=9NlXf0ZaXH>W&78?^YTh>AFsS3{E)! z`WV3GmZ$CzHK;bs!71A)Gx}ris=J}ilS_zv-u*_s&q#7S*x*aAwM7r`u8drN@LCzh z<*1MVbKk_-M|l-0Gzm(D3bbF8UsOyRLG=HR-2E4AE9}3hudDxJ=SJ**ClAlne<8+y zs{cQ3iyo53fAC}J{E-nmFBocjs5-Ckw@sgPUZ~-Cfd4N0XFItlMo=))Mo@7afA{c(zHtG&#LzLmWm*z58)TdC*9O#IKVn6)Xt;9w^bEPumccTn^w zkDZ8g5q7E-OD2}J?%hTWOClWl9du(U^<7R;>K7nstGXs%xsXq!O#a*m284VZl++LT zeoU~;uP~QE_$+GYk>sJIr?&CFO+<@^aQ33SzGix7IA}2n*En%$-@P(wO|0=@9fV>& zIft#5v&p+YB8cJu$!_7CKAXDP_vXvcqI83BAAf)am{%| zmGWgp?TT{gU)|u8gz#Jv5p}+|=LF`AP2HQ@s-jex-zjfiF4qR>yLnj3p{`h}w(e=9 zktnc8Bw4r4n@cv^H|&(z7+9ec>ux3D!SaW?zYb_;WW-Pu{%#losN+$-VY!P%; z`MuRLAD*w#WPa{zI*nth=>T5r)QHz6l2&L-UPxd;cB^sU;FS54B+VuIU2?t0X`3ZE zo0UOiT(5IUJ%0Hn2wG1B&%z!ESVAnJ>fn?m(#~c@C94*NPROV@W$TE#`9`=&9R18c zxZ-H||FgGT`Yd|sVz+34ttqr!fu!%ENd5+=Y^Hr07LQs2i;wUrEEWf$SS(*`7FQ2W z>7Y6+j%pTHjSaT_DHULICm+J*Ky$}XHkaqwe2jVo-Zq=>-(<7dZ)2gm528`41T3G@ zRFX!(UXay#Duhxa4%J7CP_28V!XCzHLaatPny-qRy#xe62d9+t(&)jXm4%_Z1>U8D z(Eo4qmWtiQ4)LLfrD&K!wB83o2xIdOXe205BuYgOdxfwU96@ekC8??v_uvysM6JNQ zk4LU|th!TF-O}_c5WOsa?jDIIX-9zWV-R2qQ^E48e5Ou!0{pA;N72|ws=%0C1-OYEa+|75Z&$uJ(JrL`*XGmH$c$TIoqvuPV$q9)9d#0~gD%NZI z;FKx|CbM(P6HU-yIpX#Tbj|D)TQ6h6a0i$>Vz!hzi`;a|-{d1Fpwy{+;cM4A`HoC) zv|w=REcIYOs#BzLBWK-Wz+PNp?uf8>Wo2}}JR<8+8JDz`;(4%bHC(cC4Si(jUuF$R z@R>k$>(3}}d2q~andi^UVy#m8vdTlTUt1M61**?VYf8?rFgXMiwauly1uT((KR>Uc_4ei`vFooZSvox0Rc^c&k%x3cMQ zHXX^P%euX#Fqs8`Yq`c3xjQ3(7pe4vOR&9MR3RCuOor7KigZ|B zyy5IGs+x;{Qo3ov&1|g_Yp-F*?6@?M4$l=hCwOpH1axg1R2@5?wzy!GTChkR3bcPX z7c^bpfmWKHYh&egAbH70e&(z=>ADUSZ)y&&)C_$k105sXpBBOPc7Iuad{2J_aFP@* zR3ANm$|9h>xwPN>OHRezQDSF=VW75_-}UG^BSuQn6Kii=@Pm}`o3ELm&1I| zcaTfZLNsBid3ch#icA*Zm0Mw-)%AP9YALQq&9o>r%6%@V*9(ATg=81+wVY!gx-jfb zw#2frCU)h@7VzS$TAPQx8P>Y0brZLYlF%%hF)n>6E_#k9m4qeL3A5oYHO)jMR|Zvk zV#Rm34i8nUYni&kRe4zV1+MNZU`Kp?5U1DegC`oBaT=RFcWP`P)eZ z$a}CF37dbCHRbmV0^ooBYY|tRv*zch*Qa;hQMf)GaOINv6+so=!iq9kX8O2%FNm7B z%q*lgwIV;GZZA>Po~xaa*2BxnkYSq6uZPE;gF=gYeYf9Pd|I@=n@Js(W=?y)F-( z{BC$pT3m*8P7!p{#o@T$%G-mu(8m&eYEZ z?$Jm5g**yA26=JgVx|J5eSyC~G8j?wADgaLaFo5FxY4g-$FUV{Oz!GLe7>iO*f5+inHlPtvN^!DQ^*2yDV zy<{tFS|rN}boRwfRK}D@N@VYNgLzomfgnj)NniOw>H@CTaJ_}_G=(Y;dEe1oxcn~^ z7i7VIAd(BuKn=4^A+`<;)kD_y)4utuKUZ(475&e1h6bAz_Qj8b#Bq?2oeYtNMsvP} zL|l+C&-{zUt{LWUwyJLlPpM%!ZR5{MrV;Y@&<%gWpl7p=362hQxXM<0lu} zRs7~B-cODzep0<~wGeTImwzRYtx@*Z3{H8XoJ>-@H?yI4FwN!E>(x(P|9#CnB>tST z3$H}JKN~-i*>FU+;I~`&oT{?|ejI5qV}B*Q;-D15rVpy`K7<5Q#X|4yNB z`PL#zJn7FNg_&c%^nI$=2eOZaC^q5;v#k;!QrOznEMJmGvYX_M6$~@%mKA1Fm@r>Z zh75(FcT&P#dDEWv#ygGV-pPlv@dMf9!R}LpzZ!*$gYExF;{vJvK(-^I8aSBUA_H&- zeDK+ZK>JJS8=Zp8gT8W3xe#(ZNyW^8Qku)Q%6C;L)YxC^D+hAV0}2x<2|hbJz{VBe z2yRl6dB|4<9O;IF^L(l5oq}WcZT~D^mB6_Uirye!K42s}TX%b82o~R)ImDr}!egVp zGh2UvPD=l#(myQ<|C={7T~m3+PV2lcJ6lsoVLDr33L5)cgktjNplBhz;X_Wz{@LYH zWB=@^d^j|j_R@XXhN}yIRyaR{&)zoSTY~e;Z%~%qQb#*LY%phyQ6gjMV6go^1g0Zr zHld8#ve@j%+K7XM1DMm8vJGYVpA8Y&E@u;u^S-*++~?>h?`K<=O54eSp%0ep2Z!G% zdf{GG4zmSoY=Wim3fO%8Eb}da>fwfStiVnI>S%rKk0tw3V)9lAnZ+t{d$*-DiZ-Q<%}1|9 zv!zgAG?>-gt&Ne=;`2rDwMeC~GCHJd4d(q{wk(-#5bDahe#YU*f_w5v>+UKCoeHV1 z7%GMY;#tVo_fy)ZQC2YBbrkaT{jvJKHDirrKQzIFXu>%iNz?Z()7N#(2bsOC0wWuL zT0zm@ckYkx0)516XRQ9|HJ2O7oyP3Im4g(e&gU5~czVY3G}9Hz*6-|jHM3!tC-pwC z>UtBh9JI-zdwkKQF0%ZUfK3h{C>B+O$qnYm9xtRyHoo1c-)!_iLM`y2}U`Wxi*v1+B ze&7b6aex}>ACxoscsBk-wtlOT+-k(1h;5WN)?f4}C+1P~cMEDjBaNv(dbN4rTH}SiMlnA~UJ_t(%;xsq1pdBaP;P z8?BPwLH1gyP;ayN!1|MT!y3}XRyfi#Df8hH|8wxP3AbqAv!!Js;$(BF#XFH@?c8hu!Aoa%$c)d}6#^Sx}FBV1}Hy)Epv81_n+)m~3 zYn88}<+`ioK*UXA9R#`hlSV^0yG2Zd`sp{+ckg2nDQS^vlUvK=J54<%)v~SXU4SHy zAwfom{EXG>mMPjOm11$H<$dbqlk8bW(2e*}V_y0Ax@c+*bTDR@8}p)q&qh(Y>?Tn{ z8x1M3(U5W%8me-usw`*_tf5Wv(?J89D3x4je3YN6x8jXN(EVOTBO|M*OH9%)qi=!t ziV=SWkKI4*pVN7+qMNb~OX+sJz} zdeDNNVF=l7oeYSyC(M_BBMXDW?y@ZZryr~U_(r+2b5GGkRz#8|+m?m{T`}5gi%3o%~0LOxe(MgTX zusmCaI|F*S!-Iv0edgxD)a@MPmB=Y~Lc${+fQBcHi3B~`k@Uslp*6u3AFwIY{bdE2 zhEUls{xLgIVcOklxA=+7hLC6N0xT+^0GKej#M{pmn%kF-=H5Q+uwPUwDVXU-N?LIa_Xfk7`7o!l*I!aP4RVk(Ed`e?Lw=cDwLE{1Qd3$$E5%1 z31W*y_vi2{^>Lwx4mlO<`4qyf0qBYhakLb4J)YTc+>`cmUPbqS1sNgPsHiEB2eOX| ztU^3!CA%eI6(^5ZJ|^F@Nt2@mV)5|Wu`oGXkE<|g?WEBm?ShJzDJO|i;IVn%pXflR zK3rLEW<@4?y-Abo2v5CnGt1&_)w)*^LtHdsBaVs!Ic4iF|vOYK%A42 z*>Kd89s_53J|)%hV2+SuDK=Vc+21Nukv|+%EGg8Nz8*E|j~2iVHJB%IR&)uik1ARN z^=MX+mA*=rGGt{{l)b2HvK8PJD_0`9gk-;!4Y0x&aW|^VneLJ+>H}%ahGa>mb#~8V z$iN$3p(KjLy|n(d%=C&XX;o2-cmHGz{fbN870W0H+X|rM-CfZB61FROJhPh%RR|fS z6|HLo>A^Nuf{R1WteZhj<4Jx2BWx6eq2NX26EvPos_f!$c2;$X5X?eZ{F#R=8vg=&sKA6FKh+P|_?TJF zir2X!V|KM_vYJ!hDzSsF#9Bo}gP)g^A|me9Z=kI2gVq#yPE{j+9>G;29ig1lGN6xvM-An29gvyZjV6j>QOTrX`xMl3vfW3fs% zccoFkm+05Y&}ppXTsDVDl;p%DQ??hv9;F7l;-gtBAGSX(!zsEe zG96QCVU!UZ%{sL}l0M+Fm!ha7_e7gJ;+55lX?hFo$Nyuwf2%V3W{ivg5Epyy6R*;~I$ zCCWnHc6f7TV`>g+KAhfIY0!Ff@m1eX-g8U}mYvfbgdV8yMxs{&=63 zIg3k9c%wp{Ui_vzc?GL#KrQo7jpZRftz=5(EgYR7x6+64+7H;F2A23%1Rj|A6tSFh zsdG021?u3Y0q<~YxzegWLQUZ|2-k1|sv47vglLm`r6dIO*FLWqD_*w0=Pm`T z+?W+*K&jjl(VDmZ7*jWscay%LNL&STDRMFtgLPZ|-6=SG48rI^Xk~j4HAvSi&&U4~ zluNuGaK-Bv*n`vBTrQ*c9=z9p$UA4#BTC!?oBvb(Ui=YeM1}yV z2@;SCRYMu}JBC~hbl)Trpxd|}`Nb%A%<$4}p7<)rb6F zno9IMf}ub4BhZQ^B5a#PkY`1N51=YJSWbYA^n9GYo_dYnv3XJ_KCr)5*9lUe6r?vP zh1o=eO8~5z1Q?tuy50?t9Mpi0J76T=v-2W7=k1h%O%DlFFeGTM1?M!<-mlHB3LJTG z#Via6L(w_%m>%~#;SO-Fn8%8zejP*gT+A3_f2)9zKVI6u(Fx8VeXZ5)3Su&tfrMK*7>QSMMuRPA;P*G--$2`W~T9~Nj zw)|R@2~z)o&9u5oKN8T_V184!;7YQpT}@3VkGH-th{JAur~WQUZPCj)^s;9W1CFuj zU}l5KNzN43O5sOsXC@+QJF|gI&G&sF@?xTf1BUO19)85)$J2`OVfBnCwx_h`1)^6$ z!eD;7xf+1ro#|YJ9?ekZQ+0S4^89+EB9A-CW~l}G0CO@kJd$$d{$5ci23LOWb(3MP z%Hzqe4A&5&X_%%`2?FybMM^U3YUH83FP1C+P)gjk-7luoN=yJ4$nc?cbKJ**S4!HRo$ku3&&E4M2N0Ef*@t(B^pX zS#q8@*;lydDsF;Iwtg?82n1NCs#S7ZicFoVCb><_Sm&Ge5)BZmskyqHgo6YcvBzqF zyM8JuK8X-_#X2N-R=kr*4r#>7t1E5`z7hmVE@E(CV4a%QA#bGBUkn=}>NxddnGMIZ zl=z)~vbF#S{S7i^IM!(XBRdIgXHQoz9_5x2#&p4F8LAx1&Z^Qtm<*U#p}rn5=2cj^<;E&I zv3x9BSDsBUH~@u1*@pQF(m=K@A+N}I(~hgIQ3ca;fp+OvKD4JeOUxTTmRZO3;UfRK z-=UIV+vgSKbPr^rqQsL*tyqda@OrJXF!;>__%bBym>3@O@kf+p$!s{Fob>?}mqU&~ zqdAdd_z_IiH->U~?1*Dhms$lvuCSL_@fZ$!8u!S=kFl(&2emkcomatxx%2cO=b#p? zDX?zokvYU|P}!48D~ika%tNeZ(2^`aIp-c@n+t4|p3kdQ@~f&nhy%jok%U&&go{Y@ zVTJG*vL&d#b6N5H}kk&>^!BN;w0iFi94bJX>wwL*|if7 zR!E}b5i6`!o=2^!Xr@OkSVbV|Wfc;v3~~*TB(x$M@*01#AdJNV$n;<8BZ9;VCBkOk zdM&&pT#$Ulw0~Dch-g1O=CU1G4c4F4-m_;)kKZ2j!N&cfOs=Fd_`37MpA9G;7v+bs zZv#x&t0g4_V!nK+pmMk!@N=XbuA)Z-GhgBfVf!sJuLAkZhmXqSQLz1=z{q+ewv|3H zDC}>g<8V8eY3H%@r=EaAMH)S@;iSr(oWx&_ky>Op;oO)Fi;;}abZ*FWdZ)eg&9D8# z)t*x)BnQXrlJe&qQl)Woqp-JgeFY27`MKc01&M8x~NzCTqhhzRz2r5*pY zc~Hb8=YvBSjns>{3{5;_mz5S5YG9+wI%8EG`7tG7qWT5@|wV%KMSl#Y-x(#6n z-BmVClK#{5tSa;OmKrnKJ$1P2XH#0clmsP1U2l#b&tcJ66HEmI$^NdNjma(Ydr6e{ z{IRX_zZX6vnnVvpq_H%kZ=QFsYFV_F1TP`9zX+c&7FNw^6dJ-*mLv z%V@=Ab!BvgJwz7IyD8fM#CKEV%;voVSLSet-{g z6z=H{g3pq3;8TEr;?Ezp{iXlI?TZ&Y8$X8jU)g8PB(>@dcGv?r+!*3i>bvp6F2+4Y5|@y+P!EQkTdH7gQ@vqA}7X@15BMr zyS`Yx$-G;#Kl4!F3>R~OA!~dHi?Fz&r?L8ztFZ_4$m)P9>rIz3!2DX?l&FYQ$w!&x zsO$`?Bhtmx0(wC5m5t_hg}t3s(_5J_6l&;4W==;@psLov5FFAC(oy8mSPPQA2^&oU zO;R3Js9NShx*^#;7U1{^ElCm$=w!bXFy(HQz@-7T+zMqJh{gNqBwj*|q{Vkn?8s1Cc&XxgTgg~ypn>L5Fp5Ll;7GwqEywao zWmlV}c5Aify|gtn6jRdTwt2RbIze)bi_f#Sh5x?(m&b_-U zdHqN4Q9+vz$b0WSe`e;)nKLtI&Ybnhxw7`xn;AK_{_`j8p?k_wJn9*9p)z$_Jf$>E9?i+<`IuR3A`UsIef=&k(Spwm)#W^+w84az+W&Z z77_|A0{=;`)xh#(+U{E-7RT9+AaR?ljiIb}k2i_NHEJx}#f25{+Cc%@A330ZvRscW)UNJOqJBYQ z^+FR)g5BT2+-5U2a)1rdAR;%}e2_%@3GH_tV23UovvY6w&Vm`;`m4#vL37ESP;f75 z-=JJ;iX|<@;}|{hdiZM4jw%c#dXzOY*=2v(LvL8P`C2@0?rmhSu6_Z*4GI&){j@+{ zuayhAxg~Xx*-0`Sr6DK8IzlEsI;LbxnjPyp9T{+4|6iAiuF@R83u6;YEvB3^+cYG zcL9Kt5s$T>aGZayMnXu0lB+9fEsDGEM`ap~)s49}#8{1WE2}n&`!(3cAs@E6WPY=? z_|4dX&GVZ*9&3MGPBIxfGRDP3-pCJ4HmUh~)G`ExykqR!>pH zwi6r37O_vma@0KQ56V^&W`@byiZhBYK_m<0_Jxx*vnbpCvEf_~wzm(rvY~;AI$%Cf z6JYF~qc>O&n@oVkdP$EfGS*0eo3x{8h+uVy#=5OlP#|T7)+g&1u1^R(xqy0(M15H%d!UQuS6q0K)hX4rj+x!)EnN!p9WG0y?%=V>d+WRGQLfMCljhQ-?Q-a^ z{nGxfMhbyXQ6`*B>9;f#`{6LeW?E)t!m(TE!=Mz0BzhVsY{OuWsWm);l)ZMtqxTLw z(pQ+zTJcG-r&N&uv-H34olas8u8{w^ORp&hhRfFmsI&+NVUBIkZF-)QI$-VpavCe5Dmx!N7@A z*LtrRYfAZuZDM$@v{7qd^fj)H-d7ik!Xd}u|5L-{&xK%AKX30)m-x4=^;*LUDW^H7 zzqc((whblkUzA+8Z6ZZqD_t?4u{?dQUr2dXo!9#N>f6G2_Sx7Rls#R}fJ=7C~RSO}!`GDGWAoIJdDt;Otna*IE^2cC1I&!C=Aw3Y2ej zhla}BqdT6JvM#OTsTz_Lg*L2HzkZ@?iJ(i_-yZwxjxha7(i)MX5-N=g6#tyYA?hZ& z7YVj)b~qx7uE`2DQWk;|KxO+$jC>M z(Y=em>3#CU#C+x%*MUE{<}61-Ks_$p#vZ+YUY4B6hALbHtPR-`4b|@Kj0FUmX=b7O z(23oSvixP;!n34(PdIagIQ~!N(Xk9?g!aTj9evf10{O!bR`H7onOh2j;4Q^jc&?22 zW>OiqTn0?qJW|(Grr9^)X5R$MunF zneE=;f62;*P;kHzAjRTTq-(9*Y!L;~RSL><@hOIuzCs!Ul{Jk} zycD5w^TU5>&`vF>;hs`5_T;0yB>YT+$)4_ESQZ^hfR+S1+LeBryH(w*zr>YL=dmX> zz!v&O?W`J?jn;uN0<;kHtOVJZ8}oNnPIYJ4v;va;t?EnvDG-rFd21A7B>&#Jp~-vj zsL4#PYc?ojaCVn6IC`3!fA85)DNTC3(YyO2#!N^8O-{xz8yYG8;rL7afY$91{}}GX zz2<sOFyP)j|rWTQ^(=1NBAW-Xj5721p*h$-kmhxO7d-iaq}VIAH_oYh)o~O zY5!QS0f;Z4$@@C;OAJ40a+KIvUB_}#py^XP>0^!F_P+&U%`Q7kY7pz-VHSHIO6Gli zS!}q(hcdUYVx^YmWIh2Umf;jymIY8^*ggQ$pG8aDzf+;qAr+upbpa^b2=`-28&6oQ zhR?r}5#CJ}5XHRJt9Tz^??yYzr&Ly5`|<*AMi_#tz$b;m+sXH*IHyJNM{8B5W)#`Vt3=j}vxbZ27j=!rQh|&eqXi zu}#8-zbs5qT}N0OV}~xwt!mnNij4Oc0UrROzm3?gkdCObImv4Fb_sf19JlJ0^6NX;kEnT zl?UBKf7uR+Z3lfifFA9js10RqJg4rMU&4mo@wA?9mSs|J||728Vv*I`GrS~y}u;#HbOR`5Sv(~=&fOzk*0_Dk+J{{?t z>u|7wQ*f{nvA&X~RF4X=pa}=~TsW{^eebXH)~n*J4k&-Mmn#1wLL0SSNq&r4CNZCt zSf~PW$dd56(qE`39rajE;?ca-WP0n9s8e8lx+T9wn~(C1War~pzu~8e2m>d&PJ*m2 zPx`wCdC-4Or&F20wCOs*CwpP~oqj30zinQBq+Ecwy7u}hE!jnFwJDuT?opF47;-eF zuA00Le#=astoo+XF~81lGOOgqj9>~lft)b)BAL>Bjd1`sXCE0Fj?_4ie26PFm8>i$ zQ_oQrB~N{7MfCd(ca8F}VLrXP!S`l2xhY@+sJ;1l?h9g3n+~Q}I?YF0b5^Qms|3#G&52^*}~Q#NGxSEWoT%F_R>>@cm*&}bMCRNhN z!=eRyrdJz#W)FP@>k;u^FffKod1}>chKl$yTNzhYaSG(VYxUGrMeJ>Cyyl^K?uj@` zF&yWuj!!BaWnr$1PTc3te^QCG%X2a0kzn=iX*Lq!M)yqF?ut0Uv1D>)(~q46b(CxR zi}_7+%tOLsfl-Cra9d`%z0>CMBPB3@c`Z2POdC_Mz)veAtu|J1UL(9MMrFNWivXXf z_PIkG5!Uu;Eea@q!Jf!1=?56=A})KLoZiIrJwhb5kOQN-#}pt9CGZRxD47|2BNVm}JS z>9)SUNv+)BK#+nAOsEU$pr8tS1c?%R-Da;R1L98sgJ*ur zAY0VA)eGrrDF*xleMU!Yj}VdSIa(?Few69Q>6lwfi0?u`caTtnY1+;f-&hgzICGu< zX7lCxQ679^2FuYl#t{)4*A%|%6gv_~lBSkL?`$k;>AktJ$g5Z;o<>lC%82sfv6TjN{U|%vmm?{?GCO%|*##7CwOaaKF>VrQos#chRyu@fkGM09%NUJf-WueVX zm|-2{5>8{jJcUXhYVfJV8Zo8=BNI7UKWRLcGLPRRz#?d=1fx28%s2q_Fr8FRg6V%O4W{^DT!#c#S_sf5G&2zCAUNe(G6JuZ< z*o~JF{{Mop{s1b9G0p^WRUp7Uo}A1p??sm zWaLpalI?*=coM?VK2XLfG8N9;g_Ru{&<JS6uQszW1`~MxqN1dX zlOeM4Ueq5sA$Y74gra#g{J{<;pk$lUDQH4-}++1#sB1lYBRya5p zPfYVdEYx5_FUoG+Fm%yTYz`ZYVo?x?+rE&k6{hy}mEZJ;NL0+zDN}#&cZ??8OC^3H zKx8=cjLu)S=69gTI1W#jY$mK4rov&6r$r-#n>ima#Nxq}JwF`blm^0J8TMfbcMj_n z@aRAk@SKW0Ure?xHc^`g;av^Op!QaE2nRw~u@Uk^!&B8Z6_C&T9^v;GI597U(Fkas zc@ANt&G)veH*jIGod67$gdhXrJ#Z)aYnG9R?|rd$uV@RT%N|WrzADRQwAOn^#7!0Q zPZ8uWiD*>`LOm5(J(58wafwjiWCFyIx}K5QOaC8f>ZDk1{ba1Ys;Kogbt`vIdEM-G zR=2UbNQg~f{1JV?GDb!Zj2K=60J_Uxt#X|=hq@zGamh_rH!+)YnPx>RoKr5tqqg+} zL$Yd3BnX@!hK_t5C-QxRCy`2rvPt2MKNn=zPnj`{hKUXs)x=SjDTl?BOqaUmv9_hm zVt{U&ZOT-dn=~Z0a;oBb4=`0SDpp;QcO&%6Jla=N#rxJ{Bn$N$!6jkbRaalOE#31XNIkW zN;XQH-LLU*s>^5s)1A7${Oi{Dr#Q96K38^p38h2lA0pC5;?{|@lkQxBMIp`Wtc zAvx?Cm9hdPZ^(n>>O4rU@gZR~Q=`?c(i`(2c~c%F*ZPnQxJGMSr8nn6a$O!I*ZYtR zx<==_N^i-7OL^6oe#4wTj+sf5YM$Vf>h*S3wG=jwjHVv0xP5=WXIk`V-wQ}#vOHJL8RR^x z+Q%J2N|)#;e@m4`VLa72`|t0qnQuUFc5fc9`c8-Ee1lV-(rY85iz8##3#zfw2&_H< zJU{qfPxaZl!Y&NKaua>&*@A~ufr!)b#m%FLKmL|B_aYpC=d0n(|L(R3`d+w{SAE_a z1P>x|jM|H%jf3Z4Pp3k z;CcP~7wvHeq56jL(hxHf7CfWEsdFWj6SZVVB>lE-5_q_kdPW1P^KrA4~m}d(f zB{rn?;^^r0f@-u>TG<%zoZPkbZl|^OJ%1^$`cA(=@Jt9Njnw${f{KHGu>C0TeD&p3 zNvHMn4YLG}_N6NY4`LMchf~E9*9$667@uUgf#)xOMW-x)b-eEd#4T|(VZk#hoHSBn z*9)q#Qo;pEMbJ6>>F?f|aE3|W^C)H$eWzy&9?rJ2*5~sN%rE}AZr=8LE{cCnIsW;* zPwj#}z zpMS0VP$b|V7E$xGmN5&SdY_~&~izxj!a z;-6v1Kiz9?N}ZQ~Y_Jf9VxIbCui%(QP;#EQ%$TQoGV|C-K^aM&jvs#NGXdvd1j0F2 zOy(RLCRR|f&2|6n4}U#in+ju_ipgwaW5gU6&y+9y=N|_=bCvPTWs`Zv2Iz4oa8{ju znlthUN5x_q!&FaZ7@OU!4&s(Cf9oHAA>bB{p}{RzOy(Aw+Gs0Us_y!QzxiRnDiy{m z6_Z)T<~8$3a^~KHUwb;>6Am!ICznm;6PwgNlN{OdKNbW`Qf5M?T41BkI$l{PMUBB}y0f*ogL72?Tambi}kwhugg)icfWxIb* zrkW@{%svY|LPCr{mW&D*36xTKt|UsH`QWd7Jm3=C0xU&W=eT5Cz=%~$vPqKs?m+qP z1bo7IANb_T9G^@G7%__pesN0s*h^;uPGM`Ag=k)mQ^o|0*u~aG=`qJX+}RcIitanG zL=yq8j0zaXw1bXYerd~|-we0~`w%teY60Wam~jE)*p^jV{4)G63ttQPh2&?*k}Cy_ z(_+YjGAGBlk|ve!EB=#!V-%d(=gkvkoDwr8U>xhBVvA=!KQHu)0nd=ej5UZf5`hkr z$1}Z7qHNppftN3aXAo`TnRor~Tc5fZo`HeIGk^2kcW=5FocFfxw_QM>gal1F?( zA6JwozVgkN>}$nqLr?Cawf_3b``5j*!uHp=A45L6hdAJ5jsv#tV$c5^?DFIao@*u8 z5J|i()&6J51^i%!%p>28UMpF=#oH65s)Ko;Q)ccAVsa{QNNgsFw_;py*3N~0m>Dd=VMCI7;dJ2v!g#DY^vCy z6(lObQxo%6a4<6S9pSTuGbp)yo6%5eU2)Y~?@GVhU>nr=x3j?ls8V3mmnOX!6z9sD zQn?T`D9L$!FOaI_RCnZ5T)CP~^`%4cXc`Ak-|32Y^J!dyeO^^OlIf04#BrC1QA6?O zf3?|G5s&=9L`GFS`jVP1i4Ff8d_?%p();E0Zw0qmhZPfm>ZN*&&?M^+Rbx%bLFR@oy7hh4q$ z_-d2}K9vU*Q9#|Jt0+g2eRUNvZ(PNS_-e+0PZdE$G->zfDmr-h>MF7dx{8%?c9&JM zGN_2_&po<|ZcCi6t|D@7lpXq?ugwo23HV<@9NHqa@eJ80GH$p6p{8X?9S_nPu^Ce# z2Qva3xRt1j5@w$lEgmF4O9Ngm8*(m4#=lpdc}7s7!mX_+%u2a5$wl!RSOeF zxsuKC0k?7ZMbSws4lX@M*N3k9>z@^j$R8ln7w*TS0+UsPps-0$~SIg-7X4e8c0+T|w$(FBke8B88HCuwM%$qB!R&j7SKcy~*g~i8WpL zHTe8^EeH^T`2a?l$I#fwJtE(xmuP;3>y0dr2rAj*i+k(VrG~7_XM7_?70NqBdJf;Q1(kMh z|EjLTcW7+S28wPvvfVH$M)2Ou?}hh8{|(pk@mDN+=pHcxnG9oT7dCJl5yJM+shUsI z->F1&mo`3k)u<2`KxrrXplXmo0Jw`XF#3UGR5`#A`cfTD@E+ns{y_{#OAfGS4hQO$ zaEg1rPJ#_nd*m1$k7W8aB5S&EDSNT@K|8TYtpPmFwfITB4)!Xxo;lM_=k_C0Z5<4t zj8TKHXC5jl(ng&9urc+-l*#CxIdZN%hE&U?&)O4v{@P?^szKu=(^fqn23+bT*7O|a zg^gA_F?>)obyyf?&>ad8I{o1vEAYT(nAQZ7A1h$EQtc0oA|p+Vcy7YMO{b78+&^i1 zade2w9}9fM-!OyQBPVPYq5z!GEc^wE*eo12H$AhEN+%@QSM`jsN|v-U>?h&=^y4-y zPOj%r(|T=gp0o?V=!gv;s!e1bWk(FYv%M=e7)Haf-?Azr-Sgtj$JunSjz|3I^Q>I! z;hlZluMytYe7xg@tq>vHsXc@6zR2;|@I%bx)+=Dk;?@uI*FRp8w)6lTU*4QLC3a_{ zY*mjoyR==fDg`U$fvnpvmFF_Tv2~{6dYx21X$0Y2dCXFYWm>7p1ml=F%r(T6ImHV# zFODZc2F;7(eXtQf0=t)OtIVyLr9s`(Q|cB$HdmLb1?r}MMbprAoSoT68MN@e+gK2f zYPP^9Ljs!^4N-{w5xcemXCd(m%&OzD=Svi5boAIOrMm2qccNPvHw;FP_Wh^?FC;l> zUDXgTBS-tjOEDL+wJUTN;Zc(E=2x%rtIx`>zJeSHk%3y(9q3@2mZ|a(lfiyuxZi?# zLSOo%d9qob^h2XVhJ53s@)EXte_c6Dl|+D7mPO#CNqOFp%nd%pWi1rgxw9cDt?beq znmjB;Oq(2OnKm5t+}vfO6=k#-Hz=Ndz^08DH%}QQYJmCEq}3BewxKNi)wzqVy1l6D zS+@64{p!nJ9?aaruCPlH9scSp``X(s*DxpIA``XsWuJSZn)YA*QG%8up?i9(saaZI zrmY~|@|0^on*w3NC3tsm*!*RwkP%H>x3W^}ke5@!vpqh9nSw#6S;Z}cDSy=GOuZgSOzd~<mrkH!fXW5(B>kKXlpz=ZH-62?U=Ma9xF0m z5XmOxu2)b;mOj2tEix%34cB*&6N~^x{U^kXyC_5sbOQm20TEGCs4uZPB4UyV~UI$I67%qE8UexyUBnF}SaDXrI_h>H8#R?s=ApGS=TYd+Tyu@n6Q`3$ho;8UL(E-~i_$n7F#j z3bF8KEjAWycbnczx}a|MCKGz{Vq|hcY3?}WFzrojH}v?v!vRfmdXtcuMKO_SE!7>3 zyu&1ac4vsxq*al5-J5&bu7)iya7zdypFpKZ?<_8C;%IO5db6dop*b|F4>nXGXW)?3 z5^;KWZwYjpwG^R@eAZ#mwprTgalF$ z3nUU-to6FFc!)V*8R}nQ0q1=0Us)#1yqtR=k8p{!ayLrZ-{6%UB{KAu8Sk1E8S_ z#~u@&%+6?UYG;RysuZs5fZ*RfkprzTsnJCXlNw=tBA?XPGS7|F)F351AfD*2F9!@D zIFY6Pi7fR2a4+nb7EXcG#ry;i5;DWUA=_L#p;H z1&e(+78B<1sK9~Xw$cYNZ&dN!nRZd0yh;`>*D93*$l zKPKiMNvbH9mB+@?Apg!*Te0P=BE!KnV`v|)}N1Bd!1*F%KJ zn|>^{j`0a4SL!;MjfxmXY>lFjvX1YB7Fqc;>ec-3;E zA{jprh$Fs0WZlHFv|*={adl#vGV)q_7)^872*^bO<0wdL@m0)DM`nNo;7Y}g5@F#$ zX3`S@JF3N=1q9WEMp!Y3%p$T_ZMyf0sF&p91Rbl#2teBqjlhoSTO?yAN!C31x=@#* z+ToTV@1B2G)+$LroH^1NaD;(HrEgn?%(mnx784q>5S&WqFaaHM7oD>$Id<=COGTAY z+qW$#?rckn8(n<(4{9?~TQf zbwD&Et81umWi25}Iax`2SSmx_y)to}(p!zH%s3AvJG;#U z(dQ;Ur~eth(ByAeHE@d{XCxg5bXwK}nkQeSqRPF*YOwc&q-%k- zqW19LvN_(D7eTN+)RwNUqn)+aa7EQgOVCrL;l%koHRg)*84d$P~6zO+kwj0}V z0UK<`>8kt*_#Xh&Ka2<{Nv5LKdzlqK3CScecR$nUggjKx&nCI0B9=g`wZy&>TAz_n z;v@>SmJ zdwQ8kgM>;LrJ9H2Z$3eoi*28tgpS0rvKq39`p~DZJ7;%*uSJZlS|=f!bumscU4^@Z zwQ&7DxM~Cecd}bY5_o_@Mbe1}oo~ld{0=}R3D80B6Jx47YFZ5Qox$d}-)Hc} z0eEbXABl&zOES6!ZYb2i2sBDchjo(p?7HfM#jU=Q=8WxLLKgr=rgR(8$RiqmC+C^b zgWfTHm2D8*3WNr?lC=EY&0{)1&V6g_&<un9Z0=?=_!-yp}3MIj&qLy2vVbDqw$s`A8+1NtowMm3sPW0n1^ z(obY5Zz~h=y(+==M)l=V;&_W*AGUE*m1f&Lj;;X zBCC0gbXBo_QR^K37Po#d{UxCA&xqx;5|mV_ zH^Gfz_bs9mLUoR8eT33ZNt|Gxon8IT)n70HGD?E{GfW!o!jER2&V2aXjopIc65bat zdh_iRXKf@{c0As#mi1wOd8FvN+l!7pZ@TNm`ozPH>LGIgOmN;5rRBBrg_tcRHl4MU zRD@%HX2{q|%32oQ*F9Ksdy(z?9v>#tNJ-{ftUcjdb_~@fYydg@5M( zd`Ri{@n^$|mhF6_>sardjot@f2nD{ZXlc}2c`U1&y!W`bkcs;OL62+>*`t-FP#eE4 z^vUfzNPW{sYe7R5ivn_b@U4>5oL;r{Pima>y~=pUH?D>7{$qK(<8R#~=BudPB4%U) zG>1A44e({H7llnV4HR{y<%qEua{mmAU(L;UuiD!op6Af0&lvZntv<(i$)R~oTq6&CPtY)s1k7>xH=MWRWR+nZDXS!)IS&!-z zLd>e&QmhDRV(8SEO5QB>YQlelRnyMkVOyRkZe5o7I3fsM_s@V4Y?Ol8+%&f-pvm5` zsmi7zjPHAqGry3nhJrR)+fdcfr#{fR$cM1nZzAx{>#jx*R?=4{O>KRZ@NV+13%c@1 zAr=1Zx7ZXNb>D8`)Tt%iG9}5S+JwhTbmvv5<5o?AjkD5^LleUiDL@=2CYyKvtaO}@ zlnrr{1-JY56%*q?*~ip801z*OEy13!EIo%hCy$Si>cREL;;!p(W~G1KDo7G=yl~^| zI@(WdrMpkhN|Q?nrqzv5v=`p*L;zs(1}Th-`r!&qBS(xs4~XGk6qR0RZt9@yemA`- z%NtZ$YVRyoZAJvJe$%gQcpzEQ-$Jz%#%)We(Q#ViVhgw!JvRn0D|rjl#4KYo?`860 zGODJ}bgq`rr>Ffp9utci$nnq9lY{tG2GVi3rGFzR3zLVGNKE&@0&={~bF8;akPL&!qA~)Me??CZL?X`I}I^DT+T9-ed{-zMd|8e zweK5;o8>4h{xr(qD1E`=oYX0?G@GGWD%j{%xEAHl#Hoia=&x>c%PH3T>*09L+7;jP zoGylft5cQTbhkeFaHHz4w?%;W^~Lw}5;4fH%Ts0BAscH`y-H;M+!wn7QZI0WYH31P zD6B;Teds9sv8;LGJ}C#`{REm~)#1C-Dmp^6TILuUoM|l;0?>Cn7=Yy)Kh8IsTKsJ& zzUSFlsmdJ|0PMJ%ueC=_H^zd_13S&yYHwIV1(nP$H(%WoMVmb>UW2!RLpKVLT}cVO zo3IW-_s`d`Y!Ev%c`u4>mG`v*)1P=%93l8hf^0p!k(|`-tS;@CI6fTSca#_5r*~Fp z&~yY9mf&kBzB3doI87nDuidPD`6NQ2``-tEfh8#?%@bN-YDL0|POE&4olq+SFK z>3F=+^RQY)Zo!U+MxL+k$jk964LTnh>U&qv5U|&3yJJv;Yl&aosWh_G7l6q{$ALl7)3Z!0ZWR zovdgy0foPw=x9Howfnvsv{yB`F#Ac?r1pL5j-iXockBal0w>AF8al0IE35egcfD#+ zVOvUx5+v?t-(Qkhjj3c&ZqNi0(BXR9H5JW_qNc7Gd|q8-fW`Z2e}TBB_vOLsF@xX4 zx|E*9OCL@uvpQF zq@~)R!bw%=V7K3_ms)EQS-l?Z4k8TsL{PIsRxwJCuCiW9*GK`TX(^Ct9;2K?!mPz zpH89J_*HcS>saPKH>yBWULiJsQ(%~ix^J}BK!lUxwdBr~j!~Lnl*q~V!{)Bi42ZnDJI`o%KDRJWWyzV%*?uf!HGv)=0$FmE-H zn-(G%WT7|AXEE-tuXaKni+Vmv50MI%(PY+=>&#Xma&3W=@CrbK^9gRNDf{&71I*E) zbcdKlAtG@V=c6`Y?D<{6Gb@e0-x55_KhVFTirSK1{VS{0kTqLgw$Z|SHkDs;zi-07 z*_d(SNmSmV+NN?hdB1U7CaCR(01RtI9ZlkJD{l48$UKmwU4VVHmOi#V%FFqX->U<87{=`TT)A{mbkv_!e$j%yP?8+%8FD_wZX4i zMkb|3PboTRenU;m9YMd9d}#7M>3>+!a&*4m*5hi+`+(mWy)U_mCR##4MSXADu)=F{ zebN6~((4+?@3{n$*~N*o4zNmOv)1~`rCYzH$Yk})AHHUQP1Y|N7=`v_6*uKQvEZ-G z1g%wY^w9$9(9QAI@%u90p0~X)PA!e;NDRvx=a4zp5_qRJen0cqQD7;OHT3~y4RW`0h&}|`TJ1T>(H4}R! z^w4_{N*UkXVJrI>^3(0t;oK06@g)nzU>xEb&AE3r{!_Y2yoGtOKjiLUMp0(ROZ03; zOB+A3P4&=RRDz>Zt-oYlo-T_wXHa0fqnS9CLNt>l%cv{LwQy!xl1nC+$B?*d;8?(wgPdkISwaX06MpGn}zQ2Db1Oc{ZDD#JDVFv z)32)G7x_Ob)PJbS`?Q-t3?zf+C_4+r49AFDD+)r*w#7xz$i&;=K$d7UFPxsTzCH)% zn(=MhfNfGX#n#!=YPLB?P}w5$VPH^VJe;B?KH=cR9LxvJM~#O^xx}7Ldk^W}U7`&= zIUmeG@TGm`IVHG83#Ar{QqteFcqsZTqDc=nBVMAoXoL z(1U28lDOS)=XaqlPH7Q#g$W66$VD0&MHT<$iaI{0RCr(KY{@o_9qBnWy?2;!qg+|*$z^szqxX2WB^*^8iyiCu(d&2> zK-Q&p&5R1;6OpL2Gt?|s6SKsJ>5uWpM@u1#@JkLY(#8ob?KQP6wvpuaKZzDZ2o{_W zdDqlBl~!jWt?0M>D&fvuR4ha!L;ysBo7HmLeXdgMg`XpsL8e`!cZ~Ow;M%K}#8^H! zl#+KyQULjyS+wC28>Y`?>s@NYl=&^!eeC&%f&pS?N=m-dw?{uQwZ?4}OxAO6tLsr- zB+X_s8JHwmb#2+R{@$9c&CbZE7$b8Dbk>yQe*t6pO9=cWXvk>WQ1$5>t(&S^1yo_6 z%C}0dd_3;ii%P7OX9WW9skD|LhAQ)zXfHs97GWsWb@erEQJz@ueH&2oiWhSDQl#UM z6bLu976el(QC~xgu}w9oxW;LjkNHjb-PKp~EWA~jY(12oW1VVCS7277gi|E3vRaR* zb*p9aB^xXA0c@(ORcwQ5vy-80t~S36n+CfD*O0SG!y;`l;!GNxB0IE78@-jK4Vm~1 z^BQi5jTc*L+)v?DC~12e^8x>iI@WY8RYt0D-wE}*lPj#qELAbWP4GJ5f(K?Y=2l+6 zlGF@T(o>VAoh3M-~% z^JOIFe1$REGW!5fo=NLSlZE?XsZ_cgjtuMkqBi2rV2SyIpJ^2P#2#FrS6XHkjPhzj zam(KC`Lk)Eo8w`Qv$e(=xUHDA8n&w3_#t#c~+)rW6oBnz~?rJ=%ahBix?C#$# z)>M>WAQu8xy*=sGjC8zyx1I4?xxf8``#7YJBb#2RdU zgGk`~>{&={D&hAh`U=Cxq;eKaSKCqW?*t2!>-Z$3)PEG_bch}RfHN`nO9eibD}bSs z*mf_^Oe{y$SQ-xv=N1~Mgo`c_Z_!tcOl6{ekuVU5mAcs1|6P$-xj-GSM9}(0;r)ul z>KY9P&S6A=SOjO0J`)jEZokAMz71hA#Z_MGDZE-9E#ic{-{xhob)=|(+<(lE#qR3y zD;7U%n)KYo&-ofP4Z!iavie1N?5pzdS5d0-lJ;q#vI!@7K^l3CV7t=vtV>T^eL!Ai zzzd-@_Dcvg+Ak2=s#}HN=OB^2?@yIl?yFPn@`|CEAF02iC}ZLwt^q^U;eDc8zXNz| z7A?^#YV>2%Iu9+uJHpNYK0<$neoF<#!!^DU5PaCD53JF+yF#qnHl4p9lWSXXd9K?rtn1Mj+kF8&RhXa})h!uO1JVnL8o!>dPmu>5UDS#(G~% zui--`Dp{gi%%zy917f*kFDhgMhi!(Kek3ZJODLU8SAsxUm9QeqWC*1{0rA)~H6Rs@ zq{do90^%i}3=P$6Dz9rSbMK`%fp??#hAdc=;BuCtPrsS+YyI`TEWEE5)q@yuDZ9y) zjdk^Fg5%#i)r7$S`Q6TIdMm#KY3nRH&$LbH*_=T89L!zM0)sRrP7XEJHLPjB)a>vK(+*4CBD>8b^i!g9Qf&KWiN+$f<%{C{e-=aH z^E177Y%=~J&4YZdON+K#^3L8&S*B!faRL5^UyejxEjki;CC4Xb`gA=P?j$cMZ?VBc z#aX{(llL9l&x3S>cy3;qb0{8pWfJ{nrRS=i$X!;}CUOhsHdbhG{vbmMVI0n6aDoIB zSnK_z>C|#EV2g<0u72s%`fr$A|4&?f?s_W;ckR%FIuTd7PB6w^opUVS{Hmc*R)SB# zu|eBAty>+SrKI~>M$l$>-!Wt{ZQOgEz95C+!VvfrW!^;%J|$PLs%vQ2e6_Zc0ldL4 zXMkI|xzxd{i3fvS`dR6}fNkaCVuj@_Tl5u}0aa~`7F}Lz)#*mLcK+_X@snQGo@r zTYPMBSADi4E)I3TPV>2G=q5 ztTY$X*sBsVz-Fb%w2N>!BW;_Ies|)L2q z+&M%jrc1+Uk(U=AU0j(mMnieGLI(K~>Of=IY|_ZSd^Q`oo)h&;G9OSs&Es`VOBC{n z&|7Mz+}n8F@qiP6T27D!52l1t>I>r&9=k^maPT(mm!AIgjr5`mX}I z-=$~K7Rfm)y_P2%1%n6E2v-;e9vF?*HE0y1WZNkCvcU4zoMXDbboO*NI!vDITGg4r z-OVq>wM)YEUlq`4mFpQ=G76L;4S2mqL6i?hL0gi+C}bB{b2$A{Yf; zHZ2YOHJWf@H77bCuvu7A8r((^!-T$7&gQB@AVDj$xj9Ddcg z3e{;{BtI1)>8JVH-~k`}v$VlK)`uzDU{de2SQ7n<4Z`ttd7i<=x0aj@qNN7fP=b}Q zq0(7OQ!E`6h$@wkie}lPrr0XhYE3~C2#vZ1IEpMz>`?aLuLg_%gr9dQ;hH(?_1(;r ze3WmrXHd}52kj)75;@P_mKW(xf%3AzoPCv!7>kRuU|TVS^T`odu;yw<%Qg%4%W6?t zLr4}ZtUqCQeoOJ4txr-eYWSf-+Og3u6p5`LGiyi%F4jhxP#A&j1@(8V3u@Eow#MK= z?XC$P)bT>UW7&K4iyVb5Y}66g(HH&DS5_1@0NJn$aKIlUya!btty#jiuB>}AlY)q} zF}zRaHD-ON#e%?L!XBI{H`(^`hi5TsgV_Hpj=WkQrf}pXyvxea=LL(HuZ){iWD0l& zoHmSD=H8RvNXR+x!DI;E6$|<$hDM= zuV9RA22L#NUV$YN?)pbJLb@|E+$A5OXt3ih$olegbduPvpS+7bu&8u1(qICei#JRh zirvAlwJq!3R>&)Z*B8(im29qRIlQD$0nu0Ob*R0%ZE7ok_XhzSVw+>wj}sh5Oy_~3dcZ8x@5p94c50rgmCMO!a5f@c=NBAHrx!eYR-($gE$morm+OQdyf%crj5 z*!~0u5*V= zBj%WO-A$o5Lqdd%$W3~2iF6~H5}e7?zBaV@(BkqgQ)ZanR?g&s;zFqDpH@QDbIi-B zPYIfKqP{Y>l$k?wdZPYDnAG4g{gBCrwL;m%%H`=J+I=@a6hJtH z&!)wOOaJT8;@gP2bI{^RJ~>**J97@c_y|+&zY1SGi*kAnTKol{pasV5-Mw-!!!FBK zx|wk&^2I(GgYU4J0XJ4|OEj4!(XiBQ%yELq6$?&iY9^UN>57T_lVvHJ8QOqhPF4Bb z%mEB3)xpdVf4Z5W38^bhsG3+U1(H*zn=~_UU^JgujK{-b^Wru$d^e(gi{oRxQp4TR z<3f0KY6c1A3*d#TgpL!9%MIkE!9hyZVwM(hi;GQieXZ;=>~tUxzk*{s7ciGK<2W{UTE-SkBfd>mKsx0r$1o&i+J(x}z_~k)20v$LlBy4Ltec;=aXD z58q6JtPlj_DW@FJ4}a3dJ&_kJ zbEY*JJxUZC8jj&MXl)O2$be8{TPz+_BT-@($F-4fF01s{X}-I8*wVIz3(1?M`Lo&42+5w;iB)1KrbvtBVe|5>?eqdgS4Bot8E09MZg<2fCz1AUNSx zrDajq&-bODDGqWZS-#zc(dDf{157g)b7_cqLoE@v1{ujM8E zn4oJuarbkY|Kfk4ZNXkKUb7hAGHV)XPtSvhOtaH}4&RlRpBMW(vbu$IGjFy+k z6nb5w_7!n?(e#Qbb;}rGnUev1&cyWDfZ}Df5Y4HiPv0qUmPOR%hMnk!M^%C2H^_cs=nrzAv@evQS z2vVCkDMRl=QjZKKj%e0bzOy&*Vr9({f4?TH?R`66+k1wG^Jseyp!_rE|I2B6pT~~O z7d}wX>4G+aWA5w4YkO-|f!OU;tO3s2U%J-&cQQNR3K!c;e4AW1yE44LvcbJNme#*p zWqF48m6?O&wxz^s$DS`c?!|_=REeE#iX5S20aJE=VT?gKTvP zA>gZPG_}xH?8NHj=|8l2i>s>KNh0RMd^h(fysXhF0&kQhp(r6y&3QnUHhN!k39@}1 z)u{w=S>sTxNz`gs`k$I=+f0EhNVQK$fs})<+~lg(+_S0nqLk^gsFrYf!vD)sZH=j# z1*vwkR88^4*@nm8IAweCwEV~q{%cH2O}*G5_TU1Wxd5{~DP8+4X1SA7_O?eS6Hc?+ zS6SUGE32ml_UWEr)lCM#_(HeFfkps9;Ui+u5v zUL@6ZkhfVE#xp#eXHk2U&j#{;F&D;w)b~7%njyckZnoYOmIi+=J$ouXji-NV_(W~}Ea+Bwr`Auy$5w*E_*fk3 zRD8Cke`@#;6?!grz(<{Hq>$Nsm02Z3JW302n;A=+yeGUY8b2BNbhgQRA)CHzZ*iub zL6`#BwGJ{q__p*E2^kMX zt<~mm)^De$p0z9Wr0slAPA+QwKF8kF0oyL2oLuz!U3eoZ*);tfD)2qff-^h_*x;FY zOV(XYZvI2A^>^IiKTybhk8N6ozu=(z?zYmkxe#J=K@*?lYlouso3MVVx;^Hya_+Z4IP)J|N=J%*({VF4=^hn~t=#rfKYS=KCI1t$(~N>>v01dlBQ+}Hu@yzQ5)|R z$Ni@ptfb;!RZ<}ZP2T=VCBN*RDCYthM1{59^?n&eu?yN?WA5wN0F-a4Ub{i2bEEf* z*_Tb;Hml&Gc-EuLfi}~&Tzkw0G6zoSdb!{1M(gD5{!_$StMQ*?KQ(!m`%l_xUh9>) zr!BLdbOx{2NN=9hzg46`Ccs8Ngx+6)IISQvx;hI}cnppGnMDWp1P3 z0QxPsw(N`vx#udJ<7%ycvfQ?wlKlJlK4@kwK>2vXIGluv3bZF8vH^$LB&RY6DJ z%>Sk_<9o-*61X6Hh0>6X6XMrAnDsa`PiYvM7C09v@p?AFEN-J|oq4*HV;u5W@-9DT zH=+|C;X{g6q`m&m?VBKkm6>w?b*?IVeR4Zahyf!Lb@l7owI|!%JQ3eH_aty<{vlVE zol!YEEp)VbqONIGICT^xB-nwwvcvqA!w*0kIDWXaVU;<(PI0@N%frEW^*bmZ@A)nb zhxc`<{qVk&p6dGA2)y)Nc$Ox_vL1fc4q@Y|)HyoO_vW^4R!J_Nc!#Ovatk(daYGpg zqy5`FjDt6WyU*y`^*eLZ;%DXJi%?dVVT~B#)Me(0PJszvzqv!4n<4PF(RGP`IggkA zEpvu?qG)%|_W(QIqvRpohDp3jZ&E4!O{50(-VlxVe23ql>;6fpMqOX)vSg3SXejMR zcb7iIyZ#q{ldk$a*L|qt$*7aS_&gdwDzM zI8NZt>|e1?Lz`pxU~&ZE;Wxu9c5t))4x*LcOzWKO;$3(Bx_F0JTm9Me6bOy$GEcd# zY`)WRZoVJ9T|hT1aGM#iC$;LAZeCXwA`8!VhU0t-donWF}cR#0yevVSo^O4Sq`M-x-Eb|?r zPT4zpLJ$-^G`Hmme70Wbo05B4IXj-zhogLJCxCXh3T1wY`W*-K{to_c?-5ud}Q7aujT zv-NW?w|6EY@nmF=35dt~Bj`LDg@@~+@%Fcp0v$G9*8CXxhI98IJx15b$it;1;RMt~ zoPhiZe0uvwUJJxP}=&ytcKXp*H$QurkcX8h1zTjyt3UN zeF(;K#otFB9-7;*d7U(YzuPO)aA)8@RL=)G2KX@)x;+eUXH(0a1;@4~H*UG)GF-#f z+umT~w}(sp2)k^4>>)JkPVjfv6c7^x)sA!)Ybc8{SA!BXC^*btqIUzk6L5@U_9P=) zYa$unXt5|lW^*u1)3yNxh)ylRTtT<>!WsMuaA1+oW<&L=;e~o zf=+MywKQ~huWoAq5e_Ebg%QG}?=Rb?vCRx-9*?!}z9ihWm#1?z5>EXtUm-l?;F#VG zoFU*kdPWCM5AWM1+RQl$`TAZkch|!e+n=@W+^MshexKqmC`QCpU%)D)03I%w)dHN@ zS-exlgVx>-CG6^1|IpgPKcM&_2FY#|4kbEg@1l5G5%>KO<)H#>0Mb9k(!P)lcP_la zfJip)sWYx8s__ka1$+12oQOQ8>CpU`|IK1%#=d{;|+7xfa>?3C~7mG2@~qDK!whwE0B%y^GwGv4DRGu|U< zT4s10XU}+#t?*iiW%?m@)_^3a>jeSa>jeCn(-d5p79>5XS~NZ&3KPBGv4EM zGv4F;8Sn9i8SinyjQ4ocjQ6;3#(RAGjQ6-`#(R9{jQ6-?#(TVF#(P{k<2~Lw<2^2) z@gCnh<2|mJ@gD1EyvJ2D-sAgcyvK$a?{W2v_qb-pd;G;2@3C>ldt5u?J+7Pa9&exV z9`Bg(9zQhWJ>EIvJ$_`yd%SDLd;I83_1Gmx@>}F*CP(SsWJ-^HX&hM5zjCf-cH-@0 z^W(`bIgI-}K1TLApEP^%_Az=OX%1p`?#XHTWM&hdV)o3nRpDR8M5an@j{GX=g>ydZ zPtsn_Q6AZ4`(eA-v8apgZYL9szaNI@pA6Tw8MePib%>=WUUgS^|GMbjQsU=vr>~3b z%{-OaPO`r<&;ECIGlnUa*LHN5?U?MMO}3QUYp4_6zb3M`E;`yikC);7tD5&(!p>dn zlCuTXyweh>?$kc*ny$mPlR2DN({tFiAs*?D4#(qL*&0hWKVo||k2qKU!*i#)@*mWj z=pGIoh4-^39v!~>S=&q@llQ~3Z8L?PdhNW*mroJma)Kgl6nUMBBq}@Dh2Sg*FgKFu zefaL@tPSY0v%=aa>$d%J*Ug&Md1Yv1=atq-S$ELMIxa_y4Ci)rI^C{L`F2Cob+k^Y z{(~|!(s_wBQocPvX4UFTa-g0An^i0G$`nS2J(LTglUJrNIz(*+pt4C-7@fQ_h0!U$ z2z2tw6h?=zi3_5WSEevJ>~&oboxC!I(cx0mfRUOD^V+JFd1VTt!zsfHqLWvqFgj!d zydXMxWeTHHbrI;~l_`u4`>z*7C$CIlblBj%AUb(v3Zp~z-V2USUYWw^)LaBQd1VTt zbKOOtlUJrNI&7m~5S_d-h0(d;BGAbzQy85E7lBS*nZoGYbP?#}l_`wQ!izvBuS{Wd z-hL72#sMWB;crZ76UTm(9KWeTIialH$olUJrN zI=5Z~I(cOZqqF=X(8()P7#)(>Ul5(VGKJAuaS`a`l_`u4$BQl~3i8SnMrYMUpp#do zFgowQ2z2tw6h?>eo(rOrSEevJt1kkbyfTH+S#uHS^ z$;UJEX9_e_xb~iO|M!TF%0?T8AKt34t;o*LaY&5m^M6oZ4kEkfF+K-1KF{p7;o}z8;`X^M zPwCZO_bM6bB^p*Y%ugVL{hnL^sQfVQT`nke(dT&QJ^nl5lgjiDELb%_HyFxT`>Bfd zpJzaibk1#rpism{PZ84o=)~H$SG2?Nr-)!Ijo@j380(7fAO#(Fyi#wL>J?|crJ1LL zGkG^~ag~zKGS&}QWSoMK))Cb&-%#uyNg5mw%H^4g4LYQxLp)FWZ=TMLP{5|v)JJKV zD=n;V5>hvv1MFpmz|Qr1$65Wp-+yx;^E)}ou^H?ML|;=I9cgN*C_LjSovdGDH@WX_ z+EB{lTJJ}HYiK1Sk2G#zR)N-w?#xW0lcBd&6wwsPT|yxOcT6&cRy=# z$X(werb~3K(L7A)Z_@_u=>&@6saOVFV1lDJoU#)ufg=&@fL8aDsJ&&@Qu~`Xl=!z( zJpK(wMC(WL$9`mbv%qjm9KGsh46ARSx4d~nDfLC9R=<9aAk>Ks`;qB2n(6%62V8;l z?R-y{2^q!p2eh+ct&NN{wv3$f%vr$nk4lzI4OlKARiQ>8FJSp4^G9Axz_JbgqYS>p zE2{(|UYQ}iKYm0+DRb`4Ip)lKtTws_j*0zGotR_7v zVm{NH2efmxBuAoah0#LZ%k{}J_7uBT@glrGrGJt=_O-0LG5bO-;sc(Ih=S}tKI(?e zJf!QBcu3bLtY&zBk2T<$FW=sjec>7?w;L$ddI$Xm{BUZ#qj=vP1O`YlWe`+$tR+C& zT1>eHDs`(gKv3VZzqvM4A%bUG;frr$tz6bSd677A~liUQG_(?a22 z4^Np33dWoc3Xk~>WKkfta#|?d<2R6HBtj*pg~Cl!QBdULbWlh?Gi5Fi$T%$&_V^8C zQ6MgHS}1(NZy?J^3NxGz3O7teVbL^E_~%1Y<^n;0(?a17cONZy<{T@o>{Z;aB|zvW!G{+q6)4(^M1`tu`GL z{-JluTp;*tS|~i?H;_evSh8uM@GE`;Sw>Q5*mO|1dMXM;dQA(3?|p5`TtLa177Dxk z2C^t94r@9n{IcIbmXQdnnidLIPDP<{nkanx=_zwTK~K{`VW;0f76oFMriH=>{06d& zL`c%KM&a_QC@8{cIw%}_YRX(7U}#z>Z1)?;qCou5v{3jZzkw_xDV%3ID7(wwV?R54#33Th8TO{P=mz9ZXY;1}R^itc=TmD2?PSBj4stITJHilsmRV z&e(XJ-+On~`gMD&(JX;~SY<@AMDrt7MijGTALP;y!4i?( zRz~znG;g;uBA1`Wd7G$Z{v_HFvD}@i$+&3cCw1N?QYk`AeTh;DUHuL`A{6JH8QtVI z(J2vm+{%bdK|*O!$)#4{vH&Y{z{-e5iRNBwMQRO9E}X{_mv#^cd`ciRo+=ZU%vNe zi3BY<5>yE=BLP0V90`VbFaZu1Ea!V6F0dHUDOAv-B^XFF&ClNdM1p&6_sh&>&;8f=8i5UV<0nWwWfM~O{_O$kHjf4rMNIGxVlQOm5IA7cO?`NiFPHFe~G!S zyu#aQGtut1auv!g6q34$`ttPanE}*_ZJK}cW};DnaQ?C_*{M+)KsZ0wq@4Ns!Icd+Y_);Dhd-rh{ZV^smniB|4NzkFr9^zY+l`j*a7?Jm{{5qL#Z0 zi86_8N~kBW4yayHD`AB=f-U2ok?+Tvx9gX)T@;zzXy0(jxtg@(;cC(n0p^;ymS$)k z387{lSOgRXOTrO&qJ17xBe`VWo3>KXOii0l;&#vlIj zz}{A2!Jup-XAwd#&qIjcQGep8pW-^1;lWLd4X| z^APh!!Td8oOz8x6FC9t{7cunD=`#&LB!PyA-76r+^u+F+g~*|o=OIVclK&*+AobNW z$#F*^a_HrG$Z^@?|0LwNYTD#jSBM;Xc^-1Sf{OH?VzN}_lj9$GU@~FC7H=lZ+UY1x z3CD_$4HLnkh#^A^Gv3`lSi@s?kKV_dD$ZrPoL*!t|5QzvD+IbE1T)u02hsTkeoaqw zDi$RmK#1lN_%ST-;_u$}vrUNDrX@w~GV9H@TNps=U#}B8#Nj{gC0b&ZzZJQRBK;AI z%v4CGXAy87!I2f=RJHurIA`n2sv&MRALQTj0Nr8_AZ>^!<#Ko&W|Aq%#_HqTm_oeQ z3XwKX4kcFCbX)XMJmUKeQAoHoJKsz4&_bG3oofF+)skcd37Y2|m71`cgJdSw`sC=K zIX$Y0;7)7~ugY!m|9KaC6>v*8iT$X!Eli80&EAo1pTtpAoS93Hr4jGQRy`J_kKtB5 zn{FNLo-RQqpf{*1g)j3@xst*4c88FfkNFong1n|SL z_J>31_(mGeNECx+QqkMCU;KLu^U(EDrg=C>!5J~9$`*YJWOQAPqr(+F-o6dAx zB&tCec@(qLQ7_Lk9X||wR_CYaF$$(**K^!TN|3fMoh-NYuFct%=dW%+MtL_ka1+BRH@szF&^?T`hZp%XdGY2HBubs25`hW(A@~FB8#|=MpvVddtrSpPXZ~j)qhJm%8tPkE*)z zpO66t7??qWjTIr)(9#CG)L;t@ZUZGqS%zkS1Y8wpi-BlG-MTy`T&~ z73%X5oqcV&&HDW4Ru48{x_Q7w~?BtMNfa`b{G;H-jfG`S_eX09koYh z@Sk&sl zVIvC%ip7O5ELFw1htv+f)IaV%+)v&YZY6F_iJJFc$1xEW8fEK5qz9j&=sgLE9a9Ec zUoQh9euSYzY>hQtkYhz#p*N7|CWy>4QLu%D0dEQkYr~Klm379(Vge>#XpM)N5o=1V z@t_L8;Oi1*ZK}X-Ci$vwZjA?A7=vMc0YC+I^VL`VPkIA^aW#H+17jeYY$;>IrfQz| zFj$`CVj%gb-XIZ}A4pN)iysxCslFZQ*2gq((8?Eze*+ZjWm`qxw(2EYv2Doh$xIB1 z!2XqlVgIrfBXwGQt*lWmk?k9sYbi|GztQO4C9^q;ve(Lv0?Hf9n!`ShKC!Gjt?U6D zy%Sa6gmZ~nWT$HWFifuXODH-pZYV0-S^ZgQvUvppDxHRmLG;MZBQIlIarquC?pLzH zdbWa+;Ta>flI}AN&$_{%VE#J}&xV3Tr;Ff}C|0x6(>X**BJN@;If}196a_b}9hevf zAVf(uB7wavIzqRfaR>ICBv~WY^huJB!b%^N=>{XQYv)Y8Z7XJClIQO{D#O=?4!u0A z>=-s1C0f|9xdG_`#1`b#uFmnk)t=(+I#JkuSb$Er#l1MdhD3Nr_S+dbaYH> z@e->!=&KxxXI3aa+s_u#1}ULg?Eq#;ts16B+Oi`%ux~1P0RgLmdf5)Wq|FGH%3i7+ zhhEmoc6eG~$yS-^Zq*}Oan{u(Z#ldVb_?Xd3oTH_TpF8SBie{ww^3SPNfX|^hpMCn zQbW>Wr3G@^Wm>GXK<>5LL?gmOfK3|pi)w_ytgA-S0y#v>D=J|Ngt~n0tSzutDudn& zPYYz^Sz6#Nmr&q;-wDz?w7}oN_4v*$5K|Ucbm!0ldnl~FEs&9CX@MoAgn9nYw!j$t z*%@0P+gYgYK@4i7t=0ViA-$|kY+M@^WCOc2v;iK*lztFS{mog`a3yUhYsJ^zS}B+X zwZ++GZPuHHH_5=wJ(VS~nl|5>tK}1Ioo<`^E7lj5a|fN2!Ob~(Nw0jk%l`Njso=-B z+Hl?6G(l1XkfIU~lAi(zy=iQs>t$O`S+9nR)7%fXwMkoROa3}>54Pwf@&=Qa-l8%O zk_sS!>5(x*C-fk;o6m44#y)|}-9rgz4c%0nIG@>ZLLiBPz|a7KP?@qr-}oNX(F>)? zH_`x`E#E2wrP=ZUvyJP&&YZQDNc*MUDXE0Xl=luvB}}H&)sjjW-4Kov*vQF1q6{Wf zk?OncYF${$ZV+bD8Plu4+eJd5Vo?{C9T_DblX5AHjb*JH?jaY6(U@i_xMtI@#XBe? z$yRvyQSNv-@rKsW#mELpf^OAsqG+=X#%hKLnDP;{>qW9qFGHYF!$M+F-A3kF^G^-| zB2tybBT~U8qctXRw3c2dm)Gqmj8=&=wwoZnH5G1=sxYwaL}@BYSL{JMHrK93UiZCD z#(H|_Q z8-=I_#hNMe<-;I#`hA1r3hreaitWd@KCwh}ZXKoFsa zqvLU@z-3lW*b6tSd{Wo48Obr06%Zpu+?1>sgh;Q3>ln*=#h~?`!(iZAY?}D{4hG=5 zbbGY(9t<3{YA|guz{s-<25!Wz8&=2P(_8uugMmHRA@$CKfscAccMgLAeqfTi;&GCy zZ&03PFff^vFwg(l!N6_Uc9(H5kXYG`PU0p!(B@-zPV!abIuNMEq@qZ#+jW16*)bJg z&kv3BA6y(9l+%%7$_U%EmZ{cWtY+@!` zm+bmY#m)=Nwcz-T>sslHW1`9y+a-{`YFxib?*Yc~%vn^@>pB6yjIJs9I4ZPt8W(fO z*}mxkHiy=AOA!OZMHRt<7`iv6#_q&stlWzBjJvP`$QOEe*7*2=P~AsSluM%RPqx{_ zdZS4-0<#d!=5LcQI1pw9K+a(|n=Mgs8uf;ZV~PlUy$qS)jLwLy{z&@z&y z8d&jDrd7C`&OCHV61fc;$DKyjzT5?@_E@e?XlU*U4{JlAhfWf79YOIKp+@r>YCT@?KuCO6eQ)K&bsf^kD(ty}Ye(pdC;Y)>iX|}BJ!c6JRB$SDR8TJ`LsLk z(ii|*N%_ezK9k5TYW1iMo4gJFp@`t6Lva#h9ZM=Ri=vZ4@yjS4R0e>fleE&w2)C|d zv*16(qPGlldG`Yxw{lvEo=g&2r*Sh6b=TQ55AZ3|Cf_ntoZg8I94g|&q6s8$<$%r;Q9JE(1qr zYVkFkCyuyEz~EL-NubfEFHxhC-kA09j!vOdyWKOiliqV6)DkAkNdCCexec zs*4(kLa*0riqlz>)wk6{534h4LrtzPnuYtVaJ}ZDA99OOgLbg}%ybT+C|KoP? zy_p2T$g>FIGc1o4^>-Zjxq>Kh1@R+#HAD~-&RY;onFPVevk2moEbkvi5R+X&d>1!r zDM4Iu-h$YbNf3-Yiy*FGdH*niD0Ky~d7v$bkDs?78Z!xkk!KM^KFj+D5k&2&P2ky; z#RkTcmBo0QNMI5hL9_GJykMfS%!NuwG(~j+##KFk3h~ov6 z@_#}*=k$1WPWs2V@((t7iLb&KdmH$|hoez}P)1mcx;Vsmc8l6naU$CihQ} z>$1(7+&>{O`!%_LLSVLNa{q+D+^5O?69UtrZQ%VA0<%?<`zHiulXeg9pAeXX+6LY~ zAuyeq+&>{Oy_(!VAuw&4+&>{OJ2bg}LSWi8xqm`n9@OOi34z&(Q`N*tn!B}oc>jdJ z9Md-N{t1C;)a3pNfoan2;r$Z=b5z^F`zHkE0c}0+pAeYs+C98~LNDoBtQ+Go|G=#% zdJ!UUD~g`l+EePg|75A}N2f}CKlxj!?+0&}`W`)9>f4hl_5Ict^&QQM`u;E=>id{K z>YFk!>YFtv>RUKC>RTR&`feN&^?hw<)OY(Zzy+hen?^)^4~3$>-QlS3t&vgRn4G9@ z{-~&L-bGPg^n+1f{UuS~kxQe#5o4pij&V`nB_E0UhD?n5F8Bn(S4MsLg;C!XlcK(v zS4DkgpN#sJeJbj^b#l~q5dX^b&M4T#H6&J7W9Xe;fBFVb1zn! zR{|F6WCfIiY#auLjgekD{y8V5;kI_q079!}IJtvzk@8}l6DinPd0M24u+#Ikl6Ins z=E~j0NScBDKMD=3ue}3jBCZ~(t?3D4`LyOExON+JUhWGr)$Bh9LEs9Pns-3gdDZYJ zF;zXW=F7B5H|ia`@GIf(<6YZuEbEc>>_|6uC&>-RgTXeN2ws-0;ma~MY%I!|S@%AQ zjf%b#Cqq9k>CsA#;d&nI0WxqED=sicnLQ}pMEE$u?Fe_3n%mKQu(c>w(~(^riPiM@ zs)n?d93}cBK6%t5H<=v6MYvcfe7>aZxvHbF&cGi==j$cB65yCz?>ph2GF{u98>{K` z)f59U-Fe+-aOahEfDEGI70nO{?kJ~l!}H7~GvqmQeB#!_lcIW6+)$ocWL}T7NQ_P1`zqOr{WSSGy zN_t{7xqgtkJtI4~h1|4@w+>mr)tCiA)r3*6t#u6@SOFD?7hKRZ_hL@XI8*^Pp5j!5 zULPmC_+G3iO+_W2aI^REyVhKUlIYh|kXn61`w1*`wIhR67%reTWg&(RVj(Thg+^L- zeZw&nia5Khr}~!#xT3P0n$MwHa9jcxzi7rml%hAtQ?V&aV1mj@V_4g4kR?4X3AA1& zzW0^*L4r`uKsdrUAI0$1OBXKAk*v0sg|Rehx8xyhlBQ%%y$9U1aKt7@&pv z==D;1?4_~NH5_?akA#Qeb7PLQnonZ;ZCK0Mko=$iXmOe&uV%HBo@3;cHlG5lsYh~* z;51+qFW!+3V)WlbASC2O2^0xyDyAgISWuef=9@Du%guPA4S<(BSrjhNg-#!in8oTCpjkLIzvotPu*TKR+Onm3SSvP~u6G%jG$>FfOPbRj0}soKstX z?nV^k4y<&t60=KkG*z31)M;4|ep8eQA6Ig7YrM@aK7JG-{&U7KH*+A`z-a2D(mKIJ zY6Mw7f=25C22H6PsfwrVlT67Ll}7Q}ncX^pU@Oa9fRb=*>ZVlHNDHz#Pm?UkKe!;7 zag4MGunA5+Ws$+%j_uTJgU_N!PW8aVCRErvAgp>X998w@$anr6A%_xaMvhoHy1}R7 z=y52LsEwK1!jT;NHP@@c~v{EG&nC~Dvw^H*qhz4I-zyOXap;B=f z7&>X&IzcOo1n*j0qi@oRV+}bH)N^X(!mchXAfdme)1NKdZAVT6^fbL*t*k5g!^C>* z9hN3DRu{c2tyrD8)u3lM^pfgh(L&Y^iR~6O#$kwoiLc8x9q9xXWXv7N)aKG`SWXQp zj%_5iON=wCP1=koGZT_8>dI(tHfX)+2vv=0bDZxUf%I$?Ok5ZGkJ{bR*dbcnXZ{*{ zvfq6MnQ=}^Mk*W~$#|uSZA%SVL!Je z8GL8Yssg(uW9Y6zcwu7l@+Fkr$+G8LWeWz`pdhGJ0Sdbo>9q<_*tPgBDTB`fjMh#L zt+`Zh;2X527rlOv1AuvEJ6s+7M#nl`Som_&Z?L%$!owyP-#WF)g{-MmM1maI`664a zcJt}0`T#a0a1em4N-$aejas}3@yX(tq-Rx)#c(m(VA*Q9$nut?0tofdsji z(qIbEY7LDH#QD_Xdl?o)nsL2|luxZ;C*qy+4oOs+V;Hfe7_E%?iUexSz{K~YZUmL5 z!~!W%GnN8j)e@CO@q|m`Sgasnj3E?Nf!({fIZF}9c!D`GVuuy&EK1aofy5WkNMpNM zjBm|=WR7k~GPOXGrz6?vn1p)ax+qQ_ZR!oac-wJ-NK$LCs25-k?9jp+wi4EfX%M-A z`kZg`>!5LY1*CvEF*4wgBq>U^*04-3^);kkgen>-$)sNQ5jO6+M9uwhB~1Nv{@P z4T$6gijo4UQq5o-zDJ9vk|Y|67T?TBA-F)4Lo>Dr7)7l$Y(hA;n@``GujmTcl6yVD zoR|j5<;q=NDR+X2+*y#Qi7Jr*VjNU)QV_Q$F_5fRO{PFqpR|Pn5nfSq4Jt(%z0|bU zP)Ya;l#~iY-ddb-y1}PrY-d=MTWhFeSQ=wNobf`=21W{)W~^i6Za&Gbf|rJ`8Px=H zVhqUzcCAJtuWTd)lSaa_q>-pX3E(MC3gVFl2EcAvZ?@2=>QWSr72st{8HR%WBDC$u zrb}}ufNk=yRMfWS%gXZ7x@s<%GAU-F7^W>4-hwMq(U=3G!`w&=;5EQ>6% z1dNm=#$HtsikGsacwt`3QV{1sU83n^Dz(_#GdcZJtTT-JR>MUlIoOCkmV>BBPC+Cb zJDDB2YXc2o8I}h9T3HWwyY#Txm-Jv7S`-Oauf*iZvVby0wk$JRRasAL5At*|PgktT zFW*1z!mws7HoJ7WJps12`ZwM-N>@|)k}mEHK|`Ohu`9XHj_j7#7|4>Xt)v6!xltB{ z_Y{?o4mICLzrvY0=AF{Vl=LE=bsZrcn2VyWSU5&Aq(haddK&DI&8Y<)pa3lnK&lxo zsO<$ER%Exv*I1eq;s2=ZoCB|geSd99Z~4Ml&1lYA^Co7Rgk!+c{Z}*&%$c}-kzp~V z64)(C*t}yf0Li!dH=+uB$!8#1O#E<+Uo+YzDOWU{U@jW$L3Pn&hw2Man}r9k>y5xRamOoc{K?@tF7pOol5^Ofy`8`l{!o74@EknY_=| z1Jtgq2b^8G79i5E~VOn=%)0`aKme;GGLl>icdv z$o3YHSfW&1TCCbH4%x*l)3XF0GLq^^Yl<{H!w%s#btYL5R$F8b%v$io%DeR7Qa$X` zrFw#!l3JS9i~W%vp6N;pIWby$xvEfnmW}6Bu&JNv%8sE&>^X%tx~DaM6p_?t%z6>} zN>jFUkPO%E=96xzH7~1F+YPG;EN0b6#|Z~K`?Wroj?mpN5xpv1m5X^c@>u$&?3=J# zU=X9OfWQ(jYL?^zRbYLbRP!1Zm@wSBk+Z2F=Ppc)kqJ~oeXt7`VFDl(BQ*av3jB8$ zwcR#bnKKK&(!@Fu0fr02=}ot6xNwL5VTypSwEiFEkdJ*sk)8OZ9@^hQxi|PQt zeo5oAsDW^yyS9K7F`ifJamE+K8IO8FcS&hPRr{F-?-SliE4nheBCwM$FN*KAH4p`0 zi379fT+E`wm{Fs<;3vhNz#3X?Z=QlG5CU*!1fa&8Fq#rWdRboV(>}~p)&dqM3>YPy zXzdf^+KE9wn%IW+0iO~;a1vk?TMJfJhF82!pTK8u1q1vMX*D78l<{wRO{^_fJVI}? z1)XZ%N^B|#&g~wOA{7gb%@%2pvIVt%?!bk7={k`b+Z^wC3vKIerzVv(A1Bo#AW*7w zViX&eGC;Swfofm`5s6Z^AJIw(kF8WXCt=6wp&X8Eo7k5lNW>ab z|Nr0!*w4TbQcyDf{yB6bop0#b2mvM<$$y zu3ec~*A9qwi_P+?A$pSJLy8o9-;-6DBI3CyS@%OZPH;mtv+ zX6(YVHNF>5+A7Stn8)DzkyEv&P9t^=oC188-i3kWvzSOS!mel9$96_=_ALRiaK7p< z>2a2lEedaYTXrHwX}MKS556+e$VfwyFr0%I0`JQ;|LoXq#$8tP0hI`C=Wx$WPsSC= zYn;k#HV4I#l~HMp<{tq9LKtq<<6_vo6)A_EWrmmda*R!g%iX5 zr;l9!t?itJ9svGL`e8(d$_a;dX-|}yqL++Dhm|KzdwDO*bLQ53SJGu*w;&4Lb$0-k zQeM6YFK2?xeD!0(jB>V!_yv`6yjfmN%=(n`XtTl6w1xo7R5V$RP@|XqrX*nQA3K#( z4W~2XMyx5;OY$KXzQF1;tK|&k0R*bJv%NLB8bLUAk85-eS^=+h8}Lh4G&}m2fPeF z0}Xs?4Wk*BA~kW)>c$R;Q8Rpqcl?AW(MlZuXCpP;V7?-Og46JaqWprYKWzn4u=3f$ z^C>wMt(dP+luk@s2*c#r^47_#jL!ikBX-6}|0794ybKIjbmCuSG|~j}mFF|gSkVkg zE<&>7w-qKNe^CQjwV8k>@H zwTzL*E=f|N^a8}`WkMXFB4SZiNiL$2c@^Tf+=6LB z!sQAe!Y%F;FL-GnokgNAH4&>VK#kJcr_vz1iBbh+p3Me^o?kh^(i&=F9_1pcD2`N; zQ6Oa~M=C2=9I3m2i;h$Q5O|nf^4P$qCXQ)wq#kFa1x6*nxKF?&+|YqAPORc7j#L4* z9I3|$7Pn&>B$q2Od8H$jU?MR>idv}>2_QPDij#t9${C;|mCd=p)3ypk#>$Z@X(C@N zL=Ya1R7$%*v;u}5aaa(*Qp!j6VU`AG*`fgS=yCydJ>yd6P?$(IIjz= zLW!y%PUJ;xH7jv*4GS>#lQJpNCXO+h!0F-=w_%j4UY0ZB3PusPlgwCn8X1<=49pS) z4`X!k2^Sc`n0SH<8c03bz)D?8!lD%EFc_;@aE#FeP8TuQFl1D%Fu~z2Fv_CB)f=N}(27Y*)SDp)XC+ z)L=kl?Re8wf(W}lo(I`jYj?J*Ub*1~kF)Hy3`@ajzF%v7H`bX8|M}>G5+1XWJxe_U zFn7B~jyQG7fGEFDV1qWPfTzpJQ>qetKhxaWqEj2V&R%8-_3tRZjo9O=G>pKDHl;V)>!D3nt(uau~Q>8rOYNx z?ec-;_at`k2n$Y2u@rjjMH09_2-yS7jv-Sx zI}+SDazhy~soX`)#8d`MC8rAy6t#uE-@LIov7DH&hmWf%m~aIJB|bBR>;Y!yQbRV} z)F2O-RPLg-${d@%!lt4pLf>ynjCtQEI?7Wi?*m2k>NL&!AfxH;6Gf-!Tzg+?Z3i*E z4>GEF-zXaMK2h`xy=3o;jOvLggN$$>7hj`<**O2kGDV?;rCY8COP7lw54vwXp-0NP zLyuq?lMUpN2*PDOb_01EQ{MN7v4@C>jrCnnar^s5#TD;?iZ`S`d_T}rB)EY`C~(vWej@slu%DxCP431>Sj7OoB#4+n8zbnI zgMhbC17G6?oL)CSiwhCl?fmX3hi>fisKM55jQN7t#mlST&r_?6R->DX;+Y$jX-pG6`#42Hi$1aXNH{54Z_1-98xg-RYvoSPez zXhcFdB_R3O1SH^ORH7jrJRw10)=NeVa0~PXAy#FuDx+SBUkKAAJyFEU6%KWSh@1)~ zQCh=;#H}jZu27*?sRO+@N<{U56A{H30yQK}GdAJrI7vlBl76T|i*F#D!Do?Ffi0p2 zi4wFBkpioi3ezRY)*&2!5QdfZV2ObFL_r0!ol!*8KstDOf;sAxP$?oqi1nh?>Xg0- zVVa~X5j6;CoQN>*7Od9prygBN2?vniBd0PMqF7};oDlO}DVnMwby0(rMNuSoQWWi9 zbBUEvwF`AGht{wfB_=P{;}4PrFAi*%WK@F`W?_=+U=0Dau`nuok1oKNmGFib5=v2E ze^+Z=+-c%c4dMZkCLvV-5Sv{|#(qF4RGvx>TD*=?l7Q{Sc7v73bgi7AH!vUUKwR=G zb#ydNrD+0#Caz!%;;}#ypM*CAhs=0$6597+w(mzrO8eedlA?jlXwTN()EeIoENFnV zYVc9BQX2TgrggIKtImgKjj{0A;>QMIE>S54k_XY*WS4YrH2Ah*7EmyNP4#R1C_XE> z0o?%Bhq1H%I+v7)b9Ae_s4Tn|SB`XBwTLY`*!&3$x=?p-!Jb1s(!?cBaLbZgHx@}* zTgitKA$pk7_rJ$F@d<-oVGW0UO1fdq(~8Vl`?=PV9;PD&8w|yXA{z{Ic{(eYUDksw zYDFd8SbtR8{H)2mb-pn91m@?w__h}Zn>35fS6D+|cpGf}9<$yaM(Np2*TF(by7r9q5 z*y^tp{$B1627saxmJ`Xzj)2jT=x258SAdpF(c~RM(B`c7^B7u>r9ZZuq?9ot7jAh} z0okoZQ3XL}@`zh#S}t_n014PT3_+V!NttDIrD6pV)2o8|j9Pzz|J&K93Hoz-;lyHs z?2y7Mk8|`UcXPQ|WYM=`N3Xq1frHatW5JLC3U>khAe0vzBFQJk>ya9_{X^JAIj&Nk ztL0fO&vo*wljjC`*2{B~JU7d8i#+d>=T><>AkPQoxk{cZX(&R^y5p6}`}WSfX2(+_1+F>^{NUbNPJVikym7KVRT8 zyIA&B58Pbt)2~{J_|!AkY9+^GJ*lc-sw$8gbv@#)P2RL3U^W5r+SrY~7I^9zz@@I* zik!%UOdSS}y&AX@ANlmF7ARb$W(?W1l4Gf=3Ki1LN7QLGeI$C z9mmWc0lEc+UBkj!gn6Jd=K|(L`z1{$+OM5;Lkno%MA|0-NC=9ASAQBly8={hB#IwS-r`v8)#J7Ub7&G;JC_hSxn|--=+x4r1rb zKX&7BA2o6x4%mjXFbpUAC~eqB!J{gw3m+z6yRorg>DFhyh`c}*t2vGXL8+>oR8?3B z)GP)kEi1wmZ7kwefE6}DbWn6fF2lHQ?q{&#I3Fe-9ZVUu5_QIk z>B3vQsV0DW_#w);mh^U!-WH4=3!m3+=v}rgmqJ|S*KRoe>n*6q`Q-~!qvk-*i&`o# zF4|WWD12+CR&_iXt}u}&HHylgd=8P@HUk;}LsyJ7XAya_NTSejOwg`kV#Vfh^L-WT z@GxJb7F-Me=Lan5HnJB>@Jb@>s$NiOW4olHnwi?6-sS_6sdXT6p{Mjsx#4(KU_Qtz z1$k30y${iq7gzAd{1piR`l0hz449u9#kg%0iaxv=qR_HZSMe=%6=jsVib68CzxXBw z)WQ3E@G|AnPCTnVRhk;r26%eZ1Nsmx(oq^U9|zmlLW6IF$F@VD3!k^(2Lrwm@KY`& z3sr+sqgLU~;&2-go8JfFEsc?X#ihs^5g$Jf=VCR<{5nEk3;7hf+qO-7@!h|PV*Cb5HJ3q_v8#ihEC&U_ zieIjc0&_hvnqws;fRt3#5Eit7(S=Pd<|mPo_&%J_sd3{Gml`)wo|EJ`6;E}Jz^FPV@mVm@j+$D=Cl53B$a z!~J}Y^6`0T@0anss)x_3yYXCJKPnFi%j<{d$j_x+5;?F_e#V*dbH#D|+;{iDT!82$ zzWamn>%TvYU!x>&|7gC)J1|gd9k>XfS@^$=iT4Nb);iFK=McZIsdb=VQmwuH*wT(H z+j_Vf6F-JvYE%VU%>AVRT9IY`kjk`zEfkRzb7brP1_WbQ6Tnv$08A}mDu^4}g)}JH zEGYbemeja8BF|EJF2b`S3d^u8h3^cb4bR9AYb*1^2L1{<(2V7*!6!<33x89p-Dsw& z(DC+Kx{2Y9QPQ>Se&%bzddD&iXA@BBk|m3;!{8`t+iTa{Rn*)T^;NK=Ghc&}U_Ijo z(6bCQNZp`M*P+R@%vB$Ytqx~bcSLY4<_lqk>UHu{cjJWzT{tUj_SA1_))j;!c z$fmG~y;(&yxKJX2E~Um*2-fn(Ww2C_^RZCxDcW~yNFR(AJ|NW=YxNhMzU7T2i$P|2 z<4QvDaYm@rxYfXD>mGj<&5?lBFtgYwai7MtsoBj|bNmZVD6%aspE4_#7u@aPwGz%h zhv!*Sv-gJ{nU*uZJoL!Tg9;BXG-d>H<8R$|iCz=bX9bH+!jZEmko|1Y-)rfMB70DgPOYIvQI`a&pb;^#ZMd`3QUq_^OVzh1+lNz|SHoO23G1|d7Ca7jc(g_3 zIG7r@4)RTnt5fxcVzWtAmap)wa`U$!5oQ*}4=?9GbEib)EN($v+f{+ZD$&;1jXg3B zn7{DXb6+X`)vtKVY*B0F@OVq*kP~h9vsERRmK(TtA~kA1nucE0TUgbT8Z{p6qp&MA zD$n}ei?qTn2n%qHge&PTEa@ujDmqa$`0>vJb8=Yx&8orrK3p*=)-3Dz3OprMXI9y*Jzol7Hd0KLX*_d zpS@aLeg)p~8sr(1QNAxR#=ueGRsiLmi2Bn@RM65c0a#%;k zTm8(wZt5qluNnSGqw+6<=@Lv1tg#?} z>O6>j5yT#QGNlbJ`c2h8=~q?bwH5PR)aWy@o&i-OFj~sqMhR-4^(Pl&4C=lSc|{b& z<)uc|p@g?)C3qYhor72~-(fKm#m!{V0IDDtfDXHr@MBlJ-u(IPM`@Q!go0Efj; zxT`U<@CJ=ogrE7)g{Al{(;pOa%k`c4*W-PmzAJwj!9D%Wa9E`WJB@$4lBF8{4IB3TT9h5=*p)g`Lxvn*23Otq-L)yGLm3kpS$|5`Fbfj&T~nwgUy)J7^S+rz*CiQpSs`2k9y zN^yt2GBZNLJ?0S>apZgQ#-R z_h3XAU4ec8SLkC{G6}-tReGq^gGwhasHjAt`jfEGuv&?~Aq`>(&x87+-7^kcg-el- z+K+ro88s(=BCpi_38Am1RZC_YpYs_vr;6TyY5P6XVUQ+;kv9*f4Nn-ap_P}t1H^D# zEikH`1q}FHDMzRIsZpIyc~##}7GYb-r``d{$KmIjA?TEmuR_FJ*D6`s4AqeNp`@(3Iytg zuSRRC`lliCTR~NL^m@c73qe6wbd17uYY_(FF`NSdanRNjRCja*;V^?$9m_t@6tqcP zjJqBjs$il0S>^g0t%JhAUOA-P3<%wRC_Dyuq<6hbZ>%$KzL(?)7Rk?R*XIY{8n^{z zW>rlT6&@mQqA8D7E1D-O<*4W)%@3$zHe8=S2{m2}D>4Z>0WM&w$FLvCQP97lxWU;Z zwptd0evJ6Qta0(4618S9>p{CP40&XJzQIH z7e?{<@jU#P*HMAk^;s5InK@HF{BA|#V+kBLL4f8J9%z^gJNhC|^oQMOuKC%xKk7!C zp6JnTG!LuU&{FxT$j3a<<6UU^n6*XVMQ(Jx2l^v!bd@KX7u#9vEcQg>!fQMF8c#Gf z>)X*2J<;^VC?vHfb5Ky|?jIp0RHxxtd-8wL`K*mpUTV}{iiu^cXJqJ`BM}vPcvI=! z6n#T6e#{Q;Ed4z0-~UmM8j`ZZt0(vWtA!jb7%7 z#!9)3JK~9c#D(T6kd0)&8$H$&y~B+Tc%mP5qu=1RREwR*-00^#(Z6z|TRhRb+~@~A z(YxK~22XUe8@CQo#W8(r#&KHx@A@kBrAMqlQMe%g&5=7~P+Mt5@^$zuKq zCz@u5Bko-=X{vTNX;I%NHb#9P#NV&*w@t@gnE1U7e~%;W0sI>H8;1BL_|3-Oj}iYg z{>l;8iQf^hYrd=j1G4=CM-Cb}a-@IcpuzsYNdMp=cp1vSp(Fjn@H=v3P@e8%up3Md z4F{Gp{~J2OgJ_@yXaC|gG;(D4Ou3Qf{u}NF`-g^M{B#+3q)f=a@R^;RmF@XAV1S;= zsaG)H#4lw>Ii4`0zF*?~ZRD#%coo8b#NPpg%klR=`1?=%y@K>c{QVApr;t7#aU=0p zfbg~W`wYSd@%vT$cHnP1!j%2@@GJC;88aqp03Q68J;tvBd=4BmI51@Bu;B19BgTZn zBQLlxXVgU>$h~;Xm=9huX7rd#tsxVJCaF=m7#XzAq@DJ)4%&gf&mN5*JlLA`0NzvM zMgxRd8XNKIcDEeAjBIwsTNuB1hcDx;A@Ca-2KyC(D`kuqR^twgE$ktM`Qx>(r&4&pW!#!l8T!6&BM^q9BY~zAnOX-jg8vjGrYwG}EY()$^8?Fks|Lw{(ejW1 zCDVN>9eLLEOUK;tb7UQZG^SUEIgiE*kyU2H(WdZO+#EbOUmO|>LyxQ(5PGEbQFc`Y z`y2oJzy9lEClc7z@I-TBZ1xk&^@~D}G%qh`d$b9|mF3xoLXSLQS#w0!yU6R#rMsph|o%|6vQHlB>0NHm`soPA1v&UqWyoE)p~f%`H0#q2$y zN6P&L?RxWBaHGRU`D~dmp7&?8HgDrAsXI2r4<&bUM~ET%Q*!$Q;5NHtrY{S z)h9+~vT3;>Fc&7(^X;f_2mbcp?-l$V#UIO?uV0@ZE`yT>_jpz2=PlH$^Yh|O)r;e= zRWFS{U%e>)R`r6l{&?z^xhs74u7D5MeCsmU$o={rI0|y~-`tzcfmRO0KlQ>rSQl+q zsjuoS_pb0|@2@DH9`arIYFX6$H4?I0mt6P^oPRAR+T*X)3^?(J`15!^AAf7@@M@HC z>);bF#-8z=c)>18KWkB6JyTH&kYHgd=(*&ts4!hhMSofB_SaF5s~r<=tGfpK`rxZy zp182Na_K_zUpcktg2JK`&s&iyN3WfSit*tUE`&v>)7sAv7TtDkR^_nNg8ckOzJGIY zIif~Gao9Z|S1u|e1sw~^t^cMd8aQu1L z@3*NMmC@MWXw0bzYb$5O{&u=5s9r*KBcTlXM18eC{uUs(q`t25G8D`g0Us4ReL56> z8VM>Q6hDA)8jdFsAvgdE%#tru_lSUD!-FcSDp>SpRiNnYP#rJ51aXK*U|m&^B{TjT zcr`20=$Do(zCrw)*IkRb{=#xI1RykKz+FrTB&Rh68!V6kjKo>( zL%^87;Dt;6vShJV;lDx4bs`0+r(H;b)BVvu8^8*T{;d8L|3bYeF7hQml~=}aYo{&j zaj}#~*bf6hpU9yCt9FP;wjOb5K=%j`(?lY~X4O^|DygyxMGdz^H;`zSnZ-RKGcIl9 z=)c273Qyml;agY!>mV&wr6erTCPGZgGB5#BPm3q*j3<)91KB4Cf8moiVD@9j_LB&p z9f2U5zr0j`!@R$WV>C4!wQL`Oob;HatKnj%^e;)e8qW1emkR{pAr$*HlUC1%O%`Z7 z3*lN_96On+yf$|7bmam)OnpA==<{b|r(AvhWbD*wN4Y;bUti?M79!u$-(R}I7u8Rh zGthr$w_bSUI&IJrtUjo*9K}-VmqoJxp6o?Ni))a6-Y^!7Vy&b0>i5 z!5Frc22+RiYXaKLiTdY*+T2O{!mw68xpmNS^o@W&W)FJfNVcTNiiBr|#r!j;u0mRx zW}Yt^TYLwF9*?q|8ByjLpO>EZfF_+Dk21U$dfo$?bb36M{a)yK4`>{EV5S2w)(i5n zK#61QtNfT&2Wn5lysfLe1E!lVGTvAT6Yjh$(TD1{ctPiSL8o~^CjtAFu)g{{f5B6i z>{&f%?FI1zw~jdRY^=?9qTTvI`FYxOzcy6g1N)rY0`&7}*Zq0`Ry?4Ld=Tc{PxGEj z^Pa|h2&usx`ACjRxW(I(ei8Fvc zod!fch6)~IT6X2YM*7(a4Zx9UfR+T`UHj`Zqx$6$(rGWLId#LpyK7H<@Rz*<{_|Gs zKKTFl@Y(4l7wtIA*aR&od?!gDxUK&8; zVQ-ltl^-Ntge^^L-n>5zRnX+E0((x&J%Qb-0<;^uJhJS;az6H-+u|&@qzQKisKMuh zWbkQ7`Pg`|Z_M!!9v&kV%&ahqZg&dW+} zt)@Fx8>278*QEk@EygQ0=dnT)U%`OgBO(ar%}m0<-a1T(JpTDG2I%<<%?U8lP)GXw zFv^yJ4QKILt%GK$5!O`snK}VK9Kah(IDmg%pF2VSI%`};?iez`ZXkJxJ{aS8{dcJS z&&o*tUt}adpCfr0R_1tQ%85mv(L4ORiK&TMpv7j1zg3l9*Om*6)jhg zd&fuTJ?!gaR{t62QTlc}kaxk&^X&bNndd_%R}`BIkk|IA1hL}}wxX!3@*~DIdtrpl zAEC7yGpDxt)WFiqj*pV37r~Vr>)nx0XR$F2l}pF|Qedgr`aj~>_j9{YKoDVhMJf?n zY>3Oe0Snl6cCP1KzQ>)<*?Vlc7c-;2Jcu$f>q~_w%J`-7Gqn^y|4{n!<{KV;=}&7W zeerZu=Qix@qc0HLFCPXo9)0n$B~}JshF_Sqc4I8`XZGGeIYLMZS3^% z>Pzf=^yNX6ky&4MD6wvrpQ&5$^ADvjZ({eDqc8nw&7?1$f#$oiFF)J&?)7Ca@}5~= zJ`83&`r>8BN6DX?zI40>eKEcIB8Z?bQi;$P;xeDamLx}C-1&ssFc9Ft#QZRiw#(cj zbNVOYAwOICOm3PvOa5|tJtZCe;eWgO8tbffwlLP^uLCL82&yiB6JFTu;)e3==o3q^ zN;hX7P8)1NJpY+jVl0WC+U}5Nl$yuEjKioEKzYxfZ+ROsmiID-tt`(n=qRr;b9uvB zoc{jY_^ZfR-nXpsEQ5gZ{F%!uI^XhUWh`&HRi33#C~x!NjPktMTiy(({;+%6s=OKb zi!g|ujL|tpbJ!~|v7!-r$huTpRXCWEozE~t3#2YDf-}Dq0f4`Uh@gDhEyOSv%v-^4IJj&qM+-H8$nS`8c{z=EY z`Inz}{>rrc-*)oHI;Ua`i?M4ERV)Xi5Tv+Lu(IxXzmwJM@!8wz*mKB z`CP5V5^rn}=3*zon;amDLTtJ7u-|z+DrGd*I2Y+%p+{y0p)hj!iGFaohD(jwrpHbV zs2Pe0I!-G#LqV6vddA*1bVU~5`DL8tTGn!XW_WpVH1tT*8FLPXsX)%4o%4js*|-u4 zzC3$oj$~d9a-CvpPu+pnn&Bw9f(d3FvOLC5H7_sPbK7tbprXI3FoCV>%`dR}2kCSD zdO2JQ3rnN(%-5k&@YXGj?acwmXt)UTqF^`=3bz0fSTGL`BD5BB=AYmRf`P=8bE;R{ zF<;}yuqyL&WB-irmDaA21^cQ%Y=27DcIknv@I4gum6~4yCHhRB^$6=D;M6E;s~)+Q zt6u)1=353AHYs>%c>pP&XMXEdWPtEddAZo~jhZsC2?ovJ(E-?XAmC_koO`!&-@({h z2JOgNf;nHg{;Bv|cMLRUW+ic~jXP}DVd?(&`aW!M8d|ik(ywFshJ2$fulqtjgKhIP0hIm~zwe`u3$Srz=ITMWoO->U&=?}dAv{^ShvUpg6qF_#OTay}DI4w$4|I>63x2MV*3 zARPB;^?#GcUv0k#8@Eke{~ZOildD#Bd+EHQfdF|SLH z!hW+rHqPj7#)yc95*kU*%mp}oRds=heSGS^C?uI5LQZj#6D~DwFZ!3%xc%}xD9;Ia zE-as4NVU!x)>M;o4O;`8`p?DMc?N|pdLGvqZKvhBX>6Oh!mGhRe7^$wSW`di7BIu;;6~k=}J;85$CIt>m6~CHv4VBZ>fbd*GJAMS#66 zYc9Snw(s**gHJqnqCNJU@4CfHaM6QOKx7F}!o&9C8LS$DcmIi(kUamyOHzCQsB^MO zNZ`av*+;HJ63)DXQrkjgxRB-$9<&JGkL@@-xJcH6hZ2XL7s3yK@Hd6Ki zAv|mm9<&Hw%rdR!a&Z1a5pUQQVbB#J7r29p8r(+#0k}!INJ5QNT>>UuB0&yF+*5e? z^LNZm&KCi@bfyb*b!e4l!ZW9;I<)iK~fkb z)EDfA*mOu^TRK$6t1Z2VKlg@FC^lJ?-=v!=zKkxU;73O$-3HR*n_oL7Gqt; z4*QZ5tW*`>uHv8b;bbf;dk>+j8lSyBKbLmS3P&jRo{LWXLiXCzF zi;Y(_Jz08IeWIG@P|cxwVnnD+RP%tSxscUIllrJQ_2(j`KR<0da;gOzVNZ>v0`;^Y zpzmqHRW*%ImHEs9nrK{2vph7u*}9GPvmTCfU?m*i_7;`Mlc3 zI-ZYfa?C4$Lfzkhwc5g_`EnyoH*S2Gf8Qc~Kdy?%^Ob)0zJDz^R5>>K-NL5O4{+I* zc7us4#c_A7SaL++w&{|d>rTibfxmKuc|Ft!`Zy3p!V%tt6Y}Q0h`OI@kFLZpHlN1p zIN3LVrC4JdUB{{rwo@W4A1 z>XD;~f4ib9rC2_u&u#}f*D=pB=J}eH$B6h7fdkzsBhr<~JA|4N>bv#XT>zgz@GS)Y zj9mmSeMqcs>jUQ}++MpNv5oeq+s36Mwk*bqjTu%5n#@R5MGxWFh<(7yhSx;XgzQrO$2z7k~R7f0ZH- zZLR}mwW0?IwuxYmSYWnzpkEz{io-VAx3ceN;43a5jyY-vPKNY zx|M!ZKtC{o#BCQ+()wk1)i*B16P*1A!FLh-rveUrV!9We`Sp#A1^f!an}n~i;rrrW zDe#O1{HF<@^BCYG3SN)X;0q@_j~n|TUr*y3Cit=V=}!U^^^JrC%0KS_%2`Bt>Pk70B<{h1NjsWKWywZpz)%uMZ^xfVl<4S zp7>dAII_hCzR!&`#=8aCJ)}~XNdVF}@+dKc_LZNryM;CF!OLR2G@8Exhd2M#k)VMa z?^I{~4*F`@*Ncf{^e!NoAV@s5w$-LnX&6TUhB48l)5vkdb`=}O98YAOMM^x3NKq4> zHIDs|uO3ZNj8fG4#sHq+ZT-(c)&`Q*@P@;iUEhgn3orVN#8OXqh7}e=Y3adaV%keg z|3XaA&%~B5!CnYVuaaaAVY&$Ok@V8o-}SQ>cEcCd8=axZ-~1HlChZ2g_O3MI!GK#o z9{t|T3`?2e$9*$wqu5JV3|cW7l*gLKM@=7U%o_Mu?d{w6S+K5!bv z{Ef^%zF&T)JxlR6wq;ME&3+pfXtW9wJ}ikz*b-x!-d;~!Q-2Ly|3+N= zXGAJ(vd>BIp29(}Q#is-;RxG>lPL?oBE(|q$bW&59VFzH*DOMW8ro+sbD8vq6=T;e z!>b%&)Hd@FhF6AGoh@T={w5T6d!ORae?I8sF$^wh+2S}qx!6R2VTWjhGbtp6;t<`H zMsx(P+Z`IxM7H%O;9(1Sc&O7OG8&bHrGgT+^~r0~mND-^;oqB=B9}Z%UFs8=^5-+Z zuNh^3DntI-#5$K`lJidJp56|0Q;E(@dRP$+06n#db}zo##IE$$t?93I-q&*Pdwp>Bm6TLsUKR z>063!{Rlo@gy&R2ZGuav&TH(9y_enKyfu9%i<+?qMH#9n;V%W?TzmhyH&ST`b;f*FzV9#L5Xw_g#wi{MWwaM&jct<$ke ztFYj8!soXD{(BC*rF}-ESm8G!`TYx;$Bavv@kT47RUa9P$tQF@p+A)l&H0=wopZ6J zUh1FxA<(uHZHH;=g<-TgwQm@%Vi<<26-K1mX3b&N+iWf2e2wTQ>;?K-2R-Czbuylc z$RM99nYV&@OWeE^(HZDCW8dNB_YV&M=}sc;`m@ciUgA$|xU|psY9|3Z2-xZXI`xx* z+B(7qe*^gM^n*8MVT70(w+Qp8bPv*cj@$K(#cBXK4Jc%!OvltD;wvV;Yt927G3gtp zDtvF;PkdqJ+BuGw#!BKl@rup3!;jz6PG^`X?b)(I|HYi!nRB5d08!rw{wV}v)( z4sUhDvk4#G2lyLoczbe`5&s7XKZEdB*zoqiM##20+&6y!uvG*bq`)k0z5Tn_Y_$;n zKEglqr*r|qKb28FRzVw?v5gtOt1>!fB|}CStmZtAEwJr#36bQq0?DF2r3=08*v-pg zn3;;1>2hx-Px-DOT?{0_tH9H(dfu}Q*y@Pw>Emev=sRC_=3DShVkYf)ARFIyrp+qF zZ~G=2|K^OTtYLhkK6@v$d@jpuVwqoX%fvSeJ@a$3pWC8CpM4B@FJRtI<{jteWhFap z%!o94MU6Qq%Y1Gt@-5hpe6Rgc_(YEaFu3T|V8;^2Lj+q#uzd>5qd#fzR;L~#{DXx5 zb{}|G4W#lcukn1sw-bJOA9y{!01epV@8B!^9gFaz_<@UinY_3zno_*$8|UB&7EgR1 zxPu3Pdnj=0apv^k<16sdIpW}}kQWyp%hWd#EAajJ`@mOBe2=}1=n@m3m^>ae=TCVZ zYv}>2N+Di4zP?V_t%SV`uoN2Pn+RO|wl#n4RQ}fm1UpEun=CL_z9n6W3VeTsJ-wr; z3|qaaswPY9LE;HK0X$=EJXoPfjF<+tcK_&plQfaU+jOXCb8JN%N{1Y|Db zv?L7oy`u)Z_0%!zYG(b8C#&#;{E7DYcK>40y@2o!5dNlq@V0#4{8R?{Uc!w2-y-A3 zt&C26v}A%$ei!h|2!Fc6st+6gzh{E~72)?1{wWLI(_ha~`eH;T+JUegxX%t8wF6e; zGa~D(7=!CDc6g2_toldgtqB9fhH3Y}@FosBo}aq4!#SStvA5m$2Rz{op72Ufcmlv} zJakvt;ZhIGE>C=qC%)Sg-{gr`4bxqFnu;`i<77P1I2PaM>5`*(XgSWKY=V3Gc`DQ#^@P3ZJlaF&3=hnBPuQ!%$31j<)s`3M*)&h`$gR>7AN1gy z>WTL@HNPjm*Fzh>&2HoOHigZecz%D{hPmDo?`^XAp7?qXe5Z#tZcTI(K z3G0vcu&K4-iKh1E7Ee=q1uu=O4xy=?eBRsC#6BCwncCGdi<8JKJ21fxICjrAZch7g z+l*@p3~LG?&Cec{!13&{A>M}JGG-Xwit#FqSD;=cIFk+ZHY%@u^EP0w(s&!5x3awo z;cevJ3iBEQuj0CvMO9cQDpTKR;)x2I{vA(+U4@s%;v=ZASos7U&hhAw9&@*2)~!`zsLlCWncKO z5x$G?wHe_H`r!X(!jC=*_-H2hmvI+-8a*QjKa21m$^?I9U-%aq0AES?H`+7s`^As; z!T&SDZzX(lCiq*%_kmwS_=AMMCnNkv`oPa6d=KHjkO_YMhx@>fA$_%Dot!fc1nE8c=N$KdT{&qq^DD23{}^G*%a#%AXO^d~te%mk zvUwdU*GZ~vzAyc?(S4Qaucc56?xCRD!Qf3tZ9zNwbT;i7pXeP<>b%GX6WI(R`yh~c z<|~#ed+N)sgiP&&?#;ya1UvaXQ~R*x;H4nG2^4H61zV2vVduR4m1kEfu0$kG2JH&6 z`60piPA#}|UB+MU#HUr3m;T?}4f-cO3;Np+_ox5-{L5#jpZ?^;ly^ygta-J?i7tQYs za2gpLJM_2xfKa*51L~KAa{oDO+xt)+6i0WPD#=LS8&Ztvf#ae6JW$4({Ax$TbmG6B z_{-AqJN}J7;!I>ef738#+r?~StZW%KbU3a_$9tK+F+};l)cAa>C8PLJjL$uOGrq!a z=8nkWhwJeU;lZ25v~kQ6?+xd8VBEZ7&DQTn9)06pJR$DFdhk_x41CS}U7EO|-!_3I z>x4SBQFYyEhc&ogk>WUJ*LfYYkqs7ik$O9@$qsC`16!;B^>cl-RM~1gLDqdb$Z8~6 zKYz+1%kk|hn`|lQtpq$yz;D=qmdZHwdEvMW^;yJxGyZ^lbFF;nWD>JJ_!s359G$qD zL1{RaD{TmKtY(hUl0zjzYq@{3b0ZSln3#Ifq1R0GTx=t;$lXi0Uc&v}hO;$14c~o) zTkrzles05&zV@m1Hbkp`t0dey!hO?*bMV>zw+r(#@z0DM%sAJ|=*a7jmuG+H}0s{FBi{zTces3HbOCuTFqjTV+$OQK5?g*HS* zV!R60?pw$1<%9N{^yoqRZ3oj%FS2XiqU4DUpk#6fDEY&0MMFIHOj!l7XP#YR!u|RM z(kx0%lh_(AGkrF9~Vb}Xj5Yj|KLN*~zwX0gQmaUEuu#re%|7To^02qEE5a;w{4{f}W6p@miI3`*nk9(E zcTc6=TYw`G<+$$s%=I91ec&wR?NWBlZ6Shhr#^cJT2P4~SL+k+bmn6=I$6GO(_(uo{M|R;oJbD024KewrB;F+)UU=tHfw{BInAXG-_3Q>se;4pHx`%aiE^IO{KPZE1H9sdaLFhiv#g~B7SneY7a)EbY^?gx^?3| zPY*Z4(Nud3pd8I!7;l(eiX}nMHeMqQ=TZ-h7v5Wz2dA?!*50hDL|ZL=>T1=ezF6mJ zDTndWxayDK^G~hb>V|$=18HZW+v#zgs_+aa?9NzJ={|k-7HGh2#J!iewRGHUVwv>G zLUOM7FCzZjly@5xzzIwax9W zzVfv@{WXkxU7TqL zI_-cRBRXL<*e|lIbu6pOElcUcQkAd&ej%sp(DC(9b6VemJM8lM6&!J5Y#6WQ{CzD* z@x204UfqlN@_XCw%d%&5@F|E~q<3KVp;S5^KxNjd5VwZG;XU8?$g` zjYZyG2hR4BvoJVQ3M#T2sOS<{Yw7n8VY>-?yv2r9^|8{fj~R9#-wxP%&ieQT5Tq%B zL#!kHGc)9^k84QDsy~C0e+4DyyT2)2Nk&^lIThfL;7HIGTm~sSggY=!E*p;!epH{` z20M4xS`eORg79s791*6|Qx6ad$;RxhfzLDh_00Z7H#__#@7mvhN*QgH_y3oFYY1}J z8ZZz@kpE^6|5I&k$+H7~6%bXt6PeP~#+Ixjqlg_N!ZP*Q$06&>Sk@|*b(LF|($|c| zTxbGgLI5TI5vS#zZ=%+$q9|IJJ)4f8EhSGPahXq>X8oYE=!c$ZO;@e>D)}fY68|NKuh9=vDfLk4TC+tMS$UMYBnOP zY^rA1f$?_0uL77Ci~B?QuendGv$na1>_2znO|EhD*A{F7T9ue^0SI+_Z>P>}aH%y* zaejIycnH4+9-4OBigP}DVyD_P=h=a?5#LMVFFh;qf5Fnpxf0)X2Z-NJ;i#)%zf)jb)irQqznQpu~MQtrq3}~&M?7SFQdp> z>FZ!^{4Tp*EcL?py4t4BA$*1%(_e`?JcM^BB@#zL!~Y85P?_9*1F zl6EINWsUnun(-?k%`g@@qff(_>Ivt0!d!TR>0=7Iev{$NQ;(LERhxRId zwMj$Bl-&f*-d=C40#g&;08^_Q)1^&&n(rAG4Djr9xg=i~H(eiow=;w+Y!fq#amu@5Pl6Ll4Dp^CONJ z&M@9zYV+e%VxAr2w}>g}TZw3!2O+1#vt8+xXkt}A(LFG&b=dSd73Vc#zq}QMuKOzp z-T$ydsMCK3Jhtjwbn{)0=QGq7?PucT|6}ic;H$3c|M9DVEyA1$Nried(5VB5qAfz5 z!Vrz=MW<4NGT2~~vCaKaEYyiC*Di0P!X!moiA6<)$@EsFGYP3Em!U0P$)`x~+h(pr zU5fa7KF{CR``!(~)Zgd(eSCRvc3L@E z5oUO(!b0;dSYZkJ?bxm+}~ubmny0+TKzs*-}T-y#ys!-z!X~YRo&J?|*s+(0A$^FYdFxkJm!q zmDD%=<99*da|Y6P%$|MMcP#ZC^)mD=%+~kq@z1;eq1zOW_o`l}YOcih>Yr^jG$mEL z;~r&7ci%{|WPSLwI|8;gd2TzVPnQyXGtp}_I_95vi*cf9(q(H>K-4~>PBEy)pSY-P zw~;Wdv`guBkH}vVVb{U~^|D8J;Op3h3+fcLUZ5}X)WH}B>scR9nBo=>{DsV3J}Bv&nQqHuunCI( zSTSI6uOovUWbiXGaQVA1lT5w;L*$}Yfqb))hV>1*-~I7{@IOubcH&=V@Pm@|vND+U zlaCW`8}Uvxc&aiedu$8yUd4h3s#_et+8eMQwF0{1Qza-S=Hjn_QkAcP!An1o#SMFG z3)BD6^gHkyp_do~|2l9Fm$2@%{}kN^L#$<;`1}Ip7VUi za6Zp_1J94jdd_>kda($WYUcAdzHjmw;lGW~yZQX-tmovvp3e(n7vcUd_uP$`@uJ!b zKeGj4R=qw?f^rhvYzRbuu+BJ2@%r#SM`-p8&mv(v2`{pew1;QZhjqzw*Fv$wh`x>J z$3)RlezvVGP9@Scc(d6o->yoYyAqUtS_sP60if*t9!-MX?6446+Ab;mmgGhv8P{P@QP%!ZwqwJ`b@s*2YTc7S&KfM43sXGt` zx$L{zL7lyn|MT%yK0d=d_UrA+|M@)r9y~wFJ`b95!cnKbfc9{+?P`tR1@_EW5MaFO zvdV>BgBcV$SgEnB0P$p7KK`QczEL3#Hhcw<)KW^mdtIaj37W=)t52bP(~js2nJtq` z6%RBL?Ay;Hj}7Ee=6M87Bf?pV-p;;NyJ8&eqf&%qAmO%{cn0A^|h0DMQE0;zE8rbBz(XSlK<9k@_YqOB#kjOnsAYTXB$|t zGW#ZT$*PsC8l(=ce|*oL=cDHvd41yvBubO$bSod{ZTgpRZUUJ(VM&p_Kh8`-|1%#H zqlbcGxS~+)|NXX^g5~Kq+ljQ4NY8#d!yd#Rm5INW_&vnGe<1wyeHr{4i9h)u;NO&q z9~9??{o#wS_iE#H*#lQm)uT6^&2|16$P38i6=~+UiXPy~ThFGW#uRT$@q)s1IN=Jo`PG%{eHjqPuKCv3zDd^Z&{xc!$ep#E%CopW7}I6&sWJU$GrFvL1H`#-MSStR0XmqI8 z=$KoIJM^wf{tBr<>V1>l@y{Nxq+PiqXRf zvku}WC(17N{KKVSGyl~;$FRb8_xe2CHGP;PVN0Jm#zB7?^{0$wWl8pwZC@<*T06C^5sG0HF!oNIr*-H z?C8=jDcdrW4K+2=*oiRhExsvxr$_1I@1DCYwZ^!GIppZG7%U%~!s zz&4V9JBZKT87q0K_CK7eZ=mYOL-nAfGu(=em%zT-5|pg9zS0$P3r8fhnxaxB$5?nd zs@c|AU{`kt*gbVSEaCTePQsFKWEOEJG1n0D9%AZ$9{*byHAV1ih`*KiH+cM@czD?V z7ho3msr`BVmRKM5=P{md43Bu6>(IqRaHK!HQlSCN5AP$WwBDs}M*kpr56=bfv7Wc` z7w~T#od3_ad;W)d{ugKR|M4Z@pCJEV-sbXZ`FH<$Q2pl!{`V*}rT@zWrT!O?|0?pY z$l&km(*SP|PY!qgK`qqd#l{?2n8qxxT@1EeWcvZbmh-jg-?Q@*bDC~D(S{!iv}eB_ z$(>#=8|CofBV1owOZ;l$-=B@&cVoIT{AG_eNqTxX%;nWg$rg~hoz&N4QnP;Be3+L~ zhhtk$y|mrb7oLC23wHU&Wbh;8wVk}iX=v~dM ztNHKPjP>V@M4CvXM--CrbzS~L66sflJGQ&^`sy-L%q7JwQ3^F*#s~T$HKUZ+D~P=? zicNcrvDMcY#?8#dskP-6XOjWMskP|QH;Yi>NZKu}X_EIBU*%+30#mc3y>e?g7Ew}# zhao?=-kRx8JO`f>wv18d*!_|Llc$C?OqTUx5;--JQ;Fsjl;moClTCeOG+8kc@B1=& zYB<(0GAoh)x)6*~WHcnAQYOFNk5jQMevdO*Db}m6?D{78?IypCUz1r>`zu4jyNR#g z*SgJ-8lPQ2(t;5ny(U7cyvqA8l^7!O8V?hWlUYL?l|((|`r_^j@VuYT z4{^`A{*BK&J3KC{Y$x8Vk-&TQ7MU4ng!LHAzrvA6Vk@8oJHZo;M#>hZ`M8DTD@eXB zlN|JD@N&b)kFZ+_#t3DkNs*>8LgVzJ{*#F`^+P~9-y*s7p}+kjV||DX)B8!VmIS;U zL)B0Fy#vj7y?$@&Z!>|{MZA|+MKkQ=(=MBcHv4d(J!;X^_YiQ%h5IYHJnW(j0ei0i z{tDom`cKM!Qr==IRq>*I=?q&xhV`|k?yzgEEr*TzrK=gF${z))%PkexpH@3O$l*!z zF~nOzyiZs>&7JLq@fp`lXbrb(%I8o|Q=O!I{i`bD4qv005`CCxy+nILqgnQRZ+iOz$z3Sk=V3B!fN5ca7#Ba6jYpF4ys_()$_j zBWXKHM=R0+#>*-rM$(h#0ew5spZ~J)hq&Qy9SP%WH8Rs3DNj!B&=}Dd5Lc2@?nlAt zF3m|>B*VWgz86bCwT4s&WysUaO?$bGXuF8^^h(n#_)BEqkdGb#ZP+f4Hf7AtrZ7w~ zS-Qt^@+lk*KDSyv)<39UEAiPmj0&%{U_n@K!Rg^b3(gH^TX0D@Q-e2b;R&*EijAqa z#7?oXPCh%<#&~8h{IHGnG4_7M*!aAMsY+=x{d{x=l~Gbu~W-r-16?;!OAOU?dj2)6P2W~LwhyX+rK!|;z!gJk%TAlY-Xt=~(mzt6Tn z_Ck#tlWtC=w}J=fbUnrg{Q1bOHpQ)nxapp$GFtyl`fSE!RAwcWxzZ>@|990+md(jT z-9*%B9#xrCv}blotq3>j9_7_@LD)yagEgVYH@C3ymQ#0#MCrF|j2g?u@fTK3frER0 z_xog*e-zj~5NP}9eHWW?u?Ix|E(-79{R9MOgf$iI@#s0oTPO4O*A?FXU3swMe)PlE(arwb?VwR_U2}Q*W-{1C2H*4y zf~I)58f5I(R`S<yx#F!oji9HSbSRX%hh9u)5)(e4t_Hwzf?Hgkr_`Kp~!~l zZN&GItej*Y0oefUKi}4S50GqiGL`nx>7Z*T-CvV3|5^P(Q!j5Mcz6^`7U1YGMUeH? z4i1@|2)}7DD#Nd7(A-GSYGdl;^yh4B1DmI6#;9Q#)Ug`&>M{2?Y8d|*G%Ru&y7EaD zZx-FuW^_|qXQnTEZfZ>rhX}X=AeiyHiL%^m%qoLFDRF(N^dtVmPF@kNw;NPOgb)CELkl zdpp^BeO0rxT@OR&6RDC&R|(m)H^+&UAF|cV3`ZvteHGEq&OlfAg~TsjA-lG13O;o)@13z{~EMe4UFETnv8-t~HVGlbMjNPT#en*OZU+4Oh` z>uj)h{|M*LrY(3FyMU>+WbnjIBD1PKnES5h|3&t%=+Jvm50a!CG6r;a8oHo(Z6f_g z9MF3>zzMx{fE$2KFK(K=StKbW$s&^Y{;8!1K9)$|u4wIU&;VtqKHz5zD-Nn8TM9w1 z%0%BI!YJ+$nT4O3>0-rIpzH7Y+43=CcrR_=F_qfk-@o?nHv$bl2~by>Jcv%Vjlo}- zYVH)_To)pe>Z1`Bd?9M@Xf@om2gK@wCU_r2z`01a>6=7)xk#VxVYh|tfXHps@@7>* zrCzukNQ#s$wUXNAJLySr(`z!Q6xvF;%ilcRZ7bWYd2Qv%piH(E;xDZH>Y21MyptXD z^N6Iexi^IR$b%HGEouox1^U_u#KQ_y9pG-W}mcwrm86 za=l#iX*b@@C@!Sx(#G@m*90xA@g$MHzn}FZsDyZH-*y300h_+m*)a$POP92g=Lo^G zNAT_@TByePv+E0ZzHJn75ufgl*(koQ-^I|m7471F>Y^L|pTjMX<`U575 zhJV+m(D3IRkB0xf*V~4lgH8P7`o)rt-I%{%S;tND`?$&Y&_9rj;Zo;}@IDJxhdSC%*69zYS&Eds; zj_UzdDXdpM3Y+0AW1;AFDmqGO0dPimum!8b4{A^=I@CmzqIpWu?OM@~Dn++zMK3cE zrD&OnVkPzM^ zzpm0P(sv0s*Ehh{X@g*2Ozg`TuZDXjfn+X)N@b*yQhAxFcb2~`svKEVui(-Xl$fcy z)^qDl&G1}NPO|)bnGI5l1Nl{keKGMnVb*tor_9$o%ik7Tt}M0}0%2Lysr~gdufAm; zm+YT@+u0XM_77&T_Z}!8NY9L>?@L{hIn>SZ?I*ic%w;R!^T{@j`Y=8z!vi-lEkz`? z`b2c03$Mx;0R-aWQ@fz2uV5V|x|10W))Hl zKXw4eqeF(qIDTu~{k)2(YfTn1BGvdq0n|uSjb|Ec&h7Y^@736hWbN<#JO&whf9J;* ztP8)RL9@T}bsJOrJ4qYsq>k4z_Rj6^u&h@y`y(MIXzB?MHors7@9WqgVERku_j&XC zcl>G#ZPurc?>P|`N}U7?ZLXIV665n;Vn?1N|4@0J0E*Vky+d@4q2Q#5m|h=PGm6%N)PmTDirW& z0mlTq6aHvzuvNh81x%l{IE@0{-@CKY-p2nYm&0C)=v{auz2JK%zzh0MffxL|MtQ;8 zRjs6uVhWjYDum3^LUdEC{szJSx_Tp3Z#y2U@1W{;EH?HjGLD>ekoE0oe@vTq7{yNi z1jHVr#X5@x|G%~^$}~pD+T);O7j;}#?HiB)=llA9q?U&g>BT^?d){V%@JUh)DFoFF zMMeCS#Xl_@|9!+SB>rfJUuf|U&c^=}CQ+$s;`c71R(`*hoA5n&Y8C3$oAB#M&`yG% zksv5Z*z%odfm{o0w?O8`XLRx)_khYV1~gRi+na&hOOiWWa-XO`Opp7;+?&f#mgive z!RbQo48cbZ`{mx&2!SK_zj}l$v7cq{fYHO}JRo5s5PvbKyyRF8pK<1c?|`3+NUCTO ztUKolQ-56F=nP$8%{syYWIxeTUw<8E)?)+0n5^ro+L{;Ch%p6=8IAvB}z_ul3XB>p0`f$l-?#k z!0NqO7krnRH*M4Nrpv~Pf}e>k*T7i6ms`^VxV~_4caR`bA7qW+mpUN* zOx6ME2eOXIx*`2l`jhlIS%18bYU?gljmHw*czopJ!ny||lIlJk){QT)KJ-qMFDLKG zHkLBVclFUigCruUS!Y0lJ1b22mSmTjbt_j=k+Sgl^;c*~2MlBZ4eEp2(Ap*2w&E{z z-1RY`vp_S`$Nq`Cjdr)g0m}YoZPQ1-+R0`r+1v{@ZoI+yd*wRx z=lgOW260UD&WSo}Liqh&%+1{vh}FT}E$fwWo;)~?Lv}zU3x7sIrqawp-+Y?|tY?_} z9KVvv*r)m-(MOyK^oJZe=68PKB`7fqGC|1GS2g_omNbLZ4Ue+jo8XkAyx;sL%VAJ|#9^WWN4ex+$4-JRi4+bOlpEcb%d0-ELD+SPQ{HQ(m}GE1MhLGzv3 zK*C*@D?*b4_5Nco)mRbk;BN=kCEo}i2bfeRP7~=zKniXx9BL%eKT$ERq21%rzpcOu;} zD-8wew=>KmeQ|pteS{Z%mN{-1eiW=)$!hmy6iRvh{~-P5uuuK=glYUHiN( zc)cory(qUH2TC{SN@*Nmy*}#sVUVlEcg`M$lh;)8I?Af0)~D~p2}GW6m}ROpUt4Jm z51=YdeK%}b!5aPIbIf$#P%bQo$2`MM2&>qvT!x6z9X_h^U?!=nJ_5Pzl>41It|V>w zObu6q^+4++ec_%v2GndJb#a<~MryVKuXVhMW>l12ip%T`TS~Ep79MK&v@%joJ}M7p zUfcCyS(ixv7C78ow*wfI=O#W=d{*ffuv*Edk$i3^pQN}% z%pDNKMhmKd)-SpdF4Fxr@l=5<5aeM5H(-#7a@SNyRO&992&T!l0{n&J`~ib?w}rC> zkyLCta`2~1g(XaR?w?wAsv^V>o?$z|i6Ac(nfHbmAP} z>1{}!yB>!4_2FWq_;W;3o5-Z=v(^xU(VObnCh4yweIMyp3i`MyclV-?yB$MTsWVBN ze-3C%9j$Xp0pK{}9#}}93GU#rt?;;KQQaa3YvnXUPD>iCNinEoN-ihQr)Q;4LxXod4Wqf3D8{d8!VY{67kpRrX} zM%>M)I?aAOcfo>=I>f^xnV*gX!NW*I3rAmX`qM~A7;!En^v&Uu}tiP;St5UPy8Q0x9t|dVK zvjp^}RX6WPP9f|I1Getw*C4DT8~_E9T#yjNYpHUroy)`$$+yb z(})JLT)R~IEcpdQo&Ak?kZjw4zsUaeknY-)da6?RX{ge2iLFY}{3s4~Cw2V>yV6uP z-g5p%*z>1!;RE>f zb4zrGKTr?4!n^sa+B5T}+?5p2PXWs#0`}>9CmoyNQa5fH5uQi3CYB!-iP+TeBoUh( zj$y1t(RDV47ylW(y^0Ox_6feA`YTpBow6P&;lw}pS&VIrk6~O%x?xK%6aMf&mf=u- z@g)lkZbnCPU{$ z`i)#Yj@Pk&MPh$bF<*H)xIz{_x`WNB0ylf`Cj`y)vZ_&tT&hlN>wk9K6s+@!k@e&{ zpY8@(!3v)^7;=Q6U=m4}d?dUt_-~G*E7e5kicuB*q7k|F5YZUdA(Gm99xA|%7l<0h z`Nxu{ZDrZ554}t!?k?h9B5~PZ`r4*ym)-v&LHv9W9Fsv1;C<-y!p*LOF%tgz0T9d} z!AmoRHso*S{`O+vNHdRjPJCgwF{f+2#8YjK4aywrwK-}aQ}s<;lP;qI>!?6uL;+4D zEB|8cVU8G2B=UA5pB+J_Juq)81U~5s9G&S6b{`D7oCN3&v2+8z|Mq8R9((@<2`7^9 ziA2Oake3r~1-`2qkyb8Ax=PaBY3QieYT)DZ;dn2-Yi9a{@5uE8vzT}x>DG{LL8iQp zepoNOh%D5Xu@mXDfy^_lV^Fb7&FUZ=7D&C^ntUJ^$K^t*?f!hvC|K(9>r>^|tIO|) z!=dD;nNaef^PN$!lZU59ji6eXQ)p?a%8lJ~wVl;+R2&y*5)QKMr1KSm3`->9K z*0mQL*n)BI<7A9?!5w2HmxeDfnHY`Xa|*=f^7UY7SEY=MPgBMY%DBwP;A{7@o@D** z4ios*Ds9p?D2yihhzo&!qE(6YGmm%!yyu#W^yu>0Q}3gx$l#wS2-?WyhcE6wjeP)K zfVAU)Lze3SyIzNTg!=;#<9vmTmXp!lhLJHi^;xah=MWnq9Q-xc~f*%+BU;hx+Xa zyUlMGel;Jn*0Y9u@-70OA6Y)6UuW>!&F^YQXZ*IDbmgSG+R__#49w>UUeXj=vq%XxYL$RMML87W^jFH(3+uo4^ImVc*72%9r9;O3UE6 z7(`9SUknrqDYKa}c{zsaf2S*^-C+@#s&X|)DTfnxBXN(C`i)Zf%fnpt+Y{!f-_2o+ zza6uw=Sz<>%WJ~t@tbVn)F_dDdZ^MfpgOwgR>GEX6)M?QguhVl>p)74x&$KELt*_s zS^ptC)Qa`i%J8?pu&t=6X;s9ZLHwl}pT}&Pv?P_4UHS^0Gl{o^c%=%@`$tzeT`8Li zi>Rz38m{k*7*3)QvzUKN1U-cAc7FZ0AwVo5;>%}89Uy2Kg^Y#8UC+ZboPUN-Zl_7O zE|AcRnKRQ1@6=-$KgP%&OZf47IY@2SM~*_DWtgtRmbv%~TVm*mJqcv9ljh>br2!E_YX$NW%P_> z8*_?0UGpBOI`=bBb;UGVn(N7}MCE$&wRo7Zo?MM*ZfxlQoqMx|aST~*B+E}Kmew`Y zuj;*X!;0UrzePtrG5j1s9?>oh520X!)!`7O!;qoN)pU5lFW8}(E$Br05*y_=0u$-! zHp-cCBK=7l-KnC-+bGxE6X}oI=m<DM1Jf;c@+q#yVRqdcWuj(Ax6 z81&<5@Mgq}n=ra28cju`+oRF`Xmo_1_mWjXG&&<1t&B#ON2Bf0=%#42+eew9eni7N zf3FOF!D-6?9vS*BS#4SY~v|ZrPZw$WQ^`B}}+(xolJW3XC#LO>z z^f&ZMfD^-=1e-R}E3fIIkpNbQH3W+{8n5hnP&vy+bua=qZriB#${*XP_R70#RD0zr z8`WOfVx!tCud-3?l?!cDdu87J$}2Y-ul&=aEVhkNuS8UOC8E+R5tUwvsPsxirB@;< zy%JIBm555OL{xeuqS7l7m0pRc^h#t%d1VeW)P$Jw%2$79vM0R~l)@{ES0vKE-?N9k zHo+|({Fw&rU5Bp0@^ebpj#@x>qU>Vb>SHOmxK-=35lL;B4R8PKnS39@tVbk^Q(}Oa z!T@nocm`C*c3kHhV+-OJ#&jdOL2u+7KrX%HG6GzD6B%@;RGU!nEPrdqEwz&Ip zD#EUW2CH9#_U0OvjRIaGU>@}|I2}w6zd|`0yvc)0J$NO-K=K$E)&}IOTFJKA_={fV zu-As|`&ffP8nwE!O0IvY+$JgX?@trNnfHhvQd!M@kQr{`MNEc9H7k)1xNh zedKwMz#bg`|Aty({EuHvZpOiDNnUU{$nVb}NB`a(u5zCi`CTq)Z(1cf<2U~V1@F>#wy&b_*2@B5vsljJ=rZd~L6H=t^^oq`2AmM}jz{u;V%1a12fbf~l`ku)ziWyM(_NP&e(Y#}LD(C$$-77rxSI}LYG zZg?YhAOa~$Cs$`B&!sUgVsZx;U&C`1IEvsI1YOq6SKxFFwtHNf>xUGgwTL$0fsr(+ zNl*ah#$u88%!R>RX$a(`bcw;zwL&dhQKclhPOiyJ-aD5w_76Qb6I~1a4>ocly6j!( zuQSm#mwPjl_s(T`Cc5UbI5TlQfbw#twFU+wynlrw1E%3B!(m#5lOYrM;rJEHe(|_syn}@7Cm!xtx@n81M@P> zqHxtOVPk@`!Y^8|F1${I=0({$8&faJ&a<&j47I~j#!7Hl)(_5A)Q{U$)DP)Z)Q|R6 zl*3!6VdNszre5=+Y%jKobYIu6Kj@o6?~|Hd&i4Nks{ME4F)Unc!b7{xXYgBzzm)j5 z6W_n&<=@onH9Dv%eXoA4XeP<9CWez)By;~V4*eSJj}v<*u}_U)bNwa4-K?g(_#*Ig zD}aAc27XXdq_r7fpyJv%x0c~n2O@{i#R7p`7Z~jQCD&lLY(qPX6O`ZMbVIq|CL|== zQuqrOJRM4_krj{jO<)eTG6z#nmG*J{u^)Oz_IPYR(6UO&Dxs{%j*!cw(dGn=0Ry`( zARnMHl02!OnU8;cSMlazj>YzrSX5IAwEbIoOk`76%JS6OB6Xm`TP^qtBjkhF%@dA7 zB-OqE7CGq@Z;^rQG0=if%NS^xNS~&3b~do(n{1h_9{2o9Ydgc`DH)UsIPPGv6lS_v zt$$>Js~YT_{+AnH9_f4%mm=05tQ6PMyJ{b>!0xR{bHSl>H|8+6yvuUcjS z9j6s^PV63&yPi}m!*WVyYNj1Cx?5BOvvzwhdFn`bz*IYW83uB$!DaC~|7%=DvoE9tgPa@DT5Ig!3sJyWOp66tUINO;?s*3DQalWp{8*d{LZJB<3R zqkhL^>1X=kY(>4l$re+#;Lhu!b{ekq$kBSNex7#1{FkkC5|LEi70~0(0&OS0uRE%d zFLvN_XaOE`=VOPhW;-pAwm_u!>eky;r;zJXa-D9ty6zF*C(Q}hH5mTm-WvbM;e@F! z@=u=_EnSo^`1jWv{=Ws{ThPCW{KqT;|JH2&eticoDpVT*&MrOHF3x1uQflyE3^alQ zmQcX4nF0cwRvWbmR!>`Sug@z2}+EOCj-_AyY3%y*Lv^hYuHyX_m!!bM^6OD@F zVq_)GiZQx2iY!+f@w6}cbhuxdCapLM#_06u)0NR^XEfRqjdDFvWN?I7$p+_%(P+X& z-6WjJW|wm9ww`YG+N7?^VfFNR<+ zgA5MJV8HdB!VWG=XYOz3ggdx95j3p}{|LaVjD@8wNYDaS=~Mq-p@4P@xEmdaubwz> z(J7WKJJE0FgsqxyPk24~Vxj43$IdJ;O(DA;vb#9S4(m&m;dDio2#eHjVOXes<6!}R zeSOM4w{Qp$jA6{y!jtHuQUx^-^!y1*Z!F2sq5qyDs~NgzgY0)WJ35K=Ah9~sY-OVY zS2Fdx1e=zG-^4GDJ&EjZL-xDEFCrag-5542#O`nj5mj-m)}KL`O070ft4p+2-k<}W zXDB2?&A`kL-a`gGWbmO32E0E#hw`$Hbqopn)VjY?#B4PF>{;;1tp%Uo9j}X(-y6=k zm;RD@ULhykKzbe+{|*2@cELjR*N~tUG=~)Ck#RX0HyOqzi(GH4B=!K`9Y~PBW@8$@ zkCM%5vKepnYnmK#|AOD0kMq~vA8M}48IB^d-_v{JKF82x_}97)bbtb zcXQayU*#4?y|tv(>ZMYH^YdO|f zT3akST5UEBPGmra7SIfrMKRm8OgA!S@p==x?>`lLl%RMN?P%jd+DV11t+)WFF%4FaL{k_&m{m0_X(IoPn*77q{9te zIxC39S?Xaorwdq27C|zR%%xDNj8w8&@ZqG?@*F^D5Xq?|^l(xrhH4Jx;bqtiN$LaV z7b>unsnZFvJ}#S#C?=lx3y1r_UxmXRfJmyY0cA2`tSl4ZLUtM=3OA6B=SyFDV5Bvn zZzbDC;Vb3%lpjOs80gn=LcZl?fB3+)*-7Ii=1kPFkzZ3dPxl$jgr_^8OOXkUIr_p|C{m{l(gGQ>KzrADLE&^ z4YmUQFPy(64nBDQ8UBa)e+R2V_>1*ug~c~Za5&HjGbrBxO3+eG?CmFVaG}62lCWbr zQ?FCtT!IY>%qLjsQ|I{93w-L?K6SEBo#0cC@u?qGppurWK&AXpfINus`u91y@zzTQ z)IeKxaF_}k%ew{DmRU$ta~*vrIiq`mV4XwdQmjI8x41KkTim^LtjzmJAP%0|n}2x& zQ$#J*3l0Y#e2fc!(F^4~WqLurKl|E~=#t_~&?SA~NZlnRTiDhKJsE|be$W6V*!Nn` z^8IrV3^pi`1BdN`R*p*K0AY>5@q(jrC9UKsWu*ikshiYU=H(sW>Be*sqrJmIg{-8g z;;4bnAj!a2cZ_>odc?>bEQs(wSkq5-u%!t92{8J}fVa!^-Xeo*>>I1Mn3EHIPR0-% z#5NHdh`B-#y#2X-C#*SGzM^G5S(N$P@Azni9RFnCWeuJ_aOu7y_GuXb-4f{|pU~YE zH4P8L&PPO1eObb8>@)-|YK}JHICfDAd<@mOOZ~f5aFzv=2?jCRjnUTL&JpE7vt+=$nJ!WFH#|g@Y~wp<=weo*&bVoQ5|PxbrRZ<&JY4rTLCbDX zhmU^)N9yccJu>GXaK`0!hTOW2*z40%znx&~4j~>!xt)}IjFIcsW3ZkxYAs3=`vAG> zw=2xyuUgMB?}={z1ITxi{8?N$VM*1mTR(Fv)qWw^e##YRX~T_oQAR3Uk6(wHY}yds zZXSG2wq zgFIVBU$D_e72TnuJHzjMoEt&u@Ehj$R`dHM^Lvx|y`I0SPMP)Q_cJRiuSZsnG+7Bs z@=P(=i&XsyA-@l6Hx)~EhM&5fncW%9>`s%}(~X8EvnSf9&TQO9b!HE>QJvWXZB%FW z#hYmgrM$WH<-A9se7qUTmwnKcLy})jy$DaZ@48uM#eF*1U54T=jCA)zqPz^U5@8mu z|M5GBSV|Fl4%H%(CHS87ZOC#{>V_>lQKI2ZLhRaWUV4SMfJNayn(+m zcLy_f1vemfag#fqPpGuK-ELNaO)*Esg=%JnHpzDi)MN`^T|4gUG|zTpp5NR-^B|_o z^K-_Ew;S^u6)5-KZp@QwquM+N*r+zozgH+^d{O?Y-|FIZGMyINtQN*(!Y*)&(-mDb z?Rd>gnZ>*n`tmlIC3hLj^1fW>SGJmSKdgTZGm-sW;2lVh?yG&DtfrFH1BYl<>itjP zao=hK`6$U|H)$!+mk|9+23?(xZ*_QP7qXOiYl*ke;#vI$+TWe-^)d_&BZDq7I3|O^ z0LS_|+Sv)dhe~&}670X7`qzbh>UUO{R=-8z4*X{C6ZVE%k#6i_e2T%u6f;6Q#6TY*-oM0BX)XAcFk*e5LP={4C~EhU1>bE@{N(LQD=&N7TLjTQQ zeQn;e3RFUS6sUy$ULh_If5qR(F<6?zv^J3ST}7gJ->FEN!>_3%Wt5}>74K#RD&9>B zae26yzkA_b!so06%Q$#-Z&@F<1rE@96CB`}_hr`SF-9|Y5F&a)yk8%4|NSq)VKX`G z%#j>|lDMTe4VA0NewwFh<<{i6yc)QbjB;AR=yo#l=hvfR%|VsV5_>YS7i+ORe^7ag z$>dpPSUZtemBczbq8$8uF#dhXb99yR|7odf5RHV#h_{t^e}Avc zKKS<b2nIH<5FTSF#1qxj zT8im{f_jVH07kJJz{Xu;W7c2bB1v=0o8E@lmvo7fv=|EFC6=0zYyb# z5s0MLwZR>a#SIvu^=JK9tux|QpOVF^66yDVf-|aBnGg4tVqR(7PbzcF;9a3I9jG2M znPI{!oo0cK2b7;fB(*LHOTCU;Bw#6?#~SrX+*hKiw`mPF6KgxM{;09MNe5{CT*InZ znANQt$Rc+ISgeY$NcvaB-CS>zaZGoekHvA9W_m!$XxEpW9zhw^lu_Vh_%7Y9ha}x_ zOVO^;*KYsMgERzbcO58QCVHP41lW!(vQL2VmP_|_1?#FVT`%*9n#Bbm)GW^tE3ZBh z6}wi5m9P}c+F+b_pZM%A?SA6>CYK$*tyQK;7w;f@3&{$OcY2ZKuof!@K}Qe4a)8N} z6#x_Iiyu&xmBqJgDN=B60RF<8N8^E8dp-n_RDXaHJsS6ASdYa$!N3*ez$nUrLbR4x z8r3Kmtm_vR7{z$qjM8zJ@FpaLk74@G!Qrp@tCf5ZV6vl`Pd6%X6~XT+P%Ze~slaZg zepP|31X}?H=51ZwlrBfIsRRM@X5fxGqJKtFGC4fYGnt}5#kx>|N{w*@1FB)!Q4bBv zOiS@Dr;)p))EAqku1JAfu>(b^oy#+@?|}?qmd`I2kebg)9{J&3B^Uo9|sO zXQBB0FrZ*RY_;ct>oxi;KF(%14RC#}NY8o2p4T2}zJ&VI;#@I~Q7-LK1!=@JrI8VTF2jh#R&!MUK_;j`e6J0V6!V37!S>o(a z2sS-uv#rX70#?iPZo)bzOGM7oB3JAFZSns*6;@D%&p-w1A$}thnZZWpW+%uwk^87P zJ>=;ii2uv#;!xa&!HM!9a+=9yELX=4S^gpXz2R;mT@M~XFw3(-hy9}EtCbrY!_JhX zc>~261hFjMF|4vj@ZcIaChFK3HOIz=WZ>bh7o5cQI#{_m8F(m^AeflV54~GNE?gML z)djzZyLgYnSvr_tAPQK=yD zrJ(H=w9`FKM=4GI*Bd#`8$=3NDfU)xBy6&{53?4=9|;1n(6%cWa!$59?5G zh1_N@%k}cX@_$lE-LB>Xv>7RInUa2ocT0pbq&&lprBE{*OT{AJ0EvmR?epltT-SlZ z#|2KFNN;tvjH;05>MVL$fnPa@%2Ne?uYflSc&UJ=3o~>pp4vQPd{@)4j@dnR8Ov%o z%i#nC?qq5lV6ubtGaRWvR?l#l0$Dr5H*O#TD`dD!fs+Y_0CAO`lYvzaB-`dM&%+(` zi14S1Qc3xd0+p1t3RF_Qu0SQ_W(6uKHxk@C=ea-$f^F!{tzWEiN+DgqLtG;sDIj+e zz^!u!lN}~J$iWe+V3Vj8%LTkbG&!XL9xdRVjwf0!0Z$d~F zv&}U{wkJfF8Ev^=V@WzR*JH$TGVopj-k1UKax?H=0A8_vX95VJ1bXya_WP!S#&$|@rXo9~~ zV57iTA=-{o0go2&PJzGP!P5C6-KiNa#F{gVc0Cl{?AT&D*6!MyAlM|}83G<5;2zhW zVHhXiY5`9a@NOq;P+iqjYB&l22eI)NQ>p8JU{)x(?pBXTYU{0-SGDx1d6iqAC|-;E zfAN&7k?Tz9+3BuWEHm>vH;L2hb*uE-$0Nvn^lETFHp(6ApJIVLDb{r(w=PFkhfCo^ zS`W8Q@3w}cTQjpAW|VWGNcY^L5(i87t7%cqrwg8S0^S!sl9rp7wvPNad}et*wv}~L z_lV|pK{+XRE$qFDNqgwbFH*WM0C{gPE7(a}HIsJD0k2;;HGCN(V)7LnAtufthheI5f~zi^kiG#BppB%21V=Y=D23@Ea^nJwf?Qphq2*+n6@K!|mA zwVvQ!f;8C@UbZ@143T=ZpJLsz#L1HPG2~r%8+d;*%9~=c&Wn`vVSU?eckR-*Yya)L zU{OvMFZV{&+m>u;gy2N_ufRZ+4Co`_vxTx@#Af1=+46+izI5!oFjG zYARNM#}3Z%>23!r7%*|k0GO6UFF22tlgpJ9q9&J~8@eneo5>|#Rk`7Ag@@+Rl?3v= z`pp#V5(saSn<%%pN@z10w4@+9kzRH=OEseCTVySn366_}aZB{n8%y-Y*cbvNkPx1z^nMdv9aU1^6J=RN z65lM_1F}k*tD@TPRue_bcwk(q!ahrLtQ;VSTD&u3J+YP-c$iu68pk%UvS=G zp|a|F|Btp2-g?r%B^=F&=eaNG@1`uNPqe8LRcN42VzA80hRw`Xu)pJ0fL6lquSX*& z$qNR=lfy*>V!dp((578A0(y2* zDsb|^-fBNuq*n_3okC-_i57poNG}lhjUqiQbl4!^B?9gfJX?jOaz%Q=r@Nzp!6=^? zbPEM`h>UR7X%&tO#b!Aems-%?->stQY0L0V1=7UfR~1Ohhph@!Wpgb-Q8w6*_3T=f z02^Op`nnn!1zY`-4n7HsK#Yw}p<|(dV*=hR;N1>RYBv9=B%6ue1ReRXY4}%_TrHBP zGWj=5?$}NFoeE>E#|U}^JVMx!Zwy=8Z4xlA<*?~91e`ByEf1n?7wKyRTrOa_jI|W( z4S%=JWk)JF|KTm6mb2=RDXit-FY0;ct!DX_FRhpP z=@-R$r_%@1P0H;Ny7>x}6sK3BI`Di zJxIQ!ZcBvRY5~s>a6-V||F9Aw(z$A={W7|u&b3FIE}C@t_KR5ZP0Gu#?M8Ak*da3F z;h=bXB7NQrOsfKXr+sJzYOy8B1|*YxeG0BWDrZZ=fv>I9Vk6tGUVDB5Ga^u=N4Pl- z;xd5!LKs|%&{ImcOZ$G?MOs%i8rxv)WZPE!MLUuFs@U_n4v|##+84rnmZDzu-6N=a zH0>6qy_v(x{9+$3k)Ct2UK3o2N|H!_a|+i4tyBSYTVrQxCd_XNB=B{#G>j=lh28M( z?(Wf4v@qPMez%9c{0*c%eVO1*BEOYVu?lCJeWp=Sd_z9FcdajhF0Nw06^AIr~B59Ygq?<4mJR zH8XSq&6Sobl7ZSWuY$?jUO4RK(ZD{pKg^|5;*_dyqCJ!S(_grtEw%wGhUf2Wp9KW` zx@lPW5lkXE7{PZ9+Pd^ew?foO_t#M)raD12_;=O zKIC34us)&WcO}o=2Bps+n^k0UfnekAW74{s{rtm-+ezGG1TICok((O}M3wS8Qf@9D8CT^3IpNKPvLt3%}>l z^DndnBLua1LoQ0a+>RlH9PwUL+}6_Ax)z~03t z4#G`H8L*ZGQcu755xq-T=2zN5+DF>$tyiI~uv)T>cN(KlI002DRd^qY{Pah3kq0Gn zZRr+Sz;!F{ZozxgOAiobBX$+UYlEUZWScKbUAAEn_$`;Q)JkaUv+(W}aIY%hv@YOt zm!W{$??(a8!JQXq8{PLc_oqV^mB;5uxS;oYX$Jv&1WDz3VZnbtJJvKRWwLE2{=%E* z+l#YJofpygQwf zY~0tO&Kc=}em_-@Z3{(uOu$>k?#@a9&k}H4z-hO?f_Gj8EI(^sB+_#P+~qdA@M@8O z=L$Gaz_JzHDRhukb-hTJEoY-hA1-)K7U`mq42Fnw*+Fg-`m@8bwp}ICMI#f;7U|qw zw)kU2x)>+~y+XHAfxpqGyUHId^@+h~fjrfxySC8*fp{9B65PB9AvcivNIj+gGG8*k z(hkx-(r(h8($3QUvRq_&$#RtCE6ZK_gY*;WKhm$Hzezuo{we)d`m^+N>Ho4`$oeAd zk*r^`-pTqX>#3~2vR=#jF53awKD>KlfbG~>#?l4;qT`wNIW)FQevZcWGe3_uwrp?x zCQzjq;Eoa=Uf|RHdvE;$q1z(_og#fYs-Ufdts=c$;3q_SuE)0znHCpuVn>O&Auw$Tq@+vk?RwsjA{wy)#f31v?=NKTo& z+q~eD%}_g${v&AE({gm6QN&FYZXDvM*JQBCUV#xQ23c!b4*tnD?t4PhB1m<29-mCL za~_1+)3n;`deuKa9`^HS>=@VBrd}UN~&#s zT$eq@rsP=Q|E#`SwrQf>^Syv<0A&L!8)4Z{%f?(b_@Yzry@u?JWGgCLSJ`??SmH=p z!P5&8(&fx+&`+$$+{s)EYj_h0yG3Sg|L3*6OEH>(^W!gS-LD(r{H+hc`Tu;sZXbdH z$FZ}l=TEjk+ybsWd3P#>bPri-vLh2d>D@#6&zsf=>Fol3bAJ$0ylA1%|FYGVZK|`_ zsymCH*TWfdABHn@b=Z#BufG>BR})qBP5O%Ed(3U3>(xGjd5P{0FyMQwtF>>4Zll$v ztg?XZ3H<#>&VM#p*J{rK+#`dm+jGuf-Aj3|T!~z4U@nFs7oxu~I%Iz$Ah54zibqyq zH8q11!h@b@cJS@DPXT35A6G)c)ztL|j_B#yEvtsMYrnGV zE^XHbYhc%+EwJlj_t@Ic@wXZD*o&{t{nmR>%V(zlIhNOYIc!Xxy8*T6 z_volnyU1bZk6dPyy&YLL5Mg9?R9nfYa4Q(yPDWy^pG}{gG7!g8$#Dfao)b|`WiVN? zG3@_0J_J#+(d{QEBMX76ZT>R>TT_tH1SIRyP9r0RIjJh zWbaQU=Gz48y1|9mWE8L7FxfE?*RI^SB`2((#AEY1 zmLHaj*o^RE5vvZTyVwm|mZP@~5AT5kw2*Y@2E_424IFGk3(u4r9@^$QWSi2Pm6GGm z#aWy&St;_HMw+wyrjbrrn?5fwe^v@V z++$h2F(*p#B~4-IZ-~SiR18-V^;;_3 zwkP1h(&ddZ{;d`qL2}Xu<=HVAnuohT!51*3;$G}KogPH4*lBi##L-)k^&t+9>a%{3 z^uhG^m-0mU_)EW{>E7hgbZ^>dy1(crn(puUjHdhIil+M_ji&pH+oI|I7Ej!};%%sl z_lQ$jym=zIl%;-9X0o_XD1siyYmHM^f;c$pi{ux1-x0nT>{=JU~zX=utTJ`3wWu3eGS3D*{8P@09Nxr{ncAW zaSqbw9Q~?~1T8!99Os*mla?_66Y0;DtK1qs?gCiy!3D6MG=onw`OH;(s97R?lHsGd zj#06oMWKD>{(m`f?~kCpK3@yhL@z{Q|D$7pH-c2hiaEvzqW5EgX0@OD~Zu;1TvC7Vo7sk@PD)&zRpTzz1EeEc_z7y9_88K3IopJF`W<0mj)i(Ea4d*hYkJA*?`Hif{$OEQE6r3K8PKt3+6a(2l@=b7LQhU4U>F!bF7Q z5spOo@f#y!n-RJYK7jb0_-#g*_r%E9RS0beUqSd5!bXI0;^Ox&2+twxLHOVwAroOd zLJ>j&;WC7)5N<|Thj1UlFAyF>=tbCrFsyrI>==Z}2s037BQzqkA+#f`NBAj17s5`2 zT?hyLX=H2!LOwzfLIR;2VJX5_5ZV#$L)e1w1VS3&WrTxZmk%K%p#Mn-qY-)$`Vl&j zhaLFkzaqdVA&f>C{`kn)kqG$+MF^z`l?Y1_Zbn#((24K_!cK&Kggx6q2U`BS?CFuQ zA0oVpFm=bs*aHZY{s;OY%>66!|F@B`R)oh8mhBuF+m3Mb-(drUtq7x@fjoroA@m}g z^(^v-(1$QJjr<}U8NyBouOj^JIh4acK#$OgklTwgL70K?Z-m>P2Q9)C|3sM}Jclsm z1>pW=Wb8@&PU-_sgx?|bAx!+&$XGqXj}dku)Bvyk-|z#3eeO4dJH+$k=BQZbNtyVdAUsZ-k>E z^FV}6e;yfIfbb!NEj=S+(-5}6x939d5wPz>=)-@H?H(EHL3jqC58+jWA+N)?5k?^# zjW8Ku8bT?;0)!fbB?xT@cOtAu*o3eJ;dcl<2x){}2nX%~AB22_$p|wLK8sL|unZxE z@EF2Qgr7q8I)pnBzJ{;@VHv_)gjopZAxuS>gm65T=EbqE^~HiIAkeF6Tt7U63M{P)3Fta&&> z4dS)H}moGtjU953lb*!>+aWzO|3u+o;b@P#4 zwJ6rGcv0-?va4c?>#mGVtE#RTTToctG=40KGZrhKe`>5^NkweQk|nXcvc|^xs(DR~ z6%7<0%d4(xXj}jS#G0A#U;I1cj5A_W&OdM3IcHy9e8C0hUqDvpUsQV5MboBTKJB6z zGZ??Y1fy>e%HaXP$k|6yp1|SgfSD#33inyx>e5 zyRdlXMaAb$DYg&KSC)^(h8=(W@$oa`4RsastIDe5HMNZu@v?cfO^xxYn#PLy8l+X! z*Vop^Ynm3%tEi7pC@AqG&{Pd2Ah5D& zVTI9{@nJ?#eMMP$!--edSD|F{<7GAF@rK%X*?iFCHPtY`HRToM)z=&sFKa+98XCc| zVHj{5$@7}prh2P!!!-?!6^q9Y8+MM(yV77mZFP0+)m1eMC&e3)FPNc@ERdid!-e8y z3(Kl%@`u$y_o{i-*Ti9{s>a%S;?&jGE+jroA1|+HEUT)HUtQG*&qwCQU3FD_L3P{RZx`j7C}K>NH)tT8f2}^B#%?pQHqx>MzNivX;JRw@sf(gd|G%a z1m<0R_0{9SNhgel)Z>7CW~0hSW7T5iCM+1*p$g8|5MNMVQ4!BOJ29jDxbfiNxW&n% z!K$^mX?`VaSYH87we_`43t>`tVT~@Xv(7pH!UmP!t1Ifq!6iwnOP={$Pz4uQ06RCq z>?G6rkSbnYThUN+Y~z6THpZ?fV-s~v#O{riP#yov;`5r2lNt!0_qnRNleExt;#b!; zRhP%Fs(=lZ>eW??pn7e*vZAcsR=h@-CQ)5c)=&ZJ>WW6>HNL2(_G-l=KVDT{QC3}j zO@6#V7t{ROI@BTU5^SYZy)!hU9Rr~77Dp(E5R8?0qFHJS7Izo-A znyX-;s)c1}2CA5OwlDlQY?#W%iPcr}6fkL!_F-)K_+h0PHqaJur1|l&4daLD4AOSB z^(b#xzLxncYn&9nqM-twV73IUOuB=dH97n+-1FDWS)PjNW zMUzK3Vnf{Otg7`edVFmS>Vfw6hDuc;Wz}d3j510Riw`QX?v*vsxAGc}8>XxbFYyj< zvaz@f#R#vfSg?TE0bvHOPYt7&!&%tsl+B;tR8JFAh(>IPS6l_1npmXXn^s}h70#Mv0l ztExe@oN~dGhDm7LP-n{Hr^O4Fpc`D0uNo`#cs?l>i+|oe)W6rl4R1?V!RiCRsbZj}DaDHt$O47ryQO&}} zN+#vU@w}m;x?(=^WD}?ps@^rI@RQJ{)zz^=7~HYtS|8L6^e#w+IVcPMMT~{@b#N$1 zLr+B3F~ti0j@AizT!>btP9a_jM&ri=oRbg7Byqgqn#Jf$#!ehRVZqq3$3byTizjH) zRsP}qaDWBqTjM3A)8fa(CyYA@b}NT|e00J|ng`IK!?0L=;|cZE<*0vT1c8&#w=Gz3 z!s5mSIuDJt%GD|wq1;s!pE5OJ0o-U_8T!Qrcq4OOR=p5?Ok?F@+S2KCb#473rH|1J zK3P>8AA8F9lNNZqI6QQIZ4G+ErumAOF2?cW#}jAlspYCiZ>X)lssj1Pz^P_o!!RQw zj()5TJs7cQAuAgt(=>k(S~jbn;->YA(?F_&s;EaVjR=w0rx9dthwAV6U&)8@OW~mK zVg8*1F6F4-#E$DmgI)tz{acLQS248ZS%o2r$;-BDOJi%V!dSKH;@B*N+%J~K`tpim z8*+<(VoTn^>fNXCEKK8UlvjU(nCu0YCK!5!Zq4rkSyL3+4@9m>Ju!9C-rViC;BlfWPZjuLg}yJ$r!paF`0XS!{!$EdqW5 zVeS__?ZS#0jQHlq^iTlf)Ef3mX!JNh1a0hkEw=!4?T|0!?!E>3wM~nyfX&t$II(hO zY+h|`L*t}Ljg=gmU5;)TqpbNAmphizVXIu&pLDyIm&Q5)vpi;_Y%H9B+`3yJ59w3U zt)rF3s0wa(RateDs@ClEkXm0>gK^=6@#9aPKy}v&y3erxMFU_kL0MI<@h8P6Oe`oE zKOQ6Bf`VATpea#8%)r>wIw=!Q!n^``%}q{IKJob}6HfWW$pytHjhis>lqusT&OfDM z+*t($r;I!KtSO&3<>YA-Pn!6NQ?A7@Wq!ptj`gVHrsmRE?2ehS8Tf7gmd<1T4e%eN zb@ACWVEHhdXme*@2v)@jn#BdzYc@C$^_bu(kD5%0opoVZA%4GV9C ztnVXjJ@CFaGd2eC7~-A4DZ(#tHY2U;2k?;}0uR3%5HG;*4E)wH4x9waE4E=~tQjHk zqnWYEh|k4uH*nhVOPu+t_vHWkH1G5?@qt4cd+cwefNI(c(=q`43K8I<0gdT9ZuLIRn$zV!{)@ z6wj_wJ>2Bd(=j%vjaS#!z(dxHI#CXI#2Cil%z#B%j1$#VRcptGlXhAxs{d z6IT#RwFYXV9O4UVn=tlKGa612YZg>3#JIaWe%5(2E{tQ6htkL3c43X442e|Agk6hE zk+C^(lqTkC3t@gWBctu7Ox2dvE^*SS@%flZVqS+1M43qqy5KMz3ab&jDLAEP20xa^ zf5or7s=;I$d0S9lyEyI*A1_CH1eb2W`UZMG*UHge5k1t{!>Nn8CPv9+^;H-fo|6DS z_JNtaH4i<5`eXqN3N6ajL|OIUECrR{z3E3DZMB1=MQ^B znq!th#&I-MfuR;hbh`GN%x4yL9-ARONQ+5-zNa9^~X zoUk^q4$njDaru0eemT-@@@XXVcFd+zD|iDFt4E4KX1Q|S#W~w0W%cvxF=URPbIv)F z)XLDb`r6N-Q7o;j$4C!yqy8{3-31kBTQ~}sQdw53*8I+%j<5(Y=24zriBgS{)A(dm4Q7HaSWc3L>>`8y<{2l37%#IV zFr~3v<-W!?K|do^BDhm|Cb5p=3<1u)jD!CD^;g@3jU5N&lP zaqWTyRcet`;AFANvW0CWSS(a?!2D=Y4NWNihK2=A7@Q2shf`L}+p-ElX9ILtN~x}` zUBqP%tVzHfk3}1dK0I;$+(-=3AGcdu%Vmn5<zwH zDvtm0edTNe1_U^+Kn_R5GPvj@*_Hu=&eEyaYDgy+Y^-{=1S*H_W|G)3QoIHN-?at25&i2{a zUFoaS)#4U36X3+foz3GOgs0+eYa@O&x*|;yzpc%UJq|A>{uFpI@u$Gc(fN$Wi%Zk2 zHLdNR^ih>A@rDg(_17@tr=5yxI+7{~8 z*=b$k+1?_`Iu8N&RiS8OE9wEBD`^Fb7{xpFTI$Ku+Kj%A=)}p8oE;HTStlkay#iN^ z>uAZ4T3o0eflJM01cL|nONv$410ht5mb2N!1 z8ga7Zb6eSfG5VmQ818IYO}O-ISchj<0|C7rf9#UkCRIjZ(M!j zb$u|Nzo4w79A!}Y@Ny6dqYb9fGUAV{fl%>F5GQ=x2$RGYhoiMof}a@wu6EIqitfm* zgEY0l5(cTLsRNin{J;&fFIpH=y%<-Ev&H_ZfqI_MA9RAUWjx|bzzD;N3~nj@mR zp`FlX-!qWb_Kx=HqRLW1BTh&#{MpnIC8dBIB?6ZkCJ=F_8f;lfd0_=)irQbl2Kk03 zR-9D-33V$my;6+Z+AsjB$6_)_ay-7U;|!-U0T?{~N6*EVX;jm=C*k%c3(_-ksU3D$pye_ed-Hg^+Brd5dx@bb6$`*ApXp~!RE%R)TuMhw!%d-jKIRyw zGD!Wg?#CNbDnJSR8lcl^tZiyRC4us9T`epDu;_uA0iRLR3I{aVdlIgt9dpMv(t=1G zRb^F0umU}uqa5f&x5711G;$Y`tqznI)K-@Og8r(YzhF^dN%mfauPiAq+M9U&HNoQA z{Ng~qv;x^{8vgwJikk9ZX+=>*IirS%)`Xx#aB3l4-ARVC-Z2o8bU;#YX_034IzxCpxc810Y{)1p!q|Oga!evj_XM4 zehnc^r!e#+JsQ!V(POW0`Oj>Ip4dW{_K$>L#pAXck9xW+e<$L>0$-I7}9KcwzwAg~<;2 zV}XL6$6x?J_*6CO8ycHJD_1qQoN{VwTYE?Nw9ZJhYxSD7>(*!bva)k#&7PAx*E@aQ zG-~fj-$CJ9F&=7fT*tC98JmT5QnKJAcYQq92Ky53h9`~lkwC7dJjT>-K-ngo)&Jc}{Nkgm#WW2fH`I!W-tD&`}QM4+{7zUjXL^DH4X`=a{ zR!;f4iF9`|eNlZUPgZ1IJC;S-_~g=u^oo^XDuW``UF{;J;wdKAt6MtBxQ7quSHs8> zb_|Un?X)g`@O(C~ z-+Y!fdOphoR08S%VZa8!4!{5)ZGZR!!hjyY4nQBEA20ye1z-mN58ws#0N8=}26zFP zfIL7Ypl)G4+X1L7&1bs+X=VAW58yo!?gWP+?(_3m-bMLrDBfjw*xDxcb^I6YTpm{Z5E8K3z_bl*nH)!4i|9cVc0nm8}aea(%Qwo?j zqk#42&Sx8E;(1&F>zj-86c(_7;sO>ff&T)$11if3SX~g`iwaoJJxJ3^e76>`v^Mwy zD%%U#j&K3XjNqFf3cS??Y(p2`*C5=PptlZib^*&f2hVfi|0DRFhd3_)-i2_#2s~T{ zT35lZ7xZp{+t2WRTLBi20rx|WfPQ+v8#EpS&O>;A1YsU6U>gD6#|zjQjfI8znK}6L zQ(0wv?d0gAz5L5tgg#wa*u*@WqtWm&GiQ?ZCk>lgVSPi!pEKF?dH=;9>P)_vk+A^{~bM#*FgA`v-)N8sfH=NLVaW%eB|Eh)>A%wPz zo~XULib{)@v{M)#34N3Eg1|zRGz~Sq9---fD3;uK(I-sfl~HK_sma4PSCQb^)xiI2 zfLSP4d%59+#)PazxydM3neZ>F!HAY?@907CPxGQd;(9u_ndO>BrzxW8Bbp;xe}$AV z)939M+`_zFS;iG8q{u_dp*kzbU3V9)9rWNDZlc~)<*d^H$I;Px)))=%Fz{nEy~*(7 zc#6^bCJU2{Ctdrir(461;b|E7G5ibzKdCla=O-@BNwv}`!iW(ntrm%lZWL8DwhY9@ zg!^9fBgmQAyL70y6_B*r_~&s}Q%SakWiU=G|5$-uK9*(~oSMeq@vP$l~co zmNAAY0*g!)t5Y=DB3-K*KjD*kq3-g2k7!EsFgY>dl?Ntrgo8N(MmKG+Xe3iz>~V1x z^tD+~%&)JTga~ zPU)ifJ42_4We#Zx!A%p%Oi#`mmzB~I*U89}Ld=~j`51|A3Jt z_R65bpt{lg8GQnj-!PQJP7VY?7%InV5=nMwh{Y|;v13hPE86ZT)47=s78Qh59jA8& zr|BeN81yJ-U5=sd5c`4E$$ID`@OvQvpw})X| zgGC|3A>+f&HAsys5acujwurRG%y|_nPuQX+3`qq?lsBLo=cmW)tnI1E0GB;-6Ez3A z_^xOKThn-)ylsgH_aS&C^>95b?fGi?5aoeniCVt0s}mf!8Vjm~!nintZ{3oc8(^N= z0=rqh&yw#W9+vEgA4;DSiDC__Qzwf)hP+V)IF7~jWxAz`Nh@Z+$Nn$q-SB|&jGIUj zNw`CkhQdx`ONoM(N3;jD?tq~(3|>G9ixnt|_2~Oxu|?R_$I6@H9T8F*BesD;+X>Tx<) zw78q5mwF{RCqzKL^OEJuRjJpOd3Z93DL(XUK+1O9%#VtD3zX*oPTzp`NO>0~QUkk0V~>Si~ut zQu`_7BW1(4ppwlBFG-xnV1Kf&O6gAuLBIlKx z*-%P^I}GtD1r!qMVXw5pq)`)P(YADq+^DGzdIBlI~=dx z+>R*EEY>~=r|yzzk?)?(h-=ZBv6f0_PzLv{YQroT=!?~K=9 z$ILqmp;IPEp}+p$KJRqa@Ksx)@7j>VN8KQR>cp_a#P7;L*fSadomBpvF;!7zXUE!g zM;}e3*{djL>?`Qnzrg(dYsePRhxY-%E&%%ydVfG3pc3Hy20D8{-);a4u!~7QVg!aA zzHVfIdG`yjx&r`X0ysw|!1>@dm&3MMS)5%|U0YpR5hRPQ1r;UbY%juBmim_ls)zzO z*z5460so>vZAGv+P*uHmbVx~ETH!CiF)I$4z2PUn*dMGdtg0xhEv~3WuEx-yUR?|W z)Iu7XGH(APWJv}v{nDJP>b6rCxsidG(^@oPgz6gH+f-$y)Q zI@R1kW3pvMBwRVtpy;~Dwv}7m({2%r_2mMohAXBrpoW7bh>X`q%PK;W5w&QEa&VVWv{Vc8{aBYCNb*r4yV5hWVQKe-Ne>f#Xi*gWuDjXjvN(&-> zaL-C~kugDCZeeE9iiw{Xcwn2QX%5tN<$TDlcFo5PTZJ^kWesV(hZao?ND_2O%^78cOu0_yptUqrG>sR9ud2# zm;lOaG9@e;+?9rYdtkhF_YDLBn9oJ0+(!S-!G98DLVHh*lLbI8zY`kHe2d!v~ z6UIv1t)Z)>wMm?a0G?^HDB>ibcZy$ZGgD8TvQUq`CQaBFiMmMs{GEi1Urn{2@wNHR zb@dGmogvy3P=ixgFkG*O2|6#U(x1_~l+t4bF}+^Y(L&t@TiF8RCCyH|vjg_(+=79z zBj7J5qRy@=+T5Wwh0r_SC;~hzu)}glVq;R((B4W1lR+fn-N`4oLsr;6)`(4bEnIgm z_si-cWP|q55-;)lYN3mvjTh2gExC~^Z!aoWR~D6ft6)pj=HSrwdrT=|w?$e_CoF1! zw8Rp+Q%B~|*PhxUPR9|)9-)yChXl~{TW;M49aZ1ddLf*gyc#YIl}E$HR|y_2KA+~w zeT;e=A#{V<_CYsg)LihNN*^*wo-Tl1HenE@Ys8EZbksgbBBE$u^@!Sq$uy*y%%`rR zQgRi{^y9tlp*2ud@p`J7v!TQCLMyDnNRyL@jEdh?8xT6OXGDXo`>2_^!O1-PbNbrHj$*iv+`pwwq5p5O3wE4)W2Q-gt6# z7~vU_a8 z`X3+Jl&z~iu@ow@F!4=F3zast*0M-$x~G)mkVLZWMbk&?f5a<}Vj!g^?3ro9sZfQW zbL4xc<(WJns%W}=yKZV+AyrJ%y&4aqUmc90=sBxLq(V(nPf$Z(X&Q#kPM-fk_MBp} z;7kGr(UZGfq}}6?6b6OY{HQ!@A%!O{J}6iOa-G21;&LnzW{@dpE9tVD1Cx^5Jw3MMGgFn*ATh>SyrctUm$#ga<~C7JeIIT2x7BBJG@ zk*7_H(*V^5W+)&rYC!MW@Bd=gw^)OW}NItjX72skVEL zIkDs%=0H%a2SJ5P#|cp@LMsz%TiUwXsB6mh(Oxa7bLVCk{_No7Smy=Y}!qsxBt@KT{Aky+9cDzlMj;6n$OL*FJf`7-4Aq7qt zy}zJN-?S};ikTiCQp-P;zZgSDWZX2K7T9Eao0FNFnV-pf2JWxflk<@t(P+lXBVh+ z!8{dndd*p;mk-={Eu~JE!b&q3XA1$jQF%k(#OM3!n`BFA;@@-vuVaxb+-U1SQx`2X zxgLazd{hp6nJ&%^sugbD!s)g)5*3jK;(^wH)V>7@hoy8!SJe`B3{GZ5*G74G&5d?` z37WKUNaadyCLlU$9|gVZ`wZw?S?r_Vz{+nEr=i?%7IPzZAc-BN za5S=<>TO5+j8lNl=YjOj&tQ{v1C1FqeaLrjd=Oy>;1ER{2)a5w)lRzdch!QD?hr)X zG+>U4Nj1jdq&68G3Vpd^#7!G!tLxWeq)w@G-%ob>z65D=(GsRkr{nTAob)9lOmbIp zN}NV5WK1fl-f4rVk)NUxyyNEDuid$RBh3W{@@ zP?kC*F|py2x?NEpT)Ocq}gvdxXZe)%k+8&`&N(XqSWQ85+aOK7m zA42rDuD>e}mk%oE{4^i3R&b^W!)HXvT8()*TU5)E2nFl5d^8ru5(-wB(PFvdJMIFd z1aA|dC_q;rca09lb>^AW@PLN*$3Zqw8(;Ldo>9ocfDM2;yO4Q- zlLlabOaO&p2%~_$2`H{Q&7a)#xb%3!z~%U$zY8z`=m%VY^z|ccWV_2eh!+sX_rNbo zSPz~%0A9lR3{L?2D!@kLn|+cxOy4FErU!UwpF%cx-VV3AA;Q%q2vAeK1K@VNvoBNQ*8wLFIF*1> z3OfWo15OWcb^t!O6t)*b;P(JWm;c51PD7bYmG(T~R05|CFb(hFA@B!&g7bBO(+7AC z@BKsIZy+4xqpBaR_)hyeHBVmPR05|CFdFaSA@Fa$1Uvy}0I&;UxRy?+RNtXuKrs9LEA=j*s=H63@=H|TDp1lGTmk~hXpEP6O} zFfb%-{<5;A(3r)a45}i5k(^M+J9r?;guVc38alhZWj*yWLht74fF+J{00xG0QaPtc zGTgd=!DD>Th!dBx^P)JpDJ+iX>CW(0z<7302iGcHwNNS$x_HioC~Df9Fr?a7-VVFaV%-jz}Sa2 zl#@(x7HA`1M&|lgwaQFaosg<&Rwf<25Eo}8T)&2^+Jy>?bVzc6k`AH6aGL0^YT<`k zV6lIX!e{aDQxK*)P>P#$y!@1sjH9M{$xcJ)WU*=o+mV1QHuHc?W6Dk})5q9qLIZ*o z@-|xY6|&+(Jxa5ft0JZ;UVnK3x9cVqIsEY8snVZNR+!ihmee3wa4gC* zNrU2|;pjAPfj=0?KphR?;8PlR2_G)IX;2~7N09HFsl*XYnd+^m0wE#UZ;5_}kSNha z9^}_laVEXskmm=G_o?#Yy~0YFq^1mw1M;O-53FNz5>R zj4wV=H(}Q@cqNsC&M#ly7Wo1-30Kw&Z!}4iGCpqZkf)c*4myWEgt z3)I|h3E{dR(tJZLL?xY@vhclMg3&tK%~J>a7Cc0OfgKC%SZS{|9lC-FLfWJdwrpYD zGma%$9&xB!hEo!W>{MiSnSaS(N7Yim8)2mSfQOjo^)D)lb0HG3I21~7JW~mC>QT_7 zh|r0Bh)NP4P;8qARLGYZElu-8HpnKhv|@3fDuZ%l zDiyNC?O>K{2qUT;q#eH04r)<$;Q$Mv$42wUe|kNlvx*2=E1QB1EVZ;?tr;n`$KSS9tu2G`$>b{ zg^6sd#Kc-l8;r*20oyEkWQ#|Rc;F@+a-5CL`{-jS^cod^6e_w-Nv5-Yt%@4uwMDwe zq%o%L)e?xjLP@QzDa+s#jicVH4I&+eH9yibDn@UwACg0Wgvu;qstyq+n@mx_fNEez899`FwCc}Qy1KkPm8Ndrj6qaOqJ7jtRaEXSl8;!z^ zc&H;fhdLa)Y2VfaeC#=s!6*KNkRJ5Favp9iDyQg8`DI=Y#7Jm(-oU zO7GzR2|PC<-d!o;B{}qg|5o7YvRoo*6yVuI;gJ`~;_lz#@~-PtAA&pa@l!n05Po9{ z{)vxwz(-CTtwcIjucSK~&yC=%e+as{s8e@uc6n4f*B-bLe;4Dq0W=0u&*7coz7Nj<3X>un@!o^HEC8<3-Db-0hf;XN zTbZIfQTPkM`x95k^1cJ##KUGhGm-WUR4(z%1H`YBWB^C$bjQeWjGn;lOA(IZ9*wv! zzA9G7yB6ORcN3m@;C%GkKUf@;e>mm{007Mb^Q92F4+sa=t|->GLLY?8$uM!w3D7g_e{HD?Xjc zBEzs*%gfkw4lj(b;gbql&JxZ9jNr^uN?S~ly~})L^1=9pka)U0#>y!PEvF!2QJQWf z+6ki^%evQ{WYaQ@8ro)u(-U+SqVm*Vn>RWb0o}oexyP(88=e57ZY=09&zX&VTqYW zEUT`9QKE1O#^VTmo^a(Fqoir#JoBvNDT6}TsY*@YLki>s&bqcWfj3t%$Ce?X zRL)A|n4QQmCz0c*nM%wJ(lR)ajQTZxj?)X`IkosgM(T>I&rq2-IXH zuRD44<`g zOYFE+SEOo57+(LAIMGt~8lOg26RT39M!I4!Ed04f6$9&1rxntDrGAvxVm)-~w!}@N zBM4b0O3DiYOHfbNa$|O+UoLd0UOR&?d%!(qnbX3|ChNR#co=x%id*9CcoS#@cNc~#s5ie(|jY(NfR768+DHU~gI zRlfpdl@(Pq-w`t+-Ru}`QP`KDc(;VJ61bw{zzGWL;tP;gCLt9Nq@iXO)bFXrzF4}& z-b-4s*79UiYlV~=@F94JOMe3pkC(FYW9}cfB9fw_~_UPdU)t_VmW9m8~ zsqTpjS2wSU9VDxMmbX*GtV=qz81_}1vE^=18e#^Ai3kuMHI-!Ur7Bi+ASm|y&zqb* z*~^bP7WSHPLvvkrqMYz^o)Zkop`a!4bh2{%s;wB@povgezZNzCKt)@8xJI!nwUfOF0z2{LHMQ42WF zL0ko`#|blYUX3(*bVkWuPytU#+qzlbPMMoE+%h*SRhd)eXgFn#UpupU_Atv_N<9?M zwZZv@noq4d1g^%=8kJ-PFDCy7wH-qch;94y!a(&Vg|dvNAimrU=HH=^lzW%PAl_33 zCI<9&JD&F;ba}(%KZeTQq+v(`#7NS*GW*-9E3=1NS7xWGE2{htr>@NA_vm zxca()j6EaihOQID(tw-3m@$&Wf$JZee%U8Dc=}!<8F#F>V^XfmRm6*n%{%z^JBOl< z6B~CTTq%35=T5rsEP>2BL$m`?i72oOa(vB;496x#7PMMQ< zTAGEuH7$|2wh%BwA=`|hcD|humotui63KFJ=&BuWI$^c5j;EiRh(UWFXUnk>47LWz zN0oJ?n`(vYA6qW?`9oBHC7xa%xX5B_!*J5389-Bo;r~d=8B=h^@)T@Xk*-`B?(!8= zmn1jI`IdFb!PDy!=Q~ABijUK&8E0Fqopf)zU1I2i$~h ztxGN9b$1StYwWHea=|*9oO9zt6mM7Nac#0rH&xq1OGVW7#NngbD1K?Trdq^C%fUBP zqA8L4J->~;pp=O-^ZnI9XQ!suU+twu%&FSG(4n#TPSYW2@$|?lgY?jbRaJvj@|5p? zv0qfSK!fr}^$D81-5sIH+YYCXND_|nORrZn|0Gm0W1uH(7fQ8()U5`*=qIb|itKRe zdkk(O{sz~3p%tRLr~aR`G1Zlw(_jwsWk^{&ZHHTqV*5kc&baD^_;$wip&g?C580P0 zD-Q~do9?*wO-mOQMi(zuKF-)P4xh?nOna>P|Nr}mso~h0{lsp*4U+HwyZ7yiIfJtm zH{}-E6rS;0aZ_&T9nMxc%Ij)|*7!7j<4*3$thAYFEEt_X zue$LZ>~96^0&F}F`)n`5`z1xJ=Q8X$y#jvScwUdaw?D&sFWzs*zSteu7yAIspcZDwXB?LAD#@o$R)RdkdCOQ&1?$^rONIAmj+ zUIQe}jcjg}KiS@@ce24%?_`UczNiGtGi98%awq#-^-lX0)%#rc-A6VL(%r{-B$Fyo zN%t2(&ydd2p~a}Kz>9`Qe5x=Se?E;rAMuyYbt~x(F7c_tX}tL~-m)})vWOpvpQXi_ zrNx;=ai*8ol+9OiEeKTSSCv%KQWY_+!fW!%;_||Ya8-fwAmOA#@1o;syk(KB(hEyU zwS3Cf_{!G!%GUVG)?|^b#hoqk3inyY@|Uf}nXSnqTg$5)O*T0i4>=kSIT{Z+8V@-d z4>?*s3b!B~G8ady%D*HA2aQ5iiGxLX zq5{yn;*Q>R&YW+DEARmvmn-od%aw4`xuP&GN5VgrBd2W5(aP~0UT>=cyalI>R(ZqA zbj9LwYJQZPR;K6h{0>xARk;4ST0PFy>Q=6n&$(JY=W69HSK}#Ht6RBR8O!ByRtJ&q z1>j5;DwpTETKsdh_~&Zz&!za$E>`9jQf+h6J6DT;t``4XE&jQb{`Bgl<@u#0uoH0P zGMD%gGQwGj+PlkxFVju8FO!#Ve=vxBCA^(hVO<`4nJy2$OqT~=rke-8Of6omzw`0_ zPSW&I+R;DfSCkisx=|(iLFKRUrS)?@-p?rSuWU+2^MIv?-r(rM;L zb&WSLvTc#?w6H*aGG47e^zr^sxodLbeV%gHc+1k{B>FmWbF+|ve5Yj{Dg-ioww8BV zU+B~NLZ8+b`n0~#r}c$C-WMvG8c$mP=hON>pVt5RwEoYh^?yFC|MO}6pHJ)md|LnK z)A~Q3*8ll<|CcV(ua$q_EG_L?zv$!rV!F6uItE`WH(DR*)A~rC)<^n8AGxR^7^p4} z1aNJ&CU>o`^zpt@%8vJs>Yeu^JiMxRzS(ZQ_G$f@PwUToqCX?U9vpKVtSTwO@fCVH zW@}|z>(6|%MP1LYsG`0Xw{=(fi+IPX_|eMy9Fko+)hnb5A9Cr_0t-UrHXb9jA3 z`$Gj$xoNWGeV=lta?abTit@seB3^WzFdE-;v@$kFEBCyOmbA3C*{8M5KHfH`7w2OH z;_#!j(LSw>_GxXjPiv!nS{v=l)#B&vwTxeDn|)f_?Bi{7dPybEll1xi^724|9A!BC z@HSh~ar+FP)@J*7n=R)dTu=(1WRo5Y__cP0x8us6@-aPTT$81>;aPlsBXF}a-SU>D zwdYy9Jy$qx+mxlX;aOT6o~5ofvAUrw+d2El zHzO;@`+YAx8W<~sI%|1hXUFV{duL~J1c<^5k2&7l zIo_;nBAV%)J=>cNJOs(|&YkO>?e&ou5oZ=+gRX_AU79jDcN0mS5%+U%m2q!HBK%ln zK?euuH+IprSWP6ZS~}ShHue->LjRWbl^rquZVV13PN=c7ab~2s-Uq`c7X>O9b=42W zpyHsz`a4^=#kjieOkMUQj@YM+Z0rcH!`>pgWJ<+E#s|c-iYo;@?W!YwJLs?}GIsr( zk1XO9Qq4v%exX%F-f^Y7srNP6AqRI&xXpQQ>gaIZ*JO8T?+w~}llES(y`M%bs62@| zV@kz)3NA6lu0(P9mg|Uppz3la>|>72Z6!Fm^as~!HsCBO$QWgRl^fTf5S0B1%LdPG zz3jLd@5CFEUnm=t4~jj0xhj=YT-+dkA|BlHN_fx?*L&+%*SGKsTGcgbatkNFeT?ck zFnKBF`e`UPSK{Dkazk3h3$aP$m5A14wh_pxn zfxvNVj~5?qBAjo*uwJj#m1~+vV=p-q-24yogOwZY=rx@etqurI{zv6PWi?5e7V++J zdH!!Qim3|WmItl9btHmHRqxc%42nZG(83*E7C&(tXK%ye4tsuZ;b2oo8^U>2!Sad#0$;8Y zIdtXazg~)w-^te$iiR5LerfuNFlY+-RY1JE6rSF+0+a^*FD z4ePw>s&syPHQl?2>zOGJ`DN~CR2Qo;bxBD{>iAG!qqwdpLPuYM9qi+7t&cP##ZzWZ z;r9>X#>2L*NR)1W_AbVDD%!yriLS$Fuc5y2R2O~u6gORZ+WElMNxMjQQhy9QIKH~s zP{;wNpLgL*aY&L6H4?|eo2?Y_P&?#!OZms}L1SVEApxJ%(zpmt9_lpQ7Dz`NOiLA@ zh>n(kC)G;1XoG2qR>xsHAz!iq(U1ny(JJInc%o`KSc7R%y}&@lWt(9tH-jci%PRf( z3j+lwD~oSA4eab_bFQg%ad4|8%_R8n5*1M0V|y~yM)~2;(=K-9_$y;bN}9owadVfr zy(IyXL#qkbl(k{K9Jhza=$T%j_zm!#bfOI9&qSABs)+Tpcn_m)iU%0{kY7FB&6sK7 z>{xZmFUI##+(M2c^fcM5#7G)psm-BznFxY*r-5#O#@%a5hU7~e>hzVHZ>EbEM~{Q*8qFIw-a@|!BCxT}D&$CKQ%QjyDrGz}TqU}& zP$$BnT1aNdhAKIKGMpc~+UX|X`qpYvlW3{ilduIejU8Ut*$ZSl+>a8H11hZzd=>SZb^H(2Z<$}9L+ zMP*RBmseERRN~M*d=s&t_FYj)F~FB-6uKTn(;xqhxJ$}mc|?AAM@au7e@Q9fmIs2g zip+Vzdrdi#kYCK*X*nDviP5TQxqm*`2o!KU`j(#Hd45eH(q2+cu9Su#f1z;I#Wjj} zAXrg>wWp<30U(nfS!fhg)Hw9v0R{#A(uxWs3$#$)5w5hN90p+cCff_iEPq$ba$Kyb zVI7%-A0Qhm#1betv8DnMkn~F_?Nxy?V6mF=g}8gMTx6&>12%GyZ2;pbVIr3i!N?>O zor>{0W4KjS{&<4b$MorlXIU`6GA<}?TV2fq>V9e=uyAtNZoq`bi95~@R|`<24eMwJ z1XVWTFAfK@r*@2bM7lZu+?*{jePQb6_|e|dP`e1qmemx*%VkjfVr(=OV=X>{iV5RZ z{)SE{Y8!Dwff#~Dy%{*`G0M}g#UZY*RZ4v~Otiie@gl8*aN}|0x`u|Q8mxFsr4UXY z8)Ns~jQdCKD#7J3Xqy0ixQD$TP>1)*2k{Qr@DSdg#~A9jc*isR0>)x50$xIxVT8|n zw1jz|MR?HN1z?Y1tk#Do;!Oj10hxe)xaU0qykEiZDZIn2lEOV#!VVo~JR2Y0yLd(o zgFeaOKD4nz$*T^$X99+s-VMN2>Fq(9cTn1&DPer7h2A*S-q^V=Obb%b=HpvTcWA)f zP#*~~MwN-Y-lZ07}?{p zO0Fdq(5`U zdEg0^80NW9f<)yw0dC?%QAarf#W00r%+=V_Eh}0gFk?e7PM@SfasYRylAKm{wL;sb z`3aAOv@JV&XLcG9x9Vwl&sj^7JZD=G!lo_7_t@ z#dMO9{ZL)riW(@iiV4H&7r(u@C{}J4Dt2{S?BS)`d=- zXrBiCe5h8cKNxEVk1Z=flPgz63@t0km9gf~TJTrj8j4WOg?#90Sv*ny`4dTLC))M6 zSt-)hfI3VvY+n_{g??1WJ3zOsel5enBgpR-Qr)sn`O+$%Rk%mok3k;anGSzCd71EV z8BG~~(z%~_k$l%jqxFp-ufC}$^Kb0K=C)qJjw)P#$XKwW1SOiDn45$;TPS~n9rL*a zgB?Lgma+1VXblEAwPeNRyu-T7eb3e2=Vnm(6d9A{#la!WN_v!H^EozEttrOgX~&Y^0i4 zg$uT*!zB6zEvs9o%_~ElZwa?zH4AC(YCsp&2u#pyYGT#REi0o{w9E}ZdN0Kp3GhR_ z6+{D1Kjl?f{iz`_|7NTRG)sY0iYMh~;53pKFNZv1N+KeED8C7>ptB>)(+YaXJHCKI zL@9zr^^ILPN? zytzPLH+HHxI6uTY+7$$6qPPmq7Kv<=WrrlA$`O?y#wyYHQW(_65b;pdftCW_NKJqa zsHFTZ3$>M@nIIYk)X7)VNyWTJ;<7Gj6X`4s0#`9eq5empRKLcq0>-Cg!^I|oFH7aj06lW3?a5^ zC^EtwEu1Fs<%kUKC~w3I>Y-EFWVSLr{flJfrZa#VyE;2DW~k*2mG;fmrO|rc@F^T} zBl>7XR;qUjr{2|5(K@9IBh>b$dJ>SjpN|=)WqU@99JSBB`;FfJfCJMGI{1(=-x)h@ z{Dg^<4n6Gf?|P4z{Jr!ezdt2o>QP5en?7S^rVmDAvu4l9oqNo&$IUzbguMEOM$CU! zHMg8{YHM42NBFePNVIG9nzifJFI#@{irTv5{->XD<`2%=aP|++Irm5BoqxfF7ybC+ zOMY_c#>+0>bj6k3S6zM0wbyOla{UcGTW`GS=H6Rw{prtc`}ys6Y}>x$&R^Vh_s)Cn zz3=`99(?HGM;`5a?D1bd@#L?bdivMTJp0^lp8swC3%~pQi!Z(W%B!#a;g7Gs@#b3t zZ~y7f@4WloU*7-g-~Rr=KmPgQu8;op@h6{t_W2iIe)aV?|NhTzk{|yW^iv=1Gu~;m z^OHFH@}HUDClHR}zsU)HZY2K)-!^=X`4FHVkoE=Uih#VY0cm-hD>uLW^Yd{!xce|-_0RBIK6@l6TtcBA@W8h)zNL-nVQEnPLfEht% zjz&#m=KdH9?Q5kGH{Mh~_(z)~(e|cJYFgP)^&s9~ebbY8|0FHQJ^%~=UIjb{cmi-A z;C8^xfX#r7fQtd=0@eb;fF{5aKq;UAkO#;GWCGFwhXTd`Mgth&lLHYK;B~-@fTsa{ zfcpTq19|{g04@e>0IUUs0nLCqKoC$0C;;RFG65L?FJKH{6o3IfIRNnh-T}M{cn;79 zxEpXgpa*aT;9|fAz*;~Q5C${@mIH!-Qa}M94{#hH7mx$U1WW^X0pkH_02}bd{)ij! zKHzo0i-4yAeSo_Gw*z_rR|7TzE&yx*L;$N@|Pqyr8GqycQe7yBU| zzyRPyz|(+-0Cxj!2lN2025bbND6xU81uQdr0rsdaU_ChtSlX-wEDz8>8<4wz)d4ol zUBLPPR992}`dW_qH6aY-Tqz1ViaI`Dd&%>qcWdJ-nCH@rTk0yZ8LoS!-&vC8242ob zj6yvVKh#PS6*J-Qg9X*x-Jr^;euyk>6hhd-(L^n_srK3+gcrulgAOu1_#Ypm4>C;S zh*8Wm@Ipb@L0EyE=3xhUJm29ze5oITf(E4pKRgU`)Is3wJBSZNi3UY;kjKFRKK%&W zL|boC6zp((qkE^;h@t6VXr$OA_|9OX3=5bif$|Y>BO{Q!o2z+z6s`_=Md@9FXC+e^`Y7SF9_VYFvw8zWdI*sK8`;@w~;83yZ%Vwqs|Le_u! zLY8;NLe>N517x0w@3R)N0l*GG9lkdL`T&`KEN8m_8(%7CnJ?r0gL0Plk8+l_W+4j$ z`T%L5seXCu5gw4Xb|I?-YydEPdjavkKKNy>13q9E;SQ9u9nY4t@bif4?*PQr|3*2h zd$XKX=9M!q;>kQ4{4d1!W|ZA`;Pxlr05%?9#s*pt$0)5cW0Tzk=`Q!3W+e=^L{2 z{<9o+G-Lf7(1U(>0MJK$@|URNfE`Fb)%Tt-cmec4c00ZT&ZqGE3_4Nj$04&_NMB|L zXnzQr6VQ%;{{i6kzl-ollQ$1MzgogN+B;URtZ$8k*3m??E2Q*!s2}z|qtj5CERTf> zLv;-Gh3C(q`=Y(Z+bBHq@cd#Qw7qx^;7N$j(Gw1R^n}CB{F%otpr;poJUvI*teKvu zs6l$>VGe|60U-B;YL<(qw?2q^X;59U_XFK2s4JQHw%JJID146ttY8*9$wGZIcJucP z!^YDC7{Qj>mbKIa7-3n2b2g`e`iL;=!P!x8I|a`LCbL9%lhasgndV8T!bATrR z4*_y3s@dIms{6M1y~8orG-vGV^>U3b=>w+WgS2B_^$~4ouKYU_A^Y+z6Xw(FkwPgR+G=zVeMe2pl|DDFSGlN@l5>v&6vo<-y}AP9m@X> zW3RFsj2`1f{(qnGE91KoXCiQPti##6hL@ek#<8(%j`57~tnn27Ca?*T`gnFv68b*l zRd$SVzhRmm7}JwbCmwDzZZbAA`u`N8&1g4{F^HdY3>zKc1MDNC!-(aG!fZ8?^E2H{ zoL-;t4*SYDpS^7Sfqmb+jGc?h-E4S_7ULQo`$uevS!Nv0_TlNh-&kZWHs53Kun#yt zbJ;h>0wX@mPNSS%Yg}dQlY*ZmN#*l08*d(I<``$OzZ*5?;jE0uyv+EKvE4WUUm>LP ze&gRp8J-i&1;#7vF%~qdO_I+7<6ySas6hj?z_^z^!e*GnORn*P@jHXulglT0ew}Q* z!HxqbkFqlm=O2u}v1P_tMxn9UcpbIA%6yHz#I~XhC`0TvIJwODJ)348!ui>0RIu0B z(WVD{RvMQ18{;>|E5?Jy@#ZhUPx)T)^RPjGn|Y3jvQcJy&Mq-F8n3ZhaCkWD;1WB} zm}pEera%%?*$(4-Qa&%U??5IeGq1S}tzkE~IGLCBkBkg9(M&F%6OxvnF^Kan_8;Q| z<9F;xbG|_(@lDpp&N1?hU69NIW2Simk7KKGs!8Qyr%?oV%CAZ0@upk%sI=c>RPo%} zWE_n;l$@WBl9r!4j2GDXXg!G9oyK3$2?6Ws&pu526X7{6={3HApfFI(eo>9w4{OmO9P`^T~ z5$^v&9#$IHGAh#z#4)q^<3%Z-bJ$N1+Mw2lOXnWs z*t-ZFV8>&IG7fW~#Qj&Q{JIV?9b%3$u7_+!p>9+gPlIA5=1CtTuB+H#$g8bfHd~Qn zJB<_BICHFQ4-45$gl;x_t?vSEHhPU)j1z!Ug_%R95i*nYr>XdP0Tf$}=UEftO*3bi z>x@|_CDm+y^8l2KRpt?J|J3l~z08=5xPt69<6v*ckMEnc#CF`x(-D2>Utvnmxo@WXhebMya_J9N)?6jej9U2Qf

j4fsjA_9Re87 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 Zp-OOClLF4q$dBuGNoiqIU8%IHY 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." -#elif Q_MOC_OUTPUT_REVISION != 62 -#error "This file was generated using the moc from 4.6.2. It" -#error "cannot be used with the include files from this version of Qt." -#error "(The moc has changed too much.)" -#endif - -QT_BEGIN_MOC_NAMESPACE -static const uint qt_meta_data_CCommands[] = { - - // content: - 4, // revision - 0, // classname - 0, 0, // classinfo - 0, 0, // methods - 0, 0, // properties - 0, 0, // enums/sets - 0, 0, // constructors - 0, // flags - 0, // signalCount - - 0 // eod -}; - -static const char qt_meta_stringdata_CCommands[] = { - "CCommands\0" -}; - -const QMetaObject CCommands::staticMetaObject = { - { &QObject::staticMetaObject, qt_meta_stringdata_CCommands, - qt_meta_data_CCommands, 0 } -}; - -#ifdef Q_NO_DATA_RELOCATION -const QMetaObject &CCommands::getStaticMetaObject() { return staticMetaObject; } -#endif //Q_NO_DATA_RELOCATION - -const QMetaObject *CCommands::metaObject() const -{ - return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; -} - -void *CCommands::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_CCommands)) - return static_cast(const_cast< CCommands*>(this)); - if (!strcmp(_clname, "ICommandProvider")) - return static_cast< ICommandProvider*>(const_cast< CCommands*>(this)); - if (!strcmp(_clname, "org.GHost.ICommandProvider/1.0")) - return static_cast< ICommandProvider*>(const_cast< CCommands*>(this)); - return QObject::qt_metacast(_clname); -} - -int CCommands::qt_metacall(QMetaObject::Call _c, int _id, void **_a) -{ - _id = QObject::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - return _id; -} -QT_END_MOC_NAMESPACE diff --git a/ghost/language.h b/ghost/language.h deleted file mode 100644 index 07c060f..0000000 --- a/ghost/language.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - - Copyright [2008] [Trevor Hogan] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/ - -*/ - -#ifndef LANGUAGE_H -#define LANGUAGE_H - -#include - -class CConfig; - -// -// CLanguage -// - -class CLanguage -{ -private: - CConfig *m_CFG; - -public: - CLanguage( const QString &nCFGFile ); - ~CLanguage( ); - - QString UnableToCreateGameTryAnotherName( const QString &server, const QString &gamename ); - QString UserIsAlreadyAnAdmin( const QString &server, const QString &user ); - QString AddedUserToAdminDatabase( const QString &server, const QString &user ); - QString ErrorAddingUserToAdminDatabase( const QString &server, const QString &user ); - QString YouDontHaveAccessToThatCommand( ); - QString UserIsAlreadyBanned( const QString &server, const QString &victim ); - QString BannedUser( const QString &server, const QString &victim ); - QString ErrorBanningUser( const QString &server, const QString &victim ); - QString UserIsAnAdmin( const QString &server, const QString &user ); - QString UserIsNotAnAdmin( const QString &server, const QString &user ); - QString UserWasBannedOnByBecause( const QString &server, const QString &victim, const QString &date, const QString &admin, const QString &reason ); - QString UserIsNotBanned( const QString &server, const QString &victim ); - QString ThereAreNoAdmins( const QString &server ); - QString ThereIsAdmin( const QString &server ); - QString ThereAreAdmins( const QString &server, const QString &count ); - QString ThereAreNoBannedUsers( const QString &server ); - QString ThereIsBannedUser( const QString &server ); - QString ThereAreBannedUsers( const QString &server, const QString &count ); - QString YouCantDeleteTheRootAdmin( ); - QString DeletedUserFromAdminDatabase( const QString &server, const QString &user ); - QString ErrorDeletingUserFromAdminDatabase( const QString &server, const QString &user ); - QString UnbannedUser( const QString &victim ); - QString ErrorUnbanningUser( const QString &victim ); - QString GameNumberIs( const QString &number, const QString &description ); - QString GameNumberDoesntExist( const QString &number ); - QString GameIsInTheLobby( const QString &description, const QString ¤t, const QString &max ); - QString ThereIsNoGameInTheLobby( const QString ¤t, const QString &max ); - QString UnableToLoadConfigFilesOutside( ); - QString LoadingConfigFile( const QString &file ); - QString UnableToLoadConfigFileDoesntExist( const QString &file ); - QString CreatingPrivateGame( const QString &gamename, const QString &user ); - QString CreatingPublicGame( const QString &gamename, const QString &user ); - QString UnableToUnhostGameCountdownStarted( const QString &description ); - QString UnhostingGame( const QString &description ); - QString UnableToUnhostGameNoGameInLobby( ); - QString VersionAdmin( const QString &version ); - QString VersionNotAdmin( const QString &version ); - QString UnableToCreateGameAnotherGameInLobby( const QString &gamename, const QString &description ); - QString UnableToCreateGameMaxGamesReached( const QString &gamename, const QString &max ); - QString GameIsOver( const QString &description ); - QString SpoofCheckByReplying( ); - QString GameRefreshed( ); - QString SpoofPossibleIsAway( const QString &user ); - QString SpoofPossibleIsUnavailable( const QString &user ); - QString SpoofPossibleIsRefusingMessages( const QString &user ); - QString SpoofDetectedIsNotInGame( const QString &user ); - QString SpoofDetectedIsInPrivateChannel( const QString &user ); - QString SpoofDetectedIsInAnotherGame( const QString &user ); - QString CountDownAborted( ); - QString TryingToJoinTheGameButBanned( const QString &victim ); - QString UnableToBanNoMatchesFound( const QString &victim ); - QString PlayerWasBannedByPlayer( const QString &server, const QString &victim, const QString &user ); - QString UnableToBanFoundMoreThanOneMatch( const QString &victim ); - QString AddedPlayerToTheHoldList( const QString &user ); - QString UnableToKickNoMatchesFound( const QString &victim ); - QString UnableToKickFoundMoreThanOneMatch( const QString &victim ); - QString SettingLatencyToMinimum( const QString &min ); - QString SettingLatencyToMaximum( const QString &max ); - QString SettingLatencyTo( const QString &latency ); - QString KickingPlayersWithPingsGreaterThan( const QString &total, const QString &ping ); - QString HasPlayedGamesWithThisBot( const QString &user, const QString &firstgame, const QString &lastgame, const QString &totalgames, const QString &avgloadingtime, const QString &avgstay ); - QString HasntPlayedGamesWithThisBot( const QString &user ); - QString AutokickingPlayerForExcessivePing( const QString &victim, const QString &ping ); - QString SpoofCheckAcceptedFor( const QString &server, const QString &user ); - QString PlayersNotYetSpoofChecked( const QString ¬spoofchecked ); - QString ManuallySpoofCheckByWhispering( const QString &hostname ); - QString SpoofCheckByWhispering( const QString &hostname ); - QString EveryoneHasBeenSpoofChecked( ); - QString PlayersNotYetPinged( const QString ¬pinged ); - QString EveryoneHasBeenPinged( ); - QString ShortestLoadByPlayer( const QString &user, const QString &loadingtime ); - QString LongestLoadByPlayer( const QString &user, const QString &loadingtime ); - QString YourLoadingTimeWas( const QString &loadingtime ); - QString HasPlayedDotAGamesWithThisBot( const QString &user, const QString &totalgames, const QString &totalwins, const QString &totallosses, const QString &totalkills, const QString &totaldeaths, const QString &totalcreepkills, const QString &totalcreepdenies, const QString &totalassists, const QString &totalneutralkills, const QString &totaltowerkills, const QString &totalraxkills, const QString &totalcourierkills, const QString &avgkills, const QString &avgdeaths, const QString &avgcreepkills, const QString &avgcreepdenies, const QString &avgassists, const QString &avgneutralkills, const QString &avgtowerkills, const QString &avgraxkills, const QString &avgcourierkills ); - QString HasntPlayedDotAGamesWithThisBot( const QString &user ); - QString WasKickedForReservedPlayer( const QString &reserved ); - QString WasKickedForOwnerPlayer( const QString &owner ); - QString WasKickedByPlayer( const QString &user ); - QString HasLostConnectionPlayerError( const QString &error ); - QString HasLostConnectionSocketError( const QString &error ); - QString HasLostConnectionClosedByRemoteHost( ); - QString HasLeftVoluntarily( ); - QString EndingGame( const QString &description ); - QString HasLostConnectionTimedOut( ); - QString GlobalChatMuted( ); - QString GlobalChatUnmuted( ); - QString ShufflingPlayers( ); - QString UnableToLoadConfigFileGameInLobby( ); - QString PlayersStillDownloading( const QString &stilldownloading ); - QString RefreshMessagesEnabled( ); - QString RefreshMessagesDisabled( ); - QString AtLeastOneGameActiveUseForceToShutdown( ); - QString CurrentlyLoadedMapCFGIs( const QString &mapcfg ); - QString LaggedOutDroppedByAdmin( ); - QString LaggedOutDroppedByVote( ); - QString PlayerVotedToDropLaggers( const QString &user ); - QString LatencyIs( const QString &latency ); - QString SyncLimitIs( const QString &synclimit ); - QString SettingSyncLimitToMinimum( const QString &min ); - QString SettingSyncLimitToMaximum( const QString &max ); - QString SettingSyncLimitTo( const QString &synclimit ); - QString UnableToCreateGameNotLoggedIn( const QString &gamename ); - QString AdminLoggedIn( ); - QString AdminInvalidPassword( const QString &attempt ); - QString ConnectingToBNET( const QString &server ); - QString ConnectedToBNET( const QString &server ); - QString DisconnectedFromBNET( const QString &server ); - QString LoggedInToBNET( const QString &server ); - QString BNETGameHostingSucceeded( const QString &server ); - QString BNETGameHostingFailed( const QString &server, const QString &gamename ); - QString ConnectingToBNETTimedOut( const QString &server ); - QString PlayerDownloadedTheMap( const QString &user, const QString &seconds, const QString &rate ); - QString UnableToCreateGameNameTooLong( const QString &gamename ); - QString SettingGameOwnerTo( const QString &owner ); - QString TheGameIsLocked( ); - QString GameLocked( ); - QString GameUnlocked( ); - QString UnableToStartDownloadNoMatchesFound( const QString &victim ); - QString UnableToStartDownloadFoundMoreThanOneMatch( const QString &victim ); - QString UnableToSetGameOwner( const QString &owner ); - QString UnableToCheckPlayerNoMatchesFound( const QString &victim ); - QString CheckedPlayer( const QString &victim, const QString &ping, const QString &from, const QString &admin, const QString &owner, const QString &spoofed, const QString &spoofedrealm, const QString &reserved ); - QString UnableToCheckPlayerFoundMoreThanOneMatch( const QString &victim ); - QString TheGameIsLockedBNET( ); - QString UnableToCreateGameDisabled( const QString &gamename ); - QString BotDisabled( ); - QString BotEnabled( ); - QString UnableToCreateGameInvalidMap( const QString &gamename ); - QString WaitingForPlayersBeforeAutoStart( const QString &players, const QString &playersleft ); - QString AutoStartDisabled( ); - QString AutoStartEnabled( const QString &players ); - QString AnnounceMessageEnabled( ); - QString AnnounceMessageDisabled( ); - QString AutoHostEnabled( ); - QString AutoHostDisabled( ); - QString UnableToLoadSaveGamesOutside( ); - QString UnableToLoadSaveGameGameInLobby( ); - QString LoadingSaveGame( const QString &file ); - QString UnableToLoadSaveGameDoesntExist( const QString &file ); - QString UnableToCreateGameInvalidSaveGame( const QString &gamename ); - QString UnableToCreateGameSaveGameMapMismatch( const QString &gamename ); - QString AutoSaveEnabled( ); - QString AutoSaveDisabled( ); - QString DesyncDetected( ); - QString UnableToMuteNoMatchesFound( const QString &victim ); - QString MutedPlayer( const QString &victim, const QString &user ); - QString UnmutedPlayer( const QString &victim, const QString &user ); - QString UnableToMuteFoundMoreThanOneMatch( const QString &victim ); - QString PlayerIsSavingTheGame( const QString &player ); - QString UpdatingClanList( ); - QString UpdatingFriendsList( ); - QString MultipleIPAddressUsageDetected( const QString &player, const QString &others ); - QString UnableToVoteKickAlreadyInProgress( ); - QString UnableToVoteKickNotEnoughPlayers( ); - QString UnableToVoteKickNoMatchesFound( const QString &victim ); - QString UnableToVoteKickPlayerIsReserved( const QString &victim ); - QString StartedVoteKick( const QString &victim, const QString &user, const QString &votesneeded ); - QString UnableToVoteKickFoundMoreThanOneMatch( const QString &victim ); - QString VoteKickPassed( const QString &victim ); - QString ErrorVoteKickingPlayer( const QString &victim ); - QString VoteKickAcceptedNeedMoreVotes( const QString &victim, const QString &user, const QString &votes ); - QString VoteKickCancelled( const QString &victim ); - QString VoteKickExpired( const QString &victim ); - QString WasKickedByVote( ); - QString TypeYesToVote( const QString &commandtrigger ); - QString PlayersNotYetPingedAutoStart( const QString ¬pinged ); - QString WasKickedForNotSpoofChecking( ); - QString WasKickedForHavingFurthestScore( const QString &score, const QString &average ); - QString PlayerHasScore( const QString &player, const QString &score ); - QString RatedPlayersSpread( const QString &rated, const QString &total, const QString &spread ); - QString ErrorListingMaps( ); - QString FoundMaps( const QString &maps ); - QString NoMapsFound( ); - QString ErrorListingMapConfigs( ); - QString FoundMapConfigs( const QString &mapconfigs ); - QString NoMapConfigsFound( ); - QString PlayerFinishedLoading( const QString &user ); - QString PleaseWaitPlayersStillLoading( ); - QString MapDownloadsDisabled( ); - QString MapDownloadsEnabled( ); - QString MapDownloadsConditional( ); - QString SettingHCL( const QString &HCL ); - QString UnableToSetHCLInvalid( ); - QString UnableToSetHCLTooLong( ); - QString TheHCLIs( const QString &HCL ); - QString TheHCLIsTooLongUseForceToStart( ); - QString ClearingHCL( ); - QString TryingToRehostAsPrivateGame( const QString &gamename ); - QString TryingToRehostAsPublicGame( const QString &gamename ); - QString RehostWasSuccessful( ); - QString TryingToJoinTheGameButBannedByName( const QString &victim ); - QString TryingToJoinTheGameButBannedByIP( const QString &victim, const QString &ip, const QString &bannedname ); - QString HasBannedName( const QString &victim ); - QString HasBannedIP( const QString &victim, const QString &ip, const QString &bannedname ); - QString PlayersInGameState( const QString &number, const QString &players ); - QString ValidServers( const QString &servers ); - QString TeamCombinedScore( const QString &team, const QString &score ); - QString BalancingSlotsCompleted( ); - QString PlayerWasKickedForFurthestScore( const QString &name, const QString &score, const QString &average ); - QString LocalAdminMessagesEnabled( ); - QString LocalAdminMessagesDisabled( ); - QString WasDroppedDesync( ); - QString WasKickedForHavingLowestScore( const QString &score ); - QString PlayerWasKickedForLowestScore( const QString &name, const QString &score ); - QString ReloadingConfigurationFiles( ); - QString CountDownAbortedSomeoneLeftRecently( ); - QString UnableToCreateGameMustEnforceFirst( const QString &gamename ); - QString UnableToLoadReplaysOutside( ); - QString LoadingReplay( const QString &file ); - QString UnableToLoadReplayDoesntExist( const QString &file ); - QString CommandTrigger( const QString &trigger ); - QString CantEndGameOwnerIsStillPlaying( const QString &owner ); - QString CantUnhostGameOwnerIsPresent( const QString &owner ); - QString WasAutomaticallyDroppedAfterSeconds( const QString &seconds ); - QString HasLostConnectionTimedOutGProxy( ); - QString HasLostConnectionSocketErrorGProxy( const QString &error ); - QString HasLostConnectionClosedByRemoteHostGProxy( ); - QString WaitForReconnectSecondsRemain( const QString &seconds ); - QString WasUnrecoverablyDroppedFromGProxy( ); - QString PlayerReconnectedWithGProxy( const QString &name ); -}; - -#endif diff --git a/mysql/include/mysql/config-win.h b/include/mysql/config-win.h similarity index 100% rename from mysql/include/mysql/config-win.h rename to include/mysql/config-win.h diff --git a/mysql/include/mysql/decimal.h b/include/mysql/decimal.h similarity index 100% rename from mysql/include/mysql/decimal.h rename to include/mysql/decimal.h diff --git a/mysql/include/mysql/errmsg.h b/include/mysql/errmsg.h similarity index 100% rename from mysql/include/mysql/errmsg.h rename to include/mysql/errmsg.h diff --git a/mysql/include/mysql/keycache.h b/include/mysql/keycache.h similarity index 100% rename from mysql/include/mysql/keycache.h rename to include/mysql/keycache.h diff --git a/mysql/include/mysql/libmysql.def b/include/mysql/libmysql.def similarity index 100% rename from mysql/include/mysql/libmysql.def rename to include/mysql/libmysql.def diff --git a/mysql/include/mysql/libmysqld.def b/include/mysql/libmysqld.def similarity index 100% rename from mysql/include/mysql/libmysqld.def rename to include/mysql/libmysqld.def diff --git a/mysql/include/mysql/m_ctype.h b/include/mysql/m_ctype.h similarity index 100% rename from mysql/include/mysql/m_ctype.h rename to include/mysql/m_ctype.h diff --git a/mysql/include/mysql/m_string.h b/include/mysql/m_string.h similarity index 100% rename from mysql/include/mysql/m_string.h rename to include/mysql/m_string.h diff --git a/mysql/include/mysql/my_alloc.h b/include/mysql/my_alloc.h similarity index 100% rename from mysql/include/mysql/my_alloc.h rename to include/mysql/my_alloc.h diff --git a/mysql/include/mysql/my_attribute.h b/include/mysql/my_attribute.h similarity index 100% rename from mysql/include/mysql/my_attribute.h rename to include/mysql/my_attribute.h diff --git a/mysql/include/mysql/my_dbug.h b/include/mysql/my_dbug.h similarity index 100% rename from mysql/include/mysql/my_dbug.h rename to include/mysql/my_dbug.h diff --git a/mysql/include/mysql/my_dir.h b/include/mysql/my_dir.h similarity index 100% rename from mysql/include/mysql/my_dir.h rename to include/mysql/my_dir.h diff --git a/mysql/include/mysql/my_getopt.h b/include/mysql/my_getopt.h similarity index 100% rename from mysql/include/mysql/my_getopt.h rename to include/mysql/my_getopt.h diff --git a/mysql/include/mysql/my_global.h b/include/mysql/my_global.h similarity index 100% rename from mysql/include/mysql/my_global.h rename to include/mysql/my_global.h diff --git a/mysql/include/mysql/my_list.h b/include/mysql/my_list.h similarity index 100% rename from mysql/include/mysql/my_list.h rename to include/mysql/my_list.h diff --git a/mysql/include/mysql/my_net.h b/include/mysql/my_net.h similarity index 100% rename from mysql/include/mysql/my_net.h rename to include/mysql/my_net.h diff --git a/mysql/include/mysql/my_no_pthread.h b/include/mysql/my_no_pthread.h similarity index 100% rename from mysql/include/mysql/my_no_pthread.h rename to include/mysql/my_no_pthread.h diff --git a/mysql/include/mysql/my_pthread.h b/include/mysql/my_pthread.h similarity index 100% rename from mysql/include/mysql/my_pthread.h rename to include/mysql/my_pthread.h diff --git a/mysql/include/mysql/my_sys.h b/include/mysql/my_sys.h similarity index 100% rename from mysql/include/mysql/my_sys.h rename to include/mysql/my_sys.h diff --git a/mysql/include/mysql/my_xml.h b/include/mysql/my_xml.h similarity index 100% rename from mysql/include/mysql/my_xml.h rename to include/mysql/my_xml.h diff --git a/mysql/include/mysql/mysql.h b/include/mysql/mysql.h similarity index 100% rename from mysql/include/mysql/mysql.h rename to include/mysql/mysql.h diff --git a/mysql/include/mysql/mysql/plugin.h b/include/mysql/mysql/plugin.h similarity index 100% rename from mysql/include/mysql/mysql/plugin.h rename to include/mysql/mysql/plugin.h diff --git a/mysql/include/mysql/mysql_com.h b/include/mysql/mysql_com.h similarity index 100% rename from mysql/include/mysql/mysql_com.h rename to include/mysql/mysql_com.h diff --git a/mysql/include/mysql/mysql_embed.h b/include/mysql/mysql_embed.h similarity index 100% rename from mysql/include/mysql/mysql_embed.h rename to include/mysql/mysql_embed.h diff --git a/mysql/include/mysql/mysql_time.h b/include/mysql/mysql_time.h similarity index 100% rename from mysql/include/mysql/mysql_time.h rename to include/mysql/mysql_time.h diff --git a/mysql/include/mysql/mysql_version.h b/include/mysql/mysql_version.h similarity index 100% rename from mysql/include/mysql/mysql_version.h rename to include/mysql/mysql_version.h diff --git a/mysql/include/mysql/mysqld_ername.h b/include/mysql/mysqld_ername.h similarity index 100% rename from mysql/include/mysql/mysqld_ername.h rename to include/mysql/mysqld_ername.h diff --git a/mysql/include/mysql/mysqld_error.h b/include/mysql/mysqld_error.h similarity index 100% rename from mysql/include/mysql/mysqld_error.h rename to include/mysql/mysqld_error.h diff --git a/mysql/include/mysql/sql_common.h b/include/mysql/sql_common.h similarity index 100% rename from mysql/include/mysql/sql_common.h rename to include/mysql/sql_common.h diff --git a/mysql/include/mysql/sql_state.h b/include/mysql/sql_state.h similarity index 100% rename from mysql/include/mysql/sql_state.h rename to include/mysql/sql_state.h diff --git a/mysql/include/mysql/sslopt-case.h b/include/mysql/sslopt-case.h similarity index 100% rename from mysql/include/mysql/sslopt-case.h rename to include/mysql/sslopt-case.h diff --git a/mysql/include/mysql/sslopt-longopts.h b/include/mysql/sslopt-longopts.h similarity index 100% rename from mysql/include/mysql/sslopt-longopts.h rename to include/mysql/sslopt-longopts.h diff --git a/mysql/include/mysql/sslopt-vars.h b/include/mysql/sslopt-vars.h similarity index 100% rename from mysql/include/mysql/sslopt-vars.h rename to include/mysql/sslopt-vars.h diff --git a/mysql/include/mysql/typelib.h b/include/mysql/typelib.h similarity index 100% rename from mysql/include/mysql/typelib.h rename to include/mysql/typelib.h diff --git a/zlib/include/zconf.h b/include/zlib/zconf.h similarity index 100% rename from zlib/include/zconf.h rename to include/zlib/zconf.h diff --git a/zlib/include/zlib.h b/include/zlib/zlib.h similarity index 100% rename from zlib/include/zlib.h rename to include/zlib/zlib.h diff --git a/BNCSutil.dll b/lib/BNCSutil.dll similarity index 100% rename from BNCSutil.dll rename to lib/BNCSutil.dll diff --git a/libmysql.dll b/lib/libmysql.dll similarity index 100% rename from libmysql.dll rename to lib/libmysql.dll diff --git a/zlib1.dll b/lib/zlib1.dll similarity index 100% rename from zlib1.dll rename to lib/zlib1.dll diff --git a/mysql/lib/opt/libmysql.lib b/mysql/lib/opt/libmysql.lib deleted file mode 100644 index 0608eff3049a778e739fd0f3f940983c6136a279..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34876 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 diff --git a/StormLib/Info.plist b/src/StormLib/Info.plist similarity index 100% rename from StormLib/Info.plist rename to src/StormLib/Info.plist diff --git a/StormLib/Storm.lib b/src/StormLib/Storm.lib similarity index 100% rename from StormLib/Storm.lib rename to src/StormLib/Storm.lib diff --git a/StormLib/StormDll.bat b/src/StormLib/StormDll.bat similarity index 100% rename from StormLib/StormDll.bat rename to src/StormLib/StormDll.bat diff --git a/StormLib/StormDll.sln b/src/StormLib/StormDll.sln similarity index 100% rename from StormLib/StormDll.sln rename to src/StormLib/StormDll.sln diff --git a/StormLib/StormDll.vcproj b/src/StormLib/StormDll.vcproj similarity index 100% rename from StormLib/StormDll.vcproj rename to src/StormLib/StormDll.vcproj diff --git a/StormLib/StormLib-Info.plist b/src/StormLib/StormLib-Info.plist similarity index 100% rename from StormLib/StormLib-Info.plist rename to src/StormLib/StormLib-Info.plist diff --git a/StormLib/StormLib.bat b/src/StormLib/StormLib.bat similarity index 100% rename from StormLib/StormLib.bat rename to src/StormLib/StormLib.bat diff --git a/StormLib/StormLib.sln b/src/StormLib/StormLib.sln similarity index 100% rename from StormLib/StormLib.sln rename to src/StormLib/StormLib.sln diff --git a/StormLib/StormLib.vcproj b/src/StormLib/StormLib.vcproj similarity index 100% rename from StormLib/StormLib.vcproj rename to src/StormLib/StormLib.vcproj diff --git a/StormLib/StormLib.xcodeproj/project.pbxproj b/src/StormLib/StormLib.xcodeproj/project.pbxproj similarity index 100% rename from StormLib/StormLib.xcodeproj/project.pbxproj rename to src/StormLib/StormLib.xcodeproj/project.pbxproj diff --git a/StormLib/StormLib64-Info.plist b/src/StormLib/StormLib64-Info.plist similarity index 100% rename from StormLib/StormLib64-Info.plist rename to src/StormLib/StormLib64-Info.plist diff --git a/StormLib/StormLibDll.sln b/src/StormLib/StormLibDll.sln similarity index 100% rename from StormLib/StormLibDll.sln rename to src/StormLib/StormLibDll.sln diff --git a/StormLib/StormLibDll.vcproj b/src/StormLib/StormLibDll.vcproj similarity index 100% rename from StormLib/StormLibDll.vcproj rename to src/StormLib/StormLibDll.vcproj diff --git a/StormLib/StormLibTest.sln b/src/StormLib/StormLibTest.sln similarity index 100% rename from StormLib/StormLibTest.sln rename to src/StormLib/StormLibTest.sln diff --git a/StormLib/StormLibTest.vcproj b/src/StormLib/StormLibTest.vcproj similarity index 100% rename from StormLib/StormLibTest.vcproj rename to src/StormLib/StormLibTest.vcproj diff --git a/StormLib/doc/History.txt b/src/StormLib/doc/History.txt similarity index 100% rename from StormLib/doc/History.txt rename to src/StormLib/doc/History.txt diff --git a/StormLib/doc/The MoPaQ File Format 0.9.txt b/src/StormLib/doc/The MoPaQ File Format 0.9.txt similarity index 100% rename from StormLib/doc/The MoPaQ File Format 0.9.txt rename to src/StormLib/doc/The MoPaQ File Format 0.9.txt diff --git a/StormLib/doc/The MoPaQ File Format 1.0.txt b/src/StormLib/doc/The MoPaQ File Format 1.0.txt similarity index 100% rename from StormLib/doc/The MoPaQ File Format 1.0.txt rename to src/StormLib/doc/The MoPaQ File Format 1.0.txt diff --git a/StormLib/storm.dll b/src/StormLib/storm.dll similarity index 100% rename from StormLib/storm.dll rename to src/StormLib/storm.dll diff --git a/StormLib/stormdll/StormDll.cpp b/src/StormLib/stormdll/StormDll.cpp similarity index 100% rename from StormLib/stormdll/StormDll.cpp rename to src/StormLib/stormdll/StormDll.cpp diff --git a/StormLib/stormdll/StormDll.def b/src/StormLib/stormdll/StormDll.def similarity index 100% rename from StormLib/stormdll/StormDll.def rename to src/StormLib/stormdll/StormDll.def diff --git a/StormLib/stormdll/StormDll.h b/src/StormLib/stormdll/StormDll.h similarity index 100% rename from StormLib/stormdll/StormDll.h rename to src/StormLib/stormdll/StormDll.h diff --git a/StormLib/stormlib/GfxDecode.cpp b/src/StormLib/stormlib/GfxDecode.cpp similarity index 100% rename from StormLib/stormlib/GfxDecode.cpp rename to src/StormLib/stormlib/GfxDecode.cpp diff --git a/StormLib/stormlib/Makefile b/src/StormLib/stormlib/Makefile similarity index 100% rename from StormLib/stormlib/Makefile rename to src/StormLib/stormlib/Makefile diff --git a/StormLib/stormlib/SAttrFile.cpp b/src/StormLib/stormlib/SAttrFile.cpp similarity index 100% rename from StormLib/stormlib/SAttrFile.cpp rename to src/StormLib/stormlib/SAttrFile.cpp diff --git a/StormLib/stormlib/SCommon.cpp b/src/StormLib/stormlib/SCommon.cpp similarity index 100% rename from StormLib/stormlib/SCommon.cpp rename to src/StormLib/stormlib/SCommon.cpp diff --git a/StormLib/stormlib/SCommon.h b/src/StormLib/stormlib/SCommon.h similarity index 100% rename from StormLib/stormlib/SCommon.h rename to src/StormLib/stormlib/SCommon.h diff --git a/StormLib/stormlib/SCompression.cpp b/src/StormLib/stormlib/SCompression.cpp similarity index 100% rename from StormLib/stormlib/SCompression.cpp rename to src/StormLib/stormlib/SCompression.cpp diff --git a/StormLib/stormlib/SCompression_new.cpp b/src/StormLib/stormlib/SCompression_new.cpp similarity index 100% rename from StormLib/stormlib/SCompression_new.cpp rename to src/StormLib/stormlib/SCompression_new.cpp diff --git a/StormLib/stormlib/SCompression_old.cpp b/src/StormLib/stormlib/SCompression_old.cpp similarity index 100% rename from StormLib/stormlib/SCompression_old.cpp rename to src/StormLib/stormlib/SCompression_old.cpp diff --git a/StormLib/stormlib/SFileCompactArchive.cpp b/src/StormLib/stormlib/SFileCompactArchive.cpp similarity index 100% rename from StormLib/stormlib/SFileCompactArchive.cpp rename to src/StormLib/stormlib/SFileCompactArchive.cpp diff --git a/StormLib/stormlib/SFileCreateArchiveEx.cpp b/src/StormLib/stormlib/SFileCreateArchiveEx.cpp similarity index 100% rename from StormLib/stormlib/SFileCreateArchiveEx.cpp rename to src/StormLib/stormlib/SFileCreateArchiveEx.cpp diff --git a/StormLib/stormlib/SFileExtractFile.cpp b/src/StormLib/stormlib/SFileExtractFile.cpp similarity index 100% rename from StormLib/stormlib/SFileExtractFile.cpp rename to src/StormLib/stormlib/SFileExtractFile.cpp diff --git a/StormLib/stormlib/SFileFindFile.cpp b/src/StormLib/stormlib/SFileFindFile.cpp similarity index 100% rename from StormLib/stormlib/SFileFindFile.cpp rename to src/StormLib/stormlib/SFileFindFile.cpp diff --git a/StormLib/stormlib/SFileOpenArchive.cpp b/src/StormLib/stormlib/SFileOpenArchive.cpp similarity index 100% rename from StormLib/stormlib/SFileOpenArchive.cpp rename to src/StormLib/stormlib/SFileOpenArchive.cpp diff --git a/StormLib/stormlib/SFileOpenFileEx.cpp b/src/StormLib/stormlib/SFileOpenFileEx.cpp similarity index 100% rename from StormLib/stormlib/SFileOpenFileEx.cpp rename to src/StormLib/stormlib/SFileOpenFileEx.cpp diff --git a/StormLib/stormlib/SFileReadFile.cpp b/src/StormLib/stormlib/SFileReadFile.cpp similarity index 100% rename from StormLib/stormlib/SFileReadFile.cpp rename to src/StormLib/stormlib/SFileReadFile.cpp diff --git a/StormLib/stormlib/SListFile.cpp b/src/StormLib/stormlib/SListFile.cpp similarity index 100% rename from StormLib/stormlib/SListFile.cpp rename to src/StormLib/stormlib/SListFile.cpp diff --git a/StormLib/stormlib/StormDll.h b/src/StormLib/stormlib/StormDll.h similarity index 100% rename from StormLib/stormlib/StormDll.h rename to src/StormLib/stormlib/StormDll.h diff --git a/StormLib/stormlib/StormLib.h b/src/StormLib/stormlib/StormLib.h similarity index 100% rename from StormLib/stormlib/StormLib.h rename to src/StormLib/stormlib/StormLib.h diff --git a/StormLib/stormlib/StormPort.h b/src/StormLib/stormlib/StormPort.h similarity index 100% rename from StormLib/stormlib/StormPort.h rename to src/StormLib/stormlib/StormPort.h diff --git a/StormLib/stormlib/StormPortLinux.cpp b/src/StormLib/stormlib/StormPortLinux.cpp similarity index 100% rename from StormLib/stormlib/StormPortLinux.cpp rename to src/StormLib/stormlib/StormPortLinux.cpp diff --git a/StormLib/stormlib/StormPortMac.cpp b/src/StormLib/stormlib/StormPortMac.cpp similarity index 100% rename from StormLib/stormlib/StormPortMac.cpp rename to src/StormLib/stormlib/StormPortMac.cpp diff --git a/StormLib/stormlib/bzip2/CHANGES b/src/StormLib/stormlib/bzip2/CHANGES similarity index 100% rename from StormLib/stormlib/bzip2/CHANGES rename to src/StormLib/stormlib/bzip2/CHANGES diff --git a/StormLib/stormlib/bzip2/LICENSE b/src/StormLib/stormlib/bzip2/LICENSE similarity index 100% rename from StormLib/stormlib/bzip2/LICENSE rename to src/StormLib/stormlib/bzip2/LICENSE diff --git a/StormLib/stormlib/bzip2/Makefile b/src/StormLib/stormlib/bzip2/Makefile similarity index 100% rename from StormLib/stormlib/bzip2/Makefile rename to src/StormLib/stormlib/bzip2/Makefile diff --git a/StormLib/stormlib/bzip2/Makefile-libbz2_so b/src/StormLib/stormlib/bzip2/Makefile-libbz2_so similarity index 100% rename from StormLib/stormlib/bzip2/Makefile-libbz2_so rename to src/StormLib/stormlib/bzip2/Makefile-libbz2_so diff --git a/StormLib/stormlib/bzip2/README b/src/StormLib/stormlib/bzip2/README similarity index 100% rename from StormLib/stormlib/bzip2/README rename to src/StormLib/stormlib/bzip2/README diff --git a/StormLib/stormlib/bzip2/README.COMPILATION.PROBLEMS b/src/StormLib/stormlib/bzip2/README.COMPILATION.PROBLEMS similarity index 100% rename from StormLib/stormlib/bzip2/README.COMPILATION.PROBLEMS rename to src/StormLib/stormlib/bzip2/README.COMPILATION.PROBLEMS diff --git a/StormLib/stormlib/bzip2/README.XML.STUFF b/src/StormLib/stormlib/bzip2/README.XML.STUFF similarity index 100% rename from StormLib/stormlib/bzip2/README.XML.STUFF rename to src/StormLib/stormlib/bzip2/README.XML.STUFF diff --git a/StormLib/stormlib/bzip2/Y2K_INFO b/src/StormLib/stormlib/bzip2/Y2K_INFO similarity index 100% rename from StormLib/stormlib/bzip2/Y2K_INFO rename to src/StormLib/stormlib/bzip2/Y2K_INFO diff --git a/StormLib/stormlib/bzip2/blocksort.c b/src/StormLib/stormlib/bzip2/blocksort.c similarity index 100% rename from StormLib/stormlib/bzip2/blocksort.c rename to src/StormLib/stormlib/bzip2/blocksort.c diff --git a/StormLib/stormlib/bzip2/bz-common.xsl b/src/StormLib/stormlib/bzip2/bz-common.xsl similarity index 100% rename from StormLib/stormlib/bzip2/bz-common.xsl rename to src/StormLib/stormlib/bzip2/bz-common.xsl diff --git a/StormLib/stormlib/bzip2/bz-fo.xsl b/src/StormLib/stormlib/bzip2/bz-fo.xsl similarity index 100% rename from StormLib/stormlib/bzip2/bz-fo.xsl rename to src/StormLib/stormlib/bzip2/bz-fo.xsl diff --git a/StormLib/stormlib/bzip2/bz-html.xsl b/src/StormLib/stormlib/bzip2/bz-html.xsl similarity index 100% rename from StormLib/stormlib/bzip2/bz-html.xsl rename to src/StormLib/stormlib/bzip2/bz-html.xsl diff --git a/StormLib/stormlib/bzip2/bzdiff b/src/StormLib/stormlib/bzip2/bzdiff similarity index 100% rename from StormLib/stormlib/bzip2/bzdiff rename to src/StormLib/stormlib/bzip2/bzdiff diff --git a/StormLib/stormlib/bzip2/bzdiff.1 b/src/StormLib/stormlib/bzip2/bzdiff.1 similarity index 100% rename from StormLib/stormlib/bzip2/bzdiff.1 rename to src/StormLib/stormlib/bzip2/bzdiff.1 diff --git a/StormLib/stormlib/bzip2/bzgrep b/src/StormLib/stormlib/bzip2/bzgrep similarity index 100% rename from StormLib/stormlib/bzip2/bzgrep rename to src/StormLib/stormlib/bzip2/bzgrep diff --git a/StormLib/stormlib/bzip2/bzgrep.1 b/src/StormLib/stormlib/bzip2/bzgrep.1 similarity index 100% rename from StormLib/stormlib/bzip2/bzgrep.1 rename to src/StormLib/stormlib/bzip2/bzgrep.1 diff --git a/StormLib/stormlib/bzip2/bzip.css b/src/StormLib/stormlib/bzip2/bzip.css similarity index 100% rename from StormLib/stormlib/bzip2/bzip.css rename to src/StormLib/stormlib/bzip2/bzip.css diff --git a/StormLib/stormlib/bzip2/bzip2.1 b/src/StormLib/stormlib/bzip2/bzip2.1 similarity index 100% rename from StormLib/stormlib/bzip2/bzip2.1 rename to src/StormLib/stormlib/bzip2/bzip2.1 diff --git a/StormLib/stormlib/bzip2/bzip2.1.preformatted b/src/StormLib/stormlib/bzip2/bzip2.1.preformatted similarity index 100% rename from StormLib/stormlib/bzip2/bzip2.1.preformatted rename to src/StormLib/stormlib/bzip2/bzip2.1.preformatted diff --git a/StormLib/stormlib/bzip2/bzip2.c b/src/StormLib/stormlib/bzip2/bzip2.c similarity index 100% rename from StormLib/stormlib/bzip2/bzip2.c rename to src/StormLib/stormlib/bzip2/bzip2.c diff --git a/StormLib/stormlib/bzip2/bzip2.txt b/src/StormLib/stormlib/bzip2/bzip2.txt similarity index 100% rename from StormLib/stormlib/bzip2/bzip2.txt rename to src/StormLib/stormlib/bzip2/bzip2.txt diff --git a/StormLib/stormlib/bzip2/bzip2recover.c b/src/StormLib/stormlib/bzip2/bzip2recover.c similarity index 100% rename from StormLib/stormlib/bzip2/bzip2recover.c rename to src/StormLib/stormlib/bzip2/bzip2recover.c diff --git a/StormLib/stormlib/bzip2/bzlib.c b/src/StormLib/stormlib/bzip2/bzlib.c similarity index 100% rename from StormLib/stormlib/bzip2/bzlib.c rename to src/StormLib/stormlib/bzip2/bzlib.c diff --git a/StormLib/stormlib/bzip2/bzlib.h b/src/StormLib/stormlib/bzip2/bzlib.h similarity index 100% rename from StormLib/stormlib/bzip2/bzlib.h rename to src/StormLib/stormlib/bzip2/bzlib.h diff --git a/StormLib/stormlib/bzip2/bzlib_private.h b/src/StormLib/stormlib/bzip2/bzlib_private.h similarity index 100% rename from StormLib/stormlib/bzip2/bzlib_private.h rename to src/StormLib/stormlib/bzip2/bzlib_private.h diff --git a/StormLib/stormlib/bzip2/bzmore b/src/StormLib/stormlib/bzip2/bzmore similarity index 100% rename from StormLib/stormlib/bzip2/bzmore rename to src/StormLib/stormlib/bzip2/bzmore diff --git a/StormLib/stormlib/bzip2/bzmore.1 b/src/StormLib/stormlib/bzip2/bzmore.1 similarity index 100% rename from StormLib/stormlib/bzip2/bzmore.1 rename to src/StormLib/stormlib/bzip2/bzmore.1 diff --git a/StormLib/stormlib/bzip2/compress.c b/src/StormLib/stormlib/bzip2/compress.c similarity index 100% rename from StormLib/stormlib/bzip2/compress.c rename to src/StormLib/stormlib/bzip2/compress.c diff --git a/StormLib/stormlib/bzip2/crctable.c b/src/StormLib/stormlib/bzip2/crctable.c similarity index 100% rename from StormLib/stormlib/bzip2/crctable.c rename to src/StormLib/stormlib/bzip2/crctable.c diff --git a/StormLib/stormlib/bzip2/decompress.c b/src/StormLib/stormlib/bzip2/decompress.c similarity index 100% rename from StormLib/stormlib/bzip2/decompress.c rename to src/StormLib/stormlib/bzip2/decompress.c diff --git a/StormLib/stormlib/bzip2/dlltest.c b/src/StormLib/stormlib/bzip2/dlltest.c similarity index 100% rename from StormLib/stormlib/bzip2/dlltest.c rename to src/StormLib/stormlib/bzip2/dlltest.c diff --git a/StormLib/stormlib/bzip2/dlltest.dsp b/src/StormLib/stormlib/bzip2/dlltest.dsp similarity index 100% rename from StormLib/stormlib/bzip2/dlltest.dsp rename to src/StormLib/stormlib/bzip2/dlltest.dsp diff --git a/StormLib/stormlib/bzip2/entities.xml b/src/StormLib/stormlib/bzip2/entities.xml similarity index 100% rename from StormLib/stormlib/bzip2/entities.xml rename to src/StormLib/stormlib/bzip2/entities.xml diff --git a/StormLib/stormlib/bzip2/format.pl b/src/StormLib/stormlib/bzip2/format.pl similarity index 100% rename from StormLib/stormlib/bzip2/format.pl rename to src/StormLib/stormlib/bzip2/format.pl diff --git a/StormLib/stormlib/bzip2/huffman.c b/src/StormLib/stormlib/bzip2/huffman.c similarity index 100% rename from StormLib/stormlib/bzip2/huffman.c rename to src/StormLib/stormlib/bzip2/huffman.c diff --git a/StormLib/stormlib/bzip2/libbz2.def b/src/StormLib/stormlib/bzip2/libbz2.def similarity index 100% rename from StormLib/stormlib/bzip2/libbz2.def rename to src/StormLib/stormlib/bzip2/libbz2.def diff --git a/StormLib/stormlib/bzip2/libbz2.dsp b/src/StormLib/stormlib/bzip2/libbz2.dsp similarity index 100% rename from StormLib/stormlib/bzip2/libbz2.dsp rename to src/StormLib/stormlib/bzip2/libbz2.dsp diff --git a/StormLib/stormlib/bzip2/makefile.msc b/src/StormLib/stormlib/bzip2/makefile.msc similarity index 100% rename from StormLib/stormlib/bzip2/makefile.msc rename to src/StormLib/stormlib/bzip2/makefile.msc diff --git a/StormLib/stormlib/bzip2/manual.html b/src/StormLib/stormlib/bzip2/manual.html similarity index 100% rename from StormLib/stormlib/bzip2/manual.html rename to src/StormLib/stormlib/bzip2/manual.html diff --git a/StormLib/stormlib/bzip2/manual.pdf b/src/StormLib/stormlib/bzip2/manual.pdf similarity index 100% rename from StormLib/stormlib/bzip2/manual.pdf rename to src/StormLib/stormlib/bzip2/manual.pdf diff --git a/StormLib/stormlib/bzip2/manual.ps b/src/StormLib/stormlib/bzip2/manual.ps similarity index 100% rename from StormLib/stormlib/bzip2/manual.ps rename to src/StormLib/stormlib/bzip2/manual.ps diff --git a/StormLib/stormlib/bzip2/manual.xml b/src/StormLib/stormlib/bzip2/manual.xml similarity index 100% rename from StormLib/stormlib/bzip2/manual.xml rename to src/StormLib/stormlib/bzip2/manual.xml diff --git a/StormLib/stormlib/bzip2/mk251.c b/src/StormLib/stormlib/bzip2/mk251.c similarity index 100% rename from StormLib/stormlib/bzip2/mk251.c rename to src/StormLib/stormlib/bzip2/mk251.c diff --git a/StormLib/stormlib/bzip2/randtable.c b/src/StormLib/stormlib/bzip2/randtable.c similarity index 100% rename from StormLib/stormlib/bzip2/randtable.c rename to src/StormLib/stormlib/bzip2/randtable.c diff --git a/StormLib/stormlib/bzip2/sample1.bz2 b/src/StormLib/stormlib/bzip2/sample1.bz2 similarity index 100% rename from StormLib/stormlib/bzip2/sample1.bz2 rename to src/StormLib/stormlib/bzip2/sample1.bz2 diff --git a/StormLib/stormlib/bzip2/sample1.ref b/src/StormLib/stormlib/bzip2/sample1.ref similarity index 100% rename from StormLib/stormlib/bzip2/sample1.ref rename to src/StormLib/stormlib/bzip2/sample1.ref diff --git a/StormLib/stormlib/bzip2/sample2.bz2 b/src/StormLib/stormlib/bzip2/sample2.bz2 similarity index 100% rename from StormLib/stormlib/bzip2/sample2.bz2 rename to src/StormLib/stormlib/bzip2/sample2.bz2 diff --git a/StormLib/stormlib/bzip2/sample2.ref b/src/StormLib/stormlib/bzip2/sample2.ref similarity index 100% rename from StormLib/stormlib/bzip2/sample2.ref rename to src/StormLib/stormlib/bzip2/sample2.ref diff --git a/StormLib/stormlib/bzip2/sample3.bz2 b/src/StormLib/stormlib/bzip2/sample3.bz2 similarity index 100% rename from StormLib/stormlib/bzip2/sample3.bz2 rename to src/StormLib/stormlib/bzip2/sample3.bz2 diff --git a/StormLib/stormlib/bzip2/sample3.ref b/src/StormLib/stormlib/bzip2/sample3.ref similarity index 100% rename from StormLib/stormlib/bzip2/sample3.ref rename to src/StormLib/stormlib/bzip2/sample3.ref diff --git a/StormLib/stormlib/bzip2/spewG.c b/src/StormLib/stormlib/bzip2/spewG.c similarity index 100% rename from StormLib/stormlib/bzip2/spewG.c rename to src/StormLib/stormlib/bzip2/spewG.c diff --git a/StormLib/stormlib/bzip2/unzcrash.c b/src/StormLib/stormlib/bzip2/unzcrash.c similarity index 100% rename from StormLib/stormlib/bzip2/unzcrash.c rename to src/StormLib/stormlib/bzip2/unzcrash.c diff --git a/StormLib/stormlib/bzip2/words0 b/src/StormLib/stormlib/bzip2/words0 similarity index 100% rename from StormLib/stormlib/bzip2/words0 rename to src/StormLib/stormlib/bzip2/words0 diff --git a/StormLib/stormlib/bzip2/words1 b/src/StormLib/stormlib/bzip2/words1 similarity index 100% rename from StormLib/stormlib/bzip2/words1 rename to src/StormLib/stormlib/bzip2/words1 diff --git a/StormLib/stormlib/bzip2/words2 b/src/StormLib/stormlib/bzip2/words2 similarity index 100% rename from StormLib/stormlib/bzip2/words2 rename to src/StormLib/stormlib/bzip2/words2 diff --git a/StormLib/stormlib/bzip2/words3 b/src/StormLib/stormlib/bzip2/words3 similarity index 100% rename from StormLib/stormlib/bzip2/words3 rename to src/StormLib/stormlib/bzip2/words3 diff --git a/StormLib/stormlib/bzip2/xmlproc.sh b/src/StormLib/stormlib/bzip2/xmlproc.sh similarity index 100% rename from StormLib/stormlib/bzip2/xmlproc.sh rename to src/StormLib/stormlib/bzip2/xmlproc.sh diff --git a/StormLib/stormlib/huffman/huff.cpp b/src/StormLib/stormlib/huffman/huff.cpp similarity index 100% rename from StormLib/stormlib/huffman/huff.cpp rename to src/StormLib/stormlib/huffman/huff.cpp diff --git a/StormLib/stormlib/huffman/huff.h b/src/StormLib/stormlib/huffman/huff.h similarity index 100% rename from StormLib/stormlib/huffman/huff.h rename to src/StormLib/stormlib/huffman/huff.h diff --git a/StormLib/stormlib/misc/crc32.cpp b/src/StormLib/stormlib/misc/crc32.cpp similarity index 100% rename from StormLib/stormlib/misc/crc32.cpp rename to src/StormLib/stormlib/misc/crc32.cpp diff --git a/StormLib/stormlib/misc/crc32.h b/src/StormLib/stormlib/misc/crc32.h similarity index 100% rename from StormLib/stormlib/misc/crc32.h rename to src/StormLib/stormlib/misc/crc32.h diff --git a/StormLib/stormlib/misc/md5.cpp b/src/StormLib/stormlib/misc/md5.cpp similarity index 100% rename from StormLib/stormlib/misc/md5.cpp rename to src/StormLib/stormlib/misc/md5.cpp diff --git a/StormLib/stormlib/misc/md5.h b/src/StormLib/stormlib/misc/md5.h similarity index 100% rename from StormLib/stormlib/misc/md5.h rename to src/StormLib/stormlib/misc/md5.h diff --git a/StormLib/stormlib/pklib/crc32.c b/src/StormLib/stormlib/pklib/crc32.c similarity index 100% rename from StormLib/stormlib/pklib/crc32.c rename to src/StormLib/stormlib/pklib/crc32.c diff --git a/StormLib/stormlib/pklib/explode.c b/src/StormLib/stormlib/pklib/explode.c similarity index 100% rename from StormLib/stormlib/pklib/explode.c rename to src/StormLib/stormlib/pklib/explode.c diff --git a/StormLib/stormlib/pklib/implode.c b/src/StormLib/stormlib/pklib/implode.c similarity index 100% rename from StormLib/stormlib/pklib/implode.c rename to src/StormLib/stormlib/pklib/implode.c diff --git a/StormLib/stormlib/pklib/pklib.h b/src/StormLib/stormlib/pklib/pklib.h similarity index 100% rename from StormLib/stormlib/pklib/pklib.h rename to src/StormLib/stormlib/pklib/pklib.h diff --git a/StormLib/stormlib/wave/wave.cpp b/src/StormLib/stormlib/wave/wave.cpp similarity index 100% rename from StormLib/stormlib/wave/wave.cpp rename to src/StormLib/stormlib/wave/wave.cpp diff --git a/StormLib/stormlib/wave/wave.h b/src/StormLib/stormlib/wave/wave.h similarity index 100% rename from StormLib/stormlib/wave/wave.h rename to src/StormLib/stormlib/wave/wave.h diff --git a/StormLib/stormlib/zlib/ChangeLog b/src/StormLib/stormlib/zlib/ChangeLog similarity index 100% rename from StormLib/stormlib/zlib/ChangeLog rename to src/StormLib/stormlib/zlib/ChangeLog diff --git a/StormLib/stormlib/zlib/FAQ b/src/StormLib/stormlib/zlib/FAQ similarity index 100% rename from StormLib/stormlib/zlib/FAQ rename to src/StormLib/stormlib/zlib/FAQ diff --git a/StormLib/stormlib/zlib/INDEX b/src/StormLib/stormlib/zlib/INDEX similarity index 100% rename from StormLib/stormlib/zlib/INDEX rename to src/StormLib/stormlib/zlib/INDEX diff --git a/StormLib/stormlib/zlib/Makefile b/src/StormLib/stormlib/zlib/Makefile similarity index 100% rename from StormLib/stormlib/zlib/Makefile rename to src/StormLib/stormlib/zlib/Makefile diff --git a/StormLib/stormlib/zlib/Makefile.in b/src/StormLib/stormlib/zlib/Makefile.in similarity index 100% rename from StormLib/stormlib/zlib/Makefile.in rename to src/StormLib/stormlib/zlib/Makefile.in diff --git a/StormLib/stormlib/zlib/README b/src/StormLib/stormlib/zlib/README similarity index 100% rename from StormLib/stormlib/zlib/README rename to src/StormLib/stormlib/zlib/README diff --git a/StormLib/stormlib/zlib/adler32.c b/src/StormLib/stormlib/zlib/adler32.c similarity index 100% rename from StormLib/stormlib/zlib/adler32.c rename to src/StormLib/stormlib/zlib/adler32.c diff --git a/StormLib/stormlib/zlib/algorithm.txt b/src/StormLib/stormlib/zlib/algorithm.txt similarity index 100% rename from StormLib/stormlib/zlib/algorithm.txt rename to src/StormLib/stormlib/zlib/algorithm.txt diff --git a/StormLib/stormlib/zlib/amiga/Makefile.pup b/src/StormLib/stormlib/zlib/amiga/Makefile.pup similarity index 100% rename from StormLib/stormlib/zlib/amiga/Makefile.pup rename to src/StormLib/stormlib/zlib/amiga/Makefile.pup diff --git a/StormLib/stormlib/zlib/amiga/Makefile.sas b/src/StormLib/stormlib/zlib/amiga/Makefile.sas similarity index 100% rename from StormLib/stormlib/zlib/amiga/Makefile.sas rename to src/StormLib/stormlib/zlib/amiga/Makefile.sas diff --git a/StormLib/stormlib/zlib/as400/bndsrc b/src/StormLib/stormlib/zlib/as400/bndsrc similarity index 100% rename from StormLib/stormlib/zlib/as400/bndsrc rename to src/StormLib/stormlib/zlib/as400/bndsrc diff --git a/StormLib/stormlib/zlib/as400/compile.clp b/src/StormLib/stormlib/zlib/as400/compile.clp similarity index 100% rename from StormLib/stormlib/zlib/as400/compile.clp rename to src/StormLib/stormlib/zlib/as400/compile.clp diff --git a/StormLib/stormlib/zlib/as400/readme.txt b/src/StormLib/stormlib/zlib/as400/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/as400/readme.txt rename to src/StormLib/stormlib/zlib/as400/readme.txt diff --git a/StormLib/stormlib/zlib/as400/zlib.inc b/src/StormLib/stormlib/zlib/as400/zlib.inc similarity index 100% rename from StormLib/stormlib/zlib/as400/zlib.inc rename to src/StormLib/stormlib/zlib/as400/zlib.inc diff --git a/StormLib/stormlib/zlib/compress.c b/src/StormLib/stormlib/zlib/compress.c similarity index 100% rename from StormLib/stormlib/zlib/compress.c rename to src/StormLib/stormlib/zlib/compress.c diff --git a/StormLib/stormlib/zlib/configure b/src/StormLib/stormlib/zlib/configure similarity index 100% rename from StormLib/stormlib/zlib/configure rename to src/StormLib/stormlib/zlib/configure diff --git a/StormLib/stormlib/zlib/contrib/README.contrib b/src/StormLib/stormlib/zlib/contrib/README.contrib similarity index 100% rename from StormLib/stormlib/zlib/contrib/README.contrib rename to src/StormLib/stormlib/zlib/contrib/README.contrib diff --git a/StormLib/stormlib/zlib/contrib/ada/buffer_demo.adb b/src/StormLib/stormlib/zlib/contrib/ada/buffer_demo.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/buffer_demo.adb rename to src/StormLib/stormlib/zlib/contrib/ada/buffer_demo.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/mtest.adb b/src/StormLib/stormlib/zlib/contrib/ada/mtest.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/mtest.adb rename to src/StormLib/stormlib/zlib/contrib/ada/mtest.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/read.adb b/src/StormLib/stormlib/zlib/contrib/ada/read.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/read.adb rename to src/StormLib/stormlib/zlib/contrib/ada/read.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/readme.txt b/src/StormLib/stormlib/zlib/contrib/ada/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/readme.txt rename to src/StormLib/stormlib/zlib/contrib/ada/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/ada/test.adb b/src/StormLib/stormlib/zlib/contrib/ada/test.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/test.adb rename to src/StormLib/stormlib/zlib/contrib/ada/test.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib-streams.adb b/src/StormLib/stormlib/zlib/contrib/ada/zlib-streams.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib-streams.adb rename to src/StormLib/stormlib/zlib/contrib/ada/zlib-streams.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib-streams.ads b/src/StormLib/stormlib/zlib/contrib/ada/zlib-streams.ads similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib-streams.ads rename to src/StormLib/stormlib/zlib/contrib/ada/zlib-streams.ads diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib-thin.adb b/src/StormLib/stormlib/zlib/contrib/ada/zlib-thin.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib-thin.adb rename to src/StormLib/stormlib/zlib/contrib/ada/zlib-thin.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib-thin.ads b/src/StormLib/stormlib/zlib/contrib/ada/zlib-thin.ads similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib-thin.ads rename to src/StormLib/stormlib/zlib/contrib/ada/zlib-thin.ads diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib.adb b/src/StormLib/stormlib/zlib/contrib/ada/zlib.adb similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib.adb rename to src/StormLib/stormlib/zlib/contrib/ada/zlib.adb diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib.ads b/src/StormLib/stormlib/zlib/contrib/ada/zlib.ads similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib.ads rename to src/StormLib/stormlib/zlib/contrib/ada/zlib.ads diff --git a/StormLib/stormlib/zlib/contrib/ada/zlib.gpr b/src/StormLib/stormlib/zlib/contrib/ada/zlib.gpr similarity index 100% rename from StormLib/stormlib/zlib/contrib/ada/zlib.gpr rename to src/StormLib/stormlib/zlib/contrib/ada/zlib.gpr diff --git a/StormLib/stormlib/zlib/contrib/asm586/README.586 b/src/StormLib/stormlib/zlib/contrib/asm586/README.586 similarity index 100% rename from StormLib/stormlib/zlib/contrib/asm586/README.586 rename to src/StormLib/stormlib/zlib/contrib/asm586/README.586 diff --git a/StormLib/stormlib/zlib/contrib/asm586/match.S b/src/StormLib/stormlib/zlib/contrib/asm586/match.S similarity index 100% rename from StormLib/stormlib/zlib/contrib/asm586/match.S rename to src/StormLib/stormlib/zlib/contrib/asm586/match.S diff --git a/StormLib/stormlib/zlib/contrib/asm686/README.686 b/src/StormLib/stormlib/zlib/contrib/asm686/README.686 similarity index 100% rename from StormLib/stormlib/zlib/contrib/asm686/README.686 rename to src/StormLib/stormlib/zlib/contrib/asm686/README.686 diff --git a/StormLib/stormlib/zlib/contrib/asm686/match.S b/src/StormLib/stormlib/zlib/contrib/asm686/match.S similarity index 100% rename from StormLib/stormlib/zlib/contrib/asm686/match.S rename to src/StormLib/stormlib/zlib/contrib/asm686/match.S diff --git a/StormLib/stormlib/zlib/contrib/blast/Makefile b/src/StormLib/stormlib/zlib/contrib/blast/Makefile similarity index 100% rename from StormLib/stormlib/zlib/contrib/blast/Makefile rename to src/StormLib/stormlib/zlib/contrib/blast/Makefile diff --git a/StormLib/stormlib/zlib/contrib/blast/README b/src/StormLib/stormlib/zlib/contrib/blast/README similarity index 100% rename from StormLib/stormlib/zlib/contrib/blast/README rename to src/StormLib/stormlib/zlib/contrib/blast/README diff --git a/StormLib/stormlib/zlib/contrib/blast/blast.c b/src/StormLib/stormlib/zlib/contrib/blast/blast.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/blast/blast.c rename to src/StormLib/stormlib/zlib/contrib/blast/blast.c diff --git a/StormLib/stormlib/zlib/contrib/blast/blast.h b/src/StormLib/stormlib/zlib/contrib/blast/blast.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/blast/blast.h rename to src/StormLib/stormlib/zlib/contrib/blast/blast.h diff --git a/StormLib/stormlib/zlib/contrib/blast/test.pk b/src/StormLib/stormlib/zlib/contrib/blast/test.pk similarity index 100% rename from StormLib/stormlib/zlib/contrib/blast/test.pk rename to src/StormLib/stormlib/zlib/contrib/blast/test.pk diff --git a/StormLib/stormlib/zlib/contrib/blast/test.txt b/src/StormLib/stormlib/zlib/contrib/blast/test.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/blast/test.txt rename to src/StormLib/stormlib/zlib/contrib/blast/test.txt diff --git a/StormLib/stormlib/zlib/contrib/delphi/ZLib.pas b/src/StormLib/stormlib/zlib/contrib/delphi/ZLib.pas similarity index 100% rename from StormLib/stormlib/zlib/contrib/delphi/ZLib.pas rename to src/StormLib/stormlib/zlib/contrib/delphi/ZLib.pas diff --git a/StormLib/stormlib/zlib/contrib/delphi/ZLibConst.pas b/src/StormLib/stormlib/zlib/contrib/delphi/ZLibConst.pas similarity index 100% rename from StormLib/stormlib/zlib/contrib/delphi/ZLibConst.pas rename to src/StormLib/stormlib/zlib/contrib/delphi/ZLibConst.pas diff --git a/StormLib/stormlib/zlib/contrib/delphi/readme.txt b/src/StormLib/stormlib/zlib/contrib/delphi/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/delphi/readme.txt rename to src/StormLib/stormlib/zlib/contrib/delphi/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/delphi/zlibd32.mak b/src/StormLib/stormlib/zlib/contrib/delphi/zlibd32.mak similarity index 100% rename from StormLib/stormlib/zlib/contrib/delphi/zlibd32.mak rename to src/StormLib/stormlib/zlib/contrib/delphi/zlibd32.mak diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.build b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.build similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.build rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.build diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.chm b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.chm similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.chm rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.chm diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.sln b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.sln similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.sln rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib.sln diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Deflater.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Deflater.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Deflater.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Deflater.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Inflater.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Inflater.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Inflater.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/Inflater.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs rename to src/StormLib/stormlib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/LICENSE_1_0.txt b/src/StormLib/stormlib/zlib/contrib/dotzlib/LICENSE_1_0.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/LICENSE_1_0.txt rename to src/StormLib/stormlib/zlib/contrib/dotzlib/LICENSE_1_0.txt diff --git a/StormLib/stormlib/zlib/contrib/dotzlib/readme.txt b/src/StormLib/stormlib/zlib/contrib/dotzlib/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/dotzlib/readme.txt rename to src/StormLib/stormlib/zlib/contrib/dotzlib/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/infback9/README b/src/StormLib/stormlib/zlib/contrib/infback9/README similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/README rename to src/StormLib/stormlib/zlib/contrib/infback9/README diff --git a/StormLib/stormlib/zlib/contrib/infback9/infback9.c b/src/StormLib/stormlib/zlib/contrib/infback9/infback9.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/infback9.c rename to src/StormLib/stormlib/zlib/contrib/infback9/infback9.c diff --git a/StormLib/stormlib/zlib/contrib/infback9/infback9.h b/src/StormLib/stormlib/zlib/contrib/infback9/infback9.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/infback9.h rename to src/StormLib/stormlib/zlib/contrib/infback9/infback9.h diff --git a/StormLib/stormlib/zlib/contrib/infback9/inffix9.h b/src/StormLib/stormlib/zlib/contrib/infback9/inffix9.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/inffix9.h rename to src/StormLib/stormlib/zlib/contrib/infback9/inffix9.h diff --git a/StormLib/stormlib/zlib/contrib/infback9/inflate9.h b/src/StormLib/stormlib/zlib/contrib/infback9/inflate9.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/inflate9.h rename to src/StormLib/stormlib/zlib/contrib/infback9/inflate9.h diff --git a/StormLib/stormlib/zlib/contrib/infback9/inftree9.c b/src/StormLib/stormlib/zlib/contrib/infback9/inftree9.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/inftree9.c rename to src/StormLib/stormlib/zlib/contrib/infback9/inftree9.c diff --git a/StormLib/stormlib/zlib/contrib/infback9/inftree9.h b/src/StormLib/stormlib/zlib/contrib/infback9/inftree9.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/infback9/inftree9.h rename to src/StormLib/stormlib/zlib/contrib/infback9/inftree9.h diff --git a/StormLib/stormlib/zlib/contrib/inflate86/inffas86.c b/src/StormLib/stormlib/zlib/contrib/inflate86/inffas86.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/inflate86/inffas86.c rename to src/StormLib/stormlib/zlib/contrib/inflate86/inffas86.c diff --git a/StormLib/stormlib/zlib/contrib/inflate86/inffast.S b/src/StormLib/stormlib/zlib/contrib/inflate86/inffast.S similarity index 100% rename from StormLib/stormlib/zlib/contrib/inflate86/inffast.S rename to src/StormLib/stormlib/zlib/contrib/inflate86/inffast.S diff --git a/StormLib/stormlib/zlib/contrib/iostream/test.cpp b/src/StormLib/stormlib/zlib/contrib/iostream/test.cpp similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream/test.cpp rename to src/StormLib/stormlib/zlib/contrib/iostream/test.cpp diff --git a/StormLib/stormlib/zlib/contrib/iostream/zfstream.cpp b/src/StormLib/stormlib/zlib/contrib/iostream/zfstream.cpp similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream/zfstream.cpp rename to src/StormLib/stormlib/zlib/contrib/iostream/zfstream.cpp diff --git a/StormLib/stormlib/zlib/contrib/iostream/zfstream.h b/src/StormLib/stormlib/zlib/contrib/iostream/zfstream.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream/zfstream.h rename to src/StormLib/stormlib/zlib/contrib/iostream/zfstream.h diff --git a/StormLib/stormlib/zlib/contrib/iostream2/zstream.h b/src/StormLib/stormlib/zlib/contrib/iostream2/zstream.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream2/zstream.h rename to src/StormLib/stormlib/zlib/contrib/iostream2/zstream.h diff --git a/StormLib/stormlib/zlib/contrib/iostream2/zstream_test.cpp b/src/StormLib/stormlib/zlib/contrib/iostream2/zstream_test.cpp similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream2/zstream_test.cpp rename to src/StormLib/stormlib/zlib/contrib/iostream2/zstream_test.cpp diff --git a/StormLib/stormlib/zlib/contrib/iostream3/README b/src/StormLib/stormlib/zlib/contrib/iostream3/README similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream3/README rename to src/StormLib/stormlib/zlib/contrib/iostream3/README diff --git a/StormLib/stormlib/zlib/contrib/iostream3/TODO b/src/StormLib/stormlib/zlib/contrib/iostream3/TODO similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream3/TODO rename to src/StormLib/stormlib/zlib/contrib/iostream3/TODO diff --git a/StormLib/stormlib/zlib/contrib/iostream3/test.cc b/src/StormLib/stormlib/zlib/contrib/iostream3/test.cc similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream3/test.cc rename to src/StormLib/stormlib/zlib/contrib/iostream3/test.cc diff --git a/StormLib/stormlib/zlib/contrib/iostream3/zfstream.cc b/src/StormLib/stormlib/zlib/contrib/iostream3/zfstream.cc similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream3/zfstream.cc rename to src/StormLib/stormlib/zlib/contrib/iostream3/zfstream.cc diff --git a/StormLib/stormlib/zlib/contrib/iostream3/zfstream.h b/src/StormLib/stormlib/zlib/contrib/iostream3/zfstream.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/iostream3/zfstream.h rename to src/StormLib/stormlib/zlib/contrib/iostream3/zfstream.h diff --git a/StormLib/stormlib/zlib/contrib/masm686/match.asm b/src/StormLib/stormlib/zlib/contrib/masm686/match.asm similarity index 100% rename from StormLib/stormlib/zlib/contrib/masm686/match.asm rename to src/StormLib/stormlib/zlib/contrib/masm686/match.asm diff --git a/StormLib/stormlib/zlib/contrib/masmx64/bld_ml64.bat b/src/StormLib/stormlib/zlib/contrib/masmx64/bld_ml64.bat similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx64/bld_ml64.bat rename to src/StormLib/stormlib/zlib/contrib/masmx64/bld_ml64.bat diff --git a/StormLib/stormlib/zlib/contrib/masmx64/gvmat64.asm b/src/StormLib/stormlib/zlib/contrib/masmx64/gvmat64.asm similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx64/gvmat64.asm rename to src/StormLib/stormlib/zlib/contrib/masmx64/gvmat64.asm diff --git a/StormLib/stormlib/zlib/contrib/masmx64/inffas8664.c b/src/StormLib/stormlib/zlib/contrib/masmx64/inffas8664.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx64/inffas8664.c rename to src/StormLib/stormlib/zlib/contrib/masmx64/inffas8664.c diff --git a/StormLib/stormlib/zlib/contrib/masmx64/inffasx64.asm b/src/StormLib/stormlib/zlib/contrib/masmx64/inffasx64.asm similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx64/inffasx64.asm rename to src/StormLib/stormlib/zlib/contrib/masmx64/inffasx64.asm diff --git a/StormLib/stormlib/zlib/contrib/masmx64/readme.txt b/src/StormLib/stormlib/zlib/contrib/masmx64/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx64/readme.txt rename to src/StormLib/stormlib/zlib/contrib/masmx64/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/masmx86/bld_ml32.bat b/src/StormLib/stormlib/zlib/contrib/masmx86/bld_ml32.bat similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx86/bld_ml32.bat rename to src/StormLib/stormlib/zlib/contrib/masmx86/bld_ml32.bat diff --git a/StormLib/stormlib/zlib/contrib/masmx86/gvmat32.asm b/src/StormLib/stormlib/zlib/contrib/masmx86/gvmat32.asm similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx86/gvmat32.asm rename to src/StormLib/stormlib/zlib/contrib/masmx86/gvmat32.asm diff --git a/StormLib/stormlib/zlib/contrib/masmx86/gvmat32c.c b/src/StormLib/stormlib/zlib/contrib/masmx86/gvmat32c.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx86/gvmat32c.c rename to src/StormLib/stormlib/zlib/contrib/masmx86/gvmat32c.c diff --git a/StormLib/stormlib/zlib/contrib/masmx86/inffas32.asm b/src/StormLib/stormlib/zlib/contrib/masmx86/inffas32.asm similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx86/inffas32.asm rename to src/StormLib/stormlib/zlib/contrib/masmx86/inffas32.asm diff --git a/StormLib/stormlib/zlib/contrib/masmx86/mkasm.bat b/src/StormLib/stormlib/zlib/contrib/masmx86/mkasm.bat similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx86/mkasm.bat rename to src/StormLib/stormlib/zlib/contrib/masmx86/mkasm.bat diff --git a/StormLib/stormlib/zlib/contrib/masmx86/readme.txt b/src/StormLib/stormlib/zlib/contrib/masmx86/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/masmx86/readme.txt rename to src/StormLib/stormlib/zlib/contrib/masmx86/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/minizip/ChangeLogUnzip b/src/StormLib/stormlib/zlib/contrib/minizip/ChangeLogUnzip similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/ChangeLogUnzip rename to src/StormLib/stormlib/zlib/contrib/minizip/ChangeLogUnzip diff --git a/StormLib/stormlib/zlib/contrib/minizip/Makefile b/src/StormLib/stormlib/zlib/contrib/minizip/Makefile similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/Makefile rename to src/StormLib/stormlib/zlib/contrib/minizip/Makefile diff --git a/StormLib/stormlib/zlib/contrib/minizip/crypt.h b/src/StormLib/stormlib/zlib/contrib/minizip/crypt.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/crypt.h rename to src/StormLib/stormlib/zlib/contrib/minizip/crypt.h diff --git a/StormLib/stormlib/zlib/contrib/minizip/ioapi.c b/src/StormLib/stormlib/zlib/contrib/minizip/ioapi.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/ioapi.c rename to src/StormLib/stormlib/zlib/contrib/minizip/ioapi.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/ioapi.h b/src/StormLib/stormlib/zlib/contrib/minizip/ioapi.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/ioapi.h rename to src/StormLib/stormlib/zlib/contrib/minizip/ioapi.h diff --git a/StormLib/stormlib/zlib/contrib/minizip/iowin32.c b/src/StormLib/stormlib/zlib/contrib/minizip/iowin32.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/iowin32.c rename to src/StormLib/stormlib/zlib/contrib/minizip/iowin32.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/iowin32.h b/src/StormLib/stormlib/zlib/contrib/minizip/iowin32.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/iowin32.h rename to src/StormLib/stormlib/zlib/contrib/minizip/iowin32.h diff --git a/StormLib/stormlib/zlib/contrib/minizip/miniunz.c b/src/StormLib/stormlib/zlib/contrib/minizip/miniunz.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/miniunz.c rename to src/StormLib/stormlib/zlib/contrib/minizip/miniunz.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/minizip.c b/src/StormLib/stormlib/zlib/contrib/minizip/minizip.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/minizip.c rename to src/StormLib/stormlib/zlib/contrib/minizip/minizip.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/mztools.c b/src/StormLib/stormlib/zlib/contrib/minizip/mztools.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/mztools.c rename to src/StormLib/stormlib/zlib/contrib/minizip/mztools.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/mztools.h b/src/StormLib/stormlib/zlib/contrib/minizip/mztools.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/mztools.h rename to src/StormLib/stormlib/zlib/contrib/minizip/mztools.h diff --git a/StormLib/stormlib/zlib/contrib/minizip/unzip.c b/src/StormLib/stormlib/zlib/contrib/minizip/unzip.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/unzip.c rename to src/StormLib/stormlib/zlib/contrib/minizip/unzip.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/unzip.h b/src/StormLib/stormlib/zlib/contrib/minizip/unzip.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/unzip.h rename to src/StormLib/stormlib/zlib/contrib/minizip/unzip.h diff --git a/StormLib/stormlib/zlib/contrib/minizip/zip.c b/src/StormLib/stormlib/zlib/contrib/minizip/zip.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/zip.c rename to src/StormLib/stormlib/zlib/contrib/minizip/zip.c diff --git a/StormLib/stormlib/zlib/contrib/minizip/zip.h b/src/StormLib/stormlib/zlib/contrib/minizip/zip.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/minizip/zip.h rename to src/StormLib/stormlib/zlib/contrib/minizip/zip.h diff --git a/StormLib/stormlib/zlib/contrib/pascal/example.pas b/src/StormLib/stormlib/zlib/contrib/pascal/example.pas similarity index 100% rename from StormLib/stormlib/zlib/contrib/pascal/example.pas rename to src/StormLib/stormlib/zlib/contrib/pascal/example.pas diff --git a/StormLib/stormlib/zlib/contrib/pascal/readme.txt b/src/StormLib/stormlib/zlib/contrib/pascal/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/pascal/readme.txt rename to src/StormLib/stormlib/zlib/contrib/pascal/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/pascal/zlibd32.mak b/src/StormLib/stormlib/zlib/contrib/pascal/zlibd32.mak similarity index 100% rename from StormLib/stormlib/zlib/contrib/pascal/zlibd32.mak rename to src/StormLib/stormlib/zlib/contrib/pascal/zlibd32.mak diff --git a/StormLib/stormlib/zlib/contrib/pascal/zlibpas.pas b/src/StormLib/stormlib/zlib/contrib/pascal/zlibpas.pas similarity index 100% rename from StormLib/stormlib/zlib/contrib/pascal/zlibpas.pas rename to src/StormLib/stormlib/zlib/contrib/pascal/zlibpas.pas diff --git a/StormLib/stormlib/zlib/contrib/puff/Makefile b/src/StormLib/stormlib/zlib/contrib/puff/Makefile similarity index 100% rename from StormLib/stormlib/zlib/contrib/puff/Makefile rename to src/StormLib/stormlib/zlib/contrib/puff/Makefile diff --git a/StormLib/stormlib/zlib/contrib/puff/README b/src/StormLib/stormlib/zlib/contrib/puff/README similarity index 100% rename from StormLib/stormlib/zlib/contrib/puff/README rename to src/StormLib/stormlib/zlib/contrib/puff/README diff --git a/StormLib/stormlib/zlib/contrib/puff/puff.c b/src/StormLib/stormlib/zlib/contrib/puff/puff.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/puff/puff.c rename to src/StormLib/stormlib/zlib/contrib/puff/puff.c diff --git a/StormLib/stormlib/zlib/contrib/puff/puff.h b/src/StormLib/stormlib/zlib/contrib/puff/puff.h similarity index 100% rename from StormLib/stormlib/zlib/contrib/puff/puff.h rename to src/StormLib/stormlib/zlib/contrib/puff/puff.h diff --git a/StormLib/stormlib/zlib/contrib/puff/zeros.raw b/src/StormLib/stormlib/zlib/contrib/puff/zeros.raw similarity index 100% rename from StormLib/stormlib/zlib/contrib/puff/zeros.raw rename to src/StormLib/stormlib/zlib/contrib/puff/zeros.raw diff --git a/StormLib/stormlib/zlib/contrib/testzlib/testzlib.c b/src/StormLib/stormlib/zlib/contrib/testzlib/testzlib.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/testzlib/testzlib.c rename to src/StormLib/stormlib/zlib/contrib/testzlib/testzlib.c diff --git a/StormLib/stormlib/zlib/contrib/testzlib/testzlib.txt b/src/StormLib/stormlib/zlib/contrib/testzlib/testzlib.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/testzlib/testzlib.txt rename to src/StormLib/stormlib/zlib/contrib/testzlib/testzlib.txt diff --git a/StormLib/stormlib/zlib/contrib/untgz/Makefile b/src/StormLib/stormlib/zlib/contrib/untgz/Makefile similarity index 100% rename from StormLib/stormlib/zlib/contrib/untgz/Makefile rename to src/StormLib/stormlib/zlib/contrib/untgz/Makefile diff --git a/StormLib/stormlib/zlib/contrib/untgz/Makefile.msc b/src/StormLib/stormlib/zlib/contrib/untgz/Makefile.msc similarity index 100% rename from StormLib/stormlib/zlib/contrib/untgz/Makefile.msc rename to src/StormLib/stormlib/zlib/contrib/untgz/Makefile.msc diff --git a/StormLib/stormlib/zlib/contrib/untgz/untgz.c b/src/StormLib/stormlib/zlib/contrib/untgz/untgz.c similarity index 100% rename from StormLib/stormlib/zlib/contrib/untgz/untgz.c rename to src/StormLib/stormlib/zlib/contrib/untgz/untgz.c diff --git a/StormLib/stormlib/zlib/contrib/vstudio/readme.txt b/src/StormLib/stormlib/zlib/contrib/vstudio/readme.txt similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/readme.txt rename to src/StormLib/stormlib/zlib/contrib/vstudio/readme.txt diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/miniunz.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/miniunz.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/miniunz.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/miniunz.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/minizip.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/minizip.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/minizip.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/minizip.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/testzlib.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/testzlib.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/testzlib.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/testzlib.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlib.rc b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlib.rc similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/zlib.rc rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlib.rc diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibstat.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibstat.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibstat.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibstat.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.def b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.def similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.def rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.def diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.sln b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.sln similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.sln rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.sln diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc7/zlibvc.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/miniunz.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/miniunz.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/miniunz.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/miniunz.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/minizip.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/minizip.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/minizip.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/minizip.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlib.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlib.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlib.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlib.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlibdll.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlibdll.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlibdll.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/testzlibdll.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlib.rc b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlib.rc similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/zlib.rc rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlib.rc diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibstat.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibstat.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibstat.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibstat.vcproj diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.def b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.def similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.def rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.def diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.sln b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.sln similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.sln rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.sln diff --git a/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.vcproj b/src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.vcproj similarity index 100% rename from StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.vcproj rename to src/StormLib/stormlib/zlib/contrib/vstudio/vc8/zlibvc.vcproj diff --git a/StormLib/stormlib/zlib/crc32.c b/src/StormLib/stormlib/zlib/crc32.c similarity index 100% rename from StormLib/stormlib/zlib/crc32.c rename to src/StormLib/stormlib/zlib/crc32.c diff --git a/StormLib/stormlib/zlib/crc32.h b/src/StormLib/stormlib/zlib/crc32.h similarity index 100% rename from StormLib/stormlib/zlib/crc32.h rename to src/StormLib/stormlib/zlib/crc32.h diff --git a/StormLib/stormlib/zlib/deflate.c b/src/StormLib/stormlib/zlib/deflate.c similarity index 100% rename from StormLib/stormlib/zlib/deflate.c rename to src/StormLib/stormlib/zlib/deflate.c diff --git a/StormLib/stormlib/zlib/deflate.h b/src/StormLib/stormlib/zlib/deflate.h similarity index 100% rename from StormLib/stormlib/zlib/deflate.h rename to src/StormLib/stormlib/zlib/deflate.h diff --git a/StormLib/stormlib/zlib/example.c b/src/StormLib/stormlib/zlib/example.c similarity index 100% rename from StormLib/stormlib/zlib/example.c rename to src/StormLib/stormlib/zlib/example.c diff --git a/StormLib/stormlib/zlib/examples/README.examples b/src/StormLib/stormlib/zlib/examples/README.examples similarity index 100% rename from StormLib/stormlib/zlib/examples/README.examples rename to src/StormLib/stormlib/zlib/examples/README.examples diff --git a/StormLib/stormlib/zlib/examples/fitblk.c b/src/StormLib/stormlib/zlib/examples/fitblk.c similarity index 100% rename from StormLib/stormlib/zlib/examples/fitblk.c rename to src/StormLib/stormlib/zlib/examples/fitblk.c diff --git a/StormLib/stormlib/zlib/examples/gun.c b/src/StormLib/stormlib/zlib/examples/gun.c similarity index 100% rename from StormLib/stormlib/zlib/examples/gun.c rename to src/StormLib/stormlib/zlib/examples/gun.c diff --git a/StormLib/stormlib/zlib/examples/gzappend.c b/src/StormLib/stormlib/zlib/examples/gzappend.c similarity index 100% rename from StormLib/stormlib/zlib/examples/gzappend.c rename to src/StormLib/stormlib/zlib/examples/gzappend.c diff --git a/StormLib/stormlib/zlib/examples/gzjoin.c b/src/StormLib/stormlib/zlib/examples/gzjoin.c similarity index 100% rename from StormLib/stormlib/zlib/examples/gzjoin.c rename to src/StormLib/stormlib/zlib/examples/gzjoin.c diff --git a/StormLib/stormlib/zlib/examples/gzlog.c b/src/StormLib/stormlib/zlib/examples/gzlog.c similarity index 100% rename from StormLib/stormlib/zlib/examples/gzlog.c rename to src/StormLib/stormlib/zlib/examples/gzlog.c diff --git a/StormLib/stormlib/zlib/examples/gzlog.h b/src/StormLib/stormlib/zlib/examples/gzlog.h similarity index 100% rename from StormLib/stormlib/zlib/examples/gzlog.h rename to src/StormLib/stormlib/zlib/examples/gzlog.h diff --git a/StormLib/stormlib/zlib/examples/zlib_how.html b/src/StormLib/stormlib/zlib/examples/zlib_how.html similarity index 100% rename from StormLib/stormlib/zlib/examples/zlib_how.html rename to src/StormLib/stormlib/zlib/examples/zlib_how.html diff --git a/StormLib/stormlib/zlib/examples/zpipe.c b/src/StormLib/stormlib/zlib/examples/zpipe.c similarity index 100% rename from StormLib/stormlib/zlib/examples/zpipe.c rename to src/StormLib/stormlib/zlib/examples/zpipe.c diff --git a/StormLib/stormlib/zlib/examples/zran.c b/src/StormLib/stormlib/zlib/examples/zran.c similarity index 100% rename from StormLib/stormlib/zlib/examples/zran.c rename to src/StormLib/stormlib/zlib/examples/zran.c diff --git a/StormLib/stormlib/zlib/gzio.c b/src/StormLib/stormlib/zlib/gzio.c similarity index 100% rename from StormLib/stormlib/zlib/gzio.c rename to src/StormLib/stormlib/zlib/gzio.c diff --git a/StormLib/stormlib/zlib/infback.c b/src/StormLib/stormlib/zlib/infback.c similarity index 100% rename from StormLib/stormlib/zlib/infback.c rename to src/StormLib/stormlib/zlib/infback.c diff --git a/StormLib/stormlib/zlib/inffast.c b/src/StormLib/stormlib/zlib/inffast.c similarity index 100% rename from StormLib/stormlib/zlib/inffast.c rename to src/StormLib/stormlib/zlib/inffast.c diff --git a/StormLib/stormlib/zlib/inffast.h b/src/StormLib/stormlib/zlib/inffast.h similarity index 100% rename from StormLib/stormlib/zlib/inffast.h rename to src/StormLib/stormlib/zlib/inffast.h diff --git a/StormLib/stormlib/zlib/inffixed.h b/src/StormLib/stormlib/zlib/inffixed.h similarity index 100% rename from StormLib/stormlib/zlib/inffixed.h rename to src/StormLib/stormlib/zlib/inffixed.h diff --git a/StormLib/stormlib/zlib/inflate.c b/src/StormLib/stormlib/zlib/inflate.c similarity index 100% rename from StormLib/stormlib/zlib/inflate.c rename to src/StormLib/stormlib/zlib/inflate.c diff --git a/StormLib/stormlib/zlib/inflate.h b/src/StormLib/stormlib/zlib/inflate.h similarity index 100% rename from StormLib/stormlib/zlib/inflate.h rename to src/StormLib/stormlib/zlib/inflate.h diff --git a/StormLib/stormlib/zlib/inftrees.c b/src/StormLib/stormlib/zlib/inftrees.c similarity index 100% rename from StormLib/stormlib/zlib/inftrees.c rename to src/StormLib/stormlib/zlib/inftrees.c diff --git a/StormLib/stormlib/zlib/inftrees.h b/src/StormLib/stormlib/zlib/inftrees.h similarity index 100% rename from StormLib/stormlib/zlib/inftrees.h rename to src/StormLib/stormlib/zlib/inftrees.h diff --git a/StormLib/stormlib/zlib/minigzip.c b/src/StormLib/stormlib/zlib/minigzip.c similarity index 100% rename from StormLib/stormlib/zlib/minigzip.c rename to src/StormLib/stormlib/zlib/minigzip.c diff --git a/StormLib/stormlib/zlib/msdos/Makefile.bor b/src/StormLib/stormlib/zlib/msdos/Makefile.bor similarity index 100% rename from StormLib/stormlib/zlib/msdos/Makefile.bor rename to src/StormLib/stormlib/zlib/msdos/Makefile.bor diff --git a/StormLib/stormlib/zlib/msdos/Makefile.dj2 b/src/StormLib/stormlib/zlib/msdos/Makefile.dj2 similarity index 100% rename from StormLib/stormlib/zlib/msdos/Makefile.dj2 rename to src/StormLib/stormlib/zlib/msdos/Makefile.dj2 diff --git a/StormLib/stormlib/zlib/msdos/Makefile.emx b/src/StormLib/stormlib/zlib/msdos/Makefile.emx similarity index 100% rename from StormLib/stormlib/zlib/msdos/Makefile.emx rename to src/StormLib/stormlib/zlib/msdos/Makefile.emx diff --git a/StormLib/stormlib/zlib/msdos/Makefile.msc b/src/StormLib/stormlib/zlib/msdos/Makefile.msc similarity index 100% rename from StormLib/stormlib/zlib/msdos/Makefile.msc rename to src/StormLib/stormlib/zlib/msdos/Makefile.msc diff --git a/StormLib/stormlib/zlib/msdos/Makefile.tc b/src/StormLib/stormlib/zlib/msdos/Makefile.tc similarity index 100% rename from StormLib/stormlib/zlib/msdos/Makefile.tc rename to src/StormLib/stormlib/zlib/msdos/Makefile.tc diff --git a/StormLib/stormlib/zlib/old/Makefile.riscos b/src/StormLib/stormlib/zlib/old/Makefile.riscos similarity index 100% rename from StormLib/stormlib/zlib/old/Makefile.riscos rename to src/StormLib/stormlib/zlib/old/Makefile.riscos diff --git a/StormLib/stormlib/zlib/old/README b/src/StormLib/stormlib/zlib/old/README similarity index 100% rename from StormLib/stormlib/zlib/old/README rename to src/StormLib/stormlib/zlib/old/README diff --git a/StormLib/stormlib/zlib/old/descrip.mms b/src/StormLib/stormlib/zlib/old/descrip.mms similarity index 100% rename from StormLib/stormlib/zlib/old/descrip.mms rename to src/StormLib/stormlib/zlib/old/descrip.mms diff --git a/StormLib/stormlib/zlib/old/os2/Makefile.os2 b/src/StormLib/stormlib/zlib/old/os2/Makefile.os2 similarity index 100% rename from StormLib/stormlib/zlib/old/os2/Makefile.os2 rename to src/StormLib/stormlib/zlib/old/os2/Makefile.os2 diff --git a/StormLib/stormlib/zlib/old/os2/zlib.def b/src/StormLib/stormlib/zlib/old/os2/zlib.def similarity index 100% rename from StormLib/stormlib/zlib/old/os2/zlib.def rename to src/StormLib/stormlib/zlib/old/os2/zlib.def diff --git a/StormLib/stormlib/zlib/old/visual-basic.txt b/src/StormLib/stormlib/zlib/old/visual-basic.txt similarity index 100% rename from StormLib/stormlib/zlib/old/visual-basic.txt rename to src/StormLib/stormlib/zlib/old/visual-basic.txt diff --git a/StormLib/stormlib/zlib/old/zlib.html b/src/StormLib/stormlib/zlib/old/zlib.html similarity index 100% rename from StormLib/stormlib/zlib/old/zlib.html rename to src/StormLib/stormlib/zlib/old/zlib.html diff --git a/StormLib/stormlib/zlib/projects/README.projects b/src/StormLib/stormlib/zlib/projects/README.projects similarity index 100% rename from StormLib/stormlib/zlib/projects/README.projects rename to src/StormLib/stormlib/zlib/projects/README.projects diff --git a/StormLib/stormlib/zlib/projects/visualc6/README.txt b/src/StormLib/stormlib/zlib/projects/visualc6/README.txt similarity index 100% rename from StormLib/stormlib/zlib/projects/visualc6/README.txt rename to src/StormLib/stormlib/zlib/projects/visualc6/README.txt diff --git a/StormLib/stormlib/zlib/projects/visualc6/example.dsp b/src/StormLib/stormlib/zlib/projects/visualc6/example.dsp similarity index 100% rename from StormLib/stormlib/zlib/projects/visualc6/example.dsp rename to src/StormLib/stormlib/zlib/projects/visualc6/example.dsp diff --git a/StormLib/stormlib/zlib/projects/visualc6/minigzip.dsp b/src/StormLib/stormlib/zlib/projects/visualc6/minigzip.dsp similarity index 100% rename from StormLib/stormlib/zlib/projects/visualc6/minigzip.dsp rename to src/StormLib/stormlib/zlib/projects/visualc6/minigzip.dsp diff --git a/StormLib/stormlib/zlib/projects/visualc6/zlib.dsp b/src/StormLib/stormlib/zlib/projects/visualc6/zlib.dsp similarity index 100% rename from StormLib/stormlib/zlib/projects/visualc6/zlib.dsp rename to src/StormLib/stormlib/zlib/projects/visualc6/zlib.dsp diff --git a/StormLib/stormlib/zlib/projects/visualc6/zlib.dsw b/src/StormLib/stormlib/zlib/projects/visualc6/zlib.dsw similarity index 100% rename from StormLib/stormlib/zlib/projects/visualc6/zlib.dsw rename to src/StormLib/stormlib/zlib/projects/visualc6/zlib.dsw diff --git a/StormLib/stormlib/zlib/qnx/package.qpg b/src/StormLib/stormlib/zlib/qnx/package.qpg similarity index 100% rename from StormLib/stormlib/zlib/qnx/package.qpg rename to src/StormLib/stormlib/zlib/qnx/package.qpg diff --git a/StormLib/stormlib/zlib/trees.c b/src/StormLib/stormlib/zlib/trees.c similarity index 100% rename from StormLib/stormlib/zlib/trees.c rename to src/StormLib/stormlib/zlib/trees.c diff --git a/StormLib/stormlib/zlib/trees.h b/src/StormLib/stormlib/zlib/trees.h similarity index 100% rename from StormLib/stormlib/zlib/trees.h rename to src/StormLib/stormlib/zlib/trees.h diff --git a/StormLib/stormlib/zlib/uncompr.c b/src/StormLib/stormlib/zlib/uncompr.c similarity index 100% rename from StormLib/stormlib/zlib/uncompr.c rename to src/StormLib/stormlib/zlib/uncompr.c diff --git a/StormLib/stormlib/zlib/win32/DLL_FAQ.txt b/src/StormLib/stormlib/zlib/win32/DLL_FAQ.txt similarity index 100% rename from StormLib/stormlib/zlib/win32/DLL_FAQ.txt rename to src/StormLib/stormlib/zlib/win32/DLL_FAQ.txt diff --git a/StormLib/stormlib/zlib/win32/Makefile.bor b/src/StormLib/stormlib/zlib/win32/Makefile.bor similarity index 100% rename from StormLib/stormlib/zlib/win32/Makefile.bor rename to src/StormLib/stormlib/zlib/win32/Makefile.bor diff --git a/StormLib/stormlib/zlib/win32/Makefile.emx b/src/StormLib/stormlib/zlib/win32/Makefile.emx similarity index 100% rename from StormLib/stormlib/zlib/win32/Makefile.emx rename to src/StormLib/stormlib/zlib/win32/Makefile.emx diff --git a/StormLib/stormlib/zlib/win32/Makefile.gcc b/src/StormLib/stormlib/zlib/win32/Makefile.gcc similarity index 100% rename from StormLib/stormlib/zlib/win32/Makefile.gcc rename to src/StormLib/stormlib/zlib/win32/Makefile.gcc diff --git a/StormLib/stormlib/zlib/win32/Makefile.msc b/src/StormLib/stormlib/zlib/win32/Makefile.msc similarity index 100% rename from StormLib/stormlib/zlib/win32/Makefile.msc rename to src/StormLib/stormlib/zlib/win32/Makefile.msc diff --git a/StormLib/stormlib/zlib/win32/VisualC.txt b/src/StormLib/stormlib/zlib/win32/VisualC.txt similarity index 100% rename from StormLib/stormlib/zlib/win32/VisualC.txt rename to src/StormLib/stormlib/zlib/win32/VisualC.txt diff --git a/StormLib/stormlib/zlib/win32/zlib.def b/src/StormLib/stormlib/zlib/win32/zlib.def similarity index 100% rename from StormLib/stormlib/zlib/win32/zlib.def rename to src/StormLib/stormlib/zlib/win32/zlib.def diff --git a/StormLib/stormlib/zlib/win32/zlib1.rc b/src/StormLib/stormlib/zlib/win32/zlib1.rc similarity index 100% rename from StormLib/stormlib/zlib/win32/zlib1.rc rename to src/StormLib/stormlib/zlib/win32/zlib1.rc diff --git a/StormLib/stormlib/zlib/zconf.h b/src/StormLib/stormlib/zlib/zconf.h similarity index 100% rename from StormLib/stormlib/zlib/zconf.h rename to src/StormLib/stormlib/zlib/zconf.h diff --git a/StormLib/stormlib/zlib/zconf.in.h b/src/StormLib/stormlib/zlib/zconf.in.h similarity index 100% rename from StormLib/stormlib/zlib/zconf.in.h rename to src/StormLib/stormlib/zlib/zconf.in.h diff --git a/StormLib/stormlib/zlib/zlib.3 b/src/StormLib/stormlib/zlib/zlib.3 similarity index 100% rename from StormLib/stormlib/zlib/zlib.3 rename to src/StormLib/stormlib/zlib/zlib.3 diff --git a/StormLib/stormlib/zlib/zlib.h b/src/StormLib/stormlib/zlib/zlib.h similarity index 100% rename from StormLib/stormlib/zlib/zlib.h rename to src/StormLib/stormlib/zlib/zlib.h diff --git a/StormLib/stormlib/zlib/zutil.c b/src/StormLib/stormlib/zlib/zutil.c similarity index 100% rename from StormLib/stormlib/zlib/zutil.c rename to src/StormLib/stormlib/zlib/zutil.c diff --git a/StormLib/stormlib/zlib/zutil.h b/src/StormLib/stormlib/zlib/zutil.h similarity index 100% rename from StormLib/stormlib/zlib/zutil.h rename to src/StormLib/stormlib/zlib/zutil.h diff --git a/StormLib/stormlibdll/DllMain.c b/src/StormLib/stormlibdll/DllMain.c similarity index 100% rename from StormLib/stormlibdll/DllMain.c rename to src/StormLib/stormlibdll/DllMain.c diff --git a/StormLib/stormlibdll/StormLib.def b/src/StormLib/stormlibdll/StormLib.def similarity index 100% rename from StormLib/stormlibdll/StormLib.def rename to src/StormLib/stormlibdll/StormLib.def diff --git a/StormLib/test/Test.cpp b/src/StormLib/test/Test.cpp similarity index 100% rename from StormLib/test/Test.cpp rename to src/StormLib/test/Test.cpp diff --git a/bncsutil/src/bncsutil/Makefile b/src/bncsutil/Makefile.old similarity index 100% rename from bncsutil/src/bncsutil/Makefile rename to src/bncsutil/Makefile.old diff --git a/bncsutil/src/bncsutil/bncsutil.h b/src/bncsutil/bncsutil.h similarity index 100% rename from bncsutil/src/bncsutil/bncsutil.h rename to src/bncsutil/bncsutil.h diff --git a/src/bncsutil/bncsutil.pro b/src/bncsutil/bncsutil.pro new file mode 100644 index 0000000..49ff55f --- /dev/null +++ b/src/bncsutil/bncsutil.pro @@ -0,0 +1,25 @@ +# ------------------------------------------------- +# Project created by QtCreator 2010-04-19T13:31:03 +# ------------------------------------------------- +! include( ../lib.pri ) { + error( Couldn't find lib.pri! ) +} + +QT -= gui +TARGET = bncsutil +INCLUDEPATH += ../ + + + + +SOURCES += bsha1.cpp cdkeydecoder.cpp checkrevision.cpp decodekey.cpp file.cpp libinfo.cpp oldauth.cpp \ + nls.c pe.c sha1.c stack.c + +LIBS += -L../../lib \ + -lgmp +#macx { +# LIBS += -framework CoreFoundation -framework CoreServices +# LIBS += -L. -L/usr/lib -lbz2 -lz +#} + +HEADERS += diff --git a/bncsutil/src/bncsutil/bsha1.cpp b/src/bncsutil/bsha1.cpp similarity index 100% rename from bncsutil/src/bncsutil/bsha1.cpp rename to src/bncsutil/bsha1.cpp diff --git a/bncsutil/src/bncsutil/bsha1.h b/src/bncsutil/bsha1.h similarity index 100% rename from bncsutil/src/bncsutil/bsha1.h rename to src/bncsutil/bsha1.h diff --git a/bncsutil/src/bncsutil/buffer.h b/src/bncsutil/buffer.h similarity index 100% rename from bncsutil/src/bncsutil/buffer.h rename to src/bncsutil/buffer.h diff --git a/bncsutil/src/bncsutil/cdkeydecoder.cpp b/src/bncsutil/cdkeydecoder.cpp similarity index 100% rename from bncsutil/src/bncsutil/cdkeydecoder.cpp rename to src/bncsutil/cdkeydecoder.cpp diff --git a/bncsutil/src/bncsutil/cdkeydecoder.h b/src/bncsutil/cdkeydecoder.h similarity index 100% rename from bncsutil/src/bncsutil/cdkeydecoder.h rename to src/bncsutil/cdkeydecoder.h diff --git a/bncsutil/src/bncsutil/checkrevision.cpp b/src/bncsutil/checkrevision.cpp similarity index 100% rename from bncsutil/src/bncsutil/checkrevision.cpp rename to src/bncsutil/checkrevision.cpp diff --git a/bncsutil/src/bncsutil/checkrevision.h b/src/bncsutil/checkrevision.h similarity index 100% rename from bncsutil/src/bncsutil/checkrevision.h rename to src/bncsutil/checkrevision.h diff --git a/bncsutil/src/bncsutil/debug.c b/src/bncsutil/debug.c similarity index 100% rename from bncsutil/src/bncsutil/debug.c rename to src/bncsutil/debug.c diff --git a/bncsutil/src/bncsutil/debug.h b/src/bncsutil/debug.h similarity index 100% rename from bncsutil/src/bncsutil/debug.h rename to src/bncsutil/debug.h diff --git a/bncsutil/src/bncsutil/decodekey.cpp b/src/bncsutil/decodekey.cpp similarity index 100% rename from bncsutil/src/bncsutil/decodekey.cpp rename to src/bncsutil/decodekey.cpp diff --git a/bncsutil/src/bncsutil/decodekey.h b/src/bncsutil/decodekey.h similarity index 100% rename from bncsutil/src/bncsutil/decodekey.h rename to src/bncsutil/decodekey.h diff --git a/bncsutil/src/bncsutil/file.cpp b/src/bncsutil/file.cpp similarity index 100% rename from bncsutil/src/bncsutil/file.cpp rename to src/bncsutil/file.cpp diff --git a/bncsutil/src/bncsutil/file.h b/src/bncsutil/file.h similarity index 100% rename from bncsutil/src/bncsutil/file.h rename to src/bncsutil/file.h diff --git a/bncsutil/src/bncsutil/gmp.h b/src/bncsutil/gmp.h similarity index 100% rename from bncsutil/src/bncsutil/gmp.h rename to src/bncsutil/gmp.h diff --git a/bncsutil/src/bncsutil/keytables.h b/src/bncsutil/keytables.h similarity index 100% rename from bncsutil/src/bncsutil/keytables.h rename to src/bncsutil/keytables.h diff --git a/bncsutil/src/bncsutil/libinfo.cpp b/src/bncsutil/libinfo.cpp similarity index 100% rename from bncsutil/src/bncsutil/libinfo.cpp rename to src/bncsutil/libinfo.cpp diff --git a/bncsutil/src/bncsutil/libinfo.h b/src/bncsutil/libinfo.h similarity index 100% rename from bncsutil/src/bncsutil/libinfo.h rename to src/bncsutil/libinfo.h diff --git a/bncsutil/src/bncsutil/ms_stdint.h b/src/bncsutil/ms_stdint.h similarity index 100% rename from bncsutil/src/bncsutil/ms_stdint.h rename to src/bncsutil/ms_stdint.h diff --git a/bncsutil/src/bncsutil/mutil.h b/src/bncsutil/mutil.h similarity index 100% rename from bncsutil/src/bncsutil/mutil.h rename to src/bncsutil/mutil.h diff --git a/bncsutil/src/bncsutil/mutil_types.h b/src/bncsutil/mutil_types.h similarity index 100% rename from bncsutil/src/bncsutil/mutil_types.h rename to src/bncsutil/mutil_types.h diff --git a/bncsutil/src/bncsutil/nls.c b/src/bncsutil/nls.c similarity index 100% rename from bncsutil/src/bncsutil/nls.c rename to src/bncsutil/nls.c diff --git a/bncsutil/src/bncsutil/nls.h b/src/bncsutil/nls.h similarity index 100% rename from bncsutil/src/bncsutil/nls.h rename to src/bncsutil/nls.h diff --git a/bncsutil/src/bncsutil/oldauth.cpp b/src/bncsutil/oldauth.cpp similarity index 100% rename from bncsutil/src/bncsutil/oldauth.cpp rename to src/bncsutil/oldauth.cpp diff --git a/bncsutil/src/bncsutil/oldauth.h b/src/bncsutil/oldauth.h similarity index 100% rename from bncsutil/src/bncsutil/oldauth.h rename to src/bncsutil/oldauth.h diff --git a/bncsutil/src/bncsutil/pe.c b/src/bncsutil/pe.c similarity index 100% rename from bncsutil/src/bncsutil/pe.c rename to src/bncsutil/pe.c diff --git a/bncsutil/src/bncsutil/pe.h b/src/bncsutil/pe.h similarity index 100% rename from bncsutil/src/bncsutil/pe.h rename to src/bncsutil/pe.h diff --git a/bncsutil/src/bncsutil/sha1.c b/src/bncsutil/sha1.c similarity index 100% rename from bncsutil/src/bncsutil/sha1.c rename to src/bncsutil/sha1.c diff --git a/bncsutil/src/bncsutil/sha1.h b/src/bncsutil/sha1.h similarity index 100% rename from bncsutil/src/bncsutil/sha1.h rename to src/bncsutil/sha1.h diff --git a/bncsutil/src/bncsutil/stack.c b/src/bncsutil/stack.c similarity index 100% rename from bncsutil/src/bncsutil/stack.c rename to src/bncsutil/stack.c diff --git a/bncsutil/src/bncsutil/stack.h b/src/bncsutil/stack.h similarity index 100% rename from bncsutil/src/bncsutil/stack.h rename to src/bncsutil/stack.h diff --git a/src/cli/cli.pro b/src/cli/cli.pro new file mode 100644 index 0000000..5a1b41b --- /dev/null +++ b/src/cli/cli.pro @@ -0,0 +1,22 @@ +# ------------------------------------------------- +# Project created by QtCreator 2010-04-19T13:31:03 +# ------------------------------------------------- +QT += network sql +QT -= gui +TARGET = ghost++ +CONFIG += console debug_and_release link_prl +CONFIG -= app_bundle +TEMPLATE = app +SOURCES += main.cpp +OTHER_FILES += w3g_format.txt \ + w3g_actions.txt \ + ghost.vcproj +INCLUDEPATH += ../ \ + ../libghost +# ../zlib/include +LIBS += -L../../lib \ + -lghost -lbncsutil + +#HEADERS += ghost.h + +DESTDIR = ../../bin \ No newline at end of file diff --git a/ghost/main.cpp b/src/cli/main.cpp similarity index 80% rename from ghost/main.cpp rename to src/cli/main.cpp index b432814..df6cabd 100644 --- a/ghost/main.cpp +++ b/src/cli/main.cpp @@ -12,7 +12,6 @@ #include "windows.h" #endif -QTime gBasicTime; QFile gLogFile; QTextStream gLogStream(&gLogFile); @@ -20,20 +19,10 @@ QString gCFGFile; quint32 gLogMethod; CGHost *gGHost = NULL; -quint32 GetTime() -{ - return GetTicks( ) / 1000; -} - -quint32 GetTicks() -{ - return gBasicTime.elapsed(); -} - void SignalCatcher2( int s ) { CONSOLE_Print( "[!!!] caught signal " + QString::number( s ) + ", exiting NOW" ); - + if( gGHost ) { if( gGHost->m_Exiting ) @@ -49,43 +38,15 @@ void SignalCatcher( int s ) { // signal( SIGABRT, SignalCatcher2 ); signal( SIGINT, SignalCatcher2 ); - + CONSOLE_Print( "[!!!] caught signal " + QString::number( s ) + ", exiting nicely" ); - + if( gGHost ) gGHost->EventExitNice(); else exit( 1 ); } -void CONSOLE_Print( QString message ) -{ - cout << message.toStdString() << endl; - - // logging - - /*if (!gLogFile.fileName().isEmpty()) - { - if( gLogMethod == 1 ) - { - gLogFile.open(QFile::WriteOnly | QFile::Append); - - if( gLogFile.isWritable() ) - { - gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; - gLogFile.close(); - } - } - else if( gLogMethod == 2 && gLogFile.isWritable() ) - gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; - }*/ -} - -void DEBUG_Print( QString message ) -{ - cout << message.toStdString() << endl; -} - // // main // @@ -97,12 +58,12 @@ int main( int argc, char **argv ) { QCoreApplication a(argc, argv); - MPQArchive arch("/mnt/disk/Programme/Warcraft III/War3Patch.mpq"); + /*MPQArchive arch("/mnt/disk/Programme/Warcraft III/War3Patch.mpq"); if (!arch.open() && arch.m_Error != MPQArchive::NO_FILE_LIST) { DEBUG_Print("Failed to open, error " + QString::number(arch.m_Error)); exit(1); - } + }*/ @@ -112,7 +73,7 @@ int main( int argc, char **argv ) }*/ - DEBUG_Print("Successfully open MPQ file"); + /*DEBUG_Print("Successfully open MPQ file"); MPQFile* common_j = arch.getFile("Scripts\\common.j"); @@ -120,7 +81,7 @@ int main( int argc, char **argv ) { DEBUG_Print("Failed to read common.j, error " + QString::number(common_j->m_Error)); } - exit(0); + exit(0);*/ gCFGFile = "ghost.cfg"; @@ -129,7 +90,6 @@ int main( int argc, char **argv ) // read config file - gBasicTime.start(); CConfig CFG; CFG.Read( "default.cfg" ); CFG.Read( gCFGFile ); diff --git a/ghost configurator/ReadMe.txt b/src/ghost configurator/ReadMe.txt similarity index 100% rename from ghost configurator/ReadMe.txt rename to src/ghost configurator/ReadMe.txt diff --git a/ghost configurator/ghost configurator.sln b/src/ghost configurator/ghost configurator.sln similarity index 100% rename from ghost configurator/ghost configurator.sln rename to src/ghost configurator/ghost configurator.sln diff --git a/ghost configurator/ghost configurator/Form1.Designer.vb b/src/ghost configurator/ghost configurator/Form1.Designer.vb similarity index 100% rename from ghost configurator/ghost configurator/Form1.Designer.vb rename to src/ghost configurator/ghost configurator/Form1.Designer.vb diff --git a/ghost configurator/ghost configurator/Form1.resx b/src/ghost configurator/ghost configurator/Form1.resx similarity index 100% rename from ghost configurator/ghost configurator/Form1.resx rename to src/ghost configurator/ghost configurator/Form1.resx diff --git a/ghost configurator/ghost configurator/Form1.vb b/src/ghost configurator/ghost configurator/Form1.vb similarity index 100% rename from ghost configurator/ghost configurator/Form1.vb rename to src/ghost configurator/ghost configurator/Form1.vb diff --git a/ghost configurator/ghost configurator/My Project/Application.Designer.vb b/src/ghost configurator/ghost configurator/My Project/Application.Designer.vb similarity index 100% rename from ghost configurator/ghost configurator/My Project/Application.Designer.vb rename to src/ghost configurator/ghost configurator/My Project/Application.Designer.vb diff --git a/ghost configurator/ghost configurator/My Project/Application.myapp b/src/ghost configurator/ghost configurator/My Project/Application.myapp similarity index 100% rename from ghost configurator/ghost configurator/My Project/Application.myapp rename to src/ghost configurator/ghost configurator/My Project/Application.myapp diff --git a/ghost configurator/ghost configurator/My Project/AssemblyInfo.vb b/src/ghost configurator/ghost configurator/My Project/AssemblyInfo.vb similarity index 100% rename from ghost configurator/ghost configurator/My Project/AssemblyInfo.vb rename to src/ghost configurator/ghost configurator/My Project/AssemblyInfo.vb diff --git a/ghost configurator/ghost configurator/My Project/Resources.Designer.vb b/src/ghost configurator/ghost configurator/My Project/Resources.Designer.vb similarity index 100% rename from ghost configurator/ghost configurator/My Project/Resources.Designer.vb rename to src/ghost configurator/ghost configurator/My Project/Resources.Designer.vb diff --git a/ghost configurator/ghost configurator/My Project/Resources.resx b/src/ghost configurator/ghost configurator/My Project/Resources.resx similarity index 100% rename from ghost configurator/ghost configurator/My Project/Resources.resx rename to src/ghost configurator/ghost configurator/My Project/Resources.resx diff --git a/ghost configurator/ghost configurator/My Project/Settings.Designer.vb b/src/ghost configurator/ghost configurator/My Project/Settings.Designer.vb similarity index 100% rename from ghost configurator/ghost configurator/My Project/Settings.Designer.vb rename to src/ghost configurator/ghost configurator/My Project/Settings.Designer.vb diff --git a/ghost configurator/ghost configurator/My Project/Settings.settings b/src/ghost configurator/ghost configurator/My Project/Settings.settings similarity index 100% rename from ghost configurator/ghost configurator/My Project/Settings.settings rename to src/ghost configurator/ghost configurator/My Project/Settings.settings diff --git a/ghost configurator/ghost configurator/My Project/app.manifest b/src/ghost configurator/ghost configurator/My Project/app.manifest similarity index 100% rename from ghost configurator/ghost configurator/My Project/app.manifest rename to src/ghost configurator/ghost configurator/My Project/app.manifest diff --git a/ghost configurator/ghost configurator/Resources/parametres 3D.ico b/src/ghost configurator/ghost configurator/Resources/parametres 3D.ico similarity index 100% rename from ghost configurator/ghost configurator/Resources/parametres 3D.ico rename to src/ghost configurator/ghost configurator/Resources/parametres 3D.ico diff --git a/ghost configurator/ghost configurator/bin/Debug/ghost.cfg b/src/ghost configurator/ghost configurator/bin/Debug/ghost.cfg similarity index 100% rename from ghost configurator/ghost configurator/bin/Debug/ghost.cfg rename to src/ghost configurator/ghost configurator/bin/Debug/ghost.cfg diff --git a/ghost configurator/ghost configurator/ghost configurator.vbproj b/src/ghost configurator/ghost configurator/ghost configurator.vbproj similarity index 100% rename from ghost configurator/ghost configurator/ghost configurator.vbproj rename to src/ghost configurator/ghost configurator/ghost configurator.vbproj diff --git a/ghost configurator/ghost configurator/ghost configurator.vbproj.user b/src/ghost configurator/ghost configurator/ghost configurator.vbproj.user similarity index 100% rename from ghost configurator/ghost configurator/ghost configurator.vbproj.user rename to src/ghost configurator/ghost configurator/ghost configurator.vbproj.user diff --git a/src/lib.pri b/src/lib.pri new file mode 100644 index 0000000..4f736a4 --- /dev/null +++ b/src/lib.pri @@ -0,0 +1,3 @@ +CONFIG += staticlib create_prl +DESTDIR = ../../lib +TEMPLATE = lib \ No newline at end of file diff --git a/ghost/StormLibRAS.lib b/src/libghost/StormLibRAS.lib similarity index 100% rename from ghost/StormLibRAS.lib rename to src/libghost/StormLibRAS.lib diff --git a/ghost/bncsutilinterface.cpp b/src/libghost/bncsutilinterface.cpp similarity index 100% rename from ghost/bncsutilinterface.cpp rename to src/libghost/bncsutilinterface.cpp diff --git a/ghost/bncsutilinterface.h b/src/libghost/bncsutilinterface.h similarity index 100% rename from ghost/bncsutilinterface.h rename to src/libghost/bncsutilinterface.h diff --git a/ghost/bnet.cpp b/src/libghost/bnet.cpp similarity index 78% rename from ghost/bnet.cpp rename to src/libghost/bnet.cpp index 21e25ac..cbc6f65 100644 --- a/ghost/bnet.cpp +++ b/src/libghost/bnet.cpp @@ -33,7 +33,7 @@ #include "savegame.h" #include "replay.h" #include "gameprotocol.h" -#include "game_base.h" +#include "game.h" #include "includes.h" #include @@ -382,7 +382,7 @@ void CBNET::socketError() QTimer::singleShot(90000, this, SLOT(socketConnect())); } -QByteArray CBNET :: GetUniqueName( ) +QByteArray CBNET :: GetUniqueName( ) const { return m_Protocol->GetUniqueName( ); } @@ -401,11 +401,11 @@ void CBNET::EventCallableUpdateTimeout() quint32 Count = i->second->GetResult( ); if( Count == 0 ) - QueueChatCommand( m_GHost->m_Language->ThereAreNoAdmins( m_Server ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereAreNoAdmins( m_Server ), i->first, !i->first.isEmpty( ) ); else if( Count == 1 ) - QueueChatCommand( m_GHost->m_Language->ThereIsAdmin( m_Server ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereIsAdmin( m_Server ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->ThereAreAdmins( m_Server, QString::number( Count ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereAreAdmins( m_Server, QString::number( Count ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -422,10 +422,10 @@ void CBNET::EventCallableUpdateTimeout() if( i->second->GetResult( ) ) { AddAdmin( i->second->GetUser( ) ); - QueueChatCommand( m_GHost->m_Language->AddedUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->AddedUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorAddingUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorAddingUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -442,10 +442,10 @@ void CBNET::EventCallableUpdateTimeout() if( i->second->GetResult( ) ) { RemoveAdmin( i->second->GetUser( ) ); - QueueChatCommand( m_GHost->m_Language->DeletedUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->DeletedUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorDeletingUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorDeletingUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -462,11 +462,11 @@ void CBNET::EventCallableUpdateTimeout() quint32 Count = i->second->GetResult( ); if( Count == 0 ) - QueueChatCommand( m_GHost->m_Language->ThereAreNoBannedUsers( m_Server ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereAreNoBannedUsers( m_Server ), i->first, !i->first.isEmpty( ) ); else if( Count == 1 ) - QueueChatCommand( m_GHost->m_Language->ThereIsBannedUser( m_Server ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereIsBannedUser( m_Server ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->ThereAreBannedUsers( m_Server, QString::number( Count ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereAreBannedUsers( m_Server, QString::number( Count ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -483,10 +483,10 @@ void CBNET::EventCallableUpdateTimeout() if( i->second->GetResult( ) ) { AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); - QueueChatCommand( m_GHost->m_Language->BannedUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->BannedUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -503,10 +503,10 @@ void CBNET::EventCallableUpdateTimeout() if( i->second->GetResult( ) ) { RemoveBan( i->second->GetUser( ) ); - QueueChatCommand( m_GHost->m_Language->UnbannedUser( i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->UnbannedUser( i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->ErrorUnbanningUser( i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorUnbanningUser( i->second->GetUser( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -523,9 +523,9 @@ void CBNET::EventCallableUpdateTimeout() CDBGamePlayerSummary *GamePlayerSummary = i->second->GetResult( ); if( GamePlayerSummary ) - QueueChatCommand( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ), i->first, !i->first.isEmpty( ) ); else - QueueChatCommand( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -543,7 +543,7 @@ void CBNET::EventCallableUpdateTimeout() if( DotAPlayerSummary ) { - QString Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), + QString Summary = m_GHost->GetLanguage( )->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), QString::number( DotAPlayerSummary->GetTotalGames( ) ), QString::number( DotAPlayerSummary->GetTotalWins( ) ), QString::number( DotAPlayerSummary->GetTotalLosses( ) ), @@ -569,7 +569,7 @@ void CBNET::EventCallableUpdateTimeout() QueueChatCommand( Summary, i->first, !i->first.isEmpty( ) ); } else - QueueChatCommand( m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.isEmpty( ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -953,11 +953,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // this case covers whispers - we assume that anyone who sends a whisper to the bot with message "spoofcheck" should be considered spoof checked // note that this means you can whisper "spoofcheck" even in a public game to manually spoofcheck if the /whois fails - if( Event == CBNETProtocol :: EID_WHISPER && m_GHost->m_CurrentGame ) + if( Event == CBNETProtocol :: EID_WHISPER && m_GHost->GetCurrentGame( ) ) { if( Message == "s" || Message == "sc" || Message == "spoof" || Message == "check" || Message == "spoofcheck" ) - m_GHost->m_CurrentGame->AddToSpoofed( m_Server, User, true ); - else if( Message.indexOf( m_GHost->m_CurrentGame->GetGameName( ) ) != -1 ) + m_GHost->GetCurrentGame( )->AddToSpoofed( m_Server, User, true ); + else if( Message.indexOf( m_GHost->GetCurrentGame( )->GetGameName( ) ) != -1 ) { // look for messages like "entered a Warcraft III The Frozen Throne game called XYZ" // we don't look for the English part of the text anymore because we want this to work with multiple languages @@ -970,17 +970,17 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QList Tokens = UTIL_Tokenize( Message, ' ' ); if( Tokens.size( ) >= 3 ) - m_GHost->m_CurrentGame->AddToSpoofed( m_Server, Tokens[2], false ); + m_GHost->GetCurrentGame( )->AddToSpoofed( m_Server, Tokens[2], false ); } else - m_GHost->m_CurrentGame->AddToSpoofed( m_Server, User, false ); + m_GHost->GetCurrentGame( )->AddToSpoofed( m_Server, User, false ); } } // handle bot commands if( Message == "?trigger" && ( IsAdmin( User ) || IsRootAdmin( User ) || ( m_PublicCommands && m_OutPackets.size( ) <= 3 ) ) ) - QueueChatCommand( m_GHost->m_Language->CommandTrigger( QString( 1, m_CommandTrigger ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->CommandTrigger( QString( 1, m_CommandTrigger ) ), User, Whisper ); else if( !Message.isEmpty( ) && Message[0] == m_CommandTrigger ) { // extract the command trigger, the command, and the payload @@ -997,6 +997,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } else Command = Message.mid( 1 ); + + emit SignalBnetCommand( this, User, Command, Payload, Whisper ); Command = Command.toLower(); @@ -1017,12 +1019,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) { if( IsAdmin( Payload ) ) - QueueChatCommand( m_GHost->m_Language->UserIsAlreadyAnAdmin( m_Server, Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserIsAlreadyAnAdmin( m_Server, Payload ), User, Whisper ); else m_PairedAdminAdds.push_back( PairedAdminAdd( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedAdminAdd( m_Server, Payload ) ) ); } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1050,7 +1052,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } if( IsBannedName( Victim ) ) - QueueChatCommand( m_GHost->m_Language->UserIsAlreadyBanned( m_Server, Victim ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserIsAlreadyBanned( m_Server, Victim ), User, Whisper ); else m_PairedBanAdds.push_back( PairedBanAdd( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedBanAdd( m_Server, Victim, QString( ), QString( ), User, Reason ) ) ); } @@ -1059,12 +1061,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !ANNOUNCE // - if( Command == "announce" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) ) + if( Command == "announce" && m_GHost->GetCurrentGame( ) && !m_GHost->GetCurrentGame( )->GetCountDownStarted( ) ) { if( Payload.isEmpty( ) || Payload == "off" ) { - QueueChatCommand( m_GHost->m_Language->AnnounceMessageDisabled( ), User, Whisper ); - m_GHost->m_CurrentGame->SetAnnounce( 0, QString( ) ); + QueueChatCommand( m_GHost->GetLanguage( )->AnnounceMessageDisabled( ), User, Whisper ); + m_GHost->GetCurrentGame( )->SetAnnounce( 0, QString( ) ); } else { @@ -1090,8 +1092,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Start != -1 ) Message = Message.mid( Start ); - QueueChatCommand( m_GHost->m_Language->AnnounceMessageEnabled( ), User, Whisper ); - m_GHost->m_CurrentGame->SetAnnounce( Interval, Message ); + QueueChatCommand( m_GHost->GetLanguage( )->AnnounceMessageEnabled( ), User, Whisper ); + m_GHost->GetCurrentGame( )->SetAnnounce( Interval, Message ); } } } @@ -1107,7 +1109,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( Payload.isEmpty( ) || Payload == "off" ) { - QueueChatCommand( m_GHost->m_Language->AutoHostDisabled( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->AutoHostDisabled( ), User, Whisper ); m_GHost->m_AutoHostGameName.clear( ); m_GHost->m_AutoHostOwner.clear( ); m_GHost->m_AutoHostServer.clear( ); @@ -1148,9 +1150,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Start != -1 ) GameName = GameName.mid( Start ); - QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); - delete m_GHost->m_AutoHostMap; - m_GHost->m_AutoHostMap = new CMap( *m_GHost->m_Map ); + QueueChatCommand( m_GHost->GetLanguage( )->AutoHostEnabled( ), User, Whisper ); + + m_GHost->SetAutoHostMap( new CMap( *m_GHost->GetCurrentMap( ) ) ); m_GHost->m_AutoHostGameName = GameName; m_GHost->m_AutoHostOwner = User; m_GHost->m_AutoHostServer = m_Server; @@ -1165,7 +1167,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1178,7 +1180,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( Payload.isEmpty( ) || Payload == "off" ) { - QueueChatCommand( m_GHost->m_Language->AutoHostDisabled( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->AutoHostDisabled( ), User, Whisper ); m_GHost->m_AutoHostGameName.clear( ); m_GHost->m_AutoHostOwner.clear( ); m_GHost->m_AutoHostServer.clear( ); @@ -1233,9 +1235,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Start != -1 ) GameName = GameName.mid( Start ); - QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper ); - delete m_GHost->m_AutoHostMap; - m_GHost->m_AutoHostMap = new CMap( *m_GHost->m_Map ); + QueueChatCommand( m_GHost->GetLanguage( )->AutoHostEnabled( ), User, Whisper ); + + m_GHost->SetAutoHostMap( new CMap( *m_GHost->GetCurrentMap( ) ) ); m_GHost->m_AutoHostGameName = GameName; m_GHost->m_AutoHostOwner = User; m_GHost->m_AutoHostServer = m_Server; @@ -1252,19 +1254,19 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // // !AUTOSTART // - if( Command == "autostart" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) ) + if( Command == "autostart" && m_GHost->GetCurrentGame( ) && !m_GHost->GetCurrentGame( )->GetCountDownStarted( ) ) { if( Payload.isEmpty( ) || Payload == "off" ) { - QueueChatCommand( m_GHost->m_Language->AutoStartDisabled( ), User, Whisper ); - m_GHost->m_CurrentGame->SetAutoStartPlayers( 0 ); + QueueChatCommand( m_GHost->GetLanguage( )->AutoStartDisabled( ), User, Whisper ); + m_GHost->GetCurrentGame( )->SetAutoStartPlayers( 0 ); } else { @@ -1272,8 +1274,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( AutoStartPlayers != 0 ) { - QueueChatCommand( m_GHost->m_Language->AutoStartEnabled( QString::number( AutoStartPlayers ) ), User, Whisper ); - m_GHost->m_CurrentGame->SetAutoStartPlayers( AutoStartPlayers ); + QueueChatCommand( m_GHost->GetLanguage( )->AutoStartEnabled( QString::number( AutoStartPlayers ) ), User, Whisper ); + m_GHost->GetCurrentGame( )->SetAutoStartPlayers( AutoStartPlayers ); } } } @@ -1294,12 +1296,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) { if( IsAdmin( Payload ) ) - QueueChatCommand( m_GHost->m_Language->UserIsAnAdmin( m_Server, Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserIsAnAdmin( m_Server, Payload ), User, Whisper ); else - QueueChatCommand( m_GHost->m_Language->UserIsNotAnAdmin( m_Server, Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserIsNotAnAdmin( m_Server, Payload ), User, Whisper ); } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1311,18 +1313,18 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) CDBBan *Ban = IsBannedName( Payload ); if( Ban ) - QueueChatCommand( m_GHost->m_Language->UserWasBannedOnByBecause( m_Server, Payload, Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserWasBannedOnByBecause( m_Server, Payload, Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ), User, Whisper ); else - QueueChatCommand( m_GHost->m_Language->UserIsNotBanned( m_Server, Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserIsNotBanned( m_Server, Payload ), User, Whisper ); } // // !CLOSE (close slot) // - if( Command == "close" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) + if( Command == "close" && !Payload.isEmpty( ) && m_GHost->GetCurrentGame( ) ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 @@ -1339,23 +1341,23 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) break; } else - m_GHost->m_CurrentGame->CloseSlot( (unsigned char)( SID - 1 ), true ); + m_GHost->GetCurrentGame( )->CloseSlot( (unsigned char)( SID - 1 ), true ); } } else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // // !CLOSEALL // - if( Command == "closeall" && m_GHost->m_CurrentGame ) + if( Command == "closeall" && m_GHost->GetCurrentGame( ) ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) - m_GHost->m_CurrentGame->CloseAllSlots( ); + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) + m_GHost->GetCurrentGame( )->CloseAllSlots( ); else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // @@ -1367,7 +1369,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) m_PairedAdminCounts.push_back( PairedAdminCount( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedAdminCount( m_Server ) ) ); else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1393,12 +1395,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) { if( !IsAdmin( Payload ) ) - QueueChatCommand( m_GHost->m_Language->UserIsNotAnAdmin( m_Server, Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UserIsNotAnAdmin( m_Server, Payload ), User, Whisper ); else m_PairedAdminRemoves.push_back( PairedAdminRemove( Whisper ? User : QString( ), m_GHost->m_DB->ThreadedAdminRemove( m_Server, Payload ) ) ); } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1417,11 +1419,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( IsRootAdmin( User ) ) { - QueueChatCommand( m_GHost->m_Language->BotDisabled( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->BotDisabled( ), User, Whisper ); m_GHost->m_Enabled = false; } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1434,17 +1436,17 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Downloads == 0 ) { - QueueChatCommand( m_GHost->m_Language->MapDownloadsDisabled( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->MapDownloadsDisabled( ), User, Whisper ); m_GHost->m_AllowDownloads = 0; } else if( Downloads == 1 ) { - QueueChatCommand( m_GHost->m_Language->MapDownloadsEnabled( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->MapDownloadsEnabled( ), User, Whisper ); m_GHost->m_AllowDownloads = 1; } else if( Downloads == 2 ) { - QueueChatCommand( m_GHost->m_Language->MapDownloadsConditional( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->MapDownloadsConditional( ), User, Whisper ); m_GHost->m_AllowDownloads = 2; } } @@ -1457,11 +1459,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( IsRootAdmin( User ) ) { - QueueChatCommand( m_GHost->m_Language->BotEnabled( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->BotEnabled( ), User, Whisper ); m_GHost->m_Enabled = true; } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1479,16 +1481,16 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // if the game owner is still in the game only allow the root admin to end the game if( m_GHost->m_Games[GameNumber]->GetPlayerFromName( m_GHost->m_Games[GameNumber]->GetOwnerName( ), false ) && !IsRootAdmin( User ) ) - QueueChatCommand( m_GHost->m_Language->CantEndGameOwnerIsStillPlaying( m_GHost->m_Games[GameNumber]->GetOwnerName( ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->CantEndGameOwnerIsStillPlaying( m_GHost->m_Games[GameNumber]->GetOwnerName( ) ), User, Whisper ); else { - QueueChatCommand( m_GHost->m_Language->EndingGame( m_GHost->m_Games[GameNumber]->GetDescription( ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->EndingGame( m_GHost->m_Games[GameNumber]->GetDescription( ) ), User, Whisper ); CONSOLE_Print( "[GAME: " + m_GHost->m_Games[GameNumber]->GetGameName( ) + "] is over (admin ended game)" ); m_GHost->m_Games[GameNumber]->StopPlayers( "was disconnected (admin ended game)" ); } } else - QueueChatCommand( m_GHost->m_Language->GameNumberDoesntExist( Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->GameNumberDoesntExist( Payload ), User, Whisper ); } // @@ -1500,14 +1502,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // only load files in the current directory just to be safe if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) - QueueChatCommand( m_GHost->m_Language->UnableToLoadReplaysOutside( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UnableToLoadReplaysOutside( ), User, Whisper ); else { QString File = m_GHost->m_ReplayPath + Payload + ".w3g"; if( QFile::exists( File ) ) { - QueueChatCommand( m_GHost->m_Language->LoadingReplay( File ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->LoadingReplay( File ), User, Whisper ); CReplay *Replay = new CReplay( ); Replay->Load( File, false ); Replay->ParseReplay( false ); @@ -1515,7 +1517,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) delete Replay; } else - QueueChatCommand( m_GHost->m_Language->UnableToLoadReplayDoesntExist( File ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UnableToLoadReplayDoesntExist( File ), User, Whisper ); } } @@ -1534,14 +1536,14 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) m_GHost->deleteLater(); else { - if( m_GHost->m_CurrentGame || !m_GHost->m_Games.isEmpty( ) ) - QueueChatCommand( m_GHost->m_Language->AtLeastOneGameActiveUseForceToShutdown( ), User, Whisper ); + if( m_GHost->GetCurrentGame( ) || !m_GHost->m_Games.isEmpty( ) ) + QueueChatCommand( m_GHost->GetLanguage( )->AtLeastOneGameActiveUseForceToShutdown( ), User, Whisper ); else m_GHost->deleteLater(); } } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1551,7 +1553,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "getclan" ) { SendGetClanList( ); - QueueChatCommand( m_GHost->m_Language->UpdatingClanList( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UpdatingClanList( ), User, Whisper ); } // @@ -1561,7 +1563,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "getfriends" ) { SendGetFriendsList( ); - QueueChatCommand( m_GHost->m_Language->UpdatingFriendsList( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UpdatingFriendsList( ), User, Whisper ); } // @@ -1573,9 +1575,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) int GameNumber = Payload.toUInt() - 1; if( GameNumber < m_GHost->m_Games.size( ) ) - QueueChatCommand( m_GHost->m_Language->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ), User, Whisper ); else - QueueChatCommand( m_GHost->m_Language->GameNumberDoesntExist( Payload ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->GameNumberDoesntExist( Payload ), User, Whisper ); } // @@ -1584,17 +1586,17 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "getgames" ) { - if( m_GHost->m_CurrentGame ) - QueueChatCommand( m_GHost->m_Language->GameIsInTheLobby( m_GHost->m_CurrentGame->GetDescription( ), QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ), User, Whisper ); + if( m_GHost->GetCurrentGame( ) ) + QueueChatCommand( m_GHost->GetLanguage( )->GameIsInTheLobby( m_GHost->GetCurrentGame( )->GetDescription( ), QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ), User, Whisper ); else - QueueChatCommand( m_GHost->m_Language->ThereIsNoGameInTheLobby( QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->ThereIsNoGameInTheLobby( QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ), User, Whisper ); } // // !HOLD (hold a slot for someone) // - if( Command == "hold" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) + if( Command == "hold" && !Payload.isEmpty( ) && m_GHost->GetCurrentGame( ) ) { // hold as many players as specified, e.g. "Varlock Kilranin" holds players "Varlock" and "Kilranin" @@ -1612,8 +1614,8 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } else { - QueueChatCommand( m_GHost->m_Language->AddedPlayerToTheHoldList( HoldName ), User, Whisper ); - m_GHost->m_CurrentGame->AddToReserved( HoldName ); + QueueChatCommand( m_GHost->GetLanguage( )->AddedPlayerToTheHoldList( HoldName ), User, Whisper ); + m_GHost->GetCurrentGame( )->AddToReserved( HoldName ); } } } @@ -1623,7 +1625,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // if( Command == "hostsg" && !Payload.isEmpty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, true, Payload, User, User, m_Server, Whisper ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PRIVATE, true, Payload, User, User, m_Server, Whisper ); // // !LOAD (load config file) @@ -1632,7 +1634,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "load" ) { if( Payload.isEmpty( ) ) - QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->CurrentlyLoadedMapCFGIs( m_GHost->GetCurrentMap( )->GetCFGFile( ) ), User, Whisper ); else { try @@ -1643,7 +1645,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( !MapCFGPath.exists() ) { CONSOLE_Print( "[ADMINGAME] error listing map configs - map config path doesn't exist" ); - QueueChatCommand( m_GHost->m_Language->ErrorListingMapConfigs( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorListingMapConfigs( ), User, Whisper ); } else { @@ -1651,30 +1653,30 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) quint32 Matches = files.size(); if( Matches == 0 ) - QueueChatCommand( m_GHost->m_Language->NoMapConfigsFound( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->NoMapConfigsFound( ), User, Whisper ); else if (files.contains(Pattern)) { - QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ), User, Whisper ); CConfig MapCFG; MapCFG.Read( Pattern ); - m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); } else if (Matches == 1) { QString File = files.at(0); - QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + File ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + File ), User, Whisper ); CConfig MapCFG; MapCFG.Read( m_GHost->m_MapCFGPath + File ); - m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); } else - QueueChatCommand( m_GHost->m_Language->FoundMapConfigs( files.join(", ") ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->FoundMapConfigs( files.join(", ") ), User, Whisper ); } } catch( const exception &ex ) { CONSOLE_Print( QString( "[ADMINGAME] error listing map configs - caught exception [" ) + ex.what( ) + "]" ); - QueueChatCommand( m_GHost->m_Language->ErrorListingMapConfigs( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorListingMapConfigs( ), User, Whisper ); } } } @@ -1688,7 +1690,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // only load files in the current directory just to be safe if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) - QueueChatCommand( m_GHost->m_Language->UnableToLoadSaveGamesOutside( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UnableToLoadSaveGamesOutside( ), User, Whisper ); else { QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; @@ -1696,11 +1698,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( QFile::exists( File ) ) { - if( m_GHost->m_CurrentGame ) - QueueChatCommand( m_GHost->m_Language->UnableToLoadSaveGameGameInLobby( ), User, Whisper ); + if( m_GHost->GetCurrentGame( ) ) + QueueChatCommand( m_GHost->GetLanguage( )->UnableToLoadSaveGameGameInLobby( ), User, Whisper ); else { - QueueChatCommand( m_GHost->m_Language->LoadingSaveGame( File ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->LoadingSaveGame( File ), User, Whisper ); m_GHost->m_SaveGame->Load( File, false ); m_GHost->m_SaveGame->ParseSaveGame( ); m_GHost->m_SaveGame->SetFileName( File ); @@ -1708,7 +1710,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) } } else - QueueChatCommand( m_GHost->m_Language->UnableToLoadSaveGameDoesntExist( File ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UnableToLoadSaveGameDoesntExist( File ), User, Whisper ); } } @@ -1719,7 +1721,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "map" ) { if( Payload.isEmpty( ) ) - QueueChatCommand( m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->CurrentlyLoadedMapCFGIs( m_GHost->GetCurrentMap( )->GetCFGFile( ) ), User, Whisper ); else { QString FoundMaps; @@ -1732,7 +1734,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( !MapPath.exists() ) { CONSOLE_Print( "[ADMINGAME] error listing maps - map path doesn't exist" ); - QueueChatCommand( m_GHost->m_Language->ErrorListingMaps( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorListingMaps( ), User, Whisper ); } else { @@ -1740,38 +1742,38 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) quint32 Matches = files.size(); if( Matches == 0 ) - QueueChatCommand( m_GHost->m_Language->NoMapsFound( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->NoMapsFound( ), User, Whisper ); else if (files.contains(Pattern)) { - QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( Pattern ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->LoadingConfigFile( Pattern ), User, Whisper ); // hackhack: create a config file in memory with the required information to load the map CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + Pattern ); MapCFG.Set( "map_localpath", Pattern ); - m_GHost->m_Map->Load( &MapCFG, Pattern ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, Pattern ); } else if( Matches == 1 ) { QString File = files.at(0); - QueueChatCommand( m_GHost->m_Language->LoadingConfigFile( File ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->LoadingConfigFile( File ), User, Whisper ); // hackhack: create a config file in memory with the required information to load the map CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + File ); MapCFG.Set( "map_localpath", File ); - m_GHost->m_Map->Load( &MapCFG, File ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, File ); } else - QueueChatCommand( m_GHost->m_Language->FoundMaps( files.join(", ") ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->FoundMaps( files.join(", ") ), User, Whisper ); } } catch( const exception &ex ) { CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error listing maps - caught exception [" + ex.what( ) + "]" ); - QueueChatCommand( m_GHost->m_Language->ErrorListingMaps( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->ErrorListingMaps( ), User, Whisper ); } } } @@ -1780,9 +1782,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // !OPEN (open slot) // - if( Command == "open" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) + if( Command == "open" && !Payload.isEmpty( ) && m_GHost->GetCurrentGame( ) ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) { // open as many slots as specified, e.g. "5 10" opens slots 5 and 10 @@ -1799,23 +1801,23 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) break; } else - m_GHost->m_CurrentGame->OpenSlot( (unsigned char)( SID - 1 ), true ); + m_GHost->GetCurrentGame( )->OpenSlot( (unsigned char)( SID - 1 ), true ); } } else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // // !OPENALL // - if( Command == "openall" && m_GHost->m_CurrentGame ) + if( Command == "openall" && m_GHost->GetCurrentGame( ) ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) - m_GHost->m_CurrentGame->OpenAllSlots( ); + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) + m_GHost->GetCurrentGame( )->OpenAllSlots( ); else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // @@ -1823,7 +1825,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // if( Command == "priv" && !Payload.isEmpty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, Payload, User, User, m_Server, Whisper ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PRIVATE, false, Payload, User, User, m_Server, Whisper ); // // !PRIVBY (host private game by other player) @@ -1842,7 +1844,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, GameName, Owner, User, m_Server, Whisper ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PRIVATE, false, GameName, Owner, User, m_Server, Whisper ); } } @@ -1851,7 +1853,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // if( Command == "pub" && !Payload.isEmpty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, Payload, User, User, m_Server, Whisper ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PUBLIC, false, Payload, User, User, m_Server, Whisper ); // // !PUBBY (host public game by other player) @@ -1870,7 +1872,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); - m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, GameName, Owner, User, m_Server, Whisper ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PUBLIC, false, GameName, Owner, User, m_Server, Whisper ); } } @@ -1882,11 +1884,11 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( IsRootAdmin( User ) ) { - QueueChatCommand( m_GHost->m_Language->ReloadingConfigurationFiles( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->ReloadingConfigurationFiles( ), User, Whisper ); m_GHost->ReloadConfigs( ); } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1930,12 +1932,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( GameNumber - 1 < m_GHost->m_Games.size( ) ) m_GHost->m_Games[GameNumber - 1]->SendAllChat( "ADMIN: " + Message ); else - QueueChatCommand( m_GHost->m_Language->GameNumberDoesntExist( QString::number( GameNumber ) ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->GameNumberDoesntExist( QString::number( GameNumber ) ), User, Whisper ); } } } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // @@ -1946,58 +1948,58 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) { if( IsRootAdmin( User ) ) { - if( m_GHost->m_CurrentGame ) - m_GHost->m_CurrentGame->SendAllChat( Payload ); + if( m_GHost->GetCurrentGame( ) ) + m_GHost->GetCurrentGame( )->SendAllChat( Payload ); for( QList :: const_iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) (*i)->SendAllChat( "ADMIN: " + Payload ); } else - QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } // // !SP // - if( Command == "sp" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) ) + if( Command == "sp" && m_GHost->GetCurrentGame( ) && !m_GHost->GetCurrentGame( )->GetCountDownStarted( ) ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) { - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->ShufflingPlayers( ) ); - m_GHost->m_CurrentGame->ShuffleSlots( ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->ShufflingPlayers( ) ); + m_GHost->GetCurrentGame( )->ShuffleSlots( ); } else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // // !START // - if( Command == "start" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) && m_GHost->m_CurrentGame->GetNumHumanPlayers( ) > 0 ) + if( Command == "start" && m_GHost->GetCurrentGame( ) && !m_GHost->GetCurrentGame( )->GetCountDownStarted( ) && m_GHost->GetCurrentGame( )->GetNumHumanPlayers( ) > 0 ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) { // if the player sent "!start force" skip the checks and start the countdown // otherwise check that the game is ready to start if( Payload == "force" ) - m_GHost->m_CurrentGame->StartCountDown( true ); + m_GHost->GetCurrentGame( )->StartCountDown( true ); else - m_GHost->m_CurrentGame->StartCountDown( false ); + m_GHost->GetCurrentGame( )->StartCountDown( false ); } else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // // !SWAP (swap slots) // - if( Command == "swap" && !Payload.isEmpty( ) && m_GHost->m_CurrentGame ) + if( Command == "swap" && !Payload.isEmpty( ) && m_GHost->GetCurrentGame( ) ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) + if( !m_GHost->GetCurrentGame( )->GetLocked( ) ) { quint32 SID1; quint32 SID2; @@ -2018,12 +2020,12 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( SS.status() != QTextStream::Ok ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #2 to swap command" ); else - m_GHost->m_CurrentGame->SwapSlots( (unsigned char)( SID1 - 1 ), (unsigned char)( SID2 - 1 ) ); + m_GHost->GetCurrentGame( )->SwapSlots( (unsigned char)( SID1 - 1 ), (unsigned char)( SID2 - 1 ) ); } } } else - QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->TheGameIsLockedBNET( ), User, Whisper ); } // @@ -2032,23 +2034,23 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "unhost" ) { - if( m_GHost->m_CurrentGame ) + if( m_GHost->GetCurrentGame( ) ) { - if( m_GHost->m_CurrentGame->GetCountDownStarted( ) ) - QueueChatCommand( m_GHost->m_Language->UnableToUnhostGameCountdownStarted( m_GHost->m_CurrentGame->GetDescription( ) ), User, Whisper ); + if( m_GHost->GetCurrentGame( )->GetCountDownStarted( ) ) + QueueChatCommand( m_GHost->GetLanguage( )->UnableToUnhostGameCountdownStarted( m_GHost->GetCurrentGame( )->GetDescription( ) ), User, Whisper ); // if the game owner is still in the game only allow the root admin to unhost the game - else if( m_GHost->m_CurrentGame->GetPlayerFromName( m_GHost->m_CurrentGame->GetOwnerName( ), false ) && !IsRootAdmin( User ) ) - QueueChatCommand( m_GHost->m_Language->CantUnhostGameOwnerIsPresent( m_GHost->m_CurrentGame->GetOwnerName( ) ), User, Whisper ); + else if( m_GHost->GetCurrentGame( )->GetPlayerFromName( m_GHost->GetCurrentGame( )->GetOwnerName( ), false ) && !IsRootAdmin( User ) ) + QueueChatCommand( m_GHost->GetLanguage( )->CantUnhostGameOwnerIsPresent( m_GHost->GetCurrentGame( )->GetOwnerName( ) ), User, Whisper ); else { - QueueChatCommand( m_GHost->m_Language->UnhostingGame( m_GHost->m_CurrentGame->GetDescription( ) ), User, Whisper ); - m_GHost->m_CurrentGame->deleteLater(); + QueueChatCommand( m_GHost->GetLanguage( )->UnhostingGame( m_GHost->GetCurrentGame( )->GetDescription( ) ), User, Whisper ); + m_GHost->GetCurrentGame( )->deleteLater(); } } else - QueueChatCommand( m_GHost->m_Language->UnableToUnhostGameNoGameInLobby( ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->UnableToUnhostGameNoGameInLobby( ), User, Whisper ); } // @@ -2118,9 +2120,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "version" ) { if( IsAdmin( User ) || IsRootAdmin( User ) ) - QueueChatCommand( m_GHost->m_Language->VersionAdmin( m_GHost->m_Version ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->VersionAdmin( m_GHost->m_Version ), User, Whisper ); else - QueueChatCommand( m_GHost->m_Language->VersionNotAdmin( m_GHost->m_Version ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->VersionNotAdmin( m_GHost->m_Version ), User, Whisper ); } } } @@ -2151,20 +2153,20 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // this case covers whois results which are used when hosting a public game (we send out a "/whois [player]" for each player) // at all times you can still /w the bot with "spoofcheck" to manually spoof check - if( m_GHost->m_CurrentGame && m_GHost->m_CurrentGame->GetPlayerFromName( UserName, true ) ) + if( m_GHost->GetCurrentGame( ) && m_GHost->GetCurrentGame( )->GetPlayerFromName( UserName, true ) ) { if( Message.indexOf( "is away" ) != -1 ) - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsAway( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofPossibleIsAway( UserName ) ); else if( Message.indexOf( "is unavailable" ) != -1 ) - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsUnavailable( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofPossibleIsUnavailable( UserName ) ); else if( Message.indexOf( "is refusing messages" ) != -1 ) - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofPossibleIsRefusingMessages( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofPossibleIsRefusingMessages( UserName ) ); else if( Message.indexOf( "is using Warcraft III The Frozen Throne in the channel" ) != -1 ) - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsNotInGame( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofDetectedIsNotInGame( UserName ) ); else if( Message.indexOf( "is using Warcraft III The Frozen Throne in channel" ) != -1 ) - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsNotInGame( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofDetectedIsNotInGame( UserName ) ); else if( Message.indexOf( "is using Warcraft III The Frozen Throne in a private channel" ) != -1 ) - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsInPrivateChannel( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofDetectedIsInPrivateChannel( UserName ) ); if( Message.indexOf( "is using Warcraft III The Frozen Throne in game" ) != -1 || Message.indexOf( "is using Warcraft III Frozen Throne and is currently in game" ) != -1 ) { @@ -2172,10 +2174,10 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) // this is because when the game is rehosted, players who joined recently will be in the previous game according to battle.net // note: if the game is rehosted more than once it is possible (but unlikely) for a false positive because only two game names are checked - if( Message.indexOf( m_GHost->m_CurrentGame->GetGameName( ) ) != -1 || Message.indexOf( m_GHost->m_CurrentGame->GetLastGameName( ) ) != -1 ) - m_GHost->m_CurrentGame->AddToSpoofed( m_Server, UserName, false ); + if( Message.indexOf( m_GHost->GetCurrentGame( )->GetGameName( ) ) != -1 || Message.indexOf( m_GHost->GetCurrentGame( )->GetLastGameName( ) ) != -1 ) + m_GHost->GetCurrentGame( )->AddToSpoofed( m_Server, UserName, false ); else - m_GHost->m_CurrentGame->SendAllChat( m_GHost->m_Language->SpoofDetectedIsInAnotherGame( UserName ) ); + m_GHost->GetCurrentGame( )->SendAllChat( m_GHost->GetLanguage( )->SpoofDetectedIsInAnotherGame( UserName ) ); } } } diff --git a/ghost/bnet.h b/src/libghost/bnet.h similarity index 84% rename from ghost/bnet.h rename to src/libghost/bnet.h index aab16bf..e142c26 100644 --- a/ghost/bnet.h +++ b/src/libghost/bnet.h @@ -22,6 +22,7 @@ #define BNET_H #include "includes.h" +#include "interfaces.h" #include #include #include @@ -50,6 +51,7 @@ class CGHost; class CSaveGame; class CBaseGame; class CMap; +class CBNETPrivate; typedef pair PairedAdminCount; typedef pair PairedAdminAdd; @@ -67,6 +69,10 @@ typedef pair PairedDPSCheck; class CBNET : public QObject { Q_OBJECT +private: + Q_DECLARE_PRIVATE(CBNET); +signals: + void SignalBnetCommand( CBNET *bnet, const QString &user, const QString &command, const QString &payload, bool whisper ); public slots: void socketConnected(); void socketDisconnected(); @@ -169,28 +175,28 @@ public slots: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAlias, const QString &nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, const QString &nCDKeyROC, const QString &nCDKeyTFT, const QString &nCountryAbbrev, const QString &nCountry, quint32 nLocaleID, const QString &nUserName, const QString &nUserPassword, const QString &nFirstChannel, const QString &nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, const QByteArray &nEXEVersion, const QByteArray &nEXEVersionHash, const QString &nPasswordHashType, const QString &nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); virtual ~CBNET( ); - QString GetServer( ) { return m_Server; } - QString GetServerAlias( ) { return m_ServerAlias; } - QString GetCDKeyROC( ) { return m_CDKeyROC; } - QString GetCDKeyTFT( ) { return m_CDKeyTFT; } - QString GetUserName( ) { return m_UserName; } - QString GetUserPassword( ) { return m_UserPassword; } - QString GetFirstChannel( ) { return m_FirstChannel; } - QString GetCurrentChannel( ) { return m_CurrentChannel; } - QString GetRootAdmin( ) { return m_RootAdmin; } - char GetCommandTrigger( ) { return m_CommandTrigger; } - QByteArray GetEXEVersion( ) { return m_EXEVersion; } - QByteArray GetEXEVersionHash( ) { return m_EXEVersionHash; } - QString GetPasswordHashType( ) { return m_PasswordHashType; } - QString GetPVPGNRealmName( ) { return m_PVPGNRealmName; } - quint32 GetHostCounterID( ) { return m_HostCounterID; } - bool GetLoggedIn( ) { return m_LoggedIn; } - bool GetInChat( ) { return m_InChat; } - bool GetHoldFriends( ) { return m_HoldFriends; } - bool GetHoldClan( ) { return m_HoldClan; } - bool GetPublicCommands( ) { return m_PublicCommands; } - quint32 GetOutPacketsQueued( ) { return m_OutPackets.size( ); } - QByteArray GetUniqueName( ); + QString GetServer( ) const { return m_Server; } + QString GetServerAlias( ) const { return m_ServerAlias; } + QString GetCDKeyROC( ) const { return m_CDKeyROC; } + QString GetCDKeyTFT( ) const { return m_CDKeyTFT; } + QString GetUserName( ) const { return m_UserName; } + QString GetUserPassword( ) const { return m_UserPassword; } + QString GetFirstChannel( ) const { return m_FirstChannel; } + QString GetCurrentChannel( ) const { return m_CurrentChannel; } + QString GetRootAdmin( ) const { return m_RootAdmin; } + char GetCommandTrigger( ) const { return m_CommandTrigger; } + QByteArray GetEXEVersion( ) const { return m_EXEVersion; } + QByteArray GetEXEVersionHash( ) const { return m_EXEVersionHash; } + QString GetPasswordHashType( ) const { return m_PasswordHashType; } + QString GetPVPGNRealmName( ) const { return m_PVPGNRealmName; } + quint32 GetHostCounterID( ) const { return m_HostCounterID; } + bool GetLoggedIn( ) const { return m_LoggedIn; } + bool GetInChat( ) const { return m_InChat; } + bool GetHoldFriends( ) const { return m_HoldFriends; } + bool GetHoldClan( ) const { return m_HoldClan; } + bool GetPublicCommands( ) const { return m_PublicCommands; } + quint32 GetOutPacketsQueued( ) const { return m_OutPackets.size( ); } + QByteArray GetUniqueName( ) const; // processing functions diff --git a/ghost/bnetprotocol.cpp b/src/libghost/bnetprotocol.cpp similarity index 100% rename from ghost/bnetprotocol.cpp rename to src/libghost/bnetprotocol.cpp diff --git a/ghost/bnetprotocol.h b/src/libghost/bnetprotocol.h similarity index 100% rename from ghost/bnetprotocol.h rename to src/libghost/bnetprotocol.h diff --git a/ghost/bnlsclient.cpp b/src/libghost/bnlsclient.cpp similarity index 100% rename from ghost/bnlsclient.cpp rename to src/libghost/bnlsclient.cpp diff --git a/ghost/bnlsclient.h b/src/libghost/bnlsclient.h similarity index 100% rename from ghost/bnlsclient.h rename to src/libghost/bnlsclient.h diff --git a/ghost/bnlsprotocol.cpp b/src/libghost/bnlsprotocol.cpp similarity index 100% rename from ghost/bnlsprotocol.cpp rename to src/libghost/bnlsprotocol.cpp diff --git a/ghost/bnlsprotocol.h b/src/libghost/bnlsprotocol.h similarity index 100% rename from ghost/bnlsprotocol.h rename to src/libghost/bnlsprotocol.h diff --git a/ghost/commandpacket.cpp b/src/libghost/commandpacket.cpp similarity index 100% rename from ghost/commandpacket.cpp rename to src/libghost/commandpacket.cpp diff --git a/ghost/commandpacket.h b/src/libghost/commandpacket.h similarity index 100% rename from ghost/commandpacket.h rename to src/libghost/commandpacket.h diff --git a/ghost/config.cpp b/src/libghost/config.cpp similarity index 100% rename from ghost/config.cpp rename to src/libghost/config.cpp diff --git a/ghost/config.h b/src/libghost/config.h similarity index 100% rename from ghost/config.h rename to src/libghost/config.h diff --git a/ghost/crc32.cpp b/src/libghost/crc32.cpp similarity index 100% rename from ghost/crc32.cpp rename to src/libghost/crc32.cpp diff --git a/ghost/crc32.h b/src/libghost/crc32.h similarity index 100% rename from ghost/crc32.h rename to src/libghost/crc32.h diff --git a/ghost/csvparser.cpp b/src/libghost/csvparser.cpp similarity index 100% rename from ghost/csvparser.cpp rename to src/libghost/csvparser.cpp diff --git a/ghost/csvparser.h b/src/libghost/csvparser.h similarity index 100% rename from ghost/csvparser.h rename to src/libghost/csvparser.h diff --git a/ghost/game.cpp b/src/libghost/game.cpp similarity index 81% rename from ghost/game.cpp rename to src/libghost/game.cpp index a0c20bf..e570f1c 100644 --- a/ghost/game.cpp +++ b/src/libghost/game.cpp @@ -165,9 +165,9 @@ void CGame::EventCallableUpdateTimeout() CDBBan *Ban = i->second->GetResult( ); if( Ban ) - SendAllChat( m_GHost->m_Language->UserWasBannedOnByBecause( i->second->GetServer( ), i->second->GetUser( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->UserWasBannedOnByBecause( i->second->GetServer( ), i->second->GetUser( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); else - SendAllChat( m_GHost->m_Language->UserIsNotBanned( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->UserIsNotBanned( i->second->GetServer( ), i->second->GetUser( ) ) ); m_GHost->m_DB->RecoverCallable( i->second ); delete i->second; @@ -189,7 +189,7 @@ void CGame::EventCallableUpdateTimeout() (*j)->AddBan( i->second->GetUser( ), i->second->GetIP( ), i->second->GetGameName( ), i->second->GetAdmin( ), i->second->GetReason( ) ); } - SendAllChat( m_GHost->m_Language->PlayerWasBannedByPlayer( i->second->GetServer( ), i->second->GetUser( ), i->first ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerWasBannedByPlayer( i->second->GetServer( ), i->second->GetUser( ), i->first ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -209,25 +209,25 @@ void CGame::EventCallableUpdateTimeout() if( GamePlayerSummary ) { if( i->first.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); + SendAllChat( m_GHost->GetLanguage( )->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); else { CGamePlayer *Player = GetPlayerFromName( i->first, true ); if( Player ) - SendChat( Player, m_GHost->m_Language->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->HasPlayedGamesWithThisBot( i->second->GetName( ), GamePlayerSummary->GetFirstGameDateTime( ), GamePlayerSummary->GetLastGameDateTime( ), QString::number( GamePlayerSummary->GetTotalGames( ) ), QString::number( (float)GamePlayerSummary->GetAvgLoadingTime( ) / 1000, 'g', 2 ), QString::number( GamePlayerSummary->GetAvgLeftPercent( ) ) ) ); } } else { if( i->first.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->HasntPlayedGamesWithThisBot( i->second->GetName( ) ) ); else { CGamePlayer *Player = GetPlayerFromName( i->first, true ); if( Player ) - SendChat( Player, m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->HasntPlayedGamesWithThisBot( i->second->GetName( ) ) ); } } @@ -247,7 +247,7 @@ void CGame::EventCallableUpdateTimeout() if( DotAPlayerSummary ) { - QString Summary = m_GHost->m_Language->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), + QString Summary = m_GHost->GetLanguage( )->HasPlayedDotAGamesWithThisBot( i->second->GetName( ), QString::number( DotAPlayerSummary->GetTotalGames( ) ), QString::number( DotAPlayerSummary->GetTotalWins( ) ), QString::number( DotAPlayerSummary->GetTotalLosses( ) ), @@ -283,13 +283,13 @@ void CGame::EventCallableUpdateTimeout() else { if( i->first.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ) ); else { CGamePlayer *Player = GetPlayerFromName( i->first, true ); if( Player ) - SendChat( Player, m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ) ); } } @@ -406,7 +406,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( ( Command == "abort" || Command == "a" ) && m_CountDownStarted && !m_GameLoading && !m_GameLoaded ) { - SendAllChat( m_GHost->m_Language->CountDownAborted( ) ); + SendAllChat( m_GHost->GetLanguage( )->CountDownAborted( ) ); m_CountdownTimer.stop(); m_CountDownStarted = false; } @@ -465,11 +465,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToBanNoMatchesFound( Victim ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToBanNoMatchesFound( Victim ) ); else if( Matches == 1 ) m_PairedBanAdds.push_back( PairedBanAdd( User, m_GHost->m_DB->ThreadedBanAdd( LastMatch->GetServer( ), LastMatch->GetName( ), LastMatch->GetIP( ), m_GameName, User, Reason ) ) ); else - SendAllChat( m_GHost->m_Language->UnableToBanFoundMoreThanOneMatch( Victim ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToBanFoundMoreThanOneMatch( Victim ) ); } else { @@ -477,11 +477,11 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 Matches = GetPlayerFromNamePartial( Victim, &LastMatch ); if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToBanNoMatchesFound( Victim ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToBanNoMatchesFound( Victim ) ); else if( Matches == 1 ) m_PairedBanAdds.push_back( PairedBanAdd( User, m_GHost->m_DB->ThreadedBanAdd( LastMatch->GetJoinedRealm( ), LastMatch->GetName( ), LastMatch->GetExternalIPString( ), m_GameName, User, Reason ) ) ); else - SendAllChat( m_GHost->m_Language->UnableToBanFoundMoreThanOneMatch( Victim ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToBanFoundMoreThanOneMatch( Victim ) ); } } @@ -493,7 +493,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( Payload.isEmpty( ) || Payload == "off" ) { - SendAllChat( m_GHost->m_Language->AnnounceMessageDisabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->AnnounceMessageDisabled( ) ); SetAnnounce( 0, QString( ) ); } else @@ -521,7 +521,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Start != -1 ) Message = Message.mid( Start ); - SendAllChat( m_GHost->m_Language->AnnounceMessageEnabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->AnnounceMessageEnabled( ) ); SetAnnounce( Interval, Message ); } } @@ -536,12 +536,12 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( Payload == "on" ) { - SendAllChat( m_GHost->m_Language->AutoSaveEnabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->AutoSaveEnabled( ) ); m_AutoSave = true; } else if( Payload == "off" ) { - SendAllChat( m_GHost->m_Language->AutoSaveDisabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->AutoSaveDisabled( ) ); m_AutoSave = false; } } @@ -554,7 +554,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( Payload.isEmpty( ) || Payload == "off" ) { - SendAllChat( m_GHost->m_Language->AutoStartDisabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->AutoStartDisabled( ) ); m_AutoStartPlayers = 0; } else @@ -563,7 +563,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( AutoStartPlayers != 0 ) { - SendAllChat( m_GHost->m_Language->AutoStartEnabled( QString::number( AutoStartPlayers ) ) ); + SendAllChat( m_GHost->GetLanguage( )->AutoStartEnabled( QString::number( AutoStartPlayers ) ) ); m_AutoStartPlayers = AutoStartPlayers; } } @@ -588,7 +588,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToCheckPlayerNoMatchesFound( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToCheckPlayerNoMatchesFound( Payload ) ); else if( Matches == 1 ) { bool LastMatchAdminCheck = false; @@ -613,13 +613,13 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } } - SendAllChat( m_GHost->m_Language->CheckedPlayer( LastMatch->GetName( ), LastMatch->GetNumPings( ) > 0 ? QString::number( LastMatch->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32( Util::reverse(LastMatch->GetExternalIP( )) ) ), LastMatchAdminCheck || LastMatchRootAdminCheck ? "Yes" : "No", IsOwner( LastMatch->GetName( ) ) ? "Yes" : "No", LastMatch->GetSpoofed( ) ? "Yes" : "No", LastMatch->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : LastMatch->GetSpoofedRealm( ), LastMatch->GetReserved( ) ? "Yes" : "No" ) ); + SendAllChat( m_GHost->GetLanguage( )->CheckedPlayer( LastMatch->GetName( ), LastMatch->GetNumPings( ) > 0 ? QString::number( LastMatch->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32( Util::reverse(LastMatch->GetExternalIP( )) ) ), LastMatchAdminCheck || LastMatchRootAdminCheck ? "Yes" : "No", IsOwner( LastMatch->GetName( ) ) ? "Yes" : "No", LastMatch->GetSpoofed( ) ? "Yes" : "No", LastMatch->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : LastMatch->GetSpoofedRealm( ), LastMatch->GetReserved( ) ? "Yes" : "No" ) ); } else - SendAllChat( m_GHost->m_Language->UnableToCheckPlayerFoundMoreThanOneMatch( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToCheckPlayerFoundMoreThanOneMatch( Payload ) ); } else - SendAllChat( m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? QString::number( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse(player->GetExternalIP( ))) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); + SendAllChat( m_GHost->GetLanguage( )->CheckedPlayer( User, player->GetNumPings( ) > 0 ? QString::number( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse(player->GetExternalIP( ))) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); } // @@ -639,7 +639,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "clearhcl" && !m_CountDownStarted ) { m_HCLCommandString.clear( ); - SendAllChat( m_GHost->m_Language->ClearingHCL( ) ); + SendAllChat( m_GHost->GetLanguage( )->ClearingHCL( ) ); } // @@ -919,7 +919,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToStartDownloadNoMatchesFound( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToStartDownloadNoMatchesFound( Payload ) ); else if( Matches == 1 ) { if( !LastMatch->GetDownloadStarted( ) && !LastMatch->GetDownloadFinished( ) ) @@ -939,7 +939,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } } else - SendAllChat( m_GHost->m_Language->UnableToStartDownloadFoundMoreThanOneMatch( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToStartDownloadFoundMoreThanOneMatch( Payload ) ); } // @@ -1044,16 +1044,16 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Payload.indexOf( QRegExp("[^" + HCLChars + "]") ) == -1 ) { m_HCLCommandString = Payload; - SendAllChat( m_GHost->m_Language->SettingHCL( m_HCLCommandString ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingHCL( m_HCLCommandString ) ); } else - SendAllChat( m_GHost->m_Language->UnableToSetHCLInvalid( ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToSetHCLInvalid( ) ); } else - SendAllChat( m_GHost->m_Language->UnableToSetHCLTooLong( ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToSetHCLTooLong( ) ); } else - SendAllChat( m_GHost->m_Language->TheHCLIs( m_HCLCommandString ) ); + SendAllChat( m_GHost->GetLanguage( )->TheHCLIs( m_HCLCommandString ) ); } // @@ -1079,7 +1079,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri } else { - SendAllChat( m_GHost->m_Language->AddedPlayerToTheHoldList( HoldName ) ); + SendAllChat( m_GHost->GetLanguage( )->AddedPlayerToTheHoldList( HoldName ) ); AddToReserved( HoldName ); } } @@ -1095,10 +1095,10 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToKickNoMatchesFound( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToKickNoMatchesFound( Payload ) ); else if( Matches == 1 ) { - LastMatch->SetLeftReason( m_GHost->m_Language->WasKickedByPlayer( User ) ); + LastMatch->SetLeftReason( m_GHost->GetLanguage( )->WasKickedByPlayer( User ) ); if( !m_GameLoading && !m_GameLoaded ) LastMatch->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -1110,7 +1110,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri OpenSlot( GetSIDFromPID( LastMatch->GetPID( ) ), false ); } else - SendAllChat( m_GHost->m_Language->UnableToKickFoundMoreThanOneMatch( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToKickFoundMoreThanOneMatch( Payload ) ); } // @@ -1120,7 +1120,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "latency" ) { if( Payload.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->LatencyIs( QString::number( m_Latency ) ) ); + SendAllChat( m_GHost->GetLanguage( )->LatencyIs( QString::number( m_Latency ) ) ); else { m_RequestedLatency = Payload.toUInt(); @@ -1130,15 +1130,15 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( m_RequestedLatency <= min ) { m_RequestedLatency = min; - SendAllChat( m_GHost->m_Language->SettingLatencyToMinimum( QString::number(m_RequestedLatency) ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingLatencyToMinimum( QString::number(m_RequestedLatency) ) ); } else if( m_RequestedLatency >= max ) { m_RequestedLatency = max; - SendAllChat( m_GHost->m_Language->SettingLatencyToMaximum( QString::number(m_RequestedLatency) ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingLatencyToMaximum( QString::number(m_RequestedLatency) ) ); } else - SendAllChat( m_GHost->m_Language->SettingLatencyTo( QString::number( m_RequestedLatency ) ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingLatencyTo( QString::number( m_RequestedLatency ) ) ); } } @@ -1148,7 +1148,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "lock" && ( RootAdminCheck || IsOwner( User ) ) ) { - SendAllChat( m_GHost->m_Language->GameLocked( ) ); + SendAllChat( m_GHost->GetLanguage( )->GameLocked( ) ); m_Locked = true; } @@ -1160,12 +1160,12 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( Payload == "on" ) { - SendAllChat( m_GHost->m_Language->LocalAdminMessagesEnabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->LocalAdminMessagesEnabled( ) ); m_LocalAdminMessages = true; } else if( Payload == "off" ) { - SendAllChat( m_GHost->m_Language->LocalAdminMessagesDisabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->LocalAdminMessagesDisabled( ) ); m_LocalAdminMessages = false; } } @@ -1180,14 +1180,14 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToMuteNoMatchesFound( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToMuteNoMatchesFound( Payload ) ); else if( Matches == 1 ) { - SendAllChat( m_GHost->m_Language->MutedPlayer( LastMatch->GetName( ), User ) ); + SendAllChat( m_GHost->GetLanguage( )->MutedPlayer( LastMatch->GetName( ), User ) ); LastMatch->SetMuted( true ); } else - SendAllChat( m_GHost->m_Language->UnableToMuteFoundMoreThanOneMatch( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToMuteFoundMoreThanOneMatch( Payload ) ); } // @@ -1196,7 +1196,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "muteall" && m_GameLoaded ) { - SendAllChat( m_GHost->m_Language->GlobalChatMuted( ) ); + SendAllChat( m_GHost->GetLanguage( )->GlobalChatMuted( ) ); m_MuteAll = true; } @@ -1243,17 +1243,17 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( !Payload.isEmpty( ) ) { - SendAllChat( m_GHost->m_Language->SettingGameOwnerTo( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingGameOwnerTo( Payload ) ); m_OwnerName = Payload; } else { - SendAllChat( m_GHost->m_Language->SettingGameOwnerTo( User ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingGameOwnerTo( User ) ); m_OwnerName = User; } } else - SendAllChat( m_GHost->m_Language->UnableToSetGameOwner( m_OwnerName ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToSetGameOwner( m_OwnerName ) ); } // @@ -1316,7 +1316,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri SendAllChat( Pings ); if( Kicked > 0 ) - SendAllChat( m_GHost->m_Language->KickingPlayersWithPingsGreaterThan( QString::number( Kicked ), QString::number( KickPing ) ) ); + SendAllChat( m_GHost->GetLanguage( )->KickingPlayersWithPingsGreaterThan( QString::number( Kicked ), QString::number( KickPing ) ) ); } // @@ -1326,7 +1326,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "priv" && !Payload.isEmpty( ) && !m_CountDownStarted && !m_SaveGame ) { CONSOLE_Print( "[GAME: " + m_GameName + "] trying to rehost as private game [" + Payload + "]" ); - SendAllChat( m_GHost->m_Language->TryingToRehostAsPrivateGame( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->TryingToRehostAsPrivateGame( Payload ) ); m_GameState = GAME_PRIVATE; m_LastGameName = m_GameName; m_GameName = Payload; @@ -1362,7 +1362,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "pub" && !Payload.isEmpty( ) && !m_CountDownStarted && !m_SaveGame ) { CONSOLE_Print( "[GAME: " + m_GameName + "] trying to rehost as public game [" + Payload + "]" ); - SendAllChat( m_GHost->m_Language->TryingToRehostAsPublicGame( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->TryingToRehostAsPublicGame( Payload ) ); m_GameState = GAME_PUBLIC; m_LastGameName = m_GameName; m_GameName = Payload; @@ -1394,12 +1394,12 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri { if( Payload == "on" ) { - SendAllChat( m_GHost->m_Language->RefreshMessagesEnabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->RefreshMessagesEnabled( ) ); m_RefreshMessages = true; } else if( Payload == "off" ) { - SendAllChat( m_GHost->m_Language->RefreshMessagesDisabled( ) ); + SendAllChat( m_GHost->GetLanguage( )->RefreshMessagesDisabled( ) ); m_RefreshMessages = false; } } @@ -1479,7 +1479,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "sp" && !m_CountDownStarted ) { - SendAllChat( m_GHost->m_Language->ShufflingPlayers( ) ); + SendAllChat( m_GHost->GetLanguage( )->ShufflingPlayers( ) ); ShuffleSlots( ); } @@ -1499,7 +1499,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( GetTicks( ) - m_LastPlayerLeaveTicks >= 2000 ) StartCountDown( false ); else - SendAllChat( m_GHost->m_Language->CountDownAbortedSomeoneLeftRecently( ) ); + SendAllChat( m_GHost->GetLanguage( )->CountDownAbortedSomeoneLeftRecently( ) ); } } @@ -1540,7 +1540,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "synclimit" ) { if( Payload.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->SyncLimitIs( QString::number( m_SyncLimit ) ) ); + SendAllChat( m_GHost->GetLanguage( )->SyncLimitIs( QString::number( m_SyncLimit ) ) ); else { m_SyncLimit = Payload.toUInt(); @@ -1548,15 +1548,15 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( m_SyncLimit <= 10 ) { m_SyncLimit = 10; - SendAllChat( m_GHost->m_Language->SettingSyncLimitToMinimum( "10" ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingSyncLimitToMinimum( "10" ) ); } else if( m_SyncLimit >= 10000 ) { m_SyncLimit = 10000; - SendAllChat( m_GHost->m_Language->SettingSyncLimitToMaximum( "10000" ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingSyncLimitToMaximum( "10000" ) ); } else - SendAllChat( m_GHost->m_Language->SettingSyncLimitTo( QString::number( m_SyncLimit ) ) ); + SendAllChat( m_GHost->GetLanguage( )->SettingSyncLimitTo( QString::number( m_SyncLimit ) ) ); } } @@ -1573,7 +1573,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "unlock" && ( RootAdminCheck || IsOwner( User ) ) ) { - SendAllChat( m_GHost->m_Language->GameUnlocked( ) ); + SendAllChat( m_GHost->GetLanguage( )->GameUnlocked( ) ); m_Locked = false; } @@ -1587,14 +1587,14 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) - SendAllChat( m_GHost->m_Language->UnableToMuteNoMatchesFound( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToMuteNoMatchesFound( Payload ) ); else if( Matches == 1 ) { - SendAllChat( m_GHost->m_Language->UnmutedPlayer( LastMatch->GetName( ), User ) ); + SendAllChat( m_GHost->GetLanguage( )->UnmutedPlayer( LastMatch->GetName( ), User ) ); LastMatch->SetMuted( false ); } else - SendAllChat( m_GHost->m_Language->UnableToMuteFoundMoreThanOneMatch( Payload ) ); + SendAllChat( m_GHost->GetLanguage( )->UnableToMuteFoundMoreThanOneMatch( Payload ) ); } // @@ -1603,7 +1603,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "unmuteall" && m_GameLoaded ) { - SendAllChat( m_GHost->m_Language->GlobalChatUnmuted( ) ); + SendAllChat( m_GHost->GetLanguage( )->GlobalChatUnmuted( ) ); m_MuteAll = false; } @@ -1624,7 +1624,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "votecancel" && !m_KickVotePlayer.isEmpty( ) ) { - SendAllChat( m_GHost->m_Language->VoteKickCancelled( m_KickVotePlayer ) ); + SendAllChat( m_GHost->GetLanguage( )->VoteKickCancelled( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); m_VotekickTimer.stop(); } @@ -1657,7 +1657,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri else { CONSOLE_Print( "[GAME: " + m_GameName + "] admin command ignored, the game is locked" ); - SendChat( player, m_GHost->m_Language->TheGameIsLocked( ) ); + SendChat( player, m_GHost->GetLanguage( )->TheGameIsLocked( ) ); } } else @@ -1677,7 +1677,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // if( Command == "checkme" ) - SendChat( player, m_GHost->m_Language->CheckedPlayer( User, player->GetNumPings( ) > 0 ? QString::number( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse(player->GetExternalIP( ))) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); + SendChat( player, m_GHost->GetLanguage( )->CheckedPlayer( User, player->GetNumPings( ) > 0 ? QString::number( player->GetPing( m_GHost->m_LCPings ) ) + "ms" : "N/A", m_GHost->m_DBLocal->FromCheck( Util::extractUInt32(Util::reverse(player->GetExternalIP( ))) ), AdminCheck || RootAdminCheck ? "Yes" : "No", IsOwner( User ) ? "Yes" : "No", player->GetSpoofed( ) ? "Yes" : "No", player->GetSpoofedRealm( ).isEmpty( ) ? "N/A" : player->GetSpoofedRealm( ), player->GetReserved( ) ? "Yes" : "No" ) ); // // !STATS @@ -1724,9 +1724,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "version" ) { if( player->GetSpoofed( ) && ( AdminCheck || RootAdminCheck || IsOwner( User ) ) ) - SendChat( player, m_GHost->m_Language->VersionAdmin( m_GHost->m_Version ) ); + SendChat( player, m_GHost->GetLanguage( )->VersionAdmin( m_GHost->m_Version ) ); else - SendChat( player, m_GHost->m_Language->VersionNotAdmin( m_GHost->m_Version ) ); + SendChat( player, m_GHost->GetLanguage( )->VersionNotAdmin( m_GHost->m_Version ) ); } // @@ -1736,20 +1736,20 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "votekick" && m_GHost->m_VoteKickAllowed && !Payload.isEmpty( ) ) { if( !m_KickVotePlayer.isEmpty( ) ) - SendChat( player, m_GHost->m_Language->UnableToVoteKickAlreadyInProgress( ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToVoteKickAlreadyInProgress( ) ); else if( m_Players.size( ) == 2 ) - SendChat( player, m_GHost->m_Language->UnableToVoteKickNotEnoughPlayers( ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToVoteKickNotEnoughPlayers( ) ); else { CGamePlayer *LastMatch = NULL; quint32 Matches = GetPlayerFromNamePartial( Payload, &LastMatch ); if( Matches == 0 ) - SendChat( player, m_GHost->m_Language->UnableToVoteKickNoMatchesFound( Payload ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToVoteKickNoMatchesFound( Payload ) ); else if( Matches == 1 ) { if( LastMatch->GetReserved( ) ) - SendChat( player, m_GHost->m_Language->UnableToVoteKickPlayerIsReserved( LastMatch->GetName( ) ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToVoteKickPlayerIsReserved( LastMatch->GetName( ) ) ); else { m_KickVotePlayer = LastMatch->GetName( ); @@ -1760,12 +1760,12 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri player->SetKickVote( true ); CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] started by player [" + User + "]" ); - SendAllChat( m_GHost->m_Language->StartedVoteKick( LastMatch->GetName( ), User, QString::number( (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); - SendAllChat( m_GHost->m_Language->TypeYesToVote( QString( 1, m_GHost->m_CommandTrigger ) ) ); + SendAllChat( m_GHost->GetLanguage( )->StartedVoteKick( LastMatch->GetName( ), User, QString::number( (quint32)ceil( ( GetNumHumanPlayers( ) - 1 ) * (float)m_GHost->m_VoteKickPercentage / 100 ) - 1 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->TypeYesToVote( QString( 1, m_GHost->m_CommandTrigger ) ) ); } } else - SendChat( player, m_GHost->m_Language->UnableToVoteKickFoundMoreThanOneMatch( Payload ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToVoteKickFoundMoreThanOneMatch( Payload ) ); } } @@ -1791,7 +1791,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Victim ) { - Victim->SetLeftReason( m_GHost->m_Language->WasKickedByVote( ) ); + Victim->SetLeftReason( m_GHost->GetLanguage( )->WasKickedByVote( ) ); if( !m_GameLoading && !m_GameLoaded ) Victim->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -1804,16 +1804,16 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri OpenSlot( GetSIDFromPID( Victim->GetPID( ) ), false ); CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] passed with " + QString::number( Votes ) + "/" + QString::number( GetNumHumanPlayers( ) ) + " votes" ); - SendAllChat( m_GHost->m_Language->VoteKickPassed( m_KickVotePlayer ) ); + SendAllChat( m_GHost->GetLanguage( )->VoteKickPassed( m_KickVotePlayer ) ); } else - SendAllChat( m_GHost->m_Language->ErrorVoteKickingPlayer( m_KickVotePlayer ) ); + SendAllChat( m_GHost->GetLanguage( )->ErrorVoteKickingPlayer( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); m_VotekickTimer.stop(); } else - SendAllChat( m_GHost->m_Language->VoteKickAcceptedNeedMoreVotes( m_KickVotePlayer, User, QString::number( VotesNeeded - Votes ) ) ); + SendAllChat( m_GHost->GetLanguage( )->VoteKickAcceptedNeedMoreVotes( m_KickVotePlayer, User, QString::number( VotesNeeded - Votes ) ) ); } return HideCommand; diff --git a/ghost/game.h b/src/libghost/game.h similarity index 100% rename from ghost/game.h rename to src/libghost/game.h diff --git a/ghost/game_admin.cpp b/src/libghost/game_admin.cpp similarity index 75% rename from ghost/game_admin.cpp rename to src/libghost/game_admin.cpp index 88d703d..8b30c33 100644 --- a/ghost/game_admin.cpp +++ b/src/libghost/game_admin.cpp @@ -30,7 +30,7 @@ #include "replay.h" #include "gameplayer.h" #include "gameprotocol.h" -#include "game_base.h" +#include "game.h" #include "game_admin.h" #include @@ -92,11 +92,11 @@ void CAdminGame::EventCallableUpdateTimeout() quint32 Count = i->second->GetResult( ); if( Count == 0 ) - SendChat( Player, m_GHost->m_Language->ThereAreNoAdmins( i->second->GetServer( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ThereAreNoAdmins( i->second->GetServer( ) ) ); else if( Count == 1 ) - SendChat( Player, m_GHost->m_Language->ThereIsAdmin( i->second->GetServer( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ThereIsAdmin( i->second->GetServer( ) ) ); else - SendChat( Player, m_GHost->m_Language->ThereAreAdmins( i->second->GetServer( ), QString::number( Count ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ThereAreAdmins( i->second->GetServer( ), QString::number( Count ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -125,9 +125,9 @@ void CAdminGame::EventCallableUpdateTimeout() if( Player ) { if( i->second->GetResult( ) ) - SendChat( Player, m_GHost->m_Language->AddedUserToAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->AddedUserToAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); else - SendChat( Player, m_GHost->m_Language->ErrorAddingUserToAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ErrorAddingUserToAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -156,9 +156,9 @@ void CAdminGame::EventCallableUpdateTimeout() if( Player ) { if( i->second->GetResult( ) ) - SendChat( Player, m_GHost->m_Language->DeletedUserFromAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->DeletedUserFromAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); else - SendChat( Player, m_GHost->m_Language->ErrorDeletingUserFromAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ErrorDeletingUserFromAdminDatabase( i->second->GetServer( ), i->second->GetUser( ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -180,11 +180,11 @@ void CAdminGame::EventCallableUpdateTimeout() quint32 Count = i->second->GetResult( ); if( Count == 0 ) - SendChat( Player, m_GHost->m_Language->ThereAreNoBannedUsers( i->second->GetServer( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ThereAreNoBannedUsers( i->second->GetServer( ) ) ); else if( Count == 1 ) - SendChat( Player, m_GHost->m_Language->ThereIsBannedUser( i->second->GetServer( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ThereIsBannedUser( i->second->GetServer( ) ) ); else - SendChat( Player, m_GHost->m_Language->ThereAreBannedUsers( i->second->GetServer( ), QString::number( Count ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ThereAreBannedUsers( i->second->GetServer( ), QString::number( Count ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -215,9 +215,9 @@ void CAdminGame::EventCallableUpdateTimeout() if( Player ) { if( i->second->GetResult( ) ) - SendChat( Player, m_GHost->m_Language->BannedUser( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->BannedUser( i->second->GetServer( ), i->second->GetUser( ) ) ); else - SendChat( Player, m_GHost->m_Language->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -248,9 +248,9 @@ void CAdminGame::EventCallableUpdateTimeout() if( Player ) { if( i->second->GetResult( ) ) - SendChat( Player, m_GHost->m_Language->UnbannedUser( i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->UnbannedUser( i->second->GetUser( ) ) ); else - SendChat( Player, m_GHost->m_Language->ErrorUnbanningUser( i->second->GetUser( ) ) ); + SendChat( Player, m_GHost->GetLanguage( )->ErrorUnbanningUser( i->second->GetUser( ) ) ); } m_GHost->m_DB->RecoverCallable( i->second ); @@ -374,7 +374,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, FoundServer = true; if( (*i)->IsAdmin( Name ) ) - SendChat( player, m_GHost->m_Language->UserIsAlreadyAnAdmin( Server, Name ) ); + SendChat( player, m_GHost->GetLanguage( )->UserIsAlreadyAnAdmin( Server, Name ) ); else m_PairedAdminAdds.push_back( PairedAdminAdd( player->GetName( ), m_GHost->m_DB->ThreadedAdminAdd( Server, Name ) ) ); @@ -383,7 +383,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, } if( !FoundServer ) - SendChat( player, m_GHost->m_Language->ValidServers( Servers ) ); + SendChat( player, m_GHost->GetLanguage( )->ValidServers( Servers ) ); } } @@ -395,7 +395,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { if( Payload.isEmpty( ) || Payload == "off" ) { - SendChat( player, m_GHost->m_Language->AutoHostDisabled( ) ); + SendChat( player, m_GHost->GetLanguage( )->AutoHostDisabled( ) ); m_GHost->m_AutoHostGameName.clear( ); m_GHost->m_AutoHostOwner.clear( ); m_GHost->m_AutoHostServer.clear( ); @@ -437,9 +437,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Start != -1 ) GameName = GameName.mid( Start ); - SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); - delete m_GHost->m_AutoHostMap; - m_GHost->m_AutoHostMap = new CMap( *m_GHost->m_Map ); + SendChat( player, m_GHost->GetLanguage( )->AutoHostEnabled( ) ); + + m_GHost->SetAutoHostMap( new CMap( *m_GHost->GetCurrentMap( ) ) ); m_GHost->m_AutoHostGameName = GameName; m_GHost->m_AutoHostOwner = User; m_GHost->m_AutoHostServer.clear( ); @@ -462,7 +462,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { if( Payload.isEmpty( ) || Payload == "off" ) { - SendChat( player, m_GHost->m_Language->AutoHostDisabled( ) ); + SendChat( player, m_GHost->GetLanguage( )->AutoHostDisabled( ) ); m_GHost->m_AutoHostGameName.clear( ); m_GHost->m_AutoHostOwner.clear( ); m_GHost->m_AutoHostServer.clear( ); @@ -518,9 +518,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Start != -1 ) GameName = GameName.mid( Start ); - SendChat( player, m_GHost->m_Language->AutoHostEnabled( ) ); - delete m_GHost->m_AutoHostMap; - m_GHost->m_AutoHostMap = new CMap( *m_GHost->m_Map ); + SendChat( player, m_GHost->GetLanguage( )->AutoHostEnabled( ) ); + + m_GHost->SetAutoHostMap( new CMap( *m_GHost->GetCurrentMap( ) ) ); m_GHost->m_AutoHostGameName = GameName; m_GHost->m_AutoHostOwner = User; m_GHost->m_AutoHostServer.clear( ); @@ -579,16 +579,16 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, FoundServer = true; if( (*i)->IsAdmin( Name ) ) - SendChat( player, m_GHost->m_Language->UserIsAnAdmin( Server, Name ) ); + SendChat( player, m_GHost->GetLanguage( )->UserIsAnAdmin( Server, Name ) ); else - SendChat( player, m_GHost->m_Language->UserIsNotAnAdmin( Server, Name ) ); + SendChat( player, m_GHost->GetLanguage( )->UserIsNotAnAdmin( Server, Name ) ); break; } } if( !FoundServer ) - SendChat( player, m_GHost->m_Language->ValidServers( Servers ) ); + SendChat( player, m_GHost->GetLanguage( )->ValidServers( Servers ) ); } } @@ -635,16 +635,16 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, CDBBan *Ban = (*i)->IsBannedName( Name ); if( Ban ) - SendChat( player, m_GHost->m_Language->UserWasBannedOnByBecause( Server, Name, Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); + SendChat( player, m_GHost->GetLanguage( )->UserWasBannedOnByBecause( Server, Name, Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); else - SendChat( player, m_GHost->m_Language->UserIsNotBanned( Server, Name ) ); + SendChat( player, m_GHost->GetLanguage( )->UserIsNotBanned( Server, Name ) ); break; } } if( !FoundServer ) - SendChat( player, m_GHost->m_Language->ValidServers( Servers ) ); + SendChat( player, m_GHost->GetLanguage( )->ValidServers( Servers ) ); } } @@ -720,7 +720,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, FoundServer = true; if( !(*i)->IsAdmin( Name ) ) - SendChat( player, m_GHost->m_Language->UserIsNotAnAdmin( Server, Name ) ); + SendChat( player, m_GHost->GetLanguage( )->UserIsNotAnAdmin( Server, Name ) ); else m_PairedAdminRemoves.push_back( PairedAdminRemove( player->GetName( ), m_GHost->m_DB->ThreadedAdminRemove( Server, Name ) ) ); @@ -729,7 +729,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, } if( !FoundServer ) - SendChat( player, m_GHost->m_Language->ValidServers( Servers ) ); + SendChat( player, m_GHost->GetLanguage( )->ValidServers( Servers ) ); } } @@ -747,7 +747,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "disable" ) { - SendChat( player, m_GHost->m_Language->BotDisabled( ) ); + SendChat( player, m_GHost->GetLanguage( )->BotDisabled( ) ); m_GHost->m_Enabled = false; } @@ -761,17 +761,17 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Downloads == 0 ) { - SendChat( player, m_GHost->m_Language->MapDownloadsDisabled( ) ); + SendChat( player, m_GHost->GetLanguage( )->MapDownloadsDisabled( ) ); m_GHost->m_AllowDownloads = 0; } else if( Downloads == 1 ) { - SendChat( player, m_GHost->m_Language->MapDownloadsEnabled( ) ); + SendChat( player, m_GHost->GetLanguage( )->MapDownloadsEnabled( ) ); m_GHost->m_AllowDownloads = 1; } else if( Downloads == 2 ) { - SendChat( player, m_GHost->m_Language->MapDownloadsConditional( ) ); + SendChat( player, m_GHost->GetLanguage( )->MapDownloadsConditional( ) ); m_GHost->m_AllowDownloads = 2; } } @@ -782,7 +782,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "enable" ) { - SendChat( player, m_GHost->m_Language->BotEnabled( ) ); + SendChat( player, m_GHost->GetLanguage( )->BotEnabled( ) ); m_GHost->m_Enabled = true; } @@ -798,12 +798,12 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( GameNumber < m_GHost->m_Games.size( ) ) { - SendChat( player, m_GHost->m_Language->EndingGame( m_GHost->m_Games[GameNumber]->GetDescription( ) ) ); + SendChat( player, m_GHost->GetLanguage( )->EndingGame( m_GHost->m_Games[GameNumber]->GetDescription( ) ) ); CONSOLE_Print( "[GAME: " + m_GHost->m_Games[GameNumber]->GetGameName( ) + "] is over (admin ended game)" ); m_GHost->m_Games[GameNumber]->StopPlayers( "was disconnected (admin ended game)" ); } else - SendChat( player, m_GHost->m_Language->GameNumberDoesntExist( Payload ) ); + SendChat( player, m_GHost->GetLanguage( )->GameNumberDoesntExist( Payload ) ); } // @@ -815,14 +815,14 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // only load files in the current directory just to be safe if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) - SendChat( player, m_GHost->m_Language->UnableToLoadReplaysOutside( ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToLoadReplaysOutside( ) ); else { QString File = m_GHost->m_ReplayPath + Payload + ".w3g"; if( QFile::exists( File ) ) { - SendChat( player, m_GHost->m_Language->LoadingReplay( File ) ); + SendChat( player, m_GHost->GetLanguage( )->LoadingReplay( File ) ); CReplay *Replay = new CReplay( ); Replay->Load( File, false ); Replay->ParseReplay( false ); @@ -830,7 +830,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, delete Replay; } else - SendChat( player, m_GHost->m_Language->UnableToLoadReplayDoesntExist( File ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToLoadReplayDoesntExist( File ) ); } } @@ -847,8 +847,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, deleteLater(); else { - if( m_GHost->m_CurrentGame || !m_GHost->m_Games.isEmpty( ) ) - SendChat( player, m_GHost->m_Language->AtLeastOneGameActiveUseForceToShutdown( ) ); + if( m_GHost->GetCurrentGame( ) || !m_GHost->m_Games.isEmpty( ) ) + SendChat( player, m_GHost->GetLanguage( )->AtLeastOneGameActiveUseForceToShutdown( ) ); else deleteLater(); } @@ -863,9 +863,9 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, int GameNumber = Payload.toUInt() - 1; if( GameNumber < m_GHost->m_Games.size( ) ) - SendChat( player, m_GHost->m_Language->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ) ); + SendChat( player, m_GHost->GetLanguage( )->GameNumberIs( Payload, m_GHost->m_Games[GameNumber]->GetDescription( ) ) ); else - SendChat( player, m_GHost->m_Language->GameNumberDoesntExist( Payload ) ); + SendChat( player, m_GHost->GetLanguage( )->GameNumberDoesntExist( Payload ) ); } // @@ -874,10 +874,10 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "getgames" ) { - if( m_GHost->m_CurrentGame ) - SendChat( player, m_GHost->m_Language->GameIsInTheLobby( m_GHost->m_CurrentGame->GetDescription( ), QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ) ); + if( m_GHost->GetCurrentGame( ) ) + SendChat( player, m_GHost->GetLanguage( )->GameIsInTheLobby( m_GHost->GetCurrentGame( )->GetDescription( ), QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ) ); else - SendChat( player, m_GHost->m_Language->ThereIsNoGameInTheLobby( QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ) ); + SendChat( player, m_GHost->GetLanguage( )->ThereIsNoGameInTheLobby( QString::number( m_GHost->m_Games.size( ) ), QString::number( m_GHost->m_MaxGames ) ) ); } // @@ -885,7 +885,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // if( Command == "hostsg" && !Payload.isEmpty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, true, Payload, User, User, QString( ), false ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PRIVATE, true, Payload, User, User, QString( ), false ); // // !LOAD (load config file) @@ -894,7 +894,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "load" ) { if( Payload.isEmpty( ) ) - SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); + SendChat( player, m_GHost->GetLanguage( )->CurrentlyLoadedMapCFGIs( m_GHost->GetCurrentMap( )->GetCFGFile( ) ) ); else { try @@ -905,7 +905,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( !MapCFGPath.exists() ) { CONSOLE_Print( "[ADMINGAME] error listing map configs - map config path doesn't exist" ); - SendChat( player, m_GHost->m_Language->ErrorListingMapConfigs( ) ); + SendChat( player, m_GHost->GetLanguage( )->ErrorListingMapConfigs( ) ); } else { @@ -913,30 +913,30 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, quint32 Matches = files.size(); if( Matches == 0 ) - SendChat( player, m_GHost->m_Language->NoMapConfigsFound( ) ); + SendChat( player, m_GHost->GetLanguage( )->NoMapConfigsFound( ) ); else if (files.contains(Pattern)) { - SendChat( player, m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ) ); + SendChat( player, m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ) ); CConfig MapCFG; MapCFG.Read( Pattern ); - m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); } else if (Matches == 1) { QString File = files.at(0); - SendChat( player, m_GHost->m_Language->LoadingConfigFile( m_GHost->m_MapCFGPath + File ) ); + SendChat( player, m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + File ) ); CConfig MapCFG; MapCFG.Read( m_GHost->m_MapCFGPath + File ); - m_GHost->m_Map->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); } else - SendChat( player, m_GHost->m_Language->FoundMapConfigs( files.join(", ") ) ); + SendChat( player, m_GHost->GetLanguage( )->FoundMapConfigs( files.join(", ") ) ); } } catch( const exception &ex ) { CONSOLE_Print( QString( "[ADMINGAME] error listing map configs - caught exception [" ) + ex.what( ) + "]" ); - SendChat( player, m_GHost->m_Language->ErrorListingMapConfigs( ) ); + SendChat( player, m_GHost->GetLanguage( )->ErrorListingMapConfigs( ) ); } } } @@ -950,7 +950,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // only load files in the current directory just to be safe if( Payload.indexOf( "/" ) != -1 || Payload.indexOf( "\\" ) != -1 ) - SendChat( player, m_GHost->m_Language->UnableToLoadSaveGamesOutside( ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToLoadSaveGamesOutside( ) ); else { QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; @@ -958,11 +958,11 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( QFile::exists( File ) ) { - if( m_GHost->m_CurrentGame ) - SendChat( player, m_GHost->m_Language->UnableToLoadSaveGameGameInLobby( ) ); + if( m_GHost->GetCurrentGame( ) ) + SendChat( player, m_GHost->GetLanguage( )->UnableToLoadSaveGameGameInLobby( ) ); else { - SendChat( player, m_GHost->m_Language->LoadingSaveGame( File ) ); + SendChat( player, m_GHost->GetLanguage( )->LoadingSaveGame( File ) ); m_GHost->m_SaveGame->Load( File, false ); m_GHost->m_SaveGame->ParseSaveGame( ); m_GHost->m_SaveGame->SetFileName( File ); @@ -970,7 +970,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, } } else - SendChat( player, m_GHost->m_Language->UnableToLoadSaveGameDoesntExist( File ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToLoadSaveGameDoesntExist( File ) ); } } @@ -981,7 +981,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "map" ) { if( Payload.isEmpty( ) ) - SendChat( player, m_GHost->m_Language->CurrentlyLoadedMapCFGIs( m_GHost->m_Map->GetCFGFile( ) ) ); + SendChat( player, m_GHost->GetLanguage( )->CurrentlyLoadedMapCFGIs( m_GHost->GetCurrentMap( )->GetCFGFile( ) ) ); else { try @@ -992,7 +992,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( !MapPath.exists() ) { CONSOLE_Print( "[ADMINGAME] error listing maps - map path doesn't exist" ); - SendChat( player, m_GHost->m_Language->ErrorListingMaps( ) ); + SendChat( player, m_GHost->GetLanguage( )->ErrorListingMaps( ) ); } else { @@ -1000,38 +1000,38 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, quint32 Matches = files.size(); if( Matches == 0 ) - SendChat( player, m_GHost->m_Language->NoMapsFound( ) ); + SendChat( player, m_GHost->GetLanguage( )->NoMapsFound( ) ); else if (files.contains(Pattern)) { - SendChat( player, m_GHost->m_Language->LoadingConfigFile( Pattern ) ); + SendChat( player, m_GHost->GetLanguage( )->LoadingConfigFile( Pattern ) ); // hackhack: create a config file in memory with the required information to load the map CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + Pattern ); MapCFG.Set( "map_localpath", Pattern ); - m_GHost->m_Map->Load( &MapCFG, Pattern ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, Pattern ); } else if( Matches == 1 ) { QString File = files.at(0); - SendChat( player, m_GHost->m_Language->LoadingConfigFile( File ) ); + SendChat( player, m_GHost->GetLanguage( )->LoadingConfigFile( File ) ); // hackhack: create a config file in memory with the required information to load the map CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + File ); MapCFG.Set( "map_localpath", File ); - m_GHost->m_Map->Load( &MapCFG, File ); + m_GHost->GetCurrentMap( )->Load( &MapCFG, File ); } else - SendChat( player, m_GHost->m_Language->FoundMaps( files.join(", ") ) ); + SendChat( player, m_GHost->GetLanguage( )->FoundMaps( files.join(", ") ) ); } } catch( const exception &ex ) { CONSOLE_Print( QString( "[ADMINGAME] error listing maps - caught exception [" ) + ex.what( ) + "]" ); - SendChat( player, m_GHost->m_Language->ErrorListingMaps( ) ); + SendChat( player, m_GHost->GetLanguage( )->ErrorListingMaps( ) ); } } } @@ -1041,7 +1041,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // if( Command == "priv" && !Payload.isEmpty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, Payload, User, User, QString( ), false ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PRIVATE, false, Payload, User, User, QString( ), false ); // // !PRIVBY (host private game by other player) @@ -1060,7 +1060,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); - m_GHost->CreateGame( m_GHost->m_Map, GAME_PRIVATE, false, GameName, Owner, User, QString( ), false ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PRIVATE, false, GameName, Owner, User, QString( ), false ); } } @@ -1069,7 +1069,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, // if( Command == "pub" && !Payload.isEmpty( ) ) - m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, Payload, User, User, QString( ), false ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PUBLIC, false, Payload, User, User, QString( ), false ); // // !PUBBY (host public game by other player) @@ -1088,7 +1088,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, { Owner = Payload.mid( 0, GameNameStart ); GameName = Payload.mid( GameNameStart + 1 ); - m_GHost->CreateGame( m_GHost->m_Map, GAME_PUBLIC, false, GameName, Owner, User, QString( ), false ); + m_GHost->CreateGame( m_GHost->GetCurrentMap( ), GAME_PUBLIC, false, GameName, Owner, User, QString( ), false ); } } @@ -1098,7 +1098,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "reload" ) { - SendChat( player, m_GHost->m_Language->ReloadingConfigurationFiles( ) ); + SendChat( player, m_GHost->GetLanguage( )->ReloadingConfigurationFiles( ) ); m_GHost->ReloadConfigs( ); } @@ -1144,7 +1144,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( GameNumber - 1 < m_GHost->m_Games.size( ) ) m_GHost->m_Games[GameNumber - 1]->SendAllChat( "ADMIN: " + Message ); else - SendChat( player, m_GHost->m_Language->GameNumberDoesntExist( QString::number( GameNumber ) ) ); + SendChat( player, m_GHost->GetLanguage( )->GameNumberDoesntExist( QString::number( GameNumber ) ) ); } } } @@ -1155,8 +1155,8 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "saygames" && !Payload.isEmpty( ) ) { - if( m_GHost->m_CurrentGame ) - m_GHost->m_CurrentGame->SendAllChat( Payload ); + if( m_GHost->GetCurrentGame( ) ) + m_GHost->GetCurrentGame( )->SendAllChat( Payload ); for( QList :: const_iterator i = m_GHost->m_Games.begin( ); i != m_GHost->m_Games.end( ); i++ ) (*i)->SendAllChat( "ADMIN: " + Payload ); @@ -1168,18 +1168,18 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "unhost" ) { - if( m_GHost->m_CurrentGame ) + if( m_GHost->GetCurrentGame( ) ) { - if( m_GHost->m_CurrentGame->GetCountDownStarted( ) ) - SendChat( player, m_GHost->m_Language->UnableToUnhostGameCountdownStarted( m_GHost->m_CurrentGame->GetDescription( ) ) ); + if( m_GHost->GetCurrentGame( )->GetCountDownStarted( ) ) + SendChat( player, m_GHost->GetLanguage( )->UnableToUnhostGameCountdownStarted( m_GHost->GetCurrentGame( )->GetDescription( ) ) ); else { - SendChat( player, m_GHost->m_Language->UnhostingGame( m_GHost->m_CurrentGame->GetDescription( ) ) ); - m_GHost->m_CurrentGame->deleteLater(); + SendChat( player, m_GHost->GetLanguage( )->UnhostingGame( m_GHost->GetCurrentGame( )->GetDescription( ) ) ); + m_GHost->GetCurrentGame( )->deleteLater(); } } else - SendChat( player, m_GHost->m_Language->UnableToUnhostGameNoGameInLobby( ) ); + SendChat( player, m_GHost->GetLanguage( )->UnableToUnhostGameNoGameInLobby( ) ); } // @@ -1221,7 +1221,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( !m_Password.isEmpty( ) && Payload == m_Password ) { CONSOLE_Print( "[ADMINGAME] user [" + User + "] logged in" ); - SendChat( player, m_GHost->m_Language->AdminLoggedIn( ) ); + SendChat( player, m_GHost->GetLanguage( )->AdminLoggedIn( ) ); player->SetLoggedIn( true ); } else @@ -1229,7 +1229,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, quint32 LoginAttempts = player->GetLoginAttempts( ) + 1; player->SetLoginAttempts( LoginAttempts ); CONSOLE_Print( "[ADMINGAME] user [" + User + "] login attempt failed" ); - SendChat( player, m_GHost->m_Language->AdminInvalidPassword( QString::number( LoginAttempts ) ) ); + SendChat( player, m_GHost->GetLanguage( )->AdminInvalidPassword( QString::number( LoginAttempts ) ) ); if( LoginAttempts >= 1 ) { diff --git a/ghost/game_admin.h b/src/libghost/game_admin.h similarity index 100% rename from ghost/game_admin.h rename to src/libghost/game_admin.h diff --git a/ghost/game_base.cpp b/src/libghost/game_base.cpp similarity index 91% rename from ghost/game_base.cpp rename to src/libghost/game_base.cpp index ec76da0..56ffd39 100644 --- a/ghost/game_base.cpp +++ b/src/libghost/game_base.cpp @@ -266,10 +266,10 @@ CBaseGame :: ~CBaseGame( ) { for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) { - (*i)->QueueChatCommand( m_GHost->m_Language->GameIsOver( GetDescription( ) ) ); + (*i)->QueueChatCommand( m_GHost->GetLanguage( )->GameIsOver( GetDescription( ) ) ); if( (*i)->GetServer( ) == GetCreatorServer( ) ) - (*i)->QueueChatCommand( m_GHost->m_Language->GameIsOver( GetDescription( ) ), GetCreatorName( ), true ); + (*i)->QueueChatCommand( m_GHost->GetLanguage( )->GameIsOver( GetDescription( ) ), GetCreatorName( ), true ); } // save replay @@ -663,7 +663,7 @@ void CBaseGame::EventRefreshTimeout() // only print the "game refreshed" message if we actually refreshed on at least one battle.net server if( m_RefreshMessages && Refreshed ) - SendAllChat( m_GHost->m_Language->GameRefreshed( ) ); + SendAllChat( m_GHost->GetLanguage( )->GameRefreshed( ) ); } } @@ -801,7 +801,7 @@ void CBaseGame::EventVotekickTimeout() return; CONSOLE_Print( "[GAME: " + m_GameName + "] votekick against player [" + m_KickVotePlayer + "] expired" ); - SendAllChat( m_GHost->m_Language->VoteKickExpired( m_KickVotePlayer ) ); + SendAllChat( m_GHost->GetLanguage( )->VoteKickExpired( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); } @@ -1228,7 +1228,7 @@ void CBaseGame::CheckPlayersStartedLaggging() void CBaseGame::EventDropLaggerTimeout() { - StopLaggers( m_GHost->m_Language->WasAutomaticallyDroppedAfterSeconds( QString::number(m_WaitTime) ) ); + StopLaggers( m_GHost->GetLanguage( )->WasAutomaticallyDroppedAfterSeconds( QString::number(m_WaitTime) ) ); } void CBaseGame::EventResetLagscreenTimeout() @@ -1363,7 +1363,7 @@ void CBaseGame :: EventPlayerDeleted() // unlock the game if the owner leaves if( m_Locked && player->GetName() == m_OwnerName ) { - SendAllChat( m_GHost->m_Language->GameUnlocked( ) ); + SendAllChat( m_GHost->GetLanguage( )->GameUnlocked( ) ); m_Locked = false; } @@ -1396,7 +1396,7 @@ void CBaseGame :: EventPlayerDeleted() else (*i)->UnqueueChatCommand( "/whois " + player->GetName( ) ); - (*i)->UnqueueChatCommand( "/w " + player->GetName( ) + " " + m_GHost->m_Language->SpoofCheckByReplying( ) ); + (*i)->UnqueueChatCommand( "/w " + player->GetName( ) + " " + m_GHost->GetLanguage( )->SpoofCheckByReplying( ) ); } } } @@ -1476,14 +1476,14 @@ void CBaseGame :: EventPlayerDeleted() if( m_CountDownStarted && !m_GameLoading && !m_GameLoaded ) { - SendAllChat( m_GHost->m_Language->CountDownAborted( ) ); + SendAllChat( m_GHost->GetLanguage( )->CountDownAborted( ) ); m_CountDownStarted = false; } // abort the votekick if( !m_KickVotePlayer.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->VoteKickCancelled( m_KickVotePlayer ) ); + SendAllChat( m_GHost->GetLanguage( )->VoteKickCancelled( m_KickVotePlayer ) ); m_KickVotePlayer.clear( ); m_VotekickTimer.stop(); @@ -1495,7 +1495,7 @@ void CBaseGame :: EventPlayerDisconnectTimedOut( CGamePlayer *player ) { if( !player->GetGProxyDisconnectNoticeSent( ) ) { - SendAllChat( player->GetName( ) + " " + m_GHost->m_Language->HasLostConnectionTimedOutGProxy( ) + "." ); + SendAllChat( player->GetName( ) + " " + m_GHost->GetLanguage( )->HasLostConnectionTimedOutGProxy( ) + "." ); player->SetGProxyDisconnectNoticeSent( true ); } @@ -1512,7 +1512,7 @@ void CBaseGame :: EventPlayerDisconnectTimedOut( CGamePlayer *player ) void CBaseGame::EventPlayerLaggedOut(CGamePlayer *player) { - player->SetLeftReason( m_GHost->m_Language->HasLostConnectionTimedOut( ) ); + player->SetLeftReason( m_GHost->GetLanguage( )->HasLostConnectionTimedOut( ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); if( !m_GameLoading && !m_GameLoaded ) @@ -1524,7 +1524,7 @@ void CBaseGame :: EventPlayerDisconnectPlayerError( CGamePlayer *player ) // at the time of this comment there's only one player error and that's when we receive a bad packet from the player // since TCP has checks and balances for data corruption the chances of this are pretty slim - player->SetLeftReason( m_GHost->m_Language->HasLostConnectionPlayerError( player->GetErrorString( ) ) ); + player->SetLeftReason( m_GHost->GetLanguage( )->HasLostConnectionPlayerError( player->GetErrorString( ) ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); if( !m_GameLoading && !m_GameLoaded ) @@ -1537,7 +1537,7 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) { if( !player->GetGProxyDisconnectNoticeSent( ) ) { - SendAllChat( player->GetName( ) + " " + m_GHost->m_Language->HasLostConnectionSocketErrorGProxy( player->GetSocket( )->errorString() ) + "." ); + SendAllChat( player->GetName( ) + " " + m_GHost->GetLanguage( )->HasLostConnectionSocketErrorGProxy( player->GetSocket( )->errorString() ) + "." ); player->SetGProxyDisconnectNoticeSent( true ); } @@ -1548,14 +1548,14 @@ void CBaseGame :: EventPlayerDisconnectSocketError( CGamePlayer *player ) if( TimeRemaining > ( (quint32)m_GProxyEmptyActions + 1 ) * 60 ) TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; - SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); + SendAllChat( player->GetPID( ), m_GHost->GetLanguage( )->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); player->SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } return; } - player->SetLeftReason( m_GHost->m_Language->HasLostConnectionSocketError( player->GetSocket( )->errorString( ) ) ); + player->SetLeftReason( m_GHost->GetLanguage( )->HasLostConnectionSocketError( player->GetSocket( )->errorString( ) ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); if( !m_GameLoading && !m_GameLoaded ) @@ -1568,7 +1568,7 @@ void CBaseGame :: EventPlayerDisconnectConnectionClosed( CGamePlayer *player ) { if( !player->GetGProxyDisconnectNoticeSent( ) ) { - SendAllChat( player->GetName( ) + " " + m_GHost->m_Language->HasLostConnectionClosedByRemoteHostGProxy( ) + "." ); + SendAllChat( player->GetName( ) + " " + m_GHost->GetLanguage( )->HasLostConnectionClosedByRemoteHostGProxy( ) + "." ); player->SetGProxyDisconnectNoticeSent( true ); } @@ -1579,14 +1579,14 @@ void CBaseGame :: EventPlayerDisconnectConnectionClosed( CGamePlayer *player ) if( TimeRemaining > ( (quint32)m_GProxyEmptyActions + 1 ) * 60 ) TimeRemaining = ( m_GProxyEmptyActions + 1 ) * 60; - SendAllChat( player->GetPID( ), m_GHost->m_Language->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); + SendAllChat( player->GetPID( ), m_GHost->GetLanguage( )->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); player->SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } return; } - player->SetLeftReason( m_GHost->m_Language->HasLostConnectionClosedByRemoteHost( ) ); + player->SetLeftReason( m_GHost->GetLanguage( )->HasLostConnectionClosedByRemoteHost( ) ); player->SetLeftCode( PLAYERLEAVE_DISCONNECT ); if( !m_GameLoading && !m_GameLoaded ) @@ -1620,7 +1620,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( GetPlayerFromName( joinPlayer->GetName( ), false ) ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but that name is already taken" ); - // SendAllChat( m_GHost->m_Language->TryingToJoinTheGameButTaken( joinPlayer->GetName( ) ) ); + // SendAllChat( m_GHost->GetLanguage( )->TryingToJoinTheGameButTaken( joinPlayer->GetName( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); return; @@ -1665,8 +1665,8 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_IgnoredNames.find( joinPlayer->GetName( ) ) == m_IgnoredNames.end( ) ) { - SendAllChat( m_GHost->m_Language->TryingToJoinTheGameButBannedByName( joinPlayer->GetName( ) ) ); - SendAllChat( m_GHost->m_Language->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->TryingToJoinTheGameButBannedByName( joinPlayer->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); m_IgnoredNames.insert( joinPlayer->GetName( ) ); } @@ -1693,8 +1693,8 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_IgnoredNames.find( joinPlayer->GetName( ) ) == m_IgnoredNames.end( ) ) { - SendAllChat( m_GHost->m_Language->TryingToJoinTheGameButBannedByIP( joinPlayer->GetName( ), potential->GetExternalIPString( ), Ban->GetName( ) ) ); - SendAllChat( m_GHost->m_Language->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->TryingToJoinTheGameButBannedByIP( joinPlayer->GetName( ), potential->GetExternalIPString( ), Ban->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); m_IgnoredNames.insert( joinPlayer->GetName( ) ); } @@ -1800,7 +1800,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( KickedPlayer ) { - KickedPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForReservedPlayer( joinPlayer->GetName( ) ) ); + KickedPlayer->SetLeftReason( m_GHost->GetLanguage( )->WasKickedForReservedPlayer( joinPlayer->GetName( ) ) ); KickedPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); // send a playerleave message immediately since it won't normally get sent until the player is deleted which is after we send a playerjoin message @@ -1833,7 +1833,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( KickedPlayer ) { - KickedPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForOwnerPlayer( joinPlayer->GetName( ) ) ); + KickedPlayer->SetLeftReason( m_GHost->GetLanguage( )->WasKickedForOwnerPlayer( joinPlayer->GetName( ) ) ); KickedPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); // send a playerleave message immediately since it won't normally get sent until the player is deleted which is after we send a playerjoin message @@ -1868,8 +1868,8 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( Ban ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is using a banned name" ); - SendAllChat( m_GHost->m_Language->HasBannedName( joinPlayer->GetName( ) ) ); - SendAllChat( m_GHost->m_Language->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->HasBannedName( joinPlayer->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); break; } } @@ -1879,8 +1879,8 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( Ban ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is using a banned IP address" ); - SendAllChat( m_GHost->m_Language->HasBannedIP( joinPlayer->GetName( ), potential->GetExternalIPString( ), Ban->GetName( ) ) ); - SendAllChat( m_GHost->m_Language->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->HasBannedIP( joinPlayer->GetName( ), potential->GetExternalIPString( ), Ban->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->UserWasBannedOnByBecause( Ban->GetServer( ), Ban->GetName( ), Ban->GetDate( ), Ban->GetAdmin( ), Ban->GetReason( ) ) ); break; } } @@ -2012,7 +2012,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP QByteArray UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) - SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( UniqueName ) ); + SendChat( Player, m_GHost->GetLanguage( )->SpoofCheckByWhispering( UniqueName ) ); } } @@ -2034,14 +2034,14 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP } if( !Others.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->MultipleIPAddressUsageDetected( joinPlayer->GetName( ), Others ) ); + SendAllChat( m_GHost->GetLanguage( )->MultipleIPAddressUsageDetected( joinPlayer->GetName( ), Others ) ); } // abort the countdown if there was one in progress if( m_CountDownStarted && !m_GameLoading && !m_GameLoaded ) { - SendAllChat( m_GHost->m_Language->CountDownAborted( ) ); + SendAllChat( m_GHost->GetLanguage( )->CountDownAborted( ) ); m_CountDownStarted = false; } @@ -2049,7 +2049,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP if( m_GHost->m_AutoLock && !m_Locked && IsOwner( joinPlayer->GetName( ) ) ) { - SendAllChat( m_GHost->m_Language->GameLocked( ) ); + SendAllChat( m_GHost->GetLanguage( )->GameLocked( ) ); m_Locked = true; } } @@ -2076,7 +2076,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( GetPlayerFromName( joinPlayer->GetName( ), false ) ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + joinPlayer->GetName( ) + "|" + potential->GetExternalIPString( ) + "] is trying to join the game but that name is already taken" ); - // SendAllChat( m_GHost->m_Language->TryingToJoinTheGameButTaken( joinPlayer->GetName( ) ) ); + // SendAllChat( m_GHost->GetLanguage( )->TryingToJoinTheGameButTaken( joinPlayer->GetName( ) ) ); potential->Send( m_Protocol->SEND_W3GS_REJECTJOIN( REJECTJOIN_FULL ) ); potential->deleteLater(); return; @@ -2193,9 +2193,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SID = GetSIDFromPID( FurthestPlayer->GetPID( ) ); if( FurthestPlayer->GetScore( ) < -99999.0 ) - FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( "N/A", QString::number( AverageScore, 'g', 2 ) ) ); + FurthestPlayer->SetLeftReason( m_GHost->GetLanguage( )->WasKickedForHavingFurthestScore( "N/A", QString::number( AverageScore, 'g', 2 ) ) ); else - FurthestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingFurthestScore( QString::number( FurthestPlayer->GetScore( ), 'g', 2 ), QString::number( AverageScore, 'g', 2 ) ) ); + FurthestPlayer->SetLeftReason( m_GHost->GetLanguage( )->WasKickedForHavingFurthestScore( QString::number( FurthestPlayer->GetScore( ), 'g', 2 ), QString::number( AverageScore, 'g', 2 ) ) ); FurthestPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2207,9 +2207,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco FurthestPlayer->deleteLater(); if( FurthestPlayer->GetScore( ) < -99999.0 ) - SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", QString::number( AverageScore, 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), "N/A", QString::number( AverageScore, 'g', 2 ) ) ); else - SendAllChat( m_GHost->m_Language->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), QString::number( FurthestPlayer->GetScore( ), 'g', 2 ), QString::number( AverageScore, 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerWasKickedForFurthestScore( FurthestPlayer->GetName( ), QString::number( FurthestPlayer->GetScore( ), 'g', 2 ), QString::number( AverageScore, 'g', 2 ) ) ); } else if( m_GHost->m_MatchMakingMethod == 2 ) { @@ -2253,9 +2253,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco SID = GetSIDFromPID( LowestPlayer->GetPID( ) ); if( LowestPlayer->GetScore( ) < -99999.0 ) - LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( "N/A" ) ); + LowestPlayer->SetLeftReason( m_GHost->GetLanguage( )->WasKickedForHavingLowestScore( "N/A" ) ); else - LowestPlayer->SetLeftReason( m_GHost->m_Language->WasKickedForHavingLowestScore( QString::number( LowestPlayer->GetScore( ), 'g', 2 ) ) ); + LowestPlayer->SetLeftReason( m_GHost->GetLanguage( )->WasKickedForHavingLowestScore( QString::number( LowestPlayer->GetScore( ), 'g', 2 ) ) ); LowestPlayer->SetLeftCode( PLAYERLEAVE_LOBBY ); @@ -2267,9 +2267,9 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco LowestPlayer->deleteLater(); if( LowestPlayer->GetScore( ) < -99999.0 ) - SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), "N/A" ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), "N/A" ) ); else - SendAllChat( m_GHost->m_Language->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), QString::number( LowestPlayer->GetScore( ), 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerWasKickedForLowestScore( LowestPlayer->GetName( ), QString::number( LowestPlayer->GetScore( ), 'g', 2 ) ) ); } } @@ -2391,14 +2391,14 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco QByteArray UniqueName = (*i)->GetUniqueName( ); if( (*i)->GetServer( ) == JoinedRealm ) - SendChat( Player, m_GHost->m_Language->SpoofCheckByWhispering( UniqueName.end( )) ); + SendChat( Player, m_GHost->GetLanguage( )->SpoofCheckByWhispering( UniqueName.end( )) ); } } if( score < -99999.0 ) - SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), "N/A" ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerHasScore( joinPlayer->GetName( ), "N/A" ) ); else - SendAllChat( m_GHost->m_Language->PlayerHasScore( joinPlayer->GetName( ), QString::number( score, 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerHasScore( joinPlayer->GetName( ), QString::number( score, 'g', 2 ) ) ); quint32 PlayersScored = 0; quint32 PlayersNotScored = 0; @@ -2430,7 +2430,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco } double Spread = MaxScore - MinScore; - SendAllChat( m_GHost->m_Language->RatedPlayersSpread( QString::number( PlayersScored ), QString::number( PlayersScored + PlayersNotScored ), QString::number( (quint32)Spread ) ) ); + SendAllChat( m_GHost->GetLanguage( )->RatedPlayersSpread( QString::number( PlayersScored ), QString::number( PlayersScored + PlayersNotScored ), QString::number( (quint32)Spread ) ) ); // check for multiple IP usage @@ -2450,14 +2450,14 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco } if( !Others.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->MultipleIPAddressUsageDetected( joinPlayer->GetName( ), Others ) ); + SendAllChat( m_GHost->GetLanguage( )->MultipleIPAddressUsageDetected( joinPlayer->GetName( ), Others ) ); } // abort the countdown if there was one in progress if( m_CountDownStarted && !m_GameLoading && !m_GameLoaded ) { - SendAllChat( m_GHost->m_Language->CountDownAborted( ) ); + SendAllChat( m_GHost->GetLanguage( )->CountDownAborted( ) ); m_CountDownStarted = false; } @@ -2465,7 +2465,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco if( m_GHost->m_AutoLock && !m_Locked && IsOwner( joinPlayer->GetName( ) ) ) { - SendAllChat( m_GHost->m_Language->GameLocked( ) ); + SendAllChat( m_GHost->GetLanguage( )->GameLocked( ) ); m_Locked = true; } @@ -2482,9 +2482,9 @@ void CBaseGame :: EventPlayerLeft( CGamePlayer *player, quint32 reason ) if( reason == PLAYERLEAVE_GPROXY ) - player->SetLeftReason( m_GHost->m_Language->WasUnrecoverablyDroppedFromGProxy( ) ); + player->SetLeftReason( m_GHost->GetLanguage( )->WasUnrecoverablyDroppedFromGProxy( ) ); else - player->SetLeftReason( m_GHost->m_Language->HasLeftVoluntarily( ) ); + player->SetLeftReason( m_GHost->GetLanguage( )->HasLeftVoluntarily( ) ); player->SetLeftCode( PLAYERLEAVE_LOST ); player->deleteLater(); @@ -2537,11 +2537,11 @@ void CBaseGame :: EventPlayerLoaded() for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) { if( *i != player && (*i)->GetFinishedLoading( ) ) - SendChat( *i, m_GHost->m_Language->PlayerFinishedLoading( player->GetName( ) ) ); + SendChat( *i, m_GHost->GetLanguage( )->PlayerFinishedLoading( player->GetName( ) ) ); } if( !FinishedLoading ) - SendChat( player, m_GHost->m_Language->PleaseWaitPlayersStillLoading( ) ); + SendChat( player, m_GHost->GetLanguage( )->PleaseWaitPlayersStillLoading( ) ); } else SendAll( m_Protocol->SEND_W3GS_GAMELOADED_OTHERS( player->GetPID( ) ) ); @@ -2558,7 +2558,7 @@ void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *actio if( !action->GetAction( )->isEmpty( ) && (*action->GetAction( )).at(0) == 6 ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] is saving the game" ); - SendAllChat( m_GHost->m_Language->PlayerIsSavingTheGame( player->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerIsSavingTheGame( player->GetName( ) ) ); } } @@ -2596,7 +2596,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check if( (*i)->GetCheckSums( )->front( ) != FirstCheckSum ) { CONSOLE_Print( "[GAME: " + m_GameName + "] desync detected" ); - SendAllChat( m_GHost->m_Language->DesyncDetected( ) ); + SendAllChat( m_GHost->GetLanguage( )->DesyncDetected( ) ); // try to figure out who desynced // this is complicated by the fact that we don't know what the correct game state is so we let the players vote @@ -2636,7 +2636,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check } } - SendAllChat( m_GHost->m_Language->PlayersInGameState( QString::number( StateNumber ), Players ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersInGameState( QString::number( StateNumber ), Players ) ); StateNumber++; } @@ -2652,7 +2652,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check // todotodo: it would be possible to split the game at this point and create a "new" game for each game state CONSOLE_Print( "[GAME: " + m_GameName + "] can't kick desynced players because there is a tie, kicking all players instead" ); - StopPlayers( m_GHost->m_Language->WasDroppedDesync( ) ); + StopPlayers( m_GHost->GetLanguage( )->WasDroppedDesync( ) ); AddToReplay = false; } else @@ -2674,7 +2674,7 @@ void CBaseGame :: EventPlayerKeepAlive( CGamePlayer */*player*/, quint32 /*check if( Player ) { - Player->SetLeftReason( m_GHost->m_Language->WasDroppedDesync( ) ); + Player->SetLeftReason( m_GHost->GetLanguage( )->WasDroppedDesync( ) ); Player->SetLeftCode( PLAYERLEAVE_LOST ); Player->deleteLater(); } @@ -2765,7 +2765,7 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye QString Message = chatPlayer->GetMessage( ); if( Message == "?trigger" ) - SendChat( player, m_GHost->m_Language->CommandTrigger( QString( 1, m_GHost->m_CommandTrigger ) ) ); + SendChat( player, m_GHost->GetLanguage( )->CommandTrigger( QString( 1, m_GHost->m_CommandTrigger ) ) ); else if( !Message.isEmpty( ) && Message[0] == m_GHost->m_CommandTrigger ) { // extract the command trigger, the command, and the payload @@ -2806,10 +2806,10 @@ void CBaseGame :: EventPlayerChatToHost( CGamePlayer *player, CIncomingChatPlaye } } -bool CBaseGame :: EventPlayerBotCommand( CGamePlayer */*player*/, const QString &/*command*/, const QString &/*payload*/ ) +bool CBaseGame :: EventPlayerBotCommand( CGamePlayer *player, const QString &command, const QString &payload ) { // return true if the command itself should be hidden from other players - + emit SignalPlayerCommand( this, player, command, payload ); return false; } @@ -2959,7 +2959,7 @@ void CBaseGame :: EventPlayerDropRequest( CGamePlayer *player ) if( m_Lagging ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] voted to drop laggers" ); - SendAllChat( m_GHost->m_Language->PlayerVotedToDropLaggers( player->GetName( ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerVotedToDropLaggers( player->GetName( ) ) ); // check if at least half the players voted to drop @@ -2972,7 +2972,7 @@ void CBaseGame :: EventPlayerDropRequest( CGamePlayer *player ) } if( (float)Votes / m_Players.size( ) > 0.49 ) - StopLaggers( m_GHost->m_Language->LaggedOutDroppedByVote( ) ); + StopLaggers( m_GHost->GetLanguage( )->LaggedOutDroppedByVote( ) ); } } @@ -3035,7 +3035,7 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map float Seconds = (float)( GetTicks( ) - player->GetStartedDownloadingTicks( ) ) / 1000; float Rate = (float)MapSize / 1024 / Seconds; CONSOLE_Print( "[GAME: " + m_GameName + "] map download finished for player [" + player->GetName( ) + "] in " + QString::number( Seconds, 'g', 1 ) + " seconds" ); - SendAllChat( m_GHost->m_Language->PlayerDownloadedTheMap( player->GetName( ), QString::number( Seconds, 'g', 1 ), QString::number( Rate, 'g', 1 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayerDownloadedTheMap( player->GetName( ), QString::number( Seconds, 'g', 1 ), QString::number( Rate, 'g', 1 ) ) ); player->SetDownloadFinished( true ); player->SetFinishedDownloadingTime( GetTime( ) ); @@ -3105,7 +3105,7 @@ void CBaseGame :: EventPlayerPongToHost( CGamePlayer *player, quint32 /*pong*/ ) { // send a chat message because we don't normally do so when a player leaves the lobby - SendAllChat( m_GHost->m_Language->AutokickingPlayerForExcessivePing( player->GetName( ), QString::number( player->GetPing( m_GHost->m_LCPings ) ) ) ); + SendAllChat( m_GHost->GetLanguage( )->AutokickingPlayerForExcessivePing( player->GetName( ), QString::number( player->GetPing( m_GHost->m_LCPings ) ) ) ); player->SetLeftReason( "was autokicked for excessive ping of " + QString::number( player->GetPing( m_GHost->m_LCPings ) ) ); player->SetLeftCode( PLAYERLEAVE_LOBBY ); player->deleteLater(); @@ -3121,7 +3121,7 @@ void CBaseGame :: EventGameRefreshed( const QString &/*server*/ ) // but since we unqueue game refreshes when rehosting, the only way this can happen is due to network delay // it's a risk we're willing to take but can result in a false positive here - SendAllChat( m_GHost->m_Language->RehostWasSuccessful( ) ); + SendAllChat( m_GHost->GetLanguage( )->RehostWasSuccessful( ) ); m_RefreshRehosted = false; } } @@ -3335,12 +3335,12 @@ void CBaseGame :: EventGameLoaded( ) if( Shortest && Longest ) { - SendAllChat( m_GHost->m_Language->ShortestLoadByPlayer( Shortest->GetName( ), QString::number( (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); - SendAllChat( m_GHost->m_Language->LongestLoadByPlayer( Longest->GetName( ), QString::number( (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->ShortestLoadByPlayer( Shortest->GetName( ), QString::number( (float)( Shortest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->LongestLoadByPlayer( Longest->GetName( ), QString::number( (float)( Longest->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); } for( QList :: const_iterator i = m_Players.begin( ); i != m_Players.end( ); i++ ) - SendChat( *i, m_GHost->m_Language->YourLoadingTimeWas( QString::number( (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); + SendChat( *i, m_GHost->GetLanguage( )->YourLoadingTimeWas( QString::number( (float)( (*i)->GetFinishedLoadingTicks( ) - m_StartedLoadingTicks ) / 1000, 'g', 2 ) ) ); // read from gameloaded.txt if available @@ -4101,7 +4101,7 @@ void CBaseGame :: BalanceSlots( ) // a possible alternative: stop after enough iterations and/or time has passed CONSOLE_Print( "[GAME: " + m_GameName + "] shuffling slots instead of balancing - the algorithm is too slow (with a cost of " + QString::number( AlgorithmCost ) + ") for this team configuration" ); - SendAllChat( m_GHost->m_Language->ShufflingPlayers( ) ); + SendAllChat( m_GHost->GetLanguage( )->ShufflingPlayers( ) ); ShuffleSlots( ); return; } @@ -4139,7 +4139,7 @@ void CBaseGame :: BalanceSlots( ) else { CONSOLE_Print( "[GAME: " + m_GameName + "] shuffling slots instead of balancing - the balancing algorithm tried to do an invalid swap (this shouldn't happen)" ); - SendAllChat( m_GHost->m_Language->ShufflingPlayers( ) ); + SendAllChat( m_GHost->GetLanguage( )->ShufflingPlayers( ) ); ShuffleSlots( ); return; } @@ -4150,7 +4150,7 @@ void CBaseGame :: BalanceSlots( ) } CONSOLE_Print( "[GAME: " + m_GameName + "] balancing slots completed in " + QString::number( EndTicks - StartTicks ) + "ms (with a cost of " + QString::number( AlgorithmCost ) + ")" ); - SendAllChat( m_GHost->m_Language->BalancingSlotsCompleted( ) ); + SendAllChat( m_GHost->GetLanguage( )->BalancingSlotsCompleted( ) ); SendAllSlotInfo( ); for( unsigned char i = 0; i < 12; i++ ) @@ -4175,7 +4175,7 @@ void CBaseGame :: BalanceSlots( ) } if( TeamHasPlayers ) - SendAllChat( m_GHost->m_Language->TeamCombinedScore( QString::number( i + 1 ), QString::number( TeamScore, 'g', 2 ) ) ); + SendAllChat( m_GHost->GetLanguage( )->TeamCombinedScore( QString::number( i + 1 ), QString::number( TeamScore, 'g', 2 ) ) ); } } @@ -4189,7 +4189,7 @@ void CBaseGame :: AddToSpoofed( const QString &server, const QString &name, bool Player->SetSpoofed( true ); if( sendMessage ) - SendAllChat( m_GHost->m_Language->SpoofCheckAcceptedFor( server, name ) ); + SendAllChat( m_GHost->GetLanguage( )->SpoofCheckAcceptedFor( server, name ) ); } } @@ -4267,7 +4267,7 @@ void CBaseGame :: StartCountDown( bool force ) if( m_HCLCommandString.size( ) > (int)GetSlotsOccupied( ) ) { - SendAllChat( m_GHost->m_Language->TheHCLIsTooLongUseForceToStart( ) ); + SendAllChat( m_GHost->GetLanguage( )->TheHCLIsTooLongUseForceToStart( ) ); return; } @@ -4292,7 +4292,7 @@ void CBaseGame :: StartCountDown( bool force ) } if( !StillDownloading.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->PlayersStillDownloading( StillDownloading ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersStillDownloading( StillDownloading ) ); // check if everyone is spoof checked @@ -4312,7 +4312,7 @@ void CBaseGame :: StartCountDown( bool force ) } if( !NotSpoofChecked.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); } // check if everyone has been pinged enough (3 times) that the autokicker would have kicked them by now @@ -4332,7 +4332,7 @@ void CBaseGame :: StartCountDown( bool force ) } if( !NotPinged.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->PlayersNotYetPinged( NotPinged ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersNotYetPinged( NotPinged ) ); // if no problems found start the game @@ -4355,7 +4355,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( GetNumHumanPlayers( ) < m_AutoStartPlayers ) { - SendAllChat( m_GHost->m_Language->WaitingForPlayersBeforeAutoStart( QString::number( m_AutoStartPlayers ), QString::number( m_AutoStartPlayers - GetNumHumanPlayers( ) ) ) ); + SendAllChat( m_GHost->GetLanguage( )->WaitingForPlayersBeforeAutoStart( QString::number( m_AutoStartPlayers ), QString::number( m_AutoStartPlayers - GetNumHumanPlayers( ) ) ) ); return; } @@ -4381,7 +4381,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( !StillDownloading.isEmpty( ) ) { - SendAllChat( m_GHost->m_Language->PlayersStillDownloading( StillDownloading ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersStillDownloading( StillDownloading ) ); return; } @@ -4403,7 +4403,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) } if( !NotSpoofChecked.isEmpty( ) ) - SendAllChat( m_GHost->m_Language->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersNotYetSpoofChecked( NotSpoofChecked ) ); } // check if everyone has been pinged enough (3 times) that the autokicker would have kicked them by now @@ -4424,7 +4424,7 @@ void CBaseGame :: StartCountDownAuto( bool requireSpoofChecks ) if( !NotPinged.isEmpty( ) ) { - SendAllChat( m_GHost->m_Language->PlayersNotYetPingedAutoStart( NotPinged ) ); + SendAllChat( m_GHost->GetLanguage( )->PlayersNotYetPingedAutoStart( NotPinged ) ); return; } diff --git a/ghost/game_base.h b/src/libghost/game_base.h similarity index 97% rename from ghost/game_base.h rename to src/libghost/game_base.h index cf1b2f1..4d456e8 100644 --- a/ghost/game_base.h +++ b/src/libghost/game_base.h @@ -54,6 +54,7 @@ class CBaseGame : public QObject signals: void startedLoading(); void finishedLoading(); + void SignalPlayerCommand( CBaseGame *game, CGamePlayer *player, const QString &command, const QString &payload ); public: CGHost *m_GHost; diff --git a/ghost/gameplayer.cpp b/src/libghost/gameplayer.cpp similarity index 94% rename from ghost/gameplayer.cpp rename to src/libghost/gameplayer.cpp index 3820819..c38f7f6 100644 --- a/ghost/gameplayer.cpp +++ b/src/libghost/gameplayer.cpp @@ -122,7 +122,7 @@ void CGamePlayer::EventWhoisTimeout() (*i)->QueueChatCommand( "/whois " + m_Name ); } else if( m_Game->GetGameState( ) == GAME_PRIVATE ) - (*i)->QueueChatCommand( m_Game->m_GHost->m_Language->SpoofCheckByReplying( ), m_Name, true ); + (*i)->QueueChatCommand( m_Game->m_GHost->GetLanguage( )->SpoofCheckByReplying( ), m_Name, true ); } } @@ -384,7 +384,7 @@ void CGamePlayer::EventSpoofCheckTimeout() return; deleteLater(); - SetLeftReason( m_Game->m_GHost->m_Language->WasKickedForNotSpoofChecking( ) ); + SetLeftReason( m_Game->m_GHost->GetLanguage( )->WasKickedForNotSpoofChecking( ) ); SetLeftCode( PLAYERLEAVE_LOBBY ); m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false ); } @@ -424,7 +424,7 @@ void CGamePlayer::EventSendGProxyMessage() if( TimeRemaining > ( (quint32)m_Game->GetGProxyEmptyActions() + 1 ) * 60 ) TimeRemaining = ( m_Game->GetGProxyEmptyActions() + 1 ) * 60; - m_Game->SendAllChat( GetPID( ), m_Game->m_GHost->m_Language->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); + m_Game->SendAllChat( GetPID( ), m_Game->m_GHost->GetLanguage( )->WaitForReconnectSecondsRemain( QString::number( TimeRemaining ) ) ); SetLastGProxyWaitNoticeSentTime( GetTime( ) ); } @@ -600,7 +600,7 @@ void CGamePlayer :: ProcessPackets( ) break; case CGameProtocol :: W3GS_MAPSIZE: - MapSize = m_Protocol->RECEIVE_W3GS_MAPSIZE( Packet->GetData( ), m_Game->m_GHost->m_Map->GetMapSize( ) ); + MapSize = m_Protocol->RECEIVE_W3GS_MAPSIZE( Packet->GetData( ), m_Game->m_GHost->GetCurrentMap( )->GetMapSize( ) ); if( MapSize ) m_Game->EventPlayerMapSize( this, MapSize ); @@ -742,5 +742,5 @@ void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPac m_GProxyBuffer = TempBuffer; m_GProxyDisconnectNoticeSent = false; - m_Game->SendAllChat( m_Game->m_GHost->m_Language->PlayerReconnectedWithGProxy( m_Name ) ); + m_Game->SendAllChat( m_Game->m_GHost->GetLanguage( )->PlayerReconnectedWithGProxy( m_Name ) ); } diff --git a/ghost/gameplayer.h b/src/libghost/gameplayer.h similarity index 100% rename from ghost/gameplayer.h rename to src/libghost/gameplayer.h diff --git a/ghost/gameprotocol.cpp b/src/libghost/gameprotocol.cpp similarity index 100% rename from ghost/gameprotocol.cpp rename to src/libghost/gameprotocol.cpp diff --git a/ghost/gameprotocol.h b/src/libghost/gameprotocol.h similarity index 100% rename from ghost/gameprotocol.h rename to src/libghost/gameprotocol.h diff --git a/ghost/gameslot.cpp b/src/libghost/gameslot.cpp similarity index 100% rename from ghost/gameslot.cpp rename to src/libghost/gameslot.cpp diff --git a/ghost/gameslot.h b/src/libghost/gameslot.h similarity index 100% rename from ghost/gameslot.h rename to src/libghost/gameslot.h diff --git a/ghost/ghost.cpp b/src/libghost/ghost.cpp similarity index 88% rename from ghost/ghost.cpp rename to src/libghost/ghost.cpp index 663240b..e112abb 100644 --- a/ghost/ghost.cpp +++ b/src/libghost/ghost.cpp @@ -19,6 +19,7 @@ */ #include "ghost.h" +#include "ghost_p.h" #include "util.h" #include "crc32.h" #include "sha1.h" @@ -52,23 +53,135 @@ #include #include +// TODOTODO: remove this crappy implementation and replace it with something monotonic :) +static bool timerStarted=FALSE; +static QTime gBasicTime; + + +quint32 GetTime() +{ + return GetTicks( ) / 1000; +} + +quint32 GetTicks() +{ + if( !timerStarted ) + gBasicTime.start(); + return gBasicTime.elapsed(); +} + +void CONSOLE_Print( QString message ) +{ + cout << message.toStdString() << endl; + + // logging + + /*if (!gLogFile.fileName().isEmpty()) + { + if( gLogMethod == 1 ) + { + gLogFile.open(QFile::WriteOnly | QFile::Append); + + if( gLogFile.isWritable() ) + { + gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; + gLogFile.close(); + } + } + else if( gLogMethod == 2 && gLogFile.isWritable() ) + gLogStream << "[" << QTime::currentTime().toString() << "] " << message << endl; + }*/ +} + +void DEBUG_Print( QString message ) +{ + cout << message.toStdString() << endl; +} + + // // CGHost // +CGame *CGHost :: GetCurrentGame() const +{ + return m_CurrentGame; +} + +CAdminGame *CGHost :: GetAdminGame() const +{ + return m_AdminGame; +} + +CLanguage *CGHost :: GetLanguage( ) const +{ + return m_Language; +} + +CMap *CGHost :: GetCurrentMap( ) const +{ + return m_Map; +} + +void CGHost :: SetCurrentMap( CMap *map) +{ + if( m_Map ) + delete m_Map; + m_Map = map; +} + +CMap *CGHost :: GetAdminMap( ) const +{ + return m_AdminMap; +} + +CMap *CGHost :: GetAutoHostMap( ) const +{ + return m_AutoHostMap; +} + +void CGHost :: SetAutoHostMap( CMap *map) +{ + if( m_AutoHostMap ) + delete m_AutoHostMap; + m_AutoHostMap = map; +} + +void CGHost :: EventGameCommand( CBaseGame *game, CGamePlayer *player, const QString &command, const QString &payload ) +{ + CommandData data( command, payload ); + // TODO: what do we do with IsAdmin and IsRootAdmin? + for( QList :: const_iterator i = d_ptr->m_CommandProviders.begin( ); i != d_ptr->m_CommandProviders.end( ); i++ ) + { + (*i)->OnGameCommand( game, player, data ); + } +} + +void CGHost :: EventBnetCommand( CBNET *bnet, const QString &user, const QString &command, const QString &payload, bool whisper ) +{ + CommandData data( command, payload ); + data.SetAdmin( bnet->IsAdmin( user ) ); + data.SetRootAdmin( bnet->IsRootAdmin( user ) ); + for( QList :: const_iterator i = d_ptr->m_CommandProviders.begin( ); i != d_ptr->m_CommandProviders.end( ); i++ ) + { + (*i)->OnBNETCommand( bnet, user, whisper, data ); + } +} + CGHost :: CGHost( CConfig *CFG, QString configFile ) - : m_ConfigFile(configFile) + : d_ptr(new CGHostPrivate()), + m_ConfigFile(configFile) { foreach( QObject *plugin, QPluginLoader::staticInstances() ) { - LoadPlugin( plugin ); + LoadPlugin( plugin, CFG ); } QDir pluginsDir = QDir( qApp->applicationDirPath() ); QString cfgPluginDir = CFG->GetString( "bot_plugindir", "plugins" ); pluginsDir.cd( cfgPluginDir ); - LoadPlugins( pluginsDir ); + LoadPlugins( pluginsDir, CFG ); m_UDPSocket = new QUdpSocket(this); m_UDPSocket->setProperty("target", CFG->GetString( "udp_broadcasttarget", QString( ) ) ); @@ -269,8 +382,12 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CONSOLE_Print( "[GHOST] unable to get system locale, using default locale of 1033" ); #endif } - - m_BNETs.push_back( new CBNET( this, Server, ServerAlias, BNLSServer, (quint16)BNLSPort, (quint32)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger.at(0).toAscii(), HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ) ); + CBNET *bnet = new CBNET( this, Server, ServerAlias, BNLSServer, (quint16)BNLSPort, (quint32)BNLSWardenCookie, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, LocaleID, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger.at(0).toAscii(), HoldFriends, HoldClan, PublicCommands, War3Version, EXEVersion, EXEVersionHash, PasswordHashType, PVPGNRealmName, MaxMessageLength, i ); + QObject::connect(bnet, + SIGNAL(SignalBnetCommand(CBNET*, const QString&, const QString&, const QString&, bool)), + this, + SLOT(EventBnetCommand(CBNET*, const QString&, const QString&, const QString&, bool))); + m_BNETs.push_back( bnet ); } if( m_BNETs.isEmpty( ) ) @@ -333,6 +450,10 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) { CONSOLE_Print( "[GHOST] creating admin game" ); m_AdminGame = new CAdminGame( this, m_AdminMap, NULL, m_AdminGamePort, 0, "GHost++ Admin Game", m_AdminGamePassword ); + QObject::connect(m_AdminGame, + SIGNAL(SignalPlayerCommand(CBaseGame*, CGamePlayer *, const QString &, const QString &)), + this, + SLOT(EventGameCommand(CBaseGame*, CGamePlayer *, const QString &, const QString &))); QObject::connect(m_AdminGame, SIGNAL(destroyed()), this, SLOT(EventAdminGameDeleted())); if( m_AdminGamePort == m_HostPort ) @@ -359,30 +480,32 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) } } -void CGHost :: LoadPlugin( QObject *plugin ) +void CGHost :: LoadPlugin( QObject *plugin, CConfig *cfg ) { bool validPlugin = false; - /*IGHostPlugin *iPlugin = qobject_cast( plugin ); + IGHostPlugin *iPlugin = qobject_cast( plugin ); if( !iPlugin ) { CONSOLE_Print( "[PLUGIN] ERROR: Plugin does not implement IGHostPlugin" ); return; - }*/ + } + + iPlugin->PluginLoaded(this, cfg); ICommandProvider *iCmd = qobject_cast( plugin ); if( iCmd ) { - CONSOLE_Print( "[PLUGIN] Found CommandProvider" ); + CONSOLE_Print( "[PLUGIN] Found CommandProvider [" + iCmd->GetName() + "]" ); validPlugin = true; - m_Commands.append( iCmd ); + d_ptr->m_CommandProviders.append( iCmd ); } if( !validPlugin ) CONSOLE_Print( "[PLUGIN] WARNING: plugin did not contain valid interfaces!" ); } -void CGHost :: LoadPlugins( QDir path ) +void CGHost :: LoadPlugins( QDir path, CConfig *cfg ) { CONSOLE_Print( "[PLUGIN] Loading plugins from [" + path.absolutePath() + "]" ); @@ -392,7 +515,7 @@ void CGHost :: LoadPlugins( QDir path ) if( plugin ) { CONSOLE_Print( "[PLUGIN] Loading plugin [" + fileName + "]" ); - LoadPlugin( plugin ); + LoadPlugin( plugin, cfg ); } else CONSOLE_Print( "[PLUGIN] Ignoring non-plugin file [" + fileName + "]" ); @@ -1209,7 +1332,11 @@ void CGHost :: CreateGame( CMap *map, unsigned char gameState, bool saveGame, co m_CurrentGame = new CGame( this, map, m_SaveGame, m_HostPort, gameState, gameName, ownerName, creatorName, creatorServer ); else m_CurrentGame = new CGame( this, map, NULL, m_HostPort, gameState, gameName, ownerName, creatorName, creatorServer ); - + + QObject::connect(m_CurrentGame, + SIGNAL(SignalPlayerCommand(CBaseGame*, CGamePlayer *, const QString &, const QString &)), + this, + SLOT(EventGameCommand(CBaseGame*, CGamePlayer *, const QString &, const QString &))); QObject::connect(m_CurrentGame, SIGNAL(startedLoading()), this, SLOT(EventGameStarted())); QObject::connect(m_CurrentGame, SIGNAL(destroyed()), this, SLOT(EventGameDeleted())); diff --git a/ghost/ghost.h b/src/libghost/ghost.h similarity index 88% rename from ghost/ghost.h rename to src/libghost/ghost.h index 301fe05..e5c0127 100644 --- a/ghost/ghost.h +++ b/src/libghost/ghost.h @@ -22,10 +22,12 @@ #define GHOST_H #include "includes.h" +#include "interfaces.h" #include #include #include +#include // // CGHost @@ -36,6 +38,7 @@ class CCRC32; class CSHA1; class CBNET; class CBaseGame; +class CGame; class CAdminGame; class CGHostDB; class CBaseCallable; @@ -43,7 +46,7 @@ class CLanguage; class CMap; class CSaveGame; class CConfig; -class ICommandProvider; +class CGHostPrivate; QT_FORWARD_DECLARE_CLASS(QDir) QT_FORWARD_DECLARE_CLASS(QUdpSocket) QT_FORWARD_DECLARE_CLASS(QTcpServer) @@ -51,7 +54,33 @@ QT_FORWARD_DECLARE_CLASS(QTcpServer) class CGHost : public QObject { Q_OBJECT - +public: + CGame *GetCurrentGame( ) const; + CAdminGame *GetAdminGame( ) const; + CLanguage *GetLanguage( ) const; + CMap *GetCurrentMap( ) const; + void SetCurrentMap( CMap *map); + CMap *GetAdminMap( ) const; + CMap *GetAutoHostMap( ) const; + void SetAutoHostMap( CMap *map ); + +// slots for game events +public slots: + void EventGameStarted(); + void EventGameDeleted(); + void EventGameCommand( CBaseGame *game, CGamePlayer *player, const QString &command, const QString &payload ); + void EventBnetCommand( CBNET *bnet, const QString &user, const QString &command, const QString &payload, bool whisper ); +protected: + QScopedPointer d_ptr; +private: + Q_DECLARE_PRIVATE(CGHost) + CGame *m_CurrentGame; // this game is still in the lobby state + CAdminGame *m_AdminGame; // this "fake game" allows an admin who knows the password to control the bot from the local network + CLanguage *m_Language; // language + CMap *m_Map; // the currently loaded map + CMap *m_AdminMap; // the map to use in the admin game + CMap *m_AutoHostMap; // the map to use when autohosting + public slots: void EventIncomingReconnection(); void EventReconnectionSocketReadyRead(); @@ -60,13 +89,11 @@ public slots: void EventExitNice(); void EventWaitForNiceExitTimeout(); void EventAutoHost(); - void EventGameStarted(); - void EventGameDeleted(); void EventAdminGameDeleted(); void CreateReconnectServer(); private: - void LoadPlugin( QObject *plugin ); - void LoadPlugins( QDir path ); + void LoadPlugin( QObject *plugin, CConfig *cfg ); + void LoadPlugins( QDir path, CConfig *cfg ); public: QTime m_LastAutoHostTime; QTimer m_CallableUpdateTimer, m_AutoHostTimer; @@ -75,19 +102,12 @@ public slots: CGPSProtocol *m_GPSProtocol; CCRC32 *m_CRC; // for calculating CRC's CSHA1 *m_SHA; // for calculating SHA1's - QList m_Commands; // list of plugins providing commands QList m_BNETs; // all our battle.net connections (there can be more than one) - CBaseGame *m_CurrentGame; // this game is still in the lobby state - CAdminGame *m_AdminGame; // this "fake game" allows an admin who knows the password to control the bot from the local network QList m_Games; // these games are in progress CGHostDB *m_DB; // database CGHostDB *m_DBLocal; // local database (for temporary data) QList m_Callables; // vector of orphaned callables waiting to die QList m_LocalAddresses; // vector of local IP addresses - CLanguage *m_Language; // language - CMap *m_Map; // the currently loaded map - CMap *m_AdminMap; // the map to use in the admin game - CMap *m_AutoHostMap; // the map to use when autohosting CSaveGame *m_SaveGame; // the save game to use QList m_EnforcePlayers; // vector of pids to force players to use in the next game (used with saved games) bool m_Exiting; // set to true to force ghost to shutdown next update (used by SignalCatcher) diff --git a/ghost/ghost.vcproj b/src/libghost/ghost.vcproj similarity index 100% rename from ghost/ghost.vcproj rename to src/libghost/ghost.vcproj diff --git a/src/libghost/ghost_p.h b/src/libghost/ghost_p.h new file mode 100644 index 0000000..e0b093e --- /dev/null +++ b/src/libghost/ghost_p.h @@ -0,0 +1,30 @@ +/* + * ghost_p.h + * ghost + * + * Created by Lucas on 14.05.10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef GHOST_P_H +#define GHOST_P_H + +class ICommandProvider; + +// +// W A R N I N G +// ------------- +// +// This file is not part of the GHost API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// + +class CGHostPrivate +{ +public: + QList m_CommandProviders; +}; + +#endif diff --git a/ghost/ghostdb.cpp b/src/libghost/ghostdb.cpp similarity index 100% rename from ghost/ghostdb.cpp rename to src/libghost/ghostdb.cpp diff --git a/ghost/ghostdb.h b/src/libghost/ghostdb.h similarity index 100% rename from ghost/ghostdb.h rename to src/libghost/ghostdb.h diff --git a/ghost/ghostdbmysql.cpp b/src/libghost/ghostdbmysql.cpp similarity index 100% rename from ghost/ghostdbmysql.cpp rename to src/libghost/ghostdbmysql.cpp diff --git a/ghost/ghostdbmysql.h b/src/libghost/ghostdbmysql.h similarity index 100% rename from ghost/ghostdbmysql.h rename to src/libghost/ghostdbmysql.h diff --git a/ghost/ghostdbsqlite.cpp b/src/libghost/ghostdbsqlite.cpp similarity index 100% rename from ghost/ghostdbsqlite.cpp rename to src/libghost/ghostdbsqlite.cpp diff --git a/ghost/ghostdbsqlite.h b/src/libghost/ghostdbsqlite.h similarity index 100% rename from ghost/ghostdbsqlite.h rename to src/libghost/ghostdbsqlite.h diff --git a/ghost/gpsprotocol.cpp b/src/libghost/gpsprotocol.cpp similarity index 100% rename from ghost/gpsprotocol.cpp rename to src/libghost/gpsprotocol.cpp diff --git a/ghost/gpsprotocol.h b/src/libghost/gpsprotocol.h similarity index 100% rename from ghost/gpsprotocol.h rename to src/libghost/gpsprotocol.h diff --git a/ghost/includes.h b/src/libghost/includes.h similarity index 100% rename from ghost/includes.h rename to src/libghost/includes.h diff --git a/ghost/interfaces.h b/src/libghost/interfaces.h similarity index 55% rename from ghost/interfaces.h rename to src/libghost/interfaces.h index 6f027e3..4fc8729 100644 --- a/ghost/interfaces.h +++ b/src/libghost/interfaces.h @@ -29,58 +29,62 @@ class CBNET; class CGHost; class CConfig; -class CGameBase; +class CBaseGame; class CGamePlayer; class CCommandPacket; +class CommandData; -/*class IGHostPlugin : public QObject +class IGHostPlugin { - Q_OBJECT public: - - //virtual QString GetName() const = 0; - virtual ~IGHostPlugin() {} -};*/ + virtual QString GetName( ) const = 0; + //virtual bool InitPlugin( CGHost *ghost ) const = 0; + virtual void PluginLoaded( CGHost *ghost, CConfig *cfg ) = 0; +}; -class IPacketHandler //: public IGHostPlugin +class IPacketHandler : public IGHostPlugin { +public: + virtual ~IPacketHandler() {} virtual bool HandlePacket( CCommandPacket* packet, bool wasHandled ) = 0; }; -class ICommandProvider //: public IGHostPlugin +class ICommandProvider : public IGHostPlugin { protected: //QHashGetString( "lang_0001", "lang_0001" ); Out.replace("$SERVER$", server); @@ -46,7 +46,7 @@ QString CLanguage :: UnableToCreateGameTryAnotherName( const QString &server, co return Out; } -QString CLanguage :: UserIsAlreadyAnAdmin( const QString &server, const QString &user ) +QString CLanguage :: UserIsAlreadyAnAdmin( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0002", "lang_0002" ); Out.replace("$SERVER$", server); @@ -54,7 +54,7 @@ QString CLanguage :: UserIsAlreadyAnAdmin( const QString &server, const QString return Out; } -QString CLanguage :: AddedUserToAdminDatabase( const QString &server, const QString &user ) +QString CLanguage :: AddedUserToAdminDatabase( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0003", "lang_0003" ); Out.replace("$SERVER$", server); @@ -62,7 +62,7 @@ QString CLanguage :: AddedUserToAdminDatabase( const QString &server, const QStr return Out; } -QString CLanguage :: ErrorAddingUserToAdminDatabase( const QString &server, const QString &user ) +QString CLanguage :: ErrorAddingUserToAdminDatabase( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0004", "lang_0004" ); Out.replace("$SERVER$", server); @@ -70,12 +70,12 @@ QString CLanguage :: ErrorAddingUserToAdminDatabase( const QString &server, cons return Out; } -QString CLanguage :: YouDontHaveAccessToThatCommand( ) +QString CLanguage :: YouDontHaveAccessToThatCommand( ) const { return m_CFG->GetString( "lang_0005", "lang_0005" ); } -QString CLanguage :: UserIsAlreadyBanned( const QString &server, const QString &victim ) +QString CLanguage :: UserIsAlreadyBanned( const QString &server, const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0006", "lang_0006" ); Out.replace("$SERVER$", server); @@ -83,7 +83,7 @@ QString CLanguage :: UserIsAlreadyBanned( const QString &server, const QString & return Out; } -QString CLanguage :: BannedUser( const QString &server, const QString &victim ) +QString CLanguage :: BannedUser( const QString &server, const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0007", "lang_0007" ); Out.replace("$SERVER$", server); @@ -91,7 +91,7 @@ QString CLanguage :: BannedUser( const QString &server, const QString &victim ) return Out; } -QString CLanguage :: ErrorBanningUser( const QString &server, const QString &victim ) +QString CLanguage :: ErrorBanningUser( const QString &server, const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0008", "lang_0008" ); Out.replace("$SERVER$", server); @@ -99,7 +99,7 @@ QString CLanguage :: ErrorBanningUser( const QString &server, const QString &vic return Out; } -QString CLanguage :: UserIsAnAdmin( const QString &server, const QString &user ) +QString CLanguage :: UserIsAnAdmin( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0009", "lang_0009" ); Out.replace("$SERVER$", server); @@ -107,7 +107,7 @@ QString CLanguage :: UserIsAnAdmin( const QString &server, const QString &user ) return Out; } -QString CLanguage :: UserIsNotAnAdmin( const QString &server, const QString &user ) +QString CLanguage :: UserIsNotAnAdmin( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0010", "lang_0010" ); Out.replace("$SERVER$", server); @@ -115,7 +115,7 @@ QString CLanguage :: UserIsNotAnAdmin( const QString &server, const QString &use return Out; } -QString CLanguage :: UserWasBannedOnByBecause( const QString &server, const QString &victim, const QString &date, const QString &admin, const QString &reason ) +QString CLanguage :: UserWasBannedOnByBecause( const QString &server, const QString &victim, const QString &date, const QString &admin, const QString &reason ) const { QString Out = m_CFG->GetString( "lang_0011", "lang_0011" ); Out.replace("$SERVER$", server); @@ -126,7 +126,7 @@ QString CLanguage :: UserWasBannedOnByBecause( const QString &server, const QStr return Out; } -QString CLanguage :: UserIsNotBanned( const QString &server, const QString &victim ) +QString CLanguage :: UserIsNotBanned( const QString &server, const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0012", "lang_0012" ); Out.replace("$SERVER$", server); @@ -134,21 +134,21 @@ QString CLanguage :: UserIsNotBanned( const QString &server, const QString &vict return Out; } -QString CLanguage :: ThereAreNoAdmins( const QString &server ) +QString CLanguage :: ThereAreNoAdmins( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0013", "lang_0013" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereIsAdmin( const QString &server ) +QString CLanguage :: ThereIsAdmin( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0014", "lang_0014" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereAreAdmins( const QString &server, const QString &count ) +QString CLanguage :: ThereAreAdmins( const QString &server, const QString &count ) const { QString Out = m_CFG->GetString( "lang_0015", "lang_0015" ); Out.replace("$SERVER$", server); @@ -156,21 +156,21 @@ QString CLanguage :: ThereAreAdmins( const QString &server, const QString &count return Out; } -QString CLanguage :: ThereAreNoBannedUsers( const QString &server ) +QString CLanguage :: ThereAreNoBannedUsers( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0016", "lang_0016" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereIsBannedUser( const QString &server ) +QString CLanguage :: ThereIsBannedUser( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0017", "lang_0017" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ThereAreBannedUsers( const QString &server, const QString &count ) +QString CLanguage :: ThereAreBannedUsers( const QString &server, const QString &count ) const { QString Out = m_CFG->GetString( "lang_0018", "lang_0018" ); Out.replace("$SERVER$", server); @@ -178,12 +178,12 @@ QString CLanguage :: ThereAreBannedUsers( const QString &server, const QString & return Out; } -QString CLanguage :: YouCantDeleteTheRootAdmin( ) +QString CLanguage :: YouCantDeleteTheRootAdmin( ) const { return m_CFG->GetString( "lang_0019", "lang_0019" ); } -QString CLanguage :: DeletedUserFromAdminDatabase( const QString &server, const QString &user ) +QString CLanguage :: DeletedUserFromAdminDatabase( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0020", "lang_0020" ); Out.replace("$SERVER$", server); @@ -191,7 +191,7 @@ QString CLanguage :: DeletedUserFromAdminDatabase( const QString &server, const return Out; } -QString CLanguage :: ErrorDeletingUserFromAdminDatabase( const QString &server, const QString &user ) +QString CLanguage :: ErrorDeletingUserFromAdminDatabase( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0021", "lang_0021" ); Out.replace("$SERVER$", server); @@ -199,21 +199,21 @@ QString CLanguage :: ErrorDeletingUserFromAdminDatabase( const QString &server, return Out; } -QString CLanguage :: UnbannedUser( const QString &victim ) +QString CLanguage :: UnbannedUser( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0022", "lang_0022" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: ErrorUnbanningUser( const QString &victim ) +QString CLanguage :: ErrorUnbanningUser( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0023", "lang_0023" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: GameNumberIs( const QString &number, const QString &description ) +QString CLanguage :: GameNumberIs( const QString &number, const QString &description ) const { QString Out = m_CFG->GetString( "lang_0024", "lang_0024" ); Out.replace("$NUMBER$", number); @@ -221,14 +221,14 @@ QString CLanguage :: GameNumberIs( const QString &number, const QString &descrip return Out; } -QString CLanguage :: GameNumberDoesntExist( const QString &number ) +QString CLanguage :: GameNumberDoesntExist( const QString &number ) const { QString Out = m_CFG->GetString( "lang_0025", "lang_0025" ); Out.replace("$NUMBER$", number); return Out; } -QString CLanguage :: GameIsInTheLobby( const QString &description, const QString ¤t, const QString &max ) +QString CLanguage :: GameIsInTheLobby( const QString &description, const QString ¤t, const QString &max ) const { QString Out = m_CFG->GetString( "lang_0026", "lang_0026" ); Out.replace("$DESCRIPTION$", description); @@ -237,7 +237,7 @@ QString CLanguage :: GameIsInTheLobby( const QString &description, const QString return Out; } -QString CLanguage :: ThereIsNoGameInTheLobby( const QString ¤t, const QString &max ) +QString CLanguage :: ThereIsNoGameInTheLobby( const QString ¤t, const QString &max ) const { QString Out = m_CFG->GetString( "lang_0027", "lang_0027" ); Out.replace("$CURRENT$", current); @@ -245,26 +245,26 @@ QString CLanguage :: ThereIsNoGameInTheLobby( const QString ¤t, const QStr return Out; } -QString CLanguage :: UnableToLoadConfigFilesOutside( ) +QString CLanguage :: UnableToLoadConfigFilesOutside( ) const { return m_CFG->GetString( "lang_0028", "lang_0028" ); } -QString CLanguage :: LoadingConfigFile( const QString &file ) +QString CLanguage :: LoadingConfigFile( const QString &file ) const { QString Out = m_CFG->GetString( "lang_0029", "lang_0029" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToLoadConfigFileDoesntExist( const QString &file ) +QString CLanguage :: UnableToLoadConfigFileDoesntExist( const QString &file ) const { QString Out = m_CFG->GetString( "lang_0030", "lang_0030" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: CreatingPrivateGame( const QString &gamename, const QString &user ) +QString CLanguage :: CreatingPrivateGame( const QString &gamename, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0031", "lang_0031" ); Out.replace("$GAMENAME$", gamename); @@ -272,7 +272,7 @@ QString CLanguage :: CreatingPrivateGame( const QString &gamename, const QString return Out; } -QString CLanguage :: CreatingPublicGame( const QString &gamename, const QString &user ) +QString CLanguage :: CreatingPublicGame( const QString &gamename, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0032", "lang_0032" ); Out.replace("$GAMENAME$", gamename); @@ -280,40 +280,40 @@ QString CLanguage :: CreatingPublicGame( const QString &gamename, const QString return Out; } -QString CLanguage :: UnableToUnhostGameCountdownStarted( const QString &description ) +QString CLanguage :: UnableToUnhostGameCountdownStarted( const QString &description ) const { QString Out = m_CFG->GetString( "lang_0033", "lang_0033" ); Out.replace("$DESCRIPTION$", description); return Out; } -QString CLanguage :: UnhostingGame( const QString &description ) +QString CLanguage :: UnhostingGame( const QString &description ) const { QString Out = m_CFG->GetString( "lang_0034", "lang_0034" ); Out.replace("$DESCRIPTION$", description); return Out; } -QString CLanguage :: UnableToUnhostGameNoGameInLobby( ) +QString CLanguage :: UnableToUnhostGameNoGameInLobby( ) const { return m_CFG->GetString( "lang_0035", "lang_0035" ); } -QString CLanguage :: VersionAdmin( const QString &version ) +QString CLanguage :: VersionAdmin( const QString &version ) const { QString Out = m_CFG->GetString( "lang_0036", "lang_0036" ); Out.replace("$VERSION$", version); return Out; } -QString CLanguage :: VersionNotAdmin( const QString &version ) +QString CLanguage :: VersionNotAdmin( const QString &version ) const { QString Out = m_CFG->GetString( "lang_0037", "lang_0037" ); Out.replace("$VERSION$", version); return Out; } -QString CLanguage :: UnableToCreateGameAnotherGameInLobby( const QString &gamename, const QString &description ) +QString CLanguage :: UnableToCreateGameAnotherGameInLobby( const QString &gamename, const QString &description ) const { QString Out = m_CFG->GetString( "lang_0038", "lang_0038" ); Out.replace("$GAMENAME$", gamename); @@ -321,7 +321,7 @@ QString CLanguage :: UnableToCreateGameAnotherGameInLobby( const QString &gamena return Out; } -QString CLanguage :: UnableToCreateGameMaxGamesReached( const QString &gamename, const QString &max ) +QString CLanguage :: UnableToCreateGameMaxGamesReached( const QString &gamename, const QString &max ) const { QString Out = m_CFG->GetString( "lang_0039", "lang_0039" ); Out.replace("$GAMENAME$", gamename); @@ -329,85 +329,85 @@ QString CLanguage :: UnableToCreateGameMaxGamesReached( const QString &gamename, return Out; } -QString CLanguage :: GameIsOver( const QString &description ) +QString CLanguage :: GameIsOver( const QString &description ) const { QString Out = m_CFG->GetString( "lang_0040", "lang_0040" ); Out.replace("$DESCRIPTION$", description); return Out; } -QString CLanguage :: SpoofCheckByReplying( ) +QString CLanguage :: SpoofCheckByReplying( ) const { return m_CFG->GetString( "lang_0041", "lang_0041" ); } -QString CLanguage :: GameRefreshed( ) +QString CLanguage :: GameRefreshed( ) const { return m_CFG->GetString( "lang_0042", "lang_0042" ); } -QString CLanguage :: SpoofPossibleIsAway( const QString &user ) +QString CLanguage :: SpoofPossibleIsAway( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0043", "lang_0043" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofPossibleIsUnavailable( const QString &user ) +QString CLanguage :: SpoofPossibleIsUnavailable( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0044", "lang_0044" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofPossibleIsRefusingMessages( const QString &user ) +QString CLanguage :: SpoofPossibleIsRefusingMessages( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0045", "lang_0045" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofDetectedIsNotInGame( const QString &user ) +QString CLanguage :: SpoofDetectedIsNotInGame( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0046", "lang_0046" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofDetectedIsInPrivateChannel( const QString &user ) +QString CLanguage :: SpoofDetectedIsInPrivateChannel( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0047", "lang_0047" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: SpoofDetectedIsInAnotherGame( const QString &user ) +QString CLanguage :: SpoofDetectedIsInAnotherGame( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0048", "lang_0048" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: CountDownAborted( ) +QString CLanguage :: CountDownAborted( ) const { return m_CFG->GetString( "lang_0049", "lang_0049" ); } -QString CLanguage :: TryingToJoinTheGameButBanned( const QString &victim ) +QString CLanguage :: TryingToJoinTheGameButBanned( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0050", "lang_0050" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToBanNoMatchesFound( const QString &victim ) +QString CLanguage :: UnableToBanNoMatchesFound( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0051", "lang_0051" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: PlayerWasBannedByPlayer( const QString &server, const QString &victim, const QString &user ) +QString CLanguage :: PlayerWasBannedByPlayer( const QString &server, const QString &victim, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0052", "lang_0052" ); Out.replace("$SERVER$", server); @@ -416,56 +416,56 @@ QString CLanguage :: PlayerWasBannedByPlayer( const QString &server, const QStri return Out; } -QString CLanguage :: UnableToBanFoundMoreThanOneMatch( const QString &victim ) +QString CLanguage :: UnableToBanFoundMoreThanOneMatch( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0053", "lang_0053" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: AddedPlayerToTheHoldList( const QString &user ) +QString CLanguage :: AddedPlayerToTheHoldList( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0054", "lang_0054" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: UnableToKickNoMatchesFound( const QString &victim ) +QString CLanguage :: UnableToKickNoMatchesFound( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0055", "lang_0055" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToKickFoundMoreThanOneMatch( const QString &victim ) +QString CLanguage :: UnableToKickFoundMoreThanOneMatch( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0056", "lang_0056" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: SettingLatencyToMinimum( const QString &min ) +QString CLanguage :: SettingLatencyToMinimum( const QString &min ) const { QString Out = m_CFG->GetString( "lang_0057", "lang_0057" ); Out.replace("$MIN$", min); return Out; } -QString CLanguage :: SettingLatencyToMaximum( const QString &max ) +QString CLanguage :: SettingLatencyToMaximum( const QString &max ) const { QString Out = m_CFG->GetString( "lang_0058", "lang_0058" ); Out.replace("$MAX$", max); return Out; } -QString CLanguage :: SettingLatencyTo( const QString &latency ) +QString CLanguage :: SettingLatencyTo( const QString &latency ) const { QString Out = m_CFG->GetString( "lang_0059", "lang_0059" ); Out.replace("$LATENCY$", latency); return Out; } -QString CLanguage :: KickingPlayersWithPingsGreaterThan( const QString &total, const QString &ping ) +QString CLanguage :: KickingPlayersWithPingsGreaterThan( const QString &total, const QString &ping ) const { QString Out = m_CFG->GetString( "lang_0060", "lang_0060" ); Out.replace("$TOTAL$", total); @@ -473,7 +473,7 @@ QString CLanguage :: KickingPlayersWithPingsGreaterThan( const QString &total, c return Out; } -QString CLanguage :: HasPlayedGamesWithThisBot( const QString &user, const QString &firstgame, const QString &lastgame, const QString &totalgames, const QString &avgloadingtime, const QString &avgstay ) +QString CLanguage :: HasPlayedGamesWithThisBot( const QString &user, const QString &firstgame, const QString &lastgame, const QString &totalgames, const QString &avgloadingtime, const QString &avgstay ) const { QString Out = m_CFG->GetString( "lang_0061", "lang_0061" ); Out.replace("$USER$", user); @@ -485,14 +485,14 @@ QString CLanguage :: HasPlayedGamesWithThisBot( const QString &user, const QStri return Out; } -QString CLanguage :: HasntPlayedGamesWithThisBot( const QString &user ) +QString CLanguage :: HasntPlayedGamesWithThisBot( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0062", "lang_0062" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: AutokickingPlayerForExcessivePing( const QString &victim, const QString &ping ) +QString CLanguage :: AutokickingPlayerForExcessivePing( const QString &victim, const QString &ping ) const { QString Out = m_CFG->GetString( "lang_0063", "lang_0063" ); Out.replace("$VICTIM$", victim); @@ -500,7 +500,7 @@ QString CLanguage :: AutokickingPlayerForExcessivePing( const QString &victim, c return Out; } -QString CLanguage :: SpoofCheckAcceptedFor( const QString &server, const QString &user ) +QString CLanguage :: SpoofCheckAcceptedFor( const QString &server, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0064", "lang_0064" ); Out.replace("$SERVER$", server); @@ -508,45 +508,45 @@ QString CLanguage :: SpoofCheckAcceptedFor( const QString &server, const QString return Out; } -QString CLanguage :: PlayersNotYetSpoofChecked( const QString ¬spoofchecked ) +QString CLanguage :: PlayersNotYetSpoofChecked( const QString ¬spoofchecked ) const { QString Out = m_CFG->GetString( "lang_0065", "lang_0065" ); Out.replace("$NOTSPOOFCHECKED$", notspoofchecked); return Out; } -QString CLanguage :: ManuallySpoofCheckByWhispering( const QString &hostname ) +QString CLanguage :: ManuallySpoofCheckByWhispering( const QString &hostname ) const { QString Out = m_CFG->GetString( "lang_0066", "lang_0066" ); Out.replace("$HOSTNAME$", hostname); return Out; } -QString CLanguage :: SpoofCheckByWhispering( const QString &hostname ) +QString CLanguage :: SpoofCheckByWhispering( const QString &hostname ) const { QString Out = m_CFG->GetString( "lang_0067", "lang_0067" ); Out.replace("$HOSTNAME$", hostname); return Out; } -QString CLanguage :: EveryoneHasBeenSpoofChecked( ) +QString CLanguage :: EveryoneHasBeenSpoofChecked( ) const { return m_CFG->GetString( "lang_0068", "lang_0068" ); } -QString CLanguage :: PlayersNotYetPinged( const QString ¬pinged ) +QString CLanguage :: PlayersNotYetPinged( const QString ¬pinged ) const { QString Out = m_CFG->GetString( "lang_0069", "lang_0069" ); Out.replace("$NOTPINGED$", notpinged); return Out; } -QString CLanguage :: EveryoneHasBeenPinged( ) +QString CLanguage :: EveryoneHasBeenPinged( ) const { return m_CFG->GetString( "lang_0070", "lang_0070" ); } -QString CLanguage :: ShortestLoadByPlayer( const QString &user, const QString &loadingtime ) +QString CLanguage :: ShortestLoadByPlayer( const QString &user, const QString &loadingtime ) const { QString Out = m_CFG->GetString( "lang_0071", "lang_0071" ); Out.replace("$USER$", user); @@ -554,7 +554,7 @@ QString CLanguage :: ShortestLoadByPlayer( const QString &user, const QString &l return Out; } -QString CLanguage :: LongestLoadByPlayer( const QString &user, const QString &loadingtime ) +QString CLanguage :: LongestLoadByPlayer( const QString &user, const QString &loadingtime ) const { QString Out = m_CFG->GetString( "lang_0072", "lang_0072" ); Out.replace("$USER$", user); @@ -562,14 +562,14 @@ QString CLanguage :: LongestLoadByPlayer( const QString &user, const QString &lo return Out; } -QString CLanguage :: YourLoadingTimeWas( const QString &loadingtime ) +QString CLanguage :: YourLoadingTimeWas( const QString &loadingtime ) const { QString Out = m_CFG->GetString( "lang_0073", "lang_0073" ); Out.replace("$LOADINGTIME$", loadingtime); return Out; } -QString CLanguage :: HasPlayedDotAGamesWithThisBot( const QString &user, const QString &totalgames, const QString &totalwins, const QString &totallosses, const QString &totalkills, const QString &totaldeaths, const QString &totalcreepkills, const QString &totalcreepdenies, const QString &totalassists, const QString &totalneutralkills, const QString &totaltowerkills, const QString &totalraxkills, const QString &totalcourierkills, const QString &avgkills, const QString &avgdeaths, const QString &avgcreepkills, const QString &avgcreepdenies, const QString &avgassists, const QString &avgneutralkills, const QString &avgtowerkills, const QString &avgraxkills, const QString &avgcourierkills ) +QString CLanguage :: HasPlayedDotAGamesWithThisBot( const QString &user, const QString &totalgames, const QString &totalwins, const QString &totallosses, const QString &totalkills, const QString &totaldeaths, const QString &totalcreepkills, const QString &totalcreepdenies, const QString &totalassists, const QString &totalneutralkills, const QString &totaltowerkills, const QString &totalraxkills, const QString &totalcourierkills, const QString &avgkills, const QString &avgdeaths, const QString &avgcreepkills, const QString &avgcreepdenies, const QString &avgassists, const QString &avgneutralkills, const QString &avgtowerkills, const QString &avgraxkills, const QString &avgcourierkills ) const { QString Out = m_CFG->GetString( "lang_0074", "lang_0074" ); Out.replace("$USER$", user); @@ -597,226 +597,226 @@ QString CLanguage :: HasPlayedDotAGamesWithThisBot( const QString &user, const Q return Out; } -QString CLanguage :: HasntPlayedDotAGamesWithThisBot( const QString &user ) +QString CLanguage :: HasntPlayedDotAGamesWithThisBot( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0075", "lang_0075" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: WasKickedForReservedPlayer( const QString &reserved ) +QString CLanguage :: WasKickedForReservedPlayer( const QString &reserved ) const { QString Out = m_CFG->GetString( "lang_0076", "lang_0076" ); Out.replace("$RESERVED$", reserved); return Out; } -QString CLanguage :: WasKickedForOwnerPlayer( const QString &owner ) +QString CLanguage :: WasKickedForOwnerPlayer( const QString &owner ) const { QString Out = m_CFG->GetString( "lang_0077", "lang_0077" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: WasKickedByPlayer( const QString &user ) +QString CLanguage :: WasKickedByPlayer( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0078", "lang_0078" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: HasLostConnectionPlayerError( const QString &error ) +QString CLanguage :: HasLostConnectionPlayerError( const QString &error ) const { QString Out = m_CFG->GetString( "lang_0079", "lang_0079" ); Out.replace("$ERROR$", error); return Out; } -QString CLanguage :: HasLostConnectionSocketError( const QString &error ) +QString CLanguage :: HasLostConnectionSocketError( const QString &error ) const { QString Out = m_CFG->GetString( "lang_0080", "lang_0080" ); Out.replace("$ERROR$", error); return Out; } -QString CLanguage :: HasLostConnectionClosedByRemoteHost( ) +QString CLanguage :: HasLostConnectionClosedByRemoteHost( ) const { return m_CFG->GetString( "lang_0081", "lang_0081" ); } -QString CLanguage :: HasLeftVoluntarily( ) +QString CLanguage :: HasLeftVoluntarily( ) const { return m_CFG->GetString( "lang_0082", "lang_0082" ); } -QString CLanguage :: EndingGame( const QString &description ) +QString CLanguage :: EndingGame( const QString &description ) const { QString Out = m_CFG->GetString( "lang_0083", "lang_0083" ); Out.replace("$DESCRIPTION$", description); return Out; } -QString CLanguage :: HasLostConnectionTimedOut( ) +QString CLanguage :: HasLostConnectionTimedOut( ) const { return m_CFG->GetString( "lang_0084", "lang_0084" ); } -QString CLanguage :: GlobalChatMuted( ) +QString CLanguage :: GlobalChatMuted( ) const { return m_CFG->GetString( "lang_0085", "lang_0085" ); } -QString CLanguage :: GlobalChatUnmuted( ) +QString CLanguage :: GlobalChatUnmuted( ) const { return m_CFG->GetString( "lang_0086", "lang_0086" ); } -QString CLanguage :: ShufflingPlayers( ) +QString CLanguage :: ShufflingPlayers( ) const { return m_CFG->GetString( "lang_0087", "lang_0087" ); } -QString CLanguage :: UnableToLoadConfigFileGameInLobby( ) +QString CLanguage :: UnableToLoadConfigFileGameInLobby( ) const { return m_CFG->GetString( "lang_0088", "lang_0088" ); } -QString CLanguage :: PlayersStillDownloading( const QString &stilldownloading ) +QString CLanguage :: PlayersStillDownloading( const QString &stilldownloading ) const { QString Out = m_CFG->GetString( "lang_0089", "lang_0089" ); Out.replace("$STILLDOWNLOADING$", stilldownloading); return Out; } -QString CLanguage :: RefreshMessagesEnabled( ) +QString CLanguage :: RefreshMessagesEnabled( ) const { return m_CFG->GetString( "lang_0090", "lang_0090" ); } -QString CLanguage :: RefreshMessagesDisabled( ) +QString CLanguage :: RefreshMessagesDisabled( ) const { return m_CFG->GetString( "lang_0091", "lang_0091" ); } -QString CLanguage :: AtLeastOneGameActiveUseForceToShutdown( ) +QString CLanguage :: AtLeastOneGameActiveUseForceToShutdown( ) const { return m_CFG->GetString( "lang_0092", "lang_0092" ); } -QString CLanguage :: CurrentlyLoadedMapCFGIs( const QString &mapcfg ) +QString CLanguage :: CurrentlyLoadedMapCFGIs( const QString &mapcfg ) const { QString Out = m_CFG->GetString( "lang_0093", "lang_0093" ); Out.replace("$MAPCFG$", mapcfg); return Out; } -QString CLanguage :: LaggedOutDroppedByAdmin( ) +QString CLanguage :: LaggedOutDroppedByAdmin( ) const { return m_CFG->GetString( "lang_0094", "lang_0094" ); } -QString CLanguage :: LaggedOutDroppedByVote( ) +QString CLanguage :: LaggedOutDroppedByVote( ) const { return m_CFG->GetString( "lang_0095", "lang_0095" ); } -QString CLanguage :: PlayerVotedToDropLaggers( const QString &user ) +QString CLanguage :: PlayerVotedToDropLaggers( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0096", "lang_0096" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: LatencyIs( const QString &latency ) +QString CLanguage :: LatencyIs( const QString &latency ) const { QString Out = m_CFG->GetString( "lang_0097", "lang_0097" ); Out.replace("$LATENCY$", latency); return Out; } -QString CLanguage :: SyncLimitIs( const QString &synclimit ) +QString CLanguage :: SyncLimitIs( const QString &synclimit ) const { QString Out = m_CFG->GetString( "lang_0098", "lang_0098" ); Out.replace("$SYNCLIMIT$", synclimit); return Out; } -QString CLanguage :: SettingSyncLimitToMinimum( const QString &min ) +QString CLanguage :: SettingSyncLimitToMinimum( const QString &min ) const { QString Out = m_CFG->GetString( "lang_0099", "lang_0099" ); Out.replace("$MIN$", min); return Out; } -QString CLanguage :: SettingSyncLimitToMaximum( const QString &max ) +QString CLanguage :: SettingSyncLimitToMaximum( const QString &max ) const { QString Out = m_CFG->GetString( "lang_0100", "lang_0100" ); Out.replace("$MAX$", max); return Out; } -QString CLanguage :: SettingSyncLimitTo( const QString &synclimit ) +QString CLanguage :: SettingSyncLimitTo( const QString &synclimit ) const { QString Out = m_CFG->GetString( "lang_0101", "lang_0101" ); Out.replace("$SYNCLIMIT$", synclimit); return Out; } -QString CLanguage :: UnableToCreateGameNotLoggedIn( const QString &gamename ) +QString CLanguage :: UnableToCreateGameNotLoggedIn( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0102", "lang_0102" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: AdminLoggedIn( ) +QString CLanguage :: AdminLoggedIn( ) const { return m_CFG->GetString( "lang_0103", "lang_0103" ); } -QString CLanguage :: AdminInvalidPassword( const QString &attempt ) +QString CLanguage :: AdminInvalidPassword( const QString &attempt ) const { QString Out = m_CFG->GetString( "lang_0104", "lang_0104" ); Out.replace("$ATTEMPT$", attempt); return Out; } -QString CLanguage :: ConnectingToBNET( const QString &server ) +QString CLanguage :: ConnectingToBNET( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0105", "lang_0105" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: ConnectedToBNET( const QString &server ) +QString CLanguage :: ConnectedToBNET( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0106", "lang_0106" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: DisconnectedFromBNET( const QString &server ) +QString CLanguage :: DisconnectedFromBNET( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0107", "lang_0107" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: LoggedInToBNET( const QString &server ) +QString CLanguage :: LoggedInToBNET( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0108", "lang_0108" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: BNETGameHostingSucceeded( const QString &server ) +QString CLanguage :: BNETGameHostingSucceeded( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0109", "lang_0109" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: BNETGameHostingFailed( const QString &server, const QString &gamename ) +QString CLanguage :: BNETGameHostingFailed( const QString &server, const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0110", "lang_0110" ); Out.replace("$SERVER$", server); @@ -824,14 +824,14 @@ QString CLanguage :: BNETGameHostingFailed( const QString &server, const QString return Out; } -QString CLanguage :: ConnectingToBNETTimedOut( const QString &server ) +QString CLanguage :: ConnectingToBNETTimedOut( const QString &server ) const { QString Out = m_CFG->GetString( "lang_0111", "lang_0111" ); Out.replace("$SERVER$", server); return Out; } -QString CLanguage :: PlayerDownloadedTheMap( const QString &user, const QString &seconds, const QString &rate ) +QString CLanguage :: PlayerDownloadedTheMap( const QString &user, const QString &seconds, const QString &rate ) const { QString Out = m_CFG->GetString( "lang_0112", "lang_0112" ); Out.replace("$USER$", user); @@ -840,64 +840,64 @@ QString CLanguage :: PlayerDownloadedTheMap( const QString &user, const QString return Out; } -QString CLanguage :: UnableToCreateGameNameTooLong( const QString &gamename ) +QString CLanguage :: UnableToCreateGameNameTooLong( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0113", "lang_0113" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: SettingGameOwnerTo( const QString &owner ) +QString CLanguage :: SettingGameOwnerTo( const QString &owner ) const { QString Out = m_CFG->GetString( "lang_0114", "lang_0114" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: TheGameIsLocked( ) +QString CLanguage :: TheGameIsLocked( ) const { return m_CFG->GetString( "lang_0115", "lang_0115" ); } -QString CLanguage :: GameLocked( ) +QString CLanguage :: GameLocked( ) const { return m_CFG->GetString( "lang_0116", "lang_0116" ); } -QString CLanguage :: GameUnlocked( ) +QString CLanguage :: GameUnlocked( ) const { return m_CFG->GetString( "lang_0117", "lang_0117" ); } -QString CLanguage :: UnableToStartDownloadNoMatchesFound( const QString &victim ) +QString CLanguage :: UnableToStartDownloadNoMatchesFound( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0118", "lang_0118" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( const QString &victim ) +QString CLanguage :: UnableToStartDownloadFoundMoreThanOneMatch( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0119", "lang_0119" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToSetGameOwner( const QString &owner ) +QString CLanguage :: UnableToSetGameOwner( const QString &owner ) const { QString Out = m_CFG->GetString( "lang_0120", "lang_0120" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: UnableToCheckPlayerNoMatchesFound( const QString &victim ) +QString CLanguage :: UnableToCheckPlayerNoMatchesFound( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0121", "lang_0121" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: CheckedPlayer( const QString &victim, const QString &ping, const QString &from, const QString &admin, const QString &owner, const QString &spoofed, const QString &spoofedrealm, const QString &reserved ) +QString CLanguage :: CheckedPlayer( const QString &victim, const QString &ping, const QString &from, const QString &admin, const QString &owner, const QString &spoofed, const QString &spoofedrealm, const QString &reserved ) const { QString Out = m_CFG->GetString( "lang_0122", "lang_0122" ); Out.replace("$VICTIM$", victim); @@ -911,43 +911,43 @@ QString CLanguage :: CheckedPlayer( const QString &victim, const QString &ping, return Out; } -QString CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( const QString &victim ) +QString CLanguage :: UnableToCheckPlayerFoundMoreThanOneMatch( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0123", "lang_0123" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: TheGameIsLockedBNET( ) +QString CLanguage :: TheGameIsLockedBNET( ) const { return m_CFG->GetString( "lang_0124", "lang_0124" ); } -QString CLanguage :: UnableToCreateGameDisabled( const QString &gamename ) +QString CLanguage :: UnableToCreateGameDisabled( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0125", "lang_0125" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: BotDisabled( ) +QString CLanguage :: BotDisabled( ) const { return m_CFG->GetString( "lang_0126", "lang_0126" ); } -QString CLanguage :: BotEnabled( ) +QString CLanguage :: BotEnabled( ) const { return m_CFG->GetString( "lang_0127", "lang_0127" ); } -QString CLanguage :: UnableToCreateGameInvalidMap( const QString &gamename ) +QString CLanguage :: UnableToCreateGameInvalidMap( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0128", "lang_0128" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: WaitingForPlayersBeforeAutoStart( const QString &players, const QString &playersleft ) +QString CLanguage :: WaitingForPlayersBeforeAutoStart( const QString &players, const QString &playersleft ) const { QString Out = m_CFG->GetString( "lang_0129", "lang_0129" ); Out.replace("$PLAYERS$", players); @@ -955,99 +955,99 @@ QString CLanguage :: WaitingForPlayersBeforeAutoStart( const QString &players, c return Out; } -QString CLanguage :: AutoStartDisabled( ) +QString CLanguage :: AutoStartDisabled( ) const { return m_CFG->GetString( "lang_0130", "lang_0130" ); } -QString CLanguage :: AutoStartEnabled( const QString &players ) +QString CLanguage :: AutoStartEnabled( const QString &players ) const { QString Out = m_CFG->GetString( "lang_0131", "lang_0131" ); Out.replace("$PLAYERS$", players); return Out; } -QString CLanguage :: AnnounceMessageEnabled( ) +QString CLanguage :: AnnounceMessageEnabled( ) const { return m_CFG->GetString( "lang_0132", "lang_0132" ); } -QString CLanguage :: AnnounceMessageDisabled( ) +QString CLanguage :: AnnounceMessageDisabled( ) const { return m_CFG->GetString( "lang_0133", "lang_0133" ); } -QString CLanguage :: AutoHostEnabled( ) +QString CLanguage :: AutoHostEnabled( ) const { return m_CFG->GetString( "lang_0134", "lang_0134" ); } -QString CLanguage :: AutoHostDisabled( ) +QString CLanguage :: AutoHostDisabled( ) const { return m_CFG->GetString( "lang_0135", "lang_0135" ); } -QString CLanguage :: UnableToLoadSaveGamesOutside( ) +QString CLanguage :: UnableToLoadSaveGamesOutside( ) const { return m_CFG->GetString( "lang_0136", "lang_0136" ); } -QString CLanguage :: UnableToLoadSaveGameGameInLobby( ) +QString CLanguage :: UnableToLoadSaveGameGameInLobby( ) const { return m_CFG->GetString( "lang_0137", "lang_0137" ); } -QString CLanguage :: LoadingSaveGame( const QString &file ) +QString CLanguage :: LoadingSaveGame( const QString &file ) const { QString Out = m_CFG->GetString( "lang_0138", "lang_0138" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToLoadSaveGameDoesntExist( const QString &file ) +QString CLanguage :: UnableToLoadSaveGameDoesntExist( const QString &file ) const { QString Out = m_CFG->GetString( "lang_0139", "lang_0139" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToCreateGameInvalidSaveGame( const QString &gamename ) +QString CLanguage :: UnableToCreateGameInvalidSaveGame( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0140", "lang_0140" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: UnableToCreateGameSaveGameMapMismatch( const QString &gamename ) +QString CLanguage :: UnableToCreateGameSaveGameMapMismatch( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0141", "lang_0141" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: AutoSaveEnabled( ) +QString CLanguage :: AutoSaveEnabled( ) const { return m_CFG->GetString( "lang_0142", "lang_0142" ); } -QString CLanguage :: AutoSaveDisabled( ) +QString CLanguage :: AutoSaveDisabled( ) const { return m_CFG->GetString( "lang_0143", "lang_0143" ); } -QString CLanguage :: DesyncDetected( ) +QString CLanguage :: DesyncDetected( ) const { return m_CFG->GetString( "lang_0144", "lang_0144" ); } -QString CLanguage :: UnableToMuteNoMatchesFound( const QString &victim ) +QString CLanguage :: UnableToMuteNoMatchesFound( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0145", "lang_0145" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: MutedPlayer( const QString &victim, const QString &user ) +QString CLanguage :: MutedPlayer( const QString &victim, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0146", "lang_0146" ); Out.replace("$VICTIM$", victim); @@ -1055,7 +1055,7 @@ QString CLanguage :: MutedPlayer( const QString &victim, const QString &user ) return Out; } -QString CLanguage :: UnmutedPlayer( const QString &victim, const QString &user ) +QString CLanguage :: UnmutedPlayer( const QString &victim, const QString &user ) const { QString Out = m_CFG->GetString( "lang_0147", "lang_0147" ); Out.replace("$VICTIM$", victim); @@ -1063,31 +1063,31 @@ QString CLanguage :: UnmutedPlayer( const QString &victim, const QString &user ) return Out; } -QString CLanguage :: UnableToMuteFoundMoreThanOneMatch( const QString &victim ) +QString CLanguage :: UnableToMuteFoundMoreThanOneMatch( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0148", "lang_0148" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: PlayerIsSavingTheGame( const QString &player ) +QString CLanguage :: PlayerIsSavingTheGame( const QString &player ) const { QString Out = m_CFG->GetString( "lang_0149", "lang_0149" ); Out.replace("$PLAYER$", player); return Out; } -QString CLanguage :: UpdatingClanList( ) +QString CLanguage :: UpdatingClanList( ) const { return m_CFG->GetString( "lang_0150", "lang_0150" ); } -QString CLanguage :: UpdatingFriendsList( ) +QString CLanguage :: UpdatingFriendsList( ) const { return m_CFG->GetString( "lang_0151", "lang_0151" ); } -QString CLanguage :: MultipleIPAddressUsageDetected( const QString &player, const QString &others ) +QString CLanguage :: MultipleIPAddressUsageDetected( const QString &player, const QString &others ) const { QString Out = m_CFG->GetString( "lang_0152", "lang_0152" ); Out.replace("$PLAYER$", player); @@ -1095,31 +1095,31 @@ QString CLanguage :: MultipleIPAddressUsageDetected( const QString &player, cons return Out; } -QString CLanguage :: UnableToVoteKickAlreadyInProgress( ) +QString CLanguage :: UnableToVoteKickAlreadyInProgress( ) const { return m_CFG->GetString( "lang_0153", "lang_0153" ); } -QString CLanguage :: UnableToVoteKickNotEnoughPlayers( ) +QString CLanguage :: UnableToVoteKickNotEnoughPlayers( ) const { return m_CFG->GetString( "lang_0154", "lang_0154" ); } -QString CLanguage :: UnableToVoteKickNoMatchesFound( const QString &victim ) +QString CLanguage :: UnableToVoteKickNoMatchesFound( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0155", "lang_0155" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: UnableToVoteKickPlayerIsReserved( const QString &victim ) +QString CLanguage :: UnableToVoteKickPlayerIsReserved( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0156", "lang_0156" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: StartedVoteKick( const QString &victim, const QString &user, const QString &votesneeded ) +QString CLanguage :: StartedVoteKick( const QString &victim, const QString &user, const QString &votesneeded ) const { QString Out = m_CFG->GetString( "lang_0157", "lang_0157" ); Out.replace("$VICTIM$", victim); @@ -1128,28 +1128,28 @@ QString CLanguage :: StartedVoteKick( const QString &victim, const QString &user return Out; } -QString CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( const QString &victim ) +QString CLanguage :: UnableToVoteKickFoundMoreThanOneMatch( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0158", "lang_0158" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: VoteKickPassed( const QString &victim ) +QString CLanguage :: VoteKickPassed( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0159", "lang_0159" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: ErrorVoteKickingPlayer( const QString &victim ) +QString CLanguage :: ErrorVoteKickingPlayer( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0160", "lang_0160" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: VoteKickAcceptedNeedMoreVotes( const QString &victim, const QString &user, const QString &votes ) +QString CLanguage :: VoteKickAcceptedNeedMoreVotes( const QString &victim, const QString &user, const QString &votes ) const { QString Out = m_CFG->GetString( "lang_0161", "lang_0161" ); Out.replace("$VICTIM$", victim); @@ -1158,45 +1158,45 @@ QString CLanguage :: VoteKickAcceptedNeedMoreVotes( const QString &victim, const return Out; } -QString CLanguage :: VoteKickCancelled( const QString &victim ) +QString CLanguage :: VoteKickCancelled( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0162", "lang_0162" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: VoteKickExpired( const QString &victim ) +QString CLanguage :: VoteKickExpired( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0163", "lang_0163" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: WasKickedByVote( ) +QString CLanguage :: WasKickedByVote( ) const { return m_CFG->GetString( "lang_0164", "lang_0164" ); } -QString CLanguage :: TypeYesToVote( const QString &commandtrigger ) +QString CLanguage :: TypeYesToVote( const QString &commandtrigger ) const { QString Out = m_CFG->GetString( "lang_0165", "lang_0165" ); Out.replace("$COMMANDTRIGGER$", commandtrigger); return Out; } -QString CLanguage :: PlayersNotYetPingedAutoStart( const QString ¬pinged ) +QString CLanguage :: PlayersNotYetPingedAutoStart( const QString ¬pinged ) const { QString Out = m_CFG->GetString( "lang_0166", "lang_0166" ); Out.replace("$NOTPINGED$", notpinged); return Out; } -QString CLanguage :: WasKickedForNotSpoofChecking( ) +QString CLanguage :: WasKickedForNotSpoofChecking( ) const { return m_CFG->GetString( "lang_0167", "lang_0167" ); } -QString CLanguage :: WasKickedForHavingFurthestScore( const QString &score, const QString &average ) +QString CLanguage :: WasKickedForHavingFurthestScore( const QString &score, const QString &average ) const { QString Out = m_CFG->GetString( "lang_0168", "lang_0168" ); Out.replace("$SCORE$", score); @@ -1204,7 +1204,7 @@ QString CLanguage :: WasKickedForHavingFurthestScore( const QString &score, cons return Out; } -QString CLanguage :: PlayerHasScore( const QString &player, const QString &score ) +QString CLanguage :: PlayerHasScore( const QString &player, const QString &score ) const { QString Out = m_CFG->GetString( "lang_0169", "lang_0169" ); Out.replace("$PLAYER$", player); @@ -1212,7 +1212,7 @@ QString CLanguage :: PlayerHasScore( const QString &player, const QString &score return Out; } -QString CLanguage :: RatedPlayersSpread( const QString &rated, const QString &total, const QString &spread ) +QString CLanguage :: RatedPlayersSpread( const QString &rated, const QString &total, const QString &spread ) const { QString Out = m_CFG->GetString( "lang_0170", "lang_0170" ); Out.replace("$RATED$", rated); @@ -1221,128 +1221,128 @@ QString CLanguage :: RatedPlayersSpread( const QString &rated, const QString &to return Out; } -QString CLanguage :: ErrorListingMaps( ) +QString CLanguage :: ErrorListingMaps( ) const { return m_CFG->GetString( "lang_0171", "lang_0171" ); } -QString CLanguage :: FoundMaps( const QString &maps ) +QString CLanguage :: FoundMaps( const QString &maps ) const { QString Out = m_CFG->GetString( "lang_0172", "lang_0172" ); Out.replace("$MAPS$", maps); return Out; } -QString CLanguage :: NoMapsFound( ) +QString CLanguage :: NoMapsFound( ) const { return m_CFG->GetString( "lang_0173", "lang_0173" ); } -QString CLanguage :: ErrorListingMapConfigs( ) +QString CLanguage :: ErrorListingMapConfigs( ) const { return m_CFG->GetString( "lang_0174", "lang_0174" ); } -QString CLanguage :: FoundMapConfigs( const QString &mapconfigs ) +QString CLanguage :: FoundMapConfigs( const QString &mapconfigs ) const { QString Out = m_CFG->GetString( "lang_0175", "lang_0175" ); Out.replace("$MAPCONFIGS$", mapconfigs); return Out; } -QString CLanguage :: NoMapConfigsFound( ) +QString CLanguage :: NoMapConfigsFound( ) const { return m_CFG->GetString( "lang_0176", "lang_0176" ); } -QString CLanguage :: PlayerFinishedLoading( const QString &user ) +QString CLanguage :: PlayerFinishedLoading( const QString &user ) const { QString Out = m_CFG->GetString( "lang_0177", "lang_0177" ); Out.replace("$USER$", user); return Out; } -QString CLanguage :: PleaseWaitPlayersStillLoading( ) +QString CLanguage :: PleaseWaitPlayersStillLoading( ) const { return m_CFG->GetString( "lang_0178", "lang_0178" ); } -QString CLanguage :: MapDownloadsDisabled( ) +QString CLanguage :: MapDownloadsDisabled( ) const { return m_CFG->GetString( "lang_0179", "lang_0179" ); } -QString CLanguage :: MapDownloadsEnabled( ) +QString CLanguage :: MapDownloadsEnabled( ) const { return m_CFG->GetString( "lang_0180", "lang_0180" ); } -QString CLanguage :: MapDownloadsConditional( ) +QString CLanguage :: MapDownloadsConditional( ) const { return m_CFG->GetString( "lang_0181", "lang_0181" ); } -QString CLanguage :: SettingHCL( const QString &HCL ) +QString CLanguage :: SettingHCL( const QString &HCL ) const { QString Out = m_CFG->GetString( "lang_0182", "lang_0182" ); Out.replace("$HCL$", HCL); return Out; } -QString CLanguage :: UnableToSetHCLInvalid( ) +QString CLanguage :: UnableToSetHCLInvalid( ) const { return m_CFG->GetString( "lang_0183", "lang_0183" ); } -QString CLanguage :: UnableToSetHCLTooLong( ) +QString CLanguage :: UnableToSetHCLTooLong( ) const { return m_CFG->GetString( "lang_0184", "lang_0184" ); } -QString CLanguage :: TheHCLIs( const QString &HCL ) +QString CLanguage :: TheHCLIs( const QString &HCL ) const { QString Out = m_CFG->GetString( "lang_0185", "lang_0185" ); Out.replace("$HCL$", HCL); return Out; } -QString CLanguage :: TheHCLIsTooLongUseForceToStart( ) +QString CLanguage :: TheHCLIsTooLongUseForceToStart( ) const { return m_CFG->GetString( "lang_0186", "lang_0186" ); } -QString CLanguage :: ClearingHCL( ) +QString CLanguage :: ClearingHCL( ) const { return m_CFG->GetString( "lang_0187", "lang_0187" ); } -QString CLanguage :: TryingToRehostAsPrivateGame( const QString &gamename ) +QString CLanguage :: TryingToRehostAsPrivateGame( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0188", "lang_0188" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: TryingToRehostAsPublicGame( const QString &gamename ) +QString CLanguage :: TryingToRehostAsPublicGame( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0189", "lang_0189" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: RehostWasSuccessful( ) +QString CLanguage :: RehostWasSuccessful( ) const { return m_CFG->GetString( "lang_0190", "lang_0190" ); } -QString CLanguage :: TryingToJoinTheGameButBannedByName( const QString &victim ) +QString CLanguage :: TryingToJoinTheGameButBannedByName( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0191", "lang_0191" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: TryingToJoinTheGameButBannedByIP( const QString &victim, const QString &ip, const QString &bannedname ) +QString CLanguage :: TryingToJoinTheGameButBannedByIP( const QString &victim, const QString &ip, const QString &bannedname ) const { QString Out = m_CFG->GetString( "lang_0192", "lang_0192" ); Out.replace("$VICTIM$", victim); @@ -1351,14 +1351,14 @@ QString CLanguage :: TryingToJoinTheGameButBannedByIP( const QString &victim, co return Out; } -QString CLanguage :: HasBannedName( const QString &victim ) +QString CLanguage :: HasBannedName( const QString &victim ) const { QString Out = m_CFG->GetString( "lang_0193", "lang_0193" ); Out.replace("$VICTIM$", victim); return Out; } -QString CLanguage :: HasBannedIP( const QString &victim, const QString &ip, const QString &bannedname ) +QString CLanguage :: HasBannedIP( const QString &victim, const QString &ip, const QString &bannedname ) const { QString Out = m_CFG->GetString( "lang_0194", "lang_0194" ); Out.replace("$VICTIM$", victim); @@ -1367,7 +1367,7 @@ QString CLanguage :: HasBannedIP( const QString &victim, const QString &ip, cons return Out; } -QString CLanguage :: PlayersInGameState( const QString &number, const QString &players ) +QString CLanguage :: PlayersInGameState( const QString &number, const QString &players ) const { QString Out = m_CFG->GetString( "lang_0195", "lang_0195" ); Out.replace("$NUMBER$", number); @@ -1375,14 +1375,14 @@ QString CLanguage :: PlayersInGameState( const QString &number, const QString &p return Out; } -QString CLanguage :: ValidServers( const QString &servers ) +QString CLanguage :: ValidServers( const QString &servers ) const { QString Out = m_CFG->GetString( "lang_0196", "lang_0196" ); Out.replace("$SERVERS$", servers); return Out; } -QString CLanguage :: TeamCombinedScore( const QString &team, const QString &score ) +QString CLanguage :: TeamCombinedScore( const QString &team, const QString &score ) const { QString Out = m_CFG->GetString( "lang_0197", "lang_0197" ); Out.replace("$TEAM$", team); @@ -1390,12 +1390,12 @@ QString CLanguage :: TeamCombinedScore( const QString &team, const QString &scor return Out; } -QString CLanguage :: BalancingSlotsCompleted( ) +QString CLanguage :: BalancingSlotsCompleted( ) const { return m_CFG->GetString( "lang_0198", "lang_0198" ); } -QString CLanguage :: PlayerWasKickedForFurthestScore( const QString &name, const QString &score, const QString &average ) +QString CLanguage :: PlayerWasKickedForFurthestScore( const QString &name, const QString &score, const QString &average ) const { QString Out = m_CFG->GetString( "lang_0199", "lang_0199" ); Out.replace("$NAME$", name); @@ -1404,29 +1404,29 @@ QString CLanguage :: PlayerWasKickedForFurthestScore( const QString &name, const return Out; } -QString CLanguage :: LocalAdminMessagesEnabled( ) +QString CLanguage :: LocalAdminMessagesEnabled( ) const { return m_CFG->GetString( "lang_0200", "lang_0200" ); } -QString CLanguage :: LocalAdminMessagesDisabled( ) +QString CLanguage :: LocalAdminMessagesDisabled( ) const { return m_CFG->GetString( "lang_0201", "lang_0201" ); } -QString CLanguage :: WasDroppedDesync( ) +QString CLanguage :: WasDroppedDesync( ) const { return m_CFG->GetString( "lang_0202", "lang_0202" ); } -QString CLanguage :: WasKickedForHavingLowestScore( const QString &score ) +QString CLanguage :: WasKickedForHavingLowestScore( const QString &score ) const { QString Out = m_CFG->GetString( "lang_0203", "lang_0203" ); Out.replace("$SCORE$", score); return Out; } -QString CLanguage :: PlayerWasKickedForLowestScore( const QString &name, const QString &score ) +QString CLanguage :: PlayerWasKickedForLowestScore( const QString &name, const QString &score ) const { QString Out = m_CFG->GetString( "lang_0204", "lang_0204" ); Out.replace("$NAME$", name); @@ -1434,100 +1434,100 @@ QString CLanguage :: PlayerWasKickedForLowestScore( const QString &name, const Q return Out; } -QString CLanguage :: ReloadingConfigurationFiles( ) +QString CLanguage :: ReloadingConfigurationFiles( ) const { return m_CFG->GetString( "lang_0205", "lang_0205" ); } -QString CLanguage :: CountDownAbortedSomeoneLeftRecently( ) +QString CLanguage :: CountDownAbortedSomeoneLeftRecently( ) const { return m_CFG->GetString( "lang_0206", "lang_0206" ); } -QString CLanguage :: UnableToCreateGameMustEnforceFirst( const QString &gamename ) +QString CLanguage :: UnableToCreateGameMustEnforceFirst( const QString &gamename ) const { QString Out = m_CFG->GetString( "lang_0207", "lang_0207" ); Out.replace("$GAMENAME$", gamename); return Out; } -QString CLanguage :: UnableToLoadReplaysOutside( ) +QString CLanguage :: UnableToLoadReplaysOutside( ) const { return m_CFG->GetString( "lang_0208", "lang_0208" ); } -QString CLanguage :: LoadingReplay( const QString &file ) +QString CLanguage :: LoadingReplay( const QString &file ) const { QString Out = m_CFG->GetString( "lang_0209", "lang_0209" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: UnableToLoadReplayDoesntExist( const QString &file ) +QString CLanguage :: UnableToLoadReplayDoesntExist( const QString &file ) const { QString Out = m_CFG->GetString( "lang_0210", "lang_0210" ); Out.replace("$FILE$", file); return Out; } -QString CLanguage :: CommandTrigger( const QString &trigger ) +QString CLanguage :: CommandTrigger( const QString &trigger ) const { QString Out = m_CFG->GetString( "lang_0211", "lang_0211" ); Out.replace("$TRIGGER$", trigger); return Out; } -QString CLanguage :: CantEndGameOwnerIsStillPlaying( const QString &owner ) +QString CLanguage :: CantEndGameOwnerIsStillPlaying( const QString &owner ) const { QString Out = m_CFG->GetString( "lang_0212", "lang_0212" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: CantUnhostGameOwnerIsPresent( const QString &owner ) +QString CLanguage :: CantUnhostGameOwnerIsPresent( const QString &owner ) const { QString Out = m_CFG->GetString( "lang_0213", "lang_0213" ); Out.replace("$OWNER$", owner); return Out; } -QString CLanguage :: WasAutomaticallyDroppedAfterSeconds( const QString &seconds ) +QString CLanguage :: WasAutomaticallyDroppedAfterSeconds( const QString &seconds ) const { QString Out = m_CFG->GetString( "lang_0214", "lang_0214" ); Out.replace("$SECONDS$", seconds); return Out; } -QString CLanguage :: HasLostConnectionTimedOutGProxy( ) +QString CLanguage :: HasLostConnectionTimedOutGProxy( ) const { return m_CFG->GetString( "lang_0215", "lang_0215" ); } -QString CLanguage :: HasLostConnectionSocketErrorGProxy( const QString &error ) +QString CLanguage :: HasLostConnectionSocketErrorGProxy( const QString &error ) const { QString Out = m_CFG->GetString( "lang_0216", "lang_0216" ); Out.replace("$ERROR$", error); return Out; } -QString CLanguage :: HasLostConnectionClosedByRemoteHostGProxy( ) +QString CLanguage :: HasLostConnectionClosedByRemoteHostGProxy( ) const { return m_CFG->GetString( "lang_0217", "lang_0217" ); } -QString CLanguage :: WaitForReconnectSecondsRemain( const QString &seconds ) +QString CLanguage :: WaitForReconnectSecondsRemain( const QString &seconds ) const { QString Out = m_CFG->GetString( "lang_0218", "lang_0218" ); Out.replace("$SECONDS$", seconds); return Out; } -QString CLanguage :: WasUnrecoverablyDroppedFromGProxy( ) +QString CLanguage :: WasUnrecoverablyDroppedFromGProxy( ) const { return m_CFG->GetString( "lang_0219", "lang_0219" ); } -QString CLanguage :: PlayerReconnectedWithGProxy( const QString &name ) +QString CLanguage :: PlayerReconnectedWithGProxy( const QString &name ) const { QString Out = m_CFG->GetString( "lang_0220", "lang_0220" ); Out.replace("$NAME$", name); diff --git a/src/libghost/language.h b/src/libghost/language.h new file mode 100644 index 0000000..f85b477 --- /dev/null +++ b/src/libghost/language.h @@ -0,0 +1,263 @@ +/* + + Copyright [2008] [Trevor Hogan] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/ + +*/ + +#ifndef LANGUAGE_H +#define LANGUAGE_H + +#include + +class CConfig; + +// +// CLanguage +// + +class CLanguage +{ +private: + CConfig *m_CFG; + +public: + CLanguage( const QString &nCFGFile ); + ~CLanguage( ); + + QString UnableToCreateGameTryAnotherName( const QString &server, const QString &gamename ) const; + QString UserIsAlreadyAnAdmin( const QString &server, const QString &user ) const; + QString AddedUserToAdminDatabase( const QString &server, const QString &user ) const; + QString ErrorAddingUserToAdminDatabase( const QString &server, const QString &user ) const; + QString YouDontHaveAccessToThatCommand( ) const; + QString UserIsAlreadyBanned( const QString &server, const QString &victim ) const; + QString BannedUser( const QString &server, const QString &victim ) const; + QString ErrorBanningUser( const QString &server, const QString &victim ) const; + QString UserIsAnAdmin( const QString &server, const QString &user ) const; + QString UserIsNotAnAdmin( const QString &server, const QString &user ) const; + QString UserWasBannedOnByBecause( const QString &server, const QString &victim, const QString &date, const QString &admin, const QString &reason ) const; + QString UserIsNotBanned( const QString &server, const QString &victim ) const; + QString ThereAreNoAdmins( const QString &server ) const; + QString ThereIsAdmin( const QString &server ) const; + QString ThereAreAdmins( const QString &server, const QString &count ) const; + QString ThereAreNoBannedUsers( const QString &server ) const; + QString ThereIsBannedUser( const QString &server ) const; + QString ThereAreBannedUsers( const QString &server, const QString &count ) const; + QString YouCantDeleteTheRootAdmin( ) const; + QString DeletedUserFromAdminDatabase( const QString &server, const QString &user ) const; + QString ErrorDeletingUserFromAdminDatabase( const QString &server, const QString &user ) const; + QString UnbannedUser( const QString &victim ) const; + QString ErrorUnbanningUser( const QString &victim ) const; + QString GameNumberIs( const QString &number, const QString &description ) const; + QString GameNumberDoesntExist( const QString &number ) const; + QString GameIsInTheLobby( const QString &description, const QString ¤t, const QString &max ) const; + QString ThereIsNoGameInTheLobby( const QString ¤t, const QString &max ) const; + QString UnableToLoadConfigFilesOutside( ) const; + QString LoadingConfigFile( const QString &file ) const; + QString UnableToLoadConfigFileDoesntExist( const QString &file ) const; + QString CreatingPrivateGame( const QString &gamename, const QString &user ) const; + QString CreatingPublicGame( const QString &gamename, const QString &user ) const; + QString UnableToUnhostGameCountdownStarted( const QString &description ) const; + QString UnhostingGame( const QString &description ) const; + QString UnableToUnhostGameNoGameInLobby( ) const; + QString VersionAdmin( const QString &version ) const; + QString VersionNotAdmin( const QString &version ) const; + QString UnableToCreateGameAnotherGameInLobby( const QString &gamename, const QString &description ) const; + QString UnableToCreateGameMaxGamesReached( const QString &gamename, const QString &max ) const; + QString GameIsOver( const QString &description ) const; + QString SpoofCheckByReplying( ) const; + QString GameRefreshed( ) const; + QString SpoofPossibleIsAway( const QString &user ) const; + QString SpoofPossibleIsUnavailable( const QString &user ) const; + QString SpoofPossibleIsRefusingMessages( const QString &user ) const; + QString SpoofDetectedIsNotInGame( const QString &user ) const; + QString SpoofDetectedIsInPrivateChannel( const QString &user ) const; + QString SpoofDetectedIsInAnotherGame( const QString &user ) const; + QString CountDownAborted( ) const; + QString TryingToJoinTheGameButBanned( const QString &victim ) const; + QString UnableToBanNoMatchesFound( const QString &victim ) const; + QString PlayerWasBannedByPlayer( const QString &server, const QString &victim, const QString &user ) const; + QString UnableToBanFoundMoreThanOneMatch( const QString &victim ) const; + QString AddedPlayerToTheHoldList( const QString &user ) const; + QString UnableToKickNoMatchesFound( const QString &victim ) const; + QString UnableToKickFoundMoreThanOneMatch( const QString &victim ) const; + QString SettingLatencyToMinimum( const QString &min ) const; + QString SettingLatencyToMaximum( const QString &max ) const; + QString SettingLatencyTo( const QString &latency ) const; + QString KickingPlayersWithPingsGreaterThan( const QString &total, const QString &ping ) const; + QString HasPlayedGamesWithThisBot( const QString &user, const QString &firstgame, const QString &lastgame, const QString &totalgames, const QString &avgloadingtime, const QString &avgstay ) const; + QString HasntPlayedGamesWithThisBot( const QString &user ) const; + QString AutokickingPlayerForExcessivePing( const QString &victim, const QString &ping ) const; + QString SpoofCheckAcceptedFor( const QString &server, const QString &user ) const; + QString PlayersNotYetSpoofChecked( const QString ¬spoofchecked ) const; + QString ManuallySpoofCheckByWhispering( const QString &hostname ) const; + QString SpoofCheckByWhispering( const QString &hostname ) const; + QString EveryoneHasBeenSpoofChecked( ) const; + QString PlayersNotYetPinged( const QString ¬pinged ) const; + QString EveryoneHasBeenPinged( ) const; + QString ShortestLoadByPlayer( const QString &user, const QString &loadingtime ) const; + QString LongestLoadByPlayer( const QString &user, const QString &loadingtime ) const; + QString YourLoadingTimeWas( const QString &loadingtime ) const; + QString HasPlayedDotAGamesWithThisBot( const QString &user, const QString &totalgames, const QString &totalwins, const QString &totallosses, const QString &totalkills, const QString &totaldeaths, const QString &totalcreepkills, const QString &totalcreepdenies, const QString &totalassists, const QString &totalneutralkills, const QString &totaltowerkills, const QString &totalraxkills, const QString &totalcourierkills, const QString &avgkills, const QString &avgdeaths, const QString &avgcreepkills, const QString &avgcreepdenies, const QString &avgassists, const QString &avgneutralkills, const QString &avgtowerkills, const QString &avgraxkills, const QString &avgcourierkills ) const; + QString HasntPlayedDotAGamesWithThisBot( const QString &user ) const; + QString WasKickedForReservedPlayer( const QString &reserved ) const; + QString WasKickedForOwnerPlayer( const QString &owner ) const; + QString WasKickedByPlayer( const QString &user ) const; + QString HasLostConnectionPlayerError( const QString &error ) const; + QString HasLostConnectionSocketError( const QString &error ) const; + QString HasLostConnectionClosedByRemoteHost( ) const; + QString HasLeftVoluntarily( ) const; + QString EndingGame( const QString &description ) const; + QString HasLostConnectionTimedOut( ) const; + QString GlobalChatMuted( ) const; + QString GlobalChatUnmuted( ) const; + QString ShufflingPlayers( ) const; + QString UnableToLoadConfigFileGameInLobby( ) const; + QString PlayersStillDownloading( const QString &stilldownloading ) const; + QString RefreshMessagesEnabled( ) const; + QString RefreshMessagesDisabled( ) const; + QString AtLeastOneGameActiveUseForceToShutdown( ) const; + QString CurrentlyLoadedMapCFGIs( const QString &mapcfg ) const; + QString LaggedOutDroppedByAdmin( ) const; + QString LaggedOutDroppedByVote( ) const; + QString PlayerVotedToDropLaggers( const QString &user ) const; + QString LatencyIs( const QString &latency ) const; + QString SyncLimitIs( const QString &synclimit ) const; + QString SettingSyncLimitToMinimum( const QString &min ) const; + QString SettingSyncLimitToMaximum( const QString &max ) const; + QString SettingSyncLimitTo( const QString &synclimit ) const; + QString UnableToCreateGameNotLoggedIn( const QString &gamename ) const; + QString AdminLoggedIn( ) const; + QString AdminInvalidPassword( const QString &attempt ) const; + QString ConnectingToBNET( const QString &server ) const; + QString ConnectedToBNET( const QString &server ) const; + QString DisconnectedFromBNET( const QString &server ) const; + QString LoggedInToBNET( const QString &server ) const; + QString BNETGameHostingSucceeded( const QString &server ) const; + QString BNETGameHostingFailed( const QString &server, const QString &gamename ) const; + QString ConnectingToBNETTimedOut( const QString &server ) const; + QString PlayerDownloadedTheMap( const QString &user, const QString &seconds, const QString &rate ) const; + QString UnableToCreateGameNameTooLong( const QString &gamename ) const; + QString SettingGameOwnerTo( const QString &owner ) const; + QString TheGameIsLocked( ) const; + QString GameLocked( ) const; + QString GameUnlocked( ) const; + QString UnableToStartDownloadNoMatchesFound( const QString &victim ) const; + QString UnableToStartDownloadFoundMoreThanOneMatch( const QString &victim ) const; + QString UnableToSetGameOwner( const QString &owner ) const; + QString UnableToCheckPlayerNoMatchesFound( const QString &victim ) const; + QString CheckedPlayer( const QString &victim, const QString &ping, const QString &from, const QString &admin, const QString &owner, const QString &spoofed, const QString &spoofedrealm, const QString &reserved ) const; + QString UnableToCheckPlayerFoundMoreThanOneMatch( const QString &victim ) const; + QString TheGameIsLockedBNET( ) const; + QString UnableToCreateGameDisabled( const QString &gamename ) const; + QString BotDisabled( ) const; + QString BotEnabled( ) const; + QString UnableToCreateGameInvalidMap( const QString &gamename ) const; + QString WaitingForPlayersBeforeAutoStart( const QString &players, const QString &playersleft ) const; + QString AutoStartDisabled( ) const; + QString AutoStartEnabled( const QString &players ) const; + QString AnnounceMessageEnabled( ) const; + QString AnnounceMessageDisabled( ) const; + QString AutoHostEnabled( ) const; + QString AutoHostDisabled( ) const; + QString UnableToLoadSaveGamesOutside( ) const; + QString UnableToLoadSaveGameGameInLobby( ) const; + QString LoadingSaveGame( const QString &file ) const; + QString UnableToLoadSaveGameDoesntExist( const QString &file ) const; + QString UnableToCreateGameInvalidSaveGame( const QString &gamename ) const; + QString UnableToCreateGameSaveGameMapMismatch( const QString &gamename ) const; + QString AutoSaveEnabled( ) const; + QString AutoSaveDisabled( ) const; + QString DesyncDetected( ) const; + QString UnableToMuteNoMatchesFound( const QString &victim ) const; + QString MutedPlayer( const QString &victim, const QString &user ) const; + QString UnmutedPlayer( const QString &victim, const QString &user ) const; + QString UnableToMuteFoundMoreThanOneMatch( const QString &victim ) const; + QString PlayerIsSavingTheGame( const QString &player ) const; + QString UpdatingClanList( ) const; + QString UpdatingFriendsList( ) const; + QString MultipleIPAddressUsageDetected( const QString &player, const QString &others ) const; + QString UnableToVoteKickAlreadyInProgress( ) const; + QString UnableToVoteKickNotEnoughPlayers( ) const; + QString UnableToVoteKickNoMatchesFound( const QString &victim ) const; + QString UnableToVoteKickPlayerIsReserved( const QString &victim ) const; + QString StartedVoteKick( const QString &victim, const QString &user, const QString &votesneeded ) const; + QString UnableToVoteKickFoundMoreThanOneMatch( const QString &victim ) const; + QString VoteKickPassed( const QString &victim ) const; + QString ErrorVoteKickingPlayer( const QString &victim ) const; + QString VoteKickAcceptedNeedMoreVotes( const QString &victim, const QString &user, const QString &votes ) const; + QString VoteKickCancelled( const QString &victim ) const; + QString VoteKickExpired( const QString &victim ) const; + QString WasKickedByVote( ) const; + QString TypeYesToVote( const QString &commandtrigger ) const; + QString PlayersNotYetPingedAutoStart( const QString ¬pinged ) const; + QString WasKickedForNotSpoofChecking( ) const; + QString WasKickedForHavingFurthestScore( const QString &score, const QString &average ) const; + QString PlayerHasScore( const QString &player, const QString &score ) const; + QString RatedPlayersSpread( const QString &rated, const QString &total, const QString &spread ) const; + QString ErrorListingMaps( ) const; + QString FoundMaps( const QString &maps ) const; + QString NoMapsFound( ) const; + QString ErrorListingMapConfigs( ) const; + QString FoundMapConfigs( const QString &mapconfigs ) const; + QString NoMapConfigsFound( ) const; + QString PlayerFinishedLoading( const QString &user ) const; + QString PleaseWaitPlayersStillLoading( ) const; + QString MapDownloadsDisabled( ) const; + QString MapDownloadsEnabled( ) const; + QString MapDownloadsConditional( ) const; + QString SettingHCL( const QString &HCL ) const; + QString UnableToSetHCLInvalid( ) const; + QString UnableToSetHCLTooLong( ) const; + QString TheHCLIs( const QString &HCL ) const; + QString TheHCLIsTooLongUseForceToStart( ) const; + QString ClearingHCL( ) const; + QString TryingToRehostAsPrivateGame( const QString &gamename ) const; + QString TryingToRehostAsPublicGame( const QString &gamename ) const; + QString RehostWasSuccessful( ) const; + QString TryingToJoinTheGameButBannedByName( const QString &victim ) const; + QString TryingToJoinTheGameButBannedByIP( const QString &victim, const QString &ip, const QString &bannedname ) const; + QString HasBannedName( const QString &victim ) const; + QString HasBannedIP( const QString &victim, const QString &ip, const QString &bannedname ) const; + QString PlayersInGameState( const QString &number, const QString &players ) const; + QString ValidServers( const QString &servers ) const; + QString TeamCombinedScore( const QString &team, const QString &score ) const; + QString BalancingSlotsCompleted( ) const; + QString PlayerWasKickedForFurthestScore( const QString &name, const QString &score, const QString &average ) const; + QString LocalAdminMessagesEnabled( ) const; + QString LocalAdminMessagesDisabled( ) const; + QString WasDroppedDesync( ) const; + QString WasKickedForHavingLowestScore( const QString &score ) const; + QString PlayerWasKickedForLowestScore( const QString &name, const QString &score ) const; + QString ReloadingConfigurationFiles( ) const; + QString CountDownAbortedSomeoneLeftRecently( ) const; + QString UnableToCreateGameMustEnforceFirst( const QString &gamename ) const; + QString UnableToLoadReplaysOutside( ) const; + QString LoadingReplay( const QString &file ) const; + QString UnableToLoadReplayDoesntExist( const QString &file ) const; + QString CommandTrigger( const QString &trigger ) const; + QString CantEndGameOwnerIsStillPlaying( const QString &owner ) const; + QString CantUnhostGameOwnerIsPresent( const QString &owner ) const; + QString WasAutomaticallyDroppedAfterSeconds( const QString &seconds ) const; + QString HasLostConnectionTimedOutGProxy( ) const; + QString HasLostConnectionSocketErrorGProxy( const QString &error ) const; + QString HasLostConnectionClosedByRemoteHostGProxy( ) const; + QString WaitForReconnectSecondsRemain( const QString &seconds ) const; + QString WasUnrecoverablyDroppedFromGProxy( ) const; + QString PlayerReconnectedWithGProxy( const QString &name ) const; +}; + +#endif diff --git a/ghost/ghost.pro b/src/libghost/libghost.pro similarity index 67% rename from ghost/ghost.pro rename to src/libghost/libghost.pro index 52d7e37..061a21b 100644 --- a/ghost/ghost.pro +++ b/src/libghost/libghost.pro @@ -1,14 +1,39 @@ # ------------------------------------------------- # Project created by QtCreator 2010-04-19T13:31:03 # ------------------------------------------------- -QT += network \ - sql +! include( ../lib.pri ) { + error( Couldn't find lib.pri! ) +} + +QT += network sql QT -= gui TARGET = ghost -CONFIG += console \ - debug -CONFIG -= app_bundle -TEMPLATE = app +CONFIG += debug_and_release +QMAKE_CXXFLAGS += -fvisibility=hidden +LFLAGS += -fvisibility=hidden +#CONFIG -= app_bundle +INCLUDEPATH += .. \ + ../../include \ + ../../include/mysql +LIBS += -L../../src/lib +LIBS += -lbncsutil \ + -lgmp + +macx { + LIBS += -framework CoreFoundation -framework CoreServices + LIBS += -L. -L/usr/lib -lbz2 -lz + CONFIG += x86_64 x86 +} + +#!isEmpty( $$MY_LIBRARY_DEST_PATH ) { +# QMAKE_POST_LINK = make install +# list_of_files_to_install.files = $TARGET.$TARGET_EXT +# list_of_files_to_install.path = $$MY_LIBRARY_DEST_PATH +# INSTALLS += list_of_files_to_install +#} + + + SOURCES += util.cpp \ statsw3mmd.cpp \ statsdota.cpp \ @@ -40,21 +65,11 @@ SOURCES += util.cpp \ bnetprotocol.cpp \ bnet.cpp \ bncsutilinterface.cpp \ - main.cpp \ mpqarchive.cpp \ mpqfile.cpp -OTHER_FILES += w3g_format.txt \ - w3g_actions.txt \ - ghost.vcproj -INCLUDEPATH += ../bncsutil/src \ - ../zlib/include -LIBS += -L../bncsutil/src/bncsutil \ - -L"../bncsutil/vc8_build/Release MySQL" \ - -lbncsutil -macx { - LIBS += -framework CoreFoundation -framework CoreServices - LIBS += -L. -L/usr/lib -lbz2 -lz -} +#OTHER_FILES += w3g_format.txt \ +# w3g_actions.txt \ +# ghost.vcproj HEADERS += interfaces.h \ util.h \ @@ -76,6 +91,7 @@ HEADERS += interfaces.h \ ghostdbmysql.h \ ghostdb.h \ ghost.h \ + ghost_p.h \ gameslot.h \ gameprotocol.h \ gameplayer.h \ diff --git a/src/libghost/main.cpp b/src/libghost/main.cpp new file mode 100644 index 0000000..df6cabd --- /dev/null +++ b/src/libghost/main.cpp @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include + +#include "ghost.h" +#include "util.h" +#include "config.h" +#ifdef WIN32 +#include "windows.h" +#endif + +QFile gLogFile; +QTextStream gLogStream(&gLogFile); + +QString gCFGFile; +quint32 gLogMethod; +CGHost *gGHost = NULL; + +void SignalCatcher2( int s ) +{ + CONSOLE_Print( "[!!!] caught signal " + QString::number( s ) + ", exiting NOW" ); + + if( gGHost ) + { + if( gGHost->m_Exiting ) + exit( 1 ); + else + gGHost->m_Exiting = true; + } + else + exit( 1 ); +} + +void SignalCatcher( int s ) +{ + // signal( SIGABRT, SignalCatcher2 ); + signal( SIGINT, SignalCatcher2 ); + + CONSOLE_Print( "[!!!] caught signal " + QString::number( s ) + ", exiting nicely" ); + + if( gGHost ) + gGHost->EventExitNice(); + else + exit( 1 ); +} + +// +// main +// + +#include "mpqarchive.h" +#include "mpqfile.h" + +int main( int argc, char **argv ) +{ + QCoreApplication a(argc, argv); + + /*MPQArchive arch("/mnt/disk/Programme/Warcraft III/War3Patch.mpq"); + if (!arch.open() && arch.m_Error != MPQArchive::NO_FILE_LIST) + { + DEBUG_Print("Failed to open, error " + QString::number(arch.m_Error)); + exit(1); + }*/ + + + + /*if (!arch.m_ListFile->read()) + { + DEBUG_Print("Failed to read file list, error " + QString::number(arch.m_ListFile->m_Error)); + }*/ + + + /*DEBUG_Print("Successfully open MPQ file"); + + MPQFile* common_j = arch.getFile("Scripts\\common.j"); + + if (!common_j->read()) + { + DEBUG_Print("Failed to read common.j, error " + QString::number(common_j->m_Error)); + } + exit(0);*/ + + gCFGFile = "ghost.cfg"; + + if( argc > 1 && argv[1] ) + gCFGFile = argv[1]; + + // read config file + + CConfig CFG; + CFG.Read( "default.cfg" ); + CFG.Read( gCFGFile ); + gLogFile.setFileName(CFG.GetString( "bot_log", QString( ) )); + gLogMethod = CFG.GetInt( "bot_logmethod", 1 ); + + if( !gLogFile.fileName().isEmpty() ) + { + if( gLogMethod == 1 ) + { + // log method 1: open, append, and close the log for every message + // this works well on Linux but poorly on Windows, particularly as the log file grows in size + // the log file can be edited/moved/deleted while GHost++ is running + } + else if( gLogMethod == 2 ) + { + // log method 2: open the log on startup, flush the log for every message, close the log on shutdown + // the log file CANNOT be edited/moved/deleted while GHost++ is running + + gLogFile.open(QFile::WriteOnly | QFile::Append); + } + } + + CONSOLE_Print( "[GHOST] starting up" ); + + if( !gLogFile.fileName().isEmpty() ) + { + if( gLogMethod == 1 ) + CONSOLE_Print( "[GHOST] using log method 1, logging is enabled and [" + gLogFile.fileName() + "] will not be locked" ); + else if( gLogMethod == 2 ) + { + if( gLogFile.error() != QFile::NoError ) + CONSOLE_Print( "[GHOST] using log method 2 but unable to open [" + gLogFile.fileName() + "] for appending, logging is disabled" ); + else + CONSOLE_Print( "[GHOST] using log method 2, logging is enabled and [" + gLogFile.fileName() + "] is now locked" ); + } + } + else + CONSOLE_Print( "[GHOST] no log file specified, logging is disabled" ); + + // catch SIGABRT and SIGINT + + // signal( SIGABRT, SignalCatcher ); + signal( SIGINT, SignalCatcher ); + +#ifndef WIN32 + // disable SIGPIPE since some systems like OS X don't define MSG_NOSIGNAL + + signal( SIGPIPE, SIG_IGN ); +#endif + +#ifdef WIN32 + // increase process priority + + CONSOLE_Print( "[GHOST] setting process priority to \"above normal\"" ); + SetPriorityClass( GetCurrentProcess( ), ABOVE_NORMAL_PRIORITY_CLASS ); +#endif + + // initialize ghost + + gGHost = new CGHost( &CFG, gCFGFile ); + + QObject::connect(gGHost, SIGNAL(destroyed()), &a, SLOT(deleteLater())); + + return a.exec(); +} diff --git a/ghost/map.cpp b/src/libghost/map.cpp similarity index 100% rename from ghost/map.cpp rename to src/libghost/map.cpp diff --git a/ghost/map.h b/src/libghost/map.h similarity index 100% rename from ghost/map.h rename to src/libghost/map.h diff --git a/ghost/mpqarchive.cpp b/src/libghost/mpqarchive.cpp similarity index 100% rename from ghost/mpqarchive.cpp rename to src/libghost/mpqarchive.cpp diff --git a/ghost/mpqarchive.h b/src/libghost/mpqarchive.h similarity index 100% rename from ghost/mpqarchive.h rename to src/libghost/mpqarchive.h diff --git a/ghost/mpqfile.cpp b/src/libghost/mpqfile.cpp similarity index 100% rename from ghost/mpqfile.cpp rename to src/libghost/mpqfile.cpp diff --git a/ghost/mpqfile.h b/src/libghost/mpqfile.h similarity index 100% rename from ghost/mpqfile.h rename to src/libghost/mpqfile.h diff --git a/ghost/next_combination.h b/src/libghost/next_combination.h similarity index 100% rename from ghost/next_combination.h rename to src/libghost/next_combination.h diff --git a/ghost/packed.cpp b/src/libghost/packed.cpp similarity index 100% rename from ghost/packed.cpp rename to src/libghost/packed.cpp diff --git a/ghost/packed.h b/src/libghost/packed.h similarity index 100% rename from ghost/packed.h rename to src/libghost/packed.h diff --git a/ghost/replay.cpp b/src/libghost/replay.cpp similarity index 100% rename from ghost/replay.cpp rename to src/libghost/replay.cpp diff --git a/ghost/replay.h b/src/libghost/replay.h similarity index 100% rename from ghost/replay.h rename to src/libghost/replay.h diff --git a/ghost/savegame.cpp b/src/libghost/savegame.cpp similarity index 100% rename from ghost/savegame.cpp rename to src/libghost/savegame.cpp diff --git a/ghost/savegame.h b/src/libghost/savegame.h similarity index 100% rename from ghost/savegame.h rename to src/libghost/savegame.h diff --git a/ghost/sha1.cpp b/src/libghost/sha1.cpp similarity index 100% rename from ghost/sha1.cpp rename to src/libghost/sha1.cpp diff --git a/ghost/sha1.h b/src/libghost/sha1.h similarity index 100% rename from ghost/sha1.h rename to src/libghost/sha1.h diff --git a/ghost/sqlite3.c b/src/libghost/sqlite3.c similarity index 100% rename from ghost/sqlite3.c rename to src/libghost/sqlite3.c diff --git a/ghost/sqlite3.h b/src/libghost/sqlite3.h similarity index 100% rename from ghost/sqlite3.h rename to src/libghost/sqlite3.h diff --git a/ghost/sqlite3ext.h b/src/libghost/sqlite3ext.h similarity index 100% rename from ghost/sqlite3ext.h rename to src/libghost/sqlite3ext.h diff --git a/ghost/stats.cpp b/src/libghost/stats.cpp similarity index 100% rename from ghost/stats.cpp rename to src/libghost/stats.cpp diff --git a/ghost/stats.h b/src/libghost/stats.h similarity index 100% rename from ghost/stats.h rename to src/libghost/stats.h diff --git a/ghost/statsdota.cpp b/src/libghost/statsdota.cpp similarity index 100% rename from ghost/statsdota.cpp rename to src/libghost/statsdota.cpp diff --git a/ghost/statsdota.h b/src/libghost/statsdota.h similarity index 100% rename from ghost/statsdota.h rename to src/libghost/statsdota.h diff --git a/ghost/statsw3mmd.cpp b/src/libghost/statsw3mmd.cpp similarity index 100% rename from ghost/statsw3mmd.cpp rename to src/libghost/statsw3mmd.cpp diff --git a/ghost/statsw3mmd.h b/src/libghost/statsw3mmd.h similarity index 100% rename from ghost/statsw3mmd.h rename to src/libghost/statsw3mmd.h diff --git a/src/libghost/ttmath/CHANGELOG b/src/libghost/ttmath/CHANGELOG new file mode 100644 index 0000000..c280246 --- /dev/null +++ b/src/libghost/ttmath/CHANGELOG @@ -0,0 +1,498 @@ +Version 0.9.1 (2010.02.07): + * fixed: the parser didn't use characters for changing the base (# and &) + those characters were skipped + (this bug was introduced in 0.9.0) + * fixed: added in the parser: operator's associativity + operator ^ (powering) is right-associative: + sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24 + previously was: 2^3^4 = (2^3)^4 = 4096 + * fixed: in Big::ToString_CreateNewMantissaAndExponent() changed the formula: + new_exp_ = [log base (2^exponent)] + 1 + now the part '+ 1' is only made when the logarithm is positive and with fraction + if the value is negative we can only skip the fraction, previously + we lost some last digits from the new mantissa + Consider this binary value (32 bit mantissa): + (bin)1.0000000000000000000000000000011 + previously ToString() gave 1, now we have: 1.000000001 + * changed: in Big::ToString() the base rounding is made only if the result value + would not be an integer, e.g. if the value is 1.999999999999 then + the base rounding will not be done - because as the result would be 2 + * added: IEEE 754 half-to-even rounding (bankers' rounding) to the following + floating point algorithms: Big::Add, Big::Sub, Big::Mul, Big::Div + * added: static sint UInt::FindLowestBitInWord(uint x) + this method is looking for the lowest set bit in a word + * added: UInt::FindLowestBit(uint & table_id, uint & index) + this method is looking for the lowest set bit + + +Version 0.9.0 (2009.11.25): + * added: support for wide characters (wchar_t, std::wstring) + * added: Big::IsInteger() + returns true if the value is integer (without fraction) + (NaN flag is not checked) + * added: global Gamma() function + * added: gamma() function to the parser + * added: CGamma class + is used with Gamma() and Factorial() in multithreaded environment + * added: multithread support for Big<> class + you should compile with TTMATH_MULTITHREADS + and use TTMATH_MULTITHREADS_HELPER macro somewhere in your *.cpp file + * added: x86_64 asm code for Microsoft Visual compiler + file: ttmathuint_x86_64_msvc.asm + (this file should be compiled first because MS VC doesn't support inline assembler in x86_64 mode) + * added: flag TTMATH_BIG_ZERO to Big<> class + if this flag is set then there is a value zero + Big::IsZero() is faster now + * added: Big::ClearInfoBit(unsigned char) + Big::SetInfoBit(unsigned char) + Big::IsInfoBit(unsigned char) + some methods for manipulating the info flags + * added: macro: TTMATH_BITS(min_bits) + which returns the number of machine words + capable to hold min_bits bits + * added: bool Parser::Calculated() + this method returns true is something was calculated + (at least one mathematical operator was used or a function or variable) + * added: to the parser: operator percentage + e.g. 1000-50%=1000-(1000*0,5)=500 + * added: struct: Conv + consists of some parameters used + in ToString() and FromString() + * added: Big::ToString() can group digits + e.g. 1234567 -> 1`234`567 + * added: Parser::SetGroup(int g) + Parser::SetComma(int c, int c2 = 0) + Parser::SetParamSep(int s) + * added: std::string UInt::ToString(uint b = 10) + std::wstring UInt::ToWString(uint b = 10) + std::string Int::ToString(uint b = 10) + std::wstring Int::ToWString(uint b = 10) + uint Big::ToString(std::string & result, const Conv & conv) + uint Big::ToString(std::wstring & result, const Conv & conv) + std::string Big::ToString(const Conv & conv) + std::string Big::ToString() + std::wstring Big::ToWString(const Conv & conv) + std::wstring Big::ToWString() + * added: uint FromString(const char * source, const Conv & conv, const char **, bool *) + uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *) + uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *) + uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *) + * added: UInt::Sqrt() - a new algorithm for calculating the square root + * added: to the parser: function frac() - returns a value without the integer part + (only fraction remains) + * added: Int::DivInt(sint divisor, sint * remainder) + * added: const char * UInt::LibTypeStr() + const char * Big::LibTypeStr() + LibTypeCode UInt::LibType() + LibTypeCode Big::LibType() + returning a string/enum represents the currect type of the library + we have following types: + asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) + asm_gcc_32 - with asm code designed for GCC (32 bits) + asm_vc_64 - with asm for VC (64 bit) + asm_gcc_64 - with asm for GCC (64 bit) + no_asm_32 - pure C++ version (32 bit) - without any asm code + no_asm_64 - pure C++ version (64 bit) - without any asm code + * added: UInt::operator>>(int) + UInt::operator>>=(int) + UInt::operator<<(int) + UInt::operator<<=(int) + * changed: Factorial() is using the Gamma() function now + * changed: Big::Div(ss2) + Big::Mod(ss2) + they return 2 when ss2 is zero + previously returned 1 + * changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n) + they were not too much accurate for some integers + e.g. Root(16;4) returned a value very closed to 2 (not exactly 2) + * changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16 + the previous version was not accurate on some last digits (after the comma operator) + consider this binary value (32 bit mantissa): + base 2: 1.1111 1111 1111 1111 1111 1111 1110 101 + previous ToString() gave: + base 4: 1.33333333333332 + base 8: 1.777777777 + base 16: 1.FFFFFF + now we have: + base 4: 1.3333333333333222 + base 8: 1.77777777724 + base 16: 1.FFFFFFEA + * changed: in Big::ToString() some additional rounding (base_round) is now made only + when the value is not an integer + * changed: another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM) + * removed: Parser<>::SetFactorialMax() method + the factorial() is such a fast now that we don't need the method longer + * removed: ErrorCode::err_too_big_factorial + * removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2 + the comma characters we have in Conv struct now + + +Version 0.8.6 (2009.10.25): + * fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was + equal 1 (should be set 2) + this affected only no-asm parts - when macro TTMATH_NOASM was defined + * fixed: UInt::MulInt(uint ss2) + there was a buffer overflow when value_size was equal 1 + * fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile + when macro TTMATH_NOASM was defined + * fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character) + * fixed: Int::FromString(const tt_string & s, uint b = 10) + didn't use 'b' (always was '10') + * fixed: buffer overflow in Big::ToInt(Int & result) + * fixed: powering algorithm in: + UInt::Pow(UInt pow) + Big::Pow(UInt pow) + Big::PowUInt(Big pow) + when 'pow' was sufficient large the algorithm returned carry + but the result could have been calculated correctly + + +Version 0.8.5 (2009.06.16): + * fixed: Big::Mod(x) didn't correctly return a carry + and the result was sometimes very big (even greater than x) + * fixed: global function Mod(x) didn't set an ErrorCode object + * fixed: global function Round() didn't test a carry + now it sets ErrorCode object + * changed: function Sin(x) to Sin(x, ErrorCode * err=0) + when x was very big the function returns zero + now it sets ErrorCode object to err_overflow + and the result has a NaN flag set + the same is to Cos() function + * changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period + should be a little accurate especially on a very big 'x' + * changed: uint Mul(const UInt & ss2, uint algorithm = 100) + void MulBig(const UInt & ss2, UInt & result, uint algorithm = 100) + those methods by default use MulFastest() and MulFastestBig() + * changed: changed a little Mul2Big() to cooperate with Mul3Big() + * added: uint UInt::Mul3(const UInt & ss2) + void UInt::Mul3Big(const UInt & ss2, UInt & result) + a new multiplication algorithm: Karatsuba multiplication, + on a vector UInt<100> with all items different from zero this algorithm is faster + about 3 times than Mul2Big(), and on a vector UInt<1000> with all items different from + zero this algorithm is faster more than 5 times than Mul2Big() + (measured on 32bit platform with GCC 4.3.3 with -O3 and -DTTMATH_RELEASE) + * added: uint MulFastest(const UInt & ss2) + void MulFastestBig(const UInt & ss2, UInt & result) + those methods are trying to select the fastest multiplication algorithm + * added: uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + three forms: asm x86, asm x86_64, no-asm + those methods are used by the Karatsuba multiplication algorithm + * added: to Big<> class: support for NaN flag (Not a Number) + bool Big::IsNan() - returns true if the NaN flag is set + void Big::SetNan() - sets the NaN flag + The NaN flag is set by default after creating an object: + Big<1, 2> a; // NaN is set (it means the object has not a valid number) + std::cout << a; // cout gives "NaN" + a = 123; // now NaN is not set + std::cout << a; // cout gives "123" + The NaN is set if there was a carry during calculations + a.Mul(very_big_value); // a will have a NaN set + The NaN is set if an argument is NaN too + b.SetNan(); + a.Add(b); // a will have NaN because b has NaN too + If you try to do something on a NaN object, the result is a NaN too + a.SetNan(); + a.Add(2); // a is still a NaN + The NaN is set if you use incorrect arguments + a.Ln(-10); // a will have the NaN flag + The only way to clear the NaN flag is to assign a correct value or other correct object, + supposing 'a' has NaN flag, to remove the flag you can either: + a = 10; + a.FromInt(30); + a.SetOne(); + a.FromBig(other_object_without_nan); + etc. + + +Version 0.8.4 (2009.05.08): + * fixed: UInt::DivInt() didn't check whether the divisor is zero + there was a hardware interruption when the divisor was zero + (now the method returns one) + * fixed: the problem with GCC optimization on x86_64 + sometimes when using -O2 or -O3 GCC doesn't set correctly + the stack pointer (actually the stack is used for other things) + and you can't use instructions like push/pop in assembler code. + All the asm code in x86_64 have been rewritten, now instructions + push/pop are not used, other thing which have access to stack + (like "m" (mask) constraints in Rcl2 and Rcr2) have also gone away, + now the library works well with -O2 and -O3 and the asm code + is a little faster + * added: UInt::PrintLog(const char * msg, std::ostream & output) + used (for debugging purposes) by macro TTMATH_LOG(msg) + (it is used in nearly all methods in UInt class) + * added: macro TTMATH_DEBUG_LOG: when defined then TTMATH_LOG() + put some debug information (to std::cout) + * added: ttmathuint_x86.h, ttmathuint_x86_64.h, ttmathuint_noasm.h, + all the methods which are using assembler code have been + rewritten to no-asm forms, now we have: + 1. asm for x86 file: ttmathuint_x86.h + 2. asm for x86_64 file: ttmathuint_x86_64.h + 3. no asm file: ttmathuint_noasm.h + (it's used when macro TTMATH_NOASM is defined) + The third form can be used on x86 and x86_64 as well and + on other platforms with a little effort. + + +Version 0.8.3 (2009.04.06): + * fixed: RclMoveAllWords() and RcrMoveAllWords() sometimes didn't return + the proper carry, (when 'bits' was greater than or equal to 'value_size') + this had impact on Rcl() and Rcr(), they also returned the wrong carry + * fixed: UInt::Div() didn't return a correct result when the divisor was equal 1 + there was an error in UInt::DivInt() - when the divisor was 1 it returned + zero and the carry was set + * fixed: there was a TTMATH_REREFENCE_ASSERT error in Big::PowUInt() caused by: start.Mul(start) + * fixed: Big::Add incorrectly rounded 'this' when both exponents were equal + it caused that sometimes when adding a zero the result has changed + this had impact among other things on FromString() method + "0,8" had different binary representation from "0,80" + * fixed: template Big::FromBig(const Big & another) + didn't correctly set the exponent (when the mantisses had different size - + when 'man' was different from 'another_man') + this had impact on operator= too + sample: + Big<2,3> a = 100; + Big<3,5> b; + b = a; // b had a wrong value + * fixed: Big::Pow(const Big & pow) + it's using PowInt() only when pow.exponent is in range (-man*TTMATH_BITS_PER_UINT; 0] + previously the powering 'hung' on an input like this: "(1+ 1e-10000) ^ 10e100000000" + (there was 10e100000000 iterations in PowInt()) + * fixed: in function DegToRad(const ValueType & x, ErrorCode * err = 0) it is better + to make division first and then mutliplication -- the result is more + accurate especially when x is: 90,180,270 or 360 + * fixed: the parser didn't correctly treat operators for changing the base + (radix) -- operators '#' and '&', e.g.: + '#sin(1)' was equal '0' -- there was a zero from '#' and then + it was multipied by 'sin(1)' + the parser didn't check whether Big::FromString() has actually + read a proper value -- the method Big::FromString() didn't have + something to report such a situation + * fixed: Big::FromString() when the base is 10, the method reads the scientific + part only if such a part it correctly supplied, e.g: + '1234e10', '1234e+10', '1234e-5' + previous '1234e' was treated as: '1234e0' (now parsing stops on 'e' and + the 'e' can be parsed by other parsers, e.g. the mathematical + parser -- now in the parser would be: '1234e' = '1234 * e' = '3354,3597...' ) + * changed: renamed: Big::PowUInt(UInt pow) -> Big::Pow(UInt pow) + it returns 2 when there is: 0^0 + * changed: renamed: Big::PowInt(Int pow) -> Big::Pow(Int pow) + it returns 2 when there is: 0^0 or 0^(-something) + * changed: renamed: Big::PowBUInt() -> PowUInt(), Big::PowBInt() -> Big::PowInt() + they return 2 when the arguments are incorrect (like above) + * changed: UInt::SetBitInWord(uint & value, uint bit) is taking the first argument by a reference now, + the specific bit is set in the 'value' and the method returns the last state of the bit (zero or one) + * changed: UInt::SetBit(uint bit_index) - it's using TTMATH_ASSERT now + * changed: the size of built-in variables (constants) in ttmathbig.h + now they consist of 256 32bit words + macro TTMATH_BUILTIN_VARIABLES_SIZE is equal: 256u on a 32bit platform and 128ul on a 64bit platform + * changed: the asm code in ttmathuint.h and ttmathuint64.h has been completely rewritten + now UInt<> is faster about 15-30% than UInt<> from 0.8.2 + this has impact on Big<> too - it's faster about 10% now + * changed: in the parser: the form with operators '#' and '&' is as follows: + [-|+][#|&]numeric_value + previous was: [-|+][#|&][-|+]numeric_value + * changed: in the parser: the short form of multiplication has the same + priority as the normal multiplication, e.g.: + '2x^3' = 2 * (x^3) + previous the priority was greater than powering priority + previous: '2x^3' = (2*x) ^ 3 + * added: UInt::GetBit(uint bit_index) - returning the state of the specific bit + * added: Big::operator=(double) and Big::Big(double) + * added: UInt::Pow(UInt pow) and Int::Pow(Int pow) + * added: global template functions in ttmath.h: + ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) + ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) + ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) + ValueType DegToGrad(const ValueType & d, const ValueType & m, + const ValueType & s, ErrorCode * err = 0) + ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) + * added: Parser::SetDegRadGrad(int angle) - 0 deg, 1 rad (default), 2 grad + this affects following functions (in the parser only): sin, cos, tan, cot, + asin, acos, atan, acot + * added: functions to the parser: gradtorad(grad), radtograd(rad), degtograd(deg), + degtograd(d,m,s), gradtodeg(grad) + * added: UInt::FromString, added a parametr 'after_source' + which is pointing at the end of the parsed string + * added: Int::FromString(): parameter 'const char ** after_source = 0' + if exists it's pointing at the end of the parsed string + * added: to UInt::FromString(), Int::FromString(), Big::FromString(): + parameter 'bool * value_read = 0' - (if exists) tells + whether something has actually been read (at least one digit) + * added: Objects::IsDefined(const std::string & name) + returning true if such an object is defined + * removed: Big::FromString() this method doesn't longer recognize operators + for changing the base ('#' and '&') + + +Version 0.8.2 (2008.06.18): + * added: UInt::BitNot2() this method has been proposed by + Arek + * changed: Int::FromInt(const Int & p), + Int::FromInt(sint value) (it returns zero now) + Int::operator=(uint i) + Int::Int(uint i) + * added: Int::FromUInt(const UInt & p), + Int::FromUInt(uint value) + and appropriate constructors and assignment + operators as well + * changed: Big::FromInt(Int value), + * added: Big::FromUInt(UInt value), + Big::operator=(const UInt & value) + Big::Big(const UInt & value) + * changed: the parser is allowed to recognize values which + begin with a dot, e.g '.5' is treated as '0.5' + * added: a method Big::FromDouble(double) which converts from + standard double into a Big + * added: uint Big::ToDouble(double&) - converting into double + * added: Big::FromBig() and an operator= and a contructor + for converting from another kind of a Big class + * added: to the parser: avg(), sum() + * added: 'decimal_point' parameter into Big::ToString(...) + * fixed: Big::operator>> didn't use TTMATH_COMMA_CHARACTER_2 macro + * added: a short form of multiplication (without the '*' character) + e.g. '5y', (it's used only if the second parameter + is a variable or function) + * changed: variables and functions are case-sensitive now + * added: variables and functions can have underline characters + in their names + * changed: 'max_digit_after_comma' in Big::ToString() + remove the -2 state + * added: 'remove_trailing_zeroes' in Big::ToString() + it's either true or false + * fixed/changed: the way of using Big::SetSign() + the method do not check whether there is a zero or not now + (even if there's a zero the method can set a sign bit) + I changed this due to some prior errors + (errors corrected in revision 17, 49 and 58) + + +Version 0.8.1 (2007.04.17): + * fixed: Big::PowFrac(..) didn't return a correct error code + (when 'this' was negative) + * added: Root(x; index) (and to the parser as well) + * added: macro: TTMATH_PRERELEASE_VER (can be either zero or one) + * added: UInt::MulInt(int, UInt::&) + * added: Big::MulUInt(uint) + * changed: Big::MulInt(sint) + * added: Big::ToUInt(uint &) + * changed: Big::ToInt(sint&) + * changed: Factorial() it uses Big::MulUInt() at the beginning + (faster now especially more on a 32bit platform) + * added: doxygen.cfg for generating a documentation from the doxygen + * changed: UInt::Rcl(uint c=0) and UInt::Rcr(uint c=0) into + UInt::Rcl2(uint bits, uint c) and UInt::Rcr2(uint bits, uint c) + now they can move more than one bit and they are only private + * fixed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c) + didn't correctly return a carry if the 'bits' were equal + to 'value_size*TTMATH_BITS_PER_UINT' + * changed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c) + into UInt::Rcl(uint bits, uint c=0) and + UInt::Rcr(uint bits, uint c=0) + they are faster now when the bits is greater than a half of + the TTMATH_BITS_PER_UINT + * changed: UInt::CompensationToLeft() it's faster now + * changed: more small changes where there were UInt::Rcl(uint c=0) and + UInt::Rcr(uint c=0) used + * changed: as the Big type uses UInt::Rcl() and UInt::Rcr() a lot then + it is much faster now (about 5-25%) + * added: ASinh(), ACosh(), ATanh() /ATgh()/, ACoth() /ACtgh()/ + and to the parser as well + * added: UInt::BitAnd(), UInt::BitOr(), UInt::BitXor(), UInt::BitNot(), + Big::BitAnd(), Big::BitOr(), Big::BitXor() + * added: to the parser: bitand(), bitor(), bitxor() + /band(), bor(), bxor()/ + * changed: the way of parsing operators in the mathematical parser + (the parser is not too much greedy now) + + +Version 0.8.0 (2007.03.28): + * added: into the parser: SetFactorialMax() + * added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec), + RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x), + Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/ + * changed: class Objects in ttmathobjects.h has been completely rewritten, + we can change the names of user-defined variables or functions, + and the names are case-sensitive now + * added: class History which is used in functions which take a lot of time + during calculating e.g. Factorial(x) + * added: Tg(x) a wrapper for Tan(x) + * changed: CTan(x) is Cot(x) now + * added: Ctg(x) a wrapper for Cot(x) + * added: ATg(x) a wrapper for ATan(x) + * changed: ACTan(x) is ACot(x) now + * added: ACtg(x) a wrapper for ACot(x) + * added: UInt::PrintTable() (for debugging etc.) + * changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have + been rewritten, now they have 128 32bit words (it's about + 1232 valid decimal digits) + * fixed: previous values from Big::SetPi() Big::SetE() and + Big::SetLn2() were not too much accurate (last 2-3 words were wrong) + * added: Big::SetLn10() (128 32bit words as well) + * added: macro TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on + 32bit platforms and 64ul on 64bit platforms (128/2=64) + * added: macros TTMATH_PLATFORM32 and TTMATH_PLATFORM64 + * changed: a small optimisation in UInt::Mul2Big() + * added: at the end of ttmath.h: #include "ttmathparser.h" + this is for convenience for a programmer, he can only use #include + with ttmath.h even if he uses the parser + * added: to samples: big.cpp, parser.cpp + * added/changes/fixed: in copy-constructors and operators= in Int, + Uint and Big (more info in the commit log) + * renamed: Big::SetDotOne() into Big::Set05() + * changes: a few small optimisations in Big + * deleted: the word 'virtual' from destructors: UInt, Int, Big + (types in this library are not projected to be base-classes for + another ones derived from them) + * and more small changes (look at the commit log) + + +Version 0.7.2 (2007.03.09): + * added: Big::Mod - the remainder from a division + * added: Big::Sgn - the 'sign' from the value (-1,0,1) + * added: global functions Mod and Sgn too + * added: checking whether a user gives a correct value of a variable or function + (user-defined variables/functions in the mathematical parser) + * added: into the parser: logical operators: > < >= <= == != && || + * added: into the parser: logical functions: and() or() not() if() + * added: ErrorCode::err_unknown_operator when the parser couldn't read an operator + + +Version 0.7.1 (2007.02.27): + * fixed: the error 'overflow during printing' which was caused + by Big::FromInt(Int value) (the sign has to be set at the end) + * fixed: many small errors + * added: ATan (arctan), ACTan (arc ctan) functions + + +Version 0.7.0 (2007.02.24): + * finished: support for 64bit platforms + * added: ASin (arcsin), ACos (arccos) functions + + +Version 0.6.4 (2007.01.29): + * fixed: the problem with a sign in the mathematical parser /-(1) was 1/ + * added: UInt::AddInt and UInt::SubInt + * changed: UInt::AddOne and UInt::SubOne (much faster now) + * added: UInt::SetBitInWord + * changed: UInt::SetBit (much faster now) + UInt::AddTwoUints renamed to UInt::AddTwoInts + UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord + UInt::Mul64 renamed to UInt::MulTwoWords + UInt::Div64 renamed to UInt::DivTwoWords + * added: UInt::SetBitInWord + * and more small changes in UInt type + * start adding support for Amd64 (not finished yet) (added ttmathuint64.h) + + +Version 0.6.3 (2007.01.22): + * changed: position of arguments (x and base) in logarithm functions are swapped + * changed: it's possible to use any multiplication algorithms in the same time + (macros UINT_MUL_VERSION_'X' have gone) + * added: ExceptionInfo, ReferenceError and RuntimeError classes + * changed: the mess in macros has been cleaned up + * added: TTMATH_RELEASE macro + + +Version 0.6.2 (2007.01.10): + * added: New division algorithm (radix b) where b is 2^32 diff --git a/src/libghost/ttmath/COPYRIGHT b/src/libghost/ttmath/COPYRIGHT new file mode 100644 index 0000000..f03126c --- /dev/null +++ b/src/libghost/ttmath/COPYRIGHT @@ -0,0 +1,28 @@ +Copyright (c) 2006-2010, Tomasz Sowa +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name Tomasz Sowa nor the names of contributors to this + project may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/libghost/ttmath/README b/src/libghost/ttmath/README new file mode 100644 index 0000000..ea5bc1c --- /dev/null +++ b/src/libghost/ttmath/README @@ -0,0 +1,23 @@ +A bignum library for C++ + +TTMath is a small library which allows one to perform arithmetic operations +with big unsigned integer, big signed integer and big floating point numbers. +It provides standard mathematical operations like adding, subtracting, +multiplying, dividing. With the library also goes a mathematical parser to +help you solving mathematical expressions. + +TTMath is developed under the BSD licence which means that it is free for +both personal and commercial use. + +The main goal of the library is to allow one to use big values in the same +way as the standard types like int or float. It does not need to be compiled +first because the whole library is written as the C++ templates. This means +only C++ developers can use this library and one thing they have to do is +to use 'include' directive of the preprocessor. How big the values can be +is set at compile time. + +Author: Tomasz Sowa +WWW: http://www.ttmath.org + +Contributors: +Christian Kaiser diff --git a/src/libghost/ttmath/samples/Makefile b/src/libghost/ttmath/samples/Makefile new file mode 100644 index 0000000..3303ccd --- /dev/null +++ b/src/libghost/ttmath/samples/Makefile @@ -0,0 +1,46 @@ +CC = g++ +CFLAGS = -Wall -pedantic -s -O2 -I.. + + +.SUFFIXES: .cpp .o + +.cpp.o: + $(CC) -c $(CFLAGS) $< + + +all: uint int big big2 parser + + +uint: uint.o + $(CC) -o uint $(CFLAGS) uint.o + +int: int.o + $(CC) -o int $(CFLAGS) int.o + +big: big.o + $(CC) -o big $(CFLAGS) big.o + +big2: big2.o + $(CC) -o big2 $(CFLAGS) big2.o + +parser: parser.o + $(CC) -o parser $(CFLAGS) parser.o + + +uint.o: uint.cpp +int.o: int.cpp +big.o: big.cpp +big2.o: big2.cpp +parser.o: parser.cpp + + +clean: + rm -f *.o + rm -f *.s + rm -f uint + rm -f int + rm -f big + rm -f big2 + rm -f parser +# on MS Windows can automatically be added suffixes .exe to the names of output programs + rm -f *.exe diff --git a/src/libghost/ttmath/samples/big.cpp b/src/libghost/ttmath/samples/big.cpp new file mode 100644 index 0000000..8e9fa6a --- /dev/null +++ b/src/libghost/ttmath/samples/big.cpp @@ -0,0 +1,100 @@ +#include +#include + +// for convenience we're defining MyBig type +// this type has 2 words for its mantissa and 1 word for its exponent +// (on a 32bit platform one word means a word of 32 bits, +// and on a 64bit platform one word means a word of 64 bits) + +// Big +typedef ttmath::Big<1,2> MyBig; + + +void SimpleCalculating(const MyBig & a, const MyBig & b) +{ + std::cout << "Simple calculating" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "a + b = " << a+b << std::endl; + std::cout << "a - b = " << a-b << std::endl; + std::cout << "a * b = " << a*b << std::endl; + std::cout << "a / b = " << a/b << std::endl; +} + + +void CalculatingWithCarry(const MyBig & a, const MyBig & b) +{ +MyBig atemp; + + std::cout << "Calculating with a carry" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + + atemp = a; + if( !atemp.Add(b) ) + std::cout << "a + b = " << atemp << std::endl; + else + std::cout << "a + b = (carry)" << std::endl; + // it have no sense to print 'atemp' (it's undefined) + + atemp = a; + if( !atemp.Sub(b) ) + std::cout << "a - b = " << atemp << std::endl; + else + std::cout << "a - b = (carry)" << std::endl; + + atemp = a; + if( !atemp.Mul(b) ) + std::cout << "a * b = " << atemp << std::endl; + else + std::cout << "a * b = (carry)" << std::endl; + + + atemp = a; + if( !atemp.Div(b) ) + std::cout << "a / b = " << atemp << std::endl; + else + std::cout << "a / b = (carry or division by zero) " << std::endl; + +} + + +int main() +{ +MyBig a,b; + + // conversion from 'const char *' + a = "123456.543456"; + b = "98767878.124322"; + + SimpleCalculating(a,b); + + // 'a' will have the max value which can be held in this type + a.SetMax(); + + // conversion from double + b = 456.32; + + // Look at the value 'a' and the product from a+b and a-b + // Don't worry this is the nature of floating point numbers + CalculatingWithCarry(a,b); +} + +/* +the result (on 32 bit platform): + +Simple calculating +a = 123456.543456 +b = 98767878.124322 +a + b = 98891334.667778 +a - b = -98644421.580866 +a * b = 12193540837712.2708 +a / b = 0.00124996654580957646 +Calculating with a carry +a = 1.624801256066640878e+646457012 +b = 456.319999999999993 +a + b = 1.624801256066640878e+646457012 +a - b = 1.624801256066640878e+646457012 +a * b = (carry) +a / b = 3.560661939136222174e+646457009 +*/ diff --git a/src/libghost/ttmath/samples/big2.cpp b/src/libghost/ttmath/samples/big2.cpp new file mode 100644 index 0000000..fcb74bf --- /dev/null +++ b/src/libghost/ttmath/samples/big2.cpp @@ -0,0 +1,113 @@ +#include +#include + + +// this is a similar example to big.cpp +// but now we're using TTMATH_BITS() macro +// this macro returns how many words we need to store +// the given number of bits + +// TTMATH_BITS(64) +// on a 32bit platform the macro returns 2 (2*32=64) +// on a 64bit platform the macro returns 1 + +// TTMATH_BITS(128) +// on a 32bit platform the macro returns 4 (4*32=128) +// on a 64bit platform the macro returns 2 (2*64=128) + +// Big +typedef ttmath::Big MyBig; + +// consequently on a 32bit platform we define: Big<2, 4> +// and on a 64bit platform: Big<1, 2> +// and the calculations will be the same on both platforms + + +void SimpleCalculating(const MyBig & a, const MyBig & b) +{ + std::cout << "Simple calculating" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "a + b = " << a+b << std::endl; + std::cout << "a - b = " << a-b << std::endl; + std::cout << "a * b = " << a*b << std::endl; + std::cout << "a / b = " << a/b << std::endl; +} + + +void CalculatingWithCarry(const MyBig & a, const MyBig & b) +{ +MyBig atemp; + + std::cout << "Calculating with a carry" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + + atemp = a; + if( !atemp.Add(b) ) + std::cout << "a + b = " << atemp << std::endl; + else + std::cout << "a + b = (carry)" << std::endl; + // it have no sense to print 'atemp' (it's undefined) + + atemp = a; + if( !atemp.Sub(b) ) + std::cout << "a - b = " << atemp << std::endl; + else + std::cout << "a - b = (carry)" << std::endl; + + atemp = a; + if( !atemp.Mul(b) ) + std::cout << "a * b = " << atemp << std::endl; + else + std::cout << "a * b = (carry)" << std::endl; + + + atemp = a; + if( !atemp.Div(b) ) + std::cout << "a / b = " << atemp << std::endl; + else + std::cout << "a / b = (carry or division by zero) " << std::endl; + +} + + +int main() +{ +MyBig a,b; + + // conversion from 'const char *' + a = "123456.543456"; + b = "98767878.124322"; + + SimpleCalculating(a,b); + + // 'a' will have the max value which can be held in this type + a.SetMax(); + + // conversion from double + b = 456.32; + + // Look at the value 'a' and the product from a+b and a-b + // Don't worry this is the nature of floating point numbers + CalculatingWithCarry(a,b); +} + +/* +the result (the same on a 32 or 64bit platform): + +Simple calculating +a = 123456.543456 +b = 98767878.124322 +a + b = 98891334.667778 +a - b = -98644421.580866 +a * b = 12193540837712.270763536832 +a / b = 0.001249966545809576460596448526166860913 +Calculating with a carry +a = 2.3495345545711177736883282090959505003e+2776511644261678604 +b = 456.3199999999999931787897367030382156 +a + b = 2.3495345545711177736883282090959505003e+2776511644261678604 +a - b = 2.3495345545711177736883282090959505003e+2776511644261678604 +a * b = (carry) +a / b = 5.1488748127873374141170361292780486452e+2776511644261678601 +*/ diff --git a/src/libghost/ttmath/samples/int.cpp b/src/libghost/ttmath/samples/int.cpp new file mode 100644 index 0000000..13760d2 --- /dev/null +++ b/src/libghost/ttmath/samples/int.cpp @@ -0,0 +1,92 @@ +#include +#include + + +void SimpleCalculating(const ttmath::Int<2> & a, const ttmath::Int<2> & b) +{ + std::cout << "Simple calculating" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "a + b = " << a+b << std::endl; + std::cout << "a - b = " << a-b << std::endl; + std::cout << "a * b = " << a*b << std::endl; + std::cout << "a / b = " << a/b << std::endl; +} + + +void CalculatingWithCarry(const ttmath::Int<2> & a, const ttmath::Int<2> & b) +{ +ttmath::Int<2> atemp; + + std::cout << "Calculating with a carry" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + + atemp = a; + if( !atemp.Add(b) ) + std::cout << "a + b = " << atemp << std::endl; + else + std::cout << "a + b = (carry) " << atemp << std::endl; + + atemp = a; + if( !atemp.Sub(b) ) + std::cout << "a - b = " << atemp << std::endl; + else + std::cout << "a - b = (carry) " << atemp << std::endl; + + atemp = a; + if( !atemp.Mul(b) ) + std::cout << "a * b = " << atemp << std::endl; + else + std::cout << "a * b = (carry: the result is too big) " << std::endl; + // it have no sense to print 'atemp' (it's undefined) + + atemp = a; + if( !atemp.Div(b) ) + std::cout << "a / b = " << atemp << std::endl; + else + std::cout << "a / b = (division by zero) " << std::endl; + +} + +int main() +{ +// on 32bit platforms: 'a' and 'b' have 2-words (two 32bit words) +// it means a,b are from <-2^63, 2^63 - 1> +ttmath::Int<2> a,b; + + // conversion from int + a = 123456; + + // conversion from 'const char *' + b = "98767878"; + + SimpleCalculating(a,b); + + // 'a' will have the max value which can be held in this type + a.SetMax(); + + // conversion from 'int' + b = 10; + + CalculatingWithCarry(a,b); +} + +/* +the result (on 32 bit platform): + +Simple calculating +a = 123456 +b = 98767878 +a + b = 98891334 +a - b = -98644422 +a * b = 12193487146368 +a / b = 0 +Calculating with a carry +a = 9223372036854775807 +b = 10 +a + b = (carry) -9223372036854775799 +a - b = 9223372036854775797 +a * b = (carry) the result is too big) +a / b = 922337203685477580 +*/ diff --git a/src/libghost/ttmath/samples/parser.cpp b/src/libghost/ttmath/samples/parser.cpp new file mode 100644 index 0000000..6cbf192 --- /dev/null +++ b/src/libghost/ttmath/samples/parser.cpp @@ -0,0 +1,39 @@ +#include +#include + + +// for convenience we're defining MyBig type +// this type has 2 words for its mantissa and 1 word for its exponent +// (on a 32bit platform one word means a word of 32 bits, +// and on a 64bit platform one word means a word of 64 bits) +typedef ttmath::Big<1,2> MyBig; + + +int main() +{ +ttmath::Parser parser; + +// the sine function takes its parameter as being in radians, +// the product from the arcus tangent will be in radians as well +const char equation[] = " (34 + 24) * 123 - 34.32 ^ 6 * sin(2.56) - atan(10)"; + + ttmath::ErrorCode err = parser.Parse(equation); + + if( err == ttmath::err_ok ) + std::cout << parser.stack[0].value << std::endl; + else + std::cout << "Error: " + << static_cast(err) + << std::endl; +} + +/* +the result (on 32 bit platform): +-897705014.52573107 +*/ + + +/* +the result (on 64 bit platform): +-897705014.5257310676097719585259773124 +*/ diff --git a/src/libghost/ttmath/samples/uint.cpp b/src/libghost/ttmath/samples/uint.cpp new file mode 100644 index 0000000..f6b0df4 --- /dev/null +++ b/src/libghost/ttmath/samples/uint.cpp @@ -0,0 +1,93 @@ +#include +#include + + +void SimpleCalculating(const ttmath::UInt<2> & a, const ttmath::UInt<2> & b) +{ + std::cout << "Simple calculating" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "a + b = " << a+b << std::endl; + std::cout << "a - b = " << a-b << std::endl; + std::cout << "a * b = " << a*b << std::endl; + std::cout << "a / b = " << a/b << std::endl; +} + + +void CalculatingWithCarry(const ttmath::UInt<2> & a, const ttmath::UInt<2> & b) +{ +ttmath::UInt<2> atemp; + + std::cout << "Calculating with a carry" << std::endl; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + + atemp = a; + if( !atemp.Add(b) ) + std::cout << "a + b = " << atemp << std::endl; + else + // if there was a carry then atemp.Add(...) would have returned 1 + std::cout << "a + b = (carry: the result is too big) " << atemp << std::endl; + + atemp = a; + if( !atemp.Sub(b) ) + std::cout << "a - b = " << atemp << std::endl; + else + std::cout << "a - b = (carry: 'a' was smaller than 'b') " << atemp << std::endl; + + atemp = a; + if( !atemp.Mul(b) ) + std::cout << "a * b = " << atemp << std::endl; + else + std::cout << "a * b = (carry: the result is too big) " << std::endl; + // it have no sense to print 'atemp' (it's undefined) + + atemp = a; + if( !atemp.Div(b) ) + std::cout << "a / b = " << atemp << std::endl; + else + std::cout << "a / b = (division by zero) " << std::endl; + +} + +int main() +{ +// on 32bit platforms: 'a' and 'b' have 2-words (two 32bit words) +// it means a,b are from <0, 2^64 - 1> +ttmath::UInt<2> a,b; + + // conversion from 'const char *' + a = "123456"; + + // conversion from int + b = 9876; + + SimpleCalculating(a,b); + + // 'a' will have the max value which can be held in this type + a.SetMax(); + + // conversion from 'int' + b = 5; + + CalculatingWithCarry(a,b); +} + +/* +the result (on 32 bit platform): + +Simple calculating +a = 123456 +b = 9876 +a + b = 133332 +a - b = 113580 +a * b = 1219251456 +a / b = 12 +Calculating with a carry +a = 18446744073709551615 +b = 5 +a + b = (carry: the result is too big) 4 +a - b = 18446744073709551610 +a * b = (carry: the result is too big) +a / b = 3689348814741910323 +*/ diff --git a/src/libghost/ttmath/ttmath/ttmath.h b/src/libghost/ttmath/ttmath/ttmath.h new file mode 100644 index 0000000..8bd24f5 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmath.h @@ -0,0 +1,2835 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef headerfilettmathmathtt +#define headerfilettmathmathtt + +/*! + \file ttmath.h + \brief Mathematics functions. +*/ + +#ifdef _MSC_VER +//warning C4127: conditional expression is constant +#pragma warning( disable: 4127 ) +//warning C4702: unreachable code +#pragma warning( disable: 4702 ) +//warning C4800: forcing value to bool 'true' or 'false' (performance warning) +#pragma warning( disable: 4800 ) +#endif + + +#include "ttmathbig.h" +#include "ttmathobjects.h" + + +namespace ttmath +{ + /* + * + * functions defined here are used only with Big<> types + * + * + */ + + + /* + * + * functions for rounding + * + * + */ + + + /*! + this function skips the fraction from x + e.g 2.2 = 2 + 2.7 = 2 + -2.2 = 2 + -2.7 = 2 + */ + template + ValueType SkipFraction(const ValueType & x) + { + ValueType result( x ); + result.SkipFraction(); + + return result; + } + + + /*! + this function rounds to the nearest integer value + e.g 2.2 = 2 + 2.7 = 3 + -2.2 = -2 + -2.7 = -3 + */ + template + ValueType Round(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType result( x ); + uint c = result.Round(); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + + /*! + this function returns a value representing the smallest integer + that is greater than or equal to x + + Ceil(-3.7) = -3 + Ceil(-3.1) = -3 + Ceil(-3.0) = -3 + Ceil(4.0) = 4 + Ceil(4.2) = 5 + Ceil(4.8) = 5 + */ + template + ValueType Ceil(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType result(x); + uint c = 0; + + result.SkipFraction(); + + if( result != x ) + { + // x is with fraction + // if x is negative we don't have to do anything + if( !x.IsSign() ) + { + ValueType one; + one.SetOne(); + + c += result.Add(one); + } + } + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function returns a value representing the largest integer + that is less than or equal to x + + Floor(-3.6) = -4 + Floor(-3.1) = -4 + Floor(-3) = -3 + Floor(2) = 2 + Floor(2.3) = 2 + Floor(2.8) = 2 + */ + template + ValueType Floor(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType result(x); + uint c = 0; + + result.SkipFraction(); + + if( result != x ) + { + // x is with fraction + // if x is positive we don't have to do anything + if( x.IsSign() ) + { + ValueType one; + one.SetOne(); + + c += result.Sub(one); + } + } + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + + /* + * + * logarithms and the exponent + * + * + */ + + + /*! + this function calculates the natural logarithm (logarithm with the base 'e') + */ + template + ValueType Ln(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType result; + uint state = result.Ln(x); + + if( err ) + { + switch( state ) + { + case 0: + *err = err_ok; + break; + case 1: + *err = err_overflow; + break; + case 2: + *err = err_improper_argument; + break; + default: + *err = err_internal_error; + break; + } + } + + + return result; + } + + + /*! + this function calculates the logarithm + */ + template + ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) + { + if( x.IsNan() || base.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // default NaN + } + + ValueType result; + uint state = result.Log(x, base); + + if( err ) + { + switch( state ) + { + case 0: + *err = err_ok; + break; + case 1: + *err = err_overflow; + break; + case 2: + case 3: + *err = err_improper_argument; + break; + default: + *err = err_internal_error; + break; + } + } + + return result; + } + + + /*! + this function calculates the expression e^x + */ + template + ValueType Exp(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType result; + uint c = result.Exp(x); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + * + * trigonometric functions + * + */ + + + /* + this namespace consists of auxiliary functions + (something like 'private' in a class) + */ + namespace auxiliaryfunctions + { + + /*! + an auxiliary function for calculating the Sine + (you don't have to call this function) + */ + template + uint PrepareSin(ValueType & x, bool & change_sign) + { + ValueType temp; + + change_sign = false; + + if( x.IsSign() ) + { + // we're using the formula 'sin(-x) = -sin(x)' + change_sign = !change_sign; + x.ChangeSign(); + } + + // we're reducing the period 2*PI + // (for big values there'll always be zero) + temp.Set2Pi(); + + if( x.Mod(temp) ) + return 1; + + + // we're setting 'x' as being in the range of <0, 0.5PI> + + temp.SetPi(); + + if( x > temp ) + { + // x is in (pi, 2*pi> + x.Sub( temp ); + change_sign = !change_sign; + } + + temp.Set05Pi(); + + if( x > temp ) + { + // x is in (0.5pi, pi> + x.Sub( temp ); + x = temp - x; + } + + return 0; + } + + + /*! + an auxiliary function for calculating the Sine + (you don't have to call this function) + + it returns Sin(x) where 'x' is from <0, PI/2> + we're calculating the Sin with using Taylor series in zero or PI/2 + (depending on which point of these two points is nearer to the 'x') + + Taylor series: + sin(x) = sin(a) + cos(a)*(x-a)/(1!) + - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!) + + sin(a)*((x-a)^4)/(4!) + ... + + when a=0 it'll be: + sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ... + + and when a=PI/2: + sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... + */ + template + ValueType Sin0pi05(const ValueType & x) + { + ValueType result; + ValueType numerator, denominator; + ValueType d_numerator, d_denominator; + ValueType one, temp, old_result; + + // temp = pi/4 + temp.Set05Pi(); + temp.exponent.SubOne(); + + one.SetOne(); + + if( x < temp ) + { + // we're using the Taylor series with a=0 + result = x; + numerator = x; + denominator = one; + + // d_numerator = x^2 + d_numerator = x; + d_numerator.Mul(x); + + d_denominator = 2; + } + else + { + // we're using the Taylor series with a=PI/2 + result = one; + numerator = one; + denominator = one; + + // d_numerator = (x-pi/2)^2 + ValueType pi05; + pi05.Set05Pi(); + + temp = x; + temp.Sub( pi05 ); + d_numerator = temp; + d_numerator.Mul( temp ); + + d_denominator = one; + } + + uint c = 0; + bool addition = false; + + old_result = result; + for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) + { + // we're starting from a second part of the formula + c += numerator. Mul( d_numerator ); + c += denominator. Mul( d_denominator ); + c += d_denominator.Add( one ); + c += denominator. Mul( d_denominator ); + c += d_denominator.Add( one ); + temp = numerator; + c += temp.Div(denominator); + + if( c ) + // Sin is from <-1,1> and cannot make an overflow + // but the carry can be from the Taylor series + // (then we only break our calculations) + break; + + if( addition ) + result.Add( temp ); + else + result.Sub( temp ); + + + addition = !addition; + + // we're testing whether the result has changed after adding + // the next part of the Taylor formula, if not we end the loop + // (it means 'x' is zero or 'x' is PI/2 or this part of the formula + // is too small) + if( result == old_result ) + break; + + old_result = result; + } + + return result; + } + + } // namespace auxiliaryfunctions + + + + /*! + this function calculates the Sine + */ + template + ValueType Sin(ValueType x, ErrorCode * err = 0) + { + using namespace auxiliaryfunctions; + + ValueType one, result; + bool change_sign; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + if( err ) + *err = err_ok; + + if( PrepareSin( x, change_sign ) ) + { + // x is too big, we cannnot reduce the 2*PI period + // prior to version 0.8.5 the result was zero + + // result has NaN flag set by default + + if( err ) + *err = err_overflow; // maybe another error code? err_improper_argument? + + return result; // NaN is set by default + } + + result = Sin0pi05( x ); + + one.SetOne(); + + // after calculations there can be small distortions in the result + if( result > one ) + result = one; + else + if( result.IsSign() ) + // we've calculated the sin from <0, pi/2> and the result + // should be positive + result.SetZero(); + + if( change_sign ) + result.ChangeSign(); + + return result; + } + + + /*! + this function calulates the Cosine + we're using the formula cos(x) = sin(x + PI/2) + */ + template + ValueType Cos(ValueType x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType pi05; + pi05.Set05Pi(); + + uint c = x.Add( pi05 ); + + if( c ) + { + if( err ) + *err = err_overflow; + + return ValueType(); // result is undefined (NaN is set by default) + } + + return Sin(x, err); + } + + + /*! + this function calulates the Tangent + we're using the formula tan(x) = sin(x) / cos(x) + + it takes more time than calculating the Tan directly + from for example Taylor series but should be a bit preciser + because Tan receives its values from -infinity to +infinity + and when we calculate it from any series then we can make + a greater mistake than calculating 'sin/cos' + */ + template + ValueType Tan(const ValueType & x, ErrorCode * err = 0) + { + ValueType result = Cos(x, err); + + if( err && *err != err_ok ) + return result; + + if( result.IsZero() ) + { + if( err ) + *err = err_improper_argument; + + result.SetNan(); + + return result; + } + + return Sin(x, err) / result; + } + + + /*! + this function calulates the Tangent + look at the description of Tan(...) + + (the abbreviation of Tangent can be 'tg' as well) + */ + template + ValueType Tg(const ValueType & x, ErrorCode * err = 0) + { + return Tan(x, err); + } + + + /*! + this function calulates the Cotangent + we're using the formula tan(x) = cos(x) / sin(x) + + (why do we make it in this way? + look at information in Tan() function) + */ + template + ValueType Cot(const ValueType & x, ErrorCode * err = 0) + { + ValueType result = Sin(x, err); + + if( err && *err != err_ok ) + return result; + + if( result.IsZero() ) + { + if( err ) + *err = err_improper_argument; + + result.SetNan(); + + return result; + } + + return Cos(x, err) / result; + } + + + /*! + this function calulates the Cotangent + look at the description of Cot(...) + + (the abbreviation of Cotangent can be 'ctg' as well) + */ + template + ValueType Ctg(const ValueType & x, ErrorCode * err = 0) + { + return Cot(x, err); + } + + + /* + * + * inverse trigonometric functions + * + * + */ + + namespace auxiliaryfunctions + { + + /*! + an auxiliary function for calculating the Arc Sine + + we're calculating asin from the following formula: + asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ... + where abs(x) <= 1 + + we're using this formula when x is from <0, 1/2> + */ + template + ValueType ASin_0(const ValueType & x) + { + ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x; + ValueType two, result(x), x2(x); + ValueType nominator_temp, denominator_temp, old_result = result; + uint c = 0; + + x2.Mul(x); + two = 2; + + nominator.SetOne(); + denominator = two; + nominator_add = nominator; + denominator_add = denominator; + nominator_x = x; + denominator_x = 3; + + for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) + { + c += nominator_x.Mul(x2); + nominator_temp = nominator_x; + c += nominator_temp.Mul(nominator); + denominator_temp = denominator; + c += denominator_temp.Mul(denominator_x); + c += nominator_temp.Div(denominator_temp); + + // if there is a carry somewhere we only break the calculating + // the result should be ok -- it's from <-pi/2, pi/2> + if( c ) + break; + + result.Add(nominator_temp); + + if( result == old_result ) + // there's no sense to calculate more + break; + + old_result = result; + + + c += nominator_add.Add(two); + c += denominator_add.Add(two); + c += nominator.Mul(nominator_add); + c += denominator.Mul(denominator_add); + c += denominator_x.Add(two); + } + + return result; + } + + + + /*! + an auxiliary function for calculating the Arc Sine + + we're calculating asin from the following formula: + asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp + asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ... + + where abs(x) <= 1 + + we're using this formula when x is from (1/2, 1> + */ + template + ValueType ASin_1(const ValueType & x) + { + ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x; + ValueType denominator2; + ValueType one, two, result; + ValueType nominator_temp, denominator_temp, old_result; + uint c = 0; + + two = 2; + + one.SetOne(); + nominator = one; + result = one; + old_result = result; + denominator = two; + nominator_add = nominator; + denominator_add = denominator; + nominator_x = one; + nominator_x.Sub(x); + nominator_x_add = nominator_x; + denominator_x = 3; + denominator2 = two; + + + for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) + { + nominator_temp = nominator_x; + c += nominator_temp.Mul(nominator); + denominator_temp = denominator; + c += denominator_temp.Mul(denominator_x); + c += denominator_temp.Mul(denominator2); + c += nominator_temp.Div(denominator_temp); + + // if there is a carry somewhere we only break the calculating + // the result should be ok -- it's from <-pi/2, pi/2> + if( c ) + break; + + result.Add(nominator_temp); + + if( result == old_result ) + // there's no sense to calculate more + break; + + old_result = result; + + c += nominator_x.Mul(nominator_x_add); + c += nominator_add.Add(two); + c += denominator_add.Add(two); + c += nominator.Mul(nominator_add); + c += denominator.Mul(denominator_add); + c += denominator_x.Add(two); + c += denominator2.Mul(two); + } + + + nominator_x_add.exponent.AddOne(); // *2 + one.exponent.SubOne(); // =0.5 + nominator_x_add.Pow(one); // =sqrt(nominator_x_add) + result.Mul(nominator_x_add); + + one.Set05Pi(); + one.Sub(result); + + return one; + } + + + } // namespace auxiliaryfunctions + + + /*! + this function calculates the Arc Sine + x is from <-1,1> + */ + template + ValueType ASin(ValueType x, ErrorCode * err = 0) + { + using namespace auxiliaryfunctions; + + ValueType result, one; + one.SetOne(); + bool change_sign = false; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + if( x.GreaterWithoutSignThan(one) ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + if( x.IsSign() ) + { + change_sign = true; + x.Abs(); + } + + one.exponent.SubOne(); // =0.5 + + // asin(-x) = -asin(x) + if( x.GreaterWithoutSignThan(one) ) + result = ASin_1(x); + else + result = ASin_0(x); + + if( change_sign ) + result.ChangeSign(); + + if( err ) + *err = err_ok; + + return result; + } + + + /*! + this function calculates the Arc Cosine + + we're using the formula: + acos(x) = pi/2 - asin(x) + */ + template + ValueType ACos(const ValueType & x, ErrorCode * err = 0) + { + ValueType temp; + + temp.Set05Pi(); + temp.Sub(ASin(x, err)); + + return temp; + } + + + + namespace auxiliaryfunctions + { + + /*! + an auxiliary function for calculating the Arc Tangent + + arc tan (x) where x is in <0; 0.5) + (x can be in (-0.5 ; 0.5) too) + + we're using the Taylor series expanded in zero: + atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ... + */ + template + ValueType ATan0(const ValueType & x) + { + ValueType nominator, denominator, nominator_add, denominator_add, temp; + ValueType result, old_result; + bool adding = false; + uint c = 0; + + result = x; + old_result = result; + nominator = x; + nominator_add = x; + nominator_add.Mul(x); + + denominator.SetOne(); + denominator_add = 2; + + for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) + { + c += nominator.Mul(nominator_add); + c += denominator.Add(denominator_add); + + temp = nominator; + c += temp.Div(denominator); + + if( c ) + // the result should be ok + break; + + if( adding ) + result.Add(temp); + else + result.Sub(temp); + + if( result == old_result ) + // there's no sense to calculate more + break; + + old_result = result; + adding = !adding; + } + + return result; + } + + + /*! + an auxiliary function for calculating the Arc Tangent + + where x is in <0 ; 1> + */ + template + ValueType ATan01(const ValueType & x) + { + ValueType half; + half.Set05(); + + /* + it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here + + because as you can see below: + when x = sqrt(2)-1 + abs(x) = abs( (x-1)/(1+x) ) + so when we're calculating values around x + then they will be better converged to each other + + for example if we have x=0.4999 then during calculating ATan0(0.4999) + we have to make about 141 iterations but when we have x=0.5 + then during calculating ATan0( (x-1)/(1+x) ) we have to make + only about 89 iterations (both for Big<3,9>) + + in the future this 0.5 can be changed + */ + if( x.SmallerWithoutSignThan(half) ) + return ATan0(x); + + + /* + x>=0.5 and x<=1 + (x can be even smaller than 0.5) + + y = atac(x) + x = tan(y) + + tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b)) + y-b = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) ) + y = b + atan( (x-tab(b)) / (1+x*tan(b)) ) + + let b = pi/4 + tan(b) = tan(pi/4) = 1 + y = pi/4 + atan( (x-1)/(1+x) ) + + so + atac(x) = pi/4 + atan( (x-1)/(1+x) ) + when x->1 (x converges to 1) the (x-1)/(1+x) -> 0 + and we can use ATan0() function here + */ + + ValueType n(x),d(x),one,result; + + one.SetOne(); + n.Sub(one); + d.Add(one); + n.Div(d); + + result = ATan0(n); + + n.Set05Pi(); + n.exponent.SubOne(); // =pi/4 + result.Add(n); + + return result; + } + + + /*! + an auxiliary function for calculating the Arc Tangent + where x > 1 + + we're using the formula: + atan(x) = pi/2 - atan(1/x) for x>0 + */ + template + ValueType ATanGreaterThanPlusOne(const ValueType & x) + { + ValueType temp, atan; + + temp.SetOne(); + + if( temp.Div(x) ) + { + // if there was a carry here that means x is very big + // and atan(1/x) fast converged to 0 + atan.SetZero(); + } + else + atan = ATan01(temp); + + temp.Set05Pi(); + temp.Sub(atan); + + return temp; + } + + } // namespace auxiliaryfunctions + + + /*! + this function calculates the Arc Tangent + */ + template + ValueType ATan(ValueType x) + { + using namespace auxiliaryfunctions; + + ValueType one, result; + one.SetOne(); + bool change_sign = false; + + if( x.IsNan() ) + return result; // NaN is set by default + + // if x is negative we're using the formula: + // atan(-x) = -atan(x) + if( x.IsSign() ) + { + change_sign = true; + x.Abs(); + } + + if( x.GreaterWithoutSignThan(one) ) + result = ATanGreaterThanPlusOne(x); + else + result = ATan01(x); + + if( change_sign ) + result.ChangeSign(); + + return result; + } + + + /*! + this function calculates the Arc Tangent + look at the description of ATan(...) + + (the abbreviation of Arc Tangent can be 'atg' as well) + */ + template + ValueType ATg(const ValueType & x) + { + return ATan(x); + } + + + /*! + this function calculates the Arc Cotangent + + we're using the formula: + actan(x) = pi/2 - atan(x) + */ + template + ValueType ACot(const ValueType & x) + { + ValueType result; + + result.Set05Pi(); + result.Sub(ATan(x)); + + return result; + } + + + /*! + this function calculates the Arc Cotangent + look at the description of ACot(...) + + (the abbreviation of Arc Cotangent can be 'actg' as well) + */ + template + ValueType ACtg(const ValueType & x) + { + return ACot(x); + } + + + /* + * + * hyperbolic functions + * + * + */ + + + /*! + this function calculates the Hyperbolic Sine + + we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2 + */ + template + ValueType Sinh(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType ex, emx; + uint c = 0; + + c += ex.Exp(x); + c += emx.Exp(-x); + + c += ex.Sub(emx); + c += ex.exponent.SubOne(); + + if( err ) + *err = c ? err_overflow : err_ok; + + return ex; + } + + + /*! + this function calculates the Hyperbolic Cosine + + we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2 + */ + template + ValueType Cosh(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType ex, emx; + uint c = 0; + + c += ex.Exp(x); + c += emx.Exp(-x); + + c += ex.Add(emx); + c += ex.exponent.SubOne(); + + if( err ) + *err = c ? err_overflow : err_ok; + + return ex; + } + + + /*! + this function calculates the Hyperbolic Tangent + + we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) ) + */ + template + ValueType Tanh(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType ex, emx, nominator, denominator; + uint c = 0; + + c += ex.Exp(x); + c += emx.Exp(-x); + + nominator = ex; + c += nominator.Sub(emx); + denominator = ex; + c += denominator.Add(emx); + + c += nominator.Div(denominator); + + if( err ) + *err = c ? err_overflow : err_ok; + + return nominator; + } + + + /*! + this function calculates the Hyperbolic Tangent + look at the description of Tanh(...) + + (the abbreviation of Hyperbolic Tangent can be 'tgh' as well) + */ + template + ValueType Tgh(const ValueType & x, ErrorCode * err = 0) + { + return Tanh(x, err); + } + + /*! + this function calculates the Hyperbolic Cotangent + + we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) ) + */ + template + ValueType Coth(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + if( x.IsZero() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // NaN is set by default + } + + ValueType ex, emx, nominator, denominator; + uint c = 0; + + c += ex.Exp(x); + c += emx.Exp(-x); + + nominator = ex; + c += nominator.Add(emx); + denominator = ex; + c += denominator.Sub(emx); + + c += nominator.Div(denominator); + + if( err ) + *err = c ? err_overflow : err_ok; + + return nominator; + } + + + /*! + this function calculates the Hyperbolic Cotangent + look at the description of Coth(...) + + (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well) + */ + template + ValueType Ctgh(const ValueType & x, ErrorCode * err = 0) + { + return Coth(x, err); + } + + + /* + * + * inverse hyperbolic functions + * + * + */ + + + /*! + inverse hyperbolic sine + + asinh(x) = ln( x + sqrt(x^2 + 1) ) + */ + template + ValueType ASinh(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType xx(x), one, result; + uint c = 0; + one.SetOne(); + + c += xx.Mul(x); + c += xx.Add(one); + one.exponent.SubOne(); // one=0.5 + // xx is >= 1 + c += xx.PowFrac(one); // xx=sqrt(xx) + c += xx.Add(x); + c += result.Ln(xx); // xx > 0 + + // here can only be a carry + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + inverse hyperbolic cosine + + acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity) + */ + template + ValueType ACosh(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType xx(x), one, result; + uint c = 0; + one.SetOne(); + + if( x < one ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + c += xx.Mul(x); + c += xx.Sub(one); + // xx is >= 0 + // we can't call a PowFrac when the 'x' is zero + // if x is 0 the sqrt(0) is 0 + if( !xx.IsZero() ) + { + one.exponent.SubOne(); // one=0.5 + c += xx.PowFrac(one); // xx=sqrt(xx) + } + c += xx.Add(x); + c += result.Ln(xx); // xx >= 1 + + // here can only be a carry + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + inverse hyperbolic tangent + + atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1) + */ + template + ValueType ATanh(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType nominator(x), denominator, one, result; + uint c = 0; + one.SetOne(); + + if( !x.SmallerWithoutSignThan(one) ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + c += nominator.Add(one); + denominator = one; + c += denominator.Sub(x); + c += nominator.Div(denominator); + c += result.Ln(nominator); + c += result.exponent.SubOne(); + + // here can only be a carry + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + inverse hyperbolic tantent + */ + template + ValueType ATgh(const ValueType & x, ErrorCode * err = 0) + { + return ATanh(x, err); + } + + + /*! + inverse hyperbolic cotangent + + acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity) + */ + template + ValueType ACoth(const ValueType & x, ErrorCode * err = 0) + { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + + ValueType nominator(x), denominator(x), one, result; + uint c = 0; + one.SetOne(); + + if( !x.GreaterWithoutSignThan(one) ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + c += nominator.Add(one); + c += denominator.Sub(one); + c += nominator.Div(denominator); + c += result.Ln(nominator); + c += result.exponent.SubOne(); + + // here can only be a carry + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + inverse hyperbolic cotantent + */ + template + ValueType ACtgh(const ValueType & x, ErrorCode * err = 0) + { + return ACoth(x, err); + } + + + + + + /* + * + * functions for converting between degrees, radians and gradians + * + * + */ + + + /*! + this function converts degrees to radians + + it returns: x * pi / 180 + */ + template + ValueType DegToRad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + result = x; + + // it is better to make division first and then multiplication + // the result is more accurate especially when x is: 90,180,270 or 360 + temp = 180; + c += result.Div(temp); + + temp.SetPi(); + c += result.Mul(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts radians to degrees + + it returns: x * 180 / pi + */ + template + ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, delimiter; + uint c = 0; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + result = 180; + c += result.Mul(x); + + delimiter.SetPi(); + c += result.Div(delimiter); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts degrees in the long format into one value + + long format: (degrees, minutes, seconds) + minutes and seconds must be greater than or equal zero + + result: + if d>=0 : result= d + ((s/60)+m)/60 + if d<0 : result= d - ((s/60)+m)/60 + + ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because + there's only one division) + + for example: + DegToDeg(10, 30, 0) = 10.5 + DegToDeg(10, 24, 35.6)=10.4098(8) + */ + template + ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s, + ErrorCode * err = 0) + { + ValueType delimiter, multipler; + uint c = 0; + + if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() ) + { + if( err ) + *err = err_improper_argument; + + return delimiter ; // NaN is set by default + } + + multipler = 60; + delimiter = 3600; + + c += multipler.Mul(m); + c += multipler.Add(s); + c += multipler.Div(delimiter); + + if( d.IsSign() ) + multipler.ChangeSign(); + + c += multipler.Add(d); + + if( err ) + *err = c ? err_overflow : err_ok; + + return multipler; + } + + + /*! + this function converts degrees in the long format to radians + */ + template + ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s, + ErrorCode * err = 0) + { + ValueType temp_deg = DegToDeg(d,m,s,err); + + if( err && *err!=err_ok ) + return temp_deg; + + return DegToRad(temp_deg, err); + } + + + /*! + this function converts gradians to radians + + it returns: x * pi / 200 + */ + template + ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + result = x; + + // it is better to make division first and then multiplication + // the result is more accurate especially when x is: 100,200,300 or 400 + temp = 200; + c += result.Div(temp); + + temp.SetPi(); + c += result.Mul(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts radians to gradians + + it returns: x * 200 / pi + */ + template + ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, delimiter; + uint c = 0; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + result = 200; + c += result.Mul(x); + + delimiter.SetPi(); + c += result.Div(delimiter); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts degrees to gradians + + it returns: x * 200 / 180 + */ + template + ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + result = x; + + temp = 200; + c += result.Mul(temp); + + temp = 180; + c += result.Div(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts degrees in the long format to gradians + */ + template + ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s, + ErrorCode * err = 0) + { + ValueType temp_deg = DegToDeg(d,m,s,err); + + if( err && *err!=err_ok ) + return temp_deg; + + return DegToGrad(temp_deg, err); + } + + + /*! + this function converts degrees to gradians + + it returns: x * 180 / 200 + */ + template + ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + result = x; + + temp = 180; + c += result.Mul(temp); + + temp = 200; + c += result.Div(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + + + /* + * + * another functions + * + * + */ + + + /*! + this function calculates the square root + + Sqrt(9) = 3 + */ + template + ValueType Sqrt(ValueType x, ErrorCode * err = 0) + { + if( x.IsNan() || x.IsSign() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // NaN is set by default + } + + uint c = x.Sqrt(); + + if( err ) + *err = c ? err_overflow : err_ok; + + return x; + } + + + + namespace auxiliaryfunctions + { + + template + bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( index.IsSign() ) + { + // index cannot be negative + if( err ) + *err = err_improper_argument; + + x.SetNan(); + + return true; + } + + return false; + } + + + template + bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( index.IsZero() ) + { + if( x.IsZero() ) + { + // there isn't root(0;0) - we assume it's not defined + if( err ) + *err = err_improper_argument; + + x.SetNan(); + + return true; + } + + // root(x;0) is 1 (if x!=0) + x.SetOne(); + + if( err ) + *err = err_ok; + + return true; + } + + return false; + } + + + template + bool RootCheckIndexOne(const ValueType & index, ErrorCode * err) + { + ValueType one; + one.SetOne(); + + if( index == one ) + { + //root(x;1) is x + // we do it because if we used the PowFrac function + // we would lose the precision + if( err ) + *err = err_ok; + + return true; + } + + return false; + } + + + template + bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( index == 2 ) + { + x = Sqrt(x, err); + + return true; + } + + return false; + } + + + template + bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( !index.IsInteger() ) + { + // index must be integer + if( err ) + *err = err_improper_argument; + + x.SetNan(); + + return true; + } + + return false; + } + + + template + bool RootCheckXZero(ValueType & x, ErrorCode * err) + { + if( x.IsZero() ) + { + // root(0;index) is zero (if index!=0) + // RootCheckIndexZero() must be called beforehand + x.SetZero(); + + if( err ) + *err = err_ok; + + return true; + } + + return false; + } + + + template + bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign) + { + *change_sign = false; + + if( index.Mod2() ) + { + // index is odd (1,3,5...) + if( x.IsSign() ) + { + *change_sign = true; + x.Abs(); + } + } + else + { + // index is even + // x cannot be negative + if( x.IsSign() ) + { + if( err ) + *err = err_improper_argument; + + x.SetNan(); + + return true; + } + } + + return false; + } + + + template + uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index) + { + if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() ) + return 0; + + // old_x is integer, + // x is not integer, + // index is relatively small (index.exponent<0 or index.exponent<=0) + // (because we're using a special powering algorithm Big::PowUInt()) + + uint c = 0; + + ValueType temp(x); + c += temp.Round(); + + ValueType temp_round(temp); + c += temp.PowUInt(index); + + if( temp == old_x ) + x = temp_round; + + return (c==0)? 0 : 1; + } + + + + } // namespace auxiliaryfunctions + + + + /*! + indexth Root of x + index must be integer and not negative <0;1;2;3....) + + if index==0 the result is one + if x==0 the result is zero and we assume root(0;0) is not defined + + if index is even (2;4;6...) the result is x^(1/index) and x>0 + if index is odd (1;2;3;...) the result is either + -(abs(x)^(1/index)) if x<0 or + x^(1/index)) if x>0 + + (for index==1 the result is equal x) + */ + template + ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0) + { + using namespace auxiliaryfunctions; + + if( x.IsNan() || index.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // NaN is set by default + } + + if( RootCheckIndexSign(x, index, err) ) return x; + if( RootCheckIndexZero(x, index, err) ) return x; + if( RootCheckIndexOne ( index, err) ) return x; + if( RootCheckIndexTwo (x, index, err) ) return x; + if( RootCheckIndexFrac(x, index, err) ) return x; + if( RootCheckXZero (x, err) ) return x; + + // index integer and index!=0 + // x!=0 + + ValueType old_x(x); + bool change_sign; + + if( RootCheckIndex(x, index, err, &change_sign ) ) return x; + + ValueType temp; + uint c = 0; + + // we're using the formula: root(x ; n) = exp( ln(x) / n ) + c += temp.Ln(x); + c += temp.Div(index); + c += x.Exp(temp); + + if( change_sign ) + { + // x is different from zero + x.SetSign(); + } + + c += RootCorrectInteger(old_x, x, index); + + if( err ) + *err = c ? err_overflow : err_ok; + + return x; + } + + + + /*! + absolute value of x + e.g. -2 = 2 + 2 = 2 + */ + template + ValueType Abs(const ValueType & x) + { + ValueType result( x ); + result.Abs(); + + return result; + } + + + /*! + it returns the sign of the value + e.g. -2 = -1 + 0 = 0 + 10 = 1 + */ + template + ValueType Sgn(ValueType x) + { + x.Sgn(); + + return x; + } + + + /*! + the remainder from a division + + e.g. + mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 + mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6) + mod( 12.6 ; -3) = 0.6 + mod(-12.6 ; -3) = -0.6 + */ + template + ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0) + { + if( a.IsNan() || b.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // NaN is set by default + } + + uint c = a.Mod(b); + + if( err ) + *err = c ? err_overflow : err_ok; + + return a; + } + + + + namespace auxiliaryfunctions + { + + /*! + this function is used to store factorials in a given container + 'more' means how many values should be added at the end + + e.g. + std::vector fact; + SetFactorialSequence(fact, 3); + // now the container has three values: 1 1 2 + + SetFactorialSequence(fact, 2); + // now the container has five values: 1 1 2 6 24 + */ + template + void SetFactorialSequence(std::vector & fact, uint more = 20) + { + if( more == 0 ) + more = 1; + + uint start = static_cast(fact.size()); + fact.resize(fact.size() + more); + + if( start == 0 ) + { + fact[0] = 1; + ++start; + } + + for(uint i=start ; i + ValueType SetBernoulliNumbersSum(CGamma & cgamma, const ValueType & n_, uint m, + const volatile StopCalculating * stop = 0) + { + ValueType k_, temp, temp2, temp3, sum; + + sum.SetZero(); + + for(uint k=0 ; kWasStopSignal() ) + return ValueType(); // NaN + + if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero + continue; + + k_ = k; + + temp = n_; // n_ is equal 2 + temp.Pow(k_); + // temp = 2^k + + temp2 = cgamma.fact[m]; + temp3 = cgamma.fact[k]; + temp3.Mul(cgamma.fact[m-k]); + temp2.Div(temp3); + // temp2 = (m k) = m! / ( k! * (m-k)! ) + + temp.Mul(temp2); + temp.Mul(cgamma.bern[k]); + + sum.Add(temp); + // sum += 2^k * (m k) * B(k) + + if( sum.IsNan() ) + break; + } + + return sum; + } + + + /*! + an auxiliary function used to calculate Bernoulli numbers + start is >= 2 + + we use the recurrence formula: + B(m) = 1 / (2*(1 - 2^m)) * sum(m) + where sum(m) is calculated by SetBernoulliNumbersSum() + */ + template + bool SetBernoulliNumbersMore(CGamma & cgamma, uint start, const volatile StopCalculating * stop = 0) + { + ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_; + + const uint n = 2; + n_ = n; + + // start is >= 2 + for(uint m=start ; mWasStopSignal() ) + { + cgamma.bern.resize(m); // valid numbers are in [0, m-1] + return false; + } + + cgamma.bern[m].Div(denominator); + } + } + + return true; + } + + + /*! + this function is used to calculate Bernoulli numbers, + returns false if there was a stop signal, + 'more' means how many values should be added at the end + + e.g. + typedef Big<1,2> MyBig; + CGamma cgamma; + SetBernoulliNumbers(cgamma, 3); + // now we have three first Bernoulli numbers: 1 -0.5 0.16667 + + SetBernoulliNumbers(cgamma, 4); + // now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238 + */ + template + bool SetBernoulliNumbers(CGamma & cgamma, uint more = 20, const volatile StopCalculating * stop = 0) + { + if( more == 0 ) + more = 1; + + uint start = static_cast(cgamma.bern.size()); + cgamma.bern.resize(cgamma.bern.size() + more); + + if( start == 0 ) + { + cgamma.bern[0].SetOne(); + ++start; + } + + if( cgamma.bern.size() == 1 ) + return true; + + if( start == 1 ) + { + cgamma.bern[1].Set05(); + cgamma.bern[1].ChangeSign(); + ++start; + } + + // we should have sufficient factorials in cgamma.fact + if( cgamma.fact.size() < cgamma.bern.size() ) + SetFactorialSequence(cgamma.fact, static_cast(cgamma.bern.size() - cgamma.fact.size())); + + + return SetBernoulliNumbersMore(cgamma, start, stop); + } + + + /*! + an auxiliary function used to calculate the Gamma() function + + we calculate a sum: + sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ... + B(m) means a mth Bernoulli number + the sum starts from m=2, we calculate as long as the value will not change after adding a next part + */ + template + ValueType GammaFactorialHighSum(const ValueType & n, CGamma & cgamma, ErrorCode & err, + const volatile StopCalculating * stop) + { + ValueType temp, temp2, denominator, sum, oldsum; + + sum.SetZero(); + + for(uint m=2 ; mWasStopSignal() ) + { + err = err_interrupt; + return ValueType(); // NaN + } + + temp = (m-1); + denominator = n; + denominator.Pow(temp); + // denominator = n ^ (m-1) + + temp = m; + temp2 = temp; + temp.Mul(temp2); + temp.Sub(temp2); + // temp = m^2 - m + + denominator.Mul(temp); + // denominator = (m^2 - m) * n ^ (m-1) + + if( m >= cgamma.bern.size() ) + { + if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed + { + // there was the stop signal + err = err_interrupt; + return ValueType(); // NaN + } + } + + temp = cgamma.bern[m]; + temp.Div(denominator); + + oldsum = sum; + sum.Add(temp); + + if( sum.IsNan() || oldsum==sum ) + break; + } + + return sum; + } + + + /*! + an auxiliary function used to calculate the Gamma() function + + we calculate a helper function GammaFactorialHigh() by using Stirling's series: + n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) ) + where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY) + and sum(n) is calculated by GammaFactorialHighSum() + */ + template + ValueType GammaFactorialHigh(const ValueType & n, CGamma & cgamma, ErrorCode & err, + const volatile StopCalculating * stop) + { + ValueType temp, temp2, temp3, denominator, sum; + + temp.Set2Pi(); + temp.Mul(n); + temp2 = Sqrt(temp); + // temp2 = sqrt(2*pi*n) + + temp = n; + temp3.SetE(); + temp.Div(temp3); + temp.Pow(n); + // temp = (n/e)^n + + sum = GammaFactorialHighSum(n, cgamma, err, stop); + temp3.Exp(sum); + // temp3 = exp(sum) + + temp.Mul(temp2); + temp.Mul(temp3); + + return temp; + } + + + /*! + an auxiliary function used to calculate the Gamma() function + + Gamma(x) = GammaFactorialHigh(x-1) + */ + template + ValueType GammaPlusHigh(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) + { + ValueType one; + + one.SetOne(); + n.Sub(one); + + return GammaFactorialHigh(n, cgamma, err, stop); + } + + + /*! + an auxiliary function used to calculate the Gamma() function + + we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY] + we use the formula: + gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1) + */ + template + ValueType GammaPlusLowIntegerInt(uint n, CGamma & cgamma) + { + TTMATH_ASSERT( n > 0 ) + + if( n - 1 < static_cast(cgamma.fact.size()) ) + return cgamma.fact[n - 1]; + + ValueType res; + uint start = 2; + + if( cgamma.fact.size() < 2 ) + { + res.SetOne(); + } + else + { + start = static_cast(cgamma.fact.size()); + res = cgamma.fact[start-1]; + } + + for(uint i=start ; i + ValueType GammaPlusLowInteger(const ValueType & n, CGamma & cgamma) + { + sint n_; + + n.ToInt(n_); + + return GammaPlusLowIntegerInt(n_, cgamma); + } + + + /*! + an auxiliary function used to calculate the Gamma() function + + we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY] + we use a recurrence formula: + gamma(z+1) = z * gamma(z) + then: gamma(z) = gamma(z+1) / z + + e.g. + gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 ) + */ + template + ValueType GammaPlusLow(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) + { + ValueType one, denominator, temp, boundary; + + if( n.IsInteger() ) + return GammaPlusLowInteger(n, cgamma); + + one.SetOne(); + denominator = n; + boundary = TTMATH_GAMMA_BOUNDARY; + + while( n < boundary ) + { + n.Add(one); + denominator.Mul(n); + } + + n.Add(one); + + // now n is sufficient big + temp = GammaPlusHigh(n, cgamma, err, stop); + temp.Div(denominator); + + return temp; + } + + + /*! + an auxiliary function used to calculate the Gamma() function + */ + template + ValueType GammaPlus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) + { + if( n > TTMATH_GAMMA_BOUNDARY ) + return GammaPlusHigh(n, cgamma, err, stop); + + return GammaPlusLow(n, cgamma, err, stop); + } + + + /*! + an auxiliary function used to calculate the Gamma() function + + this function is used when n is negative + we use the reflection formula: + gamma(1-z) * gamma(z) = pi / sin(pi*z) + then: gamma(z) = pi / (sin(pi*z) * gamma(1-z)) + + */ + template + ValueType GammaMinus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) + { + ValueType pi, denominator, temp, temp2; + + if( n.IsInteger() ) + { + // gamma function is not defined when n is negative and integer + err = err_improper_argument; + return temp; // NaN + } + + pi.SetPi(); + + temp = pi; + temp.Mul(n); + temp2 = Sin(temp); + // temp2 = sin(pi * n) + + temp.SetOne(); + temp.Sub(n); + temp = GammaPlus(temp, cgamma, err, stop); + // temp = gamma(1 - n) + + temp.Mul(temp2); + pi.Div(temp); + + return pi; + } + + } // namespace auxiliaryfunctions + + + + /*! + this function calculates the Gamma function + + it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma() + e.g. + typedef Big<1,2> MyBig; + MyBig x=234, y=345.53; + CGamma cgamma; + std::cout << Gamma(x, cgamma) << std::endl; + std::cout << Gamma(y, cgamma) << std::endl; + in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), + and they will be reused in next calls to the function + + each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too + */ + template + ValueType Gamma(const ValueType & n, CGamma & cgamma, ErrorCode * err = 0, + const volatile StopCalculating * stop = 0) + { + using namespace auxiliaryfunctions; + + ValueType result; + ErrorCode err_tmp; + + if( n.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + + if( cgamma.history.Get(n, result, err_tmp) ) + { + if( err ) + *err = err_tmp; + + return result; + } + + err_tmp = err_ok; + + if( n.IsSign() ) + { + result = GammaMinus(n, cgamma, err_tmp, stop); + } + else + if( n.IsZero() ) + { + err_tmp = err_improper_argument; + result.SetNan(); + } + else + { + result = GammaPlus(n, cgamma, err_tmp, stop); + } + + if( result.IsNan() && err_tmp==err_ok ) + err_tmp = err_overflow; + + if( err ) + *err = err_tmp; + + if( stop && !stop->WasStopSignal() ) + cgamma.history.Add(n, result, err_tmp); + + return result; + } + + + /*! + this function calculates the Gamma function + + note: this function should be used only in a single-thread environment + */ + template + ValueType Gamma(const ValueType & n, ErrorCode * err = 0) + { + // warning: this static object is not thread safe + static CGamma cgamma; + + return Gamma(n, cgamma, err); + } + + + + namespace auxiliaryfunctions + { + + /*! + an auxiliary function for calculating the factorial function + + we use the formula: + x! = gamma(x+1) + */ + template + ValueType Factorial2(ValueType x, + CGamma * cgamma = 0, + ErrorCode * err = 0, + const volatile StopCalculating * stop = 0) + { + ValueType result, one; + + if( x.IsNan() || x.IsSign() || !x.IsInteger() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN set by default + } + + one.SetOne(); + x.Add(one); + + if( cgamma ) + return Gamma(x, *cgamma, err, stop); + + return Gamma(x, err); + } + + } // namespace auxiliaryfunctions + + + + /*! + the factorial from given 'x' + e.g. + Factorial(4) = 4! = 1*2*3*4 + + it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial() + e.g. + typedef Big<1,2> MyBig; + MyBig x=234, y=54345; + CGamma cgamma; + std::cout << Factorial(x, cgamma) << std::endl; + std::cout << Factorial(y, cgamma) << std::endl; + in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), + and they will be reused in next calls to the function + + each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too + */ + template + ValueType Factorial(const ValueType & x, CGamma & cgamma, ErrorCode * err = 0, + const volatile StopCalculating * stop = 0) + { + return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop); + } + + + /*! + the factorial from given 'x' + e.g. + Factorial(4) = 4! = 1*2*3*4 + + note: this function should be used only in a single-thread environment + */ + template + ValueType Factorial(const ValueType & x, ErrorCode * err = 0) + { + return auxiliaryfunctions::Factorial2(x, (CGamma*)0, err, 0); + } + + + /*! + this method prepares some coefficients: factorials and Bernoulli numbers + stored in 'fact' and 'bern' objects + + we're defining the method here because we're using Gamma() function which + is not available in ttmathobjects.h + + read the doc info in ttmathobjects.h file where CGamma<> struct is declared + */ + template + void CGamma::InitAll() + { + ValueType x = TTMATH_GAMMA_BOUNDARY + 1; + + // history.Remove(x) removes only one object + // we must be sure that there are not others objects with the key 'x' + while( history.Remove(x) ) + { + } + + // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1) + // when x is larger then fewer coefficients we need + Gamma(x, *this); + } + + + +} // namespace + + +/*! + this is for convenience for the user + he can only use '#include ' even if he uses the parser +*/ +#include "ttmathparser.h" + + +#ifdef _MSC_VER +//warning C4127: conditional expression is constant +#pragma warning( default: 4127 ) +//warning C4702: unreachable code +#pragma warning( default: 4702 ) +//warning C4800: forcing value to bool 'true' or 'false' (performance warning) +#pragma warning( default: 4800 ) +#endif + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathbig.h b/src/libghost/ttmath/ttmath/ttmathbig.h new file mode 100644 index 0000000..771f9c8 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathbig.h @@ -0,0 +1,5236 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2010, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfilettmathbig +#define headerfilettmathbig + +/*! + \file ttmathbig.h + \brief A Class for representing floating point numbers +*/ + +#include "ttmathint.h" +#include "ttmaththreads.h" + +#include + +#ifdef TTMATH_MULTITHREADS +#include +#endif + +namespace ttmath +{ + + +/*! + \brief Big implements the floating point numbers +*/ +template +class Big +{ + +/* + value = mantissa * 2^exponent + + exponent - an integer value with a sign + mantissa - an integer value without a sing + + mantissa must be pushed into the left side that is the highest bit from + mantissa must be one (of course if there's another value than zero) -- this job + (pushing bits into the left side) making Standardizing() method + + for example: + if we want to store value one (1) into our Big object we must: + set mantissa to 1 + set exponent to 0 + set info to 0 + and call method Standardizing() +*/ + + +public: + +Int exponent; +UInt mantissa; +unsigned char info; + + +/*! + Sign + the mask of a bit from 'info' which means that there is a sign + (when the bit is set) +*/ +#define TTMATH_BIG_SIGN 128 + + +/*! + Not a number + if this bit is set that there is not a valid number +*/ +#define TTMATH_BIG_NAN 64 + + +/*! + Zero + if this bit is set that there is value zero + mantissa should be zero and exponent should be zero too + (the Standardizing() method does this) +*/ +#define TTMATH_BIG_ZERO 32 + + + /*! + this method sets NaN if there was a carry (and returns 1 in such a case) + + c can be 0, 1 or other value different from zero + */ + uint CheckCarry(uint c) + { + if( c != 0 ) + { + SetNan(); + return 1; + } + + return 0; + } + +public: + + + /*! + returning the string represents the currect type of the library + we have following types: + asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) + asm_gcc_32 - with asm code designed for GCC (32 bits) + asm_vc_64 - with asm for VC (64 bit) + asm_gcc_64 - with asm for GCC (64 bit) + no_asm_32 - pure C++ version (32 bit) - without any asm code + no_asm_64 - pure C++ version (64 bit) - without any asm code + */ + static const char * LibTypeStr() + { + return UInt::LibTypeStr(); + } + + + /*! + returning the currect type of the library + */ + static LibTypeCode LibType() + { + return UInt::LibType(); + } + + + + /*! + this method moves all bits from mantissa into its left side + (suitably changes the exponent) or if the mantissa is zero + it sets the exponent to zero as well + (and clears the sign bit and sets the zero bit) + + it can return a carry + the carry will be when we don't have enough space in the exponent + + you don't have to use this method if you don't change the mantissa + and exponent directly + */ + uint Standardizing() + { + if( mantissa.IsTheHighestBitSet() ) + { + ClearInfoBit(TTMATH_BIG_ZERO); + return 0; + } + + if( CorrectZero() ) + return 0; + + uint comp = mantissa.CompensationToLeft(); + + return exponent.Sub( comp ); + } + + +private: + + /*! + if the mantissa is equal zero this method sets exponent to zero and + info without the sign + + it returns true if there was the correction + */ + bool CorrectZero() + { + if( mantissa.IsZero() ) + { + SetInfoBit(TTMATH_BIG_ZERO); + ClearInfoBit(TTMATH_BIG_SIGN); + exponent.SetZero(); + + return true; + } + else + { + ClearInfoBit(TTMATH_BIG_ZERO); + } + + return false; + } + + +public: + + /*! + this method clears a specific bit in the 'info' variable + + bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. + */ + void ClearInfoBit(unsigned char bit) + { + info = info & (~bit); + } + + + /*! + this method sets a specific bit in the 'info' variable + + bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. + + */ + void SetInfoBit(unsigned char bit) + { + info = info | bit; + } + + + /*! + this method returns true if a specific bit in the 'info' variable is set + + bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. + */ + bool IsInfoBit(unsigned char bit) const + { + return (info & bit) != 0; + } + + + /*! + this method sets zero + */ + void SetZero() + { + info = TTMATH_BIG_ZERO; + exponent.SetZero(); + mantissa.SetZero(); + + /* + we don't have to compensate zero + */ + } + + + /*! + this method sets one + */ + void SetOne() + { + FromUInt(1); + } + + + /*! + this method sets value 0.5 + */ + void Set05() + { + FromUInt(1); + exponent.SubOne(); + } + + + /*! + this method sets NaN flag (Not a Number) + when this flag is set that means there is no a valid number + */ + void SetNan() + { + SetInfoBit(TTMATH_BIG_NAN); + } + + +private: + + /*! + this method sets the mantissa of the value of pi + */ + void SetMantissaPi() + { + // this is a static table which represents the value of Pi (mantissa of it) + // (first is the highest word) + // we must define this table as 'unsigned int' because + // both on 32bit and 64bit platforms this table is 32bit + static const unsigned int temp_table[] = { + 0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22, + 0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245, + 0xe485b576, 0x625e7ec6, 0xf44c42e9, 0xa637ed6b, 0x0bff5cb6, 0xf406b7ed, 0xee386bfb, 0x5a899fa5, + 0xae9f2411, 0x7c4b1fe6, 0x49286651, 0xece45b3d, 0xc2007cb8, 0xa163bf05, 0x98da4836, 0x1c55d39a, + 0x69163fa8, 0xfd24cf5f, 0x83655d23, 0xdca3ad96, 0x1c62f356, 0x208552bb, 0x9ed52907, 0x7096966d, + 0x670c354e, 0x4abc9804, 0xf1746c08, 0xca18217c, 0x32905e46, 0x2e36ce3b, 0xe39e772c, 0x180e8603, + 0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5, + 0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64, + 0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7, + 0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64, + 0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31, + 0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26, + 0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9, + 0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed, + 0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1, + 0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de, + 0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831, + 0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b, + 0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03, + 0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3, + 0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8, + 0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0, + 0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee, + 0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c, + 0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466, + 0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9, + 0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd, + 0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d, + 0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1, + 0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7, + 0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df, + 0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52 + //0x86d44014, ... + // (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..) + // 256 32bit words for the mantissa -- about 2464 valid decimal digits + }; + // the value of PI is comming from the website http://zenwerx.com/pi.php + // 3101 digits were taken from this website + // (later the digits were compared with: + // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html ) + // and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform) + // and then the first 256 words were taken into this table + // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, + // and on 64bit platform value 128 (256/2=128)) + + mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); + } + +public: + + + /*! + this method sets the value of pi + */ + void SetPi() + { + SetMantissaPi(); + info = 0; + exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; + } + + + /*! + this method sets the value of 0.5 * pi + */ + void Set05Pi() + { + SetMantissaPi(); + info = 0; + exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1; + } + + + /*! + this method sets the value of 2 * pi + */ + void Set2Pi() + { + SetMantissaPi(); + info = 0; + exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3; + } + + + /*! + this method sets the value of e + (the base of the natural logarithm) + */ + void SetE() + { + static const unsigned int temp_table[] = { + 0xadf85458, 0xa2bb4a9a, 0xafdc5620, 0x273d3cf1, 0xd8b9c583, 0xce2d3695, 0xa9e13641, 0x146433fb, + 0xcc939dce, 0x249b3ef9, 0x7d2fe363, 0x630c75d8, 0xf681b202, 0xaec4617a, 0xd3df1ed5, 0xd5fd6561, + 0x2433f51f, 0x5f066ed0, 0x85636555, 0x3ded1af3, 0xb557135e, 0x7f57c935, 0x984f0c70, 0xe0e68b77, + 0xe2a689da, 0xf3efe872, 0x1df158a1, 0x36ade735, 0x30acca4f, 0x483a797a, 0xbc0ab182, 0xb324fb61, + 0xd108a94b, 0xb2c8e3fb, 0xb96adab7, 0x60d7f468, 0x1d4f42a3, 0xde394df4, 0xae56ede7, 0x6372bb19, + 0x0b07a7c8, 0xee0a6d70, 0x9e02fce1, 0xcdf7e2ec, 0xc03404cd, 0x28342f61, 0x9172fe9c, 0xe98583ff, + 0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2, + 0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238, + 0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270, + 0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e, + 0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef, + 0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6, + 0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a, + 0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a, + 0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b, + 0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a, + 0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a, + 0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910, + 0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3, + 0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6, + 0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e, + 0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403, + 0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1, + 0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64, + 0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829, + 0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282, + 0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74, + 0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b, + 0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457, + 0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e, + 0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e, + 0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749 + // 0x2fe26dd4, ... + // 256 32bit words for the mantissa -- about 2464 valid decimal digits + }; + + // above value was calculated using Big<1,400> type on a 32bit platform + // and then the first 256 words were taken, + // the calculating was made by using ExpSurrounding0(1) method + // which took 1420 iterations + // (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil) + // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, + // and on 64bit platform value 128 (256/2=128)) + + mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); + exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; + info = 0; + } + + + /*! + this method sets the value of ln(2) + the natural logarithm from 2 + */ + void SetLn2() + { + static const unsigned int temp_table[] = { + 0xb17217f7, 0xd1cf79ab, 0xc9e3b398, 0x03f2f6af, 0x40f34326, 0x7298b62d, 0x8a0d175b, 0x8baafa2b, + 0xe7b87620, 0x6debac98, 0x559552fb, 0x4afa1b10, 0xed2eae35, 0xc1382144, 0x27573b29, 0x1169b825, + 0x3e96ca16, 0x224ae8c5, 0x1acbda11, 0x317c387e, 0xb9ea9bc3, 0xb136603b, 0x256fa0ec, 0x7657f74b, + 0x72ce87b1, 0x9d6548ca, 0xf5dfa6bd, 0x38303248, 0x655fa187, 0x2f20e3a2, 0xda2d97c5, 0x0f3fd5c6, + 0x07f4ca11, 0xfb5bfb90, 0x610d30f8, 0x8fe551a2, 0xee569d6d, 0xfc1efa15, 0x7d2e23de, 0x1400b396, + 0x17460775, 0xdb8990e5, 0xc943e732, 0xb479cd33, 0xcccc4e65, 0x9393514c, 0x4c1a1e0b, 0xd1d6095d, + 0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c, + 0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b, + 0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b, + 0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982, + 0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2, + 0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c, + 0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a, + 0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9, + 0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae, + 0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8, + 0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c, + 0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f, + 0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00, + 0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783, + 0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8, + 0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a, + 0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda, + 0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8, + 0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527, + 0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7, + 0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca, + 0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb, + 0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab, + 0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797, + 0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6, + 0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992 + //0xcbb9ac40, ... + // (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..) + // 256 32bit words for the mantissa -- about 2464 valid decimal digits + }; + + // above value was calculated using Big<1,400> type on a 32bit platform + // and then the first 256 words were taken, + // the calculating was made by using LnSurrounding1(2) method + // which took 4035 iterations + // (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html) + // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, + // and on 64bit platform value 128 (256/2=128)) + + mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); + exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT); + info = 0; + } + + + /*! + this method sets the value of ln(10) + the natural logarithm from 10 + + I introduced this constant especially to make the conversion ToString() + being faster. In fact the method ToString() is keeping values of logarithms + it has calculated but it must calculate the logarithm at least once. + If a program, which uses this library, is running for a long time this + would be ok, but for programs which are running shorter, for example for + CGI applications which only once are printing values, this would be much + inconvenience. Then if we're printing with base (radix) 10 and the mantissa + of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE + we don't calculate the logarithm but take it from this constant. + */ + void SetLn10() + { + static const unsigned int temp_table[] = { + 0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72, + 0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6, + 0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb, + 0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981, + 0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0, + 0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e, + 0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5, + 0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e, + 0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47, + 0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834, + 0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a, + 0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d, + 0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a, + 0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353, + 0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd, + 0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8, + 0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022, + 0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f, + 0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31, + 0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766, + 0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84, + 0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8, + 0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8, + 0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f, + 0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6, + 0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c, + 0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73, + 0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7, + 0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68, + 0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d, + 0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687, + 0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347 + // 0xb4a638ef, ... + //(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..) + // 256 32bit words for the mantissa -- about 2464 valid digits (decimal) + }; + + // above value was calculated using Big<1,400> type on a 32bit platform + // and then the first 256 32bit words were taken, + // the calculating was made by using LnSurrounding1(10) method + // which took 22080 iterations + // (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html) + // (the formula used in LnSurrounding1(x) converges badly when + // the x is greater than one but in fact we can use it, only the + // number of iterations will be greater) + // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, + // and on 64bit platform value 128 (256/2=128)) + + mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); + exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; + info = 0; + } + + + /*! + this method sets the maximum value which can be held in this type + */ + void SetMax() + { + info = 0; + mantissa.SetMax(); + exponent.SetMax(); + + // we don't have to use 'Standardizing()' because the last bit from + // the mantissa is set + } + + + /*! + this method sets the minimum value which can be held in this type + */ + void SetMin() + { + info = 0; + + mantissa.SetMax(); + exponent.SetMax(); + SetSign(); + + // we don't have to use 'Standardizing()' because the last bit from + // the mantissa is set + } + + + /*! + testing whether there is a value zero or not + */ + bool IsZero() const + { + return IsInfoBit(TTMATH_BIG_ZERO); + } + + + /*! + this method returns true when there's the sign set + also we don't check the NaN flag + */ + bool IsSign() const + { + return IsInfoBit(TTMATH_BIG_SIGN); + } + + + /*! + this method returns true when there is not a valid number + */ + bool IsNan() const + { + return IsInfoBit(TTMATH_BIG_NAN); + } + + + + /*! + this method clears the sign + (there'll be an absolute value) + + e.g. + -1 -> 1 + 2 -> 2 + */ + void Abs() + { + ClearInfoBit(TTMATH_BIG_SIGN); + } + + + /*! + this method remains the 'sign' of the value + e.g. -2 = -1 + 0 = 0 + 10 = 1 + */ + void Sgn() + { + // we have to check the NaN flag, because the next SetOne() method would clear it + if( IsNan() ) + return; + + if( IsSign() ) + { + SetOne(); + SetSign(); + } + else + if( IsZero() ) + SetZero(); + else + SetOne(); + } + + + + /*! + this method sets the sign + + e.g. + -1 -> -1 + 2 -> -2 + + we do not check whether there is a zero or not, if you're using this method + you must be sure that the value is (or will be afterwards) different from zero + */ + void SetSign() + { + SetInfoBit(TTMATH_BIG_SIGN); + } + + + /*! + this method changes the sign + when there is a value of zero then the sign is not changed + + e.g. + -1 -> 1 + 2 -> -2 + */ + void ChangeSign() + { + // we don't have to check the NaN flag here + + if( IsZero() ) + return; + + if( IsSign() ) + ClearInfoBit(TTMATH_BIG_SIGN); + else + SetInfoBit(TTMATH_BIG_SIGN); + } + + + +private: + + /*! + this method does the half-to-even rounding (banker's rounding) + + if is_half is: + true - that means the rest was equal the half (0.5 decimal) + false - that means the rest was greater than a half (greater than 0.5 decimal) + + if the rest was less than a half then don't call this method + (the rounding should does nothing then) + */ + uint RoundHalfToEven(bool is_half, bool rounding_up = true) + { + uint c = 0; + + if( !is_half || mantissa.IsTheLowestBitSet() ) + { + if( rounding_up ) + { + if( mantissa.AddOne() ) + { + mantissa.Rcr(1, 1); + c = exponent.AddOne(); + } + } + else + { + #ifdef TTMATH_DEBUG + uint c_from_zero = + #endif + mantissa.SubOne(); + + // we're using rounding_up=false in Add() when the mantissas have different signs + // mantissa can be zero only when previous mantissa was equal to ss2.mantissa + // but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false + TTMATH_ASSERT( c_from_zero == 0 ) + } + } + + return c; + } + + + + + + /*! + * + * basic mathematic functions + * + */ + +private: + + + /*! + an auxiliary method for adding + */ + void AddCheckExponents( Big & ss2, + Int & exp_offset, + bool & last_bit_set, + bool & rest_zero, + bool & do_adding, + bool & do_rounding) + { + Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); + + if( exp_offset == mantissa_size_in_bits ) + { + last_bit_set = ss2.mantissa.IsTheHighestBitSet(); + rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1); + do_rounding = true; // we'are only rounding + } + else + if( exp_offset < mantissa_size_in_bits ) + { + uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa + rest_zero = true; + + if( moved > 0 ) + { + last_bit_set = static_cast( ss2.mantissa.GetBit(moved-1) ); + + if( moved > 1 ) + rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1); + + // (2) moving 'exp_offset' times + ss2.mantissa.Rcr(moved, 0); + } + + do_adding = true; + do_rounding = true; + } + + // if exp_offset is greater than mantissa_size_in_bits then we do nothing + // ss2 is too small for taking into consideration in the sum + } + + + /*! + an auxiliary method for adding + */ + uint AddMantissas( Big & ss2, + bool & last_bit_set, + bool & rest_zero, + bool & rounding_up) + { + uint c = 0; + + if( IsSign() == ss2.IsSign() ) + { + // values have the same signs + if( mantissa.Add(ss2.mantissa) ) + { + // we have one bit more from addition (carry) + // now rest_zero means the old rest_zero with the old last_bit_set + rest_zero = (!last_bit_set && rest_zero); + last_bit_set = mantissa.Rcr(1,1); + c += exponent.AddOne(); + } + + rounding_up = true; + } + else + { + // values have different signs + // there shouldn't be a carry here because + // (1) (2) guarantee that the mantissa of this + // is greater than or equal to the mantissa of the ss2 + + #ifdef TTMATH_DEBUG + uint c_temp = + #endif + mantissa.Sub(ss2.mantissa); + + TTMATH_ASSERT( c_temp == 0 ) + } + + return c; + } + + +public: + + + /*! + Addition this = this + ss2 + + it returns carry if the sum is too big + */ + uint Add(Big ss2, bool round = true) + { + bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up; + Int exp_offset( exponent ); + uint c = 0; + + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + exp_offset.Sub( ss2.exponent ); + exp_offset.Abs(); + + // (1) abs(this) will be >= abs(ss2) + if( SmallerWithoutSignThan(ss2) ) + { + // !! use Swap here (not implemented yet) + Big temp(ss2); + + ss2 = *this; + *this = temp; + } + + if( ss2.IsZero() ) + return 0; + + last_bit_set = rest_zero = do_adding = do_rounding = rounding_up = false; + AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding); + + if( do_adding ) + c += AddMantissas(ss2, last_bit_set, rest_zero, rounding_up); + + if( !round || !last_bit_set ) + do_rounding = false; + + if( do_rounding ) + c += RoundHalfToEven(rest_zero, rounding_up); + + if( do_adding || do_rounding ) + c += Standardizing(); + + return CheckCarry(c); + } + + + + /*! + Subtraction this = this - ss2 + + it returns carry if the result is too big + */ + uint Sub(Big ss2, bool round = true) + { + ss2.ChangeSign(); + + return Add(ss2, round); + } + + + /*! + bitwise AND + + this and ss2 must be >= 0 + return values: + 0 - ok + 1 - carry + 2 - this or ss2 was negative + */ + uint BitAnd(Big ss2) + { + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + if( IsSign() || ss2.IsSign() ) + return 2; + + if( IsZero() ) + return 0; + + if( ss2.IsZero() ) + { + SetZero(); + return 0; + } + + Int exp_offset( exponent ); + Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); + + uint c = 0; + + exp_offset.Sub( ss2.exponent ); + exp_offset.Abs(); + + // abs(this) will be >= abs(ss2) + if( SmallerWithoutSignThan(ss2) ) + { + Big temp(ss2); + + ss2 = *this; + *this = temp; + } + + if( exp_offset >= mantissa_size_in_bits ) + { + // the second value is too small + SetZero(); + return 0; + } + + // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times + ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); + mantissa.BitAnd(ss2.mantissa); + + c += Standardizing(); + + return CheckCarry(c); + } + + + /*! + bitwise OR + + this and ss2 must be >= 0 + return values: + 0 - ok + 1 - carry + 2 - this or ss2 was negative + */ + uint BitOr(Big ss2) + { + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + if( IsSign() || ss2.IsSign() ) + return 2; + + if( IsZero() ) + { + *this = ss2; + return 0; + } + + if( ss2.IsZero() ) + return 0; + + Int exp_offset( exponent ); + Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); + + uint c = 0; + + exp_offset.Sub( ss2.exponent ); + exp_offset.Abs(); + + // abs(this) will be >= abs(ss2) + if( SmallerWithoutSignThan(ss2) ) + { + Big temp(ss2); + + ss2 = *this; + *this = temp; + } + + if( exp_offset >= mantissa_size_in_bits ) + // the second value is too small + return 0; + + // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times + ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); + mantissa.BitOr(ss2.mantissa); + + c += Standardizing(); + + return CheckCarry(c); + } + + + /*! + bitwise XOR + + this and ss2 must be >= 0 + return values: + 0 - ok + 1 - carry + 2 - this or ss2 was negative + */ + uint BitXor(Big ss2) + { + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + if( IsSign() || ss2.IsSign() ) + return 2; + + if( ss2.IsZero() ) + return 0; + + if( IsZero() ) + { + *this = ss2; + return 0; + } + + Int exp_offset( exponent ); + Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); + + uint c = 0; + + exp_offset.Sub( ss2.exponent ); + exp_offset.Abs(); + + // abs(this) will be >= abs(ss2) + if( SmallerWithoutSignThan(ss2) ) + { + Big temp(ss2); + + ss2 = *this; + *this = temp; + } + + if( exp_offset >= mantissa_size_in_bits ) + // the second value is too small + return 0; + + // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times + ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); + mantissa.BitXor(ss2.mantissa); + + c += Standardizing(); + + return CheckCarry(c); + } + + + + /*! + Multiplication this = this * ss2 (ss2 is uint) + + ss2 without a sign + */ + uint MulUInt(uint ss2) + { + UInt man_result; + uint i,c = 0; + + if( IsNan() ) + return 1; + + if( IsZero() ) + return 0; + + if( ss2 == 0 ) + { + SetZero(); + return 0; + } + + // man_result = mantissa * ss2.mantissa + mantissa.MulInt(ss2, man_result); + + sint bit = UInt::FindLeadingBitInWord(man_result.table[man]); // man - last word + + if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) ) + { + // 'i' will be from 0 to TTMATH_BITS_PER_UINT + i = man_result.CompensationToLeft(); + c = exponent.Add( TTMATH_BITS_PER_UINT - i ); + + for(i=0 ; i0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 ) + + for(i=0 ; i & ss2, bool round = true) + { + TTMATH_REFERENCE_ASSERT( ss2 ) + + UInt man_result; + uint c = 0; + uint i; + + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + if( IsZero() ) + return 0; + + if( ss2.IsZero() ) + { + SetZero(); + return 0; + } + + // man_result = mantissa * ss2.mantissa + mantissa.MulBig(ss2.mantissa, man_result); + + // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT + // because mantissa and ss2.mantissa are standardized + // (the highest bit in man_result is set to 1 or + // if there is a zero value in man_result the method CompensationToLeft() + // returns 0 but we'll correct this at the end in Standardizing() method) + i = man_result.CompensationToLeft(); + uint exp_add = man * TTMATH_BITS_PER_UINT - i; + + if( exp_add ) + c += exponent.Add( exp_add ); + + c += exponent.Add( ss2.exponent ); + + for(i=0 ; i & ss2, bool round = true) + { + TTMATH_REFERENCE_ASSERT( ss2 ) + + UInt man1; + UInt man2; + uint i,c = 0; + + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + if( ss2.IsZero() ) + { + SetNan(); + return 2; + } + + if( IsZero() ) + return 0; + + for(i=0 ; i & ss2) + { + TTMATH_REFERENCE_ASSERT( ss2 ) + + uint c = 0; + + if( IsNan() || ss2.IsNan() ) + return CheckCarry(1); + + if( ss2.IsZero() ) + { + SetNan(); + return 2; + } + + if( !SmallerWithoutSignThan(ss2) ) + { + Big temp(*this); + + c = temp.Div(ss2); + temp.SkipFraction(); + c += temp.Mul(ss2); + c += Sub(temp); + + if( !SmallerWithoutSignThan( ss2 ) ) + c += 1; + } + + return CheckCarry(c); + } + + + + + /*! + power this = this ^ pow + (pow without a sign) + + binary algorithm (r-to-l) + + return values: + 0 - ok + 1 - carry + 2 - incorrect arguments (0^0) + */ + template + uint Pow(UInt pow) + { + if( IsNan() ) + return 1; + + if( IsZero() ) + { + if( pow.IsZero() ) + { + // we don't define zero^zero + SetNan(); + return 2; + } + + // 0^(+something) is zero + return 0; + } + + Big start(*this), start_temp; + Big result; + result.SetOne(); + uint c = 0; + + while( !c ) + { + if( pow.table[0] & 1 ) + c += result.Mul(start); + + pow.Rcr(1); + + if( pow.IsZero() ) + break; + + start_temp = start; + c += start.Mul(start_temp); + } + + *this = result; + + return CheckCarry(c); + } + + + /*! + power this = this ^ pow + p can be negative + + return values: + 0 - ok + 1 - carry + 2 - incorrect arguments 0^0 or 0^(-something) + */ + template + uint Pow(Int pow) + { + if( IsNan() ) + return 1; + + if( !pow.IsSign() ) + return Pow( UInt(pow) ); + + if( IsZero() ) + { + // if 'p' is negative then + // 'this' must be different from zero + SetNan(); + return 2; + } + + uint c = pow.ChangeSign(); + + Big t(*this); + c += t.Pow( UInt(pow) ); // here can only be a carry (return:1) + + SetOne(); + c += Div(t); + + return CheckCarry(c); + } + + + /*! + this method returns: 'this' mod 2 + (either zero or one) + + this method is much faster than using Mod( object_with_value_two ) + */ + uint Mod2() const + { + if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) ) + return 0; + + sint exp_int = exponent.ToInt(); + // 'exp_int' is negative (or zero), we set it as positive + exp_int = -exp_int; + + return mantissa.GetBit(exp_int); + } + + + + /*! + power this = this ^ abs([pow]) + pow is treated as a value without a sign and without a fraction + if pow has a sign then the method pow.Abs() is used + if pow has a fraction the fraction is skipped (not used in calculation) + + return values: + 0 - ok + 1 - carry + 2 - incorrect arguments (0^0) + */ + uint PowUInt(Big pow) + { + if( IsNan() || pow.IsNan() ) + return CheckCarry(1); + + if( IsZero() ) + { + if( pow.IsZero() ) + { + SetNan(); + return 2; + } + + // 0^(+something) is zero + return 0; + } + + if( pow.IsSign() ) + pow.Abs(); + + Big start(*this), start_temp; + Big result; + Big one; + Int e_one; + uint c = 0; + + e_one.SetOne(); + one.SetOne(); + result = one; + + while( !c ) + { + if( pow.Mod2() ) + c += result.Mul(start); + + c += pow.exponent.Sub( e_one ); // !! may use SubOne() here? + + if( pow < one ) + break; + + start_temp = start; + c += start.Mul(start_temp); + } + + *this = result; + + return CheckCarry(c); + } + + + /*! + power this = this ^ [pow] + pow is treated as a value without a fraction + pow can be negative + + return values: + 0 - ok + 1 - carry + 2 - incorrect arguments 0^0 or 0^(-something) + */ + uint PowInt(const Big & pow) + { + TTMATH_REFERENCE_ASSERT( pow ) + + if( IsNan() || pow.IsNan() ) + return CheckCarry(1); + + if( !pow.IsSign() ) + return PowUInt(pow); + + if( IsZero() ) + { + // if 'pow' is negative then + // 'this' must be different from zero + SetNan(); + return 2; + } + + Big temp(*this); + uint c = temp.PowUInt(pow); // here can only be a carry (result:1) + + SetOne(); + c += Div(temp); + + return CheckCarry(c); + } + + + /*! + power this = this ^ pow + this must be greater than zero (this > 0) + pow can be negative and with fraction + + return values: + 0 - ok + 1 - carry + 2 - incorrect argument ('this' <= 0) + */ + uint PowFrac(const Big & pow) + { + TTMATH_REFERENCE_ASSERT( pow ) + + if( IsNan() || pow.IsNan() ) + return CheckCarry(1); + + Big temp; + uint c = temp.Ln(*this); + + if( c != 0 ) // can be 2 from Ln() + { + SetNan(); + return c; + } + + c += temp.Mul(pow); + c += Exp(temp); + + return CheckCarry(c); + } + + + + /*! + power this = this ^ pow + pow can be negative and with fraction + + return values: + 0 - ok + 1 - carry + 2 - incorrect argument ('this' or 'pow') + */ + uint Pow(const Big & pow) + { + TTMATH_REFERENCE_ASSERT( pow ) + + if( IsNan() || pow.IsNan() ) + return CheckCarry(1); + + if( IsZero() ) + { + // 0^pow will be 0 only for pow>0 + if( pow.IsSign() || pow.IsZero() ) + { + SetNan(); + return 2; + } + + SetZero(); + + return 0; + } + + if( pow.exponent>-int(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 ) + { + if( pow.IsInteger() ) + return PowInt( pow ); + } + + return PowFrac(pow); + } + + + /*! + this function calculates the square root + e.g. let this=9 then this.Sqrt() gives 3 + + return: 0 - ok + 1 - carry + 2 - improper argument (this<0 or NaN) + */ + uint Sqrt() + { + if( IsNan() || IsSign() ) + { + SetNan(); + return 2; + } + + if( IsZero() ) + return 0; + + Big old(*this); + Big ln; + uint c = 0; + + // we're using the formula: sqrt(x) = e ^ (ln(x) / 2) + c += ln.Ln(*this); + c += ln.exponent.SubOne(); // ln = ln / 2 + c += Exp(ln); + + // above formula doesn't give accurate results for some integers + // e.g. Sqrt(81) would not be 9 but a value very closed to 9 + // we're rounding the result, calculating result*result and comparing + // with the old value, if they are equal then the result is an integer too + + if( !c && old.IsInteger() && !IsInteger() ) + { + Big temp(*this); + c += temp.Round(); + + Big temp2(temp); + c += temp.Mul(temp2); + + if( temp == old ) + *this = temp2; + } + + return CheckCarry(c); + } + + +private: + +#ifdef TTMATH_CONSTANTSGENERATOR +public: +#endif + + /*! + Exponent this = exp(x) = e^x where x is in (-1,1) + + we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ... + */ + void ExpSurrounding0(const Big & x, uint * steps = 0) + { + TTMATH_REFERENCE_ASSERT( x ) + + Big denominator, denominator_i; + Big one, old_value, next_part; + Big numerator = x; + + SetOne(); + one.SetOne(); + denominator.SetOne(); + denominator_i.SetOne(); + + uint i; + old_value = *this; + + // we begin from 1 in order to not test at the beginning + #ifdef TTMATH_CONSTANTSGENERATOR + for(i=1 ; true ; ++i) + #else + for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) + #endif + { + bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' + + next_part = numerator; + + if( next_part.Div( denominator ) ) + // if there is a carry here we only break the loop + // however the result we return as good + // it means there are too many parts of the formula + break; + + // there shouldn't be a carry here + Add( next_part ); + + if( testing ) + { + if( old_value == *this ) + // we've added next few parts of the formula but the result + // is still the same then we break the loop + break; + else + old_value = *this; + } + + // we set the denominator and the numerator for a next part of the formula + if( denominator_i.Add(one) ) + // if there is a carry here the result we return as good + break; + + if( denominator.Mul(denominator_i) ) + break; + + if( numerator.Mul(x) ) + break; + } + + if( steps ) + *steps = i; + } + +public: + + + /*! + Exponent this = exp(x) = e^x + + we're using the fact that our value is stored in form of: + x = mantissa * 2^exponent + then + e^x = e^(mantissa* 2^exponent) or + e^x = (e^mantissa)^(2^exponent) + + 'Exp' returns a carry if we can't count the result ('x' is too big) + */ + uint Exp(const Big & x) + { + uint c = 0; + + if( x.IsNan() ) + return CheckCarry(1); + + if( x.IsZero() ) + { + SetOne(); + return 0; + } + + // m will be the value of the mantissa in range (-1,1) + Big m(x); + m.exponent = -sint(man*TTMATH_BITS_PER_UINT); + + // 'e_' will be the value of '2^exponent' + // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and + // e_.exponent.Add(1) mean: + // e_.mantissa.table[0] = 1; + // e_.Standardizing(); + // e_.exponent.Add(man*TTMATH_BITS_PER_UINT) + // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa) + Big e_(x); + e_.mantissa.SetZero(); + e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; + c += e_.exponent.Add(1); + e_.Abs(); + + /* + now we've got: + m - the value of the mantissa in range (-1,1) + e_ - 2^exponent + + e_ can be as: + ...2^-2, 2^-1, 2^0, 2^1, 2^2 ... + ...1/4 , 1/2 , 1 , 2 , 4 ... + + above one e_ is integer + + if e_ is greater than 1 we calculate the exponent as: + e^(m * e_) = ExpSurrounding0(m) ^ e_ + and if e_ is smaller or equal one we calculate the exponent in this way: + e^(m * e_) = ExpSurrounding0(m* e_) + because if e_ is smaller or equal 1 then the product of m*e_ is smaller or equal m + */ + + if( e_ <= 1 ) + { + m.Mul(e_); + ExpSurrounding0(m); + } + else + { + ExpSurrounding0(m); + c += PowUInt(e_); + } + + return CheckCarry(c); + } + + + + +private: + +#ifdef TTMATH_CONSTANTSGENERATOR +public: +#endif + + /*! + Natural logarithm this = ln(x) where x in range <1,2) + + we're using the formula: + ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ] + */ + void LnSurrounding1(const Big & x, uint * steps = 0) + { + Big old_value, next_part, denominator, one, two, x1(x), x2(x); + + one.SetOne(); + + if( x == one ) + { + // LnSurrounding1(1) is 0 + SetZero(); + return; + } + + two = 2; + + x1.Sub(one); + x2.Add(one); + + x1.Div(x2); + x2 = x1; + x2.Mul(x1); + + denominator.SetOne(); + SetZero(); + + old_value = *this; + uint i; + + + #ifdef TTMATH_CONSTANTSGENERATOR + for(i=1 ; true ; ++i) + #else + // we begin from 1 in order to not test at the beginning + for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) + #endif + { + bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' + + next_part = x1; + + if( next_part.Div(denominator) ) + // if there is a carry here we only break the loop + // however the result we return as good + // it means there are too many parts of the formula + break; + + // there shouldn't be a carry here + Add(next_part); + + if( testing ) + { + if( old_value == *this ) + // we've added next (step_test) parts of the formula but the result + // is still the same then we break the loop + break; + else + old_value = *this; + } + + if( x1.Mul(x2) ) + // if there is a carry here the result we return as good + break; + + if( denominator.Add(two) ) + break; + } + + // this = this * 2 + // ( there can't be a carry here because we calculate the logarithm between <1,2) ) + exponent.AddOne(); + + if( steps ) + *steps = i; + } + + + + +public: + + + /*! + Natural logarithm this = ln(x) + (a logarithm with the base equal 'e') + + we're using the fact that our value is stored in form of: + x = mantissa * 2^exponent + then + ln(x) = ln (mantissa * 2^exponent) = ln (mantissa) + (exponent * ln (2)) + + the mantissa we'll show as a value from range <1,2) because the logarithm + is decreasing too fast when 'x' is going to 0 + + return values: + 0 - ok + 1 - overflow (carry) + 2 - incorrect argument (x<=0) + */ + uint Ln(const Big & x) + { + TTMATH_REFERENCE_ASSERT( x ) + + if( x.IsNan() ) + return CheckCarry(1); + + if( x.IsSign() || x.IsZero() ) + { + SetNan(); + return 2; + } + + // m will be the value of the mantissa in range <1,2) + Big m(x); + m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1); + + LnSurrounding1(m); + + Big exponent_temp; + exponent_temp.FromInt( x.exponent ); + + // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa + uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1); + + Big ln2; + ln2.SetLn2(); + c += exponent_temp.Mul(ln2); + c += Add(exponent_temp); + + return CheckCarry(c); + } + + + + /*! + Logarithm from 'x' with a 'base' + + we're using the formula: + Log(x) with 'base' = ln(x) / ln(base) + + return values: + 0 - ok + 1 - overflow + 2 - incorrect argument (x<=0) + 3 - incorrect base (a<=0 lub a=1) + */ + uint Log(const Big & x, const Big & base) + { + TTMATH_REFERENCE_ASSERT( base ) + TTMATH_REFERENCE_ASSERT( x ) + + if( x.IsNan() || base.IsNan() ) + return CheckCarry(1); + + if( x.IsSign() || x.IsZero() ) + { + SetNan(); + return 2; + } + + Big denominator;; + denominator.SetOne(); + + if( base.IsSign() || base.IsZero() || base==denominator ) + { + SetNan(); + return 3; + } + + if( x == denominator ) // (this is: if x == 1) + { + // log(1) is 0 + SetZero(); + return 0; + } + + // another error values we've tested at the beginning + // there can only be a carry + uint c = Ln(x); + + c += denominator.Ln(base); + c += Div(denominator); + + return CheckCarry(c); + } + + + + + /*! + * + * converting methods + * + */ + + + /*! + converting from another type of a Big object + */ + template + uint FromBig(const Big & another) + { + info = another.info; + + if( IsNan() ) + return 1; + + if( exponent.FromInt(another.exponent) ) + { + SetNan(); + return 1; + } + + uint man_len_min = (man < another_man)? man : another_man; + uint i; + uint c = 0; + + for( i = 0 ; i another_man )' and 'if( man < another_man )' and there'll be no such situation here + #ifdef _MSC_VER + #pragma warning( disable: 4307 ) + #endif + + if( man > another_man ) + { + uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT; + c += exponent.SubInt(man_diff, 0); + } + else + if( man < another_man ) + { + uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT; + c += exponent.AddInt(man_diff, 0); + } + + #ifdef _MSC_VER + #pragma warning( default: 4307 ) + #endif + + // mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero) + CorrectZero(); + + return CheckCarry(c); + } + + + /*! + this method converts 'this' into 'result' + + if the value is too big this method returns a carry (1) + */ + uint ToUInt(uint & result, bool test_sign = true) const + { + result = 0; + + if( IsZero() ) + return 0; + + if( test_sign && IsSign() ) + // the result should be positive + return 1; + + sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); + + if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) ) + // if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed + // into the 'sint' type (it's too big) + return 1; + + if( exponent <= maxbit ) + // our value is from the range of (-1,1) and we return zero + return 0; + + UInt mantissa_temp(mantissa); + // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) > + sint how_many_bits = exponent.ToInt(); + + // how_many_bits is negative, we'll make it positive + how_many_bits = -how_many_bits; + + // we're taking into account only the last word in a mantissa table + mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); + result = mantissa_temp.table[ man-1 ]; + + return 0; + } + + + + /*! + this method converts 'this' into 'result' + + if the value is too big this method returns a carry (1) + */ + uint ToInt(sint & result) const + { + result = 0; + uint result_uint; + + if( ToUInt(result_uint, false) ) + return 1; + + result = static_cast( result_uint ); + + // the exception for the minimal value + if( IsSign() && result_uint == TTMATH_UINT_HIGHEST_BIT ) + return 0; + + if( (result_uint & TTMATH_UINT_HIGHEST_BIT) != 0 ) + // the value is too big + return 1; + + if( IsSign() ) + result = -result; + + return 0; + } + + + /*! + this method converts 'this' into 'result' + + if the value is too big this method returns a carry (1) + */ + template + uint ToInt(Int & result) const + { + result.SetZero(); + + if( IsZero() ) + return 0; + + sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); + + if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) ) + // if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed + // into the 'Int' type (it's too big) + return 1; + + if( exponent <= maxbit ) + // our value is from range (-1,1) and we return zero + return 0; + + sint how_many_bits = exponent.ToInt(); + + if( how_many_bits < 0 ) + { + how_many_bits = -how_many_bits; + uint index = how_many_bits / TTMATH_BITS_PER_UINT; + + UInt mantissa_temp(mantissa); + mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); + + for(uint i=index, a=0 ; i min; + min.SetMin(); + + if( result == min ) + return 0; + } + + if( (result.table[int_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0 ) + // the value is too big + return 1; + + if( IsSign() ) + result.ChangeSign(); + + return 0; + } + + + /*! + a method for converting 'uint' to this class + */ + void FromUInt(uint value) + { + info = 0; + + for(uint i=0 ; i> 20; + uint m1 = ((temp.u[1] & 0xFFFFFu) << 11) | (temp.u[0] >> 21); + uint m2 = temp.u[0] << 11; + + if( e == 2047 ) + { + // If E=2047 and F is nonzero, then V=NaN ("Not a number") + // If E=2047 and F is zero and S is 1, then V=-Infinity + // If E=2047 and F is zero and S is 0, then V=Infinity + + // we do not support -Infinity and +Infinity + // we assume that there is always NaN + + SetNan(); + } + else + if( e > 0 ) + { + // If 0 m; + m.table[1] = m1; + m.table[0] = m2; + uint moved = m.CompensationToLeft(); + + FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0, + e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0, + m.table[1], m.table[2]); + } + else + { + // If E=0 and F is zero and S is 1, then V=-0 + // If E=0 and F is zero and S is 0, then V=0 + + // we do not support -0 or 0, only is one 0 + SetZero(); + } + } + } + + +private: + + void FromDouble_SetExpAndMan(bool is_sign, int e, uint mhighest, uint m1, uint m2) + { + exponent = e; + + if( man > 1 ) + { + mantissa.table[man-1] = m1 | mhighest; + mantissa.table[sint(man-2)] = m2; + // although man>1 we're using casting into sint + // to get rid from a warning which generates Microsoft Visual: + // warning C4307: '*' : integral constant overflow + + for(uint i=0 ; i> 52; + uint m = (temp.u & 0xFFFFFFFFFFFFFul) << 11; + + if( e == 2047 ) + { + // If E=2047 and F is nonzero, then V=NaN ("Not a number") + // If E=2047 and F is zero and S is 1, then V=-Infinity + // If E=2047 and F is zero and S is 0, then V=Infinity + + // we do not support -Infinity and +Infinity + // we assume that there is always NaN + + SetNan(); + } + else + if( e > 0 ) + { + // If 0= 1024 - e_correction ) + { + // +/- infinity + result = ToDouble_SetDouble( 0, 2047, 0, true); + + return 1; + } + else + if( exponent <= -1023 - 52 - e_correction ) + { + // too small value - we assume that there'll be a zero + result = 0; + + // and return a carry + return 1; + } + + sint e = exponent.ToInt() + e_correction; + + if( e <= -1023 ) + { + // -1023-52 < e <= -1023 (unnormalized value) + result = ToDouble_SetDouble( IsSign(), 0, -(e + 1023)); + } + else + { + // -1023 < e < 1024 + result = ToDouble_SetDouble( IsSign(), e + 1023, -1); + } + + return 0; + } + +private: + +#ifdef TTMATH_PLATFORM32 + + // 32bit platforms + double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const + { + union + { + double d; + uint u[2]; // two 32bit words + } temp; + + temp.u[0] = temp.u[1] = 0; + + if( is_sign ) + temp.u[1] |= 0x80000000u; + + temp.u[1] |= (e << 20) & 0x7FF00000u; + + if( nan ) + { + temp.u[0] |= 1; + return temp.d; + } + + if( infinity ) + return temp.d; + + UInt<2> m; + m.table[1] = mantissa.table[man-1]; + m.table[0] = ( man > 1 ) ? mantissa.table[sint(man-2)] : 0; + // although man>1 we're using casting into sint + // to get rid from a warning which generates Microsoft Visual: + // warning C4307: '*' : integral constant overflow + + m.Rcr( 12 + move ); + m.table[1] &= 0xFFFFFu; // cutting the 20 bit (when 'move' was -1) + + temp.u[1] |= m.table[1]; + temp.u[0] |= m.table[0]; + + return temp.d; + } + +#else + + // 64bit platforms + double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const + { + union + { + double d; + uint u; // 64bit word + } temp; + + temp.u = 0; + + if( is_sign ) + temp.u |= 0x8000000000000000ul; + + temp.u |= (e << 52) & 0x7FF0000000000000ul; + + if( nan ) + { + temp.u |= 1; + return temp.d; + } + + if( infinity ) + return temp.d; + + uint m = mantissa.table[man-1]; + + m >>= ( 12 + move ); + m &= 0xFFFFFFFFFFFFFul; // cutting the 20 bit (when 'move' was -1) + temp.u |= m; + + return temp.d; + } + +#endif + + +public: + + + /*! + an operator= for converting 'sint' to this class + */ + Big & operator=(sint value) + { + FromInt(value); + + return *this; + } + + + /*! + an operator= for converting 'uint' to this class + */ + Big & operator=(uint value) + { + FromUInt(value); + + return *this; + } + + + /*! + an operator= for converting 'double' to this class + */ + Big & operator=(double value) + { + FromDouble(value); + + return *this; + } + + + /*! + a constructor for converting 'sint' to this class + */ + Big(sint value) + { + FromInt(value); + } + + /*! + a constructor for converting 'uint' to this class + */ + Big(uint value) + { + FromUInt(value); + } + + + /*! + a constructor for converting 'double' to this class + */ + Big(double value) + { + FromDouble(value); + } + + +#ifdef TTMATH_PLATFORM64 + + /*! + in 64bit platforms we must define additional operators and contructors + in order to allow a user initializing the objects in this way: + Big<...> type = 20; + or + Big<...> type; + type = 30; + + decimal constants such as 20, 30 etc. are integer literal of type int, + if the value is greater it can even be long int, + 0 is an octal integer of type int + (ISO 14882 p2.13.1 Integer literals) + */ + + /*! + an operator= for converting 'signed int' to this class + ***this operator is created only on a 64bit platform*** + it takes one argument of 32bit + + + */ + Big & operator=(signed int value) + { + FromInt(sint(value)); + + return *this; + } + + + /*! + an operator= for converting 'unsigned int' to this class + ***this operator is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Big & operator=(unsigned int value) + { + FromUInt(uint(value)); + + return *this; + } + + + /*! + a constructor for converting 'signed int' to this class + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Big(signed int value) + { + FromInt(sint(value)); + } + + /*! + a constructor for converting 'unsigned int' to this class + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Big(unsigned int value) + { + FromUInt(uint(value)); + } + +#endif + +private: + + /*! + an auxiliary method for converting from UInt and Int + + we assume that there'll never be a carry here + (we have an exponent and the value in Big can be bigger than + that one from the UInt) + */ + template + void FromUIntOrInt(const UInt & value, sint compensation) + { + uint minimum_size = (int_size < man)? int_size : man; + exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation; + + // copying the highest words + uint i; + for(i=1 ; i<=minimum_size ; ++i) + mantissa.table[man-i] = value.table[int_size-i]; + + // setting the rest of mantissa.table into zero (if some has left) + for( ; i<=man ; ++i) + mantissa.table[man-i] = 0; + + // the highest bit is either one or zero (when the whole mantissa is zero) + // we can only call CorrectZero() + CorrectZero(); + } + + +public: + + + /*! + a method for converting from 'UInt' to this class + */ + template + void FromUInt(UInt value) + { + info = 0; + sint compensation = (sint)value.CompensationToLeft(); + + return FromUIntOrInt(value, compensation); + } + + + /*! + a method for converting from 'Int' to this class + */ + template + void FromInt(Int value) + { + info = 0; + bool is_sign = false; + + if( value.IsSign() ) + { + value.ChangeSign(); + is_sign = true; + } + + sint compensation = (sint)value.CompensationToLeft(); + FromUIntOrInt(value, compensation); + + if( is_sign ) + SetSign(); + } + + + /*! + an operator= for converting from 'Int' to this class + */ + template + Big & operator=(const Int & value) + { + FromInt(value); + + return *this; + } + + + /*! + a constructor for converting from 'Int' to this class + */ + template + Big(const Int & value) + { + FromInt(value); + } + + + /*! + an operator= for converting from 'UInt' to this class + */ + template + Big & operator=(const UInt & value) + { + FromUInt(value); + + return *this; + } + + + /*! + a constructor for converting from 'UInt' to this class + */ + template + Big(const UInt & value) + { + FromUInt(value); + } + + + /*! + an operator= for converting from 'Big' to this class + */ + template + Big & operator=(const Big & value) + { + FromBig(value); + + return *this; + } + + + /*! + a constructor for converting from 'Big' to this class + */ + template + Big(const Big & value) + { + FromBig(value); + } + + + /*! + a default constructor + + we don't set any of the members to zero + only NaN flag is set + */ + Big() + { + info = TTMATH_BIG_NAN; + + /* + we're directly setting 'info' (instead of calling SetNan()) + in order to get rid of a warning saying that 'info' is uninitialized + */ + } + + + /*! + a destructor + */ + ~Big() + { + } + + + /*! + the default assignment operator + */ + Big & operator=(const Big & value) + { + info = value.info; + exponent = value.exponent; + mantissa = value.mantissa; + + return *this; + } + + + /*! + a constructor for copying from another object of this class + */ + + Big(const Big & value) + { + operator=(value); + } + + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + + output: + return value: + 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value + 1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there + is somewhere an error in the library) + */ + uint ToString( std::string & result, + uint base = 10, + bool scient = false, + sint scient_from = 15, + sint round = -1, + bool trim_zeroes = true, + wchar_t comma = '.' ) const + { + Conv conv; + + conv.base = base; + conv.scient = scient; + conv.scient_from = scient_from; + conv.round = round; + conv.trim_zeroes = trim_zeroes; + conv.comma = static_cast(comma); + + return ToStringBase(result, conv); + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + uint ToString( std::wstring & result, + uint base = 10, + bool scient = false, + sint scient_from = 15, + sint round = -1, + bool trim_zeroes = true, + wchar_t comma = '.' ) const + { + Conv conv; + + conv.base = base; + conv.scient = scient; + conv.scient_from = scient_from; + conv.round = round; + conv.trim_zeroes = trim_zeroes; + conv.comma = static_cast(comma); + + return ToStringBase(result, conv); + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + uint ToString(std::string & result, const Conv & conv) const + { + return ToStringBase(result, conv); + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + uint ToString(std::wstring & result, const Conv & conv) const + { + return ToStringBase(result, conv); + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + std::string ToString(const Conv & conv) const + { + std::string result; + ToStringBase(result, conv); + + return result; + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + std::string ToString() const + { + Conv conv; + + return ToString(conv); + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + std::wstring ToWString(const Conv & conv) const + { + std::wstring result; + ToStringBase(result, conv); + + return result; + } + + + /*! + a method for converting into a string + struct Conv is defined in ttmathtypes.h, look there for more information about parameters + */ + std::wstring ToWString() const + { + Conv conv; + + return ToWString(conv); + } + + +private: + + + /*! + an auxiliary method for converting into the string + */ + template + uint ToStringBase(string_type & result, const Conv & conv) const + { + static char error_overflow_msg[] = "overflow"; + static char error_nan_msg[] = "NaN"; + result.erase(); + + if( IsNan() ) + { + Misc::AssignString(result, error_nan_msg); + return 0; + } + + if( conv.base<2 || conv.base>16 ) + { + Misc::AssignString(result, error_overflow_msg); + return 1; + } + + if( IsZero() ) + { + result = '0'; + + return 0; + } + + /* + since 'base' is greater or equal 2 that 'new_exp' of type 'Int' should + hold the new value of exponent but we're using 'Int' because + if the value for example would be 'max()' then we couldn't show it + + max() -> 11111111 * 2 ^ 11111111111 (bin)(the mantissa and exponent have all bits set) + if we were using 'Int' we couldn't show it in this format: + 1,1111111 * 2 ^ 11111111111 (bin) + because we have to add something to the mantissa and because + mantissa is full we can't do it and it'll be a carry + (look at ToString_SetCommaAndExponent(...)) + + when the base would be greater than two (for example 10) + we could use 'Int' here + */ + Int new_exp; + + if( ToString_CreateNewMantissaAndExponent(result, conv, new_exp) ) + { + Misc::AssignString(result, error_overflow_msg); + return 1; + } + + + if( ToString_SetCommaAndExponent(result, conv, new_exp) ) + { + Misc::AssignString(result, error_overflow_msg); + return 1; + } + + if( IsSign() ) + result.insert(result.begin(), '-'); + + + // converted successfully + return 0; + } + + + + /*! + in the method 'ToString_CreateNewMantissaAndExponent()' we're using + type 'Big' and we should have the ability to use some + necessary methods from that class (methods which are private here) + */ + friend class Big; + + + /*! + an auxiliary method for converting into the string + + input: + base - the base in range <2,16> + + output: + return values: + 0 - ok + 1 - if there was a carry + new_man - the new mantissa for 'base' + new_exp - the new exponent for 'base' + + mathematic part: + + the value is stored as: + value = mantissa * 2^exponent + we want to show 'value' as: + value = new_man * base^new_exp + + then 'new_man' we'll print using the standard method from UInt<> type for printing + and 'new_exp' is the offset of the comma operator in a system of a base 'base' + + value = mantissa * 2^exponent + value = mantissa * 2^exponent * (base^new_exp / base^new_exp) + value = mantissa * (2^exponent / base^new_exp) * base^new_exp + + look at the part (2^exponent / base^new_exp), there'll be good if we take + a 'new_exp' equal that value when the (2^exponent / base^new_exp) will be equal one + + on account of the 'base' is not as power of 2 (can be from 2 to 16), + this formula will not be true for integer 'new_exp' then in our case we take + 'base^new_exp' _greater_ than '2^exponent' + + if 'base^new_exp' were smaller than '2^exponent' the new mantissa could be + greater than the max value of the container UInt + + value = mantissa * (2^exponent / base^new_exp) * base^new_exp + let M = mantissa * (2^exponent / base^new_exp) then + value = M * base^new_exp + + in our calculation we treat M as floating value showing it as: + M = mm * 2^ee where ee will be <= 0 + + next we'll move all bits of mm into the right when ee is equal zero + abs(ee) must not be too big that only few bits from mm we can leave + + then we'll have: + M = mmm * 2^0 + 'mmm' is the new_man which we're looking for + + + new_exp we calculate in this way: + 2^exponent <= base^new_exp + new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent) + + but we need new_exp as integer then we test: + if new_exp is greater than zero and with fraction we add one to new_exp + new_exp = new_exp + 1 (if new_exp>0 and with fraction) + and at the end we take the integer part: + new_exp = int(new_exp) + */ + template + uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv, + Int & new_exp) const + { + uint c = 0; + + if( conv.base<2 || conv.base>16 ) + return 1; + + // the speciality for base equal 2 + if( conv.base == 2 ) + return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp); + + // the speciality for base equal 4 + if( conv.base == 4 ) + return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2); + + // the speciality for base equal 8 + if( conv.base == 8 ) + return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3); + + // the speciality for base equal 16 + if( conv.base == 16 ) + return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4); + + + // this = mantissa * 2^exponent + + // temp = +1 * 2^exponent + // we're using a bigger type than 'big' (look below) + Big temp; + temp.info = 0; + temp.exponent = exponent; + temp.mantissa.SetOne(); + c += temp.Standardizing(); + + // new_exp_ = log base (2^exponent) + // if new_exp_ is positive and with fraction then we add one + Big new_exp_; + c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated + + // adding some epsilon value (to get rid of some floating point errors) + temp.Set05(); + temp.exponent.SubOne(); // temp = 0.5/2 = 0.25 + c += new_exp_.Add(temp); + + if( !new_exp_.IsSign() && !new_exp_.IsInteger() ) + { + // new_exp_ > 0 and with fraction + temp.SetOne(); + c += new_exp_.Add( temp ); + } + + // new_exp_ = int(new_exp_) + new_exp_.SkipFraction(); + + + // because 'base^new_exp' is >= '2^exponent' then + // because base is >= 2 then we've got: + // 'new_exp_' must be smaller or equal 'new_exp' + // and we can pass it into the Int type + // (in fact we're using a greater type then it'll be ok) + c += new_exp_.ToInt(new_exp); + + // base_ = base + Big base_(conv.base); + + // base_ = base_ ^ new_exp_ + c += base_.Pow( new_exp_ ); + // if we hadn't used a bigger type than 'Big' then the result + // of this formula 'Pow(...)' would have been with an overflow + + // temp = mantissa * 2^exponent / base_^new_exp_ + // the sign don't interest us here + temp.mantissa = mantissa; + temp.exponent = exponent; + c += temp.Div(base_, false); // dividing without rounding + + // moving all bits of the mantissa into the right + // (how many times to move depend on the exponent) + c += temp.ToString_MoveMantissaIntoRight(); + + // because we took 'new_exp' as small as it was + // possible ([log base (2^exponent)] + 1) that after the division + // (temp.Div( base_ )) the value of exponent should be equal zero or + // minimum smaller than zero then we've got the mantissa which has + // maximum valid bits + temp.mantissa.ToString(new_man, conv.base); + + // base rounding + if( conv.base_round ) + c += ToString_BaseRound(new_man, conv, new_exp); + + return (c==0)? 0 : 1; + } + + + /*! + this method calculates the logarithm + it is used by ToString_CreateNewMantissaAndExponent() method + + it's not too complicated + because x=+1*2^exponent (mantissa is one) then during the calculation + the Ln(x) will not be making the long formula from LnSurrounding1() + and only we have to calculate 'Ln(base)' but it'll be calculated + only once, the next time we will get it from the 'history' + + x is greater than 0 + base is in <2,16> range + */ + uint ToString_Log(const Big & x, uint base) + { + TTMATH_REFERENCE_ASSERT( x ) + TTMATH_ASSERT( base>=2 && base<=16 ) + + Big temp; + temp.SetOne(); + + if( x == temp ) + { + // log(1) is 0 + SetZero(); + + return 0; + } + + // there can be only a carry + // because the 'x' is in '1+2*exponent' form then + // the long formula from LnSurrounding1() will not be calculated + // (LnSurrounding1() will return one immediately) + uint c = Ln(x); + + if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE ) + { + // for the base equal 10 we're using SelLn10() instead of calculating it + // (only if we have the constant sufficient big) + temp.SetLn10(); + } + else + { + c += ToString_LogBase(base, temp); + } + + c += Div( temp ); + + return (c==0)? 0 : 1; + } + + +#ifndef TTMATH_MULTITHREADS + + /*! + this method calculates the logarithm of 'base' + it's used in single thread environment + */ + uint ToString_LogBase(uint base, Big & result) + { + TTMATH_ASSERT( base>=2 && base<=16 ) + + // this guardians are initialized before the program runs (static POD types) + static int guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + static Big log_history[15]; + uint index = base - 2; + uint c = 0; + + if( guardians[index] == 0 ) + { + Big base_(base); + c += log_history[index].Ln(base_); + guardians[index] = 1; + } + + result = log_history[index]; + + return (c==0)? 0 : 1; + } + +#else + + /*! + this method calculates the logarithm of 'base' + it's used in multi-thread environment + */ + uint ToString_LogBase(uint base, Big & result) + { + TTMATH_ASSERT( base>=2 && base<=16 ) + + // this guardians are initialized before the program runs (static POD types) + volatile static sig_atomic_t guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + static Big * plog_history; + uint index = base - 2; + uint c = 0; + + // double-checked locking + if( guardians[index] == 0 ) + { + ThreadLock thread_lock; + + // locking + if( thread_lock.Lock() ) + { + static Big log_history[15]; + + if( guardians[index] == 0 ) + { + plog_history = log_history; + + Big base_(base); + c += log_history[index].Ln(base_); + guardians[index] = 1; + } + } + else + { + // there was a problem with locking, we store the result directly in 'result' object + Big base_(base); + c += result.Ln(base_); + + return (c==0)? 0 : 1; + } + + // automatically unlocking + } + + result = plog_history[index]; + + return (c==0)? 0 : 1; + } + +#endif + + /*! + an auxiliary method for converting into the string (private) + + this method moving all bits from mantissa into the right side + the exponent tell us how many times moving (the exponent is <=0) + */ + uint ToString_MoveMantissaIntoRight() + { + if( exponent.IsZero() ) + return 0; + + // exponent can't be greater than zero + // because we would cat the highest bits of the mantissa + if( !exponent.IsSign() ) + return 1; + + + if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) + // if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)' + // it means that we must cut the whole mantissa + // (there'll not be any of the valid bits) + return 1; + + // e will be from (-man*TTMATH_BITS_PER_UINT, 0> + sint e = -( exponent.ToInt() ); + mantissa.Rcr(e,0); + + return 0; + } + + + /*! + a special method similar to the 'ToString_CreateNewMantissaAndExponent' + when the 'base' is equal 2 + + we use it because if base is equal 2 we don't have to make those + complicated calculations and the output is directly from the source + (there will not be any small distortions) + */ + template + uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man, + Int & new_exp ) const + { + for( sint i=man-1 ; i>=0 ; --i ) + { + uint value = mantissa.table[i]; + + for( uint bit=0 ; bit + uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man, + Int & new_exp, + uint bits) const + { + sint move; // how many times move the mantissa + UInt man_temp(mantissa); // man+1 for moving + new_exp = exponent; + new_exp.DivInt((sint)bits, move); + + if( move != 0 ) + { + // we're moving the man_temp to left-hand side + if( move < 0 ) + { + move = sint(bits) + move; + new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too + } + + man_temp.Rcl(move); + } + + + if( bits == 3 ) + { + // base 8 + // now 'move' is greater than or equal 0 + uint len = man*TTMATH_BITS_PER_UINT + move; + return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits); + } + else + { + // base 4 or 16 + return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits); + } + } + + + /*! + a special method used to calculate the new mantissa + when the 'base' is equal 8 + + bits is always 3 + + we can use this algorithm when the base is 4 or 16 too + but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16() + */ + template + uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man, + UInt & man_temp, + uint len, + uint bits) const + { + uint shift = TTMATH_BITS_PER_UINT - bits; + uint mask = TTMATH_UINT_MAX_VALUE >> shift; + uint i; + + for( i=0 ; i(Misc::DigitToChar(digit))); + + man_temp.Rcr(bits); + } + + TTMATH_ASSERT( man_temp.IsZero() ) + + return 0; + } + + + /*! + a special method used to calculate the new mantissa + when the 'base' is equal 4 or 16 + + when the base is equal 4 or 16 the bits is 2 or 4 + and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4) + then we can get digits from the end of our mantissa + */ + template + uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man, + UInt & man_temp, + uint bits) const + { + TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 ) + TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 ) + + uint shift = TTMATH_BITS_PER_UINT - bits; + uint mask = TTMATH_UINT_MAX_VALUE << shift; + uint digit; + + // table[man] - last word - is different from zero if we moved man_temp + digit = man_temp.table[man]; + + if( digit != 0 ) + new_man += static_cast(Misc::DigitToChar(digit)); + + + for( int i=man-1 ; i>=0 ; --i ) + { + uint shift_local = shift; + uint mask_local = mask; + + while( mask_local != 0 ) + { + digit = man_temp.table[i] & mask_local; + + if( shift_local != 0 ) + digit = digit >> shift_local; + + new_man += static_cast(Misc::DigitToChar(digit)); + mask_local = mask_local >> bits; + shift_local = shift_local - bits; + } + } + + return 0; + } + + + /*! + an auxiliary method for converting into the string + */ + template + bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int & new_exp) const + { + // if new_exp is greater or equal to zero then we have an integer value, + // if new_exp is equal -1 then we have only one digit after the comma + // and after rounding it would be an integer value + if( !new_exp.IsSign() || new_exp == -1 ) + return true; + + if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 ) + return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding + + uint i = 0; + char_type digit; + + if( new_exp >= -sint(new_man.size()) ) + { + uint new_exp_abs = -new_exp.ToInt(); + i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator + } + + if( Misc::CharToDigit(new_man[new_man.size()-1]) >= conv.base/2 ) + { + if( new_exp < -sint(new_man.size()) ) + { + // there are some zeroes after the comma operator + // (between the comma and the first digit from the mantissa) + // and the result value will never be an integer + return false; + } + + digit = static_cast( Misc::DigitToChar(conv.base-1) ); + } + else + { + digit = '0'; + } + + for( ; i < new_man.size()-1 ; ++i) + if( new_man[i] != digit ) + return false; // it will not be an integer + + return true; // it will be integer after rounding + } + + + /*! + an auxiliary method for converting into the string + + this method is used for base!=2, base!=4, base!=8 and base!=16 + we do the rounding when the value has fraction (is not an integer) + */ + template + uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int & new_exp) const + { + // we must have minimum two characters + if( new_man.size() < 2 ) + return 0; + + // assert that there will not be an integer after rounding + if( ToString_RoundMantissaWouldBeInteger(new_man, conv, new_exp) ) + return 0; + + typename string_type::size_type i = new_man.length() - 1; + + // we're erasing the last character + uint digit = Misc::CharToDigit( new_man[i] ); + new_man.erase(i, 1); + uint c = new_exp.AddOne(); + + // if the last character is greater or equal 'base/2' + // we are adding one into the new mantissa + if( digit >= conv.base / 2 ) + ToString_RoundMantissa_AddOneIntoMantissa(new_man, conv); + + return c; + } + + + /*! + an auxiliary method for converting into the string + + this method addes one into the new mantissa + */ + template + void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const + { + if( new_man.empty() ) + return; + + sint i = sint( new_man.length() ) - 1; + bool was_carry = true; + + for( ; i>=0 && was_carry ; --i ) + { + // we can have the comma as well because + // we're using this method later in ToString_CorrectDigitsAfterComma_Round() + // (we're only ignoring it) + if( new_man[i] == static_cast(conv.comma) ) + continue; + + // we're adding one + uint digit = Misc::CharToDigit( new_man[i] ) + 1; + + if( digit == conv.base ) + digit = 0; + else + was_carry = false; + + new_man[i] = static_cast( Misc::DigitToChar(digit) ); + } + + if( i<0 && was_carry ) + new_man.insert( new_man.begin() , '1' ); + } + + + + /*! + an auxiliary method for converting into the string + + this method sets the comma operator and/or puts the exponent + into the string + */ + template + uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int & new_exp) const + { + uint carry = 0; + + if( new_man.empty() ) + return carry; + + Int scientific_exp( new_exp ); + + // 'new_exp' depends on the 'new_man' which is stored like this e.g: + // 32342343234 (the comma is at the end) + // we'd like to show it in this way: + // 3.2342343234 (the 'scientific_exp' is connected with this example) + + sint offset = sint( new_man.length() ) - 1; + carry += scientific_exp.Add( offset ); + // there shouldn't have been a carry because we're using + // a greater type -- 'Int' instead of 'Int' + + bool print_scientific = conv.scient; + + if( !print_scientific ) + { + if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) ) + print_scientific = true; + } + + if( !print_scientific ) + ToString_SetCommaAndExponent_Normal(new_man, conv, new_exp); + else + // we're passing the 'scientific_exp' instead of 'new_exp' here + ToString_SetCommaAndExponent_Scientific(new_man, conv, scientific_exp); + + return (carry==0)? 0 : 1; + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int & new_exp ) const + { + if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 ) + ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp); + else + ToString_SetCommaAndExponent_Normal_SetCommaInside(new_man, conv, new_exp); + + + ToString_Group_man(new_man, conv); + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man, + Int & new_exp) const + { + // we're adding zero characters at the end + // 'i' will be smaller than 'when_scientific' (or equal) + uint i = new_exp.ToInt(); + + if( new_man.length() + i > new_man.capacity() ) + // about 6 characters more (we'll need it for the comma or something) + new_man.reserve( new_man.length() + i + 6 ); + + for( ; i>0 ; --i) + new_man += '0'; + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_SetCommaAndExponent_Normal_SetCommaInside( + string_type & new_man, + const Conv & conv, + Int & new_exp ) const + { + // new_exp is < 0 + + sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign + sint e = -( new_exp.ToInt() ); // 'e' will be positive + + if( new_exp > -new_man_len ) + { + // we're setting the comma within the mantissa + + sint index = new_man_len - e; + new_man.insert( new_man.begin() + index, static_cast(conv.comma)); + } + else + { + // we're adding zero characters before the mantissa + + uint how_many = e - new_man_len; + string_type man_temp(how_many+1, '0'); + + man_temp.insert( man_temp.begin()+1, static_cast(conv.comma)); + new_man.insert(0, man_temp); + } + + ToString_CorrectDigitsAfterComma(new_man, conv); + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_SetCommaAndExponent_Scientific( string_type & new_man, + const Conv & conv, + Int & scientific_exp ) const + { + if( new_man.empty() ) + return; + + if( new_man.size() > 1 ) + { + new_man.insert( new_man.begin()+1, static_cast(conv.comma) ); + ToString_CorrectDigitsAfterComma(new_man, conv); + } + + ToString_Group_man(new_man, conv); + + if( conv.base == 10 ) + { + new_man += 'e'; + + if( !scientific_exp.IsSign() ) + new_man += '+'; + } + else + { + // the 10 here is meant as the base 'base' + // (no matter which 'base' we're using there'll always be 10 here) + Misc::AddString(new_man, "*10^"); + } + + string_type temp_exp; + scientific_exp.ToString( temp_exp, conv.base ); + + new_man += temp_exp; + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_Group_man(string_type & new_man, const Conv & conv) const + { + typedef typename string_type::size_type StrSize; + + if( conv.group == 0 ) + return; + + // first we're looking for the comma operator + StrSize index = new_man.find(static_cast(conv.comma), 0); + + if( index == string_type::npos ) + index = new_man.size(); + + ToString_Group_man_before_comma(new_man, conv, index); + ToString_Group_man_after_comma(new_man, conv, index+1); + } + + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv, + typename string_type::size_type & index) const + { + typedef typename string_type::size_type StrSize; + uint group = 0; + + StrSize i = index; + + // adding group characters before the comma operator + // i>0 because on the first position we don't put any additional grouping characters + for( ; i>0 ; --i, ++group) + { + if( group >= 3 ) + { + group = 0; + new_man.insert(i, 1, static_cast(conv.group)); + ++index; + } + } + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv, + typename string_type::size_type index) const + { + uint group = 0; + + for( ; index= 3 ) + { + group = 0; + new_man.insert(index, 1, static_cast(conv.group)); + ++index; + } + } + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_CorrectDigitsAfterComma( string_type & new_man, + const Conv & conv ) const + { + if( conv.round >= 0 ) + ToString_CorrectDigitsAfterComma_Round(new_man, conv); + + if( conv.trim_zeroes ) + ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(new_man, conv); + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( + string_type & new_man, + const Conv & conv) const + { + // minimum two characters + if( new_man.length() < 2 ) + return; + + // we're looking for the index of the last character which is not zero + uint i = uint( new_man.length() ) - 1; + for( ; i>0 && new_man[i]=='0' ; --i ); + + // if there is another character than zero at the end + // we're finishing + if( i == new_man.length() - 1 ) + return; + + // we must have a comma + // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round + // which is called before) + if( new_man.find_last_of(static_cast(conv.comma), i) == string_type::npos ) + return; + + // if directly before the first zero is the comma operator + // we're cutting it as well + if( i>0 && new_man[i]==static_cast(conv.comma) ) + --i; + + new_man.erase(i+1, new_man.length()-i-1); + } + + + /*! + an auxiliary method for converting into the string + */ + template + void ToString_CorrectDigitsAfterComma_Round( + string_type & new_man, + const Conv & conv ) const + { + typedef typename string_type::size_type StrSize; + + // first we're looking for the comma operator + StrSize index = new_man.find(static_cast(conv.comma), 0); + + if( index == string_type::npos ) + // nothing was found (actually there can't be this situation) + return; + + // we're calculating how many digits there are at the end (after the comma) + // 'after_comma' will be greater than zero because at the end + // we have at least one digit + StrSize after_comma = new_man.length() - index - 1; + + // if 'max_digit_after_comma' is greater than 'after_comma' (or equal) + // we don't have anything for cutting + if( static_cast(conv.round) >= after_comma ) + return; + + uint last_digit = Misc::CharToDigit( new_man[ index + conv.round + 1 ], conv.base ); + + // we're cutting the rest of the string + new_man.erase(index + conv.round + 1, after_comma - conv.round); + + if( conv.round == 0 ) + { + // we're cutting the comma operator as well + // (it's not needed now because we've cut the whole rest after the comma) + new_man.erase(index, 1); + } + + if( last_digit >= conv.base / 2 ) + // we must round here + ToString_RoundMantissa_AddOneIntoMantissa(new_man, conv); + } + + + +public: + + /*! + a method for converting a string into its value + + it returns 1 if the value is too big -- we cannot pass it into the range + of our class Big (or if the base is incorrect) + + that means only digits before the comma operator can make this value too big, + all digits after the comma we can ignore + + 'source' - pointer to the string for parsing + + if 'after_source' is set that when this method finishes + it sets the pointer to the new first character after parsed value + + 'value_read' - if the pointer is provided that means the value_read will be true + only when a value has been actually read, there can be situation where only such + a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but + no value has been read (there are no digits) + on other words if 'value_read' is true -- there is at least one digit in the string + */ + uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0) + { + Conv conv; + conv.base = base; + + return FromStringBase(source, conv, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + Conv conv; + conv.base = base; + + return FromStringBase(source, conv, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(source, conv, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(source, conv, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const std::string & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromString(string.c_str(), base, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromString(string.c_str(), base, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const std::string & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromString(string.c_str(), conv, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromString(string.c_str(), conv, after_source, value_read); + } + +private: + + + /*! + an auxiliary method for converting from a string + */ + template + uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0) + { + bool is_sign; + bool value_read_temp = false; + + if( conv.base<2 || conv.base>16 ) + { + SetNan(); + + if( after_source ) + *after_source = source; + + if( value_read ) + *value_read = value_read_temp; + + return 1; + } + + SetZero(); + FromString_TestSign( source, is_sign ); + + uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp ); + + if( FromString_TestCommaOperator(source, conv) ) + c += FromString_ReadPartAfterComma( source, conv, value_read_temp ); + + if( value_read_temp && conv.base == 10 ) + c += FromString_ReadScientificIfExists( source ); + + if( is_sign && !IsZero() ) + ChangeSign(); + + if( after_source ) + *after_source = source; + + if( value_read ) + *value_read = value_read_temp; + + return CheckCarry(c); + } + + + /*! + we're testing whether the value is with the sign + + (this method is used from 'FromString_ReadPartScientific' too) + */ + template + void FromString_TestSign( const char_type * & source, bool & is_sign ) + { + Misc::SkipWhiteCharacters(source); + + is_sign = false; + + if( *source == '-' ) + { + is_sign = true; + ++source; + } + else + if( *source == '+' ) + { + ++source; + } + } + + + /*! + we're testing whether there's a comma operator + */ + template + bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv) + { + if( (*source == static_cast(conv.comma)) || + (*source == static_cast(conv.comma2) && conv.comma2 != 0 ) ) + { + ++source; + + return true; + } + + return false; + } + + + /*! + this method reads the first part of a string + (before the comma operator) + */ + template + uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read ) + { + sint character; + Big temp; + Big base_( conv.base ); + + Misc::SkipWhiteCharacters( source ); + + for( ; true ; ++source ) + { + if( conv.group!=0 && *source==static_cast(conv.group) ) + continue; + + character = Misc::CharToDigit(*source, conv.base); + + if( character == -1 ) + break; + + value_read = true; + temp = character; + + if( Mul(base_) ) + return 1; + + if( Add(temp) ) + return 1; + } + + return 0; + } + + + /*! + this method reads the second part of a string + (after the comma operator) + */ + template + uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read ) + { + sint character; + uint c = 0, index = 1; + Big sum, part, power, old_value, base_( conv.base ); + + // we don't remove any white characters here + + // this is only to avoid getting a warning about an uninitialized object 'old_value' which GCC reports + // (in fact we will initialize it later when the condition 'testing' is fulfilled) + old_value.SetZero(); + + power.SetOne(); + sum.SetZero(); + + for( ; true ; ++source, ++index ) + { + if( conv.group!=0 && *source==static_cast(conv.group) ) + continue; + + character = Misc::CharToDigit(*source, conv.base); + + if( character == -1 ) + break; + + value_read = true; + + part = character; + + if( power.Mul( base_ ) ) + // there's no sens to add the next parts, but we can't report this + // as an error (this is only inaccuracy) + break; + + if( part.Div( power ) ) + break; + + // every 5 iteration we make a test whether the value will be changed or not + // (character must be different from zero to this test) + bool testing = (character != 0 && (index % 5) == 0); + + if( testing ) + old_value = sum; + + // there actually shouldn't be a carry here + c += sum.Add( part ); + + if( testing && old_value == sum ) + // after adding 'part' the value has not been changed + // there's no sense to add any next parts + break; + } + + // we could break the parsing somewhere in the middle of the string, + // but the result (value) still can be good + // we should set a correct value of 'source' now + for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source ); + + c += Add(sum); + + return (c==0)? 0 : 1; + } + + + /*! + this method checks whether there is a scientific part: [e|E][-|+]value + + it is called when the base is 10 and some digits were read before + */ + template + uint FromString_ReadScientificIfExists(const char_type * & source) + { + uint c = 0; + + bool scientific_read = false; + const char_type * before_scientific = source; + + if( FromString_TestScientific(source) ) + c += FromString_ReadPartScientific( source, scientific_read ); + + if( !scientific_read ) + source = before_scientific; + + return (c==0)? 0 : 1; + } + + + + /*! + we're testing whether is there the character 'e' + + this character is only allowed when we're using the base equals 10 + */ + template + bool FromString_TestScientific(const char_type * & source) + { + Misc::SkipWhiteCharacters(source); + + if( *source=='e' || *source=='E' ) + { + ++source; + + return true; + } + + return false; + } + + + /*! + this method reads the exponent (after 'e' character) when there's a scientific + format of value and only when we're using the base equals 10 + */ + template + uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read ) + { + uint c = 0; + Big new_exponent, temp; + bool was_sign = false; + + FromString_TestSign( source, was_sign ); + c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read ); + + if( scientific_read ) + { + if( was_sign ) + new_exponent.ChangeSign(); + + temp = 10; + c += temp.Pow( new_exponent ); + c += Mul(temp); + } + + return (c==0)? 0 : 1; + } + + + /*! + this method reads the value of the extra exponent when scientific format is used + (only when base == 10) + */ + template + uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big & new_exponent, bool & scientific_read ) + { + sint character; + Big base, temp; + + Misc::SkipWhiteCharacters(source); + + new_exponent.SetZero(); + base = 10; + + for( ; (character=Misc::CharToDigit(*source, 10)) != -1 ; ++source ) + { + scientific_read = true; + + temp = character; + + if( new_exponent.Mul(base) ) + return 1; + + if( new_exponent.Add(temp) ) + return 1; + } + + return 0; + } + + +public: + + + /*! + a constructor for converting a string into this class + */ + Big(const char * string) + { + FromString( string ); + } + + + /*! + a constructor for converting a string into this class + */ + Big(const wchar_t * string) + { + FromString( string ); + } + + + /*! + a constructor for converting a string into this class + */ + Big(const std::string & string) + { + FromString( string.c_str() ); + } + + + /*! + a constructor for converting a string into this class + */ + Big(const std::wstring & string) + { + FromString( string.c_str() ); + } + + + /*! + an operator= for converting a string into its value + */ + Big & operator=(const char * string) + { + FromString( string ); + + return *this; + } + + + /*! + an operator= for converting a string into its value + */ + Big & operator=(const wchar_t * string) + { + FromString( string ); + + return *this; + } + + + /*! + an operator= for converting a string into its value + */ + Big & operator=(const std::string & string) + { + FromString( string.c_str() ); + + return *this; + } + + + /*! + an operator= for converting a string into its value + */ + Big & operator=(const std::wstring & string) + { + FromString( string.c_str() ); + + return *this; + } + + + + /*! + * + * methods for comparing + * + */ + + + /*! + this method performs the formula 'abs(this) < abs(ss2)' + and returns the result + + (in other words it treats 'this' and 'ss2' as values without a sign) + we don't check the NaN flag + */ + bool SmallerWithoutSignThan(const Big & ss2) const + { + if( IsZero() ) + { + if( ss2.IsZero() ) + // we've got two zeroes + return false; + else + // this==0 and ss2!=0 + return true; + } + + if( ss2.IsZero() ) + // this!=0 and ss2==0 + return false; + + // we're using the fact that all bits in mantissa are pushed + // into the left side -- Standardizing() + if( exponent == ss2.exponent ) + return mantissa < ss2.mantissa; + + return exponent < ss2.exponent; + } + + + /*! + this method performs the formula 'abs(this) > abs(ss2)' + and returns the result + + (in other words it treats 'this' and 'ss2' as values without a sign) + we don't check the NaN flag + */ + bool GreaterWithoutSignThan(const Big & ss2) const + { + if( IsZero() ) + { + if( ss2.IsZero() ) + // we've got two zeroes + return false; + else + // this==0 and ss2!=0 + return false; + } + + if( ss2.IsZero() ) + // this!=0 and ss2==0 + return true; + + // we're using the fact that all bits in mantissa are pushed + // into the left side -- Standardizing() + if( exponent == ss2.exponent ) + return mantissa > ss2.mantissa; + + return exponent > ss2.exponent; + } + + + /*! + this method performs the formula 'abs(this) == abs(ss2)' + and returns the result + + (in other words it treats 'this' and 'ss2' as values without a sign) + we don't check the NaN flag + */ + bool EqualWithoutSign(const Big & ss2) const + { + if( IsZero() ) + { + if( ss2.IsZero() ) + // we've got two zeroes + return true; + else + // this==0 and ss2!=0 + return false; + } + + if( ss2.IsZero() ) + // this!=0 and ss2==0 + return false; + + if( exponent==ss2.exponent && mantissa==ss2.mantissa ) + return true; + + return false; + } + + + bool operator<(const Big & ss2) const + { + if( IsSign() && !ss2.IsSign() ) + // this<0 and ss2>=0 + return true; + + if( !IsSign() && ss2.IsSign() ) + // this>=0 and ss2<0 + return false; + + // both signs are the same + + if( IsSign() ) + return ss2.SmallerWithoutSignThan( *this ); + + return SmallerWithoutSignThan( ss2 ); + } + + + bool operator==(const Big & ss2) const + { + if( IsSign() != ss2.IsSign() ) + return false; + + return EqualWithoutSign( ss2 ); + } + + + bool operator>(const Big & ss2) const + { + if( IsSign() && !ss2.IsSign() ) + // this<0 and ss2>=0 + return false; + + if( !IsSign() && ss2.IsSign() ) + // this>=0 and ss2<0 + return true; + + // both signs are the same + + if( IsSign() ) + return ss2.GreaterWithoutSignThan( *this ); + + return GreaterWithoutSignThan( ss2 ); + } + + + bool operator>=(const Big & ss2) const + { + return !operator<( ss2 ); + } + + + bool operator<=(const Big & ss2) const + { + return !operator>( ss2 ); + } + + + bool operator!=(const Big & ss2) const + { + return !operator==(ss2); + } + + + + + + /*! + * + * standard mathematical operators + * + */ + + + /*! + an operator for changing the sign + + this method is not changing 'this' but the changed value is returned + */ + Big operator-() const + { + Big temp(*this); + + temp.ChangeSign(); + + return temp; + } + + + Big operator-(const Big & ss2) const + { + Big temp(*this); + + temp.Sub(ss2); + + return temp; + } + + Big & operator-=(const Big & ss2) + { + Sub(ss2); + + return *this; + } + + + Big operator+(const Big & ss2) const + { + Big temp(*this); + + temp.Add(ss2); + + return temp; + } + + + Big & operator+=(const Big & ss2) + { + Add(ss2); + + return *this; + } + + + Big operator*(const Big & ss2) const + { + Big temp(*this); + + temp.Mul(ss2); + + return temp; + } + + + Big & operator*=(const Big & ss2) + { + Mul(ss2); + + return *this; + } + + + Big operator/(const Big & ss2) const + { + Big temp(*this); + + temp.Div(ss2); + + return temp; + } + + + Big & operator/=(const Big & ss2) + { + Div(ss2); + + return *this; + } + + + /*! + this method makes an integer value by skipping any fractions + + for example: + 10.7 will be 10 + 12.1 -- 12 + -20.2 -- 20 + -20.9 -- 20 + -0.7 -- 0 + 0.8 -- 0 + */ + void SkipFraction() + { + if( IsNan() || IsZero() ) + return; + + if( !exponent.IsSign() ) + // exponent >=0 -- the value don't have any fractions + return; + + if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) + { + // the value is from (-1,1), we return zero + SetZero(); + return; + } + + // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) + sint e = exponent.ToInt(); + + mantissa.ClearFirstBits( -e ); + + // we don't have to standardize 'Standardizing()' the value because + // there's at least one bit in the mantissa + // (the highest bit which we didn't touch) + } + + + /*! + this method remains only a fraction from the value + + for example: + 30.56 will be 0.56 + -12.67 -- -0.67 + */ + void RemainFraction() + { + if( IsNan() || IsZero() ) + return; + + if( !exponent.IsSign() ) + { + // exponent >= 0 -- the value doesn't have any fractions + // we return zero + SetZero(); + return; + } + + if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) + { + // the value is from (-1,1) + // we don't make anything with the value + return; + } + + // e will be from (-man*TTMATH_BITS_PER_UINT, 0) + sint e = exponent.ToInt(); + + sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative + mantissa.Rcl( how_many_bits_leave, 0); + + // there'll not be a carry because the exponent is too small + exponent.Sub( how_many_bits_leave ); + + // we must call Standardizing() here + Standardizing(); + } + + + + /*! + this method returns true if the value is integer + (there is no a fraction) + + (we don't check nan) + */ + bool IsInteger() const + { + if( IsZero() ) + return true; + + if( !exponent.IsSign() ) + // exponent >=0 -- the value don't have any fractions + return true; + + if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) + // the value is from (-1,1) + return false; + + // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) + sint e = exponent.ToInt(); + e = -e; // e means how many bits we must check + + uint len = e / TTMATH_BITS_PER_UINT; + uint rest = e % TTMATH_BITS_PER_UINT; + uint i = 0; + + for( ; i 0 ) + { + uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest); + if( (mantissa.table[i] & rest_mask) != 0 ) + return false; + } + + return true; + } + + + /*! + this method rounds to the nearest integer value + (it returns a carry if it was) + + for example: + 2.3 = 2 + 2.8 = 3 + + -2.3 = -2 + -2.8 = 3 + */ + uint Round() + { + Big half; + uint c; + + if( IsNan() ) + return 1; + + if( IsZero() ) + return 0; + + half.Set05(); + + if( IsSign() ) + { + // 'this' is < 0 + c = Sub( half ); + } + else + { + // 'this' is > 0 + c = Add( half ); + } + + SkipFraction(); + + return CheckCarry(c); + } + + + + /*! + * + * input/output operators for standard streams + * + */ + +private: + + /*! + an auxiliary method for outputing to standard streams + */ + template + static ostream_type & OutputToStream(ostream_type & s, const Big & l) + { + string_type ss; + + l.ToString(ss); + s << ss; + + return s; + } + + +public: + + + /*! + output to standard streams + */ + friend std::ostream & operator<<(std::ostream & s, const Big & l) + { + return OutputToStream(s, l); + } + + + /*! + output to standard streams + */ + friend std::wostream & operator<<(std::wostream & s, const Big & l) + { + return OutputToStream(s, l); + } + + +private: + + /*! + an auxiliary method for converting from a string + */ + template + static istream_type & InputFromStream(istream_type & s, Big & l) + { + string_type ss; + + // char or wchar_t for operator>> + char_type z, old_z; + bool was_comma = false; + bool was_e = false; + + + // operator>> omits white characters if they're set for ommiting + s >> z; + + if( z=='-' || z=='+' ) + { + ss += z; + s >> z; // we're reading a next character (white characters can be ommited) + } + + old_z = 0; + + // we're reading only digits (base=10) and only one comma operator + for( ; s.good() ; z=static_cast(s.get()) ) + { + if( z=='.' || z==',' ) + { + if( was_comma || was_e ) + // second comma operator or comma operator after 'e' character + break; + + was_comma = true; + } + else + if( z == 'e' || z == 'E' ) + { + if( was_e ) + // second 'e' character + break; + + was_e = true; + } + else + if( z == '+' || z == '-' ) + { + if( old_z != 'e' && old_z != 'E' ) + // '+' or '-' is allowed only after 'e' character + break; + } + else + if( Misc::CharToDigit(z, 10) < 0 ) + break; + + + ss += z; + old_z = z; + } + + // we're leaving the last read character + // (it's not belonging to the value) + s.unget(); + + l.FromString( ss ); + + return s; + } + + + +public: + + /*! + input from standard streams + */ + friend std::istream & operator>>(std::istream & s, Big & l) + { + return InputFromStream(s, l); + } + + + /*! + input from standard streams + */ + friend std::wistream & operator>>(std::wistream & s, Big & l) + { + return InputFromStream(s, l); + } + +}; + + +} // namespace + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathint.h b/src/libghost/ttmath/ttmath/ttmathint.h new file mode 100644 index 0000000..bf2c55a --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathint.h @@ -0,0 +1,1547 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef headerfilettmathint +#define headerfilettmathint + +/*! + \file ttmathint.h + \brief template class Int +*/ + +#include "ttmathuint.h" + +namespace ttmath +{ + + +/*! + \brief Int implements a big integer value with a sign + + value_size - how many bytes specify our value + on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits + on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits + value_size = 1,2,3,4,5,6.... +*/ +template +class Int : public UInt +{ +public: + + /*! + this method sets the max value which this class can hold + (all bits will be one besides the last one) + */ + void SetMax() + { + UInt::SetMax(); + UInt::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT; + } + + + /*! + this method sets the min value which this class can hold + (all bits will be zero besides the last one which is one) + */ + void SetMin() + { + UInt::SetZero(); + UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; + } + + + /*! + this method sets -1 as the value + (-1 is equal the max value in an unsigned type) + */ + void SetSignOne() + { + UInt::SetMax(); + } + + + /*! + we change the sign of the value + + if it isn't possible to change the sign this method returns 1 + else return 0 and changing the sign + */ + uint ChangeSign() + { + Int temp; + + temp.SetMin(); + + /* + if the value is equal that one which has been returned from SetMin + that means we can't change sign because the value is too big (bigger about one) + + e.g. when value_size = 1 and value is -2147483648 we can't change it to the + 2147483648 because the max value which can be held is 2147483647 + + we don't change the value and we're using this fact somewhere in some methods + (if we look on our value without the sign we get the correct value + eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type) + */ + if( operator==(temp) ) + return 1; + + temp.SetZero(); + temp.UInt::Sub(*this); + + operator=(temp); + + return 0; + } + + + + /*! + this method sets the sign + + e.g. 1 -> -1 + -2 -> -2 + + from a positive value we make a negative value, + if the value is negative we do nothing + */ + void SetSign() + { + if( IsSign() ) + return; + + ChangeSign(); + } + + + + /*! + this method returns true if there's the sign + + (the highest bit will be converted to the bool) + */ + bool IsSign() const + { + return UInt::IsTheHighestBitSet(); + } + + + + /*! + it sets an absolute value + + it can return carry (1) (look on ChangeSign() for details) + */ + uint Abs() + { + if( !IsSign() ) + return 0; + + return ChangeSign(); + } + + + + + /*! + * + * basic mathematic functions + * + */ + +private: + + uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign) + { + if( !p1_is_sign && !p2_is_sign ) + { + if( UInt::IsTheHighestBitSet() ) + return 1; + } + + if( p1_is_sign && p2_is_sign ) + { + if( ! UInt::IsTheHighestBitSet() ) + return 1; + } + + return 0; + } + + +public: + + /*! + this method adds two value with a sign and returns a carry + + we're using methods from the base class because values are stored with U2 + we must only make the carry correction + + this = p1(=this) + p2 + + when p1>=0 i p2>=0 carry is set when the highest bit of value is set + when p1<0 i p2<0 carry is set when the highest bit of value is clear + when p1>=0 i p2<0 carry will never be set + when p1<0 i p2>=0 carry will never be set + */ + uint Add(const Int & ss2) + { + bool p1_is_sign = IsSign(); + bool p2_is_sign = ss2.IsSign(); + + UInt::Add(ss2); + + return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign); + } + + + /*! + this method adds one *unsigned* word (at a specific position) + and returns a carry (if it was) + + look at a description in UInt<>::AddInt(...) + */ + uint AddInt(uint value, uint index = 0) + { + bool p1_is_sign = IsSign(); + + UInt::AddInt(value, index); + + return CorrectCarryAfterAdding(p1_is_sign, false); + } + + + /*! + this method adds two *unsigned* words to the existing value + and these words begin on the 'index' position + + index should be equal or smaller than value_size-2 (index <= value_size-2) + x1 - lower word, x2 - higher word + + look at a description in UInt<>::AddTwoInts(...) + */ + uint AddTwoInts(uint x2, uint x1, uint index) + { + bool p1_is_sign = IsSign(); + + UInt::AddTwoInts(x2, x1, index); + + return CorrectCarryAfterAdding(p1_is_sign, false); + } + +private: + + uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign) + { + if( !p1_is_sign && p2_is_sign ) + { + if( UInt::IsTheHighestBitSet() ) + return 1; + } + + if( p1_is_sign && !p2_is_sign ) + { + if( ! UInt::IsTheHighestBitSet() ) + return 1; + } + + return 0; + } + +public: + + /*! + this method subtracts two values with a sign + + we don't use the previous Add because the method ChangeSign can + sometimes return carry + + this = p1(=this) - p2 + + when p1>=0 i p2>=0 carry will never be set + when p1<0 i p2<0 carry will never be set + when p1>=0 i p2<0 carry is set when the highest bit of value is set + when p1<0 i p2>=0 carry is set when the highest bit of value is clear + */ + uint Sub(const Int & ss2) + { + bool p1_is_sign = IsSign(); + bool p2_is_sign = ss2.IsSign(); + + UInt::Sub(ss2); + + return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign); + } + + + /*! + this method subtracts one *unsigned* word (at a specific position) + and returns a carry (if it was) + */ + uint SubInt(uint value, uint index = 0) + { + bool p1_is_sign = IsSign(); + + UInt::SubInt(value, index); + + return CorrectCarryAfterSubtracting(p1_is_sign, false); + } + + + /*! + this method adds one to the value and returns carry + */ + uint AddOne() + { + bool p1_is_sign = IsSign(); + + UInt::AddOne(); + + return CorrectCarryAfterAdding(p1_is_sign, false); + } + + + /*! + this method subtracts one from the value and returns carry + */ + uint SubOne() + { + bool p1_is_sign = IsSign(); + + UInt::SubOne(); + + return CorrectCarryAfterSubtracting(p1_is_sign, false); + } + + + + /*! + multiplication this = this * ss2 + + it returns carry if the result is too big + (we're using the method from the base class but we have to make + one correction in account of signs) + */ + uint Mul(Int ss2) + { + bool ss1_is_sign, ss2_is_sign; + + ss1_is_sign = IsSign(); + ss2_is_sign = ss2.IsSign(); + + /* + we don't have to check the carry from Abs (values will be correct + because next we're using the method Mul from the base class UInt + which is without a sign) + */ + Abs(); + ss2.Abs(); + + if( UInt::Mul(ss2) ) + return 1; + + + /* + we have to examine the sign of the result now + but if the result is with the sign then: + 1. if the signs were the same that means the result is too big + (the result must be without a sign) + 2. if the signs were different that means if the result + is different from that one which has been returned from SetMin() + that is carry (result too big) but if the result is equal SetMin() + there'll be ok (and the next SetSign will has no effect because + the value is actually negative -- look at description of that case + in ChangeSign()) + */ + if( IsSign() ) + { + /* + there can be one case where signs are different and + the result will be equal the value from SetMin() + (this situation is ok) + */ + if( ss1_is_sign != ss2_is_sign ) + { + Int temp; + temp.SetMin(); + + if( operator!=(temp) ) + /* + the result is too big + */ + return 1; + } + else + { + /* + the result is too big + */ + return 1; + } + } + + if( ss1_is_sign != ss2_is_sign ) + SetSign(); + + + return 0; + } + + + /*! + division this = this / ss2 + returned values: + 0 - ok + 1 - division by zero + + for example: (result means 'this') + 20 / 3 --> result: 6 remainder: 2 + -20 / 3 --> result: -6 remainder: -2 + 20 / -3 --> result: -6 remainder: 2 + -20 / -3 --> result: 6 remainder: -2 + + in other words: this(old) = ss2 * this(new)(result) + remainder + */ + uint Div(Int ss2, Int * remainder = 0) + { + bool ss1_is_sign, ss2_is_sign; + + ss1_is_sign = IsSign(); + ss2_is_sign = ss2.IsSign(); + + /* + we don't have to test the carry from Abs as well as in Mul + */ + Abs(); + ss2.Abs(); + + uint c = UInt::Div(ss2, remainder); + + if( ss1_is_sign != ss2_is_sign ) + SetSign(); + + if( ss1_is_sign && remainder ) + remainder->SetSign(); + + return c; + } + + uint Div(const Int & ss2, Int & remainder) + { + return Div(ss2, &remainder); + } + + + /*! + division this = this / ss2 (ss2 is int) + returned values: + 0 - ok + 1 - division by zero + + for example: (result means 'this') + 20 / 3 --> result: 6 remainder: 2 + -20 / 3 --> result: -6 remainder: -2 + 20 / -3 --> result: -6 remainder: 2 + -20 / -3 --> result: 6 remainder: -2 + + in other words: this(old) = ss2 * this(new)(result) + remainder + */ + uint DivInt(sint ss2, sint * remainder = 0) + { + bool ss1_is_sign, ss2_is_sign; + + ss1_is_sign = IsSign(); + + /* + we don't have to test the carry from Abs as well as in Mul + */ + Abs(); + + if( ss2 < 0 ) + { + ss2 = -ss2; + ss2_is_sign = true; + } + else + { + ss2_is_sign = false; + } + + uint rem; + uint c = UInt::DivInt((uint)ss2, &rem); + + if( ss1_is_sign != ss2_is_sign ) + SetSign(); + + if( remainder ) + { + if( ss1_is_sign ) + *remainder = -sint(rem); + else + *remainder = sint(rem); + } + + return c; + } + + + uint DivInt(sint ss2, sint & remainder) + { + return DivInt(ss2, &remainder); + } + + +private: + + + /*! + power this = this ^ pow + this can be negative + pow is >= 0 + */ + uint Pow2(const Int & pow) + { + bool was_sign = IsSign(); + uint c = 0; + + if( was_sign ) + c += Abs(); + + uint c_temp = UInt::Pow(pow); + if( c_temp > 0 ) + return c_temp; // c_temp can be: 0, 1 or 2 + + if( was_sign && (pow.table[0] & 1) == 1 ) + // negative value to the power of odd number is negative + c += ChangeSign(); + + return (c==0)? 0 : 1; + } + + +public: + + + /*! + power this = this ^ pow + + return values: + 0 - ok + 1 - carry + 2 - incorrect arguments 0^0 or 0^(-something) + */ + uint Pow(Int pow) + { + if( !pow.IsSign() ) + return Pow2(pow); + + if( UInt::IsZero() ) + // if 'pow' is negative then + // 'this' must be different from zero + return 2; + + if( pow.ChangeSign() ) + return 1; + + Int t(*this); + uint c_temp = t.Pow2(pow); + if( c_temp > 0 ) + return c_temp; + + UInt::SetOne(); + if( Div(t) ) + return 1; + + return 0; + } + + + + /*! + * + * convertion methods + * + */ +private: + + + /*! + an auxiliary method for converting both from UInt and Int + */ + template + uint FromUIntOrInt(const UInt & p, bool UInt_type) + { + uint min_size = (value_size < argument_size)? value_size : argument_size; + uint i; + + for(i=0 ; i::table[i] = p.table[i]; + + + if( value_size > argument_size ) + { + uint fill; + + if( UInt_type ) + fill = 0; + else + fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? + TTMATH_UINT_MAX_VALUE : 0; + + // 'this' is longer than 'p' + for( ; i::table[i] = fill; + } + else + { + uint test = (UInt::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? + TTMATH_UINT_MAX_VALUE : 0; + + if( UInt_type && test!=0 ) + return 1; + + for( ; i type into this class + + this operation has mainly sense if the value from p + can be held in this type + + it returns a carry if the value 'p' is too big + */ + template + uint FromInt(const Int & p) + { + return FromUIntOrInt(p, false); + } + + + /*! + this method converts the sint type into this class + */ + uint FromInt(sint value) + { + uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0; + + for(uint i=1 ; i::table[i] = fill; + + UInt::table[0] = uint(value); + + // there'll never be a carry here + return 0; + } + + + /*! + this method converts UInt into this class + */ + template + uint FromUInt(const UInt & p) + { + return FromUIntOrInt(p, true); + } + + + /*! + this method converts the uint type into this class + */ + uint FromUInt(uint value) + { + for(uint i=1 ; i::table[i] = 0; + + UInt::table[0] = value; + + // there can be a carry here when the size of this value is equal one word + // and the 'value' has the highest bit set + if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) + return 1; + + return 0; + } + + + + /*! + the default assignment operator + */ + Int & operator=(const Int & p) + { + FromInt(p); + + return *this; + } + + + /*! + this operator converts an Int type to this class + + it doesn't return a carry + */ + template + Int & operator=(const Int & p) + { + FromInt(p); + + return *this; + } + + + /*! + this method converts the sint type to this class + */ + Int & operator=(sint i) + { + FromInt(i); + + return *this; + } + + + /*! + a constructor for converting the uint to this class + */ + Int(sint i) + { + FromInt(i); + } + + + /*! + a copy constructor + */ + Int(const Int & u) + { + FromInt(u); + } + + + /*! + a constructor for copying from another types + */ + template + Int(const Int & u) + { + // look that 'size' we still set as 'value_size' and not as u.value_size + FromInt(u); + } + + + + /*! + this operator converts an UInt type to this class + + it doesn't return a carry + */ + template + Int & operator=(const UInt & p) + { + FromUInt(p); + + return *this; + } + + + /*! + this method converts the Uint type to this class + */ + Int & operator=(uint i) + { + FromUInt(i); + + return *this; + } + + + /*! + a constructor for converting the uint to this class + */ + Int(uint i) + { + FromUInt(i); + } + + + /*! + a constructor for copying from another types + */ + template + Int(const UInt & u) + { + // look that 'size' we still set as 'value_size' and not as u.value_size + FromUInt(u); + } + + + + +#ifdef TTMATH_PLATFORM64 + + /*! + this method converts the signed int type to this class + + ***this operator is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Int & operator=(signed int i) + { + FromInt(sint(i)); + + return *this; + } + + + /*! + a constructor for converting the signed int to this class + + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Int(signed int i) + { + FromInt(sint(i)); + } + + + /*! + this method converts the unsigned int type to this class + + ***this operator is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Int & operator=(unsigned int i) + { + FromUInt(uint(i)); + + return *this; + } + + + /*! + a constructor for converting the unsigned int to this class + + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + */ + Int(unsigned int i) + { + FromUInt(uint(i)); + } + +#endif + + + /*! + a constructor for converting string to this class (with the base=10) + */ + Int(const char * s) + { + FromString(s); + } + + + /*! + a constructor for converting string to this class (with the base=10) + */ + Int(const wchar_t * s) + { + FromString(s); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + Int(const std::string & s) + { + FromString( s.c_str() ); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + Int(const std::wstring & s) + { + FromString( s.c_str() ); + } + + + /*! + a default constructor + + we don't clear table etc. + */ + Int() + { + } + + + /*! + the destructor + */ + ~Int() + { + } + + + /*! + this method returns the lowest value from table with a sign + + we must be sure when we using this method whether the value + will hold in an sint type or not (the rest value from table must be zero or -1) + */ + sint ToInt() const + { + return sint( UInt::table[0] ); + } + + +private: + + /*! + an auxiliary method for converting to a string + */ + template + void ToStringBase(string_type & result, uint b = 10) const + { + if( IsSign() ) + { + Int temp(*this); + temp.Abs(); + + temp.UInt::ToString(result, b); + result.insert(result.begin(), '-'); + } + else + { + UInt::ToString(result, b); + } + } + +public: + + /*! + this method converts the value to a string with a base equal 'b' + */ + void ToString(std::string & result, uint b = 10) const + { + return ToStringBase(result, b); + } + + + /*! + this method converts the value to a string with a base equal 'b' + */ + void ToString(std::wstring & result, uint b = 10) const + { + return ToStringBase(result, b); + } + + + /*! + this method converts the value to a string with a base equal 'b' + */ + std::string ToString(uint b = 10) const + { + std::string result; + ToStringBase(result, b); + + return result; + } + + + /*! + this method converts the value to a string with a base equal 'b' + */ + std::wstring ToWString(uint b = 10) const + { + std::wstring result; + ToStringBase(result, b); + + return result; + } + + +private: + + /*! + an auxiliary method for converting from a string + */ + template + uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) + { + bool is_sign = false; + + Misc::SkipWhiteCharacters(s); + + if( *s == '-' ) + { + is_sign = true; + Misc::SkipWhiteCharacters(++s); + } + else + if( *s == '+' ) + { + Misc::SkipWhiteCharacters(++s); + } + + if( UInt::FromString(s,b,after_source,value_read) ) + return 1; + + if( is_sign ) + { + Int mmin; + + mmin.SetMin(); + + /* + the reference to mmin will be automatically converted to the reference + to UInt type + (this value can be equal mmin -- look at a description in ChangeSign()) + */ + if( UInt::operator>( mmin ) ) + return 1; + + /* + if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it) + */ + ChangeSign(); + } + else + { + Int mmax; + + mmax.SetMax(); + + if( UInt::operator>( mmax ) ) + return 1; + } + + return 0; + } + + +public: + + /*! + this method converts a string into its value + it returns carry=1 if the value will be too big or an incorrect base 'b' is given + + string is ended with a non-digit value, for example: + "-12" will be translated to -12 + as well as: + "- 12foo" will be translated to -12 too + + existing first white characters will be ommited + (between '-' and a first digit can be white characters too) + + after_source (if exists) is pointing at the end of the parsed string + + value_read (if exists) tells whether something has actually been read (at least one digit) + */ + uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + + /*! + this method converts a string into its value + */ + uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + + /*! + this method converts a string into its value + it returns carry=1 if the value will be too big or an incorrect base 'b' is given + */ + uint FromString(const std::string & s, uint b = 10) + { + return FromString( s.c_str(), b ); + } + + + /*! + this method converts a string into its value + it returns carry=1 if the value will be too big or an incorrect base 'b' is given + */ + uint FromString(const std::wstring & s, uint b = 10) + { + return FromString( s.c_str(), b ); + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + Int & operator=(const char * s) + { + FromString(s); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + Int & operator=(const wchar_t * s) + { + FromString(s); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + Int & operator=(const std::string & s) + { + FromString( s.c_str() ); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + Int & operator=(const std::wstring & s) + { + FromString( s.c_str() ); + + return *this; + } + + + /*! + * + * methods for comparing + * + * + */ + + bool operator==(const Int & l) const + { + return UInt::operator==(l); + } + + bool operator!=(const Int & l) const + { + return UInt::operator!=(l); + } + + bool operator<(const Int & l) const + { + sint i=value_size-1; + + sint a1 = sint(UInt::table[i]); + sint a2 = sint(l.table[i]); + + if( a1 != a2 ) + return a1 < a2; + + + for(--i ; i>=0 ; --i) + { + if( UInt::table[i] != l.table[i] ) + // comparison as unsigned int + return UInt::table[i] < l.table[i]; + } + + // they're equal + return false; + } + + + bool operator>(const Int & l) const + { + sint i=value_size-1; + + sint a1 = sint(UInt::table[i]); + sint a2 = sint(l.table[i]); + + if( a1 != a2 ) + return a1 > a2; + + + for(--i ; i>=0 ; --i) + { + if( UInt::table[i] != l.table[i] ) + // comparison as unsigned int + return UInt::table[i] > l.table[i]; + } + + // they're equal + return false; + } + + + bool operator<=(const Int & l) const + { + sint i=value_size-1; + + sint a1 = sint(UInt::table[i]); + sint a2 = sint(l.table[i]); + + if( a1 != a2 ) + return a1 < a2; + + + for(--i ; i>=0 ; --i) + { + if( UInt::table[i] != l.table[i] ) + // comparison as unsigned int + return UInt::table[i] < l.table[i]; + } + + // they're equal + return true; + } + + + bool operator>=(const Int & l) const + { + sint i=value_size-1; + + sint a1 = sint(UInt::table[i]); + sint a2 = sint(l.table[i]); + + if( a1 != a2 ) + return a1 > a2; + + + for(--i ; i>=0 ; --i) + { + if( UInt::table[i] != l.table[i] ) + // comparison as unsigned int + return UInt::table[i] > l.table[i]; + } + + // they're equal + return true; + } + + + + /*! + * + * standard mathematical operators + * + */ + + + /*! + an operator for changing the sign + + it's not changing 'this' but the changed value will be returned + */ + Int operator-() const + { + Int temp(*this); + + temp.ChangeSign(); + + return temp; + } + + + Int operator-(const Int & p2) const + { + Int temp(*this); + + temp.Sub(p2); + + return temp; + } + + + Int & operator-=(const Int & p2) + { + Sub(p2); + + return *this; + } + + + Int operator+(const Int & p2) const + { + Int temp(*this); + + temp.Add(p2); + + return temp; + } + + + Int & operator+=(const Int & p2) + { + Add(p2); + + return *this; + } + + + Int operator*(const Int & p2) const + { + Int temp(*this); + + temp.Mul(p2); + + return temp; + } + + + Int & operator*=(const Int & p2) + { + Mul(p2); + + return *this; + } + + + Int operator/(const Int & p2) const + { + Int temp(*this); + + temp.Div(p2); + + return temp; + } + + + Int & operator/=(const Int & p2) + { + Div(p2); + + return *this; + } + + + Int operator%(const Int & p2) const + { + Int temp(*this); + Int remainder; + + temp.Div(p2, remainder); + + return remainder; + } + + + Int & operator%=(const Int & p2) + { + Int temp(*this); + Int remainder; + + temp.Div(p2, remainder); + + operator=(remainder); + + return *this; + } + + + /*! + Prefix operator e.g. ++variable + */ + UInt & operator++() + { + AddOne(); + + return *this; + } + + + /*! + Postfix operator e.g. variable++ + */ + UInt operator++(int) + { + UInt temp( *this ); + + AddOne(); + + return temp; + } + + + UInt & operator--() + { + SubOne(); + + return *this; + } + + + UInt operator--(int) + { + UInt temp( *this ); + + SubOne(); + + return temp; + } + + + + /*! + * + * input/output operators for standard streams + * + */ + +private: + + /*! + an auxiliary method for outputing to standard streams + */ + template + static ostream_type & OutputToStream(ostream_type & s, const Int & l) + { + string_type ss; + + l.ToString(ss); + s << ss; + + return s; + } + + + +public: + + + /*! + output to standard streams + */ + friend std::ostream & operator<<(std::ostream & s, const Int & l) + { + return OutputToStream(s, l); + } + + + /*! + output to standard streams + */ + friend std::wostream & operator<<(std::wostream & s, const Int & l) + { + return OutputToStream(s, l); + } + + + +private: + + /*! + an auxiliary method for converting from a string + */ + template + static istream_type & InputFromStream(istream_type & s, Int & l) + { + string_type ss; + + // char or wchar_t for operator>> + char_type z; + + // operator>> omits white characters if they're set for ommiting + s >> z; + + if( z=='-' || z=='+' ) + { + ss += z; + s >> z; // we're reading a next character (white characters can be ommited) + } + + // we're reading only digits (base=10) + while( s.good() && Misc::CharToDigit(z, 10)>=0 ) + { + ss += z; + z = static_cast(s.get()); + } + + // we're leaving the last readed character + // (it's not belonging to the value) + s.unget(); + + l.FromString(ss); + + return s; + } + + +public: + + /*! + input from standard streams + */ + friend std::istream & operator>>(std::istream & s, Int & l) + { + return InputFromStream(s, l); + } + + + /*! + input from standard streams + */ + friend std::wistream & operator>>(std::wistream & s, Int & l) + { + return InputFromStream(s, l); + } + +}; + +} // namespace + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathmisc.h b/src/libghost/ttmath/ttmath/ttmathmisc.h new file mode 100644 index 0000000..38ab596 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathmisc.h @@ -0,0 +1,243 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfilettmathmisc +#define headerfilettmathmisc + + +/*! + \file ttmathmisc.h + \brief some helpful functions +*/ + + +#include + + +namespace ttmath +{ + +/*! + some helpful functions +*/ +class Misc +{ +public: + + +/* + * + * AssignString(result, str) + * result = str + * + */ + +/*! + result = str +*/ +static void AssignString(std::string & result, const char * str) +{ + result = str; +} + + +/*! + result = str +*/ +static void AssignString(std::wstring & result, const char * str) +{ + result.clear(); + + for( ; *str ; ++str ) + result += *str; +} + + +/*! + result = str +*/ +static void AssignString(std::wstring & result, const std::string & str) +{ + return AssignString(result, str.c_str()); +} + + +/*! + result = str +*/ +static void AssignString(std::string & result, const wchar_t * str) +{ + result.clear(); + + for( ; *str ; ++str ) + result += static_cast(*str); +} + + +/*! + result = str +*/ +static void AssignString(std::string & result, const std::wstring & str) +{ + return AssignString(result, str.c_str()); +} + + +/* + * + * AddString(result, str) + * result += str + * + */ + + +/*! + result += str +*/ +static void AddString(std::string & result, const char * str) +{ + result += str; +} + + +/*! + result += str +*/ +static void AddString(std::wstring & result, const char * str) +{ + for( ; *str ; ++str ) + result += *str; +} + + + +/* + this method omits any white characters from the string + char_type is char or wchar_t +*/ +template +static void SkipWhiteCharacters(const char_type * & c) +{ + // 13 is at the end in a DOS text file (\r\n) + while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) + ++c; +} + + + + +/*! + this static method converts one character into its value + + for example: + 1 -> 1 + 8 -> 8 + A -> 10 + f -> 15 + + this method don't check whether c is correct or not +*/ +static uint CharToDigit(uint c) +{ + if(c>='0' && c<='9') + return c-'0'; + + if(c>='a' && c<='z') + return c-'a'+10; + +return c-'A'+10; +} + + +/*! + this method changes a character 'c' into its value + (if there can't be a correct value it returns -1) + + for example: + c=2, base=10 -> function returns 2 + c=A, base=10 -> function returns -1 + c=A, base=16 -> function returns 10 +*/ +static sint CharToDigit(uint c, uint base) +{ + if( c>='0' && c<='9' ) + c=c-'0'; + else + if( c>='a' && c<='z' ) + c=c-'a'+10; + else + if( c>='A' && c<='Z' ) + c=c-'A'+10; + else + return -1; + + + if( c >= base ) + return -1; + + +return sint(c); +} + + + +/*! + this method converts a digit into a char + digit should be from <0,F> + (we don't have to get a base) + + for example: + 1 -> 1 + 8 -> 8 + 10 -> A + 15 -> F +*/ +static uint DigitToChar(uint digit) +{ + if( digit < 10 ) + return digit + '0'; + +return digit - 10 + 'A'; +} + + +}; // struct Misc + +} + + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathobjects.h b/src/libghost/ttmath/ttmath/ttmathobjects.h new file mode 100644 index 0000000..5fe343d --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathobjects.h @@ -0,0 +1,766 @@ +/* + * This file is a part of TTMath Mathematical Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef headerfilettmathobject +#define headerfilettmathobject + +/*! + \file ttmathobjects.h + \brief Mathematic functions. +*/ + +#include +#include +#include +#include + +#include "ttmathtypes.h" +#include "ttmathmisc.h" + + +namespace ttmath +{ + +/*! + objects of this class are used with the mathematical parser + they hold variables or functions defined by a user + + each object has its own table in which we're keeping variables or functions +*/ +class Objects +{ +public: + + + /*! + one item (variable or function) + 'items' will be on the table + */ + struct Item + { + // name of a variable of a function + // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used) + std::string value; + + // number of parameters required by the function + // (if there's a variable this 'param' is ignored) + int param; + + Item() {} + Item(const std::string & v, int p) : value(v), param(p) {} + }; + + // 'Table' is the type of our table + typedef std::map Table; + typedef Table::iterator Iterator; + typedef Table::const_iterator CIterator; + + + + /*! + this method returns true if a character 'c' is a character + which can be in a name + + if 'can_be_digit' is true that means when the 'c' is a digit this + method returns true otherwise it returns false + */ + static bool CorrectCharacter(wchar_t c, bool can_be_digit) + { + if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) + return true; + + if( can_be_digit && ((c>='0' && c<='9') || c=='_') ) + return true; + + return false; + } + + + /*! + this method returns true if the name can be as a name of an object + */ + template + static bool IsNameCorrect(const string_type & name) + { + if( name.empty() ) + return false; + + if( !CorrectCharacter(name[0], false) ) + return false; + + typename string_type::const_iterator i = name.begin(); + + for(++i ; i!=name.end() ; ++i) + if( !CorrectCharacter(*i, true) ) + return false; + + return true; + } + + + /*! + this method returns true if such an object is defined (name exists) + */ + bool IsDefined(const std::string & name) + { + Iterator i = table.find(name); + + if( i != table.end() ) + // we have this object in our table + return true; + + return false; + } + + + /*! + this method returns true if such an object is defined (name exists) + */ + bool IsDefined(const std::wstring & name) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return false; + + Misc::AssignString(str_tmp1, name); + + return IsDefined(str_tmp1); + } + + + /*! + this method adds one object (variable of function) into the table + */ + ErrorCode Add(const std::string & name, const std::string & value, int param = 0) + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Iterator i = table.find(name); + + if( i != table.end() ) + // we have this object in our table + return err_object_exists; + + table.insert( std::make_pair(name, Item(value, param)) ); + + return err_ok; + } + + + /*! + this method adds one object (variable of function) into the table + */ + ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + Misc::AssignString(str_tmp2, value); + + return Add(str_tmp1, str_tmp2, param); + } + + + /*! + this method returns 'true' if the table is empty + */ + bool Empty() const + { + return table.empty(); + } + + + /*! + this method clears the table + */ + void Clear() + { + return table.clear(); + } + + + /*! + this method returns 'const_iterator' on the first item on the table + */ + CIterator Begin() const + { + return table.begin(); + } + + + /*! + this method returns 'const_iterator' pointing at the space after last item + (returns table.end()) + */ + CIterator End() const + { + return table.end(); + } + + + /*! + this method changes the value and the number of parameters for a specific object + */ + ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Iterator i = table.find(name); + + if( i == table.end() ) + return err_unknown_object; + + i->second.value = value; + i->second.param = param; + + return err_ok; + } + + + /*! + this method changes the value and the number of parameters for a specific object + */ + ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + Misc::AssignString(str_tmp2, value); + + return EditValue(str_tmp1, str_tmp2, param); + } + + + /*! + this method changes the name of a specific object + */ + ErrorCode EditName(const std::string & old_name, const std::string & new_name) + { + if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) + return err_incorrect_name; + + Iterator old_i = table.find(old_name); + if( old_i == table.end() ) + return err_unknown_object; + + if( old_name == new_name ) + // the new name is the same as the old one + // we treat it as a normal situation + return err_ok; + + ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param); + + if( err == err_ok ) + { + old_i = table.find(old_name); + TTMATH_ASSERT( old_i != table.end() ) + + table.erase(old_i); + } + + return err; + } + + + /*! + this method changes the name of a specific object + */ + ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, old_name); + Misc::AssignString(str_tmp2, new_name); + + return EditName(str_tmp1, str_tmp2); + } + + + /*! + this method deletes an object + */ + ErrorCode Delete(const std::string & name) + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Iterator i = table.find(name); + + if( i == table.end() ) + return err_unknown_object; + + table.erase( i ); + + return err_ok; + } + + + /*! + this method deletes an object + */ + ErrorCode Delete(const std::wstring & name) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + + return Delete(str_tmp1); + } + + + /*! + this method gets the value of a specific object + */ + ErrorCode GetValue(const std::string & name, std::string & value) const + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + CIterator i = table.find(name); + + if( i == table.end() ) + { + value.clear(); + return err_unknown_object; + } + + value = i->second.value; + + return err_ok; + } + + + /*! + this method gets the value of a specific object + */ + ErrorCode GetValue(const std::wstring & name, std::wstring & value) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + ErrorCode err = GetValue(str_tmp1, str_tmp2); + Misc::AssignString(value, str_tmp2); + + return err; + } + + + /*! + this method gets the value of a specific object + (this version is used for not copying the whole string) + */ + ErrorCode GetValue(const std::string & name, const char ** value) const + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + CIterator i = table.find(name); + + if( i == table.end() ) + { + *value = 0; + return err_unknown_object; + } + + *value = i->second.value.c_str(); + + return err_ok; + } + + + /*! + this method gets the value of a specific object + (this version is used for not copying the whole string) + */ + ErrorCode GetValue(const std::wstring & name, const char ** value) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + + return GetValue(str_tmp1, value); + } + + + /*! + this method gets the value and the number of parameters + of a specific object + */ + ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + CIterator i = table.find(name); + + if( i == table.end() ) + { + value.empty(); + *param = 0; + return err_unknown_object; + } + + value = i->second.value; + *param = i->second.param; + + return err_ok; + } + + + /*! + this method gets the value and the number of parameters + of a specific object + */ + ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param); + Misc::AssignString(value, str_tmp2); + + return err; + } + + + /*! + this method sets the value and the number of parameters + of a specific object + (this version is used for not copying the whole string) + */ + ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const + { + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + CIterator i = table.find(name); + + if( i == table.end() ) + { + *value = 0; + *param = 0; + return err_unknown_object; + } + + *value = i->second.value.c_str(); + *param = i->second.param; + + return err_ok; + } + + + /*! + this method sets the value and the number of parameters + of a specific object + (this version is used for not copying the whole string + but in fact we make one copying during AssignString()) + */ + ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + + return GetValueAndParam(str_tmp1, value, param); + } + + + /*! + this method returns a pointer into the table + */ + Table * GetTable() + { + return &table; + } + + +private: + + Table table; + std::string str_tmp1, str_tmp2; + +}; // end of class Objects + + + + + + + +/*! + objects of the class History are used to keep values in functions + which take a lot of time during calculating, for instance in the + function Factorial(x) + + it means that when we're calculating e.g. Factorial(1000) and the + Factorial finds that we have calculated it before, the value (result) + is taken from the history +*/ +template +class History +{ + /*! + one item in the History's object holds a key, a value for the key + and a corresponding error code + */ + struct Item + { + ValueType key, value; + ErrorCode err; + }; + + + /*! + we use std::list for simply deleting the first item + but because we're searching through the whole container + (in the method Get) the container should not be too big + (linear time of searching) + */ + typedef std::list buffer_type; + buffer_type buffer; + typename buffer_type::size_type buffer_max_size; + +public: + + /*! + default constructor + default max size of the History's container is 15 items + */ + History() + { + buffer_max_size = 15; + } + + + /*! + a constructor which takes another value of the max size + of the History's container + */ + History(typename buffer_type::size_type new_size) + { + buffer_max_size = new_size; + } + + + /*! + this method adds one item into the History + if the size of the container is greater than buffer_max_size + the first item will be removed + */ + void Add(const ValueType & key, const ValueType & value, ErrorCode err) + { + Item item; + item.key = key; + item.value = value; + item.err = err; + + buffer.insert( buffer.end(), item ); + + if( buffer.size() > buffer_max_size ) + buffer.erase(buffer.begin()); + } + + + /*! + this method checks whether we have an item which has the key equal 'key' + + if there's such item the method sets the 'value' and the 'err' + and returns true otherwise it returns false and 'value' and 'err' + remain unchanged + */ + bool Get(const ValueType & key, ValueType & value, ErrorCode & err) + { + typename buffer_type::iterator i = buffer.begin(); + + for( ; i != buffer.end() ; ++i ) + { + if( i->key == key ) + { + value = i->value; + err = i->err; + return true; + } + } + + return false; + } + + + /*! + this methods deletes an item + + we assume that there is only one item with the 'key' + (this methods removes the first one) + */ + bool Remove(const ValueType & key) + { + typename buffer_type::iterator i = buffer.begin(); + + for( ; i != buffer.end() ; ++i ) + { + if( i->key == key ) + { + buffer.erase(i); + return true; + } + } + + return false; + } + + +}; // end of class History + + + +/*! + this is an auxiliary class used when calculating Gamma() or Factorial() + + in multithreaded environment you can provide an object of this class to + the Gamma() or Factorial() function, e.g; + typedef Big<1, 3> MyBig; + MyBig x = 123456; + CGamma cgamma; + std::cout << Gamma(x, cgamma); + each thread should have its own CGamma<> object + + in a single-thread environment a CGamma<> object is a static variable + in a second version of Gamma() and you don't have to explicitly use it, e.g. + typedef Big<1, 3> MyBig; + MyBig x = 123456; + std::cout << Gamma(x); +*/ +template +struct CGamma +{ + /*! + this table holds factorials + 1 + 1 + 2 + 6 + 24 + 120 + 720 + ....... + */ + std::vector fact; + + + /*! + this table holds Bernoulli numbers + 1 + -0.5 + 0.166666666666666666666666667 + 0 + -0.0333333333333333333333333333 + 0 + 0.0238095238095238095238095238 + 0 + -0.0333333333333333333333333333 + 0 + 0.075757575757575757575757576 + ..... + */ + std::vector bern; + + + /*! + here we store some calculated values + (this is for speeding up, if the next argument of Gamma() or Factorial() + is in the 'history' then the result we are not calculating but simply + return from the 'history' object) + */ + History history; + + + /*! + this method prepares some coefficients: factorials and Bernoulli numbers + stored in 'fact' and 'bern' objects + + how many values should be depends on the size of the mantissa - if + the mantissa is larger then we must calculate more values + for a mantissa which consists of 256 bits (8 words on a 32bit platform) + we have to calculate about 30 values (the size of fact and bern will be 30), + and for a 2048 bits mantissa we have to calculate 306 coefficients + + you don't have to call this method, these coefficients will be automatically calculated + when they are needed + + you must note that calculating these coefficients is a little time-consuming operation, + (especially when the mantissa is large) and first call to Gamma() or Factorial() + can take more time than next calls, and in the end this is the point when InitAll() + comes in handy: you can call this method somewhere at the beginning of your program + */ + void InitAll(); + // definition is in ttmath.h +}; + + + + +} // namespace + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathparser.h b/src/libghost/ttmath/ttmath/ttmathparser.h new file mode 100644 index 0000000..3f9c796 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathparser.h @@ -0,0 +1,2754 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2010, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef headerfilettmathparser +#define headerfilettmathparser + +/*! + \file ttmathparser.h + \brief A mathematical parser +*/ + +#include +#include +#include +#include + +#include "ttmath.h" +#include "ttmathobjects.h" +#include "ttmathmisc.h" + + + +namespace ttmath +{ + +/*! + \brief Mathematical parser + + let x will be an input string meaning an expression for converting: + + x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]... + where: + an operator can be: + ^ (pow) (the heighest priority) + + * (mul) (or multiplication without an operator -- short mul) + / (div) (* and / have the same priority) + + + (add) + - (sub) (+ and - have the same priority) + + < (lower than) + > (greater than) + <= (lower or equal than) + >= (greater or equal than) + == (equal) + != (not equal) (all above logical operators have the same priority) + + && (logical and) + + || (logical or) (the lowest priority) + + short mul: + if the second Value (Var below) is either a variable or function there might not be + an operator between them, e.g. + "[+|-]Value Var" is treated as "[+|-]Value * Var" and the multiplication + has the same priority as a normal multiplication: + 4x = 4 * x + 2^3m = (2^3)* m + 6h^3 = 6 * (h^3) + 2sin(pi) = 2 * sin(pi) + etc. + + Value can be: + constant e.g. 100, can be preceded by operators for changing the base (radix): [#|&] + # - hex + & - bin + sample: #10 = 16 + &10 = 2 + variable e.g. pi + another expression between brackets e.g (x) + function e.g. sin(x) + + for example a correct input string can be: + "1" + "2.1234" + "2,1234" (they are the same, by default we can either use a comma or a dot) + "1 + 2" + "(1 + 2) * 3" + "pi" + "sin(pi)" + "(1+2)*(2+3)" + "log(2;1234)" there's a semicolon here (not a comma), we use it in functions + for separating parameters + "1 < 2" (the result will be: 1) + "4 < 3" (the result will be: 0) + "2+x" (of course if the variable 'x' is defined) + "4x+10" + "#20+10" = 32 + 10 = 42 + "10 ^ -&101" = 10 ^ -5 = 0.00001 + "8 * -&10" = 8 * -2 = -16 + etc. + + we can also use a semicolon for separating any 'x' input strings + for example: + "1+2;4+5" + the result will be on the stack as follows: + "3" + "9" +*/ +template +class Parser +{ +private: + +/*! + there are 5 mathematical operators as follows (with their standard priorities): + add (+) + sub (-) + mul (*) + div (/) + pow (^) + and 'shortmul' used when there is no any operators between + a first parameter and a variable or function + (the 'shortmul' has the same priority as the normal multiplication ) +*/ + class MatOperator + { + public: + + enum Type + { + none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul + }; + + enum Assoc + { + right, // right-associative + non_right // associative or left-associative + }; + + Type GetType() const { return type; } + int GetPriority() const { return priority; } + Assoc GetAssoc() const { return assoc; } + + void SetType(Type t) + { + type = t; + assoc = non_right; + + switch( type ) + { + case lor: + priority = 4; + break; + + case land: + priority = 5; + break; + + case eq: + case neq: + case lt: + case gt: + case let: + case get: + priority = 7; + break; + + case add: + case sub: + priority = 10; + break; + + case mul: + case shortmul: + case div: + priority = 12; + break; + + case pow: + priority = 14; + assoc = right; + break; + + default: + Error( err_internal_error ); + break; + } + } + + MatOperator(): type(none), priority(0), assoc(non_right) + { + } + + private: + + Type type; + int priority; + Assoc assoc; + }; // end of MatOperator class + + + +public: + + + + /*! + Objects of type 'Item' we are keeping on our stack + */ + struct Item + { + enum Type + { + none, numerical_value, mat_operator, first_bracket, + last_bracket, variable, semicolon + }; + + // The kind of type which we're keeping + Type type; + + // if type == numerical_value + ValueType value; + + // if type == mat_operator + MatOperator moperator; + + /* + if type == first_bracket + + if 'function' is set to true it means that the first recognized bracket + was the bracket from function in other words we must call a function when + we'll find the 'last' bracket + */ + bool function; + + // if function is true + std::string function_name; + + /* + the sign of value + + it can be for type==numerical_value or type==first_bracket + when it's true it means e.g. that value is equal -value + */ + bool sign; + + Item(): type(none), function(false), sign(false) + { + } + + }; // end of Item struct + + +/*! + stack on which we're keeping the Items + + at the end of parsing we'll have the result on its + the result don't have to be one value, it can be a list + of values separated by the 'semicolon item' +*/ +std::vector stack; + + +private: + + +/*! + size of the stack when we're starting parsing of the string + + if it's to small while parsing the stack will be automatically resized +*/ +const int default_stack_size; + + + +/*! + index of an object in our stack + it's pointing on the place behind the last element + for example at the beginning of parsing its value is zero +*/ +unsigned int stack_index; + + +/*! + code of the last error +*/ +ErrorCode error; + + +/*! + pointer to the currently reading char + it's either char* or wchar_t* + + when an error has occured it may be used to count the index of the wrong character +*/ +const char * pstring; + + +/*! + the base (radix) of the mathematic system (for example it may be '10') +*/ +int base; + + +/*! + the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot + 0 - deg + 1 - rad (default) + 2 - grad +*/ +int deg_rad_grad; + + + +/*! + a pointer to an object which tell us whether we should stop calculating or not +*/ +const volatile StopCalculating * pstop_calculating; + + + +/*! + a pointer to the user-defined variables' table +*/ +const Objects * puser_variables; + +/*! + a pointer to the user-defined functions' table +*/ +const Objects * puser_functions; + + +typedef std::map FunctionLocalVariables; + +/*! + a pointer to the local variables of a function +*/ +const FunctionLocalVariables * pfunction_local_variables; + + +/*! + a temporary set using during parsing user defined variables +*/ +std::set visited_variables; + + +/*! + a temporary set using during parsing user defined functions +*/ +std::set visited_functions; + + + + +/*! + pfunction is the type of pointer to a mathematic function + + these mathematic functions are private members of this class, + they are the wrappers for standard mathematics function + + 'pstack' is the pointer to the first argument on our stack + 'amount_of_arg' tell us how many argument there are in our stack + 'result' is the reference for result of function +*/ +typedef void (Parser::*pfunction)(int pstack, int amount_of_arg, ValueType & result); + + +/*! + pfunction is the type of pointer to a method which returns value of variable +*/ +typedef void (ValueType::*pfunction_var)(); + + +/*! + table of mathematic functions + + this map consists of: + std::string - function's name + pfunction - pointer to specific function +*/ +typedef std::map FunctionsTable; +FunctionsTable functions_table; + + +/*! + table of mathematic operators + + this map consists of: + std::string - operators's name + MatOperator::Type - type of the operator +*/ +typedef std::map OperatorsTable; +OperatorsTable operators_table; + + +/*! + table of mathematic variables + + this map consists of: + std::string - variable's name + pfunction_var - pointer to specific function which returns value of variable +*/ +typedef std::map VariablesTable; +VariablesTable variables_table; + + +/*! + some coefficients used when calculating the gamma (or factorial) function +*/ +CGamma cgamma; + + +/*! + temporary object for a whole string when Parse(std::wstring) is used +*/ +std::string wide_to_ansi; + + +/*! + group character (used when parsing) + default zero (not used) +*/ +int group; + + +/*! + characters used as a comma + default: '.' and ',' + comma2 can be zero (it means it is not used) +*/ +int comma, comma2; + + +/*! + an additional character used as a separator between function parameters + (semicolon is used always) +*/ +int param_sep; + + +/*! + true if something was calculated (at least one mathematical operator was used or a function or a variable) +*/ +bool calculated; + + + +/*! + we're using this method for reporting an error +*/ +static void Error(ErrorCode code) +{ + throw code; +} + + +/*! + this method skips the white character from the string + + it's moving the 'pstring' to the first no-white character +*/ +void SkipWhiteCharacters() +{ + while( (*pstring==' ' ) || (*pstring=='\t') ) + ++pstring; +} + + +/*! + an auxiliary method for RecurrenceParsingVariablesOrFunction(...) +*/ +void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name) +{ + if( variable ) + { + if( visited_variables.find(name) != visited_variables.end() ) + Error( err_variable_loop ); + } + else + { + if( visited_functions.find(name) != visited_functions.end() ) + Error( err_functions_loop ); + } +} + + +/*! + an auxiliary method for RecurrenceParsingVariablesOrFunction(...) +*/ +void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) +{ + if( variable ) + visited_variables.insert( name ); + else + visited_functions.insert( name ); +} + + +/*! + an auxiliary method for RecurrenceParsingVariablesOrFunction(...) +*/ +void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) +{ + if( variable ) + visited_variables.erase( name ); + else + visited_functions.erase( name ); +} + + +/*! + this method returns the value of a variable or function + by creating a new instance of the mathematical parser + and making the standard parsing algorithm on the given string + + this method is used only during parsing user defined variables or functions + + (there can be a recurrence here therefore we're using 'visited_variables' + and 'visited_functions' sets to make a stop condition) +*/ +ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, + FunctionLocalVariables * local_variables = 0) +{ + RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); + RecurrenceParsingVariablesOrFunction_AddName(variable, name); + + Parser NewParser(*this); + ErrorCode err; + + NewParser.pfunction_local_variables = local_variables; + + try + { + err = NewParser.Parse(new_string); + } + catch(...) + { + RecurrenceParsingVariablesOrFunction_DeleteName(variable, name); + + throw; + } + + RecurrenceParsingVariablesOrFunction_DeleteName(variable, name); + + if( err != err_ok ) + Error( err ); + + if( NewParser.stack.size() != 1 ) + Error( err_must_be_only_one_value ); + + if( NewParser.stack[0].type != Item::numerical_value ) + // I think there shouldn't be this error here + Error( err_incorrect_value ); + +return NewParser.stack[0].value; +} + + +public: + + +/*! + this method returns the user-defined value of a variable +*/ +bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result) +{ + if( !puser_variables ) + return false; + + const char * string_value; + + if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) + return false; + + result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value); + calculated = true; + +return true; +} + + +/*! + this method returns the value of a local variable of a function +*/ +bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result) +{ + if( !pfunction_local_variables ) + return false; + + typename FunctionLocalVariables::const_iterator i = pfunction_local_variables->find(variable_name); + + if( i == pfunction_local_variables->end() ) + return false; + + result = i->second; + +return true; +} + + +/*! + this method returns the value of a variable from variables' table + + we make an object of type ValueType then call a method which + sets the correct value in it and finally we'll return the object +*/ +ValueType GetValueOfVariable(const std::string & variable_name) +{ +ValueType result; + + if( GetValueOfFunctionLocalVariable(variable_name, result) ) + return result; + + if( GetValueOfUserDefinedVariable(variable_name, result) ) + return result; + + + typename std::map::iterator i = + variables_table.find(variable_name); + + if( i == variables_table.end() ) + Error( err_unknown_variable ); + + (result.*(i->second))(); + calculated = true; + +return result; +} + + +private: + +/*! + wrappers for mathematic functions + + 'sindex' is pointing on the first argument on our stack + (the second argument has 'sindex+2' + because 'sindex+1' is guaranted for the 'semicolon' operator) + the third artument has of course 'sindex+4' etc. + + 'result' will be the result of the function + + (we're using exceptions here for example when function gets an improper argument) +*/ + + +/*! + used by: sin,cos,tan,cot +*/ +ValueType ConvertAngleToRad(const ValueType & input) +{ + if( deg_rad_grad == 1 ) // rad + return input; + + ValueType result; + ErrorCode err; + + if( deg_rad_grad == 0 ) // deg + result = ttmath::DegToRad(input, &err); + else // grad + result = ttmath::GradToRad(input, &err); + + if( err != err_ok ) + Error( err ); + +return result; +} + + +/*! + used by: asin,acos,atan,acot +*/ +ValueType ConvertRadToAngle(const ValueType & input) +{ + if( deg_rad_grad == 1 ) // rad + return input; + + ValueType result; + ErrorCode err; + + if( deg_rad_grad == 0 ) // deg + result = ttmath::RadToDeg(input, &err); + else // grad + result = ttmath::RadToGrad(input, &err); + + if( err != err_ok ) + Error( err ); + +return result; +} + + +void Gamma(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + + result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating); + + if(err != err_ok) + Error( err ); +} + + +/*! + factorial + result = 1 * 2 * 3 * 4 * .... * x +*/ +void Factorial(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + + result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating); + + if(err != err_ok) + Error( err ); +} + + +void Abs(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ttmath::Abs(stack[sindex].value); +} + +void Sin(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err ); + + if(err != err_ok) + Error( err ); +} + +void Cos(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err ); + + if(err != err_ok) + Error( err ); +} + +void Tan(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Tan(ConvertAngleToRad(stack[sindex].value), &err); + + if(err != err_ok) + Error( err ); +} + +void Cot(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Cot(ConvertAngleToRad(stack[sindex].value), &err); + + if(err != err_ok) + Error( err ); +} + +void Int(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ttmath::SkipFraction(stack[sindex].value); +} + + +void Round(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = stack[sindex].value; + + if( result.Round() ) + Error( err_overflow ); +} + + +void Ln(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Ln(stack[sindex].value, &err); + + if(err != err_ok) + Error( err ); +} + +void Log(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 2 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Log(stack[sindex].value, stack[sindex+2].value, &err); + + if(err != err_ok) + Error( err ); +} + +void Exp(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Exp(stack[sindex].value, &err); + + if(err != err_ok) + Error( err ); +} + + +void Max(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args == 0 ) + { + result.SetMax(); + + return; + } + + result = stack[sindex].value; + + for(int i=1 ; i stack[sindex + i*2].value ) + result = stack[sindex + i*2].value; + } +} + + +void ASin(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + ValueType temp = ttmath::ASin(stack[sindex].value, &err); + + if(err != err_ok) + Error( err ); + + result = ConvertRadToAngle(temp); +} + + +void ACos(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + ValueType temp = ttmath::ACos(stack[sindex].value, &err); + + if(err != err_ok) + Error( err ); + + result = ConvertRadToAngle(temp); +} + + +void ATan(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ConvertRadToAngle(ttmath::ATan(stack[sindex].value)); +} + + +void ACot(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ConvertRadToAngle(ttmath::ACot(stack[sindex].value)); +} + + +void Sgn(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ttmath::Sgn(stack[sindex].value); +} + + +void Mod(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 2 ) + Error( err_improper_amount_of_arguments ); + + if( stack[sindex+2].value.IsZero() ) + Error( err_improper_argument ); + + result = stack[sindex].value; + uint c = result.Mod(stack[sindex+2].value); + + if( c ) + Error( err_overflow ); +} + + +void If(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 3 ) + Error( err_improper_amount_of_arguments ); + + + if( !stack[sindex].value.IsZero() ) + result = stack[sindex+2].value; + else + result = stack[sindex+4].value; +} + + +void Or(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args < 2 ) + Error( err_improper_amount_of_arguments ); + + for(int i=0 ; iGetValueAndParam(function_name, &string_value, ¶m) != err_ok ) + return false; + + if( param != amount_of_args ) + Error( err_improper_amount_of_arguments ); + + + FunctionLocalVariables local_variables; + + if( amount_of_args > 0 ) + { + char buffer[30]; + + // x = x1 + buffer[0] = 'x'; + buffer[1] = 0; + local_variables.insert( std::make_pair(buffer, stack[sindex].value) ); + + for(int i=0 ; i*(i->second))(sindex, amount_of_args, stack[sindex-1].value); + calculated = true; +} + + + + + +/*! + inserting a function to the functions' table + + function_name - name of the function + pf - pointer to the function (to the wrapper) +*/ +void InsertFunctionToTable(const char * function_name, pfunction pf) +{ + std::string str; + Misc::AssignString(str, function_name); + + functions_table.insert( std::make_pair(str, pf) ); +} + + + +/*! + inserting a function to the variables' table + (this function returns value of variable) + + variable_name - name of the function + pf - pointer to the function +*/ +void InsertVariableToTable(const char * variable_name, pfunction_var pf) +{ + std::string str; + Misc::AssignString(str, variable_name); + + variables_table.insert( std::make_pair(str, pf) ); +} + + +/*! + this method creates the table of functions +*/ +void CreateFunctionsTable() +{ + InsertFunctionToTable("gamma", &Parser::Gamma); + InsertFunctionToTable("factorial", &Parser::Factorial); + InsertFunctionToTable("abs", &Parser::Abs); + InsertFunctionToTable("sin", &Parser::Sin); + InsertFunctionToTable("cos", &Parser::Cos); + InsertFunctionToTable("tan", &Parser::Tan); + InsertFunctionToTable("tg", &Parser::Tan); + InsertFunctionToTable("cot", &Parser::Cot); + InsertFunctionToTable("ctg", &Parser::Cot); + InsertFunctionToTable("int", &Parser::Int); + InsertFunctionToTable("round", &Parser::Round); + InsertFunctionToTable("ln", &Parser::Ln); + InsertFunctionToTable("log", &Parser::Log); + InsertFunctionToTable("exp", &Parser::Exp); + InsertFunctionToTable("max", &Parser::Max); + InsertFunctionToTable("min", &Parser::Min); + InsertFunctionToTable("asin", &Parser::ASin); + InsertFunctionToTable("acos", &Parser::ACos); + InsertFunctionToTable("atan", &Parser::ATan); + InsertFunctionToTable("atg", &Parser::ATan); + InsertFunctionToTable("acot", &Parser::ACot); + InsertFunctionToTable("actg", &Parser::ACot); + InsertFunctionToTable("sgn", &Parser::Sgn); + InsertFunctionToTable("mod", &Parser::Mod); + InsertFunctionToTable("if", &Parser::If); + InsertFunctionToTable("or", &Parser::Or); + InsertFunctionToTable("and", &Parser::And); + InsertFunctionToTable("not", &Parser::Not); + InsertFunctionToTable("degtorad", &Parser::DegToRad); + InsertFunctionToTable("radtodeg", &Parser::RadToDeg); + InsertFunctionToTable("degtodeg", &Parser::DegToDeg); + InsertFunctionToTable("gradtorad", &Parser::GradToRad); + InsertFunctionToTable("radtograd", &Parser::RadToGrad); + InsertFunctionToTable("degtograd", &Parser::DegToGrad); + InsertFunctionToTable("gradtodeg", &Parser::GradToDeg); + InsertFunctionToTable("ceil", &Parser::Ceil); + InsertFunctionToTable("floor", &Parser::Floor); + InsertFunctionToTable("sqrt", &Parser::Sqrt); + InsertFunctionToTable("sinh", &Parser::Sinh); + InsertFunctionToTable("cosh", &Parser::Cosh); + InsertFunctionToTable("tanh", &Parser::Tanh); + InsertFunctionToTable("tgh", &Parser::Tanh); + InsertFunctionToTable("coth", &Parser::Coth); + InsertFunctionToTable("ctgh", &Parser::Coth); + InsertFunctionToTable("root", &Parser::Root); + InsertFunctionToTable("asinh", &Parser::ASinh); + InsertFunctionToTable("acosh", &Parser::ACosh); + InsertFunctionToTable("atanh", &Parser::ATanh); + InsertFunctionToTable("atgh", &Parser::ATanh); + InsertFunctionToTable("acoth", &Parser::ACoth); + InsertFunctionToTable("actgh", &Parser::ACoth); + InsertFunctionToTable("bitand", &Parser::BitAnd); + InsertFunctionToTable("bitor", &Parser::BitOr); + InsertFunctionToTable("bitxor", &Parser::BitXor); + InsertFunctionToTable("band", &Parser::BitAnd); + InsertFunctionToTable("bor", &Parser::BitOr); + InsertFunctionToTable("bxor", &Parser::BitXor); + InsertFunctionToTable("sum", &Parser::Sum); + InsertFunctionToTable("avg", &Parser::Avg); + InsertFunctionToTable("frac", &Parser::Frac); +} + + +/*! + this method creates the table of variables +*/ +void CreateVariablesTable() +{ + InsertVariableToTable("pi", &ValueType::SetPi); + InsertVariableToTable("e", &ValueType::SetE); +} + + +/*! + converting from a big letter to a small one +*/ +int ToLowerCase(int c) +{ + if( c>='A' && c<='Z' ) + return c - 'A' + 'a'; + +return c; +} + + +/*! + this method read the name of a variable or a function + + 'result' will be the name of a variable or a function + function return 'false' if this name is the name of a variable + or function return 'true' if this name is the name of a function + + what should be returned is tested just by a '(' character that means if there's + a '(' character after a name that function returns 'true' +*/ +bool ReadName(std::string & result) +{ +int character; + + + result.erase(); + character = *pstring; + + /* + the first letter must be from range 'a' - 'z' or 'A' - 'Z' + */ + if( ! (( character>='a' && character<='z' ) || ( character>='A' && character<='Z' )) ) + Error( err_unknown_character ); + + + do + { + result += static_cast( character ); + character = * ++pstring; + } + while( (character>='a' && character<='z') || + (character>='A' && character<='Z') || + (character>='0' && character<='9') || + character=='_' ); + + + SkipWhiteCharacters(); + + + /* + if there's a character '(' that means this name is a name of a function + */ + if( *pstring == '(' ) + { + ++pstring; + return true; + } + + +return false; +} + + +/*! + we're checking whether the first character is '-' or '+' + if it is we'll return 'true' and if it is equally '-' we'll set the 'sign' member of 'result' +*/ +bool TestSign(Item & result) +{ + SkipWhiteCharacters(); + result.sign = false; + + if( *pstring == '-' || *pstring == '+' ) + { + if( *pstring == '-' ) + result.sign = true; + + ++pstring; + + return true; + } + +return false; +} + + +/*! + we're reading the name of a variable or a function + if is there a function we'll return 'true' +*/ +bool ReadVariableOrFunction(Item & result) +{ +std::string name; +bool is_it_name_of_function = ReadName(name); + + if( is_it_name_of_function ) + { + /* + we've read the name of a function + */ + result.function_name = name; + result.type = Item::first_bracket; + result.function = true; + } + else + { + /* + we've read the name of a variable and we're getting its value now + */ + result.value = GetValueOfVariable( name ); + } + +return is_it_name_of_function; +} + + + + +/*! + we're reading a numerical value directly from the string +*/ +void ReadValue(Item & result, int reading_base) +{ +const char * new_stack_pointer; +bool value_read; +Conv conv; + + conv.base = reading_base; + conv.comma = comma; + conv.comma2 = comma2; + conv.group = group; + + uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read); + pstring = new_stack_pointer; + + if( carry ) + Error( err_overflow ); + + if( !value_read ) + Error( err_unknown_character ); +} + + +/*! + this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too) +*/ +bool ValueStarts(int character, int base) +{ + if( character == comma ) + return true; + + if( comma2!=0 && character==comma2 ) + return true; + + if( Misc::CharToDigit(character, base) != -1 ) + return true; + +return false; +} + + +/*! + we're reading the item + + return values: + 0 - all ok, the item is successfully read + 1 - the end of the string (the item is not read) + 2 - the final bracket ')' +*/ +int ReadValueVariableOrFunction(Item & result) +{ +bool it_was_sign = false; +int character; + + + if( TestSign(result) ) + // 'result.sign' was set as well + it_was_sign = true; + + SkipWhiteCharacters(); + character = ToLowerCase( *pstring ); + + + if( character == 0 ) + { + if( it_was_sign ) + // at the end of the string a character like '-' or '+' has left + Error( err_unexpected_end ); + + // there's the end of the string here + return 1; + } + else + if( character == '(' ) + { + // we've got a normal bracket (not a function) + result.type = Item::first_bracket; + result.function = false; + ++pstring; + + return 0; + } + else + if( character == ')' ) + { + // we've got a final bracket + // (in this place we can find a final bracket only when there are empty brackets + // without any values inside or with a sign '-' or '+' inside) + + if( it_was_sign ) + Error( err_unexpected_final_bracket ); + + result.type = Item::last_bracket; + + // we don't increment 'pstring', this final bracket will be read next by the + // 'ReadOperatorAndCheckFinalBracket(...)' method + + return 2; + } + else + if( character == '#' ) + { + ++pstring; + SkipWhiteCharacters(); + + // after '#' character we do not allow '-' or '+' (can be white characters) + if( ValueStarts(*pstring, 16) ) + ReadValue( result, 16 ); + else + Error( err_unknown_character ); + } + else + if( character == '&' ) + { + ++pstring; + SkipWhiteCharacters(); + + // after '&' character we do not allow '-' or '+' (can be white characters) + if( ValueStarts(*pstring, 2) ) + ReadValue( result, 2 ); + else + Error( err_unknown_character ); + } + else + if( ValueStarts(character, base) ) + { + ReadValue( result, base ); + } + else + if( character>='a' && character<='z' ) + { + if( ReadVariableOrFunction(result) ) + // we've read the name of a function + return 0; + } + else + Error( err_unknown_character ); + + + + /* + we've got a value in the 'result' + this value is from a variable or directly from the string + */ + result.type = Item::numerical_value; + + if( result.sign ) + { + result.value.ChangeSign(); + result.sign = false; + } + + +return 0; +} + + +void InsertOperatorToTable(const char * name, typename MatOperator::Type type) +{ + operators_table.insert( std::make_pair(std::string(name), type) ); +} + + +/*! + this method creates the table of operators +*/ +void CreateMathematicalOperatorsTable() +{ + InsertOperatorToTable("||", MatOperator::lor); + InsertOperatorToTable("&&", MatOperator::land); + InsertOperatorToTable("!=", MatOperator::neq); + InsertOperatorToTable("==", MatOperator::eq); + InsertOperatorToTable(">=", MatOperator::get); + InsertOperatorToTable("<=", MatOperator::let); + InsertOperatorToTable(">", MatOperator::gt); + InsertOperatorToTable("<", MatOperator::lt); + InsertOperatorToTable("-", MatOperator::sub); + InsertOperatorToTable("+", MatOperator::add); + InsertOperatorToTable("/", MatOperator::div); + InsertOperatorToTable("*", MatOperator::mul); + InsertOperatorToTable("^", MatOperator::pow); +} + + +/*! + returns true if 'str2' is the substring of str1 + + e.g. + true when str1="test" and str2="te" +*/ +bool IsSubstring(const std::string & str1, const std::string & str2) +{ + if( str2.length() > str1.length() ) + return false; + + for(typename std::string::size_type i=0 ; ifirst, oper) ) + { + oper.erase( --oper.end() ); // we've got mininum one element + + if( iter_old != operators_table.end() && iter_old->first == oper ) + { + result.type = Item::mat_operator; + result.moperator.SetType( iter_old->second ); + break; + } + + Error( err_unknown_operator ); + } + + iter_old = iter_new; + } +} + + +/*! + this method makes a calculation for the percentage operator + e.g. + 1000-50% = 1000-(1000*0,5) = 500 +*/ +void OperatorPercentage() +{ + if( stack_index < 3 || + stack[stack_index-1].type != Item::numerical_value || + stack[stack_index-2].type != Item::mat_operator || + stack[stack_index-3].type != Item::numerical_value ) + Error(err_percent_from); + + ++pstring; + SkipWhiteCharacters(); + + uint c = 0; + c += stack[stack_index-1].value.Div(100); + c += stack[stack_index-1].value.Mul(stack[stack_index-3].value); + + if( c ) + Error(err_overflow); +} + + +/*! + this method reads a mathematic operators + or the final bracket or the semicolon operator + + return values: + 0 - ok + 1 - the string is finished +*/ +int ReadOperator(Item & result) +{ + SkipWhiteCharacters(); + + if( *pstring == '%' ) + OperatorPercentage(); + + + if( *pstring == 0 ) + return 1; + else + if( *pstring == ')' ) + { + result.type = Item::last_bracket; + ++pstring; + } + else + if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) ) + { + result.type = Item::semicolon; + ++pstring; + } + else + if( (*pstring>='a' && *pstring<='z') || (*pstring>='A' && *pstring<='Z') ) + { + // short mul (without any operators) + + result.type = Item::mat_operator; + result.moperator.SetType( MatOperator::shortmul ); + } + else + ReadMathematicalOperator(result); + +return 0; +} + + + +/*! + this method is making the standard mathematic operation like '-' '+' '*' '/' and '^' + + the operation is made between 'value1' and 'value2' + the result of this operation is stored in the 'value1' +*/ +void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator, + const ValueType & value2) +{ +uint res; + + calculated = true; + + switch( mat_operator ) + { + case MatOperator::land: + (!value1.IsZero() && !value2.IsZero()) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::lor: + (!value1.IsZero() || !value2.IsZero()) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::eq: + (value1 == value2) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::neq: + (value1 != value2) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::lt: + (value1 < value2) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::gt: + (value1 > value2) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::let: + (value1 <= value2) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::get: + (value1 >= value2) ? value1.SetOne() : value1.SetZero(); + break; + + case MatOperator::sub: + if( value1.Sub(value2) ) Error( err_overflow ); + break; + + case MatOperator::add: + if( value1.Add(value2) ) Error( err_overflow ); + break; + + case MatOperator::mul: + case MatOperator::shortmul: + if( value1.Mul(value2) ) Error( err_overflow ); + break; + + case MatOperator::div: + if( value2.IsZero() ) Error( err_division_by_zero ); + if( value1.Div(value2) ) Error( err_overflow ); + break; + + case MatOperator::pow: + res = value1.Pow( value2 ); + + if( res == 1 ) Error( err_overflow ); + else + if( res == 2 ) Error( err_improper_argument ); + + break; + + default: + /* + on the stack left an unknown operator but we had to recognize its before + that means there's an error in our algorithm + */ + Error( err_internal_error ); + } +} + + + + +/*! + this method is trying to roll the stack up with the operator's priority + + for example if there are: + "1 - 2 +" + we can subtract "1-2" and the result store on the place where is '1' and copy the last + operator '+', that means there'll be '-1+' on our stack + + but if there are: + "1 - 2 *" + we can't roll the stack up because the operator '*' has greater priority than '-' +*/ +void TryRollingUpStackWithOperatorPriority() +{ + while( stack_index>=4 && + stack[stack_index-4].type == Item::numerical_value && + stack[stack_index-3].type == Item::mat_operator && + stack[stack_index-2].type == Item::numerical_value && + stack[stack_index-1].type == Item::mat_operator && + ( + ( + // the first operator has greater priority + stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority() + ) || + ( + // or both operators have the same priority and the first operator is not right associative + stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() && + stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right + ) + ) + ) + { + MakeStandardMathematicOperation(stack[stack_index-4].value, + stack[stack_index-3].moperator.GetType(), + stack[stack_index-2].value); + + + /* + copying the last operator and setting the stack pointer to the correct value + */ + stack[stack_index-3] = stack[stack_index-1]; + stack_index -= 2; + } +} + + +/*! + this method is trying to roll the stack up without testing any operators + + for example if there are: + "1 - 2" + there'll be "-1" on our stack +*/ +void TryRollingUpStack() +{ + while( stack_index >= 3 && + stack[stack_index-3].type == Item::numerical_value && + stack[stack_index-2].type == Item::mat_operator && + stack[stack_index-1].type == Item::numerical_value ) + { + MakeStandardMathematicOperation( stack[stack_index-3].value, + stack[stack_index-2].moperator.GetType(), + stack[stack_index-1].value ); + + stack_index -= 2; + } +} + + +/*! + this method is reading a value or a variable or a function + (the normal first bracket as well) and push it into the stack +*/ +int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp) +{ +int code = ReadValueVariableOrFunction( temp ); + + if( code == 0 ) + { + if( stack_index < stack.size() ) + stack[stack_index] = temp; + else + stack.push_back( temp ); + + ++stack_index; + } + + if( code == 2 ) + // there was a final bracket, we didn't push it into the stack + // (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next) + code = 0; + + +return code; +} + + + +/*! + this method calculate how many parameters there are on the stack + and the index of the first parameter + + if there aren't any parameters on the stack this method returns + 'size' equals zero and 'index' pointing after the first bracket + (on non-existend element) +*/ +void HowManyParameters(int & size, int & index) +{ + size = 0; + index = stack_index; + + if( index == 0 ) + // we haven't put a first bracket on the stack + Error( err_unexpected_final_bracket ); + + + if( stack[index-1].type == Item::first_bracket ) + // empty brackets + return; + + for( --index ; index>=1 ; index-=2 ) + { + if( stack[index].type != Item::numerical_value ) + { + /* + this element must be 'numerical_value', if not that means + there's an error in our algorithm + */ + Error( err_internal_error ); + } + + ++size; + + if( stack[index-1].type != Item::semicolon ) + break; + } + + if( index<1 || stack[index-1].type != Item::first_bracket ) + { + /* + we haven't put a first bracket on the stack + */ + Error( err_unexpected_final_bracket ); + } +} + + +/*! + this method is being called when the final bracket ')' is being found + + this method's rolling the stack up, counting how many parameters there are + on the stack and if there was a function it's calling the function +*/ +void RollingUpFinalBracket() +{ +int amount_of_parameters; +int index; + + + if( stack_index<1 || + (stack[stack_index-1].type != Item::numerical_value && + stack[stack_index-1].type != Item::first_bracket) + ) + Error( err_unexpected_final_bracket ); + + + TryRollingUpStack(); + HowManyParameters(amount_of_parameters, index); + + // 'index' will be greater than zero + // 'amount_of_parameters' can be zero + + + if( amount_of_parameters==0 && !stack[index-1].function ) + Error( err_unexpected_final_bracket ); + + + bool was_sign = stack[index-1].sign; + + + if( stack[index-1].function ) + { + // the result of a function will be on 'stack[index-1]' + // and then at the end we'll set the correct type (numerical value) of this element + CallFunction(stack[index-1].function_name, amount_of_parameters, index); + } + else + { + /* + there was a normal bracket (not a funcion) + */ + if( amount_of_parameters != 1 ) + Error( err_unexpected_semicolon_operator ); + + + /* + in the place where is the bracket we put the result + */ + stack[index-1] = stack[index]; + } + + + /* + if there was a '-' character before the first bracket + we change the sign of the expression + */ + stack[index-1].sign = false; + + if( was_sign ) + stack[index-1].value.ChangeSign(); + + stack[index-1].type = Item::numerical_value; + + + /* + the pointer of the stack will be pointing on the next (non-existing now) element + */ + stack_index = index; +} + + +/*! + this method is putting the operator on the stack +*/ + +void PushOperatorIntoStack(Item & temp) +{ + if( stack_index < stack.size() ) + stack[stack_index] = temp; + else + stack.push_back( temp ); + + ++stack_index; +} + + + +/*! + this method is reading a operator and if it's a final bracket + it's calling RollingUpFinalBracket() and reading a operator again +*/ +int ReadOperatorAndCheckFinalBracket(Item & temp) +{ + do + { + if( ReadOperator(temp) == 1 ) + { + /* + the string is finished + */ + return 1; + } + + if( temp.type == Item::last_bracket ) + RollingUpFinalBracket(); + + } + while( temp.type == Item::last_bracket ); + +return 0; +} + + +/*! + we check wheter there are only numerical value's or 'semicolon' operators on the stack +*/ +void CheckIntegrityOfStack() +{ + for(unsigned int i=0 ; iWasStopSignal() ) + Error( err_interrupt ); + + result_code = ReadValueVariableOrFunctionAndPushItIntoStack( item ); + + if( result_code == 0 ) + { + if( item.type == Item::first_bracket ) + continue; + + result_code = ReadOperatorAndCheckFinalBracket( item ); + } + + + if( result_code==1 || item.type==Item::semicolon ) + { + /* + the string is finished or the 'semicolon' operator has appeared + */ + + if( stack_index == 0 ) + Error( err_nothing_has_read ); + + TryRollingUpStack(); + + if( result_code == 1 ) + { + CheckIntegrityOfStack(); + + return; + } + } + + + PushOperatorIntoStack( item ); + TryRollingUpStackWithOperatorPriority(); + } +} + +/*! + this method is called at the end of the parsing process + + on our stack we can have another value than 'numerical_values' for example + when someone use the operator ';' in the global scope or there was an error during + parsing and the parser hasn't finished its job + + if there was an error the stack is cleaned up now + otherwise we resize stack and leave on it only 'numerical_value' items +*/ +void NormalizeStack() +{ + if( error!=err_ok || stack_index==0 ) + { + stack.clear(); + return; + } + + + /* + 'stack_index' tell us how many elements there are on the stack, + we must resize the stack now because 'stack_index' is using only for parsing + and stack has more (or equal) elements than value of 'stack_index' + */ + stack.resize( stack_index ); + + for(uint i=stack_index-1 ; i!=uint(-1) ; --i) + { + if( stack[i].type != Item::numerical_value ) + stack.erase( stack.begin() + i ); + } +} + + +public: + + +/*! + the default constructor +*/ +Parser(): default_stack_size(100) +{ + pstop_calculating = 0; + puser_variables = 0; + puser_functions = 0; + pfunction_local_variables = 0; + base = 10; + deg_rad_grad = 1; + error = err_ok; + group = 0; + comma = '.'; + comma2 = ','; + param_sep = 0; + + CreateFunctionsTable(); + CreateVariablesTable(); + CreateMathematicalOperatorsTable(); +} + + +/*! + the assignment operator +*/ +Parser & operator=(const Parser & p) +{ + pstop_calculating = p.pstop_calculating; + puser_variables = p.puser_variables; + puser_functions = p.puser_functions; + pfunction_local_variables = 0; + base = p.base; + deg_rad_grad = p.deg_rad_grad; + error = p.error; + group = p.group; + comma = p.comma; + comma2 = p.comma2; + param_sep = p.param_sep; + + /* + we don't have to call 'CreateFunctionsTable()' etc. + we can only copy these tables + */ + functions_table = p.functions_table; + variables_table = p.variables_table; + operators_table = p.operators_table; + + visited_variables = p.visited_variables; + visited_functions = p.visited_functions; + +return *this; +} + + +/*! + the copying constructor +*/ +Parser(const Parser & p): default_stack_size(p.default_stack_size) +{ + operator=(p); +} + + +/*! + the new base of mathematic system + default is 10 +*/ +void SetBase(int b) +{ + if( b>=2 && b<=16 ) + base = b; +} + + +/*! + the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot + 0 - deg + 1 - rad (default) + 2 - grad +*/ +void SetDegRadGrad(int angle) +{ + if( angle >= 0 || angle <= 2 ) + deg_rad_grad = angle; +} + +/*! + this method sets a pointer to the object which tell us whether we should stop + calculations +*/ +void SetStopObject(const volatile StopCalculating * ps) +{ + pstop_calculating = ps; +} + + +/*! + this method sets the new table of user-defined variables + if you don't want any other variables just put zero value into the 'puser_variables' variable + + (you can have only one table at the same time) +*/ +void SetVariables(const Objects * pv) +{ + puser_variables = pv; +} + + +/*! + this method sets the new table of user-defined functions + if you don't want any other functions just put zero value into the 'puser_functions' variable + + (you can have only one table at the same time) +*/ +void SetFunctions(const Objects * pf) +{ + puser_functions = pf; +} + + +/*! + setting the group character + default zero (not used) +*/ +void SetGroup(int g) +{ + group = g; +} + + +/*! + setting the main comma operator and the additional comma operator + the additional operator can be zero (which means it is not used) + default are: '.' and ',' +*/ +void SetComma(int c, int c2 = 0) +{ + comma = c; + comma2 = c2; +} + + +/*! + setting an additional character which is used as a parameters separator + the main parameters separator is a semicolon (is used always) + + this character is used also as a global separator +*/ +void SetParamSep(int s) +{ + param_sep = s; +} + + +/*! + the main method using for parsing string +*/ +ErrorCode Parse(const char * str) +{ + stack_index = 0; + pstring = str; + error = err_ok; + calculated = false; + + stack.resize( default_stack_size ); + + try + { + Parse(); + } + catch(ErrorCode c) + { + error = c; + calculated = false; + } + + NormalizeStack(); + +return error; +} + + +/*! + the main method using for parsing string +*/ +ErrorCode Parse(const std::string & str) +{ + return Parse(str.c_str()); +} + + +/*! + the main method using for parsing string +*/ +ErrorCode Parse(const wchar_t * str) +{ + Misc::AssignString(wide_to_ansi, str); + +return Parse(wide_to_ansi.c_str()); +} + + +/*! + the main method using for parsing string +*/ +ErrorCode Parse(const std::wstring & str) +{ + return Parse(str.c_str()); +} + + +/*! + this method returns true is something was calculated + (at least one mathematical operator was used or a function or variable) + e.g. true if the string to Parse() looked like this: + "1+1" + "2*3" + "sin(5)" + + if the string was e.g. "678" the result is false +*/ +bool Calculated() +{ + return calculated; +} + + +}; + + + +} // namespace + + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmaththreads.h b/src/libghost/ttmath/ttmath/ttmaththreads.h new file mode 100644 index 0000000..586227f --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmaththreads.h @@ -0,0 +1,250 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef headerfilettmaththreads +#define headerfilettmaththreads + +#include "ttmathtypes.h" + +#ifdef TTMATH_WIN32_THREADS +#include +#include +#endif + +#ifdef TTMATH_POSIX_THREADS +#include +#endif + + + +/*! + \file ttmaththreads.h + \brief Some objects used in multithreads environment +*/ + + +/* + this is a simple skeleton of a program in multithreads environment: + + #define TTMATH_MULTITHREADS + #include + + TTMATH_MULTITHREADS_HELPER + + int main() + { + [...] + } + + make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file) + use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope) +*/ + + +namespace ttmath +{ + + +#ifdef TTMATH_WIN32_THREADS + + /* + we use win32 threads + */ + + + /*! + in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro + somewhere in *.cpp file + + (at the moment in win32 this macro does nothing) + */ + #define TTMATH_MULTITHREADS_HELPER + + + /*! + objects of this class are used to synchronize + */ + class ThreadLock + { + HANDLE mutex_handle; + + + void CreateName(char * buffer) const + { + #ifdef _MSC_VER + #pragma warning (disable : 4996) + // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. + #endif + + sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId()); + + #ifdef _MSC_VER + #pragma warning (default : 4996) + #endif + } + + + public: + + bool Lock() + { + char buffer[50]; + + CreateName(buffer); + mutex_handle = CreateMutexA(0, false, buffer); + + if( mutex_handle == 0 ) + return false; + + WaitForSingleObject(mutex_handle, INFINITE); + + return true; + } + + + ThreadLock() + { + mutex_handle = 0; + } + + + ~ThreadLock() + { + if( mutex_handle != 0 ) + { + ReleaseMutex(mutex_handle); + CloseHandle(mutex_handle); + } + } + }; + +#endif // #ifdef TTMATH_WIN32_THREADS + + + + + +#ifdef TTMATH_POSIX_THREADS + + /* + we use posix threads + */ + + + /*! + in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro + somewhere in *.cpp file + (this macro defines a pthread_mutex_t object used by TTMath library) + */ + #define TTMATH_MULTITHREADS_HELPER \ + namespace ttmath \ + { \ + pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \ + } + + + /*! + ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro + */ + extern pthread_mutex_t ttmath_mutex; + + + /*! + objects of this class are used to synchronize + */ + class ThreadLock + { + public: + + bool Lock() + { + if( pthread_mutex_lock(&ttmath_mutex) != 0 ) + return false; + + return true; + } + + + ~ThreadLock() + { + pthread_mutex_unlock(&ttmath_mutex); + } + }; + +#endif // #ifdef TTMATH_POSIX_THREADS + + + + +#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) + + /*! + we don't use win32 and pthreads + */ + + /*! + */ + #define TTMATH_MULTITHREADS_HELPER + + + /*! + objects of this class are used to synchronize + actually we don't synchronize, the method Lock() returns always 'false' + */ + class ThreadLock + { + public: + + bool Lock() + { + return false; + } + }; + + +#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) + + + + + +} // namespace + +#endif + diff --git a/src/libghost/ttmath/ttmath/ttmathtypes.h b/src/libghost/ttmath/ttmath/ttmathtypes.h new file mode 100644 index 0000000..f3236ea --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathtypes.h @@ -0,0 +1,646 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2010, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef headerfilettmathtypes +#define headerfilettmathtypes + +/*! + \file ttmathtypes.h + \brief constants used in the library + + As our library is written in header files (templates) we cannot use + constants like 'const int' etc. because we should have some source files + *.cpp to define this variables. Only what we can have are constants + defined by #define preprocessor macros. + + All macros are preceded by TTMATH_ prefix +*/ + + +#include +#include +#include + +/*! + the version of the library + + TTMATH_PRERELEASE_VER is either zero or one + if zero that means this is the release version of the library +*/ +#define TTMATH_MAJOR_VER 0 +#define TTMATH_MINOR_VER 9 +#define TTMATH_REVISION_VER 1 +#define TTMATH_PRERELEASE_VER 0 + + +/*! + TTMATH_DEBUG + this macro enables further testing during writing your code + you don't have to define it in a release mode + + if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT + are set as well and these macros can throw an exception if a condition in it + is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) + + TTMATH_RELEASE + if you are confident that your code is perfect you can define TTMATH_RELEASE + macro for example by using -D option in gcc + gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp + or by defining this macro in your code before using any header files of this library + + if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically +*/ +#ifndef TTMATH_RELEASE + #define TTMATH_DEBUG +#endif + + + +namespace ttmath +{ + +#if !defined _M_X64 && !defined __x86_64__ + + /*! + we're using a 32bit platform + */ + #define TTMATH_PLATFORM32 + +#else + + /*! + we're using a 64bit platform + */ + #define TTMATH_PLATFORM64 + +#endif + + + +/*! + another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM) +*/ +#if !defined _MSC_VER && !defined __GNUC__ + #define TTMATH_NOASM +#endif + + + +#ifdef TTMATH_PLATFORM32 + + /*! + on 32bit platforms one word (uint, sint) will be equal 32bits + */ + typedef unsigned int uint; + typedef signed int sint; + + /*! + this type is twice bigger than uint + (64bit on a 32bit platforms) + + although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long) + but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it + + this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined + but only on a 32bit platform + */ + #ifdef TTMATH_NOASM + typedef unsigned long long int ulint; + #endif + + /*! + how many bits there are in the uint type + */ + #define TTMATH_BITS_PER_UINT 32u + + /*! + the mask for the highest bit in the unsigned 32bit word (2^31) + */ + #define TTMATH_UINT_HIGHEST_BIT 2147483648u + + /*! + the max value of the unsigned 32bit word (2^32 - 1) + (all bits equal one) + */ + #define TTMATH_UINT_MAX_VALUE 4294967295u + + /*! + the number of words (32bit words on 32bit platform) + which are kept in built-in variables for a Big<> type + (these variables are defined in ttmathbig.h) + */ + #define TTMATH_BUILTIN_VARIABLES_SIZE 256u + + /*! + this macro returns the number of machine words + capable to hold min_bits bits + e.g. TTMATH_BITS(128) returns 4 + */ + #define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1) + +#else + + /*! + on 64bit platforms one word (uint, sint) will be equal 64bits + */ + #ifdef _MSC_VER + /* in VC 'long' type has 32 bits, __int64 is VC extension */ + typedef unsigned __int64 uint; + typedef signed __int64 sint; + #else + typedef unsigned long uint; + typedef signed long sint; + #endif + + /*! + on 64bit platform we do not define ulint + sizeof(long long) is 8 (64bit) but we need 128bit + + on 64 bit platform (when there is defined TTMATH_NOASM macro) + methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit + */ + //typedef unsigned long long int ulint; + + /*! + how many bits there are in the uint type + */ + #define TTMATH_BITS_PER_UINT 64ul + + /*! + the mask for the highest bit in the unsigned 64bit word (2^63) + */ + #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul + + /*! + the max value of the unsigned 64bit word (2^64 - 1) + (all bits equal one) + */ + #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul + + /*! + the number of words (64bit words on 64bit platforms) + which are kept in built-in variables for a Big<> type + (these variables are defined in ttmathbig.h) + */ + #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul + + /*! + this macro returns the number of machine words + capable to hold min_bits bits + e.g. TTMATH_BITS(128) returns 2 + */ + #define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1) + +#endif +} + + +#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC) + #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) + + #if defined(_WIN32) + #define TTMATH_WIN32_THREADS + #elif defined(unix) || defined(__unix__) || defined(__unix) + #define TTMATH_POSIX_THREADS + #endif + + #endif +#endif + + + +/*! + this variable defines how many iterations are performed + during some kind of calculating when we're making any long formulas + (for example Taylor series) + + it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. + + note! there'll not be so many iterations, iterations are stopped when + there is no sense to continue calculating (for example when the result + still remains unchanged after adding next series and we know that the next + series are smaller than previous ones) +*/ +#define TTMATH_ARITHMETIC_MAX_LOOP 10000 + + + +/*! + this is a limit when calculating Karatsuba multiplication + if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE + the Karatsuba algorithm will use standard schoolbook multiplication +*/ +#ifdef TTMATH_DEBUG_LOG + // if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler + #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 +#else + #ifdef __GNUC__ + #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 + #else + #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 + #endif +#endif + + +/*! + this is a special value used when calculating the Gamma(x) function + if x is greater than this value then the Gamma(x) will be calculated using + some kind of series + + don't use smaller values than about 100 +*/ +#define TTMATH_GAMMA_BOUNDARY 2000 + + + + + +namespace ttmath +{ + + /*! + lib type codes: + asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) + asm_gcc_32 - with asm code designed for GCC (32 bits) + asm_vc_64 - with asm for VC (64 bit) + asm_gcc_64 - with asm for GCC (64 bit) + no_asm_32 - pure C++ version (32 bit) - without any asm code + no_asm_64 - pure C++ version (64 bit) - without any asm code + */ + enum LibTypeCode + { + asm_vc_32 = 0, + asm_gcc_32, + asm_vc_64, + asm_gcc_64, + no_asm_32, + no_asm_64 + }; + + + /*! + error codes + */ + enum ErrorCode + { + err_ok = 0, + err_nothing_has_read, + err_unknown_character, + err_unexpected_final_bracket, + err_stack_not_clear, + err_unknown_variable, + err_division_by_zero, + err_interrupt, + err_overflow, + err_unknown_function, + err_unknown_operator, + err_unexpected_semicolon_operator, + err_improper_amount_of_arguments, + err_improper_argument, + err_unexpected_end, + err_internal_error, + err_incorrect_name, + err_incorrect_value, + err_variable_exists, + err_variable_loop, + err_functions_loop, + err_must_be_only_one_value, + err_object_exists, + err_unknown_object, + err_still_calculating, + err_in_short_form_used_function, + err_percent_from + }; + + + /*! + this struct is used when converting to/from a string + /temporarily only in Big::ToString() and Big::FromString()/ + */ + struct Conv + { + /*! + base (radix) on which the value will be shown (or read) + default: 10 + */ + uint base; + + + /*! + used only in Big::ToString() + if true the value will be always shown in the scientific mode, e.g: 123e+30 + default: false + */ + bool scient; + + + /*! + used only in Big::ToString() + if scient is false then the value will be print in the scientific mode + only if the exponent is greater than scien_from + default: 15 + */ + sint scient_from; + + + /*! + if 'base_round' is true and 'base' is different from 2, 4, 8, or 16 + and the result value is not an integer then we make an additional rounding + (after converting the last digit from the result is skipped) + default: true + + e.g. + Conv c; + c.base_round = false; + Big<1, 1> a = "0.1"; // decimal input + std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999 + */ + bool base_round; + + + /*! + used only in Big::ToString() + tells how many digits after comma are possible + default: -1 which means all digits are printed + + set it to zero if you want integer value only + + for example when the value is: + 12.345678 and 'round' is 4 + then the result will be + 12.3457 (the last digit was rounded) + */ + sint round; + + + /*! + if true that not mattered digits in the mantissa will be cut off + (zero characters at the end -- after the comma operator) + e.g. 1234,78000 will be: 1234,78 + default: true + */ + bool trim_zeroes; + + + /*! + the main comma operator (used when reading and writing) + default is a dot '.' + */ + uint comma; + + + /*! + additional comma operator (used only when reading) + if you don't want it just set it to zero + default is a comma ',' + + this allowes you to convert from a value: + 123.45 as well as from 123,45 + */ + uint comma2; + + + /*! + it sets the character which is used for grouping + if group=' ' then: 1234,56789 will be printed as: 1 234,567 89 + + if you don't want grouping just set it to zero (which is default) + */ + uint group; + + + /*! + */ + uint group_exp; // not implemented yet + + + + + Conv() + { + // default values + base = 10; + scient = false; + scient_from = 15; + base_round = true; + round = -1; + trim_zeroes = true; + comma = '.'; + comma2 = ','; + group = 0; + group_exp = 0; + } + }; + + + + /*! + this simple class can be used in multithreading model + (you can write your own class derived from this one) + + for example: in some functions like Factorial() + /at the moment only Factorial/ you can give a pointer to + the 'stop object', if the method WasStopSignal() of this + object returns true that means we should break the calculating + and return + */ + class StopCalculating + { + public: + virtual bool WasStopSignal() const volatile { return false; } + virtual ~StopCalculating(){} + }; + + + /*! + a small class which is useful when compiling with gcc + + object of this type holds the name and the line of a file + in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used + */ + class ExceptionInfo + { + const char * file; + int line; + + public: + ExceptionInfo() : file(0), line(0) {} + ExceptionInfo(const char * f, int l) : file(f), line(l) {} + + std::string Where() const + { + if( !file ) + return "unknown"; + + std::ostringstream result; + result << file << ":" << line; + + return result.str(); + } + }; + + + /*! + A small class used for reporting 'reference' errors + + In the library is used macro TTMATH_REFERENCE_ASSERT which + can throw an exception of this type + + If you compile with gcc you can get a small benefit + from using method Where() (it returns std::string) with + the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT + was used) + + What is the 'reference' error? + Some kind of methods use a reference as their argument to another object, + and the another object not always can be the same which is calling, e.g. + Big<1,2> foo(10); + foo.Mul(foo); // this is incorrect + above method Mul is making something more with 'this' object and + 'this' cannot be passed as the argument because the result will be undefined + + macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem + + note! some methods can use 'this' object as the argument + for example this code is correct: + UInt<2> foo(10); + foo.Add(foo); + but there are only few methods which can do that + */ + class ReferenceError : public std::logic_error, public ExceptionInfo + { + public: + + ReferenceError() : std::logic_error("reference error") + { + } + + ReferenceError(const char * f, int l) : + std::logic_error("reference error"), ExceptionInfo(f,l) + { + } + + std::string Where() const + { + return ExceptionInfo::Where(); + } + }; + + + /*! + a small class used for reporting errors + + in the library is used macro TTMATH_ASSERT which + (if the condition in it is false) throw an exception + of this type + + if you compile with gcc you can get a small benefit + from using method Where() (it returns std::string) with + the name and the line of a file where the macro TTMATH_ASSERT + was used) + */ + class RuntimeError : public std::runtime_error, public ExceptionInfo + { + public: + + RuntimeError() : std::runtime_error("internal error") + { + } + + RuntimeError(const char * f, int l) : + std::runtime_error("internal error"), ExceptionInfo(f,l) + { + } + + std::string Where() const + { + return ExceptionInfo::Where(); + } + }; + + + + /*! + look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG + */ + #ifdef TTMATH_DEBUG + + #if defined(__FILE__) && defined(__LINE__) + + #define TTMATH_REFERENCE_ASSERT(expression) \ + if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); + + #define TTMATH_ASSERT(expression) \ + if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); + + #else + + #define TTMATH_REFERENCE_ASSERT(expression) \ + if( &(expression) == this ) throw ReferenceError(); + + #define TTMATH_ASSERT(expression) \ + if( !(expression) ) throw RuntimeError(); + #endif + + #else + #define TTMATH_REFERENCE_ASSERT(expression) + #define TTMATH_ASSERT(expression) + #endif + + + + #ifdef TTMATH_DEBUG_LOG + #define TTMATH_LOG(msg) PrintLog(msg, std::cout); + #define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout); + #define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len); + #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len); + #else + #define TTMATH_LOG(msg) + #define TTMATH_LOGC(msg, carry) + #define TTMATH_VECTOR_LOG(msg, vector, len) + #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) + #endif + + + + +} // namespace + + +#endif + diff --git a/src/libghost/ttmath/ttmath/ttmathuint.h b/src/libghost/ttmath/ttmath/ttmathuint.h new file mode 100644 index 0000000..5f3e3e2 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathuint.h @@ -0,0 +1,3520 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef headerfilettmathuint +#define headerfilettmathuint + + +/*! + \file ttmathuint.h + \brief template class UInt +*/ + +#include +#include + + +#include "ttmathtypes.h" +#include "ttmathmisc.h" + + + +/*! + \brief a namespace for the TTMath library +*/ +namespace ttmath +{ + +/*! + \brief UInt implements a big integer value without a sign + + value_size - how many bytes specify our value + on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits + on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits + value_size = 1,2,3,4,5,6.... +*/ +template +class UInt +{ +public: + + /*! + buffer for the integer value + table[0] - the lowest word of the value + */ + uint table[value_size]; + + + + /*! + some methods used for debugging purposes + */ + + + /*! + this method is only for debugging purposes or when we want to make + a table of a variable (constant) in ttmathbig.h + + it prints the table in a nice form of several columns + */ + template + void PrintTable(ostream_type & output) const + { + // how many columns there'll be + const int columns = 8; + + int c = 1; + for(int i=value_size-1 ; i>=0 ; --i) + { + output << "0x" << std::setfill('0'); + + #ifdef TTMATH_PLATFORM32 + output << std::setw(8); + #else + output << std::setw(16); + #endif + + output << std::hex << table[i]; + + if( i>0 ) + { + output << ", "; + + if( ++c > columns ) + { + output << std::endl; + c = 1; + } + } + } + + output << std::dec << std::endl; + } + + + /*! + this method is used when macro TTMATH_DEBUG_LOG is defined + */ + template + static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len) + { + output << msg << std::endl; + + for(uint i=0 ; i + static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len) + { + PrintVectorLog(msg, output, vector, vector_len); + output << " carry: " << carry << std::endl; + } + + + /*! + this method is used when macro TTMATH_DEBUG_LOG is defined + */ + template + void PrintLog(const char_type * msg, ostream_type & output) const + { + PrintVectorLog(msg, output, table, value_size); + } + + + /*! + this method is used when macro TTMATH_DEBUG_LOG is defined + */ + template + void PrintLog(const char_type * msg, uint carry, ostream_type & output) const + { + PrintVectorLog(msg, output, table, value_size); + output << " carry: " << carry << std::endl; + } + + + /*! + this method returns the size of the table + */ + uint Size() const + { + return value_size; + } + + + /*! + this method sets zero + */ + void SetZero() + { + // in the future here can be 'memset' + + for(uint i=0 ; i=0 && temp_table_index=0 ; --i) + table[i] = 0; + + + TTMATH_LOG("UInt::SetFromTable") + } + +#endif + + +#ifdef TTMATH_PLATFORM64 + /*! + this method copies the value stored in an another table + (warning: first values in temp_table are the highest words -- it's different + from our table) + + ***this method is created only on a 64bit platform*** + + we copy as many words as it is possible + + if temp_table_len is bigger than value_size we'll try to round + the lowest word from table depending on the last not used bit in temp_table + (this rounding isn't a perfect rounding -- look at the description below) + + and if temp_table_len is smaller than value_size we'll clear the rest words + in the table + + warning: we're using 'temp_table' as a pointer at 32bit words + */ + void SetFromTable(const unsigned int * temp_table, uint temp_table_len) + { + uint temp_table_index = 0; + sint i; // 'i' with a sign + + for(i=value_size-1 ; i>=0 && temp_table_index= 0 ; --i) + table[i] = 0; + + TTMATH_LOG("UInt::SetFromTable") + } + +#endif + + + + + + /*! + * + * basic mathematic functions + * + */ + + + + + /*! + this method adds one to the existing value + */ + uint AddOne() + { + return AddInt(1); + } + + + /*! + this method subtracts one from the existing value + */ + uint SubOne() + { + return SubInt(1); + } + + +private: + + + /*! + an auxiliary method for moving bits into the left hand side + + this method moves only words + */ + void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) + { + rest_bits = bits % TTMATH_BITS_PER_UINT; + uint all_words = bits / TTMATH_BITS_PER_UINT; + uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; + + + if( all_words >= value_size ) + { + if( all_words == value_size && rest_bits == 0 ) + last_c = table[0] & 1; + // else: last_c is default set to 0 + + // clearing + for(uint i = 0 ; i 0 ) + { + // 0 < all_words < value_size + + sint first, second; + last_c = table[value_size - all_words] & 1; // all_words is greater than 0 + + // copying the first part of the value + for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second) + table[first] = table[second]; + + // setting the rest to 'c' + for( ; first>=0 ; --first ) + table[first] = mask; + } + + TTMATH_LOG("UInt::RclMoveAllWords") + } + +public: + + /*! + moving all bits into the left side 'bits' times + return value <- this <- C + + bits is from a range of <0, man * TTMATH_BITS_PER_UINT> + or it can be even bigger then all bits will be set to 'c' + + the value c will be set into the lowest bits + and the method returns state of the last moved bit + */ + uint Rcl(uint bits, uint c=0) + { + uint last_c = 0; + uint rest_bits = bits; + + if( bits == 0 ) + return 0; + + if( bits >= TTMATH_BITS_PER_UINT ) + RclMoveAllWords(rest_bits, last_c, bits, c); + + if( rest_bits == 0 ) + { + TTMATH_LOG("UInt::Rcl") + return last_c; + } + + // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now + if( rest_bits == 1 ) + { + last_c = Rcl2_one(c); + } + else if( rest_bits == 2 ) + { + // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c) + Rcl2_one(c); + last_c = Rcl2_one(c); + } + else + { + last_c = Rcl2(rest_bits, c); + } + + TTMATH_LOGC("UInt::Rcl", last_c) + + return last_c; + } + +private: + + /*! + an auxiliary method for moving bits into the right hand side + + this method moves only words + */ + void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) + { + rest_bits = bits % TTMATH_BITS_PER_UINT; + uint all_words = bits / TTMATH_BITS_PER_UINT; + uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; + + + if( all_words >= value_size ) + { + if( all_words == value_size && rest_bits == 0 ) + last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; + // else: last_c is default set to 0 + + // clearing + for(uint i = 0 ; i 0 ) + { + // 0 < all_words < value_size + + uint first, second; + last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0 + + // copying the first part of the value + for(first=0, second=all_words ; second this -> return value + + bits is from a range of <0, man * TTMATH_BITS_PER_UINT> + or it can be even bigger then all bits will be set to 'c' + + the value c will be set into the highest bits + and the method returns state of the last moved bit + */ + uint Rcr(uint bits, uint c=0) + { + uint last_c = 0; + uint rest_bits = bits; + + if( bits == 0 ) + return 0; + + if( bits >= TTMATH_BITS_PER_UINT ) + RcrMoveAllWords(rest_bits, last_c, bits, c); + + if( rest_bits == 0 ) + { + TTMATH_LOG("UInt::Rcr") + return last_c; + } + + // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now + if( rest_bits == 1 ) + { + last_c = Rcr2_one(c); + } + else if( rest_bits == 2 ) + { + // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c) + Rcr2_one(c); + last_c = Rcr2_one(c); + } + else + { + last_c = Rcr2(rest_bits, c); + } + + TTMATH_LOGC("UInt::Rcr", last_c) + + return last_c; + } + + + /*! + this method moves all bits into the left side + (it returns value how many bits have been moved) + */ + uint CompensationToLeft() + { + uint moving = 0; + + // a - index a last word which is different from zero + sint a; + for(a=value_size-1 ; a>=0 && table[a]==0 ; --a); + + if( a < 0 ) + return moving; // all words in table have zero + + if( a != value_size-1 ) + { + moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT; + + // moving all words + sint i; + for(i=value_size-1 ; a>=0 ; --i, --a) + table[i] = table[a]; + + // setting the rest word to zero + for(; i>=0 ; --i) + table[i] = 0; + } + + uint moving2 = FindLeadingBitInWord( table[value_size-1] ); + // moving2 is different from -1 because the value table[value_size-1] + // is not zero + + moving2 = TTMATH_BITS_PER_UINT - moving2 - 1; + Rcl(moving2); + + TTMATH_LOG("UInt::CompensationToLeft") + + return moving + moving2; + } + + + /*! + this method looks for the highest set bit + + result: + if 'this' is not zero: + return value - true + 'table_id' - the index of a word <0..value_size-1> + 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) + + if 'this' is zero: + return value - false + both 'table_id' and 'index' are zero + */ + bool FindLeadingBit(uint & table_id, uint & index) const + { + for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id); + + if( table_id==0 && table[table_id]==0 ) + { + // is zero + index = 0; + + return false; + } + + // table[table_id] is different from 0 + index = FindLeadingBitInWord( table[table_id] ); + + return true; + } + + + /*! + this method looks for the smallest set bit + + result: + if 'this' is not zero: + return value - true + 'table_id' - the index of a word <0..value_size-1> + 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) + + if 'this' is zero: + return value - false + both 'table_id' and 'index' are zero + */ + bool FindLowestBit(uint & table_id, uint & index) const + { + for(table_id=0 ; table_id= value_size ) + { + // is zero + index = 0; + table_id = 0; + + return false; + } + + // table[table_id] is different from 0 + index = FindLowestBitInWord( table[table_id] ); + + return true; + } + + + /*! + getting the 'bit_index' bit + + bit_index bigger or equal zero + */ + uint GetBit(uint bit_index) const + { + TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) + + uint index = bit_index / TTMATH_BITS_PER_UINT; + uint bit = bit_index % TTMATH_BITS_PER_UINT; + + uint temp = table[index]; + uint res = SetBitInWord(temp, bit); + + return res; + } + + + /*! + setting the 'bit_index' bit + and returning the last state of the bit + + bit_index bigger or equal zero + */ + uint SetBit(uint bit_index) + { + TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) + + uint index = bit_index / TTMATH_BITS_PER_UINT; + uint bit = bit_index % TTMATH_BITS_PER_UINT; + uint res = SetBitInWord(table[index], bit); + + TTMATH_LOG("UInt::SetBit") + + return res; + } + + + /*! + this method performs a bitwise operation AND + */ + void BitAnd(const UInt & ss2) + { + for(uint x=0 ; x & ss2) + { + for(uint x=0 ; x & ss2) + { + for(uint x=0 ; x + + for example: + BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7 + */ + void BitNot2() + { + uint table_id, index; + + if( FindLeadingBit(table_id, index) ) + { + for(uint x=0 ; x>= shift; + + table[table_id] ^= mask; + } + else + table[0] = 1; + + + TTMATH_LOG("UInt::BitNot2") + } + + + + /*! + * + * Multiplication + * + * + */ + +public: + + /*! + multiplication: this = this * ss2 + + it can return a carry + */ + uint MulInt(uint ss2) + { + uint r1, r2, x1; + uint c = 0; + + UInt u(*this); + SetZero(); + + if( ss2 == 0 ) + { + TTMATH_LOGC("UInt::MulInt(uint)", 0) + return 0; + } + + for(x1=0 ; x1 + void MulInt(uint ss2, UInt & result) const + { + TTMATH_ASSERT( result_size > value_size ) + + uint r2,r1; + uint x1size=value_size; + uint x1start=0; + + result.SetZero(); + + if( ss2 == 0 ) + { + TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) + return; + } + + if( value_size > 2 ) + { + // if the value_size is smaller than or equal to 2 + // there is no sense to set x1size and x1start to another values + + for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); + + if( x1size == 0 ) + { + TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) + return; + } + + for(x1start=0 ; x1start)", result.table, result_size) + + return; + } + + + + /*! + the multiplication 'this' = 'this' * ss2 + + algorithm: 100 - means automatically choose the fastest algorithm + */ + uint Mul(const UInt & ss2, uint algorithm = 100) + { + switch( algorithm ) + { + case 1: + return Mul1(ss2); + + case 2: + return Mul2(ss2); + + case 3: + return Mul3(ss2); + + case 100: + default: + return MulFastest(ss2); + } + } + + + /*! + the multiplication 'result' = 'this' * ss2 + + since the 'result' is twice bigger than 'this' and 'ss2' + this method never returns a carry + + algorithm: 100 - means automatically choose the fastest algorithm + */ + void MulBig(const UInt & ss2, + UInt & result, + uint algorithm = 100) + { + switch( algorithm ) + { + case 1: + return Mul1Big(ss2, result); + + case 2: + return Mul2Big(ss2, result); + + case 3: + return Mul3Big(ss2, result); + + case 100: + default: + return MulFastestBig(ss2, result); + } + } + + + + /*! + the first version of the multiplication algorithm + */ + + /*! + multiplication: this = this * ss2 + + it returns carry if it has been + */ + uint Mul1(const UInt & ss2) + { + TTMATH_REFERENCE_ASSERT( ss2 ) + + UInt ss1( *this ); + SetZero(); + + for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i) + { + if( Add(*this) ) + { + TTMATH_LOGC("UInt::Mul1", 1) + return 1; + } + + if( ss1.Rcl(1) ) + if( Add(ss2) ) + { + TTMATH_LOGC("UInt::Mul1", 1) + return 1; + } + } + + TTMATH_LOGC("UInt::Mul1", 0) + + return 0; + } + + + /*! + multiplication: result = this * ss2 + + result is twice bigger than 'this' and 'ss2' + this method never returns carry + */ + void Mul1Big(const UInt & ss2_, UInt & result) + { + UInt ss2; + uint i; + + // copying *this into result and ss2_ into ss2 + for(i=0 ; i & ss2) + { + UInt result; + uint i, c = 0; + + Mul2Big(ss2, result); + + // copying result + for(i=0 ; i & ss2, UInt & result) + { + Mul2Big2(table, ss2.table, result); + + TTMATH_LOG("UInt::Mul2Big") + } + + +private: + + /*! + an auxiliary method for calculating the multiplication + + arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding + unnecessary copying objects), the result should be taken as a pointer too, + but at the moment there is no method AddTwoInts() which can operate on pointers + */ + template + void Mul2Big2(const uint * ss1, const uint * ss2, UInt & result) + { + uint x1size = ss_size, x2size = ss_size; + uint x1start = 0, x2start = 0; + + if( ss_size > 2 ) + { + // if the ss_size is smaller than or equal to 2 + // there is no sense to set x1size (and others) to another values + + for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size); + for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size); + + for(x1start=0 ; x1start(ss1, ss2, result, x1start, x1size, x2start, x2size); + } + + + + /*! + an auxiliary method for calculating the multiplication + */ + template + void Mul2Big3(const uint * ss1, const uint * ss2, UInt & result, uint x1start, uint x1size, uint x2start, uint x2size) + { + uint r2, r1; + + result.SetZero(); + + if( x1size==0 || x2size==0 ) + return; + + for(uint x1=x1start ; x1 & ss2) + { + UInt result; + uint i, c = 0; + + Mul3Big(ss2, result); + + // copying result + for(i=0 ; i & ss2, UInt & result) + { + Mul3Big2(table, ss2.table, result.table); + + TTMATH_LOG("UInt::Mul3Big") + } + + + +private: + + /*! + an auxiliary method for calculating the Karatsuba multiplication + + result_size is equal ss_size*2 + */ + template + void Mul3Big2(const uint * ss1, const uint * ss2, uint * result) + { + const uint * x1, * x0, * y1, * y0; + + + if( ss_size>1 && ss_size res; + Mul2Big2(ss1, ss2, res); + + for(uint i=0 ; i(x1, x0, y1, y0, result); + } + else + { + // ss_size is even + x0 = ss1; + y0 = ss2; + x1 = ss1 + ss_size / 2; + y1 = ss2 + ss_size / 2; + + // all four vectors (x0 x1 y0 y1) are equal in size + Mul3Big3(x1, x0, y1, y0, result); + } + } + + + +#ifdef _MSC_VER +#pragma warning (disable : 4717) +//warning C4717: recursive on all control paths, function will cause runtime stack overflow +//we have the stop point in Mul3Big2() method +#endif + + + /*! + an auxiliary method for calculating the Karatsuba multiplication + + x = x1*B^m + x0 + y = y1*B^m + y0 + + first_size - is the size of vectors: x0 and y0 + second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size) + + x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0 + where + z0 = x0*y0 + z2 = x1*y1 + z1 = (x1 + x0)*(y1 + y0) - z2 - z0 + */ + template + void Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result) + { + uint i, c, xc, yc; + + UInt temp, temp2; + UInt z1; + + // z0 and z2 we store directly in the result (we don't use any temporary variables) + Mul3Big2(x0, y0, result); // z0 + Mul3Big2(x1, y1, result+first_size*2); // z2 + + // now we calculate z1 + // temp = (x0 + x1) + // temp2 = (y0 + y1) + // we're using temp and temp2 with UInt, although there can be a carry but + // we simple remember it in xc and yc (xc and yc can be either 0 or 1), + // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm): + // + // xc | temp + // yc | temp2 + // -------------------- + // (temp * temp2) + // xc*temp2 | + // yc*temp | + // xc*yc | + // ---------- z1 -------- + // + // and the result is never larger in size than 3*first_size + + xc = AddVector(x0, x1, first_size, second_size, temp.table); + yc = AddVector(y0, y1, first_size, second_size, temp2.table); + + Mul3Big2(temp.table, temp2.table, z1.table); + + // clearing the rest of z1 + for(i=first_size*2 ; i second_size ) + { + uint z1_size = result_size - first_size; + TTMATH_ASSERT( z1_size <= first_size*3 ) + + for(i=z1_size ; i & ss2) + { + UInt result; + uint i, c = 0; + + MulFastestBig(ss2, result); + + // copying result + for(i=0 ; i & ss2, UInt & result) + { + if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE ) + return Mul2Big(ss2, result); + + uint x1size = value_size, x2size = value_size; + uint x1start = 0, x2start = 0; + + for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); + for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size); + + if( x1size==0 || x2size==0 ) + { + // either 'this' or 'ss2' is equal zero - the result is zero too + result.SetZero(); + return; + } + + for(x1start=0 ; x1start(table, ss2.table, result, x1start, x1size, x2start, x2size); + + + // Karatsuba multiplication + Mul3Big(ss2, result); + + TTMATH_LOG("UInt::MulFastestBig") + } + + + /*! + * + * Division + * + * + */ + +public: + + + /*! + division by one unsigned word + + returns 1 when divisor is zero + */ + uint DivInt(uint divisor, uint * remainder = 0) + { + if( divisor == 0 ) + { + if( remainder ) + *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized + + TTMATH_LOG("UInt::DivInt") + + return 1; + } + + if( divisor == 1 ) + { + if( remainder ) + *remainder = 0; + + TTMATH_LOG("UInt::DivInt") + + return 0; + } + + UInt dividend(*this); + SetZero(); + + sint i; // i must be with a sign + uint r = 0; + + // we're looking for the last word in ss1 + for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i); + + for( ; i>=0 ; --i) + DivTwoWords(r, dividend.table[i], divisor, &table[i], &r); + + if( remainder ) + *remainder = r; + + TTMATH_LOG("UInt::DivInt") + + return 0; + } + + uint DivInt(uint divisor, uint & remainder) + { + return DivInt(divisor, &remainder); + } + + + + /*! + division this = this / ss2 + + return values: + 0 - ok + 1 - division by zero + 'this' will be the quotient + 'remainder' - remainder + */ + uint Div( const UInt & divisor, + UInt * remainder = 0, + uint algorithm = 3) + { + switch( algorithm ) + { + case 1: + return Div1(divisor, remainder); + + case 2: + return Div2(divisor, remainder); + + case 3: + default: + return Div3(divisor, remainder); + } + } + + uint Div(const UInt & divisor, UInt & remainder, uint algorithm = 3) + { + return Div(divisor, &remainder, algorithm); + } + + + +private: + + /*! + return values: + 0 - none has to be done + 1 - division by zero + 2 - division should be made + */ + uint Div_StandardTest( const UInt & v, + uint & m, uint & n, + UInt * remainder = 0) + { + switch( Div_CalculatingSize(v, m, n) ) + { + case 4: // 'this' is equal v + if( remainder ) + remainder->SetZero(); + + SetOne(); + TTMATH_LOG("UInt::Div_StandardTest") + return 0; + + case 3: // 'this' is smaller than v + if( remainder ) + *remainder = *this; + + SetZero(); + TTMATH_LOG("UInt::Div_StandardTest") + return 0; + + case 2: // 'this' is zero + if( remainder ) + remainder->SetZero(); + + SetZero(); + TTMATH_LOG("UInt::Div_StandardTest") + return 0; + + case 1: // v is zero + TTMATH_LOG("UInt::Div_StandardTest") + return 1; + } + + TTMATH_LOG("UInt::Div_StandardTest") + + return 2; + } + + + + /*! + return values: + 0 - ok + 'm' - is the index (from 0) of last non-zero word in table ('this') + 'n' - is the index (from 0) of last non-zero word in v.table + 1 - v is zero + 2 - 'this' is zero + 3 - 'this' is smaller than v + 4 - 'this' is equal v + + if the return value is different than zero the 'm' and 'n' are undefined + */ + uint Div_CalculatingSize(const UInt & v, uint & m, uint & n) + { + m = n = value_size-1; + + for( ; n!=0 && v.table[n]==0 ; --n); + + if( n==0 && v.table[n]==0 ) + return 1; + + for( ; m!=0 && table[m]==0 ; --m); + + if( m==0 && table[m]==0 ) + return 2; + + if( m < n ) + return 3; + else + if( m == n ) + { + uint i; + for(i = n ; i!=0 && table[i]==v.table[i] ; --i); + + if( table[i] < v.table[i] ) + return 3; + else + if (table[i] == v.table[i] ) + return 4; + } + + return 0; + } + + +public: + + /*! + the first division algorithm + radix 2 + */ + uint Div1(const UInt & divisor, UInt * remainder = 0) + { + uint m,n, test; + + test = Div_StandardTest(divisor, m, n, remainder); + if( test < 2 ) + return test; + + if( !remainder ) + { + UInt rem; + + return Div1_Calculate(divisor, rem); + } + + return Div1_Calculate(divisor, *remainder); + } + + +private: + + + uint Div1_Calculate(const UInt & divisor, UInt & rest) + { + TTMATH_REFERENCE_ASSERT( divisor ) + + sint loop; + sint c; + + rest.SetZero(); + loop = value_size * TTMATH_BITS_PER_UINT; + c = 0; + + + div_a: + c = Rcl(1, c); + c = rest.Add(rest,c); + c = rest.Sub(divisor,c); + + c = !c; + + if(!c) + goto div_d; + + + div_b: + --loop; + if(loop) + goto div_a; + + c = Rcl(1, c); + TTMATH_LOG("UInt::Div1_Calculate") + return 0; + + + div_c: + c = Rcl(1, c); + c = rest.Add(rest,c); + c = rest.Add(divisor); + + if(c) + goto div_b; + + + div_d: + --loop; + if(loop) + goto div_c; + + c = Rcl(1, c); + c = rest.Add(divisor); + + TTMATH_LOG("UInt::Div1_Calculate") + + return 0; + } + + +public: + + + /*! + the second division algorithm + + return values: + 0 - ok + 1 - division by zero + */ + uint Div2(const UInt & divisor, UInt * remainder = 0) + { + TTMATH_REFERENCE_ASSERT( divisor ) + + uint bits_diff; + uint status = Div2_Calculate(divisor, remainder, bits_diff); + if( status < 2 ) + return status; + + if( CmpBiggerEqual(divisor) ) + { + Div2(divisor, remainder); + SetBit(bits_diff); + } + else + { + if( remainder ) + *remainder = *this; + + SetZero(); + SetBit(bits_diff); + } + + TTMATH_LOG("UInt::Div2") + + return 0; + } + + + uint Div2(const UInt & divisor, UInt & remainder) + { + return Div2(divisor, &remainder); + } + + +private: + + /*! + return values: + 0 - we've calculated the division + 1 - division by zero + 2 - we have to still calculate + + */ + uint Div2_Calculate(const UInt & divisor, UInt * remainder, + uint & bits_diff) + { + uint table_id, index; + uint divisor_table_id, divisor_index; + + uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder, + table_id, index, + divisor_table_id, divisor_index); + + if( status < 2 ) + { + TTMATH_LOG("UInt::Div2_Calculate") + return status; + } + + // here we know that 'this' is greater than divisor + // then 'index' is greater or equal 'divisor_index' + bits_diff = index - divisor_index; + + UInt divisor_copy(divisor); + divisor_copy.Rcl(bits_diff, 0); + + if( CmpSmaller(divisor_copy, table_id) ) + { + divisor_copy.Rcr(1); + --bits_diff; + } + + Sub(divisor_copy, 0); + + TTMATH_LOG("UInt::Div2_Calculate") + + return 2; + } + + + /*! + return values: + 0 - we've calculated the division + 1 - division by zero + 2 - we have to still calculate + */ + uint Div2_FindLeadingBitsAndCheck( const UInt & divisor, + UInt * remainder, + uint & table_id, uint & index, + uint & divisor_table_id, uint & divisor_index) + { + if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) ) + { + // division by zero + TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") + return 1; + } + + if( !FindLeadingBit(table_id, index) ) + { + // zero is divided by something + + SetZero(); + + if( remainder ) + remainder->SetZero(); + + TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") + + return 0; + } + + divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT; + index += table_id * TTMATH_BITS_PER_UINT; + + if( divisor_table_id == 0 ) + { + // dividor has only one 32-bit word + + uint r; + DivInt(divisor.table[0], &r); + + if( remainder ) + { + remainder->SetZero(); + remainder->table[0] = r; + } + + TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") + + return 0; + } + + + if( Div2_DivisorGreaterOrEqual( divisor, remainder, + table_id, index, + divisor_index) ) + { + TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") + return 0; + } + + + TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") + + return 2; + } + + + /*! + return values: + true if divisor is equal or greater than 'this' + */ + bool Div2_DivisorGreaterOrEqual( const UInt & divisor, + UInt * remainder, + uint table_id, uint index, + uint divisor_index ) + { + if( divisor_index > index ) + { + // divisor is greater than this + + if( remainder ) + *remainder = *this; + + SetZero(); + + TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") + + return true; + } + + if( divisor_index == index ) + { + // table_id == divisor_table_id as well + + uint i; + for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i); + + if( table[i] < divisor.table[i] ) + { + // divisor is greater than 'this' + + if( remainder ) + *remainder = *this; + + SetZero(); + + TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") + + return true; + } + else + if( table[i] == divisor.table[i] ) + { + // divisor is equal 'this' + + if( remainder ) + remainder->SetZero(); + + SetOne(); + + TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") + + return true; + } + } + + TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") + + return false; + } + + +public: + + /*! + the third division algorithm + + this algorithm is described in the following book: + "The art of computer programming 2" (4.3.1 page 272) + Donald E. Knuth + */ + uint Div3(const UInt & v, UInt * remainder = 0) + { + TTMATH_REFERENCE_ASSERT( v ) + + uint m,n, test; + + test = Div_StandardTest(v, m, n, remainder); + if( test < 2 ) + return test; + + if( n == 0 ) + { + uint r; + DivInt( v.table[0], &r ); + + if( remainder ) + { + remainder->SetZero(); + remainder->table[0] = r; + } + + TTMATH_LOG("UInt::Div3") + + return 0; + } + + + // we can only use the third division algorithm when + // the divisor is greater or equal 2^32 (has more than one 32-bit word) + ++m; + ++n; + m = m - n; + Div3_Division(v, remainder, m, n); + + TTMATH_LOG("UInt::Div3") + + return 0; + } + + + +private: + + + void Div3_Division(UInt v, UInt * remainder, uint m, uint n) + { + TTMATH_ASSERT( n>=2 ) + + UInt uu, vv; + UInt q; + uint d, u_value_size, u0, u1, u2, v1, v0, j=m; + + u_value_size = Div3_Normalize(v, n, d); + + if( j+n == value_size ) + u2 = u_value_size; + else + u2 = table[j+n]; + + Div3_MakeBiggerV(v, vv); + + for(uint i = j+1 ; i & uu, uint j, uint n, uint u_max) + { + uint i; + + for(i=0 ; i so and 'i' is from <0..value_size> + // then table[i] is always correct (look at the declaration of 'uu') + uu.table[i] = u_max; + + for( ++i ; i & uu, uint j, uint n) + { + uint i; + + for(i=0 ; i & v, UInt & vv) + { + for(uint i=0 ; i & v, uint n, uint & d) + { + // v.table[n-1] is != 0 + + uint bit = (uint)FindLeadingBitInWord(v.table[n-1]); + uint move = (TTMATH_BITS_PER_UINT - bit - 1); + uint res = table[value_size-1]; + d = move; + + if( move > 0 ) + { + v.Rcl(move, 0); + Rcl(move, 0); + res = res >> (bit + 1); + } + else + { + res = 0; + } + + TTMATH_LOG("UInt::Div3_Normalize") + + return res; + } + + + void Div3_Unnormalize(UInt * remainder, uint n, uint d) + { + for(uint i=n ; i u_temp; + uint rp; + bool next_test; + + TTMATH_ASSERT( v1 != 0 ) + + u_temp.table[1] = u2; + u_temp.table[0] = u1; + u_temp.DivInt(v1, &rp); + + TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 ) + + do + { + bool decrease = false; + + if( u_temp.table[1] == 1 ) + decrease = true; + else + { + UInt<2> temp1, temp2; + + UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table); + temp2.table[1] = rp; + temp2.table[0] = u0; + + if( temp1 > temp2 ) + decrease = true; + } + + next_test = false; + + if( decrease ) + { + u_temp.SubOne(); + + rp += v1; + + if( rp >= v1 ) // it means that there wasn't a carry (r & uu, + const UInt & vv, uint & qp) + { + // D4 (in the book) + + UInt vv_temp(vv); + vv_temp.MulInt(qp); + + if( uu.Sub(vv_temp) ) + { + // there was a carry + + // + // !!! this part of code was not tested + // + + --qp; + uu.Add(vv); + + // can be a carry from this additions but it should be ignored + // because it cancels with the borrow from uu.Sub(vv_temp) + } + + TTMATH_LOG("UInt::Div3_MultiplySubtract") + } + + + + + + +public: + + + /*! + power this = this ^ pow + binary algorithm (r-to-l) + + return values: + 0 - ok + 1 - carry + 2 - incorrect argument (0^0) + */ + uint Pow(UInt pow) + { + if(pow.IsZero() && IsZero()) + // we don't define zero^zero + return 2; + + UInt start(*this), start_temp; + UInt result; + result.SetOne(); + uint c = 0; + + while( !c ) + { + if( pow.table[0] & 1 ) + c += result.Mul(start); + + pow.Rcr2_one(0); + if( pow.IsZero() ) + break; + + start_temp = start; + // in the second Mul algorithm we can use start.Mul(start) directly (there is no TTMATH_ASSERT_REFERENCE there) + c += start.Mul(start_temp); + } + + *this = result; + + TTMATH_LOGC("UInt::Pow(UInt<>)", c) + + return (c==0)? 0 : 1; + } + + + /*! + square root + e.g. Sqrt(9) = 3 + ('digit-by-digit' algorithm) + */ + void Sqrt() + { + UInt bit, temp; + + if( IsZero() ) + return; + + UInt value(*this); + + SetZero(); + bit.SetZero(); + bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1); + + while( bit > value ) + bit.Rcr(2); + + while( !bit.IsZero() ) + { + temp = *this; + temp.Add(bit); + + if( value >= temp ) + { + value.Sub(temp); + Rcr(1); + Add(bit); + } + else + { + Rcr(1); + } + + bit.Rcr(2); + } + + TTMATH_LOG("UInt::Sqrt") + } + + + + /*! + this method sets n first bits to value zero + + For example: + let n=2 then if there's a value 111 (bin) there'll be '100' (bin) + */ + void ClearFirstBits(uint n) + { + if( n >= value_size*TTMATH_BITS_PER_UINT ) + { + SetZero(); + TTMATH_LOG("UInt::ClearFirstBits") + return; + } + + uint * p = table; + + // first we're clearing the whole words + while( n >= TTMATH_BITS_PER_UINT ) + { + *p++ = 0; + n -= TTMATH_BITS_PER_UINT; + } + + if( n == 0 ) + { + TTMATH_LOG("UInt::ClearFirstBits") + return; + } + + // and then we're clearing one word which has left + // mask -- all bits are set to one + uint mask = TTMATH_UINT_MAX_VALUE; + + mask = mask << n; + + (*p) &= mask; + + TTMATH_LOG("UInt::ClearFirstBits") + } + + + /*! + this method returns true if the highest bit of the value is set + */ + bool IsTheHighestBitSet() const + { + return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0; + } + + + /*! + this method returns true if the lowest bit of the value is set + */ + bool IsTheLowestBitSet() const + { + return (*table & 1) != 0; + } + + + /*! + this method returns true if the value is equal zero + */ + bool IsZero() const + { + for(uint i=0 ; i> (TTMATH_BITS_PER_UINT - rest); + + return (table[i] & mask) == 0; + } + + + + /*! + * + * conversion methods + * + */ + + + + /*! + this method converts an UInt type to this class + + this operation has mainly sense if the value from p is + equal or smaller than that one which is returned from UInt::SetMax() + + it returns a carry if the value 'p' is too big + */ + template + uint FromUInt(const UInt & p) + { + uint min_size = (value_size < argument_size)? value_size : argument_size; + uint i; + + for(i=0 ; i argument_size ) + { + // 'this' is longer than 'p' + + for( ; i)", 1) + return 1; + } + } + + TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0) + + return 0; + } + + + /*! + this method converts the uint type to this class + */ + void FromUInt(uint value) + { + for(uint i=1 ; i type to this class + + it doesn't return a carry + */ + template + UInt & operator=(const UInt & p) + { + FromUInt(p); + + return *this; + } + + + /*! + the assignment operator + */ + UInt & operator=(const UInt & p) + { + for(uint i=0 ; i)") + + return *this; + } + + + /*! + this method converts the uint type to this class + */ + UInt & operator=(uint i) + { + FromUInt(i); + + return *this; + } + + + /*! + a constructor for converting the uint to this class + */ + UInt(uint i) + { + FromUInt(i); + } + + + /*! + this method converts the sint type to this class + + we provide operator(sint) and the constructor(sint) in order to allow + the programmer do that: + UInt<..> type = 10; + + above "10" constant has the int type (signed int), if we don't give such + operators and constructors the compiler will not compile the program, + because it has to make a conversion and doesn't know into which type + (the UInt class has operator=(const char*), operator=(uint) etc.) + */ + UInt & operator=(sint i) + { + FromUInt(uint(i)); + + return *this; + } + + + /*! + a constructor for converting the sint to this class + + look at the description of UInt::operator=(sint) + */ + UInt(sint i) + { + FromUInt(uint(i)); + } + + + +#ifdef TTMATH_PLATFORM64 + + /*! + in 64bit platforms we must define additional operators and contructors + in order to allow a user initializing the objects in this way: + UInt<...> type = 20; + or + UInt<...> type; + type = 30; + + decimal constants such as 20, 30 etc. are integer literal of type int, + if the value is greater it can even be long int, + 0 is an octal integer of type int + (ISO 14882 p2.13.1 Integer literals) + */ + + /*! + this operator converts the unsigned int type to this class + + ***this operator is created only on a 64bit platform*** + it takes one argument of 32bit + */ + UInt & operator=(unsigned int i) + { + FromUInt(uint(i)); + + return *this; + } + + + /*! + a constructor for converting the unsigned int to this class + + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + */ + UInt(unsigned int i) + { + FromUInt(uint(i)); + } + + + /*! + an operator for converting the signed int to this class + + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + + look at the description of UInt::operator=(sint) + */ + UInt & operator=(signed int i) + { + FromUInt(uint(i)); + + return *this; + } + + + /*! + a constructor for converting the signed int to this class + + ***this constructor is created only on a 64bit platform*** + it takes one argument of 32bit + + look at the description of UInt::operator=(sint) + */ + UInt(signed int i) + { + FromUInt(uint(i)); + } + + +#endif + + + + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + UInt(const char * s) + { + FromString(s); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + UInt(const wchar_t * s) + { + FromString(s); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + UInt(const std::string & s) + { + FromString( s.c_str() ); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + UInt(const std::wstring & s) + { + FromString( s.c_str() ); + } + + + /*! + a default constructor + + we don't clear the table + */ + UInt() + { + // when macro TTMATH_DEBUG_LOG is defined + // we set special values to the table + // in order to be everywhere the same value of the UInt object + // without this it would be difficult to analyse the log file + #ifdef TTMATH_DEBUG_LOG + #ifdef TTMATH_PLATFORM32 + for(uint i=0 ; i & u) + { + for(uint i=0 ; i)") + } + + + + /*! + a template for producting constructors for copying from another types + */ + template + UInt(const UInt & u) + { + // look that 'size' we still set as 'value_size' and not as u.value_size + FromUInt(u); + } + + + + + /*! + a destructor + */ + ~UInt() + { + } + + + /*! + this method returns the lowest value from table + + we must be sure when we using this method whether the value + will hold in an uint type or not (the rest value from the table must be zero) + */ + uint ToUInt() const + { + return table[0]; + } + + +private: + + /*! + an auxiliary method for converting to a string + */ + template + void ToStringBase(string_type & result, uint b = 10) const + { + UInt temp( *this ); + char character; + uint rem; + + result.clear(); + + if( b<2 || b>16 ) + return; + + do + { + temp.DivInt(b, &rem); + character = static_cast( Misc::DigitToChar(rem) ); + result.insert(result.begin(), character); + } + while( !temp.IsZero() ); + + return; + } + + +public: + + /*! + this method converts the value to a string with a base equal 'b' + */ + void ToString(std::string & result, uint b = 10) const + { + return ToStringBase(result, b); + } + + void ToString(std::wstring & result, uint b = 10) const + { + return ToStringBase(result, b); + } + + std::string ToString(uint b = 10) const + { + std::string result; + ToStringBase(result, b); + + return result; + } + + std::wstring ToWString(uint b = 10) const + { + std::wstring result; + ToStringBase(result, b); + + return result; + } + + +private: + + /*! + an auxiliary method for converting from a string + */ + template + uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) + { + UInt base( b ); + UInt temp; + sint z; + uint c = 0; + + SetZero(); + temp.SetZero(); + Misc::SkipWhiteCharacters(s); + + if( after_source ) + *after_source = s; + + if( value_read ) + *value_read = false; + + if( b<2 || b>16 ) + return 1; + + + for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s) + { + if( value_read ) + *value_read = true; + + if( c == 0 ) + { + temp.table[0] = z; + + c += Mul(base); + c += Add(temp); + } + } + + if( after_source ) + *after_source = s; + + TTMATH_LOGC("UInt::FromString", c) + + return (c==0)? 0 : 1; + } + + +public: + + + /*! + this method converts a string into its value + it returns carry=1 if the value will be too big or an incorrect base 'b' is given + + string is ended with a non-digit value, for example: + "12" will be translated to 12 + as well as: + "12foo" will be translated to 12 too + + existing first white characters will be ommited + + if the value from s is too large the rest digits will be skipped + + after_source (if exists) is pointing at the end of the parsed string + + value_read (if exists) tells whether something has actually been read (at least one digit) + */ + uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + + /*! + this method converts a string into its value + */ + uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + + /*! + this method converts a string into its value + + (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) + */ + uint FromString(const std::string & s, uint b = 10) + { + return FromString( s.c_str(), b ); + } + + + /*! + this method converts a string into its value + + (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) + */ + uint FromString(const std::wstring & s, uint b = 10) + { + return FromString( s.c_str(), b ); + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + UInt & operator=(const char * s) + { + FromString(s); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + UInt & operator=(const wchar_t * s) + { + FromString(s); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + UInt & operator=(const std::string & s) + { + FromString( s.c_str() ); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + UInt & operator=(const std::wstring & s) + { + FromString( s.c_str() ); + + return *this; + } + + + /*! + * + * methods for comparing + * + */ + + + /*! + this method returns true if 'this' is smaller than 'l' + + 'index' is an index of the first word from will be the comparison performed + (note: we start the comparison from back - from the last word, when index is -1 /default/ + it is automatically set into the last word) + I introduced it for some kind of optimization made in the second division algorithm (Div2) + */ + bool CmpSmaller(const UInt & l, sint index = -1) const + { + sint i; + + if( index==-1 || index>=sint(value_size) ) + i = value_size - 1; + else + i = index; + + + for( ; i>=0 ; --i) + { + if( table[i] != l.table[i] ) + return table[i] < l.table[i]; + } + + // they're equal + return false; + } + + + + /*! + this method returns true if 'this' is bigger than 'l' + + 'index' is an index of the first word from will be the comparison performed + (note: we start the comparison from back - from the last word, when index is -1 /default/ + it is automatically set into the last word) + + I introduced it for some kind of optimization made in the second division algorithm (Div2) + */ + bool CmpBigger(const UInt & l, sint index = -1) const + { + sint i; + + if( index==-1 || index>=sint(value_size) ) + i = value_size - 1; + else + i = index; + + + for( ; i>=0 ; --i) + { + if( table[i] != l.table[i] ) + return table[i] > l.table[i]; + } + + // they're equal + return false; + } + + + /*! + this method returns true if 'this' is equal 'l' + + 'index' is an index of the first word from will be the comparison performed + (note: we start the comparison from back - from the last word, when index is -1 /default/ + it is automatically set into the last word) + */ + bool CmpEqual(const UInt & l, sint index = -1) const + { + sint i; + + if( index==-1 || index>=sint(value_size) ) + i = value_size - 1; + else + i = index; + + + for( ; i>=0 ; --i) + if( table[i] != l.table[i] ) + return false; + + return true; + } + + + + /*! + this method returns true if 'this' is smaller than or equal 'l' + + 'index' is an index of the first word from will be the comparison performed + (note: we start the comparison from back - from the last word, when index is -1 /default/ + it is automatically set into the last word) + */ + bool CmpSmallerEqual(const UInt & l, sint index=-1) const + { + sint i; + + if( index==-1 || index>=sint(value_size) ) + i = value_size - 1; + else + i = index; + + + for( ; i>=0 ; --i) + { + if( table[i] != l.table[i] ) + return table[i] < l.table[i]; + } + + // they're equal + return true; + } + + + + /*! + this method returns true if 'this' is bigger than or equal 'l' + + 'index' is an index of the first word from will be the comparison performed + (note: we start the comparison from back - from the last word, when index is -1 /default/ + it is automatically set into the last word) + */ + bool CmpBiggerEqual(const UInt & l, sint index=-1) const + { + sint i; + + if( index==-1 || index>=sint(value_size) ) + i = value_size - 1; + else + i = index; + + + for( ; i>=0 ; --i) + { + if( table[i] != l.table[i] ) + return table[i] > l.table[i]; + } + + // they're equal + return true; + } + + + /* + operators for comparising + */ + + bool operator<(const UInt & l) const + { + return CmpSmaller(l); + } + + + bool operator>(const UInt & l) const + { + return CmpBigger(l); + } + + + bool operator==(const UInt & l) const + { + return CmpEqual(l); + } + + + bool operator!=(const UInt & l) const + { + return !operator==(l); + } + + + bool operator<=(const UInt & l) const + { + return CmpSmallerEqual(l); + } + + bool operator>=(const UInt & l) const + { + return CmpBiggerEqual(l); + } + + + /*! + * + * standard mathematical operators + * + */ + + UInt operator-(const UInt & p2) const + { + UInt temp(*this); + + temp.Sub(p2); + + return temp; + } + + UInt & operator-=(const UInt & p2) + { + Sub(p2); + + return *this; + } + + UInt operator+(const UInt & p2) const + { + UInt temp(*this); + + temp.Add(p2); + + return temp; + } + + UInt & operator+=(const UInt & p2) + { + Add(p2); + + return *this; + } + + + UInt operator*(const UInt & p2) const + { + UInt temp(*this); + + temp.Mul(p2); + + return temp; + } + + + UInt & operator*=(const UInt & p2) + { + Mul(p2); + + return *this; + } + + + UInt operator/(const UInt & p2) const + { + UInt temp(*this); + + temp.Div(p2); + + return temp; + } + + + UInt & operator/=(const UInt & p2) + { + Div(p2); + + return *this; + } + + + UInt operator%(const UInt & p2) const + { + UInt temp(*this); + UInt remainder; + + temp.Div( p2, remainder ); + + return remainder; + } + + + UInt & operator%=(const UInt & p2) + { + UInt temp(*this); + UInt remainder; + + temp.Div( p2, remainder ); + + operator=(remainder); + + return *this; + } + + + /*! + Prefix operator e.g ++variable + */ + UInt & operator++() + { + AddOne(); + + return *this; + } + + + /*! + Postfix operator e.g variable++ + */ + UInt operator++(int) + { + UInt temp( *this ); + + AddOne(); + + return temp; + } + + + UInt & operator--() + { + SubOne(); + + return *this; + } + + + UInt operator--(int) + { + UInt temp( *this ); + + SubOne(); + + return temp; + } + + + UInt operator>>(int move) + { + UInt temp( *this ); + + temp.Rcr(move); + + return temp; + } + + + UInt & operator>>=(int move) + { + Rcr(move); + + return *this; + } + + + UInt operator<<(int move) + { + UInt temp( *this ); + + temp.Rcl(move); + + return temp; + } + + + UInt & operator<<=(int move) + { + Rcl(move); + + return *this; + } + + + /*! + * + * input/output operators for standard streams + * + * (they are very simple, in the future they should be changed) + * + */ + + +private: + + + /*! + an auxiliary method for outputing to standard streams + */ + template + static ostream_type & OutputToStream(ostream_type & s, const UInt & l) + { + string_type ss; + + l.ToString(ss); + s << ss; + + return s; + } + + +public: + + + /*! + output to standard streams + */ + friend std::ostream & operator<<(std::ostream & s, const UInt & l) + { + return OutputToStream(s, l); + } + + + /*! + output to standard streams + */ + friend std::wostream & operator<<(std::wostream & s, const UInt & l) + { + return OutputToStream(s, l); + } + + +private: + + /*! + an auxiliary method for reading from standard streams + */ + template + static istream_type & InputFromStream(istream_type & s, UInt & l) + { + string_type ss; + + // char or wchar_t for operator>> + char_type z; + + // operator>> omits white characters if they're set for ommiting + s >> z; + + // we're reading only digits (base=10) + while( s.good() && Misc::CharToDigit(z, 10)>=0 ) + { + ss += z; + z = static_cast(s.get()); + } + + // we're leaving the last read character + // (it's not belonging to the value) + s.unget(); + + l.FromString(ss); + + return s; + } + +public: + + + /*! + input from standard streams + */ + friend std::istream & operator>>(std::istream & s, UInt & l) + { + return InputFromStream(s, l); + } + + + /*! + input from standard streams + */ + friend std::wistream & operator>>(std::wistream & s, UInt & l) + { + return InputFromStream(s, l); + } + + + /* + following methods are defined in: + ttmathuint_x86.h + ttmathuint_x86_64.h + ttmathuint_noasm.h + */ + +#ifdef TTMATH_NOASM + static uint AddTwoWords(uint a, uint b, uint carry, uint * result); + static uint SubTwoWords(uint a, uint b, uint carry, uint * result); + +#ifdef TTMATH_PLATFORM64 + + union uint_ + { + struct + { + unsigned int low; // 32 bit + unsigned int high; // 32 bit + } u_; + + uint u; // 64 bit + }; + + + static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest); + static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_); + static uint DivTwoWordsUnnormalize(uint u, uint d); + static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_); + static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_); + +#endif // TTMATH_PLATFORM64 +#endif // TTMATH_NOASM + + +private: + uint Rcl2_one(uint c); + uint Rcr2_one(uint c); + uint Rcl2(uint bits, uint c); + uint Rcr2(uint bits, uint c); + +public: + static const char * LibTypeStr(); + static LibTypeCode LibType(); + uint Add(const UInt & ss2, uint c=0); + uint AddInt(uint value, uint index = 0); + uint AddTwoInts(uint x2, uint x1, uint index); + static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); + uint Sub(const UInt & ss2, uint c=0); + uint SubInt(uint value, uint index = 0); + static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); + static sint FindLeadingBitInWord(uint x); + static sint FindLowestBitInWord(uint x); + static uint SetBitInWord(uint & value, uint bit); + static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low); + static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); + +}; + + + +/*! + this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array" + when compiling Mul3Big2() method +*/ +template<> +class UInt<0> +{ +public: + uint table[1]; + + void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) }; + void SetZero() { TTMATH_ASSERT(false) }; + uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; }; +}; + + +} //namespace + + +#include "ttmathuint_x86.h" +#include "ttmathuint_x86_64.h" +#include "ttmathuint_noasm.h" + +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathuint_noasm.h b/src/libghost/ttmath/ttmath/ttmathuint_noasm.h new file mode 100644 index 0000000..ed3c180 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathuint_noasm.h @@ -0,0 +1,1013 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfilettmathuint_noasm +#define headerfilettmathuint_noasm + + +#ifdef TTMATH_NOASM + +/*! + \file ttmathuint_noasm.h + \brief template class UInt with methods without any assembler code + + this file is included at the end of ttmathuint.h +*/ + + +namespace ttmath +{ + + /*! + returning the string represents the currect type of the library + we have following types: + asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) + asm_gcc_32 - with asm code designed for GCC (32 bits) + asm_vc_64 - with asm for VC (64 bit) + asm_gcc_64 - with asm for GCC (64 bit) + no_asm_32 - pure C++ version (32 bit) - without any asm code + no_asm_64 - pure C++ version (64 bit) - without any asm code + */ + template + const char * UInt::LibTypeStr() + { + #ifdef TTMATH_PLATFORM32 + static const char info[] = "no_asm_32"; + #endif + + #ifdef TTMATH_PLATFORM64 + static const char info[] = "no_asm_64"; + #endif + + return info; + } + + + /*! + returning the currect type of the library + */ + template + LibTypeCode UInt::LibType() + { + #ifdef TTMATH_PLATFORM32 + LibTypeCode info = no_asm_32; + #endif + + #ifdef TTMATH_PLATFORM64 + LibTypeCode info = no_asm_64; + #endif + + return info; + } + + + /*! + this method adds two words together + returns carry + + this method is created only when TTMATH_NOASM macro is defined + */ + template + uint UInt::AddTwoWords(uint a, uint b, uint carry, uint * result) + { + uint temp; + + if( carry == 0 ) + { + temp = a + b; + + if( temp < a ) + carry = 1; + } + else + { + carry = 1; + temp = a + b + carry; + + if( temp > a ) // !(temp<=a) + carry = 0; + } + + *result = temp; + + return carry; + } + + + + /*! + this method adding ss2 to the this and adding carry if it's defined + (this = this + ss2 + c) + + c must be zero or one (might be a bigger value than 1) + function returns carry (1) (if it was) + */ + + template + uint UInt::Add(const UInt & ss2, uint c) + { + uint i; + + for(i=0 ; i + uint UInt::AddInt(uint value, uint index) + { + uint i, c; + + TTMATH_ASSERT( index < value_size ) + + + c = AddTwoWords(table[index], value, 0, &table[index]); + + for(i=index+1 ; i + uint UInt::AddTwoInts(uint x2, uint x1, uint index) + { + uint i, c; + + TTMATH_ASSERT( index < value_size - 1 ) + + + c = AddTwoWords(table[index], x1, 0, &table[index]); + c = AddTwoWords(table[index+1], x2, c, &table[index+1]); + + for(i=index+2 ; i + uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + { + uint i, c = 0; + + TTMATH_ASSERT( ss1_size >= ss2_size ) + + for(i=0 ; i + uint UInt::SubTwoWords(uint a, uint b, uint carry, uint * result) + { + if( carry == 0 ) + { + *result = a - b; + + if( a < b ) + carry = 1; + } + else + { + carry = 1; + *result = a - b - carry; + + if( a > b ) // !(a <= b ) + carry = 0; + } + + return carry; + } + + + + + /*! + this method's subtracting ss2 from the 'this' and subtracting + carry if it has been defined + (this = this - ss2 - c) + + c must be zero or one (might be a bigger value than 1) + function returns carry (1) (if it was) + */ + template + uint UInt::Sub(const UInt & ss2, uint c) + { + uint i; + + for(i=0 ; i + uint UInt::SubInt(uint value, uint index) + { + uint i, c; + + TTMATH_ASSERT( index < value_size ) + + + c = SubTwoWords(table[index], value, 0, &table[index]); + + for(i=index+1 ; i + uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + { + uint i, c = 0; + + TTMATH_ASSERT( ss1_size >= ss2_size ) + + for(i=0 ; i + uint UInt::Rcl2_one(uint c) + { + uint i, new_c; + + if( c != 0 ) + c = 1; + + for(i=0 ; i this -> return value + + the highest *bit* will be held the 'c' and + the state of one additional bit (on the right hand side) + will be returned + + for example: + let this is 000000010 + after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 + */ + template + uint UInt::Rcr2_one(uint c) + { + sint i; // signed i + uint new_c; + + if( c != 0 ) + c = TTMATH_UINT_HIGHEST_BIT; + + for(i=sint(value_size)-1 ; i>=0 ; --i) + { + new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0; + table[i] = (table[i] >> 1) | c; + c = new_c; + } + + TTMATH_LOGC("UInt::Rcr2_one", c) + + return c; + } + + + + + /*! + this method moves all bits into the left hand side + return value <- this <- c + + the lowest *bits* will be held the 'c' and + the state of one additional bit (on the left hand side) + will be returned + + for example: + let this is 001010000 + after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 + */ + template + uint UInt::Rcl2(uint bits, uint c) + { + TTMATH_ASSERT( bits>0 && bits> move; + + for(i=0 ; i> move; + table[i] = (table[i] << bits) | c; + c = new_c; + } + + TTMATH_LOGC("UInt::Rcl2", c) + + return (c & 1); + } + + + + + /*! + this method moves all bits into the right hand side + C -> this -> return value + + the highest *bits* will be held the 'c' and + the state of one additional bit (on the right hand side) + will be returned + + for example: + let this is 000000010 + after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 + */ + template + uint UInt::Rcr2(uint bits, uint c) + { + TTMATH_ASSERT( bits>0 && bits=0 ; --i) + { + new_c = table[i] << move; + table[i] = (table[i] >> bits) | c; + c = new_c; + } + + TTMATH_LOGC("UInt::Rcr2", c) + + return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; + } + + + + + /*! + this method returns the number of the highest set bit in x + if the 'x' is zero this method returns '-1' + */ + template + sint UInt::FindLeadingBitInWord(uint x) + { + if( x == 0 ) + return -1; + + uint bit = TTMATH_BITS_PER_UINT - 1; + + while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 ) + { + x = x << 1; + --bit; + } + + return bit; + } + + + + /*! + this method returns the number of the highest set bit in x + if the 'x' is zero this method returns '-1' + */ + template + sint UInt::FindLowestBitInWord(uint x) + { + if( x == 0 ) + return -1; + + uint bit = 0; + + while( (x & 1) == 0 ) + { + x = x >> 1; + ++bit; + } + + return bit; + } + + + + /*! + this method sets a special bit in the 'value' + and returns the last state of the bit (zero or one) + + bit is from <0,TTMATH_BITS_PER_UINT-1> + + e.g. + uint x = 100; + uint bit = SetBitInWord(x, 3); + now: x = 108 and bit = 0 + */ + template + uint UInt::SetBitInWord(uint & value, uint bit) + { + TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) + + uint mask = 1; + + if( bit > 0 ) + mask = mask << bit; + + uint last = value & mask; + value = value | mask; + + return (last != 0) ? 1 : 0; + } + + + + + + + /*! + * + * Multiplication + * + * + */ + + + /*! + multiplication: result_high:result_low = a * b + result_high - higher word of the result + result_low - lower word of the result + + this methos never returns a carry + this method is used in the second version of the multiplication algorithms + */ + template + void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) + { + #ifdef TTMATH_PLATFORM32 + + /* + on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace + this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit + */ + + union uint_ + { + struct + { + uint low; // 32 bits + uint high; // 32 bits + } u_; + + ulint u; // 64 bits + } res; + + res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits + + *result_high = res.u_.high; + *result_low = res.u_.low; + + #else + + /* + 64 bits platforms + + we don't have a native type which has 128 bits + then we're splitting 'a' and 'b' to 4 parts (high and low halves) + and using 4 multiplications (with additions and carry correctness) + */ + + uint_ a_; + uint_ b_; + uint_ res_high1, res_high2; + uint_ res_low1, res_low2; + + a_.u = a; + b_.u = b; + + /* + the multiplication is as follows (schoolbook algorithm with O(n^2) ): + + 32 bits 32 bits + + +--------------------------------+ + | a_.u_.high | a_.u_.low | + +--------------------------------+ + | b_.u_.high | b_.u_.low | + +--------------------------------+--------------------------------+ + | res_high1.u | res_low1.u | + +--------------------------------+--------------------------------+ + | res_high2.u | res_low2.u | + +--------------------------------+--------------------------------+ + + 64 bits 64 bits + */ + + + uint_ temp; + + res_low1.u = uint(b_.u_.low) * uint(a_.u_.low); + + temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high); + res_low1.u_.high = temp.u_.low; + res_high1.u_.low = temp.u_.high; + res_high1.u_.high = 0; + + res_low2.u_.low = 0; + temp.u = uint(b_.u_.high) * uint(a_.u_.low); + res_low2.u_.high = temp.u_.low; + + res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high); + + uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u); + AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here + + *result_high = res_high2.u; + *result_low = res_low2.u; + + #endif + } + + + + + /*! + * + * Division + * + * + */ + + + /*! + this method calculates 64bits word a:b / 32bits c (a higher, b lower word) + r = a:b / c and rest - remainder + + * + * WARNING: + * the c has to be suitably large for the result being keeped in one word, + * if c is equal zero there'll be a hardware interruption (0) + * and probably the end of your program + * + */ + template + void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) + { + // (a < c ) for the result to be one word + TTMATH_ASSERT( c != 0 && a < c ) + + #ifdef TTMATH_PLATFORM32 + + union + { + struct + { + uint low; // 32 bits + uint high; // 32 bits + } u_; + + ulint u; // 64 bits + } ab; + + ab.u_.high = a; + ab.u_.low = b; + + *r = uint(ab.u / c); + *rest = uint(ab.u % c); + + #else + + uint_ c_; + c_.u = c; + + + if( a == 0 ) + { + *r = b / c; + *rest = b % c; + } + else + if( c_.u_.high == 0 ) + { + // higher half of 'c' is zero + // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c') + uint_ a_, b_, res_, temp1, temp2; + + a_.u = a; + b_.u = b; + + temp1.u_.high = a_.u_.low; + temp1.u_.low = b_.u_.high; + + res_.u_.high = (unsigned int)(temp1.u / c); + temp2.u_.high = (unsigned int)(temp1.u % c); + temp2.u_.low = b_.u_.low; + + res_.u_.low = (unsigned int)(temp2.u / c); + *rest = temp2.u % c; + + *r = res_.u; + } + else + { + return DivTwoWords2(a, b, c, r, rest); + } + + #endif + } + + +#ifdef TTMATH_PLATFORM64 + + + /*! + this method is available only on 64bit platforms + + the same algorithm like the third division algorithm in ttmathuint.h + but now with the radix=2^32 + */ + template + void UInt::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) + { + // a is not zero + // c_.u_.high is not zero + + uint_ a_, b_, c_, u_, q_; + unsigned int u3; // 32 bit + + a_.u = a; + b_.u = b; + c_.u = c; + + // normalizing + uint d = DivTwoWordsNormalize(a_, b_, c_); + + // loop from j=1 to j=0 + // the first step (for j=2) is skipped because our result is only in one word, + // (first 'q' were 0 and nothing would be changed) + u_.u_.high = a_.u_.high; + u_.u_.low = a_.u_.low; + u3 = b_.u_.high; + q_.u_.high = DivTwoWordsCalculate(u_, u3, c_); + MultiplySubtract(u_, u3, q_.u_.high, c_); + + u_.u_.high = u_.u_.low; + u_.u_.low = u3; + u3 = b_.u_.low; + q_.u_.low = DivTwoWordsCalculate(u_, u3, c_); + MultiplySubtract(u_, u3, q_.u_.low, c_); + + *r = q_.u; + + // unnormalizing for the remainder + u_.u_.high = u_.u_.low; + u_.u_.low = u3; + *rest = DivTwoWordsUnnormalize(u_.u, d); + } + + + + + template + uint UInt::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_) + { + uint d = 0; + + for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) + { + c_.u = c_.u << 1; + + uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b' + + b_.u = b_.u << 1; + a_.u = a_.u << 1; // carry bits from 'a' are simply skipped + + if( bc ) + a_.u = a_.u | 1; + } + + return d; + } + + + template + uint UInt::DivTwoWordsUnnormalize(uint u, uint d) + { + if( d == 0 ) + return u; + + u = u >> d; + + return u; + } + + + template + unsigned int UInt::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_) + { + bool next_test; + uint_ qp_, rp_, temp_; + + qp_.u = u_.u / uint(v_.u_.high); + rp_.u = u_.u % uint(v_.u_.high); + + TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 ) + + do + { + bool decrease = false; + + if( qp_.u_.high == 1 ) + decrease = true; + else + { + temp_.u_.high = rp_.u_.low; + temp_.u_.low = u3; + + if( qp_.u * uint(v_.u_.low) > temp_.u ) + decrease = true; + } + + next_test = false; + + if( decrease ) + { + --qp_.u; + rp_.u += v_.u_.high; + + if( rp_.u_.high == 0 ) + next_test = true; + } + } + while( next_test ); + + return qp_.u_.low; + } + + + template + void UInt::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_) + { + uint_ temp_; + + uint res_high; + uint res_low; + + MulTwoWords(v_.u, q, &res_high, &res_low); + + uint_ sub_res_high_; + uint_ sub_res_low_; + + temp_.u_.high = u_.u_.low; + temp_.u_.low = u3; + + uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u); + + temp_.u_.high = 0; + temp_.u_.low = u_.u_.high; + c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); + + if( c ) + { + --q; + + c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); + AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); + } + + u_.u_.high = sub_res_high_.u_.low; + u_.u_.low = sub_res_low_.u_.high; + u3 = sub_res_low_.u_.low; + } + +#endif // #ifdef TTMATH_PLATFORM64 + + + +} //namespace + + +#endif //ifdef TTMATH_NOASM +#endif + + + + diff --git a/src/libghost/ttmath/ttmath/ttmathuint_x86.h b/src/libghost/ttmath/ttmath/ttmathuint_x86.h new file mode 100644 index 0000000..1dd087f --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathuint_x86.h @@ -0,0 +1,1602 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef headerfilettmathuint_x86 +#define headerfilettmathuint_x86 + + +#ifndef TTMATH_NOASM +#ifdef TTMATH_PLATFORM32 + + +/*! + \file ttmathuint_x86.h + \brief template class UInt with assembler code for 32bit x86 processors + + this file is included at the end of ttmathuint.h +*/ + + + +/*! + \brief a namespace for the TTMath library +*/ +namespace ttmath +{ + + /*! + returning the string represents the currect type of the library + we have following types: + asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) + asm_gcc_32 - with asm code designed for GCC (32 bits) + asm_vc_64 - with asm for VC (64 bit) + asm_gcc_64 - with asm for GCC (64 bit) + no_asm_32 - pure C++ version (32 bit) - without any asm code + no_asm_64 - pure C++ version (64 bit) - without any asm code + */ + template + const char * UInt::LibTypeStr() + { + #ifndef __GNUC__ + static const char info[] = "asm_vc_32"; + #endif + + #ifdef __GNUC__ + static const char info[] = "asm_gcc_32"; + #endif + + return info; + } + + + /*! + returning the currect type of the library + */ + template + LibTypeCode UInt::LibType() + { + #ifndef __GNUC__ + LibTypeCode info = asm_vc_32; + #endif + + #ifdef __GNUC__ + LibTypeCode info = asm_gcc_32; + #endif + + return info; + } + + + + /*! + * + * basic mathematic functions + * + */ + + + /*! + adding ss2 to the this and adding carry if it's defined + (this = this + ss2 + c) + + c must be zero or one (might be a bigger value than 1) + function returns carry (1) (if it has been) + */ + template + uint UInt::Add(const UInt & ss2, uint c) + { + uint b = value_size; + uint * p1 = table; + uint * p2 = const_cast(ss2.table); + + // we don't have to use TTMATH_REFERENCE_ASSERT here + // this algorithm doesn't require it + + #ifndef __GNUC__ + + // this part might be compiled with for example visual c + + __asm + { + push eax + push ebx + push ecx + push edx + push esi + + mov ecx,[b] + + mov ebx,[p1] + mov esi,[p2] + + xor edx,edx // edx=0 + mov eax,[c] + neg eax // CF=1 if rax!=0 , CF=0 if rax==0 + + ttmath_loop: + mov eax,[esi+edx*4] + adc [ebx+edx*4],eax + + inc edx + dec ecx + jnz ttmath_loop + + adc ecx, ecx + mov [c], ecx + + pop esi + pop edx + pop ecx + pop ebx + pop eax + } + + + + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + // this part should be compiled with gcc + + __asm__ __volatile__( + + "xorl %%edx, %%edx \n" + "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 + + "1: \n" + "movl (%%esi,%%edx,4), %%eax \n" + "adcl %%eax, (%%ebx,%%edx,4) \n" + + "incl %%edx \n" + "decl %%ecx \n" + "jnz 1b \n" + + "adc %%ecx, %%ecx \n" + + : "=c" (c), "=a" (dummy), "=d" (dummy2) + : "0" (b), "1" (c), "b" (p1), "S" (p2) + : "cc", "memory" ); + #endif + + TTMATH_LOGC("UInt::Add", c) + + return c; + } + + + + /*! + adding one word (at a specific position) + and returning a carry (if it has been) + + e.g. + + if we've got (value_size=3): + table[0] = 10; + table[1] = 30; + table[2] = 5; + and we call: + AddInt(2,1) + then it'll be: + table[0] = 10; + table[1] = 30 + 2; + table[2] = 5; + + of course if there was a carry from table[2] it would be returned + */ + template + uint UInt::AddInt(uint value, uint index) + { + uint b = value_size; + uint * p1 = table; + uint c; + + TTMATH_ASSERT( index < value_size ) + + #ifndef __GNUC__ + + __asm + { + push eax + push ebx + push ecx + push edx + + mov ecx, [b] + sub ecx, [index] + + mov edx, [index] + mov ebx, [p1] + + mov eax, [value] + + ttmath_loop: + add [ebx+edx*4], eax + jnc ttmath_end + + mov eax, 1 + inc edx + dec ecx + jnz ttmath_loop + + ttmath_end: + setc al + movzx edx, al + mov [c], edx + + pop edx + pop ecx + pop ebx + pop eax + } + + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "subl %%edx, %%ecx \n" + + "1: \n" + "addl %%eax, (%%ebx,%%edx,4) \n" + "jnc 2f \n" + + "movl $1, %%eax \n" + "incl %%edx \n" + "decl %%ecx \n" + "jnz 1b \n" + + "2: \n" + "setc %%al \n" + "movzx %%al, %%edx \n" + + : "=d" (c), "=a" (dummy), "=c" (dummy2) + : "0" (index), "1" (value), "2" (b), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::AddInt", c) + + return c; + } + + + + + /*! + adding only two unsigned words to the existing value + and these words begin on the 'index' position + (it's used in the multiplication algorithm 2) + + index should be equal or smaller than value_size-2 (index <= value_size-2) + x1 - lower word, x2 - higher word + + for example if we've got value_size equal 4 and: + table[0] = 3 + table[1] = 4 + table[2] = 5 + table[3] = 6 + then let + x1 = 10 + x2 = 20 + and + index = 1 + + the result of this method will be: + table[0] = 3 + table[1] = 4 + x1 = 14 + table[2] = 5 + x2 = 25 + table[3] = 6 + + and no carry at the end of table[3] + + (of course if there was a carry in table[2](5+20) then + this carry would be passed to the table[3] etc.) + */ + template + uint UInt::AddTwoInts(uint x2, uint x1, uint index) + { + uint b = value_size; + uint * p1 = table; + uint c; + + TTMATH_ASSERT( index < value_size - 1 ) + + #ifndef __GNUC__ + __asm + { + push eax + push ebx + push ecx + push edx + + mov ecx, [b] + sub ecx, [index] + + mov ebx, [p1] + mov edx, [index] + + mov eax, [x1] + add [ebx+edx*4], eax + inc edx + dec ecx + + mov eax, [x2] + + ttmath_loop: + adc [ebx+edx*4], eax + jnc ttmath_end + + mov eax, 0 + inc edx + dec ecx + jnz ttmath_loop + + ttmath_end: + setc al + movzx edx, al + mov [c], edx + + pop edx + pop ecx + pop ebx + pop eax + + } + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "subl %%edx, %%ecx \n" + + "addl %%esi, (%%ebx,%%edx,4) \n" + "incl %%edx \n" + "decl %%ecx \n" + + "1: \n" + "adcl %%eax, (%%ebx,%%edx,4) \n" + "jnc 2f \n" + + "mov $0, %%eax \n" + "incl %%edx \n" + "decl %%ecx \n" + "jnz 1b \n" + + "2: \n" + "setc %%al \n" + "movzx %%al, %%eax \n" + + : "=a" (c), "=c" (dummy), "=d" (dummy2) + : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::AddTwoInts", c) + + return c; + } + + + + /*! + this static method addes one vector to the other + 'ss1' is larger in size or equal to 'ss2' + + ss1 points to the first (larger) vector + ss2 points to the second vector + ss1_size - size of the ss1 (and size of the result too) + ss2_size - size of the ss2 + result - is the result vector (which has size the same as ss1: ss1_size) + + Example: ss1_size is 5, ss2_size is 3 + ss1: ss2: result (output): + 5 1 5+1 + 4 3 4+3 + 2 7 2+7 + 6 6 + 9 9 + of course the carry is propagated and will be returned from the last item + (this method is used by the Karatsuba multiplication algorithm) + */ + template + uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + { + TTMATH_ASSERT( ss1_size >= ss2_size ) + + uint rest = ss1_size - ss2_size; + uint c; + + #ifndef __GNUC__ + + // this part might be compiled with for example visual c + __asm + { + pushad + + mov ecx, [ss2_size] + xor edx, edx // edx = 0, cf = 0 + + mov esi, [ss1] + mov ebx, [ss2] + mov edi, [result] + + ttmath_loop: + mov eax, [esi+edx*4] + adc eax, [ebx+edx*4] + mov [edi+edx*4], eax + + inc edx + dec ecx + jnz ttmath_loop + + adc ecx, ecx // ecx has the cf state + + mov ebx, [rest] + or ebx, ebx + jz ttmath_end + + xor ebx, ebx // ebx = 0 + neg ecx // setting cf from ecx + mov ecx, [rest] // ecx is != 0 + + ttmath_loop2: + mov eax, [esi+edx*4] + adc eax, ebx + mov [edi+edx*4], eax + + inc edx + dec ecx + jnz ttmath_loop2 + + adc ecx, ecx + + ttmath_end: + mov [c], ecx + + popad + } + + #endif + + + #ifdef __GNUC__ + + // this part should be compiled with gcc + uint dummy1, dummy2, dummy3; + + __asm__ __volatile__( + "push %%edx \n" + "xor %%edx, %%edx \n" // edx = 0, cf = 0 + "1: \n" + "mov (%%esi,%%edx,4), %%eax \n" + "adc (%%ebx,%%edx,4), %%eax \n" + "mov %%eax, (%%edi,%%edx,4) \n" + + "inc %%edx \n" + "dec %%ecx \n" + "jnz 1b \n" + + "adc %%ecx, %%ecx \n" // ecx has the cf state + "pop %%eax \n" // eax = rest + + "or %%eax, %%eax \n" + "jz 3f \n" + + "xor %%ebx, %%ebx \n" // ebx = 0 + "neg %%ecx \n" // setting cf from ecx + "mov %%eax, %%ecx \n" // ecx=rest and is != 0 + "2: \n" + "mov (%%esi, %%edx, 4), %%eax \n" + "adc %%ebx, %%eax \n" + "mov %%eax, (%%edi, %%edx, 4) \n" + + "inc %%edx \n" + "dec %%ecx \n" + "jnz 2b \n" + + "adc %%ecx, %%ecx \n" + "3: \n" + + : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) + : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) + : "cc", "memory" ); + + #endif + + TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) + + return c; + } + + + /*! + subtracting ss2 from the 'this' and subtracting + carry if it has been defined + (this = this - ss2 - c) + + c must be zero or one (might be a bigger value than 1) + function returns carry (1) (if it has been) + */ + template + uint UInt::Sub(const UInt & ss2, uint c) + { + uint b = value_size; + uint * p1 = table; + uint * p2 = const_cast(ss2.table); + + // we don't have to use TTMATH_REFERENCE_ASSERT here + // this algorithm doesn't require it + + #ifndef __GNUC__ + + __asm + { + push eax + push ebx + push ecx + push edx + push esi + + mov ecx,[b] + + mov ebx,[p1] + mov esi,[p2] + + xor edx,edx // edx=0 + mov eax,[c] + neg eax // CF=1 if rax!=0 , CF=0 if rax==0 + + ttmath_loop: + mov eax,[esi+edx*4] + sbb [ebx+edx*4],eax + + inc edx + dec ecx + jnz ttmath_loop + + adc ecx, ecx + mov [c], ecx + + pop esi + pop edx + pop ecx + pop ebx + pop eax + } + + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "xorl %%edx, %%edx \n" + "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 + + "1: \n" + "movl (%%esi,%%edx,4), %%eax \n" + "sbbl %%eax, (%%ebx,%%edx,4) \n" + + "incl %%edx \n" + "decl %%ecx \n" + "jnz 1b \n" + + "adc %%ecx, %%ecx \n" + + : "=c" (c), "=a" (dummy), "=d" (dummy2) + : "0" (b), "1" (c), "b" (p1), "S" (p2) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Sub", c) + + return c; + } + + + + + /*! + this method subtracts one word (at a specific position) + and returns a carry (if it was) + + e.g. + + if we've got (value_size=3): + table[0] = 10; + table[1] = 30; + table[2] = 5; + and we call: + SubInt(2,1) + then it'll be: + table[0] = 10; + table[1] = 30 - 2; + table[2] = 5; + + of course if there was a carry from table[2] it would be returned + */ + template + uint UInt::SubInt(uint value, uint index) + { + uint b = value_size; + uint * p1 = table; + uint c; + + TTMATH_ASSERT( index < value_size ) + + #ifndef __GNUC__ + + __asm + { + push eax + push ebx + push ecx + push edx + + mov ecx, [b] + sub ecx, [index] + + mov edx, [index] + mov ebx, [p1] + + mov eax, [value] + + ttmath_loop: + sub [ebx+edx*4], eax + jnc ttmath_end + + mov eax, 1 + inc edx + dec ecx + jnz ttmath_loop + + ttmath_end: + setc al + movzx edx, al + mov [c], edx + + pop edx + pop ecx + pop ebx + pop eax + } + + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "subl %%edx, %%ecx \n" + + "1: \n" + "subl %%eax, (%%ebx,%%edx,4) \n" + "jnc 2f \n" + + "movl $1, %%eax \n" + "incl %%edx \n" + "decl %%ecx \n" + "jnz 1b \n" + + "2: \n" + "setc %%al \n" + "movzx %%al, %%edx \n" + + : "=d" (c), "=a" (dummy), "=c" (dummy2) + : "0" (index), "1" (value), "2" (b), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::SubInt", c) + + return c; + } + + + + /*! + this static method subtractes one vector from the other + 'ss1' is larger in size or equal to 'ss2' + + ss1 points to the first (larger) vector + ss2 points to the second vector + ss1_size - size of the ss1 (and size of the result too) + ss2_size - size of the ss2 + result - is the result vector (which has size the same as ss1: ss1_size) + + Example: ss1_size is 5, ss2_size is 3 + ss1: ss2: result (output): + 5 1 5-1 + 4 3 4-3 + 2 7 2-7 + 6 6-1 (the borrow from previous item) + 9 9 + return (carry): 0 + of course the carry (borrow) is propagated and will be returned from the last item + (this method is used by the Karatsuba multiplication algorithm) + */ + template + uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + { + TTMATH_ASSERT( ss1_size >= ss2_size ) + + uint rest = ss1_size - ss2_size; + uint c; + + #ifndef __GNUC__ + + // this part might be compiled with for example visual c + + /* + the asm code is nearly the same as in AddVector + only two instructions 'adc' are changed to 'sbb' + */ + __asm + { + pushad + + mov ecx, [ss2_size] + xor edx, edx // edx = 0, cf = 0 + + mov esi, [ss1] + mov ebx, [ss2] + mov edi, [result] + + ttmath_loop: + mov eax, [esi+edx*4] + sbb eax, [ebx+edx*4] + mov [edi+edx*4], eax + + inc edx + dec ecx + jnz ttmath_loop + + adc ecx, ecx // ecx has the cf state + + mov ebx, [rest] + or ebx, ebx + jz ttmath_end + + xor ebx, ebx // ebx = 0 + neg ecx // setting cf from ecx + mov ecx, [rest] // ecx is != 0 + + ttmath_loop2: + mov eax, [esi+edx*4] + sbb eax, ebx + mov [edi+edx*4], eax + + inc edx + dec ecx + jnz ttmath_loop2 + + adc ecx, ecx + + ttmath_end: + mov [c], ecx + + popad + } + + #endif + + + #ifdef __GNUC__ + + // this part should be compiled with gcc + uint dummy1, dummy2, dummy3; + + __asm__ __volatile__( + "push %%edx \n" + "xor %%edx, %%edx \n" // edx = 0, cf = 0 + "1: \n" + "mov (%%esi,%%edx,4), %%eax \n" + "sbb (%%ebx,%%edx,4), %%eax \n" + "mov %%eax, (%%edi,%%edx,4) \n" + + "inc %%edx \n" + "dec %%ecx \n" + "jnz 1b \n" + + "adc %%ecx, %%ecx \n" // ecx has the cf state + "pop %%eax \n" // eax = rest + + "or %%eax, %%eax \n" + "jz 3f \n" + + "xor %%ebx, %%ebx \n" // ebx = 0 + "neg %%ecx \n" // setting cf from ecx + "mov %%eax, %%ecx \n" // ecx=rest and is != 0 + "2: \n" + "mov (%%esi, %%edx, 4), %%eax \n" + "sbb %%ebx, %%eax \n" + "mov %%eax, (%%edi, %%edx, 4) \n" + + "inc %%edx \n" + "dec %%ecx \n" + "jnz 2b \n" + + "adc %%ecx, %%ecx \n" + "3: \n" + + : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) + : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) + : "cc", "memory" ); + + #endif + + TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) + + return c; + } + + + + /*! + this method moves all bits into the left hand side + return value <- this <- c + + the lowest *bit* will be held the 'c' and + the state of one additional bit (on the left hand side) + will be returned + + for example: + let this is 001010000 + after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 + */ + template + uint UInt::Rcl2_one(uint c) + { + uint b = value_size; + uint * p1 = table; + + #ifndef __GNUC__ + __asm + { + push ebx + push ecx + push edx + + mov ebx, [p1] + xor edx, edx + mov ecx, [c] + neg ecx + mov ecx, [b] + + ttmath_loop: + rcl dword ptr [ebx+edx*4], 1 + + inc edx + dec ecx + jnz ttmath_loop + + adc ecx, ecx + mov [c], ecx + + pop edx + pop ecx + pop ebx + } + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "xorl %%edx, %%edx \n" // edx=0 + "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 + + "1: \n" + "rcll $1, (%%ebx, %%edx, 4) \n" + + "incl %%edx \n" + "decl %%ecx \n" + "jnz 1b \n" + + "adcl %%ecx, %%ecx \n" + + : "=c" (c), "=a" (dummy), "=d" (dummy2) + : "0" (b), "1" (c), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Rcl2_one", c) + + return c; + } + + + + /*! + this method moves all bits into the right hand side + c -> this -> return value + + the highest *bit* will be held the 'c' and + the state of one additional bit (on the right hand side) + will be returned + + for example: + let this is 000000010 + after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 + */ + template + uint UInt::Rcr2_one(uint c) + { + uint b = value_size; + uint * p1 = table; + + #ifndef __GNUC__ + __asm + { + push ebx + push ecx + + mov ebx, [p1] + mov ecx, [c] + neg ecx + mov ecx, [b] + + ttmath_loop: + rcr dword ptr [ebx+ecx*4-4], 1 + + dec ecx + jnz ttmath_loop + + adc ecx, ecx + mov [c], ecx + + pop ecx + pop ebx + } + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ __volatile__( + + "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 + + "1: \n" + "rcrl $1, -4(%%ebx, %%ecx, 4) \n" + + "decl %%ecx \n" + "jnz 1b \n" + + "adcl %%ecx, %%ecx \n" + + : "=c" (c), "=a" (dummy) + : "0" (b), "1" (c), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Rcr2_one", c) + + return c; + } + + + +#ifdef _MSC_VER +#pragma warning (disable : 4731) +//warning C4731: frame pointer register 'ebp' modified by inline assembly code +#endif + + + + /*! + this method moves all bits into the left hand side + return value <- this <- c + + the lowest *bits* will be held the 'c' and + the state of one additional bit (on the left hand side) + will be returned + + for example: + let this is 001010000 + after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 + */ + template + uint UInt::Rcl2(uint bits, uint c) + { + TTMATH_ASSERT( bits>0 && bits edx -> cf) (cl times) + "movl %%edx, %%ebp \n" // ebp = edx = mask + "movl %%esi, %%ecx \n" + + "xorl %%edx, %%edx \n" + "movl %%edx, %%esi \n" + "orl %%eax, %%eax \n" + "cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0 + + "1: \n" + "roll %%cl, (%%ebx,%%edx,4) \n" + + "movl (%%ebx,%%edx,4), %%eax \n" + "andl %%ebp, %%eax \n" + "xorl %%eax, (%%ebx,%%edx,4) \n" + "orl %%esi, (%%ebx,%%edx,4) \n" + "movl %%eax, %%esi \n" + + "incl %%edx \n" + "decl %%edi \n" + "jnz 1b \n" + + "and $1, %%eax \n" + + "pop %%ebp \n" + + : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3) + : "0" (c), "1" (b), "b" (p1), "c" (bits) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Rcl2", c) + + return c; + } + + + + + /*! + this method moves all bits into the right hand side + C -> this -> return value + + the highest *bits* will be held the 'c' and + the state of one additional bit (on the right hand side) + will be returned + + for example: + let this is 000000010 + after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 + */ + template + uint UInt::Rcr2(uint bits, uint c) + { + TTMATH_ASSERT( bits>0 && bits + sint UInt::FindLeadingBitInWord(uint x) + { + sint result; + + #ifndef __GNUC__ + __asm + { + push eax + push edx + + mov edx,-1 + bsr eax,[x] + cmovz eax,edx + mov [result], eax + + pop edx + pop eax + } + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ ( + + "movl $-1, %1 \n" + "bsrl %2, %0 \n" + "cmovz %1, %0 \n" + + : "=r" (result), "=&r" (dummy) + : "r" (x) + : "cc" ); + + #endif + + return result; + } + + + + /* + this method returns the number of the smallest set bit in one 32-bit word + if the 'x' is zero this method returns '-1' + */ + template + sint UInt::FindLowestBitInWord(uint x) + { + sint result; + + #ifndef __GNUC__ + __asm + { + push eax + push edx + + mov edx,-1 + bsf eax,[x] + cmovz eax,edx + mov [result], eax + + pop edx + pop eax + } + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ ( + + "movl $-1, %1 \n" + "bsfl %2, %0 \n" + "cmovz %1, %0 \n" + + : "=r" (result), "=&r" (dummy) + : "r" (x) + : "cc" ); + + #endif + + return result; + } + + + + /*! + this method sets a special bit in the 'value' + and returns the last state of the bit (zero or one) + + bit is from <0,31> + e.g. + uint x = 100; + uint bit = SetBitInWord(x, 3); + now: x = 108 and bit = 0 + */ + template + uint UInt::SetBitInWord(uint & value, uint bit) + { + TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) + + uint old_bit; + uint v = value; + + #ifndef __GNUC__ + __asm + { + push ebx + push eax + + mov eax, [v] + mov ebx, [bit] + bts eax, ebx + mov [v], eax + + setc bl + movzx ebx, bl + mov [old_bit], ebx + + pop eax + pop ebx + } + #endif + + + #ifdef __GNUC__ + __asm__ ( + + "btsl %%ebx, %%eax \n" + "setc %%bl \n" + "movzx %%bl, %%ebx \n" + + : "=a" (v), "=b" (old_bit) + : "0" (v), "1" (bit) + : "cc" ); + + #endif + + value = v; + + return old_bit; + } + + + + + /*! + multiplication: result_high:result_low = a * b + result_high - higher word of the result + result_low - lower word of the result + + this methos never returns a carry + this method is used in the second version of the multiplication algorithms + */ + template + void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) + { + /* + we must use these temporary variables in order to inform the compilator + that value pointed with result1 and result2 has changed + + this has no effect in visual studio but it's useful when + using gcc and options like -Ox + */ + uint result1_; + uint result2_; + + #ifndef __GNUC__ + + __asm + { + push eax + push edx + + mov eax, [a] + mul dword ptr [b] + + mov [result2_], edx + mov [result1_], eax + + pop edx + pop eax + } + + #endif + + + #ifdef __GNUC__ + + __asm__ ( + + "mull %%edx \n" + + : "=a" (result1_), "=d" (result2_) + : "0" (a), "1" (b) + : "cc" ); + + #endif + + + *result_low = result1_; + *result_high = result2_; + } + + + + + + /*! + * + * Division + * + * + */ + + + + + /*! + this method calculates 64bits word a:b / 32bits c (a higher, b lower word) + r = a:b / c and rest - remainder + + * + * WARNING: + * if r (one word) is too small for the result or c is equal zero + * there'll be a hardware interruption (0) + * and probably the end of your program + * + */ + template + void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) + { + uint r_; + uint rest_; + /* + these variables have similar meaning like those in + the multiplication algorithm MulTwoWords + */ + + TTMATH_ASSERT( c != 0 ) + + #ifndef __GNUC__ + __asm + { + push eax + push edx + + mov edx, [a] + mov eax, [b] + div dword ptr [c] + + mov [r_], eax + mov [rest_], edx + + pop edx + pop eax + } + #endif + + + #ifdef __GNUC__ + + __asm__ ( + + "divl %%ecx \n" + + : "=a" (r_), "=d" (rest_) + : "0" (b), "1" (a), "c" (c) + : "cc" ); + + #endif + + + *r = r_; + *rest = rest_; + + } + + + +} //namespace + + + +#endif //ifdef TTMATH_PLATFORM32 +#endif //ifndef TTMATH_NOASM +#endif diff --git a/src/libghost/ttmath/ttmath/ttmathuint_x86_64.h b/src/libghost/ttmath/ttmath/ttmathuint_x86_64.h new file mode 100644 index 0000000..2fedb70 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathuint_x86_64.h @@ -0,0 +1,1222 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef headerfilettmathuint_x86_64 +#define headerfilettmathuint_x86_64 + + +#ifndef TTMATH_NOASM +#ifdef TTMATH_PLATFORM64 + + +/*! + \file ttmathuint_x86_64.h + \brief template class UInt with assembler code for 64bit x86_64 processors + + this file is included at the end of ttmathuint.h +*/ + +#ifdef _MSC_VER +#include +#endif + + +namespace ttmath +{ + + #ifdef _MSC_VER + + extern "C" + { + uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c); + uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); + uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2); + uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); + uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); + uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); + uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); + uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit); + uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit); + uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); + uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c); + uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c); + }; + #endif + + + /*! + returning the string represents the currect type of the library + we have following types: + asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) + asm_gcc_32 - with asm code designed for GCC (32 bits) + asm_vc_64 - with asm for VC (64 bit) + asm_gcc_64 - with asm for GCC (64 bit) + no_asm_32 - pure C++ version (32 bit) - without any asm code + no_asm_64 - pure C++ version (64 bit) - without any asm code + */ + template + const char * UInt::LibTypeStr() + { + #ifdef _MSC_VER + static const char info[] = "asm_vc_64"; + #endif + + #ifdef __GNUC__ + static const char info[] = "asm_gcc_64"; + #endif + + return info; + } + + + /*! + returning the currect type of the library + */ + template + LibTypeCode UInt::LibType() + { + #ifdef _MSC_VER + LibTypeCode info = asm_vc_64; + #endif + + #ifdef __GNUC__ + LibTypeCode info = asm_gcc_64; + #endif + + return info; + } + + + /*! + * + * basic mathematic functions + * + */ + + + + /*! + this method adding ss2 to the this and adding carry if it's defined + (this = this + ss2 + c) + + ***this method is created only on a 64bit platform*** + + c must be zero or one (might be a bigger value than 1) + function returns carry (1) (if it was) + */ + template + uint UInt::Add(const UInt & ss2, uint c) + { + uint b = value_size; + uint * p1 = table; + const uint * p2 = ss2.table; + + // we don't have to use TTMATH_REFERENCE_ASSERT here + // this algorithm doesn't require it + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + #ifdef _MSC_VER + c = ttmath_adc_x64(p1,p2,b,c); + #endif + + #ifdef __GNUC__ + uint dummy, dummy2; + + /* + this part should be compiled with gcc + */ + __asm__ __volatile__( + + "xorq %%rdx, %%rdx \n" + "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 + + "1: \n" + "movq (%%rsi,%%rdx,8), %%rax \n" + "adcq %%rax, (%%rbx,%%rdx,8) \n" + + "incq %%rdx \n" + "decq %%rcx \n" + "jnz 1b \n" + + "adcq %%rcx, %%rcx \n" + + : "=c" (c), "=a" (dummy), "=d" (dummy2) + : "0" (b), "1" (c), "b" (p1), "S" (p2) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Add", c) + + return c; + } + + + + /*! + this method adds one word (at a specific position) + and returns a carry (if it was) + + ***this method is created only on a 64bit platform*** + + + if we've got (value_size=3): + table[0] = 10; + table[1] = 30; + table[2] = 5; + and we call: + AddInt(2,1) + then it'll be: + table[0] = 10; + table[1] = 30 + 2; + table[2] = 5; + + of course if there was a carry from table[2] it would be returned + */ + template + uint UInt::AddInt(uint value, uint index) + { + uint b = value_size; + uint * p1 = table; + uint c; + + TTMATH_ASSERT( index < value_size ) + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_addindexed_x64(p1,b,index,value); + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "subq %%rdx, %%rcx \n" + + "1: \n" + "addq %%rax, (%%rbx,%%rdx,8) \n" + "jnc 2f \n" + + "movq $1, %%rax \n" + "incq %%rdx \n" + "decq %%rcx \n" + "jnz 1b \n" + + "2: \n" + "setc %%al \n" + "movzx %%al, %%rdx \n" + + : "=d" (c), "=a" (dummy), "=c" (dummy2) + : "0" (index), "1" (value), "2" (b), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::AddInt", c) + + return c; + } + + + + /*! + this method adds only two unsigned words to the existing value + and these words begin on the 'index' position + (it's used in the multiplication algorithm 2) + + ***this method is created only on a 64bit platform*** + + index should be equal or smaller than value_size-2 (index <= value_size-2) + x1 - lower word, x2 - higher word + + for example if we've got value_size equal 4 and: + table[0] = 3 + table[1] = 4 + table[2] = 5 + table[3] = 6 + then let + x1 = 10 + x2 = 20 + and + index = 1 + + the result of this method will be: + table[0] = 3 + table[1] = 4 + x1 = 14 + table[2] = 5 + x2 = 25 + table[3] = 6 + + and no carry at the end of table[3] + + (of course if there was a carry in table[2](5+20) then + this carry would be passed to the table[3] etc.) + */ + template + uint UInt::AddTwoInts(uint x2, uint x1, uint index) + { + uint b = value_size; + uint * p1 = table; + uint c; + + TTMATH_ASSERT( index < value_size - 1 ) + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_addindexed2_x64(p1,b,index,x1,x2); + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "subq %%rdx, %%rcx \n" + + "addq %%rsi, (%%rbx,%%rdx,8) \n" + "incq %%rdx \n" + "decq %%rcx \n" + + "1: \n" + "adcq %%rax, (%%rbx,%%rdx,8) \n" + "jnc 2f \n" + + "mov $0, %%rax \n" + "incq %%rdx \n" + "decq %%rcx \n" + "jnz 1b \n" + + "2: \n" + "setc %%al \n" + "movzx %%al, %%rax \n" + + : "=a" (c), "=c" (dummy), "=d" (dummy2) + : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::AddTwoInts", c) + + return c; + } + + + + /*! + this static method addes one vector to the other + 'ss1' is larger in size or equal to 'ss2' + + ss1 points to the first (larger) vector + ss2 points to the second vector + ss1_size - size of the ss1 (and size of the result too) + ss2_size - size of the ss2 + result - is the result vector (which has size the same as ss1: ss1_size) + + Example: ss1_size is 5, ss2_size is 3 + ss1: ss2: result (output): + 5 1 5+1 + 4 3 4+3 + 2 7 2+7 + 6 6 + 9 9 + of course the carry is propagated and will be returned from the last item + (this method is used by the Karatsuba multiplication algorithm) + */ + template + uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + { + TTMATH_ASSERT( ss1_size >= ss2_size ) + + uint c; + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result); + #endif + + + #ifdef __GNUC__ + uint dummy1, dummy2, dummy3; + uint rest = ss1_size - ss2_size; + + // this part should be compiled with gcc + + __asm__ __volatile__( + "mov %%rdx, %%r8 \n" + "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 + "1: \n" + "mov (%%rsi,%%rdx,8), %%rax \n" + "adc (%%rbx,%%rdx,8), %%rax \n" + "mov %%rax, (%%rdi,%%rdx,8) \n" + + "inc %%rdx \n" + "dec %%rcx \n" + "jnz 1b \n" + + "adc %%rcx, %%rcx \n" // rcx has the cf state + + "or %%r8, %%r8 \n" + "jz 3f \n" + + "xor %%rbx, %%rbx \n" // ebx = 0 + "neg %%rcx \n" // setting cf from rcx + "mov %%r8, %%rcx \n" // rcx=rest and is != 0 + "2: \n" + "mov (%%rsi, %%rdx, 8), %%rax \n" + "adc %%rbx, %%rax \n" + "mov %%rax, (%%rdi, %%rdx, 8) \n" + + "inc %%rdx \n" + "dec %%rcx \n" + "jnz 2b \n" + + "adc %%rcx, %%rcx \n" + "3: \n" + + : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) + : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) + : "%r8", "cc", "memory" ); + + #endif + + TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) + + return c; + } + + + + /*! + this method's subtracting ss2 from the 'this' and subtracting + carry if it has been defined + (this = this - ss2 - c) + + ***this method is created only on a 64bit platform*** + + c must be zero or one (might be a bigger value than 1) + function returns carry (1) (if it was) + */ + template + uint UInt::Sub(const UInt & ss2, uint c) + { + uint b = value_size; + uint * p1 = table; + const uint * p2 = ss2.table; + + + // we don't have to use TTMATH_REFERENCE_ASSERT here + // this algorithm doesn't require it + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_sbb_x64(p1,p2,b,c); + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "xorq %%rdx, %%rdx \n" + "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 + + "1: \n" + "movq (%%rsi,%%rdx,8), %%rax \n" + "sbbq %%rax, (%%rbx,%%rdx,8) \n" + + "incq %%rdx \n" + "decq %%rcx \n" + "jnz 1b \n" + + "adcq %%rcx, %%rcx \n" + + : "=c" (c), "=a" (dummy), "=d" (dummy2) + : "0" (b), "1" (c), "b" (p1), "S" (p2) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Sub", c) + + return c; + } + + + + /*! + this method subtracts one word (at a specific position) + and returns a carry (if it was) + + ***this method is created only on a 64bit platform*** + + if we've got (value_size=3): + table[0] = 10; + table[1] = 30; + table[2] = 5; + and we call: + SubInt(2,1) + then it'll be: + table[0] = 10; + table[1] = 30 - 2; + table[2] = 5; + + of course if there was a carry from table[2] it would be returned + */ + template + uint UInt::SubInt(uint value, uint index) + { + uint b = value_size; + uint * p1 = table; + uint c; + + TTMATH_ASSERT( index < value_size ) + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_subindexed_x64(p1,b,index,value); + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "subq %%rdx, %%rcx \n" + + "1: \n" + "subq %%rax, (%%rbx,%%rdx,8) \n" + "jnc 2f \n" + + "movq $1, %%rax \n" + "incq %%rdx \n" + "decq %%rcx \n" + "jnz 1b \n" + + "2: \n" + "setc %%al \n" + "movzx %%al, %%rdx \n" + + : "=d" (c), "=a" (dummy), "=c" (dummy2) + : "0" (index), "1" (value), "2" (b), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::SubInt", c) + + return c; + } + + + /*! + this static method subtractes one vector from the other + 'ss1' is larger in size or equal to 'ss2' + + ss1 points to the first (larger) vector + ss2 points to the second vector + ss1_size - size of the ss1 (and size of the result too) + ss2_size - size of the ss2 + result - is the result vector (which has size the same as ss1: ss1_size) + + Example: ss1_size is 5, ss2_size is 3 + ss1: ss2: result (output): + 5 1 5-1 + 4 3 4-3 + 2 7 2-7 + 6 6-1 (the borrow from previous item) + 9 9 + return (carry): 0 + of course the carry (borrow) is propagated and will be returned from the last item + (this method is used by the Karatsuba multiplication algorithm) + */ + template + uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) + { + TTMATH_ASSERT( ss1_size >= ss2_size ) + + uint c; + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result); + #endif + + + #ifdef __GNUC__ + + // the asm code is nearly the same as in AddVector + // only two instructions 'adc' are changed to 'sbb' + + uint dummy1, dummy2, dummy3; + uint rest = ss1_size - ss2_size; + + __asm__ __volatile__( + "mov %%rdx, %%r8 \n" + "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 + "1: \n" + "mov (%%rsi,%%rdx,8), %%rax \n" + "sbb (%%rbx,%%rdx,8), %%rax \n" + "mov %%rax, (%%rdi,%%rdx,8) \n" + + "inc %%rdx \n" + "dec %%rcx \n" + "jnz 1b \n" + + "adc %%rcx, %%rcx \n" // rcx has the cf state + + "or %%r8, %%r8 \n" + "jz 3f \n" + + "xor %%rbx, %%rbx \n" // ebx = 0 + "neg %%rcx \n" // setting cf from rcx + "mov %%r8, %%rcx \n" // rcx=rest and is != 0 + "2: \n" + "mov (%%rsi, %%rdx, 8), %%rax \n" + "sbb %%rbx, %%rax \n" + "mov %%rax, (%%rdi, %%rdx, 8) \n" + + "inc %%rdx \n" + "dec %%rcx \n" + "jnz 2b \n" + + "adc %%rcx, %%rcx \n" + "3: \n" + + : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) + : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) + : "%r8", "cc", "memory" ); + + #endif + + TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) + + return c; + } + + + /*! + this method moves all bits into the left hand side + return value <- this <- c + + the lowest *bit* will be held the 'c' and + the state of one additional bit (on the left hand side) + will be returned + + for example: + let this is 001010000 + after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 + + ***this method is created only on a 64bit platform*** + */ + template + uint UInt::Rcl2_one(uint c) + { + sint b = value_size; + uint * p1 = table; + + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_rcl_x64(p1,b,c); + #endif + + + #ifdef __GNUC__ + uint dummy, dummy2; + + __asm__ __volatile__( + + "xorq %%rdx, %%rdx \n" // rdx=0 + "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 + + "1: \n" + "rclq $1, (%%rbx, %%rdx, 8) \n" + + "incq %%rdx \n" + "decq %%rcx \n" + "jnz 1b \n" + + "adcq %%rcx, %%rcx \n" + + : "=c" (c), "=a" (dummy), "=d" (dummy2) + : "0" (b), "1" (c), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Rcl2_one", c) + + return c; + } + + + /*! + this method moves all bits into the right hand side + c -> this -> return value + + the highest *bit* will be held the 'c' and + the state of one additional bit (on the right hand side) + will be returned + + for example: + let this is 000000010 + after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 + + ***this method is created only on a 64bit platform*** + */ + template + uint UInt::Rcr2_one(uint c) + { + sint b = value_size; + uint * p1 = table; + + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + c = ttmath_rcr_x64(p1,b,c); + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ __volatile__( + + "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 + + "1: \n" + "rcrq $1, -8(%%rbx, %%rcx, 8) \n" + + "decq %%rcx \n" + "jnz 1b \n" + + "adcq %%rcx, %%rcx \n" + + : "=c" (c), "=a" (dummy) + : "0" (b), "1" (c), "b" (p1) + : "cc", "memory" ); + + #endif + + TTMATH_LOGC("UInt::Rcr2_one", c) + + return c; + } + + + + /*! + this method moves all bits into the left hand side + return value <- this <- c + + the lowest *bits* will be held the 'c' and + the state of one additional bit (on the left hand side) + will be returned + + for example: + let this is 001010000 + after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 + + ***this method is created only on a 64bit platform*** + */ + template + uint UInt::Rcl2(uint bits, uint c) + { + TTMATH_ASSERT( bits>0 && bits this -> return value + + the highest *bits* will be held the 'c' and + the state of one additional bit (on the right hand side) + will be returned + + for example: + let this is 000000010 + after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 + + ***this method is created only on a 64bit platform*** + */ + template + uint UInt::Rcr2(uint bits, uint c) + { + TTMATH_ASSERT( bits>0 && bits + sint UInt::FindLeadingBitInWord(uint x) + { + sint result; + + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + + unsigned long nIndex = 0; + + if( _BitScanReverse64(&nIndex,x) == 0 ) + result = -1; + else + result = nIndex; + + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ ( + + "movq $-1, %1 \n" + "bsrq %2, %0 \n" + "cmovz %1, %0 \n" + + : "=r" (result), "=&r" (dummy) + : "r" (x) + : "cc" ); + + #endif + + + return result; + } + + + /* + this method returns the number of the highest set bit in one 64-bit word + if the 'x' is zero this method returns '-1' + + ***this method is created only on a 64bit platform*** + */ + template + sint UInt::FindLowestBitInWord(uint x) + { + sint result; + + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + + unsigned long nIndex = 0; + + if( _BitScanForward64(&nIndex,x) == 0 ) + result = -1; + else + result = nIndex; + + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ ( + + "movq $-1, %1 \n" + "bsfq %2, %0 \n" + "cmovz %1, %0 \n" + + : "=r" (result), "=&r" (dummy) + : "r" (x) + : "cc" ); + + #endif + + + return result; + } + + + /*! + this method sets a special bit in the 'value' + and returns the last state of the bit (zero or one) + + ***this method is created only on a 64bit platform*** + + bit is from <0,63> + + e.g. + uint x = 100; + uint bit = SetBitInWord(x, 3); + now: x = 108 and bit = 0 + */ + template + uint UInt::SetBitInWord(uint & value, uint bit) + { + TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) + + uint old_bit; + uint v = value; + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + old_bit = _bittestandset64((__int64*)&value,bit) != 0; + #endif + + + #ifdef __GNUC__ + + __asm__ ( + + "btsq %%rbx, %%rax \n" + "setc %%bl \n" + "movzx %%bl, %%rbx \n" + + : "=a" (v), "=b" (old_bit) + : "0" (v), "1" (bit) + : "cc" ); + + #endif + + value = v; + + return old_bit; + } + + + /*! + * + * Multiplication + * + * + */ + + + /*! + multiplication: result_high:result_low = a * b + result_high - higher word of the result + result_low - lower word of the result + + this methos never returns a carry + this method is used in the second version of the multiplication algorithms + + ***this method is created only on a 64bit platform*** + */ + template + void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) + { + /* + we must use these temporary variables in order to inform the compilator + that value pointed with result1 and result2 has changed + + this has no effect in visual studio but it's usefull when + using gcc and options like -O + */ + uint result1_; + uint result2_; + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + result1_ = _umul128(a,b,&result2_); + #endif + + + #ifdef __GNUC__ + + __asm__ ( + + "mulq %%rdx \n" + + : "=a" (result1_), "=d" (result2_) + : "0" (a), "1" (b) + : "cc" ); + + #endif + + + *result_low = result1_; + *result_high = result2_; + } + + + + + /*! + * + * Division + * + * + */ + + + /*! + this method calculates 64bits word a:b / 32bits c (a higher, b lower word) + r = a:b / c and rest - remainder + + ***this method is created only on a 64bit platform*** + + * + * WARNING: + * if r (one word) is too small for the result or c is equal zero + * there'll be a hardware interruption (0) + * and probably the end of your program + * + */ + template + void UInt::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) + { + uint r_; + uint rest_; + /* + these variables have similar meaning like those in + the multiplication algorithm MulTwoWords + */ + + TTMATH_ASSERT( c != 0 ) + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + + ttmath_div_x64(&a,&b,c); + r_ = a; + rest_ = b; + + #endif + + + #ifdef __GNUC__ + + __asm__ ( + + "divq %%rcx \n" + + : "=a" (r_), "=d" (rest_) + : "d" (a), "a" (b), "c" (c) + : "cc" ); + + #endif + + + *r = r_; + *rest = rest_; + } + +} //namespace + + +#endif //ifdef TTMATH_PLATFORM64 +#endif //ifndef TTMATH_NOASM +#endif + + diff --git a/src/libghost/ttmath/ttmath/ttmathuint_x86_64_msvc.asm b/src/libghost/ttmath/ttmath/ttmathuint_x86_64_msvc.asm new file mode 100644 index 0000000..d2ea969 --- /dev/null +++ b/src/libghost/ttmath/ttmath/ttmathuint_x86_64_msvc.asm @@ -0,0 +1,548 @@ +; +; This file is a part of TTMath Bignum Library +; and is distributed under the (new) BSD licence. +; Author: Christian Kaiser +; + +; +; Copyright (c) 2009, Christian Kaiser +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; * Redistributions of source code must retain the above copyright notice, +; this list of conditions and the following disclaimer. +; +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; * Neither the name Christian Kaiser nor the names of contributors to this +; project may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +; THE POSSIBILITY OF SUCH DAMAGE. +; + +; +; compile with debug info: ml64.exe /Zd /Zi ttmathuint_x86_64_msvc.asm +; compile without debug info: ml64.exe ttmathuint_x86_64_msvc.asm +; this create ttmathuint_x86_64_msvc.obj file which can be linked with your program +; + +PUBLIC ttmath_adc_x64 +PUBLIC ttmath_addindexed_x64 +PUBLIC ttmath_addindexed2_x64 +PUBLIC ttmath_addvector_x64 + +PUBLIC ttmath_sbb_x64 +PUBLIC ttmath_subindexed_x64 +PUBLIC ttmath_subvector_x64 + +PUBLIC ttmath_rcl_x64 +PUBLIC ttmath_rcr_x64 + +PUBLIC ttmath_rcl2_x64 +PUBLIC ttmath_rcr2_x64 + +PUBLIC ttmath_div_x64 + +; +; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx +; +; "rax, rcx, rdx, r8-r11 are volatile." +; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile." +; + + +.CODE + + + ALIGN 8 + +;---------------------------------------- + +ttmath_adc_x64 PROC + ; rcx = p1 + ; rdx = p2 + ; r8 = nSize + ; r9 = nCarry + + xor rax, rax + xor r11, r11 + sub rax, r9 ; sets CARRY if r9 != 0 + + ALIGN 16 + loop1: + mov rax,qword ptr [rdx + r11 * 8] + adc qword ptr [rcx + r11 * 8], rax + lea r11, [r11+1] + dec r8 + jnz loop1 + + setc al + movzx rax, al + + ret + +ttmath_adc_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_addindexed_x64 PROC + + ; rcx = p1 + ; rdx = nSize + ; r8 = nPos + ; r9 = nValue + + xor rax, rax ; rax = result + sub rdx, r8 ; rdx = remaining count of uints + + add qword ptr [rcx + r8 * 8], r9 + jc next1 + + ret + +next1: + mov r9, 1 + + ALIGN 16 +loop1: + dec rdx + jz done_with_cy + lea r8, [r8+1] + add qword ptr [rcx + r8 * 8], r9 + jc loop1 + + ret + +done_with_cy: + lea rax, [rax+1] ; rax = 1 + + ret + +ttmath_addindexed_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_addindexed2_x64 PROC + + ; rcx = p1 (pointer) + ; rdx = b (value size) + ; r8 = nPos + ; r9 = nValue1 + ; [esp+0x28] = nValue2 + + xor rax, rax ; return value + mov r11, rcx ; table + sub rdx, r8 ; rdx = remaining count of uints + mov r10, [esp+028h] ; r10 = nValue2 + + add qword ptr [r11 + r8 * 8], r9 + lea r8, [r8+1] + lea rdx, [rdx-1] + adc qword ptr [r11 + r8 * 8], r10 + jc next + ret + + ALIGN 16 +loop1: + lea r8, [r8+1] + add qword ptr [r11 + r8 * 8], 1 + jc next + ret + +next: + dec rdx ; does not modify CY too... + jnz loop1 + lea rax, [rax+1] + ret + +ttmath_addindexed2_x64 ENDP + + + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + + +ttmath_addvector_x64 PROC + ; rcx = ss1 + ; rdx = ss2 + ; r8 = ss1_size + ; r9 = ss2_size + ; [esp+0x28] = result + + mov r10, [esp+028h] + sub r8, r9 + xor r11, r11 ; r11=0, cf=0 + + ALIGN 16 + loop1: + mov rax, qword ptr [rcx + r11 * 8] + adc rax, qword ptr [rdx + r11 * 8] + mov qword ptr [r10 + r11 * 8], rax + inc r11 + dec r9 + jnz loop1 + + adc r9, r9 ; r9 has the cf state + + or r8, r8 + jz done + + neg r9 ; setting cf from r9 + mov r9, 0 ; don't use xor here (cf is used) + loop2: + mov rax, qword ptr [rcx + r11 * 8] + adc rax, r9 + mov qword ptr [r10 + r11 * 8], rax + inc r11 + dec r8 + jnz loop2 + + adc r8, r8 + mov rax, r8 + + ret + +done: + mov rax, r9 + ret + +ttmath_addvector_x64 ENDP + + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_sbb_x64 PROC + + ; rcx = p1 + ; rdx = p2 + ; r8 = nCount + ; r9 = nCarry + + xor rax, rax + xor r11, r11 + sub rax, r9 ; sets CARRY if r9 != 0 + + ALIGN 16 + loop1: + mov rax,qword ptr [rdx + r11 * 8] + sbb qword ptr [rcx + r11 * 8], rax + lea r11, [r11+1] + dec r8 + jnz loop1 + + setc al + movzx rax, al + + ret + +ttmath_sbb_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_subindexed_x64 PROC + ; rcx = p1 + ; rdx = nSize + ; r8 = nPos + ; r9 = nValue + + sub rdx, r8 ; rdx = remaining count of uints + + ALIGN 16 +loop1: + sub qword ptr [rcx + r8 * 8], r9 + jnc done + + lea r8, [r8+1] + mov r9, 1 + dec rdx + jnz loop1 + + mov rax, 1 + ret + +done: + xor rax, rax + ret + +ttmath_subindexed_x64 ENDP + + + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb' + +ttmath_subvector_x64 PROC + ; rcx = ss1 + ; rdx = ss2 + ; r8 = ss1_size + ; r9 = ss2_size + ; [esp+0x28] = result + + mov r10, [esp+028h] + sub r8, r9 + xor r11, r11 ; r11=0, cf=0 + + ALIGN 16 + loop1: + mov rax, qword ptr [rcx + r11 * 8] + sbb rax, qword ptr [rdx + r11 * 8] + mov qword ptr [r10 + r11 * 8], rax + inc r11 + dec r9 + jnz loop1 + + adc r9, r9 ; r9 has the cf state + + or r8, r8 + jz done + + neg r9 ; setting cf from r9 + mov r9, 0 ; don't use xor here (cf is used) + loop2: + mov rax, qword ptr [rcx + r11 * 8] + sbb rax, r9 + mov qword ptr [r10 + r11 * 8], rax + inc r11 + dec r8 + jnz loop2 + + adc r8, r8 + mov rax, r8 + + ret + +done: + mov rax, r9 + ret + +ttmath_subvector_x64 ENDP + + + + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_rcl_x64 PROC + ; rcx = p1 + ; rdx = b + ; r8 = nLowestBit + + mov r11, rcx ; table + xor r10, r10 + neg r8 ; CY set if r8 <> 0 + + ALIGN 16 +loop1: + rcl qword ptr [r11 + r10 * 8], 1 + lea r10, [r10+1] + dec rdx + jnz loop1 + + setc al + movzx rax, al + + ret + +ttmath_rcl_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_rcr_x64 PROC + ; rcx = p1 + ; rdx = nSize + ; r8 = nLowestBit + + xor r10, r10 + neg r8 ; CY set if r8 <> 0 + + ALIGN 16 +loop1: + rcr qword ptr -8[rcx + rdx * 8], 1 + dec rdx + jnz loop1 + + setc al + movzx rax, al + + ret + +ttmath_rcr_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_div_x64 PROC + + ; rcx = &Hi + ; rdx = &Lo + ; r8 = nDiv + + mov r11, rcx + mov r10, rdx + + mov rdx, qword ptr [r11] + mov rax, qword ptr [r10] + div r8 + mov qword ptr [r10], rdx ; remainder + mov qword ptr [r11], rax ; value + + ret + +ttmath_div_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_rcl2_x64 PROC + ; rcx = p1 + ; rdx = nSize + ; r8 = bits + ; r9 = c + + push rbx + + mov r10, rcx ; r10 = p1 + xor rax, rax + + mov rcx, 64 + sub rcx, r8 + + mov r11, -1 + shr r11, cl ; r11 = mask + + mov rcx, r8 ; rcx = count of bits + + mov rbx, rax ; rbx = old value = 0 + or r9, r9 + cmovnz rbx, r11 ; if (c) then old value = mask + + mov r9, rax ; r9 = index (0..nSize-1) + + ALIGN 16 +loop1: + rol qword ptr [r10+r9*8], cl + mov rax, qword ptr [r10+r9*8] + and rax, r11 + xor qword ptr [r10+r9*8], rax + or qword ptr [r10+r9*8], rbx + mov rbx, rax + + lea r9, [r9+1] + dec rdx + + jnz loop1 + + and rax, 1 + pop rbx + ret + +ttmath_rcl2_x64 ENDP + +;---------------------------------------- + + ALIGN 8 + +;---------------------------------------- + +ttmath_rcr2_x64 PROC + ; rcx = p1 + ; rdx = nSize + ; r8 = bits + ; r9 = c + + push rbx + mov r10, rcx ; r10 = p1 + xor rax, rax + + mov rcx, 64 + sub rcx, r8 + + mov r11, -1 + shl r11, cl ; r11 = mask + + mov rcx, r8 ; rcx = count of bits + + mov rbx, rax ; rbx = old value = 0 + or r9, r9 + cmovnz rbx, r11 ; if (c) then old value = mask + + mov r9, rdx ; r9 = index (0..nSize-1) + lea r9, [r9-1] + + ALIGN 16 +loop1: + ror qword ptr [r10+r9*8], cl + mov rax, qword ptr [r10+r9*8] + and rax, r11 + xor qword ptr [r10+r9*8], rax + or qword ptr [r10+r9*8], rbx + mov rbx, rax + + lea r9, [r9-1] + dec rdx + + jnz loop1 + + rol rax, 1 + and rax, 1 + pop rbx + + ret + +ttmath_rcr2_x64 ENDP + +END diff --git a/ghost/util.cpp b/src/libghost/util.cpp similarity index 100% rename from ghost/util.cpp rename to src/libghost/util.cpp diff --git a/ghost/util.h b/src/libghost/util.h similarity index 100% rename from ghost/util.h rename to src/libghost/util.h diff --git a/ghost/w3g_actions.txt b/src/libghost/w3g_actions.txt similarity index 100% rename from ghost/w3g_actions.txt rename to src/libghost/w3g_actions.txt diff --git a/ghost/w3g_format.txt b/src/libghost/w3g_format.txt similarity index 100% rename from ghost/w3g_format.txt rename to src/libghost/w3g_format.txt diff --git a/src/plugins/cmd_builtin/cmd_builtin.pro b/src/plugins/cmd_builtin/cmd_builtin.pro new file mode 100755 index 0000000..75e0bd5 --- /dev/null +++ b/src/plugins/cmd_builtin/cmd_builtin.pro @@ -0,0 +1,12 @@ +! include( ../plugin.pri ) { + error( Couldn't find plugin.pri! ) +} + +QT += network sql + +HEADERS = commands.h +SOURCES = commands.cpp +#TARGET = $$qtLibraryTarget(cmd_builtin) +TARGET = cmd_builtin + + diff --git a/ghost/cmd_builtin/commands.cpp b/src/plugins/cmd_builtin/commands.cpp similarity index 67% rename from ghost/cmd_builtin/commands.cpp rename to src/plugins/cmd_builtin/commands.cpp index b211693..b786e92 100644 --- a/ghost/cmd_builtin/commands.cpp +++ b/src/plugins/cmd_builtin/commands.cpp @@ -10,15 +10,16 @@ #include "commands.h" #include "ghost.h" #include "config.h" -#include "game_base.h" #include "bnet.h" +#include "game.h" #include "language.h" #include +#include QStringList CCommands :: GetCommands() const { QStringList bla; - bla << "bla"; + //bla << "bla"; return bla; } @@ -27,16 +28,21 @@ void CCommands :: PluginLoaded( CGHost *ghost, CConfig *cfg ) m_GHost = ghost; } -void CCommands :: OnGameCommand( CGamePlayer *player, const CommandData &data ) +void CCommands :: OnGameCommand( CBaseGame *game, CGamePlayer *player, const CommandData &data ) { } +QString CCommands :: GetName( ) const +{ + return "Built-in commands"; +} + void CCommands :: OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ) { - if( *data.GetCommand() == "close" && !data.GetCommand()->isEmpty( ) && m_GHost->m_CurrentGame ) + if( *data.GetCommand() == "close" && !data.GetCommand()->isEmpty( ) && m_GHost->GetCurrentGame() ) { - if( !m_GHost->m_CurrentGame->GetLocked( ) ) + if( !m_GHost->GetCurrentGame()->GetLocked( ) ) { // close as many slots as specified, e.g. "5 10" closes slots 5 and 10 @@ -54,11 +60,14 @@ void CCommands :: OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, break; } else - m_GHost->m_CurrentGame->CloseSlot( (unsigned char)( SID - 1 ), true ); + m_GHost->GetCurrentGame()->CloseSlot( (unsigned char)( SID - 1 ), true ); } } else - bnet->QueueChatCommand( m_GHost->m_Language->TheGameIsLockedBNET( ), user, whisper ); + { + //m_GHost->m_Language->TheGameIsLockedBNET(); + bnet->QueueChatCommand( QString(), user, whisper ); + } } } diff --git a/ghost/cmd_builtin/commands.h b/src/plugins/cmd_builtin/commands.h similarity index 59% rename from ghost/cmd_builtin/commands.h rename to src/plugins/cmd_builtin/commands.h index 979ba5a..7049f35 100644 --- a/ghost/cmd_builtin/commands.h +++ b/src/plugins/cmd_builtin/commands.h @@ -22,13 +22,15 @@ class CCommands : public QObject, public ICommandProvider { Q_OBJECT Q_INTERFACES(ICommandProvider) + Q_INTERFACES(IGHostPlugin) private: CGHost *m_GHost; public: + virtual QString GetName() const; QStringList GetCommands() const; - void PluginLoaded( CGHost *ghost, CConfig *cfg ); - void OnGameCommand( CGamePlayer *player, const CommandData &data ); - void OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ); + virtual void PluginLoaded( CGHost *ghost, CConfig *cfg ); + virtual void OnGameCommand( CBaseGame *game, CGamePlayer *player, const CommandData &data ); + virtual void OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ); }; #endif \ No newline at end of file diff --git a/src/plugins/plugin.pri b/src/plugins/plugin.pri new file mode 100644 index 0000000..919830f --- /dev/null +++ b/src/plugins/plugin.pri @@ -0,0 +1,11 @@ +QT -= gui +TEMPLATE = lib +CONFIG += plugin debug_and_release #link_prl + +LIBS += -lghost -lbncsutil -lgmp -L/usr/lib -L../../../lib +macx { + LIBS += -lz +} + +INCLUDEPATH += ../../libghost +DESTDIR = ../../../bin/plugins \ No newline at end of file diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro new file mode 100644 index 0000000..f094ddc --- /dev/null +++ b/src/plugins/plugins.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs +SUBDIRS = cmd_builtin + +# install +#target.path = $$[QT_INSTALL_EXAMPLES]/tools/plugandpaintplugins +#sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS plugandpaintplugins.pro +#sources.path = $$[QT_INSTALL_EXAMPLES]/tools/plugandpaintplugins +#INSTALLS += target sources + +#symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/update_dota_elo/Makefile b/src/update_dota_elo/Makefile similarity index 100% rename from update_dota_elo/Makefile rename to src/update_dota_elo/Makefile diff --git a/update_dota_elo/elo.cpp b/src/update_dota_elo/elo.cpp similarity index 100% rename from update_dota_elo/elo.cpp rename to src/update_dota_elo/elo.cpp diff --git a/update_dota_elo/elo.h b/src/update_dota_elo/elo.h similarity index 100% rename from update_dota_elo/elo.h rename to src/update_dota_elo/elo.h diff --git a/update_dota_elo/update_dota_elo.cpp b/src/update_dota_elo/update_dota_elo.cpp similarity index 100% rename from update_dota_elo/update_dota_elo.cpp rename to src/update_dota_elo/update_dota_elo.cpp diff --git a/update_dota_elo/update_dota_elo.vcproj b/src/update_dota_elo/update_dota_elo.vcproj similarity index 100% rename from update_dota_elo/update_dota_elo.vcproj rename to src/update_dota_elo/update_dota_elo.vcproj diff --git a/update_w3mmd_elo/Makefile b/src/update_w3mmd_elo/Makefile similarity index 100% rename from update_w3mmd_elo/Makefile rename to src/update_w3mmd_elo/Makefile diff --git a/update_w3mmd_elo/elo.cpp b/src/update_w3mmd_elo/elo.cpp similarity index 100% rename from update_w3mmd_elo/elo.cpp rename to src/update_w3mmd_elo/elo.cpp diff --git a/update_w3mmd_elo/elo.h b/src/update_w3mmd_elo/elo.h similarity index 100% rename from update_w3mmd_elo/elo.h rename to src/update_w3mmd_elo/elo.h diff --git a/update_w3mmd_elo/update_w3mmd_elo.cpp b/src/update_w3mmd_elo/update_w3mmd_elo.cpp similarity index 100% rename from update_w3mmd_elo/update_w3mmd_elo.cpp rename to src/update_w3mmd_elo/update_w3mmd_elo.cpp diff --git a/update_w3mmd_elo/update_w3mmd_elo.vcproj b/src/update_w3mmd_elo/update_w3mmd_elo.vcproj similarity index 100% rename from update_w3mmd_elo/update_w3mmd_elo.vcproj rename to src/update_w3mmd_elo/update_w3mmd_elo.vcproj diff --git a/zlib/DLL_FAQ.txt b/zlib/DLL_FAQ.txt deleted file mode 100644 index ad4286f..0000000 --- a/zlib/DLL_FAQ.txt +++ /dev/null @@ -1,397 +0,0 @@ - - Frequently Asked Questions about ZLIB1.DLL - - -This document describes the design, the rationale, and the usage -of the official DLL build of zlib, named ZLIB1.DLL. If you have -general questions about zlib, you should see the file "FAQ" found -in the zlib distribution, or at the following location: - http://www.gzip.org/zlib/zlib_faq.html - - - 1. What is ZLIB1.DLL, and how can I get it? - - - ZLIB1.DLL is the official build of zlib as a DLL. - (Please remark the character '1' in the name.) - - Pointers to a precompiled ZLIB1.DLL can be found in the zlib - web site at: - http://www.zlib.org/ - - Applications that link to ZLIB1.DLL can rely on the following - specification: - - * The exported symbols are exclusively defined in the source - files "zlib.h" and "zlib.def", found in an official zlib - source distribution. - * The symbols are exported by name, not by ordinal. - * The exported names are undecorated. - * The calling convention of functions is "C" (CDECL). - * The ZLIB1.DLL binary is linked to MSVCRT.DLL. - - The archive in which ZLIB1.DLL is bundled contains compiled - test programs that must run with a valid build of ZLIB1.DLL. - It is recommended to download the prebuilt DLL from the zlib - web site, instead of building it yourself, to avoid potential - incompatibilities that could be introduced by your compiler - and build settings. If you do build the DLL yourself, please - make sure that it complies with all the above requirements, - and it runs with the precompiled test programs, bundled with - the original ZLIB1.DLL distribution. - - If, for any reason, you need to build an incompatible DLL, - please use a different file name. - - - 2. Why did you change the name of the DLL to ZLIB1.DLL? - What happened to the old ZLIB.DLL? - - - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required - compilation settings that were incompatible to those used by - a static build. The DLL settings were supposed to be enabled - by defining the macro ZLIB_DLL, before including "zlib.h". - Incorrect handling of this macro was silently accepted at - build time, resulting in two major problems: - - * ZLIB_DLL was missing from the old makefile. When building - the DLL, not all people added it to the build options. In - consequence, incompatible incarnations of ZLIB.DLL started - to circulate around the net. - - * When switching from using the static library to using the - DLL, applications had to define the ZLIB_DLL macro and - to recompile all the sources that contained calls to zlib - functions. Failure to do so resulted in creating binaries - that were unable to run with the official ZLIB.DLL build. - - The only possible solution that we could foresee was to make - a binary-incompatible change in the DLL interface, in order to - remove the dependency on the ZLIB_DLL macro, and to release - the new DLL under a different name. - - We chose the name ZLIB1.DLL, where '1' indicates the major - zlib version number. We hope that we will not have to break - the binary compatibility again, at least not as long as the - zlib-1.x series will last. - - There is still a ZLIB_DLL macro, that can trigger a more - efficient build and use of the DLL, but compatibility no - longer dependents on it. - - - 3. Can I build ZLIB.DLL from the new zlib sources, and replace - an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - - - In principle, you can do it by assigning calling convention - keywords to the macros ZEXPORT and ZEXPORTVA. In practice, - it depends on what you mean by "an old ZLIB.DLL", because the - old DLL exists in several mutually-incompatible versions. - You have to find out first what kind of calling convention is - being used in your particular ZLIB.DLL build, and to use the - same one in the new build. If you don't know what this is all - about, you might be better off if you would just leave the old - DLL intact. - - - 4. Can I compile my application using the new zlib interface, and - link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or - earlier? - - - The official answer is "no"; the real answer depends again on - what kind of ZLIB.DLL you have. Even if you are lucky, this - course of action is unreliable. - - If you rebuild your application and you intend to use a newer - version of zlib (post- 1.1.4), it is strongly recommended to - link it to the new ZLIB1.DLL. - - - 5. Why are the zlib symbols exported by name, and not by ordinal? - - - Although exporting symbols by ordinal is a little faster, it - is risky. Any single glitch in the maintenance or use of the - DEF file that contains the ordinals can result in incompatible - builds and frustrating crashes. Simply put, the benefits of - exporting symbols by ordinal do not justify the risks. - - Technically, it should be possible to maintain ordinals in - the DEF file, and still export the symbols by name. Ordinals - exist in every DLL, and even if the dynamic linking performed - at the DLL startup is searching for names, ordinals serve as - hints, for a faster name lookup. However, if the DEF file - contains ordinals, the Microsoft linker automatically builds - an implib that will cause the executables linked to it to use - those ordinals, and not the names. It is interesting to - notice that the GNU linker for Win32 does not suffer from this - problem. - - It is possible to avoid the DEF file if the exported symbols - are accompanied by a "__declspec(dllexport)" attribute in the - source files. You can do this in zlib by predefining the - ZLIB_DLL macro. - - - 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling - convention. Why not use the STDCALL convention? - STDCALL is the standard convention in Win32, and I need it in - my Visual Basic project! - - (For readability, we use CDECL to refer to the convention - triggered by the "__cdecl" keyword, STDCALL to refer to - the convention triggered by "__stdcall", and FASTCALL to - refer to the convention triggered by "__fastcall".) - - - Most of the native Windows API functions (without varargs) use - indeed the WINAPI convention (which translates to STDCALL in - Win32), but the standard C functions use CDECL. If a user - application is intrinsically tied to the Windows API (e.g. - it calls native Windows API functions such as CreateFile()), - sometimes it makes sense to decorate its own functions with - WINAPI. But if ANSI C or POSIX portability is a goal (e.g. - it calls standard C functions such as fopen()), it is not a - sound decision to request the inclusion of , or to - use non-ANSI constructs, for the sole purpose to make the user - functions STDCALL-able. - - The functionality offered by zlib is not in the category of - "Windows functionality", but is more like "C functionality". - - Technically, STDCALL is not bad; in fact, it is slightly - faster than CDECL, and it works with variable-argument - functions, just like CDECL. It is unfortunate that, in spite - of using STDCALL in the Windows API, it is not the default - convention used by the C compilers that run under Windows. - The roots of the problem reside deep inside the unsafety of - the K&R-style function prototypes, where the argument types - are not specified; but that is another story for another day. - - The remaining fact is that CDECL is the default convention. - Even if an explicit convention is hard-coded into the function - prototypes inside C headers, problems may appear. The - necessity to expose the convention in users' callbacks is one - of these problems. - - The calling convention issues are also important when using - zlib in other programming languages. Some of them, like Ada - (GNAT) and Fortran (GNU G77), have C bindings implemented - initially on Unix, and relying on the C calling convention. - On the other hand, the pre- .NET versions of Microsoft Visual - Basic require STDCALL, while Borland Delphi prefers, although - it does not require, FASTCALL. - - In fairness to all possible uses of zlib outside the C - programming language, we choose the default "C" convention. - Anyone interested in different bindings or conventions is - encouraged to maintain specialized projects. The "contrib/" - directory from the zlib distribution already holds a couple - of foreign bindings, such as Ada, C++, and Delphi. - - - 7. I need a DLL for my Visual Basic project. What can I do? - - - Define the ZLIB_WINAPI macro before including "zlib.h", when - building both the DLL and the user application (except that - you don't need to define anything when using the DLL in Visual - Basic). The ZLIB_WINAPI macro will switch on the WINAPI - (STDCALL) convention. The name of this DLL must be different - than the official ZLIB1.DLL. - - Gilles Vollant has contributed a build named ZLIBWAPI.DLL, - with the ZLIB_WINAPI macro turned on, and with the minizip - functionality built in. For more information, please read - the notes inside "contrib/vstudio/readme.txt", found in the - zlib distribution. - - - 8. I need to use zlib in my Microsoft .NET project. What can I - do? - - - Henrik Ravn has contributed a .NET wrapper around zlib. Look - into contrib/dotzlib/, inside the zlib distribution. - - - 9. If my application uses ZLIB1.DLL, should I link it to - MSVCRT.DLL? Why? - - - It is not required, but it is recommended to link your - application to MSVCRT.DLL, if it uses ZLIB1.DLL. - - The executables (.EXE, .DLL, etc.) that are involved in the - same process and are using the C run-time library (i.e. they - are calling standard C functions), must link to the same - library. There are several libraries in the Win32 system: - CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. - Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that - depend on it should also be linked to MSVCRT.DLL. - - -10. Why are you saying that ZLIB1.DLL and my application should - be linked to the same C run-time (CRT) library? I linked my - application and my DLLs to different C libraries (e.g. my - application to a static library, and my DLLs to MSVCRT.DLL), - and everything works fine. - - - If a user library invokes only pure Win32 API (accessible via - and the related headers), its DLL build will work - in any context. But if this library invokes standard C API, - things get more complicated. - - There is a single Win32 library in a Win32 system. Every - function in this library resides in a single DLL module, that - is safe to call from anywhere. On the other hand, there are - multiple versions of the C library, and each of them has its - own separate internal state. Standalone executables and user - DLLs that call standard C functions must link to a C run-time - (CRT) library, be it static or shared (DLL). Intermixing - occurs when an executable (not necessarily standalone) and a - DLL are linked to different CRTs, and both are running in the - same process. - - Intermixing multiple CRTs is possible, as long as their - internal states are kept intact. The Microsoft Knowledge Base - articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 - "HOWTO: Link with the Correct C Run-Time (CRT) Library" - mention the potential problems raised by intermixing. - - If intermixing works for you, it's because your application - and DLLs are avoiding the corruption of each of the CRTs' - internal states, maybe by careful design, or maybe by fortune. - - Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such - as those provided by Borland, raises similar problems. - - -11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? - - - MSVCRT.DLL exists on every Windows 95 with a new service pack - installed, or with Microsoft Internet Explorer 4 or later, and - on all other Windows 4.x or later (Windows 98, Windows NT 4, - or later). It is freely distributable; if not present in the - system, it can be downloaded from Microsoft or from other - software provider for free. - - The fact that MSVCRT.DLL does not exist on a virgin Windows 95 - is not so problematic. Windows 95 is scarcely found nowadays, - Microsoft ended its support a long time ago, and many recent - applications from various vendors, including Microsoft, do not - even run on it. Furthermore, no serious user should run - Windows 95 without a proper update installed. - - -12. Why are you not linking ZLIB1.DLL to - <> ? - - - We considered and abandoned the following alternatives: - - * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or - LIBCMT.LIB) is not a good option. People are using the DLL - mainly to save disk space. If you are linking your program - to a static C library, you may as well consider linking zlib - in statically, too. - - * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because - CRTDLL.DLL is present on every Win32 installation. - Unfortunately, it has a series of problems: it does not - work properly with Microsoft's C++ libraries, it does not - provide support for 64-bit file offsets, (and so on...), - and Microsoft discontinued its support a long time ago. - - * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied - with the Microsoft .NET platform, and Visual C++ 7.0/7.1, - raises problems related to the status of ZLIB1.DLL as a - system component. According to the Microsoft Knowledge Base - article KB326922 "INFO: Redistribution of the Shared C - Runtime Component in Visual C++ .NET", MSVCR70.DLL and - MSVCR71.DLL are not supposed to function as system DLLs, - because they may clash with MSVCRT.DLL. Instead, the - application's installer is supposed to put these DLLs - (if needed) in the application's private directory. - If ZLIB1.DLL depends on a non-system runtime, it cannot - function as a redistributable system component. - - * Linking ZLIB1.DLL to non-Microsoft runtimes, such as - Borland's, or Cygwin's, raises problems related to the - reliable presence of these runtimes on Win32 systems. - It's easier to let the DLL build of zlib up to the people - who distribute these runtimes, and who may proceed as - explained in the answer to Question 14. - - -13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, - how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 - (Visual Studio .NET) or newer? - - - Due to the problems explained in the Microsoft Knowledge Base - article KB326922 (see the previous answer), the C runtime that - comes with the VC7 environment is no longer considered a - system component. That is, it should not be assumed that this - runtime exists, or may be installed in a system directory. - Since ZLIB1.DLL is supposed to be a system component, it may - not depend on a non-system component. - - In order to link ZLIB1.DLL and your application to MSVCRT.DLL - in VC7, you need the library of Visual C++ 6.0 or older. If - you don't have this library at hand, it's probably best not to - use ZLIB1.DLL. - - We are hoping that, in the future, Microsoft will provide a - way to build applications linked to a proper system runtime, - from the Visual C++ environment. Until then, you have a - couple of alternatives, such as linking zlib in statically. - If your application requires dynamic linking, you may proceed - as explained in the answer to Question 14. - - -14. I need to link my own DLL build to a CRT different than - MSVCRT.DLL. What can I do? - - - Feel free to rebuild the DLL from the zlib sources, and link - it the way you want. You should, however, clearly state that - your build is unofficial. You should give it a different file - name, and/or install it in a private directory that can be - accessed by your application only, and is not visible to the - others (e.g. it's not in the SYSTEM or the SYSTEM32 directory, - and it's not in the PATH). Otherwise, your build may clash - with applications that link to the official build. - - For example, in Cygwin, zlib is linked to the Cygwin runtime - CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. - - -15. May I include additional pieces of code that I find useful, - link them in ZLIB1.DLL, and export them? - - - No. A legitimate build of ZLIB1.DLL must not include code - that does not originate from the official zlib source code. - But you can make your own private DLL build, under a different - file name, as suggested in the previous answer. - - For example, zlib is a part of the VCL library, distributed - with Borland Delphi and C++ Builder. The DLL build of VCL - is a redistributable file, named VCLxx.DLL. - - -16. May I remove some functionality out of ZLIB1.DLL, by enabling - macros like NO_GZCOMPRESS or NO_GZIP at compile time? - - - No. A legitimate build of ZLIB1.DLL must provide the complete - zlib functionality, as implemented in the official zlib source - code. But you can make your own private DLL build, under a - different file name, as suggested in the previous answer. - - -17. I made my own ZLIB1.DLL build. Can I test it for compliance? - - - We prefer that you download the official DLL from the zlib - web site. If you need something peculiar from this DLL, you - can send your suggestion to the zlib mailing list. - - However, in case you do rebuild the DLL yourself, you can run - it with the test programs found in the DLL distribution. - Running these test programs is not a guarantee of compliance, - but a failure can imply a detected problem. - -** - -This document is written and maintained by -Cosmin Truta diff --git a/zlib/README.txt b/zlib/README.txt deleted file mode 100644 index 5c1ac22..0000000 --- a/zlib/README.txt +++ /dev/null @@ -1,53 +0,0 @@ - -What's here -=========== - The official ZLIB1.DLL - - -Source -====== - zlib version 1.2.3 - available at http://www.gzip.org/zlib/ - - -Specification and rationale -=========================== - See the accompanying DLL_FAQ.txt - - -Usage -===== - See the accompanying USAGE.txt - - -Build info -========== - Contributed by Gilles Vollant - - Compiler: Microsoft Visual C++ Toolkit 2003 - Library: Microsoft Visual C++ 6.0 (to link with MSVCRT.DLL) - - -Copyright notice -================ - (C) 1995-2005 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - diff --git a/zlib/USAGE.txt b/zlib/USAGE.txt deleted file mode 100644 index 2ba73b9..0000000 --- a/zlib/USAGE.txt +++ /dev/null @@ -1,94 +0,0 @@ - -Installing ZLIB1.DLL -==================== - Copy ZLIB1.DLL to the SYSTEM or the SYSTEM32 directory. - - -Using ZLIB1.DLL with Microsoft Visual C++ -========================================= - 1. Install the supplied header files "zlib.h" and "zconf.h" - into a directory found in the INCLUDE path list. - - 2. Install the supplied library files "zdll.exp" and "zdll.lib" - into a directory found in the LIB path list. - - 3. Add "zdll.exp" or "zdll.lib" to your project. - - Notes: - - Usually, you don't need both the .exp file and the .lib file. - - If you wish, you may rename "zdll.exp" to "zlib1.exp", and/or - rename "zdll.lib" to "zlib1.lib". - - -Using ZLIB1.DLL with Borland C++ -================================ - 1. Install the supplied header files "zlib.h" and "zconf.h" - into a directory found in the INCLUDE path list. - - 2. Build the import library using the IMPLIB tool: - implib -a -c -f lib\zdllbor.lib zlib1.dll - - OR - - 2' Convert the supplied library file "zdll.lib" to OMF format, - using the COFF2OMF tool: - coff2omf lib\zdll.lib lib\zdllbor.lib - - 3. Install "zdllbor.lib" into a directory found in the LIB path - list. - - 4. Add "zdllbor.lib" to your project. - - Notes: - - The modules that are linked with "zdllbor.lib" must be compiled - using a 4-byte alignment (option -a): - bcc32 -a -c myprog.c - bcc32 myprog.obj zdllbor.lib - - If you wish, you may use "zlib1.lib" instead of "zdllbor.lib". - - -Using ZLIB1.DLL with gcc/MinGW -============================== - 1. Install the supplied header files "zlib.h" and "zconf.h" - into the INCLUDE directory. - - 2. Build the import library from the supplied "zlib.def": - dlltool -D zlib1.dll -d lib/zlib.def -l lib/libzdll.a - - OR - - 2' Copy the supplied library file "zdll.lib" to "libzdll.a": - cp lib/zdll.lib lib/libzdll.a - - 3. Install "libzdll.a" into the LIB directory. - - 4. Add "libzdll.a" to your project, or use the -lzdll option. - - -Using ZLIB1.DLL with gcc/Cygwin -=============================== - ZLIB1.DLL is not designed to work with Cygwin. The Cygwin - system has its own DLL build of zlib, named CYGZ.DLL. - - -Rebuilding ZLIB1.DLL -==================== - Depending on your build environment, use the appropriate - makefile from the win32/ directory, found in the zlib source - distribution. - - Your custom build has to comply with the requirements stated - in DLL_FAQ.txt, including (but not limited to) the following: - - It must be built from an unaltered zlib source distribution. - - It must be linked to MSVCRT.DLL. - - The macros that compile out certain portions of the zlib - code (such as NO_GZCOMPRESS, NO_GZIP) must not be enabled. - - The ZLIB_WINAPI macro must not be enabled. - - Furthermore, it has to run successfully with the test suite - found in this package. - - It is recommended, however, to use the supplied ZLIB1.DLL, - instead of rebuilding it yourself. You should rebuild it - only if you have a special reason. - diff --git a/zlib/lib/zdll.exp b/zlib/lib/zdll.exp deleted file mode 100644 index 2ca08c591a977ad1b7505b3b909a662817230ce6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6109 zcmeI0Uu+!39ml_M95#R<&Ob;(0wy@YA;H|8&-R(p)=8WYH;!W*hXM_3E_dt8H5cEp zcWx33wQ0ozRZ#^J5>%p69uVRom3YVlm8b-W2awvT52&hC9;y~qRfR+=A@z?U(eM0b zW^ZQ}^|=on*}whHXJ&S1fAeSOcQdPc@Q)9Fe_+>*Km(Fi4M){-r>rx|KG_RYd3}#p zmA=jYN&XF2qch93!4rz9^mYFKd9BFAOrrmQ%BW{pxQb%L{9E?_>;JL`R-p&0(Tg>> z0Rh(HM%;v((T7`bE7qYO>#+eFu?d@T8*axIY{fR*f$i9VJ8>5Va5r}19t>g^cH>?Q zVGr)ZUhKpD7{&w0A&&x98uc^z;cBCSaR5^7N=WN*Sw`Aj21ZKcwP%5fCOBAac6s?Aok#B0=CR5p&As&uij+&;@IZ&1;f zHZP`XE3PkfRPENXl=7lV-124 zNqfp%50oqCEK^!JC{?7K6j~sTG=-^p#*wDLX`#JkN?dPQcxkC(?|*`NuF2QM@=`MH zD~H5OYGxedT&Opq!;NySEmP&uC~njF;4B1ZCpa&+)2#qDo}9 zi)zsx74;C=7Ev8q^)3M>$+n8RNPA4w6xlXW&(O|_Izo1bsLQm+Ma__H7xgTy@MCq+F=cAu!XX`d4H9NAt`@6d*#o+sNU>V4YNqFx}oU(^S*Wl=AY z4U76E?HN(8kUb#kH?$Q|uaf0NeMDOob%iW1>UXq}sMp8}qCTcw6!iv~Is*jw18q&z zRkEU}PiW7IdXsEa)L&@pqOOsRiTadQokjw@MK&(#Z?xw`y-ijU)kC{Z)-6}`3coSK z(Z$vfHueWBSj~Tx0xse;eH)I|D{-^kTkQnVvn0Nwp&l*Q;y#PT`9$REzWx ziBBPEugsSDslaYNOOv?P`i{D<8bV8StKQbNZg6S(Y>d=5YINFG1&NCB^VWCYhdQpCF+8O5(XGKN2S zWE_9@ND0?HGJ#$WZOW^K9Qr(x#|DoSu+1YQ*y)iX_IP9zIggBC+#}1u#12t>lR95IJpkiBfa^edGl0)_KCOBS&(#j@ox^l0NHWxl&=M}4=>E~kzvQ+ujS zJs9BUTLlL;7BEXG6`!PHJ~ssUlK9XG@7yrZi79nVXk!>B474y6*rWp|CnWl^=qnTH z*iguid{aS^ivPNSUlMqxBHbjm{V&m)TcrBt1asZ+j0-Il>4vt0NK~OKwcG3t=jOyO zwnz<=)ut!uY?u_9VX=jJC~Qu<*XG>u4!wS-LUgt2b)ZcZM-o(1b-l`r38d|Ul(9=^ z8kc!O_6rFZDn4^&M9Z2**a=ml5L_pNMUMzgqcYt#IBhzteg>sxnJ`m~@2Lmnb?L&9le0&| Jsr?K4@gEyoqICcO diff --git a/zlib/lib/zdll.lib b/zlib/lib/zdll.lib deleted file mode 100644 index 01f4e10e6ef05b1198d2e5b3410437611826e61a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10590 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 P)(+qo*MsqY)PcVNMZggJ diff --git a/zlib/test/untgz_d.exe b/zlib/test/untgz_d.exe deleted file mode 100644 index b0198a6ea012810fb09836058588c4d993fc59dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7168 zcmeHLeQaA-6~A`V*6Wfw>+CJsvhmiwY!z+Ntm#PVw3^a)W?Y@|_g3!cRR=Uosv+S!w6)UV`W9k42hjdkdkp>uf{LXz& z>Xix!1b+;1rE@>dJ@?%6eV={D-3Qn_##jkJ*BKkZNX;Sof8L$J_To<*Syp)(jtNU?adH}371eBMYTs!CfGDXvANP(*6FvqS2S`jwipvPE)%^{=mJ{oZ$D zH_pt$i_u$V9>ew0&~wJ$EN0iog2YgN zBROhGXVoQqV@YzXB>f5>(@uGM>av@2o*uzwbM6GSLj!BTt?WUt@8;`TF*uViID$_s zbFg;(%|mooaO|l$#sY$*O71mykTj&aoE9h=# zrcEws*X>N;)g6cGpdd8aIQ_p$S*ugz9r!|d#v*T-OC z%%Q8@h68*$sq5Op%d?*3sFZW#igG8>bnEs~+MYcB?zL0r-|gP0+by&n>k)*>mvy2) zaiWWdWs93@EIp;J?cmo*Ac7-mF-*+Me3tQ+Qn=9Bp3lwbI(J)OUzZbR9^;>Kl9O%e zDeY~~=AM^OchT-KygFy@6K*~^w4m{m>h+DQ)Y5vBc56#2tFBl-@w*{Y;}*4~ag|oJ zzGdQ_q4lOAx2a|Q+T-d;5L|&Z=Gq4n$45+H+moxy_6XM9@SGFE!E<~XVOxk-#A$ZV zVkk}WW3Mjj$?YAe*H>xt$C~PO*2SxvNHhIs!sXhM3#9jm8$7Vx4pYa0y`N_45=gv7 zErrCEp%xPa*3J!G-#xZ~iPOnxUAtVjucV9W&FW>Tx7E7+*SAc($jd}5i+Jp&a11&S zpYRh!_1t~7%{}*!baRLjAPOSDYz2QzHk?{tWACvjI>-4(!8*+nNHE&8YW>Q$Fj|jgGwS5Y z^iQ?7_`8s|@<^$1^sqR}^}^w+aoE~eJD@h+x+iww(0hC=`BxnYXjA8tpROD;1Yt$; za-_&HvP#34wzkg?u}ERc-IefFz2qS2zlMD%4>23SVn0@F;^yRQ`gl;+btKQkgMGeP zQz4^QBBLvDQj{udnjXzT6-GIhlCxl*oNlvzX%Z9bj}F{>4J*%cpU<1G-6)PD`0;}6L7(2*aN z*U*rXYcaSoTjb^W42&Wwf;IIWqRa*NgB?8KAd#l&5!1DL{#xHEh`EJuu$l$6QsOxj zgna*BVbnLoA=lV~RmM3`@aeR!N@RCuaA%Q#mN@|*LkMy^Rg6RQfC&e2u2fmLGLR=9^G}U6dc&kRQDl{P13Sik};}Yu^lI?tSh2p`yfZlb5%5 z|cg6-b3;AVmq3Ntxn;+c36ANQZ4U{wBKQ>v~a|jgJC#+Yd#AThq^AAzsIV zv;W-~Z(CXv;}iaUe-II`XvKG!ojS{NSoVCvl{+(cLiBLq*Ko}4yYQ@_RTCG(36 zAtGTezbbi~EKzc`lnibZ`E?cLSMsP)RIMp;CBI}<9yZVVClme)Vh`mS9)r}9%bC~2 zre*v*j*lE(>R{vV)7`iXp50W~`~{&pKfTH{xFgG>JA+K?L_>c3}Ng4mNCeuoG81Sfs*%A4&gO6ZED_o-v#89=h|7!|ePP zda9hk(>K8VKMyi7phDRYsz_EpHhYY3j^anyDIVczY!)72-Vc*&Fb`VTNifzd3y^2zZdST!eSOj>C}Sgug5?)=N3O-~Kn4dkA#;90Qh z&WCZ0&_r8NY$D@3qVM8o`}E)lX2FBkIhg+tq+m|}U=@w{4DWDv4=VYj@*yL?41?~j zWLXTR){|u_4Z3|lki4u758j|fx2MFaRjdx}r3HIrCkXR7Vz{mx8%!$=K7`A3`vCFF zKY*QJDK>%@boo749%>>6&8IWXr=9vO4lFXwXPlYlQ-I$IT zjx&%#JELo-bnQ3!=l@1VsU2*7r(hS}d=}65WrKH|#0QiW$L@j+mAtN<)a^l>*Q>&! z-$@tH9}4J9EMI0&)@5@!z3PCVcmVx>qs`z~$t2)cfKz~@fbRpSt%h3~0Zo97fK7m{ zfG}V?U@u?@@KwM=fX4w(0hR+s0Y3qp2K)*z1(*Spf_EigC7>SA2G{}!19k(30S5s` zK}*esaS`A{nXx|r@&IaxG`$C2jRU$O+al2&5h)r|L(vFhRf)CIhNu?yM{ZK3-rdod z5|OGBi&%UsW7V*5HG-dL2-lVH_9|;7Eu!}BmI9%$QbUuXhQCqbUY{y?!(p+XSX9`& z=tv;q?N_9lni@%(J(5tuiceMimpWH%aQnz@;ZOqi#C^fgc17|JKGiVec+Ur9a<-N;tL%_A#W}uEY~CiBwy&y5?pGt|dZ|UTJqYv{jnjf)R*5;Dzpf zSj!iVCKUKN9^D4B6{Ioj)f|sU+38}hTN^A?oVptLnLQ!k1uCD&Hu^%iC_c+;tJg1uqqv$(jr*t(4gQ)^Xp|&1 z1RqdKgmxEDVp-gglNUks*)}(wn^a$z%@SQ|B$e4mVy&PbM26p^@m)d_#_rTqDH@Ra zm44vp%o_iys@l~?C(&%}Tt_@%p0=5 zoh;-F&96ru9h8uBMY!JqR|#Bg5w7AU5CeCq_HnHjm8^F+qR)?tf|){*%vLkX1h


Q6vTk!gT>3?mr+*tl z2=&$+C~RiTVDAl6c(dnC9thyqV(dzjClp2A1k3?SO7P7QUlfoyYcmH5nfzI^vNMFg zg74^XZ*X-AW!M{#j*zX)v&k1zTS8$~i8DX*cw!!pClmp*$ab~~>t03e_l6?gcy9v# znu{%v_Om4R5{jxNu<)uu=*rl)puN9OOQ@cJKeV0UUnjxO7wxBi{Snv3I$*5!85}&` zSj?mDiedj%lFFyVR8Pi)XgCmKYz^BWN(cm2*0XP#J9Z^hrN0wq z>5LMNW_U}?9SZ4WEU#r7sHC+DmP|E$Mp0*7&R#XOkzHqLi Date: Fri, 21 May 2010 09:57:59 +0000 Subject: [PATCH 64/69] ghost.qt: fixed some build problems for bncsutil on windows still got problems with undefined referenced upon linking, WIP --- {src/bncsutil => include}/gmp.h | 4297 +++++++++++++++---------------- lib/gmp.dll | Bin 0 -> 208896 bytes lib/gmp.txt | 2 + src/bncsutil/bncsutil.h | 2 + src/bncsutil/bncsutil.pro | 7 +- src/bncsutil/bsha1.cpp | 2 +- src/bncsutil/checkrevision.cpp | 8 +- src/bncsutil/file.cpp | 10 +- src/bncsutil/file.h | 2 +- src/bncsutil/mutil_types.h | 8 +- src/libghost/ghost.cpp | 2 +- src/libghost/libghost.pro | 3 +- src/libghost/packed.cpp | 2 +- 13 files changed, 2135 insertions(+), 2210 deletions(-) rename {src/bncsutil => include}/gmp.h (80%) create mode 100644 lib/gmp.dll create mode 100644 lib/gmp.txt diff --git a/src/bncsutil/gmp.h b/include/gmp.h similarity index 80% rename from src/bncsutil/gmp.h rename to include/gmp.h index 0a8c32c..28a9f2e 100644 --- a/src/bncsutil/gmp.h +++ b/include/gmp.h @@ -1,2189 +1,2108 @@ -/* Definitions for GNU multiple precision functions. -*- mode: c -*- - -Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, -2004, 2005, 2006, 2007 Free Software Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -The GNU MP Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ - -#ifndef __GMP_H__ - -#if defined (__cplusplus) -#include /* for std::istream, std::ostream, std::string */ -#endif - - -#if ! defined (__GMP_WITHIN_CONFIGURE) -# if defined( _MSC_VER ) -# if defined( _WIN64 ) -# define __GMP_BITS_PER_MP_LIMB 64 -# define BITS_PER_MP_LIMB 64 -# define GMP_LIMB_BITS 64 -# define SIZEOF_MP_LIMB_T 8 -# define _LONG_LONG_LIMB 1 -# elif defined( _WIN32 ) -# define __GMP_BITS_PER_MP_LIMB 32 -# define BITS_PER_MP_LIMB 32 -# define GMP_LIMB_BITS 32 -# define SIZEOF_MP_LIMB_T 4 -# ifdef _LONG_LONG_LIMB -# undef _LONG_LONG_LIMB -# endif -# else -# error This is the wrong version of gmp.h -# endif -# endif -# define GMP_NAIL_BITS 0 -#endif -#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) -#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS) -#define GMP_NUMB_MAX GMP_NUMB_MASK -#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) - - -/* The following (everything under ifndef __GNU_MP__) must be identical in - gmp.h and mp.h to allow both to be included in an application or during - the library build. */ -#ifndef __GNU_MP__ -#define __GNU_MP__ 4 - -#define __need_size_t /* tell gcc stddef.h we only want size_t */ -#if defined (__cplusplus) -#include /* for size_t */ -#else -#include /* for size_t */ -#endif -#undef __need_size_t - - - -/* __STDC__ - some ANSI compilers define this only to 0, hence the use of - "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 - sets __STDC__ to 0, but requires "##" for token pasting. - - _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but - don't always define __STDC__. - - __DECC - current versions of DEC C (5.9 for instance) for alpha are ANSI, - but don't define __STDC__ in their default mode. Don't know if old - versions might have been K&R, but let's not worry about that unless - someone is still using one. - - _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 - mode, but doesn't define __STDC__. - - _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za - option is given (in which case it's 1). - - _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that - all w32 compilers are ansi. - - Note: This same set of tests is used by gen-psqr.c and - demos/expr/expr-impl.h, so if anything needs adding, then be sure to - update those too. */ - -#if defined (__STDC__) \ - || defined (__cplusplus) \ - || defined (_AIX) \ - || defined (__DECC) \ - || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ - || defined (_MSC_VER) \ - || defined (_WIN32) -#define __GMP_HAVE_CONST 1 -#define __GMP_HAVE_PROTOTYPES 1 -#define __GMP_HAVE_TOKEN_PASTE 1 -#else -#define __GMP_HAVE_CONST 0 -#define __GMP_HAVE_PROTOTYPES 0 -#define __GMP_HAVE_TOKEN_PASTE 0 -#endif - - -#if __GMP_HAVE_CONST -#define __gmp_const const -#define __gmp_signed signed -#else -#define __gmp_const -#define __gmp_signed -#endif - - -/* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in - all other circumstances. - - When compiling objects for libgmp, __GMP_DECLSPEC is an export directive, - or when compiling for an application it's an import directive. The two - cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles - (and not defined from an application). - - __GMP_DECLSPEC_XX is similarly used for libgmpxx. __GMP_WITHIN_GMPXX - indicates when building libgmpxx, and in that case libgmpxx functions are - exports, but libgmp functions which might get called are imports. - - libmp.la uses __GMP_DECLSPEC, just as if it were libgmp.la. libgmp and - libmp don't call each other, so there's no conflict or confusion. - - Libtool DLL_EXPORT define is not used. - - There's no attempt to support GMP built both static and DLL. Doing so - would mean applications would have to tell us which of the two is going - to be used when linking, and that seems very tedious and error prone if - using GMP by hand, and equally tedious from a package since autoconf and - automake don't give much help. - - __GMP_DECLSPEC is required on all documented global functions and - variables, the various internals in gmp-impl.h etc can be left unadorned. - But internals used by the test programs or speed measuring programs - should have __GMP_DECLSPEC, and certainly constants or variables must - have it or the wrong address will be resolved. - - In gcc __declspec can go at either the start or end of a prototype. - - In Microsoft C __declspec must go at the start, or after the type like - void __declspec(...) *foo()". There's no __dllexport or anything to - guard against someone foolish #defining dllexport. _export used to be - available, but no longer. - - In Borland C _export still exists, but needs to go after the type, like - "void _export foo();". Would have to change the __GMP_DECLSPEC syntax to - make use of that. Probably more trouble than it's worth. */ - -#if defined (__GNUC__) -#define __GMP_DECLSPEC_EXPORT __declspec(__dllexport__) -#define __GMP_DECLSPEC_IMPORT __declspec(__dllimport__) -#endif -#if defined (_MSC_VER) || defined (__BORLANDC__) -#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) -#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) -#endif -#ifdef __WATCOMC__ -#define __GMP_DECLSPEC_EXPORT __export -#define __GMP_DECLSPEC_IMPORT __import -#endif -#ifdef __IBMC__ -#define __GMP_DECLSPEC_EXPORT _Export -#define __GMP_DECLSPEC_IMPORT _Import -#endif - -#if __GMP_LIBGMP_DLL -#if __GMP_WITHIN_GMP -/* compiling to go into a DLL libgmp */ -#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT -#else -/* compiling to go into an application which will link to a DLL libgmp */ -#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT -#endif -#else -/* all other cases */ -#define __GMP_DECLSPEC -#endif - - -#ifdef __GMP_SHORT_LIMB -typedef unsigned int mp_limb_t; -typedef int mp_limb_signed_t; -#else -#ifdef _LONG_LONG_LIMB -typedef unsigned long long int mp_limb_t; -typedef long long int mp_limb_signed_t; -#else -typedef unsigned long int mp_limb_t; -typedef long int mp_limb_signed_t; -#endif -#endif - -/* For reference, note that the name __mpz_struct gets into C++ mangled - function names, which means although the "__" suggests an internal, we - must leave this name for binary compatibility. */ -typedef struct -{ - int _mp_alloc; /* Number of *limbs* allocated and pointed - to by the _mp_d field. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ -} __mpz_struct; - -#endif /* __GNU_MP__ */ - - -typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ -typedef __mpz_struct mpz_t[1]; - -typedef mp_limb_t * mp_ptr; -typedef __gmp_const mp_limb_t * mp_srcptr; -#if defined (_CRAY) && ! defined (_CRAYMPP) -/* plain `int' is much faster (48 bits) */ -#define __GMP_MP_SIZE_T_INT 1 -typedef int mp_size_t; -typedef int mp_exp_t; -#else -#define __GMP_MP_SIZE_T_INT 0 -typedef long int mp_size_t; -typedef long int mp_exp_t; -#endif - -typedef struct -{ - __mpz_struct _mp_num; - __mpz_struct _mp_den; -} __mpq_struct; - -typedef __mpq_struct MP_RAT; /* gmp 1 source compatibility */ -typedef __mpq_struct mpq_t[1]; - -typedef struct -{ - int _mp_prec; /* Max precision, in number of `mp_limb_t's. - Set by mpf_init and modified by - mpf_set_prec. The area pointed to by the - _mp_d field contains `prec' + 1 limbs. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ -} __mpf_struct; - -/* typedef __mpf_struct MP_FLOAT; */ -typedef __mpf_struct mpf_t[1]; - -/* Available random number generation algorithms. */ -typedef enum -{ - GMP_RAND_ALG_DEFAULT = 0, - GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ -} gmp_randalg_t; - -/* Random state struct. */ -typedef struct -{ - mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ - gmp_randalg_t _mp_alg; /* Currently unused. */ - union { - void *_mp_lc; /* Pointer to function pointers structure. */ - } _mp_algdata; -} __gmp_randstate_struct; -typedef __gmp_randstate_struct gmp_randstate_t[1]; - -/* Types for function declarations in gmp files. */ -/* ??? Should not pollute user name space with these ??? */ -typedef __gmp_const __mpz_struct *mpz_srcptr; -typedef __mpz_struct *mpz_ptr; -typedef __gmp_const __mpf_struct *mpf_srcptr; -typedef __mpf_struct *mpf_ptr; -typedef __gmp_const __mpq_struct *mpq_srcptr; -typedef __mpq_struct *mpq_ptr; - - -/* This is not wanted in mp.h, so put it outside the __GNU_MP__ common - section. */ -#if __GMP_LIBGMP_DLL -#if __GMP_WITHIN_GMPXX -/* compiling to go into a DLL libgmpxx */ -#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT -#else -/* compiling to go into a application which will link to a DLL libgmpxx */ -#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT -#endif -#else -/* all other cases */ -#define __GMP_DECLSPEC_XX -#endif - - -#if __GMP_HAVE_PROTOTYPES -#define __GMP_PROTO(x) x -#else -#define __GMP_PROTO(x) () -#endif - -#ifndef __MPN -#if __GMP_HAVE_TOKEN_PASTE -#define __MPN(x) __gmpn_##x -#else -#define __MPN(x) __gmpn_/**/x -#endif -#endif - -/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, - defines EOF but not FILE. */ -#if defined (FILE) \ - || defined (H_STDIO) \ - || defined (_H_STDIO) /* AIX */ \ - || defined (_STDIO_H) /* glibc, Sun, SCO */ \ - || defined (_STDIO_H_) /* BSD, OSF */ \ - || defined (__STDIO_H) /* Borland */ \ - || defined (__STDIO_H__) /* IRIX */ \ - || defined (_STDIO_INCLUDED) /* HPUX */ \ - || defined (__dj_include_stdio_h_) /* DJGPP */ \ - || defined (_FILE_DEFINED) /* Microsoft */ \ - || defined (__STDIO__) /* Apple MPW MrC */ \ - || defined (_MSL_STDIO_H) /* Metrowerks */ \ - || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ - || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ -#define _GMP_H_HAVE_FILE 1 -#endif - -/* In ISO C, if a prototype involving "struct obstack *" is given without - that structure defined, then the struct is scoped down to just the - prototype, causing a conflict if it's subsequently defined for real. So - only give prototypes if we've got obstack.h. */ -#if defined (_OBSTACK_H) /* glibc */ -#define _GMP_H_HAVE_OBSTACK 1 -#endif - -/* The prototypes for gmp_vprintf etc are provided only if va_list is - available, via an application having included or . - Usually va_list is a typedef so can't be tested directly, but C99 - specifies that va_start is a macro (and it was normally a macro on past - systems too), so look for that. - - will define some sort of va_list for vprintf and vfprintf, but - let's not bother trying to use that since it's not standard and since - application uses for gmp_vprintf etc will almost certainly require the - whole or anyway. */ - -#ifdef va_start -#define _GMP_H_HAVE_VA_LIST 1 -#endif - -/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ -#if defined (__GNUC__) && defined (__GNUC_MINOR__) -#define __GMP_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -#define __GMP_GNUC_PREREQ(maj, min) 0 -#endif - -/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically - it means a function does nothing but examine its arguments and memory - (global or via arguments) to generate a return value, but changes nothing - and has no side-effects. __GMP_NO_ATTRIBUTE_CONST_PURE lets - tune/common.c etc turn this off when trying to write timing loops. */ -#if __GMP_GNUC_PREREQ (2,96) && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) -#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) -#else -#define __GMP_ATTRIBUTE_PURE -#endif - - -/* __GMP_CAST allows us to use static_cast in C++, so our macros are clean - to "g++ -Wold-style-cast". - - Casts in "extern inline" code within an extern "C" block don't induce - these warnings, so __GMP_CAST only needs to be used on documented - macros. */ - -#ifdef __cplusplus -#define __GMP_CAST(type, expr) (static_cast (expr)) -#else -#define __GMP_CAST(type, expr) ((type) (expr)) -#endif - - -/* An empty "throw ()" means the function doesn't throw any C++ exceptions, - this can save some stack frame info in applications. - - Currently it's given only on functions which never divide-by-zero etc, - don't allocate memory, and are expected to never need to allocate memory. - This leaves open the possibility of a C++ throw from a future GMP - exceptions scheme. - - mpz_set_ui etc are omitted to leave open the lazy allocation scheme - described in doc/tasks.html. mpz_get_d etc are omitted to leave open - exceptions for float overflows. - - Note that __GMP_NOTHROW must be given on any inlines the same as on their - prototypes (for g++ at least, where they're used together). Note also - that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like - __GMP_ATTRIBUTE_PURE. */ - -#if defined (__cplusplus) -#define __GMP_NOTHROW throw () -#else -#define __GMP_NOTHROW -#endif - - -/* PORTME: What other compilers have a useful "extern inline"? "static - inline" would be an acceptable substitute if the compiler (or linker) - discards unused statics. */ - - /* gcc has __inline__ in all modes, including strict ansi. Give a prototype - for an inline too, so as to correctly specify "dllimport" on windows, in - case the function is called rather than inlined. - GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 - inline semantics, unless -fgnu89-inline is used. */ -#ifdef __GNUC__ -#ifdef __GNUC_STDC_INLINE__ -#define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) -#else -#define __GMP_EXTERN_INLINE extern __inline__ -#endif -#define __GMP_INLINE_PROTOTYPES 1 -#endif - -/* DEC C (eg. version 5.9) supports "static __inline foo()", even in -std1 - strict ANSI mode. Inlining is done even when not optimizing (ie. -O0 - mode, which is the default), but an unnecessary local copy of foo is - emitted unless -O is used. "extern __inline" is accepted, but the - "extern" appears to be ignored, ie. it becomes a plain global function - but which is inlined within its file. Don't know if all old versions of - DEC C supported __inline, but as a start let's do the right thing for - current versions. */ -#ifdef __DECC -#define __GMP_EXTERN_INLINE static __inline -#endif - -/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict - ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes - place under -O. Without -O "foo" seems to be emitted whether it's used - or not, which is wasteful. "extern inline foo()" isn't useful, the - "extern" is apparently ignored, so foo is inlined if possible but also - emitted as a global, which causes multiple definition errors when - building a shared libgmp. */ -#ifdef __SCO_VERSION__ -#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ - && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE static inline -#endif -#endif - -/* C++ always has "inline" and since it's a normal feature the linker should - discard duplicate non-inlined copies, or if it doesn't then that's a - problem for everyone, not just GMP. */ -#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE inline -#endif - -/* Don't do any inlining within a configure run, since if the compiler ends - up emitting copies of the code into the object file it can end up - demanding the various support routines (like mpn_popcount) for linking, - making the "alloca" test and perhaps others fail. And on hppa ia64 a - pre-release gcc 3.2 was seen not respecting the "extern" in "extern - __inline__", triggering this problem too. */ -#if defined (__GMP_WITHIN_CONFIGURE) && ! __GMP_WITHIN_CONFIGURE_INLINE -#undef __GMP_EXTERN_INLINE -#endif - -/* By default, don't give a prototype when there's going to be an inline - version. Note in particular that Cray C++ objects to the combination of - prototype and inline. */ -#ifdef __GMP_EXTERN_INLINE -#ifndef __GMP_INLINE_PROTOTYPES -#define __GMP_INLINE_PROTOTYPES 0 -#endif -#else -#define __GMP_INLINE_PROTOTYPES 1 -#endif - - -#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) -#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) - -/* __GMP_USHRT_MAX is not "~ (unsigned short) 0" because short is promoted - to int by "~". */ -#define __GMP_UINT_MAX (~ (unsigned) 0) -#define __GMP_ULONG_MAX (~ (unsigned long) 0) -#define __GMP_USHRT_MAX ((unsigned short) ~0) - - -/* __builtin_expect is in gcc 3.0, and not in 2.95. */ -#if __GMP_GNUC_PREREQ (3,0) -#define __GMP_LIKELY(cond) __builtin_expect ((cond) != 0, 1) -#define __GMP_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) -#else -#define __GMP_LIKELY(cond) (cond) -#define __GMP_UNLIKELY(cond) (cond) -#endif - -#ifdef _CRAY -#define __GMP_CRAY_Pragma(str) _Pragma (str) -#else -#define __GMP_CRAY_Pragma(str) -#endif - - -/* Allow direct user access to numerator and denominator of a mpq_t object. */ -#define mpq_numref(Q) (&((Q)->_mp_num)) -#define mpq_denref(Q) (&((Q)->_mp_den)) - - -#if defined (__cplusplus) -extern "C" { -#ifdef _GMP_H_HAVE_FILE -using std::FILE; -#endif -#endif - -#define mp_set_memory_functions __gmp_set_memory_functions -__GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), - void *(*) (void *, size_t, size_t), - void (*) (void *, size_t))) __GMP_NOTHROW; - -#define mp_get_memory_functions __gmp_get_memory_functions -__GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), - void *(**) (void *, size_t, size_t), - void (**) (void *, size_t))) __GMP_NOTHROW; - -#define mp_bits_per_limb __gmp_bits_per_limb -__GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; - -#define gmp_errno __gmp_errno -__GMP_DECLSPEC extern int gmp_errno; - -#define gmp_version __gmp_version -__GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; - - -/**************** Random number routines. ****************/ - -/* obsolete */ -#define gmp_randinit __gmp_randinit -__GMP_DECLSPEC void gmp_randinit __GMP_PROTO ((gmp_randstate_t, gmp_randalg_t, ...)); - -#define gmp_randinit_default __gmp_randinit_default -__GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); - -#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp -__GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, - mpz_srcptr, unsigned long int, - unsigned long int)); - -#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size -__GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); - -#define gmp_randinit_mt __gmp_randinit_mt -__GMP_DECLSPEC void gmp_randinit_mt __GMP_PROTO ((gmp_randstate_t)); - -#define gmp_randinit_set __gmp_randinit_set -void gmp_randinit_set __GMP_PROTO ((gmp_randstate_t, __gmp_const __gmp_randstate_struct *)); - -#define gmp_randseed __gmp_randseed -__GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); - -#define gmp_randseed_ui __gmp_randseed_ui -__GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, unsigned long int)); - -#define gmp_randclear __gmp_randclear -__GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); - -#define gmp_urandomb_ui __gmp_urandomb_ui -unsigned long gmp_urandomb_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); - -#define gmp_urandomm_ui __gmp_urandomm_ui -unsigned long gmp_urandomm_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); - - -/**************** Formatted output routines. ****************/ - -#define gmp_asprintf __gmp_asprintf -__GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, __gmp_const char *, ...)); - -#define gmp_fprintf __gmp_fprintf -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); -#endif - -#define gmp_obstack_printf __gmp_obstack_printf -#if defined (_GMP_H_HAVE_OBSTACK) -__GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, __gmp_const char *, ...)); -#endif - -#define gmp_obstack_vprintf __gmp_obstack_vprintf -#if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, __gmp_const char *, va_list)); -#endif - -#define gmp_printf __gmp_printf -__GMP_DECLSPEC int gmp_printf __GMP_PROTO ((__gmp_const char *, ...)); - -#define gmp_snprintf __gmp_snprintf -__GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, ...)); - -#define gmp_sprintf __gmp_sprintf -__GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, __gmp_const char *, ...)); - -#define gmp_vasprintf __gmp_vasprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, __gmp_const char *, va_list)); -#endif - -#define gmp_vfprintf __gmp_vfprintf -#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); -#endif - -#define gmp_vprintf __gmp_vprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((__gmp_const char *, va_list)); -#endif - -#define gmp_vsnprintf __gmp_vsnprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, va_list)); -#endif - -#define gmp_vsprintf __gmp_vsprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_list)); -#endif - - -/**************** Formatted input routines. ****************/ - -#define gmp_fscanf __gmp_fscanf -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); -#endif - -#define gmp_scanf __gmp_scanf -__GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((__gmp_const char *, ...)); - -#define gmp_sscanf __gmp_sscanf -__GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, ...)); - -#define gmp_vfscanf __gmp_vfscanf -#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); -#endif - -#define gmp_vscanf __gmp_vscanf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((__gmp_const char *, va_list)); -#endif - -#define gmp_vsscanf __gmp_vsscanf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, va_list)); -#endif - - -/**************** Integer (i.e. Z) routines. ****************/ - -#define _mpz_realloc __gmpz_realloc -#define mpz_realloc __gmpz_realloc -__GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); - -#define mpz_abs __gmpz_abs -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) -__GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); -#endif - -#define mpz_add __gmpz_add -__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_add_ui __gmpz_add_ui -__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_addmul __gmpz_addmul -__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_addmul_ui __gmpz_addmul_ui -__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_and __gmpz_and -__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_array_init __gmpz_array_init -__GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); - -#define mpz_bin_ui __gmpz_bin_ui -__GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_bin_uiui __gmpz_bin_uiui -__GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); - -#define mpz_cdiv_q __gmpz_cdiv_q -__GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp -__GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); - -#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_cdiv_qr __gmpz_cdiv_qr -__GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_cdiv_r __gmpz_cdiv_r -__GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp -__GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); - -#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_cdiv_ui __gmpz_cdiv_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpz_clear __gmpz_clear -__GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); - -#define mpz_clrbit __gmpz_clrbit -__GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_cmp __gmpz_cmp -__GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_cmp_d __gmpz_cmp_d -__GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; - -#define _mpz_cmp_si __gmpz_cmp_si -__GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define _mpz_cmp_ui __gmpz_cmp_ui -__GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_cmpabs __gmpz_cmpabs -__GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_cmpabs_d __gmpz_cmpabs_d -__GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; - -#define mpz_cmpabs_ui __gmpz_cmpabs_ui -__GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_com __gmpz_com -__GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); - -#define mpz_combit __gmpz_combit -__GMP_DECLSPEC void mpz_combit __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_congruent_p __gmpz_congruent_p -__GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p -__GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_congruent_ui_p __gmpz_congruent_ui_p -__GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long, unsigned long)) __GMP_ATTRIBUTE_PURE; - -#define mpz_divexact __gmpz_divexact -__GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_divexact_ui __gmpz_divexact_ui -__GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); - -#define mpz_divisible_p __gmpz_divisible_p -__GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_divisible_ui_p __gmpz_divisible_ui_p -__GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; - -#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p -__GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_dump __gmpz_dump -__GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); - -#define mpz_export __gmpz_export -__GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr)); - -#define mpz_fac_ui __gmpz_fac_ui -__GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_fdiv_q __gmpz_fdiv_q -__GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp -__GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_fdiv_qr __gmpz_fdiv_qr -__GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_fdiv_r __gmpz_fdiv_r -__GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp -__GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_fdiv_ui __gmpz_fdiv_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpz_fib_ui __gmpz_fib_ui -__GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_fib2_ui __gmpz_fib2_ui -__GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); - -#define mpz_fits_sint_p __gmpz_fits_sint_p -__GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_fits_slong_p __gmpz_fits_slong_p -__GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_fits_sshort_p __gmpz_fits_sshort_p -__GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_fits_uint_p __gmpz_fits_uint_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) -__GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_fits_ulong_p __gmpz_fits_ulong_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) -__GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_fits_ushort_p __gmpz_fits_ushort_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) -__GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_gcd __gmpz_gcd -__GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_gcd_ui __gmpz_gcd_ui -__GMP_DECLSPEC unsigned long int mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_gcdext __gmpz_gcdext -__GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_get_d __gmpz_get_d -__GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_get_d_2exp __gmpz_get_d_2exp -__GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long int *, mpz_srcptr)); - -#define mpz_get_si __gmpz_get_si -__GMP_DECLSPEC /* signed */ long int mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_get_str __gmpz_get_str -__GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); - -#define mpz_get_ui __gmpz_get_ui -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) -__GMP_DECLSPEC unsigned long int mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_getlimbn __gmpz_getlimbn -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) -__GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_hamdist __gmpz_hamdist -__GMP_DECLSPEC unsigned long int mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_import __gmpz_import -__GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, __gmp_const void *)); - -#define mpz_init __gmpz_init -__GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); - -#define mpz_init2 __gmpz_init2 -__GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, unsigned long)); - -#define mpz_init_set __gmpz_init_set -__GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); - -#define mpz_init_set_d __gmpz_init_set_d -__GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); - -#define mpz_init_set_si __gmpz_init_set_si -__GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, signed long int)); - -#define mpz_init_set_str __gmpz_init_set_str -__GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); - -#define mpz_init_set_ui __gmpz_init_set_ui -__GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_inp_raw __gmpz_inp_raw -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); -#endif - -#define mpz_inp_str __gmpz_inp_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); -#endif - -#define mpz_invert __gmpz_invert -__GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_ior __gmpz_ior -__GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_jacobi __gmpz_jacobi -__GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_kronecker mpz_jacobi /* alias */ - -#define mpz_kronecker_si __gmpz_kronecker_si -__GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, long)) __GMP_ATTRIBUTE_PURE; - -#define mpz_kronecker_ui __gmpz_kronecker_ui -__GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; - -#define mpz_si_kronecker __gmpz_si_kronecker -__GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_ui_kronecker __gmpz_ui_kronecker -__GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((unsigned long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_lcm __gmpz_lcm -__GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_lcm_ui __gmpz_lcm_ui -__GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); - -#define mpz_legendre mpz_jacobi /* alias */ - -#define mpz_lucnum_ui __gmpz_lucnum_ui -__GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_lucnum2_ui __gmpz_lucnum2_ui -__GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); - -#define mpz_millerrabin __gmpz_millerrabin -__GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; - -#define mpz_mod __gmpz_mod -__GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ - -#define mpz_mul __gmpz_mul -__GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_mul_2exp __gmpz_mul_2exp -__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_mul_si __gmpz_mul_si -__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int)); - -#define mpz_mul_ui __gmpz_mul_ui -__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_neg __gmpz_neg -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) -__GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); -#endif - -#define mpz_nextprime __gmpz_nextprime -__GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); - -#define mpz_out_raw __gmpz_out_raw -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); -#endif - -#define mpz_out_str __gmpz_out_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); -#endif - -#define mpz_perfect_power_p __gmpz_perfect_power_p -__GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpz_perfect_square_p __gmpz_perfect_square_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) -__GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_popcount __gmpz_popcount -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) -__GMP_DECLSPEC unsigned long int mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_pow_ui __gmpz_pow_ui -__GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_powm __gmpz_powm -__GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_powm_ui __gmpz_powm_ui -__GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); - -#define mpz_probab_prime_p __gmpz_probab_prime_p -__GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; - -#define mpz_random __gmpz_random -__GMP_DECLSPEC void mpz_random __GMP_PROTO ((mpz_ptr, mp_size_t)); - -#define mpz_random2 __gmpz_random2 -__GMP_DECLSPEC void mpz_random2 __GMP_PROTO ((mpz_ptr, mp_size_t)); - -#define mpz_realloc2 __gmpz_realloc2 -__GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, unsigned long)); - -#define mpz_remove __gmpz_remove -__GMP_DECLSPEC unsigned long int mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_root __gmpz_root -__GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_rootrem __gmpz_rootrem -__GMP_DECLSPEC void mpz_rootrem __GMP_PROTO ((mpz_ptr,mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_rrandomb __gmpz_rrandomb -__GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); - -#define mpz_scan0 __gmpz_scan0 -__GMP_DECLSPEC unsigned long int mpz_scan0 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_scan1 __gmpz_scan1 -__GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_set __gmpz_set -__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); - -#define mpz_set_d __gmpz_set_d -__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); - -#define mpz_set_f __gmpz_set_f -__GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); - -#define mpz_set_q __gmpz_set_q -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) -__GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); -#endif - -#define mpz_set_si __gmpz_set_si -__GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, signed long int)); - -#define mpz_set_str __gmpz_set_str -__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); - -#define mpz_set_ui __gmpz_set_ui -__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_setbit __gmpz_setbit -__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int)); - -#define mpz_size __gmpz_size -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) -__GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_sizeinbase __gmpz_sizeinbase -__GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_sqrt __gmpz_sqrt -__GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); - -#define mpz_sqrtrem __gmpz_sqrtrem -__GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); - -#define mpz_sub __gmpz_sub -__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_sub_ui __gmpz_sub_ui -__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_ui_sub __gmpz_ui_sub -__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr)); - -#define mpz_submul __gmpz_submul -__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_submul_ui __gmpz_submul_ui -__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_swap __gmpz_swap -__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; - -#define mpz_tdiv_ui __gmpz_tdiv_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpz_tdiv_q __gmpz_tdiv_q -__GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp -__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_tdiv_qr __gmpz_tdiv_qr -__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_tdiv_r __gmpz_tdiv_r -__GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - -#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp -__GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); - -#define mpz_tstbit __gmpz_tstbit -__GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_ui_pow_ui __gmpz_ui_pow_ui -__GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); - -#define mpz_urandomb __gmpz_urandomb -__GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); - -#define mpz_urandomm __gmpz_urandomm -__GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); - -#define mpz_xor __gmpz_xor -#define mpz_eor __gmpz_xor -__GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); - - -/**************** Rational (i.e. Q) routines. ****************/ - -#define mpq_abs __gmpq_abs -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) -__GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); -#endif - -#define mpq_add __gmpq_add -__GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); - -#define mpq_canonicalize __gmpq_canonicalize -__GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); - -#define mpq_clear __gmpq_clear -__GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); - -#define mpq_cmp __gmpq_cmp -__GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define _mpq_cmp_si __gmpq_cmp_si -__GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, long, unsigned long)) __GMP_ATTRIBUTE_PURE; - -#define _mpq_cmp_ui __gmpq_cmp_ui -__GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, unsigned long int, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpq_div __gmpq_div -__GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); - -#define mpq_div_2exp __gmpq_div_2exp -__GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); - -#define mpq_equal __gmpq_equal -__GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpq_get_num __gmpq_get_num -__GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); - -#define mpq_get_den __gmpq_get_den -__GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); - -#define mpq_get_d __gmpq_get_d -__GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpq_get_str __gmpq_get_str -__GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); - -#define mpq_init __gmpq_init -__GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); - -#define mpq_inp_str __gmpq_inp_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); -#endif - -#define mpq_inv __gmpq_inv -__GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); - -#define mpq_mul __gmpq_mul -__GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); - -#define mpq_mul_2exp __gmpq_mul_2exp -__GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); - -#define mpq_neg __gmpq_neg -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) -__GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); -#endif - -#define mpq_out_str __gmpq_out_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); -#endif - -#define mpq_set __gmpq_set -__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); - -#define mpq_set_d __gmpq_set_d -__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); - -#define mpq_set_den __gmpq_set_den -__GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); - -#define mpq_set_f __gmpq_set_f -__GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); - -#define mpq_set_num __gmpq_set_num -__GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); - -#define mpq_set_si __gmpq_set_si -__GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, signed long int, unsigned long int)); - -#define mpq_set_str __gmpq_set_str -__GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, __gmp_const char *, int)); - -#define mpq_set_ui __gmpq_set_ui -__GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, unsigned long int, unsigned long int)); - -#define mpq_set_z __gmpq_set_z -__GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); - -#define mpq_sub __gmpq_sub -__GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); - -#define mpq_swap __gmpq_swap -__GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; - - -/**************** Float (i.e. F) routines. ****************/ - -#define mpf_abs __gmpf_abs -__GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_add __gmpf_add -__GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); - -#define mpf_add_ui __gmpf_add_ui -__GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); -#define mpf_ceil __gmpf_ceil -__GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_clear __gmpf_clear -__GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); - -#define mpf_cmp __gmpf_cmp -__GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_d __gmpf_cmp_d -__GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_si __gmpf_cmp_si -__GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_ui __gmpf_cmp_ui -__GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_div __gmpf_div -__GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); - -#define mpf_div_2exp __gmpf_div_2exp -__GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); - -#define mpf_div_ui __gmpf_div_ui -__GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); - -#define mpf_dump __gmpf_dump -__GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); - -#define mpf_eq __gmpf_eq -__GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_sint_p __gmpf_fits_sint_p -__GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_slong_p __gmpf_fits_slong_p -__GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_sshort_p __gmpf_fits_sshort_p -__GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_uint_p __gmpf_fits_uint_p -__GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_ulong_p __gmpf_fits_ulong_p -__GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_ushort_p __gmpf_fits_ushort_p -__GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_floor __gmpf_floor -__GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_get_d __gmpf_get_d -__GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; - -#define mpf_get_d_2exp __gmpf_get_d_2exp -__GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long int *, mpf_srcptr)); - -#define mpf_get_default_prec __gmpf_get_default_prec -__GMP_DECLSPEC unsigned long int mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_get_prec __gmpf_get_prec -__GMP_DECLSPEC unsigned long int mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_get_si __gmpf_get_si -__GMP_DECLSPEC long mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_get_str __gmpf_get_str -__GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); - -#define mpf_get_ui __gmpf_get_ui -__GMP_DECLSPEC unsigned long mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_init __gmpf_init -__GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); - -#define mpf_init2 __gmpf_init2 -__GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, unsigned long int)); - -#define mpf_init_set __gmpf_init_set -__GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_init_set_d __gmpf_init_set_d -__GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); - -#define mpf_init_set_si __gmpf_init_set_si -__GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, signed long int)); - -#define mpf_init_set_str __gmpf_init_set_str -__GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); - -#define mpf_init_set_ui __gmpf_init_set_ui -__GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); - -#define mpf_inp_str __gmpf_inp_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); -#endif - -#define mpf_integer_p __gmpf_integer_p -__GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_mul __gmpf_mul -__GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); - -#define mpf_mul_2exp __gmpf_mul_2exp -__GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); - -#define mpf_mul_ui __gmpf_mul_ui -__GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); - -#define mpf_neg __gmpf_neg -__GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_out_str __gmpf_out_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); -#endif - -#define mpf_pow_ui __gmpf_pow_ui -__GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); - -#define mpf_random2 __gmpf_random2 -__GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); - -#define mpf_reldiff __gmpf_reldiff -__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); - -#define mpf_set __gmpf_set -__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_set_d __gmpf_set_d -__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); - -#define mpf_set_default_prec __gmpf_set_default_prec -__GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((unsigned long int)) __GMP_NOTHROW; - -#define mpf_set_prec __gmpf_set_prec -__GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, unsigned long int)); - -#define mpf_set_prec_raw __gmpf_set_prec_raw -__GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, unsigned long int)) __GMP_NOTHROW; - -#define mpf_set_q __gmpf_set_q -__GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); - -#define mpf_set_si __gmpf_set_si -__GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, signed long int)); - -#define mpf_set_str __gmpf_set_str -__GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); - -#define mpf_set_ui __gmpf_set_ui -__GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); - -#define mpf_set_z __gmpf_set_z -__GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); - -#define mpf_size __gmpf_size -__GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_sqrt __gmpf_sqrt -__GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_sqrt_ui __gmpf_sqrt_ui -__GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); - -#define mpf_sub __gmpf_sub -__GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); - -#define mpf_sub_ui __gmpf_sub_ui -__GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); - -#define mpf_swap __gmpf_swap -__GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; - -#define mpf_trunc __gmpf_trunc -__GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); - -#define mpf_ui_div __gmpf_ui_div -__GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); - -#define mpf_ui_sub __gmpf_ui_sub -__GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); - -#define mpf_urandomb __gmpf_urandomb -__GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned long int)); - - -/************ Low level positive-integer (i.e. N) routines. ************/ - -/* This is ugly, but we need to make user calls reach the prefixed function. */ - -#define mpn_add __MPN(add) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) -__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); -#endif - -#define mpn_add_1 __MPN(add_1) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) -__GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; -#endif - -#define mpn_add_n __MPN(add_n) -__GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); - -#define mpn_addmul_1 __MPN(addmul_1) -__GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_bdivmod __MPN(bdivmod) -__GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); - -#define mpn_cmp __MPN(cmp) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) -__GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpn_divexact_by3(dst,src,size) \ - mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) - -#define mpn_divexact_by3c __MPN(divexact_by3c) -__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_divmod_1(qp,np,nsize,dlimb) \ - mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) - -#define mpn_divrem __MPN(divrem) -__GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); - -#define mpn_divrem_1 __MPN(divrem_1) -__GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_divrem_2 __MPN(divrem_2) -__GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); - -#define mpn_gcd __MPN(gcd) -__GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); - -#define mpn_gcd_1 __MPN(gcd_1) -__GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; - -#define mpn_gcdext __MPN(gcdext) -__GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); - -#define mpn_get_str __MPN(get_str) -__GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); - -#define mpn_hamdist __MPN(hamdist) -__GMP_DECLSPEC unsigned long int mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpn_lshift __MPN(lshift) -__GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); - -#define mpn_mod_1 __MPN(mod_1) -__GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; - -#define mpn_mul __MPN(mul) -__GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); - -#define mpn_mul_1 __MPN(mul_1) -__GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_mul_n __MPN(mul_n) -__GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); - -#define mpn_perfect_square_p __MPN(perfect_square_p) -__GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; - -#define mpn_popcount __MPN(popcount) -__GMP_DECLSPEC unsigned long int mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpn_pow_1 __MPN(pow_1) -__GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); - -/* undocumented now, but retained here for upward compatibility */ -#define mpn_preinv_mod_1 __MPN(preinv_mod_1) -__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; - -#define mpn_random __MPN(random) -__GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); - -#define mpn_random2 __MPN(random2) -__GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); - -#define mpn_rshift __MPN(rshift) -__GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); - -#define mpn_scan0 __MPN(scan0) -__GMP_DECLSPEC unsigned long int mpn_scan0 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpn_scan1 __MPN(scan1) -__GMP_DECLSPEC unsigned long int mpn_scan1 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; - -#define mpn_set_str __MPN(set_str) -__GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); - -#define mpn_sqrtrem __MPN(sqrtrem) -__GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); - -#define mpn_sub __MPN(sub) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) -__GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); -#endif - -#define mpn_sub_1 __MPN(sub_1) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) -__GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; -#endif - -#define mpn_sub_n __MPN(sub_n) -__GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); - -#define mpn_submul_1 __MPN(submul_1) -__GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_tdiv_qr __MPN(tdiv_qr) -__GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); - - -/**************** mpz inlines ****************/ - -/* The following are provided as inlines where possible, but always exist as - library functions too, for binary compatibility. - - Within gmp itself this inlining generally isn't relied on, since it - doesn't get done for all compilers, whereas if something is worth - inlining then it's worth arranging always. - - There are two styles of inlining here. When the same bit of code is - wanted for the inline as for the library version, then __GMP_FORCE_foo - arranges for that code to be emitted and the __GMP_EXTERN_INLINE - directive suppressed, eg. mpz_fits_uint_p. When a different bit of code - is wanted for the inline than for the library version, then - __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs) -__GMP_EXTERN_INLINE void -mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpz_set (__gmp_w, __gmp_u); - __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); -} -#endif - -#if GMP_NAIL_BITS == 0 -#define __GMPZ_FITS_UTYPE_P(z,maxval) \ - mp_size_t __gmp_n = z->_mp_size; \ - mp_ptr __gmp_p = z->_mp_d; \ - return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); -#else -#define __GMPZ_FITS_UTYPE_P(z,maxval) \ - mp_size_t __gmp_n = z->_mp_size; \ - mp_ptr __gmp_p = z->_mp_d; \ - return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ - || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) -#if ! defined (__GMP_FORCE_mpz_fits_uint_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ulong_p) -#if ! defined (__GMP_FORCE_mpz_fits_ulong_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ushort_p) -#if ! defined (__GMP_FORCE_mpz_fits_ushort_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_get_ui) -#if ! defined (__GMP_FORCE_mpz_get_ui) -__GMP_EXTERN_INLINE -#endif -unsigned long -mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - mp_ptr __gmp_p = __gmp_z->_mp_d; - mp_size_t __gmp_n = __gmp_z->_mp_size; - mp_limb_t __gmp_l = __gmp_p[0]; - /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings - about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland - C++ 6.0 warnings about condition always true for something like - "__GMP_ULONG_MAX < GMP_NUMB_MASK". */ -#if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) - /* limb==long and no nails, or limb==longlong, one limb is enough */ - return (__gmp_n != 0 ? __gmp_l : 0); -#else - /* limb==long and nails, need two limbs when available */ - __gmp_n = __GMP_ABS (__gmp_n); - if (__gmp_n <= 1) - return (__gmp_n != 0 ? __gmp_l : 0); - else - return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS); -#endif -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_getlimbn) -#if ! defined (__GMP_FORCE_mpz_getlimbn) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW -{ - mp_limb_t __gmp_result = 0; - if (__GMP_LIKELY (__gmp_n >= 0 && __gmp_n < __GMP_ABS (__gmp_z->_mp_size))) - __gmp_result = __gmp_z->_mp_d[__gmp_n]; - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_neg) -__GMP_EXTERN_INLINE void -mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpz_set (__gmp_w, __gmp_u); - __gmp_w->_mp_size = - __gmp_w->_mp_size; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_perfect_square_p) -#if ! defined (__GMP_FORCE_mpz_perfect_square_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_perfect_square_p (mpz_srcptr __gmp_a) -{ - mp_size_t __gmp_asize; - int __gmp_result; - - __gmp_asize = __gmp_a->_mp_size; - __gmp_result = (__gmp_asize >= 0); /* zero is a square, negatives are not */ - if (__GMP_LIKELY (__gmp_asize > 0)) - __gmp_result = mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_popcount) -#if ! defined (__GMP_FORCE_mpz_popcount) -__GMP_EXTERN_INLINE -#endif -unsigned long -mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW -{ - mp_size_t __gmp_usize; - unsigned long __gmp_result; - - __gmp_usize = __gmp_u->_mp_size; - __gmp_result = (__gmp_usize < 0 ? __GMP_ULONG_MAX : 0); - if (__GMP_LIKELY (__gmp_usize > 0)) - __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_set_q) -#if ! defined (__GMP_FORCE_mpz_set_q) -__GMP_EXTERN_INLINE -#endif -void -mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) -{ - mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_size) -#if ! defined (__GMP_FORCE_mpz_size) -__GMP_EXTERN_INLINE -#endif -size_t -mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - return __GMP_ABS (__gmp_z->_mp_size); -} -#endif - - -/**************** mpq inlines ****************/ - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_abs) -__GMP_EXTERN_INLINE void -mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpq_set (__gmp_w, __gmp_u); - __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_neg) -__GMP_EXTERN_INLINE void -mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpq_set (__gmp_w, __gmp_u); - __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; -} -#endif - - -/**************** mpn inlines ****************/ - -/* The comments with __GMPN_ADD_1 below apply here too. - - The test for FUNCTION returning 0 should predict well. If it's assumed - {yp,ysize} will usually have a random number of bits then the high limb - won't be full and a carry out will occur a good deal less than 50% of the - time. - - ysize==0 isn't a documented feature, but is used internally in a few - places. - - Producing cout last stops it using up a register during the main part of - the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" - doesn't seem able to move the true and false legs of the conditional up - to the two places cout is generated. */ - -#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x; \ - \ - /* ASSERT ((ysize) >= 0); */ \ - /* ASSERT ((xsize) >= (ysize)); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ - \ - __gmp_i = (ysize); \ - if (__gmp_i != 0) \ - { \ - if (FUNCTION (wp, xp, yp, __gmp_i)) \ - { \ - do \ - { \ - if (__gmp_i >= (xsize)) \ - { \ - (cout) = 1; \ - goto __gmp_done; \ - } \ - __gmp_x = (xp)[__gmp_i]; \ - } \ - while (TEST); \ - } \ - } \ - if ((wp) != (xp)) \ - __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ - (cout) = 0; \ - __gmp_done: \ - ; \ - } while (0) - -#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ - __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ - (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) -#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ - __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ - (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) - - -/* The use of __gmp_i indexing is designed to ensure a compile time src==dst - remains nice and clear to the compiler, so that __GMPN_COPY_REST can - disappear, and the load/add/store gets a chance to become a - read-modify-write on CISC CPUs. - - Alternatives: - - Using a pair of pointers instead of indexing would be possible, but gcc - isn't able to recognise compile-time src==dst in that case, even when the - pointers are incremented more or less together. Other compilers would - very likely have similar difficulty. - - gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or - similar to detect a compile-time src==dst. This works nicely on gcc - 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems - to be always false, for a pointer p. But the current code form seems - good enough for src==dst anyway. - - gcc on x86 as usual doesn't give particularly good flags handling for the - carry/borrow detection. It's tempting to want some multi instruction asm - blocks to help it, and this was tried, but in truth there's only a few - instructions to save and any gain is all too easily lost by register - juggling setting up for the asm. */ - -#if GMP_NAIL_BITS == 0 -#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_r; \ - \ - /* ASSERT ((n) >= 1); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ - \ - __gmp_x = (src)[0]; \ - __gmp_r = __gmp_x OP (v); \ - (dst)[0] = __gmp_r; \ - if (CB (__gmp_r, __gmp_x, (v))) \ - { \ - (cout) = 1; \ - for (__gmp_i = 1; __gmp_i < (n);) \ - { \ - __gmp_x = (src)[__gmp_i]; \ - __gmp_r = __gmp_x OP 1; \ - (dst)[__gmp_i] = __gmp_r; \ - ++__gmp_i; \ - if (!CB (__gmp_r, __gmp_x, 1)) \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, __gmp_i); \ - (cout) = 0; \ - break; \ - } \ - } \ - } \ - else \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, 1); \ - (cout) = 0; \ - } \ - } while (0) -#endif - -#if GMP_NAIL_BITS >= 1 -#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_r; \ - \ - /* ASSERT ((n) >= 1); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ - \ - __gmp_x = (src)[0]; \ - __gmp_r = __gmp_x OP (v); \ - (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ - if (__gmp_r >> GMP_NUMB_BITS != 0) \ - { \ - (cout) = 1; \ - for (__gmp_i = 1; __gmp_i < (n);) \ - { \ - __gmp_x = (src)[__gmp_i]; \ - __gmp_r = __gmp_x OP 1; \ - (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ - ++__gmp_i; \ - if (__gmp_r >> GMP_NUMB_BITS == 0) \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, __gmp_i); \ - (cout) = 0; \ - break; \ - } \ - } \ - } \ - else \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, 1); \ - (cout) = 0; \ - } \ - } while (0) -#endif - -#define __GMPN_ADDCB(r,x,y) ((r) < (y)) -#define __GMPN_SUBCB(r,x,y) ((x) < (y)) - -#define __GMPN_ADD_1(cout, dst, src, n, v) \ - __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) -#define __GMPN_SUB_1(cout, dst, src, n, v) \ - __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) - - -/* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or - negative. size==0 is allowed. On random data usually only one limb will - need to be examined to get a result, so it's worth having it inline. */ -#define __GMPN_CMP(result, xp, yp, size) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_y; \ - \ - /* ASSERT ((size) >= 0); */ \ - \ - (result) = 0; \ - __gmp_i = (size); \ - while (--__gmp_i >= 0) \ - { \ - __gmp_x = (xp)[__gmp_i]; \ - __gmp_y = (yp)[__gmp_i]; \ - if (__gmp_x != __gmp_y) \ - { \ - /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ - (result) = (__gmp_x > __gmp_y ? 1 : -1); \ - break; \ - } \ - } \ - } while (0) - - -#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) -#define __GMPN_COPY_REST(dst, src, size, start) \ - do { \ - /* ASSERT ((start) >= 0); */ \ - /* ASSERT ((start) <= (size)); */ \ - __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ - } while (0) -#endif - -/* Copy {src,size} to {dst,size}, starting at "start". This is designed to - keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, - __GMPN_ADD, etc. */ -#if ! defined (__GMPN_COPY_REST) -#define __GMPN_COPY_REST(dst, src, size, start) \ - do { \ - mp_size_t __gmp_j; \ - /* ASSERT ((size) >= 0); */ \ - /* ASSERT ((start) >= 0); */ \ - /* ASSERT ((start) <= (size)); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ - __GMP_CRAY_Pragma ("_CRI ivdep"); \ - for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ - (dst)[__gmp_j] = (src)[__gmp_j]; \ - } while (0) -#endif - -/* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use - mpn_copyi if there's a native version, and if we don't mind demanding - binary compatibility for it (on targets which use it). */ - -#if ! defined (__GMPN_COPY) -#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) -#endif - - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add) -#if ! defined (__GMP_FORCE_mpn_add) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) -{ - mp_limb_t __gmp_c; - __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add_1) -#if ! defined (__GMP_FORCE_mpn_add_1) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW -{ - mp_limb_t __gmp_c; - __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_cmp) -#if ! defined (__GMP_FORCE_mpn_cmp) -__GMP_EXTERN_INLINE -#endif -int -mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW -{ - int __gmp_result; - __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) -#if ! defined (__GMP_FORCE_mpn_sub) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) -{ - mp_limb_t __gmp_c; - __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub_1) -#if ! defined (__GMP_FORCE_mpn_sub_1) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW -{ - mp_limb_t __gmp_c; - __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); - return __gmp_c; -} -#endif - -#if defined (__cplusplus) -} -#endif - - -/* Allow faster testing for negative, zero, and positive. */ -#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) -#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) -#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) - -/* When using GCC, optimize certain common comparisons. */ -#if defined (__GNUC__) -#define mpz_cmp_ui(Z,UI) \ - (__builtin_constant_p (UI) && (UI) == 0 \ - ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) -#define mpz_cmp_si(Z,SI) \ - (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ - : __builtin_constant_p (SI) && (SI) > 0 \ - ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ - : _mpz_cmp_si (Z,SI)) -#define mpq_cmp_ui(Q,NUI,DUI) \ - (__builtin_constant_p (NUI) && (NUI) == 0 \ - ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) -#define mpq_cmp_si(q,n,d) \ - (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ - ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ - : _mpq_cmp_si (q, n, d)) -#else -#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) -#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) -#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) -#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) -#endif - - -/* Using "&" rather than "&&" means these can come out branch-free. Every - mpz_t has at least one limb allocated, so fetching the low limb is always - allowed. */ -#define mpz_odd_p(z) (((z)->_mp_size != 0) & __GMP_CAST (int, (z)->_mp_d[0])) -#define mpz_even_p(z) (! mpz_odd_p (z)) - - -/**************** C++ routines ****************/ - -#ifdef __cplusplus -__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); -__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); -__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); -__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); -__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); -__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); -#endif - - -/* Source-level compatibility with GMP 2 and earlier. */ -#define mpn_divmod(qp,np,nsize,dp,dsize) \ - mpn_divrem (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dp, dsize) - -/* Source-level compatibility with GMP 1. */ -#define mpz_mdiv mpz_fdiv_q -#define mpz_mdivmod mpz_fdiv_qr -#define mpz_mmod mpz_fdiv_r -#define mpz_mdiv_ui mpz_fdiv_q_ui -#define mpz_mdivmod_ui(q,r,n,d) \ - (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) -#define mpz_mmod_ui(r,n,d) \ - (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) - -/* Useful synonyms, but not quite compatible with GMP 1. */ -#define mpz_div mpz_fdiv_q -#define mpz_divmod mpz_fdiv_qr -#define mpz_div_ui mpz_fdiv_q_ui -#define mpz_divmod_ui mpz_fdiv_qr_ui -#define mpz_div_2exp mpz_fdiv_q_2exp -#define mpz_mod_2exp mpz_fdiv_r_2exp - -enum -{ - GMP_ERROR_NONE = 0, - GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, - GMP_ERROR_DIVISION_BY_ZERO = 2, - GMP_ERROR_SQRT_OF_NEGATIVE = 4, - GMP_ERROR_INVALID_ARGUMENT = 8 -}; - -/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ -#define __GNU_MP_VERSION 4 -#define __GNU_MP_VERSION_MINOR 2 -#define __GNU_MP_VERSION_PATCHLEVEL 2 - -#define __GMP_H__ -#endif /* __GMP_H__ */ +/* Definitions for GNU multiple precision functions. -*- mode: c -*- + +Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifndef __GMP_H__ + +#if defined (__cplusplus) +#include /* for istream, ostream */ +#endif + + +/* Instantiated by configure. */ +#if ! __GMP_WITHIN_CONFIGURE +#define __GMP_BITS_PER_MP_LIMB 32 +#define __GMP_HAVE_HOST_CPU_FAMILY_power 0 +#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0 +#define GMP_LIMB_BITS 32 +#define GMP_NAIL_BITS 0 +#endif +#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) +#define GMP_NUMB_MASK ((~(mp_limb_t) 0) >> GMP_NAIL_BITS) +#define GMP_NUMB_MAX GMP_NUMB_MASK +#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) + + +/* The following (everything under ifndef __GNU_MP__) must be identical in + gmp.h and mp.h to allow both to be included in an application or during + the library build. */ +#ifndef __GNU_MP__ +#define __GNU_MP__ 4 + +#define __need_size_t /* tell gcc stddef.h we only want size_t */ +#if defined (__cplusplus) +#include /* for size_t */ +#else +#include /* for size_t */ +#endif +#undef __need_size_t + +/* Instantiated by configure. */ +#if ! __GMP_WITHIN_CONFIGURE +/* #undef _LONG_LONG_LIMB */ +#define __GMP_LIBGMP_DLL 1 +#endif + + +/* __STDC__ - some ANSI compilers define this only to 0, hence the use of + "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 + sets __STDC__ to 0, but requires "##" for token pasting. + + _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but + don't always define __STDC__. + + _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 + mode, but doesn't define __STDC__. + + _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za + option is given (in which case it's 1). + + _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that + all w32 compilers are ansi. */ + +#if defined (__STDC__) \ + || defined (__cplusplus) \ + || defined (_AIX) \ + || defined (__DECC) \ + || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ + || defined (_MSC_VER) \ + || defined (_WIN32) +#define __GMP_HAVE_CONST 1 +#define __GMP_HAVE_PROTOTYPES 1 +#define __GMP_HAVE_TOKEN_PASTE 1 +#else +#define __GMP_HAVE_CONST 0 +#define __GMP_HAVE_PROTOTYPES 0 +#define __GMP_HAVE_TOKEN_PASTE 0 +#endif + + +#if __GMP_HAVE_CONST +#define __gmp_const const +#define __gmp_signed signed +#else +#define __gmp_const +#define __gmp_signed +#endif + + +/* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in + all other circumstances. + + When compiling objects for libgmp, __GMP_DECLSPEC is an export directive, + or when compiling for an application it's an import directive. The two + cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles + (and not defined from an application). + + __GMP_DECLSPEC_XX is similarly used for libgmpxx. __GMP_WITHIN_GMPXX + indicates when building libgmpxx, and in that case libgmpxx functions are + exports, but libgmp functions which might get called are imports. + + libmp.la uses __GMP_DECLSPEC, just as if it were libgmp.la. libgmp and + libmp don't call each other, so there's no conflict or confusion. + + Libtool DLL_EXPORT define is not used. + + There's no attempt to support GMP built both static and DLL. Doing so + would mean applications would have to tell us which of the two is going + to be used when linking, and that seems very tedious and error prone if + using GMP by hand, and equally tedious from a package since autoconf and + automake don't give much help. + + __GMP_DECLSPEC is required on all documented global functions and + variables, the various internals in gmp-impl.h etc can be left unadorned. + But internals used by the test programs or speed measuring programs + should have __GMP_DECLSPEC, and certainly constants or variables must + have it or the wrong address will be resolved. */ + +#if defined (__GNUC__) || defined (_MSC_VER) || defined (__BORLANDC__) +#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) +#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) +#endif +#ifdef __WATCOMC__ +#define __GMP_DECLSPEC_EXPORT __export +#define __GMP_DECLSPEC_IMPORT __import +#endif +#ifdef __IBMC__ +#define __GMP_DECLSPEC_EXPORT _Export +#define __GMP_DECLSPEC_IMPORT _Import +#endif + +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMP +/* compiling to go into a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into an application which will link to a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC +#endif + + +#ifdef _SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif + +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +#if defined (_CRAY) && ! defined (_CRAYMPP) +/* plain `int' is much faster (48 bits) */ +#define __GMP_MP_SIZE_T_INT 1 +typedef int mp_size_t; +typedef int mp_exp_t; +#else +#define __GMP_MP_SIZE_T_INT 0 +typedef long int mp_size_t; +typedef long int mp_exp_t; +#endif + +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#endif /* __GNU_MP__ */ + +typedef __mpz_struct MP_INT; +typedef __mpz_struct mpz_t[1]; + +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +} __mpq_struct; + +typedef __mpq_struct MP_RAT; +typedef __mpq_struct mpq_t[1]; + +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to by the + _mp_d field contains `prec' + 1 limbs. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; + +/* typedef __mpf_struct MP_FLOAT; */ +typedef __mpf_struct mpf_t[1]; + +/* Available random number generation algorithms. */ +typedef enum +{ + GMP_RAND_ALG_DEFAULT = 0, + GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ +} gmp_randalg_t; + +/* Linear congruential data struct. */ +typedef struct { + mpz_t _mp_a; /* Multiplier. */ + unsigned long int _mp_c; /* Adder. */ + mpz_t _mp_m; /* Modulus (valid only if m2exp == 0). */ + unsigned long int _mp_m2exp; /* If != 0, modulus is 2 ^ m2exp. */ +} __gmp_randata_lc; + +/* Random state struct. */ +typedef struct +{ + mpz_t _mp_seed; /* Current seed. */ + gmp_randalg_t _mp_alg; /* Algorithm used. */ + union { /* Algorithm specific data. */ + __gmp_randata_lc *_mp_lc; /* Linear congruential. */ + } _mp_algdata; +} __gmp_randstate_struct; +typedef __gmp_randstate_struct gmp_randstate_t[1]; + +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; + + +/* This is not wanted in mp.h, so put it outside the __GNU_MP__ common + section. */ +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMPXX +/* compiling to go into a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into a application which will link to a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC_XX +#endif + + +#if __GMP_HAVE_PROTOTYPES +#define __GMP_PROTO(x) x +#else +#define __GMP_PROTO(x) () +#endif + +#ifndef __MPN +#if __GMP_HAVE_TOKEN_PASTE +#define __MPN(x) __gmpn_##x +#else +#define __MPN(x) __gmpn_/**/x +#endif +#endif + +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (__dj_include_stdio_h_) /* DJGPP */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ +#define _GMP_H_HAVE_FILE 1 +#endif + +/* In ISO C, if a prototype involving "struct obstack *" is given without + that structure defined, then the struct is scoped down to just the + prototype, causing a conflict if it's subsequently defined for real. So + only give prototypes if we've got obstack.h. */ +#if defined (_OBSTACK_H) /* glibc */ +#define _GMP_H_HAVE_OBSTACK 1 +#endif + +/* The prototypes for gmp_vprintf etc are provided only if va_list is + available, via an application having included or . + Usually va_list is a typedef so can't be tested directly, but va_start is + almost certainly a macro, so look for that. + + will define some sort of va_list for vprintf and vfprintf, but + let's not bother trying to use that since it's not standard and since + application uses for gmp_vprintf etc will almost certainly require the + whole or anyway. */ + +#ifdef va_start +#define _GMP_H_HAVE_VA_LIST 1 +#endif + +/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ +#if defined (__GNUC__) && defined (__GNUC_MINOR__) +#define __GMP_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GMP_GNUC_PREREQ(maj, min) 0 +#endif + +/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically + it means a function does nothing but examine its arguments and memory + (global or via arguments) to generate a return value, but changes nothing + and has no side-effects. */ +#if __GMP_GNUC_PREREQ (2,96) +#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +#define __GMP_ATTRIBUTE_PURE +#endif + + +/* An empty "throw ()" means the function doesn't throw any C++ exceptions, + this can save some stack frame info in applications. + + Currently it's given only on functions which never divide-by-zero etc, + don't allocate memory, and are expected to never need to allocate memory. + This leaves open the possibility of a C++ throw from a future GMP + exceptions scheme. + + mpz_set_ui etc are omitted to leave open the lazy allocation scheme + described in doc/tasks.html. mpz_get_d etc are omitted to leave open + exceptions for float overflows. + + Note that __GMP_NOTHROW must be given on any inlines the same as on their + prototypes (for g++ at least, where they're used together). Note also + that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like + __GMP_ATTRIBUTE_PURE. */ + +#if defined (__cplusplus) +#define __GMP_NOTHROW throw () +#else +#define __GMP_NOTHROW +#endif + + +/* PORTME: What other compilers have a useful "extern inline"? "static + inline" would be an acceptable substitute if the compiler (or linker) + discards unused statics. */ + +/* gcc has __inline__ in all modes, including strict ansi. Give a prototype + for an inline too, so as to correctly specify "dllimport" on windows, in + case the function is called rather than inlined. */ +#ifdef __GNUC__ +#define __GMP_EXTERN_INLINE extern __inline__ +#define __GMP_INLINE_PROTOTYPES 1 +#endif + +/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict + ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes + place under -O. Without -O "foo" seems to be emitted whether it's used + or not, which is wasteful. "extern inline foo()" isn't useful, the + "extern" is apparently ignored, so foo is inlined if possible but also + emitted as a global, which causes multiple definition errors when + building a shared libgmp. */ +#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE static inline +#endif + +/* C++ always has "inline" and since it's a normal feature the linker should + discard duplicate non-inlined copies, or if it doesn't then that's a + problem for everyone, not just GMP. */ +#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE inline +#endif + +/* By default, don't give a prototype when there's going to be an inline + version. Note in particular that Cray C++ objects to the combination of + prototype and inline. */ +#ifdef __GMP_EXTERN_INLINE +#ifndef __GMP_INLINE_PROTOTYPES +#define __GMP_INLINE_PROTOTYPES 0 +#endif +#else +#define __GMP_INLINE_PROTOTYPES 1 +#endif + + +#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) + +#define __GMP_UINT_MAX (~ (unsigned) 0) +#define __GMP_ULONG_MAX (~ (unsigned long) 0) +#define __GMP_USHRT_MAX ((unsigned short) ~0) + + +/* Allow direct user access to numerator and denominator of a mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) + + +#if defined (__cplusplus) +extern "C" { +#endif + +#define mp_set_memory_functions __gmp_set_memory_functions +__GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))) __GMP_NOTHROW; + +#define mp_bits_per_limb __gmp_bits_per_limb +__GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; + +#define gmp_errno __gmp_errno +__GMP_DECLSPEC extern int gmp_errno; + +#define gmp_version __gmp_version +__GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; + +/* The following for internal use only. + Enhancement: __gmp_allocate_func could have "__attribute__ ((malloc))", + but current gcc (3.0) doesn't seem to support that. */ +__GMP_DECLSPEC extern void * (*__gmp_allocate_func) __GMP_PROTO ((size_t)); +__GMP_DECLSPEC extern void * (*__gmp_reallocate_func) __GMP_PROTO ((void *, size_t, size_t)); +__GMP_DECLSPEC extern void (*__gmp_free_func) __GMP_PROTO ((void *, size_t)); + + +/**************** Random number routines. ****************/ + +/* obsolete */ +#define gmp_randinit __gmp_randinit +__GMP_DECLSPEC void gmp_randinit __GMP_PROTO ((gmp_randstate_t, gmp_randalg_t, ...)); + +#define gmp_randinit_default __gmp_randinit_default +__GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_randinit_lc __gmp_randinit_lc +__GMP_DECLSPEC void gmp_randinit_lc __GMP_PROTO ((gmp_randstate_t, + mpz_srcptr, unsigned long int, mpz_srcptr)); + +#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp +__GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, + mpz_srcptr, unsigned long int, + unsigned long int)); + +#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size +__GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); + +#define gmp_randseed __gmp_randseed +__GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); + +#define gmp_randseed_ui __gmp_randseed_ui +__GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, unsigned long int)); + +#define gmp_randclear __gmp_randclear +__GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); + + +/**************** Formatted output routines. ****************/ + +#define gmp_asprintf __gmp_asprintf +__GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, const char *, ...)); + +#define gmp_fprintf __gmp_fprintf +#if _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, const char *, ...)); +#endif + +#define gmp_obstack_printf __gmp_obstack_printf +#if _GMP_H_HAVE_OBSTACK +__GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, const char *, ...)); +#endif + +#define gmp_obstack_vprintf __gmp_obstack_vprintf +#if _GMP_H_HAVE_OBSTACK && _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, const char *, va_list)); +#endif + +#define gmp_printf __gmp_printf +__GMP_DECLSPEC int gmp_printf __GMP_PROTO ((const char *, ...)); + +#define gmp_snprintf __gmp_snprintf +__GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, const char *, ...)); + +#define gmp_sprintf __gmp_sprintf +__GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, const char *, ...)); + +#define gmp_vasprintf __gmp_vasprintf +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, const char *, va_list)); +#endif + +#define gmp_vfprintf __gmp_vfprintf +#if _GMP_H_HAVE_FILE && _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, const char *, va_list)); +#endif + +#define gmp_vprintf __gmp_vprintf +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((const char *, va_list)); +#endif + +#define gmp_vsnprintf __gmp_vsnprintf +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, const char *, va_list)); +#endif + +#define gmp_vsprintf __gmp_vsprintf +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, const char *, va_list)); +#endif + + +/**************** Formatted input routines. ****************/ + +#define gmp_fscanf __gmp_fscanf +#if _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, const char *, ...)); +#endif + +#define gmp_scanf __gmp_scanf +__GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((const char *, ...)); + +#define gmp_sscanf __gmp_sscanf +__GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((const char *, const char *, ...)); + +#define gmp_vfscanf __gmp_vfscanf +#if _GMP_H_HAVE_FILE && _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, const char *, va_list)); +#endif + +#define gmp_vscanf __gmp_vscanf +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((const char *, va_list)); +#endif + +#define gmp_vsscanf __gmp_vsscanf +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((const char *, const char *, va_list)); +#endif + + +/**************** Integer (i.e. Z) routines. ****************/ + +#define _mpz_realloc __gmpz_realloc +#define mpz_realloc __gmpz_realloc +__GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_abs __gmpz_abs +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_abs +__GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif + +#define mpz_add __gmpz_add +__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_add_ui __gmpz_add_ui +__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_addmul __gmpz_addmul +__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_addmul_ui __gmpz_addmul_ui +__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_and __gmpz_and +__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_array_init __gmpz_array_init +__GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); + +#define mpz_bin_ui __gmpz_bin_ui +__GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_bin_uiui __gmpz_bin_uiui +__GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +#define mpz_cdiv_q __gmpz_cdiv_q +__GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp +__GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_qr __gmpz_cdiv_qr +__GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_r __gmpz_cdiv_r +__GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp +__GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_ui __gmpz_cdiv_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_clear __gmpz_clear +__GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); + +#define mpz_clrbit __gmpz_clrbit +__GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_cmp __gmpz_cmp +__GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmp_d __gmpz_cmp_d +__GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_si __gmpz_cmp_si +__GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_ui __gmpz_cmp_ui +__GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs __gmpz_cmpabs +__GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_d __gmpz_cmpabs_d +__GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_ui __gmpz_cmpabs_ui +__GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_com __gmpz_com +__GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_congruent_p __gmpz_congruent_p +__GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p +__GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_ui_p __gmpz_congruent_ui_p +__GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divexact __gmpz_divexact +__GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_divexact_ui __gmpz_divexact_ui +__GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_divisible_p __gmpz_divisible_p +__GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_ui_p __gmpz_divisible_ui_p +__GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p +__GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_dump __gmpz_dump +__GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); + +#define mpz_export __gmpz_export +__GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr z)); + +#define mpz_fac_ui __gmpz_fac_ui +__GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_fdiv_q __gmpz_fdiv_q +__GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp +__GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_qr __gmpz_fdiv_qr +__GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_r __gmpz_fdiv_r +__GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp +__GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_ui __gmpz_fdiv_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_fib_ui __gmpz_fib_ui +__GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_fib2_ui __gmpz_fib2_ui +__GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); + +#define mpz_fits_sint_p __gmpz_fits_sint_p +__GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_slong_p __gmpz_fits_slong_p +__GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_sshort_p __gmpz_fits_sshort_p +__GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_uint_p __gmpz_fits_uint_p +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_fits_uint_p +__GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ulong_p __gmpz_fits_ulong_p +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_fits_ulong_p +__GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ushort_p __gmpz_fits_ushort_p +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_fits_ushort_p +__GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_gcd __gmpz_gcd +__GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_gcd_ui __gmpz_gcd_ui +__GMP_DECLSPEC unsigned long int mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_gcdext __gmpz_gcdext +__GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_get_d __gmpz_get_d +__GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_get_d_2exp __gmpz_get_d_2exp +__GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long int *, mpz_srcptr)); + +#define mpz_get_si __gmpz_get_si +__GMP_DECLSPEC /* signed */ long int mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_get_str __gmpz_get_str +__GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); + +#define mpz_get_ui __gmpz_get_ui +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_get_ui +__GMP_DECLSPEC unsigned long int mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_getlimbn __gmpz_getlimbn +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_getlimbn +__GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_hamdist __gmpz_hamdist +__GMP_DECLSPEC unsigned long int mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_import __gmpz_import +__GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, const void *)); + +#define mpz_init __gmpz_init +__GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); + +#define mpz_init2 __gmpz_init2 +__GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, unsigned long)); + +#define mpz_init_set __gmpz_init_set +__GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_init_set_d __gmpz_init_set_d +__GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); + +#define mpz_init_set_si __gmpz_init_set_si +__GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, signed long int)); + +#define mpz_init_set_str __gmpz_init_set_str +__GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); + +#define mpz_init_set_ui __gmpz_init_set_ui +__GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_inp_raw __gmpz_inp_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); +#endif + +#define mpz_inp_str __gmpz_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); +#endif + +#define mpz_invert __gmpz_invert +__GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_ior __gmpz_ior +__GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_jacobi __gmpz_jacobi +__GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker mpz_jacobi /* alias */ + +#define mpz_kronecker_si __gmpz_kronecker_si +__GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker_ui __gmpz_kronecker_ui +__GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_si_kronecker __gmpz_si_kronecker +__GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_kronecker __gmpz_ui_kronecker +__GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((unsigned long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_lcm __gmpz_lcm +__GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_lcm_ui __gmpz_lcm_ui +__GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_legendre mpz_jacobi /* alias */ + +#define mpz_lucnum_ui __gmpz_lucnum_ui +__GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_lucnum2_ui __gmpz_lucnum2_ui +__GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); + +#define mpz_millerrabin __gmpz_millerrabin +__GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_mod __gmpz_mod +__GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_mul __gmpz_mul +__GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_mul_2exp __gmpz_mul_2exp +__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_mul_si __gmpz_mul_si +__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int)); + +#define mpz_mul_ui __gmpz_mul_ui +__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_neg __gmpz_neg +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_neg +__GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif + +#define mpz_nextprime __gmpz_nextprime +__GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_out_raw __gmpz_out_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); +#endif + +#define mpz_out_str __gmpz_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); +#endif + +#define mpz_perfect_power_p __gmpz_perfect_power_p +__GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_perfect_square_p __gmpz_perfect_square_p +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_perfect_square_p +__GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_popcount __gmpz_popcount +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_popcount +__GMP_DECLSPEC unsigned long int mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_pow_ui __gmpz_pow_ui +__GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_powm __gmpz_powm +__GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_powm_ui __gmpz_powm_ui +__GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); + +#define mpz_probab_prime_p __gmpz_probab_prime_p +__GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_random __gmpz_random +__GMP_DECLSPEC void mpz_random __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_random2 __gmpz_random2 +__GMP_DECLSPEC void mpz_random2 __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_realloc2 __gmpz_realloc2 +__GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, unsigned long)); + +#define mpz_remove __gmpz_remove +__GMP_DECLSPEC unsigned long int mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_root __gmpz_root +__GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_rrandomb __gmpz_rrandomb +__GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); + +#define mpz_scan0 __gmpz_scan0 +__GMP_DECLSPEC unsigned long int mpz_scan0 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_scan1 __gmpz_scan1 +__GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_set __gmpz_set +__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_set_d __gmpz_set_d +__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); + +#define mpz_set_f __gmpz_set_f +__GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); + +#define mpz_set_q __gmpz_set_q +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_set_q +__GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +#endif + +#define mpz_set_si __gmpz_set_si +__GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, signed long int)); + +#define mpz_set_str __gmpz_set_str +__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); + +#define mpz_set_ui __gmpz_set_ui +__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_setbit __gmpz_setbit +__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_size __gmpz_size +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpz_size +__GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_sizeinbase __gmpz_sizeinbase +__GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_sqrt __gmpz_sqrt +__GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_sqrtrem __gmpz_sqrtrem +__GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); + +#define mpz_sub __gmpz_sub +__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_sub_ui __gmpz_sub_ui +__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_ui_sub __gmpz_ui_sub +__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr)); + +#define mpz_submul __gmpz_submul +__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_submul_ui __gmpz_submul_ui +__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_swap __gmpz_swap +__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; + +#define mpz_tdiv_ui __gmpz_tdiv_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_tdiv_q __gmpz_tdiv_q +__GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp +__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_qr __gmpz_tdiv_qr +__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_r __gmpz_tdiv_r +__GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp +__GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tstbit __gmpz_tstbit +__GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_pow_ui __gmpz_ui_pow_ui +__GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +#define mpz_urandomb __gmpz_urandomb +__GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); + +#define mpz_urandomm __gmpz_urandomm +__GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); + +#define mpz_xor __gmpz_xor +#define mpz_eor __gmpz_xor +__GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + + +/**************** Rational (i.e. Q) routines. ****************/ + +#define mpq_abs __gmpq_abs +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpq_abs +__GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif + +#define mpq_add __gmpq_add +__GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_canonicalize __gmpq_canonicalize +__GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); + +#define mpq_clear __gmpq_clear +__GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); + +#define mpq_cmp __gmpq_cmp +__GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_si __gmpq_cmp_si +__GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, long, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_ui __gmpq_cmp_ui +__GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, unsigned long int, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpq_div __gmpq_div +__GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_div_2exp __gmpq_div_2exp +__GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); + +#define mpq_equal __gmpq_equal +__GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpq_get_num __gmpq_get_num +__GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); + +#define mpq_get_den __gmpq_get_den +__GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); + +#define mpq_get_d __gmpq_get_d +__GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpq_get_str __gmpq_get_str +__GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); + +#define mpq_init __gmpq_init +__GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); + +#define mpq_inp_str __gmpq_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); +#endif + +#define mpq_inv __gmpq_inv +__GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); + +#define mpq_mul __gmpq_mul +__GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_mul_2exp __gmpq_mul_2exp +__GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); + +#define mpq_neg __gmpq_neg +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpq_neg +__GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif + +#define mpq_out_str __gmpq_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); +#endif + +#define mpq_set __gmpq_set +__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); + +#define mpq_set_d __gmpq_set_d +__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); + +#define mpq_set_den __gmpq_set_den +__GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_set_f __gmpq_set_f +__GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); + +#define mpq_set_num __gmpq_set_num +__GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_set_si __gmpq_set_si +__GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, signed long int, unsigned long int)); + +#define mpq_set_str __gmpq_set_str +__GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, const char *, int)); + +#define mpq_set_ui __gmpq_set_ui +__GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, unsigned long int, unsigned long int)); + +#define mpq_set_z __gmpq_set_z +__GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_sub __gmpq_sub +__GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_swap __gmpq_swap +__GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; + + +/**************** Float (i.e. F) routines. ****************/ + +#define mpf_abs __gmpf_abs +__GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_add __gmpf_add +__GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_add_ui __gmpf_add_ui +__GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +#define mpf_ceil __gmpf_ceil +__GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_clear __gmpf_clear +__GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); + +#define mpf_cmp __gmpf_cmp +__GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_d __gmpf_cmp_d +__GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_si __gmpf_cmp_si +__GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_ui __gmpf_cmp_ui +__GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_div __gmpf_div +__GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_div_2exp __gmpf_div_2exp +__GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_div_ui __gmpf_div_ui +__GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_dump __gmpf_dump +__GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); + +#define mpf_eq __gmpf_eq +__GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sint_p __gmpf_fits_sint_p +__GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_slong_p __gmpf_fits_slong_p +__GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sshort_p __gmpf_fits_sshort_p +__GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_uint_p __gmpf_fits_uint_p +__GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ulong_p __gmpf_fits_ulong_p +__GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ushort_p __gmpf_fits_ushort_p +__GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_floor __gmpf_floor +__GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_get_d __gmpf_get_d +__GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpf_get_d_2exp __gmpf_get_d_2exp +__GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long int *, mpf_srcptr)); + +#define mpf_get_default_prec __gmpf_get_default_prec +__GMP_DECLSPEC unsigned long int mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_prec __gmpf_get_prec +__GMP_DECLSPEC unsigned long int mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_si __gmpf_get_si +__GMP_DECLSPEC long mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_str __gmpf_get_str +__GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); + +#define mpf_get_ui __gmpf_get_ui +__GMP_DECLSPEC unsigned long mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_init __gmpf_init +__GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); + +#define mpf_init2 __gmpf_init2 +__GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_init_set __gmpf_init_set +__GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_init_set_d __gmpf_init_set_d +__GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); + +#define mpf_init_set_si __gmpf_init_set_si +__GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, signed long int)); + +#define mpf_init_set_str __gmpf_init_set_str +__GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); + +#define mpf_init_set_ui __gmpf_init_set_ui +__GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_inp_str __gmpf_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); +#endif + +#define mpf_integer_p __gmpf_integer_p +__GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_mul __gmpf_mul +__GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_mul_2exp __gmpf_mul_2exp +__GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_mul_ui __gmpf_mul_ui +__GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_neg __gmpf_neg +__GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_out_str __gmpf_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); +#endif + +#define mpf_pow_ui __gmpf_pow_ui +__GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_random2 __gmpf_random2 +__GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); + +#define mpf_reldiff __gmpf_reldiff +__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_set __gmpf_set +__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_set_d __gmpf_set_d +__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); + +#define mpf_set_default_prec __gmpf_set_default_prec +__GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((unsigned long int)) __GMP_NOTHROW; + +#define mpf_set_prec __gmpf_set_prec +__GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_set_prec_raw __gmpf_set_prec_raw +__GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, unsigned long int)) __GMP_NOTHROW; + +#define mpf_set_q __gmpf_set_q +__GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); + +#define mpf_set_si __gmpf_set_si +__GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, signed long int)); + +#define mpf_set_str __gmpf_set_str +__GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); + +#define mpf_set_ui __gmpf_set_ui +__GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_set_z __gmpf_set_z +__GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); + +#define mpf_size __gmpf_size +__GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_sqrt __gmpf_sqrt +__GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_sqrt_ui __gmpf_sqrt_ui +__GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_sub __gmpf_sub +__GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_sub_ui __gmpf_sub_ui +__GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_swap __gmpf_swap +__GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; + +#define mpf_trunc __gmpf_trunc +__GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_ui_div __gmpf_ui_div +__GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); + +#define mpf_ui_sub __gmpf_ui_sub +__GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); + +#define mpf_urandomb __gmpf_urandomb +__GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned long int)); + + +/************ Low level positive-integer (i.e. N) routines. ************/ + +/* This is ugly, but we need to make user calls reach the prefixed function. */ + +#define mpn_add __MPN(add) +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpn_add +__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif + +#define mpn_add_1 __MPN(add_1) +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpn_add_1 +__GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif + +#define mpn_add_n __MPN(add_n) +__GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_addmul_1 __MPN(addmul_1) +__GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_bdivmod __MPN(bdivmod) +__GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); + +#define mpn_cmp __MPN(cmp) +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpn_cmp +__GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_divexact_by3(dst,src,size) \ + mpn_divexact_by3c (dst, src, size, (mp_limb_t) 0) + +#define mpn_divexact_by3c __MPN(divexact_by3c) +__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_divmod_1(qp,np,nsize,dlimb) \ + mpn_divrem_1 (qp, (mp_size_t) 0, np, nsize, dlimb) + +#define mpn_divrem __MPN(divrem) +__GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); + +#define mpn_divrem_1 __MPN(divrem_1) +__GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_divrem_2 __MPN(divrem_2) +__GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); + +#define mpn_gcd __MPN(gcd) +__GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); + +#define mpn_gcd_1 __MPN(gcd_1) +__GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_gcdext __MPN(gcdext) +__GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); + +#define mpn_get_str __MPN(get_str) +__GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); + +#define mpn_hamdist __MPN(hamdist) +__GMP_DECLSPEC unsigned long int mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_lshift __MPN(lshift) +__GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); + +#define mpn_mod_1 __MPN(mod_1) +__GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_mul __MPN(mul) +__GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); + +#define mpn_mul_1 __MPN(mul_1) +__GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_mul_n __MPN(mul_n) +__GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_perfect_square_p __MPN(perfect_square_p) +__GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_popcount __MPN(popcount) +__GMP_DECLSPEC unsigned long int mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_pow_1 __MPN(pow_1) +__GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); + +/* undocumented now, but retained here for upward compatibility */ +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) +__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_random __MPN(random) +__GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); + +#define mpn_random2 __MPN(random2) +__GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); + +#define mpn_rshift __MPN(rshift) +__GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); + +#define mpn_scan0 __MPN(scan0) +__GMP_DECLSPEC unsigned long int mpn_scan0 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpn_scan1 __MPN(scan1) +__GMP_DECLSPEC unsigned long int mpn_scan1 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpn_set_str __MPN(set_str) +__GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); + +#define mpn_sqrtrem __MPN(sqrtrem) +__GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); + +#define mpn_sub __MPN(sub) +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpn_sub +__GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif + +#define mpn_sub_1 __MPN(sub_1) +#if __GMP_INLINE_PROTOTYPES || __GMP_FORCE_mpn_sub_1 +__GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif + +#define mpn_sub_n __MPN(sub_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_submul_1 __MPN(submul_1) +__GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_tdiv_qr __MPN(tdiv_qr) +__GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); + + +/**************** mpz inlines ****************/ + +/* The following are provided as inlines where possible, but always exist as + library functions too, for binary compatibility. + + Within gmp itself this inlining generally isn't relied on, since it + doesn't get done for all compilers, whereas if something is worth + inlining then it's worth arranging always. + + There are two styles of inlining here. When the same bit of code is + wanted for the inline as for the library version, then __GMP_FORCE_foo + arranges for that code to be emitted and the __GMP_EXTERN_INLINE + directive suppressed, eg. mpz_fits_uint_p. When a different bit of code + is wanted for the inline than for the library version, then + __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ + +#if defined (__GMP_EXTERN_INLINE) && ! __GMP_FORCE_mpz_abs +__GMP_EXTERN_INLINE void +mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); +} +#endif + +#if GMP_NAIL_BITS == 0 +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); +#else +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ + || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_fits_uint_p +#if ! __GMP_FORCE_mpz_fits_uint_p +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_fits_ulong_p +#if ! __GMP_FORCE_mpz_fits_ulong_p +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_fits_ushort_p +#if ! __GMP_FORCE_mpz_fits_ushort_p +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_get_ui +#if ! __GMP_FORCE_mpz_get_ui +__GMP_EXTERN_INLINE +#endif +unsigned long +mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + mp_ptr __gmp_p = __gmp_z->_mp_d; + mp_size_t __gmp_n = __gmp_z->_mp_size; + mp_limb_t __gmp_l = __gmp_p[0]; + if (__GMP_ULONG_MAX <= GMP_NUMB_MASK) + return __gmp_l & (-(mp_limb_t) (__gmp_n != 0)); +#if GMP_NAIL_BITS != 0 /* redundant #if, shuts up compiler warnings */ + else /* happens for nails, but not if LONG_LONG_LIMB */ + { /* assume two limbs are enough to fill an ulong */ + __gmp_n = __GMP_ABS (__gmp_n); + if (__gmp_n <= 1) + return __gmp_l & (-(mp_limb_t) (__gmp_n != 0)); + else + return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS); + } +#endif +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_getlimbn +#if ! __GMP_FORCE_mpz_getlimbn +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW +{ + if (__GMP_ABS (__gmp_z->_mp_size) <= __gmp_n || __gmp_n < 0) + return 0; + else + return __gmp_z->_mp_d[__gmp_n]; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! __GMP_FORCE_mpz_neg +__GMP_EXTERN_INLINE void +mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = - __gmp_w->_mp_size; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_perfect_square_p +#if ! __GMP_FORCE_mpz_perfect_square_p +__GMP_EXTERN_INLINE +#endif +int +mpz_perfect_square_p (mpz_srcptr __gmp_a) +{ + mp_size_t __gmp_asize = __gmp_a->_mp_size; + if (__gmp_asize <= 0) + return (__gmp_asize == 0); /* zero is a square, negatives are not */ + else + return mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_popcount +#if ! __GMP_FORCE_mpz_popcount +__GMP_EXTERN_INLINE +#endif +unsigned long +mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW +{ + mp_size_t __gmp_usize = __gmp_u->_mp_size; + + if (__gmp_usize <= 0) + return (__gmp_usize < 0 ? __GMP_ULONG_MAX : 0); + else + return mpn_popcount (__gmp_u->_mp_d, __gmp_usize); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_set_q +#if ! __GMP_FORCE_mpz_set_q +__GMP_EXTERN_INLINE +#endif +void +mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpz_size +#if ! __GMP_FORCE_mpz_size +__GMP_EXTERN_INLINE +#endif +size_t +mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + return __GMP_ABS (__gmp_z->_mp_size); +} +#endif + + +/**************** mpq inlines ****************/ + +#if defined (__GMP_EXTERN_INLINE) && ! __GMP_FORCE_mpq_abs +__GMP_EXTERN_INLINE void +mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! __GMP_FORCE_mpq_neg +__GMP_EXTERN_INLINE void +mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; +} +#endif + + +/**************** mpn inlines ****************/ + +/* The comments with __GMPN_ADD_1 below apply here too. + + The test for FUNCTION returning 0 should predict well. If it's assumed + {yp,ysize} will usually have a random number of bits then the high limb + won't be full and a carry out will occur a good deal less than 50% of the + time. + + ysize==0 isn't a documented feature, but is used internally in a few + places. + + Producing cout last stops it using up a register during the main part of + the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" + doesn't seem able to move the true and false legs of the conditional up + to the two places cout is generated. */ + +#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x; \ + \ + /* ASSERT ((ysize) >= 0); */ \ + /* ASSERT ((xsize) >= (ysize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ + \ + __gmp_i = (ysize); \ + if (__gmp_i != 0) \ + { \ + if (FUNCTION (wp, xp, yp, __gmp_i)) \ + { \ + do \ + { \ + if (__gmp_i >= (xsize)) \ + { \ + (cout) = 1; \ + goto __gmp_done; \ + } \ + __gmp_x = (xp)[__gmp_i]; \ + } \ + while (TEST); \ + } \ + } \ + if ((wp) != (xp)) \ + __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ + (cout) = 0; \ + __gmp_done: \ + ; \ + } while (0) + +#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ + (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) +#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ + (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) + + +/* The use of __gmp_i indexing is designed to ensure a compile time src==dst + remains nice and clear to the compiler, so that __GMPN_COPY_REST can + disappear, and the load/add/store gets a chance to become a + read-modify-write on CISC CPUs. + + Alternatives: + + Using a pair of pointers instead of indexing would be possible, but gcc + isn't able to recognise compile-time src==dst in that case, even when the + pointers are incremented more or less together. Other compilers would + very likely have similar difficulty. + + gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or + similar to detect a compile-time src==dst. This works nicely on gcc + 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems + to be always false, for a pointer p. But the current code form seems + good enough for src==dst anyway. + + gcc on x86 as usual doesn't give particularly good flags handling for the + carry/borrow detection. It's tempting to want some multi instruction asm + blocks to help it, and this was tried, but in truth there's only a few + instructions to save and any gain is all too easily lost by register + juggling setting up for the asm. */ + +#if GMP_NAIL_BITS == 0 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r; \ + if (CB (__gmp_r, __gmp_x, (v))) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r; \ + ++__gmp_i; \ + if (!CB (__gmp_r, __gmp_x, 1)) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#if GMP_NAIL_BITS >= 1 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ + if (__gmp_r >> GMP_NUMB_BITS != 0) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ + ++__gmp_i; \ + if (__gmp_r >> GMP_NUMB_BITS == 0) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#define __GMPN_ADDCB(r,x,y) ((r) < (y)) +#define __GMPN_SUBCB(r,x,y) ((x) < (y)) + +#define __GMPN_ADD_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) +#define __GMPN_SUB_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) + + +/* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or + negative. size==0 is allowed. On random data usually only one limb will + need to be examined to get a result, so it's worth having it inline. */ +#define __GMPN_CMP(result, xp, yp, size) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_y; \ + \ + /* ASSERT ((size) >= 0); */ \ + \ + (result) = 0; \ + __gmp_i = (size); \ + while (--__gmp_i >= 0) \ + { \ + __gmp_x = (xp)[__gmp_i]; \ + __gmp_y = (yp)[__gmp_i]; \ + if (__gmp_x != __gmp_y) \ + { \ + /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ + (result) = (__gmp_x > __gmp_y ? 1 : -1); \ + break; \ + } \ + } \ + } while (0) + + +/* For power and powerpc we want an inline ldu/stu/bdnz loop for copying. + On ppc630 for instance this is optimal since it can sustain only 1 store + per cycle. + + gcc 2.95.x (powerpc64 -maix64, or powerpc32) doesn't recognise the "for" + loop in the generic code below can become ldu/stu/bdnz. The do/while + here helps it get to that. + + In gcc -mpowerpc64 mode, without -maix64, __size seems to want to be an + mp_limb_t to get into the ctr register, and even then the loop is a + curious ldu/stu/bdz/b. But let's not worry about that unless there's a + system using this. An asm block could force what we want if necessary. + + xlc 3.1 already generates ldu/stu/bdnz from the generic C, and does so + from this loop too. */ + +#if __GMP_HAVE_HOST_CPU_FAMILY_power || __GMP_HAVE_HOST_CPU_FAMILY_powerpc +#define __GMPN_COPY_INCR(dst, src, size) \ + do { \ + /* ASSERT ((size) >= 0); */ \ + /* ASSERT (MPN_SAME_OR_INCR_P (dst, src, size)); */ \ + if ((size) != 0) \ + { \ + mp_ptr __gmp_copy_incr_dst = (dst) - 1; \ + mp_srcptr __gmp_copy_incr_src = (src) - 1; \ + mp_size_t __gmp_copy_incr_size = (size); \ + do \ + *++__gmp_copy_incr_dst = *++__gmp_copy_incr_src; \ + while (--__gmp_copy_incr_size != 0); \ + } \ + } while (0) +#define __GMPN_COPY(dst, src, size) \ + do { \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ + __GMPN_COPY_INCR (dst, src, size); \ + } while (0) +#endif + +#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ + } while (0) +#endif + +/* Copy {src,size} to {dst,size}, starting at "start". This is designed to + keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, + __GMPN_ADD, etc. */ +#if ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + mp_size_t __gmp_j; \ + /* ASSERT ((size) >= 0); */ \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ + for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ + (dst)[__gmp_j] = (src)[__gmp_j]; \ + } while (0) +#endif + +/* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use + mpn_copyi if there's a native version, and if we don't mind demanding + binary compatibility for it (on targets which use it). */ + +#if ! defined (__GMPN_COPY) +#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) +#endif + + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpn_add +#if ! __GMP_FORCE_mpn_add +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpn_add_1 +#if ! __GMP_FORCE_mpn_add_1 +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpn_cmp +#if ! __GMP_FORCE_mpn_cmp +__GMP_EXTERN_INLINE +#endif +int +mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW +{ + int __gmp_result; + __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpn_sub +#if ! __GMP_FORCE_mpn_sub +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || __GMP_FORCE_mpn_sub_1 +#if ! __GMP_FORCE_mpn_sub_1 +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif + +#if defined (__cplusplus) +} +#endif + + +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) + +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (SI) && (SI) > 0 \ + ? _mpz_cmp_ui (Z, (unsigned long int) SI) \ + : _mpz_cmp_si (Z,SI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ + ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, (unsigned long) (n), d) \ + : _mpq_cmp_si (q, n, d)) +#else +#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) +#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) +#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) +#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) +#endif + + +/* Using "&" rather than "&&" means these can come out branch-free. Every + mpz_t has at least one limb allocated, so fetching the low limb is always + allowed. */ +#define mpz_odd_p(z) ((int) ((z)->_mp_size != 0) & (int) (z)->_mp_d[0]) +#define mpz_even_p(z) (! mpz_odd_p (z)) + + +/**************** C++ routines ****************/ + +#ifdef __cplusplus +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); +#endif + + +/* Compatibility with GMP 2 and earlier. */ +#define mpn_divmod(qp,np,nsize,dp,dsize) \ + mpn_divrem (qp, (mp_size_t) 0, np, nsize, dp, dsize) + +/* Compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + ((r == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + ((r == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) + +/* Useful synonyms, but not quite compatible with GMP 1. */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_mod_ui mpz_fdiv_r_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp + +enum +{ + GMP_ERROR_NONE = 0, + GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, + GMP_ERROR_DIVISION_BY_ZERO = 2, + GMP_ERROR_SQRT_OF_NEGATIVE = 4, + GMP_ERROR_INVALID_ARGUMENT = 8, + GMP_ERROR_ALLOCATE = 16, + GMP_ERROR_BAD_STRING = 32, + GMP_ERROR_UNUSED_ERROR +}; + +/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ +#define __GNU_MP_VERSION 4 +#define __GNU_MP_VERSION_MINOR 1 +#define __GNU_MP_VERSION_PATCHLEVEL 0 + +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/lib/gmp.dll b/lib/gmp.dll new file mode 100644 index 0000000000000000000000000000000000000000..26f4fbfc0c4526b3e077cfe026955d42b50351f6 GIT binary patch literal 208896 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 z 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 apjZOM5-65Hu>^`GP%MFB3H)zK;Qs*Ch9S2A literal 0 HcmV?d00001 diff --git a/lib/gmp.txt b/lib/gmp.txt new file mode 100644 index 0000000..3030bd5 --- /dev/null +++ b/lib/gmp.txt @@ -0,0 +1,2 @@ +beware, old version 4.1.2 of libgmp (found it precompiled online, should be replaced with a more recent one) +Remember to replace the header in ../include too! \ No newline at end of file diff --git a/src/bncsutil/bncsutil.h b/src/bncsutil/bncsutil.h index aef01ac..444cc86 100644 --- a/src/bncsutil/bncsutil.h +++ b/src/bncsutil/bncsutil.h @@ -25,6 +25,8 @@ #ifndef BNCSUTIL_BNCSUTIL_H_INCLUDED #define BNCSUTIL_BNCSUTIL_H_INCLUDED +#define uint32_t quint32 +#include #include /* Myriad Utility Header */ #include /* CheckRevision / EXE info */ diff --git a/src/bncsutil/bncsutil.pro b/src/bncsutil/bncsutil.pro index 49ff55f..2a720a5 100644 --- a/src/bncsutil/bncsutil.pro +++ b/src/bncsutil/bncsutil.pro @@ -7,16 +7,15 @@ QT -= gui TARGET = bncsutil -INCLUDEPATH += ../ - +INCLUDEPATH += ../ ../../include +DEFINES += MUTIL_LIB_BUILD SOURCES += bsha1.cpp cdkeydecoder.cpp checkrevision.cpp decodekey.cpp file.cpp libinfo.cpp oldauth.cpp \ nls.c pe.c sha1.c stack.c -LIBS += -L../../lib \ - -lgmp +LIBS += -L../../lib -lgmp #macx { # LIBS += -framework CoreFoundation -framework CoreServices # LIBS += -L. -L/usr/lib -lbz2 -lz diff --git a/src/bncsutil/bsha1.cpp b/src/bncsutil/bsha1.cpp index 4344f0f..622d050 100644 --- a/src/bncsutil/bsha1.cpp +++ b/src/bncsutil/bsha1.cpp @@ -139,7 +139,7 @@ MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) { #else -MEXP(void) calcHashBuf(const char* input, size_t length, char* result) { +void calcHashBuf(const char* input, size_t length, char* result) { int i; uint32_t a, b, c, d, e, g; uint32_t* ldata; diff --git a/src/bncsutil/checkrevision.cpp b/src/bncsutil/checkrevision.cpp index 99819a6..4d01ac1 100644 --- a/src/bncsutil/checkrevision.cpp +++ b/src/bncsutil/checkrevision.cpp @@ -358,16 +358,16 @@ MEXP(int) getExeInfo(const char* file_name, char* exe_info, switch (platform) { case BNCSUTIL_PLATFORM_X86: #ifdef MOS_WINDOWS - infoSize = GetFileVersionInfoSize(file_name, &bytesRead); + infoSize = GetFileVersionInfoSizeA(file_name, &bytesRead); if (infoSize == 0) return 0; buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, PAGE_READWRITE); if (buf == NULL) return 0; - if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) + if (GetFileVersionInfoA(file_name, NULL, infoSize, buf) == FALSE) return 0; - if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) + if (!VerQueryValueA(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) return 0; *version = @@ -444,7 +444,7 @@ MEXP(int) getExeInfo(const char* file_name, char* exe_info, } #ifdef MOS_WINDOWS - hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + hFile = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return 0; diff --git a/src/bncsutil/file.cpp b/src/bncsutil/file.cpp index 2e4e783..85c0f15 100644 --- a/src/bncsutil/file.cpp +++ b/src/bncsutil/file.cpp @@ -8,7 +8,7 @@ #define BWIN 1 #include -typedef std::map mapping_map; +typedef std::map mapping_map; #else #define BWIN 0 #include @@ -57,7 +57,7 @@ file_t file_open(const char* filename, unsigned int mode) open_mode = CREATE_ALWAYS; } - file = CreateFile(filename, access, share_mode, NULL, open_mode, + file = CreateFileA(filename, access, share_mode, NULL, open_mode, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) { @@ -83,7 +83,11 @@ file_t file_open(const char* filename, unsigned int mode) delete data; return (file_t) 0; } +#ifdef _MSC_VER strcpy_s((char*) data->filename, filename_buf_len, filename); +#else + strncpy((char*) data->filename, filename, filename_buf_len); +#endif data->f = file; @@ -164,7 +168,7 @@ void* file_map(file_t file, size_t len, off_t offset) return base; } -void file_unmap(file_t file, const void* base) +void file_unmap(file_t file, void* base) { mapping_map::iterator item = file->mappings.find(base); HANDLE mapping; diff --git a/src/bncsutil/file.h b/src/bncsutil/file.h index 4721e28..f64545b 100644 --- a/src/bncsutil/file.h +++ b/src/bncsutil/file.h @@ -53,7 +53,7 @@ size_t file_write(file_t file, const void* ptr, size_t size, size_t file_size(file_t file); void* file_map(file_t file, size_t len, off_t offset); -void file_unmap(file_t file, const void* mapping); +void file_unmap(file_t file, void* mapping); #ifdef __cplusplus } diff --git a/src/bncsutil/mutil_types.h b/src/bncsutil/mutil_types.h index aec9a3d..e64134e 100644 --- a/src/bncsutil/mutil_types.h +++ b/src/bncsutil/mutil_types.h @@ -26,9 +26,9 @@ #ifndef BNCSUTIL_MUTIL_TYPES_H_INCLUDED #define BNCSUTIL_MUTIL_TYPES_H_INCLUDED -#ifdef WIN32 - #include "ms_stdint.h" -#else +//#ifdef WIN32 +// #include "ms_stdint.h" +//#else #if defined(_MSC_VER) || (defined(HAVE_STDINT_H) && !HAVE_STDINT_H) // no stdint.h available @@ -140,6 +140,6 @@ typedef unsigned long long uintmax_t; #include #endif -#endif /* WIN32 */ +//#endif /* WIN32 */ #endif /* BNCSUTIL_MUTIL_TYPES_H_INCLUDED */ diff --git a/src/libghost/ghost.cpp b/src/libghost/ghost.cpp index e112abb..305bea9 100644 --- a/src/libghost/ghost.cpp +++ b/src/libghost/ghost.cpp @@ -314,7 +314,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) if( Locale == "system" ) { -#ifdef WIN32 +#ifdef _MSC_VER LocaleID = GetUserDefaultLangID( ); #else LocaleID = 1033; diff --git a/src/libghost/libghost.pro b/src/libghost/libghost.pro index 061a21b..8dd6abd 100644 --- a/src/libghost/libghost.pro +++ b/src/libghost/libghost.pro @@ -16,8 +16,7 @@ INCLUDEPATH += .. \ ../../include \ ../../include/mysql LIBS += -L../../src/lib -LIBS += -lbncsutil \ - -lgmp +LIBS += -lbncsutil -lgmp macx { LIBS += -framework CoreFoundation -framework CoreServices diff --git a/src/libghost/packed.cpp b/src/libghost/packed.cpp index cf59a3e..d27220f 100644 --- a/src/libghost/packed.cpp +++ b/src/libghost/packed.cpp @@ -23,7 +23,7 @@ #include "crc32.h" #include "packed.h" -#include +#include // we can't use zlib's uncompress function because it expects a complete compressed buffer // however, we're going to be passing it chunks of incomplete data From 93568c6de362b46e7c103c9c3907cdc2dc78436b Mon Sep 17 00:00:00 2001 From: luqasn Date: Thu, 27 May 2010 22:20:37 +0000 Subject: [PATCH 65/69] ghost.qt: added rcon plugin (no functionality yet) added thread-local logging wrapper fixed bug in CBNET that caused segfault when reconnecting added some more constness to various functions --- ghost.pro | 4 +- src/cli/cli.pro | 10 +- src/cli/main.cpp | 4 +- src/lib.pri | 6 +- src/libghost/bnet.cpp | 51 +-- src/libghost/bnet.h | 35 +- src/libghost/bnetprotocol.h | 26 +- src/libghost/config.cpp | 17 +- src/libghost/config.h | 10 +- src/libghost/game.cpp | 16 +- src/libghost/game_admin.cpp | 12 +- src/libghost/game_base.cpp | 33 +- src/libghost/game_base.h | 58 ++-- src/libghost/gameplayer.cpp | 10 +- src/libghost/gameplayer.h | 14 +- src/libghost/gameprotocol.cpp | 8 +- src/libghost/gameprotocol.h | 16 +- src/libghost/gameslot.h | 18 +- src/libghost/ghost.cpp | 110 +++++- src/libghost/ghost.h | 66 +++- src/libghost/ghost_p.h | 1 - src/libghost/ghostdb.h | 10 +- src/libghost/gpsprotocol.cpp | 18 +- src/libghost/gpsprotocol.h | 18 +- src/libghost/interfaces.h | 83 +++-- src/libghost/libghost.pro | 5 +- src/libghost/map.h | 40 +-- src/libghost/replay.cpp | 8 +- src/libghost/statsdota.cpp | 23 +- src/libghost/statsw3mmd.cpp | 34 +- src/libghost/util.h | 4 +- src/plugins/cmd_builtin/cmd_builtin.pro | 2 +- src/plugins/cmd_builtin/commands.cpp | 13 +- src/plugins/cmd_builtin/commands.h | 34 +- src/plugins/plugin.pri | 4 +- src/plugins/plugins.pro | 10 +- src/plugins/rcon/rcon.cpp | 441 ++++++++++++++++++++++++ src/plugins/rcon/rcon.h | 88 +++++ src/plugins/rcon/rcon.pro | 11 + 39 files changed, 1058 insertions(+), 313 deletions(-) create mode 100644 src/plugins/rcon/rcon.cpp create mode 100644 src/plugins/rcon/rcon.h create mode 100755 src/plugins/rcon/rcon.pro diff --git a/ghost.pro b/ghost.pro index 10c2c71..f3e4d42 100644 --- a/ghost.pro +++ b/ghost.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = bncsutil libghost plugins cli +SUBDIRS = bncsutil libghost cli plugins # set up correct paths libghost.subdir = src/libghost @@ -11,4 +11,4 @@ bncsutil.subdir = src/bncsutil # dependencies libghost.depends = bncsutil cli.depends = libghost -plugins.depends = libghost \ No newline at end of file +plugins.depends = libghost diff --git a/src/cli/cli.pro b/src/cli/cli.pro index 5a1b41b..4b9cb9c 100644 --- a/src/cli/cli.pro +++ b/src/cli/cli.pro @@ -15,8 +15,14 @@ INCLUDEPATH += ../ \ ../libghost # ../zlib/include LIBS += -L../../lib \ - -lghost -lbncsutil + -lghost -lbncsutil -lgmp + +macx { + LIBS += -framework CoreFoundation -framework CoreServices + QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.5.sdk + LIBS += -L/usr/lib -lbz2 -lz +} #HEADERS += ghost.h -DESTDIR = ../../bin \ No newline at end of file +DESTDIR = ../../bin diff --git a/src/cli/main.cpp b/src/cli/main.cpp index df6cabd..60ddec5 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -25,10 +25,10 @@ void SignalCatcher2( int s ) if( gGHost ) { - if( gGHost->m_Exiting ) + if( gGHost->GetExiting( ) ) exit( 1 ); else - gGHost->m_Exiting = true; + gGHost->Exit( ); } else exit( 1 ); diff --git a/src/lib.pri b/src/lib.pri index 4f736a4..cb0f962 100644 --- a/src/lib.pri +++ b/src/lib.pri @@ -1,3 +1,7 @@ CONFIG += staticlib create_prl +macx { + CONFIG += x86_64 x86 + QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.5.sdk +} DESTDIR = ../../lib -TEMPLATE = lib \ No newline at end of file +TEMPLATE = lib diff --git a/src/libghost/bnet.cpp b/src/libghost/bnet.cpp index cbc6f65..09f6ffd 100644 --- a/src/libghost/bnet.cpp +++ b/src/libghost/bnet.cpp @@ -206,6 +206,21 @@ CBNET :: ~CBNET( ) delete *i; } +void CBNET :: ResetSocket( ) +{ + if (m_Socket) + { + m_Socket->abort(); + m_Socket->deleteLater(); + } + m_Socket = new QTcpSocket( ); + + QObject::connect(m_Socket, SIGNAL(connected()), this, SLOT(socketConnected())); + QObject::connect(m_Socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); + QObject::connect(m_Socket, SIGNAL(readyRead()), this, SLOT(socketDataReady())); + QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); +} + void CBNET::socketConnect() { // attempt to connect to battle.net @@ -297,9 +312,8 @@ void CBNET::socketDisconnected() m_Retries = 0; return; } - + ResetSocket( ); QTimer::singleShot(90000, this, SLOT(socketConnect())); - } void CBNET::sendWardenResponse(const QByteArray & response) @@ -321,7 +335,7 @@ void CBNET::socketDataReady() void CBNET::EnqueuePacket(const QByteArray &pkg) { int ticks = getWaitTicks(); - int pkgs = m_OutPackets.empty(); + int pkgs = m_OutPackets.size(); m_OutPackets.enqueue(pkg); @@ -382,7 +396,7 @@ void CBNET::socketError() QTimer::singleShot(90000, this, SLOT(socketConnect())); } -QByteArray CBNET :: GetUniqueName( ) const +const QByteArray &CBNET :: GetUniqueName( ) const { return m_Protocol->GetUniqueName( ); } @@ -1420,7 +1434,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) { QueueChatCommand( m_GHost->GetLanguage( )->BotDisabled( ), User, Whisper ); - m_GHost->m_Enabled = false; + m_GHost->DisableGameCreation( ); } else QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); @@ -1460,8 +1474,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) { QueueChatCommand( m_GHost->GetLanguage( )->BotEnabled( ), User, Whisper ); - m_GHost->m_Enabled = true; - } + m_GHost->EnableGameCreation( ); } else QueueChatCommand( m_GHost->GetLanguage( )->YouDontHaveAccessToThatCommand( ), User, Whisper ); } @@ -1531,7 +1544,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( IsRootAdmin( User ) ) { if( Payload == "nice" ) - m_GHost->m_ExitingNice = true; + m_GHost->ExitNice( ); else if( Payload == "force" ) m_GHost->deleteLater(); else @@ -1694,7 +1707,6 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; - QString FileNoPath = Payload + ".w3z"; if( QFile::exists( File ) ) { @@ -1703,10 +1715,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) else { QueueChatCommand( m_GHost->GetLanguage( )->LoadingSaveGame( File ), User, Whisper ); - m_GHost->m_SaveGame->Load( File, false ); - m_GHost->m_SaveGame->ParseSaveGame( ); - m_GHost->m_SaveGame->SetFileName( File ); - m_GHost->m_SaveGame->SetFileNameNoPath( FileNoPath ); + m_GHost->LoadSavegame( File ); } } else @@ -2120,9 +2129,9 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) if( Command == "version" ) { if( IsAdmin( User ) || IsRootAdmin( User ) ) - QueueChatCommand( m_GHost->GetLanguage( )->VersionAdmin( m_GHost->m_Version ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->VersionAdmin( m_GHost->GetVersion( ) ), User, Whisper ); else - QueueChatCommand( m_GHost->GetLanguage( )->VersionNotAdmin( m_GHost->m_Version ), User, Whisper ); + QueueChatCommand( m_GHost->GetLanguage( )->VersionNotAdmin( m_GHost->GetVersion( ) ), User, Whisper ); } } } @@ -2309,8 +2318,8 @@ void CBNET :: QueueGameRefresh( unsigned char state, const QString &gameName, co state, Util::fromUInt32( MapGameType), map->GetMapGameFlags( ), - m_GHost->m_Reconnect ? FakeMapWidth : *Util::EmptyData16(), - m_GHost->m_Reconnect ? FakeMapHeight : *Util::EmptyData16(), + m_GHost->m_Reconnect ? FakeMapWidth : Util::EmptyData16(), + m_GHost->m_Reconnect ? FakeMapHeight : Util::EmptyData16(), gameName, newHostName, upTime, @@ -2399,14 +2408,14 @@ void CBNET :: UnqueueGameRefreshes( ) UnqueuePackets( CBNETProtocol :: SID_STARTADVEX3 ); } -bool CBNET :: IsAdmin( const QString &name ) +bool CBNET :: IsAdmin( const QString &name ) const { if( m_Admins.contains( name, Qt :: CaseInsensitive ) ) return true; return false; } -bool CBNET :: IsRootAdmin( const QString &name ) +bool CBNET :: IsRootAdmin( const QString &name ) const { if ( m_RootAdmins.contains(name, Qt :: CaseInsensitive ) ) { return true; @@ -2415,7 +2424,7 @@ bool CBNET :: IsRootAdmin( const QString &name ) return false; } -CDBBan *CBNET :: IsBannedName( const QString &name ) +CDBBan *CBNET :: IsBannedName( const QString &name ) const { // todotodo: optimize this - maybe use a map? @@ -2428,7 +2437,7 @@ CDBBan *CBNET :: IsBannedName( const QString &name ) return NULL; } -CDBBan *CBNET :: IsBannedIP( const QString &ip ) +CDBBan *CBNET :: IsBannedIP( const QString &ip ) const { // todotodo: optimize this - maybe use a map? diff --git a/src/libghost/bnet.h b/src/libghost/bnet.h index e142c26..ed9b7c6 100644 --- a/src/libghost/bnet.h +++ b/src/libghost/bnet.h @@ -22,7 +22,6 @@ #define BNET_H #include "includes.h" -#include "interfaces.h" #include #include #include @@ -167,6 +166,8 @@ public slots: QTime m_LastPacketSent; + void ResetSocket(); + public slots: void EnqueuePacket(const QByteArray &pkg); void SendPacket(); @@ -175,20 +176,20 @@ public slots: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAlias, const QString &nBNLSServer, quint16 nBNLSPort, quint32 nBNLSWardenCookie, const QString &nCDKeyROC, const QString &nCDKeyTFT, const QString &nCountryAbbrev, const QString &nCountry, quint32 nLocaleID, const QString &nUserName, const QString &nUserPassword, const QString &nFirstChannel, const QString &nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, unsigned char nWar3Version, const QByteArray &nEXEVersion, const QByteArray &nEXEVersionHash, const QString &nPasswordHashType, const QString &nPVPGNRealmName, quint32 nMaxMessageLength, quint32 nHostCounterID ); virtual ~CBNET( ); - QString GetServer( ) const { return m_Server; } - QString GetServerAlias( ) const { return m_ServerAlias; } + const QString &GetServer( ) const { return m_Server; } + const QString &GetServerAlias( ) const { return m_ServerAlias; } QString GetCDKeyROC( ) const { return m_CDKeyROC; } QString GetCDKeyTFT( ) const { return m_CDKeyTFT; } - QString GetUserName( ) const { return m_UserName; } - QString GetUserPassword( ) const { return m_UserPassword; } - QString GetFirstChannel( ) const { return m_FirstChannel; } - QString GetCurrentChannel( ) const { return m_CurrentChannel; } - QString GetRootAdmin( ) const { return m_RootAdmin; } + const QString &GetUserName( ) const { return m_UserName; } + const QString &GetUserPassword( ) const { return m_UserPassword; } + const QString &GetFirstChannel( ) const { return m_FirstChannel; } + const QString &GetCurrentChannel( ) const { return m_CurrentChannel; } + const QString &GetRootAdmin( ) const { return m_RootAdmin; } char GetCommandTrigger( ) const { return m_CommandTrigger; } - QByteArray GetEXEVersion( ) const { return m_EXEVersion; } - QByteArray GetEXEVersionHash( ) const { return m_EXEVersionHash; } - QString GetPasswordHashType( ) const { return m_PasswordHashType; } - QString GetPVPGNRealmName( ) const { return m_PVPGNRealmName; } + const QByteArray &GetEXEVersion( ) const { return m_EXEVersion; } + const QByteArray &GetEXEVersionHash( ) const { return m_EXEVersionHash; } + const QString &GetPasswordHashType( ) const { return m_PasswordHashType; } + const QString &GetPVPGNRealmName( ) const { return m_PVPGNRealmName; } quint32 GetHostCounterID( ) const { return m_HostCounterID; } bool GetLoggedIn( ) const { return m_LoggedIn; } bool GetInChat( ) const { return m_InChat; } @@ -196,7 +197,7 @@ public slots: bool GetHoldClan( ) const { return m_HoldClan; } bool GetPublicCommands( ) const { return m_PublicCommands; } quint32 GetOutPacketsQueued( ) const { return m_OutPackets.size( ); } - QByteArray GetUniqueName( ) const; + const QByteArray &GetUniqueName( ) const; // processing functions @@ -222,10 +223,10 @@ public slots: // other functions - bool IsAdmin( const QString &name ); - bool IsRootAdmin( const QString &name ); - CDBBan *IsBannedName( const QString &name ); - CDBBan *IsBannedIP( const QString &ip ); + bool IsAdmin( const QString &name ) const; + bool IsRootAdmin( const QString &name ) const; + CDBBan *IsBannedName( const QString &name ) const; + CDBBan *IsBannedIP( const QString &ip ) const; void AddAdmin( const QString &name ); void AddBan( const QString &name, const QString &ip, const QString &gamename, const QString &admin, const QString &reason ); void RemoveAdmin( const QString &name ); diff --git a/src/libghost/bnetprotocol.h b/src/libghost/bnetprotocol.h index 1f4c798..6559bc6 100644 --- a/src/libghost/bnetprotocol.h +++ b/src/libghost/bnetprotocol.h @@ -105,19 +105,19 @@ class CBNETProtocol CBNETProtocol( ); ~CBNETProtocol( ); - QByteArray GetClientToken( ) { return m_ClientToken; } - QByteArray GetLogonType( ) { return m_LogonType; } - QByteArray GetServerToken( ) { return m_ServerToken; } - QByteArray GetMPQFileTime( ) { return m_MPQFileTime; } - QByteArray GetIX86VerFileName( ) { return m_IX86VerFileName; } - QByteArray GetIX86VerFileNameString( ) { return m_IX86VerFileName; } - QByteArray GetValueStringFormula( ) { return m_ValueStringFormula; } - QByteArray GetValueStringFormulaString( ) { return m_ValueStringFormula; } - QByteArray GetKeyState( ) { return m_KeyState; } - QByteArray GetKeyStateDescription( ) { return m_KeyStateDescription; } - QByteArray GetSalt( ) { return m_Salt; } - QByteArray GetServerPublicKey( ) { return m_ServerPublicKey; } - QByteArray GetUniqueName( ) { return m_UniqueName; } + const QByteArray &GetClientToken( ) { return m_ClientToken; } + const QByteArray &GetLogonType( ) { return m_LogonType; } + const QByteArray &GetServerToken( ) { return m_ServerToken; } + const QByteArray &GetMPQFileTime( ) { return m_MPQFileTime; } + const QByteArray &GetIX86VerFileName( ) { return m_IX86VerFileName; } + const QByteArray &GetIX86VerFileNameString( ) { return m_IX86VerFileName; } + const QByteArray &GetValueStringFormula( ) { return m_ValueStringFormula; } + const QByteArray &GetValueStringFormulaString( ) { return m_ValueStringFormula; } + const QByteArray &GetKeyState( ) { return m_KeyState; } + const QByteArray &GetKeyStateDescription( ) { return m_KeyStateDescription; } + const QByteArray &GetSalt( ) { return m_Salt; } + const QByteArray &GetServerPublicKey( ) { return m_ServerPublicKey; } + const QByteArray &GetUniqueName( ) { return m_UniqueName; } // receive functions diff --git a/src/libghost/config.cpp b/src/libghost/config.cpp index fd8f854..9301dd9 100644 --- a/src/libghost/config.cpp +++ b/src/libghost/config.cpp @@ -39,7 +39,7 @@ CConfig :: ~CConfig( ) #include #include -void CConfig :: Read( QString file ) +void CConfig :: Read( const QString &file ) { QFile f(file); @@ -73,28 +73,25 @@ void CConfig :: Read( QString file ) } } -bool CConfig :: Exists( QString key ) +bool CConfig :: Exists( const QString &key ) const { return m_CFG.contains(key); } -int CConfig :: GetInt( QString key, int x ) +int CConfig :: GetInt( const QString &key, int x ) const { - if( m_CFG.find( key ) == m_CFG.end( ) ) + if( !m_CFG.contains( key ) ) return x; else return m_CFG[key].toInt(); } -QString CConfig :: GetString( QString key, QString x ) +QString CConfig :: GetString( const QString &key, const QString &x ) const { - if( m_CFG.find( key ) == m_CFG.end( ) ) - return x; - else - return m_CFG[key]; + return m_CFG.value(key, x); } -void CConfig :: Set( QString key, QString x ) +void CConfig :: Set( const QString &key, const QString &x ) { m_CFG[key] = x; } diff --git a/src/libghost/config.h b/src/libghost/config.h index b34a940..2b4d04d 100644 --- a/src/libghost/config.h +++ b/src/libghost/config.h @@ -34,11 +34,11 @@ class CConfig CConfig( ); ~CConfig( ); - void Read( QString file ); - bool Exists( QString key ); - int GetInt( QString key, int x ); - QString GetString( QString key, QString x ); - void Set( QString key, QString x ); + void Read( const QString &file ); + bool Exists( const QString &key ) const; + int GetInt( const QString &key, int x ) const; + QString GetString( const QString &key, const QString &x ) const; + void Set( const QString &key, const QString &x ); }; #endif diff --git a/src/libghost/game.cpp b/src/libghost/game.cpp index e570f1c..024c935 100644 --- a/src/libghost/game.cpp +++ b/src/libghost/game.cpp @@ -1330,7 +1330,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_GameState = GAME_PRIVATE; m_LastGameName = m_GameName; m_GameName = Payload; - m_HostCounter = m_GHost->m_HostCounter++; + m_HostCounter = GetNewHostCounter( ); m_RefreshError = false; m_RefreshRehosted = true; @@ -1366,7 +1366,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri m_GameState = GAME_PUBLIC; m_LastGameName = m_GameName; m_GameName = Payload; - m_HostCounter = m_GHost->m_HostCounter++; + m_HostCounter = GetNewHostCounter( ); m_RefreshError = false; m_RefreshRehosted = true; @@ -1458,8 +1458,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri QByteArray MapHeight; MapHeight.push_back( (char)0 ); MapHeight.push_back( (char)0 ); - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), - QHostAddress(IP), Port); + m_GHost->SendUdpBroadcast( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, m_HostCounter ), + Port, QHostAddress(IP) ); } else { @@ -1467,8 +1467,8 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) quint32 MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->writeDatagram( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), - QHostAddress(IP), Port); + m_GHost->SendUdpBroadcast( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, Util::fromUInt32( MapGameType), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, m_HostCounter ), + Port, QHostAddress(IP) ); } } } @@ -1724,9 +1724,9 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, QStri if( Command == "version" ) { if( player->GetSpoofed( ) && ( AdminCheck || RootAdminCheck || IsOwner( User ) ) ) - SendChat( player, m_GHost->GetLanguage( )->VersionAdmin( m_GHost->m_Version ) ); + SendChat( player, m_GHost->GetLanguage( )->VersionAdmin( m_GHost->GetVersion( ) ) ); else - SendChat( player, m_GHost->GetLanguage( )->VersionNotAdmin( m_GHost->m_Version ) ); + SendChat( player, m_GHost->GetLanguage( )->VersionNotAdmin( m_GHost->GetVersion( ) ) ); } // diff --git a/src/libghost/game_admin.cpp b/src/libghost/game_admin.cpp index 8b30c33..fbf82e0 100644 --- a/src/libghost/game_admin.cpp +++ b/src/libghost/game_admin.cpp @@ -748,7 +748,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "disable" ) { SendChat( player, m_GHost->GetLanguage( )->BotDisabled( ) ); - m_GHost->m_Enabled = false; + m_GHost->DisableGameCreation( ); } // @@ -783,7 +783,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "enable" ) { SendChat( player, m_GHost->GetLanguage( )->BotEnabled( ) ); - m_GHost->m_Enabled = true; + m_GHost->EnableGameCreation( ); } // @@ -842,7 +842,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, if( Command == "exit" || Command == "quit" ) { if( Payload == "nice" ) - m_GHost->m_ExitingNice = true; + m_GHost->ExitNice( ); else if( Payload == "force" ) deleteLater(); else @@ -954,7 +954,6 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else { QString File = m_GHost->m_SaveGamePath + Payload + ".w3z"; - QString FileNoPath = Payload + ".w3z"; if( QFile::exists( File ) ) { @@ -963,10 +962,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, else { SendChat( player, m_GHost->GetLanguage( )->LoadingSaveGame( File ) ); - m_GHost->m_SaveGame->Load( File, false ); - m_GHost->m_SaveGame->ParseSaveGame( ); - m_GHost->m_SaveGame->SetFileName( File ); - m_GHost->m_SaveGame->SetFileNameNoPath( FileNoPath ); + m_GHost->LoadSavegame( File ); } } else diff --git a/src/libghost/game_base.cpp b/src/libghost/game_base.cpp index 56ffd39..c6d7550 100644 --- a/src/libghost/game_base.cpp +++ b/src/libghost/game_base.cpp @@ -48,6 +48,8 @@ // CBaseGame // +quint32 CBaseGame::m_GlobalHostCounter = 1; + CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ) { m_GHost = nGHost; @@ -151,7 +153,7 @@ CBaseGame :: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint1 m_CreatorServer = nCreatorServer; m_HCLCommandString = m_Map->GetMapDefaultHCL( ); m_RandomSeed = GetTicks( ); - m_HostCounter = m_GHost->m_HostCounter++; + m_HostCounter = GetNewHostCounter( ); m_SyncLimit = m_GHost->m_SyncLimit; m_SyncCounter = 0; m_GameTicks = 0; @@ -315,11 +317,11 @@ CBaseGame :: ~CBaseGame( ) } } -quint32 CBaseGame :: GetSlotsOccupied( ) +quint32 CBaseGame :: GetSlotsOccupied( ) const { quint32 NumSlotsOccupied = 0; - for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: const_iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED ) NumSlotsOccupied++; @@ -328,11 +330,11 @@ quint32 CBaseGame :: GetSlotsOccupied( ) return NumSlotsOccupied; } -quint32 CBaseGame :: GetSlotsOpen( ) +quint32 CBaseGame :: GetSlotsOpen( ) const { quint32 NumSlotsOpen = 0; - for( QList :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) + for( QList :: const_iterator i = m_Slots.begin( ); i != m_Slots.end( ); i++ ) { if( (*i).GetSlotStatus( ) == SLOTSTATUS_OPEN ) NumSlotsOpen++; @@ -341,7 +343,7 @@ quint32 CBaseGame :: GetSlotsOpen( ) return NumSlotsOpen; } -quint32 CBaseGame :: GetNumPlayers( ) +quint32 CBaseGame :: GetNumPlayers( ) const { quint32 NumPlayers = GetNumHumanPlayers( ); @@ -351,7 +353,7 @@ quint32 CBaseGame :: GetNumPlayers( ) return NumPlayers; } -quint32 CBaseGame :: GetNumHumanPlayers( ) +quint32 CBaseGame :: GetNumHumanPlayers( ) const { quint32 NumHumanPlayers = 0; @@ -364,7 +366,7 @@ quint32 CBaseGame :: GetNumHumanPlayers( ) return NumHumanPlayers; } -QString CBaseGame :: GetDescription( ) +QString CBaseGame :: GetDescription( ) const { QString Description = m_GameName + " : " + m_OwnerName + " : " + QString::number( GetNumHumanPlayers( ) ) + "/" + QString::number( m_GameLoading || m_GameLoaded ? m_StartPlayers : m_Slots.size( ) ); @@ -525,8 +527,6 @@ void CBaseGame::EventBroadcastTimeout() // note: LAN broadcasts use an ID of 0, battle.net refreshes use an ID of 1-10, the rest are unused quint32 FixedHostCounter = m_HostCounter & 0x0FFFFFFF; - QString target = m_GHost->m_UDPSocket->property("target").toString(); - QHostAddress hostAddr = target == "" ? QHostAddress::LocalHost : QHostAddress(m_GHost->m_UDPSocket->property("target").toString()); if( m_SaveGame ) { @@ -539,7 +539,7 @@ void CBaseGame::EventBroadcastTimeout() QByteArray MapHeight; MapHeight.push_back( (char)0 ); MapHeight.push_back( (char)0 ); - m_GHost->m_UDPSocket->writeDatagram( + m_GHost->SendUdpBroadcast( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, @@ -556,7 +556,6 @@ void CBaseGame::EventBroadcastTimeout() 12, m_HostPort, FixedHostCounter ), - hostAddr, 6112); } else @@ -565,7 +564,7 @@ void CBaseGame::EventBroadcastTimeout() // note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect) quint32 MapGameType = MAPGAMETYPE_UNKNOWN0; - m_GHost->m_UDPSocket->writeDatagram( + m_GHost->SendUdpBroadcast( m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, @@ -582,7 +581,6 @@ void CBaseGame::EventBroadcastTimeout() 12, m_HostPort, FixedHostCounter ), - hostAddr, 6112 ); } } @@ -593,11 +591,12 @@ void CBaseGame::EventTryAutoRehost() // however, if autohosting is enabled and this game is public and this game is set to autostart, it's probably autohosted // so rehost it using the current autohost game name - QString GameName = m_GHost->m_AutoHostGameName + " #" + QString::number( m_GHost->m_HostCounter ); + m_HostCounter = GetNewHostCounter( ); + QString GameName = m_GHost->m_AutoHostGameName + " #" + QString::number( m_HostCounter ); CONSOLE_Print( "[GAME: " + m_GameName + "] automatically trying to rehost as public game [" + GameName + "] due to refresh failure" ); m_LastGameName = m_GameName; m_GameName = GameName; - m_HostCounter = m_GHost->m_HostCounter++; + m_RefreshError = false; for( QList :: const_iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) @@ -2555,7 +2554,7 @@ void CBaseGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *actio // check for players saving the game and notify everyone - if( !action->GetAction( )->isEmpty( ) && (*action->GetAction( )).at(0) == 6 ) + if( !action->GetAction( ).isEmpty( ) && action->GetAction( ).at(0) == 6 ) { CONSOLE_Print( "[GAME: " + m_GameName + "] player [" + player->GetName( ) + "] is saving the game" ); SendAllChat( m_GHost->GetLanguage( )->PlayerIsSavingTheGame( player->GetName( ) ) ); diff --git a/src/libghost/game_base.h b/src/libghost/game_base.h index 4d456e8..617a3d3 100644 --- a/src/libghost/game_base.h +++ b/src/libghost/game_base.h @@ -144,6 +144,7 @@ public slots: quint32 m_LastActionSentTicks; // GetTicks when the last action packet was sent quint32 m_StartedLaggingTime; // GetTime when the last lag screen started quint32 m_LastPlayerLeaveTicks; // GetTicks when the most recent player left the game + static quint32 m_GlobalHostCounter; // the current host counter (a unique number to identify a game, incremented each time a game is created) double m_MinimumScore; // the minimum allowed score for matchmaking mode double m_MaximumScore; // the maximum allowed score for matchmaking mode bool m_Locked; // if the game owner is the only one allowed to run game commands or not @@ -161,31 +162,36 @@ public slots: bool m_MatchMaking; // if matchmaking mode is enabled bool m_LocalAdminMessages; // if local admin messages should be relayed or not + quint32 GetNewHostCounter( ) { return m_GlobalHostCounter++; } + public: CBaseGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, quint16 nHostPort, unsigned char nGameState, QString nGameName, QString nOwnerName, QString nCreatorName, QString nCreatorServer ); virtual ~CBaseGame( ); - virtual QList GetEnforceSlots( ) { return m_EnforceSlots; } - virtual QList GetEnforcePlayers( ) { return m_EnforcePlayers; } - virtual CSaveGame *GetSaveGame( ) { return m_SaveGame; } - virtual quint16 GetHostPort( ) { return m_HostPort; } - virtual unsigned char GetGameState( ) { return m_GameState; } - virtual unsigned char GetGProxyEmptyActions( ) { return m_GProxyEmptyActions; } - virtual QString GetGameName( ) { return m_GameName; } - virtual QString GetLastGameName( ) { return m_LastGameName; } - virtual QString GetVirtualHostName( ) { return m_VirtualHostName; } - virtual QString GetOwnerName( ) { return m_OwnerName; } - virtual QString GetCreatorName( ) { return m_CreatorName; } - virtual QString GetCreatorServer( ) { return m_CreatorServer; } - virtual quint32 GetHostCounter( ) { return m_HostCounter; } - virtual quint32 GetStartedLaggingTime( ) { return m_StartedLaggingTime; } - virtual quint32 GetAutoStartPlayers( ) { return m_AutoStartPlayers; } - virtual bool GetLocked( ) { return m_Locked; } - virtual bool GetRefreshMessages( ) { return m_RefreshMessages; } - virtual bool GetCountDownStarted( ) { return m_CountDownStarted; } - virtual bool GetGameLoading( ) { return m_GameLoading; } - virtual bool GetGameLoaded( ) { return m_GameLoaded; } - virtual bool GetLagging( ) { return m_Lagging; } + static quint32 GetCurrentHostCounter( ) { return m_GlobalHostCounter; } + + + virtual const QList &GetEnforceSlots( ) { return m_EnforceSlots; } + virtual const QList &GetEnforcePlayers( ) { return m_EnforcePlayers; } + virtual CSaveGame *GetSaveGame( ) const { return m_SaveGame; } + virtual quint16 GetHostPort( ) const { return m_HostPort; } + virtual unsigned char GetGameState( ) const { return m_GameState; } + virtual unsigned char GetGProxyEmptyActions( ) const { return m_GProxyEmptyActions; } + virtual const QString &GetGameName( ) const { return m_GameName; } + virtual const QString &GetLastGameName( ) const { return m_LastGameName; } + virtual const QString &GetVirtualHostName( ) const { return m_VirtualHostName; } + virtual const QString &GetOwnerName( ) const { return m_OwnerName; } + virtual const QString &GetCreatorName( ) const { return m_CreatorName; } + virtual const QString &GetCreatorServer( ) const { return m_CreatorServer; } + virtual quint32 GetHostCounter( ) const { return m_HostCounter; } + virtual quint32 GetStartedLaggingTime( ) const { return m_StartedLaggingTime; } + virtual quint32 GetAutoStartPlayers( ) const { return m_AutoStartPlayers; } + virtual bool GetLocked( ) const { return m_Locked; } + virtual bool GetRefreshMessages( ) const { return m_RefreshMessages; } + virtual bool GetCountDownStarted( ) const { return m_CountDownStarted; } + virtual bool GetGameLoading( ) const { return m_GameLoading; } + virtual bool GetGameLoaded( ) const { return m_GameLoaded; } + virtual bool GetLagging( ) const { return m_Lagging; } virtual void SetEnforceSlots( QList nEnforceSlots ) { m_EnforceSlots = nEnforceSlots; } virtual void SetEnforcePlayers( QList nEnforcePlayers ) { m_EnforcePlayers = nEnforcePlayers; } @@ -194,11 +200,11 @@ public slots: virtual void SetMaximumScore( double nMaximumScore ) { m_MaximumScore = nMaximumScore; } virtual void SetMatchMaking( bool nMatchMaking ) { m_MatchMaking = nMatchMaking; } - virtual quint32 GetSlotsOccupied( ); - virtual quint32 GetSlotsOpen( ); - virtual quint32 GetNumPlayers( ); - virtual quint32 GetNumHumanPlayers( ); - virtual QString GetDescription( ); + virtual quint32 GetSlotsOccupied( ) const; + virtual quint32 GetSlotsOpen( ) const; + virtual quint32 GetNumPlayers( ) const; + virtual quint32 GetNumHumanPlayers( ) const; + virtual QString GetDescription( ) const; quint32 GetSyncCounter() { return m_SyncCounter; } quint32 GetSyncLimit() { return m_SyncLimit; } diff --git a/src/libghost/gameplayer.cpp b/src/libghost/gameplayer.cpp index c38f7f6..58c3775 100644 --- a/src/libghost/gameplayer.cpp +++ b/src/libghost/gameplayer.cpp @@ -98,7 +98,7 @@ void CGamePlayer::EventACKTimeout() DEBUG_Print("EventACKTimeout()"); // GProxy++ acks - Send( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) ); + Send( m_Game->m_GHost->GetGPSProtocol().SEND_GPSS_ACK( m_TotalPacketsReceived ) ); } void CGamePlayer::EventWhoisTimeout() @@ -159,7 +159,7 @@ void CGamePlayer::EventConnectionClosed() deleteLater(); } -QByteArray CPotentialPlayer :: GetExternalIP( ) +QByteArray CPotentialPlayer :: GetExternalIP( ) const { if( m_Socket ) return Util::fromUInt32(m_Socket->peerAddress().toIPv4Address()); @@ -168,7 +168,7 @@ QByteArray CPotentialPlayer :: GetExternalIP( ) return QByteArray( (char*)Zeros, 4 ); } -QString CPotentialPlayer :: GetExternalIPString( ) +QString CPotentialPlayer :: GetExternalIPString( ) const { if( m_Socket ) return m_Socket->peerAddress().toString(); @@ -647,7 +647,7 @@ void CGamePlayer :: ProcessPackets( ) if( m_Game->m_GHost->m_Reconnect ) { m_GProxy = true; - m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_INIT( m_Game->m_GHost->m_ReconnectPort, m_PID, m_GProxyReconnectKey, m_Game->GetGProxyEmptyActions( ) ) ); + m_Socket->write( m_Game->m_GHost->GetGPSProtocol().SEND_GPSS_INIT( m_Game->m_GHost->m_ReconnectPort, m_PID, m_GProxyReconnectKey, m_Game->GetGProxyEmptyActions( ) ) ); CONSOLE_Print( "[GAME: " + m_Game->GetGameName( ) + "] player [" + m_Name + "] is using GProxy++" ); } else @@ -711,7 +711,7 @@ void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPac QObject::connect(m_Socket, SIGNAL(disconnected()), this, SLOT(EventConnectionClosed())); QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(EventConnectionError(QAbstractSocket::SocketError))); - m_Socket->write( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_RECONNECT( m_TotalPacketsReceived ) ); + m_Socket->write( m_Game->m_GHost->GetGPSProtocol().SEND_GPSS_RECONNECT( m_TotalPacketsReceived ) ); quint32 PacketsAlreadyUnqueued = m_TotalPacketsSent - m_GProxyBuffer.size( ); diff --git a/src/libghost/gameplayer.h b/src/libghost/gameplayer.h index f3cfac3..682ac2c 100644 --- a/src/libghost/gameplayer.h +++ b/src/libghost/gameplayer.h @@ -68,13 +68,13 @@ public slots: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket ); virtual ~CPotentialPlayer( ); - virtual QTcpSocket *GetSocket( ) { return m_Socket; } - virtual QByteArray GetExternalIP( ); - virtual QString GetExternalIPString( ); - virtual QQueue GetPackets( ) { return m_Packets; } - virtual bool GetError( ) { return m_Error; } - virtual QString GetErrorString( ) { return m_ErrorString; } - virtual CIncomingJoinPlayer *GetJoinPlayer( ) { return m_IncomingJoinPlayer; } + virtual QTcpSocket *GetSocket( ) const { return m_Socket; } + virtual QByteArray GetExternalIP( ) const; + virtual QString GetExternalIPString( ) const; + virtual const QQueue &GetPackets( ) const { return m_Packets; } + virtual bool GetError( ) const { return m_Error; } + virtual const QString &GetErrorString( ) const { return m_ErrorString; } + virtual CIncomingJoinPlayer *GetJoinPlayer( ) const { return m_IncomingJoinPlayer; } virtual void SetSocket( QTcpSocket *nSocket ) { m_Socket = nSocket; } diff --git a/src/libghost/gameprotocol.cpp b/src/libghost/gameprotocol.cpp index 5b48646..a0f0790 100644 --- a/src/libghost/gameprotocol.cpp +++ b/src/libghost/gameprotocol.cpp @@ -508,8 +508,8 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue CIncomingAction *Action = actions.dequeue( ); subpacket.push_back( Action->GetPID( ) ); - subpacket.append(Util::fromUInt16(Action->GetAction( )->size( ))); - subpacket.append(*Action->GetAction( )); + subpacket.append(Util::fromUInt16(Action->GetAction( ).size( ))); + subpacket.append(Action->GetAction( )); } // calculate crc (we only care about the first 2 bytes though) @@ -892,7 +892,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueueGetPID( ) ); - subpacket.append(Util::fromUInt16(Action->GetAction( )->size( ))); + subpacket.append(Util::fromUInt16(Action->GetAction( ).size( ))); subpacket.append(*Action->GetAction( )); } @@ -972,7 +972,7 @@ QByteArray CGameProtocol :: EncodeSlotInfo( QList &lslots, quint32 ra // CIncomingJoinPlayer // -CIncomingJoinPlayer :: CIncomingJoinPlayer( quint32 nHostCounter, QString nName, QByteArray &nInternalIP ) +CIncomingJoinPlayer :: CIncomingJoinPlayer( quint32 nHostCounter, const QString &nName, const QByteArray &nInternalIP ) { m_HostCounter = nHostCounter; m_Name = nName; diff --git a/src/libghost/gameprotocol.h b/src/libghost/gameprotocol.h index d049fa0..8e32b67 100644 --- a/src/libghost/gameprotocol.h +++ b/src/libghost/gameprotocol.h @@ -165,12 +165,12 @@ class CIncomingJoinPlayer QByteArray m_InternalIP; public: - CIncomingJoinPlayer( quint32 nHostCounter, QString nName, QByteArray &nInternalIP ); + CIncomingJoinPlayer( quint32 nHostCounter, const QString &nName, const QByteArray &nInternalIP ); ~CIncomingJoinPlayer( ); - quint32 GetHostCounter( ) { return m_HostCounter; } - QString GetName( ) { return m_Name; } - QByteArray GetInternalIP( ) { return m_InternalIP; } + quint32 GetHostCounter( ) const { return m_HostCounter; } + const QString &GetName( ) const { return m_Name; } + const QByteArray &GetInternalIP( ) const { return m_InternalIP; } }; // @@ -188,10 +188,10 @@ class CIncomingAction CIncomingAction( unsigned char nPID, QByteArray &nCRC, QByteArray &nAction ); ~CIncomingAction( ); - unsigned char GetPID( ) { return m_PID; } - QByteArray GetCRC( ) { return m_CRC; } - QByteArray *GetAction( ) { return &m_Action; } - quint32 GetLength( ) { return m_Action.size( ) + 3; } + unsigned char GetPID( ) const { return m_PID; } + const QByteArray &GetCRC( ) const { return m_CRC; } + const QByteArray &GetAction( ) const { return m_Action; } + quint32 GetLength( ) const { return m_Action.size( ) + 3; } }; // diff --git a/src/libghost/gameslot.h b/src/libghost/gameslot.h index f4644f9..e2e74c2 100644 --- a/src/libghost/gameslot.h +++ b/src/libghost/gameslot.h @@ -59,15 +59,15 @@ class CGameSlot CGameSlot( unsigned char nPID, unsigned char nDownloadStatus, unsigned char nSlotStatus, unsigned char nComputer, unsigned char nTeam, unsigned char nColour, unsigned char nRace, unsigned char nComputerType = 1, unsigned char nHandicap = 100 ); ~CGameSlot( ); - unsigned char GetPID( ) { return m_PID; } - unsigned char GetDownloadStatus( ) { return m_DownloadStatus; } - unsigned char GetSlotStatus( ) { return m_SlotStatus; } - unsigned char GetComputer( ) { return m_Computer; } - unsigned char GetTeam( ) { return m_Team; } - unsigned char GetColour( ) { return m_Colour; } - unsigned char GetRace( ) { return m_Race; } - unsigned char GetComputerType( ) { return m_ComputerType; } - unsigned char GetHandicap( ) { return m_Handicap; } + unsigned char GetPID( ) const { return m_PID; } + unsigned char GetDownloadStatus( ) const { return m_DownloadStatus; } + unsigned char GetSlotStatus( ) const { return m_SlotStatus; } + unsigned char GetComputer( ) const { return m_Computer; } + unsigned char GetTeam( ) const { return m_Team; } + unsigned char GetColour( ) const { return m_Colour; } + unsigned char GetRace( ) const { return m_Race; } + unsigned char GetComputerType( ) const { return m_ComputerType; } + unsigned char GetHandicap( ) const { return m_Handicap; } void SetPID( unsigned char nPID ) { m_PID = nPID; } void SetDownloadStatus( unsigned char nDownloadStatus ) { m_DownloadStatus = nDownloadStatus; } diff --git a/src/libghost/ghost.cpp b/src/libghost/ghost.cpp index 305bea9..6a29825 100644 --- a/src/libghost/ghost.cpp +++ b/src/libghost/ghost.cpp @@ -52,11 +52,14 @@ #include #include #include +#include // TODOTODO: remove this crappy implementation and replace it with something monotonic :) static bool timerStarted=FALSE; static QTime gBasicTime; +QThreadStorage currentGHost; + quint32 GetTime() { @@ -74,6 +77,9 @@ void CONSOLE_Print( QString message ) { cout << message.toStdString() << endl; + if( currentGHost.hasLocalData( ) ) + currentGHost.localData()->LogInfo( message ); + // logging /*if (!gLogFile.fileName().isEmpty()) @@ -148,11 +154,79 @@ void CGHost :: SetAutoHostMap( CMap *map) m_AutoHostMap = map; } +void CGHost :: ExitNice( ) +{ + m_ExitingNice = true; +} + +void CGHost :: Exit( ) +{ + m_Exiting = true; +} + +void CGHost :: SendUdpBroadcast( const QByteArray &data, const quint16 &port, const QHostAddress& target) +{ + m_UDPSocket->writeDatagram( data, target, port ); +} + +void CGHost :: SendUdpBroadcast( const QByteArray &data, const quint16 &port) +{ + SendUdpBroadcast( data, port, m_BroadcastTarget ); +} + +void CGHost :: SendUdpBroadcast( const QByteArray &data) +{ + SendUdpBroadcast( data, 6112, m_BroadcastTarget ); +} + +void CGHost :: LoadSavegame( const QString &path ) +{ + QFileInfo info( path ); + m_SaveGame->Load( path, false ); + m_SaveGame->ParseSaveGame( ); + m_SaveGame->SetFileName( path ); + m_SaveGame->SetFileNameNoPath( info.fileName( ) ); +} + +void CGHost :: Log( const QString &message, int level ) +{ + // TODO: handle logging level + CONSOLE_Print( message ); +} + +void CGHost :: LogInfo( const QString &message ) +{ + Log( message, 0 ); + for( QList :: const_iterator i = m_LogPlugins.begin( ); i != m_LogPlugins.end( ); i++ ) + { + (*i)->LogInfo( message ); + } +} + +void CGHost :: LogWarning( const QString &message ) +{ + Log( message, 1 ); + for( QList :: const_iterator i = m_LogPlugins.begin( ); i != m_LogPlugins.end( ); i++ ) + { + (*i)->LogWarning( message ); + } +} + +void CGHost :: LogError( const QString &message ) +{ + Log( message, 2 ); + for( QList :: const_iterator i = m_LogPlugins.begin( ); i != m_LogPlugins.end( ); i++ ) + { + (*i)->LogError( message ); + } +} + void CGHost :: EventGameCommand( CBaseGame *game, CGamePlayer *player, const QString &command, const QString &payload ) { - CommandData data( command, payload ); + ICommandProvider::CommandData data( command, payload ); // TODO: what do we do with IsAdmin and IsRootAdmin? - for( QList :: const_iterator i = d_ptr->m_CommandProviders.begin( ); i != d_ptr->m_CommandProviders.end( ); i++ ) + //player->GetSpoofedRealm() + for( QList :: const_iterator i = m_CommandProviders.begin( ); i != m_CommandProviders.end( ); i++ ) { (*i)->OnGameCommand( game, player, data ); } @@ -160,10 +234,10 @@ void CGHost :: EventGameCommand( CBaseGame *game, CGamePlayer *player, const QSt void CGHost :: EventBnetCommand( CBNET *bnet, const QString &user, const QString &command, const QString &payload, bool whisper ) { - CommandData data( command, payload ); + ICommandProvider::CommandData data( command, payload ); data.SetAdmin( bnet->IsAdmin( user ) ); data.SetRootAdmin( bnet->IsRootAdmin( user ) ); - for( QList :: const_iterator i = d_ptr->m_CommandProviders.begin( ); i != d_ptr->m_CommandProviders.end( ); i++ ) + for( QList :: const_iterator i = m_CommandProviders.begin( ); i != m_CommandProviders.end( ); i++ ) { (*i)->OnBNETCommand( bnet, user, whisper, data ); } @@ -173,6 +247,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) : d_ptr(new CGHostPrivate()), m_ConfigFile(configFile) { + currentGHost.setLocalData( this ); foreach( QObject *plugin, QPluginLoader::staticInstances() ) { LoadPlugin( plugin, CFG ); @@ -184,7 +259,13 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) LoadPlugins( pluginsDir, CFG ); m_UDPSocket = new QUdpSocket(this); - m_UDPSocket->setProperty("target", CFG->GetString( "udp_broadcasttarget", QString( ) ) ); + QString broadcastTarget = CFG->GetString( "udp_broadcasttarget", QString( ) ); + if( broadcastTarget.isEmpty( ) ) + m_BroadcastTarget = QHostAddress :: Broadcast; + else + m_BroadcastTarget = QHostAddress( broadcastTarget ); + + //m_UDPSocket->setProperty("target", ); m_UDPSocket->setProperty("dontroute", CFG->GetInt( "udp_dontroute", 0 ) == 0 ? false : true ); m_ReconnectSocket = NULL; m_GPSProtocol = new CGPSProtocol( ); @@ -258,7 +339,6 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) m_ExitingNice = false; m_Enabled = true; m_Version = "17.0"; - m_HostCounter = 1; m_AutoHostMaximumGames = CFG->GetInt( "autohost_maxgames", 0 ); m_AutoHostAutoStartPlayers = CFG->GetInt( "autohost_startplayers", 0 ); m_AutoHostGameName = CFG->GetString( "autohost_gamename", QString( ) ); @@ -491,6 +571,8 @@ void CGHost :: LoadPlugin( QObject *plugin, CConfig *cfg ) return; } + m_Plugins.append( iPlugin ); + iPlugin->PluginLoaded(this, cfg); ICommandProvider *iCmd = qobject_cast( plugin ); @@ -498,11 +580,21 @@ void CGHost :: LoadPlugin( QObject *plugin, CConfig *cfg ) { CONSOLE_Print( "[PLUGIN] Found CommandProvider [" + iCmd->GetName() + "]" ); validPlugin = true; - d_ptr->m_CommandProviders.append( iCmd ); + m_CommandProviders.append( iCmd ); } + + ILogPlugin *iLogger = qobject_cast( plugin ); + if( iLogger ) + { + CONSOLE_Print( "[PLUGIN] Found Log plugin [" + iLogger->GetName() + "]" ); + validPlugin = true; + m_LogPlugins.append( iLogger ); + } + + iPlugin->AllPluginsLoaded( this, m_Plugins ); if( !validPlugin ) - CONSOLE_Print( "[PLUGIN] WARNING: plugin did not contain valid interfaces!" ); + CONSOLE_Print( "[PLUGIN] INFO: plugin did not contain any special interfaces" ); } void CGHost :: LoadPlugins( QDir path, CConfig *cfg ) @@ -783,7 +875,7 @@ void CGHost::EventAutoHost() return; } - QString GameName = m_AutoHostGameName + " #" + QString::number( m_HostCounter ); + QString GameName = m_AutoHostGameName + " #" + QString::number( CBaseGame::GetCurrentHostCounter( ) ); if( GameName.size( ) >= 31 ) { diff --git a/src/libghost/ghost.h b/src/libghost/ghost.h index e5c0127..dff00c5 100644 --- a/src/libghost/ghost.h +++ b/src/libghost/ghost.h @@ -22,12 +22,12 @@ #define GHOST_H #include "includes.h" -#include "interfaces.h" #include #include #include #include +#include // // CGHost @@ -47,6 +47,11 @@ class CMap; class CSaveGame; class CConfig; class CGHostPrivate; +class CGamePlayer; +class IGHostPlugin; +class ICommandProvider; +class ILogPlugin; + QT_FORWARD_DECLARE_CLASS(QDir) QT_FORWARD_DECLARE_CLASS(QUdpSocket) QT_FORWARD_DECLARE_CLASS(QTcpServer) @@ -63,6 +68,39 @@ class CGHost : public QObject CMap *GetAdminMap( ) const; CMap *GetAutoHostMap( ) const; void SetAutoHostMap( CMap *map ); + bool GetExiting( ) const { return m_Exiting; } + bool GetExitingNice( ) const { return m_ExitingNice; } + void ExitNice( ); + void Exit( ); + + bool IsGameCreationEnabled( ) const { return m_Enabled; } + void EnableGameCreation( ) { m_Enabled = true; } + void DisableGameCreation( ) { m_Enabled = false; } + + void SendUdpBroadcast( const QByteArray &data, const quint16 &port, const QHostAddress& target); + void SendUdpBroadcast( const QByteArray &data, const quint16 &port); + void SendUdpBroadcast( const QByteArray &data); + + void LoadSavegame( const QString& path ); + + const CGPSProtocol &GetGPSProtocol( ) { return *m_GPSProtocol; } + + const QString &GetVersion( ) { return m_Version; } + +private: /*** Plugins ***/ + QList m_Plugins; + QList m_CommandProviders; + QList m_LogPlugins; + void LoadPlugins( QDir path, CConfig *cfg ); +public: + void LoadPlugin( QObject *plugin, CConfig *cfg ); + +private: /*** Logging ***/ + void Log( const QString &message, int level ); +public: + void LogInfo( const QString &message ); + void LogWarning( const QString &message ); + void LogError( const QString &message ); // slots for game events public slots: @@ -79,7 +117,9 @@ public slots: CLanguage *m_Language; // language CMap *m_Map; // the currently loaded map CMap *m_AdminMap; // the map to use in the admin game - CMap *m_AutoHostMap; // the map to use when autohosting + CMap *m_AutoHostMap; // the map to use when autohosting + + public slots: void EventIncomingReconnection(); @@ -91,15 +131,21 @@ public slots: void EventAutoHost(); void EventAdminGameDeleted(); void CreateReconnectServer(); + private: - void LoadPlugin( QObject *plugin, CConfig *cfg ); - void LoadPlugins( QDir path, CConfig *cfg ); -public: QTime m_LastAutoHostTime; - QTimer m_CallableUpdateTimer, m_AutoHostTimer; QUdpSocket *m_UDPSocket; // a UDP socket for sending broadcasts and other junk (used with !sendlan) + QHostAddress m_BroadcastTarget; QTcpServer *m_ReconnectSocket; // listening socket for GProxy++ reliable reconnects CGPSProtocol *m_GPSProtocol; + bool m_Exiting; // set to true to force ghost to shutdown next update (used by SignalCatcher) + bool m_ExitingNice; // set to true to force ghost to disconnect from all battle.net connections and wait for all games to finish before shutting down + bool m_Enabled; // set to false to prevent new games from being created + QString m_Version; // GHost++ version QString + QTimer m_CallableUpdateTimer, m_AutoHostTimer; + CSaveGame *m_SaveGame; // the save game to use + +public: CCRC32 *m_CRC; // for calculating CRC's CSHA1 *m_SHA; // for calculating SHA1's QList m_BNETs; // all our battle.net connections (there can be more than one) @@ -108,13 +154,9 @@ public slots: CGHostDB *m_DBLocal; // local database (for temporary data) QList m_Callables; // vector of orphaned callables waiting to die QList m_LocalAddresses; // vector of local IP addresses - CSaveGame *m_SaveGame; // the save game to use QList m_EnforcePlayers; // vector of pids to force players to use in the next game (used with saved games) - bool m_Exiting; // set to true to force ghost to shutdown next update (used by SignalCatcher) - bool m_ExitingNice; // set to true to force ghost to disconnect from all battle.net connections and wait for all games to finish before shutting down - bool m_Enabled; // set to false to prevent new games from being created - QString m_Version; // GHost++ version QString - quint32 m_HostCounter; // the current host counter (a unique number to identify a game, incremented each time a game is created) + + QString m_AutoHostGameName; // the base game name to auto host with QString m_AutoHostOwner; QString m_AutoHostServer; diff --git a/src/libghost/ghost_p.h b/src/libghost/ghost_p.h index e0b093e..ba7b97c 100644 --- a/src/libghost/ghost_p.h +++ b/src/libghost/ghost_p.h @@ -24,7 +24,6 @@ class ICommandProvider; class CGHostPrivate { public: - QList m_CommandProviders; }; #endif diff --git a/src/libghost/ghostdb.h b/src/libghost/ghostdb.h index ed328d8..440b621 100644 --- a/src/libghost/ghostdb.h +++ b/src/libghost/ghostdb.h @@ -189,10 +189,10 @@ class CBaseCallable : public QObject virtual void Init( ); virtual void Close( ); - virtual QString GetError( ) { return m_Error; } - virtual bool GetReady( ) { return m_Ready; } + virtual const QString &GetError( ) const { return m_Error; } + virtual bool GetReady( ) const { return m_Ready; } virtual void SetReady( bool nReady ) { m_Ready = nReady; if (nReady) emit finished(); } - virtual quint32 GetElapsed( ) { return m_Ready ? m_EndTicks - m_StartTicks : 0; } + virtual quint32 GetElapsed( ) const { return m_Ready ? m_EndTicks - m_StartTicks : 0; } }; class CCallableAdminCount : public CBaseCallable @@ -205,8 +205,8 @@ class CCallableAdminCount : public CBaseCallable CCallableAdminCount( QString nServer ) : CBaseCallable( ), m_Server( nServer ), m_Result( 0 ) { } virtual ~CCallableAdminCount( ); - virtual QString GetServer( ) { return m_Server; } - virtual quint32 GetResult( ) { return m_Result; } + virtual const QString &GetServer( ) const { return m_Server; } + virtual quint32 GetResult( ) const { return m_Result; } virtual void SetResult( quint32 nResult ) { m_Result = nResult; } }; diff --git a/src/libghost/gpsprotocol.cpp b/src/libghost/gpsprotocol.cpp index 929ac89..2db14b7 100644 --- a/src/libghost/gpsprotocol.cpp +++ b/src/libghost/gpsprotocol.cpp @@ -42,7 +42,7 @@ CGPSProtocol :: ~CGPSProtocol( ) // SEND FUNCTIONS // //////////////////// -QByteArray CGPSProtocol :: SEND_GPSC_INIT( quint32 version ) +QByteArray CGPSProtocol :: SEND_GPSC_INIT( quint32 version ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -54,7 +54,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_INIT( quint32 version ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, quint32 reconnectKey, quint32 lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, quint32 reconnectKey, quint32 lastPacket ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -68,7 +68,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_RECONNECT( unsigned char PID, quint32 recon return packet; } -QByteArray CGPSProtocol :: SEND_GPSC_ACK( quint32 lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSC_ACK( quint32 lastPacket ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -80,7 +80,7 @@ QByteArray CGPSProtocol :: SEND_GPSC_ACK( quint32 lastPacket ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_INIT( quint16 reconnectPort, unsigned char PID, quint32 reconnectKey, unsigned char numEmptyActions ) +QByteArray CGPSProtocol :: SEND_GPSS_INIT( quint16 reconnectPort, unsigned char PID, quint32 reconnectKey, unsigned char numEmptyActions ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -95,7 +95,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_INIT( quint16 reconnectPort, unsigned char return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( quint32 lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( quint32 lastPacket ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -107,7 +107,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_RECONNECT( quint32 lastPacket ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_ACK( quint32 lastPacket ) +QByteArray CGPSProtocol :: SEND_GPSS_ACK( quint32 lastPacket ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -119,7 +119,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_ACK( quint32 lastPacket ) return packet; } -QByteArray CGPSProtocol :: SEND_GPSS_REJECT( quint32 reason ) +QByteArray CGPSProtocol :: SEND_GPSS_REJECT( quint32 reason ) const { QByteArray packet; packet.push_back( GPS_HEADER_CONSTANT ); @@ -135,7 +135,7 @@ QByteArray CGPSProtocol :: SEND_GPSS_REJECT( quint32 reason ) // OTHER FUNCTIONS // ///////////////////// -bool CGPSProtocol :: AssignLength( QByteArray &content ) +bool CGPSProtocol :: AssignLength( QByteArray &content ) const { // insert the actual length of the content array into bytes 3 and 4 (indices 2 and 3) @@ -152,7 +152,7 @@ bool CGPSProtocol :: AssignLength( QByteArray &content ) return false; } -bool CGPSProtocol :: ValidateLength( QByteArray &content ) +bool CGPSProtocol :: ValidateLength( QByteArray &content ) const { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length diff --git a/src/libghost/gpsprotocol.h b/src/libghost/gpsprotocol.h index 9f4a2dc..8d32512 100644 --- a/src/libghost/gpsprotocol.h +++ b/src/libghost/gpsprotocol.h @@ -45,20 +45,20 @@ class CGPSProtocol // send functions - QByteArray SEND_GPSC_INIT( quint32 version ); - QByteArray SEND_GPSC_RECONNECT( unsigned char PID, quint32 reconnectKey, quint32 lastPacket ); - QByteArray SEND_GPSC_ACK( quint32 lastPacket ); + QByteArray SEND_GPSC_INIT( quint32 version ) const; + QByteArray SEND_GPSC_RECONNECT( unsigned char PID, quint32 reconnectKey, quint32 lastPacket ) const; + QByteArray SEND_GPSC_ACK( quint32 lastPacket ) const; - QByteArray SEND_GPSS_INIT( quint16 reconnectPort, unsigned char PID, quint32 reconnectKey, unsigned char numEmptyActions ); - QByteArray SEND_GPSS_RECONNECT( quint32 lastPacket ); - QByteArray SEND_GPSS_ACK( quint32 lastPacket ); - QByteArray SEND_GPSS_REJECT( quint32 reason ); + QByteArray SEND_GPSS_INIT( quint16 reconnectPort, unsigned char PID, quint32 reconnectKey, unsigned char numEmptyActions ) const; + QByteArray SEND_GPSS_RECONNECT( quint32 lastPacket ) const; + QByteArray SEND_GPSS_ACK( quint32 lastPacket ) const; + QByteArray SEND_GPSS_REJECT( quint32 reason ) const; // other functions private: - bool AssignLength( QByteArray &content ); - bool ValidateLength( QByteArray &content ); + bool AssignLength( QByteArray &content ) const; + bool ValidateLength( QByteArray &content ) const; }; #endif diff --git a/src/libghost/interfaces.h b/src/libghost/interfaces.h index 4fc8729..836e237 100644 --- a/src/libghost/interfaces.h +++ b/src/libghost/interfaces.h @@ -1,6 +1,6 @@ /* - Copyright [2010] [Lucas ROmero] + Copyright [2010] [Lucas Romero] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #include #include #include +#include class CBNET; class CGHost; @@ -32,60 +33,80 @@ class CConfig; class CBaseGame; class CGamePlayer; class CCommandPacket; -class CommandData; +//class CommandData; + + class IGHostPlugin { +protected: + CGHost *m_GHost; public: + virtual ~IGHostPlugin( ) { } virtual QString GetName( ) const = 0; - //virtual bool InitPlugin( CGHost *ghost ) const = 0; - virtual void PluginLoaded( CGHost *ghost, CConfig *cfg ) = 0; + virtual void PluginLoaded( CGHost *ghost, CConfig */*cfg*/ ) { m_GHost = ghost; } + virtual void AllPluginsLoaded( CGHost */*ghost*/, const QList &/*plugins*/ ) { } }; class IPacketHandler : public IGHostPlugin { public: - virtual ~IPacketHandler() {} virtual bool HandlePacket( CCommandPacket* packet, bool wasHandled ) = 0; }; -class ICommandProvider : public IGHostPlugin +class IOutputListener : public IGHostPlugin { -protected: - //QHash actions ) CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - Block.append(Util::fromUInt16(Action->GetAction( )->size( ))); - Block.append(*Action->GetAction( )); + Block.append(Util::fromUInt16(Action->GetAction( ).size( ))); + Block.append(Action->GetAction( )); } // assign length @@ -102,8 +102,8 @@ void CReplay :: AddTimeSlot( quint16 timeIncrement, QQueue ac CIncomingAction *Action = actions.front( ); actions.dequeue( ); Block.push_back( Action->GetPID( ) ); - Block.append(Util::fromUInt16(Action->GetAction( )->size( ))); - Block.append(*Action->GetAction( )); + Block.append(Util::fromUInt16(Action->GetAction( ).size( ))); + Block.append(Action->GetAction( )); } // assign length diff --git a/src/libghost/statsdota.cpp b/src/libghost/statsdota.cpp index 9d154d4..bb30ef0 100644 --- a/src/libghost/statsdota.cpp +++ b/src/libghost/statsdota.cpp @@ -57,7 +57,7 @@ CStatsDOTA :: ~CStatsDOTA( ) bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) { unsigned int i = 0; - QByteArray *ActionData = Action->GetAction( ); + const QByteArray &ActionData = Action->GetAction( ); QByteArray Data; QByteArray Key; QByteArray Value; @@ -68,30 +68,35 @@ bool CStatsDOTA :: ProcessAction( CIncomingAction *Action ) // parsing the actions would be more correct but would be a lot more difficult to write for relatively little gain // so we take the easy route (which isn't always guaranteed to work) and search the data for the sequence "6b 64 72 2e 78 00" and hope it identifies an action - while( (unsigned int)ActionData->size( ) >= i + 6 ) + while( (unsigned int)ActionData.size( ) >= i + 6 ) { - if( (*ActionData).at(i) == 0x6b && (*ActionData).at(i + 1) == 0x64 && (*ActionData).at(i + 2) == 0x72 && (*ActionData).at(i + 3) == 0x2e && (*ActionData).at(i + 4) == 0x78 && (*ActionData).at(i + 5) == 0x00 ) + if( ActionData.at(i) == 0x6b && + ActionData.at(i + 1) == 0x64 && + ActionData.at(i + 2) == 0x72 && + ActionData.at(i + 3) == 0x2e && + ActionData.at(i + 4) == 0x78 && + ActionData.at(i + 5) == 0x00 ) { // we think we've found an action with real time replay data (but we can't be 100% sure) // next we parse out two null terminated strings and a 4 byte integer - if( (unsigned int)ActionData->size( ) >= i + 7 ) + if( (unsigned int)ActionData.size( ) >= i + 7 ) { // the first null terminated QString should either be the strings "Data" or "Global" or a player id in ASCII representation, e.g. "1" or "2" - Data = UTIL_ExtractCString( *ActionData, i + 6 ); + Data = UTIL_ExtractCString( ActionData, i + 6 ); - if( (unsigned int)ActionData->size( ) >= i + 8 + Data.size( ) ) + if( (unsigned int)ActionData.size( ) >= i + 8 + Data.size( ) ) { // the second null terminated QString should be the key - Key = UTIL_ExtractCString( *ActionData, i + 7 + Data.size( ) ); + Key = UTIL_ExtractCString( ActionData, i + 7 + Data.size( ) ); - if( (unsigned int)ActionData->size( ) >= i + 12 + Data.size( ) + Key.size( ) ) + if( (unsigned int)ActionData.size( ) >= i + 12 + Data.size( ) + Key.size( ) ) { // the 4 byte integer should be the value - Value = ActionData->mid(i + 8 + Data.size( ) + Key.size( ), 4 ); + Value = ActionData.mid(i + 8 + Data.size( ) + Key.size( ), 4 ); QString DataString = Data; QString KeyString = Key; quint32 ValueInt = Util::extractUInt32( Value ); diff --git a/src/libghost/statsw3mmd.cpp b/src/libghost/statsw3mmd.cpp index 008fc91..b31533e 100644 --- a/src/libghost/statsw3mmd.cpp +++ b/src/libghost/statsw3mmd.cpp @@ -49,34 +49,34 @@ CStatsW3MMD :: ~CStatsW3MMD( ) bool CStatsW3MMD :: ProcessAction( CIncomingAction *Action ) { unsigned int i = 0; - QByteArray *ActionData = Action->GetAction( ); + const QByteArray &ActionData = Action->GetAction( ); QByteArray MissionKey; QByteArray Key; QByteArray Value; - while( (unsigned int)ActionData->size( ) >= i + 9 ) + while( (unsigned int)ActionData.size( ) >= i + 9 ) { - if( (*ActionData).at(i) == 'k' && - (*ActionData).at(i + 1) == 'M' && - (*ActionData).at(i + 2) == 'M' && - (*ActionData).at(i + 3) == 'D' && - (*ActionData).at(i + 4) == '.' && - (*ActionData).at(i + 5) == 'D' && - (*ActionData).at(i + 6) == 'a' && - (*ActionData).at(i + 7) == 't' && - (*ActionData).at(i + 8) == 0x00 ) + if( ActionData.at(i) == 'k' && + ActionData.at(i + 1) == 'M' && + ActionData.at(i + 2) == 'M' && + ActionData.at(i + 3) == 'D' && + ActionData.at(i + 4) == '.' && + ActionData.at(i + 5) == 'D' && + ActionData.at(i + 6) == 'a' && + ActionData.at(i + 7) == 't' && + ActionData.at(i + 8) == 0x00 ) { - if( (unsigned int)ActionData->size( ) >= i + 10 ) + if( (unsigned int)ActionData.size( ) >= i + 10 ) { - MissionKey = UTIL_ExtractCString( *ActionData, i + 9 ); + MissionKey = UTIL_ExtractCString( ActionData, i + 9 ); - if( (unsigned int)ActionData->size( ) >= i + 11 + MissionKey.size( ) ) + if( (unsigned int)ActionData.size( ) >= i + 11 + MissionKey.size( ) ) { - Key = UTIL_ExtractCString( *ActionData, i + 10 + MissionKey.size( ) ); + Key = UTIL_ExtractCString( ActionData, i + 10 + MissionKey.size( ) ); - if( (unsigned int)ActionData->size( ) >= i + 15 + MissionKey.size( ) + Key.size( ) ) + if( (unsigned int)ActionData.size( ) >= i + 15 + MissionKey.size( ) + Key.size( ) ) { - Value = ActionData->mid(i + 11 + MissionKey.size( ) + Key.size( ), 4 ); + Value = ActionData.mid(i + 11 + MissionKey.size( ) + Key.size( ), 4 ); //quint32 ValueInt = UTIL_QByteArrayToUInt32( Value, false ); // CONSOLE_Print( "[STATSW3MMD] DEBUG: mkey [" + MissionKey + "], key [" + Key + "], value [" + QString::number(ValueInt) + "]" ); diff --git a/src/libghost/util.h b/src/libghost/util.h index 0730209..0aa0d40 100644 --- a/src/libghost/util.h +++ b/src/libghost/util.h @@ -34,8 +34,8 @@ class Util static QByteArray fromUInt16(const quint16 &value); static QByteArray fromUInt32(const quint32 &value); - static const QByteArray *EmptyData16( ) { return &emptyByteArray16; } - static const QByteArray *EmptyData32( ) { return &emptyByteArray32; } + static const QByteArray &EmptyData16( ) { return emptyByteArray16; } + static const QByteArray &EmptyData32( ) { return emptyByteArray32; } static QByteArray reverse(const QByteArray &b); private: diff --git a/src/plugins/cmd_builtin/cmd_builtin.pro b/src/plugins/cmd_builtin/cmd_builtin.pro index 75e0bd5..2c0abd9 100755 --- a/src/plugins/cmd_builtin/cmd_builtin.pro +++ b/src/plugins/cmd_builtin/cmd_builtin.pro @@ -2,7 +2,7 @@ error( Couldn't find plugin.pri! ) } -QT += network sql +QT += network #sql HEADERS = commands.h SOURCES = commands.cpp diff --git a/src/plugins/cmd_builtin/commands.cpp b/src/plugins/cmd_builtin/commands.cpp index b786e92..29a7140 100644 --- a/src/plugins/cmd_builtin/commands.cpp +++ b/src/plugins/cmd_builtin/commands.cpp @@ -16,11 +16,14 @@ #include #include +CCommands :: CCommands() +{ + m_SupportedCommands << "close"; +} + QStringList CCommands :: GetCommands() const { - QStringList bla; - //bla << "bla"; - return bla; + return m_SupportedCommands; } void CCommands :: PluginLoaded( CGHost *ghost, CConfig *cfg ) @@ -40,7 +43,7 @@ QString CCommands :: GetName( ) const void CCommands :: OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ) { - if( *data.GetCommand() == "close" && !data.GetCommand()->isEmpty( ) && m_GHost->GetCurrentGame() ) + if( data.GetCommand() == "close" && !data.GetCommand().isEmpty( ) && m_GHost->GetCurrentGame() ) { if( !m_GHost->GetCurrentGame()->GetLocked( ) ) { @@ -71,4 +74,4 @@ void CCommands :: OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, } } -Q_EXPORT_PLUGIN2(cmd_builtin, CCommands) \ No newline at end of file +Q_EXPORT_PLUGIN2(cmd_builtin, CCommands) diff --git a/src/plugins/cmd_builtin/commands.h b/src/plugins/cmd_builtin/commands.h index 7049f35..5a864cc 100644 --- a/src/plugins/cmd_builtin/commands.h +++ b/src/plugins/cmd_builtin/commands.h @@ -14,10 +14,40 @@ #include "interfaces.h" class CGHost; +class CGameBase; +class CGame; class CommandData; class CGamePlayer; class CBNET; +class CCommand { + public: + virtual int operator()(const QString &payload) = 0; + }; + +class CGameCommand { +protected: + CGHost *m_GHost; +public: + CGameCommand(CGHost *ghost) : m_GHost(ghost) {} + virtual int operator()(CGameBase *game, CGamePlayer *player, const QString &payload); +}; + +class CKickCommand : public CGameCommand +{ +public: + int operator()(const QString &payload) + { + + } +}; + +template + void CallGameCommand(FunctObj f, const QString &payload) + { + f( payload ); + } + class CCommands : public QObject, public ICommandProvider { Q_OBJECT @@ -25,7 +55,9 @@ class CCommands : public QObject, public ICommandProvider Q_INTERFACES(IGHostPlugin) private: CGHost *m_GHost; + QStringList m_SupportedCommands; public: + CCommands(); virtual QString GetName() const; QStringList GetCommands() const; virtual void PluginLoaded( CGHost *ghost, CConfig *cfg ); @@ -33,4 +65,4 @@ class CCommands : public QObject, public ICommandProvider virtual void OnBNETCommand( CBNET *bnet, const QString &user, bool whisper, const CommandData &data ); }; -#endif \ No newline at end of file +#endif diff --git a/src/plugins/plugin.pri b/src/plugins/plugin.pri index 919830f..19fbc07 100644 --- a/src/plugins/plugin.pri +++ b/src/plugins/plugin.pri @@ -5,7 +5,9 @@ CONFIG += plugin debug_and_release #link_prl LIBS += -lghost -lbncsutil -lgmp -L/usr/lib -L../../../lib macx { LIBS += -lz +CONFIG += x86_64 x86 +QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.5.sdk } INCLUDEPATH += ../../libghost -DESTDIR = ../../../bin/plugins \ No newline at end of file +DESTDIR = ../../../bin/plugins diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index f094ddc..677d76e 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -1,10 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = cmd_builtin - -# install -#target.path = $$[QT_INSTALL_EXAMPLES]/tools/plugandpaintplugins -#sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS plugandpaintplugins.pro -#sources.path = $$[QT_INSTALL_EXAMPLES]/tools/plugandpaintplugins -#INSTALLS += target sources - -#symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +SUBDIRS = cmd_builtin rcon \ No newline at end of file diff --git a/src/plugins/rcon/rcon.cpp b/src/plugins/rcon/rcon.cpp new file mode 100644 index 0000000..1afe2ba --- /dev/null +++ b/src/plugins/rcon/rcon.cpp @@ -0,0 +1,441 @@ +/* + * rcon.cpp + * + * Copyright 2008-2010 Lucas Romero + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "ghost.h" +#include "config.h" +#include "bnet.h" +#include "game.h" +#include "language.h" +#include +#include +#include +#include "rcon.h" +#include "config.h" +#include "gameplayer.h" +#include "bnetprotocol.h" +#include "util.h" +#include "game_base.h" +#include "gameprotocol.h" + +CRemoteConsole :: CRemoteConsole( ) +{ + CONSOLE_Print( "[RCON] Remote Console 1.5 loading" ); + m_UDPSocket = new QUdpSocket(this); + connect(m_UDPSocket, SIGNAL(readyRead()), + this, SLOT(readPendingDatagrams())); + // lookup "localhost" for later use + //bool lookup_success = (inet_aton("localhost", &localhost) == 1); +} + +CRemoteConsole :: ~CRemoteConsole( ) +{ + for( QList :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); i++ ) + { + delete *i; + } +} + +QString CRemoteConsole :: GetName() const +{ + return "Remote Console"; +} + +void CRemoteConsole :: PluginLoaded( CGHost *ghost, CConfig *cfg ) +{ + m_GHost = ghost; + QString bindto = cfg->GetString( "rcon_bindto", "255.255.255.255" ); + qint32 port = cfg->GetInt( "rcon_port", 6969 ); + m_Password = cfg->GetString( "rcon_password", "lol" ); + m_Timeout = cfg->GetInt( "rcon_timeout", 10 ); + m_KeepAliveTime = cfg->GetInt( "rcon_keepalivetime", 120 ); + m_KeepAliveInterval = cfg->GetInt( "rcon_keepaliveinterval", 2 ); + m_AnonymousBroadcast = cfg->GetInt( "rcon_anonymousbroadcast", 0 ) == 0 ? false : true; + m_AnonymousAdminGame = cfg->GetInt( "rcon_anonymousadmingame", 0 ) == 0 ? false : true; + + QHostAddress bindAddr( bindto ); + + if( m_Password.isEmpty( ) ) + { + bindAddr = QHostAddress::LocalHost; + CONSOLE_Print("[RCON] WARNING: No rcon_password set in the .cfg file! Only local commands allowed!"); + } + // we are all set, lets create our socket + + + // TODO: bind correctly + if( !m_UDPSocket->bind( bindAddr, port ) ) + { + CONSOLE_Print( "[RCON] ERROR: Could not bind to [" + bindto + "] on port [" + QString :: number( port ) + "]" ); + } + else + { + CONSOLE_Print( "[RCON] Listening at [" + bindto + "] on port [" + QString :: number( port ) + "]" ); + //disabled for now + /*if( m_AnonymousBroadcast ) + CONSOLE_Print( "[RCON] Anonymous broadcasting [enabled]" ); + else + CONSOLE_Print( "[RCON] Anonymous broadcasting [disabled]" ); + if( m_AnonymousAdminGame ) + CONSOLE_Print( "[RCON] Anonymous Admin game [enabled]" ); + else + CONSOLE_Print( "[RCON] Anonymous Admin game [disabled]" );*/ + } +} + +void CRemoteConsole :: readPendingDatagrams() +{ + while (m_UDPSocket->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(m_UDPSocket->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + + m_UDPSocket->readDatagram(datagram.data(), datagram.size(), + &sender, &senderPort); + ProcessPacket( datagram, sender, senderPort ); + // echo + m_UDPSocket->writeDatagram(datagram.data(), sender, senderPort); + } +} + +void CRemoteConsole :: ProcessPacket( const QByteArray &data, const QHostAddress &sender, const quint16 &senderPort ) +{ + QString message( data ); + message = message.trimmed(); + + if (!message.isEmpty()) + { + QString cmd; + QString payload; + QString target; + SplitLine( message, cmd, payload, target ); + + CRemoteConsoleClient *client = NULL; + for( QList :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); i++ ) + { + if( (*i)->GetAddress( ) == sender && (*i)->GetPort() == senderPort ) + { + client = *i; + // update LastReceived time + //client->Pong( ); + break; + } + } + } + + for( QList :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); ) + { + //(*i)->AutoBroadcast( m_GHost->m_CurrentGame, m_GHost->m_AdminGame ); + + /*if( GetTime( ) > (*i)->GetLastReceived( ) + m_KeepAliveTime + m_Timeout && (*i)->IsAuthed( ) ) + { + // user has not responded in time, de-auth him + (*i)->SetAuthed( false ); + (*i)->Send( "[RCON] Your session timed out" ); + CONSOLE_Print("[RCON] User [" + (*i)->GetIPString( ) + "] timed out"); + } + else if( GetTime( ) > (*i)->GetLastReceived( ) + m_KeepAliveTime + && GetTime( ) > (*i)->GetLastPinged( ) + m_KeepAliveInterval ) + { + // user has not sent an command in quite some time, send him a keep-alive packet (containing the word "PING") + (*i)->Ping( ); + } + + if ( !(*i)->IsAuthed( ) && !(*i)->IsBanned( ) ) + { + delete *i; + i = m_KnownClients.erase( i ); + } + else + i++;*/ + } +} + +void CRemoteConsole :: LogInfo( const QString &message ) +{ + Send( message ); +} + +void CRemoteConsole :: LogWarning( const QString &message ) +{ + Send( message ); +} + +void CRemoteConsole :: LogError( const QString &message ) +{ + Send( message ); +} + +/*bool CRemoteConsole :: Update( void *fd ) +{ + if( !m_Socket ) + return true; + sockaddr_in recvAddr; + string recvString; + m_Socket->RecvFrom( (fd_set *)fd, &recvAddr, &recvString); + + if( !recvString.empty( ) ) + { + // erase newline if found + if ( recvString[recvString.size()-1] == '\n' ) + recvString.erase( recvString.size()-1, 1 ); + string cmd, payload, target = ""; + SplitLine( recvString, cmd, payload, target ); + CRemoteConsoleClient *client = NULL; + for( vector :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); i++ ) + { + if( AreEqual( (*i)->GetEndPoint( ), &recvAddr , true) ) + { + client = *i; + // update LastReceived time + client->Pong( ); + break; + } + } + + if( !client ) + { + // client is not known yet + if( recvAddr.sin_addr.s_addr == localhost.s_addr || ( !m_Password.empty( ) && cmd == "rcon_password" && payload == m_Password ) ) + { + // client has authed himself + client = new CRemoteConsoleClient( m_Socket, recvAddr, -1, true ); + client->Send( "[RCON] You are now authed" ); + CONSOLE_Print("[RCON] User [" + client->GetIPString( ) + "] is now authorized"); + m_KnownClients.push_back( client ); + } + else if( cmd == "rcon_broadcast" && payload.empty( ) ) + { + bool authorized = false; + if( !authorized ) + for( vector :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); i++ ) + { + // only respond if IP is already connected and authed as rcon user + if( AreEqual( (*i)->GetEndPoint( ), &recvAddr, false ) && (*i)->IsAuthed( ) ) + { + authorized = true; + break; + } + } + if( authorized || m_AnonymousBroadcast ) + { + if( m_GHost->m_CurrentGame ) + m_GHost->m_CurrentGame->SendGame( m_Socket, recvAddr ); + + if( m_GHost->m_AdminGame && ( authorized || m_AnonymousAdminGame ) ) + m_GHost->m_AdminGame->SendGame( m_Socket, recvAddr ); + } + else + { + // ban client for 5 seconds for not being authorized + client = new CRemoteConsoleClient( m_Socket, recvAddr, 5 , false); + m_KnownClients.push_back( client ); + CONSOLE_Print("[RCON] User [" + client->GetIPString( ) + "] is not allowed to receive broadcasts"); + } + } + else + { + // ban client for 5 seconds for sending an unkown command or the wrong password + client = new CRemoteConsoleClient( m_Socket, recvAddr, 5, false ); + m_KnownClients.push_back( client ); + CONSOLE_Print("[RCON] User [" + client->GetIPString( ) + "] failed to authenticate"); + } + } + else if( client->IsBanned( ) ) + { + // we have seen this user before, but he is banned + CONSOLE_Print("[RCON] Banned user [" + client->GetIPString( ) + "] tried to execute command [" + recvString + "]"); + } + else if( !client->IsAuthed( ) ) + { + // we have seen this user before, but he hasn't provided the right login credentials yet + if( !m_Password.empty( ) && cmd == "rcon_password" && payload == m_Password ) + { + client->Send( "[RCON] You are now authed" ); + CONSOLE_Print("[RCON] User [" + client->GetIPString( ) + "] is now authorized"); + client->SetAuthed( true ); + } + else + { + // ban client for 5 seconds for sending an unkown command or the wrong password + client->Ban( 5 ); + CONSOLE_Print("[RCON] User [" + client->GetIPString( ) + "] failed to authenticate"); + } + } + else if( cmd == "rcon_password" ) + { + // client is already authed and tries to auth again, just tell him he is now authed + client->Send( "[RCON] You are now authed" ); + } + else if( cmd == "rcon_sendlobbychat" ) + { + if ( m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetGameLoading( ) && !m_GHost->m_CurrentGame->GetGameLoaded( ) ) + m_GHost->m_CurrentGame->SendAllChat( payload ); + } + else if( cmd == "rcon_kick" ) + { + if ( m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetGameLoading( ) && !m_GHost->m_CurrentGame->GetGameLoaded( ) ) + { + CGamePlayer *player = m_GHost->m_CurrentGame->GetPlayerFromName( payload, true ); + if( player ) + { + player->SetDeleteMe( true ); + player->SetLeftReason( m_GHost->m_Language->WasKickedByPlayer( "Remote Console" ) ); + player->SetLeftCode( PLAYERLEAVE_LOBBY ); + m_GHost->m_CurrentGame->OpenSlot( m_GHost->m_CurrentGame->GetSIDFromPID( player->GetPID( ) ), false ); + } + } + } + // disabled for now + //else if( cmd == "rcon_gamedetails" ) + //{ + // if( m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetGameLoading( ) && !m_GHost->m_CurrentGame->GetGameLoaded( ) ) + // client->Send( "[RCON] Game details: " + m_GHost->m_CurrentGame->GetGameDetails( ) ); + // else + // client->Send( "[RCON] Game details: no game in lobby" ); + //} + //else + if( !cmd.empty( ) ) + { + // this is a legitimate user, do what he says + ProcessInput( cmd, payload, target, client ); + } + } + + for( vector :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); ) + { + //(*i)->AutoBroadcast( m_GHost->m_CurrentGame, m_GHost->m_AdminGame ); + + if( GetTime( ) > (*i)->GetLastReceived( ) + m_KeepAliveTime + m_Timeout && (*i)->IsAuthed( ) ) + { + // user has not responded in time, de-auth him + (*i)->SetAuthed( false ); + (*i)->Send( "[RCON] Your session timed out" ); + CONSOLE_Print("[RCON] User [" + (*i)->GetIPString( ) + "] timed out"); + } + else if( GetTime( ) > (*i)->GetLastReceived( ) + m_KeepAliveTime + && GetTime( ) > (*i)->GetLastPinged( ) + m_KeepAliveInterval ) + { + // user has not sent an command in quite some time, send him a keep-alive packet (containing the word "PING") + (*i)->Ping( ); + } + + if ( !(*i)->IsAuthed( ) && !(*i)->IsBanned( ) ) + { + delete *i; + i = m_KnownClients.erase( i ); + } + else + i++; + } + + return false; +}*/ + +void CRemoteConsole :: SplitLine( const QString &input, QString &command, QString &payload, QString &target ) +{ + int pos; + QString Message = input; + // has the user specified a specific target the command should be sent to? + // looks for "" at the beginning of the received command, + // sets the target accordingly and strips it from the command + if ( input.indexOf("<") == 0 && (pos=input.indexOf(">")) != -1 ) + { + target = input.mid(1, pos - 1); + Message = input.mid( pos+1 ); + //input.erase(0, pos + 1); + } + // we expect commands not to start with the command trigger because this is a commandsocket, + // we only except commands and therefore know we received one and not some chatting + // this way the user sending the command does not have to have knowledge of the commandtrigger + // set in GHost's config file + + + int PayloadStart = Message.indexOf( " " ); + + if( PayloadStart != -1 ) + { + command = Message.mid( 0, PayloadStart ); + payload = Message.mid( PayloadStart + 1 ); + } + else + command = Message; +} + +/*void CRemoteConsole :: ProcessInput( string cmd, string payload, string target, CRemoteConsoleClient *sender ) +{ + // default server to relay the message to + bool relayed = false; + + // loop through all connections to find the server the command should be issued on + for( vector :: iterator i = m_GHost->m_BNETs.begin( ); i != m_GHost->m_BNETs.end( ); i++ ) + { + // is this the right one or should we just send it to the first in list? + if ( target == (*i)->GetServer( ) || target.empty() ) + { + // don't be so verbose! + //CONSOLE_Print("[RCON] Relaying command [" + cmd + "] with payload [" + payload + "] to server [" + (*i)->GetServer( ) + "]"); + // spoof a whisper from the rootadmin belonging to this connection + string msg = (*i)->GetCommandTrigger( ) + cmd; + if( !payload.empty( ) ) + msg += " " + payload; + CIncomingChatEvent chatCommand( CBNETProtocol::EID_WHISPER, 0, (*i)->GetRootAdmin( ), msg); + (*i)->ProcessChatEvent( &chatCommand ); + relayed = true; + break; + } + } + if (!relayed) + CONSOLE_Print("[RCON] Could not relay cmd [" + cmd + "] with payload [" + payload + "] to server [" + target + "]: server unknown"); +}*/ + +void CRemoteConsole :: Send( const QString &message ) +{ + QByteArray datagram; + QDataStream out( &datagram, QIODevice::WriteOnly ); + out << message; + for( QList :: iterator i = m_KnownClients.begin( ); i != m_KnownClients.end( ); i++ ) + { + // relay message to all unbanned clients + if( !(*i)->IsBanned( ) && (*i)->IsAuthed( ) ) + m_UDPSocket->writeDatagram( datagram, (*i)->GetAddress( ), (*i)->GetPort( ) ); + } +} + +/*bool CRemoteConsole :: AreEqual( const struct sockaddr_in *a, const struct sockaddr_in *b, bool checkports ) +{ + return a->sin_family == b->sin_family && + a->sin_addr.s_addr == b->sin_addr.s_addr && + ( !checkports || a->sin_port == b->sin_port ); +}*/ + +CRemoteConsoleClient :: CRemoteConsoleClient( const CRemoteConsole &rcon, const QHostAddress &address, quint16 port, int banTime, bool authed ) : +m_RCon( rcon ), +m_Address( address ), +m_Port( port ), +m_LastReceived( 0 ), +m_LastPinged( 0 ), +m_Authed( authed ) +{ + Ban( banTime ); +} + +Q_EXPORT_PLUGIN2(cmd_builtin, CRemoteConsole) diff --git a/src/plugins/rcon/rcon.h b/src/plugins/rcon/rcon.h new file mode 100644 index 0000000..e6814f2 --- /dev/null +++ b/src/plugins/rcon/rcon.h @@ -0,0 +1,88 @@ +/* + * commands.h + * ghost + * + * Created by Lucas on 08.05.10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ +#ifndef RCON_H +#define RCON_H + +#include +#include "interfaces.h" +#include +//#include "ghost.h" + +QT_FORWARD_DECLARE_CLASS(QUdpSocket) +class CConfig; +class CGHost; +class CRemoteConsole; + +class CRemoteConsoleClient +{ +public: + CRemoteConsoleClient( const CRemoteConsole &rcon, const QHostAddress &address, quint16 port, qint32 banTime, bool authed ); + + //virtual void Ping( ) { m_LastPinged = 000; } + //virtual void Pong( ) { m_LastReceived = 000; } + + virtual void Ban( int seconds ) { m_BannedUntil = 000 + seconds; } + virtual bool IsBanned( ) const { return false; } + virtual void UnBan( ) { m_BannedUntil = 0; } + + virtual bool IsAuthed( ) const { return m_Authed; } + virtual void SetAuthed( bool authed ) { m_Authed = authed; } + + virtual const time_t &GetLastPinged( ) const { return m_LastPinged; } + virtual const time_t &GetLastReceived( ) const { return m_LastReceived; } + + virtual const QHostAddress &GetAddress( ) const { return m_Address; } + virtual const quint16 &GetPort( ) const { return m_Port; } + //virtual bool hasAddress(const QHostAddress &a, const quint16 &port) { return m_Address == a && m_Port == port; } + //virtual void Send( const QString &message ) { } +private: + const CRemoteConsole &m_RCon; + QHostAddress m_Address; + quint16 m_Port; + time_t m_LastReceived; + time_t m_LastPinged; + time_t m_BannedUntil; + bool m_Authed; +}; + +class CRemoteConsole : public QObject, public ILogPlugin +{ + Q_OBJECT + Q_INTERFACES(IGHostPlugin) + Q_INTERFACES(ILogPlugin) +public: + virtual void LogInfo( const QString &message ); + virtual void LogWarning( const QString &message ); + virtual void LogError( const QString &message ); +private slots: + void readPendingDatagrams(); +public: + CRemoteConsole( ); + virtual ~CRemoteConsole( ); + virtual QString GetName() const; + virtual void Send( const QString &message ); // output a message to all authed clients + virtual void PluginLoaded( CGHost *ghost, CConfig *cfg ); + //virtual void ConsoleOutput( const QString &message ); +private: + CGHost *m_GHost; // our parent + QUdpSocket *m_UDPSocket; // the socket we use to communicate + QString m_Password; // the password users need to authenticate themselves with + bool m_AnonymousBroadcast; // should everyone requesting a LAN broadcast packet be granted their wish? + bool m_AnonymousAdminGame; // should the admin game also be broadcasted to anonymous requesters? + int m_KeepAliveTime; // time that has to pass before we start asking the client if he is still there + int m_KeepAliveInterval; // time to wait between ping packets when asking if client is still there + int m_Timeout; // time in which the client has to repond to our ping(s) + QList m_KnownClients; // all our console clients (includes authed but banned clients) + void Send( const QString &message, CRemoteConsoleClient *client ); // output a message only to a specific client + static void SplitLine( const QString &input, QString &command, QString &payload, QString &target ); // splits a line received by the rcon socket up into pieces + void ProcessPacket( const QByteArray &data, const QHostAddress &sender, const quint16 &senderPort ); + //virtual void ProcessInput( string cmd, string payload, string target, CRemoteConsoleClient *sender ); // does the actual action based on rcon input +}; + +#endif diff --git a/src/plugins/rcon/rcon.pro b/src/plugins/rcon/rcon.pro new file mode 100755 index 0000000..eb6bf17 --- /dev/null +++ b/src/plugins/rcon/rcon.pro @@ -0,0 +1,11 @@ +! include( ../plugin.pri ) { + error( Couldn't find plugin.pri! ) +} + +QT += network #sql + +HEADERS = rcon.h +SOURCES = rcon.cpp +TARGET = rcon + + From ab1bb8830d445afd67e133f6a30c111f08d2bb39 Mon Sep 17 00:00:00 2001 From: luqasn Date: Thu, 27 May 2010 23:47:36 +0000 Subject: [PATCH 66/69] ghost.qt: fixed stack overflow caused by console output --- src/libghost/bnet.cpp | 82 +++++++++++++++++++++--------------------- src/libghost/bnet.h | 2 +- src/libghost/ghost.cpp | 33 +++++++++-------- 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/libghost/bnet.cpp b/src/libghost/bnet.cpp index 09f6ffd..2fb77cc 100644 --- a/src/libghost/bnet.cpp +++ b/src/libghost/bnet.cpp @@ -55,12 +55,8 @@ CBNET :: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAl // todotodo: append path seperator to Warcraft3Path if needed m_Retries = 0; m_GHost = nGHost; - m_Socket = new QTcpSocket( ); - - QObject::connect(m_Socket, SIGNAL(connected()), this, SLOT(socketConnected())); - QObject::connect(m_Socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); - QObject::connect(m_Socket, SIGNAL(readyRead()), this, SLOT(socketDataReady())); - QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); + m_Socket = NULL; + ResetSocket( ); m_CallableUpdateTimer.setInterval(200); m_CallableUpdateTimer.start(); @@ -69,7 +65,7 @@ CBNET :: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAl m_BanListRefreshTimer.setInterval(3600000); m_BanListRefreshTimer.start(); m_NULLTimer.setInterval(60000); - QObject::connect(&m_NULLTimer, SIGNAL(timeout()), this, SLOT(timeout_NULL())); + QObject::connect(&m_NULLTimer, SIGNAL(timeout()), this, SLOT(sendKeepAlivePacket())); QObject::connect(&m_CallableUpdateTimer, SIGNAL(timeout()), this, SLOT(EventCallableUpdateTimeout())); QObject::connect(&m_AdminListUpdateTimer, SIGNAL(timeout()), this, SLOT(EventUpdateAdminList())); @@ -228,45 +224,47 @@ void CBNET::socketConnect() m_FirstConnect = false; CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connecting to server [" + m_Server + "] on port 6112" ); m_GHost->EventBNETConnecting( this ); + // connecting is not blocking anymore when using Qt sockets + m_Socket->connectToHost( m_Server, 6112 ); - if( m_ServerIP.isEmpty( ) ) - m_Socket->connectToHost( m_Server, 6112 ); - else - { - // use cached server IP address since resolving takes time and is blocking - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using cached server IP address " + m_ServerIP ); - m_Socket->connectToHost( m_ServerIP, 6112 ); - } - - if (m_Socket->waitForConnected(15000)) - { - m_ServerIP = m_Socket->peerAddress().toString(); - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] resolved and cached server IP address " + m_ServerIP ); - } - - else - { - // the connection attempt timed out (15 seconds) - - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connect timed out" ); - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); - m_GHost->EventBNETConnectTimedOut( this ); - m_Socket->abort(); - m_Socket->reset(); - m_Socket->deleteLater(); - m_Socket = NULL; - m_LastDisconnectedTime = GetTime( ); - QTimer::singleShot(90000, this, SLOT(socketConnect())); - m_NULLTimer.stop(); - } +// if( m_ServerIP.isEmpty( ) ) +// m_Socket->connectToHost( m_Server, 6112 ); +// else +// { +// // use cached server IP address since resolving takes time and is blocking +// +// CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using cached server IP address " + m_ServerIP ); +// m_Socket->connectToHost( m_ServerIP, 6112 ); +// } +// +// if (m_Socket->waitForConnected(15000)) +// { +// m_ServerIP = m_Socket->peerAddress().toString(); +// CONSOLE_Print( "[BNET: " + m_ServerAlias + "] resolved and cached server IP address " + m_ServerIP ); +// } +// +// else +// { +// // the connection attempt timed out (15 seconds) +// +// CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connect timed out" ); +// CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); +// m_GHost->EventBNETConnectTimedOut( this ); +// m_Socket->abort(); +// m_Socket->reset(); +// m_Socket->deleteLater(); +// m_Socket = NULL; +// m_LastDisconnectedTime = GetTime( ); +// QTimer::singleShot(90000, this, SLOT(socketConnect())); +// m_NULLTimer.stop(); +// } m_LastConnectionAttemptTime = GetTime( ); m_Retries++; } -void CBNET::timeout_NULL() +void CBNET::sendKeepAlivePacket() { m_Socket->write( m_Protocol->SEND_SID_NULL( ) ); } @@ -298,8 +296,8 @@ void CBNET::socketDisconnected() m_BNLSClient = NULL; m_BNCSUtil->Reset( m_UserName, m_UserPassword ); m_Socket->abort(); - m_Socket->deleteLater(); - m_Socket = NULL; + //m_Socket->deleteLater(); + //m_Socket = NULL; m_LastDisconnectedTime = GetTime( ); m_LoggedIn = false; m_InChat = false; @@ -312,7 +310,7 @@ void CBNET::socketDisconnected() m_Retries = 0; return; } - ResetSocket( ); + //ResetSocket( ); QTimer::singleShot(90000, this, SLOT(socketConnect())); } diff --git a/src/libghost/bnet.h b/src/libghost/bnet.h index ed9b7c6..fea75b0 100644 --- a/src/libghost/bnet.h +++ b/src/libghost/bnet.h @@ -79,7 +79,7 @@ public slots: void socketConnect(); void socketError(); void sendWardenResponse(const QByteArray & response); - void timeout_NULL(); + void sendKeepAlivePacket(); void EventCallableUpdateTimeout(); void EventUpdateAdminList(); diff --git a/src/libghost/ghost.cpp b/src/libghost/ghost.cpp index 6a29825..53a5d1e 100644 --- a/src/libghost/ghost.cpp +++ b/src/libghost/ghost.cpp @@ -53,6 +53,7 @@ #include #include #include +#include // TODOTODO: remove this crappy implementation and replace it with something monotonic :) static bool timerStarted=FALSE; @@ -75,8 +76,6 @@ quint32 GetTicks() void CONSOLE_Print( QString message ) { - cout << message.toStdString() << endl; - if( currentGHost.hasLocalData( ) ) currentGHost.localData()->LogInfo( message ); @@ -191,7 +190,7 @@ void CGHost :: LoadSavegame( const QString &path ) void CGHost :: Log( const QString &message, int level ) { // TODO: handle logging level - CONSOLE_Print( message ); + cout << message.toStdString() << endl; } void CGHost :: LogInfo( const QString &message ) @@ -317,22 +316,28 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) QObject::connect(m_DBLocal, SIGNAL(error(QString)), this, SLOT(EventDatabaseError(QString))); QObject::connect(m_DB, SIGNAL(error(QString)), this, SLOT(EventDatabaseError(QString))); - // get a list of local IP addresses - // this list is used elsewhere to determine if a player connecting to the bot is local or not - - CONSOLE_Print( "[GHOST] attempting to find local IP addresses" ); - QString HostName = QHostInfo::localHostName(); CONSOLE_Print( "[GHOST] local hostname is [" + HostName + "]" ); - QHostInfo info = QHostInfo::fromName(HostName); + // get a list of local IP addresses + // this list is used elsewhere to determine if a player connecting to the bot is local or not - for (int i = 0; i < info.addresses().size(); i++) - { - CONSOLE_Print( "[GHOST] local IP address #" + QString::number( i + 1 ) + " is [" + info.addresses().at(i).toString() + "]" ); - m_LocalAddresses.push_back( Util::fromUInt32(info.addresses().at(i).toIPv4Address() ) ); - } + CONSOLE_Print( "[GHOST] attempting to find local IP addresses" ); + + QList ipAddressesList = QNetworkInterface::allAddresses(); + // use non-localhost IPv4 addresses + // TODO: check if address is LAN-address? + for (int i = 0; i < ipAddressesList.size(); ++i) { + if (ipAddressesList.at(i) != QHostAddress::LocalHost && + ipAddressesList.at(i).toIPv4Address()) { + CONSOLE_Print( "[GHOST] local IP address found: " + ipAddressesList.at( i ).toString() ); + m_LocalAddresses.push_back( Util::fromUInt32( ipAddressesList.at( i ).toIPv4Address( ) ) ); + } + } + // if we did not find one, use IPv4 localhost + if (m_LocalAddresses.isEmpty()) + m_LocalAddresses.push_back( Util::fromUInt32( QHostAddress(QHostAddress::LocalHost).toIPv4Address( ) ) ); m_Language = NULL; m_Exiting = false; From e23eff405562aa5c8bfb1060c30d2d946633eaa1 Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 28 May 2010 00:01:27 +0000 Subject: [PATCH 67/69] ghost.qt: changed CBNET to reuse the same socket object when getting disconnected --- src/libghost/bnet.cpp | 18 +++++++++--------- src/libghost/bnet.h | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/libghost/bnet.cpp b/src/libghost/bnet.cpp index 2fb77cc..89ed7f2 100644 --- a/src/libghost/bnet.cpp +++ b/src/libghost/bnet.cpp @@ -64,8 +64,8 @@ CBNET :: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAl m_AdminListUpdateTimer.start(); m_BanListRefreshTimer.setInterval(3600000); m_BanListRefreshTimer.start(); - m_NULLTimer.setInterval(60000); - QObject::connect(&m_NULLTimer, SIGNAL(timeout()), this, SLOT(sendKeepAlivePacket())); + m_KeepAliveTimer.setInterval(60000); + QObject::connect(&m_KeepAliveTimer, SIGNAL(timeout()), this, SLOT(sendKeepAlivePacket())); QObject::connect(&m_CallableUpdateTimer, SIGNAL(timeout()), this, SLOT(EventCallableUpdateTimeout())); QObject::connect(&m_AdminListUpdateTimer, SIGNAL(timeout()), this, SLOT(EventUpdateAdminList())); @@ -140,7 +140,6 @@ CBNET :: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAl m_LastOutPacketSize = 0; m_LastAdminRefreshTime = GetTime( ); m_LastBanRefreshTime = GetTime( ); - m_FirstConnect = true; m_LoggedIn = false; m_InChat = false; m_HoldFriends = nHoldFriends; @@ -219,9 +218,10 @@ void CBNET :: ResetSocket( ) void CBNET::socketConnect() { + if( m_Socket->state() != QAbstractSocket::UnconnectedState) + return; // attempt to connect to battle.net - m_FirstConnect = false; CONSOLE_Print( "[BNET: " + m_ServerAlias + "] connecting to server [" + m_Server + "] on port 6112" ); m_GHost->EventBNETConnecting( this ); // connecting is not blocking anymore when using Qt sockets @@ -277,7 +277,7 @@ void CBNET::socketConnected() m_GHost->EventBNETConnected( this ); m_Socket->write( m_Protocol->SEND_PROTOCOL_INITIALIZE_SELECTOR( ) ); m_Socket->write( m_Protocol->SEND_SID_AUTH_INFO( m_War3Version, m_GHost->m_TFT, m_LocaleID, m_CountryAbbrev, m_Country ) ); - m_NULLTimer.start(); + m_KeepAliveTimer.start(); while( !m_OutPackets.isEmpty( ) ) m_OutPackets.dequeue( ); @@ -301,7 +301,7 @@ void CBNET::socketDisconnected() m_LastDisconnectedTime = GetTime( ); m_LoggedIn = false; m_InChat = false; - m_NULLTimer.stop(); + m_KeepAliveTimer.stop(); if (m_Retries > 6) { @@ -384,12 +384,12 @@ void CBNET::socketError() m_BNLSClient = NULL; m_BNCSUtil->Reset( m_UserName, m_UserPassword ); m_Socket->abort(); - m_Socket->deleteLater(); - m_Socket = NULL; + //m_Socket->deleteLater(); + //m_Socket = NULL; m_LastDisconnectedTime = GetTime( ); m_LoggedIn = false; m_InChat = false; - m_NULLTimer.stop(); + m_KeepAliveTimer.stop(); QTimer::singleShot(90000, this, SLOT(socketConnect())); } diff --git a/src/libghost/bnet.h b/src/libghost/bnet.h index fea75b0..e0fbb6d 100644 --- a/src/libghost/bnet.h +++ b/src/libghost/bnet.h @@ -86,7 +86,7 @@ public slots: void EventRefreshBanList(); private: - QTimer m_NULLTimer; + QTimer m_KeepAliveTimer; QTimer m_CallableUpdateTimer, m_AdminListUpdateTimer, m_BanListRefreshTimer; public: @@ -145,7 +145,6 @@ public slots: quint32 m_LastOutPacketSize; quint32 m_LastAdminRefreshTime; // GetTime when the admin list was last refreshed from the database quint32 m_LastBanRefreshTime; // GetTime when the ban list was last refreshed from the database - bool m_FirstConnect; // if we haven't tried to connect to battle.net yet bool m_LoggedIn; // if we've logged into battle.net or not bool m_InChat; // if we've entered chat or not (but we're not necessarily in a chat channel yet) bool m_HoldFriends; // whether to auto hold friends when creating a game or not From 135fa73155a6806e0111fe063f7d0a8cafca678a Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 28 May 2010 14:32:36 +0000 Subject: [PATCH 68/69] ghost.qt: changed QTcpSocket in gameplayer.h to QAbstractSocket (may switch to a udp-based protocol in the future) fixed QueueChatCommand() bug that prevented CBNET from sending messages if the queue only has 1 item implemented new Queueing mechanism (see CalculateSendWaitTime() in bnet.h) --- src/libghost/bnet.cpp | 80 ++++++++++++++++++++++++++++--------- src/libghost/bnet.h | 9 +++++ src/libghost/game_base.cpp | 1 + src/libghost/gameplayer.cpp | 8 ++-- src/libghost/gameplayer.h | 14 +++---- src/libghost/ghost.cpp | 1 + 6 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/libghost/bnet.cpp b/src/libghost/bnet.cpp index 89ed7f2..7d8c456 100644 --- a/src/libghost/bnet.cpp +++ b/src/libghost/bnet.cpp @@ -58,6 +58,11 @@ CBNET :: CBNET( CGHost *nGHost, const QString &nServer, const QString &nServerAl m_Socket = NULL; ResetSocket( ); + m_SendWindowLength = 10000; + m_SendNoWaitMaxCount = 2; + m_ConnectionTimeout = 10000; + m_ReconnectInterval = 90000; + m_CallableUpdateTimer.setInterval(200); m_CallableUpdateTimer.start(); m_AdminListUpdateTimer.setInterval(60000); @@ -216,6 +221,14 @@ void CBNET :: ResetSocket( ) QObject::connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); } +void CBNET::socketConnectTimeoutCheck() +{ + if( m_Socket->state() == QAbstractSocket::ConnectedState) + return; + CONSOLE_Print("[BNET: " + m_ServerAlias + "] connection attempt to [" + m_Server + "] on port 6112 timed out"); + socketDisconnected(); +} + void CBNET::socketConnect() { if( m_Socket->state() != QAbstractSocket::UnconnectedState) @@ -226,7 +239,7 @@ void CBNET::socketConnect() m_GHost->EventBNETConnecting( this ); // connecting is not blocking anymore when using Qt sockets m_Socket->connectToHost( m_Server, 6112 ); - + QTimer::singleShot(m_ConnectionTimeout, this, SLOT(socketConnectTimeoutCheck())); // if( m_ServerIP.isEmpty( ) ) // m_Socket->connectToHost( m_Server, 6112 ); @@ -266,7 +279,8 @@ void CBNET::socketConnect() void CBNET::sendKeepAlivePacket() { - m_Socket->write( m_Protocol->SEND_SID_NULL( ) ); + if( m_Socket->isOpen() ) + m_Socket->write( m_Protocol->SEND_SID_NULL( ) ); } void CBNET::socketConnected() @@ -290,7 +304,7 @@ void CBNET::socketDisconnected() // the socket was disconnected CONSOLE_Print( "[BNET: " + m_ServerAlias + "] disconnected from battle.net" ); - CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting 90 seconds to reconnect" ); + CONSOLE_Print( "[BNET: " + m_ServerAlias + "] waiting " + QString::number(m_ReconnectInterval/1000) + " seconds to reconnect" ); m_GHost->EventBNETDisconnected( this ); delete m_BNLSClient; m_BNLSClient = NULL; @@ -311,7 +325,7 @@ void CBNET::socketDisconnected() return; } //ResetSocket( ); - QTimer::singleShot(90000, this, SLOT(socketConnect())); + QTimer::singleShot(m_ReconnectInterval, this, SLOT(socketConnect())); } void CBNET::sendWardenResponse(const QByteArray & response) @@ -332,26 +346,35 @@ void CBNET::socketDataReady() void CBNET::EnqueuePacket(const QByteArray &pkg) { - int ticks = getWaitTicks(); - int pkgs = m_OutPackets.size(); +// int ticks = getWaitTicks(); +// int pkgs = m_OutPackets.size(); m_OutPackets.enqueue(pkg); + SendPacket( ); - if (pkgs > 0) - return; - - if (m_LastPacketSent.elapsed() >= ticks) - { - SendPacket(); - return; - } +// if (pkgs > 0) +// return; +// +// if (m_LastPacketSent.elapsed() >= ticks) +// { +// SendPacket(); +// return; +// } +// +// QTimer::singleShot(ticks - m_LastPacketSent.elapsed(), this, SLOT(SendPacket())); +} - QTimer::singleShot(ticks - m_LastPacketSent.elapsed(), this, SLOT(SendPacket())); +quint32 CBNET :: CalculateSendWaitTime(const QQueue &queue, const QList &messageLog) const +{ + if(messageLog.count() <= m_SendNoWaitMaxCount) + return 0; + // TODO: implement something clever, for now just wait 500ms for every packet previously sent + return 1000 * messageLog.count(); } void CBNET::SendPacket() { - if (m_OutPackets.size() == 0) + if( m_OutPackets.empty( ) ) { DEBUG_Print("Nice, empty query... but actually, this shouldn't happen..."); return; @@ -360,13 +383,32 @@ void CBNET::SendPacket() if( m_OutPackets.size( ) > 7 ) CONSOLE_Print( "[BNET: " + m_ServerAlias + "] packet queue warning - there are " + QString::number( m_OutPackets.size( ) ) + " packets waiting to be sent" ); - m_Socket->write( m_OutPackets.front() ); + QTime now = QTime::currentTime(); + while( !m_SentPackages.empty() && m_SentPackages.front().first.msecsTo(now) > m_SendWindowLength ) + m_SentPackages.pop_front(); + + quint32 waitTime = CalculateSendWaitTime(m_OutPackets, m_SentPackages); + if(waitTime > 0) + { + // TODO: this should probably not use a singleShot-timer, we might fire multiple times + QTimer::singleShot(waitTime, this, SLOT(SendPacket())); + return; + } + const QByteArray &data = m_OutPackets.front(); + m_Socket->write( data ); m_LastOutPacketSize = m_OutPackets.front( ).size( ); + + m_SentPackages.append( TimeAndSizePair(QTime::currentTime(), data.size()) ); + m_OutPackets.dequeue( ); m_LastPacketSent.restart(); - if (m_OutPackets.size() > 0) - QTimer::singleShot(getWaitTicks(), this, SLOT(SendPacket())); + // there are still packets left, resend + if( !m_OutPackets.empty() ) + SendPacket( ); + +// if (m_OutPackets.size() > 0) +// QTimer::singleShot(getWaitTicks(), this, SLOT(SendPacket())); } void CBNET::socketError() diff --git a/src/libghost/bnet.h b/src/libghost/bnet.h index e0fbb6d..c3b3118 100644 --- a/src/libghost/bnet.h +++ b/src/libghost/bnet.h @@ -61,6 +61,8 @@ typedef pair PairedBanRemove; typedef pair PairedGPSCheck; typedef pair PairedDPSCheck; +typedef QPair TimeAndSizePair; + // // CBNET // @@ -78,6 +80,7 @@ public slots: void socketDataReady(); void socketConnect(); void socketError(); + void socketConnectTimeoutCheck(); void sendWardenResponse(const QByteArray & response); void sendKeepAlivePacket(); @@ -100,6 +103,11 @@ public slots: QQueue m_Packets; // queue of incoming packets CBNCSUtilInterface *m_BNCSUtil; // the interface to the bncsutil library (used for logging into battle.net) QQueue m_OutPackets; // queue of outgoing packets to be sent (to prevent getting kicked for flooding) + QList m_SentPackages; // list of packets that have been sent (only time and size are saved) + int m_SendNoWaitMaxCount; // send the message instantly if only n messages were sent in the time window + int m_SendWindowLength; // how long the message queue should take into account messages sent earlier (in ms) + int m_ConnectionTimeout; // time in milliseconds until the connection attempt is aborted + int m_ReconnectInterval; // time in milliseconds to wait before reconnecting to bnet QList m_Friends; // vector of friends QList m_Clans; // vector of clan members QList m_PairedAdminCounts; // vector of paired threaded database admin counts in progress @@ -166,6 +174,7 @@ public slots: QTime m_LastPacketSent; void ResetSocket(); + quint32 CalculateSendWaitTime(const QQueue &queue, const QList &messageLog) const; public slots: void EnqueuePacket(const QByteArray &pkg); diff --git a/src/libghost/game_base.cpp b/src/libghost/game_base.cpp index c6d7550..f413b03 100644 --- a/src/libghost/game_base.cpp +++ b/src/libghost/game_base.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include "next_combination.h" diff --git a/src/libghost/gameplayer.cpp b/src/libghost/gameplayer.cpp index 58c3775..6c1b01f 100644 --- a/src/libghost/gameplayer.cpp +++ b/src/libghost/gameplayer.cpp @@ -37,7 +37,7 @@ #include #include -CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket ) +CPotentialPlayer :: CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QAbstractSocket *nSocket ) : QObject(NULL) { m_Protocol = nProtocol; @@ -267,7 +267,7 @@ void CPotentialPlayer :: Send( const QByteArray &data ) // CGamePlayer // #include -CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) +CGamePlayer :: CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QAbstractSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ) : CPotentialPlayer( nProtocol, nGame, nSocket ) { m_PID = nPID; @@ -316,7 +316,7 @@ CGamePlayer :: CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QSt // todotodo: properly copy queued packets to the new player, this just discards them // this isn't a big problem because official Warcraft III clients don't send any packets after the join request until they receive a response - QTcpSocket *s = potential->GetSocket(); + QAbstractSocket *s = potential->GetSocket(); s->disconnect(potential, SLOT(EventConnectionClosed())); s->disconnect(potential, SLOT(EventConnectionError(QAbstractSocket::SocketError))); @@ -702,7 +702,7 @@ void CGamePlayer :: Send( const QByteArray &data ) CPotentialPlayer :: Send( data ); } -void CGamePlayer :: EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPacket ) +void CGamePlayer :: EventGProxyReconnect( QAbstractSocket *NewSocket, quint32 LastPacket ) { m_Socket->deleteLater(); m_Socket = NewSocket; diff --git a/src/libghost/gameplayer.h b/src/libghost/gameplayer.h index 682ac2c..5b5479c 100644 --- a/src/libghost/gameplayer.h +++ b/src/libghost/gameplayer.h @@ -33,7 +33,7 @@ class CBaseGame; // #include -#include +#include class CPotentialPlayer : public QObject @@ -58,17 +58,17 @@ public slots: // note: we permit m_Socket to be NULL in this class to allow for the virtual host player which doesn't really exist // it also allows us to convert CPotentialPlayers to CGamePlayers without the CPotentialPlayer's destructor closing the socket - QTcpSocket *m_Socket; + QAbstractSocket *m_Socket; QQueue m_Packets; bool m_Error; QString m_ErrorString; CIncomingJoinPlayer *m_IncomingJoinPlayer; public: - CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket ); + CPotentialPlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QAbstractSocket *nSocket ); virtual ~CPotentialPlayer( ); - virtual QTcpSocket *GetSocket( ) const { return m_Socket; } + virtual QAbstractSocket *GetSocket( ) const { return m_Socket; } virtual QByteArray GetExternalIP( ) const; virtual QString GetExternalIPString( ) const; virtual const QQueue &GetPackets( ) const { return m_Packets; } @@ -76,7 +76,7 @@ public slots: virtual const QString &GetErrorString( ) const { return m_ErrorString; } virtual CIncomingJoinPlayer *GetJoinPlayer( ) const { return m_IncomingJoinPlayer; } - virtual void SetSocket( QTcpSocket *nSocket ) { m_Socket = nSocket; } + virtual void SetSocket( QAbstractSocket *nSocket ) { m_Socket = nSocket; } // processing functions @@ -162,7 +162,7 @@ public slots: quint32 m_LastGProxyAckTime; public: - CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QTcpSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); + CGamePlayer( CGameProtocol *nProtocol, CBaseGame *nGame, QAbstractSocket *nSocket, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); CGamePlayer( CPotentialPlayer *potential, unsigned char nPID, QString nJoinedRealm, QString nName, QByteArray nInternalIP, bool nReserved ); virtual ~CGamePlayer( ); @@ -249,7 +249,7 @@ public slots: // other functions virtual void Send( const QByteArray &data ); - virtual void EventGProxyReconnect( QTcpSocket *NewSocket, quint32 LastPacket ); + virtual void EventGProxyReconnect( QAbstractSocket *NewSocket, quint32 LastPacket ); }; #endif diff --git a/src/libghost/ghost.cpp b/src/libghost/ghost.cpp index 53a5d1e..6b04698 100644 --- a/src/libghost/ghost.cpp +++ b/src/libghost/ghost.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include From 9928f04699aaf4fd9394a04b1a3b95a4402c4629 Mon Sep 17 00:00:00 2001 From: luqasn Date: Fri, 28 May 2010 15:38:25 +0000 Subject: [PATCH 69/69] ghost.qt: various optimizations, most notably on CGameProtocol::SEND_W3GS_INCOMING_ACTION --- src/libghost/bnet.cpp | 8 ++-- src/libghost/bnetprotocol.cpp | 64 ++++++++++++++-------------- src/libghost/bnetprotocol.h | 48 ++++++++++----------- src/libghost/commandpacket.cpp | 2 +- src/libghost/commandpacket.h | 8 ++-- src/libghost/game_admin.cpp | 8 ++-- src/libghost/game_base.cpp | 4 +- src/libghost/gameprotocol.cpp | 78 +++++++++++++++++----------------- src/libghost/gameprotocol.h | 68 ++++++++++++++--------------- src/libghost/ghost.cpp | 4 +- src/libghost/map.cpp | 12 +++--- src/libghost/map.h | 34 +++++++-------- 12 files changed, 170 insertions(+), 168 deletions(-) diff --git a/src/libghost/bnet.cpp b/src/libghost/bnet.cpp index 7d8c456..d9e1693 100644 --- a/src/libghost/bnet.cpp +++ b/src/libghost/bnet.cpp @@ -1712,7 +1712,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ), User, Whisper ); CConfig MapCFG; MapCFG.Read( Pattern ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); + m_GHost->GetCurrentMap( )->Load( MapCFG, m_GHost->m_MapCFGPath + Pattern ); } else if (Matches == 1) { @@ -1720,7 +1720,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) QueueChatCommand( m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + File ), User, Whisper ); CConfig MapCFG; MapCFG.Read( m_GHost->m_MapCFGPath + File ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); + m_GHost->GetCurrentMap( )->Load( MapCFG, m_GHost->m_MapCFGPath + File ); } else QueueChatCommand( m_GHost->GetLanguage( )->FoundMapConfigs( files.join(", ") ), User, Whisper ); @@ -1801,7 +1801,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + Pattern ); MapCFG.Set( "map_localpath", Pattern ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, Pattern ); + m_GHost->GetCurrentMap( )->Load( MapCFG, Pattern ); } else if( Matches == 1 ) { @@ -1813,7 +1813,7 @@ void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent ) CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + File ); MapCFG.Set( "map_localpath", File ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, File ); + m_GHost->GetCurrentMap( )->Load( MapCFG, File ); } else QueueChatCommand( m_GHost->GetLanguage( )->FoundMaps( files.join(", ") ), User, Whisper ); diff --git a/src/libghost/bnetprotocol.cpp b/src/libghost/bnetprotocol.cpp index 45c4c69..7aeead4 100644 --- a/src/libghost/bnetprotocol.cpp +++ b/src/libghost/bnetprotocol.cpp @@ -37,7 +37,7 @@ CBNETProtocol :: ~CBNETProtocol( ) // RECEIVE FUNCTIONS // /////////////////////// -bool CBNETProtocol :: RECEIVE_SID_NULL( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_NULL( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_NULL" ); // DEBUG_Print( data ); @@ -48,7 +48,7 @@ bool CBNETProtocol :: RECEIVE_SID_NULL( QByteArray data ) return ValidateLength( data ); } -CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) +CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_GETADVLISTEX" ); // DEBUG_Print( data ); @@ -92,7 +92,7 @@ CIncomingGameHost *CBNETProtocol :: RECEIVE_SID_GETADVLISTEX( QByteArray data ) return NULL; } -bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_ENTERCHAT" ); // DEBUG_Print( data ); @@ -110,7 +110,7 @@ bool CBNETProtocol :: RECEIVE_SID_ENTERCHAT( QByteArray data ) return false; } -CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) +CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_CHATEVENT" ); // DEBUG_Print( data ); @@ -159,7 +159,7 @@ CIncomingChatEvent *CBNETProtocol :: RECEIVE_SID_CHATEVENT( QByteArray data ) return NULL; } -bool CBNETProtocol :: RECEIVE_SID_CHECKAD( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_CHECKAD( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_CHECKAD" ); // DEBUG_Print( data ); @@ -170,7 +170,7 @@ bool CBNETProtocol :: RECEIVE_SID_CHECKAD( QByteArray data ) return ValidateLength( data ); } -bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_STARTADVEX3" ); // DEBUG_Print( data ); @@ -190,7 +190,7 @@ bool CBNETProtocol :: RECEIVE_SID_STARTADVEX3( QByteArray data ) return false; } -QByteArray CBNETProtocol :: RECEIVE_SID_PING( QByteArray data ) +QByteArray CBNETProtocol :: RECEIVE_SID_PING( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_PING" ); // DEBUG_Print( data ); @@ -205,7 +205,7 @@ QByteArray CBNETProtocol :: RECEIVE_SID_PING( QByteArray data ) return QByteArray( ); } -bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_LOGONRESPONSE" ); // DEBUG_Print( data ); @@ -225,7 +225,7 @@ bool CBNETProtocol :: RECEIVE_SID_LOGONRESPONSE( QByteArray data ) return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_AUTH_INFO" ); // DEBUG_Print( data ); @@ -252,7 +252,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_INFO( QByteArray data ) return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_AUTH_CHECK" ); // DEBUG_Print( data ); @@ -274,7 +274,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_CHECK( QByteArray data ) return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_AUTH_ACCOUNTLOGON" ); // DEBUG_Print( data ); @@ -301,7 +301,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ) return false; } -bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ) +bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_AUTH_ACCOUNTLOGONPROOF" ); // DEBUG_Print( data ); @@ -321,7 +321,7 @@ bool CBNETProtocol :: RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ) return false; } -QByteArray CBNETProtocol :: RECEIVE_SID_WARDEN( QByteArray data ) +QByteArray CBNETProtocol :: RECEIVE_SID_WARDEN( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_WARDEN" ); // DEBUG_PRINT( data ); @@ -336,7 +336,7 @@ QByteArray CBNETProtocol :: RECEIVE_SID_WARDEN( QByteArray data ) return QByteArray( ); } -QList CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteArray data ) +QList CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_FRIENDSLIST" ); // DEBUG_Print( data ); @@ -386,7 +386,7 @@ QList CBNETProtocol :: RECEIVE_SID_FRIENDSLIST( QByteArra return Friends; } -QList CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteArray data ) +QList CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_CLANMEMBERLIST" ); // DEBUG_Print( data ); @@ -438,7 +438,7 @@ QList CBNETProtocol :: RECEIVE_SID_CLANMEMBERLIST( QByteArr return ClanList; } -CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( QByteArray data ) +CIncomingClanList *CBNETProtocol :: RECEIVE_SID_CLANMEMBERSTATUSCHANGE( const QByteArray &data ) { // DEBUG_Print( "RECEIVED SID_CLANMEMBERSTATUSCHANGE" ); // DEBUG_Print( data ); @@ -510,7 +510,7 @@ QByteArray CBNETProtocol :: SEND_SID_STOPADV( ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_GETADVLISTEX( QString gameName ) +QByteArray CBNETProtocol :: SEND_SID_GETADVLISTEX( const QString &gameName ) { char MapFilter1[] = { 255, 3, 0, 0 }; char MapFilter2[] = { 255, 3, 0, 0 }; @@ -551,7 +551,7 @@ QByteArray CBNETProtocol :: SEND_SID_ENTERCHAT( ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) +QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( const QString &channel ) { char NoCreateJoin[] = { 2, 0, 0, 0 }; char FirstJoin[] = { 1, 0, 0, 0 }; @@ -575,7 +575,7 @@ QByteArray CBNETProtocol :: SEND_SID_JOINCHANNEL( QString channel ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( QString command ) +QByteArray CBNETProtocol :: SEND_SID_CHATCOMMAND( const QString &command ) { QByteArray packet; packet.push_back( BNET_HEADER_CONSTANT ); // BNET header constant @@ -611,16 +611,16 @@ QByteArray CBNETProtocol :: SEND_SID_CHECKAD( ) QByteArray CBNETProtocol :: SEND_SID_STARTADVEX3( unsigned char state, - QByteArray mapGameType, - QByteArray mapFlags, - QByteArray mapWidth, - QByteArray mapHeight, - QString gameName, - QString hostName, + const QByteArray &mapGameType, + const QByteArray &mapFlags, + const QByteArray &mapWidth, + const QByteArray &mapHeight, + const QString &gameName, + const QString &hostName, quint32 upTime, - QString mapPath, - QByteArray mapCRC, - QByteArray mapSHA1, + const QString &mapPath, + const QByteArray &mapCRC, + const QByteArray &mapSHA1, quint32 hostCounter ) { // todotodo: sort out how GameType works, the documentation is horrendous @@ -708,7 +708,7 @@ Observers: (mask 0x00700000) cant be combined return packet; } -QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) +QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( const QString &gameName ) { char ProductID[] = { 0, 0, 0, 0 }; char ProductVersion[] = { 14, 0, 0, 0 }; // Warcraft III is 14 @@ -729,7 +729,7 @@ QByteArray CBNETProtocol :: SEND_SID_NOTIFYJOIN( QString gameName ) return packet; } -QByteArray CBNETProtocol :: SEND_SID_PING( QByteArray pingValue ) +QByteArray CBNETProtocol :: SEND_SID_PING( const QByteArray &pingValue ) { QByteArray packet; @@ -956,7 +956,7 @@ QByteArray CBNETProtocol :: SEND_SID_CLANMEMBERLIST( ) // OTHER FUNCTIONS // ///////////////////// -bool CBNETProtocol :: AssignLength( QByteArray &content ) +bool CBNETProtocol :: AssignLength( QByteArray &content ) const { // insert the actual length of the content array into bytes 3 and 4 (indices 2 and 3) @@ -973,7 +973,7 @@ bool CBNETProtocol :: AssignLength( QByteArray &content ) return false; } -bool CBNETProtocol :: ValidateLength( QByteArray &content ) +bool CBNETProtocol :: ValidateLength( const QByteArray &content ) const { // verify that bytes 3 and 4 (indices 2 and 3) of the content array describe the length diff --git a/src/libghost/bnetprotocol.h b/src/libghost/bnetprotocol.h index 6559bc6..081543c 100644 --- a/src/libghost/bnetprotocol.h +++ b/src/libghost/bnetprotocol.h @@ -121,36 +121,36 @@ class CBNETProtocol // receive functions - bool RECEIVE_SID_NULL( QByteArray data ); - CIncomingGameHost *RECEIVE_SID_GETADVLISTEX( QByteArray data ); - bool RECEIVE_SID_ENTERCHAT( QByteArray data ); - CIncomingChatEvent *RECEIVE_SID_CHATEVENT( QByteArray data ); - bool RECEIVE_SID_CHECKAD( QByteArray data ); - bool RECEIVE_SID_STARTADVEX3( QByteArray data ); - QByteArray RECEIVE_SID_PING( QByteArray data ); - bool RECEIVE_SID_LOGONRESPONSE( QByteArray data ); - bool RECEIVE_SID_AUTH_INFO( QByteArray data ); - bool RECEIVE_SID_AUTH_CHECK( QByteArray data ); - bool RECEIVE_SID_AUTH_ACCOUNTLOGON( QByteArray data ); - bool RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( QByteArray data ); - QByteArray RECEIVE_SID_WARDEN( QByteArray data ); - QList RECEIVE_SID_FRIENDSLIST( QByteArray data ); - QList RECEIVE_SID_CLANMEMBERLIST( QByteArray data ); - CIncomingClanList *RECEIVE_SID_CLANMEMBERSTATUSCHANGE( QByteArray data ); + bool RECEIVE_SID_NULL( const QByteArray &data ); + CIncomingGameHost *RECEIVE_SID_GETADVLISTEX( const QByteArray &data ); + bool RECEIVE_SID_ENTERCHAT( const QByteArray &data ); + CIncomingChatEvent *RECEIVE_SID_CHATEVENT( const QByteArray &data ); + bool RECEIVE_SID_CHECKAD( const QByteArray &data ); + bool RECEIVE_SID_STARTADVEX3( const QByteArray &data ); + QByteArray RECEIVE_SID_PING( const QByteArray &data ); + bool RECEIVE_SID_LOGONRESPONSE( const QByteArray &data ); + bool RECEIVE_SID_AUTH_INFO( const QByteArray &data ); + bool RECEIVE_SID_AUTH_CHECK( const QByteArray &data ); + bool RECEIVE_SID_AUTH_ACCOUNTLOGON( const QByteArray &data ); + bool RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( const QByteArray &data ); + QByteArray RECEIVE_SID_WARDEN( const QByteArray &data ); + QList RECEIVE_SID_FRIENDSLIST( const QByteArray &data ); + QList RECEIVE_SID_CLANMEMBERLIST( const QByteArray &data ); + CIncomingClanList *RECEIVE_SID_CLANMEMBERSTATUSCHANGE( const QByteArray &data ); // send functions QByteArray SEND_PROTOCOL_INITIALIZE_SELECTOR( ); QByteArray SEND_SID_NULL( ); QByteArray SEND_SID_STOPADV( ); - QByteArray SEND_SID_GETADVLISTEX( QString gameName ); + QByteArray SEND_SID_GETADVLISTEX( const QString &gameName ); QByteArray SEND_SID_ENTERCHAT( ); - QByteArray SEND_SID_JOINCHANNEL( QString channel ); - QByteArray SEND_SID_CHATCOMMAND( QString command ); + QByteArray SEND_SID_JOINCHANNEL( const QString &channel ); + QByteArray SEND_SID_CHATCOMMAND( const QString &command ); QByteArray SEND_SID_CHECKAD( ); - QByteArray SEND_SID_STARTADVEX3( unsigned char state, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, QByteArray mapSHA1, quint32 hostCounter ); - QByteArray SEND_SID_NOTIFYJOIN( QString gameName ); - QByteArray SEND_SID_PING( QByteArray pingValue ); + QByteArray SEND_SID_STARTADVEX3( unsigned char state, const QByteArray &mapGameType, const QByteArray &mapFlags, const QByteArray &mapWidth, const QByteArray &mapHeight, const QString &gameName, const QString &hostName, quint32 upTime, const QString &mapPath, const QByteArray &mapCRC, const QByteArray &mapSHA1, quint32 hostCounter ); + QByteArray SEND_SID_NOTIFYJOIN( const QString &gameName ); + QByteArray SEND_SID_PING( const QByteArray &pingValue ); QByteArray SEND_SID_LOGONRESPONSE( QByteArray clientToken, QByteArray serverToken, QByteArray passwordHash, QString accountName ); QByteArray SEND_SID_NETGAMEPORT( quint16 serverPort ); QByteArray SEND_SID_AUTH_INFO( unsigned char ver, bool TFT, quint32 localeID, QString countryAbbrev, QString country ); @@ -164,8 +164,8 @@ class CBNETProtocol // other functions private: - bool AssignLength( QByteArray &content ); - bool ValidateLength( QByteArray &content ); + bool AssignLength( QByteArray &content ) const; + bool ValidateLength( const QByteArray &content ) const; }; // diff --git a/src/libghost/commandpacket.cpp b/src/libghost/commandpacket.cpp index cbecd0e..2d19238 100644 --- a/src/libghost/commandpacket.cpp +++ b/src/libghost/commandpacket.cpp @@ -25,7 +25,7 @@ // CCommandPacket // -CCommandPacket :: CCommandPacket( unsigned char nPacketType, int nID, QByteArray nData ) +CCommandPacket :: CCommandPacket( unsigned char nPacketType, int nID, const QByteArray &nData ) { m_PacketType = nPacketType; m_ID = nID; diff --git a/src/libghost/commandpacket.h b/src/libghost/commandpacket.h index 1c90015..5ec7f95 100644 --- a/src/libghost/commandpacket.h +++ b/src/libghost/commandpacket.h @@ -33,12 +33,12 @@ class CCommandPacket QByteArray m_Data; public: - CCommandPacket( unsigned char nPacketType, int nID, QByteArray nData ); + CCommandPacket( unsigned char nPacketType, int nID, const QByteArray &nData ); ~CCommandPacket( ); - unsigned char GetPacketType( ) { return m_PacketType; } - int GetID( ) { return m_ID; } - QByteArray GetData( ) { return m_Data; } + unsigned char GetPacketType( ) const { return m_PacketType; } + int GetID( ) const { return m_ID; } + const QByteArray &GetData( ) const { return m_Data; } }; #endif diff --git a/src/libghost/game_admin.cpp b/src/libghost/game_admin.cpp index fbf82e0..305c79f 100644 --- a/src/libghost/game_admin.cpp +++ b/src/libghost/game_admin.cpp @@ -919,7 +919,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, SendChat( player, m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + Pattern ) ); CConfig MapCFG; MapCFG.Read( Pattern ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + Pattern ); + m_GHost->GetCurrentMap( )->Load( MapCFG, m_GHost->m_MapCFGPath + Pattern ); } else if (Matches == 1) { @@ -927,7 +927,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, SendChat( player, m_GHost->GetLanguage( )->LoadingConfigFile( m_GHost->m_MapCFGPath + File ) ); CConfig MapCFG; MapCFG.Read( m_GHost->m_MapCFGPath + File ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, m_GHost->m_MapCFGPath + File ); + m_GHost->GetCurrentMap( )->Load( MapCFG, m_GHost->m_MapCFGPath + File ); } else SendChat( player, m_GHost->GetLanguage( )->FoundMapConfigs( files.join(", ") ) ); @@ -1006,7 +1006,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + Pattern ); MapCFG.Set( "map_localpath", Pattern ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, Pattern ); + m_GHost->GetCurrentMap( )->Load( MapCFG, Pattern ); } else if( Matches == 1 ) { @@ -1018,7 +1018,7 @@ bool CAdminGame :: EventPlayerBotCommand( CGamePlayer *player, QString command, CConfig MapCFG; MapCFG.Set( "map_path", "Maps\\Download\\" + File ); MapCFG.Set( "map_localpath", File ); - m_GHost->GetCurrentMap( )->Load( &MapCFG, File ); + m_GHost->GetCurrentMap( )->Load( MapCFG, File ); } else SendChat( player, m_GHost->GetLanguage( )->FoundMaps( files.join(", ") ) ); diff --git a/src/libghost/game_base.cpp b/src/libghost/game_base.cpp index f413b03..6c8677f 100644 --- a/src/libghost/game_base.cpp +++ b/src/libghost/game_base.cpp @@ -2991,9 +2991,9 @@ void CBaseGame :: EventPlayerMapSize( CGamePlayer *player, CIncomingMapSize *map if( m_GHost->m_AllowDownloads != 0 ) { - QByteArray *MapData = m_Map->GetMapData( ); + const QByteArray &MapData = m_Map->GetMapData( ); - if( !MapData->isEmpty( ) ) + if( !MapData.isEmpty( ) ) { if( m_GHost->m_AllowDownloads == 1 || ( m_GHost->m_AllowDownloads == 2 && player->GetDownloadAllowed( ) ) ) { diff --git a/src/libghost/gameprotocol.cpp b/src/libghost/gameprotocol.cpp index a0f0790..8c9a18c 100644 --- a/src/libghost/gameprotocol.cpp +++ b/src/libghost/gameprotocol.cpp @@ -44,7 +44,7 @@ CGameProtocol :: ~CGameProtocol( ) // RECEIVE FUNCTIONS // /////////////////////// -CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) +CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_REQJOIN" ); // DEBUG_Print( data ); @@ -76,7 +76,7 @@ CIncomingJoinPlayer *CGameProtocol :: RECEIVE_W3GS_REQJOIN( QByteArray data ) return NULL; } -quint32 CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_LEAVEGAME" ); // DEBUG_Print( data ); @@ -91,7 +91,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_LEAVEGAME( QByteArray data ) return 0; } -bool CGameProtocol :: RECEIVE_W3GS_GAMELOADED_SELF( QByteArray data ) +bool CGameProtocol :: RECEIVE_W3GS_GAMELOADED_SELF( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_GAMELOADED_SELF" ); // DEBUG_Print( data ); @@ -105,7 +105,7 @@ bool CGameProtocol :: RECEIVE_W3GS_GAMELOADED_SELF( QByteArray data ) return false; } -CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, unsigned char PID ) +CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( const QByteArray & data, unsigned char PID ) { // DEBUG_Print( "RECEIVED W3GS_OUTGOING_ACTION" ); // DEBUG_Print( data ); @@ -125,7 +125,7 @@ CIncomingAction *CGameProtocol :: RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, return NULL; } -quint32 CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_OUTGOING_KEEPALIVE" ); // DEBUG_Print( data ); @@ -141,7 +141,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ) return 0; } -CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data ) +CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_CHAT_TO_HOST" ); // DEBUG_Print( data ); @@ -208,7 +208,7 @@ CIncomingChatPlayer *CGameProtocol :: RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data return NULL; } -bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char war3Version ) +bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( const QByteArray & data, unsigned char war3Version ) { quint32 ProductID = 1462982736; // "W3XP" quint32 Version = war3Version; @@ -237,7 +237,7 @@ bool CGameProtocol :: RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char wa return false; } -CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray /*mapSize*/ ) +CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( const QByteArray & data, const QByteArray & /*mapSize*/ ) { // DEBUG_Print( "RECEIVED W3GS_MAPSIZE" ); // DEBUG_Print( data ); @@ -254,7 +254,7 @@ CIncomingMapSize *CGameProtocol :: RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteA return NULL; } -quint32 CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_MAPPARTOK" ); // DEBUG_Print( data ); @@ -272,7 +272,7 @@ quint32 CGameProtocol :: RECEIVE_W3GS_MAPPARTOK( QByteArray data ) return 0; } -quint32 CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ) +quint32 CGameProtocol :: RECEIVE_W3GS_PONG_TO_HOST( const QByteArray & data ) { // DEBUG_Print( "RECEIVED W3GS_PONG_TO_HOST" ); // DEBUG_Print( data ); @@ -309,7 +309,7 @@ QByteArray CGameProtocol :: SEND_W3GS_PING_FROM_HOST( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFOJOIN( unsigned char PID, const QByteArray &port, const QByteArray &externalIP, QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { char Zeros[] = { 0, 0, 0, 0 }; @@ -357,7 +357,7 @@ QByteArray CGameProtocol :: SEND_W3GS_REJECTJOIN( quint32 reason ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ) +QByteArray CGameProtocol :: SEND_W3GS_PLAYERINFO( unsigned char PID, const QString & name, const QByteArray & externalIP, const QByteArray & internalIP ) { char PlayerJoinCounter[] = { 2, 0, 0, 0 }; char Zeros[] = { 0, 0, 0, 0 }; @@ -443,7 +443,7 @@ QByteArray CGameProtocol :: SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: SEND_W3GS_SLOTINFO( const QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo = EncodeSlotInfo( lslots, randomSeed, layoutStyle, playerSlots ); QByteArray packet; @@ -488,7 +488,7 @@ QByteArray CGameProtocol :: SEND_W3GS_COUNTDOWN_END( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue actions, quint16 sendInterval ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( const QList &actions, quint16 sendInterval ) { QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -503,9 +503,10 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue { QByteArray subpacket; - while( !actions.isEmpty( ) ) + // discarding QQueue qualities because we don't need it here and can take advantage of not copying the data when using const QQueue& + for( QList :: const_iterator i = actions.begin( ); i != actions.end( ); i++ ) { - CIncomingAction *Action = actions.dequeue( ); + CIncomingAction *Action = (*i); subpacket.push_back( Action->GetPID( ) ); subpacket.append(Util::fromUInt16(Action->GetAction( ).size( ))); @@ -529,7 +530,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION( QQueue return packet; } -QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, QString message ) +QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, const QByteArray &toPIDs, unsigned char flag, const QByteArray & flagExtra, const QString & message ) { QByteArray packet; @@ -556,7 +557,7 @@ QByteArray CGameProtocol :: SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QBy return packet; } -QByteArray CGameProtocol :: SEND_W3GS_START_LAG( QList players, bool loadInGame ) +QByteArray CGameProtocol :: SEND_W3GS_START_LAG( const QList &players, bool loadInGame ) { QByteArray packet; @@ -660,7 +661,7 @@ QByteArray CGameProtocol :: SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Ve return packet; } -QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ) +QByteArray CGameProtocol :: SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, const QByteArray & mapGameType, const QByteArray & mapFlags, const QByteArray & mapWidth, const QByteArray & mapHeight, const QString &gameName, const QString &hostName, quint32 upTime, const QString &mapPath, const QByteArray & mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ) { char ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3" char ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP" @@ -783,7 +784,7 @@ QByteArray CGameProtocol :: SEND_W3GS_DECREATEGAME( ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ) +QByteArray CGameProtocol :: SEND_W3GS_MAPCHECK( const QString &mapPath, const QByteArray & mapSize, const QByteArray & mapInfo, const QByteArray & mapCRC, const QByteArray & mapSHA1 ) { char Unknown[] = { 1, 0, 0, 0 }; @@ -829,13 +830,13 @@ QByteArray CGameProtocol :: SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ) return packet; } -QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QByteArray *mapData ) +QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, const QByteArray &mapData ) { char Unknown[] = { 1, 0, 0, 0 }; QByteArray packet; - if( start < (unsigned int)mapData->size( ) ) + if( start < (unsigned int)mapData.size( ) ) { packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant packet.push_back( W3GS_MAPPART ); // W3GS_MAPPART @@ -850,17 +851,17 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c quint32 End = start + 1442; - if( End > (unsigned int)mapData->size( ) ) - End = mapData->size( ); + if( End > (unsigned int)mapData.size( ) ) + End = mapData.size( ); // calculate crc - QByteArray crc32 = Util::fromUInt32( m_GHost->m_CRC->FullCRC( mapData->mid(start, End - start) ) ); + QByteArray crc32 = Util::fromUInt32( m_GHost->m_CRC->FullCRC( mapData.mid(start, End - start) ) ); packet.append(crc32); // map data - packet.append( mapData->mid(start, End - start) ); + packet.append( mapData.mid(start, End - start) ); AssignLength( packet ); } else @@ -871,7 +872,7 @@ QByteArray CGameProtocol :: SEND_W3GS_MAPPART( unsigned char fromPID, unsigned c return packet; } -QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueue actions ) +QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( const QList &actions ) { QByteArray packet; packet.push_back( W3GS_HEADER_CONSTANT ); // W3GS header constant @@ -887,13 +888,14 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueue :: const_iterator i = actions.begin( ); i != actions.end( ); i++ ) { - CIncomingAction *Action = actions.front( ); - actions.dequeue( ); + CIncomingAction *Action = (*i); + subpacket.push_back( Action->GetPID( ) ); subpacket.append(Util::fromUInt16(Action->GetAction( ).size( ))); - subpacket.append(*Action->GetAction( )); + subpacket.append(Action->GetAction( )); } // calculate crc (we only care about the first 2 bytes though) @@ -917,7 +919,7 @@ QByteArray CGameProtocol :: SEND_W3GS_INCOMING_ACTION2( QQueue &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) +QByteArray CGameProtocol :: EncodeSlotInfo( const QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ) { QByteArray SlotInfo; SlotInfo.push_back( (unsigned char)lslots.size( ) ); // number of slots @@ -988,7 +990,7 @@ CIncomingJoinPlayer :: ~CIncomingJoinPlayer( ) // CIncomingAction // -CIncomingAction :: CIncomingAction( unsigned char nPID, QByteArray &nCRC, QByteArray &nAction ) +CIncomingAction :: CIncomingAction( unsigned char nPID, const QByteArray &nCRC, const QByteArray &nAction ) { m_PID = nPID; m_CRC = nCRC; @@ -1004,7 +1006,7 @@ CIncomingAction :: ~CIncomingAction( ) // CIncomingChatPlayer // -CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage ) +CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, const QByteArray &nToPIDs, unsigned char nFlag, const QString &nMessage ) { m_Type = CTH_MESSAGE; m_FromPID = nFromPID; @@ -1013,7 +1015,7 @@ CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray & m_Message = nMessage; } -CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage, QByteArray &nExtraFlags ) +CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, const QByteArray &nToPIDs, unsigned char nFlag, const QString &nMessage, const QByteArray &nExtraFlags ) { m_Type = CTH_MESSAGEEXTRA; m_FromPID = nFromPID; @@ -1023,7 +1025,7 @@ CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray & m_ExtraFlags = nExtraFlags; } -CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ) +CIncomingChatPlayer :: CIncomingChatPlayer( unsigned char nFromPID, const QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ) { if( nFlag == 17 ) m_Type = CTH_TEAMCHANGE; diff --git a/src/libghost/gameprotocol.h b/src/libghost/gameprotocol.h index 8e32b67..b6e1ce1 100644 --- a/src/libghost/gameprotocol.h +++ b/src/libghost/gameprotocol.h @@ -109,48 +109,48 @@ class CGameProtocol // receive functions - CIncomingJoinPlayer *RECEIVE_W3GS_REQJOIN( QByteArray data ); - quint32 RECEIVE_W3GS_LEAVEGAME( QByteArray data ); - bool RECEIVE_W3GS_GAMELOADED_SELF( QByteArray data ); - CIncomingAction *RECEIVE_W3GS_OUTGOING_ACTION( QByteArray data, unsigned char PID ); - quint32 RECEIVE_W3GS_OUTGOING_KEEPALIVE( QByteArray data ); - CIncomingChatPlayer *RECEIVE_W3GS_CHAT_TO_HOST( QByteArray data ); - bool RECEIVE_W3GS_SEARCHGAME( QByteArray data, unsigned char war3Version ); - CIncomingMapSize *RECEIVE_W3GS_MAPSIZE( QByteArray data, QByteArray mapSize ); - quint32 RECEIVE_W3GS_MAPPARTOK( QByteArray data ); - quint32 RECEIVE_W3GS_PONG_TO_HOST( QByteArray data ); + CIncomingJoinPlayer *RECEIVE_W3GS_REQJOIN( const QByteArray &data ); + quint32 RECEIVE_W3GS_LEAVEGAME( const QByteArray &data ); + bool RECEIVE_W3GS_GAMELOADED_SELF( const QByteArray &data ); + CIncomingAction *RECEIVE_W3GS_OUTGOING_ACTION( const QByteArray &data, unsigned char PID ); + quint32 RECEIVE_W3GS_OUTGOING_KEEPALIVE( const QByteArray &data ); + CIncomingChatPlayer *RECEIVE_W3GS_CHAT_TO_HOST( const QByteArray &data ); + bool RECEIVE_W3GS_SEARCHGAME( const QByteArray &data, unsigned char war3Version ); + CIncomingMapSize *RECEIVE_W3GS_MAPSIZE( const QByteArray &data, const QByteArray &mapSize ); + quint32 RECEIVE_W3GS_MAPPARTOK( const QByteArray &data ); + quint32 RECEIVE_W3GS_PONG_TO_HOST( const QByteArray &data ); // send functions QByteArray SEND_W3GS_PING_FROM_HOST( ); - QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, QByteArray port, QByteArray externalIP, QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFOJOIN( unsigned char PID, const QByteArray & port, const QByteArray & externalIP, QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_REJECTJOIN( quint32 reason ); - QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, QString name, QByteArray externalIP, QByteArray internalIP ); + QByteArray SEND_W3GS_PLAYERINFO( unsigned char PID, const QString &name, const QByteArray & externalIP, const QByteArray & internalIP ); QByteArray SEND_W3GS_PLAYERLEAVE_OTHERS( unsigned char PID, quint32 leftCode ); QByteArray SEND_W3GS_GAMELOADED_OTHERS( unsigned char PID ); - QByteArray SEND_W3GS_SLOTINFO( QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + QByteArray SEND_W3GS_SLOTINFO( const QList &lslots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); QByteArray SEND_W3GS_COUNTDOWN_START( ); QByteArray SEND_W3GS_COUNTDOWN_END( ); - QByteArray SEND_W3GS_INCOMING_ACTION( QQueue actions, quint16 sendInterval ); - QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, QByteArray toPIDs, unsigned char flag, QByteArray flagExtra, QString message ); - QByteArray SEND_W3GS_START_LAG( QList players, bool loadInGame = false ); + QByteArray SEND_W3GS_INCOMING_ACTION( const QList &actions, quint16 sendInterval ); + QByteArray SEND_W3GS_CHAT_FROM_HOST( unsigned char fromPID, const QByteArray & toPIDs, unsigned char flag, const QByteArray & flagExtra, const QString & message ); + QByteArray SEND_W3GS_START_LAG( const QList &players, bool loadInGame = false ); QByteArray SEND_W3GS_STOP_LAG( CGamePlayer *player, bool loadInGame = false ); QByteArray SEND_W3GS_SEARCHGAME( bool TFT, unsigned char war3Version ); - QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, QByteArray mapGameType, QByteArray mapFlags, QByteArray mapWidth, QByteArray mapHeight, QString gameName, QString hostName, quint32 upTime, QString mapPath, QByteArray mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ); + QByteArray SEND_W3GS_GAMEINFO( bool TFT, unsigned char war3Version, const QByteArray & mapGameType, const QByteArray & mapFlags, const QByteArray & mapWidth, const QByteArray & mapHeight, const QString & gameName, const QString & hostName, quint32 upTime, const QString & mapPath, const QByteArray & mapCRC, quint32 slotsTotal, quint32 slotsOpen, quint16 port, quint32 hostCounter ); QByteArray SEND_W3GS_CREATEGAME( bool TFT, unsigned char war3Version ); QByteArray SEND_W3GS_REFRESHGAME( quint32 players, quint32 playerSlots ); QByteArray SEND_W3GS_DECREATEGAME( ); - QByteArray SEND_W3GS_MAPCHECK( QString mapPath, QByteArray mapSize, QByteArray mapInfo, QByteArray mapCRC, QByteArray mapSHA1 ); + QByteArray SEND_W3GS_MAPCHECK( const QString & mapPath, const QByteArray & mapSize, const QByteArray & mapInfo, const QByteArray & mapCRC, const QByteArray & mapSHA1 ); QByteArray SEND_W3GS_STARTDOWNLOAD( unsigned char fromPID ); - QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, QByteArray *mapData ); - QByteArray SEND_W3GS_INCOMING_ACTION2( QQueue actions ); + QByteArray SEND_W3GS_MAPPART( unsigned char fromPID, unsigned char toPID, quint32 start, const QByteArray &mapData ); + QByteArray SEND_W3GS_INCOMING_ACTION2( const QList &actions ); // other functions private: - bool AssignLength( QByteArray &content ); - bool ValidateLength( QByteArray &content ); - QByteArray EncodeSlotInfo( QList &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); + bool AssignLength( QByteArray &content ) const; + bool ValidateLength( const QByteArray &content ) const; + QByteArray EncodeSlotInfo( const QList &slots, quint32 randomSeed, unsigned char layoutStyle, unsigned char playerSlots ); }; // @@ -185,7 +185,7 @@ class CIncomingAction QByteArray m_Action; public: - CIncomingAction( unsigned char nPID, QByteArray &nCRC, QByteArray &nAction ); + CIncomingAction( unsigned char nPID, const QByteArray &nCRC, const QByteArray &nAction ); ~CIncomingAction( ); unsigned char GetPID( ) const { return m_PID; } @@ -221,18 +221,18 @@ class CIncomingChatPlayer QByteArray m_ExtraFlags; public: - CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage ); - CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, QString nMessage, QByteArray &nExtraFlags ); - CIncomingChatPlayer( unsigned char nFromPID, QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ); + CIncomingChatPlayer( unsigned char nFromPID, const QByteArray &nToPIDs, unsigned char nFlag, const QString &nMessage ); + CIncomingChatPlayer( unsigned char nFromPID, const QByteArray &nToPIDs, unsigned char nFlag, const QString &nMessage, const QByteArray &nExtraFlags ); + CIncomingChatPlayer( unsigned char nFromPID, const QByteArray &nToPIDs, unsigned char nFlag, unsigned char nByte ); ~CIncomingChatPlayer( ); - ChatToHostType GetType( ) { return m_Type; } - unsigned char GetFromPID( ) { return m_FromPID; } - QByteArray GetToPIDs( ) { return m_ToPIDs; } - unsigned char GetFlag( ) { return m_Flag; } - QString GetMessage( ) { return m_Message; } - unsigned char GetByte( ) { return m_Byte; } - QByteArray GetExtraFlags( ) { return m_ExtraFlags; } + ChatToHostType GetType( ) const { return m_Type; } + unsigned char GetFromPID( ) const { return m_FromPID; } + const QByteArray &GetToPIDs( ) const { return m_ToPIDs; } + unsigned char GetFlag( ) const { return m_Flag; } + const QString &GetMessage( ) const { return m_Message; } + unsigned char GetByte( ) const { return m_Byte; } + const QByteArray &GetExtraFlags( ) const { return m_ExtraFlags; } }; class CIncomingMapSize diff --git a/src/libghost/ghost.cpp b/src/libghost/ghost.cpp index 6b04698..34b6ccf 100644 --- a/src/libghost/ghost.cpp +++ b/src/libghost/ghost.cpp @@ -495,7 +495,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CConfig MapCFG; MapCFG.Read( m_MapCFGPath + m_DefaultMap ); - m_Map = new CMap( this, &MapCFG, m_MapCFGPath + m_DefaultMap ); + m_Map = new CMap( this, MapCFG, m_MapCFGPath + m_DefaultMap ); if( !m_AdminGameMap.isEmpty( ) ) { @@ -508,7 +508,7 @@ CGHost :: CGHost( CConfig *CFG, QString configFile ) CONSOLE_Print( "[GHOST] trying to load default admin game map" ); CConfig AdminMapCFG; AdminMapCFG.Read( m_MapCFGPath + m_AdminGameMap ); - m_AdminMap = new CMap( this, &AdminMapCFG, m_MapCFGPath + m_AdminGameMap ); + m_AdminMap = new CMap( this, AdminMapCFG, m_MapCFGPath + m_AdminGameMap ); if( !m_AdminMap->GetValid( ) ) { diff --git a/src/libghost/map.cpp b/src/libghost/map.cpp index 080296d..f3ca283 100644 --- a/src/libghost/map.cpp +++ b/src/libghost/map.cpp @@ -73,7 +73,7 @@ CMap :: CMap( CGHost *nGHost ) m_Slots.push_back( CGameSlot( 0, 255, SLOTSTATUS_OPEN, 0, 11, 11, SLOTRACE_RANDOM | SLOTRACE_SELECTABLE ) ); } -CMap :: CMap( CGHost *nGHost, CConfig *CFG, QString nCFGFile ) +CMap :: CMap( CGHost *nGHost, const CConfig &CFG, const QString &nCFGFile ) { m_GHost = nGHost; Load( CFG, nCFGFile ); @@ -84,7 +84,7 @@ CMap :: ~CMap( ) } -QByteArray CMap :: GetMapGameFlags( ) +QByteArray CMap :: GetMapGameFlags( ) const { /* @@ -158,7 +158,7 @@ QByteArray CMap :: GetMapGameFlags( ) return Util::fromUInt32(GameFlags); } -quint32 CMap :: GetMapGameType( ) +quint32 CMap :: GetMapGameType( ) const { /* spec stolen from Strilanc as follows: @@ -233,7 +233,7 @@ quint32 CMap :: GetMapGameType( ) return GameType; } -unsigned char CMap :: GetMapLayoutStyle( ) +unsigned char CMap :: GetMapLayoutStyle( ) const { // 0 = melee // 1 = custom forces @@ -249,14 +249,14 @@ unsigned char CMap :: GetMapLayoutStyle( ) return 3; } -void CMap :: Load( CConfig *CFG, QString nCFGFile ) +void CMap :: Load( const CConfig &CFG, const QString &nCFGFile ) { m_Valid = true; m_CFGFile = nCFGFile; // load the map data - m_MapLocalPath = CFG->GetString( "map_localpath", QString( ) ); + m_MapLocalPath = CFG.GetString( "map_localpath", QString( ) ); m_MapData.clear( ); if( !m_MapLocalPath.isEmpty( ) ) diff --git a/src/libghost/map.h b/src/libghost/map.h index 3492f20..a048c89 100644 --- a/src/libghost/map.h +++ b/src/libghost/map.h @@ -127,26 +127,26 @@ class CMap public: CMap( CGHost *nGHost ); - CMap( CGHost *nGHost, CConfig *CFG, QString nCFGFile ); + CMap( CGHost *nGHost, const CConfig &CFG, const QString &nCFGFile ); ~CMap( ); bool GetValid( ) const { return m_Valid; } - QString GetCFGFile( ) const { return m_CFGFile; } - QString GetMapPath( ) const { return m_MapPath; } - QByteArray GetMapSize( ) const { return m_MapSize; } - QByteArray GetMapInfo( ) const { return m_MapInfo; } - QByteArray GetMapCRC( ) const { return m_MapCRC; } - QByteArray GetMapSHA1( ) const { return m_MapSHA1; } + const QString &GetCFGFile( ) const { return m_CFGFile; } + const QString &GetMapPath( ) const { return m_MapPath; } + const QByteArray &GetMapSize( ) const { return m_MapSize; } + const QByteArray &GetMapInfo( ) const { return m_MapInfo; } + const QByteArray &GetMapCRC( ) const { return m_MapCRC; } + const QByteArray &GetMapSHA1( ) const { return m_MapSHA1; } unsigned char GetMapSpeed( ) const { return m_MapSpeed; } unsigned char GetMapVisibility( ) const { return m_MapVisibility; } unsigned char GetMapObservers( ) const { return m_MapObservers; } unsigned char GetMapFlags( ) const { return m_MapFlags; } - QByteArray GetMapGameFlags( ); - quint32 GetMapGameType( ); + QByteArray GetMapGameFlags( ) const; + quint32 GetMapGameType( ) const; quint32 GetMapOptions( ) const { return m_MapOptions; } - unsigned char GetMapLayoutStyle( ); - QByteArray GetMapWidth( ) const { return m_MapWidth; } - QByteArray GetMapHeight( ) const { return m_MapHeight; } + unsigned char GetMapLayoutStyle( ) const; + const QByteArray &GetMapWidth( ) const { return m_MapWidth; } + const QByteArray &GetMapHeight( ) const { return m_MapHeight; } const QString &GetMapType( ) const { return m_MapType; } const QString &GetMapMatchMakingCategory( ) const { return m_MapMatchMakingCategory; } const QString &GetMapStatsW3MMDCategory( ) const { return m_MapStatsW3MMDCategory; } @@ -154,12 +154,12 @@ class CMap quint32 GetMapDefaultPlayerScore( ) { return m_MapDefaultPlayerScore; } const QString &GetMapLocalPath( ) const { return m_MapLocalPath; } bool GetMapLoadInGame( ) const { return m_MapLoadInGame; } - QByteArray *GetMapData( ) { return &m_MapData; } - quint32 GetMapNumPlayers( ) { return m_MapNumPlayers; } - quint32 GetMapNumTeams( ) { return m_MapNumTeams; } - QList GetSlots( ) { return m_Slots; } + const QByteArray &GetMapData( ) const { return m_MapData; } + quint32 GetMapNumPlayers( ) const { return m_MapNumPlayers; } + quint32 GetMapNumTeams( ) const { return m_MapNumTeams; } + const QList &GetSlots( ) const { return m_Slots; } - void Load( CConfig *CFG, QString nCFGFile ); + void Load( const CConfig &CFG, const QString &nCFGFile ); void CheckValid( ); quint32 XORRotateLeft( unsigned char *data, quint32 length ); };