Skip to content

Commit

Permalink
Make snapshot_t contain server commands and use a vector for entities
Browse files Browse the repository at this point in the history
  • Loading branch information
Kangz committed Jan 17, 2015
1 parent 451ed5e commit a34a08f
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 154 deletions.
40 changes: 29 additions & 11 deletions src/engine/client/cg_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,38 @@ typedef struct

playerState_t ps; // complete information about the current player at this time

int numEntities; // all of the entities that need to be presented
entityState_t entities[ MAX_ENTITIES_IN_SNAPSHOT ]; // at the time of this snapshot
// all of the entities that need to be presented at the time of this snapshot
std::vector<entityState_t> entities;

// text based server commands to execute when this snapshot becomes current
int serverCommandSequence;
std::vector<std::string> serverCommands;
} snapshot_t;

template<> struct IPC::SerializeTraits<snapshot_t> {
static void Write(Writer& stream, const snapshot_t& snap)
{
stream.Write<int>(snap.snapFlags);
stream.Write<int>(snap.ping);
stream.Write<int>(snap.serverTime);
stream.WriteData(&snap.areamask, MAX_MAP_AREA_BYTES);
stream.Write<playerState_t>(snap.ps);
stream.Write<std::vector<entityState_t>>(snap.entities);
stream.Write<std::vector<std::string>>(snap.serverCommands);
}
static snapshot_t Read(Reader& stream)
{
snapshot_t snap;
snap.snapFlags = stream.Read<int>();
snap.ping = stream.Read<int>();
snap.serverTime = stream.Read<int>();
stream.ReadData(&snap.areamask, MAX_MAP_AREA_BYTES);
snap.ps = stream.Read<playerState_t>();
snap.entities = std::move(stream.Read<std::vector<entityState_t>>());
snap.serverCommands = std::move(stream.Read<std::vector<std::string>>());
return snap;
}
};

typedef enum {
ROCKET_STRING,
ROCKET_FLOAT,
Expand Down Expand Up @@ -121,7 +146,6 @@ typedef enum cgameImport_s
CG_CM_MARKFRAGMENTS,
CG_GETCURRENTSNAPSHOTNUMBER,
CG_GETSNAPSHOT,
CG_GETSERVERCOMMAND,
CG_GETCURRENTCMDNUMBER,
CG_GETUSERCMD,
CG_SETUSERCMDVALUE,
Expand Down Expand Up @@ -274,11 +298,6 @@ typedef IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, CG_GETSNAPSHOT>, int>,
IPC::Reply<bool, snapshot_t>
> GetSnapshotMsg;
// GetServerCommandMsg
typedef IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, CG_GETSERVERCOMMAND>, int>,
IPC::Reply<bool, std::string>
> GetServerCommandMsg;
// GetCurrentCmdNumberMsg
typedef IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, CG_GETCURRENTCMDNUMBER>>,
Expand Down Expand Up @@ -774,7 +793,7 @@ typedef IPC::SyncMessage<
> CGameStaticInitMsg;
// CGameInitMsg
typedef IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, CG_INIT>, int, int, int, glconfig_t, GameStateCSs>
IPC::Message<IPC::Id<VM::QVM, CG_INIT>, int, int, glconfig_t, GameStateCSs>
> CGameInitMsg;
// CGameShutdownMsg
typedef IPC::SyncMessage<
Expand Down Expand Up @@ -907,7 +926,6 @@ void trap_R_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs
int trap_R_LerpTag( orientation_t *tag, const refEntity_t *refent, const char *tagName, int startIndex );
void trap_GetCurrentSnapshotNumber( int *snapshotNumber, int *serverTime );
qboolean trap_GetSnapshot( int snapshotNumber, snapshot_t *snapshot );
qboolean trap_GetServerCommand( int serverCommandNumber, std::string& cmdText );
int trap_GetCurrentCmdNumber( void );
qboolean trap_GetUserCmd( int cmdNumber, usercmd_t *ucmd );
void trap_SetUserCmdValue( int stateValue, int flags, float sensitivityScale, int mpIdentClient );
Expand Down
165 changes: 68 additions & 97 deletions src/engine/client/cl_cgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,69 +100,6 @@ void CL_GetCurrentSnapshotNumber( int *snapshotNumber, int *serverTime )
*serverTime = cl.snap.serverTime;
}

/*
====================
CL_GetSnapshot
====================
*/
qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot )
{
clSnapshot_t *clSnap;
int i, count;

if ( snapshotNumber > cl.snap.messageNum )
{
Com_Error( ERR_DROP, "CL_GetSnapshot: snapshotNumber > cl.snapshot.messageNum" );
}

// if the frame has fallen out of the circular buffer, we can't return it
if ( cl.snap.messageNum - snapshotNumber >= PACKET_BACKUP )
{
return qfalse;
}

// if the frame is not valid, we can't return it
clSnap = &cl.snapshots[ snapshotNumber & PACKET_MASK ];

if ( !clSnap->valid )
{
return qfalse;
}

// 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 qfalse;
}

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

