本文整理汇总了C++中MSG_Bitstream函数的典型用法代码示例。如果您正苦于以下问题:C++ MSG_Bitstream函数的具体用法?C++ MSG_Bitstream怎么用?C++ MSG_Bitstream使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了MSG_Bitstream函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: SV_ExecuteClientMessage
/*
===================
SV_ExecuteClientMessage
Parse a client packet
===================
*/
void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
int c;
int serverId;
MSG_Bitstream(msg);
serverId = MSG_ReadLong( msg );
cl->messageAcknowledge = MSG_ReadLong( msg );
if (cl->messageAcknowledge < 0) {
// usually only hackers create messages like this
// it is more annoying for them to let them hanging
//SV_DropClient( cl, "illegible client message" );
return;
}
cl->reliableAcknowledge = MSG_ReadLong( msg );
// NOTE: when the client message is fux0red the acknowledgement numbers
// can be out of range, this could cause the server to send thousands of server
// commands which the server thinks are not yet acknowledged in SV_UpdateServerCommandsToClient
if (cl->reliableAcknowledge < cl->reliableSequence - MAX_RELIABLE_COMMANDS) {
// usually only hackers create messages like this
// it is more annoying for them to let them hanging
//SV_DropClient( cl, "illegible client message" );
cl->reliableAcknowledge = cl->reliableSequence;
return;
}
// if this is a usercmd from a previous gamestate,
// ignore it or retransmit the current gamestate
//
// if the client was downloading, let it stay at whatever serverId and
// gamestate it was at. This allows it to keep downloading even when
// the gamestate changes. After the download is finished, we'll
// notice and send it a new game state
if ( serverId != sv.serverId && !*cl->downloadName ) {
if ( serverId == sv.restartedServerId ) {
// they just haven't caught the map_restart yet
return;
}
// if we can tell that the client has dropped the last
// gamestate we sent them, resend it
if ( cl->messageAcknowledge > cl->gamestateMessageNum ) {
Com_DPrintf( "%s : dropped gamestate, resending\n", cl->name );
SV_SendClientGameState( cl );
}
return;
}
// read optional clientCommand strings
do {
c = MSG_ReadByte( msg );
if ( c == clc_EOF ) {
break;
}
if ( c != clc_clientCommand ) {
break;
}
if ( !SV_ClientCommand( cl, msg ) ) {
return; // we couldn't execute it because of the flood protection
}
if (cl->state == CS_ZOMBIE) {
return; // disconnect command
}
} while ( 1 );
// read the usercmd_t
if ( c == clc_move ) {
SV_UserMove( cl, msg, qtrue );
} else if ( c == clc_moveNoDelta ) {
SV_UserMove( cl, msg, qfalse );
} else if ( c != clc_EOF ) {
Com_Printf( "WARNING: bad command byte for client %i\n", cl - svs.clients );
}
// if ( msg->readcount != msg->cursize ) {
// Com_Printf( "WARNING: Junk at end of packet for client %i\n", cl - svs.clients );
// }
}
示例2: SV_ExecuteClientMessage
/*
===================
SV_ExecuteClientMessage
Parse a client packet
===================
*/
void SV_ExecuteClientMessage( client_t *cl, msg_t *msg )
{
int c;
int serverId;
MSG_Bitstream( msg );
serverId = MSG_ReadLong( msg );
cl->messageAcknowledge = MSG_ReadLong( msg );
if ( cl->messageAcknowledge < 0 )
{
// usually only hackers create messages like this
// it is more annoying for them to let them hanging
#ifndef NDEBUG
SV_DropClient( cl, "DEBUG: illegible client message" );
#endif
return;
}
cl->reliableAcknowledge = MSG_ReadLong( msg );
// NOTE: when the client message is fux0red the acknowledgement numbers
// can be out of range, this could cause the server to send thousands of server
// commands which the server thinks are not yet acknowledged in SV_UpdateServerCommandsToClient
if ( cl->reliableAcknowledge < cl->reliableSequence - MAX_RELIABLE_COMMANDS )
{
// usually only hackers create messages like this
// it is more annoying for them to let them hanging
#ifndef NDEBUG
SV_DropClient( cl, "DEBUG: illegible client message" );
#endif
cl->reliableAcknowledge = cl->reliableSequence;
return;
}
// if this is a usercmd from a previous gamestate,
// ignore it or retransmit the current gamestate
//
// if the client was downloading, let it stay at whatever serverId and
// gamestate it was at. This allows it to keep downloading even when
// the gamestate changes. After the download is finished, we'll
// notice and send it a new game state
//
// show_bug.cgi?id=536
// don't drop as long as previous command was a nextdl, after a dl is done, downloadName is set back to ""
// but we still need to read the next message to move to next download or send gamestate
// I don't like this hack though, it must have been working fine at some point, suspecting the fix is somewhere else
if ( serverId != sv.serverId && !*cl->downloadName && !strstr( cl->lastClientCommandString, "nextdl" ) )
{
if ( serverId >= sv.restartedServerId && serverId < sv.serverId )
{
// TTimo - use a comparison here to catch multiple map_restart
// they just haven't caught the map_restart yet
Log::Debug( "%s^7: ignoring pre map_restart / outdated client message", cl->name );
return;
}
// if we can tell that the client has dropped the last
// gamestate we sent them, resend it
if ( cl->messageAcknowledge > cl->gamestateMessageNum )
{
Log::Debug( "%s^7: dropped gamestate, resending", cl->name );
SV_SendClientGameState( cl );
}
// read optional clientCommand strings
do
{
c = MSG_ReadByte( msg );
if ( c == clc_EOF )
{
break;
}
if ( c != clc_clientCommand )
{
break;
}
if ( !SV_ClientCommand( cl, msg, true ) )
{
return; // we couldn't execute it because of the flood protection
}
if ( cl->state == clientState_t::CS_ZOMBIE )
{
return; // disconnect command
}
}
while ( 1 );
//.........这里部分代码省略.........
示例3: SVD_StartDemoFile
/*
Start a server-side demo.
This does it all, create the file and adjust the demo-related
stuff in client_t.
This is mostly ripped from sv_client.c/SV_SendClientGameState
and cl_main.c/CL_Record_f.
*/
static void SVD_StartDemoFile(client_t *client, const char *path)
{
int i, len;
entityState_t *base, nullstate;
msg_t msg;
byte buffer[MAX_MSGLEN];
fileHandle_t file;
#ifdef USE_DEMO_FORMAT_42
char *s;
int v, size;
#endif
Com_DPrintf("SVD_StartDemoFile\n");
assert(!client->demo_recording);
// create the demo file and write the necessary header
file = FS_FOpenFileWrite(path);
assert(file != 0);
/* File_write_header_demo // ADD this fx */
/* HOLBLIN entete demo */
#ifdef USE_DEMO_FORMAT_42
//@Barbatos: get the mod version from the server
s = Cvar_VariableString("g_modversion");
size = strlen( s );
len = LittleLong( size );
FS_Write( &len, 4, file );
FS_Write( s , size , file );
v = LittleLong( PROTOCOL_VERSION );
FS_Write ( &v, 4 , file );
len = 0;
len = LittleLong( len );
FS_Write ( &len, 4 , file );
FS_Write ( &len, 4 , file );
#endif
/* END HOLBLIN entete demo */
MSG_Init(&msg, buffer, sizeof(buffer));
MSG_Bitstream(&msg); // XXX server code doesn't do this, client code does
MSG_WriteLong(&msg, client->lastClientCommand); // TODO: or is it client->reliableSequence?
MSG_WriteByte(&msg, svc_gamestate);
MSG_WriteLong(&msg, client->reliableSequence);
for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
if (sv.configstrings[i][0]) {
MSG_WriteByte(&msg, svc_configstring);
MSG_WriteShort(&msg, i);
MSG_WriteBigString(&msg, sv.configstrings[i]);
}
}
Com_Memset(&nullstate, 0, sizeof(nullstate));
for (i = 0 ; i < MAX_GENTITIES; i++) {
base = &sv.svEntities[i].baseline;
if (!base->number) {
continue;
}
MSG_WriteByte(&msg, svc_baseline);
MSG_WriteDeltaEntity(&msg, &nullstate, base, qtrue);
}
MSG_WriteByte(&msg, svc_EOF);
MSG_WriteLong(&msg, client - svs.clients);
MSG_WriteLong(&msg, sv.checksumFeed);
MSG_WriteByte(&msg, svc_EOF); // XXX server code doesn't do this, SV_Netchan_Transmit adds it!
len = LittleLong(client->netchan.outgoingSequence-1);
FS_Write(&len, 4, file);
len = LittleLong (msg.cursize);
FS_Write(&len, 4, file);
FS_Write(msg.data, msg.cursize, file);
#ifdef USE_DEMO_FORMAT_42
// add size of packet in the end for backward play /* holblin */
FS_Write(&len, 4, file);
#endif
FS_Flush(file);
// adjust client_t to reflect demo started
client->demo_recording = qtrue;
client->demo_file = file;
client->demo_waiting = qtrue;
//.........这里部分代码省略.........
示例4: CL_ParseServerMessage
/*
=====================
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage( msg_t *msg ) {
int cmd;
if ( cl_shownet->integer == 1 ) {
Com_Printf ("%i ",msg->cursize);
} else if ( cl_shownet->integer >= 2 ) {
Com_Printf ("------------------\n");
}
MSG_Bitstream(msg);
// get the reliable sequence acknowledge number
clc.reliableAcknowledge = MSG_ReadLong( msg );
//
if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
clc.reliableAcknowledge = clc.reliableSequence;
}
//
// parse the message
//
while ( 1 ) {
if ( msg->readcount > msg->cursize ) {
Com_Error (ERR_DROP,"CL_ParseServerMessage: read past end of server message");
break;
}
cmd = MSG_ReadByte( msg );
if (cmd == svc_EOF) {
SHOWNET( msg, "END OF MESSAGE" );
break;
}
if ( cl_shownet->integer >= 2 ) {
if ( (cmd < 0) || (!svc_strings[cmd]) ) {
Com_Printf( "%3i:BAD CMD %i\n", msg->readcount-1, cmd );
} else {
SHOWNET( msg, svc_strings[cmd] );
}
}
// other commands
switch ( cmd ) {
default:
Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message");
break;
case svc_nop:
break;
case svc_serverCommand:
CL_ParseCommandString( msg );
break;
case svc_gamestate:
CL_ParseGamestate( msg );
break;
case svc_snapshot:
CL_ParseSnapshot( msg );
break;
case svc_download:
CL_ParseDownload( msg );
break;
case svc_voipSpeex:
#ifdef USE_VOIP
CL_ParseVoip( msg, qtrue );
#endif
break;
case svc_voipOpus:
#ifdef USE_VOIP
CL_ParseVoip( msg, !clc.voipEnabled );
#endif
break;
}
}
}
示例5: CL_WritePacket
/*
===================
CL_WritePacket
Create and send the command packet to the server
Including both the reliable commands and the usercmds
A client packet will contain something like:
4 sequence number
2 qport
4 serverid
4 acknowledged sequence number
4 clc.serverCommandSequence
<optional reliable commands>
1 clc_move or clc_moveNoDelta
1 command count
<count * usercmds>
===================
*/
void CL_WritePacket()
{
msg_t buf;
byte data[ MAX_MSGLEN ];
int i, j;
usercmd_t *cmd, *oldcmd;
usercmd_t nullcmd;
int packetNum;
int oldPacketNum;
int count;
// don't send anything if playing back a demo
if ( clc.demoplaying || cls.state == CA_CINEMATIC )
{
return;
}
memset( &nullcmd, 0, sizeof( nullcmd ) );
oldcmd = &nullcmd;
MSG_Init( &buf, data, sizeof( data ) );
MSG_Bitstream( &buf );
// write the current serverId so the server
// can tell if this is from the current gameState
MSG_WriteLong( &buf, cl.serverId );
// write the last message we received, which can
// be used for delta compression, and is also used
// to tell if we dropped a gamestate
MSG_WriteLong( &buf, clc.serverMessageSequence );
// write the last reliable message we received
MSG_WriteLong( &buf, clc.serverCommandSequence );
// write any unacknowledged clientCommands
// NOTE TTimo: if you verbose this, you will see that there are quite a few duplicates
// typically several unacknowledged cp or userinfo commands stacked up
for ( i = clc.reliableAcknowledge + 1; i <= clc.reliableSequence; i++ )
{
MSG_WriteByte( &buf, clc_clientCommand );
MSG_WriteLong( &buf, i );
MSG_WriteString( &buf, clc.reliableCommands[ i & ( MAX_RELIABLE_COMMANDS - 1 ) ] );
}
// we want to send all the usercmds that were generated in the last
// few packet, so even if a couple packets are dropped in a row,
// all the cmds will make it to the server
if ( cl_packetdup->integer < 0 )
{
Cvar_Set( "cl_packetdup", "0" );
}
else if ( cl_packetdup->integer > 5 )
{
Cvar_Set( "cl_packetdup", "5" );
}
oldPacketNum = ( clc.netchan.outgoingSequence - 1 - cl_packetdup->integer ) & PACKET_MASK;
count = cl.cmdNumber - cl.outPackets[ oldPacketNum ].p_cmdNumber;
if ( count > MAX_PACKET_USERCMDS )
{
count = MAX_PACKET_USERCMDS;
Com_Printf( "MAX_PACKET_USERCMDS" );
}
#ifdef USE_VOIP
if ( clc.voipOutgoingDataSize > 0 )
{
if ( ( clc.voipFlags & VOIP_SPATIAL ) || Com_IsVoipTarget( clc.voipTargets, sizeof( clc.voipTargets ), -1 ) )
{
MSG_WriteByte( &buf, clc_voip );
MSG_WriteByte( &buf, clc.voipOutgoingGeneration );
MSG_WriteLong( &buf, clc.voipOutgoingSequence );
MSG_WriteByte( &buf, clc.voipOutgoingDataFrames );
MSG_WriteData( &buf, clc.voipTargets, sizeof( clc.voipTargets ) );
MSG_WriteByte( &buf, clc.voipFlags );
MSG_WriteShort( &buf, clc.voipOutgoingDataSize );
//.........这里部分代码省略.........
示例6: CL_ParseServerMessage
/*
=====================
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage(msg_t *msg)
{
int cmd;
if (cl_shownet->integer == 1)
{
Com_Printf("%i ", msg->cursize);
}
else if (cl_shownet->integer >= 2)
{
Com_Printf("------------------\n");
}
MSG_Bitstream(msg);
// get the reliable sequence acknowledge number
clc.reliableAcknowledge = MSG_ReadLong(msg);
if (clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS)
{
clc.reliableAcknowledge = clc.reliableSequence;
}
// parse the message
while (1)
{
if (msg->readcount > msg->cursize)
{
Com_Error(ERR_DROP, "CL_ParseServerMessage: read past end of server message");
break;
}
cmd = MSG_ReadByte(msg);
if (cmd == svc_EOF)
{
SHOWNET(msg, "END OF MESSAGE");
break;
}
if (cl_shownet->integer >= 2)
{
if (cmd < 0 || cmd > svc_EOF) // MSG_ReadByte might return -1 and we can't access our svc_strings array ...
{
Com_Printf("%3i:BAD BYTE %i\n", msg->readcount - 1, cmd); // -> ERR_DROP
}
else
{
if (!svc_strings[cmd])
{
Com_Printf("%3i:BAD CMD %i\n", msg->readcount - 1, cmd);
}
else
{
SHOWNET(msg, svc_strings[cmd]);
}
}
}
// other commands
switch (cmd)
{
default:
Com_Error(ERR_DROP, "CL_ParseServerMessage: Illegible server message %d", cmd);
break;
case svc_nop:
break;
case svc_serverCommand:
CL_ParseCommandString(msg);
break;
case svc_gamestate:
CL_ParseGamestate(msg);
break;
case svc_snapshot:
CL_ParseSnapshot(msg);
break;
case svc_download:
CL_ParseDownload(msg);
break;
}
}
CL_ParseBinaryMessage(msg);
}
示例7: CL_WritePacket
/*
===================
CL_WritePacket
Create and send the command packet to the server
Including both the reliable commands and the usercmds
During normal gameplay, a client packet will contain something like:
4 sequence number
2 qport
4 serverid
4 acknowledged sequence number
4 clc.serverCommandSequence
<optional reliable commands>
1 clc_move or clc_moveNoDelta
1 command count
<count * usercmds>
===================
*/
void CL_WritePacket( void ) {
msg_t buf;
byte data[MAX_MSGLEN];
int i, j;
usercmd_t *cmd, *oldcmd;
usercmd_t nullcmd;
int packetNum;
int oldPacketNum;
int count, key;
// don't send anything if playing back a demo
if ( clc.demoplaying || cls.state == CA_CINEMATIC ) {
return;
}
Com_Memset( &nullcmd, 0, sizeof(nullcmd) );
oldcmd = &nullcmd;
MSG_Init( &buf, data, sizeof(data) );
MSG_Bitstream( &buf );
// write the current serverId so the server
// can tell if this is from the current gameState
MSG_WriteLong( &buf, cl.serverId );
// write the last message we received, which can
// be used for delta compression, and is also used
// to tell if we dropped a gamestate
MSG_WriteLong( &buf, clc.serverMessageSequence );
// write the last reliable message we received
MSG_WriteLong( &buf, clc.serverCommandSequence );
// write any unacknowledged clientCommands
for ( i = clc.reliableAcknowledge + 1 ; i <= clc.reliableSequence ; i++ ) {
MSG_WriteByte( &buf, clc_clientCommand );
MSG_WriteLong( &buf, i );
MSG_WriteString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
}
// we want to send all the usercmds that were generated in the last
// few packet, so even if a couple packets are dropped in a row,
// all the cmds will make it to the server
if ( cl_packetdup->integer < 0 ) {
Cvar_Set( "cl_packetdup", "0" );
} else if ( cl_packetdup->integer > 5 ) {
Cvar_Set( "cl_packetdup", "5" );
}
oldPacketNum = (clc.netchan.outgoingSequence - 1 - cl_packetdup->integer) & PACKET_MASK;
count = cl.cmdNumber - cl.outPackets[ oldPacketNum ].p_cmdNumber;
if ( count > MAX_PACKET_USERCMDS ) {
count = MAX_PACKET_USERCMDS;
Com_Printf("MAX_PACKET_USERCMDS\n");
}
if ( count >= 1 ) {
if ( cl_showSend->integer ) {
Com_Printf( "(%i)", count );
}
// begin a client move command
if ( cl_nodelta->integer || !cl.snap.valid
|| clc.demowaiting
|| clc.serverMessageSequence != cl.snap.messageNum ) {
MSG_WriteByte (&buf, clc_moveNoDelta);
} else {
MSG_WriteByte (&buf, clc_move);
}
// write the command count
MSG_WriteByte( &buf, count );
// use the checksum feed in the key
key = clc.checksumFeed;
// also use the message acknowledge
key ^= clc.serverMessageSequence;
// also use the last acknowledged server command in the key
key ^= Com_HashKey(clc.serverCommands[ clc.serverCommandSequence & (MAX_RELIABLE_COMMANDS-1) ], 32);
// write all the commands, including the predicted command
//.........这里部分代码省略.........
示例8: CL_PeekSnapshot
//.........这里部分代码省略.........
cl.parseEntitiesNum = parseEntitiesNumOrig;
return qfalse;
}
buf.cursize = LittleLong(buf.cursize);
if (buf.cursize == -1)
{
Com_FuncPrinf("buf.cursize == -1\n");
FS_Seek(clc.demofile, origPosition, FS_SEEK_SET);
clc.lastPacketTime = lastPacketTimeOrig;
cl.parseEntitiesNum = parseEntitiesNumOrig;
return qfalse;
}
if (buf.cursize > buf.maxsize)
{
Com_FuncDrop("demoMsglen > MAX_MSGLEN");
return qfalse;
}
r = FS_Read(buf.data, buf.cursize, clc.demofile);
if (r != buf.cursize)
{
Com_FuncPrinf("Demo file was truncated.\n");
FS_Seek(clc.demofile, origPosition, FS_SEEK_SET);
clc.lastPacketTime = lastPacketTimeOrig;
cl.parseEntitiesNum = parseEntitiesNumOrig;
return qfalse;
}
clc.lastPacketTime = cls.realtime;
buf.readcount = 0;
MSG_Bitstream(&buf);
// get the reliable sequence acknowledge number
MSG_ReadLong(&buf);
// parse the message
while (qtrue)
{
if (buf.readcount > buf.cursize)
{
Com_FuncDrop("read past end of server message");
return qfalse;
}
cmd = MSG_ReadByte(&buf);
if (cmd == svc_EOF)
{
break;
}
success = qfalse;
switch (cmd)
{
default:
Com_FuncDrop("Illegible server message");
return qfalse;
case svc_nop:
break;
case svc_serverCommand:
MSG_ReadLong(&buf); // seq
//s = MSG_ReadString(&buf);
MSG_ReadString(&buf);
break;
示例9: CL_ParseDemo
// Do very shallow parse of the demo (could be extended) just to get times and snapshot count
static void CL_ParseDemo(void)
{
int tstart = 0;
int demofile = 0;
// Reset our demo data
memset(&di, 0, sizeof(di));
// Parse start
di.gameStartTime = -1;
di.gameEndTime = -1;
FS_Seek(clc.demofile, 0, FS_SEEK_SET);
tstart = Sys_Milliseconds();
while (qtrue)
{
int r;
msg_t buf;
msg_t *msg;
byte bufData[MAX_MSGLEN];
int s;
int cmd;
di.demoPos = FS_FTell(clc.demofile);
// get the sequence number
r = FS_Read(&s, 4, clc.demofile);
if (r != 4)
{
CL_DemoCompleted();
return;
}
clc.serverMessageSequence = LittleLong(s);
// init the message
MSG_Init(&buf, bufData, sizeof(bufData));
// get the length
r = FS_Read(&buf.cursize, 4, clc.demofile);
if (r != 4)
{
break;
}
buf.cursize = LittleLong(buf.cursize);
if (buf.cursize == -1)
{
break;
}
if (buf.cursize > buf.maxsize)
{
Com_FuncPrinf("demoMsglen > MAX_MSGLEN");
break;
}
r = FS_Read(buf.data, buf.cursize, clc.demofile);
if (r != buf.cursize)
{
Com_FuncPrinf("Demo file was truncated.\n");
break;
}
clc.lastPacketTime = cls.realtime;
buf.readcount = 0;
// parse
msg = &buf;
MSG_Bitstream(msg);
// get the reliable sequence acknowledge number
clc.reliableAcknowledge = MSG_ReadLong(msg);
if (clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS)
{
clc.reliableAcknowledge = clc.reliableSequence;
}
// parse the message
while (qtrue)
{
if (msg->readcount > msg->cursize)
{
Com_FuncDrop("read past end of server message");
return;
}
cmd = MSG_ReadByte(msg);
if (cmd == svc_EOF)
{
break;
}
// other commands
switch (cmd)
{
//.........这里部分代码省略.........
示例10: CL_Record
void CL_Record(const char *name)
{
int i;
msg_t buf;
byte bufData[MAX_MSGLEN];
entityState_t *ent;
entityState_t nullstate;
char *s;
int len;
// open the demo file
Com_FuncPrinf("Recording to %s.\n", name);
clc.demofile = FS_FOpenFileWrite(name);
if (!clc.demofile)
{
Com_FuncPrinf("ERROR: couldn't open.\n");
return;
}
clc.demorecording = qtrue;
Cvar_Set("cl_demorecording", "1"); // fretn
Q_strncpyz(clc.demoName, demoName, sizeof(clc.demoName));
Cvar_Set("cl_demofilename", clc.demoName); // bani
Cvar_Set("cl_demooffset", "0"); // bani
// don't start saving messages until a non-delta compressed message is received
clc.demowaiting = qtrue;
// write out the gamestate message
MSG_Init(&buf, bufData, sizeof(bufData));
MSG_Bitstream(&buf);
// NOTE: all server->client messages now acknowledge
MSG_WriteLong(&buf, clc.reliableSequence);
MSG_WriteByte(&buf, svc_gamestate);
MSG_WriteLong(&buf, clc.serverCommandSequence);
// configstrings
for (i = 0; i < MAX_CONFIGSTRINGS; i++)
{
if (!cl.gameState.stringOffsets[i])
{
continue;
}
s = cl.gameState.stringData + cl.gameState.stringOffsets[i];
MSG_WriteByte(&buf, svc_configstring);
MSG_WriteShort(&buf, i);
MSG_WriteBigString(&buf, s);
}
// baselines
memset(&nullstate, 0, sizeof(nullstate));
for (i = 0; i < MAX_GENTITIES; i++)
{
ent = &cl.entityBaselines[i];
if (!ent->number)
{
continue;
}
MSG_WriteByte(&buf, svc_baseline);
MSG_WriteDeltaEntity(&buf, &nullstate, ent, qtrue);
}
MSG_WriteByte(&buf, svc_EOF);
// finished writing the gamestate stuff
// write the client num
MSG_WriteLong(&buf, clc.clientNum);
// write the checksum feed
MSG_WriteLong(&buf, clc.checksumFeed);
// finished writing the client packet
MSG_WriteByte(&buf, svc_EOF);
// write it to the demo file
len = LittleLong(clc.serverMessageSequence - 1);
FS_Write(&len, 4, clc.demofile);
len = LittleLong(buf.cursize);
FS_Write(&len, 4, clc.demofile);
FS_Write(buf.data, buf.cursize, clc.demofile);
// the rest of the demo file will be copied from net messages
}
示例11: demoConvert
//.........这里部分代码省略.........
newnum = MSG_ReadBits( &oldMsg, GENTITYNUM_BITS );
} else if (oldnum > newnum) {
MSG_ReadDeltaEntity( &oldMsg, &convert->entityBaselines[newnum], newstate , newnum );
if ( newstate->number != MAX_GENTITIES-1)
workFrame->entityData[ newstate->number ] = 1;
newnum = MSG_ReadBits( &oldMsg, GENTITYNUM_BITS );
}
if (newstate->number == MAX_GENTITIES-1)
continue;
parseEntitiesNum++;
parseEntitiesNum &= (MAX_PARSE_ENTITIES-1);
newSnap->numEntities++;
}}
/* Stop processing this further since it's an invalid snap due to lack of delta data */
if (!newSnap->valid)
break;
/* Skipped snapshots will be set invalid in the circular buffer */
if ( newSnap->messageNum - convert->lastMessageNum >= PACKET_BACKUP ) {
convert->lastMessageNum = newSnap->messageNum - ( PACKET_BACKUP - 1 );
}
for ( ; convert->lastMessageNum < newSnap->messageNum ; convert->lastMessageNum++ ) {
convert->snapshots[convert->lastMessageNum & PACKET_MASK].valid = qfalse;
}
convert->lastMessageNum = newSnap->messageNum + 1;
/* compress the frame into the new format */
if (nextTime > oldTime) {
demoFrame_t *cleanFrame;
int writeIndex;
for (temp = 0;temp<newSnap->numEntities;temp++) {
int p = (newSnap->parseEntitiesNum+temp) & (MAX_PARSE_ENTITIES-1);
entityState_t *newState = &convert->parseEntities[p];
workFrame->entities[newState->number] = *newState;
}
workFrame->clientData[clientNum] = 1;
workFrame->clients[clientNum] = newSnap->ps;
workFrame->serverTime = nextTime;
/* Which frame from the cache to save */
writeIndex = convert->frameIndex - (DEMOCONVERTFRAMES/2);
if (writeIndex >= 0) {
const demoFrame_t *newFrame;
msg_t writeMsg;
// init the message
MSG_Init( &writeMsg, demoBuffer, sizeof (demoBuffer));
MSG_Clear( &writeMsg );
MSG_Bitstream( &writeMsg );
newFrame = &convert->frames[ writeIndex % DEMOCONVERTFRAMES];
if ( smoothen )
demoFrameInterpolate( convert->frames, DEMOCONVERTFRAMES, writeIndex );
if ( nextTime > fullTime || writeIndex <= 0 ) {
/* Plan the next time for a full write */
fullTime = nextTime + 2000;
demoFramePack( &writeMsg, newFrame, 0 );
} else {
const demoFrame_t *oldFrame = &convert->frames[ ( writeIndex -1 ) % DEMOCONVERTFRAMES];
demoFramePack( &writeMsg, newFrame, oldFrame );
}
/* Write away the new data in the msg queue */
temp = LittleLong( writeMsg.cursize );
FS_Write (&temp, 4, newHandle );
FS_Write ( writeMsg.data , writeMsg.cursize, newHandle );
}
/* Clean up the upcoming frame for all new changes */
convert->frameIndex++;
cleanFrame = &convert->frames[ convert->frameIndex % DEMOCONVERTFRAMES];
cleanFrame->serverTime = 0;
for (temp = 0;temp<MAX_GENTITIES;temp++)
cleanFrame->entities[temp].number = MAX_GENTITIES-1;
Com_Memset( cleanFrame->clientData, 0, sizeof ( cleanFrame->clientData ));
Com_Memcpy( cleanFrame->string.data, workFrame->string.data, workFrame->string.used );
Com_Memcpy( cleanFrame->string.offsets, workFrame->string.offsets, sizeof( workFrame->string.offsets ));
cleanFrame->string.used = workFrame->string.used;
cleanFrame->commandUsed = 0;
/* keep track of this last frame's time */
oldTime = nextTime;
}
break;
case svc_download:
// read block number
temp = MSG_ReadShort ( &oldMsg );
if (!temp) //0 block, read file size
MSG_ReadLong( &oldMsg );
// read block size
temp = MSG_ReadShort ( &oldMsg );
// read the data block
for ( ;temp>0;temp--)
MSG_ReadByte( &oldMsg );
break;
}
}
}
conversionerror:
FS_FCloseFile( oldHandle );
FS_FCloseFile( newHandle );
Z_Free( convert );
return;
}
示例12: CL_ParseServerMessage
/*
=====================
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage( msg_t *msg ) {
int cmd;
if ( cl_shownet->integer == 1 ) {
Com_Printf ("%i ",msg->cursize);
} else if ( cl_shownet->integer >= 2 ) {
Com_Printf ("------------------\n");
}
MSG_Bitstream(msg);
// get the reliable sequence acknowledge number
clc.reliableAcknowledge = MSG_ReadLong( msg );
//
if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
clc.reliableAcknowledge = clc.reliableSequence;
}
//
// parse the message
//
while ( 1 ) {
if ( msg->readcount > msg->cursize ) {
Com_Error (ERR_DROP,"CL_ParseServerMessage: read past end of server message");
break;
}
cmd = MSG_ReadByte( msg );
if ( cmd == svc_EOF) {
SHOWNET( msg, "END OF MESSAGE" );
break;
}
if ( cl_shownet->integer >= 2 ) {
if ( !svc_strings[cmd] ) {
Com_Printf( "%3i:BAD CMD %i\n", msg->readcount-1, cmd );
} else {
SHOWNET( msg, svc_strings[cmd] );
}
}
// other commands
switch ( cmd ) {
default:
Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message\n");
break;
case svc_nop:
break;
case svc_serverCommand:
CL_ParseCommandString( msg );
break;
case svc_gamestate:
CL_ParseGamestate( msg );
break;
case svc_snapshot:
CL_ParseSnapshot( msg );
break;
case svc_download:
CL_ParseDownload( msg );
break;
case svc_lua:
//Make Lua VMCall Here. -Hxrmn
CL_SetLuaMessage(msg);
VM_Call (cgvm, CG_LUA_MSG);
break;
}
}
}
示例13: CL_ParseServerMessage
/*
=====================
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage( msg_t *msg )
{
int cmd;
// msg_t msgback;
// msgback = *msg;
if ( cl_shownet->integer == 1 )
{
Com_Printf("%i ", msg->cursize );
}
else if ( cl_shownet->integer >= 2 )
{
Com_Printf( "------------------\n" );
}
MSG_Bitstream( msg );
// get the reliable sequence acknowledge number
clc.reliableAcknowledge = MSG_ReadLong( msg );
//
if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS )
{
clc.reliableAcknowledge = clc.reliableSequence;
}
//
// parse the message
//
while ( 1 )
{
if ( msg->readcount > msg->cursize )
{
Com_Error( ERR_DROP, "CL_ParseServerMessage: read past end of server message" );
}
cmd = MSG_ReadByte( msg );
// See if this is an extension command after the EOF, which means we
// got data that a legacy client should ignore.
if ( ( cmd == svc_EOF ) && ( MSG_LookaheadByte( msg ) == svc_extension ) )
{
SHOWNET( msg, "EXTENSION" );
MSG_ReadByte( msg ); // throw the svc_extension byte away.
cmd = MSG_ReadByte( msg ); // something legacy clients can't do!
// sometimes you get a svc_extension at end of stream...dangling
// bits in the huffman decoder giving a bogus value?
if ( cmd == -1 )
{
cmd = svc_EOF;
}
}
if ( cmd == svc_EOF )
{
SHOWNET( msg, "END OF MESSAGE" );
break;
}
if ( cl_shownet->integer >= 2 )
{
if ( !svc_strings[ cmd ] )
{
Com_Printf( "%3i:BAD CMD %i\n", msg->readcount - 1, cmd );
}
else
{
SHOWNET( msg, svc_strings[ cmd ] );
}
}
// other commands
switch ( cmd )
{
default:
Com_Error( ERR_DROP, "CL_ParseServerMessage: Illegible server message %d", cmd );
case svc_nop:
break;
case svc_serverCommand:
CL_ParseCommandString( msg );
break;
case svc_gamestate:
CL_ParseGamestate( msg );
break;
case svc_snapshot:
CL_ParseSnapshot( msg );
break;
case svc_download:
//.........这里部分代码省略.........
示例14: demoCutWriteDeltaSnapshot
void demoCutWriteDeltaSnapshot(int firstServerCommand, fileHandle_t f, qboolean forceNonDelta, clientConnection_t *clcCut, clientActive_t *clCut) {
msg_t msgImpl, *msg = &msgImpl;
byte msgData[MAX_MSGLEN];
clSnapshot_t *frame, *oldframe;
int lastframe = 0;
int snapFlags;
MSG_Init(msg, msgData, sizeof(msgData));
MSG_Bitstream(msg);
MSG_WriteLong(msg, clcCut->reliableSequence);
// copy over any commands
for (int serverCommand = firstServerCommand; serverCommand <= clcCut->serverCommandSequence; serverCommand++) {
char *command = clcCut->serverCommands[serverCommand & (MAX_RELIABLE_COMMANDS - 1)];
MSG_WriteByte(msg, svc_serverCommand);
MSG_WriteLong(msg, serverCommand/* + serverCommandOffset*/);
MSG_WriteString(msg, command);
}
// this is the snapshot we are creating
frame = &clCut->snap;
if (clCut->snap.messageNum > 0 && !forceNonDelta) {
lastframe = 1;
oldframe = &clCut->snapshots[(clCut->snap.messageNum - 1) & PACKET_MASK]; // 1 frame previous
if (!oldframe->valid) {
// not yet set
lastframe = 0;
oldframe = NULL;
}
} else {
lastframe = 0;
oldframe = NULL;
}
MSG_WriteByte(msg, svc_snapshot);
// send over the current server time so the client can drift
// its view of time to try to match
MSG_WriteLong(msg, frame->serverTime);
// what we are delta'ing from
MSG_WriteByte(msg, lastframe);
snapFlags = frame->snapFlags;
MSG_WriteByte(msg, snapFlags);
// send over the areabits
MSG_WriteByte(msg, sizeof(frame->areamask));
MSG_WriteData(msg, frame->areamask, sizeof(frame->areamask));
// delta encode the playerstate
if (oldframe) {
#ifdef _ONEBIT_COMBO
MSG_WriteDeltaPlayerstate(msg, &oldframe->ps, &frame->ps, frame->pDeltaOneBit, frame->pDeltaNumBit);
#else
MSG_WriteDeltaPlayerstate(msg, &oldframe->ps, &frame->ps);
#endif
if (frame->ps.m_iVehicleNum) {
//then write the vehicle's playerstate too
if (!oldframe->ps.m_iVehicleNum) {
//if last frame didn't have vehicle, then the old vps isn't gonna delta
//properly (because our vps on the client could be anything)
#ifdef _ONEBIT_COMBO
MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, NULL, NULL, qtrue);
#else
MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, qtrue);
#endif
} else {
#ifdef _ONEBIT_COMBO
MSG_WriteDeltaPlayerstate(msg, &oldframe->vps, &frame->vps, frame->pDeltaOneBitVeh, frame->pDeltaNumBitVeh, qtrue);
#else
MSG_WriteDeltaPlayerstate(msg, &oldframe->vps, &frame->vps, qtrue);
#endif
}
}
} else {
#ifdef _ONEBIT_COMBO
MSG_WriteDeltaPlayerstate(msg, NULL, &frame->ps, NULL, NULL);
#else
MSG_WriteDeltaPlayerstate(msg, NULL, &frame->ps);
#endif
if (frame->ps.m_iVehicleNum) {
//then write the vehicle's playerstate too
#ifdef _ONEBIT_COMBO
MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, NULL, NULL, qtrue);
#else
MSG_WriteDeltaPlayerstate(msg, NULL, &frame->vps, qtrue);
#endif
}
}
// delta encode the entities
demoCutEmitPacketEntities(oldframe, frame, msg, clCut);
MSG_WriteByte(msg, svc_EOF);
demoCutWriteDemoMessage(msg, f, clcCut);
}
示例15: SVD_StartDemoFile
/*
Start a server-side demo.
This does it all, create the file and adjust the demo-related
stuff in client_t.
This is mostly ripped from sv_client.c/SV_SendClientGameState
and cl_main.c/CL_Record_f.
*/
static void SVD_StartDemoFile(client_t *client, const char *path)
{
int i, len;
entityState_t *base, nullstate;
msg_t msg;
byte buffer[MAX_MSGLEN];
fileHandle_t file;
Com_DPrintf("SVD_StartDemoFile\n");
assert(!client->demo_recording);
// create the demo file and write the necessary header
file = FS_FOpenFileWrite(path);
assert(file != 0);
MSG_Init(&msg, buffer, sizeof(buffer));
MSG_Bitstream(&msg); // XXX server code doesn't do this, client code does
MSG_WriteLong(&msg, client->lastClientCommand); // TODO: or is it client->reliableSequence?
MSG_WriteByte(&msg, svc_gamestate);
MSG_WriteLong(&msg, client->reliableSequence);
for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
if (sv.configstrings[i][0]) {
MSG_WriteByte(&msg, svc_configstring);
MSG_WriteShort(&msg, i);
MSG_WriteBigString(&msg, sv.configstrings[i]);
}
}
Com_Memset(&nullstate, 0, sizeof(nullstate));
for (i = 0 ; i < MAX_GENTITIES; i++) {
base = &sv.svEntities[i].baseline;
if (!base->number) {
continue;
}
MSG_WriteByte(&msg, svc_baseline);
MSG_WriteDeltaEntity(&msg, &nullstate, base, qtrue);
}
MSG_WriteByte(&msg, svc_EOF);
MSG_WriteLong(&msg, client - svs.clients);
MSG_WriteLong(&msg, sv.checksumFeed);
MSG_WriteByte(&msg, svc_EOF); // XXX server code doesn't do this, SV_Netchan_Transmit adds it!
len = LittleLong(client->netchan.outgoingSequence-1);
FS_Write(&len, 4, file);
len = LittleLong (msg.cursize);
FS_Write(&len, 4, file);
FS_Write(msg.data, msg.cursize, file);
FS_Flush(file);
// adjust client_t to reflect demo started
client->demo_recording = qtrue;
client->demo_file = file;
client->demo_waiting = qtrue;
client->demo_backoff = 1;
client->demo_deltas = 0;
}