]> git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_entframe_qw.c
Convert \ to / when loading texture from Q3 shader
[xonotic/darkplaces.git] / cl_entframe_qw.c
1 #include "quakedef.h"
2 #include "protocol.h"
3
4 static void QW_TranslateEffects(entity_state_t *s, int qweffects)
5 {
6         s->effects = 0;
7         s->internaleffects = 0;
8         if (qweffects & QW_EF_BRIGHTFIELD)
9                 s->effects |= EF_BRIGHTFIELD;
10         if (qweffects & QW_EF_MUZZLEFLASH)
11                 s->effects |= EF_MUZZLEFLASH;
12         if (qweffects & QW_EF_FLAG1)
13         {
14                 // mimic FTEQW's interpretation of EF_FLAG1 as EF_NODRAW on non-player entities
15                 if (s->number > cl.maxclients)
16                         s->effects |= EF_NODRAW;
17                 else
18                         s->internaleffects |= INTEF_FLAG1QW;
19         }
20         if (qweffects & QW_EF_FLAG2)
21         {
22                 // mimic FTEQW's interpretation of EF_FLAG2 as EF_ADDITIVE on non-player entities
23                 if (s->number > cl.maxclients)
24                         s->effects |= EF_ADDITIVE;
25                 else
26                         s->internaleffects |= INTEF_FLAG2QW;
27         }
28         if (qweffects & QW_EF_RED)
29         {
30                 if (qweffects & QW_EF_BLUE)
31                         s->effects |= EF_RED | EF_BLUE;
32                 else
33                         s->effects |= EF_RED;
34         }
35         else if (qweffects & QW_EF_BLUE)
36                 s->effects |= EF_BLUE;
37         else if (qweffects & QW_EF_BRIGHTLIGHT)
38                 s->effects |= EF_BRIGHTLIGHT;
39         else if (qweffects & QW_EF_DIMLIGHT)
40                 s->effects |= EF_DIMLIGHT;
41 }
42
43 void EntityStateQW_ReadPlayerUpdate(void)
44 {
45         int slot = MSG_ReadByte(&cl_message);
46         int enumber = slot + 1;
47         int weaponframe;
48         int msec;
49         int playerflags;
50         int bits;
51         entity_state_t *s;
52         // look up the entity
53         entity_t *ent = cl.entities + enumber;
54         vec3_t viewangles;
55         vec3_t velocity;
56
57         // slide the current state into the previous
58         ent->state_previous = ent->state_current;
59
60         // read the update
61         s = &ent->state_current;
62         *s = defaultstate;
63         s->active = ACTIVE_NETWORK;
64         s->number = enumber;
65         s->colormap = enumber;
66         playerflags = MSG_ReadShort(&cl_message);
67         MSG_ReadVector(&cl_message, s->origin, cls.protocol);
68         s->frame = MSG_ReadByte(&cl_message);
69
70         VectorClear(viewangles);
71         VectorClear(velocity);
72
73         if (playerflags & QW_PF_MSEC)
74         {
75                 // time difference between last update this player sent to the server,
76                 // and last input we sent to the server (this packet is in response to
77                 // our input, so msec is how long ago the last update of this player
78                 // entity occurred, compared to our input being received)
79                 msec = MSG_ReadByte(&cl_message);
80         }
81         else
82                 msec = 0;
83         if (playerflags & QW_PF_COMMAND)
84         {
85                 bits = MSG_ReadByte(&cl_message);
86                 if (bits & QW_CM_ANGLE1)
87                         viewangles[0] = MSG_ReadAngle16i(&cl_message); // cmd->angles[0]
88                 if (bits & QW_CM_ANGLE2)
89                         viewangles[1] = MSG_ReadAngle16i(&cl_message); // cmd->angles[1]
90                 if (bits & QW_CM_ANGLE3)
91                         viewangles[2] = MSG_ReadAngle16i(&cl_message); // cmd->angles[2]
92                 if (bits & QW_CM_FORWARD)
93                         MSG_ReadShort(&cl_message); // cmd->forwardmove
94                 if (bits & QW_CM_SIDE)
95                         MSG_ReadShort(&cl_message); // cmd->sidemove
96                 if (bits & QW_CM_UP)
97                         MSG_ReadShort(&cl_message); // cmd->upmove
98                 if (bits & QW_CM_BUTTONS)
99                         (void) MSG_ReadByte(&cl_message); // cmd->buttons
100                 if (bits & QW_CM_IMPULSE)
101                         (void) MSG_ReadByte(&cl_message); // cmd->impulse
102                 (void) MSG_ReadByte(&cl_message); // cmd->msec
103         }
104         if (playerflags & QW_PF_VELOCITY1)
105                 velocity[0] = MSG_ReadShort(&cl_message);
106         if (playerflags & QW_PF_VELOCITY2)
107                 velocity[1] = MSG_ReadShort(&cl_message);
108         if (playerflags & QW_PF_VELOCITY3)
109                 velocity[2] = MSG_ReadShort(&cl_message);
110         if (playerflags & QW_PF_MODEL)
111                 s->modelindex = MSG_ReadByte(&cl_message);
112         else
113                 s->modelindex = cl.qw_modelindex_player;
114         if (playerflags & QW_PF_SKINNUM)
115                 s->skin = MSG_ReadByte(&cl_message);
116         if (playerflags & QW_PF_EFFECTS)
117                 QW_TranslateEffects(s, MSG_ReadByte(&cl_message));
118         if (playerflags & QW_PF_WEAPONFRAME)
119                 weaponframe = MSG_ReadByte(&cl_message);
120         else
121                 weaponframe = 0;
122
123         if (enumber == cl.playerentity)
124         {
125                 // if this is an update on our player, update the angles
126                 VectorCopy(cl.viewangles, viewangles);
127         }
128
129         // calculate the entity angles from the viewangles
130         s->angles[0] = viewangles[0] * -0.0333;
131         s->angles[1] = viewangles[1];
132         s->angles[2] = 0;
133         s->angles[2] = V_CalcRoll(s->angles, velocity)*4;
134
135         // if this is an update on our player, update interpolation state
136         if (enumber == cl.playerentity)
137         {
138                 VectorCopy (cl.mpunchangle[0], cl.mpunchangle[1]);
139                 VectorCopy (cl.mpunchvector[0], cl.mpunchvector[1]);
140                 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
141                 cl.mviewzoom[1] = cl.mviewzoom[0];
142
143                 cl.idealpitch = 0;
144                 cl.mpunchangle[0][0] = 0;
145                 cl.mpunchangle[0][1] = 0;
146                 cl.mpunchangle[0][2] = 0;
147                 cl.mpunchvector[0][0] = 0;
148                 cl.mpunchvector[0][1] = 0;
149                 cl.mpunchvector[0][2] = 0;
150                 cl.mvelocity[0][0] = 0;
151                 cl.mvelocity[0][1] = 0;
152                 cl.mvelocity[0][2] = 0;
153                 cl.mviewzoom[0] = 1;
154
155                 VectorCopy(velocity, cl.mvelocity[0]);
156                 cl.stats[STAT_WEAPONFRAME] = weaponframe;
157                 if (playerflags & QW_PF_GIB)
158                         cl.stats[STAT_VIEWHEIGHT] = 8;
159                 else if (playerflags & QW_PF_DEAD)
160                         cl.stats[STAT_VIEWHEIGHT] = -16;
161                 else
162                         cl.stats[STAT_VIEWHEIGHT] = 22;
163         }
164
165         // set the cl.entities_active flag
166         cl.entities_active[enumber] = (s->active == ACTIVE_NETWORK);
167         // set the update time
168         s->time = cl.mtime[0] - msec * 0.001; // qw has no clock
169         // check if we need to update the lerp stuff
170         if (s->active == ACTIVE_NETWORK)
171                 CL_MoveLerpEntityStates(&cl.entities[enumber]);
172 }
173
174 static void EntityStateQW_ReadEntityUpdate(entity_state_t *s, int bits)
175 {
176         int qweffects = 0;
177         s->active = ACTIVE_NETWORK;
178         s->number = bits & 511;
179         bits &= ~511;
180         if (bits & QW_U_MOREBITS)
181                 bits |= MSG_ReadByte(&cl_message);
182
183         // store the QW_U_SOLID bit here?
184
185         if (bits & QW_U_MODEL)
186                 s->modelindex = MSG_ReadByte(&cl_message);
187         if (bits & QW_U_FRAME)
188                 s->frame = MSG_ReadByte(&cl_message);
189         if (bits & QW_U_COLORMAP)
190                 s->colormap = MSG_ReadByte(&cl_message);
191         if (bits & QW_U_SKIN)
192                 s->skin = MSG_ReadByte(&cl_message);
193         if (bits & QW_U_EFFECTS)
194                 QW_TranslateEffects(s, qweffects = MSG_ReadByte(&cl_message));
195         if (bits & QW_U_ORIGIN1)
196                 s->origin[0] = MSG_ReadCoord13i(&cl_message);
197         if (bits & QW_U_ANGLE1)
198                 s->angles[0] = MSG_ReadAngle8i(&cl_message);
199         if (bits & QW_U_ORIGIN2)
200                 s->origin[1] = MSG_ReadCoord13i(&cl_message);
201         if (bits & QW_U_ANGLE2)
202                 s->angles[1] = MSG_ReadAngle8i(&cl_message);
203         if (bits & QW_U_ORIGIN3)
204                 s->origin[2] = MSG_ReadCoord13i(&cl_message);
205         if (bits & QW_U_ANGLE3)
206                 s->angles[2] = MSG_ReadAngle8i(&cl_message);
207
208         if (developer_networkentities.integer >= 2)
209         {
210                 Con_Printf("ReadFields e%i", s->number);
211                 if (bits & QW_U_MODEL)
212                         Con_Printf(" U_MODEL %i", s->modelindex);
213                 if (bits & QW_U_FRAME)
214                         Con_Printf(" U_FRAME %i", s->frame);
215                 if (bits & QW_U_COLORMAP)
216                         Con_Printf(" U_COLORMAP %i", s->colormap);
217                 if (bits & QW_U_SKIN)
218                         Con_Printf(" U_SKIN %i", s->skin);
219                 if (bits & QW_U_EFFECTS)
220                         Con_Printf(" U_EFFECTS %i", qweffects);
221                 if (bits & QW_U_ORIGIN1)
222                         Con_Printf(" U_ORIGIN1 %f", s->origin[0]);
223                 if (bits & QW_U_ANGLE1)
224                         Con_Printf(" U_ANGLE1 %f", s->angles[0]);
225                 if (bits & QW_U_ORIGIN2)
226                         Con_Printf(" U_ORIGIN2 %f", s->origin[1]);
227                 if (bits & QW_U_ANGLE2)
228                         Con_Printf(" U_ANGLE2 %f", s->angles[1]);
229                 if (bits & QW_U_ORIGIN3)
230                         Con_Printf(" U_ORIGIN3 %f", s->origin[2]);
231                 if (bits & QW_U_ANGLE3)
232                         Con_Printf(" U_ANGLE3 %f", s->angles[2]);
233                 if (bits & QW_U_SOLID)
234                         Con_Printf(" U_SOLID");
235                 Con_Print("\n");
236         }
237 }
238
239 entityframeqw_database_t *EntityFrameQW_AllocDatabase(mempool_t *pool)
240 {
241         entityframeqw_database_t *d;
242         d = (entityframeqw_database_t *)Mem_Alloc(pool, sizeof(*d));
243         return d;
244 }
245
246 void EntityFrameQW_FreeDatabase(entityframeqw_database_t *d)
247 {
248         Mem_Free(d);
249 }
250
251 void EntityFrameQW_CL_ReadFrame(qboolean delta)
252 {
253         qboolean invalid = false;
254         int number, oldsnapindex, newsnapindex, oldindex, newindex, oldnum, newnum;
255         entity_t *ent;
256         entityframeqw_database_t *d;
257         entityframeqw_snapshot_t *oldsnap, *newsnap;
258
259         if (!cl.entitydatabaseqw)
260                 cl.entitydatabaseqw = EntityFrameQW_AllocDatabase(cls.levelmempool);
261         d = cl.entitydatabaseqw;
262
263         // there is no cls.netcon in demos, so this reading code can't access
264         // cls.netcon-> at all...  so cls.qw_incoming_sequence and
265         // cls.qw_outgoing_sequence are updated every time the corresponding
266         // cls.netcon->qw. variables are updated
267         // read the number of this frame to echo back in next input packet
268         cl.qw_validsequence = cls.qw_incoming_sequence;
269         newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK;
270         newsnap = d->snapshot + newsnapindex;
271         memset(newsnap, 0, sizeof(*newsnap));
272         oldsnap = NULL;
273         if (delta)
274         {
275                 number = MSG_ReadByte(&cl_message);
276                 oldsnapindex = cl.qw_deltasequence[newsnapindex];
277                 if ((number & QW_UPDATE_MASK) != (oldsnapindex & QW_UPDATE_MASK))
278                         Con_DPrintf("WARNING: from mismatch\n");
279                 if (oldsnapindex != -1)
280                 {
281                         if (cls.qw_outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1)
282                         {
283                                 Con_DPrintf("delta update too old\n");
284                                 newsnap->invalid = invalid = true; // too old
285                                 delta = false;
286                         }
287                         oldsnap = d->snapshot + (oldsnapindex & QW_UPDATE_MASK);
288                 }
289                 else
290                         delta = false;
291         }
292
293         // if we can't decode this frame properly, report that to the server
294         if (invalid)
295                 cl.qw_validsequence = 0;
296
297         // read entity numbers until we find a 0x0000
298         // (which would be an empty update on world entity, but is actually a terminator)
299         newsnap->num_entities = 0;
300         oldindex = 0;
301         for (;;)
302         {
303                 int word = (unsigned short)MSG_ReadShort(&cl_message);
304                 if (cl_message.badread)
305                         return; // just return, the main parser will print an error
306                 newnum = word == 0 ? 512 : (word & 511);
307                 oldnum = delta ? (oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number) : 9999;
308
309                 // copy unmodified oldsnap entities
310                 while (newnum > oldnum) // delta only
311                 {
312                         if (developer_networkentities.integer >= 2)
313                                 Con_Printf("copy %i\n", oldnum);
314                         // copy one of the old entities
315                         if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES)
316                                 Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES");
317                         newsnap->entities[newsnap->num_entities] = oldsnap->entities[oldindex++];
318                         newsnap->num_entities++;
319                         oldnum = oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number;
320                 }
321
322                 if (word == 0)
323                         break;
324
325                 if (developer_networkentities.integer >= 2)
326                 {
327                         if (word & QW_U_REMOVE)
328                                 Con_Printf("remove %i\n", newnum);
329                         else if (newnum == oldnum)
330                                 Con_Printf("delta %i\n", newnum);
331                         else
332                                 Con_Printf("baseline %i\n", newnum);
333                 }
334
335                 if (word & QW_U_REMOVE)
336                 {
337                         if (newnum != oldnum && !delta && !invalid)
338                         {
339                                 cl.qw_validsequence = 0;
340                                 Con_Printf(CON_WARN "WARNING: U_REMOVE %i on full update\n", newnum);
341                         }
342                 }
343                 else
344                 {
345                         if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES)
346                                 Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES");
347                         newsnap->entities[newsnap->num_entities] = (newnum == oldnum) ? oldsnap->entities[oldindex] : cl.entities[newnum].state_baseline;
348                         EntityStateQW_ReadEntityUpdate(newsnap->entities + newsnap->num_entities, word);
349                         newsnap->num_entities++;
350                 }
351
352                 if (newnum == oldnum)
353                         oldindex++;
354         }
355
356         // expand cl.num_entities to include every entity we've seen this game
357         newnum = newsnap->num_entities ? newsnap->entities[newsnap->num_entities - 1].number : 1;
358         if (cl.num_entities <= newnum)
359         {
360                 cl.num_entities = newnum + 1;
361                 if (cl.max_entities < newnum + 1)
362                         CL_ExpandEntities(newnum);
363         }
364
365         // now update the non-player entities from the snapshot states
366         number = cl.maxclients + 1;
367         for (newindex = 0;;newindex++)
368         {
369                 newnum = newindex >= newsnap->num_entities ? cl.num_entities : newsnap->entities[newindex].number;
370                 // kill any missing entities
371                 for (;number < newnum;number++)
372                 {
373                         if (cl.entities_active[number])
374                         {
375                                 cl.entities_active[number] = false;
376                                 cl.entities[number].state_current.active = ACTIVE_NOT;
377                         }
378                 }
379                 if (number >= cl.num_entities)
380                         break;
381                 // update the entity
382                 ent = &cl.entities[number];
383                 ent->state_previous = ent->state_current;
384                 ent->state_current = newsnap->entities[newindex];
385                 ent->state_current.time = cl.mtime[0];
386                 CL_MoveLerpEntityStates(ent);
387                 // the entity lives again...
388                 cl.entities_active[number] = true;
389                 number++;
390         }
391 }