]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - protocol.c
fix endless loop with gcc 4.8
[xonotic/darkplaces.git] / protocol.c
index 4f0139b502453f07d3407d205059e4ed8d531d3d..db2de2f08ec155ba4bce8a5ed7aa4af8c2a102ab 100644 (file)
@@ -2062,6 +2062,31 @@ static int EntityState5_Priority(entityframe5_database_t *d, int stateindex)
        return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1);
 }
 
+static double anim_reducetime(double t, double frameduration, double maxtime)
+{
+       if(t < 0) // clamp to non-negative
+               return 0;
+       if(t <= maxtime) // time can be represented normally
+               return t;
+       if(frameduration == 0) // don't like dividing by zero
+               return t;
+       if(maxtime <= 2 * frameduration) // if two frames don't fit, we better not do this
+               return t;
+       t -= frameduration * ceil((t - maxtime) / frameduration);
+       // now maxtime - frameduration < t <= maxtime
+       return t;
+}
+
+// see VM_SV_frameduration
+static double anim_frameduration(dp_model_t *model, int framenum)
+{
+       if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
+               return 0;
+       if(model->animscenes[framenum].framerate)
+               return model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
+       return 0;
+}
+
 void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg)
 {
        prvm_prog_t *prog = SVVM_prog;
@@ -2216,65 +2241,70 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi
                        {
                                int numbones = s->skeletonobject.model->num_bones;
                                int bonenum;
-                               short pose6s[6];
+                               short pose7s[7];
                                MSG_WriteByte(msg, 4);
                                MSG_WriteShort(msg, s->modelindex);
                                MSG_WriteByte(msg, numbones);
                                for (bonenum = 0;bonenum < numbones;bonenum++)
                                {
-                                       Matrix4x4_ToBonePose6s(s->skeletonobject.relativetransforms + bonenum, 64, pose6s);
-                                       MSG_WriteShort(msg, pose6s[0]);
-                                       MSG_WriteShort(msg, pose6s[1]);
-                                       MSG_WriteShort(msg, pose6s[2]);
-                                       MSG_WriteShort(msg, pose6s[3]);
-                                       MSG_WriteShort(msg, pose6s[4]);
-                                       MSG_WriteShort(msg, pose6s[5]);
+                                       Matrix4x4_ToBonePose7s(s->skeletonobject.relativetransforms + bonenum, 64, pose7s);
+                                       MSG_WriteShort(msg, pose7s[0]);
+                                       MSG_WriteShort(msg, pose7s[1]);
+                                       MSG_WriteShort(msg, pose7s[2]);
+                                       MSG_WriteShort(msg, pose7s[3]);
+                                       MSG_WriteShort(msg, pose7s[4]);
+                                       MSG_WriteShort(msg, pose7s[5]);
+                                       MSG_WriteShort(msg, pose7s[6]);
                                }
                        }
-                       else if (s->framegroupblend[3].lerp > 0)
-                       {
-                               MSG_WriteByte(msg, 3);
-                               MSG_WriteShort(msg, s->framegroupblend[0].frame);
-                               MSG_WriteShort(msg, s->framegroupblend[1].frame);
-                               MSG_WriteShort(msg, s->framegroupblend[2].frame);
-                               MSG_WriteShort(msg, s->framegroupblend[3].frame);
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0));
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[2].start) * 1000.0));
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[3].start) * 1000.0));
-                               MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
-                               MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
-                               MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
-                               MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f);
-                       }
-                       else if (s->framegroupblend[2].lerp > 0)
-                       {
-                               MSG_WriteByte(msg, 2);
-                               MSG_WriteShort(msg, s->framegroupblend[0].frame);
-                               MSG_WriteShort(msg, s->framegroupblend[1].frame);
-                               MSG_WriteShort(msg, s->framegroupblend[2].frame);
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0));
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[2].start) * 1000.0));
-                               MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
-                               MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
-                               MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
-                       }
-                       else if (s->framegroupblend[1].lerp > 0)
-                       {
-                               MSG_WriteByte(msg, 1);
-                               MSG_WriteShort(msg, s->framegroupblend[0].frame);
-                               MSG_WriteShort(msg, s->framegroupblend[1].frame);
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0));
-                               MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
-                               MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
-                       }
                        else
                        {
-                               MSG_WriteByte(msg, 0);
-                               MSG_WriteShort(msg, s->framegroupblend[0].frame);
-                               MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
+                               dp_model_t *model = SV_GetModelByIndex(s->modelindex);
+                               if (s->framegroupblend[3].lerp > 0)
+                               {
+                                       MSG_WriteByte(msg, 3);
+                                       MSG_WriteShort(msg, s->framegroupblend[0].frame);
+                                       MSG_WriteShort(msg, s->framegroupblend[1].frame);
+                                       MSG_WriteShort(msg, s->framegroupblend[2].frame);
+                                       MSG_WriteShort(msg, s->framegroupblend[3].frame);
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0));
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[3].start, anim_frameduration(model, s->framegroupblend[3].frame), 65.535) * 1000.0));
+                                       MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
+                                       MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
+                                       MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
+                                       MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f);
+                               }
+                               else if (s->framegroupblend[2].lerp > 0)
+                               {
+                                       MSG_WriteByte(msg, 2);
+                                       MSG_WriteShort(msg, s->framegroupblend[0].frame);
+                                       MSG_WriteShort(msg, s->framegroupblend[1].frame);
+                                       MSG_WriteShort(msg, s->framegroupblend[2].frame);
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0));
+                                       MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
+                                       MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
+                                       MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
+                               }
+                               else if (s->framegroupblend[1].lerp > 0)
+                               {
+                                       MSG_WriteByte(msg, 1);
+                                       MSG_WriteShort(msg, s->framegroupblend[0].frame);
+                                       MSG_WriteShort(msg, s->framegroupblend[1].frame);
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
+                                       MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
+                                       MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
+                               }
+                               else
+                               {
+                                       MSG_WriteByte(msg, 0);
+                                       MSG_WriteShort(msg, s->framegroupblend[0].frame);
+                                       MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+                               }
                        }
                }
                if (bits & E5_TRAILEFFECTNUM)
