buffer up to 32 recent frame numbers for clc_ack to prevent entity
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 30 Dec 2009 19:27:03 +0000 (19:27 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 30 Dec 2009 19:27:03 +0000 (19:27 +0000)
resyncs on the server when the client framerate is much lower than the
server framerate, repeat frame numbers of previous input packet
(cl_netrepeatinput cvar, just like clc_move repeats)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9752 d7cf8633-e32d-0410-b094-e92efae38249

cl_input.c
client.h
protocol.c

index f5714fa..f6d90d4 100644 (file)
@@ -1572,6 +1572,15 @@ void QW_MSG_WriteDeltaUsercmd(sizebuf_t *buf, usercmd_t *from, usercmd_t *to)
        MSG_WriteByte(buf, to->msec);
 }
 
+void CL_NewFrameReceived(int num)
+{
+       if (developer_networkentities.integer >= 10)
+               Con_Printf("recv: svc_entities %i\n", num);
+       cl.latestframenums[cl.latestframenumsposition] = num;
+       cl.latestsendnums[cl.latestframenumsposition] = cl.cmd.sequence;
+       cl.latestframenumsposition = (cl.latestframenumsposition + 1) % LATESTFRAMENUMS;
+}
+
 /*
 ==============
 CL_SendMove
@@ -1882,17 +1891,24 @@ void CL_SendMove(void)
 
        if (cls.protocol != PROTOCOL_QUAKEWORLD && buf.cursize)
        {
-               // ack the last few frame numbers
+               // ack entity frame numbers received since the last input was sent
                // (redundent to improve handling of client->server packet loss)
-               // for LATESTFRAMENUMS == 3 case this is 15 bytes
+               // if cl_netrepeatinput is 1 and client framerate matches server
+               // framerate, this is 10 bytes, if client framerate is lower this
+               // will be more...
+               int i, j;
+               int oldsequence = cl.cmd.sequence - bound(1, cl_netrepeatinput.integer + 1, 3);
+               if (oldsequence < 1)
+                       oldsequence = 1;
                for (i = 0;i < LATESTFRAMENUMS;i++)
                {
-                       if (cl.latestframenums[i] > 0)
+                       j = (cl.latestframenumsposition + i) % LATESTFRAMENUMS;
+                       if (cl.latestsendnums[j] >= oldsequence)
                        {
                                if (developer_networkentities.integer >= 10)
-                                       Con_Printf("send clc_ackframe %i\n", cl.latestframenums[i]);
+                                       Con_Printf("send clc_ackframe %i\n", cl.latestframenums[j]);
                                MSG_WriteByte(&buf, clc_ackframe);
-                               MSG_WriteLong(&buf, cl.latestframenums[i]);
+                               MSG_WriteLong(&buf, cl.latestframenums[j]);
                        }
                }
        }
index 525754b..0794530 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1043,8 +1043,10 @@ typedef struct client_state_s
 
        // entity database stuff
        // latest received entity frame numbers
-#define LATESTFRAMENUMS 3
+#define LATESTFRAMENUMS 32
+       int latestframenumsposition;
        int latestframenums[LATESTFRAMENUMS];
+       int latestsendnums[LATESTFRAMENUMS];
        entityframe_database_t *entitydatabase;
        entityframe4_database_t *entitydatabase4;
        entityframeqw_database_t *entitydatabaseqw;
index 31c2e54..85826a7 100644 (file)
@@ -1217,6 +1217,8 @@ void EntityState_ReadFields(entity_state_t *e, unsigned int bits)
        }
 }
 
+extern void CL_NewFrameReceived(int num);
+
 // (client and server) allocates a new empty database
 entityframe_database_t *EntityFrame_AllocDatabase(mempool_t *mempool)
 {
@@ -1423,9 +1425,8 @@ void EntityFrame_CL_ReadFrame(void)
        // read the frame header info
        f->time = cl.mtime[0];
        number = MSG_ReadLong();
-       for (i = 0;i < LATESTFRAMENUMS-1;i++)
-               cl.latestframenums[i] = cl.latestframenums[i+1];
-       cl.latestframenums[LATESTFRAMENUMS-1] = f->framenum = MSG_ReadLong();
+       f->framenum = MSG_ReadLong();
+       CL_NewFrameReceived(f->framenum);
        f->eye[0] = MSG_ReadFloat();
        f->eye[1] = MSG_ReadFloat();
        f->eye[2] = MSG_ReadFloat();
@@ -1690,9 +1691,8 @@ void EntityFrame4_CL_ReadFrame(void)
        // read the number of the frame this refers to
        referenceframenum = MSG_ReadLong();
        // read the number of this frame
-       for (i = 0;i < LATESTFRAMENUMS-1;i++)
-               cl.latestframenums[i] = cl.latestframenums[i+1];
-       cl.latestframenums[LATESTFRAMENUMS-1] = framenum = MSG_ReadLong();
+       framenum = MSG_ReadLong();
+       CL_NewFrameReceived(framenum);
        // read the start number
        enumber = (unsigned short) MSG_ReadShort();
        if (developer_networkentities.integer >= 10)
@@ -2390,15 +2390,12 @@ static int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t
 
 void EntityFrame5_CL_ReadFrame(void)
 {
-       int i, n, enumber;
+       int i, n, enumber, framenum;
        entity_t *ent;
        entity_state_t *s;
        // read the number of this frame to echo back in next input packet
-       for (i = 0;i < LATESTFRAMENUMS-1;i++)
-               cl.latestframenums[i] = cl.latestframenums[i+1];
-       cl.latestframenums[LATESTFRAMENUMS-1] = MSG_ReadLong();
-       if (developer_networkentities.integer >= 10)
-               Con_Printf("recv: svc_entities %i\n", cl.latestframenums[LATESTFRAMENUMS-1]);
+       framenum = MSG_ReadLong();
+       CL_NewFrameReceived(framenum);
        if (cls.protocol != PROTOCOL_QUAKE && cls.protocol != PROTOCOL_QUAKEDP && cls.protocol != PROTOCOL_NEHAHRAMOVIE && cls.protocol != PROTOCOL_DARKPLACES1 && cls.protocol != PROTOCOL_DARKPLACES2 && cls.protocol != PROTOCOL_DARKPLACES3 && cls.protocol != PROTOCOL_DARKPLACES4 && cls.protocol != PROTOCOL_DARKPLACES5 && cls.protocol != PROTOCOL_DARKPLACES6)
                cls.servermovesequence = MSG_ReadLong();
        // read entity numbers until we find a 0x8000