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(<cbp->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