//////////////////////////////////////////////////////////////////////////// // // Crytek Engine Source File. // Copyright (C), Crytek Studios, 2001-2004. // ------------------------------------------------------------------------- // File name: PunkBusterInterface.cpp // Version: v1.00 // Created: 1/3/2004 by Timur. // Compilers: Visual Studio.NET 2003 // Description: Interface to the PunkBuster from CryEngine. // ------------------------------------------------------------------------- // History: // //////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #if !defined(NOT_USE_PUNKBUSTER_SDK) #include "PunkBusterInterface.h" #define PbSdk_DEFINED #include "../PunkBuster/pbsdk.h" #include "../PunkBuster/pbmd5.h" #include "Network.h" #include "IRenderer.h" #include "ServerSlot.h" #include "Server.h" #include "Client.h" #include "ClientLocal.h" #include "ICryPak.h" static const char RegistryKeyName[] = "SOFTWARE\\Crytek\\FarCry"; static const char CDKEYREGKEY[] = "CDKey"; void PBcomputeHash ( char *idhash , CServerSlot *pSlot ) ;//defined in this source file after class definitions ////////////////////////////////////////////////////////////////////////// CPunkBusterInterface::CPunkBusterInterface( CNetwork *pNetwork ) { m_bSinglePlayer = false ; m_bClInitialized = false; m_bSvInitialized = false; m_pNetwork = pNetwork; m_pSystem = pNetwork->GetSystem(); m_pClient = 0; m_pClientLocal = 0; m_pServer = 0; sys_punkbuster_loaded = 0; cl_punkbuster = m_pSystem->GetIConsole()->CreateVariable( "cl_punkbuster","0",VF_DUMPTODISK,"Enables PunkBuster for client, 1=Enabled,0=Disabled" ); sv_punkbuster = m_pSystem->GetIConsole()->CreateVariable( "sv_punkbuster","0",VF_DUMPTODISK,"Enables PunkBuster for server, 1=Enabled,0=Disabled" ); fs_homepath = m_pSystem->GetIConsole()->CreateVariable( "fs_homepath","",VF_DUMPTODISK,"Specifies alternate PunkBuster 'home' (if non-empty)" ); // Start recieving OnBeforeVarChange events. m_pSystem->GetIConsole()->AddConsoleVarSink(this); m_pSystem->GetIConsole()->AddOutputPrintSink(this); } ////////////////////////////////////////////////////////////////////////// CPunkBusterInterface::~CPunkBusterInterface() { if ( sys_punkbuster_loaded ) { SAFE_RELEASE(sys_punkbuster_loaded); sys_punkbuster_loaded = 0 ; } m_pSystem->GetIConsole()->RemoveOutputPrintSink(this); m_pSystem->GetIConsole()->RemoveConsoleVarSink(this); } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::Init( bool bClient , bool isLocalServer ) { if ( bClient == false ) { m_bSinglePlayer = !isLocalServer ; if ( m_bSinglePlayer == true ) { ShutDown ( false ) ; return ; } } else if ( m_bSinglePlayer ) return ; if ( !sys_punkbuster_loaded ) { sys_punkbuster_loaded = m_pSystem->GetIConsole()->CreateVariable( "sys_punkbuster_loaded","1",NULL); } if ( bClient ) { if ( m_bClInitialized ) return ; PbClientInitialize ( this ) ; m_bClInitialized = true; } else { if ( m_bSvInitialized ) return ; PbServerInitialize() ; m_bSvInitialized = true; } } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::SetServer( CServer *pServer ) { m_pServer = pServer; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::SetClient( CClient *pClient ) { m_pClient = pClient; m_pClientLocal = 0; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::SetClientLocal( CClientLocal *pClient ) { m_pClientLocal = pClient; m_pClient = 0; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::LockCVars() { cl_punkbuster->SetFlags( cl_punkbuster->GetFlags() | VF_READONLY ); sv_punkbuster->SetFlags( sv_punkbuster->GetFlags() | VF_READONLY ); fs_homepath->SetFlags( fs_homepath->GetFlags() | VF_READONLY ); } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::UnlockCVars() { cl_punkbuster->SetFlags( cl_punkbuster->GetFlags() & ~VF_READONLY ); sv_punkbuster->SetFlags( sv_punkbuster->GetFlags() & ~VF_READONLY ); fs_homepath->SetFlags( fs_homepath->GetFlags() & ~VF_READONLY ); } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::ShutDown( bool bClient ) { // m_bInitialized = false; if ( sys_punkbuster_loaded ) { SAFE_RELEASE(sys_punkbuster_loaded); sys_punkbuster_loaded = 0 ; } if (bClient) { m_pClientLocal = 0; m_pClient = 0; } else { m_pServer = 0; } UnlockCVars(); } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::Update( bool bClient ) { if ( !sys_punkbuster_loaded ) return ;//no PB processing when PB has been shut down or is not yet initialized if ( bClient) { if (!m_bClInitialized) return; PbClientProcessEvents() ; } else { if (!m_bSvInitialized) return; PbServerProcessEvents() ; } } ////////////////////////////////////////////////////////////////////////// bool CPunkBusterInterface::OnBeforeVarChange( ICVar *pVar,const char *sNewValue ) { // if (!m_bInitialized) // return true; return true; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::Print( const char *inszText ) { PbCaptureConsoleOutput ( (char *) inszText , strlen ( inszText ) ) ; } ////////////////////////////////////////////////////////////////////////// bool CPunkBusterInterface::LoadCDKey( string &sCDKey ) { if (ReadStringFromRegistry("Ubi.com", CDKEYREGKEY, sCDKey)) { return true; } return false; } ////////////////////////////////////////////////////////////////////////// bool CPunkBusterInterface::ReadStringFromRegistry(const string &szKeyName, const string &szValueName, string &szValue) { #ifdef WIN32 HKEY hKey; string szREGKeyName = string(RegistryKeyName) + string("\\") + szKeyName; if (RegOpenKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS) { return false; } DWORD dwSize = 0; if (RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, 0, &dwSize) != ERROR_SUCCESS) { RegCloseKey(hKey); return false; } szValue.resize(dwSize); RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, (LPBYTE)szValue.c_str(), &dwSize); RegCloseKey(hKey); return true; #else return false; #endif } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::OnAddClient( CIPAddress &clientIP ) { // Must have server by this point. // assert( m_pServer ); if ( !m_pServer ) return ;//happens in single-player mode //at this point in the process, just add the client address and idhash, see PBgetClientInfo() later in this source file char addr[32] ; strncpy ( addr , clientIP.GetAsString(true) , 31 ) ; addr[31] = 0 ; if ( clientIP.IsLocalHost() ) strcpy ( addr , "localhost" ) ; // if ( !strcmp ( addr , "127.0.0.1:0" ) ) strcpy ( addr , "localhost" ) ; char idhash[PB_GUIDLEN+1] = "" ; CServerSlot *pSlot = m_pServer->GetPacketOwner( clientIP ); if (pSlot) { PBcomputeHash ( idhash , pSlot ) ; } else { strcpy ( idhash , "" ) ; } PbSvAddClient ( addr , "" , idhash ) ; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::OnDisconnectClient( CIPAddress &clientIP ) { char addr[32] ; strncpy ( addr , clientIP.GetAsString(true) , 31 ) ; addr[31] = 0 ; if ( !strcmp ( addr , "127.0.0.1:0" ) ) strcpy ( addr , "localhost" ) ; PbSvRemoveClient ( addr ) ; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::CheaterFound( CIPAddress &clientIP,int type,const char *sMsg ) { if (m_pServer && m_pServer->GetSecuritySink()) { m_pServer->GetSecuritySink()->CheaterFound( clientIP.GetAsUINT(),type,sMsg ); } } bool CPunkBusterInterface::CheckPBPacket(CStream &stmPacket,CIPAddress &ip) { int len = stmPacket.GetSize() >> 3 ;//convert bits to bytes if ( len >= 7) // Must be at least 7 bytes int. { BYTE *pBuf = stmPacket.GetPtr(); if ( !memcmp ( pBuf , "\xff\xff\xff\xffPB_" , 7 ) ) { //if not ded if ( pBuf[7] != 'S' && pBuf[7] != '2' && pBuf[7] != 'G' && pBuf[7] != 'I' && pBuf[7] != 'Y' && pBuf[7] != 'B' && pBuf[7] != 'L' ) PbClAddEvent ( PB_EV_PACKET , len - 4 , (char *) pBuf + 4 ) ; // if ( pBuf[7] != 'C' && pBuf[7] != '1' && pBuf[7] != 'J' ) PbSvAddEvent ( PB_EV_PACKET , -1 , len - 4 , (char *) pBuf + 4 ) ; return false ;//yes pb packet } } return true;//not a pb packet } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::ValidateClient( CServerSlot *pSlot ) { //this function is called as client is trying to connect before level load //if PB is enabled at this server, it checks to see if the PB client is enabled for the player // and checks for any ban issues with the id/hash unsigned int nFlags = pSlot->GetClientFlags(); char idhash[PB_GUIDLEN+1] = "" , addr[32] = "" ; strncpy ( addr , pSlot->GetIP().GetAsString(true) , 31 ) ; addr[31] = 0 ; PBcomputeHash ( idhash , pSlot ) ; char *res = PbAuthClient ( addr , nFlags & CLIENT_FLAGS_PUNK_BUSTER , idhash ) ; if ( res != NULL ) pSlot->Disconnect ( res ) ; } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::OnCCPPunkBusterMsg( CIPAddress &ipAddress,CStream &stm ) { if ( m_pClient || m_pClientLocal ) { BYTE *pByte = stm.GetPtr() ; PbClAddEvent ( PB_EV_PACKET , stm.GetSize() >> 3 , (char *) pByte ) ;//convert bits to bytes } if ( m_pServer ) { int i = 0 ; char *addr = ipAddress.GetAsString(true); for ( i = 0 ; i < PB_MAX_CLIENTS ; i++ ) if ( !strcmp ( addr , pbsdk->pbsv.m_client[i].pbc.ip ) ) break ; if ( i < PB_MAX_CLIENTS ) { BYTE *pByte = stm.GetPtr() ; PbSvAddEvent ( PB_EV_PACKET , i , stm.GetSize() >> 3 , (char *) pByte ) ;//convert bits to bytes } } } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::SendMsgToClient( CIPAddress &clientIP,CStream &stm ) { if (m_pServer) { CServerSlot *pSlot = m_pServer->GetPacketOwner(clientIP); if (pSlot) { pSlot->SendPunkBusterMsg(stm); } } } ////////////////////////////////////////////////////////////////////////// void CPunkBusterInterface::SendMsgToServer( CStream &stm ) { if (m_pClient)//don't check for local here because those packets are handled internally by PB { m_pClient->SendPunkBusterMsg( stm ); } } //below added by TR as "glue" functions // // PBoutgame // void PBoutgame ( char *text , int hudAlso ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; char *te = text , hold = 0 ; for(;;) { //loop in case of multiple lines (to simulate linefeeds) char *cp = strstr ( te , "\n" ) ; if ( cp != NULL ) { //linefeed found so hold end-char and terminate hold = *cp ; *cp = 0 ; } else hold = 0 ; //signifies end of line int wrapat = 89 ; if ( *te ) { //ignore empty lines char *wrp = te ; while ( *wrp ) { char hold = 0 ; if ( strlen ( wrp ) > wrapat ) { hold = wrp[wrapat] ; wrp[wrapat] = 0 ; } pip->m_pSystem->GetIConsole()->PrintLine ( wrp ) ; //output to console if ( !hold ) break ; wrp[wrapat] = hold ; wrp += wrapat ; } if ( hudAlso ) { //optionally output to screen if ( !pip->m_pSystem->IsDedicated() ) { char buf[101] ; char finalbuf[201] ; strncpy( buf,te,sizeof(buf)-1 ); buf[sizeof(buf)-1] = 0; for (int i = 0; i < strlen(buf); i++) { if (buf[i] == '\\') buf[i] = '/'; if (buf[i] == '"') buf[i] = '\''; } _snprintf ( finalbuf , sizeof(finalbuf)-1 , "#if (Hud) then Hud:AddMessage( \"%s\" ); end" , buf ) ; pip->m_pSystem->GetIConsole()->ExecuteString( finalbuf,true,true ); } } } if ( !hold ) break ; //if end of line, then break out of loop *cp = hold ; te = cp + 1 ; } } // // PBsendPktToServer // void PBsendPktToServer ( int datalen , char *data ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; CStream stm; stm.SetBits( (BYTE *) data , 0 , datalen * 8 ); stm.SetSize( datalen * 8 ) ; pip->SendMsgToServer ( stm ) ; } // // Sys_PBSendUdpPacket // void Sys_PBSendUdpPacket ( char *addr , unsigned short port , int datalen , char *data , int isFromClient ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; CStream stm; stm.SetBits( (BYTE *) data , 0 , datalen * 8 ); stm.SetSize( datalen * 8 ) ; CIPAddress cip ( port , addr ) ; if ( isFromClient ) { //from client if ( pip->m_pClient != NULL ) pip->m_pClient->SendTo ( cip , stm ) ;//no need to check for local due to PB's internal handling } else { //from server if ( pip->m_pServer != NULL ) pip->m_pServer->Send ( stm , cip ) ; } } // // PBsendPktToClient // void PBsendPktToClient ( int datalen , char *data , char *addr ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; CStream stm; stm.SetBits( (BYTE *) data , 0 , datalen * 8 ); stm.SetSize( datalen * 8 ) ; char ip[32] ; unsigned short port = 0 ; strncpy ( ip , addr , 31 ) ; ip[31] = 0 ; char *cp = strstr ( ip , ":" ) ; if ( cp != NULL ) { *cp = 0 ; port = atoi ( cp + 1 ) ; } CIPAddress cip ( port , ip ) ; pip->SendMsgToClient ( cip , stm ) ; } // // PBisLocalServer // int PBisLocalServer ( void ) { if ( pbsdk == NULL ) return 1 ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return 1 ; if ( pip->m_pClient == NULL ) return 1 ; CIPAddress ca = pip->m_pClient->GetServerIP() ; return ca.IsLocalHost() ; } // // PBgetHomePath // void PBgetHomePath ( char *path , int maxlen ) { *path = 0 ; if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; strncpy ( path , pip->fs_homepath->GetString() , maxlen - 1 ) ; path[maxlen-1] = 0 ; } // // PBgetClientInfo // int PBgetClientInfo ( stPb_Sv_Client *c ) { if ( pbsdk == NULL ) return 0 ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return 0 ; if ( pip->m_pServer == NULL ) return 0 ; char ip[32] ; unsigned short port = 0 ; strncpy ( ip , c->ip , 31 ) ; ip[31] = 0 ; char *cp = strstr ( ip , ":" ) ; if ( cp != NULL ) { *cp = 0 ; port = atoi ( cp + 1 ) ; } CIPAddress clientIP ( port , ip ) ; IServerSecuritySink::SSlotInfo playerInfo; memset ( &playerInfo , 0 , sizeof ( playerInfo ) ) ; pip->m_pServer->GetSecuritySink()->GetSlotInfo( clientIP.GetAsUINT(),playerInfo , 1 ); if ( *playerInfo.playerName == 0 ) return 0 ; //player not set up yet strncpy ( c->name , playerInfo.playerName , PB_NAMELEN ) ; c->name[PB_NAMELEN] = 0 ; if ( *c->guid == 0 ) { //if the guid is empty, compute it from the hash char idhash[PB_GUIDLEN+1] = "" ; CServerSlot *pSlot = pip->m_pServer->GetPacketOwner( clientIP ); if (pSlot) { PBcomputeHash ( idhash , pSlot ) ; strcpy ( c->guid , idhash ) ; } } return 1 ; } // // PBgetStats // int PBgetStats ( int index , char *Data ) { if ( pbsdk == NULL ) return 0 ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return 0 ; if ( pip->m_pServer == NULL ) return 0 ; char ip[32] ; unsigned short port = 0 ; strncpy ( ip , pbsdk->pbsv.m_client[index].pbc.ip , 31 ) ; ip[31] = 0 ; char *cp = strstr ( ip , ":" ) ; if ( cp != NULL ) { *cp = 0 ; port = atoi ( cp + 1 ) ; } CIPAddress clientIP ( port , ip ) ; IServerSecuritySink::SSlotInfo playerInfo; memset ( &playerInfo , 0 , sizeof ( playerInfo ) ) ; pip->m_pServer->GetSecuritySink()->GetSlotInfo( clientIP.GetAsUINT(),playerInfo , 0 ) ; if ( *playerInfo.playerName == 0 ) return 0 ;//player not set up yet sprintf ( Data , "score=%d deaths=%d" , playerInfo.score , playerInfo.deaths ) ; return 1 ; } // // PBcomputeHash // void PBcomputeHash ( char *guid , CServerSlot *pSlot ) { MD5_CTX mc ; if (pSlot->m_pbGlobalID) { MD5Init ( &mc ) ; MD5Update ( &mc , pSlot->m_pbGlobalID , pSlot->m_uiGlobalIDSize ); MD5Final ( &mc ) ; } else { memset(mc.digest,0,sizeof(mc.digest)); } _snprintf ( guid , PB_GUIDLEN , "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" , mc.digest[0] , mc.digest[1] , mc.digest[2] , mc.digest[3] , mc.digest[4] , mc.digest[5] , mc.digest[6] , mc.digest[7] , mc.digest[8] , mc.digest[9] , mc.digest[10] , mc.digest[11] , mc.digest[12] , mc.digest[13] , mc.digest[14] , mc.digest[15] ) ; } // // PBcvar_VariableString // char *PBcvar_VariableString ( const char *var_name ) { if ( pbsdk == NULL ) return "ERROR: NULL POINTER" ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return "ERROR: NULL POINTER" ; if ( pip->m_pSystem == NULL ) return "ERROR: NULL POINTER" ; ICVar *cv = pip->m_pSystem->GetIConsole()->GetCVar(var_name); if ( cv == NULL ) return "" ; return cv->GetString() ; } // // PBcvar_Set // void PBcvar_Set ( const char *cvar , const char *value ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; if ( pip->m_pSystem == NULL ) return ; ICVar *cv = pip->m_pSystem->GetIConsole()->GetCVar(cvar); if ( cv == NULL ) return ; cv->ForceSet ( value ) ; } // // PBcmd_execString // void PBcmd_execString ( const char *text ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; if ( pip->m_pSystem == NULL ) return ; pip->m_pSystem->GetIConsole()->ExecuteString( text,false,false); } // // PBdropClient // void PBdropClient ( int clientIndex , char *reason ) { if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; if ( pip->m_pServer == NULL ) return ; char ip[32] ; unsigned short port = 0 ; strncpy ( ip , pbsdk->pbsv.m_client[clientIndex].pbc.ip , 31 ) ; ip[31] = 0 ; char *cp = strstr ( ip , ":" ) ; if ( cp != NULL ) { *cp = 0 ; port = atoi ( cp + 1 ) ; } CIPAddress clientIP ( port , ip ) ; CServerSlot *pSlot = pip->m_pServer->GetPacketOwner( clientIP ); if (pSlot) pSlot->Disconnect ( reason ) ; } // // PBgameVer // char *PBgameVer ( void ) { if ( pbsdk == NULL ) return "" ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return "" ; //must return pointer to full game version info string static char buf[64] = "" ; pip->m_pSystem->GetFileVersion().ToString ( buf ) ; return buf ; } // // isPBmultiplayerMode // int isPBmultiplayerMode ( void ) { if ( pbsdk == NULL ) return 0 ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return 0 ; if ( pip->m_pNetwork == NULL ) return 0 ; if ( pip->m_pServer == NULL && pip->m_pClient == NULL && pip->m_pClientLocal == NULL ) return 0 ; return 1 ; } // // PBserverIp // char *PBserverIp ( int bServer ) { if ( pbsdk == NULL ) return "bot" ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return "bot" ; static CIPAddress cip ; if ( !bServer ) { if ( pip->m_pClient == NULL ) { if ( pip->m_pClientLocal == NULL ) return "bot" ; return "localhost" ; } cip = pip->m_pClient->GetServerIP() ; } else { if ( pip->m_pServer == NULL || pip->m_pNetwork == NULL ) return "???" ; cip.m_Address.ADDR = pip->m_pNetwork->GetLocalIP(); cip.m_Address.sin_port = htons ( pip->m_pServer->GetServerPort() ) ; } return cip.GetAsString ( true ) ; } // // PBserverHostname // char *PBserverHostname ( void ) { if ( pbsdk == NULL ) return "" ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return "" ; if ( pip->m_pServer == NULL ) return "" ; CIPAddress cip ; return (char *) pip->m_pServer->GetHostName() ; } // // PBkeyValue // const char *PBkeyValue ( char *notused , char *key ) { notused; if ( pbsdk == NULL ) return "" ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return "" ; if ( pip->m_pSystem == NULL ) return "" ; const char *newkey = key ; ICVar *cv ; if ( !stricmp ( key , "gamename" ) ) { #ifdef GAME_IS_FARCRY newkey = GetIXGame( pip->m_pSystem->GetIGame() )->IsMODLoaded() ; #else newkey = NULL; #endif if ( newkey == NULL ) return "FarCry" ; else return newkey ; } else if ( !stricmp ( key , "mapname" ) ) { newkey = "g_levelName" ; }/* else if ( !stricmp ( s , "sv_hostname" ) ) { }*/ cv = pip->m_pSystem->GetIConsole()->GetCVar( newkey ) ; if ( cv == NULL ) return "" ; return cv->GetString() ; } // // PBqueryGL // char *PBqueryGL ( int type ) { if ( pbsdk == NULL ) return "" ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return "" ; // pip->m_pSystem->GetIRenderer()->GetColorBpp() ; switch ( type ) { case PB_GL_READPIXELS: //(char *) qglReadPixels ;//function pointer return (char *) pip->m_pSystem->GetIRenderer()->EF_Query(EFQ_glReadPixels); case PB_GL_WIDTH: return (char *) pip->m_pSystem->GetIRenderer()->GetWidth() ; case PB_GL_HEIGHT: return (char *) pip->m_pSystem->GetIRenderer()->GetHeight() ; case PB_GL_RGB: return NULL ;//(char *) GL_RGB ; case PB_GL_UB: return NULL ;//(char *) GL_UNSIGNED_BYTE ; case PB_GL_D3DDEV: return (char *) pip->m_pSystem->GetIRenderer()->EF_Query(EFQ_D3DDevice); } return NULL ; } class CCVarsDump : public ICVarDumpSink { public: CCVarsDump() { m_vars.resize(0); } void OnElementFound(ICVar *pCVar) { m_vars.push_back(pCVar); } ICVar** GetVars() { return &m_vars[0]; } int NumVars() { return m_vars.size(); } private: static std::vector m_vars; }; std::vector CCVarsDump::m_vars; // // PBcvarWalk // //this is a callback function called from the PB dlls int PBcvarWalk ( char **name , char **string , int *flags , char **resetString ) { if ( pbsdk == NULL ) return 0 ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return 0 ; static int i = 0 , n = 0 ; static ICVar **pVars = NULL ; if ( i == 0 || pVars == NULL ) { CCVarsDump dump; pip->m_pSystem->GetIConsole()->DumpCVars( &dump ); pVars = dump.GetVars(); if ( pVars == NULL ) return 0 ; i = 0 ; n = dump.NumVars() ; } if ( i >= n || pVars == NULL ) {//end of enumeration i = 0 ; n = 0 ; pVars = NULL ; return 0 ; } *name = (char *) pVars[i]->GetName() ; *string = (char *) pVars[i]->GetString() ; *flags = pVars[i]->GetFlags() ; *resetString = "" ; ++i ; return 1;//keep going } class CKeyBindsDump : public IKeyBindDumpSink { public: CKeyBindsDump() { m_keys.resize(0); } void OnKeyBindFound( const char *sBind,const char *sCommand ) { m_keys.push_back(sBind); } const char** GetKeys() { return &m_keys[0]; } int NumKeys() { return m_keys.size(); } private: static std::vector m_keys; }; std::vector CKeyBindsDump::m_keys; // // PBbindStuff // int PBbindStuff ( int type , const char **data ) { if ( pbsdk == NULL ) return 0 ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return 0 ; static int i = 0 , n = 0 ; static const char **pKeys = NULL ; if ( type == 1 || n == 0 ) { n = 0 ; if ( i == 0 || pKeys == NULL ) { CKeyBindsDump dump; pip->m_pSystem->GetIConsole()->DumpKeyBinds( &dump ); pKeys = dump.GetKeys(); if ( pKeys == NULL ) return 0 ; i = 0 ; n = dump.NumKeys() ; } } if ( type == 1 ) {//return # of keys return n ; } else if ( type == 2 ) {//return keyname in *data int key = atoi ( *data ) ; *data = "" ; if ( pKeys == NULL ) return 0 ; if ( key < n ) *data = pKeys[key] ; } else {//return data for key bind name int key = atoi ( *data ) ; *data = "" ; if ( pKeys == NULL ) return 0 ; *data = pip->m_pSystem->GetIConsole()->FindKeyBind(pKeys[key]); } return 0 ; } // // PBpakNames // void PBpakNames ( char *buf )//assumes buf is 1025+ in size (bytes) { strcpy ( buf , "*ERROR*" ) ; if ( pbsdk == NULL ) return ; CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ; if ( pip == NULL ) return ; if ( pip->m_pSystem == NULL ) return ; *buf = 0 ; ICryPak::PakInfo* pPakInfo = pip->m_pSystem->GetIPak()->GetPakInfo(); //get loaded pak names int i ; char priorRoot[513] = "" ; for ( i = 0 ; i < pPakInfo->numOpenPaks ; i++ ) { int slb = strlen ( buf ) ; if ( stricmp ( priorRoot , pPakInfo->arrPaks[i].szBindRoot ) ) { //new bind root ? strncpy ( priorRoot , pPakInfo->arrPaks[i].szBindRoot , 512 ) ; //yes add to list with a * prefix priorRoot[512] = 0 ; if ( strlen ( priorRoot ) + slb < 1020 ) _snprintf ( buf + slb , 1025 - slb , "*\"%s\" " , priorRoot ) ; slb = strlen ( buf ) ; } const char *cp = pPakInfo->arrPaks[i].szFilePath ; if ( strlen ( cp ) > strlen ( priorRoot ) ) cp += strlen ( priorRoot ) ;//this should always happen if ( strlen ( cp ) + slb > 1020 ) continue ; //skip it, too many already _snprintf ( buf + slb , 1025 - slb , "\"%s\" " , cp ) ; //append pak file name from point of prior bind root } } #endif // NOT_USE_PUNKBUSTER_SDK