Exemple #1
0
/*
==================
CL_ParsePacketEntities

An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
void CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
{
	frame_t		*newframe, *oldframe;
	int		oldindex, newnum, oldnum;
	int		oldpacket, newpacket;
	cl_entity_t	*player;
	entity_state_t	*oldent;
	int		i, count;

	// save first uncompressed packet as timestamp
	if( cls.changelevel && !delta && cls.demorecording )
		CL_WriteDemoJumpTime();

	// first, allocate packet for new frame
	count = BF_ReadWord( msg );

	newpacket = cl.parsecountmod;
	newframe = &cl.frames[newpacket];

	// allocate parse entities
	newframe->first_entity = cls.next_client_entities;
	newframe->num_entities = 0;
	newframe->valid = true; // assume valid

	if( delta )
	{
		int	subtracted;

		oldpacket = BF_ReadByte( msg );
		subtracted = ((( cls.netchan.incoming_sequence & 0xFF ) - oldpacket ) & 0xFF );

		if( subtracted == 0 )
		{
			Host_Error( "CL_DeltaPacketEntities: update too old, connection dropped.\n" );
			return;
		}

		if( subtracted >= CL_UPDATE_MASK )
		{	
			// we can't use this, it is too old
			Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
			CL_FlushEntityPacket( msg );
			return;
		}

		oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];

		if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - 128 ))
		{
			Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
			CL_FlushEntityPacket( msg );
			return;
		}
	}
	else
	{
		// this is a full update that we can start delta compressing from now
		oldframe = NULL;
		oldpacket = -1;		// delta too old or is initial message
		cl.force_send_usercmd = true;	// send reply
		cls.demowaiting = false;	// we can start recording now
	}

	// mark current delta state
	cl.validsequence = cls.netchan.incoming_sequence;

	oldent = NULL;
	oldindex = 0;

	if( !oldframe )
	{
		oldnum = MAX_ENTNUMBER;
	}
	else
	{
		if( oldindex >= oldframe->num_entities )
		{
			oldnum = MAX_ENTNUMBER;
		}
		else
		{
			oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
			oldnum = oldent->number;
		}
	}

	while( 1 )
	{
		newnum = BF_ReadWord( msg );
		if( !newnum ) break; // end of packet entities

		if( BF_CheckOverflow( msg ))
			Host_Error( "CL_ParsePacketEntities: read overflow\n" );

		while( oldnum < newnum )
		{	
			// one or more entities from the old packet are unchanged
			CL_DeltaEntity( msg, newframe, oldnum, oldent, true );
			
			oldindex++;

			if( oldindex >= oldframe->num_entities )
			{
				oldnum = MAX_ENTNUMBER;
			}
			else
			{
				oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
				oldnum = oldent->number;
			}
		}

		if( oldnum == newnum )
		{	
			// delta from previous state
			CL_DeltaEntity( msg, newframe, newnum, oldent, false );
			oldindex++;

			if( oldindex >= oldframe->num_entities )
			{
				oldnum = MAX_ENTNUMBER;
			}
			else
			{
				oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
				oldnum = oldent->number;
			}
			continue;
		}

		if( oldnum > newnum )
		{	
			// delta from baseline ?
			CL_DeltaEntity( msg, newframe, newnum, NULL, false );
			continue;
		}
	}

	// any remaining entities in the old frame are copied over
	while( oldnum != MAX_ENTNUMBER )
	{	
		// one or more entities from the old packet are unchanged
		CL_DeltaEntity( msg, newframe, oldnum, oldent, true );
		oldindex++;

		if( oldindex >= oldframe->num_entities )
		{
			oldnum = MAX_ENTNUMBER;
		}
		else
		{
			oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
			oldnum = oldent->number;
		}
	}

	cl.frame = *newframe;

	if( !cl.frame.valid ) return;

	player = CL_GetLocalPlayer();
		
	if( cls.state != ca_active )
	{
		// client entered the game
		cls.state = ca_active;
		cl.force_refdef = true;
		cls.changelevel = false;		// changelevel is done
		cls.changedemo = false;		// changedemo is done

		SCR_MakeLevelShot();		// make levelshot if needs
		Cvar_SetFloat( "scr_loading", 0.0f );	// reset progress bar	

		if(( cls.demoplayback || cls.disable_servercount != cl.servercount ) && cl.video_prepped )
			SCR_EndLoadingPlaque(); // get rid of loading plaque
	}

	// update local player states
	clgame.dllFuncs.pfnTxferLocalOverrides( &player->curstate, &newframe->local.client );

	// update state for all players
	for( i = 0; i < cl.maxclients; i++ )
	{
		cl_entity_t *ent = CL_GetEntityByIndex( i + 1 );
		if( !ent ) continue;
		clgame.dllFuncs.pfnProcessPlayerState( &newframe->playerstate[i], &ent->curstate );
		newframe->playerstate[i].number = ent->index;
	}

	cl.frame = *newframe;
}
Exemple #2
0
/*
==================
CL_ParsePacketEntities

An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe)
{
	int			newnum;
	int			bits;
	entity_state_t	*oldstate;
	int			oldindex, oldnum;

	newframe->parse_entities = cl.parse_entities;
	newframe->num_entities = 0;

	// delta from the entities present in oldframe
	oldindex = 0;
	if (!oldframe)
		oldnum = 99999;
	else
	{
		if (oldindex >= oldframe->num_entities)
			oldnum = 99999;
		else
		{
			oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
			oldnum = oldstate->number;
		}
	}

	while (1)
	{
		newnum = CL_ParseEntityBits (&bits);
		if (newnum >= MAX_EDICTS)
			Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum);

		if (net_message.readcount > net_message.cursize)
			Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");

		if (!newnum)
			break;

		while (oldnum < newnum)
		{	// one or more entities from the old packet are unchanged
			if (cl_shownet->value == 3)
				Com_Printf ("   unchanged: %i\n", oldnum);
			CL_DeltaEntity (newframe, oldnum, oldstate, 0);
			
			oldindex++;

			if (oldindex >= oldframe->num_entities)
				oldnum = 99999;
			else
			{
				oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
				oldnum = oldstate->number;
			}
		}

		if (bits & U_REMOVE)
		{	// the entity present in oldframe is not in the current frame
			if (cl_shownet->value == 3)
				Com_Printf ("   remove: %i\n", newnum);
			if (oldnum != newnum)
				Com_Printf ("U_REMOVE: oldnum != newnum\n");

			oldindex++;

			if (oldindex >= oldframe->num_entities)
				oldnum = 99999;
			else
			{
				oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
				oldnum = oldstate->number;
			}
			continue;
		}

		if (oldnum == newnum)
		{	// delta from previous state
			if (cl_shownet->value == 3)
				Com_Printf ("   delta: %i\n", newnum);
			CL_DeltaEntity (newframe, newnum, oldstate, bits);

			oldindex++;

			if (oldindex >= oldframe->num_entities)
				oldnum = 99999;
			else
			{
				oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
				oldnum = oldstate->number;
			}
			continue;
		}

		if (oldnum > newnum)
		{	// delta from baseline
			if (cl_shownet->value == 3)
				Com_Printf ("   baseline: %i\n", newnum);
			CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits);
			continue;
		}

	}

	// any remaining entities in the old frame are copied over
	while (oldnum != 99999)
	{	// one or more entities from the old packet are unchanged
		if (cl_shownet->value == 3)
			Com_Printf ("   unchanged: %i\n", oldnum);
		CL_DeltaEntity (newframe, oldnum, oldstate, 0);
		
		oldindex++;

		if (oldindex >= oldframe->num_entities)
			oldnum = 99999;
		else
		{
			oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
			oldnum = oldstate->number;
		}
	}
}
Exemple #3
0
/*
==================
CL_ParsePacketEntities

==================
*/
void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *newframe )
{
	int           newnum;
	entityState_t *oldstate;
	int           oldindex, oldnum;

	newframe->parseEntitiesNum = cl.parseEntitiesNum;
	newframe->numEntities = 0;

	// delta from the entities present in oldframe
	oldindex = 0;
	oldstate = NULL;

	if ( !oldframe )
	{
		oldnum = 99999;
	}
	else
	{
		if ( oldindex >= oldframe->numEntities )
		{
			oldnum = 99999;
		}
		else
		{
			oldstate = &cl.parseEntities[
			             ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 ) ];
			oldnum = oldstate->number;
		}
	}

	while ( 1 )
	{
		// read the entity index number
		newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );

		if ( newnum == ( MAX_GENTITIES - 1 ) )
		{
			break;
		}

		if ( msg->readcount > msg->cursize )
		{
			Com_Error( ERR_DROP, "CL_ParsePacketEntities: end of message" );
		}

		while ( oldnum < newnum )
		{
			// one or more entities from the old packet are unchanged
			if ( cl_shownet->integer == 3 )
			{
				Com_Printf( "%3i:  unchanged: %i\n", msg->readcount, oldnum );
			}

			CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );

			oldindex++;

			if ( oldindex >= oldframe->numEntities )
			{
				oldnum = 99999;
			}
			else
			{
				oldstate = &cl.parseEntities[
				             ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 ) ];
				oldnum = oldstate->number;
			}
		}

		if ( oldnum == newnum )
		{
			// delta from previous state
			if ( cl_shownet->integer == 3 )
			{
				Com_Printf( "%3i:  delta: %i\n", msg->readcount, newnum );
			}

			CL_DeltaEntity( msg, newframe, newnum, oldstate, qfalse );

			oldindex++;

			if ( oldindex >= oldframe->numEntities )
			{
				oldnum = 99999;
			}
			else
			{
				oldstate = &cl.parseEntities[
				             ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 ) ];
				oldnum = oldstate->number;
			}

			continue;
		}

		if ( oldnum > newnum )
		{
			// delta from baseline
			if ( cl_shownet->integer == 3 )
			{
				Com_Printf( "%3i:  baseline: %i\n", msg->readcount, newnum );
			}

			CL_DeltaEntity( msg, newframe, newnum, &cl.entityBaselines[ newnum ], qfalse );
			continue;
		}
	}

	// any remaining entities in the old frame are copied over
	while ( oldnum != 99999 )
	{
		// one or more entities from the old packet are unchanged
		if ( cl_shownet->integer == 3 )
		{
			Com_Printf( "%3i:  unchanged: %i\n", msg->readcount, oldnum );
		}

		CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );

		oldindex++;

		if ( oldindex >= oldframe->numEntities )
		{
			oldnum = 99999;
		}
		else
		{
			oldstate = &cl.parseEntities[
			             ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 ) ];
			oldnum = oldstate->number;
		}
	}

	if ( cl_shownuments->integer )
	{
		Com_Printf( "Entities in packet: %i\n", newframe->numEntities );
	}
}
Exemple #4
0
/*
==================
CL_ParsePacketEntities

==================
*/
void CL_ParsePacketEntities( msg_t *msg, const clSnapshot_t *oldSnapshot, clSnapshot_t *newSnapshot )
{
    // The entity packet contains the delta between the two snapshots, with data only
    // for entities that were created, changed or removed. Entities entries are in
    // order of increasing entity number, as are entities in a snapshot. Using this we
    // have an efficient algorithm to create the new snapshot, that goes over the old
    // snapshot once from the beginning to the end.

    // If we don't have an old snapshot or it is empty, we'll recreate all entities
    // from the baseline entities as setting oldEntityNum to MAX_GENTITIES will force
    // us to only do step (3) below.
    unsigned int oldEntityNum = MAX_GENTITIES;
    if (oldSnapshot && oldSnapshot->entities.size() > 0){
        oldEntityNum = oldSnapshot->entities[0].number;
    }

    // Likewise when we don't have an old snapshot, oldEntities just has to be an empty
    // vector so that we skip step (4)
    std::vector<entityState_t> dummyEntities;
    auto& oldEntities = oldSnapshot? oldSnapshot->entities : dummyEntities;
    auto& newEntities = newSnapshot->entities;

    unsigned int numEntities = MSG_ReadShort(msg);
    newEntities.reserve(numEntities);

	unsigned oldIndex = 0;

    while (true) {
        unsigned int newEntityNum = MSG_ReadBits(msg, GENTITYNUM_BITS);

        if (msg->readcount > msg->cursize) {
            Sys::Drop("CL_ParsePacketEntities: Unexpected end of message");
        }

        if (newEntityNum == MAX_GENTITIES - 1) {
            break;
        }

        // (1) all entities that weren't specified between the previous newEntityNum and
        // the current one are unchanged and just copied over.
        while (oldEntityNum < newEntityNum) {
            newEntities.push_back(oldEntities[oldIndex]);

            oldIndex ++;
            if (oldIndex >= oldEntities.size()) {
                oldEntityNum = MAX_GENTITIES;
            } else {
                oldEntityNum = oldEntities[oldIndex].number;
            }
        }

        // (2) there is an entry for an entity in the old snapshot, apply the delta
        if (oldEntityNum == newEntityNum) {
            CL_DeltaEntity(msg, newSnapshot, newEntityNum, oldEntities[oldIndex]);

            oldIndex ++;
            if (oldIndex >= oldEntities.size()) {
                oldEntityNum = MAX_GENTITIES;
            } else {
                oldEntityNum = oldEntities[oldIndex].number;
            }
        } else {
            // (3) the entry isn't in the old snapshot, so the entity will be specified
            // from the baseline
            ASSERT_GT(oldEntityNum, newEntityNum);

            CL_DeltaEntity(msg, newSnapshot, newEntityNum, cl.entityBaselines[newEntityNum]);
        }
    }

    // (4) All remaining entities in the oldSnapshot are unchanged and copied over
    while (oldIndex < oldEntities.size()) {
        newEntities.push_back(oldEntities[oldIndex]);
        oldIndex ++;
    }

    ASSERT_EQ(numEntities, newEntities.size());
}