| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513 |
- /*
- ** Command & Conquer Generals(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/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: PersistentStorageThread.cpp //////////////////////////////////////////////////////
- // GameSpy Persistent Storage thread
- // This thread communicates with GameSpy's persistent storage server
- // and talks through a message queue with the rest of
- // the game.
- // Author: Matthew D. Campbell, July 2002
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/UserPreferences.h"
- #include "Common/PlayerTemplate.h"
- #include "GameNetwork/GameSpy/PersistentStorageThread.h"
- #include "mutex.h"
- #include "thread.h"
- #include "Common/StackDump.h"
- #include "Common/SubsystemInterface.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- //-------------------------------------------------------------------------
- PSRequest::PSRequest()
- {
- player.reset();
- requestType = PSREQUEST_READPLAYERSTATS;
- addDiscon = addDesync = FALSE;
- lastHouse = -1;
- }
- //-------------------------------------------------------------------------
- #define DEBUG_MAP(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \
- { \
- if (it->second > 0) \
- { \
- DEBUG_LOG(("%s(%d): %d\n", #x, it->first, it->second)); \
- } \
- }
- static void debugDumpPlayerStats( const PSPlayerStats& stats )
- {
- DEBUG_LOG(("-----------------------------------------\n"));
- DEBUG_LOG(("Tracking player stats for player %d:\n", stats.id));
- PerGeneralMap::const_iterator it;
- DEBUG_MAP(wins);
- DEBUG_MAP(losses);
- DEBUG_MAP(games);
- DEBUG_MAP(duration);
- DEBUG_MAP(unitsKilled);
- DEBUG_MAP(unitsLost);
- DEBUG_MAP(unitsBuilt);
- DEBUG_MAP(buildingsKilled);
- DEBUG_MAP(buildingsLost);
- DEBUG_MAP(buildingsBuilt);
- DEBUG_MAP(earnings);
- DEBUG_MAP(techCaptured);
- DEBUG_MAP(discons);
- DEBUG_MAP(desyncs);
- DEBUG_MAP(surrenders);
- DEBUG_MAP(gamesOf2p);
- DEBUG_MAP(gamesOf3p);
- DEBUG_MAP(gamesOf4p);
- DEBUG_MAP(gamesOf5p);
- DEBUG_MAP(gamesOf6p);
- DEBUG_MAP(gamesOf7p);
- DEBUG_MAP(gamesOf8p);
- DEBUG_MAP(customGames);
- DEBUG_MAP(QMGames);
-
- if (stats.locale > 0)
- {
- DEBUG_LOG(("Locale: %d\n", stats.locale));
- }
-
- if (stats.gamesAsRandom > 0)
- {
- DEBUG_LOG(("gamesAsRandom: %d\n", stats.gamesAsRandom));
- }
- if (stats.options.length())
- {
- DEBUG_LOG(("Options: %s\n", stats.options.c_str()));
- }
- if (stats.systemSpec.length())
- {
- DEBUG_LOG(("systemSpec: %s\n", stats.systemSpec.c_str()));
- }
- if (stats.lastFPS > 0.0f)
- {
- DEBUG_LOG(("lastFPS: %g\n", stats.lastFPS));
- }
- if (stats.battleHonors > 0)
- {
- DEBUG_LOG(("battleHonors: %x\n", stats.battleHonors));
- }
- if (stats.challengeMedals > 0)
- {
- DEBUG_LOG(("challengeMedals: %x\n", stats.challengeMedals));
- }
- if (stats.lastGeneral >= 0)
- {
- DEBUG_LOG(("lastGeneral: %d\n", stats.lastGeneral));
- }
- if (stats.gamesInRowWithLastGeneral >= 0)
- {
- DEBUG_LOG(("gamesInRowWithLastGeneral: %d\n", stats.gamesInRowWithLastGeneral));
- }
- if (stats.builtSCUD >= 0)
- {
- DEBUG_LOG(("builtSCUD: %d\n", stats.builtSCUD));
- }
- if (stats.builtNuke >= 0)
- {
- DEBUG_LOG(("builtNuke: %d\n", stats.builtNuke));
- }
- if (stats.builtParticleCannon >= 0)
- {
- DEBUG_LOG(("builtParticleCannon: %d\n", stats.builtParticleCannon));
- }
- if (stats.winsInARow >= 0)
- {
- DEBUG_LOG(("winsInARow: %d\n", stats.winsInARow));
- }
- if (stats.maxWinsInARow >= 0)
- {
- DEBUG_LOG(("maxWinsInARow: %d\n", stats.maxWinsInARow));
- }
- if (stats.disconsInARow >= 0)
- {
- DEBUG_LOG(("disconsInARow: %d\n", stats.disconsInARow));
- }
- if (stats.maxDisconsInARow >= 0)
- {
- DEBUG_LOG(("maxDisconsInARow: %d\n", stats.maxDisconsInARow));
- }
- if (stats.lossesInARow >= 0)
- {
- DEBUG_LOG(("lossesInARow: %d\n", stats.lossesInARow));
- }
- if (stats.maxLossesInARow >= 0)
- {
- DEBUG_LOG(("maxLossesInARow: %d\n", stats.maxLossesInARow));
- }
- if (stats.desyncsInARow >= 0)
- {
- DEBUG_LOG(("desyncsInARow: %d\n", stats.desyncsInARow));
- }
- if (stats.maxDesyncsInARow >= 0)
- {
- DEBUG_LOG(("maxDesyncsInARow: %d\n", stats.maxDesyncsInARow));
- }
- if (stats.lastLadderPort >= 0)
- {
- DEBUG_LOG(("lastLadderPort: %d\n", stats.lastLadderPort));
- }
- if (stats.lastLadderHost.length())
- {
- DEBUG_LOG(("lastLadderHost: %s\n", stats.lastLadderHost.c_str()));
- }
- }
- //-------------------------------------------------------------------------
- #define INCORPORATE_MAP(x) for (it = other.x.begin(); it != other.x.end(); ++it) \
- { \
- if (it->second > 0) \
- { \
- x[it->first] = it->second; \
- } \
- }
- void PSPlayerStats::incorporate( const PSPlayerStats& other )
- {
- PerGeneralMap::const_iterator it;
- INCORPORATE_MAP(wins);
- INCORPORATE_MAP(losses);
- INCORPORATE_MAP(games);
- INCORPORATE_MAP(duration);
- INCORPORATE_MAP(unitsKilled);
- INCORPORATE_MAP(unitsLost);
- INCORPORATE_MAP(unitsBuilt);
- INCORPORATE_MAP(buildingsKilled);
- INCORPORATE_MAP(buildingsLost);
- INCORPORATE_MAP(buildingsBuilt);
- INCORPORATE_MAP(earnings);
- INCORPORATE_MAP(techCaptured);
- //GS Clear all disconnects so that we don't retain any that were
- //previously reported as 1 by updateAdditionalGameSpyDisconnections
- discons.clear();
- INCORPORATE_MAP(discons);
- INCORPORATE_MAP(desyncs);
- INCORPORATE_MAP(surrenders);
- INCORPORATE_MAP(gamesOf2p);
- INCORPORATE_MAP(gamesOf3p);
- INCORPORATE_MAP(gamesOf4p);
- INCORPORATE_MAP(gamesOf5p);
- INCORPORATE_MAP(gamesOf6p);
- INCORPORATE_MAP(gamesOf7p);
- INCORPORATE_MAP(gamesOf8p);
- INCORPORATE_MAP(customGames);
- INCORPORATE_MAP(QMGames);
-
- if (other.locale > 0)
- {
- locale = other.locale;
- }
-
- if (other.gamesAsRandom > 0)
- {
- gamesAsRandom = other.gamesAsRandom;
- }
- if (other.options.length())
- {
- options = other.options;
- }
- if (other.systemSpec.length())
- {
- systemSpec = other.systemSpec;
- }
- if (other.lastFPS > 0.0f)
- {
- lastFPS = other.lastFPS;
- }
- if (other.battleHonors > 0)
- {
- battleHonors |= other.battleHonors;
- }
- if (other.challengeMedals > 0)
- {
- challengeMedals |= other.challengeMedals;
- }
- if (other.lastGeneral >= 0)
- {
- lastGeneral = other.lastGeneral;
- }
- if (other.gamesInRowWithLastGeneral >= 0)
- {
- gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral;
- }
- if (other.builtParticleCannon >= 0)
- {
- builtParticleCannon = other.builtParticleCannon;
- }
- if (other.builtNuke >= 0)
- {
- builtNuke = other.builtNuke;
- }
- if (other.builtSCUD >= 0)
- {
- builtSCUD = other.builtSCUD;
- }
- if (other.winsInARow >= 0)
- {
- winsInARow = other.winsInARow;
- }
- if (other.maxWinsInARow >= 0)
- {
- maxWinsInARow = other.maxWinsInARow;
- }
- if (other.lossesInARow >= 0)
- {
- lossesInARow = other.lossesInARow;
- }
- if (other.maxLossesInARow >= 0)
- {
- maxLossesInARow = other.maxLossesInARow;
- }
- if (other.disconsInARow >= 0)
- {
- disconsInARow = other.disconsInARow;
- }
- if (other.maxDisconsInARow >= 0)
- {
- maxDisconsInARow = other.maxDisconsInARow;
- }
- if (other.desyncsInARow >= 0)
- {
- desyncsInARow = other.desyncsInARow;
- }
- if (other.maxDesyncsInARow >= 0)
- {
- maxDesyncsInARow = other.maxDesyncsInARow;
- }
- if (other.lastLadderPort >= 0)
- {
- lastLadderPort = other.lastLadderPort;
- }
- if (other.lastLadderHost.length())
- {
- lastLadderHost = other.lastLadderHost;
- }
- }
- PSPlayerStats::PSPlayerStats( const PSPlayerStats& other )
- {
- incorporate(other);
- id = other.id;
- locale = other.locale;
- gamesAsRandom = other.gamesAsRandom;
- options = other.options;
- systemSpec = other.systemSpec;
- lastFPS = other.lastFPS;
- lastGeneral = other.lastGeneral;
- gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral;
- builtParticleCannon = other.builtParticleCannon;
- builtNuke = other.builtNuke;
- builtSCUD = other.builtSCUD;
- challengeMedals = other.challengeMedals;
- battleHonors = other.battleHonors;
- winsInARow = other.winsInARow;
- maxWinsInARow = other.maxWinsInARow;
- lossesInARow = other.lossesInARow;
- maxLossesInARow = other.maxLossesInARow;
- disconsInARow = other.disconsInARow;
- maxDisconsInARow = other.maxDisconsInARow;
- desyncsInARow = other.desyncsInARow;
- maxDesyncsInARow = other.maxDesyncsInARow;
- lastLadderHost = other.lastLadderHost;
- lastLadderPort = other.lastLadderPort;
- }
- //-------------------------------------------------------------------------
- typedef std::queue<PSRequest> RequestQueue;
- typedef std::queue<PSResponse> ResponseQueue;
- class PSThreadClass;
- class GameSpyPSMessageQueue : public GameSpyPSMessageQueueInterface
- {
- public:
- virtual ~GameSpyPSMessageQueue();
- GameSpyPSMessageQueue();
- virtual void startThread( void );
- virtual void endThread( void );
- virtual Bool isThreadRunning( void );
- virtual void addRequest( const PSRequest& req );
- virtual Bool getRequest( PSRequest& req );
- virtual void addResponse( const PSResponse& resp );
- virtual Bool getResponse( PSResponse& resp );
- virtual void trackPlayerStats( PSPlayerStats stats );
- virtual PSPlayerStats findPlayerStatsByID( Int id );
- PSThreadClass* getThread( void );
- Int getLocalPlayerID(void) { return m_localPlayerID; }
- void setLocalPlayerID(Int localPlayerID) { m_localPlayerID = localPlayerID; }
- std::string getEmail() { return m_email; }
- std::string getNick() { return m_nick; }
- std::string getPassword() { return m_password; }
- void setEmail(std::string email) { m_email = email; }
- void setNick(std::string nick) { m_nick = nick; }
- void setPassword(std::string password) { m_password = password; }
- private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- PSThreadClass *m_thread;
- Int m_localPlayerID;
- std::string m_email;
- std::string m_nick;
- std::string m_password;
- std::map<Int, PSPlayerStats> m_playerStats;
- };
- GameSpyPSMessageQueueInterface* GameSpyPSMessageQueueInterface::createNewMessageQueue( void )
- {
- return NEW GameSpyPSMessageQueue;
- }
- GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue = NULL;
- #define MESSAGE_QUEUE ((GameSpyPSMessageQueue *)TheGameSpyPSMessageQueue)
- //-------------------------------------------------------------------------
- class PSThreadClass : public ThreadClass
- {
- public:
- PSThreadClass() : ThreadClass()
- {
- m_loginOK = m_sawLocalData = m_doneTryingToLogin = false;
- m_opCount = 0;
- }
- void Thread_Function();
- void persAuthCallback( Bool val ) { m_loginOK = val; m_doneTryingToLogin = true; }
- void decrOpCount( void ) { --m_opCount; }
- void incrOpCount( void ) { ++m_opCount; }
- Int getOpCount( void ) { return m_opCount; }
- Bool sawLocalPlayerData( void ) { return m_sawLocalData; }
- void gotLocalPlayerData( void ) { m_sawLocalData = TRUE; }
- private:
- Bool tryConnect( void );
- Bool tryLogin( Int id, std::string nick, std::string password, std::string email );
- Bool m_loginOK;
- Bool m_doneTryingToLogin;
- Int m_opCount;
- Bool m_sawLocalData;
- };
- //-------------------------------------------------------------------------
- GameSpyPSMessageQueue::GameSpyPSMessageQueue()
- {
- m_thread = NULL;
- m_localPlayerID = 0;
- }
- GameSpyPSMessageQueue::~GameSpyPSMessageQueue()
- {
- endThread();
- }
- void GameSpyPSMessageQueue::startThread( void )
- {
- if (!m_thread)
- {
- m_thread = NEW PSThreadClass;
- m_thread->Execute();
- }
- else
- {
- if (!m_thread->Is_Running())
- {
- m_thread->Execute();
- }
- }
- }
- void GameSpyPSMessageQueue::endThread( void )
- {
- if (m_thread)
- delete m_thread;
- m_thread = NULL;
- }
- Bool GameSpyPSMessageQueue::isThreadRunning( void )
- {
- return (m_thread) ? m_thread->Is_Running() : false;
- }
- void GameSpyPSMessageQueue::addRequest( const PSRequest& req )
- {
- MutexClass::LockClass m(m_requestMutex);
- if (m.Failed())
- return;
- m_requests.push(req);
- }
- Bool GameSpyPSMessageQueue::getRequest( PSRequest& req )
- {
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
- }
- void GameSpyPSMessageQueue::addResponse( const PSResponse& resp )
- {
- MutexClass::LockClass m(m_responseMutex);
- if (m.Failed())
- return;
- m_responses.push(resp);
- }
- Bool GameSpyPSMessageQueue::getResponse( PSResponse& resp )
- {
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
- }
- PSThreadClass* GameSpyPSMessageQueue::getThread( void )
- {
- return m_thread;
- }
- void GameSpyPSMessageQueue::trackPlayerStats( PSPlayerStats stats )
- {
- #ifdef DEBUG_LOGGING
- debugDumpPlayerStats( stats );
- DEBUG_ASSERTCRASH(stats.id != 0, ("Tracking stats with ID of 0\n"));
- #endif
- PSPlayerStats newStats;
- std::map<Int, PSPlayerStats>::iterator it = m_playerStats.find(stats.id);
- if (it != m_playerStats.end())
- {
- newStats = it->second;
- newStats.incorporate(stats);
- m_playerStats[stats.id] = newStats;
- }
- else
- {
- m_playerStats[stats.id] = stats;
- }
- }
- PSPlayerStats GameSpyPSMessageQueue::findPlayerStatsByID( Int id )
- {
- std::map<Int, PSPlayerStats>::iterator it = m_playerStats.find(id);
- if (it != m_playerStats.end())
- {
- return it->second;
- }
- PSPlayerStats empty;
- empty.id = 0;
- return empty;
- }
- //-------------------------------------------------------------------------
- Bool PSThreadClass::tryConnect( void )
- {
- Int result;
- DEBUG_LOG(("m_opCount = %d - opening connection\n", m_opCount));
- if (IsStatsConnected())
- {
- DEBUG_LOG(("connection already open!\n"));
- return true;
- }
- // this may block for 1-2 seconds (according to GS) so it's nice we're not in the UI thread :)
- result = InitStatsConnection(0);
- #ifdef DEBUG_LOGGING
- static const char *retValStrings[6] = {
- "GE_NOERROR",
- "GE_NOSOCKET",
- "GE_NODNS",
- "GE_NOCONNECT",
- "GE_BUSY",
- "GE_DATAERROR"
- };
- #endif // DEBUG_LOGGING
- if (result != GE_NOERROR)
- {
- DEBUG_LOG(("InitStatsConnection() returned %d (%s)\n", result, retValStrings[result]));
- return false;
- }
- else
- {
- DEBUG_LOG(("InitStatsConnection() succeeded\n"));
- }
- return true;
- }
- static void persAuthCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance)
- {
- PSThreadClass *t = (PSThreadClass *)instance;
- DEBUG_LOG(("Auth callback: localid: %d profileid: %d auth: %d err: %s\n",localid, profileid, authenticated, errmsg));
- if (t)
- t->persAuthCallback(authenticated != 0);
- }
- Bool PSThreadClass::tryLogin( Int id, std::string nick, std::string password, std::string email )
- {
- char validate[33];
- DEBUG_LOG(("PSThreadClass::tryLogin id = %d, nick = %s, password = %s, email = %s\n", id, nick.c_str(), password.c_str(), email.c_str()));
- /***********
- We'll go ahead and start the authentication, using a Presence & Messaging SDK
- profileid / password. To generate the new validation token, we'll need to pass
- in the password for the profile we are authenticating.
- Again, if this is done in a client/server setting, with the Persistent Storage
- access being done on the server, and the P&M SDK is used on the client, the
- server will need to send the challenge (GetChallenge(NULL)) to the client, the
- client will create the validation token using GenerateAuth, and send it
- back to the server for use in PreAuthenticatePlayerPM
- ***********/
- char *munkeeHack = strdup(password.c_str()); // GenerateAuth takes a char*, not a const char* :P
- GenerateAuth(GetChallenge(NULL), munkeeHack, validate);
- free (munkeeHack);
- /************
- After we get the validation token, we pass it and the profileid of the user
- we are authenticating into PreAuthenticatePlayerPM.
- We pass the same authentication callback as for the first user, but a different
- localid this time.
- ************/
- m_loginOK = false;
- m_doneTryingToLogin = false;
- PreAuthenticatePlayerPM(id, id, validate, ::persAuthCallback, this);
- while (!m_doneTryingToLogin && IsStatsConnected())
- PersistThink();
- DEBUG_LOG(("Persistant Storage Login success %d\n", m_loginOK));
- return m_loginOK;
- }
- static void getPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, char *data, int len, void *instance)
- {
- DEBUG_LOG(("Data get callback: localid: %d profileid: %d success: %d len: %d data: %s\n",localid, profileid, success, len, data));
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
- t->decrOpCount();
- PSResponse resp;
- if (!success)
- {
- resp.responseType = PSResponse::PSRESPONSE_COULDNOTCONNECT;
- resp.player.id = profileid;
- TheGameSpyPSMessageQueue->addResponse(resp);
- if (!t->getOpCount() && !t->sawLocalPlayerData())
- {
- // we haven't gotten stats for ourselves - try again
- DEBUG_LOG(("Requesting retry for reading local player's stats\n"));
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- req.player.id = MESSAGE_QUEUE->getLocalPlayerID();
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- return;
- }
- if (profileid == MESSAGE_QUEUE->getLocalPlayerID())
- {
- t->gotLocalPlayerData();
- DEBUG_LOG(("getPersistentDataCallback() - got local player info\n"));
- // check if we have discons we should update on the server
- UserPreferences pref;
- AsciiString userPrefFilename;
- userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID());
- DEBUG_LOG(("using the file %s\n", userPrefFilename.str()));
- pref.load(userPrefFilename);
- Int addedInDesyncs2 = pref.getInt("0", 0);
- DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2));
- if (addedInDesyncs2 < 0)
- addedInDesyncs2 = 10;
- Int addedInDesyncs3 = pref.getInt("1", 0);
- DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3));
- if (addedInDesyncs3 < 0)
- addedInDesyncs3 = 10;
- Int addedInDesyncs4 = pref.getInt("2", 0);
- DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4));
- if (addedInDesyncs4 < 0)
- addedInDesyncs4 = 10;
- Int addedInDiscons2 = pref.getInt("3", 0);
- DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2));
- if (addedInDiscons2 < 0)
- addedInDiscons2 = 10;
- Int addedInDiscons3 = pref.getInt("4", 0);
- DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3));
- if (addedInDiscons3 < 0)
- addedInDiscons3 = 10;
- Int addedInDiscons4 = pref.getInt("5", 0);
- DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4));
- if (addedInDiscons4 < 0)
- addedInDiscons4 = 10;
- DEBUG_LOG(("addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n",
- addedInDesyncs2, addedInDesyncs3, addedInDesyncs4,
- addedInDiscons2, addedInDiscons3, addedInDiscons4));
- if (addedInDesyncs2 || addedInDesyncs3 || addedInDesyncs4 || addedInDiscons2 || addedInDiscons3 || addedInDiscons4)
- {
- DEBUG_LOG(("We have a previous discon we can attempt to update! Bummer...\n"));
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS;
- req.email = MESSAGE_QUEUE->getEmail();
- req.nick = MESSAGE_QUEUE->getNick();
- req.password = MESSAGE_QUEUE->getPassword();
- req.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:"");
- req.player.id = profileid;
- req.addDesync = FALSE;
- req.addDiscon = FALSE;
- req.lastHouse = 0;
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- }
- resp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS;
- resp.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:"");
- resp.player.id = profileid;
- TheGameSpyPSMessageQueue->addResponse(resp);
- }
- static void setPersistentDataLocaleCallback(int localid, int profileid, persisttype_t type, int index, int success, void *instance)
- {
- DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success));
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
- t->decrOpCount();
- }
- static void setPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, void *instance)
- {
- DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d\n", localid, profileid, success));
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
- if (success)
- {
- UserPreferences pref;
- AsciiString userPrefFilename;
- userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", profileid);
- DEBUG_LOG(("setPersistentDataCallback - writing stats to file %s\n", userPrefFilename.str()));
- pref.load(userPrefFilename);
- pref.clear();
- pref.write();
- }
- t->decrOpCount();
- }
- struct CDAuthInfo
- {
- Bool success;
- Bool done;
- Int id;
- };
- void preAuthCDCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance)
- {
- DEBUG_LOG(("preAuthCDCallback(): profileid: %d auth: %d err: %s\n", profileid, authenticated, errmsg));
- CDAuthInfo *authInfo = (CDAuthInfo *)instance;
- authInfo->success = authenticated;
- authInfo->done = TRUE;
- authInfo->id = profileid;
- }
- static void getPreorderCallback(int localid, int profileid, persisttype_t type, int index, int success, char *data, int len, void *instance)
- {
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
- t->decrOpCount();
- PSResponse resp;
- if (!success)
- {
- DEBUG_LOG(("Failed getPreorderCallback()\n"));
- return;
- }
- resp.responseType = PSResponse::PSRESPONSE_PREORDER;
- resp.preorder = (data && strcmp(data, "\\preorder\\1") == 0);
- DEBUG_LOG(("getPreorderCallback() - data was '%s'\n", data));
- TheGameSpyPSMessageQueue->addResponse(resp);
- }
- void PSThreadClass::Thread_Function()
- {
- try {
- _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace.
- /*********
- First step, set our game authentication info
- We could do:
- strcpy(gcd_gamename,"ccgenerals");
- strcpy(gcd_secret_key,"h5T2f6");
- or
- strcpy(gcd_gamename,"ccgeneralsb");
- strcpy(gcd_secret_key,"g3T9s2");
- ...but this is more secure:
- **********/
- /**
- gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e';
- gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a';
- gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='b';gcd_gamename[11]='\0';
- gcd_secret_key[0]='g';gcd_secret_key[1]='3';gcd_secret_key[2]='T';gcd_secret_key[3]='9';
- gcd_secret_key[4]='s';gcd_secret_key[5]='2';gcd_secret_key[6]='\0';
- /**/
- gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e';
- gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a';
- gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='\0';
- gcd_secret_key[0]='h';gcd_secret_key[1]='5';gcd_secret_key[2]='T';gcd_secret_key[3]='2';
- gcd_secret_key[4]='f';gcd_secret_key[5]='6';gcd_secret_key[6]='\0';
- /**/
-
- //strcpy(StatsServerHostname, "sdkdev.gamespy.com");
- PSRequest req;
- while ( running )
- {
- // deal with requests
- if (TheGameSpyPSMessageQueue->getRequest(req))
- {
- switch (req.requestType)
- {
- case PSRequest::PSREQUEST_SENDGAMERESTOGAMESPY:
- {
- if (tryConnect())
- {
- NewGame(0);
- #ifdef DEBUG_LOGGING
- Int res =
- #endif // DEBUG_LOGGING
- SendGameSnapShot(NULL, req.results.c_str(), SNAP_FINAL);
- DEBUG_LOG(("Just sent game results - res was %d\n", res));
- FreeGame(NULL);
- }
- }
- break;
- case PSRequest::PSREQUEST_READPLAYERSTATS:
- {
- Bool initialConnection = FALSE;
- if (!MESSAGE_QUEUE->getLocalPlayerID())
- {
- MESSAGE_QUEUE->setLocalPlayerID(req.player.id); // first request is for ourselves
- MESSAGE_QUEUE->setEmail(req.email);
- MESSAGE_QUEUE->setNick(req.nick);
- MESSAGE_QUEUE->setPassword(req.password);
- DEBUG_LOG(("Setting email/nick/password = %s/%s/%s\n", req.email.c_str(), req.nick.c_str(), req.password.c_str()));
- initialConnection = TRUE;
- }
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_READPLAYERSTATS\n"));
- if (tryConnect())
- {
- DEBUG_LOG(("Successful login\n"));
- incrOpCount();
- GetPersistDataValues(0, req.player.id, pd_public_rw, 0, "", getPersistentDataCallback, this);
- }
- else
- {
- DEBUG_LOG(("Unsuccessful login - retry=%d\n", initialConnection));
- PSResponse resp;
- resp.responseType = PSResponse::PSRESPONSE_COULDNOTCONNECT;
- resp.player.id = req.player.id;
- TheGameSpyPSMessageQueue->addResponse(resp);
- if (initialConnection)
- {
- // we haven't gotten stats for ourselves - try again
- DEBUG_LOG(("Requesting retry for reading local player's stats\n"));
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- req.player.id = MESSAGE_QUEUE->getLocalPlayerID();
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- }
- }
- break;
- case PSRequest::PSREQUEST_UPDATEPLAYERLOCALE:
- {
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERLOCALE\n"));
- if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email))
- {
- char kvbuf[256];
- sprintf(kvbuf, "\\locale\\%d", req.player.locale);
- incrOpCount();
- SetPersistDataValues(0, req.player.id, pd_public_rw, 0, kvbuf, setPersistentDataLocaleCallback, this);
- }
- }
- break;
- case PSRequest::PSREQUEST_UPDATEPLAYERSTATS:
- {
- /*
- ** NOTE THAT THIS IS HIGHLY DEPENDENT ON INI ORDERING FOR THE PLAYERTEMPLATES!!!
- */
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERSTATS\n"));
- UserPreferences pref;
- AsciiString userPrefFilename;
- userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID());
- DEBUG_LOG(("using the file %s\n", userPrefFilename.str()));
- pref.load(userPrefFilename);
- Int addedInDesyncs2 = pref.getInt("0", 0);
- DEBUG_LOG(("addedInDesyncs2 = %d\n", addedInDesyncs2));
- if (addedInDesyncs2 < 0)
- addedInDesyncs2 = 10;
- Int addedInDesyncs3 = pref.getInt("1", 0);
- DEBUG_LOG(("addedInDesyncs3 = %d\n", addedInDesyncs3));
- if (addedInDesyncs3 < 0)
- addedInDesyncs3 = 10;
- Int addedInDesyncs4 = pref.getInt("2", 0);
- DEBUG_LOG(("addedInDesyncs4 = %d\n", addedInDesyncs4));
- if (addedInDesyncs4 < 0)
- addedInDesyncs4 = 10;
- Int addedInDiscons2 = pref.getInt("3", 0);
- DEBUG_LOG(("addedInDiscons2 = %d\n", addedInDiscons2));
- if (addedInDiscons2 < 0)
- addedInDiscons2 = 10;
- Int addedInDiscons3 = pref.getInt("4", 0);
- DEBUG_LOG(("addedInDiscons3 = %d\n", addedInDiscons3));
- if (addedInDiscons3 < 0)
- addedInDiscons3 = 10;
- Int addedInDiscons4 = pref.getInt("5", 0);
- DEBUG_LOG(("addedInDiscons4 = %d\n", addedInDiscons4));
- if (addedInDiscons4 < 0)
- addedInDiscons4 = 10;
- DEBUG_LOG(("req.addDesync=%d, req.addDiscon=%d, addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d\n",
- req.addDesync, req.addDiscon, addedInDesyncs2, addedInDesyncs3, addedInDesyncs4,
- addedInDiscons2, addedInDiscons3, addedInDiscons4));
- if (req.addDesync || req.addDiscon)
- {
- AsciiString val;
- if (req.lastHouse == 2)
- {
- val.format("%d", addedInDesyncs2 + req.addDesync);
- pref["0"] = val;
- val.format("%d", addedInDiscons2 + req.addDiscon);
- pref["3"] = val;
- DEBUG_LOG(("house 2 req.addDesync || req.addDiscon: %d %d\n",
- addedInDesyncs2 + req.addDesync, addedInDiscons2 + req.addDiscon));
- }
- else if (req.lastHouse == 3)
- {
- val.format("%d", addedInDesyncs3 + req.addDesync);
- pref["1"] = val;
- val.format("%d", addedInDiscons3 + req.addDiscon);
- pref["4"] = val;
- DEBUG_LOG(("house 3 req.addDesync || req.addDiscon: %d %d\n",
- addedInDesyncs3 + req.addDesync, addedInDiscons3 + req.addDiscon));
- }
- else
- {
- val.format("%d", addedInDesyncs4 + req.addDesync);
- pref["2"] = val;
- val.format("%d", addedInDiscons4 + req.addDiscon);
- pref["5"] = val;
- DEBUG_LOG(("house 4 req.addDesync || req.addDiscon: %d %d\n",
- addedInDesyncs4 + req.addDesync, addedInDiscons4 + req.addDiscon));
- }
- pref.write();
- if (req.password.size() == 0)
- return;
- }
- if (!req.player.id)
- {
- DEBUG_LOG(("Bailing because ID is NULL!\n"));
- return;
- }
- req.player.desyncs[2] += addedInDesyncs2;
- req.player.games[2] += addedInDesyncs2;
- req.player.discons[2] += addedInDiscons2;
- req.player.games[2] += addedInDiscons2;
- req.player.desyncs[3] += addedInDesyncs3;
- req.player.games[3] += addedInDesyncs3;
- req.player.discons[3] += addedInDiscons3;
- req.player.games[3] += addedInDiscons3;
- req.player.desyncs[4] += addedInDesyncs4;
- req.player.games[4] += addedInDesyncs4;
- req.player.discons[4] += addedInDiscons4;
- req.player.games[4] += addedInDiscons4;
- DEBUG_LOG(("House2: %d/%d/%d, House3: %d/%d/%d, House4: %d/%d/%d\n",
- req.player.desyncs[2], req.player.discons[2], req.player.games[2],
- req.player.desyncs[3], req.player.discons[3], req.player.games[3],
- req.player.desyncs[4], req.player.discons[4], req.player.games[4]
- ));
- if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email))
- {
- DEBUG_LOG(("Logged in!\n"));
- if (TheGameSpyPSMessageQueue)
- TheGameSpyPSMessageQueue->trackPlayerStats(req.player);
- char *munkeeHack = strdup(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(req.player).c_str()); // GS takes a char* for some reason
- incrOpCount();
- DEBUG_LOG(("Setting values %s\n", munkeeHack));
- SetPersistDataValues(0, req.player.id, pd_public_rw, 0, munkeeHack, setPersistentDataCallback, this);
- free(munkeeHack);
- }
- else
- {
- DEBUG_LOG(("Cannot connect!\n"));
- //if (IsStatsConnected())
- //CloseStatsConnection();
- }
- }
- break;
- case PSRequest::PSREQUEST_READCDKEYSTATS:
- {
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_READCDKEYSTATS\n"));
- if (tryConnect())
- {
- incrOpCount();
- CDAuthInfo cdAuthInfo;
- cdAuthInfo.done = FALSE;
- cdAuthInfo.success = FALSE;
- cdAuthInfo.id = 0;
- char cdkeyHash[33] = "";
- char validationToken[33] = "";
- char *munkeeHack = strdup(req.cdkey.c_str()); // GenerateAuth takes a char*, not a const char* :P
- GenerateAuth(GetChallenge(NULL), munkeeHack, validationToken); // validation token
- GenerateAuth("", munkeeHack, cdkeyHash); // cdkey hash
- free (munkeeHack);
- PreAuthenticatePlayerCD( 0, "preorder", cdkeyHash, validationToken, preAuthCDCallback , &cdAuthInfo);
- while (running && IsStatsConnected() && !cdAuthInfo.done)
- PersistThink();
- DEBUG_LOG(("Looking for preorder status for %d (success=%d, done=%d) from CDKey %s with hash %s\n",
- cdAuthInfo.id, cdAuthInfo.success, cdAuthInfo.done, req.cdkey.c_str(), cdkeyHash));
- if (cdAuthInfo.done && cdAuthInfo.success)
- GetPersistDataValues(0, cdAuthInfo.id, pd_public_ro, 0, "\\preorder", getPreorderCallback, this);
- else
- decrOpCount();
- }
- }
- break;
- }
- }
- // update the network
- if (IsStatsConnected())
- {
- PersistThink();
- if (m_opCount <= 0)
- {
- DEBUG_ASSERTCRASH(m_opCount == 0, ("Negative operations pending!!!"));
- DEBUG_LOG(("m_opCount = %d - closing connection\n", m_opCount));
- CloseStatsConnection();
- m_opCount = 0;
- }
- }
- // end our timeslice
- Switch_Thread();
- }
- if (IsStatsConnected())
- CloseStatsConnection();
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in storage thread!"));
- }
- }
- //-------------------------------------------------------------------------
- PSPlayerStats::PSPlayerStats( void )
- {
- reset();
- }
- void PSPlayerStats::reset( void )
- {
- id = 0;
- locale = 0;
- gamesAsRandom = 0;
- lastFPS = 0;
- lastGeneral = 0;
- gamesInRowWithLastGeneral = 0;
- builtNuke = 0;
- builtSCUD = 0;
- builtParticleCannon = 0;
- challengeMedals = 0;
- battleHonors = 0;
- winsInARow = 0;
- maxWinsInARow = 0;
- lossesInARow = 0;
- maxLossesInARow = 0;
- disconsInARow = 0;
- maxDisconsInARow = 0;
- desyncsInARow = 0;
- maxDesyncsInARow = 0;
- lastLadderPort = 0;
- //Added By Sadullah Nader
- maxQMwinsInARow = 0;
- QMwinsInARow = 0;
- //
- }
- //-------------------------------------------------------------------------
- #define CHECK(x) if (k == #x && generalMarker >= 0) { s.x[generalMarker] = atoi(v.c_str()); continue; }
- PSPlayerStats GameSpyPSMessageQueueInterface::parsePlayerKVPairs( std::string kvPairs )
- {
- PSPlayerStats s;
- kvPairs.append("\\");
- Int offset = 0;
- while (1)
- {
- Int firstMarker = kvPairs.find_first_of('\\', offset);
- if (firstMarker < 0)
- break;
- Int secondMarker = kvPairs.find_first_of('\\', firstMarker + 1);
- if (secondMarker < 0)
- break;
- Int thirdMarker = kvPairs.find_first_of('\\', secondMarker + 1);
- if (thirdMarker < 0)
- break;
- Int generalMarker = kvPairs.find_last_not_of("0123456789", secondMarker - 1);
- std::string k, v, g;
- if (generalMarker == secondMarker - 1)
- {
- k = kvPairs.substr(firstMarker + 1, secondMarker - firstMarker - 1);
- generalMarker = -1;
- }
- else
- {
- k = kvPairs.substr(firstMarker + 1, generalMarker - firstMarker);
- g = kvPairs.substr(generalMarker + 1, secondMarker - generalMarker - 1);
- generalMarker = atoi(g.c_str());
- }
- v = kvPairs.substr(secondMarker + 1, thirdMarker - secondMarker - 1);
- //DEBUG_LOG(("%d [%s] [%s]\n", generalMarker, k.c_str(), v.c_str()));
- offset = thirdMarker - 1;
- CHECK(wins);
- CHECK(losses);
- CHECK(games);
- CHECK(duration);
- CHECK(unitsKilled);
- CHECK(unitsLost);
- CHECK(unitsBuilt);
- CHECK(buildingsKilled);
- CHECK(buildingsLost);
- CHECK(buildingsBuilt);
- CHECK(earnings);
- CHECK(techCaptured);
- CHECK(discons);
- CHECK(desyncs);
- CHECK(surrenders);
- CHECK(gamesOf2p);
- CHECK(gamesOf3p);
- CHECK(gamesOf4p);
- CHECK(gamesOf5p);
- CHECK(gamesOf6p);
- CHECK(gamesOf7p);
- CHECK(gamesOf8p);
- CHECK(customGames);
- CHECK(QMGames);
-
- if (k == "locale" && generalMarker < 0)
- {
- s.locale = atoi(v.c_str());
- continue;
- }
- if (k == "random" && generalMarker < 0)
- {
- s.gamesAsRandom = atoi(v.c_str());
- continue;
- }
- if (k == "options" && generalMarker < 0)
- {
- s.options = v;
- continue;
- }
- if (k == "systemSpec" && generalMarker < 0)
- {
- s.systemSpec = v;
- continue;
- }
- if (k == "fps" && generalMarker < 0)
- {
- s.lastFPS = atof(v.c_str());
- continue;
- }
-
- if (k == "lastGeneral" && generalMarker < 0)
- {
- s.lastGeneral = atoi(v.c_str());
- continue;
- }
- if (k == "genInRow" && generalMarker < 0)
- {
- s.gamesInRowWithLastGeneral = atoi(v.c_str());
- continue;
- }
- if (k == "builtNuke" && generalMarker < 0)
- {
- s.builtNuke = atoi(v.c_str());
- continue;
- }
- if (k == "builtSCUD" && generalMarker < 0)
- {
- s.builtSCUD = atoi(v.c_str());
- continue;
- }
- if (k == "builtCannon" && generalMarker < 0)
- {
- s.builtParticleCannon = atoi(v.c_str());
- continue;
- }
- if (k == "challenge" && generalMarker < 0)
- {
- s.challengeMedals = atoi(v.c_str());
- continue;
- }
- if (k == "battle" && generalMarker < 0)
- {
- s.battleHonors = atoi(v.c_str());
- continue;
- }
- if (k == "WinRow" && generalMarker < 0)
- {
- s.winsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "WinRowMax" && generalMarker < 0)
- {
- s.maxWinsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "LossRow" && generalMarker < 0)
- {
- s.lossesInARow = atoi(v.c_str());
- continue;
- }
- if (k == "LossRowMax" && generalMarker < 0)
- {
- s.maxLossesInARow = atoi(v.c_str());
- continue;
- }
- if (k == "DSRow" && generalMarker < 0)
- {
- s.desyncsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "DSRowMax" && generalMarker < 0)
- {
- s.maxDesyncsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "DCRow" && generalMarker < 0)
- {
- s.disconsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "DCRowMax" && generalMarker < 0)
- {
- s.maxDisconsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "ladderPort" && generalMarker < 0)
- {
- s.lastLadderPort = atoi(v.c_str());
- continue;
- }
- if (k == "ladderHost" && generalMarker < 0)
- {
- s.lastLadderHost = v;
- continue;
- }
- //DEBUG_ASSERTCRASH(generalMarker >= 0, ("Unknown KV Pair in persistent storage: [%s] = [%s]\n", k.c_str(), v.c_str()));
- //DEBUG_ASSERTCRASH(generalMarker < 0, ("Unknown KV Pair in persistent storage for PlayerTemplate %d: [%s] = [%s]\n", generalMarker, k.c_str(), v.c_str()));
- }
- return s;
- }
- #define ITERATE_OVER(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \
- { \
- if (it->second > 0) \
- { \
- sprintf(kvbuf, "\\" #x "%d\\%d", it->first, it->second); \
- s.append(kvbuf); \
- } \
- }
- std::string GameSpyPSMessageQueueInterface::formatPlayerKVPairs( PSPlayerStats stats )
- {
- char kvbuf[256];
- std::string s = "";
- PerGeneralMap::iterator it;
- ITERATE_OVER(wins);
- ITERATE_OVER(losses);
- ITERATE_OVER(games);
- ITERATE_OVER(duration);
- ITERATE_OVER(unitsKilled);
- ITERATE_OVER(unitsLost);
- ITERATE_OVER(unitsBuilt);
- ITERATE_OVER(buildingsKilled);
- ITERATE_OVER(buildingsLost);
- ITERATE_OVER(buildingsBuilt);
- ITERATE_OVER(earnings);
- ITERATE_OVER(techCaptured);
-
- //GS Report all disconnects, even if zero, because might have been
- //previously reported as 1 by updateAdditionalGameSpyDisconnections
- // ITERATE_OVER(discons);
- for (Int ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx)
- {
- // const PlayerTemplate* pTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx);
- // const GeneralPersona* pGeneral = TheChallengeGenerals->getGeneralByTemplateName(pTemplate->getName());
- // BOOL isReported = pGeneral ? pGeneral->isStartingEnabled() : FALSE;
- // if( !isReported )
- // continue; //don't report unplayable templates (observer, boss, etc.)
- sprintf(kvbuf, "\\discons%d\\%d", ptIdx, stats.discons[ptIdx]);
- s.append(kvbuf);
- }
- ITERATE_OVER(desyncs);
- ITERATE_OVER(surrenders);
- ITERATE_OVER(gamesOf2p);
- ITERATE_OVER(gamesOf3p);
- ITERATE_OVER(gamesOf4p);
- ITERATE_OVER(gamesOf5p);
- ITERATE_OVER(gamesOf6p);
- ITERATE_OVER(gamesOf7p);
- ITERATE_OVER(gamesOf8p);
- ITERATE_OVER(customGames);
- ITERATE_OVER(QMGames);
-
- if (stats.locale > 0)
- {
- sprintf(kvbuf, "\\locale\\%d", stats.locale);
- s.append(kvbuf);
- }
- if (stats.gamesAsRandom > 0)
- {
- sprintf(kvbuf, "\\random\\%d", stats.gamesAsRandom);
- s.append(kvbuf);
- }
- if (stats.options.length())
- {
- _snprintf(kvbuf, 256, "\\options\\%s", stats.options.c_str());
- kvbuf[255] = 0;
- s.append(kvbuf);
- }
- if (stats.systemSpec.length())
- {
- _snprintf(kvbuf, 256, "\\systemSpec\\%s", stats.systemSpec.c_str());
- kvbuf[255] = 0;
- s.append(kvbuf);
- }
- if (stats.lastFPS > 0.0f)
- {
- sprintf(kvbuf, "\\fps\\%g", stats.lastFPS);
- s.append(kvbuf);
- }
- if (stats.lastGeneral >= 0)
- {
- sprintf(kvbuf, "\\lastGeneral\\%d", stats.lastGeneral);
- s.append(kvbuf);
- }
- if (stats.gamesInRowWithLastGeneral >= 0)
- {
- sprintf(kvbuf, "\\genInRow\\%d", stats.gamesInRowWithLastGeneral);
- s.append(kvbuf);
- }
- if (stats.builtParticleCannon >= 0)
- {
- sprintf(kvbuf, "\\builtCannon\\%d", stats.builtParticleCannon);
- s.append(kvbuf);
- }
- if (stats.builtNuke >= 0)
- {
- sprintf(kvbuf, "\\builtNuke\\%d", stats.builtNuke);
- s.append(kvbuf);
- }
- if (stats.builtSCUD >= 0)
- {
- sprintf(kvbuf, "\\builtSCUD\\%d", stats.builtSCUD);
- s.append(kvbuf);
- }
- if (stats.challengeMedals > 0)
- {
- sprintf(kvbuf, "\\challenge\\%d", stats.challengeMedals);
- s.append(kvbuf);
- }
- if (stats.battleHonors > 0)
- {
- sprintf(kvbuf, "\\battle\\%d", stats.battleHonors);
- s.append(kvbuf);
- }
- //if (stats.winsInARow > 0)
- {
- sprintf(kvbuf, "\\WinRow\\%d", stats.winsInARow);
- s.append(kvbuf);
- }
- if (stats.maxWinsInARow > 0)
- {
- sprintf(kvbuf, "\\WinRowMax\\%d", stats.maxWinsInARow);
- s.append(kvbuf);
- }
- //if (stats.lossesInARow > 0)
- {
- sprintf(kvbuf, "\\LossRow\\%d", stats.lossesInARow);
- s.append(kvbuf);
- }
- if (stats.maxLossesInARow > 0)
- {
- sprintf(kvbuf, "\\LossRowMax\\%d", stats.maxLossesInARow);
- s.append(kvbuf);
- }
- //if (stats.disconsInARow > 0)
- {
- sprintf(kvbuf, "\\DCRow\\%d", stats.disconsInARow);
- s.append(kvbuf);
- }
- if (stats.maxDisconsInARow > 0)
- {
- sprintf(kvbuf, "\\DCRowMax\\%d", stats.maxDisconsInARow);
- s.append(kvbuf);
- }
- //if (stats.desyncsInARow > 0)
- {
- sprintf(kvbuf, "\\DSRow\\%d", stats.desyncsInARow);
- s.append(kvbuf);
- }
- if (stats.maxDesyncsInARow > 0)
- {
- sprintf(kvbuf, "\\DSRowMax\\%d", stats.maxDesyncsInARow);
- s.append(kvbuf);
- }
- if (stats.lastLadderPort > 0)
- {
- sprintf(kvbuf, "\\ladderPort\\%d", stats.lastLadderPort);
- s.append(kvbuf);
- }
- if (stats.lastLadderHost.length())
- {
- _snprintf(kvbuf, 256, "\\ladderHost\\%s", stats.lastLadderHost.c_str());
- kvbuf[255] = 0;
- s.append(kvbuf);
- }
- DEBUG_LOG(("Formatted persistent values as '%s'\n", s.c_str()));
- return s;
- }
- //-------------------------------------------------------------------------
|