4 static double anim_reducetime(double t, double frameduration, double maxtime)
6 if(t < 0) // clamp to non-negative
8 if(t <= maxtime) // time can be represented normally
10 if(frameduration == 0) // don't like dividing by zero
12 if(maxtime <= 2 * frameduration) // if two frames don't fit, we better not do this
14 t -= frameduration * ceil((t - maxtime) / frameduration);
15 // now maxtime - frameduration < t <= maxtime
19 // see VM_SV_frameduration
20 static double anim_frameduration(model_t *model, int framenum)
22 if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
24 if(model->animscenes[framenum].framerate)
25 return model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
29 void EntityFrame5_FreeDatabase(entityframe5_database_t *d)
31 // all the [maxedicts] memory is allocated at once, so there's only one
34 Mem_Free(d->deltabits);
38 static void EntityFrame5_ExpandEdicts(entityframe5_database_t *d, int newmax)
40 if (d->maxedicts < newmax)
43 int oldmaxedicts = d->maxedicts;
44 int *olddeltabits = d->deltabits;
45 unsigned char *oldpriorities = d->priorities;
46 int *oldupdateframenum = d->updateframenum;
47 entity_state_t *oldstates = d->states;
48 unsigned char *oldvisiblebits = d->visiblebits;
49 d->maxedicts = newmax;
50 data = (unsigned char *)Mem_Alloc(sv_mempool, d->maxedicts * sizeof(int) + d->maxedicts * sizeof(unsigned char) + d->maxedicts * sizeof(int) + d->maxedicts * sizeof(entity_state_t) + (d->maxedicts+7)/8 * sizeof(unsigned char));
51 d->deltabits = (int *)data;data += d->maxedicts * sizeof(int);
52 d->priorities = (unsigned char *)data;data += d->maxedicts * sizeof(unsigned char);
53 d->updateframenum = (int *)data;data += d->maxedicts * sizeof(int);
54 d->states = (entity_state_t *)data;data += d->maxedicts * sizeof(entity_state_t);
55 d->visiblebits = (unsigned char *)data;data += (d->maxedicts+7)/8 * sizeof(unsigned char);
58 memcpy(d->deltabits, olddeltabits, oldmaxedicts * sizeof(int));
59 memcpy(d->priorities, oldpriorities, oldmaxedicts * sizeof(unsigned char));
60 memcpy(d->updateframenum, oldupdateframenum, oldmaxedicts * sizeof(int));
61 memcpy(d->states, oldstates, oldmaxedicts * sizeof(entity_state_t));
62 memcpy(d->visiblebits, oldvisiblebits, (oldmaxedicts+7)/8 * sizeof(unsigned char));
63 // the previous buffers were a single allocation, so just one free
64 Mem_Free(olddeltabits);
69 static int EntityState5_Priority(entityframe5_database_t *d, int stateindex)
72 entity_state_t *s = NULL; // hush compiler warning by initializing this
73 // if it is the player, update urgently
74 if (stateindex == d->viewentnum)
75 return ENTITYFRAME5_PRIORITYLEVELS - 1;
76 // priority increases each frame no matter what happens
77 priority = d->priorities[stateindex] + 1;
78 // players get an extra priority boost
79 if (stateindex <= svs.maxclients)
81 // remove dead entities very quickly because they are just 2 bytes
82 if (d->states[stateindex].active != ACTIVE_NETWORK)
85 return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1);
87 // certain changes are more noticable than others
88 if (d->deltabits[stateindex] & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL | E5_FLAGS | E5_COLORMAP))
90 // find the root entity this one is attached to, and judge relevance by it
91 for (limit = 0;limit < 256;limit++)
93 s = d->states + stateindex;
94 if (s->flags & RENDER_VIEWMODEL)
95 stateindex = d->viewentnum;
96 else if (s->tagentity)
97 stateindex = s->tagentity;
100 if (d->maxedicts < stateindex)
101 EntityFrame5_ExpandEdicts(d, (stateindex+256)&~255);
104 Con_DPrintf("Protocol: Runaway loop recursing tagentity links on entity %i\n", stateindex);
105 // now that we have the parent entity we can make some decisions based on
106 // distance from the player
107 if (VectorDistance(d->states[d->viewentnum].netcenter, s->netcenter) < 1024.0f)
109 return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1);
112 static int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t *n)
114 unsigned int bits = 0;
115 if (n->active == ACTIVE_NETWORK)
117 if (o->active != ACTIVE_NETWORK)
118 bits |= E5_FULLUPDATE;
119 if (!VectorCompare(o->origin, n->origin))
121 if (!VectorCompare(o->angles, n->angles))
123 if (o->modelindex != n->modelindex)
125 if (o->frame != n->frame)
127 if (o->skin != n->skin)
129 if (o->effects != n->effects)
131 if (o->flags != n->flags)
133 if (o->alpha != n->alpha)
135 if (o->scale != n->scale)
137 if (o->colormap != n->colormap)
139 if (o->tagentity != n->tagentity || o->tagindex != n->tagindex)
140 bits |= E5_ATTACHMENT;
141 if (o->light[0] != n->light[0] || o->light[1] != n->light[1] || o->light[2] != n->light[2] || o->light[3] != n->light[3] || o->lightstyle != n->lightstyle || o->lightpflags != n->lightpflags)
143 if (o->glowsize != n->glowsize || o->glowcolor != n->glowcolor)
145 if (o->colormod[0] != n->colormod[0] || o->colormod[1] != n->colormod[1] || o->colormod[2] != n->colormod[2])
147 if (o->glowmod[0] != n->glowmod[0] || o->glowmod[1] != n->glowmod[1] || o->glowmod[2] != n->glowmod[2])
149 if (n->flags & RENDER_COMPLEXANIMATION)
151 if ((o->skeletonobject.model && o->skeletonobject.relativetransforms) != (n->skeletonobject.model && n->skeletonobject.relativetransforms))
153 bits |= E5_COMPLEXANIMATION;
155 else if (o->skeletonobject.model && o->skeletonobject.relativetransforms)
157 if(o->modelindex != n->modelindex)
158 bits |= E5_COMPLEXANIMATION;
159 else if(o->skeletonobject.model->num_bones != n->skeletonobject.model->num_bones)
160 bits |= E5_COMPLEXANIMATION;
161 else if(memcmp(o->skeletonobject.relativetransforms, n->skeletonobject.relativetransforms, o->skeletonobject.model->num_bones * sizeof(*o->skeletonobject.relativetransforms)))
162 bits |= E5_COMPLEXANIMATION;
164 else if (memcmp(o->framegroupblend, n->framegroupblend, sizeof(o->framegroupblend)))
166 bits |= E5_COMPLEXANIMATION;
169 if (o->traileffectnum != n->traileffectnum)
170 bits |= E5_TRAILEFFECTNUM;
173 if (o->active == ACTIVE_NETWORK)
174 bits |= E5_FULLUPDATE;
178 void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg)
180 prvm_prog_t *prog = SVVM_prog;
181 unsigned int bits = 0;
184 if (s->active != ACTIVE_NETWORK)
186 ENTITYSIZEPROFILING_START(msg, s->number, 0);
187 MSG_WriteShort(msg, number | 0x8000);
188 ENTITYSIZEPROFILING_END(msg, s->number, 0);
192 if (PRVM_serveredictfunction((&prog->edicts[s->number]), SendEntity))
196 if ((bits & E5_ORIGIN) && (!(s->flags & RENDER_LOWPRECISION) || s->exteriormodelforclient || s->tagentity || s->viewmodelforclient || (s->number >= 1 && s->number <= svs.maxclients) || s->origin[0] <= -4096.0625 || s->origin[0] >= 4095.9375 || s->origin[1] <= -4096.0625 || s->origin[1] >= 4095.9375 || s->origin[2] <= -4096.0625 || s->origin[2] >= 4095.9375))
197 // maybe also add: ((model = SV_GetModelByIndex(s->modelindex)) != NULL && model->name[0] == '*')
201 // (int)(f * 8 - 0.5) >= -32768
202 // (f * 8 - 0.5) > -32769
205 // (int)(f * 8 + 0.5) <= 32767
206 // (f * 8 + 0.5) < 32768
207 // f * 8 + 0.5) < 4095.9375
208 if ((bits & E5_ANGLES) && !(s->flags & RENDER_LOWPRECISION))
210 if ((bits & E5_MODEL) && s->modelindex >= 256)
212 if ((bits & E5_FRAME) && s->frame >= 256)
214 if (bits & E5_EFFECTS)
216 if (s->effects & 0xFFFF0000)
217 bits |= E5_EFFECTS32;
218 else if (s->effects & 0xFFFFFF00)
219 bits |= E5_EFFECTS16;
225 if (bits >= 16777216)
228 ENTITYSIZEPROFILING_START(msg, s->number, bits);
229 MSG_WriteShort(msg, number);
230 MSG_WriteByte(msg, bits & 0xFF);
231 if (bits & E5_EXTEND1)
232 MSG_WriteByte(msg, (bits >> 8) & 0xFF);
233 if (bits & E5_EXTEND2)
234 MSG_WriteByte(msg, (bits >> 16) & 0xFF);
235 if (bits & E5_EXTEND3)
236 MSG_WriteByte(msg, (bits >> 24) & 0xFF);
238 MSG_WriteByte(msg, s->flags);
239 if (bits & E5_ORIGIN)
241 if (bits & E5_ORIGIN32)
243 MSG_WriteCoord32f(msg, s->origin[0]);
244 MSG_WriteCoord32f(msg, s->origin[1]);
245 MSG_WriteCoord32f(msg, s->origin[2]);
249 MSG_WriteCoord13i(msg, s->origin[0]);
250 MSG_WriteCoord13i(msg, s->origin[1]);
251 MSG_WriteCoord13i(msg, s->origin[2]);
254 if (bits & E5_ANGLES)
256 if (bits & E5_ANGLES16)
258 MSG_WriteAngle16i(msg, s->angles[0]);
259 MSG_WriteAngle16i(msg, s->angles[1]);
260 MSG_WriteAngle16i(msg, s->angles[2]);
264 MSG_WriteAngle8i(msg, s->angles[0]);
265 MSG_WriteAngle8i(msg, s->angles[1]);
266 MSG_WriteAngle8i(msg, s->angles[2]);
271 if (bits & E5_MODEL16)
272 MSG_WriteShort(msg, s->modelindex);
274 MSG_WriteByte(msg, s->modelindex);
278 if (bits & E5_FRAME16)
279 MSG_WriteShort(msg, s->frame);
281 MSG_WriteByte(msg, s->frame);
284 MSG_WriteByte(msg, s->skin);
285 if (bits & E5_EFFECTS)
287 if (bits & E5_EFFECTS32)
288 MSG_WriteLong(msg, s->effects);
289 else if (bits & E5_EFFECTS16)
290 MSG_WriteShort(msg, s->effects);
292 MSG_WriteByte(msg, s->effects);
295 MSG_WriteByte(msg, s->alpha);
297 MSG_WriteByte(msg, s->scale);
298 if (bits & E5_COLORMAP)
299 MSG_WriteByte(msg, s->colormap);
300 if (bits & E5_ATTACHMENT)
302 MSG_WriteShort(msg, s->tagentity);
303 MSG_WriteByte(msg, s->tagindex);
307 MSG_WriteShort(msg, s->light[0]);
308 MSG_WriteShort(msg, s->light[1]);
309 MSG_WriteShort(msg, s->light[2]);
310 MSG_WriteShort(msg, s->light[3]);
311 MSG_WriteByte(msg, s->lightstyle);
312 MSG_WriteByte(msg, s->lightpflags);
316 MSG_WriteByte(msg, s->glowsize);
317 MSG_WriteByte(msg, s->glowcolor);
319 if (bits & E5_COLORMOD)
321 MSG_WriteByte(msg, s->colormod[0]);
322 MSG_WriteByte(msg, s->colormod[1]);
323 MSG_WriteByte(msg, s->colormod[2]);
325 if (bits & E5_GLOWMOD)
327 MSG_WriteByte(msg, s->glowmod[0]);
328 MSG_WriteByte(msg, s->glowmod[1]);
329 MSG_WriteByte(msg, s->glowmod[2]);
331 if (bits & E5_COMPLEXANIMATION)
333 if (s->skeletonobject.model && s->skeletonobject.relativetransforms)
335 int numbones = s->skeletonobject.model->num_bones;
338 MSG_WriteByte(msg, 4);
339 MSG_WriteShort(msg, s->modelindex);
340 MSG_WriteByte(msg, numbones);
341 for (bonenum = 0;bonenum < numbones;bonenum++)
343 Matrix4x4_ToBonePose7s(s->skeletonobject.relativetransforms + bonenum, 64, pose7s);
344 MSG_WriteShort(msg, pose7s[0]);
345 MSG_WriteShort(msg, pose7s[1]);
346 MSG_WriteShort(msg, pose7s[2]);
347 MSG_WriteShort(msg, pose7s[3]);
348 MSG_WriteShort(msg, pose7s[4]);
349 MSG_WriteShort(msg, pose7s[5]);
350 MSG_WriteShort(msg, pose7s[6]);
355 model_t *model = SV_GetModelByIndex(s->modelindex);
356 if (s->framegroupblend[3].lerp > 0)
358 MSG_WriteByte(msg, 3);
359 MSG_WriteShort(msg, s->framegroupblend[0].frame);
360 MSG_WriteShort(msg, s->framegroupblend[1].frame);
361 MSG_WriteShort(msg, s->framegroupblend[2].frame);
362 MSG_WriteShort(msg, s->framegroupblend[3].frame);
363 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
364 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
365 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0));
366 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[3].start, anim_frameduration(model, s->framegroupblend[3].frame), 65.535) * 1000.0));
367 MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
368 MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
369 MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
370 MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f);
372 else if (s->framegroupblend[2].lerp > 0)
374 MSG_WriteByte(msg, 2);
375 MSG_WriteShort(msg, s->framegroupblend[0].frame);
376 MSG_WriteShort(msg, s->framegroupblend[1].frame);
377 MSG_WriteShort(msg, s->framegroupblend[2].frame);
378 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
379 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
380 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0));
381 MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
382 MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
383 MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
385 else if (s->framegroupblend[1].lerp > 0)
387 MSG_WriteByte(msg, 1);
388 MSG_WriteShort(msg, s->framegroupblend[0].frame);
389 MSG_WriteShort(msg, s->framegroupblend[1].frame);
390 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
391 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
392 MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
393 MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
397 MSG_WriteByte(msg, 0);
398 MSG_WriteShort(msg, s->framegroupblend[0].frame);
399 MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
403 if (bits & E5_TRAILEFFECTNUM)
404 MSG_WriteShort(msg, s->traileffectnum);
405 ENTITYSIZEPROFILING_END(msg, s->number, bits);
410 qbool EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t **states, int viewentnum, unsigned int movesequence, qbool need_empty)
412 prvm_prog_t *prog = SVVM_prog;
413 const entity_state_t *n;
414 int i, num, l, framenum, packetlognumber, priority;
416 unsigned char data[128];
417 entityframe5_packetlog_t *packetlog;
419 if (prog->max_edicts > d->maxedicts)
420 EntityFrame5_ExpandEdicts(d, prog->max_edicts);
422 framenum = d->latestframenum + 1;
423 d->viewentnum = viewentnum;
425 // if packet log is full, mark all frames as lost, this will cause
426 // it to send the lost data again
427 for (packetlognumber = 0;packetlognumber < ENTITYFRAME5_MAXPACKETLOGS;packetlognumber++)
428 if (d->packetlog[packetlognumber].packetnumber == 0)
430 if (packetlognumber == ENTITYFRAME5_MAXPACKETLOGS)
432 Con_DPrintf("EntityFrame5_WriteFrame: packetlog overflow for a client, resetting\n");
433 EntityFrame5_LostFrame(d, framenum);
437 // prepare the buffer
438 memset(&buf, 0, sizeof(buf));
440 buf.maxsize = sizeof(data);
442 // detect changes in states
444 for (i = 0;i < numstates;i++)
447 // mark gaps in entity numbering as removed entities
448 for (;num < n->number;num++)
450 // if the entity used to exist, clear it
451 if (CHECKPVSBIT(d->visiblebits, num))
453 CLEARPVSBIT(d->visiblebits, num);
454 d->deltabits[num] = E5_FULLUPDATE;
455 d->priorities[num] = max(d->priorities[num], 8); // removal is cheap
456 d->states[num] = defaultstate;
457 d->states[num].number = num;
460 // update the entity state data
461 if (!CHECKPVSBIT(d->visiblebits, num))
463 // entity just spawned in, don't let it completely hog priority
464 // because of being ancient on the first frame
465 d->updateframenum[num] = framenum;
466 // initial priority is a bit high to make projectiles send on the
467 // first frame, among other things
468 d->priorities[num] = max(d->priorities[num], 4);
470 SETPVSBIT(d->visiblebits, num);
471 d->deltabits[num] |= EntityState5_DeltaBits(d->states + num, n);
472 d->priorities[num] = max(d->priorities[num], 1);
474 d->states[num].number = num;
475 // advance to next entity so the next iteration doesn't immediately remove it
478 // all remaining entities are dead
479 for (;num < d->maxedicts;num++)
481 if (CHECKPVSBIT(d->visiblebits, num))
483 CLEARPVSBIT(d->visiblebits, num);
484 d->deltabits[num] = E5_FULLUPDATE;
485 d->priorities[num] = max(d->priorities[num], 8); // removal is cheap
486 d->states[num] = defaultstate;
487 d->states[num].number = num;
491 // if there isn't at least enough room for an empty svc_entities,
492 // don't bother trying...
493 if (buf.cursize + 11 > buf.maxsize)
496 // build lists of entities by priority level
497 memset(d->prioritychaincounts, 0, sizeof(d->prioritychaincounts));
499 for (num = 0;num < d->maxedicts;num++)
501 if (d->priorities[num])
503 if (d->deltabits[num])
505 if (d->priorities[num] < (ENTITYFRAME5_PRIORITYLEVELS - 1))
506 d->priorities[num] = EntityState5_Priority(d, num);
508 priority = d->priorities[num];
509 if (d->prioritychaincounts[priority] < ENTITYFRAME5_MAXSTATES)
510 d->prioritychains[priority][d->prioritychaincounts[priority]++] = num;
513 d->priorities[num] = 0;
518 // write stat updates
519 if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5)
521 for (i = 0;i < MAX_CL_STATS && msg->cursize + 6 + 11 <= maxsize;i++)
523 if (host_client->statsdeltabits[i>>3] & (1<<(i&7)))
525 host_client->statsdeltabits[i>>3] &= ~(1<<(i&7));
526 // add packetlog entry now that we have something for it
529 packetlog = d->packetlog + packetlognumber;
530 packetlog->packetnumber = framenum;
531 packetlog->numstates = 0;
532 memset(packetlog->statsdeltabits, 0, sizeof(packetlog->statsdeltabits));
534 packetlog->statsdeltabits[i>>3] |= (1<<(i&7));
535 if (host_client->stats[i] >= 0 && host_client->stats[i] < 256)
537 MSG_WriteByte(msg, svc_updatestatubyte);
538 MSG_WriteByte(msg, i);
539 MSG_WriteByte(msg, host_client->stats[i]);
544 MSG_WriteByte(msg, svc_updatestat);
545 MSG_WriteByte(msg, i);
546 MSG_WriteLong(msg, host_client->stats[i]);
553 // only send empty svc_entities frame if needed
554 if(!l && !need_empty)
557 // add packetlog entry now that we have something for it
560 packetlog = d->packetlog + packetlognumber;
561 packetlog->packetnumber = framenum;
562 packetlog->numstates = 0;
563 memset(packetlog->statsdeltabits, 0, sizeof(packetlog->statsdeltabits));
566 // write state updates
567 if (developer_networkentities.integer >= 10)
568 Con_Printf("send: svc_entities %i\n", framenum);
569 d->latestframenum = framenum;
570 MSG_WriteByte(msg, svc_entities);
571 MSG_WriteLong(msg, framenum);
572 if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6)
573 MSG_WriteLong(msg, movesequence);
574 for (priority = ENTITYFRAME5_PRIORITYLEVELS - 1;priority >= 0 && packetlog->numstates < ENTITYFRAME5_MAXSTATES;priority--)
576 for (i = 0;i < d->prioritychaincounts[priority] && packetlog->numstates < ENTITYFRAME5_MAXSTATES;i++)
578 num = d->prioritychains[priority][i];
580 if (d->deltabits[num] & E5_FULLUPDATE)
581 d->deltabits[num] = E5_FULLUPDATE | EntityState5_DeltaBits(&defaultstate, n);
583 EntityState5_WriteUpdate(num, n, d->deltabits[num], &buf);
584 // if the entity won't fit, try the next one
585 if (msg->cursize + buf.cursize + 2 > maxsize)
587 // write entity to the packet
588 SZ_Write(msg, buf.data, buf.cursize);
589 // mark age on entity for prioritization
590 d->updateframenum[num] = framenum;
591 // log entity so deltabits can be restored later if lost
592 packetlog->states[packetlog->numstates].number = num;
593 packetlog->states[packetlog->numstates].bits = d->deltabits[num];
594 packetlog->numstates++;
595 // clear deltabits and priority so it won't be sent again
596 d->deltabits[num] = 0;
597 d->priorities[num] = 0;
600 MSG_WriteShort(msg, 0x8000);
605 entityframe5_database_t *EntityFrame5_AllocDatabase(mempool_t *pool)
608 entityframe5_database_t *d;
609 d = (entityframe5_database_t *)Mem_Alloc(pool, sizeof(*d));
610 d->latestframenum = 0;
611 for (i = 0;i < d->maxedicts;i++)
612 d->states[i] = defaultstate;
616 static int packetlog5cmp(const void *a_, const void *b_)
618 const entityframe5_packetlog_t *a = (const entityframe5_packetlog_t *) a_;
619 const entityframe5_packetlog_t *b = (const entityframe5_packetlog_t *) b_;
620 return a->packetnumber - b->packetnumber;
623 void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum)
626 entityframe5_changestate_t *s;
627 entityframe5_packetlog_t *p;
628 static unsigned char statsdeltabits[(MAX_CL_STATS+7)/8];
629 static int deltabits[MAX_EDICTS];
630 entityframe5_packetlog_t *packetlogs[ENTITYFRAME5_MAXPACKETLOGS];
632 for (i = 0, p = d->packetlog;i < ENTITYFRAME5_MAXPACKETLOGS;i++, p++)
634 qsort(packetlogs, sizeof(*packetlogs), ENTITYFRAME5_MAXPACKETLOGS, packetlog5cmp);
636 memset(deltabits, 0, sizeof(deltabits));
637 memset(statsdeltabits, 0, sizeof(statsdeltabits));
638 for (i = 0; i < ENTITYFRAME5_MAXPACKETLOGS; i++)
642 if (!p->packetnumber)
645 if (p->packetnumber <= framenum)
647 for (j = 0, s = p->states;j < p->numstates;j++, s++)
648 deltabits[s->number] |= s->bits;
650 for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
651 statsdeltabits[l] |= p->statsdeltabits[l];
657 for (j = 0, s = p->states;j < p->numstates;j++, s++)
658 deltabits[s->number] &= ~s->bits;
659 for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
660 statsdeltabits[l] &= ~p->statsdeltabits[l];
664 for(i = 0; i < d->maxedicts; ++i)
666 bits = deltabits[i] & ~d->deltabits[i];
669 d->deltabits[i] |= bits;
670 // if it was a very important update, set priority higher
671 if (bits & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL | E5_COLORMAP))
672 d->priorities[i] = max(d->priorities[i], 4);
674 d->priorities[i] = max(d->priorities[i], 1);
678 for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
679 host_client->statsdeltabits[l] |= statsdeltabits[l];
680 // no need to mask out the already-set bits here, as we do not
681 // do that priorities stuff
684 void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum)
687 // scan for packets made obsolete by this ack and delete them
688 for (i = 0;i < ENTITYFRAME5_MAXPACKETLOGS;i++)
689 if (d->packetlog[i].packetnumber <= framenum)
690 d->packetlog[i].packetnumber = 0;