예제 #1
0
파일: net_encode.c 프로젝트: Reedych/xash3d
void Delta_ParseTableField( sizebuf_t *msg )
{
	int		tableIndex, nameIndex;
	float		mul = 1.0f, post_mul = 1.0f;
	int		flags, bits;
	const char	*pName;
	delta_info_t	*dt;

	tableIndex = BF_ReadUBitLong( msg, 4 );
	dt = Delta_FindStructByIndex( tableIndex );

	if( !dt )
		Host_Error( "Delta_ParseTableField: not initialized" );
	nameIndex = BF_ReadUBitLong( msg, 8 );	// read field name index		
	if( !( nameIndex >= 0 && nameIndex < dt->maxFields ) )
		Host_Error( "Delta_ParseTableField: wrong nameIndex" );
	pName = dt->pInfo[nameIndex].name;
	flags = BF_ReadUBitLong( msg, 10 );
	bits = BF_ReadUBitLong( msg, 5 ) + 1;

	// read the multipliers
	if( BF_ReadOneBit( msg ))
		mul = BF_ReadFloat( msg );

	if( BF_ReadOneBit( msg ))
		post_mul = BF_ReadFloat( msg );

	// delta encoders it's already initialized on this machine (local game)
	if( delta_init ) return;

	// add field to table
	Delta_AddField( dt->pName, pName, flags, bits, mul, post_mul );
}
예제 #2
0
파일: cl_parse.c 프로젝트: Reedych/xash3d
/*
================
CL_UpdateUserinfo

collect userinfo from all players
================
*/
void CL_UpdateUserinfo( sizebuf_t *msg )
{
	int		slot;
	qboolean		active;
	player_info_t	*player;

	slot = BF_ReadUBitLong( msg, MAX_CLIENT_BITS );

	if( slot >= MAX_CLIENTS )
		Host_Error( "CL_ParseServerMessage: svc_updateuserinfo > MAX_CLIENTS\n" );

	player = &cl.players[slot];
	active = BF_ReadOneBit( msg ) ? true : false;

	if( active )
	{
		Q_strncpy( player->userinfo, BF_ReadString( msg ), sizeof( player->userinfo ));
		Q_strncpy( player->name, Info_ValueForKey( player->userinfo, "name" ), sizeof( player->name ));
		Q_strncpy( player->model, Info_ValueForKey( player->userinfo, "model" ), sizeof( player->model ));
		cl.playermodels[slot] = 0;
		player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" ));
		player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" ));

		if( slot == cl.playernum ) Q_memcpy( &menu.playerinfo, player, sizeof( player_info_t ));
	}
	else Q_memset( player, 0, sizeof( *player ));
}
예제 #3
0
파일: cl_events.c 프로젝트: Reedych/xash3d
/*
=============
CL_ParseReliableEvent

=============
*/
void CL_ParseReliableEvent( sizebuf_t *msg )
{
	int		event_index;
	event_args_t	nullargs, args;
	float		delay = 0.0f;
	cl_entity_t	*pEnt;

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

	event_index = BF_ReadUBitLong( msg, MAX_EVENT_BITS );

	if( BF_ReadOneBit( msg ))
		delay = (float)BF_ReadWord( msg ) * (1.0f / 100.0f);

	// reliable events not use delta-compression just null-compression
	MSG_ReadDeltaEvent( msg, &nullargs, &args );

	if(( pEnt = CL_GetEntityByIndex( args.entindex )) != NULL )
	{
		if( VectorIsNull( args.origin ))
			VectorCopy( pEnt->curstate.origin, args.origin );
		if( VectorIsNull( args.angles ))
			VectorCopy( pEnt->curstate.angles, args.angles );
		if( VectorIsNull( args.velocity ))
			VectorCopy( pEnt->curstate.velocity, args.velocity );
	}

	CL_QueueEvent( FEV_RELIABLE|FEV_SERVER, event_index, delay, &args );
}
예제 #4
0
파일: cl_parse.c 프로젝트: Reedych/xash3d
/*
================
CL_UpdateUserPings

collect pings and packet lossage from clients
================
*/
void CL_UpdateUserPings( sizebuf_t *msg )
{
	int		i, slot;
	player_info_t	*player;
	
	for( i = 0; i < MAX_CLIENTS; i++ )
	{
		if( !BF_ReadOneBit( msg )) break; // end of message

		slot = BF_ReadUBitLong( msg, MAX_CLIENT_BITS );

		if( slot >= MAX_CLIENTS )
			Host_Error( "CL_ParseServerMessage: svc_updatepings > MAX_CLIENTS\n" );

		player = &cl.players[slot];
		player->ping = BF_ReadUBitLong( msg, 12 );
		player->packet_loss = BF_ReadUBitLong( msg, 7 );
	}
}
예제 #5
0
파일: cl_parse.c 프로젝트: Reedych/xash3d
/*
================
CL_PrecacheEvent

prceache event from server
================
*/
void CL_PrecacheEvent( sizebuf_t *msg )
{
	int	eventIndex;

	eventIndex = BF_ReadUBitLong( msg, MAX_EVENT_BITS );

	if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
		Host_Error( "CL_PrecacheEvent: bad eventindex %i\n", eventIndex );

	Q_strncpy( cl.event_precache[eventIndex], BF_ReadString( msg ), sizeof( cl.event_precache[0] ));

	// can be set now
	CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
}
예제 #6
0
파일: cl_parse.c 프로젝트: Reedych/xash3d
/*
================
CL_PrecacheSound

prceache sound from server
================
*/
void CL_PrecacheSound( sizebuf_t *msg )
{
	int	soundIndex;

	soundIndex = BF_ReadUBitLong( msg, MAX_SOUND_BITS );

	if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
		Host_Error( "CL_PrecacheSound: bad soundindex %i\n", soundIndex );

	Q_strncpy( cl.sound_precache[soundIndex], BF_ReadString( msg ), sizeof( cl.sound_precache[0] ));

	// when we loading map all resources is precached sequentially
	if( !cl.audio_prepped ) return;

	cl.sound_index[soundIndex] = S_RegisterSound( cl.sound_precache[soundIndex] );
}
예제 #7
0
파일: cl_parse.c 프로젝트: Reedych/xash3d
/*
================
CL_PrecacheModel

prceache model from server
================
*/
void CL_PrecacheModel( sizebuf_t *msg )
{
	int	modelIndex;

	modelIndex = BF_ReadUBitLong( msg, MAX_MODEL_BITS );

	if( modelIndex < 0 || modelIndex >= MAX_MODELS )
		Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );

	Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));

	// when we loading map all resources is precached sequentially
	if( !cl.video_prepped ) return;

	Mod_RegisterModel( cl.model_precache[modelIndex], modelIndex );
}
예제 #8
0
파일: cl_parse.c 프로젝트: Reedych/xash3d
/*
===================
CL_ParseClientData
===================
*/
void CL_ParseClientData( sizebuf_t *msg )
{
	int		i, j;
	clientdata_t	*from_cd, *to_cd;
	weapon_data_t	*from_wd, *to_wd;
	weapon_data_t	nullwd[32];
	clientdata_t	nullcd;
	frame_t		*frame;
	int		idx;

	// this is the frame update that this message corresponds to
	i = cls.netchan.incoming_sequence;

	// did we drop some frames?
	if( i > cl.last_incoming_sequence + 1 )
	{
		// mark as dropped
		for( j = cl.last_incoming_sequence + 1; j < i; j++ )
		{
			if( cl.frames[j & CL_UPDATE_MASK].receivedtime >= 0.0 )
			{
				cl.frames[j & CL_UPDATE_MASK].receivedtime = -1;
				cl.frames[j & CL_UPDATE_MASK].latency = 0;
			}
		}
	}

	cl.parsecount = i;					// ack'd incoming messages.  
	cl.parsecountmod = cl.parsecount & CL_UPDATE_MASK;	// index into window.     
	frame = &cl.frames[cl.parsecountmod];			// frame at index.

	frame->time = cl.mtime[0];				// mark network received time
	frame->receivedtime = host.realtime;			// time now that we are parsing.  

	if( cl.last_command_ack != -1 )
	{
		int last_predicted;
		entity_state_t * ps;
		entity_state_t * pps;
		clientdata_t * pcd;
		clientdata_t * ppcd;
		weapon_data_t * wd;
		weapon_data_t * pwd;

		last_predicted = ( cl.last_incoming_sequence + (
							   cls.netchan.incoming_acknowledged - cl.last_command_ack)) & CL_UPDATE_MASK;

		pps = &cl.predict[last_predicted].playerstate;
		ppcd = &cl.predict[last_predicted].client;
		pwd = cl.predict[last_predicted].weapondata;

		ps = &frame->playerstate[cl.playernum];
		pcd = &frame->local.client;
		wd = frame->local.weapondata;

		clgame.dllFuncs.pfnTxferPredictionData( ps, pps, pcd, ppcd, wd, pwd );
	}

	// do this after all packets read for this frame?
	cl.last_command_ack = cls.netchan.incoming_acknowledged;
	cl.last_incoming_sequence = cls.netchan.incoming_sequence;

	if( hltv->integer ) return;	// clientdata for spectators ends here
	
	to_cd = &frame->local.client;
	to_wd = frame->local.weapondata;

	// clear to old value before delta parsing
	if( !BF_ReadOneBit( msg ))
	{
		Q_memset( &nullcd, 0, sizeof( nullcd ));
		Q_memset( nullwd, 0, sizeof( nullwd ));
		from_cd = &nullcd;
		from_wd = nullwd;
	}
	else
	{
		int	delta_sequence = BF_ReadByte( msg );

		from_cd = &cl.frames[delta_sequence & CL_UPDATE_MASK].local.client;
		from_wd = cl.frames[delta_sequence & CL_UPDATE_MASK].local.weapondata;
	}

	MSG_ReadClientData( msg, from_cd, to_cd, cl.mtime[0] );

	for( i = 0; i < MAX_WEAPONS; i++ )
	{
		// check for end of weapondata (and clientdata_t message)
		if( !BF_ReadOneBit( msg )) break;

		// read the weapon idx
		idx = BF_ReadUBitLong( msg, MAX_WEAPON_BITS );

		MSG_ReadWeaponData( msg, &from_wd[idx], &to_wd[idx], cl.mtime[0] );
	}
}
예제 #9
0
파일: cl_events.c 프로젝트: Reedych/xash3d
/*
=============
CL_ParseEvent

=============
*/
void CL_ParseEvent( sizebuf_t *msg )
{
	int		event_index;
	int		i, num_events;
	int		packet_ent;
	event_args_t	nullargs, args;
	qboolean		has_update;
	entity_state_t	*state;
	cl_entity_t	*pEnt;
	float		delay;

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

	num_events = BF_ReadUBitLong( msg, 5 );

	// parse events queue
	for( i = 0 ; i < num_events; i++ )
	{
		event_index = BF_ReadUBitLong( msg, MAX_EVENT_BITS );
		Q_memset( &args, 0, sizeof( args ));
		has_update = false;

		if( BF_ReadOneBit( msg ))
		{
			packet_ent = BF_ReadUBitLong( msg, MAX_ENTITY_BITS );

			if( BF_ReadOneBit( msg ))
			{
				MSG_ReadDeltaEvent( msg, &nullargs, &args );
				has_update = true;
			}
		}
		else packet_ent = -1;

		if( packet_ent != -1 )
			state = &cls.packet_entities[(cl.frame.first_entity+packet_ent)%cls.num_client_entities];
		else state = NULL;

		// it's a client. Override some params
		if( args.entindex >= 1 && args.entindex <= cl.maxclients )
		{
			if(( args.entindex - 1 ) == cl.playernum )
			{
				if( state && !CL_IsPredicted( ))
				{
					// restore viewangles from angles
					args.angles[PITCH] = -state->angles[PITCH] * 3;
					args.angles[YAW] = state->angles[YAW];
					args.angles[ROLL] = 0; // no roll
				}
				else
				{
					// get the predicted angles
					VectorCopy( cl.refdef.cl_viewangles, args.angles );
				}

				VectorCopy( cl.frame.local.client.origin, args.origin );
				VectorCopy( cl.frame.local.client.velocity, args.velocity );
			}
			else if( state )
			{
				// restore viewangles from angles
				args.angles[PITCH] = -state->angles[PITCH] * 3;
				args.angles[YAW] = state->angles[YAW];
				args.angles[ROLL] = 0; // no roll

				// if we restore origin and velocity everytime, why don't do it here also?
				if( VectorIsNull( args.origin ))
					VectorCopy( state->origin, args.origin );
				if( VectorIsNull( args.velocity ))
					VectorCopy( state->velocity, args.velocity );
			}
		}
		else if( state )
		{
			if( VectorIsNull( args.origin ))
				VectorCopy( state->origin, args.origin );
			if( VectorIsNull( args.angles ))
				VectorCopy( state->angles, args.angles );
			if( VectorIsNull( args.velocity ))
				VectorCopy( state->velocity, args.velocity );
		}
		else if(( pEnt = CL_GetEntityByIndex( args.entindex )) != NULL )
		{
			if( VectorIsNull( args.origin ))
				VectorCopy( pEnt->curstate.origin, args.origin );
			if( VectorIsNull( args.angles ))
				VectorCopy( pEnt->curstate.angles, args.angles );
			if( VectorIsNull( args.velocity ))
				VectorCopy( pEnt->curstate.velocity, args.velocity );
		}

		if( BF_ReadOneBit( msg ))
			delay = (float)BF_ReadWord( msg ) * (1.0f / 100.0f);
		else delay = 0.0f;

		// g-cont. should we need find the event with same index?
		CL_QueueEvent( 0, event_index, delay, &args );
	}
}
예제 #10
0
파일: net_encode.c 프로젝트: Reedych/xash3d
/*
==================
MSG_ReadDeltaEntity

The entity number has already been read from the message, which
is how the from state is identified.
                             
If the delta removes the entity, entity_state_t->number will be set to MAX_EDICTS
Can go from either a baseline or a previous packet_entity
==================
*/
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, qboolean player, float timebase )
{
	delta_info_t	*dt = NULL;
	delta_t		*pField;
	int		i, fRemoveType;
#ifndef XASH_DEDICATED
	if( number < 0 || number >= clgame.maxEntities )
	{
		// broken packet, try to skip it
		MsgDev( D_ERROR, "MSG_ReadDeltaEntity: bad delta entity number: %i\n", number );
		return false;
	}

	*to = *from;
	to->number = number;
	fRemoveType = BF_ReadUBitLong( msg, 2 );

	if( fRemoveType )
	{
		// check for a remove
		Q_memset( to, 0, sizeof( *to ));

		if( fRemoveType & 1 )
		{
			// removed from delta-message
			return false;
                    }

		if( fRemoveType & 2 )
		{	
			// entity was removed from server
			to->number = -1;
			return false;
		}

		MsgDev( D_ERROR, "MSG_ReadDeltaEntity: unknown update type %i\n", fRemoveType );
		return false;
	}

	if( BF_ReadOneBit( msg ))
		to->entityType = BF_ReadUBitLong( msg, 2 );


	if( to->entityType == ENTITY_BEAM )
	{
		dt = Delta_FindStruct( "custom_entity_state_t" );
	}
	else //  ENTITY_NORMAL or other (try predict type)
	{
		/* Omit connection drop on wromg data from server.
		 * I know that it is very dirty,
		 * but i don't know how to do it better.*/
		if( to->entityType != ENTITY_NORMAL )
			MsgDev( D_NOTE, "MSG_ReadDeltaEntity: broken delta: entityType = %d\n", to->entityType );
		if( player )
		{
			dt = Delta_FindStruct( "entity_state_player_t" );
		}
		else
		{
			dt = Delta_FindStruct( "entity_state_t" );
		}
	}

	if( !(dt && dt->bInitialized) ) // Broken  delta?
	{
		MsgDev( D_ERROR, "MSG_ReadDeltaEntity: broken delta\n");
		return true;
	}
	pField = dt->pFields;
	ASSERT( pField );

	// process fields
	for( i = 0; i < dt->numFields; i++, pField++ )
	{
		Delta_ReadField( msg, pField, from, to, timebase );
	}
#endif
	// message parsed
	return true;
}
예제 #11
0
/*
==================
MSG_ReadDeltaEntity

The entity number has already been read from the message, which
is how the from state is identified.

If the delta removes the entity, entity_state_t->number will be set to MAX_EDICTS
Can go from either a baseline or a previous packet_entity
==================
*/
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, qboolean player, float timebase )
{
	delta_info_t	*dt = NULL;
	delta_t		*pField;
	int		i, fRemoveType;

#ifndef _DEDICATED
	if( number < 0 || number >= clgame.maxEntities )
		Host_Error( "MSG_ReadDeltaEntity: bad delta entity number: %i\n", number );
#endif

	*to = *from;
	to->number = number;
	fRemoveType = BF_ReadUBitLong( msg, 2 );

	if( fRemoveType )
	{
		// check for a remove
		Q_memset( to, 0, sizeof( *to ));

		if( fRemoveType & 1 )
		{
			// removed from delta-message
			return false;
                    }

		if( fRemoveType & 2 )
		{
			// entity was removed from server
			to->number = -1;
			return false;
		}

		Host_Error( "MSG_ReadDeltaEntity: unknown update type %i\n", fRemoveType );
	}

	if( BF_ReadOneBit( msg ))
		to->entityType = BF_ReadUBitLong( msg, 2 );

	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 );

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

	// message parsed
	return true;
}