CCMPATH.CPP 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /***************************************************************************
  15. * *
  16. * Project Name : Command & Conquer *
  17. * *
  18. * File Name : CCMPATH.CPP *
  19. * *
  20. * Programmer : Bill R. Randolph *
  21. * *
  22. * Start Date : 01/09/96 *
  23. * *
  24. * Last Update : January 11, 1996 [BRR] *
  25. * *
  26. *-------------------------------------------------------------------------*
  27. * Functions: *
  28. * Init_MPATH -- Performs MPATH-specific initialization *
  29. * Shutdown_MPATH -- Shuts down MPATH connections *
  30. * Connect_MPATH -- Waits for connections to other players *
  31. * Destroy_MPATH_Connection -- Destroys the given connection *
  32. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  33. #include "function.h"
  34. /***************************************************************************
  35. * Init_MPATH -- Performs MPATH-specific initialization *
  36. * *
  37. * INPUT: *
  38. * none. *
  39. * *
  40. * OUTPUT: *
  41. * 1 = OK, 0 = error *
  42. * *
  43. * WARNINGS: *
  44. * none. *
  45. * *
  46. * HISTORY: *
  47. * 01/09/1996 BRR : Created. *
  48. *=========================================================================*/
  49. int Init_MPATH(void)
  50. {
  51. #if(MPATH)
  52. //------------------------------------------------------------------------
  53. // Allocate a packet buffer for MPATH's use
  54. //------------------------------------------------------------------------
  55. Session.MPathPacket = new char[Session.MPathSize];
  56. //------------------------------------------------------------------------
  57. // Read the multiplayer settings from the CONQUER.INI file, and the game
  58. // options from the options file.
  59. //------------------------------------------------------------------------
  60. Session.Read_MultiPlayer_Settings();
  61. if (!Read_MPATH_Game_Options()) {
  62. WWMessageBox().Process("Unable to load game settings!");
  63. //Prog_End();
  64. Emergency_Exit(0);
  65. }
  66. //------------------------------------------------------------------------
  67. // Flush all incoming packets
  68. //------------------------------------------------------------------------
  69. MPath->Flush_All();
  70. //------------------------------------------------------------------------
  71. // Form connections to all other players
  72. //------------------------------------------------------------------------
  73. Connect_MPATH();
  74. //------------------------------------------------------------------------
  75. // Set multiplayer values for the local system, and timing values.
  76. //------------------------------------------------------------------------
  77. Session.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
  78. return (1);
  79. #else
  80. return (1);
  81. #endif
  82. } // end of Init_MPATH
  83. /***************************************************************************
  84. * Shutdown_MPATH -- Shuts down MPATH connections *
  85. * *
  86. * INPUT: *
  87. * none. *
  88. * *
  89. * OUTPUT: *
  90. * none. *
  91. * *
  92. * WARNINGS: *
  93. * none. *
  94. * *
  95. * HISTORY: *
  96. * 01/09/1996 BRR : Created. *
  97. *=========================================================================*/
  98. void Shutdown_MPATH(void)
  99. {
  100. #if(MPATH)
  101. CDTimerClass<SystemTimerClass> timer;
  102. //------------------------------------------------------------------------
  103. // Wait a full second before exiting, to ensure all packets get sent.
  104. //------------------------------------------------------------------------
  105. timer = 60;
  106. while (timer) ;
  107. //------------------------------------------------------------------------
  108. // Free memory
  109. //------------------------------------------------------------------------
  110. if (Session.MPathPacket) {
  111. delete [] Session.MPathPacket;
  112. Session.MPathPacket = NULL;
  113. }
  114. if (MPath) {
  115. delete MPath;
  116. MPath = NULL;
  117. }
  118. return;
  119. #endif
  120. } // end of Shutdown_MPATH
  121. /***************************************************************************
  122. * Connect_MPATH -- Waits for connections to other players *
  123. * *
  124. * INPUT: *
  125. * none. *
  126. * *
  127. * OUTPUT: *
  128. * none. *
  129. * *
  130. * WARNINGS: *
  131. * none. *
  132. * *
  133. * HISTORY: *
  134. * 01/10/1996 BRR : Created. *
  135. *=========================================================================*/
  136. void Connect_MPATH(void)
  137. {
  138. #if(MPATH)
  139. typedef struct ConnectPacketTag {
  140. NetCommandType Dummy; // packet type; set to PING
  141. char Name[MPLAYER_NAME_MAX]; // player's name
  142. HousesType House; // player's ActLike
  143. unsigned char Color; // player's Color
  144. } ConnectPacketType;
  145. int num_players;
  146. int num_found;
  147. ConnectPacketType send_packet;
  148. ConnectPacketType receive_packet;
  149. int address;
  150. int found;
  151. int size;
  152. int i;
  153. CDTimerClass<SystemTimerClass> send_timer;
  154. NodeNameType *who;
  155. enum {
  156. D_TXT6_H = 7,
  157. D_MARGIN = 5,
  158. };
  159. static int x,y,w,h;
  160. char const *buf1;
  161. char const *buf2;
  162. int display = 0;
  163. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  164. //
  165. // Clear the Players list
  166. //
  167. while (Session.Players.Count() > 0) {
  168. delete Session.Players[0];
  169. Session.Players.Delete(Session.Players[0]);
  170. }
  171. //
  172. // Add myself to the list first thing
  173. //
  174. who = new NodeNameType;
  175. strcpy(who->Name, Session.Handle);
  176. who->Player.House = Session.House;
  177. who->Player.Color = Session.ColorIdx;
  178. Session.Players.Add (who);
  179. //
  180. // Find out how many players to wait for
  181. //
  182. num_players = MPath->Find_Num_Connections();
  183. num_found = 0;
  184. Session.NumPlayers = num_players + 1;
  185. //
  186. // Send out a packet announcing my presence
  187. //
  188. send_packet.Dummy = NET_PING;
  189. strcpy(send_packet.Name, Session.Handle);
  190. send_packet.House = Session.House;
  191. send_packet.Color = Session.ColorIdx;
  192. MPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);
  193. //
  194. // Start our packet-sending timer
  195. //
  196. send_timer = 240;
  197. //
  198. // Wait for all players to enter the game
  199. //
  200. display = 1;
  201. while (num_found < num_players) {
  202. #ifdef WIN32
  203. /*
  204. ** If we have just received input focus again after running in the background then
  205. ** we need to redraw.
  206. */
  207. if (AllSurfaces.SurfacesRestored) {
  208. AllSurfaces.SurfacesRestored=FALSE;
  209. display = 1;
  210. }
  211. #endif
  212. if (display) {
  213. Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT);
  214. buf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);
  215. buf2 = Text_String(TXT_PRESS_ESC);
  216. w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
  217. w += (D_MARGIN * 2);
  218. h = (D_TXT6_H * 2) + (D_MARGIN * 7);
  219. x = 160 - (w / 2);
  220. y = 100 - (h / 2);
  221. Hide_Mouse();
  222. //Set_Logic_Page(SeenBuff);
  223. Dialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);
  224. Fancy_Text_Print(buf1,
  225. 160 * RESFACTOR,
  226. (y + (D_MARGIN * 2)) * RESFACTOR,
  227. scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  228. Fancy_Text_Print(buf2,
  229. 160 * RESFACTOR,
  230. (y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,
  231. scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  232. Show_Mouse();
  233. display = 0;
  234. }
  235. MPath->Service();
  236. //
  237. // Check for an incoming packet; if a PING comes in, see if we already
  238. // have this player in our Players list. If not, add him.
  239. //
  240. if (MPath->Get_Global_Message (&receive_packet, &size, &address) &&
  241. receive_packet.Dummy == NET_PING) {
  242. found = 0;
  243. for (i = 1; i < Session.Players.Count(); i++) {
  244. if (Session.Players[i]->MPathAddress == address) {
  245. found = 1;
  246. break;
  247. }
  248. }
  249. //
  250. // Create a new connection and a new node in the list.
  251. //
  252. if (!found) {
  253. who = new NodeNameType;
  254. strcpy(who->Name, receive_packet.Name);
  255. who->MPathAddress = address;
  256. who->Player.House = receive_packet.House;
  257. who->Player.Color = (PlayerColorType)receive_packet.Color;
  258. Session.Players.Add (who);
  259. num_found++;
  260. MPath->Send_Global_Message(&send_packet, sizeof(send_packet), 1,
  261. address);
  262. }
  263. }
  264. //
  265. // If the user hits ESC, bail out.
  266. //
  267. if (Keyboard->Check()) {
  268. if (Keyboard->Get() == KN_ESC) {
  269. //Prog_End();
  270. Emergency_Exit(0);
  271. }
  272. }
  273. //
  274. // When our timer expires, re-send the packet.
  275. //
  276. if (!send_timer) {
  277. send_packet.Dummy = NET_PING;
  278. MPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);
  279. send_timer = 240;
  280. }
  281. }
  282. #else
  283. return;
  284. #endif
  285. }
  286. /***************************************************************************
  287. * Destroy_MPATH_Connection -- Destroys the given connection *
  288. * *
  289. * INPUT: *
  290. * id connection ID to destroy *
  291. * error 0 = user signed off; 1 = connection error; otherwise, *
  292. * no error is shown. *
  293. * *
  294. * OUTPUT: *
  295. * none. *
  296. * *
  297. * WARNINGS: *
  298. * none. *
  299. * *
  300. * HISTORY: *
  301. * 01/11/1996 BRR : Created. *
  302. *=========================================================================*/
  303. void Destroy_MPATH_Connection(int id, int error)
  304. {
  305. #if(MPATH)
  306. int i;
  307. HouseClass *housep;
  308. char txt[80];
  309. //------------------------------------------------------------------------
  310. // Do nothing if the house isn't human.
  311. //------------------------------------------------------------------------
  312. housep = HouseClass::As_Pointer((HousesType)id);
  313. if (!housep || !housep->IsHuman)
  314. return;
  315. /*------------------------------------------------------------------------
  316. Create a message to display to the user
  317. ------------------------------------------------------------------------*/
  318. txt[0] = '\0';
  319. if (error==1) {
  320. sprintf(txt,Text_String(TXT_CONNECTION_LOST),MPath->Connection_Name(id));
  321. } else if (error==0) {
  322. sprintf(txt,Text_String(TXT_LEFT_GAME),MPath->Connection_Name(id));
  323. }
  324. if (strlen(txt)) {
  325. Session.Messages.Add_Message (NULL,0, txt, housep->RemapColor,
  326. TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
  327. Map.Flag_To_Redraw(false);
  328. }
  329. //------------------------------------------------------------------------
  330. // Remove this player from the Players vector
  331. //------------------------------------------------------------------------
  332. for (i = 0; i < Session.Players.Count(); i++) {
  333. if (!stricmp(Session.Players[i]->Name,housep->IniName)) {
  334. delete Session.Players[i];
  335. Session.Players.Delete(Session.Players[i]);
  336. break;
  337. }
  338. }
  339. /*------------------------------------------------------------------------
  340. Delete the MPATH connection
  341. ------------------------------------------------------------------------*/
  342. MPath->Delete_Connection(id);
  343. //------------------------------------------------------------------------
  344. // Turn the player's house over to the computer's AI
  345. //------------------------------------------------------------------------
  346. housep->IsHuman = false;
  347. housep->IQ = Rule.MaxIQ;
  348. strcpy (housep->IniName,Text_String(TXT_COMPUTER));
  349. Session.NumPlayers--;
  350. /*------------------------------------------------------------------------
  351. If we're the last player left, tell the user.
  352. ------------------------------------------------------------------------*/
  353. if (Session.NumPlayers == 1) {
  354. sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
  355. Session.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,
  356. TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
  357. Map.Flag_To_Redraw(false);
  358. }
  359. #else
  360. id = id;
  361. error = error;
  362. #endif
  363. } // end of Destroy_MPATH_Connection
  364. /***************************** end of ccmpath.cpp **************************/