@@ -2287,6 +2317,8 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi
 static void EntityState5_ReadUpdate(entity_state_t *s, int number)
 {
        int bits;
+       int startoffset = cl_message.readcount;
+       int bytes = 0;
        bits = MSG_ReadByte(&cl_message);
        if (bits & E5_EXTEND1)
        {
@@ -2405,7 +2437,7 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                int type;
                int bonenum;
                int numbones;
-               short pose6s[6];
+               short pose7s[7];
                type = MSG_ReadByte(&cl_message);
                switch(type)
                {
@@ -2414,7 +2446,7 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                        s->framegroupblend[1].frame = 0;
                        s->framegroupblend[2].frame = 0;
                        s->framegroupblend[3].frame = 0;
-                       s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
                        s->framegroupblend[1].start = 0;
                        s->framegroupblend[2].start = 0;
                        s->framegroupblend[3].start = 0;
@@ -2428,8 +2460,8 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                        s->framegroupblend[1].frame = MSG_ReadShort(&cl_message);
                        s->framegroupblend[2].frame = 0;
                        s->framegroupblend[3].frame = 0;
-                       s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
-                       s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
                        s->framegroupblend[2].start = 0;
                        s->framegroupblend[3].start = 0;
                        s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
@@ -2442,9 +2474,9 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                        s->framegroupblend[1].frame = MSG_ReadShort(&cl_message);
                        s->framegroupblend[2].frame = MSG_ReadShort(&cl_message);
                        s->framegroupblend[3].frame = 0;
-                       s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
-                       s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
-                       s->framegroupblend[2].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[2].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
                        s->framegroupblend[3].start = 0;
                        s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
                        s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
@@ -2456,10 +2488,10 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                        s->framegroupblend[1].frame = MSG_ReadShort(&cl_message);
                        s->framegroupblend[2].frame = MSG_ReadShort(&cl_message);
                        s->framegroupblend[3].frame = MSG_ReadShort(&cl_message);
-                       s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
-                       s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
-                       s->framegroupblend[2].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
-                       s->framegroupblend[3].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[2].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+                       s->framegroupblend[3].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
                        s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
                        s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
                        s->framegroupblend[2].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
@@ -2483,13 +2515,14 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                        }
                        for (bonenum = 0;bonenum < numbones;bonenum++)
                        {
-                               pose6s[0] = (short)MSG_ReadShort(&cl_message);
-                               pose6s[1] = (short)MSG_ReadShort(&cl_message);
-                               pose6s[2] = (short)MSG_ReadShort(&cl_message);
-                               pose6s[3] = (short)MSG_ReadShort(&cl_message);
-                               pose6s[4] = (short)MSG_ReadShort(&cl_message);
-                               pose6s[5] = (short)MSG_ReadShort(&cl_message);
-                               Matrix4x4_FromBonePose6s(skeleton->relativetransforms + bonenum, 1.0f / 64.0f, pose6s);
+                               pose7s[0] = (short)MSG_ReadShort(&cl_message);
+                               pose7s[1] = (short)MSG_ReadShort(&cl_message);
+                               pose7s[2] = (short)MSG_ReadShort(&cl_message);
+                               pose7s[3] = (short)MSG_ReadShort(&cl_message);
+                               pose7s[4] = (short)MSG_ReadShort(&cl_message);
+                               pose7s[5] = (short)MSG_ReadShort(&cl_message);
+                               pose7s[6] = (short)MSG_ReadShort(&cl_message);
+                               Matrix4x4_FromBonePose7s(skeleton->relativetransforms + bonenum, 1.0f / 64.0f, pose7s);
                        }
                        s->skeletonobject = *skeleton;
                        break;
@@ -2502,9 +2535,10 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                s->traileffectnum = (unsigned short) MSG_ReadShort(&cl_message);
 
 
+       bytes = cl_message.readcount - startoffset;
        if (developer_networkentities.integer >= 2)
        {
-               Con_Printf("ReadFields e%i", number);
+               Con_Printf("ReadFields e%i (%i bytes)", number, bytes);
 
                if (bits & E5_ORIGIN)
                        Con_Printf(" E5_ORIGIN %f %f %f", s->origin[0], s->origin[1], s->origin[2]);
@@ -2557,6 +2591,10 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number)
                        Con_Printf(" E5_COLORMOD %f:%f:%f", s->colormod[0] / 32.0f, s->colormod[1] / 32.0f, s->colormod[2] / 32.0f);
                if (bits & E5_GLOWMOD)
                        Con_Printf(" E5_GLOWMOD %f:%f:%f", s->glowmod[0] / 32.0f, s->glowmod[1] / 32.0f, s->glowmod[2] / 32.0f);
+               if (bits & E5_COMPLEXANIMATION)
+                       Con_Printf(" E5_COMPLEXANIMATION");
+               if (bits & E5_TRAILEFFECTNUM)
+                       Con_Printf(" E5_TRAILEFFECTNUM %i", s->traileffectnum);
                Con_Print("\n");
        }
 }
