本文整理汇总了C++中MSG_WriteString函数的典型用法代码示例。如果您正苦于以下问题:C++ MSG_WriteString函数的具体用法?C++ MSG_WriteString怎么用?C++ MSG_WriteString使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了MSG_WriteString函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Host_Name_f
/*
======================
Host_Name_f
======================
*/
void Host_Name_f (void)
{
char newName[32];
if (Cmd_Argc () == 1)
{
Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
return;
}
if (Cmd_Argc () == 2)
q_strlcpy(newName, Cmd_Argv(1), sizeof(newName));
else
q_strlcpy(newName, Cmd_Args(), sizeof(newName));
newName[15] = 0; // client_t structure actually says name[32].
if (cmd_source == src_command)
{
if (Q_strcmp(cl_name.string, newName) == 0)
return;
Cvar_Set ("_cl_name", newName);
if (cls.state == ca_connected)
Cmd_ForwardToServer ();
return;
}
if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
{
if (Q_strcmp(host_client->name, newName) != 0)
Con_Printf ("%s renamed to %s\n", host_client->name, newName);
}
Q_strcpy (host_client->name, newName);
host_client->edict->v.netname = PR_SetEngineString(host_client->name);
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
MSG_WriteString (&sv.reliable_datagram, host_client->name);
}
示例2: Cam_Lock
void Cam_Lock(int playernum)
{
char st[32];
if (Cmd_FindAlias("f_trackspectate"))
{
Cbuf_AddTextEx (&cbuf_main, "f_trackspectate\n");
}
if (cl_multiview.value && cls.mvdplayback)
return;
snprintf(st, sizeof (st), "ptrack %i", playernum);
if (cls.mvdplayback) {
memcpy(cl.stats, cl.players[playernum].stats, sizeof(cl.stats));
ideal_track = playernum;
}
last_lock = cls.realtime;
if (cls.mvdplayback == QTV_PLAYBACK)
{
// its not setinfo extension, but adding new extension just for this is stupid IMO
QTV_Cmd_Printf(QTV_EZQUAKE_EXT_SETINFO, st);
}
else
{
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, st);
}
spec_track = playernum;
locked = false;
Sbar_Changed();
if (TP_NeedRefreshSkins())
TP_RefreshSkins();
}
示例3: CL_Download_f
/*
===============
CL_Download_f
Request a download from the server
===============
*/
void CL_Download_f (void)
{
char filename[MAX_OSPATH];
if (Cmd_Argc() != 2) {
Com_Printf("Usage: download <filename>\n");
return;
}
Com_sprintf(filename, sizeof(filename), "%s", Cmd_Argv(1));
if (strstr (filename, ".."))
{
Com_Printf ("Refusing to download a path with ..\n");
return;
}
if (FS_LoadFile (filename, NULL) != -1)
{ // it exists, no need to download
Com_Printf("File already exists.\n");
return;
}
strcpy (cls.downloadname, filename);
Com_Printf ("Downloading %s\n", cls.downloadname);
// download to a temp name, and only rename
// to the real name when done, so if interrupted
// a runt file wont be left
COM_StripExtension (cls.downloadname, cls.downloadtempname);
strcat (cls.downloadtempname, ".tmp");
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message,
va("download %s", cls.downloadname));
cls.downloadnumber++;
}
示例4: MSG_BeginWriting
void CHelperManager_Encoder::SendMessage_Added_toPlayer (
playerCharacter_t* pHelper, char* name, int level, int job, int worldIdx )
{
MSG_BeginWriting ( &netMessage );
MSG_Clear( &netMessage );
{
MSG_WriteByte(&netMessage, EXTEND_SECOND);
MSG_WriteShort( &netMessage, HELPER_SYSTEM );
MSG_WriteShort( &netMessage, SC_SEND_ADD_toPlayer );
MSG_WriteByte ( &netMessage, level );
MSG_WriteByte ( &netMessage, job );
MSG_WriteByte ( &netMessage, worldIdx );
MSG_WriteString ( &netMessage, name );
if ( pHelper->ready )
{
NET_SendMessage ( &pHelper->sock, &netMessage );
}
}
MSG_EndWriting(&netMessage);
}
示例5: SV_Modellist_f
/*
==================
SV_Modellist_f
==================
*/
static void SV_Modellist_f (void)
{
int i;
if (host_client->state != cs_connected)
{
Con_Printf ("modellist not valid -- already spawned\n");
return;
}
// handle the case of a level changing while a client was connecting
if ( atoi(Cmd_Argv(1)) != svs.spawncount )
{
Con_Printf ("%s from different level\n", __thisfunc__);
SV_New_f ();
return;
}
MSG_WriteByte (&host_client->netchan.message, svc_modellist);
for (i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++)
MSG_WriteString (&host_client->netchan.message, sv.model_precache[i]);
MSG_WriteByte (&host_client->netchan.message, 0);
}
示例6: Host_Name_f
/*
======================
Host_Name_f
======================
*/
void Host_Name_f (void)
{
char *newName;
if (Cmd_Argc () == 1)
{
Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
return;
}
if (Cmd_Argc () == 2)
newName = Cmd_Argv(1);
else
newName = Cmd_Args();
newName[15] = 0;
if (cmd_source == src_command)
{
if (Q_strcmp(cl_name.string, newName) == 0)
return;
Cvar_Set ("_cl_name", newName);
if (cls.state == ca_connected)
Cmd_ForwardToServer ();
return;
}
if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
if (Q_strcmp(host_client->name, newName) != 0)
Con_Printf ("%s renamed to %s\n", host_client->name, newName);
Q_strcpy (host_client->name, newName);
host_client->edict->v.netname = host_client->name - pr_strings;
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
MSG_WriteString (&sv.reliable_datagram, host_client->name);
}
示例7: Cam_Unlock
void Cam_Unlock(void)
{
if (Cmd_FindAlias("f_freeflyspectate"))
{
Cbuf_AddTextEx (&cbuf_main, "f_freeflyspectate\n");
}
if (!autocam)
{
return;
}
if (cls.mvdplayback == QTV_PLAYBACK)
{
// its not setinfo extension, but adding new extension just for this is stupid IMO
QTV_Cmd_Printf(QTV_EZQUAKE_EXT_SETINFO, "ptrack");
}
else
{
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, "ptrack");
}
autocam = CAM_NONE;
locked = false;
Sbar_Changed();
if (cls.mvdplayback && cl.teamfortress)
{
V_TF_ClearGrenadeEffects ();
}
if (TP_NeedRefreshSkins())
{
TP_RefreshSkins();
}
}
示例8: SV_FullClientUpdate
/*
===================
SV_FullClientUpdate
Writes all update values to a sizebuf
===================
*/
void SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
{
int i;
char info[MAX_INFO_STRING];
i = client - svs.clients;
if (client->state == cs_free && sv_fastconnect.value)
return;
MSG_WriteByte (buf, svc_updatefrags);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, client->old_frags);
MSG_WriteByte (buf, svc_updateping);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, SV_CalcPing (client));
MSG_WriteByte (buf, svc_updatepl);
MSG_WriteByte (buf, i);
MSG_WriteByte (buf, client->lossage);
MSG_WriteByte (buf, svc_updateentertime);
MSG_WriteByte (buf, i);
MSG_WriteFloat (buf, svs.realtime - client->connection_started);
strcpy (info, client->userinfo);
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
Info_RemoveKey (info, "pmodel");
Info_RemoveKey (info, "emodel");
MSG_WriteByte (buf, svc_updateuserinfo);
MSG_WriteByte (buf, i);
MSG_WriteLong (buf, client->userid);
MSG_WriteString (buf, info);
}
示例9: _Datagram_SearchForHosts
static void _Datagram_SearchForHosts (qboolean xmit)
{
int ret;
int n;
int i;
struct qsockaddr readaddr;
struct qsockaddr myaddr;
int control;
dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
if (xmit)
{
SZ_Clear(&net_message);
// save space for the header, filled in later
MSG_WriteLong(&net_message, 0);
MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
MSG_WriteString(&net_message, "QUAKE");
MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
SZ_Clear(&net_message);
}
while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
{
if (ret < sizeof(int))
continue;
net_message.cursize = ret;
// don't answer our own query
if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
continue;
// is the cache full?
if (hostCacheCount == HOSTCACHESIZE)
continue;
MSG_BeginReading ();
control = BigLong(*((int *)net_message.data));
MSG_ReadLong();
if (control == -1)
continue;
if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
continue;
if ((control & NETFLAG_LENGTH_MASK) != ret)
continue;
if (MSG_ReadByte() != CCREP_SERVER_INFO)
continue;
dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
// search the cache for this server
for (n = 0; n < hostCacheCount; n++)
if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
break;
// is it already there?
if (n < hostCacheCount)
continue;
// add it
hostCacheCount++;
Q_strcpy(hostcache[n].name, MSG_ReadString());
Q_strcpy(hostcache[n].map, MSG_ReadString());
hostcache[n].users = MSG_ReadByte();
hostcache[n].maxusers = MSG_ReadByte();
if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
{
Q_strcpy(hostcache[n].cname, hostcache[n].name);
hostcache[n].cname[14] = 0;
Q_strcpy(hostcache[n].name, "*");
Q_strcat(hostcache[n].name, hostcache[n].cname);
}
Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
hostcache[n].driver = net_driverlevel;
hostcache[n].ldriver = net_landriverlevel;
Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
// check for a name conflict
for (i = 0; i < hostCacheCount; i++)
{
if (i == n)
continue;
if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
{
i = Q_strlen(hostcache[n].name);
if (i < 15 && hostcache[n].name[i-1] > '8')
{
hostcache[n].name[i] = '0';
hostcache[n].name[i+1] = 0;
}
else
hostcache[n].name[i-1]++;
i = -1;
}
}
}
}
示例10: SV_New_f
/*
* SV_New_f
*
* Sends the first message from the server to a connected client.
* This will be sent on the initial connection and upon each server load.
*/
static void SV_New_f( client_t *client )
{
int playernum;
unsigned int numpure;
purelist_t *purefile;
edict_t *ent;
int sv_bitflags = 0;
Com_DPrintf( "New() from %s\n", client->name );
// if in CS_AWAITING we have sent the response packet the new once already,
// but client might have not got it so we send it again
if( client->state >= CS_SPAWNED )
{
Com_Printf( "New not valid -- already spawned\n" );
return;
}
//
// serverdata needs to go over for all types of servers
// to make sure the protocol is right, and to set the gamedir
//
SV_InitClientMessage( client, &tmpMessage, NULL, 0 );
// send the serverdata
MSG_WriteByte( &tmpMessage, svc_serverdata );
MSG_WriteLong( &tmpMessage, APP_PROTOCOL_VERSION );
MSG_WriteLong( &tmpMessage, svs.spawncount );
MSG_WriteShort( &tmpMessage, (unsigned short)svc.snapFrameTime );
MSG_WriteString( &tmpMessage, FS_BaseGameDirectory() );
MSG_WriteString( &tmpMessage, FS_GameDirectory() );
playernum = client - svs.clients;
MSG_WriteShort( &tmpMessage, playernum );
// send full levelname
MSG_WriteString( &tmpMessage, sv.mapname );
//
// game server
//
if( sv.state == ss_game )
{
// set up the entity for the client
ent = EDICT_NUM( playernum+1 );
ent->s.number = playernum+1;
client->edict = ent;
if( sv_pure->integer )
sv_bitflags |= SV_BITFLAGS_PURE;
if( client->reliable )
sv_bitflags |= SV_BITFLAGS_RELIABLE;
if( SV_Web_Running() )
{
const char *baseurl = SV_Web_UpstreamBaseUrl();
sv_bitflags |= SV_BITFLAGS_HTTP;
if( baseurl[0] )
sv_bitflags |= SV_BITFLAGS_HTTP_BASEURL;
}
MSG_WriteByte( &tmpMessage, sv_bitflags );
}
if( sv_bitflags & SV_BITFLAGS_HTTP )
{
if( sv_bitflags & SV_BITFLAGS_HTTP_BASEURL )
MSG_WriteString( &tmpMessage, sv_http_upstream_baseurl->string );
else
MSG_WriteShort( &tmpMessage, sv_http_port->integer ); // HTTP port number
}
// always write purelist
numpure = Com_CountPureListFiles( svs.purelist );
if( numpure > (short)0x7fff )
Com_Error( ERR_DROP, "Error: Too many pure files." );
MSG_WriteShort( &tmpMessage, numpure );
purefile = svs.purelist;
while( purefile )
{
MSG_WriteString( &tmpMessage, purefile->filename );
MSG_WriteLong( &tmpMessage, purefile->checksum );
purefile = purefile->next;
}
SV_ClientResetCommandBuffers( client );
SV_SendMessageToClient( client, &tmpMessage );
Netchan_PushAllFragments( &client->netchan );
// don't let it send reliable commands until we get the first configstring request
client->state = CS_CONNECTING;
}
示例11: PC_SetSummonsInfo
void CHelperManager_Encoder::SendMessage_RequestSummons(playerCharacter_t* pHelper,char* toName)
{
int idx=GTH_FindPCByName(toName);
if (0 <= idx)
{
playerCharacter_t* pTaker=gcpTools->GetPlayerRecordPointer(idx);
if(NULL == pTaker) return;
if( (playerCharacter_t::tagGonryunBattlePractice::MEMBERSHIP_LEADER
== pTaker->GonryunBattlePractice.MemberShip) ||
(playerCharacter_t::tagGonryunBattlePractice::MEMBERSHIP_OPENENT
== pTaker->GonryunBattlePractice.MemberShip)) return;
if((pTaker->worldIdx == tagGolryunBattle::Golryun_Battle_Map_Index) ||
(pTaker->worldIdx == DAN_BATTLEMAP_NO)) return;
if(BUSY_STATE_NONE != pTaker->busyState) return;
PC_SetSummonsInfo(pTaker, pHelper->name, pHelper->worldIdx, pHelper->position);
MSG_BeginWriting(&netMessage);
MSG_Clear( &netMessage );
{
MSG_WriteByte(&netMessage, EXTEND_SECOND);
MSG_WriteShort ( &netMessage, HELPER_SYSTEM );
MSG_WriteShort(&netMessage, SC_SPAWN_Req_toTaker);
MSG_WriteString(&netMessage, pHelper->name);
NET_SendMessage(&pTaker->sock, &netMessage);
}
MSG_EndWriting(&netMessage);
}
else
{
MSG_BeginWriting(&netMessage);
MSG_Clear( &netMessage );
{
MSG_WriteByte(&netMessage, EXTEND_SECOND);
MSG_WriteShort ( &netMessage, HELPER_SYSTEM );
MSG_WriteShort(&netMessage, SS_SPAWN_Req_fromServer);
MSG_WriteString(&netMessage, toName);
MSG_WriteString(&netMessage, pHelper->name);
MSG_WriteByte(&netMessage, pHelper->worldIdx);
MSG_WritePosition(&netMessage, pHelper->position);
if ( TRUE == g_config.isManager )
{
for (int serveridx=1; serveridx < MAX_MEMBER_SERVER; serveridx++)
{
if ( !g_memberServer[serveridx].active ) continue;
NET_SendUnreliableMessage(&g_memberServer[serveridx].sock, &netMessage);
}
}
else
{
MSG_WriteByte(&netMessage, g_config.gameServerNo);
NET_SendUnreliableMessage(&localSocket, &netMessage);
}
}
MSG_EndWriting(&netMessage);
}
}
示例12: 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
//.........这里部分代码省略.........
示例13: SV_NextDownload_f
/*
* SV_NextDownload_f
*
* Responds to reliable nextdl packet with unreliable download packet
* If nextdl packet's offet information is negative, download will be stopped
*/
static void SV_NextDownload_f( client_t *client )
{
int blocksize;
int offset;
if( !client->download.name )
{
Com_Printf( "nextdl message for client with no download active, from: %s\n", client->name );
return;
}
if( Q_stricmp( client->download.name, Cmd_Argv( 1 ) ) )
{
Com_Printf( "nextdl message for wrong filename, from: %s\n", client->name );
return;
}
offset = atoi( Cmd_Argv( 2 ) );
if( offset > client->download.size )
{
Com_Printf( "nextdl message with too big offset, from: %s\n", client->name );
return;
}
if( offset == -1 )
{
Com_Printf( "Upload of %s to %s%s completed\n", client->download.name, client->name, S_COLOR_WHITE );
if( client->download.data )
{
FS_FreeBaseFile( client->download.data );
client->download.data = NULL;
}
Mem_ZoneFree( client->download.name );
client->download.name = NULL;
client->download.size = 0;
client->download.timeout = 0;
return;
}
if( offset < 0 )
{
Com_Printf( "Upload of %s to %s%s failed\n", client->download.name, client->name, S_COLOR_WHITE );
if( client->download.data )
{
FS_FreeBaseFile( client->download.data );
client->download.data = NULL;
}
Mem_ZoneFree( client->download.name );
client->download.name = NULL;
client->download.size = 0;
client->download.timeout = 0;
return;
}
if( !client->download.data )
{
Com_Printf( "Starting server upload of %s to %s\n", client->download.name, client->name );
FS_LoadBaseFile( client->download.name, (void **)&client->download.data, NULL, 0 );
if( !client->download.data )
{
Com_Printf( "Error loading %s for uploading\n", client->download.name );
Mem_ZoneFree( client->download.name );
client->download.name = NULL;
client->download.size = 0;
client->download.timeout = 0;
return;
}
}
SV_InitClientMessage( client, &tmpMessage, NULL, 0 );
SV_AddReliableCommandsToMessage( client, &tmpMessage );
blocksize = client->download.size - offset;
// jalfixme: adapt download to user rate setting and sv_maxrate setting.
if( blocksize > FRAGMENT_SIZE * 2 )
blocksize = FRAGMENT_SIZE * 2;
if( offset + blocksize > client->download.size )
blocksize = client->download.size - offset;
MSG_WriteByte( &tmpMessage, svc_download );
MSG_WriteString( &tmpMessage, client->download.name );
MSG_WriteLong( &tmpMessage, offset );
MSG_WriteLong( &tmpMessage, blocksize );
MSG_CopyData( &tmpMessage, client->download.data + offset, blocksize );
SV_SendMessageToClient( client, &tmpMessage );
client->download.timeout = svs.realtime + 10000;
}
示例14: CL_SendCmd
/*
=================
CL_SendCmd
=================
*/
void CL_SendCmd (void)
{
sizebuf_t buf;
byte data[128];
int i;
usercmd_t *cmd, *oldcmd;
usercmd_t nullcmd;
int checksumIndex;
// clear buffer
memset (&buf, 0, sizeof(buf));
// build a command even if not connected
// save this command off for prediction
i = cls.netchan.outgoing_sequence & (CMD_BACKUP-1);
cmd = &cl.cmds[i];
cl.cmd_time[i] = cls.realtime; // for netgraph ping calculation
*cmd = CL_CreateCmd ();
cl.cmd = *cmd;
if (cls.state == ca_disconnected || cls.state == ca_connecting)
return;
if (cls.state == ca_connected)
{
if (cls.netchan.message.cursize || curtime - cls.netchan.last_sent > 1000 )
Netchan_Transmit (&cls.netchan, 0, buf.data);
return;
}
// send a userinfo update if needed
if (userinfo_modified)
{
CL_FixUpGender();
userinfo_modified = false;
MSG_WriteByte (&cls.netchan.message, clc_userinfo);
MSG_WriteString (&cls.netchan.message, Cvar_Userinfo() );
}
SZ_Init (&buf, data, sizeof(data));
// Knightmare- removed this, put ESC-only substitute in keys.c
/*if (cmd->buttons && cl.cinematictime > 0 && !cl.attractloop
&& cls.realtime - cl.cinematictime > 1000)
{ // skip the rest of the cinematic
SCR_FinishCinematic ();
}*/
// begin a client move command
MSG_WriteByte (&buf, clc_move);
// save the position for a checksum byte
checksumIndex = buf.cursize;
MSG_WriteByte (&buf, 0);
// let the server know what the last frame we
// got was, so the next message can be delta compressed
if (cl_nodelta->value || !cl.frame.valid || cls.demowaiting)
MSG_WriteLong (&buf, -1); // no compression
else
MSG_WriteLong (&buf, cl.frame.serverframe);
// send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered
i = (cls.netchan.outgoing_sequence-2) & (CMD_BACKUP-1);
cmd = &cl.cmds[i];
memset (&nullcmd, 0, sizeof(nullcmd));
MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence-1) & (CMD_BACKUP-1);
cmd = &cl.cmds[i];
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP-1);
cmd = &cl.cmds[i];
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
// calculate a checksum over the move commands
buf.data[checksumIndex] = COM_BlockSequenceCRCByte(
buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
cls.netchan.outgoing_sequence);
//
// deliver the message
//
Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);
}
示例15: SV_ServerRecord_f
/*
==============
SV_ServerRecord_f
Begins server demo recording. Every entity and every message will be
recorded, but no playerinfo will be stored. Primarily for demo merging.
==============
*/
static void SV_ServerRecord_f (void)
{
char name[MAX_OSPATH];
byte buf_data[32768];
sizebuf_t buf;
int len;
int i;
size_t size;
if (Cmd_Argc() != 2) {
Com_Printf ("serverrecord <demoname>\n");
return;
}
if (svs.demofile) {
Com_Printf ("Already recording.\n");
return;
}
if (sv.state != ss_game) {
Com_Printf ("You must be in a level to record.\n");
return;
}
//
// open the demo file
//
Com_sprintf (name, sizeof(name), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv(1));
FS_CreatePath(name);
svs.demofile = fopen (name, "wb");
if (!svs.demofile) {
Com_Printf ("ERROR: couldn't open.\n");
return;
}
Com_Printf ("recording to %s.\n", name);
// setup a buffer to catch all multicasts
SZ_Init (&svs.demo_multicast, svs.demo_multicast_buf, sizeof(svs.demo_multicast_buf));
//
// write a single giant fake message with all the startup info
//
SZ_Init (&buf, buf_data, sizeof(buf_data));
//
// serverdata needs to go over for all types of servers
// to make sure the protocol is right, and to set the gamedir
//
// send the serverdata
MSG_WriteByte (&buf, svc_serverdata);
MSG_WriteLong (&buf, PROTOCOL_VERSION_DEFAULT);
MSG_WriteLong (&buf, svs.spawncount);
// 2 means server demo
MSG_WriteByte (&buf, 2); // demos are always attract loops
MSG_WriteString (&buf, Cvar_VariableString ("gamedir"));
MSG_WriteShort (&buf, -1);
// send full levelname
MSG_WriteString (&buf, sv.configstrings[CS_NAME]);
for (i=0 ; i<MAX_CONFIGSTRINGS ; i++)
if (sv.configstrings[i][0])
{
MSG_WriteByte (&buf, svc_configstring);
MSG_WriteShort (&buf, i);
MSG_WriteString (&buf, sv.configstrings[i]);
}
// write it to the demo file
Com_DPrintf ("signon message length: %i\n", buf.cursize);
len = LittleLong (buf.cursize);
size = fwrite (&len, 4, 1, svs.demofile);
size = fwrite (buf.data, buf.cursize, 1, svs.demofile);
// the rest of the demo file will be individual frames
}