1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: d_clisrv.c 1542 2020-08-22 02:35:24Z wesleyjohnson $
5 //
6 // Copyright (C) 1998-2016 by DooM Legacy Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 //
19 // $Log: d_clisrv.c,v $
20 // Revision 1.47  2004/07/27 08:19:34  exl
21 // New fmod, fs functions, bugfix or 2, patrol nodes
22 //
23 // Revision 1.46  2004/04/20 00:34:26  andyp
24 // Linux compilation fixes and string cleanups
25 //
26 // Revision 1.45  2003/11/22 00:22:08  darkwolf95
27 // get rid of FS hud pics on level exit and new game, also added exl's fix for clearing hub variables on new game
28 //
29 // Revision 1.44  2003/05/04 04:30:30  sburke
30 // Ensure that big-endian machines encode/decode network packets as little-endian.
31 //
32 // Revision 1.43  2003/03/22 22:35:59  hurdler
33 //
34 // Revision 1.42  2002/09/27 16:40:08  tonyd
35 // First commit of acbot
36 //
37 // Revision 1.41  2001/08/20 20:40:39  metzgermeister
38 // Revision 1.40  2001/06/10 21:16:01  bpereira
39 //
40 // Revision 1.39  2001/05/16 17:12:52  crashrl
41 // Added md5-sum support, removed recursiv wad search
42 //
43 // Revision 1.38  2001/05/14 19:02:57  metzgermeister
44 //   * Fixed floor not moving up with player on E3M1
45 //   * Fixed crash due to oversized string in screen message ... bad bug!
46 //   * Corrected some typos
47 //   * fixed sound bug in SDL
48 //
49 // Revision 1.37  2001/04/27 13:32:13  bpereira
50 // Revision 1.36  2001/04/01 17:35:06  bpereira
51 // Revision 1.35  2001/03/30 17:12:49  bpereira
52 // Revision 1.34  2001/03/03 06:17:33  bpereira
53 // Revision 1.33  2001/02/24 13:35:19  bpereira
54 // Revision 1.32  2001/02/10 12:27:13  bpereira
55 //
56 // Revision 1.31  2001/01/25 22:15:41  bpereira
57 // added heretic support
58 //
59 // Revision 1.30  2000/11/11 13:59:45  bpereira
60 //
61 // Revision 1.29  2000/11/02 17:50:06  stroggonmeth
62 // Big 3Dfloors & FraggleScript commit!!
63 //
64 // Revision 1.28  2000/10/22 00:20:53  hurdler
65 // Updated for the latest master server code
66 //
67 // Revision 1.27  2000/10/21 23:21:56  hurdler
68 // Revision 1.26  2000/10/21 08:43:28  bpereira
69 //
70 // Revision 1.25  2000/10/17 10:09:27  hurdler
71 // Update master server code for easy connect from menu
72 //
73 // Revision 1.24  2000/10/16 20:02:28  bpereira
74 // Revision 1.23  2000/10/08 13:29:59  bpereira
75 // Revision 1.22  2000/10/01 10:18:16  bpereira
76 // Revision 1.21  2000/09/28 20:57:14  bpereira
77 // Revision 1.20  2000/09/15 19:49:21  bpereira
78 // Revision 1.19  2000/09/10 10:37:28  metzgermeister
79 // Revision 1.18  2000/09/01 19:34:37  bpereira
80 // Revision 1.17  2000/08/31 14:30:55  bpereira
81 //
82 // Revision 1.16  2000/08/21 11:06:43  hurdler
83 // Add ping and some fixes
84 //
85 // Revision 1.15  2000/08/16 15:44:18  hurdler
86 // update master server code
87 //
88 // Revision 1.14  2000/08/16 14:10:01  hurdler
89 // add master server code
90 //
91 // Revision 1.13  2000/08/11 19:10:13  metzgermeister
92 //
93 // Revision 1.12  2000/08/11 12:25:23  hurdler
94 // latest changes for v1.30
95 //
96 // Revision 1.11  2000/08/03 17:57:41  bpereira
97 // Revision 1.10  2000/04/30 10:30:10  bpereira
98 // Revision 1.9  2000/04/24 20:24:38  bpereira
99 // Revision 1.8  2000/04/16 18:38:06  bpereira
100 //
101 // Revision 1.7  2000/04/04 00:32:45  stroggonmeth
102 // Initial Boom compatability plus few misc changes all around.
103 //
104 // Revision 1.6  2000/03/29 19:39:48  bpereira
105 //
106 // Revision 1.5  2000/03/08 17:02:42  hurdler
107 // fix the joiningame problem under Linux
108 //
109 // Revision 1.4  2000/03/06 16:51:08  hurdler
110 // hack for OpenGL / Open Entry problem
111 //
112 // Revision 1.3  2000/02/27 16:30:28  hurdler
113 // dead player bug fix + add allowmlook <yes|no>
114 //
115 // Revision 1.2  2000/02/27 00:42:10  hurdler
116 // Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
117 // Initial import into CVS (v1.29 pr3)
118 //
119 //
120 // DESCRIPTION:
121 //      DOOM Network game communication and protocol,
122 //      High Level Client / Server communications and functions.
123 //
124 //-----------------------------------------------------------------------------
125 
126 
127 #include <time.h>
128 #include <unistd.h>
129 
130 #include "doomincl.h"
131 #include "doomstat.h"
132 #include "d_clisrv.h"
133 #include "command.h"
134 #include "i_net.h"
135 #include "i_tcp.h"
136 #include "i_system.h"
137 #include "i_video.h"
138 #include "v_video.h"
139 #include "d_net.h"
140 #include "d_netcmd.h"
141 #include "d_netfil.h"
142 #include "d_main.h"
143 #include "g_game.h"
144 #include "hu_stuff.h"
145 #include "keys.h"
146 #include "m_argv.h"
147 #include "m_menu.h"
148 #include "console.h"
149 #include "byteptr.h"
150 
151 #include "p_saveg.h"
152 #include "p_setup.h"
153 #include "z_zone.h"
154 #include "p_tick.h"
155 #include "p_local.h"
156 #include "m_misc.h"
157 #include "am_map.h"
158 #include "m_random.h"
159 #include "mserv.h"
160 #include "t_script.h"
161 
162 #include "b_game.h"	//added by AC for acbot
163 #include "r_things.h"
164   // skins
165 #include "g_input.h"
166   // gamecontrol
167 #include "s_sound.h"
168   // StartSound
169 #include "d_items.h"
170   // NUMINVENTORYSLOTS, NUMAMMO
171 
172 
173 //
174 // NETWORKING
175 //
176 // gametic is the tic about to (or currently being) run
177 // maketic is the tic that hasn't had control made for it yet
178 // server:
179 //   nettics is the tic for each node
180 //   next_tic_send is the lowest value of nettics
181 // client:
182 //   cl_need_tic is the tic needed by the client for run the game
183 //   next_tic_send is used to optimize a condition
184 // normaly maketic>=gametic>0,
185 
186 // The addition of wait messages should be transparent to previous network
187 // versions.
188 const int  NETWORK_VERSION = 26; // separate version number for network protocol (obsolete)
189 
190 
191 #define JOININGAME
192 
193 
194 #if NUM_SERVERTIC_CMD < BACKUPTICS
195 # error Not enough NUM_SERVERTIC_CMD
196 #endif
197 
198 // Used to signal network errors to higher level functions.
199 // Beware that server may also have a client.
200 typedef enum {
201    NETS_idle,
202    NETS_fatal,
203    NETS_shutdown,
204 // Have network.
205    NETS_open,      // Normal network.
206    NETS_internal,  // Self server network.
207 // Client
208    NETS_no_server, // Client lost the server.
209    NETS_connecting,// Client connecting to the server
210    NETS_active     // Client has server connection.
211 } network_state_e;
212 
213 #ifdef DEBUG_WINDOWED
214 static network_state_e  network_state = NETS_idle;  // easier debugging
215 #else
216 static byte  network_state = NETS_idle;  // network_state_e
217 #endif
218 static byte  quit_netgame_status = 0;  // to avoid repeating shutdown
219 static byte  wait_netplayer = 0;
220 
221 #define PREDICTIONQUEUE         BACKUPTICS
222 #define PREDICTIONMASK          (PREDICTIONQUEUE-1)
223 
224 // Server state
225 boolean  server = true; // false when Client connected to other server
226 boolean  serverrunning = false;
227 byte     serverplayer = 255;  // 255= no server player (same as -1)
228 
229 // Server specific vars.
230 // player=255 when unused
231 // nnode =255 when unused
232 // nnode_state[] = NOS_idle, when net node is unused
233 // The netnodes are counted, 0..31
234 static byte  player_to_nnode[MAXPLAYERS];
235 static byte  player_pind[MAXPLAYERS];
236 static byte  num_player_used = 0;
237 static byte  num_join_waiting_players = 0;
238 #ifdef WAIT_GAME_START_INTERMISSION
239 byte  num_wait_game_start = 0;  // waiting until next game
240 #endif
241 
242 
243 // Server net node state for
244 // tracking client nodes.
245 typedef enum {
246   NOS_idle,  // node is unused
247   NOS_fatal, // something bad
248   NOS_shutdown,  // node is shutting down
249   NOS_invalid,   // invalid node
250 // Recognized nodes.
251   NOS_recognized,
252 // node during join procedure
253   NOS_join,         // node join procedure
254   NOS_join_file,    // downloading file
255   NOS_join_savegame,// downloading savegame
256   NOS_join_sg_loaded,  // downloading done
257   NOS_join_timeout,
258 // node with a player
259   NOS_client,
260 // waiting players
261   NOS_wait_game_start, // waiting for next game start
262 // repair a client
263   NOS_repair,          // node is being repaired
264   NOS_repair_player,   // update player
265   NOS_repair_pl_done,  // player update done
266   NOS_repair_savegame, // downloading savegame
267   NOS_repair_sg_loaded,   // downloading done
268   NOS_repair_timeout,
269 // node normal play
270   NOS_active,
271 // FOR CLIENT USE ONLY.  Server must not use for client state.
272   NOS_server,   // client sees server at cl_servernode
273   NOS_internal  // client sees server on self
274 } nnode_state_e;
275 
276 // [WDJ] Used to be OR with nnode_to_player to indicate DRONE node.
277 // No longer done that way to keep player number clean, as it is used for indexing
278 // and the DRONE bit conflicted with 255=idle player.
279 // #define DRONE               0x80    // bit set in consoleplayer
280 // DRONE has playerpernode=0
281 
282 // Server: net node state of clients.
283 // Node numbers seen by server are different than those seen by clients (determined by connection order).
284 // Index by server space nnode numbers.
285 #ifdef DEBUG_WINDOWED
286 static nnode_state_e   nnode_state[MAXNETNODES];  // easier debugging
287 #else
288 static byte     nnode_state[MAXNETNODES];  // nnode_state_e
289 #endif
290 // Index by pind, [0]=main player [1]=splitscreen player
291 static byte     nnode_to_player[2][MAXNETNODES];  // 255= unused
292 static byte     playerpernode[MAXNETNODES]; // used specialy for splitscreen
293 static byte     join_waiting[MAXNETNODES];  // num of players waiting to join
294 static byte     consistency_faults[MAXNETNODES];
295 static tic_t    nettics[MAXNETNODES];     // what tic the client have received
296 static tic_t    nextsend_tic[MAXNETNODES]; // what server sent to client
297 
298 static tic_t    next_tic_send;     // min of the nettics
299 static tic_t    next_tic_clear=0;  // clear next_tic_clear to next_tic_send
300 static tic_t    maketic;
301 #ifdef CLIENTPREDICTION2
302 tic_t localgametic;
303 #endif
304 
305 // Client specific.
306 
307 // Client state
308 typedef enum {
309    CLM_idle,
310    CLM_fatal,
311    CLM_searching,
312    CLM_server_files,
313    CLM_download_req,
314    CLM_download_files,
315    CLM_askjoin,
316    CLM_wait_join_response,
317    CLM_download_savegame,
318    CLM_download_done,
319    CLM_wait_game_start,  // ready but must wait for next game start
320    CLM_connected
321 } cl_mode_t;
322 
323 #ifdef DEBUG_WINDOWED
324 static cl_mode_t  cl_mode = CLM_idle;  // easier debugging
325 #else
326 static byte     cl_mode = CLM_idle;  // cl_mode_t
327 #endif
328 
329 boolean         cl_drone; // client displays, no commands
330 static byte     cl_nnode; // net node for this client, assigned by server (server nnode space)
331 static byte     cl_error_status = 0;  // repair
332 static boolean  cl_packetmissed;
333 static tic_t    cl_need_tic;
334 static tic_t    cl_prev_tic = 0;  // client tests once per tic
335 
336 // Client view of server :
337 //   Node numbers on client are not same as those on server, each has own independent nnode space.
338 //   Server net node, 251=none (to not match invalid node)
339 byte            cl_servernode = 251;  // in client nnode space, never let server use this
340 static byte     cl_server_state = NOS_idle; // nnode_state_e, client view of server
341 
342 // Text buffer for textcmds.
343 // One extra byte at end for 0 termination, to protect against malicious use.
344 // Use textbuf_t from textcmdpak
345 
346 // Client maketic
347 // [0]=main player [1]=splitscreen player
348 byte              localplayer[2] = {255,255};  // client player number
349 static ticcmd_t   localcmds[2];
350 static textbuf_t  localtextcmd[2];
351 
352 // engine
353 // Server packet state
354 static uint32_t ticcmd_player_mask = 0;  // one bit for each player that sends ticcmd, no bots
355 static byte     num_ticcmd_per_tic = 0;  // num in ticcmd_pid
356 static byte     ticcmd_pid[MAXPLAYERS];  // pid in order of ticcmd in packet
357 static byte     update_player_count_request = 0;  // for XNetCmd, as the list is in use during execution
358 
359 // NetCmd and TextCmd store
360 // Index for netcmds and textcmds
361 #define BTIC_INDEX( tic )  ((tic)%BACKUPTICS)
362 // Index using BTIC_INDEX
363 static byte     netcmd_tic_hash[BACKUPTICS];  // tic hash for the BACKUPTIC
364 static byte     netseq[BACKUPTICS];   // bit per tic packet seq, ready=0xFF
365 ticcmd_t        netcmds[BACKUPTICS][MAXPLAYERS];
366 
367 // [WDJ] Combined textcmd buffer for all players, and server.
368 // No apparant reason to keep separate buffers at this point.
369 // MAX_TEXTCMD_BUFF must be enough for map command, but less than max packet size.
370 #if defined(SMIF_PC_DOS) || defined(DOSNET_SUPPORT)
371   // may have small packet limits
372   // 32*15 - 3
373 # define MAX_TEXTCMD_BUFF       477
374 #else
375   // 32*30 - 3
376 # define MAX_TEXTCMD_BUFF       957
377 #endif
378 typedef struct {
379    uint16_t  len;  // 0..MAX_TEXTCMD_BUFF
380    byte      buff[MAX_TEXTCMD_BUFF+1];  // format as array of textcmd_item_t
381              // Format: pn, len, text[MAXTEXTCMD]
382 } textcmdbuff_t;
383 static textcmdbuff_t  textcmdbuff[BACKUPTICS];
384 
385 static int16_t    consistency[BACKUPTICS];
386 
387 
388 
389 consvar_t cv_playdemospeed  = {"playdemospeed","0",CV_VALUE,CV_Unsigned};
390 
391 consvar_t cv_server1 = { "server1", "192.168.1.255", CV_STRING|CV_SAVE, NULL };
392 consvar_t cv_server2 = { "server2", "", CV_STRING|CV_SAVE, NULL };
393 consvar_t cv_server3 = { "server3", "", CV_STRING|CV_SAVE, NULL };
394 
395 CV_PossibleValue_t download_cons_t[] = {{0,"No Download"},{1,"Allowed"},{0,NULL}};
396 consvar_t cv_download_files = {"download_files"  ,"1", CV_SAVE, download_cons_t};
397 consvar_t cv_SV_download_files = {"sv_download_files"  ,"1", CV_SAVE, download_cons_t};
398 consvar_t cv_download_savegame = {"download_savegame"  ,"1", CV_SAVE, download_cons_t};
399 consvar_t cv_SV_download_savegame = {"sv_download_savegame"  ,"1", CV_SAVE, download_cons_t};
400 
401 CV_PossibleValue_t netrepair_cons_t[] = {{0,"None"},{1,"Minimal"},{2,"Medium"},{3,"Aggressive"},{0,NULL}};
402 consvar_t cv_netrepair = {"netrepair","2", CV_SAVE, netrepair_cons_t};
403 consvar_t cv_SV_netrepair = {"sv_netrepair","2", CV_SAVE, netrepair_cons_t};
404 
405 // consistency check, index by cv_SV_netrepair
406 static byte consistency_limit_fatal[4] = { 1, 2, 5, 8 };
407 static byte consistency_sg_bit[4]    = { 0, 0, 0x04, 0x44 };  // bit on when should req savegame
408 
409 
410 
411 // some software don't support largest packet
412 // (original sersetup, not exactly, but the probability of sending a packet
413 // of 512 octet is like 0.1)
414 uint16_t  software_MAXPACKETLENGTH;
415 
416 // Align to 4 byte
417 #define ALIGN4(p) (byte *)(((uintptr_t)(p) + 3) & ~0x03)
418 
419 // Special unaligned types for network packets.
420 // Detect which machines can do unaligned read and write, with LSB first.
421 #if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__)
422   # define UNALIGNED_INT_RW
423 #endif
424 #if defined(__ia64__) && defined(__GNUC__) && (__GNUC__ >= 3) && ! defined(__BIG_ENDIAN__)
425   # define UNALIGNED_INT_RW
426 #endif
427 #if defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED) && ! defined(__BIG_ENDIAN__)
428   # define UNALIGNED_INT_RW
429 #endif
430 
431 static inline
write_N16(N16_t * vf,uint16_t val)432 void  write_N16( N16_t * vf, uint16_t val )
433 {
434     // LSB first
435 #if defined(UNALIGNED_INT_RW)
436     *((uint16_t*)vf) = val;
437 #else
438     vf->b[0] = val;
439     vf->b[1] = val>>8;
440 #endif
441 }
442 
443 static inline
read_N16(N16_t * vf)444 uint16_t  read_N16( N16_t * vf )
445 {
446     // LSB first
447 #if defined(UNALIGNED_INT_RW)
448     return *((uint16_t*)vf);
449 #else
450     return (((uint16_t)(vf->b[1]))<<8) | vf->b[0];
451 #endif
452 }
453 
454 static inline
write_N32(N32_t * vf,uint32_t val)455 void  write_N32( N32_t * vf, uint32_t val )
456 {
457     // LSB first
458 #if defined(UNALIGNED_INT_RW)
459     *((uint32_t*)vf) = val;
460 #else
461     vf->b[0] = val;
462     vf->b[1] = val>>8;
463     vf->b[2] = val>>16;
464     vf->b[3] = val>>24;
465 #endif
466 }
467 
468 static inline
read_N32(N32_t * vf)469 uint32_t  read_N32( N32_t * vf )
470 {
471     // LSB first
472 #if defined(UNALIGNED_INT_RW)
473     return *((uint32_t*)vf);
474 #else
475     return (((((((uint32_t)(vf->b[3]))<<8) | vf->b[2])<<8) | vf->b[1])<<8) | vf->b[0];
476 #endif
477 }
478 
479 
480 // Handle errors from HSendPacket consistently.
generic_network_error_handler(byte errcode,const char * who)481 static void  generic_network_error_handler( byte errcode, const char * who )
482 {
483     if( errcode == NE_not_netgame )  return;  // known problem during join
484     if( errcode >= NE_fail )
485         network_error_print( errcode, who );
486 }
487 
btic_hash(tic_t tic)488 static byte btic_hash( tic_t tic )
489 {
490     // Overlap with the BTIC_INDEX (tic % BACKUPTICS) is wasted.
491     return (byte) (tic >> 4);
492 }
493 
494 // By Client, Server
ExpandTics(int low)495 int ExpandTics (int low)
496 {
497     int delta;
498 
499     delta = low - (maketic&0xff);
500 
501     if (delta >= -64 && delta <= 64)
502         return (maketic&~0xff) + low;
503     if (delta > 64)
504         return (maketic&~0xff) - 256 + low;
505     if (delta < -64)
506         return (maketic&~0xff) + 256 + low;
507 #ifdef PARANOIA
508     I_SoftError ("ExpandTics: strange value %i at maketic %i\n", low, maketic);
509 #endif
510     return 0;
511 }
512 
D_Clear_ticcmd(int tic)513 static void D_Clear_ticcmd(int tic)
514 {
515     int i;
516     int btic = BTIC_INDEX( tic );
517 
518     netcmd_tic_hash[btic] = 0;
519     netseq[btic] = 0;
520 
521     for(i=0;i<MAXPLAYERS;i++)
522     {
523 #ifdef TICCMD_148
524         netcmds[btic][i].ticflags = 0; //  clear TC_received;
525 #else
526         netcmds[btic][i].angleturn = 0; //&= ~TICCMD_RECEIVED;
527 #endif
528     }
529     textcmdbuff[btic].len = 0;  // all players
530     DEBFILE(va("Clear tic %5d [%2d]\n", tic, btic));
531 }
532 
533 
534 // -----------------------------------------------------------------
535 //  Some extra data function for handle textcmd buffer
536 // -----------------------------------------------------------------
537 
538 // --- Text command
539 // Client NetXCmd: XD_NAMEANDCOLOR, XD_WEAPONPREF, XD_USEARTIFACT, XD_SAY, XD_PAUSE
540 // Server NetXCmd: XD_KICK, XD_ADDPLAYER, XD_ADDBOT,
541 //    XD_MAP, XD_EXITLEVEL, XD_LOADGAME, XD_SAVEGAME
542 
543 static void net_textcmd_handler( byte nnode );
544 static void update_player_state( byte pn, byte new_player_state );
545 static void update_player_counts(void);
546 
547 // NetXCmd indirection.
548 static void (*netxcmd_func[MAXNETXCMD]) (xcmd_t * xc);
549 
Register_NetXCmd(netxcmd_e cmd_id,void (* cmd_f)(xcmd_t * xc))550 void Register_NetXCmd(netxcmd_e cmd_id, void (*cmd_f) (xcmd_t * xc))
551 {
552 #ifdef PARANOIA
553    if(cmd_id >= MAXNETXCMD)
554       I_Error("NetXCmd id %d exceeds defined range", cmd_id);
555    if(netxcmd_func[cmd_id]!=0)
556       I_Error("NetXCmd id %d already registered", cmd_id);
557 #endif
558    netxcmd_func[cmd_id] = cmd_f;
559 }
560 
561 // [WDJ] Ver 1.48.
562 // Server NetXCmd use a server textcmd channel, that bypasses the localtextcmd.
563 // This is necessary because of bots, which must issue textcmds from the server.
564 
565 // The server textcmd are appended to the textcmd buffers using SERVER_PID.
566 // This allows some checking for bogus server textcmd.
567 // During demo playback, server textcmd on [0] must also be kept open.
568 // The server NetXCmd do not use the client_pn, so either will technically work.
569 
570 // Server NetXCmd need to transit the network logic, even when there
571 // is no server player. This used to be done by unexplained kludges.
572 // A server pind = 2, is used for routing.
573 
574 // The NetXCmd must be executed in all clients during a specific gametic.
575 // The current system has all movement commands and NetXCmd for one tick
576 // in the servertick message.  Once it is received the client game tick can advance.
577 // In Ver 1.48, the servertick message can be extended to several packets, when needed.
578 
579 // Command sent over text cmd channel.  Default as main player.
580 //  cmd_id :  X command, XD_
581 //  param : parameter strings
582 //  param_len : number of parameter strings
Send_NetXCmd(byte cmd_id,void * param,int param_len)583 void Send_NetXCmd(byte cmd_id, void *param, int param_len)
584 {
585     byte pind = (localplayer[0] < MAXPLAYERS)? 0 : 1;  // main player default
586     Send_NetXCmd_pind( cmd_id, param, param_len, pind );
587 }
588 
589 // Client
590 // Command sent over text cmd channel.
591 //  cmd_id :  X command, XD_
592 //  param : parameter strings
593 //  param_len : number of parameter strings
594 //  pind : player index, [0]=main player, [1]=splitscreen player
Send_NetXCmd_pind(byte cmd_id,void * param,int param_len,byte pind)595 void Send_NetXCmd_pind( byte cmd_id, void *param, int param_len, byte pind )
596 {
597    if(demoplayback)
598        return;
599 
600    // Save the NetXCmd in a localtextcmd buffer.
601    textbuf_t * ltcbp = &localtextcmd[pind];
602    int textlen = ltcbp->len;
603    if( (textlen + 1 + param_len) > MAXTEXTCMD)  // with XD_ and param
604    {
605 #ifdef PARANOIA
606        I_SoftError("Net command exceeds buffer: pind=%d  netcmd=%d  netcmdlen=%d  total=%d\n",
607                    pind, cmd_id, param_len, (textlen + 1 + param_len));
608 #else
609        GenPrintf(EMSG_warn, "\2Net Command exceeds buffer: pind=%d  netcmd %d  netcmdlen=%d  total=%d\n",
610                    pind, cmd_id, param_len, (textlen + 1 + param_len));
611 #endif
612        return;
613    }
614 
615    // Append to player text commands.
616    // First byte is the cmd, followed by its parameters (binary or string).
617    ltcbp->text[textlen++] = cmd_id; // XD_
618    if(param && param_len)
619    {
620        memcpy(&ltcbp->text[textlen], param, param_len);
621        textlen += param_len;
622    }
623    ltcbp->len = textlen;
624 }
625 
626 // By Server or Client, routing determined by textcmd_pind.
627 //  cmd_id :  X command, XD_
628 //  param : parameter strings
629 //  param_len : number of parameter strings
630 //  textcmd_pind : the textcmd channel to use
631 //  pn : player textcmd dest, when textcmd_pind is 2
Send_NetXCmd_auto(byte cmd_id,void * param,int param_len,byte textcmd_pind,byte pn)632 void Send_NetXCmd_auto( byte cmd_id, void *param, int param_len, byte textcmd_pind, byte pn )
633 {
634     // Client on server can just as well use server channel too,
635     // as long as textcmd ends up in correct textcmd channel.
636     if( server || (textcmd_pind >= 2) || (pn == SERVER_PID) )  // routing
637     {
638         if( server )
639         {
640             // Sending NetXCmd using server channel.
641             SV_Send_NetXCmd_pn( cmd_id, param, param_len, pn );
642         }
643     }
644     else
645     {
646         // Clients send using their localtextcmd[pind].
647         Send_NetXCmd_pind( cmd_id, param, param_len, textcmd_pind );
648     }
649 }
650 
651 // NetXCmd as server, always SERVER_PID.
SV_Send_NetXCmd(byte cmd_id,void * param,int param_len)652 void  SV_Send_NetXCmd( byte cmd_id, void *param, int param_len )
653 {
654     SV_Send_NetXCmd_pn( cmd_id, param, param_len, SERVER_PID );
655 }
656 
657 // NetXCmd as server, with 2 parameters.
658 static
SV_Send_NetXCmd_p2(byte cmd_id,byte param1,byte param2)659 void SV_Send_NetXCmd_p2( byte cmd_id, byte param1, byte param2 )
660 {
661     byte buf[3];
662 
663     buf[0] = param1;
664     buf[1] = param2;
665     SV_Send_NetXCmd( cmd_id, &buf, 2 );  // always server
666 }
667 
668 // By Server, directly to server.
669 // Command sent over server text cmd channel
670 //  cmd_id :  X command, XD_
671 //  param : parameter strings
672 //  param_len : number of parameter strings
673 //  pn : to textcmd channel, by player pid, or SERVER_PID
674 //       Server uses SERVER_PID, but bots use their player pid.
SV_Send_NetXCmd_pn(byte cmd_id,void * param,int param_len,byte pn)675 void SV_Send_NetXCmd_pn( byte cmd_id, void *param, int param_len, byte pn )
676 {
677     textcmd_item_t * ip;
678 
679     // [WDJ] Server sends NetXCmd to self, even without serverplayer.
680     // Ver 1.48 PT_TEXTCMD format puts the pn into the packet.
681 
682     // Make a textcmd packet,
683     // to use existing logic for placing into correct textcmd buffers.
684     ip = & netbuffer->u.textcmdpak.textitem;
685     // Header
686     ip->pn = pn;  // server or bot
687 
688     // First byte is the cmd, followed by its parameters (binary or string).
689     ip->textbuf.text[0] = cmd_id;
690     if(param && param_len)
691     {
692        memcpy(&ip->textbuf.text[1], param, param_len);
693     }
694     ip->textbuf.len = 1 + param_len;
695 
696     netbuffer->packettype = PT_TEXTCMD;
697     netbuffer->u.textcmdpak.num_textitem = 1;
698 #if 1
699     // Give it directly to handler.
700     net_textcmd_handler( 0 );
701 #else
702     // Send it through bounce back buffer,
703     int  bufsize = offsetof(textcmd_pak_t, textitem) + sizeof_textcmd_item_t(ip->textbuf.len);
704     HSendPacket(0, SP_reliable|SP_queue|SP_error_handler, 0, bufsize );  // lost on failure
705 #endif
706 }
707 
708 // [WDJ] Server also needs to send NetXCmd, even without serverplayer.
709 // That is now done by a separate channel, sent separately.
710 
711 // By Client
712 // Send accumulated client textcmd to server.
713 // Server textcmd is sent separate.
714 // Called by NetUpdate
Send_localtextcmd(void)715 static void Send_localtextcmd( void )
716 {
717     textcmd_item_t * ip;
718     byte pind;
719     byte num_textcmd;
720 
721     // How this used to work is a mystery.
722     if( ! ((cl_mode == CLM_connected) && (network_state >= NETS_open)) )
723         goto clear_buffer;
724 
725     // Send textcmd of main player, and splitscreen player, in one packet.
726     num_textcmd = 0;  // currenly only need 2
727     ip = & netbuffer->u.textcmdpak.textitem;
728     for( pind=0; pind<2; pind++)
729     {
730         // No test for playeringame, so that quit message is not blocked.
731         textbuf_t * ltcp = &localtextcmd[pind];  // local textcmd
732         int tc_len = ltcp->len;  // text len
733         if( tc_len == 0 )  continue;
734 
735         // Header
736         ip->pn = localplayer[pind];
737         memcpy(&ip->textbuf, ltcp, sizeof_textbuf_t(tc_len) );  // len, text
738         // no 0 term on text
739         ip = (textcmd_item_t*)((byte*)ip + sizeof_textcmd_item_t(tc_len) ); // pn, len, text
740         num_textcmd ++;
741     }
742     if( num_textcmd == 0 )
743         return;  // nothing to send
744 
745     netbuffer->packettype = PT_TEXTCMD;
746     netbuffer->u.textcmdpak.num_textitem = num_textcmd;
747     int  bufsize = ((byte*)ip) - ((byte*)& netbuffer->u);
748     byte errcode = HSendPacket( cl_servernode, SP_reliable, 0, bufsize ); // send can fail for some reasons...
749     if( errcode >= NE_fail )
750         return;  // retry later
751 
752     // all extra data has been sent
753 
754     // Clear NetXCmd that would overflow the buffers.
755 clear_buffer:
756     localtextcmd[0].len = 0;
757     localtextcmd[1].len = 0;
758     return;
759 }
760 
761 
762 #define SERVER_TIC_BASE_SIZE offsetof(netbuffer_t, u.serverpak.cmds[0])
763 
764 
765 // To keep using tic size check code until tic format is updated.
766 #define CHECK_TIC_SIZE
767 
768 // By Server
769 // PT_TEXTCMD
770 //   nnode : the network client
771 // Called by Net_Packet_Handler
net_textcmd_handler(byte nnode)772 static void net_textcmd_handler( byte nnode )
773 {
774     textcmd_item_t * ip = & netbuffer->u.textcmdpak.textitem;
775     textcmdbuff_t  * tcbuf;
776     unsigned int itc_len;  // length of text in packet
777     unsigned int buflen; // length of text in storage
778     int btic;
779 #ifdef CHECK_TIC_SIZE
780     int tc_limit;  // Max size of existing textcmd that can be included with this textcmd.
781 #endif
782     tic_t tic;
783     byte num_textitem, pn;
784 
785     // Handle NetXCmd that come from clients, and some from the server.
786     // Server textcmd are sent with pn==SERVER_PID, and they must always go through.
787     // The server places them into tick messages here, which are sent to all clients,
788     // so even if placement is arbitrary here, all clients will execute them uniformly.
789 
790 #ifdef CHECK_TIC_SIZE
791 #else
792     // [WDJ] No longer necessary to check if tic message is too large, as Send_tic
793     // will handle that problem.
794 
795     // All textcmd go into the current maketic, until the storage fills up.
796 #endif
797 
798     num_textitem = netbuffer->u.textcmdpak.num_textitem;
799     if( num_textitem > 3 )  // currently only need 2
800         goto drop_packet;  // corrupt packet
801 
802     while( num_textitem-- > 0 )
803     {
804         // Detect corrupt packets, limit decode to netbuffer.
805         // Only 2 pind, so only 2 textcmd_item, yet.
806         if( ((byte*)ip) > (((byte*)& netbuffer->u.textcmdpak.textitem) + (2 * sizeof_textcmd_item_t(MAXTEXTCMD+1))) )
807             goto drop_packet; // corrupt packet
808 
809         // incoming length
810         itc_len = sizeof_textcmd_item_t( ip->textbuf.len );
811 
812         // Do not trust the network, or the clients.
813         pn = ip->pn;
814         if( pn == SERVER_PID )
815         {
816             // Server textcmd also should have routing pind == 2.
817             // Must not route pn==0 through here due to it being used by a player.
818             if( nnode != 0 )
819                 goto next_textcmd; // server textcmd from non-server
820         }
821         else if( pn > MAXPLAYERS )
822         {
823             goto next_textcmd; // bogus player
824         }
825         else
826         {
827             // players and bots
828             // Could test for (demoplayback && (pn == 0)), but that does not gain protection.
829 #if 1
830             if( ! playeringame[pn] )
831                 goto next_textcmd; // wrong player, or bad player
832 #else
833 // [WDJ] Ideal test, but bots don't set everything up yet.
834             if( player_to_nnode[pn] != nnode )
835                 goto next_textcmd; // wrong player, or bad player
836 #endif
837         }
838 
839 #ifdef CHECK_TIC_SIZE
840     // Check if tic that we are making isn't getting too large.
841     tc_limit = software_MAXPACKETLENGTH
842          - SERVER_TIC_BASE_SIZE
843          - ( num_game_players * sizeof(ticcmd_t) )
844          - ( 1 + sizeof_servertic_textcmd_t(itc_len) );
845 
846     // Search for a tic that has enough space in the ticcmd.
847 #endif
848 
849 
850         for( tic = maketic;  ; )
851         {
852             // Almost always, the first textcmd buffer is empty.
853             btic = BTIC_INDEX( tic );
854             tcbuf = & textcmdbuff[btic];
855             buflen = tcbuf->len;
856 #ifdef CHECK_TIC_SIZE
857             // The incoming textbuf needs a textbuf header in the packet,
858             // and that is already accounted for in the tc_limit.
859             if( (buflen < tc_limit)
860                 && ((itc_len + buflen) < MAX_TEXTCMD_BUFF) )
861                 break; // found one
862 #else
863             if( (itc_len + buflen) < MAX_TEXTCMD_BUFF )
864                 break; // found one
865 #endif
866 
867             // When a textbuf is too full, use the next tic.
868             tic++;
869             if( tic >= (next_tic_send+BACKUPTICS) )
870                 goto drop_packet;  // ran out of tic buffers
871         }
872 
873         // Move textcmd from netbuffer to the textbuf.
874         DEBFILE(va("Textcmd: btic %d buff[%d] player %d len %d nxttic %d maketic %d\n",
875                btic, buflen, pn, itc_len, next_tic_send, maketic));
876 
877         // Append text to the selected buffer, combine lengths.
878         memcpy(&tcbuf->buff[ buflen ], ip, itc_len);  // copy textcmd_item_t
879         tcbuf->len += itc_len;  // text len
880 
881     next_textcmd:
882         ip = (textcmd_item_t*)((byte*)ip + itc_len ); // pn, len, text
883     }
884     return;
885 
886 drop_packet:
887     // Drop the packet, let the node resend it.
888     DEBFILE(va("Textcmd dropped: size %d maketic %d nxttic %d node %d player %d\n",
889                itc_len, maketic, next_tic_send, nnode, pn));
890     Net_Cancel_Packet_Ack(nnode);
891     return;
892 }
893 
894 // SV_Tic will send ticcmd and textcmd to client.
895 
896 // Client
897 // Execute NetXCmd for this gametic.
ExtraDataTicker(void)898 void ExtraDataTicker(void)
899 {
900     textcmdbuff_t * tcbuf;
901     textcmd_item_t * ip;
902     byte * bufp;
903     byte * endbufp;
904     byte * endtxt;  // independent of changes by called xfunc
905     byte save_pn;
906     int btic = BTIC_INDEX( gametic );
907     int pn;
908     unsigned int textlen;
909     xcmd_t  xcmd;
910 
911     // Textcmd for all players, and server, are in textcmdbuff, in order of insertion.
912     tcbuf = & textcmdbuff[btic];  // all players
913     // set extra termination byte at end of buffer
914     tcbuf->buff[MAX_TEXTCMD_BUFF] = 0;  // Protect against malicious strings.
915     bufp = & tcbuf->buff[0];
916     endbufp = & bufp[ tcbuf->len ];  // end of textcmdbuff content
917     while( bufp < endbufp )
918     {
919         // Execute commands of any player in the game, and always for pn=SERVER_PID.
920         ip = (textcmd_item_t*) bufp;
921         textlen = ip->textbuf.len;  // 0..255
922         bufp += sizeof_textcmd_item_t(textlen);  // next item (pn, len, text)
923             // bufp is advanced, so can test and continue.
924 
925         if( textlen == 0 )  continue;  // empty text (should never happen)
926 #if MAXTEXTCMD < 255
927         if( textlen > MAXTEXTCMD )   textlen = MAXTEXTCMD;  // bad length
928 #endif
929 
930         pn = ip->pn;  // player pid for the textcmd
931 
932         // This test causes problems for demos, where some textcmd are issued by player 0
933         // before that player is created.
934         if( netgame
935             && !demoplayback
936             && (pn < MAXPLAYERS) )
937         {
938             // Protection against fake textcmds in netgame.
939             if( ! playeringame[pn] )  continue;   // only if player quit the game suddenly
940         }
941 
942         // Commands can have 0 strings, 1 string, or 2 strings.
943         // Inventory has just a byte number.
944         xcmd.playernum = pn;
945         xcmd.curpos = & ip->textbuf.text[0];  // start of command
946         endtxt = & ip->textbuf.text[textlen];  // after last char of text
947         if( endtxt >= endbufp )  endtxt = endbufp;
948         xcmd.endpos = endtxt;  // end of text + 1
949 
950         // [WDJ] This protects against hostile clients,
951         // that may try to use an unterminated string to tamper with the server.
952         // To put in a term0, we have to save the pn of the next command first.
953         // Saving 1 byte is just cheaper than copying the whole command to a buffer.
954         save_pn = endtxt[0];
955         endtxt[0] = 0;  // Protect against malicious strings.
956 
957         // One or more commands are within curpos..endpos-1
958         while(xcmd.curpos < endtxt)
959         {
960             xcmd.cmd = *(xcmd.curpos++);  // XD_ command
961             if(xcmd.cmd < MAXNETXCMD && netxcmd_func[xcmd.cmd])
962             {
963                 // [WDJ] TODO: Test for server xcmd restricted to SERVER_PID,
964                 // except when demoplayback.
965 
966                 // Execute a NetXCmd.
967                 // The NetXCmd must update xcmd.curpos.
968                 DEBFILE(va("Executing xcmd %d player %d ", xcmd.cmd, pn));
969                 (netxcmd_func[xcmd.cmd])(&xcmd);
970                 // nextcmd_func updates curpos, without knowing textlen
971                 DEBFILE("Execute done\n");
972             }
973             else
974             {
975                 // [WDJ] Why should a bad demo command byte be fatal.
976                 I_SoftError("Got unknown net/demo command [%d]=%d len=%d\n",
977                            (xcmd.curpos - &(ip->textbuf.text[0])),
978                            xcmd.cmd, textlen);
979 #if 1
980                 continue;
981 #else
982                 D_Clear_ticcmd(btic);
983                 break;
984 #endif
985             }
986         }
987         // Put the pn of the next command back into the buffer.
988         endtxt[0] = save_pn;
989 
990         // Does not clear textbuf when done because may be server,
991         // and may have to send this to other nodes again.
992     }
993 
994     // cannot call update_player_counts() direct from an XNetCmd
995     if( update_player_count_request )
996     {
997         update_player_count_request = 0;
998         update_player_counts();
999     }
1000 }
1001 
1002 
1003 // -----------------------------------------------------------------
1004 //  end of extra data function
1005 // -----------------------------------------------------------------
1006 
1007 // -----------------------------------------------------------------
1008 //  extra data function for lmps
1009 // -----------------------------------------------------------------
1010 
1011 // desciption of extradate byte of LEGACY 1.12 not the same of the 1.20
1012 // 1.20 don't have the extradata bits fields but a byte for each command
1013 // see XD_xxx in d_netcmd.h
1014 //
1015 // if extradatabit is set, after the ziped tic you find this :
1016 //
1017 //   type   |  description
1018 // ---------+--------------
1019 //   byte   | size of the extradata
1020 //   byte   | LEGACY 1.13:  XDNAMEANDCOLOR, XD_WEAPON_PREF bits
1021 //            LEGACY 1.20:  XD_ codes
1022 //            Determines what parameters follow.
1023 //
1024 // LEGACY 1.12 XD bits
1025 // if(xd & XDNAMEANDCOLOR)
1026 //   byte   | color
1027 //   char[MAXPLAYERNAME] | name of the player
1028 // endif
1029 // if(xd & XD_WEAPON_PREF)
1030 //   byte   | original weapon switch : boolean, true if use the old
1031 //          | weapon switch methode
1032 //   char[NUMWEAPONS] | the weapon switch priority
1033 //   byte   | autoaim : true if use the old autoaim system
1034 // endif
1035 
1036 // LEGACY 1.48 LONG TEXTCMD FORMAT
1037 // [WDJ] During record demo, commands for each player are saved independently.
1038 // Most textcmd will be within the 255 provided by an ordinary textbuf.
1039 // But 1.48 has a very long combined textbuf, containing all players.
1040 // Also the commands to create a player are now issued by SERVER_PID,
1041 // where in older demos they were issued by player 0, before player 0 existed.
1042 
1043 // For Ver 1.48, all textcmd are appended into one textcmd buffer.
1044 // Separating it into separate players, appending it again is just extra work,
1045 // without any benefit.  And SERVER_PID does not have a slot in the demo.
1046 // It is also now possible for textcmd to run over 255 bytes, even it would
1047 // almost never happen.
1048 // Several ways to deal with this were considered, all with flaws, and few
1049 // actual benefits.
1050 // Decided to just put all textcmd into the player 0 slot, which is being
1051 // used by the demo for server textcmds anyways.  No need to separate
1052 // them into individual buffers again.
1053 // The player id are embedded in the text command format already.
1054 // There are no format conversions needed this way, and this demo format
1055 // is only used for DoomLegacy, not compatible with other ports anyway.
1056 // The demoversion will be the only control for the demo format.
1057 
1058 // Save textcmd to demo using textbuf_t format.
AddLmpExtradata(byte ** demo_point,int playernum)1059 boolean AddLmpExtradata(byte **demo_point, int playernum)
1060 {
1061     textcmdbuff_t * tcbuf;
1062     byte * dp;  // textcmd text
1063 
1064     int btic = BTIC_INDEX( gametic );
1065     tcbuf = & textcmdbuff[btic];
1066     if( tcbuf->len == 0 )  // anything in the buffer
1067         return false;
1068 
1069 #if 1
1070     // DoomLegacy 1.48 Textcmd Format Only
1071     // All textcmd are in player 0.
1072     if( playernum != 0 )
1073         return false;
1074 
1075     dp = *demo_point;
1076 
1077     // Uses two byte length, MSB first
1078     unsigned int textlen = tcbuf->len;
1079     dp[0] = textlen >> 8; // MSB first
1080     dp[1] = textlen & 0xFF;
1081 
1082     memcpy( &dp[2], &tcbuf->buff, textlen );  // text
1083     dp += textlen + 2;
1084 #endif
1085 
1086 
1087 #if 0
1088     // Standard Textcmd Format in demo:
1089     //  length: byte
1090     //  textbuf with multiple commands
1091     textcmd_t * dtc;  // textcmd in demo
1092     byte * bufp, * endbufp;
1093     unsigned int  textlen;
1094     unsigned int  dt_len;
1095     byte  dt_cnt;
1096 
1097     bufp = & tcbuf->buff[0];
1098     endbufp = & tcbuf->buff[ tcbuf->len ];
1099 
1100     dp = *demo_point;
1101     dt_cnt = 0;
1102 
1103     // Demo format matches textbuf_t, length limited to 255.
1104     dtc = dp; // textcmd in demo
1105     dp = &dtc->text;
1106     dt_len = 0;
1107 
1108     while( bufp < endbufp )
1109     {
1110         textcmd_item_t * ip = (textcmd_item_t *)bufp;
1111         textlen = ip->textbuf.len;
1112         bufp += textlen + 2;  // next item (pn, len, text)
1113             // advanced bufp so can test and continue
1114 
1115         if( ip->pn == SERVER_PID )
1116         {
1117             // SERVER_PID into player[0], for now.
1118             // Cannot identify them to change them back to SERVER_PID though.
1119             // The demo needs to have a player[0].
1120             if( playernum != 0 )
1121                 continue;
1122         }
1123         else if( ip->pn != playernum )
1124             continue;  // wrong player
1125 
1126         if( textlen == 0 )  // anything in the buffer
1127             continue;
1128 
1129         // Append together when total length < 255.
1130         dt_len += textlen;  // appended length
1131         if( (dt_len > 255) && dt_cnt )
1132         {
1133             // Overruns the max textcmd in demo.
1134         // Need a code to indicate that there is more textcmd
1135         // but the next byte is the next players bit enables, which
1136         // conflicts with every coding.
1137         // This forces another byte to be used within the textcmd,
1138         // which violates it being compatible with the old textcmd format.
1139             // Start another textcmd
1140             dtc = dp;
1141             dp = &dtc->text;
1142             dt_len = textlen;
1143         }
1144 
1145         memcpy( dp, &ip->textbuf.text, textlen );  // text
1146         dp += textlen;
1147         dtc->len = dt_len;
1148         dt_cnt++;
1149     }
1150 
1151     if( dt_cnt == 0 )
1152         return false;
1153 #endif
1154 
1155     *demo_point = dp;  // update the demo ptr
1156     return true;
1157 }
1158 
ReadLmpExtraData(byte ** demo_pointer,int playernum)1159 void ReadLmpExtraData(byte **demo_pointer, int playernum)
1160 {
1161     byte * dp;
1162     textcmdbuff_t * tcbuf;
1163     textcmd_item_t * ip;
1164     unsigned int buflen;
1165     unsigned int dt_len;
1166     int btic = BTIC_INDEX( gametic );
1167 
1168     if(!demo_pointer)  goto no_text_cmd;
1169 
1170     dp = *demo_pointer;
1171     if( dp == NULL )  goto no_text_cmd;
1172 
1173     tcbuf = & textcmdbuff[btic];
1174     buflen = tcbuf->len;
1175 
1176     // [WDJ] DoomLegacy 1.48.
1177     // SERVER_PID commands have been written to player 0.
1178     // There are no markers to change them back to SERVER_PID again.
1179     // Fixed in execute, by disabling safety checks when playing demos.
1180     // Can execute server textcmd as player 0, as long as can get past checks.
1181     // Executing player 0 textcmd as SERVER_PID would cause errors.
1182 #if 0
1183     if( (playernum == 0) && ??? )
1184         playernum = SERVER_PID; // because of checks
1185 #endif
1186 
1187 #if 1
1188     if( (demoversion >= 148) && (playernum == 0) )
1189     {
1190         // DoomLegacy 1.48 Textcmd Format Only
1191         // All textcmd are in player 0, enforced by writer.
1192 
1193         // Uses two byte length, MSB first
1194         unsigned int textlen = (dp[0] << 8) + dp[1];
1195 
1196         if( textlen > MAX_TEXTCMD_BUFF )
1197             return; // cannot be valid textcmd
1198 
1199         // Do not have to append as only the demo can be entering textcmds.
1200         memcpy( &tcbuf->buff, &dp[2], textlen );  // text
1201         tcbuf->len = textlen;
1202         dp += textlen + 2;
1203         goto read_done;
1204     }
1205 #endif
1206 
1207 
1208     // [WDJ] Read older demo code.
1209     // See Clean up textcmd, in TryRunTics, that allows this to just append.
1210     ip = (textcmd_item_t *)  & tcbuf->buff[ buflen ];
1211     ip->pn = playernum;
1212 
1213     dt_len = dp[0];   // demo textbuf->len
1214 
1215     if( (buflen + dt_len) >= (MAX_TEXTCMD_BUFF - 2) )
1216         goto no_text_cmd; // will not fit
1217 
1218     // [WDJ] Clean separation of old and new formating.
1219     if(demoversion==112) // support old demos v1.12
1220     {
1221         // Different, limited, XCmd format.
1222         byte  * p = dp;
1223         byte  * bufp = & ip->textbuf.text[0];  // new textbuf in textcmdbuff
1224         byte  ex;
1225         unsigned int textlen = 0;
1226 
1227         // dt_len is length of extra data, incl length.
1228         ex = p[1];  // XCmd bits
1229         p += 2;  // skip dt_len and XCmd
1230         if(ex & 1)
1231         {
1232             *(bufp++) = XD_NAMEANDCOLOR;
1233             memcpy( bufp, p, MAXPLAYERNAME+1);
1234             p+=MAXPLAYERNAME+1;
1235             textlen += MAXPLAYERNAME+1;
1236             bufp += MAXPLAYERNAME+1;
1237         }
1238         if(ex & 2)
1239         {
1240             *(bufp++) = XD_WEAPONPREF;
1241             memcpy( bufp, p, NUMWEAPONS+2);
1242             p+=NUMWEAPONS+2;
1243             textlen += NUMWEAPONS+2;
1244         }
1245         ip->textbuf.len = textlen;
1246         buflen += textlen + 2;
1247     }
1248     else
1249     {
1250         // DoomLegacy <= 1.47
1251         // Demo format matches textbuf_t, length limited.
1252         // dt_len is textbuf->len, excluding len field.
1253         dt_len ++;
1254         memcpy( &ip->textbuf, dp, dt_len);  // len,text
1255         buflen += dt_len + 1;
1256     }
1257     tcbuf->len = buflen;
1258     dp += dt_len;
1259 
1260 read_done:
1261     // update demo pointer
1262     *demo_pointer = dp;
1263     return;
1264 
1265 no_text_cmd:
1266     return;
1267 }
1268 
1269 
1270 // -----------------------------------------------------------------
1271 //  end extra data function for lmps
1272 // -----------------------------------------------------------------
1273 
1274 // ----- Server/Client Responses
1275 static void CL_ConnectToServer(void);
1276 static int16_t  Consistency(void);
1277 static void Net_Packet_Handler(void);
1278 static void SV_Reset_NetNode(byte nnode);
1279 static boolean SV_Add_Join_Waiting(void);
1280 static void SV_Send_player_desc( player_desc_t * pdesc, byte desc_flags, byte pn, byte to_node );
1281 static void CL_init_playerdesc_receive( uint32_t r_gametic );
1282 static void CL_player_desc_handler( player_desc_t * pdesc, const char * msg );
1283 
1284 
1285 // By Server
1286 // Broadcast to all connected nodes
1287 //   flags: SP_ for HSendPacket
SV_SendPacket_All(sendpacket_flag_e flags,size_t size_packet,const char * msg)1288 static void SV_SendPacket_All( sendpacket_flag_e flags, size_t size_packet, const char * msg )
1289 {
1290     int nn;
1291     for(nn=1; nn<MAXNETNODES; nn++)
1292     {
1293         if( nnode_state[nn] >= NOS_recognized )
1294         {
1295             HSendPacket( nn, flags, 0, size_packet );  // ignore failures
1296             if( msg )
1297                 debug_Printf( "%s[ %d ]\n", msg, nn );
1298         }
1299     }
1300 }
1301 
1302 // Server, Client
1303 // send a simple packet
1304 //   nnode : client node, cl_servernode, BROADCAST_NODE
1305 // Return  NE_xx
SendPacket(byte nnode,byte packettype)1306 static byte  SendPacket( byte nnode, byte packettype )
1307 {
1308     netbuffer->packettype = packettype;
1309 
1310     if( nnode == BROADCAST_NODE )  // only by server
1311     {
1312         SV_SendPacket_All( SP_reliable|SP_queue|SP_error_handler, 0, NULL );
1313         return NE_success;
1314     }
1315 
1316     if( nnode < MAXNETNODES )
1317         return HSendPacket( nnode, SP_reliable|SP_queue|SP_error_handler, 0, 0 );
1318 
1319     return NE_fail;
1320 }
1321 
1322 
1323 // Flags used by Join msg.
1324 typedef enum {
1325   NF_drone = 0x80,
1326   NF_big_endian = 0x40,
1327   NF_download_savegame = 0x10,
1328 } join_flags_e;
1329 
1330 // By Client.
1331 // Send a request to join game.
1332 // Called by CL_ConnectToServer.
CL_Send_Join(void)1333 static boolean  CL_Send_Join( void )
1334 {
1335     byte flg = 0;
1336     if( cv_download_savegame.EV )  flg |= NF_download_savegame;
1337     if( cl_drone )  flg |= NF_drone;
1338 #ifdef __BIG_ENDIAN__
1339     flg |= NF_big_endian;
1340 #endif
1341 
1342     GenPrintf(EMSG_hud, "Send join request...\n");
1343     netbuffer->packettype=PT_CLIENTJOIN;
1344     netbuffer->u.clientcfg.version = VERSION;
1345     netbuffer->u.clientcfg.ver1 = 0;
1346     netbuffer->u.clientcfg.ver2 = VERSION;
1347     netbuffer->u.clientcfg.ver3 = REVISION;
1348     netbuffer->u.clientcfg.subversion = LE_SWAP32(NETWORK_VERSION);
1349     netbuffer->u.clientcfg.mode = 0;
1350     netbuffer->u.clientcfg.flags = flg;
1351 
1352     // Declare how many players at this node.
1353     netbuffer->u.clientcfg.num_node_players =
1354         (cl_drone)? 0
1355       : ( (cv_splitscreen.value)? 2 : 1 );
1356 
1357     byte errcode = HSendPacket( cl_servernode, SP_reliable|SP_queue|SP_error_handler, 0, sizeof(clientconfig_pak_t) );
1358     return  (errcode < NE_fail);
1359 }
1360 
1361 
1362 // ----- Server Info
1363 
1364 // By Server.
1365 // Reply to request for server info.
1366 //   reqtime : the send time of the request
SV_Send_ServerInfo(int to_node,tic_t reqtime)1367 static void SV_Send_ServerInfo(int to_node, tic_t reqtime)
1368 {
1369     byte * p;
1370 
1371     netbuffer->packettype=PT_SERVERINFO;
1372     netbuffer->u.serverinfo.version = VERSION;
1373     netbuffer->u.serverinfo.ver1 = 0;
1374     netbuffer->u.serverinfo.ver2 = VERSION;
1375     netbuffer->u.serverinfo.ver3 = REVISION;
1376     netbuffer->u.serverinfo.subversion = LE_SWAP32(NETWORK_VERSION);
1377     // return back the time value so client can compute their ping
1378     netbuffer->u.serverinfo.trip_time = LE_SWAP32(reqtime);
1379     netbuffer->u.serverinfo.num_active_players = num_game_players;
1380     netbuffer->u.serverinfo.maxplayer = cv_maxplayers.value;
1381     netbuffer->u.serverinfo.load = 0;        // unused for the moment
1382     netbuffer->u.serverinfo.deathmatch = cv_deathmatch.EV;  // menu setting
1383     strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, MAXSERVERNAME);
1384     if(game_map_filename[0])
1385     {
1386         // Map command external wad file.
1387         strcpy(netbuffer->u.serverinfo.mapname,game_map_filename);
1388     }
1389     else
1390     {
1391         // existing map
1392         strcpy(netbuffer->u.serverinfo.mapname,G_BuildMapName(gameepisode,gamemap));
1393     }
1394 
1395     p=Put_Server_FileNeed();
1396 
1397     HSendPacket( to_node, 0, 0, p - ((byte *)& netbuffer->u) );  // msg lost when too busy
1398 }
1399 
1400 
1401 // By Server.
1402 // Accept player joining the game.
1403 // Send the initial command with the config to avoid sending a second message,
1404 // which could arrive out-of-order.
1405 //   command : CTRL_ command to send with config
SV_Send_ServerConfig(byte to_node,byte command)1406 static boolean SV_Send_ServerConfig( byte to_node, byte command )
1407 {
1408     xcmd_t xc;
1409 
1410 #if 1
1411     // Send mask for all players and bots
1412     int   i,playermask=0;
1413     for(i=0;i<MAXPLAYERS;i++)
1414     {
1415          if(playeringame[i])
1416               playermask|=1<<i;
1417     }
1418     write_N32( & netbuffer->u.servercfg.playerdetected, playermask );
1419 #else
1420     // Send mask for all players, but not bots.
1421     update_player_counts();   // not necessary, already done
1422     write_N32( & netbuffer->u.servercfg.playerdetected, ticcmd_player_mask );
1423 #endif
1424 
1425     netbuffer->packettype=PT_SERVERCFG;
1426     netbuffer->u.servercfg.version         = VERSION;
1427     netbuffer->u.servercfg.ver1 = 0;
1428     netbuffer->u.servercfg.ver2 = VERSION;
1429     netbuffer->u.servercfg.ver3 = REVISION;
1430     netbuffer->u.servercfg.subversion      = LE_SWAP32(NETWORK_VERSION);
1431 
1432     netbuffer->u.servercfg.serverplayer    = serverplayer;
1433     netbuffer->u.servercfg.num_game_players= num_game_players;
1434     write_N32( & netbuffer->u.servercfg.gametic, gametic );
1435     netbuffer->u.servercfg.clientnode      = to_node;  // client node (in server space)
1436     netbuffer->u.servercfg.gamestate       = gamestate;
1437     netbuffer->u.servercfg.command         = command;
1438 
1439     xc.playernum = 0;
1440     xc.curpos = netbuffer->u.servercfg.netvar_buf;
1441     xc.endpos = xc.curpos + NETVAR_BUFF_LEN - 1;
1442     CV_SaveNetVars( &xc );
1443     // curpos is 1 past last cvar (if none then is at netvar_buf)
1444 
1445     byte errcode = HSendPacket( to_node, SP_reliable|SP_queue|SP_error_handler, 0, xc.curpos - ((byte *)& netbuffer->u) );
1446     return  (errcode < NE_fail);
1447 }
1448 
1449 
1450 
1451 #ifdef WAIT_GAME_START_INTERMISSION
1452 
1453 // By Server.
1454 // Send the state of all players.
SV_Send_PlayerState(byte to_node)1455 static void SV_Send_PlayerState( byte to_node )
1456 {
1457     // Which players are in game, which are bots.
1458     // Get name and color by asking nodes for refresh.
1459     update_player_counts();
1460 
1461     netbuffer->packettype = PT_SERVERPLAYER;
1462     write_N32( & netbuffer->u.playerstate.gametic, gametic );
1463 
1464     netbuffer->u.playerstate.serverplayer = serverplayer;
1465 
1466     // Easier to determine state when all player slots are present.
1467     // byte array of player_state
1468     // Identifies player and bot.
1469     memcpy( &netbuffer->u.playerstate.playerstate, player_state, MAXPLAYERS );
1470 
1471     // Only those players that are present
1472     // Sends one or more packets.
1473     SV_Send_player_desc( &netbuffer->u.playerstate.player_desc, PDI_inventory, 255, to_node );
1474 }
1475 
1476 
1477 // By Client
1478 // PT_SERVERPLAYER
1479 static
server_player_handler(byte nnode)1480 void  server_player_handler( byte nnode )
1481 {
1482     byte pn;
1483 
1484     // Do not know what to do with gametic yet.
1485     unsigned int sph_gametic = read_N32( & netbuffer->u.playerstate.gametic );
1486     // Ideally this should be done at the matching gametic.
1487     CL_init_playerdesc_receive( sph_gametic );
1488 
1489     serverplayer = netbuffer->u.playerstate.serverplayer;
1490     gameskill = netbuffer->u.playerstate.skill;  // for create bots
1491 
1492     // Add and remove players
1493     for( pn=0; pn<MAXPLAYERS; pn++ )
1494     {
1495         update_player_state( pn, netbuffer->u.playerstate.playerstate[pn] );
1496     }
1497     update_player_counts();
1498 
1499     // Receive all player desc.
1500     CL_player_desc_handler( &netbuffer->u.playerstate.player_desc, NULL );
1501 }
1502 #endif
1503 
1504 
1505 // By Server.
1506 // Send the level state.
SV_Send_LevelCfg(byte to_node)1507 static void SV_Send_LevelCfg( byte to_node )
1508 {
1509     netbuffer->packettype = PT_SERVERLEVEL;
1510 
1511     // The game state, level map identity and name.
1512     netbuffer->u.levelcfg.gamestate = gamestate;
1513     netbuffer->u.levelcfg.gameepisode = gameepisode;
1514     netbuffer->u.levelcfg.gamemap = gamemap;
1515     netbuffer->u.levelcfg.skill = gameskill;
1516     netbuffer->u.levelcfg.nomonsters = nomonsters;
1517     netbuffer->u.levelcfg.deathmatch = cv_deathmatch.EV;
1518 
1519 #if 0
1520     // TODO: support changing mapname by server
1521     // TODO: allow server to cycle through various map and map files.
1522     if(game_map_filename[0])
1523     {
1524         // Map command external wad file.
1525         strcpy(netbuffer->u.levelcfg.mapname,game_map_filename);
1526     }
1527     else
1528     {
1529         // existing map
1530         strcpy(netbuffer->u.levelcfg.mapname,G_BuildMapName(gameepisode,gamemap));
1531     }
1532 #endif
1533 
1534     HSendPacket(to_node, SP_reliable|SP_queue|SP_error_handler, 0, sizeof(levelcfg_pak_t) );
1535     // nothing to be done if this fails
1536 }
1537 
1538 // By Client
1539 // PT_SERVERLEVEL
1540 static
server_level_handler(byte nnode)1541 void  server_level_handler( byte nnode )
1542 {
1543     // level info should not change during game, only during intermission or pause
1544     gamestate = netbuffer->u.levelcfg.gamestate;
1545     gameepisode = netbuffer->u.levelcfg.gameepisode;
1546     gamemap = netbuffer->u.levelcfg.gamemap;
1547     gameskill = netbuffer->u.levelcfg.skill;
1548     nomonsters = netbuffer->u.levelcfg.nomonsters;
1549     CV_SetParam( &cv_deathmatch, netbuffer->u.levelcfg.deathmatch );
1550     // TODO: support changing mapname by server
1551     // TODO: allow server to cycle through various map and map files.
1552 }
1553 
1554 
1555 // ----- Control Message
1556 
1557 // Network commands
1558 typedef enum {
1559     CTRL_state,  // no node command
1560     CTRL_normal,
1561     CTRL_download_savegame,
1562     CTRL_wait_game_start,
1563     CTRL_game_start,
1564     CTRL_wait_timer,
1565 } net_control_command_e;
1566 
1567 // By Server
1568 //   ctrl_command : net_control_e
1569 //   to_gamestate : new gamestate, command dependent
1570 //   data1 : 8 bit value
1571 //   data2 : 16 bit value, timer value or other data specific to the command
1572 //   player_num : player num (255 when unused)
SV_Send_control(byte nnode,byte ctrl_command,byte data1,uint16_t data2,byte player_num)1573 static void SV_Send_control( byte nnode, byte ctrl_command, byte data1, uint16_t data2, byte player_num )
1574 {
1575     netbuffer->packettype = PT_CONTROL;
1576     netbuffer->u.control.command = ctrl_command;
1577     netbuffer->u.control.player_num = player_num;
1578     netbuffer->u.control.player_state = (player_num < MAXPLAYERS)? player_state[player_num] : PS_unused;
1579     netbuffer->u.control.gamemap = gamemap;
1580     netbuffer->u.control.gameepisode = gameepisode;
1581     write_N32( & netbuffer->u.control.gametic, gametic );
1582     write_N16( & netbuffer->u.control.data2, data2 );
1583     netbuffer->u.control.data1 = data1;
1584 
1585     if( nnode == BROADCAST_NODE )
1586     {
1587         // Broadcast it
1588         SV_SendPacket_All( true, sizeof(control_pak_t), NULL );
1589     }
1590     else if( nnode < MAXNETNODES )
1591     {
1592         byte errcode = HSendPacket( nnode, SP_reliable|SP_queue, 0, sizeof(control_pak_t) );
1593         if( errcode >= NE_fail )
1594         {
1595             generic_network_error_handler( errcode, "Control msg" );  // should not happen
1596         }
1597     }
1598 }
1599 
1600 // By Client (maybe client on server)
control_msg_handler(void)1601 static void control_msg_handler( void )
1602 {
1603     // Command from server to client.
1604     byte pn = netbuffer->u.control.player_num;
1605     byte ps = netbuffer->u.control.player_state;
1606     uint16_t data2 = read_N16( & netbuffer->u.control.data2 );
1607 
1608     if( !server )
1609     {
1610         // Client not on server.
1611         // When sent a player state, update it on client.
1612         if( pn < MAXPLAYERS )
1613             update_player_state( pn, ps );
1614 
1615         if( cl_mode < CLM_connected )
1616         {
1617             // Initialize tics on new client.
1618             gametic = read_N32( & netbuffer->u.control.gametic );
1619             cl_need_tic = maketic = gametic;  // sync
1620         }
1621 
1622         gamemap = netbuffer->u.control.gamemap;
1623         gameepisode = netbuffer->u.control.gameepisode;
1624     }
1625 
1626     // Situation specific
1627     switch( netbuffer->u.control.command )
1628     {
1629      case CTRL_normal:
1630         if( cl_mode < CLM_connected )
1631             cl_mode = CLM_connected;
1632         break;
1633 #ifdef WAIT_GAME_START_INTERMISSION
1634      case CTRL_wait_game_start:
1635         if( (cl_mode < CLM_connected) && (ps == PS_join_wait_game_start) )
1636         {
1637             cl_mode = CLM_wait_game_start;
1638 
1639             if( server )  break;  // protection, should not happen
1640 
1641             wait_netplayer = 0;  // turn off wait display
1642             gamestate = GS_INTERMISSION;
1643             // TODO: watch another player
1644         }
1645         break;
1646      case CTRL_game_start:
1647         if( cl_mode == CLM_wait_game_start )
1648         {
1649             cl_mode = CLM_connected;
1650 
1651             if( server )  break;  // protection, should not happen
1652 
1653 	    byte mode = netbuffer->u.control.data1;
1654             gametic = read_N32( & netbuffer->u.control.gametic );
1655             cl_need_tic = maketic = gametic;  // sync
1656 
1657             if( mode )
1658             {
1659                 // Invoked by Map command at server, when there are wait_game_start players.
1660 #if 0
1661 // [WDJ] TODO: NOT WORKING YET.
1662 // Map command is overriding in server, but is missing in client.
1663 
1664                 // Map command will take it to GS_LEVEL.
1665                 gamestate = GS_NULL;
1666 //                G_DoLoadLevel(1);  // if can get map first ?
1667 #endif
1668             }
1669             else
1670             {
1671                 // Server in GS_INTERMISSION.
1672                 G_Start_Intermission();  // setup intermission
1673             }
1674 
1675             // wait timer only works in GS_INTERMISSION
1676             // update from server
1677             wait_game_start_timer = data2;
1678 //          wait_netplayer = 0;  // only want the timer display
1679 
1680             // Warn the player, who probably has dozed off by now.
1681 //            S_StartSound(sfx_menuop);  // always present
1682             S_StartSound(sfx_telept);  // longer sound, likely to be in all games
1683         }
1684         break;
1685 #endif
1686      case CTRL_wait_timer:
1687         if( server )  break;  // protection, should not happen
1688 
1689         wait_game_start_timer = data2;
1690         break;
1691      default:
1692         break;
1693     }
1694 }
1695 
1696 
1697 // ----- Random State Update
1698 
1699 // Send: Fill in the fields
get_random_state(random_state_t * rs)1700 static void get_random_state( random_state_t * rs )
1701 {
1702     uint32_t rand2;
1703     rs->p_rand_index = P_Rand_GetIndex(); // to sync P_Random
1704     rs->b_rand_index = B_Rand_GetIndex(); // to sync B_Random
1705     write_N32( &rs->e_rand1, E_Rand_Get( & rand2 ) ); // to sync E_Random
1706     write_N32( &rs->e_rand2, rand2 );
1707 }
1708 
1709 #define SET_RANDOM    1
1710 // Client
1711 // Receive: Update client random state.
1712 //   set_enable : 1=enable set,  0=check only
random_state_checkset(random_state_t * rs,const char * msg,byte set_enable)1713 static void random_state_checkset( random_state_t * rs, const char * msg, byte set_enable )
1714 {
1715     uint32_t  o_ernd1, o_ernd2, rs_ernd1, rs_ernd2;
1716     byte  o_pr, o_br, rs_pr, rs_br;
1717 
1718     if( ! msg )
1719     {
1720         msg = "Client random state repair";
1721     }
1722 
1723     o_pr = P_Rand_GetIndex();
1724     rs_pr = rs->p_rand_index;
1725     if( o_pr != rs_pr )
1726     {
1727         // Warn when different P_Random index.
1728         GenPrintf( EMSG_warn, "%s: gametic %i, update P_random index %i to %i\n",
1729              msg, gametic, o_pr, rs_pr );
1730         if( set_enable )
1731             P_Rand_SetIndex( rs_pr ); // to sync P_Random
1732     }
1733 
1734     o_br = B_Rand_GetIndex();
1735     rs_br = rs->b_rand_index;
1736     if( o_br != rs_br )
1737     {
1738         GenPrintf( EMSG_warn, "%s: update B_Random index %i to %i\n", msg, o_br, rs_br );
1739         if( set_enable )
1740             B_Rand_SetIndex( rs_br ); // to sync B_Random
1741     }
1742 
1743     o_ernd1 = E_Rand_Get( & o_ernd2 );
1744     rs_ernd1 = read_N32( &rs->e_rand1 );
1745     rs_ernd2 = read_N32( &rs->e_rand2 );
1746     if( o_ernd1 != rs_ernd1 || o_ernd2 != rs_ernd2 )
1747     {
1748         GenPrintf( EMSG_warn, "%s: update E_Random (%08X,%08X) to (%08X,%08X)\n",
1749                    msg, o_ernd1, o_ernd2, rs_ernd1, rs_ernd2 );
1750         if( set_enable )
1751             E_Rand_Set( rs_ernd1, rs_ernd2 ); // to sync E_Random
1752     }
1753 }
1754 
1755 
1756 // ----- Gametic and Pause State
1757 
1758 // [WDJ] Update state by sever.
1759 // By Server
SV_Send_State(byte server_pause)1760 void SV_Send_State( byte server_pause )
1761 {
1762     netbuffer->packettype=PT_STATE;
1763     write_N32( & netbuffer->u.state.gametic, gametic );
1764     get_random_state( & netbuffer->u.state.rs ); // to sync P_Random
1765     netbuffer->u.state.server_pause = server_pause;
1766 
1767     SV_SendPacket_All( true, sizeof(state_pak_t), NULL );
1768 }
1769 
1770 // By Client
state_handler(void)1771 static void state_handler( void )
1772 {
1773     byte nnode = doomcom->remotenode;
1774 
1775     // Message is PT_STATE
1776     tic_t serv_gametic = read_N32( & netbuffer->u.state.gametic );
1777     if( serv_gametic != gametic )
1778     {
1779         if( verbose > 1 )
1780             GenPrintf( EMSG_ver, "PT_STATE: node %i, client gametic %i, server gametic %i\n", nnode, gametic, serv_gametic );
1781         // Gametic cannot be fixed directly, need game commands.
1782         // It may just be behind by a tic or two.
1783     }
1784     else
1785     {
1786         // Update the random generators.
1787         random_state_checkset( & netbuffer->u.state.rs, "PT_STATE", SET_RANDOM ); // to sync P_Random
1788     }
1789     paused = netbuffer->u.state.server_pause;
1790 
1791 #if 0
1792     debug_Printf( "STATE: gametic %i, P_Random [%i], paused %i\n",
1793           gametic, netbuffer->u.state.rs.p_rand_index, netbuffer->u.state.server_pause );
1794 #endif
1795 }
1796 
1797 
1798 // ----- Wait for Client Update to Finish
1799 
1800 // NETWORK_WAIT_ACTIVE_FLAG is carefully choosen to avoid boolean values 0/1
1801 #define NETWORK_WAIT_ACTIVE_FLAG   0x40
1802 static uint16_t  network_wait_timer = 0;
1803 static byte      network_wait_pause = 0;
1804 
1805 // Server
1806 //  wait_timeout : wait timeout in ticks
SV_network_wait_timer(uint16_t wait_timeout)1807 void  SV_network_wait_timer( uint16_t wait_timeout )
1808 {
1809     if( wait_timeout > network_wait_timer )   network_wait_timer = wait_timeout;
1810 
1811     if( ! network_wait_pause )
1812     {
1813         // save pause state, and network pause state
1814         network_wait_pause = paused | NETWORK_WAIT_ACTIVE_FLAG;
1815         if( ! paused )
1816         {
1817             // All clients except the server.
1818             SV_Send_State( 1 );  // pause game
1819         }
1820         paused = network_wait_pause;
1821     }
1822 }
1823 
1824 // Server
1825 // Wait when netgame is forced to pause.
1826 static
SV_network_wait_handler(void)1827 void  SV_network_wait_handler( void )
1828 {
1829     byte nn, ns;
1830 
1831     // Is everybody ready.
1832     for( nn=0; nn<MAXNETNODES; nn++ )
1833     {
1834         ns = nnode_state[nn];
1835         if((ns >= NOS_join) && (ns <= NOS_join_sg_loaded))  goto keep_waiting;
1836         if((ns >= NOS_repair) && (ns <= NOS_repair_sg_loaded))  goto keep_waiting;
1837     }
1838     goto unpause_game;
1839 
1840 keep_waiting:
1841     if( network_wait_timer > 1 )
1842     {
1843         network_wait_timer--;
1844         return;
1845     }
1846 
1847     // Timeout the wait
1848     network_wait_timer = 0;
1849     for( nn=0; nn<MAXNETNODES; nn++ )
1850     {
1851         byte ns = nnode_state[nn];
1852         if( ns == NOS_idle ) continue;
1853 
1854         GenPrintf(EMSG_warn, "Network timeout: node=%i  nnode_state=%i\n", nn, ns );
1855         if((ns >= NOS_join) && (ns < NOS_join_timeout))
1856         {
1857             nnode_state[nn] = NOS_join_timeout;
1858             network_wait_timer = 2;
1859         }
1860         else if((ns >= NOS_repair) && (ns < NOS_repair_timeout))
1861         {
1862             nnode_state[nn] = NOS_repair_timeout;
1863             network_wait_timer = 2;
1864         }
1865         else if( ns == NOS_repair_timeout || ns == NOS_join_timeout || ns == NOS_fatal )
1866         {
1867             Net_CloseConnection(nn, 1); // force close
1868             SV_Reset_NetNode(nn);
1869         }
1870     }
1871 
1872     if( network_wait_timer == 0 )  goto unpause_game;  // let other players continue
1873     return;
1874 
1875 unpause_game:
1876     if( network_wait_pause == NETWORK_WAIT_ACTIVE_FLAG )  // originally was not paused
1877     {
1878         // All clients except the server.
1879         SV_Send_State( 0 );  // unpause the game
1880     }
1881     paused &= ~NETWORK_WAIT_ACTIVE_FLAG;
1882     network_wait_pause = 0;
1883     network_wait_timer = 0;
1884     return;
1885 }
1886 
1887 
1888 // By Server
ready_handler(byte nnode)1889 static void  ready_handler( byte nnode )
1890 {
1891     byte  ns = nnode_state[nnode];
1892 
1893     // Client is ready
1894     if( ns == NOS_join_savegame )
1895     {
1896         nnode_state[nnode] = NOS_join_sg_loaded;  // signal to SV_Add_Join_Waiting()
1897         SV_Add_Join_Waiting();
1898     }
1899 }
1900 
1901 // ---- Client Update Player
1902 // This supports network repair and client update.
1903 
1904 // By Server.
1905 //  mo : the mobj to be sent
1906 //  mpp : mobj_pos_t in a packet message
SV_get_mobj(mobj_t * mo,mobj_pos_t * mpp)1907 static void SV_get_mobj( mobj_t * mo, /*OUT*/ mobj_pos_t * mpp )
1908 {
1909     if( mo == NULL )
1910     {
1911         memset( mpp, 0, sizeof(mobj_pos_t) );
1912         mpp->momz = LE_SWAP32(0x7FFF7FFF);  // too large to be valid
1913         return;
1914     }
1915 
1916     // Player or monster position.
1917     mpp->angle = LE_SWAP32( mo->angle );
1918     mpp->x = LE_SWAP32( mo->x );
1919     mpp->y = LE_SWAP32( mo->y );
1920     mpp->z = LE_SWAP32( mo->z );
1921     mpp->momx = LE_SWAP32( mo->momx );
1922     mpp->momy = LE_SWAP32( mo->momy );
1923     mpp->momz = LE_SWAP32( mo->momz );
1924 
1925     return;
1926 }
1927 
1928 // By Client.
1929 //   mpp : mobj_pos_t in a packet message
1930 //   objtype : create this type of object, else 0xFFFF
1931 //   msg : report message header, if NULL then no reports
1932 //   mo : the mobj being received, may be NULL
1933 //   mopp : write the new mobj, if it is created, may be NULL
1934 // Called by CL_player_repair, CL_player_desc_handler.
CL_set_mobj(mobj_pos_t * mpp,unsigned int objtype,const char * msg,mobj_t * mo,mobj_t ** mopp)1935 static void  CL_set_mobj( mobj_pos_t * mpp, unsigned int objtype, const char * msg, /*OUT*/ mobj_t * mo, mobj_t ** mopp )
1936 {
1937     angle_t  r_angle = LE_SWAP32( mpp->angle );
1938     fixed_t  r_x = LE_SWAP32( mpp->x );
1939     fixed_t  r_y = LE_SWAP32( mpp->y );
1940     fixed_t  r_z = LE_SWAP32( mpp->z );
1941     fixed_t  r_momx = LE_SWAP32( mpp->momx );
1942     fixed_t  r_momy = LE_SWAP32( mpp->momy );
1943     fixed_t  r_momz = LE_SWAP32( mpp->momz );
1944     byte  setthingpos = 0;
1945 
1946     // [WDJ] During GS_LEVEL, need mobj as position is critical.
1947     // During GS_INTERMISSION, position does not matter, and mobj is not needed.
1948     if( ! mo )
1949     {
1950         if((objtype >= NUMMOBJTYPES) || (mopp == NULL))
1951             return;
1952 
1953         // mobj is missing, create new objtype
1954 #if 1
1955         // SpawnMobj needs sector map information.
1956         // When not GS_LEVEL, cannot know if level map is present yet.
1957         if( gamestate != GS_LEVEL )  return;
1958 
1959         mo = P_SpawnMobj(r_x, r_y, r_z, objtype);
1960         // set thing pos already done by P_SpawnMobj
1961         *mopp = mo;  // save new mobj
1962 #else
1963         // incomplete
1964         mo = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
1965         *mopp = mo;  // save new mobj
1966         memset(pp->mo, 0, sizeof(mobj_t));
1967         if( gamestate == GS_LEVEL )
1968             setthingpos = 1;
1969 #endif
1970         msg = NULL;  // no checks on new mobj
1971     }
1972     else if( gamestate == GS_LEVEL )
1973     {
1974         P_UnsetThingPosition(mo);
1975         setthingpos = 1;
1976     }
1977 
1978     // Only check and report when it is repair.
1979     if( msg )
1980     {
1981         if( mo->angle != r_angle )
1982         {
1983             GenPrintf( EMSG_warn, "%s: ANGLE  client %x  server %x\n", msg, mo->angle, r_angle );
1984         }
1985 
1986         if(  mo->x != r_x || mo->y != r_y || mo->z != r_z )
1987         {
1988             GenPrintf( EMSG_warn, "%s: POS  client (%x.%x, %x.%x, %x.%x)  server (%x.%x, %x.%x, %x.%x)\n", msg,
1989                    mo->x>>16, mo->x&0xFFFF, mo->y>>16, mo->y&0xFFFF, mo->z>>16, mo->z&0xFFFF,
1990                    r_x>>16, r_x&0xFFFF, r_y>>16, r_y&0xFFFF, r_z>>16, r_z&0xFFFF  );
1991         }
1992 
1993         if(  mo->momx != r_momx || mo->momy != r_momy || mo->momz != r_momz )
1994         {
1995             GenPrintf( EMSG_warn, "%s: MOM  client (%x.%x, %x.%x, %x.%x)  server (%x.%x, %x.%x, %x.%x)\n", msg,
1996                    mo->momx>>16, mo->momx&0xFFFF, mo->momy>>16, mo->momy&0xFFFF, mo->momz>>16, mo->momz&0xFFFF,
1997                    r_momx>>16, r_momx&0xFFFF, r_momy>>16, r_momy&0xFFFF, r_momz>>16, r_momz&0xFFFF  );
1998         }
1999     }
2000 
2001     mo->angle = r_angle;
2002     mo->x = r_x;
2003     mo->y = r_y;
2004     mo->z = r_z;
2005     mo->momx = r_momx;
2006     mo->momy = r_momy;
2007     mo->momz = r_momz;
2008 
2009     if( setthingpos )
2010     {
2011         P_SetThingPosition(mo);  // set subsector, links
2012     }
2013 }
2014 
2015 
2016 typedef enum {
2017     PF_BACKPACK = 0x08,
2018     PF_AUTOAIM = 0x10,
2019     PF_ORIGWEAPONSWITCH = 0x20,
2020 } player_flags_e;
2021 
2022 // Return player_flags_e
get_player_state_flags(player_t * pp)2023 static byte  get_player_state_flags( player_t *  pp )
2024 {
2025     byte flags = 0;
2026     if( pp->autoaim_toggle )  flags |= PF_AUTOAIM;
2027     if( pp->originalweaponswitch )  flags |= PF_ORIGWEAPONSWITCH;
2028     if( pp->backpack )  flags |= PF_BACKPACK;
2029     return flags;
2030 }
2031 
2032 // Receive
2033 static uint32_t  playerdesc_gametic = 0;
2034 static byte  playerdesc_seq;   // bit per tic packet seq, ready=0xFF
2035 static byte  check_output_warn;
2036 
2037 // Initialize the playerdesc receive (conditionally on gametic).
2038 static
CL_init_playerdesc_receive(uint32_t r_gametic)2039 void  CL_init_playerdesc_receive( uint32_t r_gametic )
2040 {
2041     if( r_gametic != playerdesc_gametic )
2042     {
2043         playerdesc_seq = 0;
2044         playerdesc_gametic = r_gametic;
2045     }
2046 }
2047 
2048 static
check_output(unsigned int cv,unsigned int nv,const char * field,const char * msg)2049 void check_output( unsigned int cv, unsigned int nv, const char * field, const char * msg  )
2050 {
2051     if( cv != nv )
2052     {
2053         if( ! check_output_warn )
2054         {
2055             check_output_warn = 1;
2056             GenPrintf( EMSG_warn, "%s: ", msg );
2057         }
2058         GenPrintf( EMSG_warn, "  %s  client %x  server %x\n", field, cv, nv );
2059     }
2060 }
2061 
2062 
2063 // By Server.
2064 // Send the state of one or all players, within the caller supplied packet.
2065 // Packettype is already filled in by caller.
2066 //   pdesc : position of player_desc_t in netbuffer
2067 //   desc_flags : playerdesc_flags_e
2068 //   pn : player pid, or 255 for all players
2069 //   to_node : dest node
SV_Send_player_desc(player_desc_t * pdesc,byte desc_flags,byte pn,byte to_node)2070 static void SV_Send_player_desc( player_desc_t * pdesc, byte desc_flags, byte pn, byte to_node )
2071 {
2072     player_t *  pp;
2073     byte *  bufp;
2074     byte seq_num = 0;
2075     byte pn_end;
2076     byte errcode;
2077     int i;
2078     int entry_count;
2079     unsigned int paksize;
2080     unsigned int paksize_limit;
2081 
2082     // Limit how many can be in one packet.
2083     paksize_limit = sizeof( netbuffer->u );
2084     if( paksize_limit > software_MAXPACKETLENGTH )   paksize_limit = software_MAXPACKETLENGTH;
2085     paksize_limit -= offsetof(pd_player_t, optional) + 1;
2086 
2087     if( EN_inventory )
2088     {
2089         paksize_limit -= sizeof(pd_inventory_t);
2090     }
2091     else
2092     {
2093         desc_flags &= ~ PDI_inventory;
2094     }
2095 
2096     // Only those players that are present
2097     entry_count = 0;
2098     paksize = 0;
2099     bufp = (byte*) &pdesc->pd;
2100 
2101     if( pn < MAXPLAYERS )
2102     {
2103         // one player
2104         pn_end = pn;
2105     }
2106     else
2107     {
2108         // all players
2109         pn = 0;
2110         pn_end = MAXPLAYERS;
2111     }
2112 
2113     for(  ; pn<pn_end; pn++ )
2114     {
2115         if( ! playeringame[pn] )  continue;
2116 
2117         // As of 1.48: sizeof(netbuffer->u) = 4160, max paksize = 3072
2118         if( paksize > paksize_limit )
2119         {
2120             // Would exceed netbuffer, send as two packets
2121             pdesc->desc_flags = PDI_more | desc_flags | seq_num;
2122             errcode = HSendPacket(to_node, SP_reliable|SP_queue|SP_error_handler, 0, paksize);
2123             if( errcode >= NE_fail )  goto abort_send;
2124             entry_count = 0;
2125             seq_num++;
2126         }
2127 
2128         // Player state that would be valid during intermission, or repair.
2129         pp = &players[pn];
2130         if( ! pp )  continue;
2131 
2132         bufp = ALIGN4(bufp); // align to 4 bytes
2133 
2134         pd_player_t * pdp = (pd_player_t*) bufp;
2135         pdp->pid = pn;
2136         pdp->playerstate = pp->playerstate;  // DEAD
2137         pdp->health = LE_SWAP16( pp->health );
2138         pdp->armor = LE_SWAP16( pp->armorpoints );
2139         pdp->armortype = pp->armortype;
2140         pdp->readyweapon = pp->readyweapon;
2141         pdp->flags = get_player_state_flags( pp );
2142 
2143         SV_get_mobj( pp->mo, &pdp->pos );
2144 
2145         uint32_t wo = 0;
2146         for( i=0; i<NUMWEAPONS; i++)  // 19
2147             if( pp->weaponowned[i] )  wo |= 1<<i;
2148         pdp->weaponowned = LE_SWAP32( wo );
2149 
2150         for( i=0; i<NUMAMMO; i++ )
2151         {
2152             pdp->ammo[i] = LE_SWAP16( pp->ammo[i] );
2153             pdp->maxammo[i] = LE_SWAP16( pp->maxammo[i] );
2154         }
2155 
2156         // advance bufp upto the optional field
2157         bufp += offsetof( pd_player_t, optional );
2158 
2159         // Optional unaligned
2160         if( desc_flags & PDI_inventory )
2161         {
2162             pd_inventory_t * pdip = (pd_inventory_t*) bufp;
2163             pdip->inventoryslotnum = pp->inventorySlotNum;
2164 
2165             // Because it is a structure it might be aligned on some machines
2166             for( i=0; i<NUMINVENTORYSLOTS; i++ )
2167             {
2168                 pdip->inventory[i].type = pp->inventory[i].type;
2169                 pdip->inventory[i].count = pp->inventory[i].count;
2170             }
2171             bufp += sizeof( pd_inventory_t );
2172         }
2173 
2174         entry_count ++;
2175         pdesc->entry_count = entry_count;
2176         paksize = bufp - ((byte *)& netbuffer->u);
2177     }
2178 
2179     pdesc->desc_flags = desc_flags | seq_num;
2180     errcode = HSendPacket(to_node, SP_reliable|SP_queue|SP_error_handler, 0, paksize);
2181     if( errcode >= NE_fail )  goto abort_send;
2182     return;
2183 
2184 abort_send:
2185     // clean up
2186     return;
2187 }
2188 
2189 
2190 // By Client
2191 // PT_SERVERPLAYER, or PT_REPAIR
2192 //   msg : repair msg, otherwise NULL
2193 static
CL_player_desc_handler(player_desc_t * pdesc,const char * msg)2194 void  CL_player_desc_handler( player_desc_t * pdesc, const char * msg )
2195 {
2196     player_t *  pp;
2197     byte * bufp;
2198     int i;
2199     int entry_count = 0;
2200     byte desc_flags;
2201     byte seqbits;
2202     byte pn;
2203 
2204     desc_flags = pdesc->desc_flags;
2205     seqbits = 1 << (desc_flags & PDI_seq);
2206     if( ! (desc_flags & PDI_more) )  seqbits = -seqbits;  // 0x01=>0xFF, 0x08=>0xF8
2207     playerdesc_seq |= seqbits;  // record receiving this packet
2208 
2209     // Only those players that are present
2210     bufp = (byte*) &pdesc->pd;
2211     entry_count = pdesc->entry_count;
2212     for( ; entry_count > 0; entry_count-- )
2213     {
2214         bufp = ALIGN4(bufp); // align to 4 bytes
2215 
2216         pd_player_t * pdp = (pd_player_t*) bufp;
2217         bufp += offsetof( pd_player_t, optional );
2218 
2219         pn = pdp->pid;
2220         if( pn >= MAXPLAYERS )  break;
2221 
2222         pp = &players[pn];
2223         if( ! playeringame[pn] || ! pp )
2224         {
2225             // should not happen, skip over this entry
2226             if( desc_flags & PDI_inventory )
2227                 bufp += sizeof(pd_inventory_t);
2228             continue;
2229         }
2230 
2231         // Player state that would be valid during intermission.
2232         check_output_warn = 0;  // reset msg header
2233 
2234         uint16_t r_health = LE_SWAP16( pdp->health );
2235         uint16_t r_armorpoints = LE_SWAP16( pdp->armor );
2236 
2237         if( msg )
2238         {
2239             check_output( pp->playerstate, pdp->playerstate, "PLAYERSTATE", msg );
2240             check_output( pp->health, r_health, "HEALTH", msg );
2241             check_output( pp->armorpoints, r_armorpoints, "ARMORPOINTS", msg );
2242             check_output( pp->armortype, pdp->armortype, "ARMORTYPE", msg );
2243             check_output( pp->readyweapon, pdp->readyweapon, "READYWEAPON", msg );
2244         }
2245 
2246         pp->playerstate = pdp->playerstate;  // DEAD
2247         pp->health = r_health;
2248         pp->armorpoints = r_armorpoints;
2249         pp->armortype = pdp->armortype;
2250         pp->readyweapon = pdp->readyweapon;
2251 
2252         CL_set_mobj( &pdp->pos, MT_PLAYER, msg, /*OUT*/ pp->mo, &(pp->mo) );
2253 
2254         byte flags = pdp->flags;
2255         if( msg )
2256         {
2257             byte cflags = get_player_state_flags( pp );
2258             check_output( cflags, flags, "FLAGS", msg );
2259         }
2260         pp->autoaim_toggle = ( flags & PF_AUTOAIM )? 1:0;
2261         pp->originalweaponswitch = ( flags & PF_ORIGWEAPONSWITCH )? 1:0;
2262         pp->backpack = ( flags & PF_BACKPACK )? 1:0;
2263 
2264         uint32_t wo = LE_SWAP32( pdp->weaponowned );
2265         uint32_t cwo = 0;
2266         for( i=0; i<NUMWEAPONS; i++)  // 19
2267         {
2268             if( pp->weaponowned[i] )  cwo |= 1<<i;
2269             pp->weaponowned[i] = ( wo & (1<<i) )? 1:0;
2270         }
2271         if( msg )
2272         {
2273             check_output( cwo, wo, "WEAPONOWNED", msg );
2274         }
2275 
2276         for( i=0; i<NUMAMMO; i++ )
2277         {
2278             uint16_t r_ammo = LE_SWAP16( pdp->ammo[i] );
2279             uint16_t r_maxammo = LE_SWAP16( pdp->maxammo[i] );
2280             if( msg )
2281             {
2282                 // Not going to be specific about which ammo is wrong.
2283                 check_output( pp->ammo[i], r_ammo, "AMMO", msg );
2284                 check_output( pp->maxammo[i], r_maxammo, "MAXAMMO", msg );
2285             }
2286             pp->ammo[i] = r_ammo;
2287             pp->maxammo[i] = r_maxammo;
2288         }
2289 
2290         // Optional unaligned
2291         if( desc_flags & PDI_inventory )
2292         {
2293             pd_inventory_t * pdip = (pd_inventory_t*) bufp;
2294             if( msg )
2295             {
2296                 check_output( pp->inventorySlotNum, pdip->inventoryslotnum, "INVENTORYSLOTNUM", msg );
2297             }
2298             pp->inventorySlotNum = pdip->inventoryslotnum;
2299 
2300             // Because it is a structure it might be aligned on some machines
2301             for( i=0; i<NUMINVENTORYSLOTS; i++ )
2302             {
2303                 if( msg )
2304                 {
2305                     // Not going to be specific about which inventory is wrong.
2306                     check_output( pp->inventory[i].type, pdip->inventory[i].type, "INVENTORY_TYPE", msg );
2307                     check_output( pp->inventory[i].count, pdip->inventory[i].count, "INVENTORY_COUNT", msg );
2308                 }
2309                 pp->inventory[i].type = pdip->inventory[i].type;
2310                 pp->inventory[i].count = pdip->inventory[i].count;
2311             }
2312             bufp += sizeof(pd_inventory_t);
2313         }
2314     }
2315 }
2316 
2317 
2318 // ---- Client Update Savegame
2319 
2320 #ifdef JOININGAME
2321 
2322 // [WDJ] For little-endian and big-endian machines to play together, must fix savegames.
2323 // Each machine writes savegames in its native format, and must be able
2324 // to read its own older savegames, so cannot just change to LE savegames.
2325 // A big-endian machine needs to be able to read either endian savegames.
2326 // Other possibilities require also changing the write of savegames, at least for big-endian servers.
2327 
2328 // By Server.
2329 // Send a save game to the client.
SV_Send_SaveGame(int to_node)2330 static void SV_Send_SaveGame(int to_node)
2331 {
2332     size_t  length;
2333 
2334     SV_network_wait_timer( 90 );  // pause game during download
2335 
2336     P_Alloc_savebuffer( 1 );	// large buffer, but no header
2337     if(! savebuffer)   goto buffer_err;
2338 
2339     P_Savegame_Write_header( NULL, 1 );  // Netgame header
2340     P_Savegame_Save_game();  // fill buffer with game data
2341     // buffer will automatically grow as needed.
2342 
2343     length = P_Savegame_length();
2344     if( length < 0 )   goto buffer_err;	// overrun buffer
2345 
2346     // then send it !
2347     SV_SendData(to_node, "SAVEGAME", savebuffer, length, TAH_MALLOC_FREE, SAVEGAME_FILEID);
2348     // SendData frees the savebuffer using free() after it is sent.
2349     // This is the only use of TAH_MALLOC_FREE.
2350 
2351     // Wait for reply. Let wait timer do unpause.
2352     return;
2353 
2354 buffer_err:
2355     GenPrintf(EMSG_error, "Send_savegame: cannot allocate large enough buffer\n" );
2356     return;
2357 }
2358 
2359 // Dummy name for a savegame file.
2360 static const char *tmpsave="$$$.sav";
2361 
2362 // By Client.
2363 // Act upon the received save game from server.
2364 // Success: cl_mode = CLM_download_done
2365 // Fail:    cl_mode = CLM_fatal
CL_Load_Received_Savegame(void)2366 static void CL_Load_Received_Savegame(void)
2367 {
2368     savegame_info_t   sginfo;  // read header info
2369 
2370     // Use savebuffer and save_p from p_saveg.c.
2371     // There cannot be another savegame in progress when this occurs.
2372     // [WDJ] Changed to use new load savegame file, with smaller buffer.
2373     if( P_Savegame_Readfile( tmpsave ) < 0 )  goto cannot_read_file;
2374     // file is open and savebuffer allocated
2375 
2376     // Read netgame header.
2377     sginfo.msg[0] = 0;
2378     if( ! P_Savegame_Read_header( & sginfo, 1 ) )  goto load_failed;
2379 
2380     GenPrintf(EMSG_hud, "Loading savegame\n");
2381 
2382     G_setup_VERSION();
2383 
2384     // Sever will control pause during download.
2385     demoplayback  = false;
2386     automapactive = false;
2387 
2388     // load a base level
2389     playerdeadview = false;
2390 
2391     P_Savegame_Load_game(); // read game data in savebuffer, defer error test
2392     if( P_Savegame_Closefile( 0 ) < 0 )  goto load_failed;
2393     // savegame buffer deallocated, and file closed
2394 
2395     // done
2396     unlink(tmpsave);  // delete file (posix)
2397     consistency[ BTIC_INDEX( gametic ) ] = Consistency();
2398     CON_ToggleOff ();
2399 
2400     cl_mode = CLM_download_done;
2401     return;
2402 
2403 cannot_read_file:
2404     I_SoftError ("Can't read savegame sent\n");
2405     goto failed_exit; // must deallocate savebuffer
2406 
2407 load_failed:
2408     GenPrintf(EMSG_error, "Can't load the level !!!\n%s", sginfo.msg);
2409 failed_exit:
2410     // needed when there are error tests before Closefile.
2411     P_Savegame_Error_Closefile();  // deallocate savebuffer
2412     cl_mode = CLM_fatal;
2413     return;
2414 }
2415 
2416 #endif
2417 
2418 
2419 
2420 // ----- Consistency fail, repair position.
2421 
2422 static repair_type_e  active_repair_type = 0;
2423 
fill_repair_header(byte repair_type)2424 static void  fill_repair_header( byte repair_type )
2425 {
2426     netbuffer->packettype = PT_REPAIR;
2427     netbuffer->u.repair.repair_type = repair_type;
2428     // The fields are there, so fill them.  Easier to fill them everytime.
2429     write_N32( & netbuffer->u.repair.gametic, gametic );
2430     get_random_state( & netbuffer->u.repair.rs ); // to sync P_Random
2431 }
2432 
2433 // By Server.
2434 // Send a player repair message.
2435 //   pn : player_id, 255 for all players
2436 //   severity : 0..3, see cv_netrepair
2437 //   to_node : the net node
SV_Send_player_repair(byte pn,byte severity,byte to_node)2438 static void SV_Send_player_repair( byte pn, byte severity, byte to_node )
2439 {
2440     const char * fail_msg = "";
2441     byte desc_flags = PDI_inventory;
2442 
2443     if( severity < 2 )  desc_flags = 0;
2444     if( cv_SV_netrepair.EV < 2 )  desc_flags = 0;
2445 
2446     if( pn < MAXPLAYERS )
2447     {
2448         if( ! playeringame[pn] )
2449         {
2450             fail_msg = ", not in game";
2451             goto msg_out;
2452         }
2453 
2454         mobj_t * mo = players[pn].mo;
2455         if( ! mo )
2456         {
2457             fail_msg = ", no mobj";
2458             goto msg_out;
2459         }
2460     }
2461 
2462     // Enough to fix a small difference in player position.
2463     fill_repair_header( RQ_PLAYER );
2464     SV_Send_player_desc( & netbuffer->u.repair.u.player_desc, desc_flags, pn, to_node );
2465 
2466 msg_out:
2467     if( pn < MAXPLAYERS )
2468     {
2469         GenPrintf( EMSG_warn, "Server Send_player_repair: player %i%s\n", pn, fail_msg );
2470     }
2471     else
2472     {
2473         GenPrintf( EMSG_warn, "Server Send_player_repair: ALL player\n", pn );
2474     }
2475     return;
2476 }
2477 
2478 // By Client.
2479 // Repair the player from the repair message in the netbuffer.
CL_player_repair(void)2480 static void CL_player_repair( void )
2481 {
2482     // ignore random state for now
2483 
2484     // Compare gametic as packet field, not as a tic_t
2485     uint32_t  r_gametic = read_N32( & netbuffer->u.repair.gametic );
2486 
2487     // Receive all player desc.
2488     CL_init_playerdesc_receive( r_gametic );
2489     CL_player_desc_handler( & netbuffer->u.repair.u.player_desc, "Client player_repair" );
2490 }
2491 
2492 
2493 // By Server.
2494 //  repair_type : RQ_SUG_SAVEGAME
2495 //  to_node : to the player node
SV_Send_repair(byte repair_type,byte to_node)2496 static void SV_Send_repair( byte repair_type, byte to_node )
2497 {
2498     // simple messages
2499     fill_repair_header( repair_type );
2500     byte errcode = HSendPacket(to_node, SP_reliable|SP_queue, 0, sizeof(repair_pak_t));
2501     if( errcode >= NE_fail )
2502     {
2503         nnode_state[to_node] = NOS_fatal;
2504         generic_network_error_handler( errcode, "Send Repair" );
2505     }
2506     return;
2507 }
2508 
2509 
2510 // By Client.
2511 //  repair_type : RQ_REQ_SAVEGAME, RQ_REQ_PLAYER, RQ_CLOSE_ACK
CL_Send_Req_repair(repair_type_e repair_type)2512 static void CL_Send_Req_repair( repair_type_e repair_type )
2513 {
2514     fill_repair_header( repair_type );
2515     playerdesc_seq = 0;  // ready to receive
2516     byte errcode = HSendPacket(cl_servernode, SP_reliable|SP_queue, 0, sizeof(repair_pak_t));
2517     if( errcode >= NE_fail )
2518     {
2519         network_state = NETS_fatal;
2520         generic_network_error_handler( errcode, "Send Repair" );
2521     }
2522 }
2523 
2524 
2525 // [WDJ] Attempt to fix consistency errors.
2526 // PT_REPAIR
2527 // By Client
repair_handler_client(byte nnode)2528 static void repair_handler_client( byte nnode )
2529 {
2530     // Message is PT_REPAIR
2531     byte rq_type = netbuffer->u.repair.repair_type;
2532 
2533     if( server )
2534         return;  // Ignore attempts to corrupt server.
2535 
2536     if( rq_type < RQ_REQ_TO_SERVER )
2537     {
2538         // Server repairs client.
2539         uint32_t net_gametic = read_N32( & netbuffer->u.repair.gametic );
2540         if( gametic != net_gametic )
2541         {
2542             GenPrintf( EMSG_warn, "Client repair: gametic client %u  server %u\n", gametic, net_gametic );
2543             gametic = net_gametic;
2544         }
2545         random_state_checkset( & netbuffer->u.repair.rs, NULL, SET_RANDOM ); // to sync P_Random
2546     }
2547 
2548     switch( rq_type )
2549     {
2550      case RQ_SUG_SAVEGAME:
2551 #ifdef JOININGAME
2552         // CLIENT: Server suggests downloading a savegame from the server.
2553         if(( cv_download_savegame.EV == 0 ) || ( cv_netrepair.EV < 2 ))
2554         {
2555             CL_Send_Req_repair( RQ_REQ_PLAYER ); // to server
2556             break;
2557         }
2558 
2559         // Client: prepare for savegame download.
2560         cl_mode = CLM_download_savegame;
2561         CL_Prepare_download_savegame(tmpsave);
2562         CL_Send_Req_repair( RQ_REQ_SAVEGAME ); // to server
2563         // Loop here while savegame is downloaded.
2564         while( netfile_download )
2565         {
2566             Net_Packet_Handler();
2567             if( network_state < NETS_active )  // Need client to server connection
2568                 goto reset_to_title_exit;  // connection closed by cancel or timeout
2569 #if 1
2570             if( !server && !netgame )
2571                 goto reset_to_title_exit;  // connection closed by cancel or timeout
2572 #endif
2573 
2574             Net_AckTicker();
2575 
2576             // Operations performed only once every tic.
2577             if( cl_prev_tic != I_GetTime() )
2578             {
2579                 cl_prev_tic = I_GetTime();
2580 
2581                 // User response handler
2582                 I_OsPolling();
2583                 switch( I_GetKey() )
2584                 {
2585                   case 'q':
2586                   case KEY_ESCAPE:
2587                      goto reset_to_title_exit;
2588                 }
2589 
2590                 // Server upkeep
2591                 if( Filetx_file_cnt )  // File download in progress.
2592                     Filetx_Ticker();
2593             }
2594         }
2595 
2596         // Have received the savegame from the server.
2597         CL_Load_Received_Savegame();  // CLM_download_done, or CLM_fatal
2598         if( cl_mode != CLM_download_done )
2599         {
2600             GenPrintf( EMSG_error, "Client player_repair: savegame failed\n" );
2601             if( cv_netrepair.EV < 3 )  goto reset_to_title_exit;
2602             // aggressive
2603             if( cl_error_status > 2 )  goto reset_to_title_exit;
2604             cl_error_status = 3;  // retry once
2605             // Try again
2606             CL_Send_Req_repair( RQ_REQ_SAVEGAME ); // to server
2607             break;
2608         }
2609         // Download done
2610         goto close_repair;
2611 #else
2612         CL_Send_Req_repair( RQ_REQ_PLAYER ); // to server
2613 #endif
2614         break;
2615 
2616      case RQ_SAVEGAME_REJ:
2617         // Server rejects savegame.
2618         CL_Send_Req_repair( RQ_REQ_PLAYER ); // to server
2619         break;
2620 
2621      case RQ_PLAYER:
2622         // Server repairs player position.
2623         CL_player_repair();
2624         consistency[ BTIC_INDEX( gametic ) ] = Consistency();
2625         if( playerdesc_seq == 0xFF )  goto close_repair; // all parts of player desc received
2626         break;
2627 
2628      default:
2629         break;
2630     }
2631     return;
2632 
2633 close_repair:
2634     cl_mode = CLM_connected;
2635 
2636     // Client closes the repair state.
2637     if( cl_mode != CLM_fatal )
2638         CL_Send_Req_repair( RQ_CLOSE_ACK ); // to server
2639     cl_error_status = 1;
2640     active_repair_type = RQ_NULL;
2641     return;
2642 
2643 reset_to_title_exit:
2644     if( cl_mode != CLM_fatal )
2645         D_Quit_NetGame(); // to server
2646     CL_Reset();
2647     D_StartTitle();
2648     active_repair_type = RQ_NULL;
2649     return;
2650 }
2651 
2652 // PT_REPAIR
2653 // By Server only.
repair_handler_server(byte nnode)2654 static void repair_handler_server( byte nnode )
2655 {
2656     // Message is PT_REPAIR
2657     random_state_checkset( & netbuffer->u.repair.rs, "Repair", 0 ); // to check P_Random
2658     byte rq_type = netbuffer->u.repair.repair_type;
2659     switch( rq_type )
2660     {
2661      case RQ_REQ_SAVEGAME:
2662         // Client has requested a savegame repair
2663 #ifdef JOININGAME
2664         if( (cv_SV_download_savegame.EV == 0) || (cv_SV_netrepair.EV < 2) )
2665         {
2666             GenPrintf(EMSG_info, "Repair: Send savegame not allowed\n" );
2667         }
2668         else if(gamestate == GS_LEVEL)
2669         {
2670             nnode_state[nnode] = NOS_repair_savegame;
2671             SV_Send_SaveGame( nnode ); // send game data
2672             // netwait timer is running
2673             GenPrintf(EMSG_info, "Repair: Send savegame\n");
2674             // Client will return  RQ_REQ_SAVEGAME, RQ_REQ_PLAYER, RQ_CLOSE_ACK, or PT_CLIENTQUIT
2675             break;
2676         }
2677 #else
2678         GenPrintf(EMSG_info, "Repair: Send savegame not allowed, no Join-in-game.\n" );
2679 #endif
2680         SV_Send_repair( RQ_SAVEGAME_REJ, nnode );
2681         break;
2682 
2683      case RQ_REQ_ALLPLAYER:
2684         netbuffer->u.repair.u.player_id = 255;  // all players in game
2685      case RQ_REQ_PLAYER:
2686         // Client has requested a player repair
2687         SV_network_wait_timer( 18 );  // keep alive
2688         nnode_state[nnode] = NOS_repair_player;
2689         SV_Send_player_repair( netbuffer->u.repair.u.player_id, 3, nnode );
2690         break;
2691 
2692      case RQ_CLOSE_ACK:
2693         // Client is ending the repair.
2694 //        random_state_checkset( & netbuffer->u.repair.rs, "Repair Close", 0 ); // to check P_Random
2695         nnode_state[nnode] = NOS_active;
2696         GenPrintf(EMSG_warn, "Repair: closed.\n" );
2697         SV_network_wait_handler();
2698         break;
2699 
2700      default:
2701         break;
2702     }
2703 }
2704 
2705 
2706 // ----- Wait for Server to start net game.
2707 //#define WAITPLAYER_DEBUG
2708 
2709 static byte  num_netnodes;
2710 static byte  num_netplayer;  // wait for netplayer, some nodes are 2 players
2711 static tic_t wait_tics  = 0;
2712 
2713 // By Server
SV_Send_NetWait(void)2714 static void SV_Send_NetWait( void )
2715 {
2716     netbuffer->packettype = PT_NETWAIT;
2717     netbuffer->u.netwait.num_netplayer = num_netplayer;
2718     netbuffer->u.netwait.wait_netplayer = wait_netplayer;
2719     netbuffer->u.netwait.wait_tics = LE_SWAP16( wait_tics );
2720     get_random_state( & netbuffer->u.netwait.rs ); // to sync P_Random
2721 #ifdef WAITPLAYER_DEBUG
2722     debug_Printf( "WaitPlayer update: num_netnodes=%d num_netplayer=%d  wait_netplayer=%d  wait_tics=%d\n",
2723                num_netnodes, num_netplayer, wait_netplayer, wait_tics );
2724     SV_SendPacket_All( false, sizeof(netwait_pak_t), "  sent to player" );
2725 #else
2726     SV_SendPacket_All( false, sizeof(netwait_pak_t), NULL );
2727 #endif
2728 }
2729 
2730 // By Client
netwait_handler(void)2731 static void netwait_handler( void )
2732 {
2733     // Updates of wait for players, from the server.
2734     num_netplayer = netbuffer->u.netwait.num_netplayer;
2735     wait_netplayer = netbuffer->u.netwait.wait_netplayer;
2736     wait_tics = LE_SWAP16( netbuffer->u.netwait.wait_tics );
2737     random_state_checkset( & netbuffer->u.netwait.rs, NULL, SET_RANDOM ); // to sync P_Random
2738 }
2739 
2740 // Called from D_Display when GS_WAITINGPLAYERS, CL_ConnectToServer?
D_WaitPlayer_Drawer(void)2741 void D_WaitPlayer_Drawer( void )
2742 {
2743     WI_Draw_wait( num_netnodes, num_netplayer, wait_netplayer, wait_tics );
2744 }
2745 
2746 // Called by Menu M_StartServer
D_WaitPlayer_Setup(void)2747 void D_WaitPlayer_Setup( void )
2748 {
2749     if( netgame )
2750     {
2751         if( server )
2752         {
2753             // Wait for all player nodes, during netgame.
2754             wait_netplayer = cv_wait_players.value;
2755             wait_tics = cv_wait_timeout.value * TICRATE;
2756         }
2757         else
2758         {
2759             // Wait indefinite, until server updates the wait.
2760             wait_netplayer = 99;
2761             wait_tics = 0;
2762         }
2763     }
2764     else
2765     {
2766         // Single player and local games.
2767         wait_netplayer = 0;
2768         wait_tics = 0;
2769     }
2770     gamestate = wipegamestate = GS_WAITINGPLAYERS;
2771 }
2772 
2773 // Return true when start game.
D_WaitPlayer_Ticker(void)2774 static boolean  D_WaitPlayer_Ticker(void)
2775 {
2776     int  nn;
2777 
2778     if( server )
2779     {
2780         // Count the net nodes.
2781         num_netnodes=0;
2782         num_netplayer=0;
2783         for(nn=0; nn<MAXNETNODES; nn++)
2784         {
2785             // Only counting nodes with players.
2786             if( nnode_state[nn] >= NOS_client )
2787             {
2788                 if( playerpernode[nn] > 0 )
2789                 {
2790                     num_netnodes ++;
2791                     num_netplayer += playerpernode[nn];
2792                 }
2793             }
2794         }
2795 
2796         if( wait_tics > 0 || wait_netplayer > 0 )
2797         {
2798             // Service the wait tics.
2799             if( wait_tics > 1 )
2800             {
2801                 wait_tics--;  // count down to 1
2802             }
2803 
2804             static  byte net_update_cnt = 0;
2805             if( ++net_update_cnt > 4 )
2806             {
2807                 net_update_cnt = 0;
2808                 // Update all net nodes
2809                 SV_Send_NetWait();
2810             }
2811         }
2812     }
2813 
2814     // Clients and Server do same tests.
2815     if( wait_netplayer > 0 )
2816     {
2817         // Waiting on player net nodes, with or without timeout.
2818         if( num_netplayer < wait_netplayer )
2819         {
2820             // Waiting for player net nodes.
2821             if( wait_tics != 1 )  // timeout at 1
2822                goto wait_ret;  // waiting only for number of players
2823         }
2824     }
2825     else if( wait_tics > 1 )
2826         goto wait_ret;  // waiting for players by timeout
2827 
2828     if( server )
2829     {
2830         // All nodes need to get info to stop waiting.
2831         SV_Send_NetWait();
2832 #ifdef WAITPLAYER_DEBUG
2833         debug_Printf( "Start game sent to players at tic=%d\n", gametic   );
2834 #endif
2835     }
2836     return true;  // start game
2837 
2838 
2839 wait_ret:
2840     return false;  // keep waiting
2841 }
2842 
D_WaitPlayer_Response(int key)2843 boolean  D_WaitPlayer_Response( int key )
2844 {
2845     // [WDJ] This should not respond to the ENTER key.  Users will be pressing ENTER quickly and often.
2846     // This message will stop them, and only the correct response will start the unreversible action.
2847 
2848     // Translate for joystick.  The PAUSE is not otherwise used during WAITPLAYER and does not conflict.
2849     if( key == gamecontrol[gc_pause][0] || key == gamecontrol[gc_pause][1]
2850         || (key >= KEY_JOY0BUT2 && key <= KEY_JOY0BUT5 ) )
2851         key = 's';
2852 
2853     // User response handler
2854     switch( key )
2855     {
2856      // Also gc_menuesc (translated to KEY_ESCAPE)
2857      case 'q':
2858      case KEY_ESCAPE:
2859         if( ! dedicated )
2860         {
2861             D_Quit_NetGame();
2862             SV_StopServer();
2863             SV_ResetServer();
2864             D_StartTitle();
2865             netgame = multiplayer = false;
2866             return true;
2867         }
2868         break;
2869      case 's':
2870         if( server )
2871         {
2872             // Start game, stop waiting for player nodes.
2873             wait_netplayer = 0;
2874             wait_tics = 0;
2875             SV_Send_NetWait();
2876 #ifdef WAITPLAYER_DEBUG
2877             debug_Printf( "Start game (key) sent at tic=%d\n", gametic );
2878 #endif
2879             return true;
2880         }
2881         break;
2882     }
2883     return false;
2884 }
2885 
2886 
2887 // ----- Connect to Server
2888 
2889 // By Client.
2890 // Ask the server for some info.
2891 //   to_node : when BROADCAST_NODE then all servers will respond
2892 // Called by: CL_Broadcast_AskInfo, CL_Update_ServerList, CL_ConnectToServer
CL_Send_AskInfo(byte to_node)2893 static void CL_Send_AskInfo( byte to_node )
2894 {
2895     netbuffer->packettype = PT_ASKINFO;
2896     netbuffer->u.askinfo.version = VERSION;
2897     netbuffer->u.askinfo.ver1 = 0;
2898     netbuffer->u.askinfo.ver2 = VERSION;
2899     netbuffer->u.askinfo.ver3 = REVISION;
2900     netbuffer->u.askinfo.send_time = LE_SWAP32(I_GetTime());
2901     HSendPacket( to_node, 0, 0, sizeof(askinfo_pak_t) );  // msg lost when too busy
2902 }
2903 
2904 
2905 // By Client.
2906 // Broadcast to find some servers.
2907 //   addrstr: broadcast addr string
2908 // Called by: CL_Update_ServerList
CL_Broadcast_AskInfo(char * addrstr)2909 static void CL_Broadcast_AskInfo( char * addrstr )
2910 {
2911     // Modifies the broadcast address.
2912     if( addrstr
2913         && Bind_Node_str( BROADCAST_NODE, addrstr, server_sock_port ) )
2914     {
2915 //        debugPrintf( "CL_Broadcast_AskInfo  server_sock_port = %d\n", server_sock_port );
2916 
2917         CL_Send_AskInfo( BROADCAST_NODE );
2918     }
2919 }
2920 
2921 
2922 // --- ServerList
2923 
2924 server_info_t serverlist[MAXSERVERLIST];
2925 int serverlistcount=0;
2926 
2927 // Clear the serverlist, closing connections.
2928 //  keep_node: except this server node
SL_Clear_ServerList(int keep_node)2929 static void SL_Clear_ServerList( int keep_node )
2930 {
2931     int i;
2932     for( i=0; i<serverlistcount; i++ )
2933     {
2934         if( serverlist[i].server_node != keep_node )
2935         {
2936             Net_CloseConnection(serverlist[i].server_node, 0);
2937             serverlist[i].server_node = 0;
2938         }
2939     }
2940     serverlistcount = 0;
2941 }
2942 
2943 // Find the server in the serverlist.
2944 // Called by: SL_InsertServer, CL_ConnectToServer
SL_Find_Server(byte nnode)2945 static int SL_Find_Server( byte nnode )
2946 {
2947     int i;
2948     for( i=0; i<serverlistcount; i++ )
2949     {
2950         if( serverlist[i].server_node == nnode )
2951             return i;
2952     }
2953 
2954     return -1;
2955 }
2956 
2957 // Insert the server into the serverlist.
SL_InsertServer(serverinfo_pak_t * info,byte nnode)2958 static void SL_InsertServer( serverinfo_pak_t * info, byte nnode)
2959 {
2960     tic_t  test_time;
2961     server_info_t se;
2962     int i, i2;
2963 
2964     // search if not already on it
2965     i = SL_Find_Server( nnode );
2966     if( i < 0 )
2967     {
2968         // not found add it
2969         if( serverlistcount >= MAXSERVERLIST )
2970             return; // list full
2971         i=serverlistcount++;  // last entry
2972     }
2973 
2974     // Update info
2975     serverlist[i].info = *info;
2976     serverlist[i].server_node = nnode;
2977 
2978     // List is sorted by trip_time (has been converted to ping time)
2979     // so move the entry until it is sorted (shortest time to [0]).
2980     se = serverlist[i];  // this is always the updated entry
2981     test_time = info->trip_time;
2982     for(;;) {
2983         i2 = i;  // prev position of updated entry
2984         if( i>0
2985             && test_time < serverlist[i-1].info.trip_time )
2986         {
2987             i--;
2988         }
2989         else
2990         if( (i+1)<serverlistcount
2991             && test_time > serverlist[i+1].info.trip_time )
2992         {
2993             i++;
2994         }
2995         else
2996             break;  // done
2997         serverlist[i2] = serverlist[i];  // move other to prev position
2998         serverlist[i] = se;  // new position
2999     }
3000 }
3001 
3002 // By user, future Client.
3003 // Called by M_Connect.
CL_Update_ServerList(boolean internetsearch)3004 void CL_Update_ServerList( boolean internetsearch )
3005 {
3006     int  i;
3007 
3008     SL_Clear_ServerList(0);
3009 
3010     if( !netgame )
3011     {
3012         server = false;  // To get correct port
3013         if( ! I_NetOpenSocket() )  return;  // failed to get socket
3014 
3015         netgame = true;
3016         multiplayer = true;
3017         network_state = NETS_open;
3018         quit_netgame_status = 0;
3019     }
3020 
3021     // Search for local servers.
3022     CL_Broadcast_AskInfo( cv_server1.string );
3023     CL_Broadcast_AskInfo( cv_server2.string );
3024     CL_Broadcast_AskInfo( cv_server3.string );
3025 
3026     if( internetsearch )
3027     {
3028         msg_server_t *server_list;
3029 
3030         server_list = MS_Get_ShortServersList();
3031         if( server_list )
3032         {
3033             // Poll the servers on the list to get ping time.
3034             for (i=0; server_list[i].header[0]; i++)
3035             {
3036                 int  node;
3037                 char addr_str[24];
3038 
3039                 // insert ip (and optionaly port) in node list
3040                 sprintf(addr_str, "%s:%s", server_list[i].ip, server_list[i].port);
3041                 node = I_NetMakeNode(addr_str);
3042                 if( node >= MAXNETNODES )
3043                     break; // no more node free
3044 
3045                 CL_Send_AskInfo( node );
3046             }
3047         }
3048     }
3049 }
3050 
3051 
3052 
3053 // ----- Connect to Server
3054 
3055 // By User, future Client, and by server not dedicated.
3056 // Use adaptive send using net_bandwidth and stat.sendbytes.
3057 // Called by Command_connect, SV_SpawnServer
3058 //   cl_servernode: if set then reconnect, else search
CL_ConnectToServer(void)3059 static void CL_ConnectToServer( void )
3060 {
3061     int  i;
3062     tic_t   askinfo_tic = 0;  // to repeat askinfo
3063 
3064     if( network_state < NETS_open )
3065          goto reset_to_title_exit;  // connection closed by cancel or timeout
3066 
3067     network_state = NETS_connecting;
3068 
3069     cl_mode = CLM_searching;
3070     D_WaitPlayer_Setup();
3071 
3072     if( cl_servernode >= MAXNETNODES )
3073     {
3074         // init value and BROADCAST_NODE
3075         GenPrintf(EMSG_hud, "Searching for a DoomLegacy server ...\n");
3076     }
3077     else
3078         GenPrintf(EMSG_hud, "Contacting the DoomLegacy server ...\n");
3079 
3080     DEBFILE(va("Waiting %d players\n", wait_netplayer));
3081 
3082     SL_Clear_ServerList(cl_servernode);  // clear all except the current server
3083 
3084     GenPrintf(EMSG_hud, "Press Q or ESC to abort\n");
3085     // Every player goes through here to connect to game, including a
3086     // single player on the server.
3087     // Loop until connected or user escapes.
3088     // Because of the combination above, this loop must include code for
3089     // server responding.
3090     do
3091     {
3092         // Because of console draw in the loop
3093         V_SetupDraw( 0 | V_SCALESTART | V_SCALEPATCH | V_CENTERHORZ );
3094 
3095         switch(cl_mode) {
3096             case CLM_searching :
3097                 // serverlist is updated by GetPacket function
3098                 if( serverlistcount > 0 )
3099                 {
3100                     cl_mode = CLM_server_files;
3101                     break;
3102                 }
3103                 // Don't have a serverlist.
3104                 // Poll the server (askinfo packet).
3105                 if( askinfo_tic <= I_GetTime() )
3106                 {
3107                     // Don't be noxious on the network.
3108                     // Every 2 seconds is often enough.
3109                     askinfo_tic = I_GetTime() + (TICRATE*2);
3110                     if( cl_servernode < MAXNETNODES )
3111                     {
3112                         // Specific server.
3113                         CL_Send_AskInfo(cl_servernode);
3114                     }
3115                     else
3116                     {
3117                         // Any
3118                         CL_Update_ServerList( false );
3119                     }
3120                 }
3121                 break;
3122             case CLM_server_files :
3123                 // Have a serverlist, serverlistcount > 0.
3124                 // This can be a response to our broadcast request
3125                 if( cl_servernode < MAXNETNODES )
3126                 {
3127                     // Have a current server.  Find it in the serverlist.
3128                     i = SL_Find_Server(cl_servernode);
3129                     // Check if it shutdown, or is missing for some reason.
3130                     if (i<0)
3131                         return;  // go back to user
3132                 }
3133                 else
3134                 {
3135                     // Invalid cl_servernode, get best server from serverlist.
3136                     i = 0;
3137                     cl_servernode = serverlist[i].server_node;
3138                     GenPrintf(EMSG_hud, " Found, ");
3139                 }
3140                 // Check server for files needed.
3141                 CL_Got_Fileneed(serverlist[i].info.num_fileneed,
3142                                 serverlist[i].info.fileneed    );
3143                 GenPrintf(EMSG_hud, " Checking files ...\n");
3144                 switch( CL_CheckFiles() )
3145                 {
3146                  case CFR_no_files:
3147                  case CFR_all_found:
3148                     cl_mode = CLM_askjoin;
3149                     break;
3150                  case CFR_download_needed:
3151                     cl_mode = CLM_download_req;
3152                     break;
3153                  case CFR_iwad_error: // cannot join for some reason
3154                  case CFR_insufficient_space:
3155                  default:
3156                     goto reset_to_title_exit;
3157                 }
3158                 break;
3159             case CLM_download_req:
3160                 // Must download something.
3161                 // Check -nodownload switch, cv_download_files, or request downloads.
3162                 switch( Send_RequestFile() )
3163                 {
3164                  case RFR_success:
3165                     Net_GetNetStat();  // init for later display
3166                     cl_mode = CLM_download_files;
3167                     break;
3168                  case RFR_send_fail:
3169                     break;  // retry later
3170                  case RFR_insufficient_space: // Does not seem to be used.
3171                  case RFR_nodownload:
3172                  default:
3173                     // Due to -nodownload switch, or other fatal error.
3174                     goto  reset_to_title_exit;
3175                 }
3176                 break;
3177             case CLM_download_files :
3178                 // Wait test, and display loading files.
3179                 if( CL_waiting_on_fileneed() )
3180                     break; // continue looping
3181                 // Have all downloaded files.
3182                 cl_mode = CLM_askjoin;
3183                 // continue into next case
3184             case CLM_askjoin :
3185                 if( ! CL_Load_ServerFiles() )
3186                 {
3187                     // Cannot load some file.
3188                     goto  reset_to_title_exit;
3189                 }
3190 #ifdef JOININGAME
3191                 // prepare structures to save the file
3192                 // WARNING: this can be useless in case of server not in GS_LEVEL
3193                 // but since the network layer don't provide ordered packet ...
3194                 // This can be repeated, if CL_Send_Join fails.
3195                 CL_Prepare_download_savegame(tmpsave);
3196 #endif
3197                 if( CL_Send_Join() )  // join game
3198                     cl_mode = CLM_wait_join_response;
3199                 if( network_state < NETS_connecting )  // Need client to server connection
3200                     goto reset_to_searching;
3201 #if 1
3202                 if( !server && !netgame )
3203                     goto reset_to_searching;
3204 #endif
3205                 break;
3206             case CLM_wait_join_response :
3207                 // waiting for server response
3208                 // see server_cfg_handler()
3209                 break;
3210             case CLM_download_savegame :
3211                 // client, download a savegame
3212 #ifdef JOININGAME
3213                 M_DrawTextBox( 2, NETFILE_BOX_Y, 38, 4);
3214                 V_DrawString (30, NETFILE_BOX_Y+8, 0, "Download Savegame");
3215                 if( netfile_download )
3216                     break; // continue loop
3217 
3218                 // Have received the savegame from the server.
3219                 CL_Load_Received_Savegame();
3220                 if( cl_mode != CLM_download_done )
3221                 {
3222                     // send client quit
3223                     goto reset_to_searching;
3224                 }
3225 
3226                 // got savegame
3227                 if( SendPacket( cl_servernode, PT_CLIENTREADY ) >= NE_fail )
3228                     goto reset_to_searching;
3229 
3230                 gamestate = GS_LEVEL;  // game loaded
3231                 cl_mode = CLM_connected;
3232                 break;
3233 #else
3234                 goto reset_to_searching;  // should not end up in this state
3235 #endif
3236 
3237 #ifdef WAIT_GAME_START_INTERMISSION
3238             case CLM_wait_game_start :
3239                 // Not going to get a download.
3240                 if( netfile_download )
3241                     CL_Cancel_download_savegame();
3242 
3243                 M_DrawTextBox( 2, NETFILE_BOX_Y, 38, 4);
3244                 V_DrawString (30, NETFILE_BOX_Y+8, 0, "Wait Game Start");
3245                 // wait for control msg
3246                 break;
3247 #endif
3248 
3249             default:
3250                 break;
3251             // CLM_connected will exit the loop
3252         }
3253 
3254         Net_Packet_Handler();
3255         if( network_state < NETS_connecting )  // Need client to server.
3256             goto reset_to_searching;  // connection closed by cancel or timeout
3257         if( !server && !netgame )
3258             goto reset_to_searching;  // connection closed by cancel or timeout
3259 
3260         Net_AckTicker();
3261 
3262         // Operations performed only once every tic.
3263         if( cl_prev_tic != I_GetTime() )
3264         {
3265             cl_prev_tic = I_GetTime();
3266 
3267             // User response handler
3268             I_OsPolling();
3269             switch( I_GetKey() )
3270             {
3271               case 'q':
3272               case KEY_ESCAPE:
3273                  goto quit_ret;
3274             }
3275 
3276             if( Filetx_file_cnt )  // File download in progress.
3277                 Filetx_Ticker();
3278 
3279 #if 1
3280    if( cl_mode > CLM_searching )
3281    {
3282       // Nothing bad, just not the problem
3283             // Supporting the wait during connect, like it was in the previous
3284             // code, has marginal value.  Seems to cause more problems.
3285             D_WaitPlayer_Ticker();
3286             if( wait_tics > 0 || wait_netplayer > 0 )
3287                 D_WaitPlayer_Drawer();
3288    }
3289 #endif
3290             CON_Drawer ();
3291             I_FinishUpdate ();              // page flip or blit buffer
3292         }
3293     } while ( cl_mode != CLM_connected );
3294 
3295     // If this is still set, then did not get a savegame, so turn it off.
3296     if( netfile_download )
3297         CL_Cancel_download_savegame();
3298 
3299     network_state = NETS_active;
3300 
3301     DEBFILE(va("Synchronization Finished\n"));
3302 
3303     // [WDJ] consoleplayer no longer has DRONE bit
3304     displayplayer = consoleplayer;
3305     consoleplayer_ptr = displayplayer_ptr = &players[consoleplayer];
3306     return;
3307 
3308 reset_to_searching:
3309     if( cl_mode >= CLM_download_req )
3310     {
3311         SendPacket( cl_servernode, PT_CLIENTQUIT );  // ignore failure
3312     }
3313     cl_mode = CLM_searching;
3314     return;
3315 
3316 quit_ret:
3317     M_SimpleMessage ("Network game synchronization aborted.\n\nPress ESC\n");
3318     goto reset_to_title_exit;
3319 
3320 reset_to_title_exit:
3321     CL_Reset();
3322     D_StartTitle();
3323     return;
3324 }
3325 
3326 
3327 // By User, future Client.
Command_connect(void)3328 void Command_connect(void)
3329 {
3330     if( COM_Argc()<2 )
3331     {
3332         CONS_Printf ("connect <serveraddress> : connect to a server\n"
3333                      "connect ANY : connect to the first lan server found\n"
3334                      "connect SELF: connect to self server\n");
3335         return;
3336     }
3337     server = false;
3338     quit_netgame_status = 0;
3339 
3340     if( strcasecmp(COM_Argv(1),"self")==0 )
3341     {
3342         cl_servernode = 0;  // preset connect to server on self
3343         cl_server_state = NOS_internal;  // otherwise may reject
3344         server = true;
3345         // should be but...
3346         //SV_SpawnServer();
3347     }
3348     else
3349     {
3350         // used in menu to connect to a server in the list
3351         if( netgame && strcasecmp(COM_Argv(1),"node")==0 )
3352         {
3353             // example: "connect node 4"
3354             cl_servernode = atoi(COM_Argv(2));
3355         }
3356         else
3357         if( netgame )
3358         {
3359             CONS_Printf("You cannot connect while in netgame\n"
3360                         "Leave this game first\n");
3361             return;
3362         }
3363         else
3364         {
3365             I_NetOpenSocket();
3366             netgame = true;
3367             multiplayer = true;
3368             network_state = NETS_open;
3369 
3370             if( strcasecmp(COM_Argv(1),"any")==0 )
3371             {
3372                 // Connect to first lan server found.
3373                 cl_servernode = BROADCAST_NODE;
3374             }
3375             else
3376             if( I_NetMakeNode )
3377             {
3378                 // Connect to server at IP addr.
3379                 cl_servernode = I_NetMakeNode(COM_Argv(1));
3380                 if( cl_servernode >= MAXNETNODES )
3381                 {
3382                     // Error from I_NetMakeNode()
3383                     CONS_Printf("Network address error\n");
3384                     goto close_connection;
3385                 }
3386             }
3387             else
3388             {
3389                 CONS_Printf("There is no server identification with this network driver\n");
3390                 goto close_connection;
3391             }
3392         }
3393     }
3394     CL_ConnectToServer();
3395     return;
3396 
3397 close_connection:
3398     D_CloseConnection();
3399     network_state = NETS_idle;
3400     return;
3401 }
3402 
3403 
3404 // Called by Kick cmd.
CL_RemovePlayer(byte playernum)3405 static void CL_RemovePlayer( byte playernum )
3406 {
3407     player_t * player;
3408     int i;
3409 
3410     // Cannot trust an index from a network message.
3411     if( playernum >= MAXPLAYERS )  return;
3412     player = & players[playernum];
3413 
3414     if( server && !demoplayback )
3415     {
3416         byte nnode = player_to_nnode[playernum];
3417         if( playerpernode[nnode] )
3418             playerpernode[nnode]--;
3419         if( playerpernode[nnode] == 0 )
3420         {
3421             // No more players at this node.
3422             Net_CloseConnection(nnode, 0);
3423             SV_Reset_NetNode(nnode);  // node_state
3424         }
3425     }
3426 
3427     playeringame[playernum] = false;
3428     player_state[playernum] = PS_unused;
3429     if( localplayer[0] == playernum )   localplayer[0] = 255;
3430     if( localplayer[1] == playernum )   localplayer[1] = 255;
3431     player_to_nnode[playernum] = 255;
3432 
3433     // we should use a reset player but there is not such function
3434     // Count the players.
3435     update_player_counts();
3436 
3437     for(i=0;i<MAXPLAYERS;i++)
3438     {
3439         players[i].addfrags += players[i].frags[playernum];
3440         players[i].frags[playernum] = 0;
3441         player->frags[i] = 0;
3442     }
3443     player->addfrags = 0;
3444 
3445     // remove avatar of player
3446     if( player->mo )
3447     {
3448         player->mo->player = NULL;
3449         P_RemoveMobj( player->mo );
3450     }
3451     player->mo = NULL;
3452 
3453     B_Destroy_Bot( player );
3454 }
3455 
3456 // By Client and non-specific code, to reset client connect.
CL_Reset(void)3457 void CL_Reset (void)
3458 {
3459     if (demorecording)
3460         G_CheckDemoStatus ();
3461 
3462     // Reset client
3463     DEBFILE(va("==== Client reset ====\n"));
3464 
3465     if( cl_servernode < MAXNETNODES )
3466     {
3467         // Close connection to server
3468         // Client keeps nnode_state for server.
3469         cl_server_state = NOS_idle;
3470         Net_CloseConnection(cl_servernode, 0);
3471     }
3472     D_CloseConnection();         // netgame=false
3473     cl_servernode = 0;  // preset client to server on self, but not connected
3474     cl_error_status = 0;
3475 
3476     // Enable self server
3477     multiplayer = false;
3478     server=true;
3479 #ifdef DOSNET_SUPPORT
3480     doomcom->num_player_netnodes=1;
3481 #endif
3482     SV_StopServer();
3483     SV_ResetServer();
3484 
3485     T_Clear_HubScript(); //DarkWolf95: Originally implemented by Exl
3486     fs_fadealpha = 0;
3487     HU_Clear_FSPics();
3488 
3489     // reset game engine
3490     //D_StartTitle ();
3491 }
3492 
Command_PlayerInfo(void)3493 void Command_PlayerInfo(void)
3494 {
3495     int i;
3496 
3497     for(i=0;i<MAXPLAYERS;i++)
3498     {
3499         if(playeringame[i])
3500         {
3501             // Mark the server player in white
3502             CONS_Printf("%snum:%2d  node:%2d  %s\n",
3503                         (serverplayer==i)?"\2":"",
3504                         i, player_to_nnode[i], player_names[i]);
3505         }
3506     }
3507 }
3508 
3509 // Name can be player number, or player name.
3510 // Players 0..(MAXPLAYERS-1) are known as Player 1 .. to the user.
3511 // Return player number, 0..(MAXPLAYERS-1).
3512 // Return 255, and put msg to console, when name not found.
player_name_to_num(const char * name)3513 byte  player_name_to_num( const char * name )
3514 {
3515     // Player num can be 0..250 (limited to MAXPLAYERS).
3516     int pn;  // player num
3517 
3518     pn=atoi(name);   // test as player number 1..MAXPLAYERS
3519     // pn=0 when not numeric
3520     if((pn > 0) && (pn <= MAXPLAYERS))
3521     {
3522         // Name was numeric, and in player num range
3523         pn --;  // convert to 0..MAXPLAYERS
3524         if( ! playeringame[pn])  goto no_player;
3525         return pn;
3526     }
3527 
3528     // Search for player by name.
3529     for(pn=0; pn<MAXPLAYERS; pn++)
3530     {
3531         if(playeringame[pn] && strcasecmp(player_names[pn],name)==0)
3532             return pn;
3533     }
3534 
3535 no_player:
3536     CONS_Printf("There is no player named\"%s\"\n",name);
3537     return 255;
3538 }
3539 
3540 // network kick message codes
3541 typedef enum {
3542   KICK_MSG_GO_AWAY     = 1,
3543   KICK_MSG_CON_FAIL    = 2,
3544   KICK_MSG_PLAYER_QUIT = 3,
3545   KICK_MSG_TIMEOUT     = 4,
3546 } kick_msg_e;
3547 
Command_Kick(void)3548 void Command_Kick(void)
3549 {
3550     if (COM_Argc() != 2)
3551     {
3552         CONS_Printf ("kick <playername> or <playernum> : kick a player\n");
3553         return;
3554     }
3555 
3556     if(server)
3557     {
3558         int pn = player_name_to_num(COM_Argv(1));
3559         if(pn < MAXPLAYERS)
3560            SV_Send_NetXCmd_p2(XD_KICK, pn, KICK_MSG_GO_AWAY);
3561     }
3562     else
3563     {
3564         CONS_Printf("You are not the server\n");
3565     }
3566 }
3567 
Got_NetXCmd_KickCmd(xcmd_t * xc)3568 void Got_NetXCmd_KickCmd(xcmd_t * xc)
3569 {
3570     byte pnum=READBYTE(xc->curpos);  // unsigned player num
3571     byte msg =READBYTE(xc->curpos);  // unsigned kick message
3572 
3573     if( pnum >= MAXPLAYERS )  return;
3574     GenPrintf(EMSG_hud, "\2%s ", player_names[pnum]);
3575 
3576     switch(msg)
3577     {
3578        case KICK_MSG_GO_AWAY:
3579                GenPrintf(EMSG_hud, "has been kicked (Go away)\n");
3580                break;
3581        case KICK_MSG_CON_FAIL:
3582                GenPrintf(EMSG_hud, "has been kicked (Consistency failure)\n");
3583                break;
3584        case KICK_MSG_TIMEOUT:
3585                GenPrintf(EMSG_hud, "left the game (Connection timeout)\n");
3586                break;
3587        case KICK_MSG_PLAYER_QUIT:
3588                GenPrintf(EMSG_hud, "left the game\n");
3589                break;
3590     }
3591 
3592     if( pnum == (byte)consoleplayer )
3593     {
3594         CL_Reset();
3595         D_StartTitle();
3596         M_SimpleMessage("You have been kicked by the server\n\nPress ESC\n");
3597     }
3598     else
3599     {
3600         CL_RemovePlayer(pnum);
3601     }
3602 }
3603 
3604 CV_PossibleValue_t maxplayers_cons_t[]={{1,"MIN"},{32,"MAX"},{0,NULL}};
3605 
3606 consvar_t cv_allownewplayer = {"sv_allownewplayers","1",0,CV_OnOff};
3607 consvar_t cv_maxplayers     =
3608   {"sv_maxplayers","32",CV_NETVAR,maxplayers_cons_t,NULL,32};
3609 
3610 static void Got_NetXCmd_AddPlayer(xcmd_t * xc);
3611 static void Got_NetXCmd_AddBot(xcmd_t * xc);	//added by AC for acbot
3612 
3613 // Called one time at init, by D_Startup_NetGame.
D_Init_ClientServer(void)3614 void D_Init_ClientServer (void)
3615 {
3616   DEBFILE(va("==== %s debugfile ====\n", VERSION_BANNER));
3617 
3618     network_state = NETS_idle;
3619     cl_drone = false;
3620 
3621     // drone server generating the left view of three screen view
3622     if(M_CheckParm("-left"))
3623     {
3624         cl_drone = true;
3625         viewangleoffset = ANG90;
3626     }
3627     // drone server generating the right view of three screen view
3628     if(M_CheckParm("-right"))
3629     {
3630         cl_drone = true;
3631         viewangleoffset = -ANG90;
3632     }
3633     // [WDJ] specify secondary screen angle in degrees (general case of left/right)
3634     if(M_CheckParm("-screendeg"))
3635     {
3636         cl_drone = true;
3637         if( M_IsNextParm() )
3638         {
3639             // does not accept negative numbers, use 270, 315, etc
3640             viewangleoffset = atoi(M_GetNextParm()) * (ANG90 / 90);
3641             // it is cheating to have screen looking behind player
3642             if( viewangleoffset < -ANG90 )  viewangleoffset = -ANG90;
3643             if( viewangleoffset > ANG90 )  viewangleoffset = ANG90;
3644         }
3645     }
3646 //    debug_Printf( "viewangleoffset=%i\n", viewangleoffset );
3647 
3648     COM_AddCommand("playerinfo",Command_PlayerInfo, CC_info);
3649     COM_AddCommand("kick",Command_Kick, CC_net);
3650     COM_AddCommand("connect",Command_connect, CC_net);
3651 
3652     Register_NetXCmd(XD_KICK, Got_NetXCmd_KickCmd);
3653     Register_NetXCmd(XD_ADDPLAYER, Got_NetXCmd_AddPlayer);
3654     Register_NetXCmd(XD_ADDBOT, Got_NetXCmd_AddBot);	//added by AC for acbot
3655 
3656     CV_RegisterVar (&cv_allownewplayer);
3657     CV_RegisterVar (&cv_maxplayers);
3658 
3659     gametic = 0;
3660 #ifdef CLIENTPREDICTION2
3661     localgametic = 0;
3662 #else
3663     leveltime = 0;
3664 #endif
3665 
3666     // do not send anything before the real begin
3667     SV_StopServer();  // as an Init
3668 }
3669 
3670 // By Server
3671 // nnode: 0..(MAXNETNODES-1)
SV_Reset_NetNode(byte nnode)3672 static void SV_Reset_NetNode(byte nnode)
3673 {
3674     nnode_state[nnode] = NOS_idle;
3675     nnode_to_player[0][nnode] = 255;
3676     nnode_to_player[1][nnode] = 255;
3677     nettics[nnode]=gametic;
3678     nextsend_tic[nnode]=gametic;
3679     join_waiting[nnode]=0;
3680     playerpernode[nnode]=0;
3681 }
3682 
3683 // Called by D_Init_ClientServer, SV_SpawnServer, CL_Reset, D_WaitPlayer_Response
SV_ResetServer(void)3684 void SV_ResetServer( void )
3685 {
3686     int    i;
3687 
3688     // +1 because this command will be executed in com_executebuffer in
3689     // tryruntic so gametic will be incremented, anyway maketic > gametic
3690     // is not a issue
3691 
3692     maketic=gametic+1;
3693     cl_need_tic=maketic;
3694 #ifdef CLIENTPREDICTION2
3695     localgametic = gametic;
3696 #endif
3697     next_tic_clear=maketic;
3698 
3699     for (i=0 ; i<MAXNETNODES ; i++)
3700         SV_Reset_NetNode(i);
3701 
3702     for (i=0 ; i<MAXPLAYERS ; i++)
3703     {
3704         playeringame[i]=false;
3705         player_state[i] = PS_unused;
3706         player_to_nnode[i] = 255;
3707     }
3708 
3709     cl_nnode=0;
3710     cl_packetmissed=false;
3711     viewangleoffset=0;
3712 
3713     if( dedicated )
3714     {
3715         // [WDJ] FIXME, why dedicated required node_in_game[0].
3716         nnode_state[0] = NETS_internal;
3717         serverplayer = 255;  // no server player
3718     }
3719     else
3720         serverplayer=consoleplayer;
3721 
3722     if(server)
3723     {
3724         cl_servernode = 0;  // client sees server on self
3725         cl_server_state = NOS_internal;
3726     }
3727 
3728     update_player_counts();
3729     quit_netgame_status = 0;
3730 
3731     DEBFILE(va("==== Server Reset ====\n"));
3732 }
3733 
3734 //
3735 // D_Quit_NetGame
3736 // Server or Client
3737 // Called before quitting to leave a net game
3738 // without hanging the other players
3739 //
3740 // Called by D_Quit_Save, D_WaitPlayer_Response, Command_ExitGame_f, repair_handler
D_Quit_NetGame(void)3741 void D_Quit_NetGame (void)
3742 {
3743     if (!netgame)
3744         return;
3745 
3746     // [WDJ] Avoid the tight loop when the network fails.
3747     if( quit_netgame_status > 0 )
3748         return;
3749 
3750     quit_netgame_status = 1;
3751 
3752     DEBFILE("==== Quiting Game, closing connection ====\n" );
3753 
3754     // abort send/receive of files
3755     Close_NetFile();
3756 
3757     if( server )
3758     {
3759         // Server sends shutdown to all clients.
3760         SendPacket( BROADCAST_NODE, PT_SERVERSHUTDOWN );  // to NOS_recognized
3761 
3762         // Close registration with the Master Server.
3763         if ( serverrunning && cv_internetserver.value )
3764              MS_UnregisterServer();
3765     }
3766     else  // Client not server
3767     if( (cl_servernode < MAXNETNODES)
3768        && (cl_server_state >= NOS_server) )  // client connected to server
3769     {
3770         // Client sends quit to server.
3771         SendPacket( cl_servernode, PT_CLIENTQUIT );  // ignore failure
3772     }
3773 
3774     D_CloseConnection();
3775     cl_server_state = NOS_idle;
3776     network_state = NETS_shutdown;
3777 
3778     DEBFILE("==== Log finish ====\n" );
3779 #ifdef DEBUGFILE
3780     if (debugfile)
3781     {
3782         fclose (debugfile);
3783         debugfile = NULL;
3784     }
3785 #endif
3786 }
3787 
3788 // By Server.
3789 // Add a node to the game (player will follow at map change or at savegame....)
3790 //  set_nnode_state : the new nnode_state
3791 static
SV_AddNode(byte nnode,byte set_nnode_state)3792 void SV_AddNode(byte nnode, byte set_nnode_state)
3793 {
3794     nettics[nnode]       = gametic;
3795     nextsend_tic[nnode]  = gametic;
3796 
3797     // [WDJ] nnode_state is client state maintained by server.
3798     // This includes the client on the server.  It will not start up correctly
3799     // if the nnode_state is not kept correctly.
3800     // This used to be blocked for nnode==0 because the server was setting
3801     // node_in_game to get packets working.  This bypass is no longer done.
3802     if( nnode_state[nnode] < NOS_client )
3803         nnode_state[nnode] = set_nnode_state;
3804 }
3805 
3806 // Get a free player node.  Obey the rules.
SV_get_player_num(void)3807 byte  SV_get_player_num( void )
3808 {
3809     // The server player_state determines availability.
3810     byte pn = 0;
3811     while( player_state[pn] )  // find free player slot
3812     {
3813        pn++;
3814        if( pn >= MAXPLAYERS )  return  251;
3815     }
3816 
3817     player_state[pn] = PS_added; // pending
3818     return pn;
3819 }
3820 
3821 // Commit to using a player num slot.
3822 //   nnode : node of the player
3823 //   new_state : the new player state
3824 // Return the new player num.
3825 // Return 255 if too many players or too many player for the node.
SV_commit_player(byte nnode,byte new_state)3826 byte SV_commit_player( byte nnode, byte new_state )
3827 {
3828     byte newplayernum, pind;
3829     // Search for a free playernum.
3830     // New players will have playeringame set as a result of XCmd AddPlayer.
3831     pind = playerpernode[nnode];  // next pind
3832     if( pind > 1 )
3833         return 255;
3834 
3835     newplayernum = SV_get_player_num();
3836 
3837     // Should never happen because we check the number of players
3838     // before accepting the join.
3839     if(newplayernum >= MAXPLAYERS)
3840     {
3841 #ifdef PARANOIA
3842         I_SoftError("SV_commit_player: Reached MAXPLAYERS\n");
3843 #endif
3844         return 255;
3845     }
3846 
3847     // Commit the server network settings.
3848     playerpernode[nnode]++;
3849 
3850     player_state[newplayernum] = new_state;
3851     player_pind[newplayernum] = pind;
3852     player_to_nnode[newplayernum] = nnode;
3853     nnode_to_player[pind][nnode] = newplayernum;
3854     return newplayernum;
3855 }
3856 
3857 
3858 // Client
3859 // Add and remove players
update_player_state(byte pn,byte new_player_state)3860 static void update_player_state( byte pn, byte new_player_state )
3861 {
3862     byte pst = player_state[pn];
3863 
3864     if( (new_player_state >= PS_player) && (new_player_state <= PS_bot) && (pst == PS_unused) )
3865     {
3866         G_AddPlayer(pn);
3867         if( new_player_state == PS_bot )
3868         {
3869             B_Create_Bot( & players[pn] );
3870             pst = PS_bot;
3871         }
3872         else if( new_player_state == PS_player )
3873             new_player_state = PS_player_from_server;  // easier to track
3874 
3875         playeringame[pn]=true;  // enable this player
3876     }
3877     else if( new_player_state == PS_unused )
3878     {
3879         if( pst > PS_unused )
3880             CL_RemovePlayer(pn);
3881         return;
3882     }
3883     player_state[pn] = new_player_state;
3884 }
3885 
3886 // Server and Client
3887 // More accurate than purely inc and dec. There are too many odd ways to kill a node.
update_player_counts(void)3888 static void  update_player_counts( void )
3889 {
3890     int pn, nn;
3891 
3892     num_player_used = 0;
3893     num_game_players = 0;
3894     num_ticcmd_per_tic = 0;
3895     ticcmd_player_mask = 0;
3896 
3897     if( server )
3898     {
3899 #ifdef WAIT_GAME_START_INTERMISSION
3900         num_wait_game_start = 0;
3901 #endif
3902         num_join_waiting_players = 0;
3903         for(nn=0; nn<MAXNETNODES; nn++)
3904         {
3905             num_join_waiting_players += join_waiting[nn];
3906         }
3907     }
3908 
3909     for(pn=0; pn<MAXPLAYERS; pn++)
3910     {
3911         byte ps = player_state[pn];
3912         if( ps == PS_unused )  continue;
3913 
3914         num_player_used++;
3915 
3916 #ifdef WAIT_GAME_START_INTERMISSION
3917         if( server && (ps == PS_join_wait_game_start) )
3918             num_wait_game_start++;
3919 #endif
3920 
3921         if( playeringame[pn] )
3922         {
3923             num_game_players++;
3924             if( ps >= PS_player && ps < PS_bot )
3925             {
3926                 ticcmd_player_mask |= 1<<pn;  // players that send ticcmds
3927                 ticcmd_pid[num_ticcmd_per_tic++] = pn;  // list of pid
3928             }
3929         }
3930     }
3931 }
3932 
3933 // Client
3934 //    pmask : player_mask
3935 // The number of bits set in the player_mask.
CL_num_ticcmd_per(uint32_t pmask)3936 static void CL_num_ticcmd_per( uint32_t pmask )
3937 {
3938     byte pn = 0;
3939     num_ticcmd_per_tic = 0;
3940     ticcmd_player_mask = pmask;  // players that send ticcmds
3941     while( pmask )
3942     {
3943         if( pmask & 0x0001 )  // has a ticcmd in the packet
3944         {
3945             ticcmd_pid[num_ticcmd_per_tic++] = pn;  // list of pid
3946         }
3947         pmask >>= 1;
3948         pn++;
3949     }
3950 }
3951 
3952 
3953 #ifdef PARANOIA
3954 // FIXME: probably do not need this.
3955 //   Only use the player mask for message content, not the way to update players.
3956 // Client
3957 static
CL_player_mask_error_detection(uint32_t playerdet)3958 void  CL_player_mask_error_detection( uint32_t playerdet )
3959 {
3960     int pn;
3961 
3962     if( playerdet == ticcmd_player_mask )  return;  // quick check
3963 
3964     // When joining game, this is normal, as client has not been given all the players yet.
3965     GenPrintf(EMSG_warn, "Player mask error: server= %4X client= %4X\n", playerdet, ticcmd_player_mask );
3966 
3967     // Client only uses ticcmd_player_mask for this check.
3968     // Player_mask should match playeringame.
3969     // Does not affect players or bot set by client.
3970     for(pn=0; pn<MAXPLAYERS; pn++)
3971     {
3972         uint32_t pnb = 1<<pn;
3973         if( (playerdet & pnb) != (ticcmd_player_mask & pnb) )
3974         {
3975             GenPrintf(EMSG_warn, "  Player %d: server= %4X client= %4X\n", pn, playerdet & pnb, ticcmd_player_mask & pnb  );
3976         }
3977     }
3978 
3979 //  Causes servertic error because this is the test reference for the player list.
3980 //    ticcmd_player_mask = playerdet; // trust the server message, because the server made the message content
3981 }
3982 #endif
3983 
3984 
3985 
3986 // Broadcast the XD_ADDPLAYER
3987 //  nnode : new player is at this node
3988 //  pn : new player num
3989 //  flags : any flags that may be needed (future)
3990 static
SV_Send_AddPlayer(byte nnode,byte pn,byte flags)3991 void  SV_Send_AddPlayer( byte nnode, byte pn, byte flags )
3992 {
3993     byte buf[6];
3994 
3995     player_state[pn] = PS_added_commit;
3996 
3997     // Format: XD_ADDPLAYER   (ver 1.48)
3998     //  byte:  nnode
3999     //  byte:  player num
4000     //  byte:  pind
4001     //  byte:  flags
4002     buf[0] = nnode;
4003     buf[1] = pn;
4004     buf[2] = player_pind[pn];
4005     buf[3] = flags;
4006 
4007     // Message from server to everyone, to add the player.
4008     SV_Send_NetXCmd(XD_ADDPLAYER, buf, 4);
4009 
4010     DEBFILE(va("Server added player %d net node %d\n", pn, nnode));
4011 
4012     if( nnode_state[nnode] < NOS_client )
4013         nnode_state[nnode] = NOS_active;
4014 }
4015 
4016 
4017 // Xcmd XD_ADDPLAYER
4018 // Sent by server to all client.
4019 static
Got_NetXCmd_AddPlayer(xcmd_t * xc)4020 void Got_NetXCmd_AddPlayer(xcmd_t * xc)
4021 {
4022     static uint32_t sendconfigtic = 0xffffffff;
4023     byte nnode, newplayernum, pind;
4024     byte flags = 0;
4025 
4026     // Format: XD_ADDPLAYER
4027     // Older, from demo
4028     //  byte:  nnode
4029     //  byte:  (player num) | (splitscreen pind at 0x80)
4030     // ver 1.48
4031     //  byte:  nnode
4032     //  byte:  player num
4033     //  byte:  pind
4034     //  byte:  flags
4035 
4036     // [WDJ] Having error due to sign extension of byte read (signed char).
4037     nnode = READBYTE(xc->curpos);  // unsigned
4038     newplayernum = READBYTE(xc->curpos);  // unsigned
4039     // NetXCmd are issued by demos.
4040     if( EV_legacy >= 148 )
4041     {
4042         pind = READBYTE(xc->curpos);
4043         flags = READBYTE(xc->curpos);
4044         if( flags )
4045             GenPrintf(EMSG_warn, "AddPlayer %d unsupported flags=%x\n", (newplayernum+1), flags);
4046     }
4047     else
4048     {
4049         // Old format
4050         pind = (newplayernum & 0x80)? 1:0;
4051         newplayernum &= 0x1F;
4052     }
4053 
4054     // Make play engine player data.
4055     // Do not set playeringame until player is created.
4056     G_AddPlayer(newplayernum);
4057     playeringame[newplayernum]=true;  // enable this player
4058     player_state[newplayernum]= PS_player;
4059     update_player_count_request = 1;  // cannot call update_player_counts() direct, as it is in use
4060 
4061     // [WDJ] Players are 1..MAXPLAYERS to the user.
4062     GenPrintf(EMSG_hud, "Player %d is in the game (node %d)\n", (newplayernum+1), nnode);
4063 
4064     if(nnode==cl_nnode)
4065     {
4066         // The server is creating my player.
4067         if( ! server )
4068         {
4069             // normally server info
4070             player_to_nnode[newplayernum] = cl_nnode;  // for information only
4071             player_pind[newplayernum] = pind;
4072         }
4073         localplayer[pind] = newplayernum;
4074 
4075         if( pind == 0 )
4076         {
4077             // mainplayer
4078             consoleplayer=newplayernum;
4079             displayplayer=newplayernum;
4080             displayplayer_ptr = consoleplayer_ptr = &players[newplayernum];
4081         }
4082         else
4083         {
4084             // splitscreen
4085             displayplayer2=newplayernum;
4086             displayplayer2_ptr = &players[displayplayer2];
4087         }
4088         DEBFILE(va("Spawning player[%i] pind=%i at this node.\n", newplayernum, pind));
4089     }
4090 
4091     // the new player send their config
4092     // and the existing players send their config to the new node
4093     // WARNING : this can cause a bottleneck in the txtcmd
4094     //           this can also produce consistency failure if packet get lost
4095     //           because everybody knows the actual config except the joiner
4096     //    TODO : fixthis
4097 
4098     //  Don't send config more than once per tic (more than one player join)
4099     if( sendconfigtic!=gametic )
4100     {
4101         sendconfigtic=gametic;
4102         D_Send_PlayerConfig();
4103         if( server )
4104             B_Send_all_bots_NameColor();
4105     }
4106 }
4107 
4108 // Xcmd XD_ADDBOT
4109 static
Got_NetXCmd_AddBot(xcmd_t * xc)4110 void Got_NetXCmd_AddBot(xcmd_t * xc)  //added by AC for acbot
4111 {
4112     char * lcp = (char*)xc->curpos; // local cp
4113     char * botname; // bot name, so messages have correct name.
4114     int name_len;
4115     byte colour;
4116 
4117     // [WDJ] Having error due to sign extension of byte read (signed char).
4118     byte newplayernum = READBYTE(lcp);  // unsigned
4119     newplayernum&=0x7F;  // remove flag bit, and any sign extension
4120 
4121     if( EV_legacy < 148 )
4122     {
4123         // name and color from botinfo tables
4124         botname = botnames[botinfo[newplayernum].name_index];  // strings from a table
4125         colour = botinfo[newplayernum].colour;
4126         name_len = strlen( botname );
4127     }
4128     else
4129     {
4130         // Ver 1.48
4131         colour = READBYTE(lcp);
4132         botname = lcp;  // bot name, so messages have correct name.
4133 
4134         // [WDJ] String overflow safe
4135         name_len = strlen( lcp );
4136         lcp += name_len + 1;  // string and term
4137     }
4138 
4139     xc->curpos = (byte*)lcp;  // NetXCmd reading done
4140 
4141     if( playeringame[newplayernum] )
4142     {
4143         GenPrintf(EMSG_warn, "Bot %i: player slot already in use.\n", (newplayernum+1) );
4144         return;
4145     }
4146 
4147     G_AddPlayer(newplayernum);
4148 
4149     player_t * pl = & players[newplayernum];
4150     B_Create_Bot( pl );
4151 
4152     // [WDJ] AddBot sends the name and color because the server has that information,
4153     // and it is desirable to set those attributes correctly for the first draw.
4154     // Update bot name and color.
4155     P_SetPlayer_color( pl, colour );
4156     if( name_len > MAXPLAYERNAME-1 ) // dest protection
4157         name_len = MAXPLAYERNAME-1;  // sizeof player_names
4158     memcpy( & player_names[newplayernum], botname, (name_len + 1));  // [MAXPLAYERNAME]
4159     player_names[newplayernum][MAXPLAYERNAME-1] = '\0';  // safe
4160 
4161     playeringame[newplayernum]=true;  // enable this player
4162     player_state[newplayernum]= PS_bot;
4163     update_player_count_request = 1;  // cannot call update_player_counts() direct, as it is in use
4164 
4165     multiplayer=1;
4166 
4167     GenPrintf(EMSG_hud, "Bot %s has entered the game\n", botname);
4168 
4169     if( server )
4170     {
4171         // Bot exists, so now can send the bot info.
4172         B_Send_bot_NameColor( newplayernum );
4173     }
4174 }
4175 
4176 // By Server.
4177 // Called by SV_SpawnServer, client_join_handler.
4178 // Return true when a new player is added.
4179 static
SV_Add_Join_Waiting(void)4180 boolean SV_Add_Join_Waiting(void)
4181 {
4182     boolean  newplayer_added = false;  // return
4183     byte nnode, ns;
4184     byte newplayernum;
4185 
4186     if( num_join_waiting_players == 0 )  return 0;
4187 
4188     // The code below usually clears the join_waiting queues.
4189     num_join_waiting_players = 0;
4190 
4191     for(nnode=0; nnode<MAXNETNODES; nnode++)
4192     {
4193         ns = nnode_state[nnode];
4194         if( (ns >= NOS_join_file) && (ns <= NOS_join_savegame) )
4195         {
4196             // Join download in progress
4197             num_join_waiting_players += join_waiting[nnode];
4198             continue;
4199         }
4200 
4201         // splitscreen can allow 2 player in one node
4202         for(; join_waiting[nnode]>0; join_waiting[nnode]--)
4203         {
4204             // Search for a free playernum.
4205             // New players will have playeringame set as a result of XCmd AddPlayer.
4206             newplayernum = SV_commit_player( nnode, PS_added_commit );
4207             if( newplayernum >= MAXPLAYERS )  continue;
4208 
4209             // Message from server to everyone, to add the player.
4210             SV_Send_AddPlayer( nnode, newplayernum, 0 );  // PS_added_commit
4211             // XD_ADDPLAYER commands will stay in the cmd buffers.
4212             // When cl_mode==CLM_connected is achieved, they will be transmitted and acted upon.
4213 
4214             newplayer_added = true;
4215         }
4216     }
4217 
4218     update_player_counts();
4219 
4220     return newplayer_added;
4221 }
4222 
4223 
4224 #ifdef WAIT_GAME_START_INTERMISSION
4225 
4226 #define GAME_START_WAIT    22
4227 
4228 // Add players waiting for game start
4229 //  mode : 0= from intermission
SV_Add_game_start_waiting_players(byte mode)4230 void SV_Add_game_start_waiting_players( byte mode )
4231 {
4232     byte pn, nnode, cnt = 0;
4233     // wait_timer must be at least 1 to escape from GS_INTERMISSION.
4234     int wait_timer = (mode == 0)? TICRATE*GAME_START_WAIT : 1 ;
4235 
4236     // This seems to only work using GS_INTERMISSION
4237     for( pn=0; pn<MAXPLAYERS; pn++)
4238     {
4239         if( player_state[pn] == PS_join_wait_game_start )
4240         {
4241             nnode = player_to_nnode[pn];
4242             if( nnode_state[nnode] == NOS_wait_game_start )
4243             {
4244                 nnode_state[nnode] = NOS_active;
4245                 nextsend_tic[nnode] = gametic;
4246 
4247                 SV_Send_LevelCfg( nnode );
4248                 SV_Send_PlayerState( nnode );
4249             }
4250 
4251             // Take node out of wait_game_start.
4252             SV_Send_control( nnode, CTRL_game_start, mode, wait_timer, pn );
4253 
4254             // Update everyone else.
4255             SV_Send_AddPlayer( nnode, pn, 0 );  // NetXCmd, PS_added_commit
4256 
4257 //            SV_Send_PlayerState( nnode );
4258             cnt++;
4259         }
4260     }
4261 
4262     if( cnt == 0 )
4263         return;
4264 
4265     // Update gametic and random state.
4266     SV_Send_State( paused | network_wait_pause );
4267     SendPacket( BROADCAST_NODE, PT_REQ_CLIENTCFG );  // req all nodes to send client cfg
4268     B_Send_all_bots_NameColor();  // Bot NameColor to everybody, by NetXCmd
4269 
4270     // Invoke the next level wait timer.
4271     wait_game_start_timer = wait_timer;
4272 }
4273 #endif
4274 
4275 
CL_Splitscreen_Player_Manager(void)4276 void CL_Splitscreen_Player_Manager( void )
4277 {
4278     if( cl_mode != CLM_connected )
4279         return;
4280 
4281     if( cv_splitscreen.EV )
4282     {
4283         if( ! displayplayer2_ptr )
4284             CL_Send_Join();  // join game
4285         return;
4286     }
4287 
4288     // Remove splitscreen player
4289     if( displayplayer2_ptr )
4290         SV_Send_NetXCmd_p2(XD_KICK, displayplayer2, KICK_MSG_PLAYER_QUIT);  // player 2
4291 }
4292 
4293 
4294 // Is there a game running.
Game_Playing(void)4295 boolean Game_Playing( void )
4296 {
4297     return (server && serverrunning) || (!server && cl_mode==CLM_connected);
4298 }
4299 
4300 // By Server and Server-only commands.
4301 // Called by D_Startup_NetGame (dedicated server).
4302 // Called by Command_Map_f, Command_Load_f (server).
4303 // Return true when a new player is added.
SV_SpawnServer(void)4304 boolean SV_SpawnServer( void )
4305 {
4306     D_DisableDemo();
4307 
4308     quit_netgame_status = 0;
4309 
4310     if( serverrunning == false )
4311     {
4312         GenPrintf(EMSG_hud, "Starting Server ...\n");
4313         serverrunning = true;
4314         SV_ResetServer();
4315         network_state = NETS_internal;  // Self server network.
4316         if( netgame )
4317         {
4318             I_NetOpenSocket();
4319             network_state = NETS_open;
4320             // Register with the Master Server.
4321             if( cv_internetserver.value )
4322             {
4323                 // MasterServer address is in cv_masterserver.
4324                 MS_RegisterServer();
4325             }
4326         }
4327 
4328         D_WaitPlayer_Setup();
4329 
4330         // server just connect to itself
4331         if( !dedicated )
4332             CL_ConnectToServer();
4333     }
4334 
4335     if( num_join_waiting_players )
4336         return SV_Add_Join_Waiting();
4337 
4338     return 0;
4339 }
4340 
4341 // Called by D_Init_ClientServer, G_StopDemo, CL_Reset, SV_StartSinglePlayerServer,
4342 // D_WaitPlayer_Response.
SV_StopServer(void)4343 void SV_StopServer( void )
4344 {
4345     int i;
4346 
4347     gamestate = wipegamestate = GS_NULL;
4348 
4349     localtextcmd[0].len = 0;  // text len
4350     localtextcmd[1].len = 0; // text len
4351 
4352     for(i=0; i<BACKUPTICS; i++)
4353         D_Clear_ticcmd(i);
4354 
4355     consoleplayer=0;
4356     cl_mode = CLM_searching;
4357     maketic=gametic+1;
4358     cl_need_tic=maketic;
4359     serverrunning = false;
4360 }
4361 
4362 // called at singleplayer start and stopdemo
SV_StartSinglePlayerServer(void)4363 void SV_StartSinglePlayerServer(void)
4364 {
4365     server        = true;
4366     netgame       = false;
4367     multiplayer   = false;
4368     cl_server_state = NOS_internal; // no quit game message
4369 
4370     // no more tic the game with this settings !
4371     SV_StopServer();
4372 
4373     if( cv_splitscreen.value )
4374         multiplayer    = true;
4375 }
4376 
4377 // By Server.
4378 // Called by client_join_handler.
SV_Send_Refuse(int to_node,char * reason)4379 static void SV_Send_Refuse(int to_node, char *reason)
4380 {
4381     strncpy(netbuffer->u.stringpak.str, reason, MAX_STRINGPAK_LEN-1);
4382     netbuffer->u.stringpak.str[MAX_STRINGPAK_LEN-1] = 0;
4383 
4384     netbuffer->packettype = PT_SERVERREFUSE;
4385     HSendPacket( to_node, SP_reliable|SP_queue, 0, strlen(netbuffer->u.stringpak.str)+1 );  // ignore failure
4386     Net_CloseConnection(to_node, 0);
4387 }
4388 
4389 // By Server.
4390 // PT_ASKINFO from Client.
4391 // Handle a client request for server info.
server_askinfo_handler(byte nnode)4392 static void server_askinfo_handler( byte nnode )
4393 {
4394     if(serverrunning)
4395     {
4396         // Make the send_time the round trip ping time.
4397         SV_Send_ServerInfo(nnode, LE_SWAP32(netbuffer->u.askinfo.send_time));
4398         Net_CloseConnection(nnode, 0);  // a temp connection
4399     }
4400 }
4401 
4402 // By Server.
4403 // PT_CLIENTJOIN from future client.
4404 //   nnode: net node that is joining
client_join_handler(byte nnode)4405 static void client_join_handler( byte nnode )
4406 {
4407     byte num_to_join, command;
4408     byte join_flags = netbuffer->u.clientcfg.flags;
4409     boolean newnode=false;
4410 
4411     if( netbuffer->u.clientcfg.version != VERSION
4412         || LE_SWAP32(netbuffer->u.clientcfg.subversion) != NETWORK_VERSION)
4413     {
4414         SV_Send_Refuse(nnode,
4415            // Text is automatically centered, must not be too long.
4416            va("Incompatible client\nServer %i Net %i\nLegacy %i Net %i",
4417                VERSION, NETWORK_VERSION, netbuffer->u.clientcfg.version, LE_SWAP32(netbuffer->u.clientcfg.subversion) )
4418         );
4419         return;
4420     }
4421 
4422     // nnode==0 is self, which is always accepted.
4423     if(!cv_allownewplayer.value && nnode!=0 )
4424     {
4425         SV_Send_Refuse(nnode,
4426           "The server is not accepting players\nat this time");
4427         return;
4428     }
4429 
4430     num_to_join = netbuffer->u.clientcfg.num_node_players - playerpernode[nnode];
4431     // DRONE will have 0 players
4432 
4433     // Compute it using join and player counts.
4434     update_player_counts();
4435     if( (num_player_used + num_to_join) > cv_maxplayers.value )
4436     {
4437         SV_Send_Refuse(nnode,
4438            va("Maximum players reached (max:%d)", cv_maxplayers.value));
4439         return;
4440     }
4441 
4442     // To determine the intial command to send with the config.
4443     command = CTRL_normal;
4444     // If there is an existing player at the node, then will not be newnode.
4445     newnode = ( nnode_state[nnode] < NOS_join );
4446     if( newnode && (gamestate == GS_LEVEL) )
4447     {
4448 #ifdef JOININGAME
4449         // If cannot download, then wait for next game start.
4450         if(( join_flags & NF_download_savegame )  // joiner allows savegame download
4451           && ( cv_SV_download_savegame.EV )    )  // server allows savegame download
4452             command = CTRL_download_savegame;
4453         else
4454             command = CTRL_wait_game_start;
4455 
4456         // For savegame downloads to work, the endian must match.
4457 #ifdef __BIG_ENDIAN__
4458         // Server is big-endian
4459         if( (join_flags & NF_big_endian) == 0 )  // joiner is little-endian
4460 #else
4461         // Server is little-endian
4462         if( join_flags & NF_big_endian )  // joiner is big-endian
4463 #endif
4464             command = CTRL_wait_game_start;
4465 
4466 #else
4467         // No join-in-game, no savegame download
4468         command = CTRL_wait_game_start;
4469 #endif
4470     }
4471 
4472     // Client authorized to join.
4473     if( newnode )
4474     {
4475         // The nnode is new to this server.
4476         SV_AddNode(nnode, NOS_join);
4477 
4478         // Send inital command with the config to avoid sending a separate
4479         // command message, which could arrive out-of-order.
4480         if(! SV_Send_ServerConfig(nnode, command) )
4481             goto kill_node;
4482 
4483         DEBFILE("New node joined\n");
4484     }
4485 
4486     if( join_flags & NF_drone )
4487     {
4488         // drone only watches another player
4489         playerpernode[nnode] = 0;  // indicator that is DRONE node
4490         return;
4491     }
4492 
4493     if( num_to_join )
4494     {
4495         if( command == CTRL_wait_game_start )
4496             goto wait_for_game_start;
4497 
4498 #ifdef JOININGAME
4499         if( command == CTRL_download_savegame )
4500         {
4501             // New node with new players joining existing game.
4502             // Update the nnode with game in progress.
4503             nnode_state[nnode] = NOS_join_savegame;
4504             SV_Send_SaveGame(nnode); // send game data
4505             // netwait timer is running
4506             GenPrintf(EMSG_info, "Send savegame\n");
4507             // Client will return  PT_CLIENTREADY or PT_CLIENTQUIT
4508         }
4509 #endif
4510 
4511         // Add node players to join_waiting
4512         join_waiting[nnode] = num_to_join;
4513         num_join_waiting_players += num_to_join;
4514         SV_Add_Join_Waiting();
4515     }
4516     return;
4517 
4518 wait_for_game_start:
4519     // These players will wait until the next game start.
4520 #ifdef WAIT_GAME_START_INTERMISSION
4521     while( num_to_join-- )
4522     {
4523         byte pn = SV_commit_player( nnode, PS_join_wait_game_start );
4524         SV_Send_control( nnode, CTRL_wait_game_start, 0, 0, pn );
4525         DEBFILE(va("Client Join: node=%i, wait game start player=%i.\n", nnode, pn));
4526     }
4527 
4528     if( nnode_state[nnode] < NOS_client )
4529         nnode_state[nnode] = NOS_wait_game_start;  // release network_wait
4530 
4531     update_player_counts();
4532     return;
4533 #else
4534     SV_Send_Refuse(nnode, "This server cannot handle\nwait_for_game_start players");
4535     goto kill_node;
4536 #endif
4537 
4538 kill_node:
4539     DEBFILE("Client Join: Failure to Send.\n");
4540     GenPrintf(EMSG_error, "Client Join: Failure to Send\n" );
4541     SV_Reset_NetNode(nnode);
4542     return;
4543 }
4544 
4545 
4546 // BY Server.
4547 // PT_NODE_TIMEOUT, PT_CLIENTQUIT
4548 //   nnode : the network client node quitting
4549 //   client_pn : the client player num that sent the quit
client_quit_handler(byte nnode,byte client_pn)4550 static void client_quit_handler( byte nnode, byte client_pn )
4551 {
4552     // Set nnode_state to NOS_shutdown at the end of the kick command.
4553     // This allows the sending of some packets to the quiting client
4554     // and to have them ack back.
4555     join_waiting[nnode]= 0;
4556     if( (client_pn < MAXPLAYERS) && playeringame[client_pn])
4557     {
4558         byte reason = (netbuffer->packettype == PT_NODE_TIMEOUT) ?
4559            KICK_MSG_TIMEOUT : KICK_MSG_PLAYER_QUIT;
4560         // Update other players by kicking nnode.
4561         SV_Send_NetXCmd_p2(XD_KICK, client_pn, reason);  // kick player
4562         nnode_to_player[0][nnode] = 255;
4563 
4564         byte pn2 = nnode_to_player[1][nnode];  // splitscreen player at the nnode
4565         if( pn2 < MAXPLAYERS )
4566         {
4567             if( playeringame[pn2] )
4568             {
4569                // kick player2
4570                SV_Send_NetXCmd_p2(XD_KICK, pn2, reason);
4571             }
4572             nnode_to_player[1][nnode] = 255;
4573         }
4574     }
4575     Net_CloseConnection(nnode, 0);
4576     nnode_state[nnode] = NOS_shutdown;
4577 }
4578 
4579 
4580 
4581 // By Client
4582 // PT_SERVERINFO from Server.
4583 //  nnode : remote node
server_info_handler(byte nnode)4584 static void server_info_handler( byte nnode )
4585 {
4586     // Compute ping in ms.
4587     netbuffer->u.serverinfo.trip_time =
4588      (I_GetTime() - LE_SWAP32(netbuffer->u.serverinfo.trip_time))*1000/TICRATE;
4589     netbuffer->u.serverinfo.servername[MAXSERVERNAME-1]=0;
4590 
4591     SL_InsertServer( & netbuffer->u.serverinfo, nnode);
4592 }
4593 
4594 
4595 // By Client
4596 // PT_SERVERREFUSE from Server.
server_refuse_handler(byte nnode)4597 static void server_refuse_handler( byte nnode )
4598 {
4599     if( cl_mode == CLM_wait_join_response )
4600     {
4601         M_SimpleMessage(va("Server %i refuses connection\n\nReason :\n%s",
4602                            nnode,
4603                            netbuffer->u.stringpak.str));
4604         CL_Reset();
4605         D_StartTitle();
4606     }
4607 }
4608 
4609 
4610 // By Client
4611 // PT_SERVERCFG from Server.
4612 // Received acceptance of the player node joining the game.
server_cfg_handler(byte nnode)4613 static void server_cfg_handler( byte nnode )
4614 {
4615     xcmd_t xc;
4616 
4617     if( cl_mode != CLM_wait_join_response )
4618         return;
4619 
4620     if(!server)
4621     {
4622         // Clients not on the server, update to server time.
4623         maketic = gametic = cl_need_tic = read_N32( &  netbuffer->u.servercfg.gametic );
4624     }
4625 
4626     // Client keeps server state, even on the server.
4627     if( cl_servernode < MAXNETNODES )
4628         cl_server_state = NOS_server;  // connected
4629 
4630 #ifdef CLIENTPREDICTION2
4631     localgametic = gametic;
4632 #endif
4633 
4634     // Handle a player on the server.
4635     serverplayer = netbuffer->u.servercfg.serverplayer;
4636     // Client use of player_to_nnode, see Command_PlayerInfo, AddPlayer
4637     if (serverplayer < MAXPLAYERS)  // 255 = no player
4638         player_to_nnode[serverplayer] = cl_servernode;
4639 
4640     cl_nnode = netbuffer->u.servercfg.clientnode;  // assigned by server
4641 
4642     GenPrintf(EMSG_hud, "Join accepted, wait next map change ...\n");
4643     DEBFILE(va("Server accept join gametic=%d, client net node=%d\n",
4644                gametic, cl_nnode));
4645 
4646     // No need for the server to update itself from message from server.
4647     if( ! server )
4648     {
4649         // Client
4650 #if 1
4651 #ifdef PARANOIA
4652         uint32_t  playerdet = read_N32( & netbuffer->u.servercfg.playerdetected );
4653         CL_player_mask_error_detection( playerdet );
4654 #endif
4655 #else
4656         // This was for servertic cmds, no longer need to do this.
4657         uint32_t  playerdet = read_N32( & netbuffer->u.servercfg.playerdetected );
4658         for(j=0;j<MAXPLAYERS;j++)
4659         {
4660             playeringame[j] = (( playerdet & (1<<j) ) != 0);
4661             player_state[j] = (playeringame[j])? PS_player_from_server : 0;
4662         }
4663 #endif
4664 
4665         xc.playernum = 0;
4666         xc.curpos = netbuffer->u.servercfg.netvar_buf;
4667         xc.endpos = xc.curpos + NETVAR_BUFF_LEN - 1;
4668         CV_LoadNetVars( &xc );
4669     }
4670 
4671     // Initial command, to avoid a separate command message.
4672     switch( netbuffer->u.servercfg.command )
4673     {
4674      case CTRL_normal:
4675         cl_mode = CLM_connected;
4676         break;
4677 #ifdef JOININGAME
4678      case CTRL_download_savegame:
4679         if(netbuffer->u.servercfg.gamestate == GS_LEVEL)
4680             GenPrintf(EMSG_hud, "Server Config: Download savegame when NOT GS_LEVEL\n");
4681         cl_mode = CLM_download_savegame;
4682         break;
4683 #endif
4684 #ifdef WAIT_GAME_START_INTERMISSION
4685      case CTRL_wait_game_start:
4686         cl_mode = CLM_wait_game_start;
4687         break;
4688 #endif
4689     }
4690 }
4691 
4692 // By Client
4693 // PT_SERVERSHUTDOWN from Server.
server_shutdown_handler()4694 static void server_shutdown_handler()
4695 {
4696     network_state = NETS_no_server;
4697     if( cl_mode != CLM_searching )
4698     {
4699         M_SimpleMessage("Server has Shutdown\n\nPress Esc");
4700         CL_Reset();
4701         D_StartTitle();
4702     }
4703 }
4704 
4705 // By Client
4706 // PT_NODE_TIMEOUT
server_timeout_handler()4707 static void server_timeout_handler()
4708 {
4709     network_state = NETS_no_server;
4710     if( cl_mode != CLM_searching )
4711     {
4712         M_SimpleMessage("Server Timeout\n\nPress Esc");
4713         CL_Reset();
4714         D_StartTitle();
4715     }
4716 }
4717 
4718 
4719 // Copy a single ticcmd_t, swapping between host and network byte order.
TicCmdCopy(ticcmd_t * dst,ticcmd_t * src)4720 static void TicCmdCopy( ticcmd_t * dst, ticcmd_t * src )
4721 {
4722 #ifdef CLIENTPREDICTION2
4723     dst->x = LE_SWAP32_FAST(src->x);
4724     dst->y = LE_SWAP32_FAST(src->y);
4725 #endif
4726     dst->forwardmove = src->forwardmove;
4727     dst->sidemove    = src->sidemove;
4728     dst->angleturn   = LE_SWAP16_FAST(src->angleturn);
4729     dst->aiming      = LE_SWAP16_FAST(src->aiming);
4730     dst->buttons     = src->buttons;
4731 #ifdef TICCMD_148
4732     dst->ticflags    = src->ticflags;
4733 #endif
4734 }
4735 
4736 // Detected a consistency fault.
4737 //  nnode : the client node
4738 //  fault_tic : tick with consistency fault
4739 //  btic : BTIC_INDEX for this network message
SV_consistency_fault(byte nnode,tic_t fault_tic,int btic)4740 static void SV_consistency_fault( byte nnode, tic_t fault_tic, int btic )
4741 {
4742     // It is the node that is not consistent.
4743     byte confault = ++consistency_faults[nnode];  // failure count
4744     uint16_t sv_con = consistency[btic];
4745     uint16_t cl_con = LE_SWAP16(netbuffer->u.clientpak.consistency);
4746 
4747     // No consistency fault during intermission, because of joining players who don't have position yet.
4748     if( gamestate == GS_INTERMISSION )
4749         return;
4750 
4751     if( verbose )
4752     {
4753         GenPrintf(EMSG_warn, "Consistency failure tic %d: node %d   consistency( server=%X client=%X )\n",
4754             fault_tic, nnode, sv_con, cl_con );
4755     }
4756 
4757     if( confault >= consistency_limit_fatal[cv_SV_netrepair.EV] )
4758     {
4759         // Failed the consistency check too many times
4760         if(! verbose )
4761             GenPrintf(EMSG_warn, "Consistency failure ( server=%X client=%X ), msg tic %d, Kick node %i\n",
4762                  sv_con, cl_con, fault_tic, nnode );
4763         DEBFILE(va("Consistency failure ( server=%i client=%i ), msg tic %d, Kick node %i\n",
4764                  sv_con, cl_con, fault_tic, nnode ));
4765 
4766 #ifdef DEBUG_DISABLE_KICK_PLAYERS
4767         // Debug message instead.
4768 //        GenPrintf(EMSG_warn, "Kick node %d at tic %d, consistency failure\n", nnode, fault_tic);
4769         SV_Send_player_repair( 255, 3, nnode );
4770 #else
4771         // Kick all players at the nnode.
4772         byte pn = nnode_to_player[0][nnode];
4773         SV_Send_NetXCmd_p2(XD_KICK, pn, KICK_MSG_CON_FAIL);
4774         GenPrintf(EMSG_warn, "Kick player %d\n", pn );
4775         DEBFILE(va("Kick player %d\n", pn ));
4776 
4777         pn = nnode_to_player[1][nnode];
4778         if( pn < MAXPLAYERS )
4779         {
4780             // Kick splitscreen player
4781             SV_Send_NetXCmd_p2(XD_KICK, pn, KICK_MSG_CON_FAIL);
4782             GenPrintf(EMSG_warn, "Kick player %d\n", pn );
4783             DEBFILE(va("Kick player %d\n", pn ));
4784         }
4785 #endif
4786     }
4787 #ifdef JOININGAME
4788     else if( ( (consistency_sg_bit[cv_SV_netrepair.EV] >> (confault-1)) & 0x01)
4789              && ( cv_SV_download_savegame.EV ))
4790     {
4791         // try to use savegame to fix consistency
4792         SV_Send_repair(RQ_SUG_SAVEGAME, nnode);
4793     }
4794 #endif
4795     else if( confault > 1 )
4796     {
4797         // try to fix consistency, all players
4798         SV_Send_player_repair(255, 3, nnode);
4799     }
4800     else
4801     {
4802         // try to fix consistency cheap
4803         SV_Send_player_repair(nnode_to_player[0][nnode], 2, nnode);
4804     }
4805 }
4806 
4807 
4808 // By Client.
4809 // Send the client packet to the server
4810 // Called by NetUpdate,
CL_Send_ClientCmd(void)4811 static void CL_Send_ClientCmd (void)
4812 {
4813     // index by  [mis]
4814     static byte  PT_CLIENTCMD_options[2] = {PT_CLIENTCMD, PT_CLIENTMIS};
4815     // index by  [mis]
4816     static byte  PT_NODEKEEPALIVE_options[2] = {PT_NODEKEEPALIVE, PT_NODEKEEPALIVEMIS};
4817 
4818 /* oops can do that until i have implemented a real dead reckoning
4819     static ticcmd_t lastcmdssent;
4820     static int      lastsenttime=-TICRATE;
4821 
4822     if( memcmp(&localcmds[0],&lastcmdssent,sizeof(ticcmd_t))!=0 || lastsenttime+TICRATE/3<I_GetTime())
4823     {
4824         lastsenttime=I_GetTime();
4825 */
4826 
4827     int packetsize=0;
4828 
4829     byte  cmd_options = 0;  // easier to understand and maintain
4830     if (cl_packetmissed)
4831         cmd_options = 1;  // MIS bit
4832 
4833     netbuffer->packettype = PT_CLIENTCMD_options[cmd_options];
4834     netbuffer->u.clientpak.resendfrom = cl_need_tic;
4835     netbuffer->u.clientpak.client_tic = gametic;  // byte
4836 
4837     if( gamestate == GS_WAITINGPLAYERS )
4838     {
4839         // Server is waiting for network players before starting the game.
4840         // send NODEKEEPALIVE, or NODEKEEPALIVEMIS packet
4841         netbuffer->packettype = PT_NODEKEEPALIVE_options[cmd_options];
4842 //        packetsize = sizeof(clientcmd_pak_t)-sizeof(ticcmd_t)-sizeof(int16_t);
4843         packetsize = offsetof(clientcmd_pak_t, consistency);
4844         HSendPacket( cl_servernode, 0, 0, packetsize );  // msg lost when too busy
4845     }
4846     else
4847     if( gamestate != GS_NULL )
4848     {
4849         int btic = BTIC_INDEX( gametic );
4850         netbuffer->u.clientpak.consistency = LE_SWAP16_FAST(consistency[btic]);
4851 
4852         // Mainplayer
4853         TicCmdCopy( &netbuffer->u.clientpak.cmd[0], /*src*/ &localcmds[0] );
4854 
4855         if (cv_splitscreen.value)
4856         {
4857             // Splitscreen player
4858             TicCmdCopy( &netbuffer->u.clientpak.cmd[1], /*src*/ &localcmds[1] );
4859             netbuffer->u.clientpak.pind_mask = 0x03;
4860             packetsize = sizeof(clientcmd_pak_t);
4861         }
4862         else
4863         {
4864             // only one player
4865             netbuffer->u.clientpak.pind_mask = 0x01;
4866             packetsize = offsetof(clientcmd_pak_t, cmd[1]);
4867         }
4868 
4869         HSendPacket( cl_servernode, 0, 0, packetsize );  // msg lost when too busy
4870     }
4871 }
4872 
4873 
4874 // By Server
4875 // PT_CLIENTCMD, PT_CLIENTMIS,
4876 // PT_NODEKEEPALIVE, PT_NODEKEEPALIVEMIS from Client.
client_cmd_handler(byte netcmd,byte nnode)4877 static void client_cmd_handler( byte netcmd, byte nnode )
4878 {
4879     tic_t  start_tic, end_tic;
4880     int  btic;
4881     byte pind;
4882 
4883     // To save bytes, only the low byte of tic numbers are sent
4884     // Figure out what the rest of the bytes are
4885     start_tic  = ExpandTics (netbuffer->u.clientpak.client_tic);
4886     end_tic = ExpandTics (netbuffer->u.clientpak.resendfrom);
4887 
4888     if(  netcmd == PT_CLIENTMIS
4889          || netcmd == PT_NODEKEEPALIVEMIS
4890          || nextsend_tic[nnode] < end_tic )
4891     {
4892         nextsend_tic[nnode] = end_tic;
4893     }
4894 
4895     // Discard out of order packet
4896     if( end_tic < nettics[nnode] )
4897     {
4898         DEBFILE(va("Late client ticcmd discarded: nettics %d\n",
4899                    nettics[nnode]));
4900         return;
4901     }
4902 
4903     // Update the nettics.
4904     nettics[nnode] = end_tic;
4905 
4906     // Don't do any tic cmds for drones, just update their nettics.
4907     if( playerpernode[nnode] == 0 )   // DRONE node indicator
4908        return;
4909 
4910     if( netcmd==PT_NODEKEEPALIVE || netcmd==PT_NODEKEEPALIVEMIS )
4911        return;
4912 
4913     // Check consistency
4914     if((start_tic <= gametic)
4915        && (start_tic > (gametic - BACKUPTICS + 1)) )
4916     {
4917         // within previous tics
4918         btic = BTIC_INDEX(start_tic);
4919         if(consistency[btic] != LE_SWAP16_FAST(netbuffer->u.clientpak.consistency))
4920         {
4921             // Failed the consistency check.
4922             SV_consistency_fault( nnode, start_tic, btic );  // node has failed consistency
4923             return;  // packet contents lost when other messages sent
4924         }
4925         else if( consistency_faults[nnode] > 0 )
4926         {
4927             consistency_faults[nnode] -- ;
4928         }
4929     }
4930 
4931     // Copy the ticcmd
4932     btic = BTIC_INDEX( maketic );
4933     // This packet may have 1 or 2 players
4934     byte pind_mask = netbuffer->u.clientpak.pind_mask;
4935     for( pind=0; pind<2; pind++ )
4936     {
4937         if( (pind_mask & (1<<pind)) == 0 )  continue;
4938         byte pn = nnode_to_player[pind][nnode];
4939         if( pn < MAXPLAYERS )
4940             TicCmdCopy( &netcmds[btic][pn], /*src*/ &netbuffer->u.clientpak.cmd[pind] );
4941     }
4942     return;
4943 }
4944 
4945 
4946 // [WDJ] The ver 1.48 server tic packet has a new format.  It can send extension
4947 // packets when needed.
4948 // All of the textcmd will be included.
4949 
4950 // By Server.
4951 // Send PT_SERVERTICS, the server packet.
4952 // Send tic from next_tic_send to maketic-1.
SV_Send_Tics(void)4953 static void SV_Send_Tics (void)
4954 {
4955     static byte resend_cnt = 0;  // spread resends at less cost than Get_Time
4956 
4957     ticcmd_t * netcmd_p;
4958     byte * bufpos;  // net txtcmd text
4959     byte * endbuf, * end_ticcmd;
4960 
4961     tic_t start_tic, end_tic, ti;
4962     int  btic, j;
4963     int  packsize;
4964     int  total_textcmd_size;
4965     byte seq_num, num_cmds, num_txt, flags;
4966     byte nnode, pn;
4967 
4968     // update_player_counts sets ticcmd_player_mask, num_ticcmd_per_tic, ticcmd_pid[].
4969 
4970     // Send PT_SERVERTIC to all client, but not to myself.
4971     // For each node create a packet with num_tics and send it.
4972     // Compute num_tics using nextsend_tic[n], max packet size, and maketic.
4973     // Assume cl_servernode=0.
4974     for(nnode=1; nnode<MAXNETNODES; nnode++)
4975     {
4976         if( nnode_state[nnode] < NOS_client )  continue;
4977         // Need this to send the NetXCmd Add Player
4978 
4979         // For each node create a packet with x tics and send it.
4980         // x is computed using nextsend_tic[n], max packet size and maketic.
4981 
4982         // Send a packet to each client node in this game.
4983         // They may be different, with individual status.
4984         end_tic = maketic;
4985           // The last tic to send is one before maketic.
4986           // Does not send end_tic.
4987 
4988         // assert nextsend_tic[nnode]>=nettics[nnode]
4989         start_tic = nextsend_tic[nnode];  // last tic sent to this nnode
4990 
4991         if(start_tic >= maketic)
4992         {
4993             // We have sent all tics, so we will use the extrabandwidth
4994             // to resend packets that are supposed lost.
4995             // This is necessary since lost packet detection works when we
4996             // have received packet with (firsttic > cl_need_tic)
4997             // (in the getpacket servertics case).
4998             DEBFILE(va("Send Tics none: node %d maketic %u nxttic %u nettic %u\n",
4999                        nnode, maketic, nextsend_tic[nnode], nettics[nnode]));
5000             // Client sends a tic, then server re-sends the ticcmds to everyone.
5001             start_tic = nettics[nnode];  // last client tic received by server
5002             if( start_tic >= maketic )
5003                 continue;  // all tic are ok, do next node
5004             if( (nnode + resend_cnt++)&3 )  // some kind of randomness
5005                 continue;  // skip it
5006             DEBFILE(va("Send Tics Resend: node %d from tic %d\n", nnode, start_tic));
5007         }
5008 
5009         // Limit start to first new tic we have.
5010         if( start_tic < next_tic_send )
5011             start_tic = next_tic_send;
5012 
5013         // Compute the length of the packet and cut it if too large.
5014         packsize = SERVER_TIC_BASE_SIZE;
5015         total_textcmd_size = 0;
5016         for(ti=start_tic; ti<end_tic; ti++)
5017         {
5018             // All of the ticcmd
5019             packsize += sizeof(ticcmd_t) * num_ticcmd_per_tic;
5020             // All of the textcmd buffer and support fields
5021             // Optional textcmd support fields, are only needed when there are textcmd.
5022             int tcblen = textcmdbuff[ BTIC_INDEX(ti) ].len;
5023             if( tcblen )
5024             {
5025                 total_textcmd_size += sizeof_servertic_textcmd_t( tcblen );
5026             }
5027 
5028 #if 1
5029             // Limit each to 1 packet.
5030             if( (packsize > software_MAXPACKETLENGTH) || (total_textcmd_size > software_MAXPACKETLENGTH) )
5031 #else
5032             // Limit together at 1 packet.
5033             if( (packsize + total_textcmd_size) > software_MAXPACKETLENGTH )
5034 #endif
5035             {
5036                 // Exceeds max packet size.
5037                 // Will send extension packets to carry excess ticcmd, and all textcmd.
5038                 if(ti == start_tic)  ti++;  // do at least one tic, will send extension packet
5039 
5040                 DEBFILE(va("Packet size limited (%d) (tics %d to %d)  send tic %d \n",
5041                             packsize, start_tic, end_tic - 1, ti - 1));
5042 
5043                 end_tic = ti;  // limit this packet due to size
5044                 break;
5045             }
5046         }
5047 
5048         // Send the tics, start_tic..(end_tic-1).
5049 
5050         // Header
5051         netbuffer->packettype = PT_SERVERTICS;
5052         netbuffer->u.serverpak.starttic = start_tic;
5053         netbuffer->u.serverpak.numtics = (end_tic - start_tic); // num tics
5054         write_N32( &netbuffer->u.serverpak.cmd_player_mask, ticcmd_player_mask );  // players that send ticcmd
5055 
5056         // init
5057         netbuffer->u.serverpak.cmds_offset = 0;
5058         netbuffer->u.serverpak.num_textcmd = 0;
5059         flags = seq_num = num_cmds = num_txt = 0;
5060 
5061         bufpos= (byte *)&netbuffer->u.serverpak.cmds;
5062         // limits
5063         endbuf= ((byte*)netbuffer) + software_MAXPACKETLENGTH - 1;
5064         end_ticcmd = endbuf - sizeof(ticcmd_t);
5065         if( end_ticcmd > (byte*)& netbuffer->u.serverpak.cmds[NUM_SERVERTIC_CMD-1] )
5066             end_ticcmd = (byte*)& netbuffer->u.serverpak.cmds[NUM_SERVERTIC_CMD-1];
5067 
5068         // All the ticcmd_t, start_tic..(end_tic-1)
5069         for(ti=start_tic; ti<end_tic; ti++)
5070         {
5071             btic = BTIC_INDEX( ti );
5072             netcmd_p = netcmds[btic];
5073 
5074             // Send only the ticcmd of players in game.
5075             for( j=0; j<num_ticcmd_per_tic; j++ )
5076             {
5077                 if( bufpos > end_ticcmd )
5078                 {
5079                     // send packet section
5080                     netbuffer->u.serverpak.flags = TPF_more | flags | seq_num;
5081                     netbuffer->u.serverpak.num_cmds_present = num_cmds;
5082                     packsize = bufpos - (byte*)&(netbuffer->u);
5083                     HSendPacket(nnode, 0, 0, packsize);  // msg lost when too busy
5084 
5085                     // init next seq packet
5086                     netbuffer->u.serverpak.cmds_offset += num_cmds;
5087                     num_cmds = 0;
5088                     seq_num ++;
5089                     bufpos = (byte*)&netbuffer->u.serverpak.cmds;
5090                 }
5091 
5092                 // Use list of pid generated from playeringame and player_state.
5093                 pn = ticcmd_pid[j];
5094                 TicCmdCopy( (ticcmd_t*) bufpos, /*src*/ &netcmd_p[pn] );
5095                 bufpos += sizeof(ticcmd_t);
5096                 num_cmds++;  // ticcmd count
5097             }
5098         }
5099         netbuffer->u.serverpak.num_cmds_present = num_cmds;
5100         // Done writing ticcmds
5101 
5102         if( total_textcmd_size )
5103         {
5104             // All the textcmd, start_tic..(end_tic-1)
5105             // [WDJ] Most often there are no textcmd.  Make that case simple and small.
5106 
5107             // [WDJ] Ver 1.48, easy to send in multiple packets
5108 
5109             // The bufpos is always at end-of-packet; cannot update until the textcmd section actually gets text.
5110             for(ti=start_tic; ti<end_tic; ti++)
5111             {
5112                 // textcmd from players, bots, server
5113                 btic = BTIC_INDEX( ti );
5114                 textcmdbuff_t * tcbuf = & textcmdbuff[btic];
5115                 unsigned int buflen = tcbuf->len;
5116                 if( buflen == 0 )  continue;
5117 
5118                 if(((bufpos + sizeof_servertic_textcmd_t(buflen)) > endbuf)  // not enough room in packet
5119                     || ( num_txt >= 250 ) )   // force send
5120                 {
5121                     // Send packet, start new extension packet.
5122                     // Rarely executed.  Required when many players are texting at once.
5123                     // This may be ticcmd only, or both, or textcmd only.
5124                     netbuffer->u.serverpak.flags = TPF_more | flags | seq_num;
5125                     netbuffer->u.serverpak.num_textcmd = num_txt; // the number of textcmd
5126                     packsize = bufpos - (byte *)&(netbuffer->u);
5127                     HSendPacket(nnode, 0, 0, packsize);  // msg lost when too busy
5128 
5129                     // init next seq packet
5130                     netbuffer->u.serverpak.num_cmds_present = 0;
5131                     seq_num ++;
5132 
5133                     // Reset to start of data area, keep same packet header.
5134                     bufpos = (byte *)&netbuffer->u.serverpak.cmds;
5135                     num_txt = 0;
5136                 }
5137 
5138                 // Tics with textcmd, use a servertic_textcmd_t, unaligned.
5139                 // All players and server textcmd are already packed into the buffer.
5140                 servertic_textcmd_t * stcp = (servertic_textcmd_t *)bufpos;
5141                 stcp->tic = ti;
5142                 write_N16( & stcp->len, buflen );
5143                 // Send the textcmdbuf, length limited.
5144                 memcpy(&stcp->textitem, &tcbuf->buff, buflen);
5145                 // Cannot add field sizes as the structure might be padded.
5146                 bufpos += sizeof_servertic_textcmd_t( buflen );  // tic, len(2 bytes), buf
5147                 num_txt++;  // num_textcmd, the count of the servertic_textcmd_t
5148             }
5149             netbuffer->u.serverpak.num_textcmd = num_txt; // the number of servertic_textcmd_t
5150         }
5151 
5152         netbuffer->u.serverpak.flags = flags | seq_num; // last packet
5153         packsize = bufpos - (byte*)&(netbuffer->u);
5154         HSendPacket( nnode, 0, 0, packsize );  // msg lost when too busy
5155 
5156         // Record next tic for this net node.
5157         // Extratic causes redundant transmission of tics.
5158         ti = (end_tic - doomcom->extratics);  // normal
5159         // When tic is too large, only one tic is sent so don't go backward !
5160         if( ti <= start_tic )
5161            ti = end_tic;  // num tics is too small for extratics
5162         if( ti < nettics[nnode] )
5163            ti = nettics[nnode];
5164         nextsend_tic[nnode] = ti;
5165     }
5166     // node 0 is me !
5167     nextsend_tic[0] = maketic;
5168 }
5169 
5170 
5171 // By Client. Server does not send to self.
5172 // PT_SERVERTICS from Server.
servertic_handler(byte nnode)5173 static void servertic_handler( byte nnode )
5174 {
5175     ticcmd_t * netcmd_p;  // player array
5176     byte * bufpos;  // netbuffer position, end-of-data
5177     byte * endbuffer;  // for buffer overrun tests
5178     servertic_textcmd_t * stcp;
5179     textcmdbuff_t * tcbuf;
5180     int    btic, j;
5181     uint16_t buflen;
5182     uint32_t cmd_player_mask;
5183     tic_t  start_tic, end_tic, ti;
5184     byte   start_tic_hash;
5185     byte   packetflags;
5186     byte   seqbits;
5187     byte   cmds_offset, num_cmds, num_txt;
5188 
5189     start_tic = ExpandTics (netbuffer->u.serverpak.starttic);
5190     end_tic   = start_tic + netbuffer->u.serverpak.numtics;
5191 
5192     if( end_tic > (gametic + BACKUPTICS))
5193         end_tic = (gametic + BACKUPTICS);  // limit to backup capability
5194 
5195     // Check if missed any packets.
5196     cl_packetmissed = (start_tic > cl_need_tic);
5197 
5198     if((start_tic > cl_need_tic) || (end_tic <= cl_need_tic))
5199        goto not_in_packet;
5200 
5201     // The needed tic is within this packet.
5202     packetflags = netbuffer->u.serverpak.flags;  // tic_packet_flag_e
5203     // one bit per packet section by seq, last fills upper bits to make 0xFF
5204     seqbits = 1 << (packetflags & TPF_seq);  // 0..7 => 0x01 .. 0x80
5205     if( ! (packetflags & TPF_more) )  seqbits = -seqbits;  // 0x01=>0xFF, 0x08=>0xF8
5206 
5207     // First the nettics then the net textcmds.
5208     bufpos = (byte*)netbuffer->u.serverpak.cmds;  // first ticcmd
5209     endbuffer = (byte*)& netbuffer->u.serverpak.cmds[NUM_SERVERTIC_CMD];  // after last content
5210 
5211     cmd_player_mask = read_N32( &netbuffer->u.serverpak.cmd_player_mask );
5212     cmds_offset = netbuffer->u.serverpak.cmds_offset;
5213     num_cmds = netbuffer->u.serverpak.num_cmds_present;
5214     if( num_cmds > NUM_SERVERTIC_CMD )  goto corrupt_packet;
5215 
5216     // Hash differs between this packet and previous usage of the same btic.
5217     // Could compute it for every tic in the packet, but is not necessary.
5218     // All extension packet have the same start_tic.
5219     // Do clear separately so out-of-order packets cannot invoke errors.
5220     // Otherwise, would have to appear in both ticcmds and textcmds code.
5221     start_tic_hash = btic_hash( start_tic );
5222     for( ti=start_tic; ti<end_tic; ti++ )
5223     {
5224         // client only
5225         btic = BTIC_INDEX( ti );
5226         if( netcmd_tic_hash[btic] != start_tic_hash )
5227         {
5228             // first packet for this tic, clear old stuff
5229             D_Clear_ticcmd(btic);
5230             netcmd_tic_hash[btic] = start_tic_hash;  // after clear
5231         }
5232         // When this was in textcmds, it would only record for those that
5233         // had actually sent a textcmd.
5234         // If that packet had num_cmds=0, then empty textcmds would never be ready.
5235         netseq[btic] |= seqbits; // record receiving this packet section
5236     }
5237 
5238     // Nettics
5239     // Some extension packets may have num_cmds = 0
5240     if( num_cmds && cmd_player_mask )
5241     {
5242         // client only
5243         // Update the player list according to cmd_player_mask
5244         if( cmd_player_mask != ticcmd_player_mask )
5245             CL_num_ticcmd_per( cmd_player_mask );  // num_ticcmd_per_tic
5246 
5247         ti = start_tic;
5248         if( cmds_offset > num_ticcmd_per_tic )
5249         {
5250             // extension packet after multiple tics
5251             byte whole_tics = cmds_offset / num_ticcmd_per_tic;  // whole tics in previous packet
5252 
5253             ti += whole_tics;
5254             cmds_offset -= whole_tics * num_ticcmd_per_tic;  // 0..num_ticcmd_per_tic
5255         }
5256 
5257         for( ; ti<end_tic; ti++)
5258         {
5259             if( num_cmds == 0 )  break;  // limited to ticcmd in this packet
5260             num_cmds --;
5261 
5262             // Copy the tics
5263             btic = BTIC_INDEX( ti );
5264             // btic limited to BACKUPTICS-1
5265 
5266             netcmd_p = netcmds[btic];  // player dest
5267 
5268             // when extension packet, cmds_offset is non-zero
5269             for( j = cmds_offset; j<num_ticcmd_per_tic; j++ )
5270             {
5271                 // Use list of pid generated from cmd_player_mask.
5272                 byte pn = ticcmd_pid[j];
5273                 TicCmdCopy( &netcmd_p[pn], /*src*/ (ticcmd_t*) bufpos );
5274                 bufpos += sizeof(ticcmd_t);
5275             }
5276             cmds_offset = 0;
5277         }
5278     }
5279 
5280     // [WDJ] Ver 1.48, easy to send in multiple packets
5281     // Some packets have textcmds, most do not.
5282     num_txt = netbuffer->u.serverpak.num_textcmd;  // number textcmd sections field
5283     while( num_txt-- )
5284     {
5285         // Tics that have a textcmd have a servertic_textcmd_t, unaligned.
5286         // All players and server textcmd are already packed into the buffer.
5287         stcp = (servertic_textcmd_t *)bufpos;
5288 
5289         buflen = read_N16( & stcp->len );  // length of servertic_textcmd_t content
5290         if( (bufpos + buflen) > endbuffer )  goto textcmd_exceed_buffer;
5291         if( buflen > MAX_TEXTCMD_BUFF+1 )  goto textcmd_exceed_buffer;  // prevent dest overrun
5292 
5293         ti = ExpandTics( stcp->tic );
5294         if( (ti < start_tic) || (ti > end_tic) )  goto corrupt_packet;
5295 
5296         btic = BTIC_INDEX( ti );
5297         tcbuf = & textcmdbuff[btic];
5298         memcpy(&tcbuf->buff, &stcp->textitem, buflen);
5299         tcbuf->len = buflen;
5300         // Cannot add field sizes as the structure might be padded.
5301         bufpos += sizeof_servertic_textcmd_t( buflen );  // tic, len(2 bytes), buf
5302     }
5303 
5304     // Only advance to the next tic when all packet extensions are received.
5305     if( netseq[ BTIC_INDEX(start_tic) ] == 0xFF )
5306         cl_need_tic = end_tic;
5307 
5308     return;
5309 
5310  corrupt_packet:
5311     I_SoftError("Nettics: corrupt packet.\n");
5312     return;
5313  textcmd_exceed_buffer:
5314     I_SoftError("Nettics: textcmd exceed buffer: len=%i\n", buflen);
5315     return;
5316  not_in_packet:
5317     DEBFILE(va("Needed tic not in packet: needed tic %u, packet tic %u to %u\n", cl_need_tic, start_tic, end_tic));
5318     return;
5319 }
5320 
5321 
5322 //
5323 // Get Packets and invoke their Server and Client handlers.
5324 //
Net_Packet_Handler(void)5325 static void Net_Packet_Handler(void)
5326 {
5327     byte client_pn;
5328     byte nnode, nodestate, packettype;
5329 
5330     while ( HGetPacket() )
5331     {
5332         nnode = doomcom->remotenode;  // 0..MAXNETNODES-1, BROADCAST_NODE
5333         nodestate = (nnode < MAXNETNODES)?  nnode_state[nnode] : NOS_invalid;
5334         packettype = netbuffer->packettype;
5335 
5336         // [WDJ] Run-time messages are given priority in speed of handling.
5337 
5338         // ---- SERVER handling packets of known clients nodes.
5339         if( server && (nodestate >= NOS_recognized))
5340         {
5341             // [WDJ] pn no longer has DRONE bit.
5342             client_pn = nnode_to_player[0][nnode];  // the player
5343             // Every message type must handle the invalid client_pn individually.
5344 
5345             // Messages handled by server, for known client nodes.
5346             switch(packettype)
5347             {
5348              case PT_CLIENTCMD  :
5349              case PT_CLIENT2CMD :
5350              case PT_CLIENTMIS  :
5351              case PT_CLIENT2MIS :
5352              case PT_NODEKEEPALIVE :
5353              case PT_NODEKEEPALIVEMIS :
5354                 // updates nettics for invalid client_pn
5355                 client_cmd_handler( packettype, nnode );
5356                 continue;
5357              case PT_TEXTCMD2 : // splitscreen special
5358                 client_pn = nnode_to_player[1][nnode];
5359                 // fall through
5360              case PT_TEXTCMD :
5361                 if( client_pn >= MAXPLAYERS )  // unused = 255
5362                 {
5363                     // Do not ACK the packet from a strange client_pn.
5364                     Net_Cancel_Packet_Ack(nnode);
5365                     continue;
5366                 }
5367                 net_textcmd_handler( nnode );
5368                 continue;
5369              case PT_NODE_TIMEOUT:
5370              case PT_CLIENTQUIT:
5371                 // still closes the connection when invalid client_pn
5372                 client_quit_handler( nnode, client_pn );
5373                 continue;
5374              default:
5375                 break;
5376             }
5377         }
5378 
5379         // ---- CLIENT Handling Server packets.
5380         if( (nnode == cl_servernode) && (cl_mode >= CLM_server_files) )  // from the known server
5381         {
5382             // Messages from the server, for known server.
5383             switch(packettype)
5384             {
5385              case PT_SERVERTICS :
5386                 servertic_handler( nnode );
5387                 continue;
5388              case PT_FILEFRAGMENT :
5389                 if( !server )
5390                     Got_Filetxpak();
5391                 continue;
5392              case PT_NETWAIT:
5393                 if( !server )
5394                     netwait_handler();
5395                 continue;
5396              case PT_STATE:
5397                 if( !server )
5398                     state_handler();  // to client
5399                 continue;
5400              case PT_SERVERPLAYER :
5401 #ifdef WAIT_GAME_START_INTERMISSION
5402                 if( ! server )
5403                     server_player_handler( nnode );
5404 #endif
5405                 continue;
5406              case PT_SERVERLEVEL :
5407                 if( ! server )
5408                     server_level_handler( nnode );
5409                 continue;
5410              case PT_REPAIR:
5411                 repair_handler_client( nnode );  // from server
5412                 continue;
5413              default:
5414                 break;
5415             } // end switch
5416         }
5417 
5418         // Infrequent messages from server.
5419         if( nnode == cl_servernode )
5420         {
5421             // Any Client that knows the server.
5422             // These messages are recognized, but application is limited.
5423             switch(packettype)
5424             {
5425              case PT_STATE:
5426                 if( !server )
5427                     state_handler();  // to client
5428                 continue;
5429              case PT_CONTROL:
5430                 control_msg_handler();
5431                 continue;
5432              case PT_REQ_CLIENTCFG : // request client config
5433                 D_Send_PlayerConfig();  // Client players, via NetXCmd to everybody
5434                     // client players only, does not cover bots
5435                 continue;
5436              case PT_SERVERSHUTDOWN:
5437                 if( ! server )
5438                     server_shutdown_handler();  // only client not on server
5439                 continue;
5440              case PT_NODE_TIMEOUT:  // from server
5441                 // must be before PT_NODE_TIMEOUT from client.
5442                 if( ! server )
5443                     server_timeout_handler();  // only client not on server
5444                 continue;
5445             }
5446         }
5447 
5448         // Infrequent messages, from anybody.
5449         if( server )
5450         {
5451             // Packet can be from client trying to join server.
5452             if( (nnode != cl_servernode) && (nodestate < NOS_recognized) )
5453             {
5454                 // Client trying to Join.
5455                 DEBFILE(va("Received packet from unknown host %d\n",nnode));
5456             }
5457 
5458             // Can only be handled by a server.
5459             switch(packettype)
5460             {
5461              case PT_TEXTCMD :
5462                 // Server to server use of client channel for server NetXCmd, with no players.
5463                 // No valid player num for this nnode.
5464                 net_textcmd_handler( nnode );
5465                 continue;
5466              case PT_ASKINFO:  // client has asked server for info
5467                 // May have been sent to BROADCAST_NODE, but nnode is sender.
5468                 server_askinfo_handler( nnode );
5469                 continue;
5470              case PT_REQUESTFILE :
5471                 if( cv_SV_download_files.EV == 0 )
5472                 {
5473                     GenPrintf(EMSG_ver, "RequestFile: Blocked, Not Allowed\n" );
5474                     continue;
5475                 }
5476                 Got_RequestFilePak(nnode);
5477                 continue;
5478              case PT_CLIENTJOIN:
5479                 client_join_handler( nnode );
5480                 continue;
5481              case PT_CLIENTREADY:
5482                 ready_handler( nnode );
5483                 continue;
5484              case PT_REQ_SERVERPLAYER :
5485 #ifdef WAIT_GAME_START_INTERMISSION
5486                 SV_Send_PlayerState( nnode );
5487 #endif
5488                 continue;
5489              case PT_REQ_SERVERLEVEL :
5490                 SV_Send_LevelCfg( nnode );
5491                 continue;
5492              case PT_REPAIR:
5493                 if( nodestate >= NOS_recognized )
5494                     repair_handler_server( nnode );  // from client
5495                 continue;
5496              case PT_NODE_TIMEOUT:  // from unknown client
5497              case PT_CLIENTQUIT:  // when unknown client
5498                 Net_CloseConnection(nnode, 0);  // normal closing
5499                 continue;
5500             }
5501         }
5502 
5503         // Prospective Client, Client handling of server messages.
5504         if( cl_mode != CLM_connected )  // Protect against rogue interference.
5505         {
5506             // Messages to client before connected. They change client state.
5507             switch(packettype)
5508             {
5509              case PT_SERVERINFO:
5510                 // response from server to BROADCAST_NODE message, should have nnode same as new cl_servernode
5511                 server_info_handler( nnode );
5512                 continue;
5513              case PT_SERVERREFUSE : // negative response of client join request
5514                 server_refuse_handler( nnode );
5515                 continue;
5516              case PT_SERVERCFG :    // positive response of client join request
5517                 server_cfg_handler( nnode );
5518                 continue;
5519              case PT_FILEFRAGMENT :
5520                 // handled in d_netfil.c
5521                 if( !server )
5522                     Got_Filetxpak();
5523                 continue;
5524              case PT_SERVERTICS:
5525                 // do not remove my own server
5526                 // (we have just to get a out of order packet)
5527                 if( nnode == cl_servernode )  continue;
5528 #if 1
5529                 goto invalid;  // Server tic from unknown source.
5530 #else
5531                 break;  // kill it
5532 #endif
5533             }
5534         }
5535 
5536         switch(packettype)
5537         {
5538          case PT_ASKINFO:  // broadcast, non-servers should ignore it
5539          case PT_SERVERCFG :  // server cfg at wrong time
5540          case PT_NODE_TIMEOUT:  // errant
5541             continue;  // ignore
5542          case PT_REQUESTFILE :
5543             if( ! server )  goto server_only;
5544             continue;
5545         }
5546 
5547         // Packet not accepted.
5548         if((nnode >= MAXNETNODES) || (nodestate < NOS_recognized))
5549         {
5550             DEBFILE(va("Unknown packet received (%d) from unknown host !\n", packettype));
5551             goto close_node;
5552         }
5553 
5554         DEBFILE(va("Unknown packet type: type %d node %d\n", packettype, nnode));
5555         continue;
5556 
5557     server_only:
5558         GenPrintf(EMSG_warn, "Recv warn: unknown node=%i, Client ignores server only packet type (%d).\n", nnode, packettype );
5559         DEBFILE(va("Recv warn: unknown node=%i, Client ignores server only packet type (%d).\n", nnode, packettype));
5560         goto close_node;
5561 
5562 #if 1
5563     invalid:
5564         GenPrintf(EMSG_warn, "Recv warn: unknown node=%i, packet with unknown type (%d)\n", nnode, packettype );
5565         DEBFILE(va("Recv warn: unknown node=%i, packet received unknown type (%d)\n", nnode, packettype));
5566         goto close_node;
5567 #endif
5568 
5569     close_node:
5570         Net_CloseConnection(nnode, 0);  // a temp connection
5571         continue;
5572     } // end while
5573 
5574     if( server && network_wait_pause )
5575         SV_network_wait_handler();
5576 }
5577 
5578 
5579 // ----- NetUpdate
5580 // Builds ticcmds for console player,
5581 // sends out a packet
5582 
5583 // no more use random generator, because at very first tic isn't yet synchronized
Consistency(void)5584 static int16_t Consistency(void)
5585 {
5586     int16_t ret=0;
5587     int   pn;
5588 
5589     DEBFILE(va("TIC %d ",gametic));
5590     for(pn=0; pn<MAXPLAYERS; pn++)
5591     {
5592         if( playeringame[pn] && players[pn].mo )
5593         {
5594             DEBFILE(va("p[%d].x = %f ", pn, FIXED_TO_FLOAT(players[pn].mo->x)));
5595             ret += players[pn].mo->x;
5596         }
5597     }
5598     DEBFILE(va("pos = %d, rnd %d\n", ret, P_Rand_GetIndex()));
5599     ret+=P_Rand_GetIndex();
5600 
5601     return ret;
5602 }
5603 
5604 
5605 
5606 //
5607 // TryRunTics
5608 //
Local_Maketic(int realtics)5609 static void Local_Maketic(int realtics)
5610 {
5611     rendergametic=gametic;
5612     // translate inputs (keyboard/mouse/joystick) into game controls
5613     G_BuildTiccmd(&localcmds[0], realtics, 0);
5614     // [WDJ] requires splitscreen and player2 present
5615     if (cv_splitscreen.value && displayplayer2_ptr )
5616       G_BuildTiccmd(&localcmds[1], realtics, 1);
5617 
5618 #ifdef CLIENTPREDICTION2
5619     if( !paused && localgametic<gametic+BACKUPTICS)
5620     {
5621         P_MoveSpirit ( &players[consoleplayer], &localcmds[0], realtics );
5622         localgametic+=realtics;
5623     }
5624 #endif
5625 #ifdef TICCMD_148
5626     // moved to G_BuildTiccmd
5627 #else
5628     localcmds[0].angleturn |= TICCMD_RECEIVED;
5629 #endif
5630 }
5631 
SV_SpawnPlayer(byte playernum,int x,int y,angle_t angle)5632 void SV_SpawnPlayer( byte playernum, int x, int y, angle_t angle )
5633 {
5634     // for futur copytic use the good x,y and angle!
5635     if( server )
5636     {
5637         ticcmd_t * tc = &netcmds[ BTIC_INDEX(maketic) ][playernum];
5638 #ifdef CLIENTPREDICTION2
5639         tc->x = x;
5640         tc->y = y;
5641 #endif
5642 #ifdef TICCMD_148
5643         tc->angleturn = (angle>>16);
5644         tc->ticflags = TC_received;
5645 #else
5646         tc->angleturn=(angle>>16) | TICCMD_RECEIVED;
5647 #endif
5648     }
5649 }
5650 
5651 // create missed tic
SV_Maketic(void)5652 void SV_Maketic(void)
5653 {
5654     int btic = BTIC_INDEX( maketic );
5655     int bticprev, i, player;
5656     byte nnode;
5657 
5658     for(nnode=0; nnode<MAXNETNODES; nnode++)
5659     {
5660         if(playerpernode[nnode] == 0)  continue;  // not in use or DRONE
5661 
5662         // Detect missing ticcmd, using only player[0] at the node.
5663         player = nnode_to_player[0][nnode];
5664 #ifdef TICCMD_148
5665         if((netcmds[btic][player].ticflags & TC_received) == 0)
5666 #else
5667         if((netcmds[btic][player].angleturn & TICCMD_RECEIVED) == 0)
5668 #endif
5669         {
5670             // Catch startup glitch where playerpernode gets set
5671             // before the player is actually setup.
5672             if( ! playeringame[player] )  continue;
5673 
5674             DEBFILE(va("MISS tic %4u for node %d\n", maketic, nnode));
5675 #ifdef PARANOIA
5676             if( devparm > 1 )
5677                 GenPrintf(EMSG_dev, "\2Client %d Miss tic %d\n", nnode, maketic);
5678 #endif
5679             // Copy the previous tic
5680             bticprev = BTIC_INDEX(maketic-1);
5681             for(i=0; i<playerpernode[nnode]; i++)
5682             {
5683                 // All players at the node
5684                 netcmds[btic][player] = netcmds[bticprev][player];
5685 #ifdef TICCMD_148
5686                 netcmds[btic][player].ticflags &= ~TC_received;
5687 #else
5688                 netcmds[btic][player].angleturn &= ~TICCMD_RECEIVED;
5689 #endif
5690                 player = nnode_to_player[1][nnode];
5691             }
5692         }
5693     }
5694     // all tic are now present, make the next
5695     maketic++;
5696 }
5697 
5698 #ifdef DEBUGFILE
5699 static  int     net_load;
5700 #endif
5701 
5702 //  realtics: 0..5
TryRunTics(tic_t realtics)5703 void TryRunTics (tic_t realtics)
5704 {
5705     // the machine have laged but is not so bad
5706     if(realtics>TICRATE/7) // FIXME: consistency failure!!
5707     {
5708         if(server)
5709             realtics=1;
5710         else
5711             realtics=TICRATE/7;
5712     }
5713 
5714     if(singletics)
5715         realtics = 1;
5716 
5717     if( realtics > 0 )
5718         COM_BufExecute( CFG_none );
5719 
5720     NetUpdate();
5721 
5722     if(demoplayback)
5723     {
5724         cl_need_tic = gametic + realtics + cv_playdemospeed.value;
5725         // start a game after a demo
5726         maketic+=realtics;
5727         next_tic_send=maketic;
5728         next_tic_clear=next_tic_send;
5729     }
5730 
5731 #ifdef DEBUGFILE
5732     if(realtics==0)
5733         if(net_load) net_load--;
5734 #endif
5735     Net_Packet_Handler();
5736 
5737 #ifdef DEBUGFILE
5738     if (debugfile && (realtics || cl_need_tic>gametic))
5739     {
5740         //SoM: 3/30/2000: Need long int in the format string for args 4 & 5.
5741         fprintf (debugfile,
5742                  "------------ Tryruntic : REAL:%lu NEED:%lu GAME:%lu LOAD: %i\n",
5743                  (unsigned long)realtics, (unsigned long)cl_need_tic,
5744                  (unsigned long)gametic, net_load);
5745         net_load=100000;
5746     }
5747 #endif
5748 
5749     if( gamestate == GS_WAITINGPLAYERS )
5750     {
5751         // Server is waiting for network players.
5752         // To wait, execution must not reach G_Ticker.
5753         if( network_state < NETS_open )
5754             goto error_ret;  // connection closed by cancel or timeout
5755 
5756         if( realtics <= 0 )
5757             return;
5758 
5759         // Once per tic
5760         // Wait for players before netgame starts.
5761         if( ! D_WaitPlayer_Ticker() )
5762             return;  // Waiting
5763 
5764         // Start game
5765         if( dedicated )
5766             gamestate = GS_DEDICATEDSERVER;
5767         // Others must wait for load game to set gamestate to GS_LEVEL.
5768     }
5769     else if( gamestate == GS_INTERMISSION )
5770     {
5771         // [WDJ] Server runs timer, even when client is not-active.
5772         // G_Ticker does the GS_INTERMISSION effects.
5773         // Timer for start of next game level.
5774         if(( wait_game_start_timer > 0 ) && ! paused && (realtics > 0))
5775         {
5776             wait_game_start_timer--;
5777             if( wait_game_start_timer == 0 )
5778             {
5779                 S_StartSound(sfx_slop);
5780 
5781                 WI_Init_NoState();  // start transition to G_NextLevel
5782             }
5783 
5784             if( (wait_game_start_timer & 0x1F) == 0x03 )
5785             {
5786                 // Update the wait timer, to keep everyone in sync
5787                 SV_Send_control( BROADCAST_NODE, CTRL_wait_timer, 0, wait_game_start_timer, 255 );
5788             }
5789         }
5790     }
5791 
5792     // Server keeps forcing (cl_need_tic = maketic) in SV_Send_Tic_Update,
5793     // as it does not send tic packets to itself.
5794     if( cl_need_tic > gametic )
5795     {
5796         // All ticcmd and textcmd for gametic to cl_need_tic are present.
5797 
5798         if (demo_ctrl == DEMO_seq_advance)  // and not disabled
5799         {
5800             D_DoAdvanceDemo ();
5801             return;
5802         }
5803 
5804         // Run the count * tics
5805         while( cl_need_tic > gametic )
5806         {
5807 #ifdef CLIENTPREDICTION2
5808             DEBFILE(va("==== Run tic %u (local %d)\n",gametic, localgametic));
5809 #else
5810             DEBFILE(va("==== Run tic %u\n",gametic));
5811 #endif
5812 
5813             if(demoplayback)
5814             {
5815                 // Clean up textcmd, so demoplay can append.
5816                 D_Clear_ticcmd( gametic );
5817             }
5818 
5819             G_Ticker ();
5820             ExtraDataTicker();  // execute NetXCmd
5821             gametic++;
5822             // skip paused tic in a demo
5823             if(demoplayback)
5824             {
5825                 if(paused)
5826                    cl_need_tic++;
5827             }
5828             else
5829             {
5830                 // Consistency is calculated first thing in gametic.
5831                 consistency[ BTIC_INDEX( gametic ) ] = Consistency();
5832             }
5833         }
5834     }
5835     return;
5836 
5837 error_ret:
5838     D_StartTitle();
5839     return;
5840 }
5841 
5842 // By Server
5843 // Send Tic updates
SV_Send_Tic_Update(int count)5844 static void SV_Send_Tic_Update( int count )
5845 {
5846     byte nn;
5847 
5848     // Find lowest tic, over all nodes.
5849     next_tic_send = gametic;
5850     for( nn=0; nn<MAXNETNODES; nn++)
5851     {
5852         // Max of gametic and nettics[].
5853         if( (nnode_state[nn] >= NOS_active)
5854             && (nettics[nn] < next_tic_send) )
5855         {
5856            next_tic_send = nettics[nn];
5857         }
5858     }
5859 
5860     // Don't erase tics not acknowledged
5861     if( (maketic+count) >= (next_tic_send+BACKUPTICS) )
5862         count = (next_tic_send+BACKUPTICS) - maketic - 1;
5863 
5864     while( count-- > 0 )
5865         SV_Maketic();  // create missed tics and increment maketic
5866 
5867     // clear only when acknowledged
5868     for( ; next_tic_clear<next_tic_send; next_tic_clear++)
5869         D_Clear_ticcmd(next_tic_clear);  // clear the maketic the new tic
5870 
5871     SV_Send_Tics();
5872 
5873     // The server is a client too, but does not send cmdtic packets to itself.
5874     cl_need_tic=maketic;
5875 }
5876 
5877 
NetUpdate(void)5878 void NetUpdate(void)
5879 {
5880     static tic_t prev_netupdate_time=0;
5881     tic_t        nowtime;
5882     int          realtics;	// time is actually long [WDJ]
5883 
5884     nowtime  = I_GetTime();
5885     realtics = nowtime - prev_netupdate_time;
5886 
5887     if( realtics <= 0 )
5888     {
5889         if( realtics > -100000 )  // [WDJ] 1/16/2009  validity check
5890             return;     // same tic as previous
5891 
5892         // [WDJ] 1/16/2009 something is wrong, like time has wrapped.
5893         // Program gets stuck waiting for this, so force it out.
5894         realtics = 1;
5895     }
5896     if( realtics > 5 )
5897     {
5898         realtics = ( server )? 1 : 5;
5899     }
5900 
5901     // Executed once per tic, with realtics = 1..5.
5902     prev_netupdate_time = nowtime;
5903 
5904     if( !server )
5905         maketic = cl_need_tic;
5906 
5907     if( ! dedicated )
5908     {
5909         // Local Client
5910         I_OsPolling();       // i_getevent
5911         D_Process_Events ();
5912           // menu responder ???!!!
5913           // Cons responder
5914           // game responder call :
5915           //    HU_responder,St_responder, Am_responder
5916           //    F_responder (final)
5917           //    and G_MapEventsToControls
5918 
5919         Local_Maketic (realtics);  // make local tic
5920 
5921         if( server && !demoplayback )
5922             CL_Send_ClientCmd();     // send server tic
5923     }
5924 
5925     Send_localtextcmd();  // includes server NetXCmd cmds
5926 
5927     Net_Packet_Handler();  // get packet from client or from server
5928 
5929     // Client sends its commands after a receive of the server tic.
5930     // The server sends before because in single player is better.
5931 
5932     if( !server )
5933         CL_Send_ClientCmd();   // send tic cmd
5934     else
5935     {
5936         // By Server
5937         //Hurdler: added for acking the master server
5938         if( cv_internetserver.value )
5939             MS_SendPing_MasterServer( nowtime );
5940 
5941         if(!demoplayback)
5942             SV_Send_Tic_Update( realtics );  // realtics > 0
5943 
5944         if( Filetx_file_cnt )  // Rare to have file download in progress.
5945             Filetx_Ticker();
5946 
5947         if( num_join_waiting_players )
5948             SV_Add_Join_Waiting();
5949     }
5950 
5951     Net_AckTicker();
5952 
5953     if( ! dedicated )
5954     {
5955         M_Ticker ();
5956         CON_Ticker();
5957     }
5958 }
5959