@@ -2599,7 +2637,25 @@ static int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t
                if (o->glowmod[0] != n->glowmod[0] || o->glowmod[1] != n->glowmod[1] || o->glowmod[2] != n->glowmod[2])
                        bits |= E5_GLOWMOD;
                if (n->flags & RENDER_COMPLEXANIMATION)
-                       bits |= E5_COMPLEXANIMATION;
+               {
+                       if ((o->skeletonobject.model && o->skeletonobject.relativetransforms) != (n->skeletonobject.model && n->skeletonobject.relativetransforms))
+                       {
+                               bits |= E5_COMPLEXANIMATION;
+                       }
+                       else if (o->skeletonobject.model && o->skeletonobject.relativetransforms)
+                       {
+                               if(o->modelindex != n->modelindex)
+                                       bits |= E5_COMPLEXANIMATION;
+                               else if(o->skeletonobject.model->num_bones != n->skeletonobject.model->num_bones)
+                                       bits |= E5_COMPLEXANIMATION;
+                               else if(memcmp(o->skeletonobject.relativetransforms, n->skeletonobject.relativetransforms, o->skeletonobject.model->num_bones * sizeof(*o->skeletonobject.relativetransforms)))
+                                       bits |= E5_COMPLEXANIMATION;
+                       }
+                       else if (memcmp(o->framegroupblend, n->framegroupblend, sizeof(o->framegroupblend)))
+                       {
+                               bits |= E5_COMPLEXANIMATION;
+                       }
+               }
                if (o->traileffectnum != n->traileffectnum)
                        bits |= E5_TRAILEFFECTNUM;
        }
@@ -3209,7 +3265,6 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta)
        newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK;
        newsnap = d->snapshot + newsnapindex;
        memset(newsnap, 0, sizeof(*newsnap));
-       oldsnapindex = -1;
        oldsnap = NULL;
        if (delta)
        {