CCMPATH.CPP 15 KB

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