1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
4 // Copyright(C) 1993-1996 Id Software, Inc.
5 // Copyright(C) 2005 Simon Howard
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 // DOOM Network game communication and protocol,
24 // all OS independend parts.
26 //-----------------------------------------------------------------------------
30 #include "doomfeatures.h"
44 #include "net_client.h"
47 #include "net_query.h"
48 #include "net_server.h"
56 // gametic is the tic about to (or currently being) run
57 // maketic is the tick that hasn't had control made for it yet
58 // nettics[] has the maketics for all players
60 // a gametic cannot be run until nettics[] > gametic for all players
63 ticcmd_t netcmds
[MAXPLAYERS
][BACKUPTICS
];
64 int nettics
[MAXPLAYERS
];
68 // Used for original sync code.
73 // Reduce the bandwidth needed by sampling game input less and transmitting
74 // less. If ticdup is 2, sample half normal, 3 = one third normal, etc.
78 // Send this many extra (backup) tics in each packet.
82 // Amount to offset the timer for game sync.
86 // Use new client syncronisation code
88 boolean net_cl_new_sync
= true;
90 // Connected but not participating in the game (observer)
92 boolean drone
= false;
94 // 35 fps clock adjusted by offsetms milliseconds
96 static int GetAdjustedTime(void)
100 time_ms
= I_GetTimeMS();
104 // Use the adjustments from net_client.c only if we are
105 // using the new sync mode.
107 time_ms
+= (offsetms
/ FRACUNIT
);
110 return (time_ms
* TICRATE
) / 1000;
115 // Builds ticcmds for console player,
116 // sends out a packet
120 void NetUpdate (void)
127 // If we are running with singletics (timing a demo), this
128 // is all done separately.
133 #ifdef FEATURE_MULTIPLAYER
135 // Run network subsystems
143 nowtime
= GetAdjustedTime() / ticdup
;
144 newtics
= nowtime
- lasttime
;
148 if (skiptics
<= newtics
)
159 // build new ticcmds for console player
160 gameticdiv
= gametic
/ticdup
;
162 for (i
=0 ; i
<newtics
; i
++)
169 // Always run the menu
175 // In drone mode, do not generate any ticcmds.
182 // If playing single player, do not allow tics to buffer
185 if ((!netgame
|| demoplayback
) && maketic
- gameticdiv
> 2)
188 // Never go more than ~200ms ahead
190 if (maketic
- gameticdiv
> 8)
195 if (maketic
- gameticdiv
>= 5)
199 //printf ("mk:%i ",maketic);
202 #ifdef FEATURE_MULTIPLAYER
204 if (netgame
&& !demoplayback
)
206 NET_CL_SendTiccmd(&cmd
, maketic
);
210 netcmds
[consoleplayer
][maketic
% BACKUPTICS
] = cmd
;
213 nettics
[consoleplayer
] = maketic
;
220 // Called after the screen is set but before the game starts running.
223 void D_StartGameLoop(void)
225 lasttime
= GetAdjustedTime() / ticdup
;
231 // Works out player numbers among the net participants
233 extern int viewangleoffset
;
235 void D_CheckNetGame (void)
240 // default values for single player
249 for (i
=0; i
<MAXPLAYERS
; i
++)
251 playeringame
[i
] = false;
255 playeringame
[0] = true;
257 #ifdef FEATURE_MULTIPLAYER
260 net_addr_t
*addr
= NULL
;
265 // Start a multiplayer server, listening for connections.
268 if (M_CheckParm("-server") > 0)
271 NET_SV_AddModule(&net_loop_server_module
);
272 NET_SV_AddModule(&net_sdl_module
);
274 net_loop_client_module
.InitClient();
275 addr
= net_loop_client_module
.ResolveAddress(NULL
);
282 // Automatically search the local LAN for a multiplayer
283 // server and join it.
286 i
= M_CheckParm("-autojoin");
290 addr
= NET_FindLANServer();
294 I_Error("No server found on local LAN");
302 // Connect to a multiplayer server running on the given
306 i
= M_CheckParm("-connect");
310 net_sdl_module
.InitClient();
311 addr
= net_sdl_module
.ResolveAddress(myargv
[i
+1]);
315 I_Error("Unable to resolve '%s'\n", myargv
[i
+1]);
322 if (M_CheckParm("-drone") > 0)
330 // Run as the left screen in three screen mode.
333 if (M_CheckParm("-left") > 0)
335 viewangleoffset
= ANG90
;
342 // Run as the right screen in three screen mode.
345 if (M_CheckParm("-right") > 0)
347 viewangleoffset
= ANG270
;
351 if (!NET_CL_Connect(addr
))
353 I_Error("D_CheckNetGame: Failed to connect to %s\n",
354 NET_AddrToString(addr
));
357 printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr
));
367 for (i
=0; i
<MAXPLAYERS
; ++i
)
373 DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
374 startskill
, deathmatch
, startmap
, startepisode
);
376 DEH_printf("player %i of %i (%i nodes)\n",
377 consoleplayer
+1, num_players
, num_players
);
379 // Show players here; the server might have specified a time limit
383 DEH_printf("Levels will end after %d minute", timelimit
);
393 // Called before quitting to leave a net game
394 // without hanging the other players
396 void D_QuitNetGame (void)
401 #ifdef FEATURE_MULTIPLAYER
410 // Returns true if there are currently any players in the game.
412 static boolean
PlayersInGame(void)
416 for (i
=0; i
<MAXPLAYERS
; ++i
)
427 static int GetLowTic(void)
432 #ifdef FEATURE_MULTIPLAYER
433 if (net_client_connected
)
437 for (i
=0; i
<MAXPLAYERS
; ++i
)
441 if (nettics
[i
] < lowtic
)
464 extern boolean advancedemo
;
466 void TryRunTics (void)
471 static int oldentertics
;
477 entertic
= I_GetTime() / ticdup
;
478 realtics
= entertic
- oldentertics
;
479 oldentertics
= entertic
;
481 // get available tics
484 lowtic
= GetLowTic();
486 availabletics
= lowtic
- gametic
/ticdup
;
488 // decide how many tics to run
492 counts
= availabletics
;
496 // decide how many tics to run
497 if (realtics
< availabletics
-1)
499 else if (realtics
< availabletics
)
502 counts
= availabletics
;
513 // ideally maketic should be 1 - 3 tics above lowtic
514 // if we are consistantly slower, speed up time
516 for (i
=0 ; i
<MAXPLAYERS
; i
++)
527 // If there are no players, we can never advance anyway
532 if (consoleplayer
== keyplayer
)
534 // the key player does not adapt
538 if (maketic
<= nettics
[keyplayer
])
544 frameskip
[frameon
& 3] = (oldnettics
> nettics
[keyplayer
]);
545 oldnettics
= maketic
;
547 if (frameskip
[0] && frameskip
[1] && frameskip
[2] && frameskip
[3])
559 // wait for new tics if needed
561 while (!PlayersInGame() || lowtic
< gametic
/ticdup
+ counts
)
565 lowtic
= GetLowTic();
567 if (lowtic
< gametic
/ticdup
)
568 I_Error ("TryRunTics: lowtic < gametic");
570 // Don't stay in this loop forever. The menu is still running,
571 // so return to update the screen
573 if (I_GetTime() / ticdup
- entertic
> 0)
581 // run the count * ticdup dics
584 for (i
=0 ; i
<ticdup
; i
++)
586 // check that there are players in the game. if not, we cannot
589 if (!PlayersInGame())
594 if (gametic
/ticdup
> lowtic
)
595 I_Error ("gametic>lowtic");
602 // modify command for duplicated tics
609 buf
= (gametic
/ticdup
)%BACKUPTICS
;
610 for (j
=0 ; j
<MAXPLAYERS
; j
++)
612 cmd
= &netcmds
[j
][buf
];
614 if (cmd
->buttons
& BT_SPECIAL
)
619 NetUpdate (); // check for new console commands