示例#1
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint(vec3_t origin, clientSnapshot_t *frame, snapshotEntityNumbers_t *eNums)
{
    int e, i;
    sharedEntity_t *ent;
    svEntity_t *svEnt;
    int l;
    int clientarea, clientcluster;
    int leafnum;
    byte *clientpvs;
    byte *bitvector;

    // during an error shutdown message we may need to transmit
    // the shutdown message after the server has shutdown, so
    // specfically check for it
    if (!sv.state)
    {
        return;
    }

    leafnum = CM_PointLeafnum(origin);
    clientarea = CM_LeafArea(leafnum);
    clientcluster = CM_LeafCluster(leafnum);

    // calculate the visible areas
    frame->areabytes = CM_WriteAreaBits(frame->areabits, clientarea);

    clientpvs = CM_ClusterPVS(clientcluster);

    for (e = 0; e < sv.num_entities; e++)
    {
        ent = SV_GentityNum(e);

        // never send entities that aren't linked in
        if (!ent->r.linked)
        {
            continue;
        }

        if (ent->s.number != e)
        {
            Com_DPrintf("FIXING ENT->S.NUMBER!!!\n");
            ent->s.number = e;
        }

        // entities can be flagged to explicitly not be sent to the client
        if (ent->r.svFlags & SVF_NOCLIENT)
        {
            continue;
        }

        // entities can be flagged to be sent to only one client
        if (ent->r.svFlags & SVF_SINGLECLIENT)
        {
            if (ent->r.singleClient != frame->ps.clientNum)
            {
                continue;
            }
        }
        // entities can be flagged to be sent to everyone but one client
        if (ent->r.svFlags & SVF_NOTSINGLECLIENT)
        {
            if (ent->r.singleClient == frame->ps.clientNum)
            {
                continue;
            }
        }
        // entities can be flagged to be sent to a given mask of clients
        if (ent->r.svFlags & SVF_CLIENTMASK)
        {
            if (frame->ps.clientNum >= 32)
            {
                if (~ent->r.hack.generic1 & (1 << (frame->ps.clientNum - 32))) continue;
            }
            else
            {
                if (~ent->r.singleClient & (1 << frame->ps.clientNum)) continue;
            }
        }

        svEnt = SV_SvEntityForGentity(ent);

        // don't double add an entity through portals
        if (svEnt->snapshotCounter == sv.snapshotCounter)
        {
            continue;
        }

        // broadcast entities are always sent
        if (ent->r.svFlags & SVF_BROADCAST)
        {
            SV_AddEntToSnapshot(svEnt, ent, eNums);
            continue;
        }

        // ignore if not touching a PV leaf
        // check area
        if (!CM_AreasConnected(clientarea, svEnt->areanum))
        {
            // doors can legally straddle two areas, so
            // we may need to check another one
            if (!CM_AreasConnected(clientarea, svEnt->areanum2))
            {
                continue;  // blocked by a door
            }
        }

        bitvector = clientpvs;

        // check individual leafs
        if (!svEnt->numClusters)
        {
            continue;
        }
        l = 0;
        for (i = 0; i < svEnt->numClusters; i++)
        {
            l = svEnt->clusternums[i];
            if (bitvector[l >> 3] & (1 << (l & 7)))
            {
                break;
            }
        }

        // if we haven't found it to be visible,
        // check overflow clusters that coudln't be stored
        if (i == svEnt->numClusters)
        {
            if (svEnt->lastCluster)
            {
                for (; l <= svEnt->lastCluster; l++)
                {
                    if (bitvector[l >> 3] & (1 << (l & 7)))
                    {
                        break;
                    }
                }
                if (l == svEnt->lastCluster)
                {
                    continue;  // not visible
                }
            }
            else
            {
                continue;
            }
        }

        // add it
        SV_AddEntToSnapshot(svEnt, ent, eNums);

        // if it's a portal entity, add everything visible from its camera position
        if (ent->r.svFlags & SVF_PORTAL)
        {
            if (ent->s.generic1)
            {
                vec3_t dir;
                VectorSubtract(ent->r.currentOrigin, origin, dir);
                if (VectorLengthSquared(dir) > (float)ent->s.generic1 * ent->s.generic1)
                {
                    continue;
                }
            }
            SV_AddEntitiesVisibleFromPoint(ent->s.origin2, frame, eNums);
        }
    }
示例#2
0
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame, 
									snapshotEntityNumbers_t *eNums, qboolean portal ) {
	int		e, i;
	sharedEntity_t *ent;
	svEntity_t	*svEnt;
	int		l;
	int		clientarea, clientcluster;
	int		leafnum;
	byte	*clientpvs;
	byte	*bitvector;
	vec3_t	difference;
	float	length, radius;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state ) {
		return;
	}

	leafnum = CM_PointLeafnum (origin);
	clientarea = CM_LeafArea (leafnum);
	clientcluster = CM_LeafCluster (leafnum);

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

	clientpvs = CM_ClusterPVS (clientcluster);

	for ( e = 0 ; e < sv.num_entities ; e++ ) {
		ent = SV_GentityNum(e);

		// never send entities that aren't linked in
		if ( !ent->r.linked ) {
			continue;
		}

		if (ent->s.eFlags & EF_PERMANENT)
		{	// he's permanent, so don't send him down!
			continue;
		}

		if (ent->s.number != e) {
			Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
			ent->s.number = e;
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->r.svFlags & SVF_NOCLIENT ) {
			continue;
		}

		// entities can be flagged to be sent to only one client
		if ( ent->r.svFlags & SVF_SINGLECLIENT ) {
			if ( ent->r.singleClient != frame->ps.clientNum ) {
				continue;
			}
		}
		// entities can be flagged to be sent to everyone but one client
		if ( ent->r.svFlags & SVF_NOTSINGLECLIENT ) {
			if ( ent->r.singleClient == frame->ps.clientNum ) {
				continue;
			}
		}

		svEnt = SV_SvEntityForGentity( ent );

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
			continue;
		}

		// broadcast entities are always sent, and so is the main player so we don't see noclip weirdness
		if ( ent->r.svFlags & SVF_BROADCAST || (e == frame->ps.clientNum) || (ent->r.broadcastClients[frame->ps.clientNum/32] & (1<<(frame->ps.clientNum%32))))
		{
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		if (ent->s.isPortalEnt)
		{ //rww - portal entities are always sent as well
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		if (com_RMG && com_RMG->integer)
		{
			VectorAdd(ent->r.absmax, ent->r.absmin, difference);
			VectorScale(difference, 0.5f, difference);
			VectorSubtract(origin, difference, difference);
			length = VectorLength(difference);

			// calculate the diameter
			VectorSubtract(ent->r.absmax, ent->r.absmin, difference);
			radius = VectorLength(difference);
			if (length-radius < /*sv_RMGDistanceCull->integer*/5000.0f)
			{	// more of a diameter check
				SV_AddEntToSnapshot( svEnt, ent, eNums );
			}
		}
		else
		{
			// ignore if not touching a PV leaf
			// check area
			if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
				// doors can legally straddle two areas, so
				// we may need to check another one
				if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
					continue;		// blocked by a door
				}
			}

			bitvector = clientpvs;

			// check individual leafs
			if ( !svEnt->numClusters ) {
				continue;
			}
			l = 0;
			for ( i=0 ; i < svEnt->numClusters ; i++ ) {
				l = svEnt->clusternums[i];
				if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
					break;
				}
			}

			// if we haven't found it to be visible,
			// check overflow clusters that coudln't be stored
			if ( i == svEnt->numClusters ) {
				if ( svEnt->lastCluster ) {
					for ( ; l <= svEnt->lastCluster ; l++ ) {
						if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
							break;
						}
					}
					if ( l == svEnt->lastCluster ) {
						continue;	// not visible
					}
				} else {
					continue;
				}
			}

			if (g_svCullDist != -1.0f)
			{ //do a distance cull check
				VectorAdd(ent->r.absmax, ent->r.absmin, difference);
				VectorScale(difference, 0.5f, difference);
				VectorSubtract(origin, difference, difference);
				length = VectorLength(difference);

				// calculate the diameter
				VectorSubtract(ent->r.absmax, ent->r.absmin, difference);
				radius = VectorLength(difference);
				if (length-radius >= g_svCullDist)
				{ //then don't add it
					continue;
				}
			}

			// add it
			SV_AddEntToSnapshot( svEnt, ent, eNums );

			// if its a portal entity, add everything visible from its camera position
			if ( ent->r.svFlags & SVF_PORTAL ) {
				if ( ent->s.generic1 ) {
					vec3_t dir;
					VectorSubtract(ent->s.origin, origin, dir);
					if ( VectorLengthSquared(dir) > (float) ent->s.generic1 * ent->s.generic1 ) {
						continue;
					}
				}
				SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
			}
		}
	}
