]> git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_ents5.c
README: add some build notes
[xonotic/darkplaces.git] / sv_ents5.c
1 #include "quakedef.h"
2 #include "protocol.h"
3
4 static double anim_reducetime(double t, double frameduration, double maxtime)
5 {
6         if(t < 0) // clamp to non-negative
7                 return 0;
8         if(t <= maxtime) // time can be represented normally
9                 return t;
10         if(frameduration == 0) // don't like dividing by zero
11                 return t;
12         if(maxtime <= 2 * frameduration) // if two frames don't fit, we better not do this
13                 return t;
14         t -= frameduration * ceil((t - maxtime) / frameduration);
15         // now maxtime - frameduration < t <= maxtime
16         return t;
17 }
18
19 // see VM_SV_frameduration
20 static double anim_frameduration(model_t *model, int framenum)
21 {
22         if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
23                 return 0;
24         if(model->animscenes[framenum].framerate)
25                 return model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
26         return 0;
27 }
28
29 void EntityFrame5_FreeDatabase(entityframe5_database_t *d)
30 {
31         // all the [maxedicts] memory is allocated at once, so there's only one
32         // thing to free
33         if (d->maxedicts)
34                 Mem_Free(d->deltabits);
35         Mem_Free(d);
36 }
37
38 static void EntityFrame5_ExpandEdicts(entityframe5_database_t *d, int newmax)
39 {
40         if (d->maxedicts < newmax)
41         {
42                 unsigned char *data;
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);
56                 if (oldmaxedicts)
57                 {
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);
65                 }
66         }
67 }
68
69 static int EntityState5_Priority(entityframe5_database_t *d, int stateindex)
70 {
71         int limit, priority;
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)
80                 priority++;
81         // remove dead entities very quickly because they are just 2 bytes
82         if (d->states[stateindex].active != ACTIVE_NETWORK)
83         {
84                 priority++;
85                 return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1);
86         }
87         // certain changes are more noticable than others
88         if (d->deltabits[stateindex] & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL | E5_FLAGS | E5_COLORMAP))
89                 priority++;
90         // find the root entity this one is attached to, and judge relevance by it
91         for (limit = 0;limit < 256;limit++)
92         {
93                 s = d->states + stateindex;
94                 if (s->flags & RENDER_VIEWMODEL)
95                         stateindex = d->viewentnum;
96                 else if (s->tagentity)
97                         stateindex = s->tagentity;
98                 else
99                         break;
100                 if (d->maxedicts < stateindex)
101                         EntityFrame5_ExpandEdicts(d, (stateindex+256)&~255);
102         }
103         if (limit >= 256)
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)
108                 priority++;
109         return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1);
110 }
111
112 static int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t *n)
113 {
114         unsigned int bits = 0;
115         if (n->active == ACTIVE_NETWORK)
116         {
117                 if (o->active != ACTIVE_NETWORK)
118                         bits |= E5_FULLUPDATE;
119                 if (!VectorCompare(o->origin, n->origin))
120                         bits |= E5_ORIGIN;
121                 if (!VectorCompare(o->angles, n->angles))
122                         bits |= E5_ANGLES;
123                 if (o->modelindex != n->modelindex)
124                         bits |= E5_MODEL;
125                 if (o->frame != n->frame)
126                         bits |= E5_FRAME;
127                 if (o->skin != n->skin)
128                         bits |= E5_SKIN;
129                 if (o->effects != n->effects)
130                         bits |= E5_EFFECTS;
131                 if (o->flags != n->flags)
132                         bits |= E5_FLAGS;
133                 if (o->alpha != n->alpha)
134                         bits |= E5_ALPHA;
135                 if (o->scale != n->scale)
136                         bits |= E5_SCALE;
137                 if (o->colormap != n->colormap)
138                         bits |= E5_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)
142                         bits |= E5_LIGHT;
143                 if (o->glowsize != n->glowsize || o->glowcolor != n->glowcolor)
144                         bits |= E5_GLOW;
145                 if (o->colormod[0] != n->colormod[0] || o->colormod[1] != n->colormod[1] || o->colormod[2] != n->colormod[2])
146                         bits |= E5_COLORMOD;
147                 if (o->glowmod[0] != n->glowmod[0] || o->glowmod[1] != n->glowmod[1] || o->glowmod[2] != n->glowmod[2])
148                         bits |= E5_GLOWMOD;
149                 if (n->flags & RENDER_COMPLEXANIMATION)
150                 {
151                         if ((o->skeletonobject.model && o->skeletonobject.relativetransforms) != (n->skeletonobject.model && n->skeletonobject.relativetransforms))
152                         {
153                                 bits |= E5_COMPLEXANIMATION;
154                         }
155                         else if (o->skeletonobject.model && o->skeletonobject.relativetransforms)
156                         {
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;
163                         }
164                         else if (memcmp(o->framegroupblend, n->framegroupblend, sizeof(o->framegroupblend)))
165                         {
166                                 bits |= E5_COMPLEXANIMATION;
167                         }
168                 }
169                 if (o->traileffectnum != n->traileffectnum)
170                         bits |= E5_TRAILEFFECTNUM;
171         }
172         else
173                 if (o->active == ACTIVE_NETWORK)
174                         bits |= E5_FULLUPDATE;
175         return bits;
176 }
177
178 void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg)
179 {
180         prvm_prog_t *prog = SVVM_prog;
181         unsigned int bits = 0;
182         //model_t *model;
183
184         if (s->active != ACTIVE_NETWORK)
185         {
186                 ENTITYSIZEPROFILING_START(msg, s->number, 0);
187                 MSG_WriteShort(msg, number | 0x8000);
188                 ENTITYSIZEPROFILING_END(msg, s->number, 0);
189         }
190         else
191         {
192                 if (PRVM_serveredictfunction((&prog->edicts[s->number]), SendEntity))
193                         return;
194
195                 bits = changedbits;
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] == '*')
198                         bits |= E5_ORIGIN32;
199                         // possible values:
200                         //   negative origin:
201                         //     (int)(f * 8 - 0.5) >= -32768
202                         //          (f * 8 - 0.5) >  -32769
203                         //           f            >  -4096.0625
204                         //   positive origin:
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))
209                         bits |= E5_ANGLES16;
210                 if ((bits & E5_MODEL) && s->modelindex >= 256)
211                         bits |= E5_MODEL16;
212                 if ((bits & E5_FRAME) && s->frame >= 256)
213                         bits |= E5_FRAME16;
214                 if (bits & E5_EFFECTS)
215                 {
216                         if (s->effects & 0xFFFF0000)
217                                 bits |= E5_EFFECTS32;
218                         else if (s->effects & 0xFFFFFF00)
219                                 bits |= E5_EFFECTS16;
220                 }
221                 if (bits >= 256)
222                         bits |= E5_EXTEND1;
223                 if (bits >= 65536)
224                         bits |= E5_EXTEND2;
225                 if (bits >= 16777216)
226                         bits |= E5_EXTEND3;
227                 {
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);
237                         if (bits & E5_FLAGS)
238                                 MSG_WriteByte(msg, s->flags);
239                         if (bits & E5_ORIGIN)
240                         {
241                                 if (bits & E5_ORIGIN32)
242                                 {
243                                         MSG_WriteCoord32f(msg, s->origin[0]);
244                                         MSG_WriteCoord32f(msg, s->origin[1]);
245                                         MSG_WriteCoord32f(msg, s->origin[2]);
246                                 }
247                                 else
248                                 {
249                                         MSG_WriteCoord13i(msg, s->origin[0]);
250                                         MSG_WriteCoord13i(msg, s->origin[1]);
251                                         MSG_WriteCoord13i(msg, s->origin[2]);
252                                 }
253                         }
254                         if (bits & E5_ANGLES)
255                         {
256                                 if (bits & E5_ANGLES16)
257                                 {
258                                         MSG_WriteAngle16i(msg, s->angles[0]);
259                                         MSG_WriteAngle16i(msg, s->angles[1]);
260                                         MSG_WriteAngle16i(msg, s->angles[2]);
261                                 }
262                                 else
263                                 {
264                                         MSG_WriteAngle8i(msg, s->angles[0]);
265                                         MSG_WriteAngle8i(msg, s->angles[1]);
266                                         MSG_WriteAngle8i(msg, s->angles[2]);
267                                 }
268                         }
269                         if (bits & E5_MODEL)
270                         {
271                                 if (bits & E5_MODEL16)
272                                         MSG_WriteShort(msg, s->modelindex);
273                                 else
274                                         MSG_WriteByte(msg, s->modelindex);
275                         }
276                         if (bits & E5_FRAME)
277                         {
278                                 if (bits & E5_FRAME16)
279                                         MSG_WriteShort(msg, s->frame);
280                                 else
281                                         MSG_WriteByte(msg, s->frame);
282                         }
283                         if (bits & E5_SKIN)
284                                 MSG_WriteByte(msg, s->skin);
285                         if (bits & E5_EFFECTS)
286                         {
287                                 if (bits & E5_EFFECTS32)
288                                         MSG_WriteLong(msg, s->effects);
289                                 else if (bits & E5_EFFECTS16)
290                                         MSG_WriteShort(msg, s->effects);
291                                 else
292                                         MSG_WriteByte(msg, s->effects);
293                         }
294                         if (bits & E5_ALPHA)
295                                 MSG_WriteByte(msg, s->alpha);
296                         if (bits & E5_SCALE)
297                                 MSG_WriteByte(msg, s->scale);
298                         if (bits & E5_COLORMAP)
299                                 MSG_WriteByte(msg, s->colormap);
300                         if (bits & E5_ATTACHMENT)
301                         {
302                                 MSG_WriteShort(msg, s->tagentity);
303                                 MSG_WriteByte(msg, s->tagindex);
304                         }
305                         if (bits & E5_LIGHT)
306                         {
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);
313                         }
314                         if (bits & E5_GLOW)
315                         {
316                                 MSG_WriteByte(msg, s->glowsize);
317                                 MSG_WriteByte(msg, s->glowcolor);
318                         }
319                         if (bits & E5_COLORMOD)
320                         {
321                                 MSG_WriteByte(msg, s->colormod[0]);
322                                 MSG_WriteByte(msg, s->colormod[1]);
323                                 MSG_WriteByte(msg, s->colormod[2]);
324                         }
325                         if (bits & E5_GLOWMOD)
326                         {
327                                 MSG_WriteByte(msg, s->glowmod[0]);
328                                 MSG_WriteByte(msg, s->glowmod[1]);
329                                 MSG_WriteByte(msg, s->glowmod[2]);
330                         }
331                         if (bits & E5_COMPLEXANIMATION)
332                         {
333                                 if (s->skeletonobject.model && s->skeletonobject.relativetransforms)
334                                 {
335                                         int numbones = s->skeletonobject.model->num_bones;
336                                         int bonenum;
337                                         short pose7s[7];
338                                         MSG_WriteByte(msg, 4);
339                                         MSG_WriteShort(msg, s->modelindex);
340                                         MSG_WriteByte(msg, numbones);
341                                         for (bonenum = 0;bonenum < numbones;bonenum++)
342                                         {
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]);
351                                         }
352                                 }
353                                 else
354                                 {
355                                         model_t *model = SV_GetModelByIndex(s->modelindex);
356                                         if (s->framegroupblend[3].lerp > 0)
357                                         {
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);
371                                         }
372                                         else if (s->framegroupblend[2].lerp > 0)
373                                         {
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);
384                                         }
385                                         else if (s->framegroupblend[1].lerp > 0)
386                                         {
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);
394                                         }
395                                         else
396                                         {
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));
400                                         }
401                                 }
402                         }
403                         if (bits & E5_TRAILEFFECTNUM)
404                                 MSG_WriteShort(msg, s->traileffectnum);
405                         ENTITYSIZEPROFILING_END(msg, s->number, bits);
406                 }
407         }
408 }
409
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)
411 {
412         prvm_prog_t *prog = SVVM_prog;
413         const entity_state_t *n;
414         int i, num, l, framenum, packetlognumber, priority;
415         sizebuf_t buf;
416         unsigned char data[128];
417         entityframe5_packetlog_t *packetlog;
418
419         if (prog->max_edicts > d->maxedicts)
420                 EntityFrame5_ExpandEdicts(d, prog->max_edicts);
421
422         framenum = d->latestframenum + 1;
423         d->viewentnum = viewentnum;
424
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)
429                         break;
430         if (packetlognumber == ENTITYFRAME5_MAXPACKETLOGS)
431         {
432                 Con_DPrintf("EntityFrame5_WriteFrame: packetlog overflow for a client, resetting\n");
433                 EntityFrame5_LostFrame(d, framenum);
434                 packetlognumber = 0;
435         }
436
437         // prepare the buffer
438         memset(&buf, 0, sizeof(buf));
439         buf.data = data;
440         buf.maxsize = sizeof(data);
441
442         // detect changes in states
443         num = 1;
444         for (i = 0;i < numstates;i++)
445         {
446                 n = states[i];
447                 // mark gaps in entity numbering as removed entities
448                 for (;num < n->number;num++)
449                 {
450                         // if the entity used to exist, clear it
451                         if (CHECKPVSBIT(d->visiblebits, num))
452                         {
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;
458                         }
459                 }
460                 // update the entity state data
461                 if (!CHECKPVSBIT(d->visiblebits, num))
462                 {
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);
469                 }
470                 SETPVSBIT(d->visiblebits, num);
471                 d->deltabits[num] |= EntityState5_DeltaBits(d->states + num, n);
472                 d->priorities[num] = max(d->priorities[num], 1);
473                 d->states[num] = *n;
474                 d->states[num].number = num;
475                 // advance to next entity so the next iteration doesn't immediately remove it
476                 num++;
477         }
478         // all remaining entities are dead
479         for (;num < d->maxedicts;num++)
480         {
481                 if (CHECKPVSBIT(d->visiblebits, num))
482                 {
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;
488                 }
489         }
490
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)
494                 return false;
495
496         // build lists of entities by priority level
497         memset(d->prioritychaincounts, 0, sizeof(d->prioritychaincounts));
498         l = 0;
499         for (num = 0;num < d->maxedicts;num++)
500         {
501                 if (d->priorities[num])
502                 {
503                         if (d->deltabits[num])
504                         {
505                                 if (d->priorities[num] < (ENTITYFRAME5_PRIORITYLEVELS - 1))
506                                         d->priorities[num] = EntityState5_Priority(d, num);
507                                 l = num;
508                                 priority = d->priorities[num];
509                                 if (d->prioritychaincounts[priority] < ENTITYFRAME5_MAXSTATES)
510                                         d->prioritychains[priority][d->prioritychaincounts[priority]++] = num;
511                         }
512                         else
513                                 d->priorities[num] = 0;
514                 }
515         }
516
517         packetlog = NULL;
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)
520         {
521                 for (i = 0;i < MAX_CL_STATS && msg->cursize + 6 + 11 <= maxsize;i++)
522                 {
523                         if (host_client->statsdeltabits[i>>3] & (1<<(i&7)))
524                         {
525                                 host_client->statsdeltabits[i>>3] &= ~(1<<(i&7));
526                                 // add packetlog entry now that we have something for it
527                                 if (!packetlog)
528                                 {
529                                         packetlog = d->packetlog + packetlognumber;
530                                         packetlog->packetnumber = framenum;
531                                         packetlog->numstates = 0;
532                                         memset(packetlog->statsdeltabits, 0, sizeof(packetlog->statsdeltabits));
533                                 }
534                                 packetlog->statsdeltabits[i>>3] |= (1<<(i&7));
535                                 if (host_client->stats[i] >= 0 && host_client->stats[i] < 256)
536                                 {
537                                         MSG_WriteByte(msg, svc_updatestatubyte);
538                                         MSG_WriteByte(msg, i);
539                                         MSG_WriteByte(msg, host_client->stats[i]);
540                                         l = 1;
541                                 }
542                                 else
543                                 {
544                                         MSG_WriteByte(msg, svc_updatestat);
545                                         MSG_WriteByte(msg, i);
546                                         MSG_WriteLong(msg, host_client->stats[i]);
547                                         l = 1;
548                                 }
549                         }
550                 }
551         }
552
553         // only send empty svc_entities frame if needed
554         if(!l && !need_empty)
555                 return false;
556
557         // add packetlog entry now that we have something for it
558         if (!packetlog)
559         {
560                 packetlog = d->packetlog + packetlognumber;
561                 packetlog->packetnumber = framenum;
562                 packetlog->numstates = 0;
563                 memset(packetlog->statsdeltabits, 0, sizeof(packetlog->statsdeltabits));
564         }
565
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--)
575         {
576                 for (i = 0;i < d->prioritychaincounts[priority] && packetlog->numstates < ENTITYFRAME5_MAXSTATES;i++)
577                 {
578                         num = d->prioritychains[priority][i];
579                         n = d->states + num;
580                         if (d->deltabits[num] & E5_FULLUPDATE)
581                                 d->deltabits[num] = E5_FULLUPDATE | EntityState5_DeltaBits(&defaultstate, n);
582                         buf.cursize = 0;
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)
586                                 continue;
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;
598                 }
599         }
600         MSG_WriteShort(msg, 0x8000);
601
602         return true;
603 }
604
605 entityframe5_database_t *EntityFrame5_AllocDatabase(mempool_t *pool)
606 {
607         int i;
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;
613         return d;
614 }
615
616 static int packetlog5cmp(const void *a_, const void *b_)
617 {
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;
621 }
622
623 void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum)
624 {
625         int i, j, l, bits;
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];
631
632         for (i = 0, p = d->packetlog;i < ENTITYFRAME5_MAXPACKETLOGS;i++, p++)
633                 packetlogs[i] = p;
634         qsort(packetlogs, sizeof(*packetlogs), ENTITYFRAME5_MAXPACKETLOGS, packetlog5cmp);
635
636         memset(deltabits, 0, sizeof(deltabits));
637         memset(statsdeltabits, 0, sizeof(statsdeltabits));
638         for (i = 0; i < ENTITYFRAME5_MAXPACKETLOGS; i++)
639         {
640                 p = packetlogs[i];
641
642                 if (!p->packetnumber)
643                         continue;
644
645                 if (p->packetnumber <= framenum)
646                 {
647                         for (j = 0, s = p->states;j < p->numstates;j++, s++)
648                                 deltabits[s->number] |= s->bits;
649
650                         for (l = 0;l < (MAX_CL_STATS+7)/8;l++)
651                                 statsdeltabits[l] |= p->statsdeltabits[l];
652
653                         p->packetnumber = 0;
654                 }
655                 else
656                 {
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];
661                 }
662         }
663
664         for(i = 0; i < d->maxedicts; ++i)
665         {
666                 bits = deltabits[i] & ~d->deltabits[i];
667                 if(bits)
668                 {
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);
673                         else
674                                 d->priorities[i] = max(d->priorities[i], 1);
675                 }
676         }
677
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
682 }
683
684 void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum)
685 {
686         int i;
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;
691 }