+ int i, onum, bits, number;
+ entity_frame_t deltaframe, *o = &deltaframe;
+ entity_state_t *ent, *delta, baseline;
+
+ EntityFrame_AddFrame(d, f);
+
+ ClearStateToDefault(&baseline);
+ EntityFrame_FetchFrame(d, d->ackframe > 0 ? d->ackframe : -1, o);
+ MSG_WriteByte (msg, svc_entities);
+ MSG_WriteLong (msg, o->framenum);
+ MSG_WriteLong (msg, f->framenum);
+ MSG_WriteFloat (msg, f->eye[0]);
+ MSG_WriteFloat (msg, f->eye[1]);
+ MSG_WriteFloat (msg, f->eye[2]);
+
+ onum = 0;
+ for (i = 0;i < f->numentities;i++)
+ {
+ ent = f->entitydata + i;
+ number = ent->number;
+ for (;onum < o->numentities && o->entitydata[onum].number < number;onum++)
+ {
+ // write remove message
+ MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
+ }
+ if (onum < o->numentities && (o->entitydata[onum].number == number))
+ {
+ // delta from previous frame
+ delta = o->entitydata + onum;
+ // advance to next entity in delta frame
+ onum++;
+ }
+ else
+ {
+ // delta from baseline
+ delta = &baseline;
+ }
+ bits = 0;
+ if (ent->flags & RENDER_LOWPRECISION)
+ {
+ if ((int) ent->origin[0] != (int) delta->origin[0])
+ bits |= E_ORIGIN1;
+ if ((int) ent->origin[1] != (int) delta->origin[1])
+ bits |= E_ORIGIN2;
+ if ((int) ent->origin[2] != (int) delta->origin[2])
+ bits |= E_ORIGIN3;
+ }
+ else
+ {
+ if (fabs(ent->origin[0] - delta->origin[0]) > 0.01f)
+ bits |= E_ORIGIN1;
+ if (fabs(ent->origin[1] - delta->origin[1]) > 0.01f)
+ bits |= E_ORIGIN2;
+ if (fabs(ent->origin[2] - delta->origin[2]) > 0.01f)
+ bits |= E_ORIGIN3;
+ }
+ if ((qbyte) (ent->angles[0] * (256.0f / 360.0f)) != (qbyte) (delta->angles[0] * (256.0f / 360.0f)))
+ bits |= E_ANGLE1;
+ if ((qbyte) (ent->angles[1] * (256.0f / 360.0f)) != (qbyte) (delta->angles[1] * (256.0f / 360.0f)))
+ bits |= E_ANGLE2;
+ if ((qbyte) (ent->angles[2] * (256.0f / 360.0f)) != (qbyte) (delta->angles[2] * (256.0f / 360.0f)))
+ bits |= E_ANGLE3;
+ if ((ent->modelindex ^ delta->modelindex) & 0x00FF)
+ bits |= E_MODEL1;
+ if ((ent->modelindex ^ delta->modelindex) & 0xFF00)
+ bits |= E_MODEL2;
+ if ((ent->frame ^ delta->frame) & 0x00FF)
+ bits |= E_FRAME1;
+ if ((ent->frame ^ delta->frame) & 0xFF00)
+ bits |= E_FRAME2;
+ if ((ent->effects ^ delta->effects) & 0x00FF)
+ bits |= E_EFFECTS1;
+ if ((ent->effects ^ delta->effects) & 0xFF00)
+ bits |= E_EFFECTS2;
+ if (ent->colormap != delta->colormap)
+ bits |= E_COLORMAP;
+ if (ent->skin != delta->skin)
+ bits |= E_SKIN;
+ if (ent->alpha != delta->alpha)
+ bits |= E_ALPHA;
+ if (ent->scale != delta->scale)
+ bits |= E_SCALE;
+ if (ent->glowsize != delta->glowsize)
+ bits |= E_GLOWSIZE;
+ if (ent->glowcolor != delta->glowcolor)
+ bits |= E_GLOWCOLOR;
+ if (ent->flags != delta->flags)
+ bits |= E_FLAGS;
+
+ if (bits) // don't send anything if it hasn't changed
+ {
+ if (bits & 0xFF000000)
+ bits |= E_EXTEND3;
+ if (bits & 0x00FF0000)
+ bits |= E_EXTEND2;
+ if (bits & 0x0000FF00)
+ bits |= E_EXTEND1;
+
+ MSG_WriteShort(msg, number);
+ MSG_WriteByte(msg, bits & 0xFF);
+ if (bits & E_EXTEND1)
+ {
+ MSG_WriteByte(msg, (bits >> 8) & 0xFF);
+ if (bits & E_EXTEND2)
+ {
+ MSG_WriteByte(msg, (bits >> 16) & 0xFF);
+ if (bits & E_EXTEND3)
+ MSG_WriteByte(msg, (bits >> 24) & 0xFF);
+ }
+ }
+ // LordHavoc: have to write flags first, as they can modify protocol
+ if (bits & E_FLAGS)
+ MSG_WriteByte(msg, ent->flags);
+ if (ent->flags & RENDER_LOWPRECISION)
+ {
+ if (bits & E_ORIGIN1)
+ MSG_WriteShort(msg, ent->origin[0]);
+ if (bits & E_ORIGIN2)
+ MSG_WriteShort(msg, ent->origin[1]);
+ if (bits & E_ORIGIN3)
+ MSG_WriteShort(msg, ent->origin[2]);
+ }
+ else
+ {
+ if (bits & E_ORIGIN1)
+ MSG_WriteFloat(msg, ent->origin[0]);
+ if (bits & E_ORIGIN2)
+ MSG_WriteFloat(msg, ent->origin[1]);
+ if (bits & E_ORIGIN3)
+ MSG_WriteFloat(msg, ent->origin[2]);
+ }
+ if (bits & E_ANGLE1)
+ MSG_WriteAngle(msg, ent->angles[0]);
+ if (bits & E_ANGLE2)
+ MSG_WriteAngle(msg, ent->angles[1]);
+ if (bits & E_ANGLE3)
+ MSG_WriteAngle(msg, ent->angles[2]);
+ if (bits & E_MODEL1)
+ MSG_WriteByte(msg, ent->modelindex & 0xFF);
+ if (bits & E_MODEL2)
+ MSG_WriteByte(msg, (ent->modelindex >> 8) & 0xFF);
+ if (bits & E_FRAME1)
+ MSG_WriteByte(msg, ent->frame & 0xFF);
+ if (bits & E_FRAME2)
+ MSG_WriteByte(msg, (ent->frame >> 8) & 0xFF);
+ if (bits & E_EFFECTS1)
+ MSG_WriteByte(msg, ent->effects & 0xFF);
+ if (bits & E_EFFECTS2)
+ MSG_WriteByte(msg, (ent->effects >> 8) & 0xFF);
+ if (bits & E_COLORMAP)
+ MSG_WriteByte(msg, ent->colormap);
+ if (bits & E_SKIN)
+ MSG_WriteByte(msg, ent->skin);
+ if (bits & E_ALPHA)
+ MSG_WriteByte(msg, ent->alpha);
+ if (bits & E_SCALE)
+ MSG_WriteByte(msg, ent->scale);
+ if (bits & E_GLOWSIZE)
+ MSG_WriteByte(msg, ent->glowsize);
+ if (bits & E_GLOWCOLOR)
+ MSG_WriteByte(msg, ent->glowcolor);
+ }
+ }
+ for (;onum < o->numentities;onum++)
+ {
+ // write remove message
+ MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
+ }
+ MSG_WriteShort(msg, 0xFFFF);