if ( count > MAX_ENTITIES_IN_SNAPSHOT )
{
Com_DPrintf( "CL_GetSnapshot: truncated %i entities to %i\n", count, MAX_ENTITIES_IN_SNAPSHOT );
count = MAX_ENTITIES_IN_SNAPSHOT;
}

snapshot->numEntities = count;

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

// FIXME: configstring changes and server commands!!!

return qtrue;
}

/*
==============
CL_SetUserCmdValue
Expand Down Expand Up @@ -332,49 +269,92 @@ bool CL_HandleServerCommand(Str::StringRef text, std::string& newText) {
return qtrue;
}

// Get the server command, does client-specific handling
// that may block the propagation of the command to cgame.
// Get the server commands, does client-specific handling
// that may block the propagation of a command to cgame.
// If the propagation is not blocked then it puts the command
// in cmdText.
// Returns false if the command was blocked.
qboolean CL_GetServerCommand( int serverCommandNumber, std::string& cmdText )
// in commands.
void CL_FillServerCommands(std::vector<std::string>& commands, int start, int end)
{
const char *s;

// if we have irretrievably lost a reliable command, drop the connection
if ( serverCommandNumber <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS )
if ( start <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS )
{
// when a demo record was started after the client got a whole bunch of
// reliable commands then the client never got those first reliable commands
if ( clc.demoplaying )
{
return qfalse;
return;
}

Com_Error( ERR_DROP, "CL_GetServerCommand: a reliable command was cycled out" );
Com_Error( ERR_DROP, "CL_FillServerCommand: a reliable command was cycled out" );
}

if ( serverCommandNumber > clc.serverCommandSequence )
if ( end > clc.serverCommandSequence )
{
Com_Error( ERR_DROP, "CL_GetServerCommand: requested a command not received" );
Com_Error( ERR_DROP, "CL_FillServerCommand: requested a command not received" );
}

s = clc.serverCommands[ serverCommandNumber & ( MAX_RELIABLE_COMMANDS - 1 ) ];
clc.lastExecutedServerCommand = serverCommandNumber;
for (int i = start; i <= end; i++) {
const char* s = clc.serverCommands[ i & ( MAX_RELIABLE_COMMANDS - 1 ) ];

std::string cmdText = s;
if (CL_HandleServerCommand(s, cmdText)) {
commands.push_back(std::move(cmdText));
}
}
}

if ( cl_showServerCommands->integer )
/*
====================
CL_GetSnapshot
====================
*/
qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot )
{
clSnapshot_t *clSnap;
int i, count;

if ( snapshotNumber > cl.snap.messageNum )
{
// NERVE - SMF
Com_Printf( "serverCommand: %i : %s\n", serverCommandNumber, s );
Com_Error( ERR_DROP, "CL_GetSnapshot: snapshotNumber > cl.snapshot.messageNum" );
}

cmdText = s;
if (CL_HandleServerCommand(s, cmdText)) {
return true;
// if the frame has fallen out of the circular buffer, we can't return it
if ( cl.snap.messageNum - snapshotNumber >= PACKET_BACKUP )
{
return qfalse;
}

cmdText = "";
return false;
// if the frame is not valid, we can't return it
clSnap = &cl.snapshots[ snapshotNumber & PACKET_MASK ];

if ( !clSnap->valid )
{
return qfalse;
}

// 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 qfalse;
}

// 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 (i = 0; i < count; i++) {
snapshot->entities.push_back(cl.parseEntities[( clSnap->parseEntitiesNum + i ) & ( MAX_PARSE_ENTITIES - 1 ) ]);
}

CL_FillServerCommands(snapshot->serverCommands, clc.lastExecutedServerCommand + 1, clSnap->serverCommandNum);
clc.lastExecutedServerCommand = clSnap->serverCommandNum;

return qtrue;
}

