Beispiel #1
0
/*
=============
SV_EmitPings

=============
*/
void SV_EmitPings( sizebuf_t *msg )
{
	sv_client_t	*cl;
	int		packet_loss;
	int		i, ping;

	BF_WriteByte( msg, svc_updatepings );

	for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
	{
		if( cl->state != cs_spawned )
			continue;

		SV_GetPlayerStats( cl, &ping, &packet_loss );

		// there are 25 bits for each client
		BF_WriteOneBit( msg, 1 );
		BF_WriteUBitLong( msg, i, MAX_CLIENT_BITS );
		BF_WriteUBitLong( msg, ping, 12 );
		BF_WriteUBitLong( msg, packet_loss, 7 );
	}

	// end marker
	BF_WriteOneBit( msg, 0 );
}
Beispiel #2
0
/*
==================
MSG_WriteWeaponData

Writes current client data only for local client
Other clients can grab the client state from entity_state_t
==================
*/
void MSG_WriteWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, float timebase, int index )
{
	delta_t		*pField;
	delta_info_t	*dt;
	int		i, startBit;
	int		numChanges = 0;

	dt = Delta_FindStruct( "weapon_data_t" );
	if( !dt || !dt->bInitialized )
	{
		Host_Error( "MSG_WriteWeaponData: delta not initialized!\n" );
	}

	pField = dt->pFields;
	ASSERT( pField );

	// activate fields and call custom encode func
	Delta_CustomEncode( dt, from, to );

	startBit = msg->iCurBit;

	BF_WriteOneBit( msg, 1 );
	BF_WriteUBitLong( msg, index, MAX_WEAPON_BITS );
               
	// process fields
	for( i = 0; i < dt->numFields; i++, pField++ )
	{
		if( Delta_WriteField( msg, pField, from, to, timebase ))
			numChanges++;
	}

	// if we have no changes - kill the message
	if( !numChanges ) BF_SeekToBit( msg, startBit );
}
Beispiel #3
0
void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t *pField )
{
	int		nameIndex;
	delta_info_t	*dt;
	
	ASSERT( pField );

	if( !pField->name || !*pField->name )
		return;	// not initialized ?

	dt = Delta_FindStructByIndex( tableIndex );
	ASSERT( dt && dt->bInitialized );

	nameIndex = Delta_IndexForFieldInfo( dt->pInfo, pField->name );
	ASSERT( nameIndex >= 0 && nameIndex < dt->maxFields );

	BF_WriteByte( msg, svc_deltatable );
	BF_WriteUBitLong( msg, tableIndex, 4 );		// assume we support 16 network tables
	BF_WriteUBitLong( msg, nameIndex, 8 );		// 255 fields by struct should be enough
	BF_WriteUBitLong( msg, pField->flags, 10 );	// flags are indicated various input types
	BF_WriteUBitLong( msg, pField->bits - 1, 5 );	// max received value is 32 (32 bit)

	// multipliers is null-compressed
	if( pField->multiplier != 1.0f )
	{
		BF_WriteOneBit( msg, 1 );
		BF_WriteFloat( msg, pField->multiplier );
	}
	else BF_WriteOneBit( msg, 0 );

	if( pField->post_multiplier != 1.0f )
	{
		BF_WriteOneBit( msg, 1 );
		BF_WriteFloat( msg, pField->post_multiplier );
	}
	else BF_WriteOneBit( msg, 0 );
}
Beispiel #4
0
int SV_SoundIndex( const char *filename )
{
	char	name[64];
	int	i;

	// don't precache sentence names!
	if( !filename || !filename[0] || filename[0] == '!' )
		return 0;

	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	for( i = 1; i < MAX_SOUNDS && sv.sound_precache[i][0]; i++ )
	{
		if( !Q_stricmp( sv.sound_precache[i], name ))
			return i;
	}

	if( i == MAX_SOUNDS )
	{
		Host_Error( "SV_SoundIndex: MAX_SOUNDS limit exceeded\n" );
		return 0;
	}

	// register new sound
	Q_strncpy( sv.sound_precache[i], name, sizeof( sv.sound_precache[i] ));

	if( sv.state != ss_loading )
	{	
		// send the update to everyone
		BF_WriteByte( &sv.reliable_datagram, svc_soundindex );
		BF_WriteUBitLong( &sv.reliable_datagram, i, MAX_SOUND_BITS );
		BF_WriteString( &sv.reliable_datagram, name );
	}

	return i;
}
Beispiel #5
0
int SV_ModelIndex( const char *filename )
{
	char	name[64];
	int	i;

	if( !filename || !filename[0] )
		return 0;

	if( *filename == '!' ) filename++;
	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ )
	{
		if( !Q_stricmp( sv.model_precache[i], name ))
			return i;
	}

	if( i == MAX_MODELS )
	{
		Host_Error( "SV_ModelIndex: MAX_MODELS limit exceeded\n" );
		return 0;
	}

	// register new model
	Q_strncpy( sv.model_precache[i], name, sizeof( sv.model_precache[i] ));

	if( sv.state != ss_loading )
	{	
		// send the update to everyone
		BF_WriteByte( &sv.reliable_datagram, svc_modelindex );
		BF_WriteUBitLong( &sv.reliable_datagram, i, MAX_MODEL_BITS );
		BF_WriteString( &sv.reliable_datagram, name );
	}

	return i;
}
Beispiel #6
0
/*
=============
SV_EmitEvents

=============
*/
static void SV_EmitEvents( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg )
{
	event_state_t	*es;
	event_info_t	*info;
	entity_state_t	*state;
	event_args_t	nullargs;
	int		ev_count = 0;
	int		count, ent_index;
	int		i, j, ev;

	Q_memset( &nullargs, 0, sizeof( nullargs ));

	es = &cl->events;

	// count events
	for( ev = 0; ev < MAX_EVENT_QUEUE; ev++ )
	{
		if( es->ei[ev].index ) ev_count++;
	}

	// nothing to send
	if( !ev_count ) return; // nothing to send

	if( ev_count >= 31 ) ev_count = 31;

	for( i = 0; i < MAX_EVENT_QUEUE; i++ )
	{
		info = &es->ei[i];
		if( info->index == 0 )
			continue;

		ent_index = info->entity_index;

		for( j = 0; j < to->num_entities; j++ )
		{
			state = &svs.packet_entities[(to->first_entity+j)%svs.num_client_entities];
			if( state->number == ent_index )
				break;
		}

		if( j >= to->num_entities )
		{
			// couldn't find
			info->packet_index = to->num_entities;
			info->args.entindex = ent_index;
		}
		else
		{
			info->packet_index = j;
			info->args.ducking = 0;

			if(!( info->args.flags & FEVENT_ORIGIN ))
				VectorClear( info->args.origin );

			if(!( info->args.flags & FEVENT_ANGLES ))
				VectorClear( info->args.angles );

			VectorClear( info->args.velocity );
		}
	}

	BF_WriteByte( msg, svc_event );	// create message
	BF_WriteUBitLong( msg, ev_count, 5 );	// up to MAX_EVENT_QUEUE events

	for( count = i = 0; i < MAX_EVENT_QUEUE; i++ )
	{
		info = &es->ei[i];

		if( info->index == 0 )
		{
			info->packet_index = -1;
			info->entity_index = -1;
			continue;
		}

		// only send if there's room
		if( count < ev_count )
		{
			BF_WriteUBitLong( msg, info->index, MAX_EVENT_BITS ); // 1024 events

			if( info->packet_index == -1 )
			{
				BF_WriteOneBit( msg, 0 );
			}
			else
			{
				BF_WriteOneBit( msg, 1 );
				BF_WriteUBitLong( msg, info->packet_index, MAX_ENTITY_BITS );

				if( !Q_memcmp( &nullargs, &info->args, sizeof( event_args_t )))
				{
					BF_WriteOneBit( msg, 0 );
				}
				else
				{
					BF_WriteOneBit( msg, 1 );
					MSG_WriteDeltaEvent( msg, &nullargs, &info->args );
				}
			}

			if( info->fire_time )
			{
				BF_WriteOneBit( msg, 1 );
				BF_WriteWord( msg, Q_rint( info->fire_time * 100.0f ));
			}
			else BF_WriteOneBit( msg, 0 );
		}

		info->index = 0;
		info->packet_index = -1;
		info->entity_index = -1;
		count++;
	}
}
Beispiel #7
0
/*
==================
MSG_WriteDeltaEntity

Writes part of a packetentities message, including the entity number.
Can delta from either a baseline or a previous packet_entity
If to is NULL, a remove entity update will be sent
If force is not set, then nothing at all will be generated if the entity is
identical, under the assumption that the in-order delta code will catch it.
==================
*/
void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean player, float timebase ) 
{
	delta_info_t	*dt = NULL;
	delta_t		*pField;
	int		i, startBit;
	int		numChanges = 0;

	if( to == NULL )
	{
		int	fRemoveType;

		if( from == NULL ) return;

		// a NULL to is a delta remove message
		BF_WriteWord( msg, from->number );

		// fRemoveType:
		// 0 - keep alive, has delta-update
		// 1 - remove from delta message (but keep states)
		// 2 - completely remove from server
		if( force ) fRemoveType = 2;
		else fRemoveType = 1;

		BF_WriteUBitLong( msg, fRemoveType, 2 );
		return;
	}

	startBit = msg->iCurBit;

	if( to->number < 0 || to->number >= GI->max_edicts )
	{
		MsgDev( D_ERROR, "MSG_WriteDeltaEntity: Bad entity number: %i\n", to->number );
		return;
	}

	BF_WriteWord( msg, to->number );
	BF_WriteUBitLong( msg, 0, 2 ); // alive

	if( to->entityType != from->entityType )
	{
		BF_WriteOneBit( msg, 1 );
		BF_WriteUBitLong( msg, to->entityType, 2 );
	}
	else BF_WriteOneBit( msg, 0 ); 

	if( to->entityType == ENTITY_NORMAL )
	{
		if( player )
		{
			dt = Delta_FindStruct( "entity_state_player_t" );
		}
		else
		{
			dt = Delta_FindStruct( "entity_state_t" );
		}
	}
	else if( to->entityType == ENTITY_BEAM )
	{
		dt = Delta_FindStruct( "custom_entity_state_t" );
	}

	ASSERT( dt && dt->bInitialized );
		
	pField = dt->pFields;
	ASSERT( pField );

	// activate fields and call custom encode func
	Delta_CustomEncode( dt, from, to );

	// process fields
	for( i = 0; i < dt->numFields; i++, pField++ )
	{
		if( Delta_WriteField( msg, pField, from, to, timebase ))
			numChanges++;
	}

	// if we have no changes - kill the message
	if( !numChanges && !force ) BF_SeekToBit( msg, startBit );
}