示例#3
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame,
//                                  snapshotEntityNumbers_t *eNums, qboolean portal, clientSnapshot_t *oldframe, qboolean localClient ) {
//                                  snapshotEntityNumbers_t *eNums, qboolean portal ) {
    snapshotEntityNumbers_t *eNums /*, qboolean portal, qboolean localClient */ )
{
	int            e, i;
	sharedEntity_t *ent, *playerEnt;
	svEntity_t     *svEnt;
	int            l;
	int            clientarea, clientcluster;
	int            leafnum;
//	int             c_fullsend;
	byte           *clientpvs;
	byte           *bitvector;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state )
	{
		return;
	}

	leafnum = CM_PointLeafnum( origin );
	clientarea = CM_LeafArea( leafnum );
	clientcluster = CM_LeafCluster( leafnum );

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

	clientpvs = CM_ClusterPVS( clientcluster );

//	c_fullsend = 0;

	playerEnt = SV_GentityNum( frame->ps.clientNum );

	if ( playerEnt->r.svFlags & SVF_SELF_PORTAL )
	{
		SV_AddEntitiesVisibleFromPoint( playerEnt->s.origin2, frame, eNums );
	}

	for ( e = 0; e < sv.num_entities; e++ )
	{
		ent = SV_GentityNum( e );

		// never send entities that aren't linked in
		if ( !ent->r.linked )
		{
			continue;
		}

		if ( ent->s.number != e )
		{
			Com_DPrintf( "FIXING ENT->S.NUMBER!!!\n" );
			ent->s.number = e;
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->r.svFlags & SVF_NOCLIENT )
		{
			continue;
		}

		// entities can be flagged to be sent to only one client
		if ( ent->r.svFlags & SVF_SINGLECLIENT )
		{
			if ( ent->r.singleClient != frame->ps.clientNum )
			{
				continue;
			}
		}

		// entities can be flagged to be sent to everyone but one client
		if ( ent->r.svFlags & SVF_NOTSINGLECLIENT )
		{
			if ( ent->r.singleClient == frame->ps.clientNum )
			{
				continue;
			}
		}

		// entities can be flagged to be sent to only a given mask of clients
		if ( ent->r.svFlags & SVF_CLIENTMASK )
		{
			if ( frame->ps.clientNum >= 32 )
			{
				if ( ~ent->r.hiMask & ( 1 << ( frame->ps.clientNum - 32 ) ) )
				{
					continue;
				}
			}
			else
			{
				if ( ~ent->r.loMask & ( 1 << frame->ps.clientNum ) )
				{
					continue;
				}
			}
		}

		svEnt = SV_SvEntityForGentity( ent );

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter )
		{
			continue;
		}

		// broadcast entities are always sent
		if ( ent->r.svFlags & SVF_BROADCAST )
		{
			SV_AddEntToSnapshot( playerEnt, svEnt, ent, eNums );
			continue;
		}

		// send entity if the client is in range
		if ( (ent->r.svFlags & SVF_CLIENTS_IN_RANGE) &&
		     Distance( ent->s.origin, playerEnt->s.origin ) <= ent->r.clientRadius )
		{
			SV_AddEntToSnapshot( playerEnt, svEnt, ent, eNums );
			continue;
		}

		bitvector = clientpvs;

		// Gordon: just check origin for being in pvs, ignore bmodel extents
		if ( ent->r.svFlags & SVF_IGNOREBMODELEXTENTS )
		{
			if ( bitvector[ ent->r.originCluster >> 3 ] & ( 1 << ( ent->r.originCluster & 7 ) ) )
			{
				SV_AddEntToSnapshot( playerEnt, svEnt, ent, eNums );
			}

			continue;
		}

		// ignore if not touching a PV leaf
		// check area
		if ( !CM_AreasConnected( clientarea, ent->r.areanum ) )
		{
			// doors can legally straddle two areas, so
			// we may need to check another one
			if ( !CM_AreasConnected( clientarea, ent->r.areanum2 ) )
			{
				continue;
			}
		}

		// check individual leafs
		if ( !ent->r.numClusters )
		{
			continue;
		}

		l = 0;

		for ( i = 0; i < ent->r.numClusters; i++ )
		{
			l = ent->r.clusternums[ i ];

			if ( bitvector[ l >> 3 ] & ( 1 << ( l & 7 ) ) )
			{
				break;
			}
		}

		// if we haven't found it to be visible,
		// check the overflow clusters that couldn't be stored
		if ( i == ent->r.numClusters )
		{
			if ( ent->r.lastCluster )
			{
				for ( ; l <= ent->r.lastCluster; l++ )
				{
					if ( bitvector[ l >> 3 ] & ( 1 << ( l & 7 ) ) )
					{
						break;
					}
				}

				if ( l == ent->r.lastCluster )
				{
					continue;
				}
			}
			else
			{
				continue;
			}
		}

		//----(SA) added "visibility dummies"
		if ( ent->r.svFlags & SVF_VISDUMMY )
		{
			sharedEntity_t *ment = 0;

			//find master;
			ment = SV_GentityNum( ent->s.otherEntityNum );

			if ( ment )
			{
				svEntity_t *master = 0;

				master = SV_SvEntityForGentity( ment );

				if ( master->snapshotCounter == sv.snapshotCounter || !ment->r.linked )
				{
					continue;
				}

				SV_AddEntToSnapshot( playerEnt, master, ment, eNums );
			}

			continue; // master needs to be added, but not this dummy ent
		}
		//----(SA) end
		else if ( ent->r.svFlags & SVF_VISDUMMY_MULTIPLE )
		{
			{
				int            h;
				sharedEntity_t *ment = 0;
				svEntity_t     *master = 0;

				for ( h = 0; h < sv.num_entities; h++ )
				{
					ment = SV_GentityNum( h );

					if ( ment == ent )
					{
						continue;
					}

					if ( ment )
					{
						master = SV_SvEntityForGentity( ment );
					}
					else
					{
						continue;
					}

					if ( !( ment->r.linked ) )
					{
						continue;
					}

					if ( ment->s.number != h )
					{
						Com_DPrintf( "FIXING vis dummy multiple ment->S.NUMBER!!!\n" );
						ment->s.number = h;
					}

					if ( ment->r.svFlags & SVF_NOCLIENT )
					{
						continue;
					}

					if ( master->snapshotCounter == sv.snapshotCounter )
					{
						continue;
					}

					if ( ment->s.otherEntityNum == ent->s.number )
					{
						SV_AddEntToSnapshot( playerEnt, master, ment, eNums );
					}
				}

				continue;
			}
		}

		// add it
		SV_AddEntToSnapshot( playerEnt, svEnt, ent, eNums );

		// if it's a portal entity, add everything visible from its camera position
		if ( ent->r.svFlags & SVF_PORTAL )
		{
			if ( ent->s.generic1 )
			{
				vec3_t dir;
				VectorSubtract( ent->s.origin, origin, dir );

				if ( VectorLengthSquared( dir ) > ( float ) ent->s.generic1 * ent->s.generic1 )
				{
					continue;
				}
			}

//          SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue, oldframe, localClient );
			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums /*, qtrue, localClient */ );
		}

		continue;
	}