/*
Expand Down Expand Up @@ -1047,10 +1027,7 @@ void CL_InitCGame( void )
cls.state = CA_LOADING;

// init for this gamestate
// use the lastExecutedServerCommand instead of the serverCommandSequence
// otherwise server commands sent just before a gamestate are dropped
//bani - added clc.demoplaying, since some mods need this at init time, and drawactiveframe is too late for them
cgvm.CGameInit(clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum);
cgvm.CGameInit(clc.serverMessageSequence, clc.clientNum);

// we will send a usercmd this frame, which
// will cause the server to send us the first snapshot
Expand Down Expand Up @@ -1501,9 +1478,9 @@ void CGameVM::CGameStaticInit()
this->SendMsg<CGameStaticInitMsg>();
}

void CGameVM::CGameInit(int serverMessageNum, int serverCommandSequence, int clientNum)
void CGameVM::CGameInit(int serverMessageNum, int clientNum)
{
this->SendMsg<CGameInitMsg>(serverMessageNum, serverCommandSequence, clientNum, cls.glconfig, cl.gameState);
this->SendMsg<CGameInitMsg>(serverMessageNum, clientNum, cls.glconfig, cl.gameState);
}

void CGameVM::CGameShutdown()
Expand Down Expand Up @@ -1624,12 +1601,6 @@ void CGameVM::QVMSyscall(int index, IPC::Reader& reader, IPC::Channel& channel)
});
break;

case CG_GETSERVERCOMMAND:
IPC::HandleMsg<GetServerCommandMsg>(channel, std::move(reader), [this] (int number, bool& res, std::string& cmdText) {
res = CL_GetServerCommand(number, cmdText);
});
break;

case CG_GETCURRENTCMDNUMBER:
IPC::HandleMsg<GetCurrentCmdNumberMsg>(channel, std::move(reader), [this] (int& number) {
number = CL_GetCurrentCmdNumber();
Expand Down
2 changes: 1 addition & 1 deletion src/engine/client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ class CGameVM: public VM::VMBase {
void Start();

void CGameStaticInit();
void CGameInit(int serverMessageNum, int serverCommandSequence, int clientNum);
void CGameInit(int serverMessageNum, int clientNum);
void CGameShutdown();
void CGameDrawActiveFrame(int serverTime, bool demoPlayback);
int CGameCrosshairPlayer();
Expand Down
9 changes: 1 addition & 8 deletions src/gamelogic/cgame/cg_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

int VM::VM_API_VERSION = CGAME_API_VERSION;

void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum, glconfig_t gl, GameStateCSs gameState );
void CG_Init( int serverMessageNum, int clientNum, glconfig_t gl, GameStateCSs gameState );
void CG_RegisterCvars( void );
void CG_Shutdown( void );

Expand Down Expand Up @@ -171,13 +171,6 @@ qboolean trap_GetSnapshot( int snapshotNumber, snapshot_t *snapshot )
return res;
}

qboolean trap_GetServerCommand( int serverCommandNumber, std::string& cmdText )
{
bool res;
VM::SendMsg<GetServerCommandMsg>(serverCommandNumber, res, cmdText);
return res;
}

int trap_GetCurrentCmdNumber( void )
{
int res;
Expand Down
2 changes: 1 addition & 1 deletion src/gamelogic/cgame/cg_beacon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ void CG_ListBeacons( void )
cbeacon_t *b;
vec3_t delta;

for( cg.beaconCount = 0, i = 0; i < cg.snap->numEntities; i++ )
for( cg.beaconCount = 0, i = 0; i < cg.snap->entities.size(); i++ )
{
cent = cg_entities + cg.snap->entities[ i ].number;
es = &cent->currentState;
Expand Down
2 changes: 1 addition & 1 deletion src/gamelogic/cgame/cg_buildable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2252,7 +2252,7 @@ void CG_DrawBuildableStatus( void )
return;
}

for ( i = 0; i < cg.snap->numEntities; i++ )
for ( i = 0; i < cg.snap->entities.size(); i++ )
{
cent = &cg_entities[ cg.snap->entities[ i ].number ];
es = &cent->currentState;
Expand Down
6 changes: 3 additions & 3 deletions src/gamelogic/cgame/cg_ents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,7 @@ void CG_AddPacketEntities( void )
}

// add each entity sent over by the server
for ( num = 0; num < cg.snap->numEntities; num++ )
for ( num = 0; num < cg.snap->entities.size(); num++ )
{
cent = &cg_entities[ cg.snap->entities[ num ].number ];
cent->valid = qtrue;
Expand All @@ -1320,7 +1320,7 @@ void CG_AddPacketEntities( void )
}

// add each entity sent over by the server
for ( num = 0; num < cg.snap->numEntities; num++ )
for ( num = 0; num < cg.snap->entities.size(); num++ )
{
cent = &cg_entities[ cg.snap->entities[ num ].number ];
CG_AddCEntity( cent );
Expand All @@ -1329,7 +1329,7 @@ void CG_AddPacketEntities( void )
//make an attempt at drawing bounding boxes of selected entity types
if ( cg_drawBBOX.integer )
{
for ( num = 0; num < cg.snap->numEntities; num++ )
for ( num = 0; num < cg.snap->entities.size(); num++ )
{
float x, zd, zu;
vec3_t mins, maxs;
Expand Down
3 changes: 1 addition & 2 deletions src/gamelogic/cgame/cg_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,6 @@ typedef struct
float screenXBias;
float aspectScale;

int serverCommandSequence; // reliable command stream counter
int processedSnapshotNum; // the number of snapshots cgame has requested

// parsed from serverinfo
Expand Down Expand Up @@ -2180,7 +2179,7 @@ void CG_ShowScores_f( void );
//
// cg_servercmds.c
//
void CG_ExecuteNewServerCommands( int latestSequence );
void CG_ExecuteServerCommands( snapshot_t* snap );
void CG_ParseServerinfo( void );
void CG_SetConfigValues( void );
void CG_ShaderStateChanged( void );
Expand Down
Loading

0 comments on commit a34a08f

Please sign in to comment.