| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126 |
- /*
- ** 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/wolgmode.cpp $*
- * *
- * $Author:: Steve_t $*
- * *
- * $Modtime:: 10/19/02 12:51p $*
- * *
- * $Revision:: 124 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "WOLGMode.h"
- #include "GameData.h"
- #include "GameChanList.h"
- #include "GameChannel.h"
- #include "GameInitMgr.h"
- #include "WOLChatMgr.h"
- #include "WOLBuddyMgr.h"
- #include "WOLQuickMatch.h"
- #include "WOLGameInfo.h"
- #include "DlgWOLWait.h"
- #include "DlgMessageBox.h"
- #include "_globals.h"
- #include "colors.h"
- #include "cNetwork.h"
- #include "GameResSend.h"
- #include "PlayerManager.h"
- #include "MessageWindow.h"
- #include "natter.h"
- #include "WWProfile.h"
- #include "BandwidthCheck.h"
- #include "WOLLoginProfile.h"
- #include "DlgDownload.h"
- #include "AutoStart.h"
- #include "cpudetect.h"
- #include "dx8wrapper.h"
- #include "systeminfolog.h"
- #include "registry.h"
- #include "init.h"
- #include "debug.h"
- #include <WWOnline\WOLString.h>
- #include <WWOnline\WOLProduct.h>
- #include <WWOnline\WOLSession.h>
- #include <WWOnline\WOLChannel.h>
- #include <WWOnline\WaitCondition.h>
- #include <WWOnline\WOLGame.h>
- #include <WWOnline\WOLGameOptions.h>
- #include <WWOnline\WOLPageMsg.h>
- #include <WWOnline\WOLLadder.h>
- #include <WWOnline\WOLConnect.h>
- #include <WWOnline\WOLServer.h>
- #include <WWOnline\PingProfile.h>
- #include <WWAudio\WWAudio.h>
- #include <WWLib\RealCRC.h>
- #include "String_IDs.h"
- #include <WWTranslateDB\TranslateDB.h>
- #include <WWDebug\WWDebug.h>
- #include <WWDebug\WWProfile.h>
- #include "specialbuilds.h"
- #include "slavemaster.h"
- #include "sctextobj.h"
- #include "mainloop.h"
- using namespace WWOnline;
- // Check for patches every five minutes
- #define PATCH_CHECK_FREQUENCY (1000 * 5)
- const int RENEGADE_GAMECODE = 12;
- const wchar_t* RENEGADE_LOBBY_PASSWORD = L"not_a_valid_password"; // Password removed per Security review requirements. LFeenanEA - 27th January 2025
- const wchar_t* _cdecl Translate_WOLString(const char* token)
- {
- if (token) {
- StringClass desc(80, true);
- desc.Format("IDS_%s", token);
- const WCHAR* text = TRANSLATE_BY_DESC(desc);
- #ifdef WWDEBUG
- if (STRING_NOT_FOUND == text) {
- WWDEBUG_SAY(("ERROR: WOL String '%s' not found!\n", token));
- return L"WOL_NO_STRING";
- }
- #endif
- return text;
- }
- WWDEBUG_SAY(("WARNING: WOL_xxxx token is NULL\n"));
- return L"WOL_BADSTRING";
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::WolGameModeClass
- *
- * DESCRIPTION
- * Constructor
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- WolGameModeClass::WolGameModeClass() :
- mWOLChatMgr(NULL),
- mWOLBuddyMgr(NULL),
- mGameInProgress(false),
- mQuietMode(false),
- mConnected(false),
- mLastPatchCheckTime(0),
- mStartQuitProcessTime(0),
- mPatchAvailable(false),
- mMonitorConnection(false)
- {
- WWDEBUG_SAY(("WOLGameModeClass Instantiated\n"));
- WOLString::SetLookupFunc(Translate_WOLString);
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::~WolGameModeClass
- *
- * DESCRIPTION
- * Destructor
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- WolGameModeClass::~WolGameModeClass()
- {
- WWDEBUG_SAY(("WOLGameModeClass Destroyed\n"));
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Init
- *
- * DESCRIPTION
- * Activate Westwood Online game mode
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Init(void)
- {
- WWDEBUG_SAY(("WolGameModeClass Init\n"));
- // Check if product is already initialized
- RefPtrConst<Product> product = Product::Current();
- if (!product.IsValid()) {
- Product::Initializer(APPLICATION_SUB_KEY_NAME, RENEGADE_GAMECODE, RENEGADE_LOBBY_PASSWORD, RENEGADE_BASE_SKU);
- }
- mWOLSession = Session::GetInstance(true);
- if (mWOLSession.IsValid()) {
- mWOLSession->EnableProgressiveChannelList(true);
- mWOLSession->SetAutoRequestFlags(REQUEST_NONE);
- Observer<LadderInfoEvent>::NotifyMe(*mWOLSession);
- mWOLBuddyMgr = WOLBuddyMgr::GetInstance(true);
- WWASSERT_PRINT(mWOLBuddyMgr, "WOLBuddyManager failed to instantiate.");
- mWOLChatMgr = WOLChatMgr::GetInstance(true);
- WWASSERT_PRINT(mWOLChatMgr, "WOLChatMgr failed to instantiate.");
- WOLNATInterface.Init();
- LoginProfile::EnableSaving(mWOLSession->IsStoreLoginAllowed());
- }
- mQuickMatch = NULL;
- mTheGame = NULL;
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Shutdown
- *
- * DESCRIPTION
- * Deactivate Westwood Online game mode.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Shutdown(void)
- {
- WWDEBUG_SAY(("WolGameModeClass Shutdown\n"));
- if (mWOLSession.IsValid()) {
- WOLNATInterface.Shutdown();
- RefPtr<WaitCondition> logoutWait = mWOLSession->Logout();
- WWASSERT(logoutWait.IsValid());
- DlgWOLWait::DoDialog(IDS_WOL_LOGOFF, logoutWait);
- }
- if (mWOLBuddyMgr) {
- mWOLBuddyMgr->Release_Ref();
- mWOLBuddyMgr = NULL;
- }
- if (mWOLChatMgr) {
- mWOLChatMgr->Release_Ref();
- mWOLChatMgr = NULL;
- }
- // Release current profile.
- LoginProfile::SetCurrent(NULL);
- LoginInfo::ClearList();
- mMonitorConnection = false;
- mWOLSession.Release();
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Think
- *
- * DESCRIPTION
- * Periodic processing; called once each game loop.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Think(void)
- {
- WWPROFILE("WOL Think");
- static unsigned long _last_auto_kick = 0;
- static unsigned long _kick_history_persist_time = 1000 * 60 * 60;
- unsigned long time = TIMEGETTIME();
- //---------------------------------------------------------------------------
- // Yield time to WWOnline
- //---------------------------------------------------------------------------
- if (mWOLSession.IsValid()) {
- mWOLSession->Process();
- }
- //---------------------------------------------------------------------------
- // Periodically update quickmatch bot with recent server information
- //---------------------------------------------------------------------------
- if (mGameInProgress) {// && mQuickMatch) {
- unsigned long theTime = TIMEGETTIME();
- if (theTime >= mSendServerInfoTime) {
- //mSendServerInfoTime = (theTime + (120 * 1000));
- //
- // Try to help with hacks by updating the topic more frequently. Grrrr.
- //
- mSendServerInfoTime = (theTime + (20 * 1000));
- RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
- Update_Channel_Settings(mTheGame, channel);
- mWOLSession->SendChannelTopic();
- if (mQuickMatch) {
- const char* exInfo = channel->GetExtraInfo();
- const char* topic = channel->GetTopic();
- mQuickMatch->SendServerInfo(exInfo, topic);
- }
- }
- }
- //---------------------------------------------------------------------------
- // Autokick
- //---------------------------------------------------------------------------
- if (mGameInProgress && (time - _last_auto_kick > 2000 || time < _last_auto_kick)) {
- _last_auto_kick = time;
- Auto_Kick();
- //
- // Check for deadbeat channel lurkers.
- //
- if (cNetwork::I_Am_Server() && mGameInProgress) {
-
- unsigned long time = TIMEGETTIME();
- //
- // Clear out old kicklist entries.
- //
- for (int i = IdleKickNameList.Count() - 1 ; i >= 0 ; i--) {
- if (time - IdleKickTimeList[i] > _kick_history_persist_time || time < IdleKickTimeList[i]) {
- IdleKickTimeList.Delete(i);
- IdleKickNameList.Delete(i);
- }
- }
- const UserList& userList = mWOLSession->GetUserList();
- const unsigned int count = userList.size();
- for (unsigned int index = 0; index < count; index++) {
- const RefPtr<UserData>& user = userList[index];
- WWASSERT(user.IsValid());
-
- if (user.IsValid()) {
-
- //
- // Make sure it's not me.
- //
- const RefPtr<LoginInfo>& login = mWOLSession->GetCurrentLogin();
- WideStringClass myname;
- if (login.IsValid()) {
- myname = login->GetNickname();
- }
-
- if (myname.Compare_No_Case(user->GetName())) {
-
- //
- // Handle timer wrap.
- //
- if (time < user->mKickTimer) {
- user->mKickTimer = time;
- }
-
- if (!cPlayerManager::Find_Player(user->GetName())) {
- if (time - user->mKickTimer > 120 * 1000) {
- StringClass tempstr;
- user->GetName().Convert_To(tempstr);
- WWDEBUG_SAY(("Kicking '%s' for sitting in the channel while not in the game\n", tempstr.Peek_Buffer()));
- mWOLSession->KickUser(user->GetName());
- user->mKickTimer += 10*1000;
- //
- // If he's already been kicked for this recently then ban him.
- //
- int chances = 3;
- for (int i=0 ; i < IdleKickNameList.Count() ; i++) {
- if (IdleKickNameList[i].Compare_No_Case(tempstr) == 0) {
- chances--;
- if (chances == 0) {
- mWOLSession->BanUser(user->GetName(), true);
- WWDEBUG_SAY(("Banning '%s' for being kicked too often.\n", tempstr.Peek_Buffer()));
- break;
- }
- }
- }
- if (chances > 0) {
- WWDEBUG_SAY(("'%s' not banned - %d chances left.\n", tempstr.Peek_Buffer(), chances));
-
- StringClass stringy(user->GetName());
- IdleKickNameList.Add(stringy);
- IdleKickTimeList.Add(TIMEGETTIME());
- }
- }
- } else {
- user->mKickTimer = time;
- }
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- // Check for restart conditions.
- //---------------------------------------------------------------------------
- if (mMonitorConnection) {
- // Check for a pending restart for a new patch.
- if ((mPatchAvailable || !mConnected) && mStartQuitProcessTime) {
- if (time - mStartQuitProcessTime > 1000 * 4) {
- if (SlaveMaster.Am_I_Slave()) {
- Set_Exit_On_Exception(true);
- cGameData::Set_Manual_Exit(true);
- } else {
- Quit_And_Restart();
- }
- return;
- }
- }
- // Check for patches.
- // This doesn't work because you can't get a server list without also doing a complete reset of wolapi.
- #if (0)
- if (time - mLastPatchCheckTime > PATCH_CHECK_FREQUENCY) {
- mLastPatchCheckTime = time;
- if (mWOLSession.IsValid()) {
- #ifdef WWDEBUG
- bool success =
- #endif //WWDEBUG
- mWOLSession->RequestServerList(true);
- WWASSERT(success);
- }
- }
- #endif //(0)
- // If we have lost connection and the number of players drops to zero then we can quit.
- if (mMonitorConnection && !mConnected) {
- if (The_Game() && The_Game()->Get_Time_Limit_Minutes()) {
- if (cPlayerManager::Count() == 0) {
- Quit_And_Restart();
- }
- }
- }
- }
- // Firewall code service.
- WOLNATInterface.Service();
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::System_Timer_Reset
- *
- * DESCRIPTION
- * Reset any internal variables as needed when the system timer resets.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::System_Timer_Reset(void)
- {
- mSendServerInfoTime = (TIMEGETTIME() + (120 * 1000));
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Create_Game
- *
- * DESCRIPTION
- * Perform necessary game creation tasks for WWOnline.
- * NOTE: This should only be called by game hosts.
- *
- * INPUTS
- * Game - Instance of game to create for Westwood Online.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Create_Game(cGameData* theGame)
- {
- WWDEBUG_SAY(("WolGameModeClass::Create_Game\n"));
- if (theGame) {
- mTheGame = theGame;
- mGameID = 0;
- mGameInProgress = false;
- //-------------------------------------------------------------------------
- // Create and initialize channel for the new game.
- //-------------------------------------------------------------------------
- const WideStringClass& name = theGame->Get_Owner();
- const wchar_t* password = theGame->Get_Password();
- WWDEBUG_SAY(("Creating game channel '%S' Password: '%S'\n", (const WCHAR*)name, password));
- RefPtrConst<Product> product = Product::Current();
- WWASSERT(product.IsValid());
- int gameCode = product->GetGameCode();
- RefPtr<ChannelData> channel = ChannelData::Create(name, password, gameCode);
- WWASSERT(channel.IsValid());
- // Export channel settings for the game.
- Update_Channel_Settings(theGame, channel);
- //-------------------------------------------------------------------------
- // Request WWOnline channel creation
- //-------------------------------------------------------------------------
- mChannelCreateSuccessFlag = false;
- RefPtr<WaitCondition> createWait = mWOLSession->CreateChannel(channel, password);
- WWASSERT(createWait.IsValid());
- DlgWOLWait::DoDialog(IDS_GAME_CREATECHANNEL, createWait, this, 0, mQuietMode ? 0xffffffff : 0);
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Leave_Game
- *
- * DESCRIPTION
- * Leave WWOnline game
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Leave_Game(void)
- {
- WWDEBUG_SAY(("WolGameModeClass::Leave_Game\n"));
- // Stop listening WOLSession notifications.
- Observer<GameOptionsMessage>::StopObserving();
- Observer<ChannelEvent>::StopObserving();
- Observer<UserEvent>::StopObserving();
- Observer<ServerError>::StopObserving();
- Observer<ConnectionStatus>::StopObserving();
- // Shutdown quickmatch
- if (mQuickMatch) {
- mQuickMatch->Release_Ref();
- mQuickMatch = NULL;
- }
- // Leave the game channel.
- if (mTheGame) {
- WWASSERT(mWOLSession.IsValid());
- RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
- WWASSERT(wait.IsValid());
- DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
- }
- mTheGame = NULL;
- mGameID = 0;
- mGameInProgress = false;
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Start_Game
- *
- * DESCRIPTION
- * Start of game processing. This is performed by both the host and clients
- * at the begining of each game.
- *
- * INPUTS
- * Game - Instance of game starting
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void Get_Compact_Detail_String(StringClass& tmp);
- void WolGameModeClass::Start_Game(cGameData* theGame)
- {
- WWDEBUG_SAY(("WolGameModeClass::Start_Game\n"));
- // The game host (server) is responsible for obtaining the game ID
- if (cNetwork::I_Am_Server()) {
- WWASSERT(theGame == mTheGame && "Start_Game cGameData* mismatch");
- // Re-evaluate the clans in this game.
- Evaluate_Clans(theGame);
- //-------------------------------------------------------------------------
- // Update the channel settings for the new game.
- //-------------------------------------------------------------------------
- RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
- WWASSERT(channel.IsValid());
- Update_Channel_Settings(theGame, channel);
- // Send the chat server the new channel settings.
- mWOLSession->SendChannelExtraInfo();
- mWOLSession->SendChannelTopic();
- if (mQuickMatch) {
- const char* exInfo = channel->GetExtraInfo();
- const char* topic = channel->GetTopic();
- mQuickMatch->SendServerInfo(exInfo, topic);
- }
- // Reset timer to send server information for quickmatch
- mSendServerInfoTime = (TIMEGETTIME() + (120 * 1000));
- //-------------------------------------------------------------------------
- // Get WWOnline game id for this game.
- //-------------------------------------------------------------------------
- const WideStringClass& name = theGame->Get_Owner();
- UserList players;
- RefPtr<UserData> user = mWOLSession->FindUser(name);
- players.push_back(user);
- RefPtr<WaitCondition> wait = GameStartWait::Create(players, &Game_Start_Timeout_Callback);
- WWASSERT(wait.IsValid());
- Observer<GameStartEvent>::NotifyMe(*mWOLSession);
- DlgWOLWait::DoDialog(TRANSLATE (IDS_MENU_STARTING_WOL_GAME), wait, NULL, 0, mQuietMode ? 0xffffffff : 0);
- if (The_Game() && The_Game()->IsDedicated.Is_True()) {
- mConnected = true;
- mLastPatchCheckTime = TIMEGETTIME();
- mStartQuitProcessTime = 0;
- mMonitorConnection = true;
- Observer<ServerError>::NotifyMe(*mWOLSession);
- Observer<ConnectionStatus>::NotifyMe(*mWOLSession);
- }
- } else {
- mTheGame = theGame;
- }
- // Prevent the page dialog from showing while we are playing the game.
- // We will handle the displaying of pages and invitations within the game
- // messaging system.
- mWOLBuddyMgr->HidePagedDialog();
- Observer<WOLPagedEvent>::NotifyMe(*mWOLBuddyMgr);
- // Listen to events from WOLSession
- Observer<ChannelEvent>::NotifyMe(*mWOLSession);
- Observer<UserEvent>::NotifyMe(*mWOLSession);
- mGameInProgress = true;
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::End_Game
- *
- * DESCRIPTION
- * Do end of game processing.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::End_Game(void)
- {
- if (mGameInProgress) {
- WWDEBUG_SAY(("WolGameModeClass::End_Game\n"));
- // The server sends the end of game results
- if (mTheGame) {
- if (cNetwork::I_Am_Server()) {
- SendGameResults(mGameID, mTheGame, cPlayerManager::Get_Player_Object_List());
- mWOLSession->GetChatObject()->RequestGameEnd();
- //
- // Re-read the ban list.
- //
- KickNameList.Delete_All();
- KickIPList.Delete_All();
- Read_Kick_List();
- } else {
- #ifdef BETACLIENT
- // Jani do stuff here (send client system information string)
- StringClass info(255, true);
- info = "SYSINFO:";
- info += CPUDetectClass::Get_Compact_Log();
- info += DX8Wrapper::Get_Current_Caps()->Get_Compact_Log();
- StringClass tmp(255,true);
- Get_Compact_Detail_String(tmp);
- info += tmp;
- PlayerInfoLog::Get_Compact_Log(tmp);
- info += tmp;
- SystemInfoLog::Get_Compact_Log(tmp);
- info += tmp;
- BandwidthCheckerClass::Get_Compact_Log(tmp);
- info += tmp;
- WOLNATInterface.Get_Compact_Log(tmp);
- info += tmp;
- WWDEBUG_SAY(("Sending compact log: %s\n", info.Peek_Buffer()));
- mWOLSession->SendPrivateGameOptions(mTheGame->Get_Owner(), info);
- #endif // BETACLIENT
- }
- }
- // Allow the page dialog to show while we are no longer playing the game.
- Observer<WOLPagedEvent>::StopObserving();
- mWOLBuddyMgr->ShowPagedDialog();
- mGameID = 0;
- mGameInProgress = false;
- }
- }
- /***********************************************************************************************
- * WolGameModeClass::Post_Game_Check -- Call when game is about to cycle. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: True if cycle should be aborted *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 11/7/2001 6:07PM ST : Created *
- *=============================================================================================*/
- bool WolGameModeClass::Post_Game_Check(void)
- {
- bool retval = false;
- if (mMonitorConnection && !mConnected) {
- Quit_And_Restart();
- retval = true;
- }
- mMonitorConnection = false;
- return(retval);
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Accept_Actions
- *
- * DESCRIPTION
- *
- * INPUTS
- * Game - Instance of game joining
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Accept_Actions(void)
- {
- WWDEBUG_SAY(("WolGameModeClass::Accept_Actions\n"));
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Refusal_Actions
- *
- * DESCRIPTION
- *
- * INPUTS
- * Game - Instance of game joining
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Refusal_Actions(void)
- {
- WWDEBUG_SAY(("WolGameModeClass::Refusal_Actions\n"));
- // If the client's request to join the game was refused then we need to make
- // sure we leave the host's channel.
- RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
- DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Evaluate_Clans
- *
- * DESCRIPTION
- *
- * INPUTS
- * Game - Instance of game.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Evaluate_Clans(cGameData* theGame)
- {
- if (theGame && cNetwork::I_Am_Server()) {
- theGame->Clear_Clans();
- if (theGame->IsClanGame.Is_True()) {
- WWDEBUG_SAY(("CLANS: Evaluating clan assignments\n"));
- // If the host is a member of a clan then his clan takes a slot
- RefPtr<UserData> host = mWOLSession->GetCurrentUser();
- if (host.IsValid()) {
- unsigned long hostClanID = host->GetSquadID();
- theGame->Set_Clan(0, hostClanID);
- WWDEBUG_SAY(("CLANS: Assigning slot 0 to '%S' (host) clan #%lu\n", (const WCHAR*)host->GetName(), hostClanID));
- }
- // Determine which clans are in the game.
- const UserList& userList = mWOLSession->GetUserList();
- const unsigned int count = userList.size();
- for (unsigned int index = 0; index < count; ++index) {
- const RefPtr<UserData>& user = userList[index];
- WWASSERT(user.IsValid());
- unsigned long userClanID = user->GetSquadID();
- if (userClanID != 0) {
- // If the clan is not already assigned then assign this clan to the next slot.
- if (!theGame->Is_Clan_Competing(userClanID)) {
- int slot = theGame->Find_Free_Clan_Slot();
- WWASSERT(slot != -1 && "More clans in game than slots available");
- if (slot != -1) {
- WWDEBUG_SAY(("CLANS: Assigning slot %d to clan #%lu\n", slot, userClanID));
- theGame->Set_Clan(slot, userClanID);
- }
- }
- }
- }
- // Force server information to be resent.
- mSendServerInfoTime = 0;
- }
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Update_Channel_Settings
- *
- * DESCRIPTION
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Update_Channel_Settings(cGameData* theGame, const RefPtr<ChannelData>& channel)
- {
- WWASSERT(theGame != NULL);
- WWASSERT(channel.IsValid());
- if (theGame && channel.IsValid()) {
- WOLGameInfo gameInfo(*theGame);
- gameInfo.ExportToChannel(channel);
- // Quickmatch settings are appended to the channel topic
- if (theGame->Is_QuickMatch_Server()) {
- //---------------------------------------------------------------------------
- // Get average FPS of game (Capped at 255 fps)
- //---------------------------------------------------------------------------
- unsigned long fps = TimeManager::Get_Average_Frame_Rate();
- fps = min<unsigned long>(fps, 255);
- int numPlayers = theGame->Get_Current_Players();
- int avgPing = cPlayerManager::Get_Average_Ping();
- avgPing = min<int>(avgPing, UCHAR_MAX);
- unsigned short avgPoints = cPlayerManager::Get_Average_WOL_Points();
- int avgPlayed = cPlayerManager::Get_Average_Games_Played();
- avgPlayed = min<int>(avgPlayed, USHRT_MAX);
- // Quickmatch settings format is: |fps,mode,avg_ping,avg_rank,num_players
- const char* topic = channel->GetTopic();
- char newTopic[81];
- sprintf(newTopic, "%s|%02lx%02x%04x%04x%c", topic, fps, avgPing, avgPoints,
- avgPlayed, (32 + numPlayers));
- channel->SetTopic(newTopic);
- }
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Init_WOL_Player
- *
- * DESCRIPTION
- *
- * INPUTS
- * Player - Set players WOL settings.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Init_WOL_Player(cPlayer* player)
- {
- if (player) {
- RefPtr<UserData> user = mWOLSession->FindUser(player->Get_Name());
- if (user.IsValid()) {
- RefPtr<LadderData> ladder = user->GetTeamLadder();
- if (ladder.IsValid()) {
- player->Set_WOL_Points(ladder->GetPoints());
- player->Set_Wol_Rank(ladder->GetRung());
- player->Set_Num_Wol_Games(ladder->GetReserved2());
- return;
- }
- }
- // Ladder points start at 10000 and vary up or down depending on the players
- // performance.
- player->Set_WOL_Points(10000);
- // Ranking of -1 indicates that the player doesn't have a rank.
- player->Set_Wol_Rank(-1);
- player->Set_Num_Wol_Games(0);
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Get_WOL_User_Data
- *
- * DESCRIPTION
- *
- * INPUTS
- * Player - Name of player to find.
- *
- * RESULT
- * User - WWOnline user data
- *
- ******************************************************************************/
- RefPtr<UserData> WolGameModeClass::Get_WOL_User_Data(const wchar_t* name)
- {
- return mWOLSession->FindUser(name);
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Page_WOL_User
- *
- * DESCRIPTION
- *
- * INPUTS
- * User - Name of user to page.
- * Message - Message to send to user.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Page_WOL_User(const wchar_t* name, const wchar_t* msg)
- {
- if (name && (wcslen(name) > 0) && msg && (wcslen(msg) > 0)) {
- mWOLSession->PageUser(name, msg);
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_PAGING), name, msg);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Reply_Last_Page
- *
- * DESCRIPTION
- * Send a reply message to the last user who paged.
- *
- * INPUTS
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Reply_Last_Page(const wchar_t* msg)
- {
- if (msg && (wcslen(msg) > 0)) {
- const WCHAR* pager = mWOLBuddyMgr->GetLastPagersName();
- if (pager && (wcslen(pager) > 0)) {
- mWOLBuddyMgr->PageUser(pager, msg);
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_PAGE_REPLYING), pager, msg);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- } else {
- CombatManager::Get_Message_Window()->Add_Message(TRANSLATE(IDS_GAME_PAGE_REPLY_CANT), COLOR_CONSOLE_TEXT);
- }
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Locate_WOL_User
- *
- * DESCRIPTION
- *
- * INPUTS
- * User - Name of user to locate.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Locate_WOL_User(const wchar_t* name)
- {
- if (name && wcslen(name) > 0) {
- mWOLSession->RequestLocateUser(name);
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_LOCATING_USER), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Invite_WOL_User
- *
- * DESCRIPTION
- *
- * INPUTS
- * User - Name of user to locate.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Invite_WOL_User(const wchar_t* name, const wchar_t* msg)
- {
- if (name && wcslen(name)) {
- cPlayer* player = cPlayerManager::Find_Player(name);
- if (player) {
- WideStringClass message(0, true);
- message.Format(TRANSLATE (IDS_MENU_ALREADY_IN_GAME), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_INVITE_TEXT);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
- } else {
- mWOLBuddyMgr->InviteUser(name, msg);
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_INVITING_USER), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- }
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Join_WOL_User
- *
- * DESCRIPTION
- *
- * INPUTS
- * User - Name of user to join.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::Join_WOL_User(const wchar_t* name)
- {
- // If the name is valid and it is not me
- if (name && wcslen(name) && !mWOLSession->IsCurrentUser(name)) {
- cPlayer* player = cPlayerManager::Find_Player(name);
- if (player) {
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_MENU_YOURE_ALREADY_IN_GAME), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_INVITE_TEXT);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
- } else {
- RefPtr<UserData> user = UserData::Create(name);
- mWOLBuddyMgr->JoinUser(user);
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_JOINING_USER), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- }
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::Kick_Player
- *
- * DESCRIPTION
- * Kick a player from the game. Players kicked from a game are also banned
- * from rejoining that game. Note: This is only allowed by game server hosts.
- *
- * INPUTS
- * Player - Name of player to kick from the game.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- bool WolGameModeClass::Kick_Player(const wchar_t* name)
- {
- // If the name is not NULL. we are the server and the player to kick is
- // not ourself then proceed with the kick.
- if (name && (wcslen(name) > 0)) {
- if (cNetwork::I_Am_Server() && !mWOLSession->IsCurrentUser(name)) {
- mWOLSession->KickUser(name);
- mWOLSession->BanUser(name, true);
- // Disconnect the player from the server
- WideStringClass playername(0, true);
- playername = name;
- cPlayer* player = cPlayerManager::Find_Player(playername);
- if (player && player->Is_Human()) {
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_KICKING_USER), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- int playerID = player->Get_Id();
- cNetwork::Server_Kill_Connection(playerID);
- cNetwork::Cleanup_After_Client(playerID);
- return(true);
- }
- }
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_GAME_KICKING_NOT_ALLOWED), name);
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
- }
- return(false);
- }
- /***********************************************************************************************
- * WolGameModeClass::Ban_Player -- Add player to ban list *
- * *
- * *
- * *
- * INPUT: Player name *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/8/2002 4:33PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::Ban_Player(const wchar_t* name, unsigned long ip)
- {
- // If the name is not NULL. we are the server and the player to kick is
- // not ourself then proceed with the kick.
- if (name && cNetwork::I_Am_Server() && !mWOLSession->IsCurrentUser(name)) {
- Kick_Player(name);
- WideStringClass playername(0, true);
- playername = name;
- StringClass pn;
- playername.Convert_To(pn);
- if (!Is_Banned(pn, ip)) {
- KickNameList.Add(pn);
- KickIPList.Add(ip);
- char ipstr[128];
- pn += ":";
- unsigned char *ip_ptr = (unsigned char*)&ip;
- sprintf(ipstr, "%u.%u.%u.%u\n", (unsigned int)ip_ptr[0], (unsigned int)ip_ptr[1], (unsigned int)ip_ptr[2], (unsigned int)ip_ptr[3]);
- pn += ipstr;
- FILE *kick_list = fopen("wolbanlist.txt", "at");
- if (kick_list != NULL) {
- fwrite(pn.Peek_Buffer(), 1, pn.Get_Length(), kick_list);
- fclose(kick_list);
- }
- DynamicVectorClass<unsigned long> KickIPList;
- }
- }
- }
- /***********************************************************************************************
- * WolGameModeClass::Auto_Kick -- Kick any banned users from the game *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/8/2002 9:24PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::Auto_Kick(void)
- {
- if (cNetwork::I_Am_Server()) {
- cPlayer *player = NULL;
- for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List()->Head() ; player_node != NULL; player_node = player_node->Next()) {
- player = player_node->Data();
- if (player->Is_Active()) {
- if (!mWOLSession->IsCurrentUser(player->Get_Name())) {
- StringClass player_name(player->Get_Name());
- if (Is_Banned(player_name, player->Get_Ip_Address())) {
- Kick_Player(player->Get_Name());
- }
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * WolGameModeClass::Is_Banned -- Is this player banned from our WOL server? *
- * *
- * *
- * *
- * INPUT: Player name *
- * IP Address *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/8/2002 9:14PM ST : Created *
- *=============================================================================================*/
- bool WolGameModeClass::Is_Banned(const char *player_name, unsigned long ip)
- {
- int i;
- if (KickNameList.Count() == 0) {
- Read_Kick_List();
- }
- for (i=0 ; i<KickNameList.Count() ; i++) {
- if (stricmp(player_name, KickNameList[i].Peek_Buffer()) == 0) {
- return(true);
- }
- }
- for (i=0 ; i<KickIPList.Count() ; i++) {
- if (KickIPList[i] == ip) {
- return(true);
- }
- }
- return(false);
- }
- /***********************************************************************************************
- * WolGameModeClass::Read_Kick_List -- Read the list of autokick players *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/8/2002 9:14PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::Read_Kick_List(void)
- {
- FILE *kick_list = fopen("wolbanlist.txt", "rt");
- if (kick_list) {
- int i = 0;
- bool eof = false;
- char temp[256];
- while (!eof) {
- for (i=0 ; i<256 ; i++) {
- if (fread(&temp[i], 1, 1, kick_list) == 0) {
- eof = true;
- break;
- }
- if (temp[i] == '\n') {
- break;
- }
- }
- if (i > 10) {
- temp[i + 1] = 0;
- char *colon_ptr = strchr(temp, ':');
- if (colon_ptr) {
- *colon_ptr = 0;
- KickNameList.Add(temp);
- unsigned long ip = inet_addr(colon_ptr + 1);
- KickIPList.Add(ip);
- }
- }
- }
- fclose(kick_list);
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(ChannelEvent)
- *
- * DESCRIPTION
- *
- * INPUTS
- * Event -
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(ChannelEvent& event)
- {
- // This user has been kicked from the game.
- if (ChannelKicked == event.GetStatus()) {
- WWDEBUG_SAY(("WolGameModeClass Player Kicked!\n"));
- mGameInProgress = false;
- GameInitMgrClass::End_Game();
- GameInitMgrClass::Display_End_Game_Menu();
- DlgMsgBox::DoDialog(TRANSLATE(IDS_MENU_SERVER_MESSAGE_TITLE), TRANSLATE (IDS_MENU_SERVER_KICKED_MESSAGE));
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(UserEvent)
- *
- * DESCRIPTION
- *
- * INPUTS
- * Event -
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(UserEvent& event)
- {
- switch (event.GetEvent()) {
- // A user has been kicked from the game.
- case UserEvent::Kicked: {
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_MENU_PLAYER_KICKED_MESSAGE), event.Subject()->GetName());
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PUBLIC_TEXT);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Public_Message", Matrix3D(1));
- }
- break;
- case UserEvent::Located: {
- const RefPtr<UserData>& user = event.Subject();
- // Get the description of the user's location
- WideStringClass location(64, true);
- WOLBuddyMgr::GetLocationDescription(user, location);
- // Build a string containing the user's name
- WideStringClass message(0, true);
- message.Format(TRANSLATE(IDS_CHAT_LOCATEDUSER), user->GetName());
- message += L" - ";
- message += location;
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PRIVATE_TEXT);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
- }
- break;
- case UserEvent::LadderInfo:
- if (mTheGame) {
- const RefPtr<UserData>& user = event.Subject();
- cPlayer* player = cPlayerManager::Find_Player(user->GetName());
- Init_WOL_Player(player);
- }
- break;
- case UserEvent::Join:
- if (mTheGame && cNetwork::I_Am_Server()) {
- const RefPtr<UserData>& user = event.Subject();
- bool requestDetails = true;
- // If the user is joining a clan game.
- if (mTheGame->IsClanGame.Is_True()) {
- WWDEBUG_SAY(("CLANS: User join clan assignment\n"));
- unsigned long userClanID = user->GetSquadID();
- WWASSERT(userClanID != 0 && "User not in a clan");
- // If the game is open to a new clan then assign the user to a
- // participating clan or a new slot.
- if (mTheGame->Is_Clan_Game_Open()) {
- // If the user is not a member of a participating clan then assign
- // the next free slot to this users clan.
- if (!mTheGame->Is_Clan_Competing(userClanID)) {
- int slot = mTheGame->Find_Free_Clan_Slot();
- if (slot != -1) {
- WWDEBUG_SAY(("CLANS: Slot %d filled by '%S' Clan #%lu\n", slot,
- (const WCHAR*)user->GetName(), userClanID));
- mTheGame->Set_Clan(slot, userClanID);
- }
- // Send the chat server the new channel settings.
- RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
- Update_Channel_Settings(mTheGame, channel);
- mWOLSession->SendChannelExtraInfo();
- }
- } else {
- // If the game is closed and the user is not a member of one of the
- // competing clans then kick him.
- if (!mTheGame->Is_Clan_Competing(userClanID)) {
- WWDEBUG_SAY(("CLANS: Game closed. Kicking user '%S'\n",
- (const WCHAR*)user->GetName()));
- mWOLSession->KickUser(user->GetName());
- requestDetails = false;
- }
- }
- }
- if (requestDetails) {
- mWOLSession->RequestUserDetails(user, REQUEST_LADDERINFO|REQUEST_SQUADINFO);
- }
- }
- break;
- case UserEvent::Leave:
- if (mTheGame && cNetwork::I_Am_Server()) {
- if (mTheGame->IsClanGame.Is_True()) {
- WWDEBUG_SAY(("CLANS: User leave re-evaluate clan assignment\n"));
- Evaluate_Clans(mTheGame);
- }
- }
- break;
- default:
- break;
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(DlgWOLWaitEvent)
- *
- * DESCRIPTION
- * Response to completion of game channel creation.
- *
- * INPUTS
- * Event -
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(DlgWOLWaitEvent& wolEvent)
- {
- if (wolEvent.Result() == WaitCondition::ConditionMet) {
- WWASSERT(mTheGame != NULL);
- mChannelCreateSuccessFlag = true;
- // Startup quickmatch if we are serving quickmatch games.
- if (mTheGame->Is_QuickMatch_Server()) {
- mQuickMatch = WOLQuickMatch::Create();
- WWASSERT(mQuickMatch);
- }
- mSendServerInfoTime = 0;
- // Start listening to Game Options messages from clients
- Observer<GameOptionsMessage>::NotifyMe(*mWOLSession);
- // Listen to events from WOLSession
- Observer<ChannelEvent>::NotifyMe(*mWOLSession);
- Observer<UserEvent>::NotifyMe(*mWOLSession);
- } else {
- if (!mQuietMode) {
- DlgMsgBox::DoDialog(TRANSLATE (IDS_MENU_FAILED_TO_CREATE_GAME), wolEvent.Subject()->GetResultText());
- }
- }
- Signaler<WolGameModeClass>::SendSignal(*this);
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(GameStartEvent)
- *
- * DESCRIPTION
- * Handle game start acknowledgement.
- *
- * INPUTS
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(GameStartEvent& start)
- {
- WWDEBUG_SAY(("GameStartEvent received\n"));
- mGameID = 0;
- if (start.IsSuccess()) {
- mGameID = start.GetGameID();
- WWDEBUG_SAY(("GameID = %ld\n", mGameID));
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(GameOptionsMessage)
- *
- * DESCRIPTION
- * Handle game options requests coming from other users.
- *
- * INPUTS
- * OptionsMessage -
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(GameOptionsMessage& message)
- {
- if (cNetwork::I_Am_Server() && mTheGame) {
- const char* request = message.GetOptions();
- // Request for game information?
- if (strcmp("RGINFO", request) == 0) {
- WideStringClass requestor(0, true);
- requestor = message.GetSendersName();
- //-----------------------------------------------------------------------
- // Send game information
- //-----------------------------------------------------------------------
- unsigned long mapCRC = CRC_Stringi(mTheGame->Get_Map_Name());
- float seconds = mTheGame->Get_Time_Remaining_Seconds();
- // Game info sent as: MapCRC Seconds remaining
- StringClass info(0, true);
- info.Format("GINFO:%08lx %.4f", mapCRC, seconds);
- WWDEBUG_SAY(("%S\n", info));
- mWOLSession->SendPrivateGameOptions(requestor, info);
- //-----------------------------------------------------------------------
- // Send team information
- //-----------------------------------------------------------------------
- SList<cTeam>* teamList = cTeamManager::Get_Team_Object_List();
- WWASSERT(teamList != NULL);
- SLNode<cTeam>* teamNode = teamList->Head();
- while (teamNode) {
- cTeam* team = teamNode->Data();
- WWASSERT(team != NULL);
- int teamID = team->Get_Id();
- int teamScore = team->Get_Score();
- info.Format("TINFO:%d %d", teamID, teamScore);
- WWDEBUG_SAY(("%S\n", info));
- mWOLSession->SendPrivateGameOptions(requestor, info);
- teamNode = teamNode->Next();
- }
- //-----------------------------------------------------------------------
- // Send player information
- //-----------------------------------------------------------------------
- SList<cPlayer>* playerList = cPlayerManager::Get_Player_Object_List();
- SLNode<cPlayer>* playerNode = playerList->Head();
- while (playerNode) {
- cPlayer* player = playerNode->Data();
- if (player && player->Is_Active() && player->Is_Human()) {
- const WideStringClass& name = player->Get_Name();
- int type = player->Get_Player_Type();
- int rung = player->Get_Rung();
- int kills = player->Get_Kills();
- int deaths = player->Get_Deaths();
- int score = player->Get_Score();
- // PINFO string format: Name fps,type,rank,kills,deaths
- info.Format("PINFO:%S %d %d %d %d %d", (const WCHAR*)name, type, rung, kills, deaths, score);
- mWOLSession->SendPrivateGameOptions(requestor, info);
- }
- playerNode = playerNode->Next();
- }
- } else {
- // Write client system info to disk
- const char* cmd = strstr(request, "SYSINFO:");
- if (cmd == request) {
- static int sysinfo_log_disabled=-1;
- if (sysinfo_log_disabled==-1) { // Read from registry only once per run
- RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG );
- if ( registry.Is_Valid() ) {
- sysinfo_log_disabled=registry.Get_Int( VALUE_NAME_DISABLE_SERVER_SYSINFO_COLLECTING, -1 );
- // Write to registry to create the key if it didn't exist
- if (sysinfo_log_disabled==-1) {
- sysinfo_log_disabled=0;
- registry.Set_Int( VALUE_NAME_DISABLE_SERVER_SYSINFO_COLLECTING, sysinfo_log_disabled);
- }
- }
- }
- // Only copy the sysinfo if it isn't disabled in registry
- if (sysinfo_log_disabled==0) {
- const char* data = (request + strlen("SYSINFO:"));
- int datalen=strlen(data);
- if (!datalen) return;
- StringClass tmp(0,true);
- StringClass requestor(0, true);
- requestor = message.GetSendersName();
- StringClass datastring;
- datastring=requestor;
- datastring+="\t";
- unsigned long versionminor,versionmajor;
- Get_Version_Number(&versionmajor,&versionminor);
- SYSTEMTIME time;
- GetSystemTime(&time);
- tmp.Format("%d/%d/%d %d:%d\t%d.%d\t",
- time.wMonth,
- time.wDay,
- time.wYear,
- time.wHour,
- time.wMinute,
- versionmajor,
- versionminor);
- datastring+=tmp;
- datastring+=data;
- datastring+="\r\n";
- // Verify the sysinfo folder
- StringClass dirname(0,true);
- dirname.Format("sysinfo_%d",DebugManager::Get_Version_Number());
- if (GetFileAttributes(dirname)==0xffffffff) {
- if (!CreateDirectory(dirname,NULL)) {
- return;
- }
- }
- StringClass filename(0,true);
- filename=dirname;
- filename+="\\";
- tmp=requestor;
- filename+=tmp;
- filename+=".txt";
- DWORD written;
- HANDLE file;
- file = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (INVALID_HANDLE_VALUE != file) {
- SetFilePointer(file, 0, NULL, FILE_END);
- WriteFile(file, datastring, strlen(datastring), &written, NULL);
- CloseHandle(file);
- }
- }
- }
- }
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(LadderInfoEvent)
- *
- * DESCRIPTION
- *
- * INPUTS
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(LadderInfoEvent& ladderEvent)
- {
- if (ladderEvent.IsRanked()) {
- LadderType type = ladderEvent.GetLadderType();
- // If this is for the locale user and the ladder information is cached
- // then update there profile with the latest ladder information.
- if (LadderType_Team == type) {
- WideStringClass name(64, true);
- name = ladderEvent.GetReceivedName();
- if (mWOLSession->IsCurrentUser(name)) {
- LoginProfile* profile = LoginProfile::Get(name, false);
- if (profile) {
- WWDEBUG_SAY(("Updating team ladder info for %S\n", profile->GetName()));
- const WOL::Ladder& wolLadder = ladderEvent.GetWOLLadder();
- // Save the number of games played.
- profile->SetGamesPlayed(wolLadder.reserved2);
- // Save the ranking information
- LoginProfile::Ranking rank;
- rank.Wins = wolLadder.wins;
- rank.Losses = wolLadder.losses;
- rank.Deaths = wolLadder.reserved1;
- rank.Kills = wolLadder.kills;
- rank.Points = wolLadder.points;
- rank.Rank = wolLadder.rung;
- profile->SetRanking(LadderType_Team, rank);
- profile->SaveSettings();
- profile->Release_Ref();
- }
- }
- } else if (LadderType_Clan == type) {
- RefPtr<UserData> user = mWOLSession->GetCurrentUser();
- if (user.IsValid()) {
- RefPtr<SquadData> squad = user->GetSquad();
- if (squad.IsValid() && (stricmp(squad->GetAbbr(), ladderEvent.GetReceivedName()) == 0)) {
- LoginProfile* profile = LoginProfile::Get(user->GetName(), false);
- if (profile) {
- WWDEBUG_SAY(("Updating clan ladder info for %S\n", profile->GetName()));
- const WOL::Ladder& wolLadder = ladderEvent.GetWOLLadder();
- // Save the ranking information
- LoginProfile::Ranking rank;
- rank.Wins = wolLadder.wins;
- rank.Losses = wolLadder.losses;
- rank.Deaths = wolLadder.reserved1;
- rank.Kills = wolLadder.kills;
- rank.Points = wolLadder.points;
- rank.Rank = wolLadder.rung;
- profile->SetRanking(LadderType_Clan, rank);
- profile->SaveSettings();
- profile->Release_Ref();
- }
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * WolGameModeClass::HandleNotification -- Handle connection status notifications *
- * *
- * *
- * *
- * INPUT: Connection status *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 11/8/2001 10:20PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::HandleNotification(ConnectionStatus &status)
- {
- if (mMonitorConnection && status == ConnectionDisconnected) {
- Handle_Disconnect();
- }
- }
- /***********************************************************************************************
- * WolGameModeClass::Handle_Disconnect -- Handle disconnect from chat server *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 11/8/2001 10:21PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::Handle_Disconnect(void)
- {
- if (mMonitorConnection && mConnected) {
- mConnected = false;
- if (cNetwork::I_Am_Server()) {
- if (The_Game() && The_Game()->IsDedicated.Is_True() && AutoRestart.Get_Restart_Flag()) {
- /*
- ** If the game has a time limit and players then we will wait until the next map change otherwise we will stop now.
- */
- WWASSERT(PTheGameData != NULL);
- //if (!The_Game()->Get_Time_Limit_Minutes() || SlaveMaster.Am_I_Slave()) {
- if (cPlayerManager::Count() == 0) {
- if (SlaveMaster.Am_I_Slave()) {
- AutoRestart.Set_Restart_Flag(false);
- Set_Exit_On_Exception(true);
- cGameData::Set_Manual_Exit(true);
- } else {
- Quit_And_Restart();
- }
- } else {
- /*
- ** Tell the players we have to quit
- */
- mStartQuitProcessTime = TIMEGETTIME();
- if (cNetwork::I_Am_Server()) {
- WideStringClass widestring(TRANSLATE (IDS_MENU_QUITTING_DUE_TO_CONN_LOSS_MSG), true);
- cScTextObj * message = new cScTextObj;
- message->Init(widestring, TEXT_MESSAGE_PUBLIC, true, HOST_TEXT_SENDER, -1);
- }
- }
- //} else {
- //Quit_And_Restart();
- //}
- }
- }
- }
- }
- /***********************************************************************************************
- * WolGameModeClass::HandleNotification -- Handle server error notifications *
- * *
- * *
- * *
- * INPUT: Server error tyoe *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 11/8/2001 10:21PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::HandleNotification(ServerError& server_error)
- {
- /*
- ** This doesn't work because you can't get a server list without also doing a complete reset of wolapi.
- */
- #if (0)
- HRESULT code = server_error.GetErrorCode();
- if (code == CHAT_E_MUSTPATCH) {
- if (mMonitorConnection && mConnected) {
- mPatchAvailable = true;
- /*
- ** If the game has a time limit and players then we will wait until the next map change otherwise we will stop now.
- */
- WWASSERT(PTheGameData != NULL);
- if (!The_Game()->Get_Time_Limit_Minutes() || cPlayerManager::Count() == 0) {
- mStartQuitProcessTime = TIMEGETTIME();
- } else {
- Quit_And_Restart();
- }
- }
- }
- #endif //(0)
- }
- /***********************************************************************************************
- * WolGameModeClass::Quit_And_Restart -- Setup a restart then quit the game *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 11/8/2001 10:21PM ST : Created *
- *=============================================================================================*/
- void WolGameModeClass::Quit_And_Restart(void)
- {
- static bool reenter_ye_not = false;
- if (!reenter_ye_not) {
- reenter_ye_not = true;
- /*
- ** This will cause the server to leave the channel if needed.
- */
- GameInitMgrClass::End_Game();
- /*
- ** If there is a patch available then download it.
- */
- if (mConnected) {
- WOLLogonMgr::Logoff();
- if (mPatchAvailable) {
- RefPtr<WWOnline::Session> wolSession = WWOnline::Session::GetInstance(false);
- DlgDownload::DoDialog(TRANSLATE(IDS_WOL_DOWNLOAD), wolSession->GetPatchDownloadList(), true);
- }
- } else {
- /*
- ** If we lost connection then drop out of the game and try to re-establish connection.
- */
- AutoRestart.Set_Restart_Flag(true);
- Set_Exit_On_Exception(true);
- cGameData::Set_Manual_Exit(true);
- Stop_Main_Loop(EXIT_SUCCESS);
- }
- reenter_ye_not = false;
- }
- }
- /******************************************************************************
- *
- * NAME
- * WolGameModeClass::HandleNotification(WOLPagedEvent)
- *
- * DESCRIPTION
- * Handle the display of pages and invitations from users outside the game.
- *
- * INPUTS
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void WolGameModeClass::HandleNotification(WOLPagedEvent& event)
- {
- PageMessage* page = event.Subject();
- WWASSERT(page && "NULL page in WOLPagedEvent");
- switch (event.GetAction()) {
- case PAGE_RECEIVED: {
- WideStringClass message(255, true);
- message.Format(L"%s: %s", page->GetPagersName(), page->GetPageMessage());
- CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PAGED_TEXT);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
- break;
- }
- case INVITATION_RECEIVED:
- case INVITATION_DECLINED:
- CombatManager::Get_Message_Window()->Add_Message(page->GetPageMessage(), COLOR_INVITE_TEXT);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
- break;
- case PAGE_ERROR:
- case PAGE_NOT_THERE:
- case PAGE_TURNED_OFF: {
- WideStringClass message(255, true);
- message.Format(L"%s %s", TRANSLATE(IDS_WOL_PAGEUSERERROR), page->GetPageMessage());
- CombatManager::Get_Message_Window()->Add_Message(page->GetPageMessage(), COLOR_CONSOLE_TEXT);
- break;
- }
- }
- }
- void WolGameModeClass::Game_Start_Timeout_Callback(void)
- {
- GameModeClass* game = GameModeManager::Find("WOL");
- if (game && game->Is_Active()) {
- WolGameModeClass* wolgame = reinterpret_cast<WolGameModeClass*>(game);
- wolgame->Game_Start_Timed_Out();
- }
- }
-
-
- void WolGameModeClass::Game_Start_Timed_Out(void)
- {
- /*
- ** If we lost connection without getting a report from WW Online then the only clue we have is that we will fail to
- ** get the game ID by timing out. Since this is pretty much fatal anyway, let's quit and restart and see if things fix
- ** themselves up.
- **
- ** ST - 8/21/2002 11:27AM
- */
- if (cNetwork::I_Am_Server()) {
- if (The_Game() && The_Game()->IsDedicated.Is_True() && AutoRestart.Get_Restart_Flag()) {
- mConnected = false;
- if (SlaveMaster.Am_I_Slave()) {
- AutoRestart.Set_Restart_Flag(false);
- Set_Exit_On_Exception(true);
- cGameData::Set_Manual_Exit(true);
- } else {
- Quit_And_Restart();
- }
- }
- }
-
-
-
- }
|