| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945 |
- /*
- ** Command & Conquer Generals Zero Hour(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/>.
- */
- // FILE: PeerDefs.cpp //////////////////////////////////////////////////////
- // Generals GameSpy Peer (chat) definitions
- // Author: Matthew D. Campbell, June 2002
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include <set>
- #include "Common/GameState.h"
- #include "Common/RandomValue.h"
- #include "Common/IgnorePreferences.h"
- #include "Common/CustomMatchPreferences.h"
- #include "Common/GameSpyMiscPreferences.h"
- #include "Common/Recorder.h"
- #include "Common/Player.h"
- #include "Common/PlayerList.h"
- #include "Common/PlayerTemplate.h"
- #include "GameClient/MapUtil.h"
- #include "GameClient/ShellHooks.h"
- #include "GameClient/GameText.h"
- #include "GameNetwork/GameSpy/LadderDefs.h"
- #include "GameNetwork/GameSpy/PeerDefsImplementation.h"
- #include "GameNetwork/GameSpy/BuddyThread.h"
- #include "GameNetwork/GameSpy/PeerThread.h"
- #include "GameNetwork/GameSpy/PingThread.h"
- #include "GameNetwork/GameSpy/PersistentStorageThread.h"
- #include "GameNetwork/GameSpy/GSConfig.h"
- #include "GameNetwork/GameSpyOverlay.h"
- #include "GameNetwork/RankPointValue.h"
- #include "GameLogic/GameLogic.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- GameSpyInfoInterface *TheGameSpyInfo = NULL;
- extern GameSpyStagingRoom *TheGameSpyGame = NULL;
- void deleteNotificationBox( void );
- bool AsciiComparator::operator()(AsciiString s1, AsciiString s2) const
- {
- return stricmp(s1.str(), s2.str()) < 0;
- }
- GameSpyInfo::GameSpyInfo()
- {
- reset();
- TheGameSpyGame = &m_localStagingRoom;
- m_isDisconAfterGameStart = FALSE;
- }
- GameSpyInfo::~GameSpyInfo()
- {
- TheGameSpyGame = NULL;
- reset();
- }
- void GameSpyInfo::reset( void )
- {
- m_sawFullGameList = FALSE;
- m_isDisconAfterGameStart = FALSE;
- m_currentGroupRoomID = 0;
- clearGroupRoomList();
- clearStagingRoomList();
- m_localStagingRoomID = 0;
- m_buddyRequestMap.clear();
- m_buddyMap.clear();
- m_buddyMessages.clear();
- m_joinedStagingRoom = 0;
- m_isHosting = false;
- m_localStagingRoomID = 0;
- m_localStagingRoom.reset();
- m_gotGroupRoomList = false;
- m_localName = "";
- m_localProfileID = 0;
- m_maxMessagesPerUpdate = 100;
-
- // Added By Sadullah Nader
- // Initialization missing and needed
- m_disallowAsainText = FALSE;
- m_disallowNonAsianText = FALSE;
- m_disconReason = 0;
- m_localBaseName.clear();
- m_localEmail.clear();
- m_localPasswd.clear();
- m_pingString.clear();
- m_rawConfig.clear();
- m_rawMotd.clear();
- //
- m_internalIP = m_externalIP = 0;
- m_savedIgnoreMap.clear();
- m_preorderPlayers.clear();
- m_cachedLocalPlayerStats.reset();
-
- m_additionalDisconnects = -1;
- }
- Bool GameSpyInfo::didPlayerPreorder( Int profileID ) const
- {
- std::set<Int>::const_iterator it = m_preorderPlayers.find(profileID);
- return (it != m_preorderPlayers.end());
- }
- void GameSpyInfo::markPlayerAsPreorder( Int profileID )
- {
- m_preorderPlayers.insert(profileID);
- }
- void GameSpyInfo::setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP)
- {
- m_internalIP = internalIP;
- m_externalIP = externalIP;
- }
- void GameSpyInfo::readAdditionalDisconnects( void )
- {
- m_additionalDisconnects = GetAdditionalDisconnectsFromUserFile(m_localProfileID);
- DEBUG_LOG(("GameSpyInfo::readAdditionalDisconnects() found %d disconnects.\n", m_additionalDisconnects));
- }
- Int GameSpyInfo::getAdditionalDisconnects( void )
- {
- DEBUG_LOG(("GameSpyInfo::getAdditionalDisconnects() would have returned %d. Returning 0 instead.\n", m_additionalDisconnects));
- return 0;
- }
- void GameSpyInfo::clearAdditionalDisconnects( void )
- {
- m_additionalDisconnects = 0;
- }
- GameSpyInfoInterface* GameSpyInfoInterface::createNewGameSpyInfoInterface( void )
- {
- return NEW GameSpyInfo;
- }
- Bool GameSpyInfo::amIHost( void )
- {
- return m_isHosting;
- }
- GameSpyStagingRoom* GameSpyInfo::getCurrentStagingRoom( void )
- {
- if (m_isHosting || m_joinedStagingRoom)
- return &m_localStagingRoom;
- StagingRoomMap::iterator it = m_stagingRooms.find(m_joinedStagingRoom);
- if (it != m_stagingRooms.end())
- return it->second;
- return NULL;
- }
- void GameSpyInfo::setGameOptions( void )
- {
- if (!m_isHosting)
- return;
- // set options for game lists, and UTM players in-game
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_SETGAMEOPTIONS;
- req.options = GameInfoToAsciiString(&m_localStagingRoom).str();
- Int i;
- AsciiString mapName = TheGameState->realMapPathToPortableMapPath(m_localStagingRoom.getMap());
- AsciiString newMapName;
- for (i=0; i<mapName.getLength(); ++i)
- {
- char c = mapName.getCharAt(i);
- if (c != '\\')
- newMapName.concat(c);
- else
- newMapName.concat('/');
- }
- req.gameOptsMapName = newMapName.str();
- req.gameOptions.numPlayers = 0;
- req.gameOptions.numObservers = 0;
- Int numOpenSlots = 0;
- AsciiString playerInfo = "";
- for (i=0; i<MAX_SLOTS; ++i)
- {
- Int wins = 0, losses = 0, profileID = 0;
- GameSpyGameSlot *slot = TheGameSpyGame->getGameSpySlot(i);
- req.gameOptsPlayerNames[i] = "";
- if (!slot->isOccupied())
- {
- if (slot->isOpen())
- ++numOpenSlots;
- }
- else
- {
- AsciiString playerName;
- if (slot->isHuman())
- {
- playerName.translate(slot->getName());
- req.gameOptsPlayerNames[i] = playerName.str();
- PlayerInfoMap::iterator it = m_playerInfoMap.find(playerName);
- if (it != m_playerInfoMap.end())
- {
- wins = it->second.m_wins;
- losses = it->second.m_losses;
- profileID = it->second.m_profileID;
- }
- req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = wins;
- req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = losses;
- req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = profileID;
- req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate();
- req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor();
- if (slot->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER)
- {
- ++req.gameOptions.numObservers;
- }
- else
- {
- ++req.gameOptions.numPlayers;
- }
- }
- else if (slot->isAI())
- {
- // add in AI players
- switch (slot->getState())
- {
- case SLOT_EASY_AI:
- playerName = "CE";
- break;
- case SLOT_MED_AI:
- playerName = "CM";
- break;
- case SLOT_BRUTAL_AI:
- playerName = "CH";
- break;
- }
- req.gameOptsPlayerNames[i] = playerName.str(); // name is unused - we go off of the profileID
- req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0;
- req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0;
- req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getState();
- req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate();
- req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor();
- ++req.gameOptions.numPlayers;
- }
- }
- }
- req.gameOptions.maxPlayers = numOpenSlots + req.gameOptions.numPlayers + req.gameOptions.numObservers;
- TheGameSpyPeerMessageQueue->addRequest(req);
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM;
- req.UTM.isStagingRoom = TRUE;
- req.id = "Pings/";
- AsciiString pings;
- for (i=0; i<MAX_SLOTS; ++i)
- {
- if (i!=0)
- pings.concat(",");
- GameSpyGameSlot *slot = TheGameSpyGame->getGameSpySlot(i);
- if (slot && slot->isHuman())
- {
- pings.concat(slot->getPingString());
- }
- else
- {
- pings.concat("0");
- }
- }
- req.options = pings.str();
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- Bool GameSpyInfo::isBuddy( Int id )
- {
- return m_buddyMap.find(id) != m_buddyMap.end();
- }
- void GameSpyInfo::addGroupRoom( GameSpyGroupRoom room )
- {
- if (room.m_groupID == 0)
- {
- m_gotGroupRoomList = TRUE;
- GroupRoomMap::iterator iter;
- // figure out how many good strings we've got
- std::vector<UnicodeString> names;
- Int numRooms = 0;
- for (iter = getGroupRoomList()->begin(); iter != getGroupRoomList()->end(); ++iter)
- {
- GameSpyGroupRoom room = iter->second;
- if (room.m_groupID != TheGameSpyConfig->getQMChannel())
- {
- ++numRooms;
- AsciiString groupLabel;
- groupLabel.format("GUI:%s", room.m_name.str());
- Bool exists = FALSE;
- UnicodeString groupName = TheGameText->fetch(groupLabel, &exists);
- if (exists)
- {
- names.push_back(groupName);
- }
- }
- }
- if (!names.empty() && names.size() != numRooms)
- {
- // didn't get all names. fix up
- Int nameIndex = 0;
- Int timesThrough = 1; // start with USA Lobby 1
- for (iter = TheGameSpyInfo->getGroupRoomList()->begin(); iter != TheGameSpyInfo->getGroupRoomList()->end(); ++iter)
- {
- GameSpyGroupRoom room = iter->second;
- if (room.m_groupID != TheGameSpyConfig->getQMChannel())
- {
- room.m_translatedName.format(L"%ls %d", names[nameIndex].str(), timesThrough);
- nameIndex = (nameIndex+1)%names.size();
- m_groupRooms[room.m_groupID] = room;
- if (!nameIndex)
- {
- // we've looped through the name list already. increment the timesThrough counter
- ++timesThrough;
- }
- }
- }
- }
- }
- else
- {
- DEBUG_LOG(("Adding group room %d (%s)\n", room.m_groupID, room.m_name.str()));
- AsciiString groupLabel;
- groupLabel.format("GUI:%s", room.m_name.str());
- room.m_translatedName = TheGameText->fetch(groupLabel);
- m_groupRooms[room.m_groupID] = room;
- if ( !stricmp("quickmatch", room.m_name.str()) )
- {
- DEBUG_LOG(("Group room %d (%s) is the QuickMatch room\n", room.m_groupID, room.m_name.str()));
- TheGameSpyConfig->setQMChannel(room.m_groupID);
- }
- }
- }
- void GameSpyInfo::joinGroupRoom( Int groupID )
- {
- if (groupID > 0)
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM;
- req.groupRoom.id = groupID;
- TheGameSpyPeerMessageQueue->addRequest(req);
- m_playerInfoMap.clear();
- }
- }
- void GameSpyInfo::leaveGroupRoom( void )
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_LEAVEGROUPROOM;
- TheGameSpyPeerMessageQueue->addRequest(req);
- setCurrentGroupRoom(0);
- m_playerInfoMap.clear();
- }
- void GameSpyInfo::joinBestGroupRoom( void )
- {
- if (m_currentGroupRoomID)
- {
- DEBUG_LOG(("Bailing from GameSpyInfo::joinBestGroupRoom() - we were already in a room\n"));
- m_currentGroupRoomID = 0;
- return;
- }
- if (m_groupRooms.size())
- {
- int minID = -1;
- int minPlayers = 1000;
- GroupRoomMap::iterator iter = m_groupRooms.begin();
- while (iter != m_groupRooms.end())
- {
- GameSpyGroupRoom room = iter->second;
- DEBUG_LOG(("Group room %d: %s (%d, %d, %d, %d)\n", room.m_groupID, room.m_name.str(), room.m_numWaiting, room.m_maxWaiting,
- room.m_numGames, room.m_numPlaying));
- if (TheGameSpyConfig->getQMChannel() != room.m_groupID && minPlayers > 25 && room.m_numWaiting < minPlayers)
- {
- minID = room.m_groupID;
- minPlayers = room.m_numWaiting;
- }
- ++iter;
- }
- if (minID > 0)
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM;
- req.groupRoom.id = minID;
- TheGameSpyPeerMessageQueue->addRequest(req);
- m_playerInfoMap.clear();
- }
- else
- {
- GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL);
- }
- }
- else
- {
- GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL);
- }
- }
- void GameSpyInfo::updatePlayerInfo( PlayerInfo pi, AsciiString oldNick )
- {
- if (!oldNick.isEmpty())
- playerLeftGroupRoom(oldNick);
- m_playerInfoMap[pi.m_name] = pi;
- if (pi.m_preorder != 0)
- markPlayerAsPreorder(pi.m_profileID);
- }
- void GameSpyInfo::playerLeftGroupRoom( AsciiString nick )
- {
- PlayerInfoMap::iterator it = m_playerInfoMap.find(nick);
- if (it != m_playerInfoMap.end())
- {
- m_playerInfoMap.erase(it);
- }
- }
- void GameSpyInfo::clearStagingRoomList( void )
- {
- Int numRoomsRemoved = 0;
- m_sawFullGameList = FALSE;
- m_stagingRoomsDirty = FALSE;
-
- StagingRoomMap::iterator it = m_stagingRooms.begin();
- while (it != m_stagingRooms.end())
- {
- ++numRoomsRemoved;
- delete it->second;
- m_stagingRooms.erase(it);
- it = m_stagingRooms.begin();
- }
- if (numRoomsRemoved > 0)
- {
- //m_stagingRoomsDirty = true; // only consider ourselves dirty if we actually removed some games.
- }
- }
- void GameSpyInfo::addStagingRoom( GameSpyStagingRoom room )
- {
- removeStagingRoom(room);
- GameSpyStagingRoom *newRoom = NEW GameSpyStagingRoom;
- *newRoom = room;
- newRoom->cleanUpSlotPointers();
- m_stagingRooms[room.getID()] = newRoom;
- m_stagingRoomsDirty = m_sawFullGameList;
- }
- void GameSpyInfo::updateStagingRoom( GameSpyStagingRoom room )
- {
- addStagingRoom(room);
- }
- void GameSpyInfo::removeStagingRoom( GameSpyStagingRoom room )
- {
- StagingRoomMap::iterator it = m_stagingRooms.find(room.getID());
- if (it != m_stagingRooms.end())
- {
- delete it->second;
- m_stagingRooms.erase(it);
- m_stagingRoomsDirty = m_sawFullGameList;
- }
- }
- Bool GameSpyInfo::hasStagingRoomListChanged( void )
- {
- Bool val = m_stagingRoomsDirty;
- m_stagingRoomsDirty = false;
- return val;
- }
- GameSpyStagingRoom* GameSpyInfo::findStagingRoomByID( Int id )
- {
- StagingRoomMap::iterator it = m_stagingRooms.find(id);
- if (it != m_stagingRooms.end())
- return it->second;
- return NULL;
- }
- void GameSpyInfo::leaveStagingRoom( void )
- {
- m_localStagingRoomID = 0;
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_LEAVESTAGINGROOM;
- TheGameSpyPeerMessageQueue->addRequest(req);
- m_playerInfoMap.clear();
- m_joinedStagingRoom = FALSE;
- m_isHosting = FALSE;
- }
- void GameSpyInfo::markAsStagingRoomHost( void )
- {
- m_localStagingRoomID = 0;
- m_joinedStagingRoom = FALSE; m_isHosting = TRUE;
-
- // There are a few options we don't want to reset when we are hosting (they carry over
- // from the the create game dialog).
- // Interesting fact: oldFactionsOnly will be carried over correctly if I remove these
- // lines. UseStats won't be. I have no idea why.
- Int useStats = m_localStagingRoom.getUseStats();
- Bool oldFactionsOnly = m_localStagingRoom.oldFactionsOnly();
- m_localStagingRoom.reset();
- m_localStagingRoom.enterGame();
- m_localStagingRoom.setSeed(GetTickCount());
-
- m_localStagingRoom.setUseStats( useStats );
- m_localStagingRoom.setOldFactionsOnly( oldFactionsOnly );
- GameSlot newSlot;
- UnicodeString uName;
- uName.translate(m_localName);
- newSlot.setState(SLOT_PLAYER, uName);
- m_localStagingRoom.setLocalIP(m_externalIP);
- newSlot.setIP(m_externalIP);
- m_localStagingRoom.setSlot(0,newSlot);
- m_localStagingRoom.setLocalName(m_localName);
- TheMapCache->updateCache();
- m_localStagingRoom.setMap(getDefaultMap(TRUE));
- m_localStagingRoom.adjustSlotsForMap(); // close slots that the map can't hold. BGC
- }
- void GameSpyInfo::markAsStagingRoomJoiner( Int game )
- {
- m_localStagingRoomID = game;
- m_joinedStagingRoom = TRUE; m_isHosting = FALSE;
- m_localStagingRoom.reset();
- m_localStagingRoom.enterGame();
- StagingRoomMap::iterator it = m_stagingRooms.find(game);
- if (it != m_stagingRooms.end())
- {
- GameSpyStagingRoom *info = it->second;
- info->cleanUpSlotPointers();
- AsciiString options = GameInfoToAsciiString(info);
- #ifdef DEBUG_CRASHING
- Bool res =
- #endif
- ParseAsciiStringToGameInfo(&m_localStagingRoom, options);
- DEBUG_ASSERTCRASH(res, ("Could not parse game info \"%s\"", options.str()));
- m_localStagingRoom.setInGame();
- m_localStagingRoom.setLocalName(m_localName);
- m_localStagingRoom.setExeCRC(info->getExeCRC());
- m_localStagingRoom.setIniCRC(info->getIniCRC());
- m_localStagingRoom.setAllowObservers(info->getAllowObservers());
- m_localStagingRoom.setHasPassword(info->getHasPassword());
- m_localStagingRoom.setGameName(info->getGameName());
- DEBUG_LOG(("Joining game: host is %ls\n", m_localStagingRoom.getConstSlot(0)->getName().str()));
- }
- }
- void GameSpyInfo::setMOTD( const AsciiString& motd )
- {
- m_rawMotd = motd;
- }
- const AsciiString& GameSpyInfo::getMOTD( void )
- {
- return m_rawMotd;
- }
- void GameSpyInfo::setConfig( const AsciiString& config )
- {
- m_rawConfig = config;
- }
- const AsciiString& GameSpyInfo::getConfig( void )
- {
- return m_rawConfig;
- }
- // --------------------------------------------------------------
- void SetUpGameSpy( const char *motdBuffer, const char *configBuffer )
- {
- if (!motdBuffer)
- motdBuffer = "";
- if (!configBuffer)
- configBuffer = "";
- TearDownGameSpy();
- AsciiString dir = TheGlobalData->getPath_UserData();
- CreateDirectory(dir.str(), NULL);
- dir.format("%sGeneralsOnline", TheGlobalData->getPath_UserData().str());
- CreateDirectory(dir.str(), NULL);
- dir.format("%sGeneralsOnline\\Ladders", TheGlobalData->getPath_UserData().str());
- CreateDirectory(dir.str(), NULL);
- TheGameSpyBuddyMessageQueue = GameSpyBuddyMessageQueueInterface::createNewMessageQueue();
- TheGameSpyBuddyMessageQueue->startThread();
- TheGameSpyPeerMessageQueue = GameSpyPeerMessageQueueInterface::createNewMessageQueue();
- TheGameSpyPeerMessageQueue->startThread();
-
- TheGameSpyPSMessageQueue = GameSpyPSMessageQueueInterface::createNewMessageQueue();
- TheGameSpyPSMessageQueue->startThread();
- /*
- TheGameSpyGame = NEW GameSpyStagingRoom;
- */
- TheGameSpyInfo = GameSpyInfoInterface::createNewGameSpyInfoInterface();
- TheGameSpyInfo->setMOTD(motdBuffer);
- TheGameSpyInfo->setConfig(configBuffer);
- CustomMatchPreferences pref;
- TheGameSpyInfo->setDisallowAsianText(pref.getDisallowAsianText());
- TheGameSpyInfo->setDisallowNonAsianText( pref.getDisallowNonAsianText());
-
- TheGameSpyConfig = GameSpyConfigInterface::create(configBuffer);
- TheLadderList = NEW LadderList;
- ThePinger = PingerInterface::createNewPingerInterface();
- ThePinger->startThreads();
- TheRankPointValues = NEW RankPoints;
- }
- void TearDownGameSpy( void )
- {
- // save off cached stats
- if (TheGameSpyInfo && TheGameSpyInfo->getLocalProfileID())
- {
- // /* This was done on the score screen, so there is no need to do it now.
- // *
- PSPlayerStats localPSStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID());
- if (localPSStats.id != 0)
- {
- GameSpyMiscPreferences mPref;
- mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(localPSStats).c_str());
- mPref.write();
- }
- // */
- }
- // End our threads before we kill off the singletons they reference. No crashy-crash for you!
- if (TheGameSpyPSMessageQueue)
- TheGameSpyPSMessageQueue->endThread();
- if (TheGameSpyBuddyMessageQueue)
- TheGameSpyBuddyMessageQueue->endThread();
- if (TheGameSpyPeerMessageQueue)
- TheGameSpyPeerMessageQueue->endThread();
- if (ThePinger)
- ThePinger->endThreads();
- if(TheRankPointValues)
- {
- delete TheRankPointValues;
- TheRankPointValues = NULL;
- }
- if (TheGameSpyPSMessageQueue)
- {
- delete TheGameSpyPSMessageQueue;
- TheGameSpyPSMessageQueue = NULL;
- }
- if (TheGameSpyBuddyMessageQueue)
- {
- delete TheGameSpyBuddyMessageQueue;
- TheGameSpyBuddyMessageQueue = NULL;
- }
- if (TheGameSpyPeerMessageQueue)
- {
- delete TheGameSpyPeerMessageQueue;
- TheGameSpyPeerMessageQueue = NULL;
- }
- if (TheGameSpyInfo)
- {
- if (TheGameSpyInfo->getInternalIP())
- {
- // we've logged in before. mark us as logging out.
- SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_LOGOUT);
- }
- delete TheGameSpyInfo;
- TheGameSpyInfo = NULL;
- }
- if (ThePinger)
- {
- delete ThePinger;
- ThePinger = NULL;
- }
- if (TheLadderList)
- {
- delete TheLadderList;
- TheLadderList = NULL;
- }
- if (TheGameSpyConfig)
- {
- delete TheGameSpyConfig;
- TheGameSpyConfig = NULL;
- }
- // make sure the notification box doesn't exist
- deleteNotificationBox();
- }
- void GameSpyInfo::addToIgnoreList( AsciiString nick )
- {
- m_ignoreList.insert(nick);
- }
- void GameSpyInfo::removeFromIgnoreList( AsciiString nick )
- {
- m_ignoreList.erase(nick);
- }
- Bool GameSpyInfo::isIgnored( AsciiString nick )
- {
- return m_ignoreList.find(nick) != m_ignoreList.end();
- }
- IgnoreList GameSpyInfo::returnIgnoreList( void )
- {
- return m_ignoreList;
- }
- void GameSpyInfo::addToSavedIgnoreList( Int profileID, AsciiString nick)
- {
- m_savedIgnoreMap[profileID] = nick;
- IgnorePreferences pref;
- pref.setIgnore(nick, profileID, true);
- pref.write();
- }
- void GameSpyInfo::removeFromSavedIgnoreList( Int profileID )
- {
- m_savedIgnoreMap.erase(profileID);
- IgnorePreferences pref;
- pref.setIgnore(AsciiString::TheEmptyString, profileID, false);
- pref.write();
- }
- Bool GameSpyInfo::isSavedIgnored( Int profileID )
- {
- return m_savedIgnoreMap.find(profileID) != m_savedIgnoreMap.end();
- }
- SavedIgnoreMap GameSpyInfo::returnSavedIgnoreList( void )
- {
- return m_savedIgnoreMap;
- }
- static Int grabHexInt(const char *s)
- {
- char tmp[5] = "0xff";
- tmp[2] = s[0];
- tmp[3] = s[1];
- Int b = strtol(tmp, NULL, 16);
- return b;
- }
- Int GameSpyInfo::getPingValue( const AsciiString& otherPing )
- {
- if (m_pingString.getLength() != otherPing.getLength())
- {
- return TheGameSpyConfig->getPingTimeoutInMs();
- }
- if (m_pingString.getLength() % 2 != 0)
- {
- return TheGameSpyConfig->getPingTimeoutInMs();
- }
- Int best = 255+255;
- const char *myStr = m_pingString.str();
- const char *otherStr = otherPing.str();
- while (*myStr)
- {
- Int myVal = grabHexInt(myStr);
- Int otherVal = grabHexInt(otherStr);
- Int val = myVal + otherVal;
- best = (val < best) ? val : best;
- myStr += 2;
- otherStr += 2;
- }
- return best * TheGameSpyConfig->getPingTimeoutInMs() / (255+255);
- }
- Bool PlayerInfo::isIgnored( void )
- {
- return (m_profileID)?TheGameSpyInfo->isSavedIgnored(m_profileID):TheGameSpyInfo->isIgnored(m_name);
- }
- void GameSpyInfo::loadSavedIgnoreList( void )
- {
- m_savedIgnoreMap.clear();
- IgnorePreferences prefs;
- m_savedIgnoreMap = prefs.getIgnores();
- }
- void GameSpyInfo::setDisallowAsianText( Bool val )
- {
- m_disallowAsainText = val;
- }
- void GameSpyInfo::setDisallowNonAsianText( Bool val )
- {
- m_disallowNonAsianText = val;
- }
- Bool GameSpyInfo::getDisallowAsianText( void )
- {
- return m_disallowAsainText;
- }
- Bool GameSpyInfo::getDisallowNonAsianText(void )
- {
- return m_disallowNonAsianText;
- }
- void GameSpyInfo::setMaxMessagesPerUpdate( Int num )
- {
- m_maxMessagesPerUpdate = num;
- }
- Int GameSpyInfo::getMaxMessagesPerUpdate( void )
- {
- return m_maxMessagesPerUpdate;
- }
- /**This function is used to force an update of player's gamespy stats with an additional
- disconnection. This is used upon starting a new game so that if user disconnects prior
- to finishing game, the disconnection stays on the server. If he completes the game, we
- remove this extra disconnection inside of populatePlayerInfo() on the ScoreScreen. This
- seems like the only secure way to handle this issue since users can abort the process
- before we can detect/log disconnections.*/
- void GameSpyInfo::updateAdditionalGameSpyDisconnections(Int count)
- {
- if (TheRecorder->isMultiplayer() && TheGameLogic->isInInternetGame() && TheGameSpyGame && TheGameSpyGame->getUseStats())
- {
- Int localID = TheGameSpyInfo->getLocalProfileID();
- PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(localID);
-
- Player *player=ThePlayerList->getLocalPlayer();
- Int ptIdx;
- const PlayerTemplate *myTemplate = player->getPlayerTemplate();
- DEBUG_LOG(("myTemplate = %X(%s)\n", myTemplate, myTemplate->getName().str()));
- for (ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx)
- {
- const PlayerTemplate *nthTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx);
- DEBUG_LOG(("nthTemplate = %X(%s)\n", nthTemplate, nthTemplate->getName().str()));
- if (nthTemplate == myTemplate)
- {
- break;
- }
- }
- Bool anyAI = FALSE;
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- const GameSlot *slot = TheGameInfo->getConstSlot(i);
- if (slot->isAI())
- {
- anyAI = TRUE;
- }
- }
- //Check for cases where we're not tracking stats.
- if (anyAI || stats.id == 0 || myTemplate->isObserver() || player->getPlayerType() != PLAYER_HUMAN || player->isPlayerObserver())
- return;
- Int disCons=stats.discons[ptIdx];
- disCons += count;
- if (disCons < 0)
- { DEBUG_LOG(("updateAdditionalGameSpyDisconnections() - disconnection count below zero\n"));
- return; //something is wrong here
- }
- stats.discons[ptIdx] = disCons; //add an additional disconnection to their stats.
- //Add an additional disconnection to player stats.
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS;
- req.email = TheGameSpyInfo->getLocalEmail().str();
- req.nick = TheGameSpyInfo->getLocalBaseName().str();
- req.password = TheGameSpyInfo->getLocalPassword().str();
- req.player = stats;
- req.addDesync = FALSE;
- req.addDiscon = FALSE;
- req.lastHouse = ptIdx;
- TheGameSpyPSMessageQueue->addRequest(req);
- TheGameSpyPSMessageQueue->trackPlayerStats(stats);
- // force an update of our shtuff
- PSResponse newResp;
- newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS;
- newResp.player = stats;
- TheGameSpyPSMessageQueue->addResponse(newResp);
- // cache our stuff for easy reading next time
- GameSpyMiscPreferences mPref;
- mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(stats).c_str());
- mPref.write();
- }
- }
|