CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

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 **************************/