示例#4
0
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t* frame,
		snapshotEntityNumbers_t* eNums, bool portal, bitSet_c& areaBits )
{
	int     e;//, i;
	edict_s* ent;
	svEntity_t* svEnt;
	//int       l;
	
	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state )
	{
		return;
	}
	
	bspPointDesc_s eyeDesc; // for .bsp PVS
	pvsHandle_t procVisHandle; // for .proc vis
	if ( sv_bsp )
	{
		sv_bsp->filterPoint( origin, eyeDesc );
		sv_bsp->appendCurrentAreaBits( eyeDesc.area, areaBits );
	}
	else if ( sv_procVis )
	{
		procVisHandle = sv_procVis->SetupCurrentPVS( origin );
	}
	
	
	for ( e = 0 ; e < sv.num_entities ; e++ )
	{
		ent = SV_GentityNum( e );
		
		// never send entities that aren't active
		if ( ent->s == 0 )
		{
			continue;
		}
		
		if ( ent->s->number != e )
		{
			Com_DPrintf( "FIXING ENT->S.NUMBER!!!\n" );
			ent->s->number = e;
		}
		
		// never send entities that aren't visible
		if ( ent->s->isHidden() )
		{
			continue;
		}
		
		// never send ai waypoints (pathnodes)
		if ( ent->s->eType == ET_PATHNODE )
		{
			continue;
		}
		
		edict_s* visEnt = ent;
		while ( visEnt->s->parentNum != ENTITYNUM_NONE )
		{
			visEnt = SV_GentityNum( visEnt->s->parentNum );
		}
		if ( visEnt->bspBoxDesc == 0 )
		{
			continue; // not linked
		}
		
		svEnt = SV_SvEntityForGentity( ent );
		
		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter )
		{
			continue;
		}
		
		if ( sv_cullEntities.getInt() )
		{
			if ( sv_bsp && sv_bsp->checkVisibility( eyeDesc, *visEnt->bspBoxDesc ) == false )
			{
				continue; // culled by .bsp PVS
			}
			if ( sv_procVis && sv_procVis->InCurrentPVS( procVisHandle, visEnt->bspBoxDesc->areas.getArray(), visEnt->bspBoxDesc->areas.size() ) == false )
			{
				continue; // culled by Doom3 .proc vis
			}
		}
		
		SV_AddEntToSnapshot( svEnt, ent, eNums );
	}
	if ( sv_procVis )
	{
		sv_procVis->FreeCurrentPVS( procVisHandle );
	}
}
示例#5
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame, 
									snapshotEntityNumbers_t *eNums, qboolean portal ) {
	int		e, i;
	gentity_t	*ent;
	svEntity_t	*svEnt;
	int		l;
	int		clientarea, clientcluster;
	int		leafnum;
	int		c_fullsend;
	byte	*clientpvs;
	byte	*bitvector;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state ) {
		return;
	}

	leafnum = CM_PointLeafnum (origin);
	clientarea = CM_LeafArea (leafnum);
	clientcluster = CM_LeafCluster (leafnum);

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

	clientpvs = CM_ClusterPVS (clientcluster);

	c_fullsend = 0;

	for ( e = 0 ; e < ge->num_entities ; e++ ) {
		ent = SV_GentityNum(e);

		if (!ent->inuse) {
			continue;
		}

		if (ent->s.number != e) {
			Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
			ent->s.number = e;
		}

		// never send entities that aren't linked in
		if ( !ent->linked ) {
			continue;
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->svFlags & SVF_NOCLIENT ) {
			continue;
		}

		svEnt = SV_SvEntityForGentity( ent );

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
			continue;
		}

		// broadcast entities are always sent, and so is the main player so we don't see noclip weirdness
		if ( ent->svFlags & SVF_BROADCAST || !e) {
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		// ignore if not touching a PV leaf
		// check area
		if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
			// doors can legally straddle two areas, so
			// we may need to check another one
			if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
				continue;		// blocked by a door
			}
		}

		bitvector = clientpvs;

		// check individual leafs
		if ( !svEnt->numClusters ) {
			continue;
		}
		l = 0;
		for ( i=0 ; i < svEnt->numClusters ; i++ ) {
			l = svEnt->clusternums[i];
			if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
				break;
			}
		}

		// if we haven't found it to be visible,
		// check overflow clusters that coudln't be stored
		if ( i == svEnt->numClusters ) {
			if ( svEnt->lastCluster ) {
				for ( ; l <= svEnt->lastCluster ; l++ ) {
					if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
						break;
					}
				}
				if ( l == svEnt->lastCluster ) {
					continue;		// not visible
				}
			} else {
				continue;
			}
		}

		// add it
		SV_AddEntToSnapshot( svEnt, ent, eNums );

		// if its a portal entity, add everything visible from its camera position
		if ( ent->svFlags & SVF_PORTAL ) {
			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
		}

	}
