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