Skip to content

Commit

Permalink
Make clSnapshot own their entity vector
Browse files Browse the repository at this point in the history
  • Loading branch information
Kangz committed Nov 5, 2015
1 parent cf547df commit 98e4849
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 178 deletions.
13 changes: 1 addition & 12 deletions daemon/src/engine/client/cl_cgame.cpp
Expand Up @@ -295,24 +295,13 @@ bool CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot )
return false;
}

// if the entities in the frame have fallen out of their
// circular buffer, we can't return it
if ( cl.parseEntitiesNum - clSnap->parseEntitiesNum >= MAX_PARSE_ENTITIES )
{
return false;
}

// write the snapshot
snapshot->snapFlags = clSnap->snapFlags;
snapshot->ping = clSnap->ping;
snapshot->serverTime = clSnap->serverTime;
memcpy( snapshot->areamask, clSnap->areamask, sizeof( snapshot->areamask ) );
snapshot->ps = clSnap->ps;

snapshot->entities.reserve(clSnap->numEntities);
for (unsigned i = 0; i < clSnap->numEntities; i++) {
snapshot->entities.push_back(cl.parseEntities[( clSnap->parseEntitiesNum + i ) & ( MAX_PARSE_ENTITIES - 1 ) ]);
}
snapshot->entities = clSnap->entities;

CL_FillServerCommands(snapshot->serverCommands, clc.lastExecutedServerCommand + 1, clSnap->serverCommandNum);
clc.lastExecutedServerCommand = clSnap->serverCommandNum;
Expand Down
228 changes: 75 additions & 153 deletions daemon/src/engine/client/cl_parse.cpp
Expand Up @@ -66,38 +66,16 @@ MESSAGE PARSING
=========================================================================
*/

/*
==================
CL_DeltaEntity
Parses deltas from the given base and adds the resulting entity
to the current frame
==================
*/
void CL_DeltaEntity( msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t *old, bool unchanged )
// TODO(kangz) if we can make sure that the baseline entities have the correct entity
// number, then we could grab the entity number from old directly, simplifying code a bit.
void CL_DeltaEntity( msg_t *msg, clSnapshot_t *snapshot, int entityNum, const entityState_t &oldEntity)
{
entityState_t *state;

// save the parsed entity state into the big circular buffer so
// it can be used as the source for a later delta
state = &cl.parseEntities[ cl.parseEntitiesNum & ( MAX_PARSE_ENTITIES - 1 ) ];
entityState_t entity;
MSG_ReadDeltaEntity(msg, &oldEntity, &entity, entityNum);

if ( unchanged )
{
*state = *old;
if (entity.number != MAX_GENTITIES - 1) {
snapshot->entities.push_back(entity);
}
else
{
MSG_ReadDeltaEntity( msg, old, state, newnum );
}

if ( state->number == ( MAX_GENTITIES - 1 ) )
{
return; // entity was delta removed
}

cl.parseEntitiesNum++;
frame->numEntities++;
}

/*
Expand All @@ -106,135 +84,83 @@ CL_ParsePacketEntities
==================
*/
void CL_ParsePacketEntities( msg_t *msg, const clSnapshot_t *oldframe, clSnapshot_t *newframe )
void CL_ParsePacketEntities( msg_t *msg, const clSnapshot_t *oldSnapshot, clSnapshot_t *newSnapshot )
{
unsigned int newnum;
entityState_t *oldstate;
unsigned int oldindex, oldnum;

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

// delta from the entities present in oldframe
oldindex = 0;
oldstate = nullptr;
oldnum = MAX_GENTITIES;

if ( !oldframe )
{
static clSnapshot_t nullframe{};
nullframe.valid = false;

oldframe = &nullframe;
}

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

oldindex++;

if ( oldindex >= oldframe->numEntities )
{
oldnum = MAX_GENTITIES;
}
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, false );

oldindex++;

if ( oldindex >= oldframe->numEntities )
{
oldnum = MAX_GENTITIES;
}
else
{
oldstate = &cl.parseEntities[
( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 ) ];
oldnum = oldstate->number;
}
// 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 (newEntityNum == MAX_GENTITIES - 1) {
break;
}

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

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

CL_DeltaEntity( msg, newframe, newnum, &cl.entityBaselines[ newnum ], false );
continue;
}
}
oldIndex ++;
if (oldIndex >= oldEntities.size()) {
oldEntityNum = MAX_GENTITIES;
} else {
oldEntityNum = oldEntities[oldIndex].number;
}
}

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

