cnetwork.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667
  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/cnetwork.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 3/29/02 5:02p $*
  29. * *
  30. * $Revision:: 152 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "cnetwork.h"
  36. #include <shellapi.h>
  37. #include <stdio.h>
  38. #include "specialbuilds.h"
  39. #include "langmode.h"
  40. #include "wolgmode.h"
  41. #include "playermanager.h"
  42. #include "textdisplay.h"
  43. #include "gameobjmanager.h"
  44. #include "multihud.h"
  45. #include "WWAudio.H"
  46. #include "useroptions.h"
  47. #include "devoptions.h"
  48. #include "translatedb.h"
  49. #include "string_ids.h"
  50. #include "msgstatlistgroup.h"
  51. #include "wwprofile.h"
  52. #include "gametype.h"
  53. #include "crc.h"
  54. #include "render2d.h"
  55. #include "wwmemlog.h"
  56. #include "svrgoodbyeevent.h"
  57. #include "gameoptionsevent.h"
  58. #include "evictionevent.h"
  59. #include "changeteamevent.h"
  60. #include "clientcontrol.h"
  61. #include "serverfps.h"
  62. #include "sbbomanager.h"
  63. #include "clientgoodbyeevent.h"
  64. //#include "helptext.h"
  65. #include "natter.h"
  66. #include "vistable.h"
  67. #include "gameinitmgr.h"
  68. #include "dlgmessagebox.h"
  69. #include "apppacketstats.h"
  70. #include "clientfps.h"
  71. #include "gamechanlist.h"
  72. #include "packetmgr.h"
  73. #include "clientpingmanager.h"
  74. #include "bandwidthgraph.h"
  75. #include "buildnum.h"
  76. #include "messagewindow.h"
  77. #include "wwmemlog.h"
  78. #include "consolemode.h"
  79. #include "slavemaster.h"
  80. #include "gamedataupdateevent.h"
  81. #include "gamespyadmin.h"
  82. #include "demosupport.h"
  83. #include "serversettings.h"
  84. #include "dlgmpconnectionrefused.h"
  85. #include "Resource.h"
  86. #include <WWUI\DialogMgr.h>
  87. #include "ffactory.h"
  88. #include "realcrc.h"
  89. extern bool g_is_loading;
  90. //
  91. // Networking cNetwork statics
  92. //
  93. char cNetwork::MessageToSend[];
  94. char cNetwork::Command[];
  95. int cNetwork::ExeKey = 0;
  96. int cNetwork::ExeCRC = 0;
  97. int cNetwork::StringsCRC = 0;
  98. char cNetwork::ClientString[];
  99. char cNetwork::ClientEnumerationString[];
  100. CombatNetworkReceiverInstanceClass * cNetwork::NetworkReceiver = NULL;
  101. GameCombatNetworkHandlerClass cNetwork::NetHandler;
  102. int cNetwork::Fps = 0;
  103. int cNetwork::ThinkCount = 0;
  104. cMsgStatList * cNetwork::PClientStatList = NULL;
  105. cMsgStatListGroup * cNetwork::PServerStatListGroup = NULL;
  106. cConnection * cNetwork::PClientConnection = NULL;
  107. cConnection * cNetwork::PServerConnection = NULL;
  108. CombatNetworkReceiver * cNetwork::Receiver = NULL;
  109. float cNetwork::GraphingY;
  110. float cNetwork::BandwidthBarLength = 0;
  111. //int cNetwork::BandwidthScaler = 28800;
  112. int cNetwork::BandwidthScaler = 50000;
  113. bool cNetwork::HaveDoneTeamChangeDialog = false;
  114. bool cNetwork::HaveDoneMotdDialog = false;
  115. VisTableClass * cNetwork::VisTable = NULL;
  116. bool cNetwork::LastServerConnectionStateBad = false;
  117. bool cNetwork::SensibleUpdates = true;
  118. //-----------------------------------------------------------------------------
  119. void cNetwork::Init_Client(unsigned short my_port)
  120. {
  121. WWMEMLOG(MEM_NETWORK);
  122. #ifndef FREEDEDICATEDSERVER
  123. WWDEBUG_SAY(("cNetwork::Init_Client\n"));
  124. if (PClientConnection != NULL) {
  125. Cleanup_Client();
  126. }
  127. PClientStatList = new cMsgStatList;
  128. WWASSERT(PClientStatList != NULL);
  129. //PClientStatList->Init(MESSAGE_COUNT);
  130. PClientStatList->Init(1);
  131. for (int i = 0; i < PClientStatList->Get_Num_Stats(); i++) {
  132. //PClientStatList->Set_Name(i, Message_Type_Translation(i));
  133. /*
  134. char message_trans[200];
  135. strcpy(message_trans, Message_Type_Translation(i));
  136. PClientStatList->Set_Name(i, &message_trans[8]);
  137. */
  138. PClientStatList->Set_Name(i, "message");
  139. }
  140. WWASSERT(PClientConnection == NULL);
  141. PClientConnection = new cConnection;
  142. WWASSERT(PClientConnection != NULL);
  143. CombatManager::Set_I_Am_Client(true);
  144. PClientConnection->Install_Accept_Handler(Accept_Handler);
  145. PClientConnection->Install_Refusal_Handler(Refusal_Handler);
  146. PClientConnection->Install_Client_Broken_Connection_Handler(Client_Broken_Connection_Handler);
  147. PClientConnection->Install_Client_Packet_Handler(Client_Packet_Handler);
  148. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  149. WWASSERT(PTheGameData != NULL);
  150. The_Game()->Set_Password(cGameSpyAdmin::Get_Password_Attempt());
  151. }
  152. ULONG bbo = 0;
  153. //if (IS_SOLOPLAY || GameModeManager::Find("LAN")->Is_Active()) {
  154. if (IS_SOLOPLAY ||
  155. (GameModeManager::Find("LAN")->Is_Active() && !cGameSpyAdmin::Is_Gamespy_Game())) {
  156. bbo = cBandwidth::Get_Bandwidth_Bps_From_Type(BANDWIDTH_LANT1);
  157. WWASSERT(bbo > 0);
  158. cBandwidthGraph::Set_Scale(200000);
  159. HaveDoneTeamChangeDialog = false;
  160. } else {
  161. //WWASSERT(GameModeManager::Find("WOL")->Is_Active());
  162. bbo = cBandwidth::Get_Bandwidth_Bps_From_Type((BANDWIDTH_TYPE_ENUM)cUserOptions::Get_Bandwidth_Type());
  163. //bbo = cUserOptions::BandwidthBps.Get();
  164. WWASSERT(bbo > 0);
  165. int bw_scale = (bbo * 2) / 10;
  166. bw_scale = (bw_scale / 1000) * 1000;
  167. cBandwidthGraph::Set_Scale(bw_scale);
  168. if (GameModeManager::Find("WOL")->Is_Active()) {
  169. HaveDoneTeamChangeDialog = true;
  170. }
  171. }
  172. PClientConnection->Set_Bandwidth_Budget_Out(bbo);
  173. BOOL is_flow_control_enabled = !IS_SOLOPLAY;
  174. PClientConnection->Enable_Flow_Control(is_flow_control_enabled);
  175. WWASSERT(PTheGameData != NULL);
  176. PClientConnection->Init_As_Client(
  177. The_Game()->Get_Ip_Address(), The_Game()->Get_Port(), my_port);
  178. //
  179. // This packet resurfaces on the server in Application_Acceptance_Handler
  180. //
  181. cPacket packet;
  182. packet.Add_Wide_Terminated_String(cNetInterface::Get_Nickname());
  183. packet.Add_Wide_Terminated_String(The_Game()->Get_Password(), true);
  184. packet.Add(ExeKey);
  185. packet.Add(bbo); // note, this field is consumed by wwnet
  186. PClientConnection->Connect_Cs(packet);
  187. packet.Flush();
  188. /*
  189. if (I_Am_Only_Client()) {
  190. ServerFps.Init();
  191. }
  192. */
  193. HaveDoneMotdDialog = false;
  194. if (I_Am_Only_Client())
  195. {
  196. cAppPacketStats::Reset();
  197. }
  198. LastServerConnectionStateBad = false;
  199. cClientPingManager::Init();
  200. #endif // !FREEDEDICATEDSERVER
  201. }
  202. //-----------------------------------------------------------------------------
  203. void cNetwork::Cleanup_Client(void)
  204. {
  205. WWMEMLOG(MEM_NETWORK);
  206. #ifndef FREEDEDICATEDSERVER
  207. WWDEBUG_SAY(("cNetwork::Cleanup_Client\n"));
  208. if (I_Am_Client()) {
  209. if (PClientConnection->Is_Established()) { // i.e we did have a connection
  210. cClientGoodbyeEvent * p_event = new cClientGoodbyeEvent;
  211. p_event->Init();
  212. Flush();
  213. }
  214. delete PClientConnection;
  215. PClientConnection = NULL;
  216. }
  217. CombatManager::Set_I_Am_Client(false);
  218. delete PClientStatList;
  219. PClientStatList = NULL;
  220. delete PClientControl;
  221. PClientControl = NULL;
  222. delete PClientFps;
  223. PClientFps = NULL;
  224. #endif // !FREEDEDICATEDSERVER
  225. }
  226. //-----------------------------------------------------------------------------
  227. void cNetwork::Accept_Handler(void)
  228. {
  229. WWMEMLOG(MEM_NETWORK);
  230. #ifndef FREEDEDICATEDSERVER
  231. WWDEBUG_SAY(("cNetwork::Accept_Handler\n"));
  232. WWASSERT(I_Am_Client());
  233. CombatManager::Set_My_Id(Get_My_Id());
  234. NetworkObjectMgrClass::Init_New_Client_ID(Get_My_Id());
  235. if (I_Am_Only_Client()) {
  236. //
  237. // Create C->S mirrored client control object
  238. //
  239. WWASSERT(PClientControl == NULL);
  240. PClientControl = new CClientControl;
  241. PClientControl->Init();
  242. //
  243. // Create C->S mirrored client fps object
  244. //
  245. WWASSERT(PClientFps == NULL);
  246. PClientFps = new CClientFps;
  247. PClientFps->Init();
  248. }
  249. if (!I_Am_Server()) {
  250. if (GameModeManager::Find("LAN")->Is_Active()) {
  251. PLC->Accept_Actions();
  252. } else {
  253. GameModeClass* gameMode = GameModeManager::Find("WOL");
  254. if (gameMode && gameMode->Is_Active()) {
  255. WolGameModeClass* wolGame = static_cast<WolGameModeClass*>(gameMode);
  256. WWASSERT(wolGame);
  257. wolGame->Accept_Actions();
  258. }
  259. }
  260. }
  261. #endif // !FREEDEDICATEDSERVER
  262. }
  263. //-----------------------------------------------------------------------------
  264. void cNetwork::Refusal_Handler(REFUSAL_CODE refusal_code)
  265. {
  266. #ifndef FREEDEDICATEDSERVER
  267. WWDEBUG_SAY(("cNetwork::Refusal_Handler\n"));
  268. // Close connecting dialog as neccessary.
  269. DialogBaseClass* dialog = DialogMgrClass::Find_Dialog(IDD_MULTIPLAY_CONNECTING);
  270. if (dialog != NULL) {
  271. // Sending 1 as the parameter tells the dialog that it is being closed
  272. // as a result of a refusal from the server.
  273. dialog->On_Command(IDCANCEL, 0, 1);
  274. }
  275. // Verify refusal code is within valid range
  276. WWASSERT(REFUSAL_CLIENT_ACCEPTED <= refusal_code && REFUSAL_BY_APPLICATION >= refusal_code);
  277. WWASSERT(I_Am_Client());
  278. if (GameModeManager::Find("LAN")->Is_Active()) {
  279. PLC->Refusal_Actions();
  280. } else {
  281. GameModeClass* gameMode = GameModeManager::Find("WOL");
  282. if (gameMode && gameMode->Is_Active()) {
  283. WolGameModeClass* wolGame = static_cast<WolGameModeClass*>(gameMode);
  284. WWASSERT(wolGame);
  285. wolGame->Refusal_Actions();
  286. }
  287. }
  288. //
  289. // The server refused our connection request! At this stage this
  290. // is fatal. Later on we would have to re-init the connection etc.
  291. //
  292. static const unsigned long _refusalStrings[] = {
  293. IDS_MP_CONNECTION_REFUSED_GAME_FULL, // REFUSAL_GAME_FULL
  294. IDS_MP_PASSWORD_WRONG, // REFUSAL_BAD_PASSWORD
  295. IDS_MENU_VERSION_MISMATCH, // REFUSAL_VERSION_MISMATCH
  296. IDS_MP_CONNECTION_REFUSED_BY_APPLICATION, // REFUSAL_PLAYER_EXISTS
  297. IDS_MP_CONNECTION_REFUSED_BY_APPLICATION // REFUSAL_BY_APPLICATION
  298. };
  299. const unsigned long refusalMsg = _refusalStrings[refusal_code - 1];
  300. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  301. if (refusal_code == REFUSAL_VERSION_MISMATCH) {
  302. WideStringClass tval;
  303. tval.Format(L"%s...%s", TRANSLATE(IDS_MP_CONNECTION_REFUSED_BY_APPLICATION),
  304. TRANSLATE(IDS_MENU_VERSION_MISMATCH));
  305. DlgMPConnectionRefused::DoDialog(tval, false);
  306. } else {
  307. DlgMPConnectionRefused::DoDialog(TRANSLATE(refusalMsg), false);
  308. }
  309. } else {
  310. DlgMsgBox::DoDialog(TRANSLATE (IDS_MENU_SERVER_MESSAGE_TITLE), TRANSLATE(refusalMsg));
  311. }
  312. //
  313. // N.B. We cannot destroy the connection from inside this callback.
  314. //
  315. #endif // !FREEDEDICATEDSERVER
  316. }
  317. //-----------------------------------------------------------------------------
  318. int cNetwork::Get_Data_Files_CRC(void)
  319. {
  320. #define UNINITIALLIZED_CRC 0x4592abf1
  321. static int crc = UNINITIALLIZED_CRC;
  322. if ( crc == UNINITIALLIZED_CRC ) {
  323. char * filelist[] = {
  324. "jgo`fqv+aag", //"objects.ddb",
  325. "dwhjw+lkl", //"armor.ini",
  326. "gjk`v+lkl", //"bones.ini",
  327. "vpwcdf``cc`fqv+lkl", //"surfaceeffects.ini",
  328. "fdh`wdv+lkl", //"cameras.ini",
  329. "fZkjaZhbZi5+r6a", //"c_nod_mg_l0.w3d",
  330. "fZkjaZwnZi5+r6a", //"c_nod_rk_l0.w3d",
  331. "fZkjaZciZi5+r6a", //"c_nod_fl_l0.w3d",
  332. "fZkjaZ`kZi5+r6a", //"c_nod_en_l0.w3d",
  333. "fZkjaZhbjZi5+r6a", //"c_nod_mgo_l0.w3d",
  334. "fZkjaZwnjZi5+r6a", //"c_nod_rko_l0.w3d",
  335. "fZkjaZfm`hqZi5+r6a", //"c_nod_chemt_l0.w3d",
  336. "fZkjaZvklu`wZi5+r6a", //"c_nod_sniper_l0.w3d",
  337. "fZkjaZwvjiaZi5+r6a", //"c_nod_rsold_l0.w3d",
  338. "fZkjaZvqiqmZi5+r6a", //"c_nod_stlth_l0.w3d",
  339. "fZkjaZvdnpZi5+r6a", //"c_nod_saku_l0.w3d",
  340. "fZkjaZvdnp7Zi5+r6a", //"c_nod_saku2_l0.w3d",
  341. "fZkjaZwdsZi5+r6a", //"c_nod_rav_l0.w3d",
  342. "fZkjaZhwdsZi5+r6a", //"c_nod_mrav_l0.w3d",
  343. "fZkjaZhaZi5+r6a", //"c_nod_mdz_l0.w3d",
  344. "fZkjaZha7Zi5+r6a", //"c_nod_mdz2_l0.w3d",
  345. "fZkjaZqfZi5+r6a", //"c_nod_tc_l0.w3d",
  346. "fZkjaZhpqdkqZi5+r6a", //"c_nod_mutant_l0.w3d",
  347. "fZkjaZhviaZi5+r6a", //"c_nod_msld_l0.w3d",
  348. "fZkjaZvvjiaZi5+r6a", //"c_nod_ssold_l0.w3d",
  349. "fZkjaZu`qhZi5+r6a", //"c_nod_petm_l0.w3d",
  350. "fZkjaZndk`Zi5+r6a", //"c_nod_kane_l0.w3d",
  351. "fZbalZhbZi5+r6a", //"c_gdi_mg_l0.w3d",
  352. "fZbalZwnZi5+r6a", //"c_gdi_rk_l0.w3d",
  353. "fZbalZbwZi5+r6a", //"c_gdi_gr_l0.w3d",
  354. "fZbalZ`kZi5+r6a", //"c_gdi_en_l0.w3d",
  355. "fZbalZhbjZi5+r6a", //"c_gdi_mgo_l0.w3d",
  356. "fZbalZwnjZi5+r6a", //"c_gdi_rko_l0.w3d",
  357. "fZbalZv|aZi5+r6a", //"c_gdi_syd_l0.w3d",
  358. "fZbalZa`daZi5+r6a", //"c_gdi_dead_l0.w3d",
  359. "fZbalZbpkZi5+r6a", //"c_gdi_gun_l0.w3d",
  360. "fZbalZuqfmZi5+r6a", //"c_gdi_ptch_l0.w3d",
  361. "fZmdsjfZi5+r6a", //"c_havoc_l0.w3d",
  362. "fZmdsjfkZi5+r6a", //"c_havocn_l0.w3d",
  363. "fZmdsjfrZi5+r6a", //"c_havocw_l0.w3d",
  364. "fZmdsjfaZi5+r6a", //"c_havocd_l0.w3d",
  365. "fZbalZv|aZi5+r6a", //"c_gdi_syd_l0.w3d",
  366. "fZbalZv|a7Zi5+r6a", //"c_gdi_syd2_l0.w3d",
  367. "fZbalZhjglZi5+r6a", //"c_gdi_mobi_l0.w3d",
  368. "fZbalZmjqrZi5+r6a", //"c_gdi_hotw_l0.w3d",
  369. "fZbalZiqZi5+r6a", //"c_gdi_lt_l0.w3d",
  370. "fZkjaZu`qwZi5+r6a", //"c_nod_petr_l0.w3d",
  371. "fZijbdkZi5+r6a", //"c_logan_l0.w3d",
  372. "fZbalZijfn`Zi5+r6a", //"c_gdi_locke_l0.w3d",
  373. "sZkjaZgpbb|+r6a", //"v_nod_buggy.w3d",
  374. "sZkjaZdufZh+r6a", //"v_nod_apc_m.w3d",
  375. "sZkjaZdwqiw|+r6a", //"v_nod_artlry.w3d",
  376. "sZkjaZcidh`+r6a", //"v_nod_flame.w3d",
  377. "sZkjaZiqdkn+r6a", //"v_nod_ltank.w3d",
  378. "sZkjaZvqiqm+r6a", //"v_nod_stlth.w3d",
  379. "sZkjaZqwkvuqZh+r6a", //"v_nod_trnspt_m.w3d",
  380. "sZkjaZdudfm`Zh+r6a", //"v_nod_apache_m.w3d",
  381. "sZfmdh`i`jk+r6a", //"v_chameleon.w3d",
  382. "sZbalZmphs``+r6a", //"v_gdi_humvee.w3d",
  383. "sZbalZdufZh+r6a", //"v_gdi_apc_m.w3d",
  384. "sZbalZhwiv+r6a", //"v_gdi_mrls.w3d",
  385. "sZbalZh`aqkn+r6a", //"v_gdi_medtnk.w3d",
  386. "sZbalZhdhhqm+r6a", //"v_gdi_mammth.w3d",
  387. "sZulfnpu54+r6a", //"v_pickup01.w3d",
  388. "sZv`adk54+r6a", //"v_sedan01.w3d",
  389. "sZbalZjwfdZh+r6a", //"v_gdi_orca_m.w3d",
  390. "sZbalZqwkvuqZh+r6a", //"v_gdi_trnspt_m.w3d",
  391. };
  392. #define NUM_CRC_FILES (sizeof( filelist ) / sizeof( filelist[0] ) )
  393. crc = 0;
  394. for ( int i = 0; i < NUM_CRC_FILES; i++ ) {
  395. StringClass name = filelist[i];
  396. // Obfuscate name
  397. char * n = &name[0];
  398. while ( *n ) *n++ ^= 0x5;
  399. // Debug_Say(( " \"%s\",\n", name ));
  400. FileClass * file = _TheFileFactory->Get_File( name );
  401. if ( file && file->Is_Available() ) {
  402. int size = file->Size();
  403. file->Open();
  404. while ( size > 0 ) {
  405. unsigned char buffer[ 4096 ];
  406. int amount = min( (int)size, (int)sizeof(buffer) );
  407. amount = file->Read( buffer, amount );
  408. crc = CRC_Memory( buffer, amount, crc );
  409. size -= amount;
  410. }
  411. file->Close();
  412. } else {
  413. // Debug_Say(( "******%s not found\n", name ));
  414. }
  415. }
  416. }
  417. return crc;
  418. }
  419. //-----------------------------------------------------------------------------
  420. void cNetwork::Compute_Exe_Key(void)
  421. {
  422. WWDEBUG_SAY(("cNetwork::Compute_Exe_Key\n"));
  423. char exe_filename[500];
  424. int succeeded = 0;
  425. succeeded = ::GetModuleFileName(NULL, exe_filename, sizeof(exe_filename));
  426. WWASSERT(succeeded);
  427. StringClass key_string;
  428. StringClass string;
  429. StringClass build_string;
  430. //
  431. // 11/07/01
  432. // We now match only on build number.
  433. //
  434. string.Format("RENEGADE %u", BuildInfoClass::Get_Build_Number());
  435. WWDEBUG_SAY(("File id string: %s\n", string));
  436. key_string += string;
  437. key_string += " ";
  438. ExeCRC = CRCEngine()(string, strlen(string));
  439. //
  440. // TSS 09/07/01
  441. // N.B. Do not require scripts to be in sync any more, since they do not run on the client.
  442. // Furthermore we would have to match the correct scripts target (d/p/r) and
  443. // also handle the registry flag that forces scriptsd.dll.
  444. //
  445. //
  446. // TSS102401
  447. // We cannot match on exact strings.tdb because foreign language versions
  448. // are different files. Instead, match on filename and internal version number.
  449. //
  450. //cMiscUtil::Get_File_Id_String("Data\\strings.tdb", string);
  451. string.Format("strings.tdb %u", TranslateDBClass::Get_Version_Number());
  452. WWDEBUG_SAY(("File id string: %s\n", string));
  453. key_string += string;
  454. key_string += " ";
  455. StringsCRC = CRCEngine()(string, strlen(string));
  456. //
  457. // TSS102401 - we can't match always.dbs either.
  458. // always.dbs will not match among foreign language version for numerous reasons.
  459. //
  460. //
  461. // Use the crc of the keystring as the key
  462. //
  463. ExeKey = CRCEngine()(key_string, strlen(key_string));
  464. //
  465. // Include data file crc
  466. //
  467. int data_file_crc = Get_Data_Files_CRC();
  468. ExeKey ^= data_file_crc;
  469. }
  470. //-----------------------------------------------------------------------------
  471. void cNetwork::Onetime_Init(void)
  472. {
  473. WWMEMLOG(MEM_NETWORK);
  474. WWDEBUG_SAY(("cNetwork::Onetime_Init\n"));
  475. Compute_Exe_Key();
  476. NetworkReceiver = new CombatNetworkReceiverInstanceClass;
  477. Set_Receiver(NetworkReceiver);
  478. CombatManager::Set_Combat_Network_Handler(&NetHandler);
  479. //Clear_Help_Text();
  480. }
  481. //-----------------------------------------------------------------------------
  482. void cNetwork::Onetime_Shutdown(void)
  483. {
  484. WWDEBUG_SAY(("cNetwork::Onetime_Shutdown\n"));
  485. Set_Receiver(NULL);
  486. delete NetworkReceiver;
  487. #if 0
  488. UINT comp_bytes = cConnection::Get_Total_Compressed_Bytes_Sent();
  489. UINT uncomp_bytes = cConnection::Get_Total_Uncompressed_Bytes_Sent();
  490. Debug_Say(("\n"));
  491. Debug_Say(("TotalCompressedBytesSent = %d\n", comp_bytes));
  492. Debug_Say(("Without compression = %d\n", uncomp_bytes));
  493. if (uncomp_bytes > 0) {
  494. Debug_Say(("Compressed/Uncompressed = %-5.2f\n\n",
  495. comp_bytes / (float) uncomp_bytes));
  496. }
  497. #endif // 0
  498. #pragma message("(TSS) This packet ref count assert very occasionally fails.")
  499. //WWASSERT(cPacket::Get_Ref_Count() == 0);
  500. REF_PTR_RELEASE(VisTable);
  501. cGameChannelList::Remove_All();//TSS092201 added
  502. //
  503. // These are only printed once. So only run one game on a test run.
  504. //
  505. cAppPacketStats::Dump_Diagnostics();
  506. }
  507. //-----------------------------------------------------------------------------
  508. void cNetwork::Init_Server(void)
  509. {
  510. WWMEMLOG(MEM_NETWORK);
  511. WWDEBUG_SAY(("cNetwork::Init_Server\n"));
  512. #ifndef BETACLIENT
  513. NetworkObjectClass::Set_Is_Server(true);
  514. PServerStatListGroup = new cMsgStatListGroup;
  515. WWASSERT(PServerStatListGroup != NULL);
  516. //PServerStatListGroup->Init(The_Game()->Get_Max_Players(), MESSAGE_COUNT);
  517. WWASSERT(PTheGameData != NULL);
  518. PServerStatListGroup->Init(The_Game()->Get_Max_Players(), 1);
  519. /*
  520. for (int message_type = 0; message_type < MESSAGE_COUNT; message_type++) {
  521. char message_trans[200];
  522. strcpy(message_trans, Message_Type_Translation(message_type));
  523. PServerStatListGroup->Set_Name(message_type, &message_trans[8]);
  524. }
  525. */
  526. WWASSERT(PServerConnection == NULL);
  527. PServerConnection = new cConnection;
  528. WWASSERT(PServerConnection != NULL);
  529. CombatManager::Set_I_Am_Server(true);
  530. PServerConnection->Install_Server_Broken_Connection_Handler(Server_Broken_Connection_Handler);
  531. PServerConnection->Install_Eviction_Handler(Eviction_Handler);
  532. PServerConnection->Install_Conn_Handler(Connection_Handler);
  533. PServerConnection->Install_Application_Acceptance_Handler(Application_Acceptance_Handler);
  534. PServerConnection->Install_Server_Packet_Handler(Server_Packet_Handler);
  535. //if (IS_SOLOPLAY || GameModeManager::Find("LAN")->Is_Active()) {
  536. if (IS_SOLOPLAY ||
  537. (GameModeManager::Find("LAN")->Is_Active() && !cGameSpyAdmin::Is_Gamespy_Game())) {
  538. ULONG bbo = cBandwidth::Get_Bandwidth_Bps_From_Type(BANDWIDTH_LANT1);
  539. WWASSERT(bbo > 0);
  540. PServerConnection->Set_Bandwidth_Budget_Out(bbo);
  541. cBandwidthGraph::Set_Scale(200000);
  542. } else {
  543. //WWASSERT(GameModeManager::Find("WOL")->Is_Active());
  544. WWASSERT(cUserOptions::BandwidthBps.Get() > 0);
  545. unsigned long bw = cBandwidth::Get_Bandwidth_Bps_From_Type((BANDWIDTH_TYPE_ENUM)cUserOptions::Get_Bandwidth_Type());
  546. /*
  547. ** Only use a portion of the bandwidth based on how many slave servers there are.
  548. */
  549. if (The_Game()->IsDedicated.Get() && !SlaveMaster.Am_I_Slave()) {
  550. if (cUserOptions::Get_Bandwidth_Type() == BANDWIDTH_AUTO) {
  551. if (ServerSettingsClass::Get_Master_Bandwidth() == 0 || ServerSettingsClass::Get_Master_Bandwidth() == 0xffffffff) {
  552. int num_slaves = SlaveMaster.Get_Num_Enabled_Slaves();
  553. if (num_slaves) {
  554. bw = bw / (num_slaves+1);
  555. }
  556. }
  557. }
  558. }
  559. PServerConnection->Set_Bandwidth_Budget_Out(bw);
  560. //PServerConnection->Set_Bandwidth_Budget_Out(cUserOptions::BandwidthBps.Get());
  561. int bw_scale = (cUserOptions::BandwidthBps.Get() * 2) / 10;
  562. bw_scale = (bw_scale / 1000) * 1000;
  563. cBandwidthGraph::Set_Scale(bw_scale);
  564. }
  565. double max_acceptable_packetloss_pc = 10;
  566. PServerConnection->Set_Max_Acceptable_Packetloss_Pc(max_acceptable_packetloss_pc);
  567. BOOL is_flow_control_enabled = !IS_SOLOPLAY;
  568. PServerConnection->Enable_Flow_Control(is_flow_control_enabled);
  569. WWASSERT(PTheGameData != NULL);
  570. PServerConnection->Init_As_Server(
  571. The_Game()->Get_Port(),
  572. The_Game()->Get_Max_Players(),
  573. The_Game()->IsDedicated.Get(),
  574. ntohl(The_Game()->Get_Ip_Address()));
  575. //
  576. // Create teams
  577. //
  578. //if (The_Game()->Is_Team_Game()) {
  579. for (int team_num = 0; team_num < MAX_TEAMS; team_num++) {
  580. cTeam * p_team = new cTeam;
  581. p_team->Init(team_num);
  582. }
  583. //}
  584. cSbboManager::Reset();
  585. cAppPacketStats::Reset();
  586. #endif // not BETACLIENT
  587. }
  588. //-----------------------------------------------------------------------------
  589. void cNetwork::Cleanup_Server(void)
  590. {
  591. WWDEBUG_SAY(("cNetwork::Cleanup_Server\n"));
  592. if (I_Am_Server()) {
  593. delete PServerConnection;
  594. PServerConnection = NULL;
  595. }
  596. CombatManager::Set_I_Am_Server(false);
  597. delete PServerStatListGroup;
  598. PServerStatListGroup = NULL;
  599. NetworkObjectClass::Set_Is_Server(false);
  600. }
  601. //-----------------------------------------------------------------------------
  602. enum {
  603. CHUNKID_PLAYERMANAGER = 9876543,
  604. };
  605. //-----------------------------------------------------------------------------
  606. bool cNetwork::Save(ChunkSaveClass & csave)
  607. {
  608. csave.Begin_Chunk(CHUNKID_PLAYERMANAGER);
  609. cPlayerManager::Save(csave);
  610. csave.End_Chunk();
  611. return true;
  612. }
  613. //-----------------------------------------------------------------------------
  614. bool cNetwork::Load(ChunkLoadClass &cload)
  615. {
  616. while (cload.Open_Chunk()) {
  617. switch(cload.Cur_Chunk_ID()) {
  618. case CHUNKID_PLAYERMANAGER:
  619. //cPlayerManager::Remove_All();
  620. cPlayerManager::Load(cload);
  621. break;
  622. default:
  623. Debug_Say(( "Unrecognized cNetwork chunkID\n" ));
  624. break;
  625. }
  626. cload.Close_Chunk();
  627. }
  628. return true;
  629. }
  630. //-----------------------------------------------------------------------------
  631. void cNetwork::Update_Fps(void)
  632. {
  633. static DWORD last_time_ms = 0;
  634. static int frame_count = 0;
  635. DWORD time_now_ms = TIMEGETTIME();
  636. // Handle timer resetting.
  637. if (time_now_ms < last_time_ms) {
  638. last_time_ms = time_now_ms;
  639. }
  640. frame_count++;
  641. DWORD time_interval = time_now_ms - last_time_ms;
  642. if (time_interval > 1000) {
  643. Fps = (int) (frame_count * 1000 / (float) time_interval + 0.5f);
  644. last_time_ms = time_now_ms;
  645. frame_count = 0;
  646. // Needed for release mode too. ST - 1/23/2002 11:02PM
  647. //#ifdef WWDEBUG
  648. if (I_Am_Server()) {
  649. WWASSERT(cServerFps::Get_Instance() != NULL);
  650. cServerFps::Get_Instance()->Set_Fps(Fps);
  651. }
  652. //#endif // WWDEBUG
  653. if (I_Am_Client() && PClientFps != NULL) {
  654. PClientFps->Set_Fps(Fps);
  655. }
  656. }
  657. }
  658. void cNetwork::Connection_Status_Change_Feedback(void)
  659. {
  660. static unsigned long _last_print = TIMEGETTIME();
  661. static bool _last_print_bad = false;
  662. static unsigned long _print_good_soon = 0;
  663. unsigned long time = TIMEGETTIME();
  664. const WCHAR *string = NULL;
  665. if (LastServerConnectionStateBad) {
  666. if (_last_print_bad && time - _last_print < 4000) {
  667. return;
  668. }
  669. string = TRANSLATE (IDS_MENU_CONNECTION_INTERRUPTED);
  670. _last_print_bad = true;
  671. } else {
  672. /*
  673. ** Wait 2 secs after connection restore before printing message.
  674. */
  675. if (_last_print_bad && _print_good_soon == 0) {
  676. _print_good_soon = time;
  677. return;
  678. }
  679. if (!_last_print_bad) {
  680. return;
  681. }
  682. if (time - _print_good_soon < 2000) {
  683. return;
  684. }
  685. string = TRANSLATE (IDS_MENU_CONNECTION_RESTORED);
  686. _last_print_bad = false;
  687. }
  688. _last_print = time;
  689. WideStringClass widestring(string, true);
  690. if (CombatManager::Get_Message_Window() != NULL) {
  691. //
  692. // Display the message...
  693. //
  694. CombatManager::Get_Message_Window ()->Add_Message (widestring);
  695. }
  696. //
  697. // Write it to the logfile
  698. //
  699. StringClass temp_string;
  700. widestring.Convert_To(temp_string);
  701. WWDEBUG_SAY(("\n***%s\n", temp_string.Peek_Buffer()));
  702. }
  703. //-----------------------------------------------------------------------------
  704. void cNetwork::Update(void)
  705. {
  706. WWPROFILE( "cNetwork::Update" );
  707. WWMEMLOG(MEM_GAMEDATA);
  708. bool flush_packets = false;
  709. ThinkCount++;
  710. //
  711. // Coding bugs may result in this function being called recursively.
  712. // Detect and assert!
  713. //
  714. static int recursion_level = 0;
  715. recursion_level++;
  716. WWASSERT(recursion_level == 1);
  717. Update_Fps();
  718. #ifdef WWDEBUG
  719. //
  720. // Watch out for unexpected slow frames. They may interrupt networking.
  721. //
  722. static DWORD last_time_ms = TIMEGETTIME();
  723. DWORD time_now_ms = TIMEGETTIME();
  724. if (time_now_ms - last_time_ms > 2000) {
  725. Debug_Say(("\n***cNetwork::Update: warning, think # %d was slow (%u ms)\n\n",
  726. ThinkCount,
  727. time_now_ms - last_time_ms));
  728. }
  729. last_time_ms = time_now_ms;
  730. #endif // WWDEBUG
  731. if (I_Am_Server()) {
  732. if (I_Am_Client()) {
  733. WWPROFILE( "Client Send" );
  734. PClientConnection->Service_Send();
  735. if (PClientConnection->Is_Bad_Connection() != LastServerConnectionStateBad) {
  736. LastServerConnectionStateBad = PClientConnection->Is_Bad_Connection();
  737. //Connection_Status_Change_Feedback();
  738. }
  739. Connection_Status_Change_Feedback();
  740. }
  741. // { WWPROFILE("GameSpy_QnR");
  742. // GameSpyQnR.Think();
  743. // }
  744. WWPROFILE( "Server Read" );
  745. PServerConnection->Service_Read();
  746. if (!g_is_loading) {
  747. WWPROFILE( "Shared CS Think" );
  748. Shared_Client_And_Server_Think();
  749. }
  750. if (I_Am_Client() && !g_is_loading) {
  751. WWPROFILE( "Client_Think" );
  752. if (Client_Think()) {
  753. flush_packets = true;
  754. }
  755. }
  756. if (!g_is_loading) {
  757. WWPROFILE( "Server_Think" );
  758. if (Server_Think()) {
  759. flush_packets = true;
  760. } else {
  761. // Server only sends packets in response to server think, not client think.
  762. flush_packets = false;
  763. }
  764. }
  765. {
  766. WWPROFILE( "Server Send" );
  767. PServerConnection->Service_Send();
  768. }
  769. if (I_Am_Client()) {
  770. WWPROFILE( "Client Read" );
  771. PClientConnection->Service_Read();
  772. }
  773. } else if (I_Am_Client()) {
  774. {
  775. WWPROFILE( "Client Read" );
  776. PClientConnection->Service_Read();
  777. }
  778. if (PClientConnection->Is_Bad_Connection() != LastServerConnectionStateBad) {
  779. LastServerConnectionStateBad = PClientConnection->Is_Bad_Connection();
  780. Connection_Status_Change_Feedback();
  781. }
  782. if (!g_is_loading) {
  783. WWPROFILE( "Shared CS Think" );
  784. Shared_Client_And_Server_Think();
  785. }
  786. if (!g_is_loading) {
  787. WWPROFILE( "Client_Think" );
  788. if (Client_Think()) {
  789. flush_packets = true;
  790. }
  791. }
  792. {
  793. WWPROFILE( "Client Send" );
  794. if (PClientConnection != NULL) {
  795. PClientConnection->Service_Send();
  796. }
  797. }
  798. }
  799. DEMO_SECURITY_CHECK;
  800. NetworkObjectMgrClass::Delete_Pending();
  801. if (flush_packets) {
  802. PacketManager.Flush(true);
  803. }
  804. recursion_level--;
  805. WWASSERT(recursion_level == 0);
  806. }
  807. //-----------------------------------------------------------------------------
  808. void cNetwork::Client_Send_Packet(cPacket & packet, int mode)
  809. {
  810. #ifndef FREEDEDICATEDSERVER
  811. WWASSERT(I_Am_Client());
  812. if (cNetwork::PClientConnection->Is_Established()) {
  813. PClientConnection->Send_Packet_To_Individual(packet, 0, mode);
  814. /*
  815. BYTE message_type = packet.Peek_Message_Type();
  816. PClientStatList->Increment_Num_Msg_Sent(message_type);
  817. PClientStatList->Increment_Num_Byte_Sent(message_type, packet.Get_Compressed_Size_Bytes());
  818. */
  819. } else {
  820. WWDEBUG_SAY(("cNetwork::Client_Send_Packet: warning: Connection not yet established.\n"));
  821. //TSS2001 XXX DIE;
  822. }
  823. #endif // !FREEDEDICATEDSERVER
  824. }
  825. //-----------------------------------------------------------------------------
  826. void cNetwork::Server_Send_Packet(cPacket & packet, int mode, int recipient)
  827. {
  828. #ifndef BETACLIENT
  829. WWASSERT(I_Am_Server());
  830. WWASSERT(PServerConnection->Is_Established());
  831. if (recipient == ALL) {
  832. //
  833. // We cannot just send to all rhosts because that includes anyone
  834. // browsing the server settings, whereas here we wish to send to the
  835. // ingame players.
  836. //
  837. //PServerConnection->Send_Packet_To_All(*p_packet, mode);
  838. SLNode<cPlayer> * objnode;
  839. for (objnode = cPlayerManager::Get_Player_Object_List()->Head();
  840. objnode; objnode = objnode->Next()) {
  841. cPlayer * p_player = objnode->Data();
  842. WWASSERT(p_player != NULL);
  843. //if (p_player->Is_Human()) {
  844. if (p_player->Get_Is_Active().Is_True() &&
  845. p_player->Is_Human() &&
  846. p_player->Get_Is_In_Game().Is_True()) {
  847. int client_id = p_player->Get_Id();
  848. PServerConnection->Send_Packet_To_Individual(
  849. packet, client_id, mode);
  850. /*
  851. BYTE message_type = packet.Peek_Message_Type();
  852. PServerStatListGroup->Increment_Num_Msg_Sent(client_id - 1, message_type);
  853. PServerStatListGroup->Increment_Num_Byte_Sent(client_id - 1, message_type, packet.Get_Compressed_Size_Bytes());
  854. */
  855. }
  856. }
  857. } else {
  858. PServerConnection->Send_Packet_To_Individual(packet, recipient, mode);
  859. /*
  860. BYTE message_type = packet.Peek_Message_Type();
  861. PServerStatListGroup->Increment_Num_Msg_Sent(recipient - 1, message_type);
  862. PServerStatListGroup->Increment_Num_Byte_Sent(recipient - 1, message_type, packet.Get_Compressed_Size_Bytes());
  863. */
  864. }
  865. #endif // not BETACLIENT
  866. }
  867. //-----------------------------------------------------------------------------
  868. void cNetwork::Server_Send_Packet_To_All_Connected(cPacket & packet, int mode)
  869. {
  870. #ifndef BETACLIENT
  871. //
  872. // Traverse the rhost list here in the application level, so that
  873. // we can record message stats.
  874. //
  875. WWASSERT(I_Am_Server());
  876. WWASSERT(PServerConnection->Is_Established());
  877. //BYTE message_type = packet.Peek_Message_Type();
  878. for (int rhost_id = PServerConnection->Get_Min_RHost(); rhost_id <= PServerConnection->Get_Max_RHost(); rhost_id++) {
  879. if (Get_Server_Rhost(rhost_id) != NULL) {
  880. PServerConnection->Send_Packet_To_Individual(packet, rhost_id, mode);
  881. /*
  882. PServerStatListGroup->Increment_Num_Msg_Sent(rhost_id - 1, message_type);
  883. PServerStatListGroup->Increment_Num_Byte_Sent(rhost_id - 1, message_type, packet.Get_Compressed_Size_Bytes());
  884. */
  885. }
  886. }
  887. #endif // not BETACLIENT
  888. }
  889. //-----------------------------------------------------------------------------
  890. LPCSTR cNetwork::Get_Client_Enumeration_String(void)
  891. {
  892. WWASSERT(I_Am_Server());
  893. WWASSERT(PServerConnection->Is_Established());
  894. char temp_str[10];
  895. strcpy(ClientEnumerationString, "");
  896. for (int rhost_id = PServerConnection->Get_Min_RHost(); rhost_id <= PServerConnection->Get_Max_RHost(); rhost_id++) {
  897. if (Get_Server_Rhost(rhost_id) != NULL) {
  898. strcat(ClientEnumerationString, itoa(rhost_id, temp_str, 10));
  899. strcat(ClientEnumerationString, " ");
  900. }
  901. if (strlen(ClientEnumerationString) > 20) {
  902. strcpy(ClientEnumerationString, "many");
  903. break;
  904. }
  905. }
  906. return ClientEnumerationString;
  907. }
  908. //-----------------------------------------------------------------------------
  909. cRemoteHost * cNetwork::Get_Server_Rhost(int client_id)
  910. {
  911. WWASSERT(I_Am_Server());
  912. return PServerConnection->Get_Remote_Host(client_id);
  913. }
  914. //-----------------------------------------------------------------------------
  915. cRemoteHost * cNetwork::Get_Client_Rhost(void)
  916. {
  917. WWASSERT(I_Am_Client());
  918. return PClientConnection->Get_Remote_Host(SERVER_RHOST_ID);
  919. }
  920. //-----------------------------------------------------------------------------
  921. float cNetwork::Get_Server_Rhost_Threshold_Priority(int client_id)
  922. {
  923. WWASSERT(I_Am_Server());
  924. WWASSERT(Get_Server_Rhost(client_id) != NULL);
  925. return Get_Server_Rhost(client_id)->Get_Threshold_Priority();
  926. }
  927. //-----------------------------------------------------------------------------
  928. float cNetwork::Get_Client_Rhost_Threshold_Priority(void)
  929. {
  930. WWASSERT(I_Am_Client());
  931. WWASSERT(Get_Client_Rhost() != NULL);
  932. return Get_Client_Rhost()->Get_Threshold_Priority();
  933. }
  934. //-----------------------------------------------------------------------------
  935. int cNetwork::Get_My_Id(void)
  936. {
  937. WWASSERT(I_Am_Client());
  938. return PClientConnection->Get_Local_Id();
  939. }
  940. //-----------------------------------------------------------------------------
  941. LPCSTR cNetwork::Get_Client_String(int recipient)
  942. {
  943. //WWASSERT(I_Am_Server());
  944. if (recipient > 0) {
  945. WWASSERT(PServerConnection->Is_Established());
  946. if (recipient == ALL) {
  947. sprintf(ClientString, "all %d clients (%s)",
  948. PServerConnection->Get_Num_RHosts(),
  949. Get_Client_Enumeration_String());
  950. } else {
  951. sprintf(ClientString, "client %d", recipient);
  952. }
  953. } else {
  954. sprintf(ClientString, "server");
  955. }
  956. //
  957. // Note: This WWASSERT would catch the overwrite AFTER it has happened...
  958. //
  959. WWASSERT(strlen(ClientString) < sizeof(ClientString));
  960. return(ClientString);
  961. }
  962. //-----------------------------------------------------------------------------
  963. void cNetwork::Server_Broken_Connection_Handler(int broken_rhost_id)
  964. {
  965. WWASSERT(broken_rhost_id >= 0);
  966. //
  967. // The net lib calls this when a reliable packet fails after
  968. // many attempts. The connection data has already been destroyed.
  969. //
  970. WWDEBUG_SAY(("\n***Connection to client %d broken \n\n", broken_rhost_id));
  971. WideStringClass widestring;
  972. widestring.Format(
  973. L"%s %d\n",
  974. TRANSLATION(IDS_MP_CONNECTION_TO_CLIENT_BROKEN),
  975. broken_rhost_id);
  976. WWASSERT(CombatManager::Get_Message_Window () != NULL);
  977. //Get_Text_Display()->Print_System(widestring);
  978. //
  979. // Display the message...
  980. //
  981. CombatManager::Get_Message_Window ()->Add_Message (widestring);
  982. Vector3 color(1.0f, 1.0f, 0.0f);
  983. ConsoleBox.Add_Message(&widestring, &color);
  984. WWAudioClass::Get_Instance()->Create_Instant_Sound("Broken_Connection", Matrix3D(1));
  985. cNetwork::Cleanup_After_Client(broken_rhost_id);
  986. }
  987. //-----------------------------------------------------------------------------
  988. void cNetwork::Client_Broken_Connection_Handler(void)
  989. {
  990. //
  991. // The net lib calls this when a reliable packet fails after
  992. // many attempts. The connection data has already been destroyed.
  993. //
  994. WWASSERT(Get_Text_Display() != NULL);
  995. WWASSERT(PClientConnection != NULL);
  996. /**/
  997. if (PClientConnection->Have_Id()) {
  998. //cHelpText::Set(TRANSLATION(IDS_MP_CONNECTION_TO_SERVER_BROKEN));
  999. DlgMsgBox::DoDialog(L"", TRANSLATION(IDS_MP_CONNECTION_TO_SERVER_BROKEN));
  1000. } else {
  1001. //cHelpText::Set(TRANSLATION(IDS_MP_UNABLE_CONNECT_TO_SERVER));
  1002. }
  1003. //TSS090401
  1004. //
  1005. // The client needs to quit back to the game list
  1006. //
  1007. extern bool g_client_quit;
  1008. g_client_quit = true;
  1009. //WWAudioClass::Get_Instance()->Create_Instant_Sound("Broken_Connection", Matrix3D(1));
  1010. /**/
  1011. /*
  1012. WWDEBUG_SAY(("Connection to server broken.\n"));
  1013. if (PClientConnection->Have_Id()) {
  1014. DlgMPConnectionRefused::DoDialog(TRANSLATION(IDS_MP_CONNECTION_TO_SERVER_BROKEN), true);
  1015. } else {
  1016. extern bool g_client_quit;
  1017. g_client_quit = true;
  1018. }
  1019. */
  1020. }
  1021. //-----------------------------------------------------------------------------
  1022. void cNetwork::Process_Eviction_Sc(cPacket & packet)
  1023. {
  1024. WWDEBUG_SAY(("cNetwork::Process_Eviction_Sc\n"));
  1025. WWAudioClass::Get_Instance()->Create_Instant_Sound("Evicted_By_Server", Matrix3D(1));
  1026. WWASSERT(I_Am_Client());
  1027. UINT min_bps;
  1028. packet.Get(min_bps);//naughty... type conversion
  1029. float max_packetloss;
  1030. packet.Get(max_packetloss);
  1031. //UINT sustainable_bps = (UINT) packet.Get();
  1032. WWDEBUG_SAY(("\n* You were evicted from the server for inadequate bandwidth performance.\n"
  1033. "* This server requires packetloss of less than %5.2f %%, and a minimum\n"
  1034. "* sustainable bandwidth of %d bps.\n", max_packetloss, min_bps));
  1035. //
  1036. // At this stage, just signal to close down. This is
  1037. // a convenience during development
  1038. //
  1039. DIE;
  1040. }
  1041. //-----------------------------------------------------------------------------
  1042. void cNetwork::Eviction_Handler(int evicted_rhost_id)
  1043. {
  1044. WWMEMLOG(MEM_NETWORK);
  1045. WWDEBUG_SAY(("cNetwork::Eviction_Handler\n"));
  1046. WWASSERT(evicted_rhost_id >= 0);
  1047. WWASSERT(I_Am_Server());
  1048. //Send_Eviction_Sc(evicted_rhost_id);
  1049. cEvictionEvent * p_event = new cEvictionEvent;
  1050. p_event->Init(evicted_rhost_id, EVICTION_POOR_BANDWIDTH);
  1051. cNetwork::Flush();
  1052. //WWAudioClass::Get_Instance()->Create_Instant_Sound("Broken_Connection", Matrix3D(1));
  1053. }
  1054. //-----------------------------------------------------------------------------
  1055. bool cNetwork::I_Am_God(void)
  1056. {
  1057. bool i_am_god = false;
  1058. if (I_Am_Client()) {
  1059. cPlayer * p_player = cPlayerManager::Find_Player(Get_My_Id());
  1060. if (p_player != NULL && p_player->Invulnerable.Is_True()) {
  1061. i_am_god = true;
  1062. }
  1063. }
  1064. return i_am_god;
  1065. }
  1066. //-----------------------------------------------------------------------------
  1067. cPlayer * cNetwork::Get_My_Player_Object(void)
  1068. {
  1069. cPlayer * p_me = NULL;
  1070. if (I_Am_Client()) {
  1071. p_me = cPlayerManager::Find_Player(Get_My_Id());
  1072. }
  1073. return p_me;
  1074. }
  1075. //-----------------------------------------------------------------------------
  1076. int cNetwork::Get_My_Team_Number(void)
  1077. {
  1078. cPlayer * p_me = Get_My_Player_Object();
  1079. WWASSERT(p_me != NULL);
  1080. return p_me->Get_Player_Type();
  1081. }
  1082. //-----------------------------------------------------------------------------
  1083. Vector3 cNetwork::Get_My_Color(void)
  1084. {
  1085. cPlayer * p_me = cPlayerManager::Find_Player(Get_My_Id());
  1086. WWASSERT(p_me != NULL);
  1087. return p_me->Get_Color();
  1088. }
  1089. //-----------------------------------------------------------------------------
  1090. int cNetwork::Show_Welcome_Message(WideStringClass & name)
  1091. {
  1092. int show = false;
  1093. if (!IS_MISSION && (name == cNetInterface::Get_Nickname())) {
  1094. show = true;
  1095. }
  1096. return show;
  1097. }
  1098. //---------------------------------------------------------------------------
  1099. float cNetwork::Get_Distance_Priority(Vector3 & pos1, Vector3 & pos2)
  1100. {
  1101. Vector3 gap = pos2 - pos1;
  1102. float d = gap.Length();
  1103. WWASSERT(PTheGameData != NULL);
  1104. float max_distance = The_Game()->Get_Maximum_World_Distance();
  1105. WWASSERT(max_distance > 0);
  1106. float range1 = max_distance / 25.0f;
  1107. float range2 = max_distance / 5.0f;
  1108. float range3 = max_distance + 1;
  1109. float priority;
  1110. if (d < range1) {
  1111. priority = (float) ((range1 - d) / range1 * 0.499 + 0.50);
  1112. } else if (d < range2) {
  1113. priority = (float) ((range2 - d) / (range2 - range1) * 0.40 + 0.10);
  1114. } else if (d < range3) {
  1115. priority = (float) ((range3 - d) / (range3 - range2) * 0.10 + 0.00);
  1116. } else {
  1117. //WWASSERT(0);
  1118. static bool already_warned = false;
  1119. if (!already_warned) {
  1120. Debug_Say(("Someone went outside the world box! (possibly numerous times)\n"));
  1121. already_warned = true;
  1122. }
  1123. priority = 0;
  1124. }
  1125. WWASSERT(priority > -WWMATH_EPSILON && priority < 1 + WWMATH_EPSILON);
  1126. return(priority);
  1127. }
  1128. //-----------------------------------------------------------------------------
  1129. void cNetwork::Shell_Command(LPCSTR command)
  1130. {
  1131. WWASSERT(command != NULL);
  1132. HINSTANCE hinst = ShellExecute(NULL, NULL, command, NULL, "", SW_SHOW);
  1133. if ((int) hinst <= 32) {
  1134. WWDEBUG_SAY(("Error: ShellExecute failed.\n"));
  1135. }
  1136. }
  1137. //-----------------------------------------------------------------------------
  1138. REFUSAL_CODE cNetwork::Application_Acceptance_Handler(cPacket & packet)
  1139. {
  1140. #ifndef BETACLIENT
  1141. WWDEBUG_SAY(("cNetwork::Application_Acceptance_Handler\n"));
  1142. WWASSERT(I_Am_Server());
  1143. //
  1144. // Get player name
  1145. // This is not supposed to be empty, but if for whatever reason it it, we should
  1146. // just refuse, rather than crash.
  1147. //
  1148. WideStringClass player_name(0, true);
  1149. //packet.Get_Wide_Terminated_String(player_name.Get_Buffer(256), 256);
  1150. packet.Get_Wide_Terminated_String(player_name.Get_Buffer(256), 256, true);
  1151. if (player_name.Get_Length() == 0) {
  1152. return REFUSAL_VERSION_MISMATCH;
  1153. }
  1154. // Get the clients password
  1155. WideStringClass password(0, true);
  1156. packet.Get_Wide_Terminated_String(password.Get_Buffer(256), 256, true);
  1157. // Get clients exe version
  1158. int client_exe_key = packet.Get(client_exe_key);
  1159. // Make sure the clients password matches the games password.
  1160. WWASSERT(PTheGameData != NULL);
  1161. if (The_Game()->IsPassworded.Is_True() && password.Compare(The_Game()->Get_Password()) != 0) {
  1162. return REFUSAL_BAD_PASSWORD;
  1163. }
  1164. // Make sure the exe versions match
  1165. if (client_exe_key != cNetwork::Get_Exe_Key()) {
  1166. return REFUSAL_VERSION_MISMATCH;
  1167. }
  1168. // Make sure we haven't exceeded our max player limit
  1169. if (cPlayerManager::Count() >= The_Game()->Get_Max_Players()) {
  1170. return REFUSAL_GAME_FULL;
  1171. }
  1172. //
  1173. // TSS100501
  1174. //
  1175. // Make sure the player is not already in the game
  1176. //GAMESPY
  1177. //if (cPlayerManager::Find_Player(player_name)) {
  1178. if (!cGameSpyAdmin::Is_Gamespy_Game() &&
  1179. cPlayerManager::Find_Player(player_name)) {
  1180. return REFUSAL_PLAYER_EXISTS;
  1181. }
  1182. #endif // not BETACLIENT
  1183. return REFUSAL_CLIENT_ACCEPTED;
  1184. }
  1185. //-----------------------------------------------------------------------------
  1186. void cNetwork::Connection_Handler(int new_rhost_id)
  1187. {
  1188. WWMEMLOG(MEM_NETWORK);
  1189. #ifndef BETACLIENT
  1190. WWDEBUG_SAY(("cNetwork::Connection_Handler\n"));
  1191. WWASSERT(new_rhost_id >= 0);
  1192. WWASSERT(I_Am_Server());
  1193. WWASSERT(Receiver != NULL);
  1194. /*
  1195. //
  1196. // Tell the new guy about all the teams. He needs this early in case he
  1197. // needs to choose a team
  1198. //
  1199. SLNode<cTeam> * team_node;
  1200. cTeam * p_team;
  1201. for (team_node = cTeamManager::Get_Team_Object_List()->Head(); team_node; team_node = team_node->Next()) {
  1202. p_team = team_node->Data();
  1203. WWASSERT(p_team != NULL);
  1204. Send_Server_New_Team(p_team, new_rhost_id);
  1205. }
  1206. */
  1207. //TSS2001 - normal update mechanism won't catch this in time.
  1208. //
  1209. // Tell the new guy about all the teams. He needs this early in case he
  1210. // needs to choose a team
  1211. //
  1212. if (!cNetwork::I_Am_Client() || new_rhost_id != cNetwork::Get_My_Id()) {
  1213. for (
  1214. SLNode<cTeam> * team_node = cTeamManager::Get_Team_Object_List()->Head();
  1215. team_node;
  1216. team_node = team_node->Next()) {
  1217. cTeam * p_team = team_node->Data();
  1218. WWASSERT(p_team != NULL);
  1219. Send_Object_Update(p_team, new_rhost_id);
  1220. }
  1221. }
  1222. //
  1223. // Next, send info about any remaining game options. This is only those
  1224. // options that he doesn't pick up from the channel listing.
  1225. //
  1226. //Send_Server_Game_Options(new_rhost_id);
  1227. cGameOptionsEvent * p_event = new cGameOptionsEvent;
  1228. p_event->Init(new_rhost_id);
  1229. Send_Object_Update(p_event, new_rhost_id);
  1230. #endif // not BETACLIENT
  1231. }
  1232. //-----------------------------------------------------------------------------
  1233. void cNetwork::Set_Desired_Frame_Sleep_Ms(int b)
  1234. {
  1235. WWASSERT(b >= 0);
  1236. #ifdef WWDEBUG
  1237. cDevOptions::DesiredFrameSleepMs.Set(b);
  1238. #endif //WWDEBUG
  1239. }
  1240. //-----------------------------------------------------------------------------
  1241. void cNetwork::Set_Simulated_Packet_Loss_Pc(int b)
  1242. {
  1243. WWASSERT(b >= 0);
  1244. if (PClientConnection != NULL) {
  1245. PClientConnection->Set_Packet_Loss(b);
  1246. }
  1247. if (PServerConnection != NULL) {
  1248. PServerConnection->Set_Packet_Loss(b);
  1249. }
  1250. //SimulatedPacketLossPc = b;
  1251. #ifdef WWDEBUG
  1252. cDevOptions::SimulatedPacketLossPc.Set(b);
  1253. #endif //WWDEBUG
  1254. }
  1255. //-----------------------------------------------------------------------------
  1256. void cNetwork::Set_Simulated_Packet_Duplication_Pc(int b)
  1257. {
  1258. WWASSERT(b >= 0);
  1259. if (PClientConnection != NULL) {
  1260. PClientConnection->Set_Packet_Duplication(b);
  1261. }
  1262. if (PServerConnection != NULL) {
  1263. PServerConnection->Set_Packet_Duplication(b);
  1264. }
  1265. //SimulatedPacketDuplicationPc = b;
  1266. #ifdef WWDEBUG
  1267. cDevOptions::SimulatedPacketDuplicationPc.Set(b);
  1268. #endif
  1269. }
  1270. //-----------------------------------------------------------------------------
  1271. void cNetwork::Set_Simulated_Latency_Range_Ms(int lower, int upper)
  1272. {
  1273. WWASSERT(lower >= 0);
  1274. WWASSERT(upper >= 0);
  1275. WWASSERT(lower <= upper);
  1276. if (PClientConnection != NULL) {
  1277. PClientConnection->Set_Packet_Latency_Range(lower, upper);
  1278. }
  1279. if (PServerConnection != NULL) {
  1280. PServerConnection->Set_Packet_Latency_Range(lower, upper);
  1281. }
  1282. //SimulatedLatencyRangeMsLower = lower;
  1283. //SimulatedLatencyRangeMsUpper = upper;
  1284. #ifdef WWDEBUG
  1285. cDevOptions::SimulatedLatencyRangeMsLower.Set(lower);
  1286. cDevOptions::SimulatedLatencyRangeMsUpper.Set(upper);
  1287. #endif
  1288. }
  1289. //-----------------------------------------------------------------------------
  1290. void cNetwork::Set_Spam_Count(int spam_count)
  1291. {
  1292. WWASSERT(spam_count >= 0);
  1293. //SpamCount = spam_count;
  1294. #ifdef WWDEBUG
  1295. cDevOptions::SpamCount.Set(spam_count);
  1296. #endif
  1297. }
  1298. //-----------------------------------------------------------------------------
  1299. void cNetwork::Get_Simulated_Latency_Range_Ms(int & lower, int & upper)
  1300. {
  1301. #ifdef WWDEBUG
  1302. lower = cDevOptions::SimulatedLatencyRangeMsLower.Get();
  1303. upper = cDevOptions::SimulatedLatencyRangeMsUpper.Get();
  1304. #endif
  1305. }
  1306. //-----------------------------------------------------------------------------
  1307. void
  1308. cNetwork::Flush(void)
  1309. {
  1310. WWDEBUG_SAY(("cNetwork::Flush\n"));
  1311. const bool is_urgent = true;
  1312. //if (GameModeManager::Find ("Combat")->Is_Active() && Receiver != NULL) {
  1313. if (Receiver != NULL) {
  1314. if (I_Am_Server()) {
  1315. Receiver->Server_Update_Dynamic_Objects(is_urgent);
  1316. }
  1317. if (I_Am_Client()) {
  1318. Receiver->Client_Update_Dynamic_Objects(is_urgent);
  1319. }
  1320. }
  1321. if (I_Am_Server()) {
  1322. PServerConnection->Service_Send(is_urgent);
  1323. }
  1324. if (I_Am_Client()) {
  1325. PClientConnection->Service_Send(is_urgent);
  1326. }
  1327. PacketManager.Flush(true);
  1328. }
  1329. void cNetwork::SwitchTeam(int newTeam)
  1330. {
  1331. cPlayer* player = cPlayerManager::Find_Player(Get_My_Id());
  1332. if (player) {
  1333. int team = player->Get_Player_Type();
  1334. if (newTeam != team) {
  1335. cChangeTeamEvent* event = new cChangeTeamEvent;
  1336. event->Init();
  1337. }
  1338. }
  1339. }
  1340. //-----------------------------------------------------------------------------
  1341. void cNetwork::Enable_Waiting_Players(void)
  1342. {
  1343. SLNode<cPlayer> * objnode;
  1344. for (objnode = cPlayerManager::Get_Player_Object_List()->Head() ; objnode != NULL ; objnode = objnode->Next()) {
  1345. cPlayer * p_player = objnode->Data();
  1346. WWASSERT(p_player != NULL);
  1347. if (p_player->Is_Human() && p_player->Get_Is_Waiting_For_Intermission().Is_True()) {
  1348. p_player->Set_Is_In_Game(true);
  1349. p_player->Set_Is_Waiting_For_Intermission(false);
  1350. if (cNetwork::PServerConnection) {
  1351. cNetwork::PServerConnection->Set_Rhost_Is_In_Game(p_player->Get_Id(), true);
  1352. }
  1353. cGameDataUpdateEvent * p_event = new cGameDataUpdateEvent();
  1354. p_event->Init(p_player->Get_Id());
  1355. }
  1356. }
  1357. }