wolgmode.cpp 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/wolgmode.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 10/19/02 12:51p $*
  29. * *
  30. * $Revision:: 124 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "WOLGMode.h"
  36. #include "GameData.h"
  37. #include "GameChanList.h"
  38. #include "GameChannel.h"
  39. #include "GameInitMgr.h"
  40. #include "WOLChatMgr.h"
  41. #include "WOLBuddyMgr.h"
  42. #include "WOLQuickMatch.h"
  43. #include "WOLGameInfo.h"
  44. #include "DlgWOLWait.h"
  45. #include "DlgMessageBox.h"
  46. #include "_globals.h"
  47. #include "colors.h"
  48. #include "cNetwork.h"
  49. #include "GameResSend.h"
  50. #include "PlayerManager.h"
  51. #include "MessageWindow.h"
  52. #include "natter.h"
  53. #include "WWProfile.h"
  54. #include "BandwidthCheck.h"
  55. #include "WOLLoginProfile.h"
  56. #include "DlgDownload.h"
  57. #include "AutoStart.h"
  58. #include "cpudetect.h"
  59. #include "dx8wrapper.h"
  60. #include "systeminfolog.h"
  61. #include "registry.h"
  62. #include "init.h"
  63. #include "debug.h"
  64. #include <WWOnline\WOLString.h>
  65. #include <WWOnline\WOLProduct.h>
  66. #include <WWOnline\WOLSession.h>
  67. #include <WWOnline\WOLChannel.h>
  68. #include <WWOnline\WaitCondition.h>
  69. #include <WWOnline\WOLGame.h>
  70. #include <WWOnline\WOLGameOptions.h>
  71. #include <WWOnline\WOLPageMsg.h>
  72. #include <WWOnline\WOLLadder.h>
  73. #include <WWOnline\WOLConnect.h>
  74. #include <WWOnline\WOLServer.h>
  75. #include <WWOnline\PingProfile.h>
  76. #include <WWAudio\WWAudio.h>
  77. #include <WWLib\RealCRC.h>
  78. #include "String_IDs.h"
  79. #include <WWTranslateDB\TranslateDB.h>
  80. #include <WWDebug\WWDebug.h>
  81. #include <WWDebug\WWProfile.h>
  82. #include "specialbuilds.h"
  83. #include "slavemaster.h"
  84. #include "sctextobj.h"
  85. #include "mainloop.h"
  86. using namespace WWOnline;
  87. // Check for patches every five minutes
  88. #define PATCH_CHECK_FREQUENCY (1000 * 5)
  89. const int RENEGADE_GAMECODE = 12;
  90. const wchar_t* RENEGADE_LOBBY_PASSWORD = L"not_a_valid_password"; // Password removed per Security review requirements. LFeenanEA - 27th January 2025
  91. const wchar_t* _cdecl Translate_WOLString(const char* token)
  92. {
  93. if (token) {
  94. StringClass desc(80, true);
  95. desc.Format("IDS_%s", token);
  96. const WCHAR* text = TRANSLATE_BY_DESC(desc);
  97. #ifdef WWDEBUG
  98. if (STRING_NOT_FOUND == text) {
  99. WWDEBUG_SAY(("ERROR: WOL String '%s' not found!\n", token));
  100. return L"WOL_NO_STRING";
  101. }
  102. #endif
  103. return text;
  104. }
  105. WWDEBUG_SAY(("WARNING: WOL_xxxx token is NULL\n"));
  106. return L"WOL_BADSTRING";
  107. }
  108. /******************************************************************************
  109. *
  110. * NAME
  111. * WolGameModeClass::WolGameModeClass
  112. *
  113. * DESCRIPTION
  114. * Constructor
  115. *
  116. * INPUTS
  117. * NONE
  118. *
  119. * RESULT
  120. * NONE
  121. *
  122. ******************************************************************************/
  123. WolGameModeClass::WolGameModeClass() :
  124. mWOLChatMgr(NULL),
  125. mWOLBuddyMgr(NULL),
  126. mGameInProgress(false),
  127. mQuietMode(false),
  128. mConnected(false),
  129. mLastPatchCheckTime(0),
  130. mStartQuitProcessTime(0),
  131. mPatchAvailable(false),
  132. mMonitorConnection(false)
  133. {
  134. WWDEBUG_SAY(("WOLGameModeClass Instantiated\n"));
  135. WOLString::SetLookupFunc(Translate_WOLString);
  136. }
  137. /******************************************************************************
  138. *
  139. * NAME
  140. * WolGameModeClass::~WolGameModeClass
  141. *
  142. * DESCRIPTION
  143. * Destructor
  144. *
  145. * INPUTS
  146. * NONE
  147. *
  148. * RESULT
  149. * NONE
  150. *
  151. ******************************************************************************/
  152. WolGameModeClass::~WolGameModeClass()
  153. {
  154. WWDEBUG_SAY(("WOLGameModeClass Destroyed\n"));
  155. }
  156. /******************************************************************************
  157. *
  158. * NAME
  159. * WolGameModeClass::Init
  160. *
  161. * DESCRIPTION
  162. * Activate Westwood Online game mode
  163. *
  164. * INPUTS
  165. * NONE
  166. *
  167. * RESULT
  168. * NONE
  169. *
  170. ******************************************************************************/
  171. void WolGameModeClass::Init(void)
  172. {
  173. WWDEBUG_SAY(("WolGameModeClass Init\n"));
  174. // Check if product is already initialized
  175. RefPtrConst<Product> product = Product::Current();
  176. if (!product.IsValid()) {
  177. Product::Initializer(APPLICATION_SUB_KEY_NAME, RENEGADE_GAMECODE, RENEGADE_LOBBY_PASSWORD, RENEGADE_BASE_SKU);
  178. }
  179. mWOLSession = Session::GetInstance(true);
  180. if (mWOLSession.IsValid()) {
  181. mWOLSession->EnableProgressiveChannelList(true);
  182. mWOLSession->SetAutoRequestFlags(REQUEST_NONE);
  183. Observer<LadderInfoEvent>::NotifyMe(*mWOLSession);
  184. mWOLBuddyMgr = WOLBuddyMgr::GetInstance(true);
  185. WWASSERT_PRINT(mWOLBuddyMgr, "WOLBuddyManager failed to instantiate.");
  186. mWOLChatMgr = WOLChatMgr::GetInstance(true);
  187. WWASSERT_PRINT(mWOLChatMgr, "WOLChatMgr failed to instantiate.");
  188. WOLNATInterface.Init();
  189. LoginProfile::EnableSaving(mWOLSession->IsStoreLoginAllowed());
  190. }
  191. mQuickMatch = NULL;
  192. mTheGame = NULL;
  193. }
  194. /******************************************************************************
  195. *
  196. * NAME
  197. * WolGameModeClass::Shutdown
  198. *
  199. * DESCRIPTION
  200. * Deactivate Westwood Online game mode.
  201. *
  202. * INPUTS
  203. * NONE
  204. *
  205. * RESULT
  206. * NONE
  207. *
  208. ******************************************************************************/
  209. void WolGameModeClass::Shutdown(void)
  210. {
  211. WWDEBUG_SAY(("WolGameModeClass Shutdown\n"));
  212. if (mWOLSession.IsValid()) {
  213. WOLNATInterface.Shutdown();
  214. RefPtr<WaitCondition> logoutWait = mWOLSession->Logout();
  215. WWASSERT(logoutWait.IsValid());
  216. DlgWOLWait::DoDialog(IDS_WOL_LOGOFF, logoutWait);
  217. }
  218. if (mWOLBuddyMgr) {
  219. mWOLBuddyMgr->Release_Ref();
  220. mWOLBuddyMgr = NULL;
  221. }
  222. if (mWOLChatMgr) {
  223. mWOLChatMgr->Release_Ref();
  224. mWOLChatMgr = NULL;
  225. }
  226. // Release current profile.
  227. LoginProfile::SetCurrent(NULL);
  228. LoginInfo::ClearList();
  229. mMonitorConnection = false;
  230. mWOLSession.Release();
  231. }
  232. /******************************************************************************
  233. *
  234. * NAME
  235. * WolGameModeClass::Think
  236. *
  237. * DESCRIPTION
  238. * Periodic processing; called once each game loop.
  239. *
  240. * INPUTS
  241. * NONE
  242. *
  243. * RESULT
  244. * NONE
  245. *
  246. ******************************************************************************/
  247. void WolGameModeClass::Think(void)
  248. {
  249. WWPROFILE("WOL Think");
  250. static unsigned long _last_auto_kick = 0;
  251. static unsigned long _kick_history_persist_time = 1000 * 60 * 60;
  252. unsigned long time = TIMEGETTIME();
  253. //---------------------------------------------------------------------------
  254. // Yield time to WWOnline
  255. //---------------------------------------------------------------------------
  256. if (mWOLSession.IsValid()) {
  257. mWOLSession->Process();
  258. }
  259. //---------------------------------------------------------------------------
  260. // Periodically update quickmatch bot with recent server information
  261. //---------------------------------------------------------------------------
  262. if (mGameInProgress) {// && mQuickMatch) {
  263. unsigned long theTime = TIMEGETTIME();
  264. if (theTime >= mSendServerInfoTime) {
  265. //mSendServerInfoTime = (theTime + (120 * 1000));
  266. //
  267. // Try to help with hacks by updating the topic more frequently. Grrrr.
  268. //
  269. mSendServerInfoTime = (theTime + (20 * 1000));
  270. RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
  271. Update_Channel_Settings(mTheGame, channel);
  272. mWOLSession->SendChannelTopic();
  273. if (mQuickMatch) {
  274. const char* exInfo = channel->GetExtraInfo();
  275. const char* topic = channel->GetTopic();
  276. mQuickMatch->SendServerInfo(exInfo, topic);
  277. }
  278. }
  279. }
  280. //---------------------------------------------------------------------------
  281. // Autokick
  282. //---------------------------------------------------------------------------
  283. if (mGameInProgress && (time - _last_auto_kick > 2000 || time < _last_auto_kick)) {
  284. _last_auto_kick = time;
  285. Auto_Kick();
  286. //
  287. // Check for deadbeat channel lurkers.
  288. //
  289. if (cNetwork::I_Am_Server() && mGameInProgress) {
  290. unsigned long time = TIMEGETTIME();
  291. //
  292. // Clear out old kicklist entries.
  293. //
  294. for (int i = IdleKickNameList.Count() - 1 ; i >= 0 ; i--) {
  295. if (time - IdleKickTimeList[i] > _kick_history_persist_time || time < IdleKickTimeList[i]) {
  296. IdleKickTimeList.Delete(i);
  297. IdleKickNameList.Delete(i);
  298. }
  299. }
  300. const UserList& userList = mWOLSession->GetUserList();
  301. const unsigned int count = userList.size();
  302. for (unsigned int index = 0; index < count; index++) {
  303. const RefPtr<UserData>& user = userList[index];
  304. WWASSERT(user.IsValid());
  305. if (user.IsValid()) {
  306. //
  307. // Make sure it's not me.
  308. //
  309. const RefPtr<LoginInfo>& login = mWOLSession->GetCurrentLogin();
  310. WideStringClass myname;
  311. if (login.IsValid()) {
  312. myname = login->GetNickname();
  313. }
  314. if (myname.Compare_No_Case(user->GetName())) {
  315. //
  316. // Handle timer wrap.
  317. //
  318. if (time < user->mKickTimer) {
  319. user->mKickTimer = time;
  320. }
  321. if (!cPlayerManager::Find_Player(user->GetName())) {
  322. if (time - user->mKickTimer > 120 * 1000) {
  323. StringClass tempstr;
  324. user->GetName().Convert_To(tempstr);
  325. WWDEBUG_SAY(("Kicking '%s' for sitting in the channel while not in the game\n", tempstr.Peek_Buffer()));
  326. mWOLSession->KickUser(user->GetName());
  327. user->mKickTimer += 10*1000;
  328. //
  329. // If he's already been kicked for this recently then ban him.
  330. //
  331. int chances = 3;
  332. for (int i=0 ; i < IdleKickNameList.Count() ; i++) {
  333. if (IdleKickNameList[i].Compare_No_Case(tempstr) == 0) {
  334. chances--;
  335. if (chances == 0) {
  336. mWOLSession->BanUser(user->GetName(), true);
  337. WWDEBUG_SAY(("Banning '%s' for being kicked too often.\n", tempstr.Peek_Buffer()));
  338. break;
  339. }
  340. }
  341. }
  342. if (chances > 0) {
  343. WWDEBUG_SAY(("'%s' not banned - %d chances left.\n", tempstr.Peek_Buffer(), chances));
  344. StringClass stringy(user->GetName());
  345. IdleKickNameList.Add(stringy);
  346. IdleKickTimeList.Add(TIMEGETTIME());
  347. }
  348. }
  349. } else {
  350. user->mKickTimer = time;
  351. }
  352. }
  353. }
  354. }
  355. }
  356. }
  357. //---------------------------------------------------------------------------
  358. // Check for restart conditions.
  359. //---------------------------------------------------------------------------
  360. if (mMonitorConnection) {
  361. // Check for a pending restart for a new patch.
  362. if ((mPatchAvailable || !mConnected) && mStartQuitProcessTime) {
  363. if (time - mStartQuitProcessTime > 1000 * 4) {
  364. if (SlaveMaster.Am_I_Slave()) {
  365. Set_Exit_On_Exception(true);
  366. cGameData::Set_Manual_Exit(true);
  367. } else {
  368. Quit_And_Restart();
  369. }
  370. return;
  371. }
  372. }
  373. // Check for patches.
  374. // This doesn't work because you can't get a server list without also doing a complete reset of wolapi.
  375. #if (0)
  376. if (time - mLastPatchCheckTime > PATCH_CHECK_FREQUENCY) {
  377. mLastPatchCheckTime = time;
  378. if (mWOLSession.IsValid()) {
  379. #ifdef WWDEBUG
  380. bool success =
  381. #endif //WWDEBUG
  382. mWOLSession->RequestServerList(true);
  383. WWASSERT(success);
  384. }
  385. }
  386. #endif //(0)
  387. // If we have lost connection and the number of players drops to zero then we can quit.
  388. if (mMonitorConnection && !mConnected) {
  389. if (The_Game() && The_Game()->Get_Time_Limit_Minutes()) {
  390. if (cPlayerManager::Count() == 0) {
  391. Quit_And_Restart();
  392. }
  393. }
  394. }
  395. }
  396. // Firewall code service.
  397. WOLNATInterface.Service();
  398. }
  399. /******************************************************************************
  400. *
  401. * NAME
  402. * WolGameModeClass::System_Timer_Reset
  403. *
  404. * DESCRIPTION
  405. * Reset any internal variables as needed when the system timer resets.
  406. *
  407. * INPUTS
  408. * NONE
  409. *
  410. * RESULT
  411. * NONE
  412. *
  413. ******************************************************************************/
  414. void WolGameModeClass::System_Timer_Reset(void)
  415. {
  416. mSendServerInfoTime = (TIMEGETTIME() + (120 * 1000));
  417. }
  418. /******************************************************************************
  419. *
  420. * NAME
  421. * WolGameModeClass::Create_Game
  422. *
  423. * DESCRIPTION
  424. * Perform necessary game creation tasks for WWOnline.
  425. * NOTE: This should only be called by game hosts.
  426. *
  427. * INPUTS
  428. * Game - Instance of game to create for Westwood Online.
  429. *
  430. * RESULT
  431. * NONE
  432. *
  433. ******************************************************************************/
  434. void WolGameModeClass::Create_Game(cGameData* theGame)
  435. {
  436. WWDEBUG_SAY(("WolGameModeClass::Create_Game\n"));
  437. if (theGame) {
  438. mTheGame = theGame;
  439. mGameID = 0;
  440. mGameInProgress = false;
  441. //-------------------------------------------------------------------------
  442. // Create and initialize channel for the new game.
  443. //-------------------------------------------------------------------------
  444. const WideStringClass& name = theGame->Get_Owner();
  445. const wchar_t* password = theGame->Get_Password();
  446. WWDEBUG_SAY(("Creating game channel '%S' Password: '%S'\n", (const WCHAR*)name, password));
  447. RefPtrConst<Product> product = Product::Current();
  448. WWASSERT(product.IsValid());
  449. int gameCode = product->GetGameCode();
  450. RefPtr<ChannelData> channel = ChannelData::Create(name, password, gameCode);
  451. WWASSERT(channel.IsValid());
  452. // Export channel settings for the game.
  453. Update_Channel_Settings(theGame, channel);
  454. //-------------------------------------------------------------------------
  455. // Request WWOnline channel creation
  456. //-------------------------------------------------------------------------
  457. mChannelCreateSuccessFlag = false;
  458. RefPtr<WaitCondition> createWait = mWOLSession->CreateChannel(channel, password);
  459. WWASSERT(createWait.IsValid());
  460. DlgWOLWait::DoDialog(IDS_GAME_CREATECHANNEL, createWait, this, 0, mQuietMode ? 0xffffffff : 0);
  461. }
  462. }
  463. /******************************************************************************
  464. *
  465. * NAME
  466. * WolGameModeClass::Leave_Game
  467. *
  468. * DESCRIPTION
  469. * Leave WWOnline game
  470. *
  471. * INPUTS
  472. * NONE
  473. *
  474. * RESULT
  475. * NONE
  476. *
  477. ******************************************************************************/
  478. void WolGameModeClass::Leave_Game(void)
  479. {
  480. WWDEBUG_SAY(("WolGameModeClass::Leave_Game\n"));
  481. // Stop listening WOLSession notifications.
  482. Observer<GameOptionsMessage>::StopObserving();
  483. Observer<ChannelEvent>::StopObserving();
  484. Observer<UserEvent>::StopObserving();
  485. Observer<ServerError>::StopObserving();
  486. Observer<ConnectionStatus>::StopObserving();
  487. // Shutdown quickmatch
  488. if (mQuickMatch) {
  489. mQuickMatch->Release_Ref();
  490. mQuickMatch = NULL;
  491. }
  492. // Leave the game channel.
  493. if (mTheGame) {
  494. WWASSERT(mWOLSession.IsValid());
  495. RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
  496. WWASSERT(wait.IsValid());
  497. DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
  498. }
  499. mTheGame = NULL;
  500. mGameID = 0;
  501. mGameInProgress = false;
  502. }
  503. /******************************************************************************
  504. *
  505. * NAME
  506. * WolGameModeClass::Start_Game
  507. *
  508. * DESCRIPTION
  509. * Start of game processing. This is performed by both the host and clients
  510. * at the begining of each game.
  511. *
  512. * INPUTS
  513. * Game - Instance of game starting
  514. *
  515. * RESULT
  516. * NONE
  517. *
  518. ******************************************************************************/
  519. void Get_Compact_Detail_String(StringClass& tmp);
  520. void WolGameModeClass::Start_Game(cGameData* theGame)
  521. {
  522. WWDEBUG_SAY(("WolGameModeClass::Start_Game\n"));
  523. // The game host (server) is responsible for obtaining the game ID
  524. if (cNetwork::I_Am_Server()) {
  525. WWASSERT(theGame == mTheGame && "Start_Game cGameData* mismatch");
  526. // Re-evaluate the clans in this game.
  527. Evaluate_Clans(theGame);
  528. //-------------------------------------------------------------------------
  529. // Update the channel settings for the new game.
  530. //-------------------------------------------------------------------------
  531. RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
  532. WWASSERT(channel.IsValid());
  533. Update_Channel_Settings(theGame, channel);
  534. // Send the chat server the new channel settings.
  535. mWOLSession->SendChannelExtraInfo();
  536. mWOLSession->SendChannelTopic();
  537. if (mQuickMatch) {
  538. const char* exInfo = channel->GetExtraInfo();
  539. const char* topic = channel->GetTopic();
  540. mQuickMatch->SendServerInfo(exInfo, topic);
  541. }
  542. // Reset timer to send server information for quickmatch
  543. mSendServerInfoTime = (TIMEGETTIME() + (120 * 1000));
  544. //-------------------------------------------------------------------------
  545. // Get WWOnline game id for this game.
  546. //-------------------------------------------------------------------------
  547. const WideStringClass& name = theGame->Get_Owner();
  548. UserList players;
  549. RefPtr<UserData> user = mWOLSession->FindUser(name);
  550. players.push_back(user);
  551. RefPtr<WaitCondition> wait = GameStartWait::Create(players, &Game_Start_Timeout_Callback);
  552. WWASSERT(wait.IsValid());
  553. Observer<GameStartEvent>::NotifyMe(*mWOLSession);
  554. DlgWOLWait::DoDialog(TRANSLATE (IDS_MENU_STARTING_WOL_GAME), wait, NULL, 0, mQuietMode ? 0xffffffff : 0);
  555. if (The_Game() && The_Game()->IsDedicated.Is_True()) {
  556. mConnected = true;
  557. mLastPatchCheckTime = TIMEGETTIME();
  558. mStartQuitProcessTime = 0;
  559. mMonitorConnection = true;
  560. Observer<ServerError>::NotifyMe(*mWOLSession);
  561. Observer<ConnectionStatus>::NotifyMe(*mWOLSession);
  562. }
  563. } else {
  564. mTheGame = theGame;
  565. }
  566. // Prevent the page dialog from showing while we are playing the game.
  567. // We will handle the displaying of pages and invitations within the game
  568. // messaging system.
  569. mWOLBuddyMgr->HidePagedDialog();
  570. Observer<WOLPagedEvent>::NotifyMe(*mWOLBuddyMgr);
  571. // Listen to events from WOLSession
  572. Observer<ChannelEvent>::NotifyMe(*mWOLSession);
  573. Observer<UserEvent>::NotifyMe(*mWOLSession);
  574. mGameInProgress = true;
  575. }
  576. /******************************************************************************
  577. *
  578. * NAME
  579. * WolGameModeClass::End_Game
  580. *
  581. * DESCRIPTION
  582. * Do end of game processing.
  583. *
  584. * INPUTS
  585. * NONE
  586. *
  587. * RESULT
  588. * NONE
  589. *
  590. ******************************************************************************/
  591. void WolGameModeClass::End_Game(void)
  592. {
  593. if (mGameInProgress) {
  594. WWDEBUG_SAY(("WolGameModeClass::End_Game\n"));
  595. // The server sends the end of game results
  596. if (mTheGame) {
  597. if (cNetwork::I_Am_Server()) {
  598. SendGameResults(mGameID, mTheGame, cPlayerManager::Get_Player_Object_List());
  599. mWOLSession->GetChatObject()->RequestGameEnd();
  600. //
  601. // Re-read the ban list.
  602. //
  603. KickNameList.Delete_All();
  604. KickIPList.Delete_All();
  605. Read_Kick_List();
  606. } else {
  607. #ifdef BETACLIENT
  608. // Jani do stuff here (send client system information string)
  609. StringClass info(255, true);
  610. info = "SYSINFO:";
  611. info += CPUDetectClass::Get_Compact_Log();
  612. info += DX8Wrapper::Get_Current_Caps()->Get_Compact_Log();
  613. StringClass tmp(255,true);
  614. Get_Compact_Detail_String(tmp);
  615. info += tmp;
  616. PlayerInfoLog::Get_Compact_Log(tmp);
  617. info += tmp;
  618. SystemInfoLog::Get_Compact_Log(tmp);
  619. info += tmp;
  620. BandwidthCheckerClass::Get_Compact_Log(tmp);
  621. info += tmp;
  622. WOLNATInterface.Get_Compact_Log(tmp);
  623. info += tmp;
  624. WWDEBUG_SAY(("Sending compact log: %s\n", info.Peek_Buffer()));
  625. mWOLSession->SendPrivateGameOptions(mTheGame->Get_Owner(), info);
  626. #endif // BETACLIENT
  627. }
  628. }
  629. // Allow the page dialog to show while we are no longer playing the game.
  630. Observer<WOLPagedEvent>::StopObserving();
  631. mWOLBuddyMgr->ShowPagedDialog();
  632. mGameID = 0;
  633. mGameInProgress = false;
  634. }
  635. }
  636. /***********************************************************************************************
  637. * WolGameModeClass::Post_Game_Check -- Call when game is about to cycle. *
  638. * *
  639. * *
  640. * *
  641. * INPUT: Nothing *
  642. * *
  643. * OUTPUT: True if cycle should be aborted *
  644. * *
  645. * WARNINGS: None *
  646. * *
  647. * HISTORY: *
  648. * 11/7/2001 6:07PM ST : Created *
  649. *=============================================================================================*/
  650. bool WolGameModeClass::Post_Game_Check(void)
  651. {
  652. bool retval = false;
  653. if (mMonitorConnection && !mConnected) {
  654. Quit_And_Restart();
  655. retval = true;
  656. }
  657. mMonitorConnection = false;
  658. return(retval);
  659. }
  660. /******************************************************************************
  661. *
  662. * NAME
  663. * WolGameModeClass::Accept_Actions
  664. *
  665. * DESCRIPTION
  666. *
  667. * INPUTS
  668. * Game - Instance of game joining
  669. *
  670. * RESULT
  671. * NONE
  672. *
  673. ******************************************************************************/
  674. void WolGameModeClass::Accept_Actions(void)
  675. {
  676. WWDEBUG_SAY(("WolGameModeClass::Accept_Actions\n"));
  677. }
  678. /******************************************************************************
  679. *
  680. * NAME
  681. * WolGameModeClass::Refusal_Actions
  682. *
  683. * DESCRIPTION
  684. *
  685. * INPUTS
  686. * Game - Instance of game joining
  687. *
  688. * RESULT
  689. * NONE
  690. *
  691. ******************************************************************************/
  692. void WolGameModeClass::Refusal_Actions(void)
  693. {
  694. WWDEBUG_SAY(("WolGameModeClass::Refusal_Actions\n"));
  695. // If the client's request to join the game was refused then we need to make
  696. // sure we leave the host's channel.
  697. RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
  698. DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
  699. }
  700. /******************************************************************************
  701. *
  702. * NAME
  703. * WolGameModeClass::Evaluate_Clans
  704. *
  705. * DESCRIPTION
  706. *
  707. * INPUTS
  708. * Game - Instance of game.
  709. *
  710. * RESULT
  711. * NONE
  712. *
  713. ******************************************************************************/
  714. void WolGameModeClass::Evaluate_Clans(cGameData* theGame)
  715. {
  716. if (theGame && cNetwork::I_Am_Server()) {
  717. theGame->Clear_Clans();
  718. if (theGame->IsClanGame.Is_True()) {
  719. WWDEBUG_SAY(("CLANS: Evaluating clan assignments\n"));
  720. // If the host is a member of a clan then his clan takes a slot
  721. RefPtr<UserData> host = mWOLSession->GetCurrentUser();
  722. if (host.IsValid()) {
  723. unsigned long hostClanID = host->GetSquadID();
  724. theGame->Set_Clan(0, hostClanID);
  725. WWDEBUG_SAY(("CLANS: Assigning slot 0 to '%S' (host) clan #%lu\n", (const WCHAR*)host->GetName(), hostClanID));
  726. }
  727. // Determine which clans are in the game.
  728. const UserList& userList = mWOLSession->GetUserList();
  729. const unsigned int count = userList.size();
  730. for (unsigned int index = 0; index < count; ++index) {
  731. const RefPtr<UserData>& user = userList[index];
  732. WWASSERT(user.IsValid());
  733. unsigned long userClanID = user->GetSquadID();
  734. if (userClanID != 0) {
  735. // If the clan is not already assigned then assign this clan to the next slot.
  736. if (!theGame->Is_Clan_Competing(userClanID)) {
  737. int slot = theGame->Find_Free_Clan_Slot();
  738. WWASSERT(slot != -1 && "More clans in game than slots available");
  739. if (slot != -1) {
  740. WWDEBUG_SAY(("CLANS: Assigning slot %d to clan #%lu\n", slot, userClanID));
  741. theGame->Set_Clan(slot, userClanID);
  742. }
  743. }
  744. }
  745. }
  746. // Force server information to be resent.
  747. mSendServerInfoTime = 0;
  748. }
  749. }
  750. }
  751. /******************************************************************************
  752. *
  753. * NAME
  754. * WolGameModeClass::Update_Channel_Settings
  755. *
  756. * DESCRIPTION
  757. *
  758. * INPUTS
  759. * NONE
  760. *
  761. * RESULT
  762. * NONE
  763. *
  764. ******************************************************************************/
  765. void WolGameModeClass::Update_Channel_Settings(cGameData* theGame, const RefPtr<ChannelData>& channel)
  766. {
  767. WWASSERT(theGame != NULL);
  768. WWASSERT(channel.IsValid());
  769. if (theGame && channel.IsValid()) {
  770. WOLGameInfo gameInfo(*theGame);
  771. gameInfo.ExportToChannel(channel);
  772. // Quickmatch settings are appended to the channel topic
  773. if (theGame->Is_QuickMatch_Server()) {
  774. //---------------------------------------------------------------------------
  775. // Get average FPS of game (Capped at 255 fps)
  776. //---------------------------------------------------------------------------
  777. unsigned long fps = TimeManager::Get_Average_Frame_Rate();
  778. fps = min<unsigned long>(fps, 255);
  779. int numPlayers = theGame->Get_Current_Players();
  780. int avgPing = cPlayerManager::Get_Average_Ping();
  781. avgPing = min<int>(avgPing, UCHAR_MAX);
  782. unsigned short avgPoints = cPlayerManager::Get_Average_WOL_Points();
  783. int avgPlayed = cPlayerManager::Get_Average_Games_Played();
  784. avgPlayed = min<int>(avgPlayed, USHRT_MAX);
  785. // Quickmatch settings format is: |fps,mode,avg_ping,avg_rank,num_players
  786. const char* topic = channel->GetTopic();
  787. char newTopic[81];
  788. sprintf(newTopic, "%s|%02lx%02x%04x%04x%c", topic, fps, avgPing, avgPoints,
  789. avgPlayed, (32 + numPlayers));
  790. channel->SetTopic(newTopic);
  791. }
  792. }
  793. }
  794. /******************************************************************************
  795. *
  796. * NAME
  797. * WolGameModeClass::Init_WOL_Player
  798. *
  799. * DESCRIPTION
  800. *
  801. * INPUTS
  802. * Player - Set players WOL settings.
  803. *
  804. * RESULT
  805. * NONE
  806. *
  807. ******************************************************************************/
  808. void WolGameModeClass::Init_WOL_Player(cPlayer* player)
  809. {
  810. if (player) {
  811. RefPtr<UserData> user = mWOLSession->FindUser(player->Get_Name());
  812. if (user.IsValid()) {
  813. RefPtr<LadderData> ladder = user->GetTeamLadder();
  814. if (ladder.IsValid()) {
  815. player->Set_WOL_Points(ladder->GetPoints());
  816. player->Set_Wol_Rank(ladder->GetRung());
  817. player->Set_Num_Wol_Games(ladder->GetReserved2());
  818. return;
  819. }
  820. }
  821. // Ladder points start at 10000 and vary up or down depending on the players
  822. // performance.
  823. player->Set_WOL_Points(10000);
  824. // Ranking of -1 indicates that the player doesn't have a rank.
  825. player->Set_Wol_Rank(-1);
  826. player->Set_Num_Wol_Games(0);
  827. }
  828. }
  829. /******************************************************************************
  830. *
  831. * NAME
  832. * WolGameModeClass::Get_WOL_User_Data
  833. *
  834. * DESCRIPTION
  835. *
  836. * INPUTS
  837. * Player - Name of player to find.
  838. *
  839. * RESULT
  840. * User - WWOnline user data
  841. *
  842. ******************************************************************************/
  843. RefPtr<UserData> WolGameModeClass::Get_WOL_User_Data(const wchar_t* name)
  844. {
  845. return mWOLSession->FindUser(name);
  846. }
  847. /******************************************************************************
  848. *
  849. * NAME
  850. * WolGameModeClass::Page_WOL_User
  851. *
  852. * DESCRIPTION
  853. *
  854. * INPUTS
  855. * User - Name of user to page.
  856. * Message - Message to send to user.
  857. *
  858. * RESULT
  859. * NONE
  860. *
  861. ******************************************************************************/
  862. void WolGameModeClass::Page_WOL_User(const wchar_t* name, const wchar_t* msg)
  863. {
  864. if (name && (wcslen(name) > 0) && msg && (wcslen(msg) > 0)) {
  865. mWOLSession->PageUser(name, msg);
  866. WideStringClass message(0, true);
  867. message.Format(TRANSLATE(IDS_GAME_PAGING), name, msg);
  868. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  869. }
  870. }
  871. /******************************************************************************
  872. *
  873. * NAME
  874. * WolGameModeClass::Reply_Last_Page
  875. *
  876. * DESCRIPTION
  877. * Send a reply message to the last user who paged.
  878. *
  879. * INPUTS
  880. *
  881. * RESULT
  882. * NONE
  883. *
  884. ******************************************************************************/
  885. void WolGameModeClass::Reply_Last_Page(const wchar_t* msg)
  886. {
  887. if (msg && (wcslen(msg) > 0)) {
  888. const WCHAR* pager = mWOLBuddyMgr->GetLastPagersName();
  889. if (pager && (wcslen(pager) > 0)) {
  890. mWOLBuddyMgr->PageUser(pager, msg);
  891. WideStringClass message(0, true);
  892. message.Format(TRANSLATE(IDS_GAME_PAGE_REPLYING), pager, msg);
  893. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  894. } else {
  895. CombatManager::Get_Message_Window()->Add_Message(TRANSLATE(IDS_GAME_PAGE_REPLY_CANT), COLOR_CONSOLE_TEXT);
  896. }
  897. }
  898. }
  899. /******************************************************************************
  900. *
  901. * NAME
  902. * WolGameModeClass::Locate_WOL_User
  903. *
  904. * DESCRIPTION
  905. *
  906. * INPUTS
  907. * User - Name of user to locate.
  908. *
  909. * RESULT
  910. * NONE
  911. *
  912. ******************************************************************************/
  913. void WolGameModeClass::Locate_WOL_User(const wchar_t* name)
  914. {
  915. if (name && wcslen(name) > 0) {
  916. mWOLSession->RequestLocateUser(name);
  917. WideStringClass message(0, true);
  918. message.Format(TRANSLATE(IDS_GAME_LOCATING_USER), name);
  919. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  920. }
  921. }
  922. /******************************************************************************
  923. *
  924. * NAME
  925. * WolGameModeClass::Invite_WOL_User
  926. *
  927. * DESCRIPTION
  928. *
  929. * INPUTS
  930. * User - Name of user to locate.
  931. *
  932. * RESULT
  933. * NONE
  934. *
  935. ******************************************************************************/
  936. void WolGameModeClass::Invite_WOL_User(const wchar_t* name, const wchar_t* msg)
  937. {
  938. if (name && wcslen(name)) {
  939. cPlayer* player = cPlayerManager::Find_Player(name);
  940. if (player) {
  941. WideStringClass message(0, true);
  942. message.Format(TRANSLATE (IDS_MENU_ALREADY_IN_GAME), name);
  943. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_INVITE_TEXT);
  944. WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
  945. } else {
  946. mWOLBuddyMgr->InviteUser(name, msg);
  947. WideStringClass message(0, true);
  948. message.Format(TRANSLATE(IDS_GAME_INVITING_USER), name);
  949. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  950. }
  951. }
  952. }
  953. /******************************************************************************
  954. *
  955. * NAME
  956. * WolGameModeClass::Join_WOL_User
  957. *
  958. * DESCRIPTION
  959. *
  960. * INPUTS
  961. * User - Name of user to join.
  962. *
  963. * RESULT
  964. * NONE
  965. *
  966. ******************************************************************************/
  967. void WolGameModeClass::Join_WOL_User(const wchar_t* name)
  968. {
  969. // If the name is valid and it is not me
  970. if (name && wcslen(name) && !mWOLSession->IsCurrentUser(name)) {
  971. cPlayer* player = cPlayerManager::Find_Player(name);
  972. if (player) {
  973. WideStringClass message(0, true);
  974. message.Format(TRANSLATE(IDS_MENU_YOURE_ALREADY_IN_GAME), name);
  975. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_INVITE_TEXT);
  976. WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
  977. } else {
  978. RefPtr<UserData> user = UserData::Create(name);
  979. mWOLBuddyMgr->JoinUser(user);
  980. WideStringClass message(0, true);
  981. message.Format(TRANSLATE(IDS_GAME_JOINING_USER), name);
  982. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  983. }
  984. }
  985. }
  986. /******************************************************************************
  987. *
  988. * NAME
  989. * WolGameModeClass::Kick_Player
  990. *
  991. * DESCRIPTION
  992. * Kick a player from the game. Players kicked from a game are also banned
  993. * from rejoining that game. Note: This is only allowed by game server hosts.
  994. *
  995. * INPUTS
  996. * Player - Name of player to kick from the game.
  997. *
  998. * RESULT
  999. * NONE
  1000. *
  1001. ******************************************************************************/
  1002. bool WolGameModeClass::Kick_Player(const wchar_t* name)
  1003. {
  1004. // If the name is not NULL. we are the server and the player to kick is
  1005. // not ourself then proceed with the kick.
  1006. if (name && (wcslen(name) > 0)) {
  1007. if (cNetwork::I_Am_Server() && !mWOLSession->IsCurrentUser(name)) {
  1008. mWOLSession->KickUser(name);
  1009. mWOLSession->BanUser(name, true);
  1010. // Disconnect the player from the server
  1011. WideStringClass playername(0, true);
  1012. playername = name;
  1013. cPlayer* player = cPlayerManager::Find_Player(playername);
  1014. if (player && player->Is_Human()) {
  1015. WideStringClass message(0, true);
  1016. message.Format(TRANSLATE(IDS_GAME_KICKING_USER), name);
  1017. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  1018. int playerID = player->Get_Id();
  1019. cNetwork::Server_Kill_Connection(playerID);
  1020. cNetwork::Cleanup_After_Client(playerID);
  1021. return(true);
  1022. }
  1023. }
  1024. WideStringClass message(0, true);
  1025. message.Format(TRANSLATE(IDS_GAME_KICKING_NOT_ALLOWED), name);
  1026. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
  1027. }
  1028. return(false);
  1029. }
  1030. /***********************************************************************************************
  1031. * WolGameModeClass::Ban_Player -- Add player to ban list *
  1032. * *
  1033. * *
  1034. * *
  1035. * INPUT: Player name *
  1036. * *
  1037. * OUTPUT: Nothing *
  1038. * *
  1039. * WARNINGS: None *
  1040. * *
  1041. * HISTORY: *
  1042. * 8/8/2002 4:33PM ST : Created *
  1043. *=============================================================================================*/
  1044. void WolGameModeClass::Ban_Player(const wchar_t* name, unsigned long ip)
  1045. {
  1046. // If the name is not NULL. we are the server and the player to kick is
  1047. // not ourself then proceed with the kick.
  1048. if (name && cNetwork::I_Am_Server() && !mWOLSession->IsCurrentUser(name)) {
  1049. Kick_Player(name);
  1050. WideStringClass playername(0, true);
  1051. playername = name;
  1052. StringClass pn;
  1053. playername.Convert_To(pn);
  1054. if (!Is_Banned(pn, ip)) {
  1055. KickNameList.Add(pn);
  1056. KickIPList.Add(ip);
  1057. char ipstr[128];
  1058. pn += ":";
  1059. unsigned char *ip_ptr = (unsigned char*)&ip;
  1060. 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]);
  1061. pn += ipstr;
  1062. FILE *kick_list = fopen("wolbanlist.txt", "at");
  1063. if (kick_list != NULL) {
  1064. fwrite(pn.Peek_Buffer(), 1, pn.Get_Length(), kick_list);
  1065. fclose(kick_list);
  1066. }
  1067. DynamicVectorClass<unsigned long> KickIPList;
  1068. }
  1069. }
  1070. }
  1071. /***********************************************************************************************
  1072. * WolGameModeClass::Auto_Kick -- Kick any banned users from the game *
  1073. * *
  1074. * *
  1075. * *
  1076. * INPUT: Nothing *
  1077. * *
  1078. * OUTPUT: Nothing *
  1079. * *
  1080. * WARNINGS: None *
  1081. * *
  1082. * HISTORY: *
  1083. * 8/8/2002 9:24PM ST : Created *
  1084. *=============================================================================================*/
  1085. void WolGameModeClass::Auto_Kick(void)
  1086. {
  1087. if (cNetwork::I_Am_Server()) {
  1088. cPlayer *player = NULL;
  1089. for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List()->Head() ; player_node != NULL; player_node = player_node->Next()) {
  1090. player = player_node->Data();
  1091. if (player->Is_Active()) {
  1092. if (!mWOLSession->IsCurrentUser(player->Get_Name())) {
  1093. StringClass player_name(player->Get_Name());
  1094. if (Is_Banned(player_name, player->Get_Ip_Address())) {
  1095. Kick_Player(player->Get_Name());
  1096. }
  1097. }
  1098. }
  1099. }
  1100. }
  1101. }
  1102. /***********************************************************************************************
  1103. * WolGameModeClass::Is_Banned -- Is this player banned from our WOL server? *
  1104. * *
  1105. * *
  1106. * *
  1107. * INPUT: Player name *
  1108. * IP Address *
  1109. * *
  1110. * OUTPUT: Nothing *
  1111. * *
  1112. * WARNINGS: None *
  1113. * *
  1114. * HISTORY: *
  1115. * 8/8/2002 9:14PM ST : Created *
  1116. *=============================================================================================*/
  1117. bool WolGameModeClass::Is_Banned(const char *player_name, unsigned long ip)
  1118. {
  1119. int i;
  1120. if (KickNameList.Count() == 0) {
  1121. Read_Kick_List();
  1122. }
  1123. for (i=0 ; i<KickNameList.Count() ; i++) {
  1124. if (stricmp(player_name, KickNameList[i].Peek_Buffer()) == 0) {
  1125. return(true);
  1126. }
  1127. }
  1128. for (i=0 ; i<KickIPList.Count() ; i++) {
  1129. if (KickIPList[i] == ip) {
  1130. return(true);
  1131. }
  1132. }
  1133. return(false);
  1134. }
  1135. /***********************************************************************************************
  1136. * WolGameModeClass::Read_Kick_List -- Read the list of autokick players *
  1137. * *
  1138. * *
  1139. * *
  1140. * INPUT: Nothing *
  1141. * *
  1142. * OUTPUT: Nothing *
  1143. * *
  1144. * WARNINGS: None *
  1145. * *
  1146. * HISTORY: *
  1147. * 8/8/2002 9:14PM ST : Created *
  1148. *=============================================================================================*/
  1149. void WolGameModeClass::Read_Kick_List(void)
  1150. {
  1151. FILE *kick_list = fopen("wolbanlist.txt", "rt");
  1152. if (kick_list) {
  1153. int i = 0;
  1154. bool eof = false;
  1155. char temp[256];
  1156. while (!eof) {
  1157. for (i=0 ; i<256 ; i++) {
  1158. if (fread(&temp[i], 1, 1, kick_list) == 0) {
  1159. eof = true;
  1160. break;
  1161. }
  1162. if (temp[i] == '\n') {
  1163. break;
  1164. }
  1165. }
  1166. if (i > 10) {
  1167. temp[i + 1] = 0;
  1168. char *colon_ptr = strchr(temp, ':');
  1169. if (colon_ptr) {
  1170. *colon_ptr = 0;
  1171. KickNameList.Add(temp);
  1172. unsigned long ip = inet_addr(colon_ptr + 1);
  1173. KickIPList.Add(ip);
  1174. }
  1175. }
  1176. }
  1177. fclose(kick_list);
  1178. }
  1179. }
  1180. /******************************************************************************
  1181. *
  1182. * NAME
  1183. * WolGameModeClass::HandleNotification(ChannelEvent)
  1184. *
  1185. * DESCRIPTION
  1186. *
  1187. * INPUTS
  1188. * Event -
  1189. *
  1190. * RESULT
  1191. * NONE
  1192. *
  1193. ******************************************************************************/
  1194. void WolGameModeClass::HandleNotification(ChannelEvent& event)
  1195. {
  1196. // This user has been kicked from the game.
  1197. if (ChannelKicked == event.GetStatus()) {
  1198. WWDEBUG_SAY(("WolGameModeClass Player Kicked!\n"));
  1199. mGameInProgress = false;
  1200. GameInitMgrClass::End_Game();
  1201. GameInitMgrClass::Display_End_Game_Menu();
  1202. DlgMsgBox::DoDialog(TRANSLATE(IDS_MENU_SERVER_MESSAGE_TITLE), TRANSLATE (IDS_MENU_SERVER_KICKED_MESSAGE));
  1203. }
  1204. }
  1205. /******************************************************************************
  1206. *
  1207. * NAME
  1208. * WolGameModeClass::HandleNotification(UserEvent)
  1209. *
  1210. * DESCRIPTION
  1211. *
  1212. * INPUTS
  1213. * Event -
  1214. *
  1215. * RESULT
  1216. * NONE
  1217. *
  1218. ******************************************************************************/
  1219. void WolGameModeClass::HandleNotification(UserEvent& event)
  1220. {
  1221. switch (event.GetEvent()) {
  1222. // A user has been kicked from the game.
  1223. case UserEvent::Kicked: {
  1224. WideStringClass message(0, true);
  1225. message.Format(TRANSLATE(IDS_MENU_PLAYER_KICKED_MESSAGE), event.Subject()->GetName());
  1226. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PUBLIC_TEXT);
  1227. WWAudioClass::Get_Instance()->Create_Instant_Sound("Public_Message", Matrix3D(1));
  1228. }
  1229. break;
  1230. case UserEvent::Located: {
  1231. const RefPtr<UserData>& user = event.Subject();
  1232. // Get the description of the user's location
  1233. WideStringClass location(64, true);
  1234. WOLBuddyMgr::GetLocationDescription(user, location);
  1235. // Build a string containing the user's name
  1236. WideStringClass message(0, true);
  1237. message.Format(TRANSLATE(IDS_CHAT_LOCATEDUSER), user->GetName());
  1238. message += L" - ";
  1239. message += location;
  1240. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PRIVATE_TEXT);
  1241. WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
  1242. }
  1243. break;
  1244. case UserEvent::LadderInfo:
  1245. if (mTheGame) {
  1246. const RefPtr<UserData>& user = event.Subject();
  1247. cPlayer* player = cPlayerManager::Find_Player(user->GetName());
  1248. Init_WOL_Player(player);
  1249. }
  1250. break;
  1251. case UserEvent::Join:
  1252. if (mTheGame && cNetwork::I_Am_Server()) {
  1253. const RefPtr<UserData>& user = event.Subject();
  1254. bool requestDetails = true;
  1255. // If the user is joining a clan game.
  1256. if (mTheGame->IsClanGame.Is_True()) {
  1257. WWDEBUG_SAY(("CLANS: User join clan assignment\n"));
  1258. unsigned long userClanID = user->GetSquadID();
  1259. WWASSERT(userClanID != 0 && "User not in a clan");
  1260. // If the game is open to a new clan then assign the user to a
  1261. // participating clan or a new slot.
  1262. if (mTheGame->Is_Clan_Game_Open()) {
  1263. // If the user is not a member of a participating clan then assign
  1264. // the next free slot to this users clan.
  1265. if (!mTheGame->Is_Clan_Competing(userClanID)) {
  1266. int slot = mTheGame->Find_Free_Clan_Slot();
  1267. if (slot != -1) {
  1268. WWDEBUG_SAY(("CLANS: Slot %d filled by '%S' Clan #%lu\n", slot,
  1269. (const WCHAR*)user->GetName(), userClanID));
  1270. mTheGame->Set_Clan(slot, userClanID);
  1271. }
  1272. // Send the chat server the new channel settings.
  1273. RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
  1274. Update_Channel_Settings(mTheGame, channel);
  1275. mWOLSession->SendChannelExtraInfo();
  1276. }
  1277. } else {
  1278. // If the game is closed and the user is not a member of one of the
  1279. // competing clans then kick him.
  1280. if (!mTheGame->Is_Clan_Competing(userClanID)) {
  1281. WWDEBUG_SAY(("CLANS: Game closed. Kicking user '%S'\n",
  1282. (const WCHAR*)user->GetName()));
  1283. mWOLSession->KickUser(user->GetName());
  1284. requestDetails = false;
  1285. }
  1286. }
  1287. }
  1288. if (requestDetails) {
  1289. mWOLSession->RequestUserDetails(user, REQUEST_LADDERINFO|REQUEST_SQUADINFO);
  1290. }
  1291. }
  1292. break;
  1293. case UserEvent::Leave:
  1294. if (mTheGame && cNetwork::I_Am_Server()) {
  1295. if (mTheGame->IsClanGame.Is_True()) {
  1296. WWDEBUG_SAY(("CLANS: User leave re-evaluate clan assignment\n"));
  1297. Evaluate_Clans(mTheGame);
  1298. }
  1299. }
  1300. break;
  1301. default:
  1302. break;
  1303. }
  1304. }
  1305. /******************************************************************************
  1306. *
  1307. * NAME
  1308. * WolGameModeClass::HandleNotification(DlgWOLWaitEvent)
  1309. *
  1310. * DESCRIPTION
  1311. * Response to completion of game channel creation.
  1312. *
  1313. * INPUTS
  1314. * Event -
  1315. *
  1316. * RESULT
  1317. * NONE
  1318. *
  1319. ******************************************************************************/
  1320. void WolGameModeClass::HandleNotification(DlgWOLWaitEvent& wolEvent)
  1321. {
  1322. if (wolEvent.Result() == WaitCondition::ConditionMet) {
  1323. WWASSERT(mTheGame != NULL);
  1324. mChannelCreateSuccessFlag = true;
  1325. // Startup quickmatch if we are serving quickmatch games.
  1326. if (mTheGame->Is_QuickMatch_Server()) {
  1327. mQuickMatch = WOLQuickMatch::Create();
  1328. WWASSERT(mQuickMatch);
  1329. }
  1330. mSendServerInfoTime = 0;
  1331. // Start listening to Game Options messages from clients
  1332. Observer<GameOptionsMessage>::NotifyMe(*mWOLSession);
  1333. // Listen to events from WOLSession
  1334. Observer<ChannelEvent>::NotifyMe(*mWOLSession);
  1335. Observer<UserEvent>::NotifyMe(*mWOLSession);
  1336. } else {
  1337. if (!mQuietMode) {
  1338. DlgMsgBox::DoDialog(TRANSLATE (IDS_MENU_FAILED_TO_CREATE_GAME), wolEvent.Subject()->GetResultText());
  1339. }
  1340. }
  1341. Signaler<WolGameModeClass>::SendSignal(*this);
  1342. }
  1343. /******************************************************************************
  1344. *
  1345. * NAME
  1346. * WolGameModeClass::HandleNotification(GameStartEvent)
  1347. *
  1348. * DESCRIPTION
  1349. * Handle game start acknowledgement.
  1350. *
  1351. * INPUTS
  1352. *
  1353. * RESULT
  1354. * NONE
  1355. *
  1356. ******************************************************************************/
  1357. void WolGameModeClass::HandleNotification(GameStartEvent& start)
  1358. {
  1359. WWDEBUG_SAY(("GameStartEvent received\n"));
  1360. mGameID = 0;
  1361. if (start.IsSuccess()) {
  1362. mGameID = start.GetGameID();
  1363. WWDEBUG_SAY(("GameID = %ld\n", mGameID));
  1364. }
  1365. }
  1366. /******************************************************************************
  1367. *
  1368. * NAME
  1369. * WolGameModeClass::HandleNotification(GameOptionsMessage)
  1370. *
  1371. * DESCRIPTION
  1372. * Handle game options requests coming from other users.
  1373. *
  1374. * INPUTS
  1375. * OptionsMessage -
  1376. *
  1377. * RESULT
  1378. * NONE
  1379. *
  1380. ******************************************************************************/
  1381. void WolGameModeClass::HandleNotification(GameOptionsMessage& message)
  1382. {
  1383. if (cNetwork::I_Am_Server() && mTheGame) {
  1384. const char* request = message.GetOptions();
  1385. // Request for game information?
  1386. if (strcmp("RGINFO", request) == 0) {
  1387. WideStringClass requestor(0, true);
  1388. requestor = message.GetSendersName();
  1389. //-----------------------------------------------------------------------
  1390. // Send game information
  1391. //-----------------------------------------------------------------------
  1392. unsigned long mapCRC = CRC_Stringi(mTheGame->Get_Map_Name());
  1393. float seconds = mTheGame->Get_Time_Remaining_Seconds();
  1394. // Game info sent as: MapCRC Seconds remaining
  1395. StringClass info(0, true);
  1396. info.Format("GINFO:%08lx %.4f", mapCRC, seconds);
  1397. WWDEBUG_SAY(("%S\n", info));
  1398. mWOLSession->SendPrivateGameOptions(requestor, info);
  1399. //-----------------------------------------------------------------------
  1400. // Send team information
  1401. //-----------------------------------------------------------------------
  1402. SList<cTeam>* teamList = cTeamManager::Get_Team_Object_List();
  1403. WWASSERT(teamList != NULL);
  1404. SLNode<cTeam>* teamNode = teamList->Head();
  1405. while (teamNode) {
  1406. cTeam* team = teamNode->Data();
  1407. WWASSERT(team != NULL);
  1408. int teamID = team->Get_Id();
  1409. int teamScore = team->Get_Score();
  1410. info.Format("TINFO:%d %d", teamID, teamScore);
  1411. WWDEBUG_SAY(("%S\n", info));
  1412. mWOLSession->SendPrivateGameOptions(requestor, info);
  1413. teamNode = teamNode->Next();
  1414. }
  1415. //-----------------------------------------------------------------------
  1416. // Send player information
  1417. //-----------------------------------------------------------------------
  1418. SList<cPlayer>* playerList = cPlayerManager::Get_Player_Object_List();
  1419. SLNode<cPlayer>* playerNode = playerList->Head();
  1420. while (playerNode) {
  1421. cPlayer* player = playerNode->Data();
  1422. if (player && player->Is_Active() && player->Is_Human()) {
  1423. const WideStringClass& name = player->Get_Name();
  1424. int type = player->Get_Player_Type();
  1425. int rung = player->Get_Rung();
  1426. int kills = player->Get_Kills();
  1427. int deaths = player->Get_Deaths();
  1428. int score = player->Get_Score();
  1429. // PINFO string format: Name fps,type,rank,kills,deaths
  1430. info.Format("PINFO:%S %d %d %d %d %d", (const WCHAR*)name, type, rung, kills, deaths, score);
  1431. mWOLSession->SendPrivateGameOptions(requestor, info);
  1432. }
  1433. playerNode = playerNode->Next();
  1434. }
  1435. } else {
  1436. // Write client system info to disk
  1437. const char* cmd = strstr(request, "SYSINFO:");
  1438. if (cmd == request) {
  1439. static int sysinfo_log_disabled=-1;
  1440. if (sysinfo_log_disabled==-1) { // Read from registry only once per run
  1441. RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG );
  1442. if ( registry.Is_Valid() ) {
  1443. sysinfo_log_disabled=registry.Get_Int( VALUE_NAME_DISABLE_SERVER_SYSINFO_COLLECTING, -1 );
  1444. // Write to registry to create the key if it didn't exist
  1445. if (sysinfo_log_disabled==-1) {
  1446. sysinfo_log_disabled=0;
  1447. registry.Set_Int( VALUE_NAME_DISABLE_SERVER_SYSINFO_COLLECTING, sysinfo_log_disabled);
  1448. }
  1449. }
  1450. }
  1451. // Only copy the sysinfo if it isn't disabled in registry
  1452. if (sysinfo_log_disabled==0) {
  1453. const char* data = (request + strlen("SYSINFO:"));
  1454. int datalen=strlen(data);
  1455. if (!datalen) return;
  1456. StringClass tmp(0,true);
  1457. StringClass requestor(0, true);
  1458. requestor = message.GetSendersName();
  1459. StringClass datastring;
  1460. datastring=requestor;
  1461. datastring+="\t";
  1462. unsigned long versionminor,versionmajor;
  1463. Get_Version_Number(&versionmajor,&versionminor);
  1464. SYSTEMTIME time;
  1465. GetSystemTime(&time);
  1466. tmp.Format("%d/%d/%d %d:%d\t%d.%d\t",
  1467. time.wMonth,
  1468. time.wDay,
  1469. time.wYear,
  1470. time.wHour,
  1471. time.wMinute,
  1472. versionmajor,
  1473. versionminor);
  1474. datastring+=tmp;
  1475. datastring+=data;
  1476. datastring+="\r\n";
  1477. // Verify the sysinfo folder
  1478. StringClass dirname(0,true);
  1479. dirname.Format("sysinfo_%d",DebugManager::Get_Version_Number());
  1480. if (GetFileAttributes(dirname)==0xffffffff) {
  1481. if (!CreateDirectory(dirname,NULL)) {
  1482. return;
  1483. }
  1484. }
  1485. StringClass filename(0,true);
  1486. filename=dirname;
  1487. filename+="\\";
  1488. tmp=requestor;
  1489. filename+=tmp;
  1490. filename+=".txt";
  1491. DWORD written;
  1492. HANDLE file;
  1493. file = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
  1494. FILE_ATTRIBUTE_NORMAL, NULL);
  1495. if (INVALID_HANDLE_VALUE != file) {
  1496. SetFilePointer(file, 0, NULL, FILE_END);
  1497. WriteFile(file, datastring, strlen(datastring), &written, NULL);
  1498. CloseHandle(file);
  1499. }
  1500. }
  1501. }
  1502. }
  1503. }
  1504. }
  1505. /******************************************************************************
  1506. *
  1507. * NAME
  1508. * WolGameModeClass::HandleNotification(LadderInfoEvent)
  1509. *
  1510. * DESCRIPTION
  1511. *
  1512. * INPUTS
  1513. *
  1514. * RESULT
  1515. * NONE
  1516. *
  1517. ******************************************************************************/
  1518. void WolGameModeClass::HandleNotification(LadderInfoEvent& ladderEvent)
  1519. {
  1520. if (ladderEvent.IsRanked()) {
  1521. LadderType type = ladderEvent.GetLadderType();
  1522. // If this is for the locale user and the ladder information is cached
  1523. // then update there profile with the latest ladder information.
  1524. if (LadderType_Team == type) {
  1525. WideStringClass name(64, true);
  1526. name = ladderEvent.GetReceivedName();
  1527. if (mWOLSession->IsCurrentUser(name)) {
  1528. LoginProfile* profile = LoginProfile::Get(name, false);
  1529. if (profile) {
  1530. WWDEBUG_SAY(("Updating team ladder info for %S\n", profile->GetName()));
  1531. const WOL::Ladder& wolLadder = ladderEvent.GetWOLLadder();
  1532. // Save the number of games played.
  1533. profile->SetGamesPlayed(wolLadder.reserved2);
  1534. // Save the ranking information
  1535. LoginProfile::Ranking rank;
  1536. rank.Wins = wolLadder.wins;
  1537. rank.Losses = wolLadder.losses;
  1538. rank.Deaths = wolLadder.reserved1;
  1539. rank.Kills = wolLadder.kills;
  1540. rank.Points = wolLadder.points;
  1541. rank.Rank = wolLadder.rung;
  1542. profile->SetRanking(LadderType_Team, rank);
  1543. profile->SaveSettings();
  1544. profile->Release_Ref();
  1545. }
  1546. }
  1547. } else if (LadderType_Clan == type) {
  1548. RefPtr<UserData> user = mWOLSession->GetCurrentUser();
  1549. if (user.IsValid()) {
  1550. RefPtr<SquadData> squad = user->GetSquad();
  1551. if (squad.IsValid() && (stricmp(squad->GetAbbr(), ladderEvent.GetReceivedName()) == 0)) {
  1552. LoginProfile* profile = LoginProfile::Get(user->GetName(), false);
  1553. if (profile) {
  1554. WWDEBUG_SAY(("Updating clan ladder info for %S\n", profile->GetName()));
  1555. const WOL::Ladder& wolLadder = ladderEvent.GetWOLLadder();
  1556. // Save the ranking information
  1557. LoginProfile::Ranking rank;
  1558. rank.Wins = wolLadder.wins;
  1559. rank.Losses = wolLadder.losses;
  1560. rank.Deaths = wolLadder.reserved1;
  1561. rank.Kills = wolLadder.kills;
  1562. rank.Points = wolLadder.points;
  1563. rank.Rank = wolLadder.rung;
  1564. profile->SetRanking(LadderType_Clan, rank);
  1565. profile->SaveSettings();
  1566. profile->Release_Ref();
  1567. }
  1568. }
  1569. }
  1570. }
  1571. }
  1572. }
  1573. /***********************************************************************************************
  1574. * WolGameModeClass::HandleNotification -- Handle connection status notifications *
  1575. * *
  1576. * *
  1577. * *
  1578. * INPUT: Connection status *
  1579. * *
  1580. * OUTPUT: Nothing *
  1581. * *
  1582. * WARNINGS: None *
  1583. * *
  1584. * HISTORY: *
  1585. * 11/8/2001 10:20PM ST : Created *
  1586. *=============================================================================================*/
  1587. void WolGameModeClass::HandleNotification(ConnectionStatus &status)
  1588. {
  1589. if (mMonitorConnection && status == ConnectionDisconnected) {
  1590. Handle_Disconnect();
  1591. }
  1592. }
  1593. /***********************************************************************************************
  1594. * WolGameModeClass::Handle_Disconnect -- Handle disconnect from chat server *
  1595. * *
  1596. * *
  1597. * *
  1598. * INPUT: Nothing *
  1599. * *
  1600. * OUTPUT: Nothing *
  1601. * *
  1602. * WARNINGS: None *
  1603. * *
  1604. * HISTORY: *
  1605. * 11/8/2001 10:21PM ST : Created *
  1606. *=============================================================================================*/
  1607. void WolGameModeClass::Handle_Disconnect(void)
  1608. {
  1609. if (mMonitorConnection && mConnected) {
  1610. mConnected = false;
  1611. if (cNetwork::I_Am_Server()) {
  1612. if (The_Game() && The_Game()->IsDedicated.Is_True() && AutoRestart.Get_Restart_Flag()) {
  1613. /*
  1614. ** If the game has a time limit and players then we will wait until the next map change otherwise we will stop now.
  1615. */
  1616. WWASSERT(PTheGameData != NULL);
  1617. //if (!The_Game()->Get_Time_Limit_Minutes() || SlaveMaster.Am_I_Slave()) {
  1618. if (cPlayerManager::Count() == 0) {
  1619. if (SlaveMaster.Am_I_Slave()) {
  1620. AutoRestart.Set_Restart_Flag(false);
  1621. Set_Exit_On_Exception(true);
  1622. cGameData::Set_Manual_Exit(true);
  1623. } else {
  1624. Quit_And_Restart();
  1625. }
  1626. } else {
  1627. /*
  1628. ** Tell the players we have to quit
  1629. */
  1630. mStartQuitProcessTime = TIMEGETTIME();
  1631. if (cNetwork::I_Am_Server()) {
  1632. WideStringClass widestring(TRANSLATE (IDS_MENU_QUITTING_DUE_TO_CONN_LOSS_MSG), true);
  1633. cScTextObj * message = new cScTextObj;
  1634. message->Init(widestring, TEXT_MESSAGE_PUBLIC, true, HOST_TEXT_SENDER, -1);
  1635. }
  1636. }
  1637. //} else {
  1638. //Quit_And_Restart();
  1639. //}
  1640. }
  1641. }
  1642. }
  1643. }
  1644. /***********************************************************************************************
  1645. * WolGameModeClass::HandleNotification -- Handle server error notifications *
  1646. * *
  1647. * *
  1648. * *
  1649. * INPUT: Server error tyoe *
  1650. * *
  1651. * OUTPUT: Nothing *
  1652. * *
  1653. * WARNINGS: None *
  1654. * *
  1655. * HISTORY: *
  1656. * 11/8/2001 10:21PM ST : Created *
  1657. *=============================================================================================*/
  1658. void WolGameModeClass::HandleNotification(ServerError& server_error)
  1659. {
  1660. /*
  1661. ** This doesn't work because you can't get a server list without also doing a complete reset of wolapi.
  1662. */
  1663. #if (0)
  1664. HRESULT code = server_error.GetErrorCode();
  1665. if (code == CHAT_E_MUSTPATCH) {
  1666. if (mMonitorConnection && mConnected) {
  1667. mPatchAvailable = true;
  1668. /*
  1669. ** If the game has a time limit and players then we will wait until the next map change otherwise we will stop now.
  1670. */
  1671. WWASSERT(PTheGameData != NULL);
  1672. if (!The_Game()->Get_Time_Limit_Minutes() || cPlayerManager::Count() == 0) {
  1673. mStartQuitProcessTime = TIMEGETTIME();
  1674. } else {
  1675. Quit_And_Restart();
  1676. }
  1677. }
  1678. }
  1679. #endif //(0)
  1680. }
  1681. /***********************************************************************************************
  1682. * WolGameModeClass::Quit_And_Restart -- Setup a restart then quit the game *
  1683. * *
  1684. * *
  1685. * *
  1686. * INPUT: Nothing *
  1687. * *
  1688. * OUTPUT: Nothing *
  1689. * *
  1690. * WARNINGS: None *
  1691. * *
  1692. * HISTORY: *
  1693. * 11/8/2001 10:21PM ST : Created *
  1694. *=============================================================================================*/
  1695. void WolGameModeClass::Quit_And_Restart(void)
  1696. {
  1697. static bool reenter_ye_not = false;
  1698. if (!reenter_ye_not) {
  1699. reenter_ye_not = true;
  1700. /*
  1701. ** This will cause the server to leave the channel if needed.
  1702. */
  1703. GameInitMgrClass::End_Game();
  1704. /*
  1705. ** If there is a patch available then download it.
  1706. */
  1707. if (mConnected) {
  1708. WOLLogonMgr::Logoff();
  1709. if (mPatchAvailable) {
  1710. RefPtr<WWOnline::Session> wolSession = WWOnline::Session::GetInstance(false);
  1711. DlgDownload::DoDialog(TRANSLATE(IDS_WOL_DOWNLOAD), wolSession->GetPatchDownloadList(), true);
  1712. }
  1713. } else {
  1714. /*
  1715. ** If we lost connection then drop out of the game and try to re-establish connection.
  1716. */
  1717. AutoRestart.Set_Restart_Flag(true);
  1718. Set_Exit_On_Exception(true);
  1719. cGameData::Set_Manual_Exit(true);
  1720. Stop_Main_Loop(EXIT_SUCCESS);
  1721. }
  1722. reenter_ye_not = false;
  1723. }
  1724. }
  1725. /******************************************************************************
  1726. *
  1727. * NAME
  1728. * WolGameModeClass::HandleNotification(WOLPagedEvent)
  1729. *
  1730. * DESCRIPTION
  1731. * Handle the display of pages and invitations from users outside the game.
  1732. *
  1733. * INPUTS
  1734. *
  1735. * RESULT
  1736. * NONE
  1737. *
  1738. ******************************************************************************/
  1739. void WolGameModeClass::HandleNotification(WOLPagedEvent& event)
  1740. {
  1741. PageMessage* page = event.Subject();
  1742. WWASSERT(page && "NULL page in WOLPagedEvent");
  1743. switch (event.GetAction()) {
  1744. case PAGE_RECEIVED: {
  1745. WideStringClass message(255, true);
  1746. message.Format(L"%s: %s", page->GetPagersName(), page->GetPageMessage());
  1747. CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PAGED_TEXT);
  1748. WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
  1749. break;
  1750. }
  1751. case INVITATION_RECEIVED:
  1752. case INVITATION_DECLINED:
  1753. CombatManager::Get_Message_Window()->Add_Message(page->GetPageMessage(), COLOR_INVITE_TEXT);
  1754. WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
  1755. break;
  1756. case PAGE_ERROR:
  1757. case PAGE_NOT_THERE:
  1758. case PAGE_TURNED_OFF: {
  1759. WideStringClass message(255, true);
  1760. message.Format(L"%s %s", TRANSLATE(IDS_WOL_PAGEUSERERROR), page->GetPageMessage());
  1761. CombatManager::Get_Message_Window()->Add_Message(page->GetPageMessage(), COLOR_CONSOLE_TEXT);
  1762. break;
  1763. }
  1764. }
  1765. }
  1766. void WolGameModeClass::Game_Start_Timeout_Callback(void)
  1767. {
  1768. GameModeClass* game = GameModeManager::Find("WOL");
  1769. if (game && game->Is_Active()) {
  1770. WolGameModeClass* wolgame = reinterpret_cast<WolGameModeClass*>(game);
  1771. wolgame->Game_Start_Timed_Out();
  1772. }
  1773. }
  1774. void WolGameModeClass::Game_Start_Timed_Out(void)
  1775. {
  1776. /*
  1777. ** If we lost connection without getting a report from WW Online then the only clue we have is that we will fail to
  1778. ** get the game ID by timing out. Since this is pretty much fatal anyway, let's quit and restart and see if things fix
  1779. ** themselves up.
  1780. **
  1781. ** ST - 8/21/2002 11:27AM
  1782. */
  1783. if (cNetwork::I_Am_Server()) {
  1784. if (The_Game() && The_Game()->IsDedicated.Is_True() && AutoRestart.Get_Restart_Flag()) {
  1785. mConnected = false;
  1786. if (SlaveMaster.Am_I_Slave()) {
  1787. AutoRestart.Set_Restart_Flag(false);
  1788. Set_Exit_On_Exception(true);
  1789. cGameData::Set_Manual_Exit(true);
  1790. } else {
  1791. Quit_And_Restart();
  1792. }
  1793. }
  1794. }
  1795. }