CnC_Remastered_Collection

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

CCTEN.CPP (22497B)


      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 : CCTEN.CPP                                *
     21  *                                                                         *
     22  *                   Programmer : Bill R. Randolph                         *
     23  *                                                                         *
     24  *                   Start Date : 01/09/96                                 *
     25  *                                                                         *
     26  *                  Last Update : November 27, 1996 [BRR]                  *
     27  *                                                                         *
     28  *-------------------------------------------------------------------------*
     29  * Functions:                                                              *
     30  *   Init_TEN -- Performs TEN-specific initialization                      *
     31  *   Shutdown_TEN -- Shuts down TEN connections                            *
     32  *   Connect_TEN -- Waits for connections to other players                 *
     33  *   Destroy_TEN_Connection -- Destroys the given connection               *
     34  *   Debug_Mono -- Custom mono prints                                      *
     35  *   Send_TEN_Win_Packet -- Sends a win packet to server                   *
     36  *   Send_TEN_Alliance -- Sends an ally/enemy packet to server             *
     37  *   Send_TEN_Out_Of_Sync -- Announces this game out of sync               *
     38  *   Send_TEN_Packet_Too_Late -- Announces packet-received-too-late        *
     39  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     40 #include "function.h"
     41 
     42 #if(TEN)
     43 #ifdef WIN32
     44 #define WINDOWS
     45 #endif
     46 #include "ten.h"
     47 #endif
     48 
     49 void Connect_TEN(void);
     50 void Debug_Mono(void);
     51 
     52 /***************************************************************************
     53  * Init_TEN -- Performs TEN-specific initialization                        *
     54  *                                                                         *
     55  * INPUT:                                                                  *
     56  *		none.																						*
     57  *                                                                         *
     58  * OUTPUT:                                                                 *
     59  *		1 = OK, 0 = error																		*
     60  *                                                                         *
     61  * WARNINGS:                                                               *
     62  *		none.																						*
     63  *                                                                         *
     64  * HISTORY:                                                                *
     65  *   01/09/1996 BRR : Created.                                             *
     66  *=========================================================================*/
     67 int Init_TEN(void)
     68 {
     69 #if(TEN)
     70 	//------------------------------------------------------------------------
     71 	// Allocate a packet buffer for TEN's use
     72 	//------------------------------------------------------------------------
     73 	Session.TenPacket = new char[Session.TenSize];
     74 
     75 	//------------------------------------------------------------------------
     76 	// Read the multiplayer settings from the CONQUER.INI file, and the game
     77 	// options from the options file.
     78 	//------------------------------------------------------------------------
     79 	Session.Read_MultiPlayer_Settings();
     80 
     81 	if (!Read_TEN_Game_Options()) {
     82 		WWMessageBox().Process("Unable to load game settings!");
     83 		//Prog_End();
     84 		Emergency_Exit(0);
     85 	}
     86 
     87 	//------------------------------------------------------------------------
     88 	// Flush all incoming packets
     89 	//------------------------------------------------------------------------
     90 	Ten->Flush_All();
     91 
     92 	//------------------------------------------------------------------------
     93 	// Form connections to all other players
     94 	//------------------------------------------------------------------------
     95 	Connect_TEN();
     96 
     97 	//------------------------------------------------------------------------
     98 	// Set multiplayer values for the local system, and timing values.
     99 	//------------------------------------------------------------------------
    100 	Session.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
    101 
    102 	return (1);
    103 #else
    104 	return (1);
    105 #endif
    106 
    107 }	// end of Init_TEN
    108 
    109 
    110 /***************************************************************************
    111  * Shutdown_TEN -- Shuts down TEN connections                              *
    112  *                                                                         *
    113  * INPUT:                                                                  *
    114  *		none.																						*
    115  *                                                                         *
    116  * OUTPUT:                                                                 *
    117  *		none.																						*
    118  *                                                                         *
    119  * WARNINGS:                                                               *
    120  *		none.																						*
    121  *                                                                         *
    122  * HISTORY:                                                                *
    123  *   01/09/1996 BRR : Created.                                             *
    124  *=========================================================================*/
    125 void Shutdown_TEN(void)
    126 {
    127 #if(TEN)
    128 	CDTimerClass<SystemTimerClass> timer;
    129 
    130 	//------------------------------------------------------------------------
    131 	// Wait a full second before exiting, to ensure all packets get sent.
    132 	//------------------------------------------------------------------------
    133 	timer = 60;
    134 	while (timer) ;
    135 
    136 	//------------------------------------------------------------------------
    137 	// Free memory
    138 	//------------------------------------------------------------------------
    139 	if (Session.TenPacket) {
    140 		delete [] Session.TenPacket;
    141 		Session.TenPacket = NULL;
    142 	}
    143 
    144 	if (Ten) {
    145 		delete Ten;
    146 		Ten = NULL;
    147 	}
    148 
    149 	return;
    150 
    151 #endif
    152 }	// end of Shutdown_TEN
    153 
    154 
    155 /***************************************************************************
    156  * Connect_TEN -- Waits for connections to other players                 	*
    157  *                                                                         *
    158  * INPUT:                                                                  *
    159  *		none.																						*
    160  *                                                                         *
    161  * OUTPUT:                                                                 *
    162  *		none.																						*
    163  *                                                                         *
    164  * WARNINGS:                                                               *
    165  *		MPlayerCount must have been initialized at this point.					*
    166  *                                                                         *
    167  * HISTORY:                                                                *
    168  *   01/10/1996 BRR : Created.                                             *
    169  *=========================================================================*/
    170 void Connect_TEN(void)
    171 {
    172 #if(TEN)
    173 	typedef struct ConnectPacketTag {
    174 		NetCommandType Dummy;				// packet type; set to PING
    175 		char Name[MPLAYER_NAME_MAX];		// player's name
    176 		HousesType House;						// player's ActLike
    177 		unsigned char Color;					// player's Color
    178 	} ConnectPacketType;
    179 	int num_players;
    180 	int num_found;
    181 	ConnectPacketType send_packet;
    182 	ConnectPacketType receive_packet;
    183 	int address;
    184 	int found;
    185 	int size;
    186 	int i;
    187 	CDTimerClass<SystemTimerClass> send_timer;
    188 	NodeNameType *who;
    189 
    190 	enum {
    191 		D_TXT6_H = 7,
    192 		D_MARGIN = 5,
    193 	};
    194 	static int x,y,w,h;
    195 	char const *buf1;
    196 	char const *buf2;
    197 
    198 	int display = 0;
    199 	RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
    200 
    201 	//
    202 	// Clear the Players list
    203 	//
    204 	while (Session.Players.Count() > 0) {
    205 		delete Session.Players[0];
    206 		Session.Players.Delete(Session.Players[0]);
    207 	}
    208 
    209 	//
    210 	// Add myself to the list first thing
    211 	//
    212 	who = new NodeNameType;
    213 	strcpy(who->Name, Session.Handle);
    214 	who->Player.House = Session.House;
    215 	who->Player.Color = Session.ColorIdx;
    216 	Session.Players.Add (who);
    217 
    218 	//
    219 	// Find out how many players to wait for
    220 	//
    221 	num_players = Session.NumPlayers - 1;
    222 	num_found = 0;
    223 
    224 	//
    225 	// Send out a packet announcing my presence
    226 	//
    227 	send_packet.Dummy = NET_PING;
    228 	strcpy(send_packet.Name, Session.Handle);
    229 	send_packet.House = Session.House;
    230 	send_packet.Color = Session.ColorIdx;
    231 	Ten->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);
    232 
    233 	//
    234 	// Start our packet-sending timer
    235 	//
    236 	send_timer = 240;
    237 
    238 	//
    239 	// Wait for all players to enter the game
    240 	//
    241 	display = 1;
    242 	while (num_found < num_players) {
    243 
    244 		#ifdef WIN32
    245 		/*
    246 		** If we have just received input focus again after running in the background then
    247 		** we need to redraw.
    248 		*/
    249 		if (AllSurfaces.SurfacesRestored) {
    250 			AllSurfaces.SurfacesRestored=FALSE;
    251 			display = 1;
    252 		}
    253 		#endif
    254 
    255 		if (display) {
    256 			Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT);
    257 			buf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);
    258 			buf2 = Text_String(TXT_PRESS_ESC);
    259 			w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
    260 			w += (D_MARGIN * 2);
    261 			h = (D_TXT6_H * 2) + (D_MARGIN * 7);
    262 			x = 160 - (w / 2);
    263 			y = 100 - (h / 2);
    264 			Hide_Mouse();
    265 			//Set_Logic_Page(SeenBuff);
    266 			Dialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);
    267 
    268 			Fancy_Text_Print(buf1,
    269 				160 * RESFACTOR,
    270 				(y + (D_MARGIN * 2)) * RESFACTOR,
    271 				scheme, TBLACK, TPF_CENTER | TPF_TEXT);
    272 			Fancy_Text_Print(buf2,
    273 				160 * RESFACTOR,
    274 				(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,
    275 				scheme, TBLACK, TPF_CENTER | TPF_TEXT);
    276 			Show_Mouse();
    277 			display = 0;
    278 		}
    279 
    280 		Ten->Service();
    281 
    282 		//
    283 		// Check for an incoming packet; if a PING comes in, see if we already
    284 		// have this player in our Players list.  If not, add him.
    285 		//
    286 		if (Ten->Get_Global_Message (&receive_packet, &size, &address) &&
    287 			receive_packet.Dummy == NET_PING) {
    288 			found = 0;
    289 			for (i = 1; i < Session.Players.Count(); i++) {
    290 				if (Session.Players[i]->TenAddress == address) {
    291 					found = 1;
    292 					break;
    293 				}
    294 			}
    295 
    296 			//
    297 			// Create a new connection and a new node in the list.
    298 			//
    299 			if (!found) {
    300 
    301 				who = new NodeNameType;
    302 				strcpy(who->Name, receive_packet.Name);
    303 				who->TenAddress = address;
    304 				who->Player.House = receive_packet.House;
    305 				who->Player.Color = (PlayerColorType)receive_packet.Color;
    306 				Session.Players.Add (who);
    307 
    308 				num_found++;
    309 
    310 				Ten->Send_Global_Message(&send_packet, sizeof(send_packet), 1,
    311 					address);
    312 			}
    313 		}
    314 
    315 		//
    316 		// If the user hits ESC, bail out.
    317 		//
    318 		if (Keyboard->Check()) {
    319 			if (Keyboard->Get() == KN_ESC) {
    320 				//Prog_End();
    321 				Emergency_Exit(0);
    322 			}
    323 		}
    324 
    325 		//
    326 		// When our timer expires, re-send the packet.
    327 		//
    328 		if (!send_timer) {
    329 			send_packet.Dummy = NET_PING;
    330 			Ten->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);
    331 			send_timer = 240;
    332 		}
    333 	}
    334 
    335 #else
    336 	return;
    337 #endif
    338 }
    339 
    340 
    341 /***************************************************************************
    342  * Destroy_TEN_Connection -- Destroys the given connection                 *
    343  *                                                                         *
    344  * INPUT:                                                                  *
    345  *		id			connection ID to destroy (must be a HousesType)					*
    346  *		error		0 = user signed off; 1 = connection error; otherwise, 		*
    347  *					no error is shown.		  												*
    348  *                                                                         *
    349  * OUTPUT:                                                                 *
    350  *		none.																						*
    351  *                                                                         *
    352  * WARNINGS:                                                               *
    353  *		none.																						*
    354  *                                                                         *
    355  * HISTORY:                                                                *
    356  *   01/11/1996 BRR : Created.                                             *
    357  *=========================================================================*/
    358 void Destroy_TEN_Connection(int id, int error)
    359 {
    360 #if(TEN)
    361 	int i;
    362 	HouseClass *housep;
    363 	char txt[80];
    364 
    365 	//------------------------------------------------------------------------
    366 	//	Do nothing if the house isn't human.
    367 	//------------------------------------------------------------------------
    368 	housep = HouseClass::As_Pointer((HousesType)id);
    369 	if (!housep || !housep->IsHuman)
    370 		return;
    371 
    372 	/*------------------------------------------------------------------------
    373 	Create a message to display to the user
    374 	------------------------------------------------------------------------*/
    375 	txt[0] = '\0';
    376 	if (error==1) {
    377 		sprintf(txt,Text_String(TXT_CONNECTION_LOST),Ten->Connection_Name(id));
    378 	} else if (error==0) {
    379 		sprintf(txt,Text_String(TXT_LEFT_GAME),Ten->Connection_Name(id));
    380 	}
    381 
    382 	if (strlen(txt)) {
    383 		Session.Messages.Add_Message (NULL,0, txt, housep->RemapColor,
    384 			TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
    385 		Map.Flag_To_Redraw(false);
    386 	}
    387 
    388 	//------------------------------------------------------------------------
    389 	// Remove this player from the Players vector
    390 	//------------------------------------------------------------------------
    391 	for (i = 0; i < Session.Players.Count(); i++) {
    392 		if (!stricmp(Session.Players[i]->Name,housep->IniName)) {
    393 			delete Session.Players[i];
    394 			Session.Players.Delete(Session.Players[i]);
    395 			break;
    396 		}
    397 	}
    398 
    399 	/*------------------------------------------------------------------------
    400 	Delete the TEN connection
    401 	------------------------------------------------------------------------*/
    402 	Ten->Delete_Connection(id);
    403 
    404 	//------------------------------------------------------------------------
    405 	//	Turn the player's house over to the computer's AI
    406 	//------------------------------------------------------------------------
    407 	housep->IsHuman = false;
    408 	housep->IQ = Rule.MaxIQ;
    409 	strcpy (housep->IniName,Text_String(TXT_COMPUTER));
    410 
    411 	Session.NumPlayers--;
    412 
    413 	/*------------------------------------------------------------------------
    414 	If we're the last player left, tell the user.
    415 	------------------------------------------------------------------------*/
    416 	if (Session.NumPlayers == 1) {
    417 		sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
    418 		Session.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,
    419 			TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
    420 		Map.Flag_To_Redraw(false);
    421 	}
    422 
    423 #else
    424 	id = id;
    425 	error = error;
    426 
    427 #endif
    428 }	// end of Destroy_TEN_Connection
    429 
    430 
    431 /***************************************************************************
    432  * Debug_Mono -- Custom mono prints                                        *
    433  *                                                                         *
    434  * INPUT:                                                                  *
    435  *		none.																						*
    436  *                                                                         *
    437  * OUTPUT:                                                                 *
    438  *		none.																						*
    439  *                                                                         *
    440  * WARNINGS:                                                               *
    441  *		none.																						*
    442  *                                                                         *
    443  * HISTORY:                                                                *
    444  *   11/27/1996 BRR : Created.                                             *
    445  *=========================================================================*/
    446 void Debug_Mono(void)
    447 {
    448 #if(TEN)
    449 	int i;
    450 	int id;
    451 
    452 	Mono_Printf("STATE: # Connections:%d\n",Ten->Num_Connections());
    453 	for (i=0;i<Ten->Num_Connections();i++) {
    454 		id = Ten->Connection_ID(i);
    455 		Mono_Printf("Connection %d: Name:%s, ID:%d, Address:%d\n",
    456 			i,
    457 			Ten->Connection_Name(id),
    458 			Ten->Connection_ID(i),
    459 			Ten->Connection_Address(id));
    460 	}
    461 
    462 #endif
    463 }
    464 
    465 
    466 /***************************************************************************
    467  * Send_TEN_Win_Packet -- Sends a win packet to server                     *
    468  *                                                                         *
    469  * INPUT:                                                                  *
    470  *		none.																						*
    471  *                                                                         *
    472  * OUTPUT:                                                                 *
    473  *		none.																						*
    474  *                                                                         *
    475  * WARNINGS:                                                               *
    476  *		none.																						*
    477  *                                                                         *
    478  * HISTORY:                                                                *
    479  *   11/27/1996 BRR : Created.                                             *
    480  *=========================================================================*/
    481 void Send_TEN_Win_Packet(void)
    482 {
    483 #if(TEN)
    484 	char winbuf[80];
    485 	char idbuf[20];
    486 	int first = 1;
    487 	HouseClass *hptr;
    488 	int i;
    489 
    490 	//
    491 	// Build a special text buffer to send to the TEN server.  Format:
    492 	// "winner 'id id'", where 'id' is the Ten Player ID of each player
    493 	// on the winning team.  (For TEN, the color index is the player ID.)
    494 	//
    495 	sprintf(winbuf,"winner '");
    496 	for (i = 0; i < Session.Players.Count(); i++) {
    497 		hptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);
    498 		if (!hptr->IsDefeated) {
    499 			if (!first) {
    500 				strcat(winbuf," ");
    501 			} else {
    502 				first = 0;
    503 			}
    504 			sprintf(idbuf,"%d", Session.Players[i]->Player.Color);
    505 			strcat (winbuf, idbuf);
    506 		}
    507 	}
    508 	strcat (winbuf,"' ");
    509 	tenArSetPlayerState(winbuf);
    510 #endif	// TEN
    511 
    512 }	// end of Send_TEN_Win_Packet
    513 
    514 
    515 /***************************************************************************
    516  * Send_TEN_Alliance -- Sends an ally/enemy packet to server               *
    517  *                                                                         *
    518  * INPUT:                                                                  *
    519  *		whom		name of player we're allying / enemying with						*
    520  *		ally		1 = we're allying; 0 = we're breaking the alliance				*
    521  *                                                                         *
    522  * OUTPUT:                                                                 *
    523  *		none.																						*
    524  *                                                                         *
    525  * WARNINGS:                                                               *
    526  *		none.																						*
    527  *                                                                         *
    528  * HISTORY:                                                                *
    529  *   11/27/1996 BRR : Created.                                             *
    530  *=========================================================================*/
    531 void Send_TEN_Alliance(char *whom, int ally)
    532 {
    533 #if(TEN)
    534 	char buf[80];
    535 
    536 	if (ally) {
    537 		sprintf(buf,"ally '%s' ",whom);
    538 	} else {
    539 		sprintf(buf,"enemy '%s' ",whom);
    540 	}
    541 
    542 	tenArSetPlayerState(buf);
    543 
    544 #else
    545 	whom = whom;
    546 	ally = ally;
    547 #endif	// TEN
    548 
    549 }	// end of Send_TEN_Alliance
    550 
    551 
    552 /***************************************************************************
    553  * Send_TEN_Out_Of_Sync -- Announces this game out of sync                 *
    554  *                                                                         *
    555  * INPUT:                                                                  *
    556  *		none.																						*
    557  *                                                                         *
    558  * OUTPUT:                                                                 *
    559  *		none.																						*
    560  *                                                                         *
    561  * WARNINGS:                                                               *
    562  *		none.																						*
    563  *                                                                         *
    564  * HISTORY:                                                                *
    565  *   11/27/1996 BRR : Created.                                             *
    566  *=========================================================================*/
    567 void Send_TEN_Out_Of_Sync(void)
    568 {
    569 #if(TEN)
    570 	tenArSetPlayerState("sync '1' ");
    571 #endif	// TEN
    572 
    573 }	// end of Send_TEN_Out_Of_Sync
    574 
    575 
    576 /***************************************************************************
    577  * Send_TEN_Packet_Too_Late -- Announces packet-received-too-late          *
    578  *                                                                         *
    579  * INPUT:                                                                  *
    580  *		none.																						*
    581  *                                                                         *
    582  * OUTPUT:                                                                 *
    583  *		none.																						*
    584  *                                                                         *
    585  * WARNINGS:                                                               *
    586  *		none.																						*
    587  *                                                                         *
    588  * HISTORY:                                                                *
    589  *   11/27/1996 BRR : Created.                                             *
    590  *=========================================================================*/
    591 void Send_TEN_Packet_Too_Late(void)
    592 {
    593 #if(TEN)
    594 	tenArSetPlayerState("toolate '1' ");
    595 #endif	// TEN
    596 
    597 }	// end of Send_TEN_Packet_Too_Late
    598 
    599 
    600 /***************************** end of ccten.cpp *****************************/