shithub: choc

Download patch

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)