fixed crashes when changing a few settings while playing a demo
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 25 May 2006 03:46:21 +0000 (03:46 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 25 May 2006 03:46:21 +0000 (03:46 +0000)
fixed repeated jumping bug in cl_movement code
fixed crashes that would occur if playing a QW demo (not yet supported)

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

cl_input.c
cl_main.c
cl_parse.c
client.h
netconn.c
protocol.c

index d9a0616..402a9ec 100644 (file)
@@ -520,8 +520,12 @@ void CL_ClientMovement_InputQW(qw_usercmd_t *cmd)
        n = cl.movement_numqueue;
        cl.movement_numqueue = 0;
        for (i = 0;i < n;i++)
+       {
                if (cl.movement_queue[i].sequence > cls.netcon->qw.incoming_sequence)
                        cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+               else if (i == 0)
+                       cl.movement_replay_canjump = !cl.movement_queue[i].jump;
+       }
        // add to input queue if there is room
        if (cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])))
        {
@@ -551,14 +555,22 @@ void CL_ClientMovement_Input(qboolean buttonjump, qboolean buttoncrouch)
        if (cl.servermovesequence)
        {
                for (i = 0;i < n;i++)
+               {
                        if (cl.movement_queue[i].sequence > cl.servermovesequence)
                                cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+                       else if (i == 0)
+                               cl.movement_replay_canjump = !cl.movement_queue[i].jump;
+               }
        }
        else
        {
                for (i = 0;i < n;i++)
+               {
                        if (cl.movement_queue[i].time >= cl.mtime[0] - cl_movement_latency.value / 1000.0 && cl.movement_queue[i].time <= cl.mtime[0])
                                cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+                       else if (i == 0)
+                               cl.movement_replay_canjump = !cl.movement_queue[i].jump;
+               }
        }
        // add to input queue if there is room
        if (cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])) && cl.mtime[0] > cl.mtime[1])
@@ -1019,7 +1031,7 @@ void CL_ClientMovement_Replay(void)
        VectorCopy(cl.entities[cl.playerentity].state_current.origin, s.origin);
        VectorCopy(cl.mvelocity[0], s.velocity);
        s.crouched = true; // will be updated on first move
-       s.canjump = true;
+       s.canjump = cl.movement_replay_canjump;
 
        // set up movement variables
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
index 2c0c4ff..05570d7 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -210,7 +210,7 @@ void CL_SetInfo(const char *key, const char *value, qboolean send, qboolean allo
                return;
        }
        InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), key, value);
-       if (cls.state == ca_connected)
+       if (cls.state == ca_connected && cls.netcon)
        {
                if (cls.protocol == PROTOCOL_QUAKEWORLD)
                {
index 11688ac..c62bfe9 100644 (file)
@@ -1043,8 +1043,11 @@ void CL_ParseServerInfo (void)
                // check memory integrity
                Mem_CheckSentinelsGlobal();
 
-               MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
-               MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, 0));
+               if (cls.netcon)
+               {
+                       MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
+                       MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, 0));
+               }
 
                cls.state = ca_connected;
                cls.signon = 1;
index 02053f2..f9b16e3 100644 (file)
--- a/client.h
+++ b/client.h
@@ -474,6 +474,9 @@ typedef struct client_static_s
 
        // value of "qport" cvar at time of connection
        int qw_qport;
+       // copied from cls.netcon->qw. variables every time they change, or set by demos (which have no cls.netcon)
+       int qw_incoming_sequence;
+       int qw_outgoing_sequence;
 
        // current file download buffer (only saved when file is completed)
        char qw_downloadname[MAX_QPATH];
@@ -677,6 +680,8 @@ typedef struct client_state_s
        client_movementqueue_t movement_queue[64];
        int movesequence;
        int servermovesequence;
+       // whether the replay should allow a jump at the first sequence
+       qboolean movement_replay_canjump;
 
 // pitch drifting vars
        float idealpitch;
index e1e9f17..22f4e74 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -504,6 +504,8 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers
                {
                        *((short *)(sendbuffer + 8)) = LittleShort(cls.qw_qport);
                        packetLen += 2;
+                       // also update cls.qw_outgoing_sequence
+                       cls.qw_outgoing_sequence = conn->qw.outgoing_sequence;
                }
                if (packetLen + (sendreliable ? conn->sendMessageLength : 0) > 1400)
                {
@@ -890,6 +892,8 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len
                        reliableMessagesReceived++;
                }
                conn->qw.incoming_sequence = sequence;
+               if (conn == cls.netcon)
+                       cls.qw_incoming_sequence = conn->qw.incoming_sequence;
                conn->qw.incoming_acknowledged = sequence_ack;
                conn->qw.incoming_reliable_acknowledged = reliable_ack;
                if (reliable_message)
index 3be8a6b..40f79fb 100644 (file)
@@ -2597,7 +2597,13 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta)
                cl.entitydatabaseqw = EntityFrameQW_AllocDatabase(cls.levelmempool);
        d = cl.entitydatabaseqw;
 
-       newsnapindex = cls.netcon->qw.incoming_sequence & QW_UPDATE_MASK;
+       // there is no cls.netcon in demos, so this reading code can't access
+       // cls.netcon-> at all...  so cls.qw_incoming_sequence and
+       // cls.qw_outgoing_sequence are updated every time the corresponding
+       // cls.netcon->qw. variables are updated
+       // read the number of this frame to echo back in next input packet
+       cl.qw_validsequence = cls.qw_incoming_sequence;
+       newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK;
        newsnap = d->snapshot + newsnapindex;
        memset(newsnap, 0, sizeof(*newsnap));
        oldsnapindex = -1;
@@ -2610,7 +2616,7 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta)
                        Con_DPrintf("WARNING: from mismatch\n");
                if (oldsnapindex != -1)
                {
-                       if (cls.netcon->qw.outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1)
+                       if (cls.qw_outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1)
                        {
                                Con_DPrintf("delta update too old\n");
                                newsnap->invalid = invalid = true; // too old
@@ -2622,8 +2628,7 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta)
                        delta = false;
        }
 
-       // read the number of this frame to echo back in next input packet
-       cl.qw_validsequence = cls.netcon->qw.incoming_sequence;
+       // if we can't decode this frame properly, report that to the server
        if (invalid)
                cl.qw_validsequence = 0;