示例#6
0
static void SV_AddEntitiesVisibleFromPoint(vec3_t origin, clientSnapshot_t *frame, snapshotEntityNumbers_t *eNums)
#endif
{
	int            e, i;
	sharedEntity_t *ent, *playerEnt, *ment;
#ifdef FEATURE_ANTICHEAT
	sharedEntity_t *client;
#endif
	svEntity_t *svEnt;
	int        l;
	int        clientarea, clientcluster;
	int        leafnum;
	byte       *clientpvs;
	byte       *bitvector;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if (!sv.state)
	{
		return;
	}

	leafnum       = CM_PointLeafnum(origin);
	clientarea    = CM_LeafArea(leafnum);
	clientcluster = CM_LeafCluster(leafnum);

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits(frame->areabits, clientarea);

	clientpvs = CM_ClusterPVS(clientcluster);

	playerEnt = SV_GentityNum(frame->ps.clientNum);
	if (playerEnt->r.svFlags & SVF_SELF_PORTAL)
	{
#ifdef FEATURE_ANTICHEAT
		SV_AddEntitiesVisibleFromPoint(playerEnt->s.origin2, frame, eNums, qtrue); //  portal qtrue?!
#else
		SV_AddEntitiesVisibleFromPoint(playerEnt->s.origin2, frame, eNums);
#endif
	}

	for (e = 0 ; e < sv.num_entities ; e++)
	{
		ent = SV_GentityNum(e);

		// never send entities that aren't linked in
		if (!ent->r.linked)
		{
			continue;
		}

		if (ent->s.number != e)
		{
			Com_DPrintf("FIXING ENT->S.NUMBER!!!\n");
			ent->s.number = e;
		}

		// entities can be flagged to explicitly not be sent to the client
		if (ent->r.svFlags & SVF_NOCLIENT)
		{
			continue;
		}

		// entities can be flagged to be sent to only one client
		if (ent->r.svFlags & SVF_SINGLECLIENT)
		{
			if (ent->r.singleClient != frame->ps.clientNum)
			{
				continue;
			}
		}
		// entities can be flagged to be sent to everyone but one client
		if (ent->r.svFlags & SVF_NOTSINGLECLIENT)
		{
			if (ent->r.singleClient == frame->ps.clientNum)
			{
				continue;
			}
		}

		svEnt = SV_SvEntityForGentity(ent);

		// don't double add an entity through portals
		if (svEnt->snapshotCounter == sv.snapshotCounter)
		{
			continue;
		}

		// broadcast entities are always sent
		if (ent->r.svFlags & SVF_BROADCAST)
		{
			SV_AddEntToSnapshot(playerEnt, svEnt, ent, eNums);
			continue;
		}

		bitvector = clientpvs;

		// just check origin for being in pvs, ignore bmodel extents
		if (ent->r.svFlags & SVF_IGNOREBMODELEXTENTS)
		{
			if (bitvector[svEnt->originCluster >> 3] & (1 << (svEnt->originCluster & 7)))
			{
				SV_AddEntToSnapshot(playerEnt, svEnt, ent, eNums);
			}
			continue;
		}

		// ignore if not touching a PV leaf
		// check area
		if (!CM_AreasConnected(clientarea, svEnt->areanum))
		{
			// doors can legally straddle two areas, so
			// we may need to check another one
			if (!CM_AreasConnected(clientarea, svEnt->areanum2))
			{
				continue;
			}
		}

		// check individual leafs
		if (!svEnt->numClusters)
		{
			continue;
		}
		l = 0;
		for (i = 0 ; i < svEnt->numClusters ; i++)
		{
			l = svEnt->clusternums[i];
			if (bitvector[l >> 3] & (1 << (l & 7)))
			{
				break;
			}
		}

		// if we haven't found it to be visible,
		// check overflow clusters that coudln't be stored
		if (i == svEnt->numClusters)
		{
			if (svEnt->lastCluster)
			{
				for ( ; l <= svEnt->lastCluster ; l++)
				{
					if (bitvector[l >> 3] & (1 << (l & 7)))
					{
						break;
					}
				}
				if (l == svEnt->lastCluster)
				{
					continue; // not visible
				}
			}
			else
			{
				continue;
			}
		}

		// added "visibility dummies"
		if (ent->r.svFlags & SVF_VISDUMMY)
		{
			// find master;
			ment = SV_GentityNum(ent->s.otherEntityNum);

			if (ment)
			{
				svEntity_t *master = 0;
				master = SV_SvEntityForGentity(ment);

				if (master->snapshotCounter == sv.snapshotCounter || !ment->r.linked)
				{
					continue;
				}

				SV_AddEntToSnapshot(playerEnt, master, ment, eNums);
			}
			continue;   // master needs to be added, but not this dummy ent
		}
		else if (ent->r.svFlags & SVF_VISDUMMY_MULTIPLE)
		{
			int            h;
			sharedEntity_t *ment   = 0;
			svEntity_t     *master = 0;

			for (h = 0; h < sv.num_entities; h++)
			{
				ment = SV_GentityNum(h);

				if (ment == ent)
				{
					continue;
				}

				if (ment)
				{
					master = SV_SvEntityForGentity(ment);
				}
				else
				{
					continue;
				}

				if (!(ment->r.linked))
				{
					continue;
				}

				if (ment->s.number != h)
				{
					Com_DPrintf("FIXING vis dummy multiple ment->S.NUMBER!!!\n");
					ment->s.number = h;
				}

				if (ment->r.svFlags & SVF_NOCLIENT)
				{
					continue;
				}

				if (master->snapshotCounter == sv.snapshotCounter)
				{
					continue;
				}

				if (ment->s.otherEntityNum == ent->s.number)
				{
					SV_AddEntToSnapshot(playerEnt, master, ment, eNums);
				}
			}
			continue;
		}

#ifdef FEATURE_ANTICHEAT
		if (sv_wh_active->integer > 0 && e < sv_maxclients->integer)     // client
		{
			// note: !r.linked is already exclused - see above

			if (e == frame->ps.clientNum)
			{
				continue;
			}

			client = SV_GentityNum(frame->ps.clientNum);

			// exclude bots and free flying specs
			if (!portal && !(client->r.svFlags & SVF_BOT) && (frame->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR) && !(frame->ps.pm_flags & PMF_FOLLOW))
			{
				if (!SV_CanSee(frame->ps.clientNum, e))
				{
					SV_RandomizePos(frame->ps.clientNum, e);
					SV_AddEntToSnapshot(client, svEnt, ent, eNums);
					continue;
				}
			}
		}
#endif

		// add it
		SV_AddEntToSnapshot(playerEnt, svEnt, ent, eNums);

		// if its a portal entity, add everything visible from its camera position
		if (ent->r.svFlags & SVF_PORTAL)
		{
#ifdef FEATURE_ANTICHEAT
			SV_AddEntitiesVisibleFromPoint(ent->s.origin2, frame, eNums, qtrue /*localClient*/);
#else
			SV_AddEntitiesVisibleFromPoint(ent->s.origin2, frame, eNums /*, qtrue, localClient*/);
#endif
		}

		continue;
	}
示例#7
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame,
        snapshotEntityNumbers_t *eNums, qboolean portal ) {
    int		e, i;
    sharedEntity_t *ent;
    svEntity_t	*svEnt;
    int		l;
    int		clientarea, clientcluster;
    int		leafnum;
    byte	*clientpvs;
    byte	*bitvector;
    client_t	*cl;
    vec3_t diff;

    // during an error shutdown message we may need to transmit
    // the shutdown message after the server has shutdown, so
    // specfically check for it
    if ( !sv.state ) {
        return;
    }

    leafnum = CM_PointLeafnum (origin);
    clientarea = CM_LeafArea (leafnum);
    clientcluster = CM_LeafCluster (leafnum);

    // calculate the visible areas
    frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

    clientpvs = CM_ClusterPVS (clientcluster);

    for ( e = 0 ; e < sv.num_entities ; e++ ) {
        ent = SV_GentityNum(e);

        // never send entities that aren't linked in
        if ( !ent->r.linked ) {
            continue;
        }

        if (ent->s.number != e) {
            Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
            ent->s.number = e;
        }

        // entities can be flagged to explicitly not be sent to the client
        if ( ent->r.svFlags & SVF_NOCLIENT ) {
            continue;
        }

        // entities can be flagged to be sent to only one client
        if ( ent->r.svFlags & SVF_SINGLECLIENT ) {
            if ( ent->r.singleClient != frame->ps.clientNum ) {
                continue;
            }
        }
        // entities can be flagged to be sent to everyone but one client
        if ( ent->r.svFlags & SVF_NOTSINGLECLIENT ) {
            if ( ent->r.singleClient == frame->ps.clientNum ) {
                continue;
            }
        }
        // entities can be flagged to be sent to a given mask of clients
        if ( ent->r.svFlags & SVF_CLIENTMASK ) {
            if (frame->ps.clientNum >= 32)
                Com_Error( ERR_DROP, "SVF_CLIENTMASK: clientNum >= 32" );
            if (~ent->r.singleClient & (1 << frame->ps.clientNum))
                continue;
        }

        svEnt = SV_SvEntityForGentity( ent );

        // don't double add an entity through portals
        if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
            continue;
        }

        // broadcast entities are always sent
        cl = svs.clients+frame->ps.clientNum;
//		if ( ent->r.svFlags & SVF_BROADCAST ) {
        if ( ent->r.svFlags & SVF_BROADCAST && (ent->s.eType != ET_PLAYER || sv_antiwallhack->integer == 0 || recentlySeen(cl,ent->s.clientNum))) {// broadcast only non-players. Warning: in case sv_antiwallhack equals 1, bots will be disappearing on dm_train when touching doors, unless you compensate with "recentlySeen".
            SV_AddEntToSnapshot( svEnt, ent, eNums );
            continue;
        }

        //if (!(ent->r.svFlags & SVF_BOT)) {// if this entity is not a bot ... (compensation for the broadcast restriction to non-players)
        // ignore if not touching a PV leaf
        // check area
        if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
            // doors can legally straddle two areas, so
            // we may need to check another one
            if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
                continue;		// blocked by a door
            }
        }

        bitvector = clientpvs;

        // check individual leafs
        if ( !svEnt->numClusters ) {
            continue;
        }
        l = 0;
        for ( i=0 ; i < svEnt->numClusters ; i++ ) {
            l = svEnt->clusternums[i];
            if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
                break;
            }
        }

        // if we haven't found it to be visible,
        // check overflow clusters that coudln't be stored
        if ( i == svEnt->numClusters ) {
            if ( svEnt->lastCluster ) {
                for ( ; l <= svEnt->lastCluster ; l++ ) {
                    if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
                        break;
                    }
                }
                if ( l == svEnt->lastCluster ) {
                    continue;	// not visible
                }
            } else {
                continue;
            }
        }

        if (sv_antiwallhack->integer == 1 && (cl->netchan.remoteAddress.type != NA_BOT) && ent->s.eType == ET_PLAYER) {
            if (!SV_IsPlayerVisibleFromPoint(origin,frame,ent,diff)) {
                continue;

            }
        }

        // add it
        SV_AddEntToSnapshot( svEnt, ent, eNums );
        // reset ps.pm_type?

        // if it's a portal entity, add everything visible from its camera position
        if ( ent->r.svFlags & SVF_PORTAL ) {
            if ( ent->s.generic1 ) {
                vec3_t dir;
                VectorSubtract(ent->s.origin, origin, dir);
                if ( VectorLengthSquared(dir) > (float) ent->s.generic1 * ent->s.generic1 ) {
                    continue;
                }
            }
            SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
        }

    }
