]> git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_ents.c
Merge PR 'Use the text from modinfo.txt as the mod menu entry'
[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) clears the database to contain no frames (thus delta compression compresses against nothing)
214 void EntityFrame_ClearDatabase(entityframe_database_t *d)
215 {
216         memset(d, 0, sizeof(*d));
217 }
218
219 // (server) clears frame, to prepare for adding entities
220 void EntityFrame_Clear(entity_frame_t *f, vec3_t eye, int framenum)
221 {
222         f->time = 0;
223         f->framenum = framenum;
224         f->numentities = 0;
225         if (eye == NULL)
226                 VectorClear(f->eye);
227         else
228                 VectorCopy(eye, f->eye);
229 }
230
231 // (server) adds a entity_frame to the database, for future reference
232 void EntityFrame_AddFrame_Server(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t **entitydata)
233 {
234         int n, e;
235         entity_frameinfo_t *info;
236
237         VectorCopy(eye, d->eye);
238
239         // figure out how many entity slots are used already
240         if (d->numframes)
241         {
242                 n = d->frames[d->numframes - 1].endentity - d->frames[0].firstentity;
243                 if (n + numentities > MAX_ENTITY_DATABASE || d->numframes >= MAX_ENTITY_HISTORY)
244                 {
245                         // ran out of room, dump database
246                         EntityFrame_ClearDatabase(d);
247                 }
248         }
249
250         info = &d->frames[d->numframes];
251         info->framenum = framenum;
252         e = -1000;
253         // make sure we check the newly added frame as well, but we haven't incremented numframes yet
254         for (n = 0;n <= d->numframes;n++)
255         {
256                 if (e >= d->frames[n].framenum)
257                 {
258                         if (e == framenum)
259                                 Con_Print("EntityFrame_AddFrame: tried to add out of sequence frame to database\n");
260                         else
261                                 Con_Print("EntityFrame_AddFrame: out of sequence frames in database\n");
262                         return;
263                 }
264                 e = d->frames[n].framenum;
265         }
266         // if database still has frames after that...
267         if (d->numframes)
268                 info->firstentity = d->frames[d->numframes - 1].endentity;
269         else
270                 info->firstentity = 0;
271         info->endentity = info->firstentity + numentities;
272         d->numframes++;
273
274         n = info->firstentity % MAX_ENTITY_DATABASE;
275         e = MAX_ENTITY_DATABASE - n;
276         if (e > numentities)
277                 e = numentities;
278         memcpy(d->entitydata + n, entitydata, sizeof(entity_state_t) * e);
279         if (numentities > e)
280                 memcpy(d->entitydata, entitydata + e, sizeof(entity_state_t) * (numentities - e));
281 }
282
283 // (server) writes a frame to network stream
284 qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t **states, int viewentnum)
285 {
286         prvm_prog_t *prog = SVVM_prog;
287         int i, onum, number;
288         entity_frame_t *o = &d->deltaframe;
289         const entity_state_t *ent, *delta;
290         vec3_t eye;
291
292         d->latestframenum++;
293
294         VectorClear(eye);
295         for (i = 0;i < numstates;i++)
296         {
297                 ent = states[i];
298                 if (ent->number == viewentnum)
299                 {
300                         VectorSet(eye, ent->origin[0], ent->origin[1], ent->origin[2] + 22);
301                         break;
302                 }
303         }
304
305         EntityFrame_AddFrame_Server(d, eye, d->latestframenum, numstates, states);
306
307         EntityFrame_FetchFrame(d, d->ackframenum, o);
308
309         MSG_WriteByte (msg, svc_entities);
310         MSG_WriteLong (msg, o->framenum);
311         MSG_WriteLong (msg, d->latestframenum);
312         MSG_WriteFloat (msg, eye[0]);
313         MSG_WriteFloat (msg, eye[1]);
314         MSG_WriteFloat (msg, eye[2]);
315
316         onum = 0;
317         for (i = 0;i < numstates;i++)
318         {
319                 ent = states[i];
320                 number = ent->number;
321
322                 if (PRVM_serveredictfunction((&prog->edicts[number]), SendEntity))
323                         continue;
324                 for (;onum < o->numentities && o->entitydata[onum].number < number;onum++)
325                 {
326                         // write remove message
327                         MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
328                 }
329                 if (onum < o->numentities && (o->entitydata[onum].number == number))
330                 {
331                         // delta from previous frame
332                         delta = o->entitydata + onum;
333                         // advance to next entity in delta frame
334                         onum++;
335                 }
336                 else
337                 {
338                         // delta from defaults
339                         delta = &defaultstate;
340                 }
341                 EntityState_WriteUpdate(ent, msg, delta);
342         }
343         for (;onum < o->numentities;onum++)
344         {
345                 // write remove message
346                 MSG_WriteShort(msg, o->entitydata[onum].number | 0x8000);
347         }
348         MSG_WriteShort(msg, 0xFFFF);
349
350         return true;
351 }