]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - protocol.c
print E5_COMPLEXANIMATION and E5_TRAILEFFECTNUM in
[xonotic/darkplaces.git] / protocol.c
index 4f0139b502453f07d3407d205059e4ed8d531d3d..740434cf9a2853095c9529b583882c5bf2365138 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;
@@ -2231,50 +2256,54 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi
                                        MSG_WriteShort(msg, pose6s[5]);
                                }
                        }
-                       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 +2316,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)
        {
@@ -2414,7 +2445,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 +2459,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 +2473,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 +2487,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);
@@ -2502,9 +2533,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 +2589,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 +2635,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;
        }