示例#8
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame,
									snapshotEntityNumbers_t *eNums, qboolean portal ) {
	int		e, i;
	sharedEntity_t *ent;
	svEntity_t	*svEnt;
	int		l;
	int		clientarea, clientcluster;
	int		leafnum;
	int		c_fullsend;
	byte	*clientpvs;
	byte	*bitvector;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state ) {
		return;
	}

	leafnum = CM_PointLeafnum (origin);
	clientarea = CM_LeafArea (leafnum);
	clientcluster = CM_LeafCluster (leafnum);

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

	clientpvs = CM_ClusterPVS (clientcluster);

	c_fullsend = 0;

	for ( e = 0 ; e < sv.num_entities ; e++ ) {
		ent = SV_GentityNum(e);

		// never send entities that aren't linked in
		if ( !ent->r.linked ) {
			continue;
		}

		if (ent->s.number != e) {
			Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
			ent->s.number = e;
		}

		svEnt = SV_SvEntityForGentity( ent );

		if ( sv.gentitiesMV != NULL && sv.gentitySizeMV > 0 )
		{
			mvsharedEntity_t *mvEnt = MV_EntityNum(e);

			if ( VM_MVAPILevel( gvm ) >= 2 ) {
				// MV entities can be flagged to be sent only to
				// spectators or non-spectators
				if ( frame->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR ||
					(frame->ps.pm_flags & PMF_FOLLOW) )
				{
					if ( mvEnt->mvFlags & MVF_NOSPEC )
						continue;
				}
				else
				{
					if ( mvEnt->mvFlags & MVF_SPECONLY )
						continue;
				}
			}

			// MV entities can be flagged to be sent only to specific
			// clients (can't filter following spectators this way)
			if ( mvEnt->snapshotIgnore[frame->ps.clientNum] ) continue;
			else if ( mvEnt->snapshotEnforce[frame->ps.clientNum] )
			{
				SV_AddEntToSnapshot( svEnt, ent, eNums );
				continue;
			}
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->r.svFlags & SVF_NOCLIENT ) {
			continue;
		}

		// entities can be flagged to be sent to only one client
		if ( ent->r.svFlags & SVF_SINGLECLIENT ) {
			if ( ent->r.singleClient != frame->ps.clientNum ) {
				continue;
			}
		}
		// entities can be flagged to be sent to everyone but one client
		if ( ent->r.svFlags & SVF_NOTSINGLECLIENT ) {
			if ( ent->r.singleClient == frame->ps.clientNum ) {
				continue;
			}
		}

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
			continue;
		}

		// broadcast entities are always sent, and so is the main player so we don't see noclip weirdness
		if ( ent->r.svFlags & SVF_BROADCAST || (e == frame->ps.clientNum) || (ent->r.broadcastClients[frame->ps.clientNum/32] & (1<<(frame->ps.clientNum%32))))
		{
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		// ignore if not touching a PV leaf
		// check area
		if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
			// doors can legally straddle two areas, so
			// we may need to check another one
			if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
				continue;		// blocked by a door
			}
		}

		bitvector = clientpvs;

		// check individual leafs
		if ( !svEnt->numClusters ) {
			continue;
		}
		l = 0;
		for ( i=0 ; i < svEnt->numClusters ; i++ ) {
			l = svEnt->clusternums[i];
			if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
				break;
			}
		}

		// if we haven't found it to be visible,
		// check overflow clusters that coudln't be stored
		if ( i == svEnt->numClusters ) {
			if ( svEnt->lastCluster ) {
				for ( ; l <= svEnt->lastCluster ; l++ ) {
					if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
						break;
					}
				}
				if ( l == svEnt->lastCluster ) {
					continue;	// not visible
				}
			} else {
				continue;
			}
		}

		// add it
		SV_AddEntToSnapshot( svEnt, ent, eNums );

		// if its a portal entity, add everything visible from its camera position
		if ( ent->r.svFlags & SVF_PORTAL ) {
			if ( ent->s.generic1 ) {
				vec3_t dir;
				VectorSubtract(ent->s.origin, origin, dir);
				if ( VectorLengthSquared(dir) > (float) ent->s.generic1 * ent->s.generic1 ) {
					continue;
				}
			}
			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
		}

	}
