1 /*
2 cl_ents.c
3
4 entity parsing and management
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif
34 #ifdef HAVE_STRINGS_H
35 # include <strings.h>
36 #endif
37
38 #include "QF/cvar.h"
39 #include "QF/locs.h"
40 #include "QF/msg.h"
41 #include "QF/render.h"
42 #include "QF/skin.h"
43 #include "QF/sys.h"
44
45 #include "qw/msg_ucmd.h"
46
47 #include "qw/bothdefs.h"
48 #include "cl_cam.h"
49 #include "cl_ents.h"
50 #include "cl_main.h"
51 #include "cl_parse.h"
52 #include "cl_pred.h"
53 #include "cl_tent.h"
54 #include "compat.h"
55 #include "d_iface.h"
56 #include "host.h"
57 #include "qw/pmove.h"
58 #include "clview.h"
59
60 static struct predicted_player {
61 int flags;
62 qboolean active;
63 vec3_t origin; // predicted origin
64 } predicted_players[MAX_CLIENTS];
65
66
67 // PACKET ENTITY PARSING / LINKING ============================================
68
69 /*
70 CL_ParseDelta
71
72 Can go from either a baseline or a previous packet_entity
73 */
74 static void
CL_ParseDelta(entity_state_t * from,entity_state_t * to,int bits)75 CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
76 {
77 int i;
78
79 // set everything to the state we are delta'ing from
80 *to = *from;
81
82 to->number = bits & 511;
83 bits &= ~511;
84
85 if (bits & U_MOREBITS) { // read in the low order bits
86 i = MSG_ReadByte (net_message);
87 bits |= i;
88 }
89
90 // LordHavoc: Endy neglected to mark this as being part of the QSG
91 // version 2 stuff...
92 if (bits & U_EXTEND1) {
93 bits |= MSG_ReadByte (net_message) << 16;
94 if (bits & U_EXTEND2)
95 bits |= MSG_ReadByte (net_message) << 24;
96 }
97
98 to->flags = bits;
99
100 if (bits & U_MODEL)
101 to->modelindex = MSG_ReadByte (net_message);
102
103 if (bits & U_FRAME)
104 to->frame = MSG_ReadByte (net_message);
105
106 if (bits & U_COLORMAP)
107 to->colormap = MSG_ReadByte (net_message);
108
109 if (bits & U_SKIN)
110 to->skinnum = MSG_ReadByte (net_message);
111
112 if (bits & U_EFFECTS)
113 to->effects = MSG_ReadByte (net_message);
114
115 if (bits & U_ORIGIN1)
116 to->origin[0] = MSG_ReadCoord (net_message);
117
118 if (bits & U_ANGLE1)
119 to->angles[0] = MSG_ReadAngle (net_message);
120
121 if (bits & U_ORIGIN2)
122 to->origin[1] = MSG_ReadCoord (net_message);
123
124 if (bits & U_ANGLE2)
125 to->angles[1] = MSG_ReadAngle (net_message);
126
127 if (bits & U_ORIGIN3)
128 to->origin[2] = MSG_ReadCoord (net_message);
129
130 if (bits & U_ANGLE3)
131 to->angles[2] = MSG_ReadAngle (net_message);
132
133 if (bits & U_SOLID) {
134 // FIXME
135 }
136
137 if (!(bits & U_EXTEND1))
138 return;
139
140 // LordHavoc: Endy neglected to mark this as being part of the QSG
141 // version 2 stuff... rearranged it and implemented missing effects
142 // Ender (QSG - Begin)
143 if (bits & U_ALPHA)
144 to->alpha = MSG_ReadByte (net_message);
145 if (bits & U_SCALE)
146 to->scale = MSG_ReadByte (net_message);
147 if (bits & U_EFFECTS2)
148 to->effects = (to->effects & 0xFF) | (MSG_ReadByte (net_message) << 8);
149 if (bits & U_GLOWSIZE)
150 to->glow_size = MSG_ReadByte (net_message);
151 if (bits & U_GLOWCOLOR)
152 to->glow_color = MSG_ReadByte (net_message);
153 if (bits & U_COLORMOD)
154 to->colormod = MSG_ReadByte (net_message);
155
156 if (!(bits & U_EXTEND2))
157 return;
158
159 if (bits & U_FRAME2)
160 to->frame = (to->frame & 0xFF) | (MSG_ReadByte (net_message) << 8);
161 // Ender (QSG - End)
162 }
163
164 static void
FlushEntityPacket(void)165 FlushEntityPacket (void)
166 {
167 entity_state_t olde, newe;
168 int word;
169
170 Sys_MaskPrintf (SYS_DEV, "FlushEntityPacket\n");
171
172 memset (&olde, 0, sizeof (olde));
173
174 cl.validsequence = 0; // can't render a frame
175 cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].invalid = true;
176
177 // read it all, but ignore it
178 while (1) {
179 word = MSG_ReadShort (net_message);
180 if (net_message->badread) { // something didn't parse right...
181 Host_Error ("msg_badread in packetentities");
182 return;
183 }
184
185 if (!word)
186 break; // done
187
188 CL_ParseDelta (&olde, &newe, word);
189 }
190 }
191
192 static void
copy_state(packet_entities_t * newp,packet_entities_t * oldp,int newindex,int oldindex,int num)193 copy_state (packet_entities_t *newp, packet_entities_t *oldp, int newindex,
194 int oldindex, int num)
195 {
196 newp->entities[num] = oldp->entities[num];
197 newp->ent_nums[newindex] = num;
198 cl_entity_valid[0][num] = 1;
199 }
200
201 void
CL_ParsePacketEntities(qboolean delta)202 CL_ParsePacketEntities (qboolean delta)
203 {
204 byte from;
205 int oldindex, newindex, newnum, oldnum, oldpacket, word;
206 packet_entities_t *oldp, *newp, dummy;
207 qboolean full;
208
209 cl.prev_sequence = cl.link_sequence;
210 cl.link_sequence = cls.netchan.incoming_sequence;
211 newp = &cl.frames[cl.link_sequence & UPDATE_MASK].packet_entities;
212 cl.frames[cl.link_sequence & UPDATE_MASK].invalid = false;
213
214 if (delta) {
215 from = MSG_ReadByte (net_message);
216
217 oldpacket = cl.frames[cl.link_sequence & UPDATE_MASK].delta_sequence;
218 if (cls.demoplayback2)
219 from = oldpacket = (cls.netchan.incoming_sequence - 1);
220 if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK))
221 Sys_MaskPrintf (SYS_DEV, "WARNING: from mismatch\n");
222 } else
223 oldpacket = -1;
224
225 full = false;
226 //memcpy (cl_entity_valid[1], cl_entity_valid[0],
227 // sizeof (cl_entity_valid[0]));
228 if (oldpacket != -1) {
229 if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) {
230 // we can't use this, it is too old
231 FlushEntityPacket ();
232 return;
233 }
234 cl.validsequence = cls.netchan.incoming_sequence;
235 oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities;
236 } else { // a full update that we can start delta compressing from now
237 oldp = &dummy;
238 dummy.num_entities = 0;
239 cl.validsequence = cls.netchan.incoming_sequence;
240 full = true;
241 memset (cl_entity_valid[0], 0, sizeof (cl_entity_valid[0]));
242 }
243
244 oldindex = 0;
245 newindex = 0;
246 newp->num_entities = 0;
247
248 newnum = 0;
249 while (1) {
250 word = MSG_ReadShort (net_message);
251 if (net_message->badread) { // something didn't parse right...
252 Host_Error ("msg_badread in packetentities");
253 return;
254 }
255
256 if (!word) { // copy rest of ents from old packet
257 while (oldindex < oldp->num_entities) {
258 if (newindex >= MAX_DEMO_PACKET_ENTITIES)
259 Host_Error ("CL_ParsePacketEntities: newindex == "
260 "MAX_DEMO_PACKET_ENTITIES");
261 oldnum = oldp->ent_nums[oldindex];
262 copy_state (newp, oldp, newindex++, oldindex++, oldnum);
263 }
264 break;
265 }
266 newnum = word & 511;
267 oldnum = oldindex >= oldp->num_entities ? 9999 :
268 oldp->ent_nums[oldindex];
269
270 while (newnum > oldnum) {
271 if (full) {
272 Sys_Printf ("WARNING: oldcopy on full update");
273 FlushEntityPacket ();
274 return;
275 }
276 // copy one of the old entities over to the new packet unchanged
277 if (newindex >= MAX_DEMO_PACKET_ENTITIES)
278 Host_Error ("CL_ParsePacketEntities: newindex == "
279 "MAX_DEMO_PACKET_ENTITIES");
280 copy_state (newp, oldp, newindex++, oldindex++, oldnum);
281 oldnum = oldindex >= oldp->num_entities ? 9999 :
282 oldp->ent_nums[oldindex];
283 }
284
285 if (newnum < oldnum) { // new from baseline
286 if (word & U_REMOVE) {
287 cl_entity_valid[0][newnum] = 0;
288 if (full) {
289 cl.validsequence = 0;
290 Sys_Printf ("WARNING: U_REMOVE on full update\n");
291 FlushEntityPacket ();
292 return;
293 }
294 continue;
295 }
296
297 if (newindex >= MAX_DEMO_PACKET_ENTITIES)
298 Host_Error ("CL_ParsePacketEntities: newindex == "
299 "MAX_DEMO_PACKET_ENTITIES");
300 CL_ParseDelta (&qw_entstates.baseline[newnum],
301 &newp->entities[newnum], word);
302 newp->ent_nums[newindex] = newnum;
303 cl_entity_valid[0][newnum] = 1;
304 newindex++;
305 continue;
306 }
307
308 if (newnum == oldnum) { // delta from previous
309 if (full) {
310 cl.validsequence = 0;
311 Sys_Printf ("WARNING: delta on full update");
312 }
313 if (word & U_REMOVE) { // Clear the entity
314 cl_entity_valid[0][newnum] = 0;
315 oldindex++;
316 continue;
317 }
318 CL_ParseDelta (&oldp->entities[oldnum],
319 &newp->entities[newnum], word);
320 newp->ent_nums[newindex] = newnum;
321 cl_entity_valid[0][newnum] = 1;
322 newindex++;
323 oldindex++;
324 }
325 }
326
327 cl.num_entities = max (cl.num_entities, newnum);
328 newp->num_entities = newindex;
329 }
330
331 static int
TranslateFlags(int src)332 TranslateFlags (int src)
333 {
334 int dst = 0;
335
336 if (src & DF_EFFECTS)
337 dst |= PF_EFFECTS;
338 if (src & DF_SKINNUM)
339 dst |= PF_SKINNUM;
340 if (src & DF_DEAD)
341 dst |= PF_DEAD;
342 if (src & DF_GIB)
343 dst |= PF_GIB;
344 if (src & DF_WEAPONFRAME)
345 dst |= PF_WEAPONFRAME;
346 if (src & DF_MODEL)
347 dst |= PF_MODEL;
348
349 return dst;
350 }
351
352 static void
CL_ParseDemoPlayerinfo(int num)353 CL_ParseDemoPlayerinfo (int num)
354 {
355 int flags, i;
356 player_info_t *info;
357 player_state_t *state, *prevstate;
358 static player_state_t dummy;
359
360 info = &cl.players[num];
361 state = &cl.frames[parsecountmod].playerstate[num];
362
363 state->pls.number = num;
364
365 if (info->prevcount > cl.parsecount || !cl.parsecount) {
366 prevstate = &dummy;
367 } else {
368 if (cl.parsecount - info->prevcount >= UPDATE_BACKUP-1)
369 prevstate = &dummy;
370 else
371 prevstate = &cl.frames[info->prevcount
372 & UPDATE_MASK].playerstate[num];
373 }
374 info->prevcount = cl.parsecount;
375
376 if (cls.findtrack && info->stats[STAT_HEALTH] != 0) {
377 autocam = CAM_TRACK;
378 Cam_Lock (num);
379 ideal_track = num;
380 cls.findtrack = false;
381 }
382
383 memcpy (state, prevstate, sizeof (player_state_t));
384
385 flags = MSG_ReadShort (net_message);
386 state->pls.flags = TranslateFlags (flags);
387 state->messagenum = cl.parsecount;
388 state->pls.cmd.msec = 0;
389 state->pls.frame = MSG_ReadByte (net_message);
390 state->state_time = parsecounttime;
391 for (i=0; i <3; i++)
392 if (flags & (DF_ORIGIN << i))
393 state->pls.origin[i] = MSG_ReadCoord (net_message);
394 for (i=0; i <3; i++)
395 if (flags & (DF_ANGLES << i))
396 state->pls.cmd.angles[i] = MSG_ReadAngle16 (net_message);
397 if (flags & DF_MODEL)
398 state->pls.modelindex = MSG_ReadByte (net_message);
399 if (flags & DF_SKINNUM)
400 state->pls.skinnum = MSG_ReadByte (net_message);
401 if (flags & DF_EFFECTS)
402 state->pls.effects = MSG_ReadByte (net_message);
403 if (flags & DF_WEAPONFRAME)
404 state->pls.weaponframe = MSG_ReadByte (net_message);
405 VectorCopy (state->pls.cmd.angles, state->viewangles);
406 }
407
408 void
CL_ParsePlayerinfo(void)409 CL_ParsePlayerinfo (void)
410 {
411 int flags, msec, num, i;
412 player_state_t *state;
413
414 num = MSG_ReadByte (net_message);
415 if (num > MAX_CLIENTS)
416 Host_Error ("CL_ParsePlayerinfo: bad num");
417
418 if (cls.demoplayback2) {
419 CL_ParseDemoPlayerinfo (num);
420 return;
421 }
422
423 state = &cl.frames[parsecountmod].playerstate[num];
424
425 state->pls.number = num;
426
427 flags = state->pls.flags = MSG_ReadShort (net_message);
428
429 state->messagenum = cl.parsecount;
430 MSG_ReadCoordV (net_message, state->pls.origin);
431
432 state->pls.frame = MSG_ReadByte (net_message);
433
434 // the other player's last move was likely some time
435 // before the packet was sent out, so accurately track
436 // the exact time it was valid at
437 if (flags & PF_MSEC) {
438 msec = MSG_ReadByte (net_message);
439 state->state_time = parsecounttime - msec * 0.001;
440 } else
441 state->state_time = parsecounttime;
442
443 if (flags & PF_COMMAND)
444 MSG_ReadDeltaUsercmd (net_message, &nullcmd, &state->pls.cmd);
445
446 for (i = 0; i < 3; i++) {
447 if (flags & (PF_VELOCITY1 << i))
448 state->pls.velocity[i] = (short) MSG_ReadShort (net_message);
449 else
450 state->pls.velocity[i] = 0;
451 }
452 if (flags & PF_MODEL)
453 i = MSG_ReadByte (net_message);
454 else
455 i = cl_playerindex;
456 state->pls.modelindex = i;
457
458 if (flags & PF_SKINNUM)
459 state->pls.skinnum = MSG_ReadByte (net_message);
460 else
461 state->pls.skinnum = 0;
462
463 if (flags & PF_EFFECTS)
464 state->pls.effects = MSG_ReadByte (net_message);
465 else
466 state->pls.effects = 0;
467
468 if (flags & PF_WEAPONFRAME)
469 state->pls.weaponframe = MSG_ReadByte (net_message);
470 else
471 state->pls.weaponframe = 0;
472
473 VectorCopy (state->pls.cmd.angles, state->viewangles);
474
475 if (cl.stdver >= 2.0 && (flags & PF_QF)) {
476 // QSG2
477 int bits;
478 byte val;
479 entity_t *ent;
480
481 ent = &cl_player_ents[num];
482 bits = MSG_ReadByte (net_message);
483 if (bits & PF_ALPHA) {
484 val = MSG_ReadByte (net_message);
485 ent->colormod[3] = val / 255.0;
486 }
487 if (bits & PF_SCALE) {
488 val = MSG_ReadByte (net_message);
489 ent->scale = val / 16.0;
490 }
491 if (bits & PF_EFFECTS2) {
492 state->pls.effects |= MSG_ReadByte (net_message) << 8;
493 }
494 if (bits & PF_GLOWSIZE) {
495 state->pls.glow_size = MSG_ReadByte (net_message);
496 }
497 if (bits & PF_GLOWCOLOR) {
498 state->pls.glow_color = MSG_ReadByte (net_message);
499 }
500 if (bits & PF_COLORMOD) {
501 float r = 1.0, g = 1.0, b = 1.0;
502 val = MSG_ReadByte (net_message);
503 if (val != 255) {
504 r = (float) ((val >> 5) & 7) * (1.0 / 7.0);
505 g = (float) ((val >> 2) & 7) * (1.0 / 7.0);
506 b = (float) (val & 3) * (1.0 / 3.0);
507 }
508 VectorSet (r, g, b, ent->colormod);
509 }
510 if (bits & PF_FRAME2) {
511 state->pls.frame |= MSG_ReadByte (net_message) << 8;
512 }
513 }
514 }
515
516 /*
517 CL_SetSolid
518
519 Builds all the pmove physents for the current frame
520 */
521 void
CL_SetSolidEntities(void)522 CL_SetSolidEntities (void)
523 {
524 int i;
525 entity_state_t *state;
526 frame_t *frame;
527 packet_entities_t *pak;
528
529 pmove.physents[0].model = cl.worldmodel;
530 VectorZero (pmove.physents[0].origin);
531 VectorZero (pmove.physents[0].angles);
532 pmove.physents[0].info = 0;
533 pmove.numphysent = 1;
534
535 frame = &cl.frames[parsecountmod];
536 pak = &frame->packet_entities;
537
538 for (i = 0; i < pak->num_entities; i++) {
539 state = &pak->entities[i];
540
541 if (!state->modelindex)
542 continue;
543 if (!cl.model_precache[state->modelindex])
544 continue;
545 if (cl.model_precache[state->modelindex]->hulls[1].firstclipnode
546 || cl.model_precache[state->modelindex]->clipbox) {
547 if (pmove.numphysent == MAX_PHYSENTS) {
548 Sys_Printf ("WARNING: entity physent overflow, email "
549 "quakeforge-devel@lists.quakeforge.net\n");
550 break;
551 }
552 pmove.physents[pmove.numphysent].model =
553 cl.model_precache[state->modelindex];
554 VectorCopy (state->origin,
555 pmove.physents[pmove.numphysent].origin);
556 VectorCopy (state->angles,
557 pmove.physents[pmove.numphysent].angles);
558 pmove.numphysent++;
559 }
560 }
561 }
562
563 void
CL_ClearPredict(void)564 CL_ClearPredict (void)
565 {
566 memset (predicted_players, 0, sizeof (predicted_players));
567 //fixangle = 0;
568 }
569
570 /*
571 Calculate the new position of players, without other player clipping
572
573 We do this to set up real player prediction.
574 Players are predicted twice, first without clipping other players,
575 then with clipping against them.
576 This sets up the first phase.
577 */
578 void
CL_SetUpPlayerPrediction(qboolean dopred)579 CL_SetUpPlayerPrediction (qboolean dopred)
580 {
581 double playertime;
582 frame_t *frame;
583 int msec, j;
584 player_state_t exact;
585 player_state_t *state;
586 struct predicted_player *pplayer;
587
588 playertime = realtime - cls.latency + 0.02;
589 if (playertime > realtime)
590 playertime = realtime;
591
592 frame = &cl.frames[cl.parsecount & UPDATE_MASK];
593
594 for (j = 0, pplayer = predicted_players, state = frame->playerstate;
595 j < MAX_CLIENTS; j++, pplayer++, state++) {
596
597 pplayer->active = false;
598
599 if (state->messagenum != cl.parsecount)
600 continue; // not present this frame
601
602 if (!state->pls.modelindex)
603 continue;
604
605 pplayer->active = true;
606 pplayer->flags = state->pls.flags;
607
608 // note that the local player is special, since he moves locally
609 // we use his last predicted postition
610 if (j == cl.playernum) {
611 VectorCopy (cl.frames[cls.netchan.outgoing_sequence & UPDATE_MASK].
612 playerstate[cl.playernum].pls.origin, pplayer->origin);
613 } else {
614 // predict only half the move to minimize overruns
615 msec = 500 * (playertime - state->state_time);
616 if (msec <= 0 || !dopred) {
617 VectorCopy (state->pls.origin, pplayer->origin);
618 // Sys_MaskPrintf (SYS_DEV, "nopredict\n");
619 } else {
620 // predict players movement
621 state->pls.cmd.msec = msec = min (msec, 255);
622 // Sys_MaskPrintf (SYS_DEV, "predict: %i\n", msec);
623
624 CL_PredictUsercmd (state, &exact, &state->pls.cmd, false);
625 VectorCopy (exact.pls.origin, pplayer->origin);
626 }
627 }
628 }
629 }
630
631 /*
632 CL_SetSolid
633
634 Builds all the pmove physents for the current frame
635 Note that CL_SetUpPlayerPrediction () must be called first!
636 pmove must be setup with world and solid entity hulls before calling
637 (via CL_PredictMove)
638 */
639 void
CL_SetSolidPlayers(int playernum)640 CL_SetSolidPlayers (int playernum)
641 {
642 int j;
643 physent_t *pent;
644 struct predicted_player *pplayer;
645
646 if (!cl_solid_players->int_val)
647 return;
648
649 pent = pmove.physents + pmove.numphysent;
650
651 for (j = 0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++) {
652 if (!pplayer->active)
653 continue; // not present this frame
654
655 // the player object never gets added
656 if (j == playernum)
657 continue;
658
659 if (pplayer->flags & PF_DEAD)
660 continue; // dead players aren't solid
661
662 if (pmove.numphysent == MAX_PHYSENTS) {
663 Sys_Printf ("WARNING: player physent overflow, email "
664 "quakeforge-devel@lists.quakeforge.net\n");
665 break;
666 }
667
668 pent->model = 0;
669 VectorCopy (pplayer->origin, pent->origin);
670 VectorCopy (player_mins, pent->mins);
671 VectorCopy (player_maxs, pent->maxs);
672 pmove.numphysent++;
673 pent++;
674 }
675 }
676