CL_DeltaEntity( msg, newframe, oldnum, oldstate, true );
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(oldEntityNum > newEnityNum);

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

if ( oldindex >= oldframe->numEntities )
{
oldnum = MAX_GENTITIES;
}
else
{
oldstate = &cl.parseEntities[
( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 ) ];
oldnum = oldstate->number;
}
}
// (4) All remaining entities in the oldSnapshot are unchanged and copied over
while (oldIndex < oldEntities.size()) {
newEntities.push_back(oldEntities[oldIndex]);
oldIndex ++;
}

if ( cl_shownuments->integer )
{
Com_Printf( "Entities in packet: %i\n", newframe->numEntities );
}
assert(numEntities == newEntities.size());
}

/*
Expand Down Expand Up @@ -363,10 +289,6 @@ void CL_ParseSnapshot( msg_t *msg )
// is too old, so we can't reconstruct it properly.
Com_DPrintf( "Delta frame too old.\n" );
}
else if ( cl.parseEntitiesNum - old->parseEntitiesNum > MAX_PARSE_ENTITIES - 128 )
{
Com_DPrintf( "Delta parseEntitiesNum too old.\n" );
}
else
{
newSnap.valid = true; // valid delta parse
Expand Down
13 changes: 2 additions & 11 deletions daemon/src/engine/client/client.h
Expand Up @@ -74,11 +74,10 @@ typedef struct
int cmdNum; // the next cmdNum the server is expecting
playerState_t ps; // complete information about the current player at this time

unsigned numEntities; // all of the entities that need to be presented
int parseEntitiesNum; // at the time of this snapshot

int serverCommandNum; // execute all commands up to this before
// making the snapshot current

std::vector<entityState_t> entities;
} clSnapshot_t;

// Arnout: for double tapping
Expand Down Expand Up @@ -106,10 +105,6 @@ typedef struct
int p_realtime; // cls.realtime when packet was sent
} outPacket_t;

// the parseEntities array must be large enough to hold PACKET_BACKUP frames of
// entities, so that when a delta compressed message arives from the server
// it can be un-deltad from the original

#define MAX_PARSE_ENTITIES 2048

extern int g_console_field_width;
Expand All @@ -133,8 +128,6 @@ typedef struct

char mapname[ MAX_QPATH ]; // extracted from CS_SERVERINFO

int parseEntitiesNum; // index (not anded off) into cl_parse_entities[]

int mouseDx[ 2 ], mouseDy[ 2 ]; // added to by mouse events
int mouseIndex;
int joystickAxis[ MAX_JOYSTICK_AXIS ]; // set by joystick events
Expand Down Expand Up @@ -168,8 +161,6 @@ typedef struct
clSnapshot_t snapshots[ PACKET_BACKUP ];

entityState_t entityBaselines[ MAX_GENTITIES ]; // for delta compression when not in previous frame

entityState_t parseEntities[ MAX_PARSE_ENTITIES ];
} clientActive_t;

extern clientActive_t cl;
Expand Down
2 changes: 1 addition & 1 deletion daemon/src/engine/qcommon/msg.cpp
Expand Up @@ -1202,7 +1202,7 @@ Can go from either a baseline or a previous packet_entity
*/
extern cvar_t *cl_shownet;

void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, int number )
void MSG_ReadDeltaEntity( msg_t *msg, const entityState_t *from, entityState_t *to, int number )
{
int i, lc;
int numFields;
Expand Down
2 changes: 1 addition & 1 deletion daemon/src/engine/qcommon/qcommon.h
Expand Up @@ -109,7 +109,7 @@ void MSG_WriteDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to );
void MSG_ReadDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to );

void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entityState_s *to, bool force );
void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, int number );
void MSG_ReadDeltaEntity( msg_t *msg, const entityState_t *from, entityState_t *to, int number );

void MSG_WriteDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct playerState_s *to );
void MSG_ReadDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct playerState_s *to );
Expand Down
2 changes: 2 additions & 0 deletions daemon/src/engine/server/sv_snapshot.cpp
Expand Up @@ -70,6 +70,8 @@ static void SV_EmitPacketEntities( const clientSnapshot_t *from, clientSnapshot_
int oldnum, newnum;
int from_num_entities;

MSG_WriteShort(msg, to->num_entities);

// generate the delta update
if ( !from )
{
Expand Down

0 comments on commit 98e4849

Please sign in to comment.