added cl_nettimesyncmode cvar to choose the method of synchronizing cl.time, it defau...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 12 Feb 2007 23:38:01 +0000 (23:38 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 12 Feb 2007 23:38:01 +0000 (23:38 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6836 d7cf8633-e32d-0410-b094-e92efae38249

cl_main.c
cl_parse.c
client.h

index 6ed4985..89da9e6 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -500,14 +500,11 @@ static float CL_LerpPoint(void)
 {
        float f;
 
-       // dropped packet, or start of demo
-       if (cl.mtime[1] < cl.mtime[0] - 0.1)
-               cl.mtime[1] = cl.mtime[0] - 0.1;
-
-       cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]);
+       if (cl_nettimesyncmode.integer == 3)
+               cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]);
 
        // LordHavoc: lerp in listen games as the server is being capped below the client (usually)
-       if (cl.mtime[0] <= cl.mtime[1] || cl_nolerp.integer || cls.timedemo || (cl.islocalgame && !sv_fixedframeratesingleplayer.integer))
+       if (cl.mtime[0] <= cl.mtime[1])
        {
                cl.time = cl.mtime[0];
                return 1;
@@ -769,7 +766,6 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit)
 {
        const matrix4x4_t *matrix;
        matrix4x4_t blendmatrix, tempmatrix, matrix2;
-       //matrix4x4_t dlightmatrix;
        int j, k, l;
        float origin[3], angles[3], delta[3], lerp, d;
        entity_t *t;
@@ -995,7 +991,6 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit)
 // creates light and trails from an entity
 void CL_UpdateNetworkEntityTrail(entity_t *e)
 {
-       //matrix4x4_t dlightmatrix;
        effectnameindex_t trailtype;
        vec3_t origin;
 
index e829ca6..ef9805b 100644 (file)
@@ -166,6 +166,7 @@ cvar_t cl_sound_ric3 = {0, "cl_sound_ric3", "weapons/ric3.wav", "sound to play w
 cvar_t cl_sound_r_exp3 = {0, "cl_sound_r_exp3", "weapons/r_exp3.wav", "sound to play during TE_EXPLOSION and related effects (empty cvar disables sound)"};
 cvar_t cl_serverextension_download = {0, "cl_serverextension_download", "0", "indicates whether the server supports the download command"};
 cvar_t cl_joinbeforedownloadsfinish = {0, "cl_joinbeforedownloadsfinish", "1", "if non-zero the game will begin after the map is loaded before other downloads finish"};
+cvar_t cl_nettimesyncmode = {0, "cl_nettimesyncmode", "2", "selects method of time synchronization in client with regard to server packets, values are: 0 = no sync, 1 = exact sync (reset timing each packet), 2 = loose sync (reset timing only if it is out of bounds), 3 = tight sync and bounding"};
 
 static qboolean QW_CL_CheckOrDownloadFile(const char *filename);
 static void QW_CL_RequestNextDownload(void);
@@ -2495,6 +2496,38 @@ qboolean CL_ExaminePrintString(const char *text)
        return true;
 }
 
+static void CL_NetworkTimeReceived(double newtime)
+{
+       if (cl_nolerp.integer || cls.timedemo || (cl.islocalgame && !sv_fixedframeratesingleplayer.integer))
+               cl.mtime[1] = cl.mtime[0] = newtime;
+       else
+       {
+               cl.mtime[1] = max(cl.mtime[0], newtime - 0.1);
+               cl.mtime[0] = newtime;
+       }
+       if (cl_nettimesyncmode.integer == 3)
+               cl.time = cl.mtime[1];
+       if (cl_nettimesyncmode.integer == 2)
+       {
+               if (cl.time < cl.mtime[1] || cl.time > cl.mtime[0])
+                       cl.time = cl.mtime[1];
+       }
+       else if (cl_nettimesyncmode.integer == 1)
+               cl.time = cl.mtime[1];
+       // this packet probably contains a player entity update, so we will need
+       // to update the prediction
+       cl.movement_needupdate = true;
+       // this may get updated later in parsing by svc_clientdata
+       cl.onground = false;
+       // if true the cl.viewangles are interpolated from cl.mviewangles[]
+       // during this frame
+       // (makes spectating players much smoother and prevents mouse movement from turning)
+       cl.fixangle[1] = cl.fixangle[0];
+       cl.fixangle[0] = false;
+       if (!cls.demoplayback)
+               VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
+}
+
 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf("%3i:%s\n", msg_readcount-1, x);
 
 //[515]: csqc
@@ -2545,17 +2578,7 @@ void CL_ParseServerMessage(void)
 
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
        {
-               cl.mtime[1] = cl.mtime[0];
-               cl.mtime[0] = realtime; // qw has no clock
-               cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]);
-               cl.onground = false; // since there's no clientdata parsing, clear the onground flag here
-               // if true the cl.viewangles are interpolated from cl.mviewangles[]
-               // during this frame
-               // (makes spectating players much smoother and prevents mouse movement from turning)
-               cl.fixangle[1] = cl.fixangle[0];
-               cl.fixangle[0] = false;
-               if (!cls.demoplayback)
-                       VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
+               CL_NetworkTimeReceived(realtime); // qw has no clock
 
                // slightly kill qw player entities each frame
                for (i = 1;i < cl.maxclients;i++)
@@ -2966,17 +2989,7 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case svc_time:
-                               cl.mtime[1] = cl.mtime[0];
-                               cl.mtime[0] = MSG_ReadFloat ();
-                               cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]);
-                               cl.movement_needupdate = true;
-                               // if true the cl.viewangles are interpolated from cl.mviewangles[]
-                               // during this frame
-                               // (makes spectating players much smoother and prevents mouse movement from turning)
-                               cl.fixangle[1] = cl.fixangle[0];
-                               cl.fixangle[0] = false;
-                               if (!cls.demoplayback)
-                                       VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
+                               CL_NetworkTimeReceived(MSG_ReadFloat());
                                break;
 
                        case svc_clientdata:
@@ -3348,6 +3361,8 @@ void CL_Parse_Init(void)
        // server extension cvars set by commands issued from the server during connect
        Cvar_RegisterVariable(&cl_serverextension_download);
 
+       Cvar_RegisterVariable(&cl_nettimesyncmode);
+
        Cmd_AddCommand("nextul", QW_CL_NextUpload, "sends next fragment of current upload buffer (screenshot for example)");
        Cmd_AddCommand("stopul", QW_CL_StopUpload, "aborts current upload (screenshot for example)");
        Cmd_AddCommand("skins", QW_CL_Skins_f, "downloads missing qw skins from server");
index 711ad4e..83dcffa 100644 (file)
--- a/client.h
+++ b/client.h
@@ -750,6 +750,8 @@ typedef struct client_state_s
        // clients view of time, time should be between mtime[0] and mtime[1] to
        // generate a lerp point for other data, oldtime is the previous frame's
        // value of time, frametime is the difference between time and oldtime
+       // note: cl.time may be beyond cl.mtime[0] if packet loss is occuring, it
+       // is only forcefully limited when a packet is received
        double time, oldtime;
        // how long it has been since the previous client frame in real time
        // (not game time, for that use cl.time - cl.oldtime)
@@ -957,6 +959,7 @@ extern cvar_t cl_autofire;
 
 extern cvar_t cl_shownet;
 extern cvar_t cl_nolerp;
+extern cvar_t cl_nettimesyncmode;
 
 extern cvar_t cl_pitchdriftspeed;
 extern cvar_t lookspring;