FS2_Open
Open source remastering of the Freespace 2 engine
multi_endgame.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "network/multi.h"
14 #include "object/object.h"
15 #include "freespace2/freespace.h"
17 #include "popup/popup.h"
18 #include "popup/popupdead.h"
19 #include "network/multi_endgame.h"
20 #include "playerman/player.h"
21 #include "network/multimsgs.h"
22 #include "network/multiui.h"
23 #include "network/multiutil.h"
24 #include "network/multi_pmsg.h"
25 #include "fs2netd/fs2netd_client.h"
26 
27 
28 // ----------------------------------------------------------------------------------------------------------
29 // Put all functions/data related to leaving a netgame, handling players leaving, handling the server leaving,
30 // and notifying the user of all of these actions, here.
31 //
32 
33 
34 // ----------------------------------------------------------------------------------------------------------
35 // MULTI ENDGAME DEFINES/VARS
36 //
37 
38 
39 // set when the server/client has ended the game on some notification or error and is waiting for clients to leave
40 #define MULTI_ENDGAME_SERVER_WAIT 5.0f
44 
45 // error/notification codes (taken from parameters to multi_quit_game(...)
49 
50 // for reentrancy problems on standalone
52 
53 // ----------------------------------------------------------------------------------------------------------
54 // MULTI ENDGAME FORWARD DECLARATIONS
55 //
56 
57 // called when a given netgame is about to end completely
59 
60 // throw up a popup with the given notification code and optional winsock code
61 void multi_endgame_popup(int notify_code,int error_code,int wsa_error = -1);
62 
63 // called when server is waiting for clients to disconnect
65 
66 // check to see if we need to be warping out (strange transition possibilities)
68 
69 
70 // ----------------------------------------------------------------------------------------------------------
71 // MULTI ENDGAME FUNCTIONS
72 //
73 
74 // initialize the endgame processor (call when joining/starting a new netgame)
76 {
77  // set this so that the server/client knows he hasn't tried to end the game
80 
81  // reset the timestamp used when server is waiting for all other clients to leave.
83 
84  // initialiaze all endgame notify and error codes
88 
89  // for reentrancy problems in to endgame_process
91 }
92 
93 // process all endgame related events
95 {
97  return;
98 
100 
101  // check to see if we need to be warping out (strange transition possibilities)
103 
104  // if we're the server of the game
106  // if we're not waiting for clients to leave, do nothing
109  return;
110  }
111 
112  // if a popup is already active, do nothing
113  if(popup_active()){
115  return;
116  }
117 
118  // otherwise popup until things are hunky-dory
122  // run networking, etc.
123  game_set_frametime(-1);
125  }
126  } else {
127  popup_till_condition( multi_endgame_server_ok_to_leave , XSTR("&Cancel",645), XSTR("Waiting for clients to disconnect",646));
128  }
129  }
130 
131  // mark myself as not waiting and get out
133  } else {
134  // if we're not waiting to leave the game, do nothing
137  return;
138  }
139 
140  // otherwise, check to see if there is a popup active
141  if(popup_active()){
143  return;
144  }
145 
146  // if not, then we are good to leave
148  }
149 
151 }
152 
153 // if the game has been flagged as ended (ie, its going to be reset)
155 {
157 }
158 
159 // reentrancy check
161 // general quit function, with optional notification, error, and winsock error codes
162 int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
163 {
164  int ret_val,quit_already;
165 
166  // check for reentrancy
167  if(Multi_quit_game){
168  return 0;
169  }
170 
171  // if we're not connected or have not net-player
172  if((Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_CONNECTED)){
173  return 1;
174  }
175 
176  // reentrancy
177  Multi_quit_game = 1;
178 
179  quit_already = 0;
180 
181  // reset my control info so that I don't continually do whacky stuff. This is ugly
182  //player_control_reset_ci( &Player->ci );
183  if ( Game_mode & GM_IN_MISSION ) {
184  memset(&Player->ci, 0, sizeof(Player->ci) );
187  }
188 
189  // CASE 1 - response to a user request
190  // if there is no associated notification or error code, don't override the prompt argument
191  if((err_code == -1) && (notify_code == -1)){
192  // if we're the server and we're already waiting for clients to leave, don't do anything
194  Multi_quit_game = 0;
195  return 0;
196  }
197 
198  // if we're the client and we're already waiting to leave, don't do anythin
200  Multi_quit_game = 0;
201  return 0;
202  }
203 
204  // see if we should be prompting the host for confirmation
205  if((prompt==PROMPT_HOST || prompt==PROMPT_ALL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)){
206  int p_flags;
207 
209  if ( Game_mode & GM_IN_MISSION )
210  p_flags |= PF_RUN_STATE;
211 
212  ret_val = popup(p_flags,2,POPUP_CANCEL,POPUP_OK,XSTR("Warning - quitting will end the game for all players!",647));
213 
214  // check for host cancel
215  if((ret_val == 0) || (ret_val == -1)){
216  Multi_quit_game = 0;
217  return 0;
218  }
219 
220  // set this so that under certain circumstances, we don't call the popup below us as well
221  quit_already = 1;
222  }
223 
224  // see if we should be prompting the client for confirmation
225  if((prompt==PROMPT_CLIENT || prompt==PROMPT_ALL) && !quit_already){
226  ret_val = popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_BODY_BIG,2,POPUP_NO,POPUP_YES,XSTR("Are you sure you want to quit?",648));
227 
228  // check for host cancel
229  if((ret_val == 0) || (ret_val == -1)){
230  Multi_quit_game = 0;
231  return 0;
232  }
233  quit_already = 1;
234  }
235 
236  // if i'm the server of the game, tell all clients that i'm leaving, then wait
239 
240  // set the waiting flag and the waiting timestamp
243  }
244  // if i'm the client, quit now
245  else {
247  }
248  }
249  // CASE 2 - response to an error code or packet from the server
250  // this is the case where we're being forced to quit the game because of some error or other notification
251  else {
252  // if i'm the server, send a packet to the clients telling them that I'm leaving and why
254  // if we're in the debrief state, mark down that the server has left the game
257 
258  // add a message to the chatbox
259  multi_display_chat_msg(XSTR("<Team captains have left>",649),0,0);
260 
261  // set ourselves to be "not quitting"
262  Multi_quit_game = 0;
263 
264  // tell the users, the game has ended
265  send_netgame_end_error_packet(notify_code,err_code);
266  return 0;
267  }
268 
269  send_netgame_end_error_packet(notify_code,err_code);
270 
271  // store the globals
272  Multi_endgame_notify_code = notify_code;
273  Multi_endgame_error_code = err_code;
274  Multi_endgame_wsa_error = wsa_error;
275 
276  // by setting this, multi_endgame_process() will know to check and see if it is ok for us to leave
279  }
280  // if i'm the client, set the error codes and leave the game now
282  // if we're in the debrief state, mark down that the server has left the game
285 
286  // add a message to the chatbox
287  multi_display_chat_msg(XSTR("<The server has ended the game>",650),0,0);
288 
289  // shut our reliable socket to the server down
292 
293  // remove our do-notworking flag
295 
296  Multi_quit_game = 0;
297  return 0;
298  }
299 
300  Multi_endgame_notify_code = notify_code;
301  Multi_endgame_error_code = err_code;
302  Multi_endgame_wsa_error = wsa_error;
303 
304  // by setting this, multi_endgame_process() will know to check and see if it is ok for us to leave
306  }
307  }
308 
309  // unset the reentrancy flag
310  Multi_quit_game = 0;
311 
312  return 1;
313 }
314 
315 
316 // ----------------------------------------------------------------------------------------------------------
317 // MULTI ENDGAME FORWARD DEFINITIONS
318 //
319 
320 // called when a given netgame is about to end completely
322 {
323  int idx;
324 
326 
327  // flush all outgoing io, force all packets through
329 
330  // mark myself as disconnected
333  }
334 
335  /*this is a semi-hack so that if we're the master and we're quitting, we don't get an assert
336 
337  Karajorma - From the looks of things this code actually CAUSES an Int3 and doesn't cause an assert anymore
338  besides if the game is over why are we setting flags on a Player_obj anyway?
339 
340  if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Player_obj != NULL)){
341  Player_obj->flags &= ~(OF_PLAYER_SHIP);
342  obj_set_flags( Player_obj, Player_obj->flags | OF_COULD_BE_PLAYER );
343  }
344  */
345 
346  // shut my socket down (will also let the server know i've received any notifications/error from him)
347  // psnet_rel_close_socket( &(Net_player->reliable_socket) );
348 
349  // 11/18/98 - DB, changed the above to kill all sockets. Its the safest thing to do
350  for(idx=0; idx<MAX_PLAYERS; idx++){
353  }
354 
355  // set the game quitting flag in our local netgame info - this will _insure_ that even if we miss a packet or
356  // there is some sequencing error, the next time through the multi_do_frame() loop, the game will be ended
357  // Netgame.flags |= (NG_FLAG_QUITTING | NG_FLAG_ENDED);
358 
359  // close all open SPX/TCP reliable sockets
361  // do it for all players, since we're leaving anyway.
362  for(idx=0;idx<MAX_PLAYERS;idx++){
363  // 6/25/98 -- MWA delete all players from the game
364 
365  if ( &Net_players[idx] != Net_player ) {
366  delete_player( idx );
367  }
368  }
369  }
370 
371  // if we're currently in the pause state, pop back into gameplay first
374  }
375 
376  // handle game disconnect from FS2NetD (NOTE: must be done *before* standalone is reset!!)
379  }
380 
381  if (Game_mode & GM_STANDALONE_SERVER) {
382  // multi_standalone_quit_game();
384  } else {
386 
387  // if we're in Parallax Online mode, log back in there
389 
390  // if we have an error code, bring up the discon popup
391  if ( ((Multi_endgame_notify_code != -1) || (Multi_endgame_error_code != -1)) && !(Game_mode & GM_STANDALONE_SERVER) ) {
393  }
394  }
395 
396  /*
397  extern CFILE *obj_stream;
398  if(obj_stream != NULL){
399  cfclose(obj_stream);
400  obj_stream = NULL;
401  }
402  */
403 
404  // unload the multiplayer common interface palette
406 
407  // reinitialize endgame stuff
408  // multi_endgame_init();
409 }
410 
411 // throw up a popup with the given notification code and optional winsock code
412 void multi_endgame_popup(int notify_code,int error_code,int wsa_error)
413 {
414  char err_msg[255];
416 
417  // if there is a popup already active, just kill it
418  if(popup_active()){
419  // if there is already a popup active, kill it
421 
422  Int3();
423  } else {
424  // if there is a winsock error code, stick it on the end of the text
425  if(wsa_error != -1){
426  sprintf(err_msg,NOX("WSAERROR : %d\n\n"),wsa_error);
427  flags |= PF_TITLE_RED;
428  } else {
429  strcpy_s(err_msg,"");
430  }
431 
432  // setup the error message string
433  if(notify_code != MULTI_END_NOTIFY_NONE){
434  switch(notify_code){
436  strcat_s(err_msg,XSTR("You have been kicked",651));
437  break;
439  strcat_s(err_msg,XSTR("The server has left the game",652));
440  break;
442  strcat_s(err_msg,XSTR("Your mission file has been rejected by the server",653));
443  break;
445  strcat_s(err_msg,XSTR("The game has ended while you were ingame joining",654));
446  break;
448  strcat_s(err_msg,XSTR("You have waited too long to select a ship",655));
449  break;
451  strcat_s(err_msg,XSTR("You were kicked because mission file xfer failed",998));
452  break;
454  strcat_s(err_msg,XSTR("You were kicked because you do not have the builtin mission",999));
455  strcat_s(err_msg, NOX(" "));
457  break;
459  strcat_s(err_msg,XSTR("You were kicked because you were ingame joining a game that has ended",1000));
460  break;
461  default :
462  Int3();
463  }
464  } else {
465  switch(error_code){
467  strcat_s(err_msg,XSTR("Contact with server has been lost",656));
468  break;
470  strcat_s(err_msg,XSTR("Failed to connect to server on reliable socket",657));
471  break;
473  strcat_s(err_msg,XSTR("Failed to load mission file properly",658));
474  break;
476  strcat_s(err_msg,XSTR("Unable to create ingame join player ship",659));
477  break;
479  strcat_s(err_msg,XSTR("Recevied bogus packet data while ingame joining",660));
480  break;
482  strcat_s(err_msg,XSTR("Server transfer failed (obsolete)",661));
483  break;
485  strcat_s(err_msg,XSTR("Server encountered errors trying to assign players to ships",662));
486  break;
488  strcat_s(err_msg,XSTR("Host has left the game, aborting...",663));
489  break;
491  strcat_s(err_msg,XSTR("There was an error receiving the mission file!",665));
492  break;
494  strcat_s(err_msg,XSTR("The player wings Alpha, Beta, Gamma, and Zeta must have only 1 wave. One of these wings currently has more than 1 wave.", 987));
495  break;
496  // Karajorma - both of these should really be replaced with new strings in strings.tbl but for now this one has much the same meaning
498  strcat_s(err_msg,XSTR("All players from team 1 have left the game", 664));
499  break;
501  strcat_s(err_msg,XSTR("All players from team 2 have left the game", 664));
502  break;
504  strcat_s(err_msg,XSTR("Team captain(s) have left the game, aborting...",664));
505  break;
506  default :
507  Int3();
508  }
509  }
510 
511  // show the popup
512  popup(flags,1,POPUP_OK,err_msg);
513  }
514 }
515 
516 // called when server is waiting for clients to disconnect
518 {
519  int idx;
520 
521  // check to see if our client disconnect timestamp has elapsed
522  if ( Multi_endgame_server_wait_stamp > 0.0f ) {
524  if ( Multi_endgame_server_wait_stamp <= 0.0f ) {
525  return 1;
526  }
527  }
528 
529  // check to see if all clients have disconnected
530  for(idx=0;idx<MAX_PLAYERS;idx++){
531  if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){
532  return 0;
533  }
534  }
535 
536  // all conditions passed
537  return 1;
538 }
539 
540 // check to see if we need to be warping out (strange transition possibilities)
542 {
543  int need_to_warpout = 0;
544 
545  // if we're not in the process of warping out - do nothing
547  return;
548  }
549 
550  // determine if sufficient warping-out conditions exist
551  if((Game_mode & GM_IN_MISSION) && // if i'm still in the mission
552  ((Netgame.game_state == NETGAME_STATE_ENDGAME) || // if the netgame ended
553  (Netgame.game_state == NETGAME_STATE_DEBRIEF)) // if the netgame is now in the debriefing state
554  ) {
555  need_to_warpout = 1;
556  }
557 
558  // if we need to be warping out but are stuck in a dead popup, cancel it
560  // flush all active pushed state
562 
563  // begin the warpout process
565 
566  // if text input mode is active, clear it
568  }
569 }
#define NETINFO_FLAG_WARPING_OUT
Definition: multi.h:618
#define NETGAME_STATE_DEBRIEF
Definition: multi.h:669
#define MULTI_END_NOTIFY_KICKED_INGAME_ENDED
Definition: multi_endgame.h:40
control_info ci
Definition: player.h:126
int flags
Definition: player.h:104
void game_do_state_common(int, int)
Definition: fredstubs.cpp:195
void game_set_frametime(int)
Definition: fredstubs.cpp:196
int Game_mode
Definition: systemvars.cpp:24
int Multi_endgame_processing
int Multi_endgame_client_waiting
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
int Multi_endgame_error_code
int Multi_quit_game
net_player * Net_player
Definition: multi.cpp:94
float flFrametime
Definition: fredstubs.cpp:22
#define MULTI_END_ERROR_TEAM1_EMPTY
Definition: multi_endgame.h:55
#define NETINFO_FLAG_DO_NETWORKING
Definition: multi.h:610
physics_info phys_info
Definition: object.h:157
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
#define MULTI_END_ERROR_INGAME_SHIP
Definition: multi_endgame.h:47
#define MULTI_END_ERROR_NONE
Definition: multi_endgame.h:43
void multi_endgame_check_for_warpout()
void multi_standalone_reset_all()
Definition: multi.cpp:1610
GLclampf f
Definition: Glext.h:7097
#define MULTI_END_NOTIFY_EARLY_END
Definition: multi_endgame.h:36
#define MULTI_END_ERROR_CONTACT_LOST
Definition: multi_endgame.h:44
#define INVALID_SOCKET
Definition: psnet2.h:53
void fs2netd_gameserver_disconnect()
void multi_endgame_popup(int notify_code, int error_code, int wsa_error=-1)
int flags
Definition: multi.h:463
#define Int3()
Definition: pstypes.h:292
void multi_msg_text_flush()
Definition: multi_pmsg.cpp:329
int game_state
Definition: multi.h:498
void multi_endgame_process()
#define MULTI_END_ERROR_HOST_LEFT
Definition: multi_endgame.h:51
int multi_endgame_ending()
void multi_display_chat_msg(const char *msg, int player_index, int add_id)
Definition: multiutil.cpp:2895
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
void send_debrief_event()
Definition: multiutil.cpp:4159
#define MULTI_END_ERROR_CAPTAIN_LEFT
Definition: multi_endgame.h:56
#define MULTI_ENDGAME_SERVER_WAIT
int multi_endgame_server_ok_to_leave()
PSNET_SOCKET_RELIABLE reliable_socket
Definition: multi.h:465
netgame_info Netgame
Definition: multi.cpp:97
#define MULTI_END_NOTIFY_SERVER_LEFT
Definition: multi_endgame.h:34
void gameseq_pop_state()
float Multi_endgame_server_wait_stamp
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void send_netgame_end_error_packet(int notify_code, int err_code)
Definition: multimsgs.cpp:6907
#define MAX_PLAYERS
Definition: pstypes.h:32
#define NETINFO_FLAG_GAME_HOST
Definition: multi.h:603
#define MULTI_END_NOTIFY_FILE_REJECTED
Definition: multi_endgame.h:35
#define MULTI_END_ERROR_LOAD_FAIL
Definition: multi_endgame.h:46
int idx
Definition: multiui.cpp:761
int Multi_endgame_notify_code
#define PROMPT_HOST
Definition: multi_endgame.h:27
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
#define GM_IN_MISSION
Definition: systemvars.h:23
matrix orient
Definition: object.h:153
#define NOX(s)
Definition: pstypes.h:473
#define GM_STANDALONE_SERVER
Definition: systemvars.h:27
#define MULTI_END_NOTIFY_NONE
Definition: multi_endgame.h:32
GLbitfield flags
Definition: Glext.h:6722
int afterburner_stop
Definition: physics.h:117
#define MULTI_END_ERROR_INGAME_BOGUS
Definition: multi_endgame.h:48
#define NETINFO_FLAG_CONNECTED
Definition: multi.h:598
void physics_read_flying_controls(matrix *orient, physics_info *pi, control_info *ci, float sim_time, vec3d *wash_rot)
Definition: physics.cpp:449
#define MULTI_END_NOTIFY_INGAME_TIMEOUT
Definition: multi_endgame.h:37
int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
#define MULTI_END_ERROR_STRANS_FAIL
Definition: multi_endgame.h:49
void multi_endgame_cleanup()
#define strcat_s(...)
Definition: safe_strings.h:68
void multi_endgame_init()
void delete_player(int player_num, int kicked_reason)
Definition: multiutil.cpp:862
#define MULTI_CONNECTED(np)
Definition: multi.h:136
#define MULTI_END_NOTIFY_KICKED_CANT_XFER
Definition: multi_endgame.h:39
player * Player
void multi_handle_state_special()
Definition: multiutil.cpp:2253
#define MULTI_END_NOTIFY_KICKED_BAD_XFER
Definition: multi_endgame.h:38
#define NETINFO_FLAG_RESPAWNING
Definition: multi.h:609
#define MULTI_END_ERROR_SHIP_ASSIGN
Definition: multi_endgame.h:50
#define PROMPT_CLIENT
Definition: multi_endgame.h:28
#define PROMPT_ALL
Definition: multi_endgame.h:29
#define MULTI_END_ERROR_WAVE_COUNT
Definition: multi_endgame.h:53
#define MULTI_END_NOTIFY_KICKED
Definition: multi_endgame.h:33
#define NETGAME_STATE_ENDGAME
Definition: multi.h:671
int Multi_endgame_wsa_error
object * Player_obj
Definition: object.cpp:56
#define PLAYER_FLAGS_IS_MULTI
Definition: player.h:42
void multi_common_unload_palette()
Definition: multiui.cpp:438
void multi_io_send_buffered_packets()
Definition: multimsgs.cpp:544
void psnet_rel_close_socket(PSNET_SOCKET_RELIABLE *sockp)
Definition: psnet2.cpp:1008
int Multi_endgame_server_waiting
#define MULTI_END_ERROR_TEAM0_EMPTY
Definition: multi_endgame.h:54
void send_leave_game_packet(short player_id, int kicked_reason, net_player *target)
Definition: multimsgs.cpp:1680
#define MULTI_IS_TRACKER_GAME
Definition: multi.h:146
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
void gameseq_post_event(int event)
int popupdead_is_active()
Definition: popupdead.cpp:538
void multi_debrief_server_left()
Definition: multiui.cpp:8888
#define MULTI_END_ERROR_CONNECT_FAIL
Definition: multi_endgame.h:45
#define strcpy_s(...)
Definition: safe_strings.h:67
#define MULTI_END_ERROR_XFER_FAIL
Definition: multi_endgame.h:52