1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include "server.h"
22 #include "mvd.h"
23
24 /*
25 =============================================================================
26
27 Encode a client frame onto the network channel
28
29 =============================================================================
30 */
31
32 /*
33 =============
34 SV_EmitPacketEntities
35
36 Writes a delta update of an entity_state_t list to the message.
37 =============
38 */
SV_EmitPacketEntities(deltaFrame_t * from,deltaFrame_t * to,int clientNum,entity_state_t ** baselines)39 void SV_EmitPacketEntities( deltaFrame_t *from, deltaFrame_t *to,
40 int clientNum, entity_state_t **baselines )
41 {
42 entity_state_t *oldent, *newent, *base;
43 uint32 oldindex, newindex;
44 int oldnum, newnum;
45 uint32 from_num_entities;
46 msgEsFlags_t flags;
47 uint32 i;
48
49 if( !from )
50 from_num_entities = 0;
51 else
52 from_num_entities = from->numEntities;
53
54 newindex = 0;
55 oldindex = 0;
56 oldent = newent = 0;
57 while( newindex < to->numEntities || oldindex < from_num_entities ) {
58 if( newindex >= to->numEntities ) {
59 newnum = 9999;
60 } else {
61 i = ( to->firstEntity + newindex ) % svs.numEntityStates;
62 newent = &svs.entityStates[i];
63 newnum = newent->number;
64 }
65
66 if( oldindex >= from_num_entities ) {
67 oldnum = 9999;
68 } else {
69 i = ( from->firstEntity + oldindex ) % svs.numEntityStates;
70 oldent = &svs.entityStates[i];
71 oldnum = oldent->number;
72 }
73
74 if( newnum == oldnum ) {
75 // delta update from old position
76 // because the force parm is false, this will not result
77 // in any bytes being emited if the entity has not changed at all
78 // note that players are always 'newentities', this updates their
79 // oldorigin always and prevents warping
80 flags = 0;
81 if( clientNum == CLIENTNUM_ANY ) {
82 if( newent->number <= svs.maxGameClients &&
83 sv.state == ss_game )
84 {
85 edict_t *ent = EDICT_NUM( newent->number );
86 if( ent->client->ps.pmove.pm_type < PM_DEAD ) {
87 flags |= MSG_ES_FIRSTPERSON;
88 }
89 }
90 } else {
91 if( newent->number <= svs.maxGameClients ) {
92 flags |= MSG_ES_NEWENTITY;
93 }
94 if( clientNum != CLIENTNUM_NONE ) {
95 if( newent->number == clientNum + 1 ) {
96 flags |= MSG_ES_FIRSTPERSON;
97 }
98 }
99 }
100 MSG_WriteDeltaEntity( oldent, newent, flags );
101 oldindex++;
102 newindex++;
103 continue;
104 }
105
106 if( newnum < oldnum ) {
107 // this is a new entity, send it from the baseline
108 flags = MSG_ES_FORCE|MSG_ES_NEWENTITY;
109 if( clientNum == CLIENTNUM_ANY ) {
110 if( newent->number <= svs.maxGameClients &&
111 sv.state == ss_game )
112 {
113 edict_t *ent = EDICT_NUM( newent->number );
114 if( ent->client->ps.pmove.pm_type < PM_DEAD ) {
115 flags |= MSG_ES_FIRSTPERSON;
116 }
117 }
118 } else {
119 if( clientNum != CLIENTNUM_NONE ) {
120 if( newent->number == clientNum + 1 ) {
121 flags |= MSG_ES_FIRSTPERSON;
122 }
123 }
124 }
125 base = baselines[newnum >> SV_BASELINES_SHIFT];
126 if( base ) {
127 base += newnum & SV_BASELINES_MASK;
128 }
129 MSG_WriteDeltaEntity( base, newent, flags );
130 newindex++;
131 continue;
132 }
133
134 if( newnum > oldnum ) {
135 // the old entity isn't present in the new message
136 MSG_WriteDeltaEntity( oldent, NULL, MSG_ES_FORCE );
137 oldindex++;
138 continue;
139 }
140 }
141
142 MSG_WriteShort( 0 ); // end of packetentities
143 }
144
SV_EmitPacketPlayers(deltaFrame_t * from,deltaFrame_t * to,msgPsFlags_t flags)145 void SV_EmitPacketPlayers( deltaFrame_t *from, deltaFrame_t *to, msgPsFlags_t flags ) {
146 playerStateEx_t *oldps, *newps;
147 uint32 oldindex, newindex;
148 int oldnum, newnum;
149 uint32 from_num_players;
150 uint32 i;
151
152 if( !from ) {
153 from_num_players = 0;
154 } else {
155 from_num_players = from->numPlayers;
156 }
157
158 newindex = 0;
159 oldindex = 0;
160 oldps = newps = NULL;
161 while( newindex < to->numPlayers || oldindex < from_num_players ) {
162 if( newindex >= to->numPlayers ) {
163 newnum = 9999;
164 } else {
165 i = ( to->firstPlayer + newindex ) % svs.numPlayerStates;
166 newps = &svs.playerStates[i];
167 newnum = newps->number;
168 }
169
170 if( oldindex >= from_num_players ) {
171 oldnum = 9999;
172 } else {
173 i = ( from->firstPlayer + oldindex ) % svs.numPlayerStates;
174 oldps = &svs.playerStates[i];
175 oldnum = oldps->number;
176 }
177
178 if( newnum == oldnum ) {
179 // delta update from old position
180 // because the force parm is qfalse, this will not result
181 // in any bytes being emited if the entity has not changed at all
182 MSG_WriteDeltaPlayerstate_Packet( oldps, newps, flags );
183 oldindex++;
184 newindex++;
185 continue;
186 }
187
188 if( newnum < oldnum ) {
189 // this is a new entity, send it from the baseline
190 MSG_WriteDeltaPlayerstate_Packet( NULL, newps, flags | MSG_PS_FORCE );
191 newindex++;
192 continue;
193 }
194
195 if( newnum > oldnum ) {
196 // the old entity isn't present in the new message
197 MSG_WriteDeltaPlayerstate_Packet( oldps, NULL, flags | MSG_PS_FORCE );
198 oldindex++;
199 continue;
200 }
201 }
202
203 MSG_WriteByte( CLIENTNUM_NONE ); // end of packetentities
204 }
205
206 static deltaFrame_t *currentFrame;
207
208 /*
209 ================
210 SV_DeltaBeginFrame
211 ================
212 */
SV_DeltaBeginFrame(deltaFrame_t * frame)213 void SV_DeltaBeginFrame( deltaFrame_t *frame ) {
214 currentFrame = frame;
215
216 frame->numEntities = 0;
217 frame->firstEntity = svs.nextEntityStates;
218
219 frame->numPlayers = 0;
220 frame->firstPlayer = svs.nextPlayerStates;
221
222 }
223
224 /*
225 ================
226 Delta_AllocEntity
227 ================
228 */
SV_DeltaAllocEntity(void)229 entity_state_t *SV_DeltaAllocEntity( void ) {
230 entity_state_t *es;
231
232 es = &svs.entityStates[svs.nextEntityStates % svs.numEntityStates];
233
234 svs.nextEntityStates++;
235 currentFrame->numEntities++;
236
237 return es;
238 }
239
240 /*
241 ================
242 Delta_AllocPlayer
243 ================
244 */
SV_DeltaAllocPlayer(void)245 playerStateEx_t *SV_DeltaAllocPlayer( void ) {
246 playerStateEx_t *ps;
247
248 ps = &svs.playerStates[svs.nextPlayerStates % svs.numPlayerStates];
249
250 svs.nextPlayerStates++;
251 currentFrame->numPlayers++;
252
253 return ps;
254 }
255
256 /*
257 ==================
258 SV_WriteFrameToClient_Default
259 ==================
260 */
SV_WriteFrameToClient_Default(client_t * client)261 void SV_WriteFrameToClient_Default( client_t *client ) {
262 client_frame_t *frame, *oldframe;
263 player_state_t *oldstate;
264 int lastframe;
265
266 // this is the frame we are creating
267 frame = &client->frames[sv.framenum & UPDATE_MASK];
268 client->frame_latency[sv.framenum & LATENCY_MASK] = -1;
269
270 if( client->lastframe <= 0 ) {
271 // client is asking for a retransmit
272 oldframe = NULL;
273 lastframe = -1;
274 } else if( sv.framenum - client->lastframe > UPDATE_BACKUP - 1 ) {
275 // client hasn't gotten a good message through in a long time
276 Com_DPrintf( "%s: delta request from out-of-date packet.\n",
277 client->name );
278 oldframe = NULL;
279 lastframe = -1;
280 } else {
281 // we have a valid message to delta from
282 oldframe = &client->frames[client->lastframe & UPDATE_MASK];
283 lastframe = client->lastframe;
284
285 if( svs.nextEntityStates -
286 oldframe->delta.firstEntity > svs.numEntityStates )
287 {
288 Com_DPrintf( "%s: delta request from out-of-date entities.\n",
289 client->name );
290 oldframe = NULL;
291 lastframe = -1;
292 }
293 }
294
295 MSG_WriteByte( svc_frame );
296 MSG_WriteLong( sv.framenum );
297 MSG_WriteLong( lastframe ); // what we are delta'ing from
298 MSG_WriteByte( client->surpressCount ); // rate dropped packets
299 client->surpressCount = 0;
300
301 // send over the areabits
302 MSG_WriteByte( frame->areabytes );
303 MSG_WriteData( frame->areabits, frame->areabytes );
304
305 // delta encode the playerstate
306 MSG_WriteByte( svc_playerinfo );
307 if( oldframe ) {
308 oldstate = &oldframe->ps.ps;
309 } else {
310 oldstate = NULL;
311 }
312 MSG_WriteDeltaPlayerstate_Default( oldstate, &frame->ps.ps );
313
314 // delta encode the entities
315 MSG_WriteByte( svc_packetentities );
316 SV_EmitPacketEntities( ( deltaFrame_t * )oldframe, ( deltaFrame_t * )frame,
317 CLIENTNUM_NONE, client->baselines );
318 }
319
320 /*
321 ==================
322 SV_WriteFrameToClient_Enhanced
323 ==================
324 */
SV_WriteFrameToClient_Enhanced(client_t * client)325 void SV_WriteFrameToClient_Enhanced( client_t *client ) {
326 client_frame_t *frame, *oldframe;
327 uint32 extraflags;
328 int delta;
329 byte *b1, *b2;
330 msgPsFlags_t psFlags;
331 int clientNum;
332
333 // this is the frame we are creating
334 frame = &client->frames[sv.framenum & UPDATE_MASK];
335 client->frame_latency[sv.framenum & LATENCY_MASK] = -1;
336
337 if( client->lastframe <= 0 ) {
338 // client is asking for a retransmit
339 oldframe = NULL;
340 delta = 31;
341 } else if( sv.framenum - client->lastframe > UPDATE_BACKUP - 1 ) {
342 // client hasn't gotten a good message through in a long time
343 Com_DPrintf( "%s: delta request from out-of-date packet.\n",
344 client->name );
345 oldframe = NULL;
346 delta = 31;
347 } else {
348 // we have a valid message to delta from
349 oldframe = &client->frames[client->lastframe & UPDATE_MASK];
350 delta = sv.framenum - client->lastframe;
351
352 if( svs.nextEntityStates -
353 oldframe->delta.firstEntity > svs.numEntityStates )
354 {
355 Com_DPrintf( "%s: delta request from out-of-date entities.\n",
356 client->name );
357 oldframe = NULL;
358 delta = 31;
359 }
360 }
361
362 /* first byte to be patched */
363 b1 = SZ_GetSpace( &msg_write, 1 );
364
365 MSG_WriteLong( ( sv.framenum & FRAMENUM_MASK ) |
366 ( delta << FRAMENUM_BITS ) );
367
368 /* second byte to be patched */
369 b2 = SZ_GetSpace( &msg_write, 1 );
370
371 /* send over the areabits */
372 MSG_WriteByte( frame->areabytes );
373 MSG_WriteData( frame->areabits, frame->areabytes );
374
375 /* ignore some parts of playerstate if not recording demo */
376 psFlags = 0;
377 if( !client->settings[CLS_RECORDING] ) {
378 if( client->settings[CLS_NOGUN] ) {
379 psFlags |= MSG_PS_IGNORE_GUNFRAMES;
380 if( client->settings[CLS_NOGUN] != 2 ) {
381 psFlags |= MSG_PS_IGNORE_GUNINDEX;
382 }
383 }
384 if( client->settings[CLS_NOBLEND] ) {
385 psFlags |= MSG_PS_IGNORE_BLEND;
386 }
387 if( frame->ps.ps.pmove.pm_type < PM_DEAD ) {
388 if( !( frame->ps.ps.pmove.pm_flags & PMF_NO_PREDICTION ) ) {
389 psFlags |= MSG_PS_IGNORE_VIEWANGLES;
390 }
391 } else {
392 /* lying dead on a rotating platform? */
393 psFlags |= MSG_PS_IGNORE_DELTAANGLES;
394 }
395 }
396
397 if( client->protocol == PROTOCOL_VERSION_Q2PRO ) {
398 if( client->settings[CLS_NOPREDICT] ) {
399 psFlags |= MSG_PS_IGNORE_PREDICTION;
400 }
401 psFlags |= MSG_PS_WRITE_CLIENTNUM;
402 }
403
404 /* delta encode the playerstate */
405 extraflags = MSG_WriteDeltaPlayerstate_Enhanced(
406 oldframe ? &oldframe->ps : NULL, &frame->ps, psFlags );
407
408 /* save 3 high bits of extraflags */
409 *b1 = svc_frame | ( ( ( extraflags & 0x70 ) << 1 ) );
410
411 /* save 4 low bits of extraflags */
412 *b2 = ( client->surpressCount & SURPRESSCOUNT_MASK ) |
413 ( ( extraflags & 0x0F ) << SURPRESSCOUNT_BITS );
414
415 client->surpressCount = 0;
416
417 /* delta encode the entities */
418 clientNum = CLIENTNUM_NONE;
419 if( client->protocol == PROTOCOL_VERSION_Q2PRO &&
420 frame->ps.ps.pmove.pm_type < PM_DEAD )
421 {
422 clientNum = frame->ps.clientNum;
423 }
424 SV_EmitPacketEntities( ( deltaFrame_t * )oldframe, ( deltaFrame_t * )frame,
425 clientNum, client->baselines );
426 }
427
428 /*
429 ==================
430 SV_WriteFrameToClient_Mvd
431 ==================
432 */
SV_WriteFrameToClient_Mvd(client_t * client)433 void SV_WriteFrameToClient_Mvd( client_t *client ) {
434 client_frame_t *frame, *oldframe;
435 int delta;
436 msgPsFlags_t flags;
437
438 // this is the frame we are creating
439 frame = &client->frames[sv.framenum & UPDATE_MASK];
440 client->frame_latency[sv.framenum & LATENCY_MASK] = -1;
441
442 if( client->lastframe <= 0 ) {
443 // client is asking for a retransmit
444 oldframe = NULL;
445 delta = 31;
446 } else if( sv.framenum - client->lastframe > UPDATE_BACKUP - 1 ) {
447 // client hasn't gotten a good message through in a long time
448 Com_DPrintf( "%s: delta request from out-of-date packet.\n",
449 client->name );
450 oldframe = NULL;
451 delta = 31;
452 } else {
453 // we have a valid message to delta from
454 oldframe = &client->frames[client->lastframe & UPDATE_MASK];
455 delta = sv.framenum - client->lastframe;
456
457 if( svs.nextEntityStates -
458 oldframe->delta.firstEntity > svs.numEntityStates )
459 {
460 Com_DPrintf( "%s: delta request from out-of-date entities.\n",
461 client->name );
462 oldframe = NULL;
463 delta = 31;
464 } else if( svs.nextPlayerStates -
465 oldframe->delta.firstPlayer > svs.numPlayerStates )
466 {
467 Com_DPrintf( "%s: delta request from out-of-date players.\n",
468 client->name );
469 oldframe = NULL;
470 delta = 31;
471 }
472 }
473
474 MSG_WriteByte( svc_frame );
475 MSG_WriteLong( ( sv.framenum & FRAMENUM_MASK ) |
476 ( delta << FRAMENUM_BITS ) );
477
478 /* send over the portalbits */
479 MSG_WriteByte( frame->areabytes );
480 MSG_WriteData( frame->areabits, frame->areabytes );
481
482 flags = MSG_PS_IGNORE_PREDICTION|MSG_PS_IGNORE_DELTAANGLES;
483 if( mvd_noblend->integer ) {
484 flags |= MSG_PS_IGNORE_BLEND;
485 }
486 if( mvd_nogun->integer ) {
487 flags |= MSG_PS_IGNORE_GUNINDEX|MSG_PS_IGNORE_GUNFRAMES;
488 }
489 SV_EmitPacketPlayers( ( deltaFrame_t * )oldframe, ( deltaFrame_t * )frame,
490 flags );
491 SV_EmitPacketEntities( ( deltaFrame_t * )oldframe, ( deltaFrame_t * )frame,
492 CLIENTNUM_ANY, client->baselines );
493
494 client->surpressCount = 0;
495
496 }
497
498 /*
499 =============================================================================
500
501 Build a client frame structure
502
503 =============================================================================
504 */
505
SV_BuildMvdFrame(client_t * client)506 void SV_BuildMvdFrame( client_t *client ) {
507 client_frame_t *frame;
508 edict_t *ent;
509 entity_state_t *es;
510 playerStateEx_t *ps;
511 int i;
512
513 // this is the frame we are creating
514 frame = &client->frames[sv.framenum & UPDATE_MASK];
515 frame->senttime = svs.realtime; // save it for ping calc later
516
517 // store portalbits
518 frame->areabytes = CM_WritePortalBits( &sv.cm, frame->areabits );
519
520 // build up the list of visible entities
521 SV_DeltaBeginFrame( ( deltaFrame_t * )frame );
522
523 for( i = 1; i < ge->num_edicts; i++ ) {
524 ent = EDICT_NUM( i );
525
526 if( !( ent->svflags & SVF_NOCLIENT ) &&
527 ( ent->s.modelindex || ent->s.effects || ent->s.sound || ent->s.event ) )
528 {
529 es = SV_DeltaAllocEntity();
530 *es = ent->s;
531 es->number = i;
532 }
533 }
534
535 for( i = 0 ; i < sv_maxclients->integer; i++ ) {
536 if( MVD_PlayerIsActive( i ) ) {
537 ps = SV_DeltaAllocPlayer();
538
539 ent = EDICT_NUM( i + 1 );
540 ps->ps = ent->client->ps;
541 ps->number = i;
542 ps->clientNum = i;
543 }
544 }
545 }
546
SV_BuildProxyMvdFrame(client_t * client)547 void SV_BuildProxyMvdFrame( client_t *client ) {
548 int i, j;
549 mvdFrame_t *mvdframe;
550 client_frame_t *frame;
551 entity_state_t *es;
552 playerStateEx_t *ps;
553
554 mvdframe = &mvd.frames[mvd.validPacketNum % mvd.frameBackup];
555
556 // this is the frame we are creating
557 frame = &client->frames[sv.framenum & UPDATE_MASK];
558 frame->senttime = svs.realtime; // save it for ping calc later
559
560 // copy portalbits
561 frame->areabytes = mvdframe->numPortalBytes;
562 memcpy( frame->areabits, mvdframe->portalbytes, mvdframe->numPortalBytes );
563
564 SV_DeltaBeginFrame( ( deltaFrame_t * )frame );
565
566 for( i = 0; i < mvdframe->numEntityStates; i++ ) {
567 j = ( mvdframe->firstEntityState + i ) % mvd.maxEntityStates;
568 es = SV_DeltaAllocEntity();
569 *es = mvd.entityStates[j].s;
570 }
571
572 for( i = 0; i < mvdframe->numPlayerStates; i++ ) {
573 j = ( mvdframe->firstPlayerState + i ) % mvd.maxPlayerStates;
574 ps = SV_DeltaAllocPlayer();
575 *ps = mvd.playerStates[j];
576 }
577 }
578
579 #define BODY_QUEUE_SIZE 8
580
581 /*
582 =============
583 SV_BuildClientFrame
584
585 Decides which entities are going to be visible to the client, and
586 copies off the playerstat and areabits.
587 =============
588 */
SV_BuildClientFrame(client_t * client)589 void SV_BuildClientFrame( client_t *client ) {
590 int e, i;
591 vec3_t org;
592 edict_t *ent;
593 edict_t *clent;
594 client_frame_t *frame;
595 entity_state_t *state;
596 player_state_t *ps;
597 int l;
598 int clientarea, clientcluster;
599 cleaf_t *leaf;
600 byte *clientphs;
601 byte *clientpvs;
602
603 clent = client->edict;
604 if( !clent->client )
605 return; // not in game yet
606
607 // this is the frame we are creating
608 frame = &client->frames[sv.framenum & UPDATE_MASK];
609
610 frame->senttime = svs.realtime; // save it for ping calc later
611
612 // find the client's PVS
613 ps = &clent->client->ps;
614 VectorMA( ps->viewoffset, 0.125f, ps->pmove.origin, org );
615
616 leaf = CM_PointLeaf( &sv.cm, org );
617 clientarea = CM_LeafArea( leaf );
618 clientcluster = CM_LeafCluster( leaf );
619
620 // calculate the visible areas
621 frame->areabytes = CM_WriteAreaBits( &sv.cm, frame->areabits, clientarea );
622
623 // grab the current player_state_t
624 frame->ps.ps = *ps;
625 frame->ps.number = client->clientNum;
626 frame->ps.clientNum = client->clientNum;
627
628 clientpvs = CM_FatPVS( &sv.cm, org );
629 clientphs = CM_ClusterPHS( &sv.cm, clientcluster );
630
631 // build up the list of visible entities
632 SV_DeltaBeginFrame( ( deltaFrame_t * )frame );
633
634 for( e = 1; e < ge->num_edicts; e++ ) {
635 ent = EDICT_NUM( e );
636
637 // ignore ents without visible models
638 if( ent->svflags & SVF_NOCLIENT )
639 continue;
640
641 // ignore ents without visible models unless they have an effect
642 if( !ent->s.modelindex && !ent->s.effects && !ent->s.sound ) {
643 if( !ent->s.event ) {
644 continue;
645 }
646 if( ent->s.event == EV_FOOTSTEP && client->settings[CLS_NOFOOTSTEPS] ) {
647 continue;
648 }
649 }
650
651 if( ( ent->s.effects & EF_GIB ) && client->settings[CLS_NOGIBS] ) {
652 continue;
653 }
654
655 // ignore if not touching a PV leaf
656 if( ent != clent ) {
657 // check area
658 if( !CM_AreasConnected( &sv.cm, clientarea, ent->areanum ) ) {
659 // doors can legally straddle two areas, so
660 // we may need to check another one
661 if( !ent->areanum2 || !CM_AreasConnected( &sv.cm, clientarea, ent->areanum2 ) )
662 continue; // blocked by a door
663 }
664
665 // beams just check one point for PHS
666 if( ent->s.renderfx & RF_BEAM ) {
667 l = ent->clusternums[0];
668 if( !Q_IsBitSet( clientphs, l ) )
669 continue;
670 } else {
671 if( ent->num_clusters == -1 ) {
672 // too many leafs for individual check, go by headnode
673 if( !CM_HeadnodeVisible( CM_NodeNum( &sv.cm, ent->headnode ), clientpvs ) )
674 continue;
675 } else {
676 // check individual leafs
677 for( i = 0; i < ent->num_clusters; i++ ) {
678 l = ent->clusternums[i];
679 if( Q_IsBitSet( clientpvs, l ) )
680 break;
681 }
682 if( i == ent->num_clusters )
683 continue; // not visible
684 }
685
686 if( !ent->s.modelindex ) {
687 // don't send sounds if they will be attenuated away
688 vec3_t delta;
689 float len;
690
691 VectorSubtract( org, ent->s.origin, delta );
692 len = VectorLength( delta );
693 if( len > 400 )
694 continue;
695 }
696 }
697 }
698
699 if( ent->s.number != e ) {
700 Com_DPrintf( "FIXING ENT->S.NUMBER!!!\n" );
701 ent->s.number = e;
702 }
703
704 // add it to the circular client_entities array
705 state = SV_DeltaAllocEntity();
706 *state = ent->s;
707 if( ent->s.event == EV_FOOTSTEP && client->settings[CLS_NOFOOTSTEPS] ) {
708 state->event = 0;
709 }
710
711 if( sv_bodyque_hack->integer ) {
712 if( state->number >= svs.maxGameClients + 1 &&
713 state->number <= svs.maxGameClients + BODY_QUEUE_SIZE )
714 {
715 state->event = EV_OTHER_TELEPORT;
716 }
717 }
718
719 #if 0
720 if( sv.state == ss_broadcast &&
721 client->protocol != PROTOCOL_VERSION_Q2PRO &&
722 e == frame->ps.clientNum + 1 )
723 {
724 /* clear the modelindex for the player entity this
725 * client is following.
726 * FIXME: this way EF_FLAG effects are lost, etc */
727 state->modelindex = 0;
728 }
729 #endif
730
731 // don't mark players missiles as solid
732 if( ent->owner == client->edict )
733 state->solid = 0;
734
735 if( frame->delta.numEntities == MAX_PACKET_ENTITIES ) {
736 break;
737 }
738 }
739 }
740
741 /*
742 =============
743 SV_BuildProxyClientFrame
744
745 =============
746 */
SV_BuildProxyClientFrame(client_t * client)747 void SV_BuildProxyClientFrame( client_t *client ) {
748 int i, j, k, l;
749 vec3_t org;
750 mvdClient_t *mvdcl;
751 mvdFrame_t *mvdframe;
752 mvdGamestate_t *gs;
753 client_frame_t *frame;
754 entity_state_t *state;
755 entityStateEx_t *ent;
756 player_state_t *ps;
757 int clientarea, clientcluster;
758 cleaf_t *leaf;
759 byte *clientphs;
760 byte *clientpvs;
761
762 mvdcl = ( mvdClient_t * )client->edict->client;
763 if( !mvdcl )
764 return; // not in game yet
765
766 if( mvdcl->admin ) {
767 mvdframe = &mvd.frames[mvd.validPacketNum % mvd.frameBackup];
768 gs = &mvd.gamestates[mvd.gamestateSequence & GAMESTATE_MASK];
769 } else {
770 mvdframe = &mvd.frames[mvd.activePacketNum % mvd.frameBackup];
771 gs = &mvd.gamestates[mvd.activeGamestateSequence & GAMESTATE_MASK];
772 }
773
774 if( !( mvdframe->flags & MFF_ACTIVE ) ) {
775 SV_DropClient( client, "SV_BuildProxyClientFrame: inactive frame" );
776 return;
777 }
778
779 if( !( mvdframe->flags & MFF_VALID ) ) {
780 SV_DropClient( client, "SV_BuildProxyClientFrame: invalid frame" );
781 return;
782 }
783
784 // this is the frame we are creating
785 frame = &client->frames[sv.framenum & UPDATE_MASK];
786
787 frame->senttime = svs.realtime; // save it for ping calc later
788
789 // find the client's PVS
790 ps = &mvdcl->ps;
791 VectorMA( ps->viewoffset, 0.125f, ps->pmove.origin, org );
792
793 leaf = CM_PointLeaf( &gs->cm, org );
794 clientarea = CM_LeafArea( leaf );
795 clientcluster = CM_LeafCluster( leaf );
796
797 // copy areabits
798 if( mvd.serverProtocol == PROTOCOL_VERSION_MVD ) {
799 if( mvdcl->admin ) {
800 frame->areabytes = 0;
801 } else {
802 frame->areabytes = CM_WriteAreaBits( &gs->cm, frame->areabits, clientarea );
803 }
804 } else {
805 frame->areabytes = mvdframe->numPortalBytes;
806 memcpy( frame->areabits, mvdframe->portalbytes, mvdframe->numPortalBytes );
807 }
808
809 // grab the current player_state_t
810 frame->ps.ps = *ps;
811 frame->ps.number = client->clientNum;
812 frame->ps.clientNum = mvdcl->clientNum;
813
814 clientpvs = CM_FatPVS( &gs->cm, org );
815 clientphs = CM_ClusterPHS( &gs->cm, clientcluster );
816
817 // build up the list of visible entities
818 SV_DeltaBeginFrame( ( deltaFrame_t * )frame );
819
820 for( i = 0; i < mvdframe->numEntityStates; i++ ) {
821 j = ( mvdframe->firstEntityState + i ) % mvd.maxEntityStates;
822 ent = &mvd.entityStates[j];
823
824 // ignore ents without visible models unless they have an effect
825 if( !ent->s.modelindex && !ent->s.effects && !ent->s.sound ) {
826 if( !ent->s.event ) {
827 continue;
828 }
829 if( ent->s.event == EV_FOOTSTEP && client->settings[CLS_NOFOOTSTEPS] )
830 {
831 continue;
832 }
833 }
834
835 if( ( ent->s.effects & EF_GIB ) && client->settings[CLS_NOGIBS] ) {
836 continue;
837 }
838
839 // ignore if not touching a PV leaf
840 if( ent->linked ) {
841 // check area
842 if( !mvdcl->admin && !CM_AreasConnected( &gs->cm, clientarea, ent->areanum ) ) {
843 // doors can legally straddle two areas, so
844 // we may need to check another one
845 if( !ent->areanum2 || !CM_AreasConnected( &gs->cm, clientarea, ent->areanum2 ) ) {
846 continue; // blocked by a door
847 }
848 }
849
850 // beams just check one point for PHS
851 if( ent->s.renderfx & RF_BEAM ) {
852 l = ent->clusternums[0];
853 if( !Q_IsBitSet( clientphs, l ) ) {
854 continue;
855 }
856 } else {
857 if( ent->num_clusters == -1 ) {
858 // too many leafs for individual check, go by headnode
859 if( !CM_HeadnodeVisible( ent->headnode, clientpvs ) ) {
860 continue;
861 }
862 } else {
863 // check individual leafs
864 for( k = 0; k < ent->num_clusters; k++ ) {
865 l = ent->clusternums[k];
866 if( Q_IsBitSet( clientpvs, l ) ) {
867 break;
868 }
869 }
870 if( k == ent->num_clusters ) {
871 continue; // not visible
872 }
873 }
874
875 if( !ent->s.modelindex ) {
876 // don't send sounds if they will be attenuated away
877 vec3_t delta;
878 float len;
879
880 VectorSubtract( org, ent->s.origin, delta );
881 len = VectorLength( delta );
882 if( len > 400 ) {
883 continue;
884 }
885 }
886 }
887 }
888
889 // add it to the circular client_entities array
890 state = SV_DeltaAllocEntity();
891 *state = ent->s;
892 if( mvdframe->serverPacketNum == mvdcl->lastServerPacket ) {
893 state->event = 0;
894 if( !( state->renderfx & RF_BEAM ) ) {
895 VectorCopy( state->origin, state->old_origin );
896 }
897 } else {
898 if( state->event == EV_FOOTSTEP &&
899 client->settings[CLS_NOFOOTSTEPS] )
900 {
901 state->event = 0;
902 }
903
904 if( sv_bodyque_hack->integer ) {
905 if( state->number >= svs.maxGameClients + 1 &&
906 state->number <= svs.maxGameClients + BODY_QUEUE_SIZE )
907 {
908 state->event = EV_OTHER_TELEPORT;
909 }
910 }
911 }
912
913 if( client->protocol != PROTOCOL_VERSION_Q2PRO &&
914 state->number == frame->ps.clientNum + 1 )
915 {
916 /* clear the modelindex for the player entity this
917 * client is following.
918 * FIXME: this way EF_FLAG effects are lost, etc */
919 state->modelindex = 0;
920 }
921
922 }
923
924 mvdcl->lastServerPacket = mvdframe->serverPacketNum;
925
926 }
927
928
929