Ejemplo n.º 1
0
void HL2Rcon_SourceRconSendChatToEachClient( const char *text, rconUser_t *self, int cid, qboolean onlyme){

	rconUser_t* user;
	int i;
	msg_t msg;
	int32_t *updatelen;
	byte sourcemsgbuf[MAX_MSGLEN];



	for(i = 0, user = sourceRcon.activeRconUsers; i < MAX_RCONUSERS; i++, user++ ){

		if(!user->streamchat)
			continue;

		MSG_Init(&msg, sourcemsgbuf, sizeof(sourcemsgbuf));
		MSG_WriteLong(&msg, 0); //writing 0 for now
		MSG_WriteLong(&msg, 0);
		MSG_WriteLong(&msg, SERVERDATA_CHAT);

		if(self){
			if(self == user)
			{

				MSG_WriteByte(&msg, -2);
			}else{

				MSG_WriteByte(&msg, -1);
				if(onlyme)
				{
				    continue;
				}
			}
			MSG_WriteBigString(&msg, user->rconUsername);

		}else{

			MSG_WriteByte(&msg, cid);
		}


		MSG_WriteBigString(&msg, text);
		MSG_WriteByte(&msg, 0);

		//Adjust the length
		updatelen = (int32_t*)msg.data;
		*updatelen = msg.cursize - 4;

		NET_SendData(user->remote.sock, &msg);
	}
}
Ejemplo n.º 2
0
void HL2Rcon_SourceRconFlushRedirect(char* outputbuf, qboolean lastcommand){

	rconUser_t* user;

	if(sourceRcon.redirectUser < 1 || sourceRcon.redirectUser > MAX_RCONUSERS)
		return;

	user = &sourceRcon.activeRconUsers[sourceRcon.redirectUser -1];

	msg_t msg;
	int32_t *updatelen;
	byte sourcemsgbuf[HL2RCON_SOURCEOUTPUTBUF_LENGTH+16];

	MSG_Init(&msg, sourcemsgbuf, sizeof(sourcemsgbuf));
	MSG_WriteLong(&msg, 0); //writing 0 for now
	MSG_WriteLong(&msg, user->lastpacketid);
	MSG_WriteLong(&msg, SERVERDATA_RESPONSE_VALUE);
	MSG_WriteBigString(&msg, outputbuf);

	MSG_WriteByte(&msg, 0);

	//Adjust the length
	updatelen = (int32_t*)msg.data;
	*updatelen = msg.cursize - 4;

	NET_SendData(user->remote.sock, &msg);
}
Ejemplo n.º 3
0
static void demoFramePack( msg_t *msg, const demoFrame_t *newFrame, const demoFrame_t *oldFrame ) {
	int i;
	/* Full or delta frame marker */
	MSG_WriteBits( msg, oldFrame ? 0 : 1, 1 );
	MSG_WriteLong( msg, newFrame->serverTime );
	/* Add the config strings */
	for (i = 0;i<MAX_CONFIGSTRINGS;i++) {
		const char *oldString = !oldFrame ? "" : &oldFrame->string.data[oldFrame->string.offsets[i]];
		const char *newString = newFrame->string.data + newFrame->string.offsets[i];
		if (strcmp( oldString, newString)) {
			MSG_WriteShort( msg, i );
			MSG_WriteBigString( msg, newString );
		}
	}
	MSG_WriteShort( msg, MAX_CONFIGSTRINGS );
	/* Add the playerstates */
	for (i=0; i<MAX_CLIENTS; i++) {
		const playerState_t *oldPlayer, *newPlayer;
		if (!newFrame->clientData[i])
			continue;
		oldPlayer = (!oldFrame || !oldFrame->clientData[i]) ? &demoNullPlayerState : &oldFrame->clients[i];
		newPlayer = &newFrame->clients[i];
		MSG_WriteByte( msg, i );
		MSG_WriteDeltaPlayerstate( msg, oldPlayer, newPlayer );
	}
	MSG_WriteByte( msg, MAX_CLIENTS );
	/* Add the entities */
	for (i=0; i<MAX_GENTITIES-1; i++) {
		const entityState_t *oldEntity, *newEntity;
		newEntity = &newFrame->entities[i];
		if (oldFrame) {
			oldEntity = &oldFrame->entities[i];
			if (oldEntity->number == (MAX_GENTITIES -1))
				oldEntity = 0;
		} else {
			oldEntity = 0;
		}
		if (newEntity->number != i || newEntity->number >= (MAX_GENTITIES -1)) {
			newEntity = 0;
		} else {
			if (!oldEntity) {
				oldEntity = &demoNullEntityState;
			}
		}
		MSG_WriteDeltaEntity( msg, oldEntity, newEntity, qfalse );
	}
	MSG_WriteBits( msg, (MAX_GENTITIES-1), GENTITYNUM_BITS );
	/* Add the area mask */
	MSG_WriteByte( msg, newFrame->areaUsed );
	MSG_WriteData( msg, newFrame->areamask, newFrame->areaUsed );
	/* Add the command string data */
	MSG_WriteLong( msg, newFrame->commandUsed );
	MSG_WriteData( msg, newFrame->commandData, newFrame->commandUsed );
}
Ejemplo n.º 4
0
void SV_CreateClientGameStateMessage( client_t *client, msg_t *msg ) {
	int			start;
	entityState_t	*base, nullstate;

	// NOTE, MRE: all server->client messages now acknowledge
	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( msg, client->lastClientCommand );

	// send any server commands waiting to be sent first.
	// we have to do this cause we send the client->reliableSequence
	// with a gamestate and it sets the clc.serverCommandSequence at
	// the client side
	SV_UpdateServerCommandsToClient( client, msg );

	// send the gamestate
	MSG_WriteByte( msg, svc_gamestate );
	MSG_WriteLong( msg, client->reliableSequence );

	// write the configstrings
	for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) {
		if (sv.configstrings[start][0]) {
			MSG_WriteByte( msg, svc_configstring );
			MSG_WriteShort( msg, start );
			MSG_WriteBigString( msg, sv.configstrings[start] );
		}
	}

	// write the baselines
	Com_Memset( &nullstate, 0, sizeof( nullstate ) );
	for ( start = 0 ; start < MAX_GENTITIES; start++ ) {
		base = &sv.svEntities[start].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);

	// write the checksum feed
	MSG_WriteLong( msg, sv.checksumFeed);

	// For old RMG system.
	MSG_WriteShort ( msg, 0 );
}
Ejemplo n.º 5
0
void HL2Rcon_SourceRconSendDataToEachClient( const byte* data, int msglen, int type){

	rconUser_t* user;
	int i;
	msg_t msg;
	int32_t *updatelen;
	byte sourcemsgbuf[MAX_MSGLEN];
	qboolean msgbuild = qfalse;

	for(i = 0, user = sourceRcon.activeRconUsers; i < MAX_RCONUSERS; i++, user++ ){

		if(!user->streamgamelog && type == SERVERDATA_GAMELOG)
			continue;

		if(!user->streamlog && type == SERVERDATA_CONLOG)
			continue;

		if(!user->streamevents && type == SERVERDATA_EVENT)
			continue;

		
		if(!msgbuild){
			MSG_Init(&msg, sourcemsgbuf, sizeof(sourcemsgbuf));
			MSG_WriteLong(&msg, 0); //writing 0 for now
			MSG_WriteLong(&msg, 0);
			MSG_WriteLong(&msg, type);

			if(type == SERVERDATA_EVENT)
				MSG_WriteData(&msg, data, msglen);
			else
				MSG_WriteBigString(&msg, (char*)data);

			MSG_WriteByte(&msg, 0);

			//Adjust the length
			updatelen = (int32_t*)msg.data;
			*updatelen = msg.cursize - 4;
			msgbuild = qtrue;
		}
		NET_SendData(user->remote.sock, &msg);
	}
}
Ejemplo n.º 6
0
/*
====================
CL_Record_f

record <slot> [<demoname>]

Begins recording a demo from the current position
====================
*/
void CL_Record( client_t	*cl, char *s ) {
	char		name[MAX_OSPATH];
	char		name_zip[MAX_OSPATH];
	byte		bufData[MAX_MSGLEN];
	msg_t	buf;
	int			i;
	int			len;
	entityState_t	*ent;
	entityState_t	nullstate;
	int         clientnum;
	char	*guid;
	char	prefix[MAX_OSPATH];

	clientnum = cl - svs.clients;

	if ( cl->demorecording ) {
		Com_Printf ("Already recording client %i.\n", clientnum);
		return;
	}

//	if ( cl->state != CA_ACTIVE ) {
//		Com_Printf ("You must be in a level to record.\n");
//		return;
//	}
//  // sync 0 doesn't prevent recording, so not forcing it off .. everyone does g_sync 1 ; record ; g_sync 0 ..
//	if ( NET_IsLocalAddress( cl->serverAddress ) && !Cvar_VariableValue( "g_synchronousClients" ) ) {
//		Com_Printf (S_COLOR_YELLOW "WARNING: You should set 'g_synchronousClients 1' for smoother demo recording\n");
//	}

	if ( s ) {
		Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", s, PROTOCOL_VERSION );
	} else {
		int		number,n,a,b,c,d;
		guid = Info_ValueForKey(cl->userinfo, "cl_guid");
		if (!Q_stricmp(guid, "")) {
			guid = "LONGGONE";
		}
		Q_strncpyz(prefix, guid, 9);

		// scan for a free demo name
		for ( number = 0 ; number <= 9999 ; number++ ) {
			if(number < 0 || number > 9999)
				number = 9999;
			n = number;
			a = n / 1000;
			n -= a*1000;
			b = n / 100;
			n -= b*100;
			c = n / 10;
			n -= c*10;
			d = n;

			Com_sprintf (name, sizeof(name), "demos/%s_%s_%i%i%i%i.dm_%d", prefix, sv_mapname->string, a, b, c, d, PROTOCOL_VERSION );
			Com_sprintf (name_zip, sizeof(name_zip), "demos/%s_%s_%i%i%i%i.dm_%d.zip", prefix, sv_mapname->string, a, b, c, d, PROTOCOL_VERSION );
			Q_strlwr(name);
			Q_strlwr(name_zip);
			if (!FS_FileExists(name) && !FS_FileExists(name_zip)) {
				break;	// file doesn't exist
			}
		}
	}

	// open the demo file

	if (!sv_autorecord->integer) {
		Com_Printf ("recording client %i to %s.\n", clientnum, name);
	} else {
		Com_Printf ("Record: %i: %s\n", clientnum, name);
	}

	cl->demofile = FS_FOpenFileWrite( name );
	if ( !cl->demofile ) {
		Com_Printf ("ERROR: couldn't open.\n");
		return;
	}
	// don't start saving messages until a non-delta compressed message is received
	cl->demowaiting = qtrue;
	cl->savedemo = qfalse; // demo will not be saved if sv_autorecord 1 and cl's score is too low

	Q_strncpyz( cl->demoName, name, sizeof( cl->demoName ) );

	// write out the gamestate message
	MSG_Init (&buf, bufData, sizeof(bufData));
	MSG_Bitstream(&buf);

	// NOTE, MRE: all server->client messages now acknowledge
	MSG_WriteLong( &buf, cl->lastClientCommand );// 0007 - 000A

	MSG_WriteByte (&buf, svc_gamestate);// 000B
	MSG_WriteLong (&buf, cl->reliableSequence );// 000C - 000F


	// write the configstrings
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		if (sv.configstrings[i][0]) {
			MSG_WriteByte( &buf, svc_configstring );
			MSG_WriteShort( &buf, i );
			MSG_WriteBigString( &buf, sv.configstrings[i] );
		}
	}

	// write the baselines
	Com_Memset( &nullstate, 0, sizeof( nullstate ) );
	for ( i = 0 ; i < MAX_GENTITIES; i++ ) {
		ent = &sv.svEntities[i].baseline;
		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, clientnum);
	// write the checksum feed
	MSG_WriteLong(&buf, sv.checksumFeed);

	// finished writing the client packet
	MSG_WriteByte( &buf, svc_EOF );

	// write it to the demo file
	len = LittleLong( cl->netchan.outgoingSequence-1 );
	FS_Write (&len, 4, cl->demofile);// 0000 - 0003

	len = LittleLong (buf.cursize);
	FS_Write (&len, 4, cl->demofile);// 0004 - 0007
	FS_Write (buf.data, buf.cursize, cl->demofile);// 0007 - ...

	// the rest of the demo file will be copied from net messages
	cl->demorecording = qtrue;
}
Ejemplo n.º 7
0
/*
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;
}
Ejemplo n.º 8
0
/*
================
SV_SendClientGameState

Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each new map load.

It will be resent if the client acknowledges a later message but has
the wrong gamestate.
================
*/
void SV_SendClientGameState( client_t *client )
{
	int           start;
	entityState_t *base, nullstate;
	msg_t         msg;
	byte          msgBuffer[ MAX_MSGLEN ];

	Log::Debug( "SV_SendClientGameState() for %s", client->name );
	Log::Debug( "Going from CS_CONNECTED to CS_PRIMED for %s", client->name );
	client->state = clientState_t::CS_PRIMED;

	// when we receive the first packet from the client, we will
	// notice that it is from a different serverid and that the
	// gamestate message was not just sent, forcing a retransmit
	client->gamestateMessageNum = client->netchan.outgoingSequence;

	MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) );

	// NOTE, MRE: all server->client messages now acknowledge
	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( &msg, client->lastClientCommand );

	// send any server commands waiting to be sent first.
	// we have to do this cause we send the client->reliableSequence
	// with a gamestate and it sets the clc.serverCommandSequence at
	// the client side
	SV_UpdateServerCommandsToClient( client, &msg );

	// send the gamestate
	MSG_WriteByte( &msg, svc_gamestate );
	MSG_WriteLong( &msg, client->reliableSequence );

	// write the configstrings
	for ( start = 0; start < MAX_CONFIGSTRINGS; start++ )
	{
		if ( sv.configstrings[ start ][ 0 ] )
		{
			MSG_WriteByte( &msg, svc_configstring );
			MSG_WriteShort( &msg, start );
			MSG_WriteBigString( &msg, sv.configstrings[ start ] );
		}
	}

	// write the baselines
	memset( &nullstate, 0, sizeof( nullstate ) );

	for ( start = 0; start < MAX_GENTITIES; start++ )
	{
		base = &sv.svEntities[ start ].baseline;

		if ( !base->number )
		{
			continue;
		}

		MSG_WriteByte( &msg, svc_baseline );
		MSG_WriteDeltaEntity( &msg, &nullstate, base, true );
	}

	MSG_WriteByte( &msg, svc_EOF );

	MSG_WriteLong( &msg, client - svs.clients );

	// write the checksum feed
	MSG_WriteLong( &msg, sv.checksumFeed );

	// NERVE - SMF - debug info
	Log::Debug( "Sending %i bytes in gamestate to client: %li", msg.cursize, ( long )( client - svs.clients ) );

	// deliver this to the client
	SV_SendMessageToClient( &msg, client );
}
Ejemplo n.º 9
0
/*
================
SV_SendClientGameState

Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each new map load.

It will be resent if the client acknowledges a later message but has
the wrong gamestate.
================
*/
void SV_SendClientGameState( client_t *client ) {
	int			start;
	entityState_t	*base, nullstate;
	msg_t		msg;
	byte		msgBuffer[MAX_MSGLEN];

	// MW - my attempt to fix illegible server message errors caused by 
	// packet fragmentation of initial snapshot.
	while(client->state&&client->netchan.unsentFragments)
	{
		// send additional message fragments if the last message
		// was too large to send at once
	
		Com_Printf ("[ISM]SV_SendClientGameState() [2] for %s, writing out old fragments\n", client->name);
		SV_Netchan_TransmitNextFragment(&client->netchan);
	}

	Com_DPrintf ("SV_SendClientGameState() for %s\n", client->name);
	Com_DPrintf( "Going from CS_CONNECTED to CS_PRIMED for %s\n", client->name );
	client->state = CS_PRIMED;
	client->pureAuthentic = 0;

	// when we receive the first packet from the client, we will
	// notice that it is from a different serverid and that the
	// gamestate message was not just sent, forcing a retransmit
	client->gamestateMessageNum = client->netchan.outgoingSequence;

	MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) );

	// NOTE, MRE: all server->client messages now acknowledge
	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( &msg, client->lastClientCommand );

	// send any server commands waiting to be sent first.
	// we have to do this cause we send the client->reliableSequence
	// with a gamestate and it sets the clc.serverCommandSequence at
	// the client side
	SV_UpdateServerCommandsToClient( client, &msg );

	// send the gamestate
	MSG_WriteByte( &msg, svc_gamestate );
	MSG_WriteLong( &msg, client->reliableSequence );

	// write the configstrings
	for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) {
		if (sv.configstrings[start][0]) {
			MSG_WriteByte( &msg, svc_configstring );
			MSG_WriteShort( &msg, start );
			MSG_WriteBigString( &msg, sv.configstrings[start] );
		}
	}

	// write the baselines
	Com_Memset( &nullstate, 0, sizeof( nullstate ) );
	for ( start = 0 ; start < MAX_GENTITIES; start++ ) {
		base = &sv.svEntities[start].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);

	// write the checksum feed
	MSG_WriteLong( &msg, sv.checksumFeed);

	//rwwRMG - send info for the terrain
	if ( TheRandomMissionManager )
	{
		z_stream zdata;

		// Send the height map
		memset(&zdata, 0, sizeof(z_stream));
		deflateInit ( &zdata, Z_MAX_COMPRESSION );

		unsigned char heightmap[15000];
		zdata.next_out = (unsigned char*)heightmap;
		zdata.avail_out = 15000;
		zdata.next_in = TheRandomMissionManager->GetLandScape()->GetHeightMap();
		zdata.avail_in = TheRandomMissionManager->GetLandScape()->GetRealArea();
		deflate(&zdata, Z_SYNC_FLUSH);

		MSG_WriteShort ( &msg, (unsigned short)zdata.total_out );
		MSG_WriteBits ( &msg, 1, 1 );
		MSG_WriteData ( &msg, heightmap, zdata.total_out);

		deflateEnd(&zdata);

		// Send the flatten map
		memset(&zdata, 0, sizeof(z_stream));
		deflateInit ( &zdata, Z_MAX_COMPRESSION );

		zdata.next_out = (unsigned char*)heightmap;
		zdata.avail_out = 15000;
		zdata.next_in = TheRandomMissionManager->GetLandScape()->GetFlattenMap();
		zdata.avail_in = TheRandomMissionManager->GetLandScape()->GetRealArea();
		deflate(&zdata, Z_SYNC_FLUSH);

		MSG_WriteShort ( &msg, (unsigned short)zdata.total_out );
		MSG_WriteBits ( &msg, 1, 1 );
		MSG_WriteData ( &msg, heightmap, zdata.total_out);

		deflateEnd(&zdata);

		// Seed is needed for misc ents and noise
		MSG_WriteLong ( &msg, TheRandomMissionManager->GetLandScape()->get_rand_seed ( ) );

		SV_WriteRMGAutomapSymbols ( &msg );
	}
	else
	{
		MSG_WriteShort ( &msg, 0 );
	}

	// deliver this to the client
	SV_SendMessageToClient( &msg, client );
}
Ejemplo n.º 10
0
/*
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;
	client->demo_backoff = 1;
	client->demo_deltas = 0;
}
Ejemplo n.º 11
0
void demoCutWriteDemoHeader(fileHandle_t f, clientConnection_t *clcCut, clientActive_t *clCut) {
	byte			bufData[MAX_MSGLEN];
	msg_t			buf;
	int				i;
	int				len;
	entityState_t	*ent;
	entityState_t	nullstate;
	char			*s;
	// write out the gamestate message
	MSG_Init(&buf, bufData, sizeof(bufData));
	MSG_Bitstream(&buf);
	// NOTE, MRE: all server->client messages now acknowledge
	MSG_WriteLong(&buf, clcCut->reliableSequence);
	MSG_WriteByte(&buf, svc_gamestate);
	MSG_WriteLong(&buf, clcCut->serverCommandSequence);
	// configstrings
	for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
		if (!clCut->gameState.stringOffsets[i]) {
			continue;
		}
		s = clCut->gameState.stringData + clCut->gameState.stringOffsets[i];
		MSG_WriteByte(&buf, svc_configstring);
		MSG_WriteShort(&buf, i);
		MSG_WriteBigString(&buf, s);
	}
	// baselines
	Com_Memset(&nullstate, 0, sizeof(nullstate));
	for (i = 0; i < MAX_GENTITIES ; i++) {
		ent = &clCut->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, clcCut->clientNum);
	// write the checksum feed
	MSG_WriteLong(&buf, clcCut->checksumFeed);
	// RMG stuff
	if ( clcCut->rmgHeightMapSize ) {
		// Height map
		MSG_WriteShort(&buf, (unsigned short)clcCut->rmgHeightMapSize);
		MSG_WriteBits(&buf, 0, 1 );
		MSG_WriteData(&buf, clcCut->rmgHeightMap, clcCut->rmgHeightMapSize);
		// Flatten map
		MSG_WriteShort(&buf, (unsigned short)clcCut->rmgHeightMapSize);
		MSG_WriteBits(&buf, 0, 1 );
		MSG_WriteData(&buf, clcCut->rmgFlattenMap, clcCut->rmgHeightMapSize);
		// Seed
		MSG_WriteLong (&buf, clcCut->rmgSeed);
		// Automap symbols
		MSG_WriteShort (&buf, (unsigned short)clcCut->rmgAutomapSymbolCount);
		for (i = 0; i < clcCut->rmgAutomapSymbolCount; i ++) {
			MSG_WriteByte(&buf, (unsigned char)clcCut->rmgAutomapSymbols[i].mType);
			MSG_WriteByte(&buf, (unsigned char)clcCut->rmgAutomapSymbols[i].mSide);
			MSG_WriteLong(&buf, (long)clcCut->rmgAutomapSymbols[i].mOrigin[0]);
			MSG_WriteLong(&buf, (long)clcCut->rmgAutomapSymbols[i].mOrigin[1]);
		}
	} else {
		MSG_WriteShort (&buf, 0);
	}
	// finished writing the client packet
	MSG_WriteByte(&buf, svc_EOF);
	// write it to the demo file
	len = LittleLong(clcCut->serverMessageSequence - 1);
	FS_Write(&len, 4, f);
	len = LittleLong(buf.cursize);
	FS_Write(&len, 4, f);
	FS_Write(buf.data, buf.cursize, f);
}
Ejemplo n.º 12
0
/*
================
SV_SendClientGameState

Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each new map load.

It will be resent if the client acknowledges a later message but has
the wrong gamestate.
================
*/
void SV_SendClientGameState( client_t *client ) {
	int			start;
	entityState_t	*base, nullstate;
	msg_t		msg;
	byte		msgBuffer[MAX_MSGLEN];

	// MW - my attempt to fix illegible server message errors caused by 
	// packet fragmentation of initial snapshot.
	while(client->state&&client->netchan.unsentFragments)
	{
		// send additional message fragments if the last message
		// was too large to send at once
	
		Com_Printf ("[ISM]SV_SendClientGameState() [2] for %s, writing out old fragments\n", client->name);
		SV_Netchan_TransmitNextFragment(&client->netchan);
	}

	Com_DPrintf ("SV_SendClientGameState() for %s\n", client->name);
	Com_DPrintf( "Going from CS_CONNECTED to CS_PRIMED for %s\n", client->name );
	client->state = CS_PRIMED;
	client->pureAuthentic = 0;

	// when we receive the first packet from the client, we will
	// notice that it is from a different serverid and that the
	// gamestate message was not just sent, forcing a retransmit
	client->gamestateMessageNum = client->netchan.outgoingSequence;

	MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) );

	// NOTE, MRE: all server->client messages now acknowledge
	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( &msg, client->lastClientCommand );

	// send any server commands waiting to be sent first.
	// we have to do this cause we send the client->reliableSequence
	// with a gamestate and it sets the clc.serverCommandSequence at
	// the client side
	SV_UpdateServerCommandsToClient( client, &msg );

	// send the gamestate
	MSG_WriteByte( &msg, svc_gamestate );
	MSG_WriteLong( &msg, client->reliableSequence );

	// write the configstrings
	for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) {
		if (sv.configstrings[start][0]) {
			MSG_WriteByte( &msg, svc_configstring );
			MSG_WriteShort( &msg, start );
			MSG_WriteBigString( &msg, sv.configstrings[start] );
		}
	}

	// write the baselines
	Com_Memset( &nullstate, 0, sizeof( nullstate ) );
	for ( start = 0 ; start < MAX_GENTITIES; start++ ) {
		base = &sv.svEntities[start].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);

	// write the checksum feed
	MSG_WriteLong( &msg, sv.checksumFeed);

	// deliver this to the client
	SV_SendMessageToClient( &msg, client );
}
Ejemplo n.º 13
0
/*
================
SV_SendClientGameState

Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each new map load.

It will be resent if the client acknowledges a later message but has
the wrong gamestate.
================
*/
static void SV_SendClientGameState( client_t *client ) {
	int			start;
	entityState_t	*base, nullstate;
	msg_t		msg;
	byte		msgBuffer[MAX_MSGLEN];

 	Com_DPrintf ("SV_SendClientGameState() for %s\n", client->name);
	Com_DPrintf( "Going from CS_CONNECTED to CS_PRIMED for %s\n", client->name );
	client->state = CS_PRIMED;
	client->pureAuthentic = 0;
	client->gotCP = qfalse;

	// when we receive the first packet from the client, we will
	// notice that it is from a different serverid and that the
	// gamestate message was not just sent, forcing a retransmit
	client->gamestateMessageNum = client->netchan.outgoingSequence;

	MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) );

	// NOTE, MRE: all server->client messages now acknowledge
	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( &msg, client->lastClientCommand );

	// send any server commands waiting to be sent first.
	// we have to do this cause we send the client->reliableSequence
	// with a gamestate and it sets the clc.serverCommandSequence at
	// the client side
	SV_UpdateServerCommandsToClient( client, &msg );

	// send the gamestate
	MSG_WriteByte( &msg, svc_gamestate );
	MSG_WriteLong( &msg, client->reliableSequence );

	// write the configstrings
	for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) {
		if (sv.configstrings[start][0]) {
			MSG_WriteByte( &msg, svc_configstring );
			MSG_WriteShort( &msg, start );
			MSG_WriteBigString( &msg, sv.configstrings[start] );
		}
	}

	// write the baselines
	Com_Memset( &nullstate, 0, sizeof( nullstate ) );
	for ( start = 0 ; start < MAX_GENTITIES; start++ ) {
		base = &sv.svEntities[start].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);

	// write the checksum feed
	MSG_WriteLong( &msg, sv.checksumFeed);

	// There's something unknown going on here at the moment.
	// For now we're just going with default of adding a 0 short to keep jampded compatability.
	MSG_WriteShort( &msg, 0);

	// deliver this to the client
	SV_SendMessageToClient( &msg, client );
}
Ejemplo n.º 14
0
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
}
Ejemplo n.º 15
0
void SV_CreateClientGameStateMessage( client_t *client, msg_t *msg, qboolean updateServerCommands ) {
	int			start;
	entityState_t	*base, nullstate;

	// NOTE, MRE: all server->client messages now acknowledge
	// let the client know which reliable clientCommands we have received
	MSG_WriteLong( msg, client->lastClientCommand );

	if ( updateServerCommands ) {
		// send any server commands waiting to be sent first.
		// we have to do this cause we send the client->reliableSequence
		// with a gamestate and it sets the clc.serverCommandSequence at
		// the client side
		SV_UpdateServerCommandsToClient( client, msg );
	}

	// send the gamestate
	MSG_WriteByte( msg, svc_gamestate );
	MSG_WriteLong( msg, client->reliableSequence );

	// write the configstrings
	for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) {
		if (sv.configstrings[start][0]) {
			MSG_WriteByte( msg, svc_configstring );
			MSG_WriteShort( msg, start );
			MSG_WriteBigString( msg, sv.configstrings[start] );
		}
	}

	// write the baselines
	Com_Memset( &nullstate, 0, sizeof( nullstate ) );
	for ( start = 0 ; start < MAX_GENTITIES; start++ ) {
		base = &sv.svEntities[start].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);

	// write the checksum feed
	MSG_WriteLong( msg, sv.checksumFeed);

	//rwwRMG - send info for the terrain
	if ( TheRandomMissionManager )
	{
		z_stream zdata;

		// Send the height map
		memset(&zdata, 0, sizeof(z_stream));
		deflateInit ( &zdata, Z_BEST_COMPRESSION );

		unsigned char heightmap[15000];
		zdata.next_out = (unsigned char*)heightmap;
		zdata.avail_out = 15000;
		zdata.next_in = TheRandomMissionManager->GetLandScape()->GetHeightMap();
		zdata.avail_in = TheRandomMissionManager->GetLandScape()->GetRealArea();
		deflate(&zdata, Z_SYNC_FLUSH);

		MSG_WriteShort ( msg, (unsigned short)zdata.total_out );
		MSG_WriteBits ( msg, 1, 1 );
		MSG_WriteData ( msg, heightmap, zdata.total_out);

		deflateEnd(&zdata);

		// Send the flatten map
		memset(&zdata, 0, sizeof(z_stream));
		deflateInit ( &zdata, Z_BEST_COMPRESSION );

		zdata.next_out = (unsigned char*)heightmap;
		zdata.avail_out = 15000;
		zdata.next_in = TheRandomMissionManager->GetLandScape()->GetFlattenMap();
		zdata.avail_in = TheRandomMissionManager->GetLandScape()->GetRealArea();
		deflate(&zdata, Z_SYNC_FLUSH);

		MSG_WriteShort ( msg, (unsigned short)zdata.total_out );
		MSG_WriteBits ( msg, 1, 1 );
		MSG_WriteData ( msg, heightmap, zdata.total_out);

		deflateEnd(&zdata);

		// Seed is needed for misc ents and noise
		MSG_WriteLong ( msg, TheRandomMissionManager->GetLandScape()->get_rand_seed ( ) );

		SV_WriteRMGAutomapSymbols ( msg );
	}
	else
	{
		MSG_WriteShort ( msg, 0 );
	}
}