4 extern cvar_t sv_cullentities_trace_prediction_time;
6 int EntityState_DeltaBits(const entity_state_t *o, const entity_state_t *n)
9 // if o is not active, delta from default
10 if (o->active != ACTIVE_NETWORK)
13 if (fabs(n->origin[0] - o->origin[0]) > (1.0f / 256.0f))
15 if (fabs(n->origin[1] - o->origin[1]) > (1.0f / 256.0f))
17 if (fabs(n->origin[2] - o->origin[2]) > (1.0f / 256.0f))
19 if ((unsigned char) (n->angles[0] * (256.0f / 360.0f)) != (unsigned char) (o->angles[0] * (256.0f / 360.0f)))
21 if ((unsigned char) (n->angles[1] * (256.0f / 360.0f)) != (unsigned char) (o->angles[1] * (256.0f / 360.0f)))
23 if ((unsigned char) (n->angles[2] * (256.0f / 360.0f)) != (unsigned char) (o->angles[2] * (256.0f / 360.0f)))
25 if ((n->modelindex ^ o->modelindex) & 0x00FF)
27 if ((n->modelindex ^ o->modelindex) & 0xFF00)
29 if ((n->frame ^ o->frame) & 0x00FF)
31 if ((n->frame ^ o->frame) & 0xFF00)
33 if ((n->effects ^ o->effects) & 0x00FF)
35 if ((n->effects ^ o->effects) & 0xFF00)
37 if (n->colormap != o->colormap)
39 if (n->skin != o->skin)
41 if (n->alpha != o->alpha)
43 if (n->scale != o->scale)
45 if (n->glowsize != o->glowsize)
47 if (n->glowcolor != o->glowcolor)
49 if (n->flags != o->flags)
51 if (n->tagindex != o->tagindex || n->tagentity != o->tagentity)
52 bits |= E_TAGATTACHMENT;
53 if (n->light[0] != o->light[0] || n->light[1] != o->light[1] || n->light[2] != o->light[2] || n->light[3] != o->light[3])
55 if (n->lightstyle != o->lightstyle)
57 if (n->lightpflags != o->lightpflags)
58 bits |= E_LIGHTPFLAGS;
62 if (bits & 0xFF000000)
64 if (bits & 0x00FF0000)
66 if (bits & 0x0000FF00)
72 void EntityState_WriteExtendBits(sizebuf_t *msg, unsigned int bits)
74 MSG_WriteByte(msg, bits & 0xFF);
75 if (bits & 0x00000080)
77 MSG_WriteByte(msg, (bits >> 8) & 0xFF);
78 if (bits & 0x00008000)
80 MSG_WriteByte(msg, (bits >> 16) & 0xFF);
81 if (bits & 0x00800000)
82 MSG_WriteByte(msg, (bits >> 24) & 0xFF);
87 void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned int bits)
89 if (sv.protocol == PROTOCOL_DARKPLACES2)
92 MSG_WriteCoord16i(msg, ent->origin[0]);
94 MSG_WriteCoord16i(msg, ent->origin[1]);
96 MSG_WriteCoord16i(msg, ent->origin[2]);
100 // LadyHavoc: have to write flags first, as they can modify protocol
102 MSG_WriteByte(msg, ent->flags);
103 if (ent->flags & RENDER_LOWPRECISION)
105 if (bits & E_ORIGIN1)
106 MSG_WriteCoord16i(msg, ent->origin[0]);
107 if (bits & E_ORIGIN2)
108 MSG_WriteCoord16i(msg, ent->origin[1]);
109 if (bits & E_ORIGIN3)
110 MSG_WriteCoord16i(msg, ent->origin[2]);
114 if (bits & E_ORIGIN1)
115 MSG_WriteCoord32f(msg, ent->origin[0]);
116 if (bits & E_ORIGIN2)
117 MSG_WriteCoord32f(msg, ent->origin[1]);
118 if (bits & E_ORIGIN3)
119 MSG_WriteCoord32f(msg, ent->origin[2]);
122 if ((sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4) && (ent->flags & RENDER_LOWPRECISION))
125 MSG_WriteAngle8i(msg, ent->angles[0]);
127 MSG_WriteAngle8i(msg, ent->angles[1]);
129 MSG_WriteAngle8i(msg, ent->angles[2]);
134 MSG_WriteAngle16i(msg, ent->angles[0]);
136 MSG_WriteAngle16i(msg, ent->angles[1]);
138 MSG_WriteAngle16i(msg, ent->angles[2]);
141 MSG_WriteByte(msg, ent->modelindex & 0xFF);
143 MSG_WriteByte(msg, (ent->modelindex >> 8) & 0xFF);
145 MSG_WriteByte(msg, ent->frame & 0xFF);
147 MSG_WriteByte(msg, (ent->frame >> 8) & 0xFF);
148 if (bits & E_EFFECTS1)
149 MSG_WriteByte(msg, ent->effects & 0xFF);
150 if (bits & E_EFFECTS2)
151 MSG_WriteByte(msg, (ent->effects >> 8) & 0xFF);
152 if (bits & E_COLORMAP)
153 MSG_WriteByte(msg, ent->colormap);
155 MSG_WriteByte(msg, ent->skin);
157 MSG_WriteByte(msg, ent->alpha);
159 MSG_WriteByte(msg, ent->scale);
160 if (bits & E_GLOWSIZE)
161 MSG_WriteByte(msg, ent->glowsize);
162 if (bits & E_GLOWCOLOR)
163 MSG_WriteByte(msg, ent->glowcolor);
164 if (sv.protocol == PROTOCOL_DARKPLACES2)
166 MSG_WriteByte(msg, ent->flags);
167 if (bits & E_TAGATTACHMENT)
169 MSG_WriteShort(msg, ent->tagentity);
170 MSG_WriteByte(msg, ent->tagindex);
174 MSG_WriteShort(msg, ent->light[0]);
175 MSG_WriteShort(msg, ent->light[1]);
176 MSG_WriteShort(msg, ent->light[2]);
177 MSG_WriteShort(msg, ent->light[3]);
179 if (bits & E_LIGHTSTYLE)
180 MSG_WriteByte(msg, ent->lightstyle);
181 if (bits & E_LIGHTPFLAGS)
182 MSG_WriteByte(msg, ent->lightpflags);
185 void EntityState_WriteUpdate(const entity_state_t *ent, sizebuf_t *msg, const entity_state_t *delta)
187 prvm_prog_t *prog = SVVM_prog;
189 if (ent->active == ACTIVE_NETWORK)
191 // entity is active, check for changes from the delta
192 if ((bits = EntityState_DeltaBits(delta, ent)))
194 // write the update number, bits, and fields
195 ENTITYSIZEPROFILING_START(msg, ent->number, bits);
196 MSG_WriteShort(msg, ent->number);
197 EntityState_WriteExtendBits(msg, bits);
198 EntityState_WriteFields(ent, msg, bits);
199 ENTITYSIZEPROFILING_END(msg, ent->number, bits);
204 // entity is inactive, check if the delta was active
205 if (delta->active == ACTIVE_NETWORK)
207 // write the remove number
208 ENTITYSIZEPROFILING_START(msg, ent->number, 0);
209 MSG_WriteShort(msg, ent->number | 0x8000);
210 ENTITYSIZEPROFILING_END(msg, ent->number, 0);
215 // (server) adds a entity_frame to the database, for future reference
216 void EntityFrame_AddFrame_Server(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t **entitydata)
219 entity_frameinfo_t *info;
221 VectorCopy(eye, d->eye);
223 // figure out how many entity slots are used already
226 n = d->frames[d->numframes - 1].endentity - d->frames[0].firstentity;
227 if (n + numentities > MAX_ENTITY_DATABASE || d->numframes >= MAX_ENTITY_HISTORY)
229 // ran out of room, dump database
230 EntityFrame_ClearDatabase(d);
234 info = &d->frames[d->numframes];
235 info->framenum = framenum;
237 // make sure we check the newly added frame as well, but we haven't incremented numframes yet
238 for (n = 0;n <= d->numframes;n++)
240 if (e >= d->frames[n].framenum)
243 Con_Print("EntityFrame_AddFrame: tried to add out of sequence frame to database\n");
245 Con_Print("EntityFrame_AddFrame: out of sequence frames in database\n");
248 e = d->frames[n].framenum;
250 // if database still has frames after that...
252 info->firstentity = d->frames[d->numframes - 1].endentity;
254 info->firstentity = 0;
255 info->endentity = info->firstentity + numentities;
258 n = info->firstentity % MAX_ENTITY_DATABASE;
259 e = MAX_ENTITY_DATABASE - n;
262 memcpy(d->entitydata + n, entitydata, sizeof(entity_state_t) * e);
264 memcpy(d->entitydata, entitydata + e, sizeof(entity_state_t) * (numentities - e));
267 // (server) writes a frame to network stream
268 qbool EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t **states, int viewentnum)
270 prvm_prog_t *prog = SVVM_prog;
272 entity_frame_t *o = &d->deltaframe;
273 const entity_state_t *ent, *delta;
279 for (i = 0;i < numstates;i++)
282 if (ent->number == viewentnum)
284 VectorSet(eye, ent->origin[0], ent->origin[1], ent->origin[2] + 22);
289 EntityFrame_AddFrame_Server(d, eye, d->latestframenum, numstates, states);
291 EntityFrame_FetchFrame(d, d->ackframenum, o);
293 MSG_WriteByte (msg, svc_entities);
294 MSG_WriteLong (msg, o->framenum);
295 MSG_WriteLong (msg, d->latestframenum);
296 MSG_WriteFloat (msg, eye[0]);
297 MSG_WriteFloat (msg, eye[1]);
298 MSG_WriteFloat (msg, eye[2]);
301 for (i = 0;i < numstates;i++)
304 number = ent->number;
306 if (PRVM_serveredictfunction((&prog->edicts[number]), SendEntity))
308 for (;onum < o->numentities && o->entitydata[onum].number < number;onum++)
310 // write remove message
311 MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
313 if (onum < o->numentities && (o->entitydata[onum].number == number))
315 // delta from previous frame
316 delta = o->entitydata + onum;
317 // advance to next entity in delta frame
322 // delta from defaults
323 delta = &defaultstate;
325 EntityState_WriteUpdate(ent, msg, delta);
327 for (;onum < o->numentities;onum++)
329 // write remove message
330 MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
332 MSG_WriteShort(msg, 0xFFFF);
337 void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *msg, int maxsize)
339 prvm_prog_t *prog = SVVM_prog;
340 qbool need_empty = false;
341 int i, numsendstates, numcsqcsendstates;
343 prvm_edict_t *camera;
347 // if there isn't enough space to accomplish anything, skip it
348 if (msg->cursize + 25 > maxsize)
351 sv.writeentitiestoclient_msg = msg;
352 sv.writeentitiestoclient_clientnumber = client - svs.clients;
354 sv.writeentitiestoclient_stats_culled_pvs = 0;
355 sv.writeentitiestoclient_stats_culled_trace = 0;
356 sv.writeentitiestoclient_stats_visibleentities = 0;
357 sv.writeentitiestoclient_stats_totalentities = 0;
358 sv.writeentitiestoclient_numeyes = 0;
361 sv.writeentitiestoclient_cliententitynumber = PRVM_EDICT_TO_PROG(clent); // LadyHavoc: for comparison purposes
362 camera = PRVM_EDICT_NUM( client->clientcamera );
363 VectorAdd(PRVM_serveredictvector(camera, origin), PRVM_serveredictvector(clent, view_ofs), eye);
364 sv.writeentitiestoclient_pvsbytes = 0;
365 // get the PVS values for the eye location, later FatPVS calls will merge
366 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
367 sv.writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, eye, 8, sv.writeentitiestoclient_pvs, sizeof(sv.writeentitiestoclient_pvs), sv.writeentitiestoclient_pvsbytes != 0);
369 // add the eye to a list for SV_CanSeeBox tests
370 VectorCopy(eye, sv.writeentitiestoclient_eyes[sv.writeentitiestoclient_numeyes]);
371 sv.writeentitiestoclient_numeyes++;
373 // calculate predicted eye origin for SV_CanSeeBox tests
374 if (sv_cullentities_trace_prediction.integer)
376 vec_t predtime = bound(0, host_client->ping, sv_cullentities_trace_prediction_time.value);
378 VectorMA(eye, predtime, PRVM_serveredictvector(camera, velocity), predeye);
379 if (SV_CanSeeBox(1, 0, 0, 0, eye, predeye, predeye))
381 VectorCopy(predeye, sv.writeentitiestoclient_eyes[sv.writeentitiestoclient_numeyes]);
382 sv.writeentitiestoclient_numeyes++;
384 //if (!sv.writeentitiestoclient_useprediction)
385 // Con_DPrintf("Trying to walk into solid in a pingtime... not predicting for culling\n");
390 // build PVS from the new eyes
391 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
392 for(i = 1; i < sv.writeentitiestoclient_numeyes; ++i)
393 sv.writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv.writeentitiestoclient_eyes[i], 8, sv.writeentitiestoclient_pvs, sizeof(sv.writeentitiestoclient_pvs), sv.writeentitiestoclient_pvsbytes != 0);
395 sv.sententitiesmark++;
397 for (i = 0;i < sv.numsendentities;i++)
398 SV_MarkWriteEntityStateToClient(sv.sendentities + i);
401 numcsqcsendstates = 0;
402 for (i = 0;i < sv.numsendentities;i++)
404 s = &sv.sendentities[i];
405 if (sv.sententities[s->number] == sv.sententitiesmark)
407 if(s->active == ACTIVE_NETWORK)
409 if (s->exteriormodelforclient)
411 if (s->exteriormodelforclient == sv.writeentitiestoclient_cliententitynumber)
412 s->flags |= RENDER_EXTERIORMODEL;
414 s->flags &= ~RENDER_EXTERIORMODEL;
416 sv.writeentitiestoclient_sendstates[numsendstates++] = s;
418 else if(sv.sendentities[i].active == ACTIVE_SHARED)
419 sv.writeentitiestoclient_csqcsendstates[numcsqcsendstates++] = s->number;
421 Con_Printf("entity %d is in sv.sendentities and marked, but not active, please breakpoint me\n", s->number);
425 if (sv_cullentities_stats.integer)
426 Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv.writeentitiestoclient_stats_totalentities, sv.writeentitiestoclient_stats_visibleentities, sv.writeentitiestoclient_stats_culled_pvs + sv.writeentitiestoclient_stats_culled_trace, sv.writeentitiestoclient_stats_culled_pvs, sv.writeentitiestoclient_stats_culled_trace);
428 if(client->entitydatabase5)
429 need_empty = EntityFrameCSQC_WriteFrame(msg, maxsize, numcsqcsendstates, sv.writeentitiestoclient_csqcsendstates, client->entitydatabase5->latestframenum + 1);
431 EntityFrameCSQC_WriteFrame(msg, maxsize, numcsqcsendstates, sv.writeentitiestoclient_csqcsendstates, 0);
433 // force every 16th frame to be not empty (or cl_movement replay takes
435 // BTW, this should normally not kick in any more due to the check
436 // below, except if the client stopped sending movement frames
437 if(client->num_skippedentityframes >= 16)
440 // help cl_movement a bit more
441 if(client->movesequence != client->lastmovesequence)
443 client->lastmovesequence = client->movesequence;
445 if (client->entitydatabase5)
446 success = EntityFrame5_WriteFrame(msg, maxsize, client->entitydatabase5, numsendstates, sv.writeentitiestoclient_sendstates, client - svs.clients + 1, client->movesequence, need_empty);
447 else if (client->entitydatabase4)
449 success = EntityFrame4_WriteFrame(msg, maxsize, client->entitydatabase4, numsendstates, sv.writeentitiestoclient_sendstates);
450 Protocol_WriteStatsReliable();
452 else if (client->entitydatabase)
454 success = EntityFrame_WriteFrame(msg, maxsize, client->entitydatabase, numsendstates, sv.writeentitiestoclient_sendstates, client - svs.clients + 1);
455 Protocol_WriteStatsReliable();
459 success = EntityFrameQuake_WriteFrame(msg, maxsize, numsendstates, sv.writeentitiestoclient_sendstates);
460 Protocol_WriteStatsReliable();
464 client->num_skippedentityframes = 0;
466 ++client->num_skippedentityframes;