示例#9
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( int psIndex, int clientNum, vec3_t origin, clientSnapshot_t *frame, 
									snapshotEntityNumbers_t *eNums, qboolean portal ) {
	int		e, i;
	sharedEntity_t *ent;
	svEntity_t	*svEnt;
	int		l;
	int		clientarea, clientcluster;
	int		leafnum;
	byte	*clientpvs;
	byte	*bitvector;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state ) {
		return;
	}

	leafnum = CM_PointLeafnum (origin);
	clientarea = CM_LeafArea (leafnum);
	clientcluster = CM_LeafCluster (leafnum);

	// calculate the visible areas
	frame->areabytes[psIndex] = CM_WriteAreaBits( frame->areabits[psIndex], clientarea );

	clientpvs = CM_ClusterPVS (clientcluster);

	for ( e = 0 ; e < sv.num_entities ; e++ ) {
		ent = SV_GentityNum(e);

		// never send entities that aren't linked in
		if ( !ent->r.linked ) {
			continue;
		}

		if (ent->s.number != e) {
			Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
			ent->s.number = e;
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->r.svFlags & SVF_NOCLIENT ) {
			continue;
		}

		// entities can be flagged to be sent to a given mask of clients
		if ( ent->r.svFlags & SVF_CLIENTMASK ) {
			if ( !Com_ClientListContains( &ent->r.sendClients, clientNum ) )
				continue;
		}

		svEnt = SV_SvEntityForGentity( ent );

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
			continue;
		}

		// limit based on distance
		if ( ent->r.cullDistance ) {
			vec3_t dir;
			VectorSubtract(ent->s.origin, origin, dir);
			if ( VectorLengthSquared(dir) > (float) ent->r.cullDistance * ent->r.cullDistance ) {
				continue;
			}
		}

		// broadcast entities are always sent
		if ( ent->r.svFlags & SVF_BROADCAST ) {
			SV_AddEntToSnapshot( frame, svEnt, ent, eNums );
			continue;
		}

		// ignore if not touching a PV leaf
		// check area
		if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
			// doors can legally straddle two areas, so
			// we may need to check another one
			if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
				continue;		// blocked by a door
			}
		}

		bitvector = clientpvs;

		// check individual leafs
		if ( !svEnt->numClusters ) {
			continue;
		}
		l = 0;
		for ( i=0 ; i < svEnt->numClusters ; i++ ) {
			l = svEnt->clusternums[i];
			if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
				break;
			}
		}

		// if we haven't found it to be visible,
		// check overflow clusters that coudln't be stored
		if ( i == svEnt->numClusters ) {
			if ( svEnt->lastCluster ) {
				for ( ; l <= svEnt->lastCluster ; l++ ) {
					if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
						break;
					}
				}
				if ( l == svEnt->lastCluster ) {
					continue;	// not visible
				}
			} else {
				continue;
			}
		}

		// visibility dummies
		if ( ent->r.svFlags & SVF_VISDUMMY ) {
			sharedEntity_t *ment = NULL;

			// find master
			ment = SV_GentityNum( ent->r.visDummyNum );

			if ( ment ) {
				svEntity_t *master = NULL;
				master = SV_SvEntityForGentity( ment );

				if ( master->snapshotCounter == sv.snapshotCounter || !ment->r.linked ) {
					continue;
				}

				SV_AddEntToSnapshot( frame, master, ment, eNums );
			}

			// master needs to be added, but not this dummy ent
			continue;
		} else if ( ent->r.svFlags & SVF_VISDUMMY_MULTIPLE ) {
			int h;
			sharedEntity_t *ment = NULL;
			svEntity_t *master = NULL;

			for ( h = 0; h < sv.num_entities; h++ ) {
				ment = SV_GentityNum( h );

				if ( ment == ent ) {
					continue;
				}

				if ( ment ) {
					master = SV_SvEntityForGentity( ment );
				} else {
					continue;
				}

				if ( !ment->r.linked ) {
					continue;
				}

				if ( ment->s.number != h ) {
					Com_DPrintf( "FIXING vis dummy multiple ment->S.NUMBER!!!\n" );
					ment->s.number = h;
				}

				if ( ment->r.svFlags & SVF_NOCLIENT ) {
					continue;
				}

				if ( master->snapshotCounter == sv.snapshotCounter ) {
					continue;
				}

				if ( ment->r.visDummyNum == ent->s.number ) {
					SV_AddEntToSnapshot( frame, master, ment, eNums );
				}
			}

			// masters need to be added, but not this dummy ent
			continue;
		}

		// add it
		SV_AddEntToSnapshot( frame, svEnt, ent, eNums );

		// if it's a portal entity, add everything visible from its camera position
		if ( ent->r.svFlags & SVF_PORTAL ) {
			if ( ent->r.portalCullDistance ) {
				vec3_t dir;
				VectorSubtract(ent->s.origin, origin, dir);
				if ( VectorLengthSquared(dir) > (float) ent->r.portalCullDistance * ent->r.portalCullDistance ) {
					continue;
				}
			}
			SV_AddEntitiesVisibleFromPoint( psIndex, clientNum, ent->s.origin2, frame, eNums, qtrue );
		}

	}
