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