Beispiel #1
0
/*
* SNAP_BeginDemoRecording
*/
void SNAP_BeginDemoRecording( int demofile, unsigned int spawncount, unsigned int snapFrameTime, 
	const char *sv_name, unsigned int sv_bitflags, purelist_t *purelist, char *configstrings, 
	entity_state_t *baselines )
{
	unsigned int i;
	msg_t msg;
	uint8_t msg_buffer[MAX_MSGLEN];
	purelist_t *purefile;
	entity_state_t nullstate;
	entity_state_t *base;

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

	SNAP_DemoMetaDataMessage( &msg, "", 0 );

	SNAP_RecordDemoMetaDataMessage( demofile, &msg );

	// serverdata message
	MSG_WriteByte( &msg, svc_serverdata );
	MSG_WriteLong( &msg, APP_DEMO_PROTOCOL_VERSION );
	MSG_WriteLong( &msg, spawncount );
	MSG_WriteShort( &msg, (unsigned short)snapFrameTime );
	MSG_WriteString( &msg, FS_BaseGameDirectory() );
	MSG_WriteString( &msg, FS_GameDirectory() );
	MSG_WriteShort( &msg, -1 ); // playernum
	MSG_WriteString( &msg, sv_name ); // level name
	MSG_WriteByte( &msg, sv_bitflags & ~SV_BITFLAGS_HTTP ); // sv_bitflags

	// pure files
	i = Com_CountPureListFiles( purelist );
	if( i > (short)0x7fff )
		Com_Error( ERR_DROP, "Error: Too many pure files." );

	MSG_WriteShort( &msg, i );

	purefile = purelist;
	while( purefile )
	{
		MSG_WriteString( &msg, purefile->filename );
		MSG_WriteLong( &msg, purefile->checksum );
		purefile = purefile->next;

		DEMO_SAFEWRITE( demofile, &msg, false );
	}

	// config strings
	for( i = 0; i < MAX_CONFIGSTRINGS; i++ )
	{
		const char *configstring = configstrings + i * MAX_CONFIGSTRING_CHARS;
		if( configstring[0] )
		{
			MSG_WriteByte( &msg, svc_servercs );
			MSG_WriteString( &msg, va( "cs %i \"%s\"", i, configstring ) );

			DEMO_SAFEWRITE( demofile, &msg, false );
		}
	}

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

	for( i = 0; i < MAX_EDICTS; i++ )
	{
		base = &baselines[i];
		if( base->modelindex || base->sound || base->effects )
		{
			MSG_WriteByte( &msg, svc_spawnbaseline );
			MSG_WriteDeltaEntity( &nullstate, base, &msg, true, true );

			DEMO_SAFEWRITE( demofile, &msg, false );
		}
	}

	// client expects the server data to be in a separate packet
	DEMO_SAFEWRITE( demofile, &msg, true );

	MSG_WriteByte( &msg, svc_servercs );
	MSG_WriteString( &msg, "precache" );

	DEMO_SAFEWRITE( demofile, &msg, true );
}
Beispiel #2
0
/*
* 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;
}
/*
* TV_Downstream_New_f
* 
* Sends the first message from the server to a connected client.
* This will be sent on the initial upstream and upon each server load.
*/
void TV_Downstream_New_f( client_t *client )
{
	int playernum, numpure;
	int tv_bitflags;
	purelist_t *iter;
	msg_t message;
	uint8_t messageData[MAX_MSGLEN];

	// if in CS_AWAITING we have sended 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_DPrintf( "New not valid -- already spawned\n" );
		return;
	}

	// relay is not ready yet
	if( client->relay && client->relay->state < CA_ACTIVE )
	{
		TV_Relay_DelayNew( client );
		return;
	}

	//
	// serverdata needs to go over for all types of servers
	// to make sure the protocol is right, and to set the gamedir
	//
	TV_Downstream_InitClientMessage( client, &message, messageData, sizeof( messageData ) );

	// send the serverdata
	MSG_WriteByte( &message, svc_serverdata );
	MSG_WriteLong( &message, APP_PROTOCOL_VERSION );
	if( !client->relay )
	{
		MSG_WriteLong( &message, tvs.lobby.spawncount );
		MSG_WriteShort( &message, tvs.lobby.snapFrameTime );
		MSG_WriteString( &message, FS_BaseGameDirectory() );
		MSG_WriteString( &message, FS_GameDirectory() );
	}
	else
	{
		MSG_WriteLong( &message, client->relay->servercount );
		MSG_WriteShort( &message, client->relay->snapFrameTime );
		MSG_WriteString( &message, client->relay->basegame );
		MSG_WriteString( &message, client->relay->game );
	}

	if( client->relay )
	{
		// we use our own playernum on the relay server
		MSG_WriteShort( &message, client->relay->playernum );
	}
	else
	{
		playernum = client - tvs.clients;
		MSG_WriteShort( &message, playernum );
	}

	// send full levelname
	if( !client->relay )
		MSG_WriteString( &message, tv_name->string );
	else
		MSG_WriteString( &message, client->relay->levelname );

	memset( &client->lastcmd, 0, sizeof( client->lastcmd ) );

	tv_bitflags = SV_BITFLAGS_TVSERVER;
	if( client->reliable )
		tv_bitflags |= SV_BITFLAGS_RELIABLE;

	MSG_WriteByte( &message, tv_bitflags ); // sv_bitflags

	// purelist
	if( !client->relay )
	{
		MSG_WriteShort( &message, 0 );
	}
	else
	{
		numpure = Com_CountPureListFiles( client->relay->purelist );

		MSG_WriteShort( &message, numpure );
		iter = client->relay->purelist;
		while( iter )
		{
			MSG_WriteString( &message, iter->filename );
			MSG_WriteLong( &message, iter->checksum );
			iter = iter->next;
		}
	}

	TV_Downstream_ClientResetCommandBuffers( client, true );

	TV_Downstream_SendMessageToClient( client, &message );

	Netchan_PushAllFragments( &client->netchan );

	// don't let it send reliable commands until we get the first configstring request
	client->state = CS_CONNECTING;
}