示例#10
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame,
//									snapshotEntityNumbers_t *eNums, qboolean portal, clientSnapshot_t *oldframe, qboolean localClient ) {
//									snapshotEntityNumbers_t *eNums, qboolean portal ) {
											snapshotEntityNumbers_t *eNums, qboolean portal, qboolean localClient  ) {
	int e, i;
	sharedEntity_t *ent, *playerEnt;
	svEntity_t  *svEnt;
	int l;
	int clientarea, clientcluster;
	int leafnum;
	int c_fullsend;
	byte    *clientpvs;
	byte    *bitvector;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state ) {
		return;
	}

	leafnum = CM_PointLeafnum( origin );
	clientarea = CM_LeafArea( leafnum );
	clientcluster = CM_LeafCluster( leafnum );

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

	clientpvs = CM_ClusterPVS( clientcluster );

	c_fullsend = 0;

	playerEnt = SV_GentityNum( frame->ps.clientNum );

	for ( e = 0 ; e < sv.num_entities ; e++ ) {
		ent = SV_GentityNum( e );

		// never send entities that aren't linked in
		if ( !ent->r.linked ) {
			continue;
		}

		if ( ent->s.number != e ) {
			Com_DPrintf( "FIXING ENT->S.NUMBER!!!\n" );
			ent->s.number = e;
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->r.svFlags & SVF_NOCLIENT ) {
			continue;
		}

		// entities can be flagged to be sent to only one client
		if ( ent->r.svFlags & SVF_SINGLECLIENT ) {
			if ( ent->r.singleClient != frame->ps.clientNum ) {
				continue;
			}
		}
		// entities can be flagged to be sent to everyone but one client
		if ( ent->r.svFlags & SVF_NOTSINGLECLIENT ) {
			if ( ent->r.singleClient == frame->ps.clientNum ) {
				continue;
			}
		}

		svEnt = SV_SvEntityForGentity( ent );

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
			continue;
		}

		// if this client is viewing from a camera, only add ents visible from portal ents
		if ( ( playerEnt->s.eFlags & EF_VIEWING_CAMERA ) && !portal ) {
			if ( ent->r.svFlags & SVF_PORTAL ) {
				SV_AddEntToSnapshot( svEnt, ent, eNums );
//				SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue, oldframe, localClient );
				SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue, localClient );
			}
			continue;
		}

		// broadcast entities are always sent
		if ( ent->r.svFlags & SVF_BROADCAST ) {
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		// ignore if not touching a PV leaf
		// check area
		if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
			// doors can legally straddle two areas, so
			// we may need to check another one
			if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
				goto notVisible;    // blocked by a door
			}
		}

		bitvector = clientpvs;

		// check individual leafs
		if ( !svEnt->numClusters ) {
			goto notVisible;
		}
		l = 0;
		for ( i = 0 ; i < svEnt->numClusters ; i++ ) {
			l = svEnt->clusternums[i];
			if ( bitvector[l >> 3] & ( 1 << ( l & 7 ) ) ) {
				break;
			}
		}

		// if we haven't found it to be visible,
		// check overflow clusters that coudln't be stored
		if ( i == svEnt->numClusters ) {
			if ( svEnt->lastCluster ) {
				for ( ; l <= svEnt->lastCluster ; l++ ) {
					if ( bitvector[l >> 3] & ( 1 << ( l & 7 ) ) ) {
						break;
					}
				}
				if ( l == svEnt->lastCluster ) {
					goto notVisible;    // not visible
				}
			} else {
				goto notVisible;
			}
		}

		//----(SA) added "visibility dummies"
		if ( ent->r.svFlags & SVF_VISDUMMY ) {
			sharedEntity_t *ment = 0;

			//find master;
			ment = SV_GentityNum( ent->s.otherEntityNum );

			if ( ment ) {
				svEntity_t *master = 0;
				master = SV_SvEntityForGentity( ment );

				if ( master->snapshotCounter == sv.snapshotCounter || !ment->r.linked ) {
					goto notVisible;
					//continue;
				}

				SV_AddEntToSnapshot( master, ment, eNums );
			}
			goto notVisible;
			//continue;	// master needs to be added, but not this dummy ent
		}
		//----(SA) end
		else if ( ent->r.svFlags & SVF_VISDUMMY_MULTIPLE ) {
			{
				int h;
				sharedEntity_t *ment = 0;
				svEntity_t *master = 0;

				for ( h = 0; h < sv.num_entities; h++ )
				{
					ment = SV_GentityNum( h );

					if ( ment == ent ) {
						continue;
					}

					if ( ment ) {
						master = SV_SvEntityForGentity( ment );
					} else {
						continue;
					}

					if ( !( ment->r.linked ) ) {
						continue;
					}

					if ( ment->s.number != h ) {
						Com_DPrintf( "FIXING vis dummy multiple ment->S.NUMBER!!!\n" );
						ment->s.number = h;
					}

					if ( ment->r.svFlags & SVF_NOCLIENT ) {
						continue;
					}

					if ( master->snapshotCounter == sv.snapshotCounter ) {
						continue;
					}

					if ( ment->s.otherEntityNum == ent->s.number ) {
						SV_AddEntToSnapshot( master, ment, eNums );
					}
				}
				goto notVisible;
			}
		}

		// add it
		SV_AddEntToSnapshot( svEnt, ent, eNums );

		// if its a portal entity, add everything visible from its camera position
		if ( ent->r.svFlags & SVF_PORTAL ) {
//			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue, oldframe, localClient );
			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue, localClient );
		}

		continue;

notVisible:

		// Ridah, if this entity has changed events, then send it regardless of whether we can see it or not
		// DHM - Nerve :: not in multiplayer please
		if ( sv_gametype->integer == GT_SINGLE_PLAYER && localClient ) {
			if ( ent->r.eventTime == svs.time ) {
				ent->s.eFlags |= EF_NODRAW;     // don't draw, just process event
				SV_AddEntToSnapshot( svEnt, ent, eNums );
			} else if ( ent->s.eType == ET_PLAYER ) {
				// keep players around if they are alive and active (so sounds dont get messed up)
				if ( !( ent->s.eFlags & EF_DEAD ) ) {
					ent->s.eFlags |= EF_NODRAW;     // don't draw, just process events and sounds
					SV_AddEntToSnapshot( svEnt, ent, eNums );
				}
			}
		}

	}
