ref: 4dac08c8694f9b347b2b5c0ca12a0d26b1ae6589
parent: 63712ec1880bf0df7df6c215b01da9bafb9b6976
author: Simon Howard <fraggle@gmail.com>
date: Sat Sep 25 21:21:02 EDT 2010
Restructure player quit code to take place on the first tic after the player quit, to avoid possible desyncs. Further refactoring to split game-specific code from generic code. Subversion-branch: /branches/raven-branch Subversion-revision: 2141
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -457,9 +457,12 @@
// process one or more tics
if (singletics)
{
+ static ticcmd_t cmds[MAXPLAYERS];
+
I_StartTic ();
D_ProcessEvents ();
- G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
+ netcmds = cmds;
+ G_BuildTiccmd(&cmds[consoleplayer]);
if (advancedemo)
D_DoAdvanceDemo ();
M_Ticker ();
--- a/src/doom/d_net.c
+++ b/src/doom/d_net.c
@@ -49,19 +49,27 @@
#include "net_sdl.h"
#include "net_loop.h"
+// The complete set of data for a particular tic.
+typedef struct
+{
+ ticcmd_t cmds[MAXPLAYERS];
+ boolean ingame[MAXPLAYERS];
+} ticcmd_set_t;
+
//
// NETWORKING
//
// gametic is the tic about to (or currently being) run
-// maketic is the tick that hasn't had control made for it yet
-// nettics[] has the maketics for all players
+// maketic is the tic that hasn't had control made for it yet
+// recvtic is the latest tic received from the server.
//
-// a gametic cannot be run until nettics[] > gametic for all players
+// a gametic cannot be run until ticcmds are received for it
+// from all players.
//
-ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
-int nettics[MAXPLAYERS];
+ticcmd_set_t ticdata[BACKUPTICS];
+ticcmd_t *netcmds;
int maketic;
int recvtic;
@@ -208,10 +216,10 @@
}
#endif
- netcmds[consoleplayer][maketic % BACKUPTICS] = cmd;
+ ticdata[maketic % BACKUPTICS].cmds[consoleplayer] = cmd;
+ ticdata[maketic % BACKUPTICS].ingame[consoleplayer] = true;
++maketic;
- nettics[consoleplayer] = maketic;
}
}
@@ -245,8 +253,6 @@
static void D_Disconnected(void)
{
- int i;
-
// In drone mode, the game cannot continue once disconnected.
if (drone)
@@ -257,14 +263,6 @@
// disconnected from server
printf("Disconnected from server.\n");
-
- for (i=0; i<MAXPLAYERS; ++i)
- {
- if (i != consoleplayer && playeringame[i])
- {
- D_PlayerQuitGame(&players[i]);
- }
- }
}
//
@@ -284,23 +282,17 @@
return;
}
- for (i=0; i<MAXPLAYERS; ++i)
+ for (i = 0; i < MAXPLAYERS; ++i)
{
if (!drone && i == consoleplayer)
{
- // This is us.
+ // This is us. Don't overwrite it.
}
- else if (players_mask[i])
+ else
{
- netcmds[i][recvtic % BACKUPTICS] = ticcmds[i];
- nettics[i] = recvtic;
+ ticdata[recvtic % BACKUPTICS].cmds[i] = ticcmds[i];
+ ticdata[recvtic % BACKUPTICS].ingame[i] = players_mask[i];
}
- else if (playeringame[i])
- {
- // Player quit the game.
-
- D_PlayerQuitGame(&players[i]);
- }
}
++recvtic;
@@ -345,9 +337,10 @@
for (i=0; i<MAXPLAYERS; i++)
{
playeringame[i] = false;
- nettics[i] = 0;
}
+ recvtic = 0;
+
playeringame[0] = true;
#ifdef FEATURE_MULTIPLAYER
@@ -503,63 +496,173 @@
}
-// Returns true if there are currently any players in the game.
+static int GetLowTic(void)
+{
+ int lowtic;
-static boolean PlayersInGame(void)
+ lowtic = maketic;
+
+#ifdef FEATURE_MULTIPLAYER
+ if (net_client_connected)
+ {
+ if (drone || recvtic < lowtic)
+ {
+ lowtic = recvtic;
+ }
+ }
+#endif
+
+ return lowtic;
+}
+
+int frametics[4];
+int frameon;
+int frameskip[4];
+int oldnettics;
+
+static void OldNetSync(void)
{
- int i;
+ unsigned int i;
+ unsigned int keyplayer = -1;
- for (i=0; i<MAXPLAYERS; ++i)
+ frameon++;
+
+ // ideally maketic should be 1 - 3 tics above lowtic
+ // if we are consistantly slower, speed up time
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
{
+ // TODO: playeringame should not be used here.
+
if (playeringame[i])
{
- return true;
+ keyplayer = i;
+ break;
}
}
- return false;
+ if (keyplayer < 0)
+ {
+ // If there are no players, we can never advance anyway
+
+ return;
+ }
+
+ if (consoleplayer == keyplayer)
+ {
+ // the key player does not adapt
+ }
+ else
+ {
+ if (maketic <= recvtic)
+ {
+ lasttime--;
+ // printf ("-");
+ }
+
+ frameskip[frameon & 3] = oldnettics > recvtic;
+ oldnettics = maketic;
+
+ if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
+ {
+ skiptics = 1;
+ // printf ("+");
+ }
+ }
}
-static int GetLowTic(void)
+// Returns true if there are players in the game:
+
+static boolean PlayersInGame(void)
{
- int lowtic;
+ boolean result = false;
+ unsigned int i;
-#ifdef FEATURE_MULTIPLAYER
+ // If we are connected to a server, check if there are any players
+ // in the game.
+
if (net_client_connected)
{
- int i;
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ result = result || playeringame[i];
+ }
+ }
- lowtic = INT_MAX;
-
- for (i=0; i<MAXPLAYERS; ++i)
+ // Whether single or multi-player, unless we are running as a drone,
+ // we are in the game.
+
+ if (!drone)
+ {
+ result = true;
+ }
+
+ return result;
+}
+
+// When using ticdup, certain values must be cleared out when running
+// the duplicate ticcmds.
+
+static void TicdupSquash(ticcmd_set_t *set)
+{
+ ticcmd_t *cmd;
+ unsigned int i;
+
+ for (i = 0; i < MAXPLAYERS ; ++i)
+ {
+ cmd = &set->cmds[i];
+ cmd->chatchar = 0;
+ if (cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+ }
+}
+
+static void D_RunTic(ticcmd_set_t *set)
+{
+ extern boolean advancedemo;
+ unsigned int i;
+
+ // Check for player quits.
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (playeringame[i] && !set->ingame[i])
{
- if (playeringame[i])
- {
- if (nettics[i] < lowtic)
- lowtic = nettics[i];
- }
+ D_PlayerQuitGame(&players[i]);
}
}
- else
-#endif
+
+ netcmds = set->cmds;
+
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (advancedemo)
+ D_DoAdvanceDemo ();
+
+ G_Ticker ();
+}
+
+// When running in single player mode, clear all the ingame[] array
+// except the consoleplayer.
+
+static void SinglePlayerClear(ticcmd_set_t *set)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAXPLAYERS; ++i)
{
- lowtic = maketic;
+ if (i != consoleplayer)
+ {
+ set->ingame[i] = false;
+ }
}
-
- return lowtic;
}
//
// TryRunTics
//
-int oldnettics;
-int frametics[4];
-int frameon;
-int frameskip[4];
-int oldnettics;
-extern boolean advancedemo;
-
void TryRunTics (void)
{
int i;
@@ -601,52 +704,9 @@
if (counts < 1)
counts = 1;
- frameon++;
-
- if (!demoplayback)
+ if (net_client_connected)
{
- int keyplayer = -1;
-
- // ideally maketic should be 1 - 3 tics above lowtic
- // if we are consistantly slower, speed up time
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- keyplayer = i;
- break;
- }
- }
-
- if (keyplayer < 0)
- {
- // If there are no players, we can never advance anyway
-
- return;
- }
-
- if (consoleplayer == keyplayer)
- {
- // the key player does not adapt
- }
- else
- {
- if (maketic <= nettics[keyplayer])
- {
- lasttime--;
- // printf ("-");
- }
-
- frameskip[frameon & 3] = (oldnettics > nettics[keyplayer]);
- oldnettics = maketic;
-
- if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
- {
- skiptics = 1;
- // printf ("+");
- }
- }
+ OldNetSync();
}
}
@@ -678,41 +738,33 @@
// run the count * ticdup dics
while (counts--)
{
+ ticcmd_set_t *set;
+
+ if (!PlayersInGame())
+ {
+ return;
+ }
+
+ set = &ticdata[(gametic / ticdup) % BACKUPTICS];
+
+ if (!net_client_connected)
+ {
+ SinglePlayerClear(set);
+ }
+
for (i=0 ; i<ticdup ; i++)
{
- // check that there are players in the game. if not, we cannot
- // run a tic.
-
- if (!PlayersInGame())
- {
- return;
- }
-
- if (gametic/ticdup > lowtic)
- I_Error ("gametic>lowtic");
- if (advancedemo)
- D_DoAdvanceDemo ();
+ if (gametic/ticdup > lowtic)
+ I_Error ("gametic>lowtic");
- G_Ticker ();
+ D_RunTic(set);
gametic++;
// modify command for duplicated tics
- if (i != ticdup-1)
- {
- ticcmd_t *cmd;
- int buf;
- int j;
-
- buf = (gametic/ticdup)%BACKUPTICS;
- for (j=0 ; j<MAXPLAYERS ; j++)
- {
- cmd = &netcmds[j][buf];
- cmd->chatchar = 0;
- if (cmd->buttons & BT_SPECIAL)
- cmd->buttons = 0;
- }
- }
+
+ TicdupSquash(set);
}
+
NetUpdate (); // check for new console commands
}
}
--- a/src/doom/doomstat.h
+++ b/src/doom/doomstat.h
@@ -289,7 +289,7 @@
extern int maketic;
extern int nettics[MAXPLAYERS];
-extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
+extern ticcmd_t *netcmds;
extern int ticdup;
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -986,9 +986,9 @@
if (playeringame[i])
{
cmd = &players[i].cmd;
-
- memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
-
+
+ memcpy(cmd, &netcmds[i], sizeof(ticcmd_t));
+
if (demoplayback)
G_ReadDemoTiccmd (cmd);
if (demorecording)