- }
- // 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, org[0]);
- if (bits & E_ORIGIN2)
- MSG_WriteShort(msg, org[1]);
- if (bits & E_ORIGIN3)
- MSG_WriteShort(msg, org[2]);
- }
- else
- {
- if (bits & E_ORIGIN1)
- MSG_WriteFloat(msg, org[0]);
- if (bits & E_ORIGIN2)
- MSG_WriteFloat(msg, org[1]);
- if (bits & E_ORIGIN3)
- MSG_WriteFloat(msg, org[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);
-}
-
-// (client) reads a frame from network stream
-static entity_frame_t framedata; // FIXME?
-void EntityFrame_Read(entity_database_t *d)
-{
- int number, removed, bits;
- entity_frame_t *f = &framedata, *delta = &deltaframe;
- entity_state_t *e, baseline, *old, *oldend;
-
- ClearStateToDefault(&baseline);
-
- EntityFrame_Clear(f, NULL);
-
- // read the frame header info
- f->time = cl.mtime[0];
- number = MSG_ReadLong();
- f->framenum = MSG_ReadLong();
- f->eye[0] = MSG_ReadFloat();
- f->eye[1] = MSG_ReadFloat();
- f->eye[2] = MSG_ReadFloat();
- EntityFrame_AckFrame(d, number);
- EntityFrame_FetchFrame(d, number, delta);
- old = delta->entitydata;
- oldend = old + delta->numentities;
- // read entities until we hit the magic 0xFFFF end tag
- while ((number = (unsigned short) MSG_ReadShort()) != 0xFFFF)
- {
- if (msg_badread)
- Host_Error("EntityFrame_Read: read error\n");
- removed = number & 0x8000;
- number &= 0x7FFF;
- if (number >= MAX_EDICTS)
- Host_Error("EntityFrame_Read: number (%i) >= MAX_EDICTS (%i)\n", number, MAX_EDICTS);
-
- // seek to entity, while copying any skipped entities (assume unchanged)
- while (old < oldend && old->number < number)
- {
- if (f->numentities >= MAX_ENTITY_DATABASE)
- Host_Error("EntityFrame_Read: entity list too big\n");
- memcpy(f->entitydata + f->numentities, old, sizeof(entity_state_t));
- f->entitydata[f->numentities].time = cl.mtime[0];
- old++;
- f->numentities++;
- }
- if (removed)
- {
- if (old < oldend && old->number == number)
- old++;
- else
- Con_Printf("EntityFrame_Read: REMOVE on unused entity %i\n", number);
- }
- else
- {
- if (f->numentities >= MAX_ENTITY_DATABASE)
- Host_Error("EntityFrame_Read: entity list too big\n");
-
- // reserve this slot
- e = f->entitydata + f->numentities++;
-
- if (old < oldend && old->number == number)
- {
- // delta from old entity
- memcpy(e, old++, sizeof(*e));
- }
- else
- {
- // delta from baseline
- memcpy(e, &baseline, sizeof(*e));
- }
-
- e->active = true;
- e->time = cl.mtime[0];
- e->number = number;
-
- bits = MSG_ReadByte();
- if (bits & E_EXTEND1)
- {
- bits |= MSG_ReadByte() << 8;
- if (bits & E_EXTEND2)