示例#11
0
/*
===============
SV_AddEntitiesVisibleFromPoint
===============
*/
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame, 
									snapshotEntityNumbers_t *eNums, qboolean portal ) {
	int		e, i;
	gentity_t	*ent;
	svEntity_t	*svEnt;
	int		l;
	int		clientarea, clientcluster;
	int		leafnum;
	int		c_fullsend;
	const byte *clientpvs;
	const byte *bitvector;
	qboolean sightOn = qfalse;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state ) {
		return;
	}

	leafnum = CM_PointLeafnum (origin);
	clientarea = CM_LeafArea (leafnum);
	clientcluster = CM_LeafCluster (leafnum);

	// calculate the visible areas
	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );

	clientpvs = CM_ClusterPVS (clientcluster);

	c_fullsend = 0;

	if ( !portal )
	{//not if this if through a portal...???  James said to do this...
		if ( (frame->ps.forcePowersActive&(1<<FP_SEE)) )
		{
			sightOn = qtrue;
		}
	}

	for ( e = 0 ; e < ge->num_entities ; e++ ) {
		ent = SV_GentityNum(e);

		if (!ent->inuse) {
			continue;
		}

		if (ent->s.eFlags & EF_PERMANENT)
		{	// he's permanent, so don't send him down!
			continue;
		}

		if (ent->s.number != e) {
			Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
			ent->s.number = e;
		}

		// never send entities that aren't linked in
		if ( !ent->linked ) {
			continue;
		}

		// entities can be flagged to explicitly not be sent to the client
		if ( ent->svFlags & SVF_NOCLIENT ) {
			continue;
		}

		svEnt = SV_SvEntityForGentity( ent );

		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
			continue;
		}

		// broadcast entities are always sent, and so is the main player so we don't see noclip weirdness
		if ( ent->svFlags & SVF_BROADCAST || !e) {
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		if (ent->s.isPortalEnt)
		{ //rww - portal entities are always sent as well
			SV_AddEntToSnapshot( svEnt, ent, eNums );
			continue;
		}

		if ( sightOn )
		{//force sight is on, sees through portals, so draw them always if in radius
			if ( SV_PlayerCanSeeEnt( ent, frame->ps.forcePowerLevel[FP_SEE] ) )
			{//entity is visible
				SV_AddEntToSnapshot( svEnt, ent, eNums );
				continue;
			}
		}

		// ignore if not touching a PV leaf
		// check area
		if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
			// doors can legally straddle two areas, so
			// we may need to check another one
			if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
				continue;		// blocked by a door
			}
		}

		bitvector = clientpvs;

		// check individual leafs
		if ( !svEnt->numClusters ) {
			continue;
		}
		l = 0;
#ifdef _XBOX
		if(bitvector) {
#endif
		for ( i=0 ; i < svEnt->numClusters ; i++ ) {
			l = svEnt->clusternums[i];
			if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
				break;
			}
		}
#ifdef _XBOX
		}
#endif

		// if we haven't found it to be visible,
		// check overflow clusters that coudln't be stored
#ifdef _XBOX
		if ( bitvector && i == svEnt->numClusters ) {
#else
		if ( i == svEnt->numClusters ) {
#endif
			if ( svEnt->lastCluster ) {
				for ( ; l <= svEnt->lastCluster ; l++ ) {
					if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
						break;
					}
				}
				if ( l == svEnt->lastCluster ) {
					continue;		// not visible
				}
			} else {
				continue;
			}
		}

		// add it
		SV_AddEntToSnapshot( svEnt, ent, eNums );

		// if its a portal entity, add everything visible from its camera position
		if ( ent->svFlags & SVF_PORTAL ) {
			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
#ifdef _XBOX
			//Must get clientpvs again since above call destroyed it.
		clientpvs = CM_ClusterPVS (clientcluster);
#endif
		}
	}
}
示例#12
0
static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_frame_t *frame, sv_ents_t *ents, bool portal )
{
	edict_t		*ent;
	vec3_t		origin;
	byte		*pset;
	sv_client_t	*cl;
	int		leafnum, fullvis = false;
	int		e, clientcluster, clientarea;
	bool		force = false;

	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if( !sv.state ) return;

	if( pClient && !portal )
	{
		// portals can't change hostflags
		sv.hostflags &= ~SVF_SKIPLOCALHOST;

		cl = SV_ClientFromEdict( pClient, true );
		Com_Assert( cl == NULL );

		// setup hostflags
		if( com.atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )) == 1 )
			sv.hostflags |= SVF_SKIPLOCALHOST;
	}

	e = svgame.dllFuncs.pfnSetupVisibility( pViewEnt, pClient, portal, origin );
	if( e == 0 ) return; // invalid viewent ?
	if( e == -1 ) fullvis = true;

	clientpvs = CM_FatPVS( origin, portal );
	leafnum = CM_PointLeafnum( origin );
	clientarea = CM_LeafArea( leafnum );
	clientcluster = CM_LeafCluster( leafnum );
	clientphs = CM_FatPHS( clientcluster, portal );

	// calculate the visible areas
	if( fullvis )
	{
		if( !portal ) Mem_Set( frame->areabits, 0xFF, sizeof( frame->areabits ));
		frame->areabits_size = sizeof( frame->areabits );
	}
	else frame->areabits_size = CM_WriteAreaBits( frame->areabits, clientarea, portal );

	for( e = 1; e < svgame.globals->numEntities; e++ )
	{
		ent = EDICT_NUM( e );
		if( ent->free ) continue;

		if( ent->serialnumber != e )
		{
			// this should never happens
			MsgDev( D_NOTE, "fixing ent->serialnumber from %i to %i\n", ent->serialnumber, e );
			ent->serialnumber = e;
		}

		// don't double add an entity through portals (already added)
		if( ent->pvServerData->framenum == sv.net_framenum )
			continue;

		if( fullvis ) force = true;
		else force = false; // clear forceflag

		// NOTE: always add himslef to list
		if( !portal && ( ent == pClient ))
			force = true;

		if( ent->v.flags & FL_PHS_FILTER )
			pset = clientphs;
		else pset = clientpvs;

		if( !force )
		{
			// run custom user filter
			if( !svgame.dllFuncs.pfnAddToFullPack( pViewEnt, pClient, ent, sv.hostflags, clientarea, pset ))
				continue;
		}

		SV_AddEntToSnapshot( ent->pvServerData, ent, ents ); // add it
		if( fullvis ) continue; // portal ents will be added anywhere, ignore recursion

		// if its a portal entity, add everything visible from its camera position
		if( !portal && (ent->pvServerData->s.ed_type == ED_PORTAL || ent->pvServerData->s.ed_type == ED_SKYPORTAL))
			SV_AddEntitiesToPacket( ent, pClient, frame, ents, true );
	}
}