| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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 3 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, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Commando/GameSpy_QnR.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 7/08/02 5:55p $*
- * *
- * $Revision:: 17 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include <Gamespy\gs_patch_usage.h>
- #include <Gamespy\gcdkeyserver.h>
- #include "specialbuilds.h"
- #include "dlgcncteaminfo.h"
- #include "resource.h"
- #include "listctrl.h"
- #include "imagectrl.h"
- #include "playertype.h"
- #include "combat.h"
- #include "teammanager.h"
- #include "playermanager.h"
- #include "player.h"
- #include "soldier.h"
- #include "gameinitmgr.h"
- #include "gamemode.h"
- #include "gamedata.h"
- #include "input.h"
- #include "healthbarctrl.h"
- #include "basecontroller.h"
- #include "building.h"
- #include "damage.h"
- #include "vehicle.h"
- #include "assets.h"
- #include "translatedb.h"
- #include "WOLGMode.h"
- #include <WWOnline\WOLUser.h>
- #include "string_ids.h"
- #include "mousemgr.h"
- #include "directinput.h"
- #include "GameSpy_QnR.h"
- #include "verchk.h"
- #include "buildnum.h"
- #include "serversettings.h"
- #include "consolemode.h"
- #include "useroptions.h"
- #include "gdcnc.h"
- #include "rawfile.h"
- #include "shellapi.h"
- #include "netutil.h"
- #include "gamespybanlist.h"
- CGameSpyQnR GameSpyQnR;
- #if defined(MULTIPLAYERDEMO)
- const char *CGameSpyQnR::gamename = "ccrenegadedemo";
- const char *CGameSpyQnR::bname = "Demo";
- const int CGameSpyQnR::prodid = 10063;
- const int CGameSpyQnR::cdkey_id = 0;
- #elif defined(FREEDEDICATEDSERVER)
- const char *CGameSpyQnR::bname = "FDS";
- const char *CGameSpyQnR::gamename = "ccrenegade";
- const int CGameSpyQnR::prodid = 10064;
- const int CGameSpyQnR::cdkey_id = 577;
- #elif defined(BETACLIENT)
- const char *CGameSpyQnR::bname = "Beta";
- const char *CGameSpyQnR::gamename = "ccrenegade";
- const int CGameSpyQnR::prodid = 10064;
- const int CGameSpyQnR::cdkey_id = 0;
- #else
- const char *CGameSpyQnR::bname = "Retail";
- const char *CGameSpyQnR::gamename = "ccrenegade";
- const int CGameSpyQnR::prodid = 10064;
- const int CGameSpyQnR::cdkey_id = 577;
- #endif
- const char *CGameSpyQnR::default_heartbeat_list = "master.gamespy.com:27900, master.udpsoft.com:27900";
- /*********
- These c-style callback stubs are used by the SDK. The current game object
- (passed in qr_init) is given in userdata, so we know what object to reference
- **********/
- void c_players_callback(char *outbuf, int maxlen, void *userdata)
- {
- ((CGameSpyQnR *)userdata)->players_callback(outbuf, maxlen);
- }
- void c_rules_callback(char *outbuf, int maxlen, void *userdata)
- {
- ((CGameSpyQnR *)userdata)->rules_callback(outbuf, maxlen);
- }
- void c_info_callback(char *outbuf, int maxlen, void *userdata)
- {
- ((CGameSpyQnR *)userdata)->info_callback(outbuf, maxlen);
- }
- void c_basic_callback(char *outbuf, int maxlen, void *userdata)
- {
- ((CGameSpyQnR *)userdata)->basic_callback(outbuf, maxlen);
- }
- /***********
- A simple game object. Consists of some data and a main loop function.
- ***********/
- CGameSpyQnR::CGameSpyQnR(void) : m_GSInit(FALSE), m_GSEnabled(FALSE)
- {
- // Secret keys removed per Security review requirements. LFeenanEA - 27th January 2025
-
- //set the secret key, in a semi-obfuscated manner
- // tY1S8q = FULL , LsEwS3 = DEMO
- #ifdef MULTIPLAYERDEMO
- secret_key[3] = 'R'; if (secret_key[3])
- secret_key[1] = 'E'; if (secret_key[1])
- secret_key[0] = 'M'; if (secret_key[0])
- secret_key[4] = 'O'; if (secret_key[4])
- secret_key[5] = 'V'; if (secret_key[5])
- secret_key[3] = 'E'; if (secret_key[3])
- secret_key[2] = 'D'; if (secret_key[2])
- secret_key[6] = '1'; if (secret_key[2])
- secret_key[5] = '2'; if (secret_key[5])
- secret_key[4] = '3';
- #else
- secret_key[5] = 'R'; if (secret_key[5])
- secret_key[4] = 'E'; if (secret_key[4])
- secret_key[6] = 'M'; if (secret_key[4])
- secret_key[1] = 'O'; if (secret_key[1])
- secret_key[5] = 'V'; if (secret_key[5])
- secret_key[2] = 'E'; if (secret_key[2])
- secret_key[3] = 'D'; if (secret_key[3])
- secret_key[6] = '1'; if (secret_key[3])
- secret_key[0] = '2'; if (secret_key[0])
- secret_key[3] = '3';
- #endif
- }
- CGameSpyQnR::~CGameSpyQnR()
- {
- Shutdown();
- }
- void CGameSpyQnR::LaunchArcade(void) {
- char *akey = "Software\\GameSpy\\GameSpy Arcade";
- BOOL launched = FALSE;
- HKEY key = NULL;
- int result = 0;
- result = RegOpenKeyEx(HKEY_CURRENT_USER, akey, 0, KEY_READ, &key);
- if (result == ERROR_SUCCESS) {
- StringClass value(true);
- //
- // Get the size of the entry
- //
- DWORD data_size = 0;
- DWORD type = 0;
- result = ::RegQueryValueEx ((HKEY)key, "InstDir", NULL, &type, NULL, &data_size);
- if (result == ERROR_SUCCESS && type == REG_SZ) {
- //
- // Read the entry from the registry
- //
- ::RegQueryValueEx ((HKEY)key, "InstDir", NULL, &type,
- (LPBYTE)value.Get_Buffer(data_size), &data_size);
- }
- if (!value.Is_Empty()) {
- if (value[value.Get_Length()-1] == '\\') {
- value += "Aphex.exe";
- } else {
- value += "\\Aphex.exe";
- }
- RawFileClass file(value);
- if (file.Is_Available()) {
- StringClass params("+svc ");
- params += gamename;
- if (((int)ShellExecute (NULL, "open", value, params, NULL, SW_SHOW)) > 32) {
- launched = TRUE;
- }
- }
- }
- }
- if (!launched) {
- char url[1000] = "";
- #ifdef MULTIPLAYERDEMO
- ::strcpy(url, "http://www.gamespyarcade.com/features/launch.asp?svcname=ccrenegadedemo&distID=432");
- #else
- ::strcpy(url, "http://www.gamespyarcade.com/features/launch.asp?svcname=ccrenegade&distID=391");
- #endif
- ShellExecute (NULL, "open", url, NULL, NULL, SW_SHOW);
- }
- }
- void CGameSpyQnR::Shutdown(void) {
- #ifndef BETACLIENT
- if (m_GSInit) {
- /*
- We don't really need to set the mode to exiting here, since we immediately
- send the statechanged heartbeat and kill off the query sockets
- gamemode = "exiting";*/
- ConsoleBox.Print("Shutting down GameSpy Q&R\n");
- qr_send_exiting(query_reporting_rec);
- qr_shutdown(query_reporting_rec);
- m_GSEnabled = m_GSInit = false;
- }
- #endif
- }
- void CGameSpyQnR::TrackUsage(void) {
- #ifndef WWDEBUG
- char filename[MAX_PATH];
- GetModuleFileName(NULL, filename, sizeof(filename));
- VS_FIXEDFILEINFO version;
- GetVersionInfo(filename, &version);
- int ver = version.dwFileVersionMS;
- StringClass b(true);
- b.Format("%s %s V%d.%3.3d(%s-%d)", "Win-X86", bname, (ver&0xffff0000)>>16, ver&0xffff,
- BuildInfoClass::Get_Builder_Initials(), BuildInfoClass::Get_Build_Number());
- // Send off usage Tracking info to GameSpy
- ptTrackUsage(0, prodid, b.Peek_Buffer(), (cUserOptions::Sku.Get()&0xff)+438, false);
- #endif // WWDEBUG
- }
- void CGameSpyQnR::Init(void) {
- #ifndef BETACLIENT
- if (m_GSEnabled && !m_GSInit && The_Game() && The_Game()->Get_Game_Type() == cGameData::GAME_TYPE_CNC) {
-
- ConsoleBox.Print("Initializing GameSpy Q&R\n");
- BOOL test = FALSE;
- // Init the GameSpy QnR engine
- extern ULONG g_ip_override;
- char ipstr[32];
- char *ip = ipstr;
- if (g_ip_override == INADDR_NONE) {
- if (cUserOptions::PreferredGameSpyNic.Get()) {
- strcpy(ip, cNetUtil::Address_To_String(cUserOptions::PreferredGameSpyNic.Get()));
- } else {
- ip = NULL;
- }
- } else {
- strcpy(ip, cNetUtil::Address_To_String(g_ip_override));
- }
- if (!get_master_count()) {
- GameSpyQnR.Parse_HeartBeat_List(Get_Default_HeartBeat_List());
- }
- test = qr_init(&query_reporting_rec, ip, cUserOptions::GameSpyQueryPort.Get(),
- gamename, secret_key, c_basic_callback, c_info_callback, c_rules_callback,
- c_players_callback, this);
- WWASSERT(!test);
- gcd_init_qr(query_reporting_rec, cdkey_id);
- StartTime = time(NULL);
- m_GSInit = TRUE;
- }
- #endif
- }
- /*******
- DoGameStuff
- Simulate whatever else a game server does
- ********/
- void CGameSpyQnR::DoGameStuff(void)
- {
- // Sleep(100);
- }
- #define BANLIST_RELOAD_TIME (1*60*1000)
- /*******************
- CGameSpyQnR::run
- Simulates a main game loop
- *****************/
- void CGameSpyQnR::Think()
- {
- static DWORD stime = (DWORD)(0 - BANLIST_RELOAD_TIME);
- static DWORD ttime = 0;
- if (TIMEGETTIME() - stime > BANLIST_RELOAD_TIME) {
- GameSpyBanList.LoadBans();
- stime = TIMEGETTIME();
- }
- // check twice a second
- if (TIMEGETTIME() - ttime > 500) {
- GameSpyBanList.Think();
- ttime = TIMEGETTIME();
- }
-
- #ifndef BETACLIENT
- // DoGameStuff();
- if (m_GSInit && m_GSEnabled && GameInitMgrClass::Is_LAN_Initialized() &&
- !CombatManager::Is_Loading_Level()) {
- qr_process_queries(query_reporting_rec);
- gcd_think();
- }
- #endif
- }
- /*************
- basic_callback
- sends a (sample) response to the basic query
- includes the following keys:
- \gamename\
- \gamever\
- \location\
- *************/
- void CGameSpyQnR::basic_callback(char *outbuf, int maxlen)
- {
- WWDEBUG_SAY(("-->GS_QnR -- Basic callback\n"));
- WWASSERT(!CombatManager::Is_Loading_Level());
- if (!maxlen || !outbuf) return;
- outbuf[0] = 0;
- StringClass b(true);
- b.Format("%d", BuildInfoClass::Get_Build_Number());
- sprintf(outbuf, "\\gamename\\%s\\gamever\\%s", gamename, b.Peek_Buffer());
- // sprintf(outbuf, "\\gamename\\%s\\gamever\\%s\\location\\%d", gamename, b.Peek_Buffer(), 1);
- #ifdef WWDEBUG
- StringClass tstr(true);
- tstr.Format("GS_QnR -- Basic callback, sent: %s\n",outbuf);
- OutputDebugString(tstr.Peek_Buffer());
- #endif
- WWDEBUG_SAY(("<--GS_QnR -- Basic callback\n"));
- // printf("Basic callback, sent: %s\n\n",outbuf);
- }
- /************
- info_callback
- Sends a (sample) response to the info query
- including the following keys:
- \hostname\
- \hostport\
- \mapname\
- \gametype\
- \numplayers\
- \maxplayers\
- \gamemode\
- ************/
- void CGameSpyQnR::info_callback(char *outbuf, int maxlen)
- {
- WWDEBUG_SAY(("-->GS_QnR -- Info callback\n"));
- WWASSERT(!CombatManager::Is_Loading_Level());
- if (!maxlen || !outbuf) return;
- outbuf[0] = 0;
- while(1) {
- StringClass value(true);
- WideStringClass(The_Game()->Get_Game_Title()).Convert_To(value);
- if (value.Get_Length() > 25) {
- value[25] = 0;
- }
- if (!Append_InfoKey_Pair(outbuf, maxlen, "hostname", value)) break;
- value.Format("%d", The_Game()->Get_Port());
- if (!Append_InfoKey_Pair(outbuf, maxlen, "hostport", value)) break;
- value = The_Game()->Get_Map_Name();
- char *s = value.Peek_Buffer();
- char *t = strrchr(s, '.');
- if (t) value.Erase(t-s, s+strlen(s)-t);
- if (!Append_InfoKey_Pair(outbuf, maxlen, "mapname", value)) break;
- value = The_Game()->Get_Mod_Name();
- if (!value.Is_Empty()) {
- s = value.Peek_Buffer();
- t = strrchr(s, '.');
- if (t) value.Erase(t-s, s+strlen(s)-t);
- if (!Append_InfoKey_Pair(outbuf, maxlen, "gametype", value)) break;
- } else {
- if (!Append_InfoKey_Pair(outbuf, maxlen, "gametype", "C&C")) break;
- }
- int pcount = 0;
- for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ()
- ; player_node != NULL; player_node = player_node->Next ()) {
- cPlayer *player = player_node->Data ();
- WWASSERT (player != NULL);
- if (player->Get_Is_Active().Is_False()) {
- // if (player->Get_Is_Active().Is_False() || !player->Is_Human()) {
- continue;
- }
- pcount++;
- }
- value.Format("%d", pcount);
- if (!Append_InfoKey_Pair(outbuf, maxlen, "numplayers", value)) break;
- value.Format("%d", The_Game()->Get_Max_Players());
- if (!Append_InfoKey_Pair(outbuf, maxlen, "maxplayers", value)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "gamemode", "openplaying")) break;
- break;
- }
- #ifdef WWDEBUG
- StringClass tstr(true);
- tstr.Format("GS_QnR -- Info callback, sent: %s\n",outbuf);
- OutputDebugString(tstr.Peek_Buffer());
- #endif
- WWDEBUG_SAY(("<--GS_QnR -- Info callback\n"));
- }
- /***************
- rules_callback
- Sends a response to the rules query. You may
- need to add custom fields for your game in here. Some are provided
- as an example
- The following rules are included:
- \timelimit\
- \fraglimit\
- \teamplay\
- \rankedserver\
- ****************/
- void CGameSpyQnR::rules_callback(char *outbuf, int maxlen)
- {
- static StringClass b;
- WWDEBUG_SAY(("-->GS_QnR -- Rules callback\n"));
- WWASSERT(!CombatManager::Is_Loading_Level());
- if (!maxlen || !outbuf) return;
- outbuf[0] = 0;
- while(1) {
- StringClass value(true);
- const char *zero = "0"; const char *one = "1";
- // WideStringClass timelimit;
- // The_Game()->Get_Time_Limit_Text(timelimit);
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "timeleft", timelimit)) break;
- // value.Format("%d", The_Game()->Get_Time_Limit_Minutes());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "timelimit", value)) break;
- // if (b.Is_Empty()) {
- // char filename[MAX_PATH];
- // GetModuleFileName(NULL, filename, sizeof(filename));
- // VS_FIXEDFILEINFO version;
- // GetVersionInfo(filename, &version);
- // int ver = version.dwFileVersionMS;
- //
- // b.Format("%s %s V%d.%3.3d(%s-%d)", "Win-X86", bname, (ver&0xffff0000)>>16, ver&0xffff,
- // BuildInfoClass::Get_Builder_Initials(), BuildInfoClass::Get_Build_Number());
- // }
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "Version", b)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "ServerMOTD", WideStringClass(The_Game()->Get_Motd()))) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "OwnerName", The_Game()->Get_Owner())) break;
- value.Format("%d", (int)cUserOptions::BandwidthBps.Get());
- if (!Append_InfoKey_Pair(outbuf, maxlen, "BW", value)) break;
- // int utime = time(NULL) - StartTime;
- // value.Format("%d:%d:%d:%d", utime/60/60/24, (utime/60/60)%24, (utime/60)%60, utime%60);
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "Uptime", value)) break;
- if (!Append_InfoKey_Pair(outbuf, maxlen, "CSVR", ConsoleBox.Is_Exclusive() ? one : zero)) break;
- if (!Append_InfoKey_Pair(outbuf, maxlen, "DED", The_Game()->IsDedicated.Get() ? one : zero)) break;
- if (!Append_InfoKey_Pair(outbuf, maxlen, "DG", The_Game()->DriverIsAlwaysGunner.Get() ? one : zero)) break;
- if (!Append_InfoKey_Pair(outbuf, maxlen, "password", The_Game()->IsPassworded.Get() ? one : zero)) break;
- if (!Append_InfoKey_Pair(outbuf, maxlen, "TC", The_Game()->IsTeamChangingAllowed.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "WeaponSpawning", The_Game()->SpawnWeapons.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "TeamRemix", The_Game()->RemixTeams.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "BuildingRepair", The_Game()->CanRepairBuildings.Get() ? one : zero)) break;
- if (!Append_InfoKey_Pair(outbuf, maxlen, "FF", The_Game()->IsFriendlyFirePermitted.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "BaseDestructionEndsGame", The_Game()->As_Cnc()->BaseDestructionEndsGame.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "BeaconPlacementEndsGame", The_Game()->As_Cnc()->BeaconPlacementEndsGame.Get() ? one : zero)) break;
- // value.Format("%d", (int)The_Game()->Get_Radar_Mode());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "RadarMode", value)) break;
- value.Format("%d", The_Game()->As_Cnc()->Get_Starting_Credits());
- if (!Append_InfoKey_Pair(outbuf, maxlen, "SC", value)) break;
-
- // cTeam * p_team;
- // for (SLNode<cTeam> * objnode = cTeamManager::Get_Team_Object_List()->Head()
- // ; objnode != NULL; objnode = objnode->Next()) {
- //
- // p_team = objnode->Data();
- // WWASSERT(p_team != NULL);
- //
- // if (p_team->Get_Id() == PLAYERTYPE_GDI) {
- // value.Format("%.0f", p_team->Get_Score());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "GDI_Score", value)) break;
- // } else if (p_team->Get_Id() == PLAYERTYPE_NOD) {
- // value.Format("%.0f", p_team->Get_Score());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "NOD_Score", value)) break;
- // }
- // }
- // These don't apply to LAN/GameSpy Games
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "ClanMatch", The_Game()->IsClanGame.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "Laddered", The_Game()->IsLaddered.Get() ? one : zero)) break;
- // if (!Append_InfoKey_Pair(outbuf, maxlen, "QuickMatch", The_Game()->Is_QuickMatch_Server() ? one : zero)) break;
- break;
- }
- #ifdef WWDEBUG
- StringClass tstr(true);
- tstr.Format("GS_QnR -- Rules callback, sent: %s\n",outbuf);
- OutputDebugString(tstr.Peek_Buffer());
- #endif
- WWDEBUG_SAY(("<--GS_QnR -- Rules callback\n"));
- }
- BOOL CGameSpyQnR::Parse_HeartBeat_List(const char *list) {
- BOOL master_added = false;
- char *str = new char[strlen(list)+1];
- strcpy(str, list);
- char *t = str;
- clear_master_list();
- while (t) {
- WORD port = 27900;
- struct sockaddr_in taddr;
- memset(&taddr, 0, sizeof(taddr));
- taddr.sin_family = AF_INET;
- char *q = strchr(t, ',');
- if (q) *q++ = 0;
- char *s = strchr(t, ':');
- if (s) {
- // Parse off the port value
- *s++ = 0;
- char *p = s;
- if (atoi(p)) port = atoi(p);
- }
- // skip white space
- while (*t == ' ' || *t == '\t') t++;
- // process the address
- if (*t && get_sockaddrin(t, port, &taddr, NULL)) {
- add_master(&taddr);
- master_added = true;
- }
- t = q;
- }
- delete [] str;
- if (!master_added) {
- ConsoleBox.Print("Error processing HeartBeat List: <%s>\n", list);
- ConsoleBox.Print("Assigning default HeartBeat List\n");
- return false;
- }
- return true;
- }
- BOOL CGameSpyQnR::Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const char *value) {
- WWASSERT(value);
- WWASSERT(outbuf);
- WWASSERT(key);
- int clen = strlen(outbuf);
- if (clen + strlen(key) + strlen(value) + 3 > (unsigned int)maxlen) return FALSE;
- char *s = new char[strlen(value)+1];
- strcpy(s, value);
- char *t = s;
- while (*t) {
- if (*t == '\\') *t = '/';
- t++;
- }
- t = strtrim(s);
- sprintf(&outbuf[clen], "\\%s\\%s", key, t);
- delete [] s;
- return TRUE;
- }
- BOOL CGameSpyQnR::Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const WideStringClass &value) {
- static StringClass text;
- value.Convert_To(text);
- return Append_InfoKey_Pair(outbuf, maxlen, key, text.Peek_Buffer());
- }
- BOOL CGameSpyQnR::Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const StringClass &value) {
- return Append_InfoKey_Pair(outbuf, maxlen, key, value.Peek_Buffer());
- }
- /***************
- players_callback
- sends the players and their information.
- Note that \ characters are not stripped out of player names. If
- your game allows players or team names with the \ character, you will need
- to strip or change it here.
- The following keys are included for each player:
- \player_N\
- \frags_N\
- \deaths_N\
- \skill_N\
- \ping_N\
- \team_N\
- ***************/
- void CGameSpyQnR::players_callback(char *outbuf, int maxlen)
- {
- // Send the minimum for now to reduce Bandwidth usage.
- outbuf[0] = 0;
- return;
- int pindex = 0;
- WWDEBUG_SAY(("-->GS_QnR -- Players callback\n"));
- WWASSERT(!CombatManager::Is_Loading_Level());
- if (!maxlen || !outbuf) return;
- outbuf[0] = 0;
- for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ();
- player_node != NULL;
- player_node = player_node->Next ()) {
- cPlayer *player = player_node->Data ();
- WWASSERT (player != NULL);
- if (player->Get_Is_Active().Is_False()) {
- // if (player->Get_Is_Active().Is_False() || !player->Is_Human()) {
- continue;
- }
- StringClass keyval(true);
- StringClass value(true);
- // Set the Player's Name [Team]
- value = player->Get_Name();
- if (player->Get_Player_Type() == PLAYERTYPE_NOD) {
- value += " [NOD]";
- } else if (player->Get_Player_Type() == PLAYERTYPE_GDI) {
- value += " [GDI]";
- }
- keyval.Format("player_%d", pindex);
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
- // Set the Player's Score
- keyval.Format("frags_%d", pindex);
- value.Format("%.0f", player->Get_Score());
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
- // Set the Player's Credits
- // keyval.Format("credits_%d", pindex);
- // value.Format("%.0f", player->Get_Money());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
- // Set the Player's Ping to Server
- keyval.Format("ping_%d", pindex);
- value.Format("%d", player->Get_Ping());
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
- // Set the Player's Kills
- // keyval.Format("kills_%d", pindex);
- // value.Format("%d", player->Get_Kills());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
- // Set the Player's Deaths
- // keyval.Format("deaths_%d", pindex);
- // value.Format("%d", player->Get_Deaths());
- // if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
- /* SmartGameObj *game_obj = player->Get_GameObj ();
- if (game_obj != NULL && game_obj->As_SoldierGameObj () != NULL) {
- // Set the Player's Class (ie: Technician,Sakura,Havok)
- keyval.Format("class_%d", pindex);
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(),
- WideStringClass(TRANSLATE(game_obj->Get_Translated_Name_ID())) )) break;
-
- SoldierGameObj *soldier = game_obj->As_SoldierGameObj();
- VehicleGameObj *vehicle = soldier->Get_Vehicle ();
- // If they're in a vehicle set the vehicle name
- keyval.Format("vehicle_%d", pindex);
- if (vehicle != NULL) {
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(),
- WideStringClass(TRANSLATE(vehicle->Get_Translated_Name_ID())) )) break;
- } else {
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), "None")) break;
- }
- } else {
- // If there's no gameobj then set vehicle/class to unknown
- keyval.Format("class_%d", pindex);
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), "Unknown")) break;
- keyval.Format("vehicle_%d", pindex);
- if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), "Unknown")) break;
- } */
- pindex++;
- }
- #ifdef WWDEBUG
- StringClass tstr(true);
- tstr.Format("GS_QnR -- Players callback, sent: %s\n",outbuf);
- OutputDebugString(tstr.Peek_Buffer());
- #endif
- WWDEBUG_SAY(("<--GS_QnR -- Players callback\n"));
- return;
- }
- /************
- We'll actually start up two completely seperate "game servers"
- Each one initializes the Query & Reporting SDK and calls processs on it during
- their main loop
- ************/
- /*
- int main(int argc, char* argv[])
- {
- CGameSpyQnR mygame1("Test Game Server 1"), mygame2("Test Game Server 2");
- srand( GetTickCount() );
-
- printf("Press any key to quit\n");
- while (!_kbhit())
- {
- mygame1.run();
- mygame2.run();
- }
- return 0;
- }
- */
|