]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_ents.c
build: minor adjustments
[xonotic/darkplaces.git] / sv_ents.c
1 #include "quakedef.h"
2 #include "protocol.h"
3
4 int EntityState_DeltaBits(const entity_state_t *o, const entity_state_t *n)
5 {
6         unsigned int bits;
7         // if o is not active, delta from default
8         if (o->active != ACTIVE_NETWORK)
9                 o = &defaultstate;
10         bits = 0;
11         if (fabs(n->origin[0] - o->origin[0]) > (1.0f / 256.0f))
12                 bits |= E_ORIGIN1;
13         if (fabs(n->origin[1] - o->origin[1]) > (1.0f / 256.0f))
14                 bits |= E_ORIGIN2;
15         if (fabs(n->origin[2] - o->origin[2]) > (1.0f / 256.0f))
16                 bits |= E_ORIGIN3;
17         if ((unsigned char) (n->angles[0] * (256.0f / 360.0f)) != (unsigned char) (o->angles[0] * (256.0f / 360.0f)))
18                 bits |= E_ANGLE1;
19         if ((unsigned char) (n->angles[1] * (256.0f / 360.0f)) != (unsigned char) (o->angles[1] * (256.0f / 360.0f)))
20                 bits |= E_ANGLE2;
21         if ((unsigned char) (n->angles[2] * (256.0f / 360.0f)) != (unsigned char) (o->angles[2] * (256.0f / 360.0f)))
22                 bits |= E_ANGLE3;
23         if ((n->modelindex ^ o->modelindex) & 0x00FF)
24                 bits |= E_MODEL1;
25         if ((n->modelindex ^ o->modelindex) & 0xFF00)
26                 bits |= E_MODEL2;
27         if ((n->frame ^ o->frame) & 0x00FF)
28                 bits |= E_FRAME1;
29         if ((n->frame ^ o->frame) & 0xFF00)
30                 bits |= E_FRAME2;
31         if ((n->effects ^ o->effects) & 0x00FF)
32                 bits |= E_EFFECTS1;
33         if ((n->effects ^ o->effects) & 0xFF00)
34                 bits |= E_EFFECTS2;
35         if (n->colormap != o->colormap)
36                 bits |= E_COLORMAP;
37         if (n->skin != o->skin)
38                 bits |= E_SKIN;
39         if (n->alpha != o->alpha)
40                 bits |= E_ALPHA;
41         if (n->scale != o->scale)
42                 bits |= E_SCALE;
43         if (n->glowsize != o->glowsize)
44                 bits |= E_GLOWSIZE;
45         if (n->glowcolor != o->glowcolor)
46                 bits |= E_GLOWCOLOR;
47         if (n->flags != o->flags)
48                 bits |= E_FLAGS;
49         if (n->tagindex != o->tagindex || n->tagentity != o->tagentity)
50                 bits |= E_TAGATTACHMENT;
51         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])
52                 bits |= E_LIGHT;
53         if (n->lightstyle != o->lightstyle)
54                 bits |= E_LIGHTSTYLE;
55         if (n->lightpflags != o->lightpflags)
56                 bits |= E_LIGHTPFLAGS;
57
58         if (bits)
59         {
60                 if (bits &  0xFF000000)
61                         bits |= 0x00800000;
62                 if (bits &  0x00FF0000)
63                         bits |= 0x00008000;
64                 if (bits &  0x0000FF00)
65                         bits |= 0x00000080;
66         }
67         return bits;
68 }
69
70 void EntityState_WriteExtendBits(sizebuf_t *msg, unsigned int bits)
71 {
72         MSG_WriteByte(msg, bits & 0xFF);
73         if (bits & 0x00000080)
74         {
75                 MSG_WriteByte(msg, (bits >> 8) & 0xFF);
76                 if (bits & 0x00008000)
77                 {
78                         MSG_WriteByte(msg, (bits >> 16) & 0xFF);
79                         if (bits & 0x00800000)
80                                 MSG_WriteByte(msg, (bits >> 24) & 0xFF);
81                 }
82         }
83 }
84
85 void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned int bits)
86 {
87         if (sv.protocol == PROTOCOL_DARKPLACES2)
88         {
89                 if (bits & E_ORIGIN1)
90                         MSG_WriteCoord16i(msg, ent->origin[0]);
91                 if (bits & E_ORIGIN2)
92                         MSG_WriteCoord16i(msg, ent->origin[1]);
93                 if (bits & E_ORIGIN3)
94                         MSG_WriteCoord16i(msg, ent->origin[2]);
95         }
96         else
97         {
98                 // LadyHavoc: have to write flags first, as they can modify protocol
99                 if (bits & E_FLAGS)
100                         MSG_WriteByte(msg, ent->flags);
101                 if (ent->flags & RENDER_LOWPRECISION)
102                 {
103                         if (bits & E_ORIGIN1)
104                                 MSG_WriteCoord16i(msg, ent->origin[0]);
105                         if (bits & E_ORIGIN2)
106                                 MSG_WriteCoord16i(msg, ent->origin[1]);
107                         if (bits & E_ORIGIN3)
108                                 MSG_WriteCoord16i(msg, ent->origin[2]);
109                 }
110                 else
111                 {
112                         if (bits & E_ORIGIN1)
113                                 MSG_WriteCoord32f(msg, ent->origin[0]);
114                         if (bits & E_ORIGIN2)
115                                 MSG_WriteCoord32f(msg, ent->origin[1]);
116                         if (bits & E_ORIGIN3)
117                                 MSG_WriteCoord32f(msg, ent->origin[2]);
118                 }
119         }
120         if ((sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4) && (ent->flags & RENDER_LOWPRECISION))
121         {
122                 if (bits & E_ANGLE1)
123                         MSG_WriteAngle8i(msg, ent->angles[0]);
124                 if (bits & E_ANGLE2)
125                         MSG_WriteAngle8i(msg, ent->angles[1]);
126                 if (bits & E_ANGLE3)
127                         MSG_WriteAngle8i(msg, ent->angles[2]);
128         }
129         else
130         {
131                 if (bits & E_ANGLE1)
132                         MSG_WriteAngle16i(msg, ent->angles[0]);
133                 if (bits & E_ANGLE2)
134                         MSG_WriteAngle16i(msg, ent->angles[1]);
135                 if (bits & E_ANGLE3)
136                         MSG_WriteAngle16i(msg, ent->angles[2]);
137         }
138         if (bits & E_MODEL1)
139                 MSG_WriteByte(msg, ent->modelindex & 0xFF);
140         if (bits & E_MODEL2)
141                 MSG_WriteByte(msg, (ent->modelindex >> 8) & 0xFF);
142         if (bits & E_FRAME1)
143                 MSG_WriteByte(msg, ent->frame & 0xFF);
144         if (bits & E_FRAME2)
145                 MSG_WriteByte(msg, (ent->frame >> 8) & 0xFF);
146         if (bits & E_EFFECTS1)
147                 MSG_WriteByte(msg, ent->effects & 0xFF);
148         if (bits & E_EFFECTS2)
149                 MSG_WriteByte(msg, (ent->effects >> 8) & 0xFF);
150         if (bits & E_COLORMAP)
151                 MSG_WriteByte(msg, ent->colormap);
152         if (bits & E_SKIN)
153                 MSG_WriteByte(msg, ent->skin);
154         if (bits & E_ALPHA)
155                 MSG_WriteByte(msg, ent->alpha);
156         if (bits & E_SCALE)
157                 MSG_WriteByte(msg, ent->scale);
158         if (bits & E_GLOWSIZE)
159                 MSG_WriteByte(msg, ent->glowsize);
160         if (bits & E_GLOWCOLOR)
161                 MSG_WriteByte(msg, ent->glowcolor);
162         if (sv.protocol == PROTOCOL_DARKPLACES2)
163                 if (bits & E_FLAGS)
164                         MSG_WriteByte(msg, ent->flags);
165         if (bits & E_TAGATTACHMENT)
166         {
167                 MSG_WriteShort(msg, ent->tagentity);
168                 MSG_WriteByte(msg, ent->tagindex);
169         }
170         if (bits & E_LIGHT)
171         {
172                 MSG_WriteShort(msg, ent->light[0]);
173                 MSG_WriteShort(msg, ent->light[1]);
174                 MSG_WriteShort(msg, ent->light[2]);
175                 MSG_WriteShort(msg, ent->light[3]);
176         }
177         if (bits & E_LIGHTSTYLE)
178                 MSG_WriteByte(msg, ent->lightstyle);
179         if (bits & E_LIGHTPFLAGS)
180                 MSG_WriteByte(msg, ent->lightpflags);
181 }
182
183 void EntityState_WriteUpdate(const entity_state_t *ent, sizebuf_t *msg, const entity_state_t *delta)
184 {
185         prvm_prog_t *prog = SVVM_prog;
186         unsigned int bits;
187         if (ent->active == ACTIVE_NETWORK)
188         {
189                 // entity is active, check for changes from the delta
190                 if ((bits = EntityState_DeltaBits(delta, ent)))
191                 {
192                         // write the update number, bits, and fields
193                         ENTITYSIZEPROFILING_START(msg, ent->number, bits);
194                         MSG_WriteShort(msg, ent->number);
195                         EntityState_WriteExtendBits(msg, bits);
196                         EntityState_WriteFields(ent, msg, bits);
197                         ENTITYSIZEPROFILING_END(msg, ent->number, bits);
198                 }
199         }
200         else
201         {
202                 // entity is inactive, check if the delta was active
203                 if (delta->active == ACTIVE_NETWORK)
204                 {
205                         // write the remove number
206                         ENTITYSIZEPROFILING_START(msg, ent->number, 0);
207                         MSG_WriteShort(msg, ent->number | 0x8000);
208                         ENTITYSIZEPROFILING_END(msg, ent->number, 0);
209                 }
210         }
211 }
212
213 // (server) adds a entity_frame to the database, for future reference
214 void EntityFrame_AddFrame_Server(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t **entitydata)
215 {
216         int n, e;
217         entity_frameinfo_t *info;
218
219         VectorCopy(eye, d->eye);
220
221         // figure out how many entity slots are used already
222         if (d->numframes)
223         {
224                 n = d->frames[d->numframes - 1].endentity - d->frames[0].firstentity;
225                 if (n + numentities > MAX_ENTITY_DATABASE || d->numframes >= MAX_ENTITY_HISTORY)
226                 {
227                         // ran out of room, dump database
228                         EntityFrame_ClearDatabase(d);
229                 }
230         }
231
232         info = &d->frames[d->numframes];
233         info->framenum = framenum;
234         e = -1000;
235         // make sure we check the newly added frame as well, but we haven't incremented numframes yet
236         for (n = 0;n <= d->numframes;n++)
237         {
238                 if (e >= d->frames[n].framenum)
239                 {
240                         if (e == framenum)
241                                 Con_Print("EntityFrame_AddFrame: tried to add out of sequence frame to database\n");
242                         else
243                                 Con_Print("EntityFrame_AddFrame: out of sequence frames in database\n");
244                         return;
245                 }
246                 e = d->frames[n].framenum;
247         }
248         // if database still has frames after that...
249         if (d->numframes)
250                 info->firstentity = d->frames[d->numframes - 1].endentity;
251         else
252                 info->firstentity = 0;
253         info->endentity = info->firstentity + numentities;
254         d->numframes++;
255
256         n = info->firstentity % MAX_ENTITY_DATABASE;
257         e = MAX_ENTITY_DATABASE - n;
258         if (e > numentities)
259                 e = numentities;
260         memcpy(d->entitydata + n, entitydata, sizeof(entity_state_t) * e);
261         if (numentities > e)
262                 memcpy(d->entitydata, entitydata + e, sizeof(entity_state_t) * (numentities - e));
263 }
264
265 // (server) writes a frame to network stream
266 qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t **states, int viewentnum)
267 {
268         prvm_prog_t *prog = SVVM_prog;
269         int i, onum, number;
270         entity_frame_t *o = &d->deltaframe;
271         const entity_state_t *ent, *delta;
272         vec3_t eye;
273
274         d->latestframenum++;
275
276         VectorClear(eye);
277         for (i = 0;i < numstates;i++)
278         {
279                 ent = states[i];
280                 if (ent->number == viewentnum)
281                 {
282                         VectorSet(eye, ent->origin[0], ent->origin[1], ent->origin[2] + 22);
283                         break;
284                 }
285         }
286
287         EntityFrame_AddFrame_Server(d, eye, d->latestframenum, numstates, states);
288
289         EntityFrame_FetchFrame(d, d->ackframenum, o);
290
291         MSG_WriteByte (msg, svc_entities);
292         MSG_WriteLong (msg, o->framenum);
293         MSG_WriteLong (msg, d->latestframenum);
294         MSG_WriteFloat (msg, eye[0]);
295         MSG_WriteFloat (msg, eye[1]);
296         MSG_WriteFloat (msg, eye[2]);
297
298         onum = 0;
299         for (i = 0;i < numstates;i++)
300         {
301                 ent = states[i];
302                 number = ent->number;
303
304                 if (PRVM_serveredictfunction((&prog->edicts[number]), SendEntity))
305                         continue;
306                 for (;onum < o->numentities && o->entitydata[onum].number < number;onum++)
307                 {
308                         // write remove message
309                         MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
310                 }
311                 if (onum < o->numentities && (o->entitydata[onum].number == number))
312                 {
313                         // delta from previous frame
314                         delta = o->entitydata + onum;
315                         // advance to next entity in delta frame
316                         onum++;
317                 }
318                 else
319                 {
320                         // delta from defaults
321                         delta = &defaultstate;
322                 }
323                 EntityState_WriteUpdate(ent, msg, delta);
324         }
325         for (;onum < o->numentities;onum++)
326         {
327                 // write remove message
328                 MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
329         }
330         MSG_WriteShort(msg, 0xFFFF);
331
332         return true;
333 }