Ejemplo n.º 1
0
/*
* TV_Module_RelayError
*/
static void TV_Module_RelayError( relay_t *relay, const char *msg )
{
	if( !relay )
		TV_Module_Error( va( "RelayError without relay: %s\n", msg ) );

	if( msg )
		TV_Relay_Error( relay, "Game error: %s", msg );
	else
		TV_Relay_Error( relay, "Game error" );
}
Ejemplo n.º 2
0
/*
* TV_Module_ConfigString
*/
static void TV_Module_ConfigString( relay_t *relay, int index, const char *val )
{
	size_t len;

	if( !relay )
	{
		Com_Printf( "Error: TV_Module_ConfigString: Relay not set\n" );
		return;
	}

	if( !val )
		TV_Relay_Error( relay, "TV_Module_ConfigString: No value" );

	if( index < 0 || index >= MAX_CONFIGSTRINGS )
		TV_Relay_Error( relay, "TV_Module_ConfigString: Bad index" );

	len = strlen( val );
	if( len >= sizeof( relay->configstrings[0] ) )
	{
		Com_Printf( "WARNING: 'TV_Module_ConfigString', configstring %i overflowed (%i)\n", index, len );
		len = sizeof( relay->configstrings[0] ) - 1;
	}

	if( !COM_ValidateConfigstring( val ) )
	{
		Com_Printf( "WARNING: 'TV_Module_ConfigString' invalid configstring %i: %s\n", index, val );
		return;
	}

	// ignore if no changes
	if( !strncmp( relay->configstrings[index], val, len ) && relay->configstrings[index][len] == '\0' )
		return;

	// change the string in sv
	Q_strncpyz( relay->configstrings[index], val, sizeof( relay->configstrings[index] ) );

	{
		// We have to manually broadcast this one.
		client_t *client;
		int i;
		for( i = 0, client = tvs.clients; i < tv_maxclients->integer; i++, client++ )
		{
			if( client->state < CS_CONNECTED )
				continue;
			if( client->relay != relay )
				continue;
			TV_Downstream_SendServerCommand( client, "cs %i \"%s\"", index, val );
		}
	}
}
Ejemplo n.º 3
0
/*
* TV_Module_LocateLocalEntities
*/
static void TV_Module_LocateLocalEntities( relay_t *relay, struct edict_s *edicts, int edict_size, int num_edicts,
										  int max_edicts )
{
	int i;

	if( !relay )
	{
		Com_Printf( "Error: TV_Module_LocateLocalEntities: Relay not set\n" );
		return;
	}

	if( !edicts || edict_size < sizeof( entity_shared_t ) )
		TV_Relay_Error( relay, "TV_Module_LocateLocalEntities: bad edicts" );

	relay->gi.local_edicts = edicts;
	relay->gi.local_edict_size = edict_size;
	relay->gi.local_num_edicts = num_edicts;
	relay->gi.local_max_edicts = max_edicts;

	for( i = 0; i < tv_maxclients->integer; i++ )
	{
		if( tvs.clients[i].relay == relay )
		{
			tvs.clients[i].edict = LOCAL_EDICT_NUM( relay, i );
		}
	}
}
Ejemplo n.º 4
0
/*
* TV_Module_ExecuteClientThinks
*/
static void TV_Module_ExecuteClientThinks( relay_t *relay, int clientNum )
{
	client_t *client;

	if( !relay )
	{
		Com_Printf( "Error: TV_Module_ExecuteClientThinks: Relay not set\n" );
		return;
	}

	if( clientNum < 0 || clientNum >= tv_maxclients->integer )
		TV_Relay_Error( relay, "TV_Module_ExecuteClientThinks: Invalid clientNum" );

	client = tvs.clients + clientNum;

	if( client->state < CS_SPAWNED || client->relay != relay )
		TV_Relay_Error( relay, "TV_Module_ExecuteClientThinks: Invalid clientNum" );

	TV_Downstream_ExecuteClientThinks( relay, client );
}
Ejemplo n.º 5
0
/*
* TV_Module_GetClientState
* Game code asks for the state of this client
*/
static int TV_Module_GetClientState( relay_t *relay, int numClient )
{
	client_t *client;

	if( !relay )
	{
		Com_Printf( "Error: TV_Module_GetClientState: Relay not set\n" );
		return -1;
	}

	if( numClient < 0 || numClient >= tv_maxclients->integer )
		TV_Relay_Error( relay, "TV_Module_GetClientState: Invalid numClient" );

	client = &tvs.clients[numClient];

	if( client->relay != relay )
		TV_Relay_Error( relay, "TV_Module_GetClientState: Invalid client" );

	return client->state;
}
Ejemplo n.º 6
0
/*
* TV_Module_GameCmd
* 
* Sends the server command to clients.
* if numClient is -1 the command will be sent to all connected clients
*/
static void TV_Module_GameCmd( relay_t *relay, int numClient, const char *cmd )
{
	int i;
	client_t *client;

	if( !relay )
	{
		Com_Printf( "Error: TV_Module_GameCmd: Relay not set\n" );
		return;
	}

	if( !cmd || !cmd[0] )
		TV_Relay_Error( relay, "TV_Module_GameCmd: Missing command" );

	if( numClient < -1 || numClient >= tv_maxclients->integer )
		TV_Relay_Error( relay, "TV_Module_GameCmd: Invalid numClient" );

	if( numClient == -1 )
	{
		for( i = 0, client = tvs.clients; i < tv_maxclients->integer; i++, client++ )
		{
			if( client->state < CS_SPAWNED )
				continue;
			if( client->relay != relay )
				continue;

			TV_Downstream_AddGameCommand( relay, client, cmd );
		}
	}
	else
	{
		client = &tvs.clients[numClient];

		if( client->state == CS_FREE || client->state == CS_ZOMBIE || client->relay != relay )
			TV_Relay_Error( relay, "TV_Module_GameCmd: Invalid client" );

		TV_Downstream_AddGameCommand( relay, client, cmd );
	}
}
Ejemplo n.º 7
0
/*
* TV_Module_DropClient
*/
static void TV_Module_DropClient( relay_t *relay, int numClient, int type, const char *message )
{
	client_t *client;

	if( !relay )
	{
		Com_Printf( "Error: TV_Module_DropClient: Relay not set\n" );
		return;
	}

	if( numClient < 0 || numClient >= tv_maxclients->integer )
		TV_Relay_Error( relay, "TV_Module_DropClient: Invalid numClient" );

	client = &tvs.clients[numClient];

	if( client->state == CS_FREE || client->state == CS_ZOMBIE || client->relay != relay )
		TV_Relay_Error( relay, "TV_Module_DropClient: Invalid client" );

	if( message )
		TV_Downstream_DropClient( client, type, "%s", message );
	else
		TV_Downstream_DropClient( client, type, "" );
}
Ejemplo n.º 8
0
/*
* TV_Relay_ParseServerData
*/
static void TV_Relay_ParseServerData( relay_t *relay, msg_t *msg )
{
	int i, numpure;

	TV_Relay_ClearState( relay );

	relay->state = CA_CONNECTED;
	relay->map_checksum = 0;

	// parse protocol version number
	i = MSG_ReadLong( msg );

	if( i != APP_PROTOCOL_VERSION )
		TV_Relay_Error( relay, "Server returned version %i, not %i", i, APP_PROTOCOL_VERSION );

	relay->servercount = MSG_ReadLong( msg );
	relay->snapFrameTime = (unsigned int)MSG_ReadShort( msg );

	Q_strncpyz( relay->basegame, MSG_ReadString( msg ), sizeof( relay->basegame ) );
	Q_strncpyz( relay->game, MSG_ReadString( msg ), sizeof( relay->game ) );

	// parse player entity number
	relay->playernum = MSG_ReadShort( msg );

	// get the full level name
	Q_strncpyz( relay->levelname, MSG_ReadString( msg ), sizeof( relay->levelname ) );

	relay->sv_bitflags = MSG_ReadByte( msg );

	// using upstream->reliable won't work for TV_Relay_ParseServerMessage
	// in case of reliable demo following unreliable demo, causing "clack message while reliable" error
	relay->reliable = ( ( relay->sv_bitflags & SV_BITFLAGS_RELIABLE ) ? qtrue : qfalse );

	// pure list

	// clean old, if necessary
	Com_FreePureList( &relay->purelist );

	// add new
	numpure = MSG_ReadShort( msg );
	while( numpure > 0 )
	{
		const char *pakname = MSG_ReadString( msg );
		const unsigned checksum = MSG_ReadLong( msg );

		Com_AddPakToPureList( &relay->purelist, pakname, checksum, relay->upstream->mempool );

		numpure--;
	}
}
Ejemplo n.º 9
0
/*
* TV_Module_LocateEntities
*/
static void TV_Module_LocateEntities( relay_t *relay, struct edict_s *edicts, int edict_size, int num_edicts,
									 int max_edicts )
{
	if( !relay )
	{
		Com_Printf( "Error: TV_Module_LocateEntities: Relay not set\n" );
		return;
	}

	if( !edicts || edict_size < sizeof( entity_shared_t ) )
		TV_Relay_Error( relay, "TV_Module_LocateEntities: bad edicts" );

	relay->gi.edicts = edicts;
	relay->gi.edict_size = edict_size;
	relay->gi.num_edicts = num_edicts;
	relay->gi.max_edicts = max_edicts;
	relay->gi.max_clients = min( num_edicts, MAX_CLIENTS );
}
Ejemplo n.º 10
0
/*
* TV_Relay_ParseServerMessage
*/
void TV_Relay_ParseServerMessage( relay_t *relay, msg_t *msg )
{
	int cmd;

	assert( relay && relay->state >= CA_HANDSHAKE );
	assert( msg );

	// parse the message
	while( relay->state >= CA_HANDSHAKE )
	{
		if( msg->readcount > msg->cursize )
			TV_Relay_Error( relay, "Bad server message" );

		cmd = MSG_ReadByte( msg );
		/*if( cmd == -1 )
		Com_Printf( "%3i:CMD %i %s\n", msg->readcount-1, cmd, "EOF" );
		else
		Com_Printf( "%3i:CMD %i %s\n", msg->readcount-1, cmd, !svc_strings[cmd] ? "bad" : svc_strings[cmd] );*/

		if( cmd == -1 )
			break;

		// other commands
		switch( cmd )
		{
		default:
			TV_Relay_Error( relay, "Illegible server message" );

		case svc_nop:
			break;

		case svc_servercmd:
			if( !relay->reliable )
			{
				int cmdNum = MSG_ReadLong( msg );
				if( cmdNum < 0 )
					TV_Relay_Error( relay, "Invalid cmdNum value" );
				if( cmdNum <= relay->lastExecutedServerCommand )
				{
					MSG_ReadString( msg ); // read but ignore
					break;
				}
				relay->lastExecutedServerCommand = cmdNum;
			}
			// fall trough
		case svc_servercs: // configstrings from demo files. they don't have acknowledge
			TV_Relay_ParseServerCommand( relay, msg );
			break;

		case svc_serverdata:
			if( relay->upstream->demo.playing )
				TV_Relay_ReconnectClients( relay );

			if( relay->state == CA_HANDSHAKE )
			{
				Cbuf_Execute(); // make sure any stuffed commands are done
				TV_Relay_ParseServerData( relay, msg );
			}
			else
			{
				return; // ignore rest of the packet (serverdata is always sent alone)
			}
			break;

		case svc_spawnbaseline:
			TV_Relay_ParseBaseline( relay, msg );
			break;

		case svc_download:
			//CL_ParseDownload( msg );
			break;

		case svc_clcack:
			if( relay->reliable )
				TV_Relay_Error( relay, "clack message while reliable" );
			MSG_ReadLong( msg ); // reliableAcknowledge
			MSG_ReadLong( msg ); // ucmdAcknowledged
			break;

		case svc_frame:
			TV_Relay_ParseFrame( relay, msg );
			break;

		case svc_demoinfo:
			{
				int length;
				
				length = MSG_ReadLong( msg );
				MSG_SkipData( msg, length );
			}
			break;

		case svc_playerinfo:
		case svc_packetentities:
		case svc_match:
			TV_Relay_Error( relay, "Out of place frame data" );
			break;

		case svc_extension:
			if( 1 )
			{
				int len;

				MSG_ReadByte( msg );			// extension id
				MSG_ReadByte( msg );			// version number
				len = MSG_ReadShort( msg );		// command length
				MSG_SkipData( msg, len );		// command data
			}
			break;
		}
	}
}