/ghost-legacy/bnet.cpp
C++ | 2772 lines | 2326 code | 282 blank | 164 comment | 437 complexity | 2b307f4d48eb7d68265f6a840643a6c8 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
-
- 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 "config.h"
- #include "language.h"
- #include "socket.h"
- #include "commandpacket.h"
- #include "ghostdb.h"
- #include "bncsutilinterface.h"
- #include "bnlsclient.h"
- #include "bnetprotocol.h"
- #include "bnet.h"
- #include "map.h"
- #include "packed.h"
- #include "savegame.h"
- #include "replay.h"
- #include "gameprotocol.h"
- #include "game_base.h"
-
- #include <boost/filesystem.hpp>
-
- 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, string nLANRootAdmin, 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 )
- {
- // todotodo: append path seperator to Warcraft3Path if needed
-
- m_GHost = nGHost;
- m_Socket = new CTCPClient( );
- m_Protocol = new CBNETProtocol( );
- m_BNLSClient = NULL;
- 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;
- string LowerServer = m_Server;
- transform( LowerServer.begin( ), LowerServer.end( ), LowerServer.begin( ), (int(*)(int))tolower );
-
- if( !nServerAlias.empty( ) )
- m_ServerAlias = nServerAlias;
- else if( LowerServer == "useast.battle.net" )
- m_ServerAlias = "USEast";
- else if( LowerServer == "uswest.battle.net" )
- m_ServerAlias = "USWest";
- else if( LowerServer == "asia.battle.net" )
- m_ServerAlias = "Asia";
- else if( LowerServer == "europe.battle.net" )
- m_ServerAlias = "Europe";
- else
- m_ServerAlias = m_Server;
-
- if( nPasswordHashType == "pvpgn" && !nBNLSServer.empty( ) )
- {
- 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;
- m_BNLSPort = nBNLSPort;
- m_BNLSWardenCookie = nBNLSWardenCookie;
- m_CDKeyROC = nCDKeyROC;
- m_CDKeyTFT = nCDKeyTFT;
-
- // remove dashes and spaces 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( ) );
- 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 );
-
- if( m_CDKeyROC.size( ) != 26 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] warning - your ROC CD key is not 26 characters long and is probably invalid" );
-
- if( m_GHost->m_TFT && m_CDKeyTFT.size( ) != 26 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] warning - your TFT CD key is not 26 characters long and is probably invalid" );
-
- m_CountryAbbrev = nCountryAbbrev;
- m_Country = nCountry;
- m_LocaleID = nLocaleID;
- m_UserName = nUserName;
- m_UserPassword = nUserPassword;
- m_FirstChannel = nFirstChannel;
- m_RootAdmin = nRootAdmin;
- transform( m_RootAdmin.begin( ), m_RootAdmin.end( ), m_RootAdmin.begin( ), (int(*)(int))tolower );
- m_LANRootAdmin = nLANRootAdmin;
- transform( m_LANRootAdmin.begin( ), m_LANRootAdmin.end( ), m_LANRootAdmin.begin( ), (int(*)(int))tolower );
- m_CommandTrigger = nCommandTrigger;
- m_War3Version = nWar3Version;
- m_EXEVersion = nEXEVersion;
- m_EXEVersionHash = nEXEVersionHash;
- m_PasswordHashType = nPasswordHashType;
- m_PVPGNRealmName = nPVPGNRealmName;
- m_MaxMessageLength = nMaxMessageLength;
- 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;
- m_HoldClan = nHoldClan;
- m_PublicCommands = nPublicCommands;
- }
-
- CBNET :: ~CBNET( )
- {
- delete m_Socket;
- delete m_Protocol;
- delete m_BNLSClient;
-
- while( !m_Packets.empty( ) )
- {
- delete m_Packets.front( );
- m_Packets.pop( );
- }
-
- delete m_BNCSUtil;
-
- for( vector<CIncomingFriendList *> :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ )
- delete *i;
-
- for( vector<CIncomingClanList *> :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ )
- delete *i;
-
- for( vector<PairedAdminCount> :: iterator i = m_PairedAdminCounts.begin( ); i != m_PairedAdminCounts.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedAdminAdd> :: iterator i = m_PairedAdminAdds.begin( ); i != m_PairedAdminAdds.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedAdminRemove> :: iterator i = m_PairedAdminRemoves.begin( ); i != m_PairedAdminRemoves.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedBanCount> :: iterator i = m_PairedBanCounts.begin( ); i != m_PairedBanCounts.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedBanAdd> :: iterator i = m_PairedBanAdds.begin( ); i != m_PairedBanAdds.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedBanRemove> :: iterator i = m_PairedBanRemoves.begin( ); i != m_PairedBanRemoves.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedGPSCheck> :: iterator i = m_PairedGPSChecks.begin( ); i != m_PairedGPSChecks.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- for( vector<PairedDPSCheck> :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); i++ )
- m_GHost->m_Callables.push_back( i->second );
-
- if( m_CallableAdminList )
- m_GHost->m_Callables.push_back( m_CallableAdminList );
-
- if( m_CallableBanList )
- m_GHost->m_Callables.push_back( m_CallableBanList );
-
- for( vector<CDBBan *> :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ )
- delete *i;
- }
-
- BYTEARRAY CBNET :: GetUniqueName( )
- {
- return m_Protocol->GetUniqueName( );
- }
-
- vector<pair<string, int> > CBNET :: GetFriends( )
- {
- vector<pair<string, int> > result;
-
- for( vector<CIncomingFriendList *> :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ )
- result.push_back(pair<string, int>((*i)->GetAccount( ), (*i)->GetArea( ) ) );
-
- return result;
- }
-
- vector<pair<string, int> > CBNET :: GetClan( )
- {
- vector<pair<string, int> > result;
-
- int k = 0;
- for( vector<CIncomingClanList *> :: iterator i = m_Clans.begin( ); i != m_Clans.end( ) && k < 50; i++, k++ )
- result.push_back(pair<string, int>((*i)->GetName( ), (*i)->GetRawStatus( ) ) );
-
- return result;
- }
-
- vector<pair<string, int> > CBNET :: GetBans( )
- {
- vector<pair<string, int> > result;
-
- int k = 0;
- for( vector<CDBBan *> :: iterator i = m_Bans.begin( ); i != m_Bans.end( ) && k < 100; i++, k++ )
- result.push_back(pair<string, int>((*i)->GetName( ), 0 ) );
-
- return result;
- }
-
- vector<pair<string, int> > CBNET :: GetAdmins( )
- {
- vector<pair<string, int> > result;
-
- vector<string> roots = UTIL_Tokenize( m_RootAdmin, ' ' );
-
- for( vector<string> :: iterator i = roots.begin( ); i != roots.end( ); i++ )
- result.push_back(pair<string, int>( *i, 2 ) );
-
- for( vector<string> :: iterator i = m_Admins.begin( ); i != m_Admins.end( ); i++ )
- result.push_back(pair<string, int>( *i, 0 ) );
-
- return result;
- }
-
- unsigned int CBNET :: SetFD( void *fd, void *send_fd, int *nfds )
- {
- unsigned int NumFDs = 0;
-
- if( !m_Socket->HasError( ) && m_Socket->GetConnected( ) )
- {
- 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;
- }
-
- bool CBNET :: Update( void *fd, void *send_fd )
- {
- //
- // update callables
- //
-
- for( vector<PairedAdminCount> :: 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( ), false );
- else if( Count == 1 )
- QueueChatCommand( m_GHost->m_Language->ThereIsAdmin( m_Server ), i->first, !i->first.empty( ), false );
- else
- QueueChatCommand( m_GHost->m_Language->ThereAreAdmins( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedAdminCounts.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedAdminAdd> :: 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( ), false );
- }
- else
- QueueChatCommand( m_GHost->m_Language->ErrorAddingUserToAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedAdminAdds.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedAdminRemove> :: 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( ), false );
- }
- else
- QueueChatCommand( m_GHost->m_Language->ErrorDeletingUserFromAdminDatabase( m_Server, i->second->GetUser( ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedAdminRemoves.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedBanCount> :: 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( ), false );
- else if( Count == 1 )
- QueueChatCommand( m_GHost->m_Language->ThereIsBannedUser( m_Server ), i->first, !i->first.empty( ), false );
- else
- QueueChatCommand( m_GHost->m_Language->ThereAreBannedUsers( m_Server, UTIL_ToString( Count ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedBanCounts.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedBanAdd> :: 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( ), false );
- }
- else
- QueueChatCommand( m_GHost->m_Language->ErrorBanningUser( i->second->GetServer( ), i->second->GetUser( ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedBanAdds.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedBanRemove> :: 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( ), false );
- }
- else
- QueueChatCommand( m_GHost->m_Language->ErrorUnbanningUser( i->second->GetUser( ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedBanRemoves.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedGPSCheck> :: 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( ), false );
- else
- QueueChatCommand( m_GHost->m_Language->HasntPlayedGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedGPSChecks.erase( i );
- }
- else
- i++;
- }
-
- for( vector<PairedDPSCheck> :: iterator i = m_PairedDPSChecks.begin( ); i != m_PairedDPSChecks.end( ); )
- {
- if( i->second->GetReady( ) )
- {
- CDBDotAPlayerSummary *DotAPlayerSummary = i->second->GetResult( );
-
- if( DotAPlayerSummary )
- {
- string 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 ) );
-
- QueueChatCommand( Summary, i->first, !i->first.empty( ), false );
- }
- else
- QueueChatCommand( m_GHost->m_Language->HasntPlayedDotAGamesWithThisBot( i->second->GetName( ) ), i->first, !i->first.empty( ), false );
-
- m_GHost->m_DB->RecoverCallable( i->second );
- delete i->second;
- i = m_PairedDPSChecks.erase( i );
- }
- else
- 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)" );
- m_Admins = m_CallableAdminList->GetResult( );
- m_GHost->m_DB->RecoverCallable( m_CallableAdminList );
- delete m_CallableAdminList;
- m_CallableAdminList = NULL;
- 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)" );
-
- for( vector<CDBBan *> :: iterator i = m_Bans.begin( ); i != m_Bans.end( ); i++ )
- delete *i;
-
- m_Bans = m_CallableBanList->GetResult( );
- m_GHost->m_DB->RecoverCallable( m_CallableBanList );
- delete m_CallableBanList;
- 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 )
- {
- if( m_BNLSClient->Update( fd, send_fd ) )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] deleting BNLS client" );
- delete m_BNLSClient;
- m_BNLSClient = NULL;
- }
- else
- {
- BYTEARRAY WardenResponse = m_BNLSClient->GetWardenResponse( );
-
- if( !WardenResponse.empty( ) )
- 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.empty( ) && 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_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.empty( ) )
- m_OutPackets.pop( );
-
- 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.empty( ) )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] attempting to bind to address [" + m_GHost->m_BindAddress + "]" );
-
- if( m_ServerIP.empty( ) )
- {
- 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
-
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] using cached server IP address " + m_ServerIP );
- m_Socket->Connect( m_GHost->m_BindAddress, m_ServerIP, 6112 );
- }
-
- m_WaitingToConnect = false;
- m_LastConnectionAttemptTime = GetTime( );
- return m_Exiting;
- }
-
- return m_Exiting;
- }
-
- 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( );
- 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
-
- while( Bytes.size( ) >= 4 )
- {
- // byte 0 is always 255
-
- if( Bytes[0] == BNET_HEADER_CONSTANT )
- {
- // bytes 2 and 3 contain the length of the packet
-
- uint16_t Length = UTIL_ByteArrayToUInt16( 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 ) ) );
- *RecvBuffer = RecvBuffer->substr( Length );
- Bytes = BYTEARRAY( Bytes.begin( ) + Length, Bytes.end( ) );
- }
- else
- return;
- }
- else
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad length), disconnecting" );
- m_Socket->Disconnect( );
- return;
- }
- }
- else
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] error - received invalid packet from battle.net (bad header constant), disconnecting" );
- m_Socket->Disconnect( );
- return;
- }
- }
- }
-
- void CBNET :: ProcessPackets( )
- {
- CIncomingGameHost *GameHost = NULL;
- CIncomingChatEvent *ChatEvent = NULL;
- BYTEARRAY WardenData;
- vector<CIncomingFriendList *> Friends;
- vector<CIncomingClanList *> Clans;
-
- // process all the received packets in the m_Packets queue
- // this normally means sending some kind of response
-
- while( !m_Packets.empty( ) )
- {
- CCommandPacket *Packet = m_Packets.front( );
- m_Packets.pop( );
-
- if( Packet->GetPacketType( ) == BNET_HEADER_CONSTANT )
- {
- switch( Packet->GetID( ) )
- {
- case CBNETProtocol :: SID_NULL:
- // warning: we do not respond to NULL packets with a NULL packet of our own
- // this is because PVPGN servers are programmed to respond to NULL packets so it will create a vicious cycle of useless traffic
- // official battle.net servers do not respond to NULL packets
-
- m_Protocol->RECEIVE_SID_NULL( Packet->GetData( ) );
- break;
-
- case CBNETProtocol :: SID_GETADVLISTEX:
- GameHost = m_Protocol->RECEIVE_SID_GETADVLISTEX( Packet->GetData( ) );
-
- if( GameHost )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] joining game [" + GameHost->GetGameName( ) + "]", GetRealmId( ), false );
-
- delete GameHost;
- GameHost = NULL;
- break;
-
- case CBNETProtocol :: SID_ENTERCHAT:
- if( m_Protocol->RECEIVE_SID_ENTERCHAT( Packet->GetData( ) ) )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] joining channel [" + m_FirstChannel + "]", GetRealmId( ), false );
- m_InChat = true;
- m_Socket->PutBytes( m_Protocol->SEND_SID_JOINCHANNEL( m_FirstChannel ) );
- }
-
- break;
-
- case CBNETProtocol :: SID_CHATEVENT:
- ChatEvent = m_Protocol->RECEIVE_SID_CHATEVENT( Packet->GetData( ) );
-
- if( ChatEvent )
- ProcessChatEvent( ChatEvent );
-
- delete ChatEvent;
- ChatEvent = NULL;
- break;
-
- case CBNETProtocol :: SID_CHECKAD:
- m_Protocol->RECEIVE_SID_CHECKAD( Packet->GetData( ) );
- break;
-
- case CBNETProtocol :: SID_STARTADVEX3:
- if( m_Protocol->RECEIVE_SID_STARTADVEX3( Packet->GetData( ) ) )
- {
- m_InChat = false;
- m_GHost->EventBNETGameRefreshed( this );
- }
- else
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] startadvex3 failed" );
- m_GHost->EventBNETGameRefreshFailed( this );
- }
-
- break;
-
- case CBNETProtocol :: SID_PING:
- m_Socket->PutBytes( m_Protocol->SEND_SID_PING( m_Protocol->RECEIVE_SID_PING( Packet->GetData( ) ) ) );
- break;
-
- 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( ) ) )
- {
- // override the exe information generated by bncsutil if specified in the config file
- // apparently this is useful for pvpgn users
-
- 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] ) );
- 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] ) );
- m_BNCSUtil->SetEXEVersionHash( m_EXEVersionHash );
- }
-
- 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" );
-
- 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" ) );
-
- // the Warden seed is the first 4 bytes of the ROC key hash
- // initialize the Warden handler
-
- if( !m_BNLSServer.empty( ) )
- {
- 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 ) );
- }
- }
- else
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - bncsutil key hash failed (check your Warcraft 3 path and cd keys), disconnecting" );
- m_Socket->Disconnect( );
- delete Packet;
- return;
- }
- }
-
- break;
-
- case CBNETProtocol :: SID_AUTH_CHECK:
- if( m_Protocol->RECEIVE_SID_AUTH_CHECK( Packet->GetData( ) ) )
- {
- // cd keys accepted
-
- 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 ) );
- }
- else
- {
- // cd keys not accepted
-
- switch( UTIL_ByteArrayToUInt32( 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" );
- break;
- case CBNETProtocol :: KR_TFT_KEY_IN_USE:
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - TFT CD key in use by user [" + m_Protocol->GetKeyStateDescription( ) + "], disconnecting" );
- break;
- case CBNETProtocol :: KR_OLD_GAME_VERSION:
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - game version is too old, disconnecting" );
- break;
- case CBNETProtocol :: KR_INVALID_VERSION:
- 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" );
- break;
- }
-
- m_Socket->Disconnect( );
- delete Packet;
- return;
- }
-
- break;
-
- case CBNETProtocol :: SID_AUTH_ACCOUNTLOGON:
- if( m_Protocol->RECEIVE_SID_AUTH_ACCOUNTLOGON( Packet->GetData( ) ) )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] username [" + m_UserName + "] accepted" );
-
- if( m_PasswordHashType == "pvpgn" )
- {
- // pvpgn logon
-
- 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( ) ) );
- }
- else
- {
- // battle.net logon
-
- 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( ) ) );
- }
- }
- else
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - invalid username, disconnecting" );
- m_Socket->Disconnect( );
- delete Packet;
- return;
- }
-
- break;
-
- case CBNETProtocol :: SID_AUTH_ACCOUNTLOGONPROOF:
- if( m_Protocol->RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF( Packet->GetData( ) ) )
- {
- // logon successful
-
- 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( ) );
- }
- else
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] logon failed - invalid password, disconnecting" );
-
- // 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;
- 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" ) )
- 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" );
- 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( );
- delete Packet;
- return;
- }
-
- break;
-
- case CBNETProtocol :: SID_WARDEN:
- WardenData = m_Protocol->RECEIVE_SID_WARDEN( Packet->GetData( ) );
-
- if( m_BNLSClient )
- m_BNLSClient->QueueWardenRaw( WardenData );
- else
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] warning - received warden packet but no BNLS server is available, you will be kicked from battle.net soon" );
-
- break;
-
- case CBNETProtocol :: SID_FRIENDSLIST:
- Friends = m_Protocol->RECEIVE_SID_FRIENDSLIST( Packet->GetData( ) );
-
- for( vector<CIncomingFriendList *> :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); i++ )
- delete *i;
-
- m_Friends = Friends;
- break;
-
- case CBNETProtocol :: SID_CLANMEMBERLIST:
- vector<CIncomingClanList *> Clans = m_Protocol->RECEIVE_SID_CLANMEMBERLIST( Packet->GetData( ) );
-
- for( vector<CIncomingClanList *> :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); i++ )
- delete *i;
-
- m_Clans = Clans;
- break;
- }
- }
-
- delete Packet;
- }
- }
-
- void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent )
- {
- CBNETProtocol :: IncomingChatEvent Event = chatEvent->GetChatEvent( );
- uint32_t UserFlags = chatEvent->GetUserFlags( );
- bool Whisper = ( Event == CBNETProtocol :: EID_WHISPER );
- bool WhisperResponses = ( m_GHost->m_WhisperResponses );
- string User = chatEvent->GetUser( );
- string Message = chatEvent->GetMessage( );
-
- if( Event == CBNETProtocol :: EID_SHOWUSER )
- CONSOLE_AddChannelUser( User, GetRealmId( ), UserFlags );
- else if( Event == CBNETProtocol :: EID_USERFLAGS )
- CONSOLE_UpdateChannelUser( User, GetRealmId( ), UserFlags );
- else if( Event == CBNETProtocol :: EID_JOIN )
- CONSOLE_AddChannelUser( User, GetRealmId( ), UserFlags );
- else if( Event == CBNETProtocol :: EID_LEAVE )
- CONSOLE_RemoveChannelUser( User, GetRealmId( ));
- else if( Event == CBNETProtocol :: EID_WHISPER )
- {
- m_ReplyTarget = User;
-
- CONSOLE_Print( "[WHISPER: " + m_ServerAlias + "] [" + User + "] " + Message, GetRealmId( ), false );
- m_GHost->EventBNETWhisper( this, User, Message );
- }
- else if( Event == CBNETProtocol :: EID_TALK )
- {
- CONSOLE_Print( "[LOCAL: " + m_ServerAlias + "] [" + User + "] " + Message, GetRealmId( ), false );
- m_GHost->EventBNETChat( this, User, Message );
- }
- else if( Event == CBNETProtocol :: EID_BROADCAST )
- {
- CONSOLE_Print( "[BROADCAST: " + m_ServerAlias + "] " + Message, GetRealmId( ), false );
- m_GHost->EventBNETBROADCAST( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_CHANNEL )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] joined channel [" + Message + "]", GetRealmId( ), false );
- m_CurrentChannel = Message;
- CONSOLE_ChangeChannel( Message, GetRealmId( ) );
- CONSOLE_RemoveChannelUsers( GetRealmId( ) );
- CONSOLE_AddChannelUser( m_UserName, GetRealmId( ), UserFlags );
- m_GHost->EventBNETCHANNEL( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_WHISPERSENT )
- {
- CONSOLE_Print ( "[WHISPERED: " + m_ServerAlias + "] [" + User + "] " + Message, GetRealmId( ), false );
- m_GHost->EventBNETWHISPERSENT( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_CHANNELFULL )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] channel is full", GetRealmId( ), false );
- m_GHost->EventBNETCHANNELFULL( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_CHANNELDOESNOTEXIST )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] channel does not exist", GetRealmId( ), false );
- m_GHost->EventBNETCHANNELDOESNOTEXIST( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_CHANNELRESTRICTED )
- {
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] channel restricted", GetRealmId( ), false );
- m_GHost->EventBNETCHANNELRESTRICTED( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_ERROR )
- {
- CONSOLE_Print( "[ERROR: " + m_ServerAlias + "] " + Message, GetRealmId( ), false );
- m_GHost->EventBNETError( this, User, Message );
- }
-
- else if( Event == CBNETProtocol :: EID_EMOTE )
- {
- CONSOLE_Print( "[EMOTE: " + m_ServerAlias + "] [" + User + "] " + Message, GetRealmId( ), false );
- m_GHost->EventBNETEmote( this, User, Message );
- }
-
- if( Event == CBNETProtocol :: EID_WHISPER || Event == CBNETProtocol :: EID_TALK || Event == 29 )
- {
- // handle spoof checking for current game
- // 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( 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 )
- {
- // 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
- // it's a pretty safe bet that anyone whispering the bot with a message containing the game name is a valid spoofcheck
-
- if( m_PasswordHashType == "pvpgn" && User == m_PVPGNRealmName )
- {
- // the equivalent pvpgn message is: [PvPGN Realm] Your friend abc has entered a Warcraft III Frozen Throne game named "xyz".
-
- vector<string> Tokens = UTIL_Tokenize( Message, ' ' );
-
- if( Tokens.size( ) >= 3 )
- m_GHost->m_CurrentGame->AddToSpoofed( m_Server, Tokens[2], false );
- }
- else
- m_GHost->m_CurrentGame->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( string( 1, m_CommandTrigger ) ), User, Whisper, WhisperResponses );
- 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( " " );
-
- if( PayloadStart != string :: npos )
- {
- Command = Message.substr( 1, PayloadStart - 1 );
- Payload = Message.substr( PayloadStart + 1 );
- }
- else
- Command = Message.substr( 1 );
-
- transform( Command.begin( ), Command.end( ), Command.begin( ), (int(*)(int))tolower );
-
- if( IsAdmin( User ) || IsRootAdmin( User ) )
- {
- if( User == "" )
- User = m_UserName;
-
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] admin [" + User + "] sent command [" + Message + "]" );
-
- /*****************
- * ADMIN COMMANDS *
- ******************/
-
- //
- // !ADDADMIN
- //
-
- if( Command == "addadmin" && !Payload.empty( ) )
- {
- if( IsRootAdmin( User ) )
- {
- if( IsAdmin( Payload ) )
- QueueChatCommand( m_GHost->m_Language->UserIsAlreadyAnAdmin( m_Server, Payload ), User, Whisper, WhisperResponses );
- else
- m_PairedAdminAdds.push_back( PairedAdminAdd( Whisper ? User : string( ), m_GHost->m_DB->ThreadedAdminAdd( m_Server, Payload ) ) );
- }
- else
- QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper, WhisperResponses );
- }
-
- //
- // !ADDBAN
- // !BAN
- //
-
- if( ( Command == "addban" || Command == "ban" ) && !Payload.empty( ) )
- {
- // extract the victim and the reason
- // e.g. "Varlock leaver after dying" -> victim: "Varlock", reason: "leaver after dying"
-
- string Victim;
- string Reason;
- stringstream SS;
- SS << Payload;
- SS >> Victim;
-
- if( !SS.eof( ) )
- {
- getline( SS, Reason );
- string :: size_type Start = Reason.find_first_not_of( " " );
-
- if( Start != string :: npos )
- Reason = Reason.substr( Start );
- }
-
- if( IsBannedName( Victim ) )
- QueueChatCommand( m_GHost->m_Language->UserIsAlreadyBanned( m_Server, Victim ), User, Whisper, false );
- else
- m_PairedBanAdds.push_back( PairedBanAdd( Whisper ? User : string( ), m_GHost->m_DB->ThreadedBanAdd( m_Server, Victim, string( ), string( ), User, Reason ) ) );
- }
-
- //
- // !ANNOUNCE
- //
-
- if( Command == "announce" && m_GHost->m_CurrentGame && !m_GHost->m_CurrentGame->GetCountDownStarted( ) )
- {
- if( Payload.empty( ) || Payload == "off" )
- {
- QueueChatCommand( m_GHost->m_Language->AnnounceMessageDisabled( ), User, Whisper, WhisperResponses );
- m_GHost->m_CurrentGame->SetAnnounce( 0, string( ) );
- }
- else
- {
- // extract the interval and the message
- // e.g. "30 hello everyone" -> interval: "30", message: "hello everyone"
-
- uint32_t Interval;
- string Message;
- stringstream SS;
- SS << Payload;
- SS >> Interval;
-
- if( SS.fail( ) || Interval == 0 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to announce command" );
- else
- {
- if( SS.eof( ) )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #2 to announce command" );
- else
- {
- getline( SS, Message );
- string :: size_type Start = Message.find_first_not_of( " " );
-
- if( Start != string :: npos )
- Message = Message.substr( Start );
-
- QueueChatCommand( m_GHost->m_Language->AnnounceMessageEnabled( ), User, Whisper, WhisperResponses );
- m_GHost->m_CurrentGame->SetAnnounce( Interval, Message );
- }
- }
- }
- }
-
- //
- // !AUTOHOST
- //
-
- if( Command == "autohost" )
- {
- if( IsRootAdmin( User ) )
- {
- if( Payload.empty( ) || Payload == "off" )
- {
- QueueChatCommand( m_GHost->m_Language->AutoHostDisabled( ), User, Whisper, WhisperResponses );
- m_GHost->m_AutoHostGameName.clear( );
- m_GHost->m_AutoHostOwner.clear( );
- 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;
- }
- else
- {
- // 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;
- string GameName;
- stringstream SS;
- SS << Payload;
- SS >> MaximumGames;
-
- if( SS.fail( ) || MaximumGames == 0 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to autohost command" );
- else
- {
- SS >> AutoStartPlayers;
-
- if( SS.fail( ) || AutoStartPlayers == 0 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #2 to autohost command" );
- else
- {
- if( SS.eof( ) )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] missing input #3 to autohost command" );
- else
- {
- getline( SS, GameName );
- string :: size_type Start = GameName.find_first_not_of( " " );
-
- if( Start != string :: npos )
- GameName = GameName.substr( Start );
-
- QueueChatCommand( m_GHost->m_Language->AutoHostEnabled( ), User, Whisper, WhisperResponses );
- delete m_GHost->m_AutoHostMap;
- m_GHost->m_AutoHostMap = new CMap( *m_GHost->m_Map );
- m_GHost->m_AutoHostGameName = GameName;
- m_GHost->m_AutoHostOwner = User;
- 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;
- }
- }
- }
- }
- }
- else
- QueueChatCommand( m_GHost->m_Language->YouDontHaveAccessToThatCommand( ), User, Whisper, WhisperResponses );
- }
-
- //
- // !AUTOHOSTMM
- //
-
- if( Command == "autohostmm" )
- {
- if( IsRootAdmin( User ) )
- {
- if( Payload.empty( ) || Payload == "off" )
- {
- QueueChatCommand( m_GHost->m_Language->AutoHostDisabled( ), User, Whisper, WhisperResponses );
- m_GHost->m_AutoHostGameName.clear( );
- m_GHost->m_AutoHostOwner.clear( );
- 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;
- }
- else
- {
- // 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;
- double MinimumScore;
- double MaximumScore;
- string GameName;
- stringstream SS;
- SS << Payload;
- SS >> MaximumGames;
-
- if( SS.fail( ) || MaximumGames == 0 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #1 to autohostmm command" );
- else
- {
- SS >> AutoStartPlayers;
-
- if( SS.fail( ) || AutoStartPlayers == 0 )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #2 to autohostmm command" );
- else
- {
- SS >> MinimumScore;
-
- if( SS.fail( ) )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #3 to autohostmm command" );
- else
- {
- SS >> MaximumScore;
-
- if( SS.fail( ) )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] bad input #4 to autohostmm command" );
- else
- {
- if( SS.eof( ) )
- CONSOLE_Print( "[BNET: " + m_ServerAlias + "] m…
Large files files are truncated, but you can click here to view the full file