etqw-sdk/source/game/Game_Repeater.cpp

336 lines
9.8 KiB
C++
Raw Normal View History

2008-05-29 00:00:00 +00:00
#include "precompiled.h"
#pragma hdrstop
#ifdef SD_SUPPORT_REPEATER
#include "rules/GameRules.h"
/*
============
idGameLocal::RepeaterClientDisconnect
============
*/
void idGameLocal::RepeaterClientDisconnect( int clientNum ) {
if ( clientNum >= repeaterNetworkInfo.Num() ) {
return;
}
ShutdownRepeatersNetworkState( clientNum );
}
/*
============
idGameLocal::RepeaterWriteInitialReliableMessages
============
*/
void idGameLocal::RepeaterWriteInitialReliableMessages( int clientNum ) {
WriteInitialReliableMessages( sdReliableMessageClientInfoRepeater( clientNum ) );
}
/*
============
idGameLocal::RepeaterWriteSnapshot
============
*/
void idGameLocal::RepeaterWriteSnapshot( int clientNum, int sequence, idBitMsg &msg, idBitMsg &ucmdmsg, const repeaterUserOrigin_t& userOrigin, bool clientIsRepeater ) {
bool useAOR = net_useAOR.GetBool() && !clientIsRepeater;
snapShotClientIsRepeater = clientIsRepeater;
SetSnapShotClient( NULL );
SetSnapShotPlayer( NULL );
idPlayer* followPlayer = NULL;
if ( !clientIsRepeater ) {
if ( userOrigin.followClient >= 0 && userOrigin.followClient < MAX_CLIENTS ) {
followPlayer = GetClient( userOrigin.followClient );
}
}
if ( followPlayer != NULL ) {
SetSnapShotPlayer( followPlayer );
aorManager.SetClient( followPlayer );
msg.WriteByte( followPlayer->entityNumber + 1 );
} else {
aorManager.SetPosition( userOrigin.origin );
msg.WriteByte( 0 );
}
clientNetworkInfo_t& nwInfo = GetRepeaterNetworkInfo( clientNum );
// free too old snapshots
FreeSnapshotsOlderThanSequence( nwInfo, sequence - 64 );
snapshot_t* snapshot = AllocateSnapshot( sequence, nwInfo );
WriteSnapshotGameStates( snapshot, nwInfo, msg );
WriteSnapshotEntityStates( snapshot, nwInfo, -1, msg, useAOR );
WriteUnreliableEntityNetEvents( clientNum, false, msg );
WriteSnapshotUserCmds( snapshot, ucmdmsg, -1, useAOR );
snapShotClientIsRepeater = false;
SetSnapShotClient( NULL );
SetSnapShotPlayer( NULL );
}
/*
============
idGameLocal::RepeaterAllowClient
============
*/
allowReply_t idGameLocal::RepeaterAllowClient( int numViewers, int maxViewers, const clientNetworkAddress_t& address, const sdNetClientId& netClientId, const char *guid, const char *password, allowFailureReason_t& reason, bool isRepeater ) {
clientGUIDLookup_t lookup;
lookup.ip = ( *( int* )address.ip );
lookup.pbid = 0;
lookup.clientId = netClientId;
sdGUIDFile::banState_t banState = guidFile.CheckForBan( lookup );
switch ( banState ) {
case sdGUIDFile::BS_PERM_BAN:
reason = ALLOWFAIL_PERMBAN;
return ALLOW_NO;
case sdGUIDFile::BS_TEMP_BAN:
reason = ALLOWFAIL_TEMPBAN;
return ALLOW_NO;
case sdGUIDFile::BS_NOT_BANNED:
break;
}
if ( serverInfo.GetInt( "si_pure" ) && ( rules == NULL || !rules->IsPureReady() ) ) {
reason = ALLOWFAIL_SERVERSPAWNING;
return ALLOW_NOTYET;
}
bool isPrivateClient = false;
const char* privatePass = g_privateViewerPassword.GetString();
if ( *privatePass != '\0' && idStr::Cmp( privatePass, password ) == 0 ) {
isPrivateClient = true;
} else if ( isRepeater ) {
const char* pass = g_repeaterPassword.GetString();
if ( *pass != '\0' ) {
if ( idStr::Cmp( pass, password ) != 0 ) {
reason = ALLOWFAIL_INVALIDPASSWORD;
Printf( "Rejecting client %s from IP '%i.%i.%i.%i': invalid password\n", guid, address.ip[ 0 ], address.ip[ 1 ], address.ip[ 2 ], address.ip[ 3 ] );
return ALLOW_BADPASS;
}
}
} else if ( ri_useViewerPass.GetBool() ) {
const char* pass = g_viewerPassword.GetString();
if ( *pass == '\0' ) {
// Gordon: FIXME: This is rubbish
gameLocal.Warning( "ri_useViewerPass is set but g_password is empty" );
cmdSystem->BufferCommandText( CMD_EXEC_NOW, "say ri_useViewerPass is set but g_viewerPassword is empty" );
// avoids silent misconfigured state
reason = ALLOWFAIL_SERVERMISCONFIGURED;
return ALLOW_NOTYET;
}
if ( idStr::Cmp( pass, password ) != 0 ) {
reason = ALLOWFAIL_INVALIDPASSWORD;
Printf( "Rejecting client %s from IP '%i.%i.%i.%i': invalid password\n", guid, address.ip[ 0 ], address.ip[ 1 ], address.ip[ 2 ], address.ip[ 3 ] );
return ALLOW_BADPASS;
}
}
int maxPrivatePlayers = ri_privateViewers.GetInteger();
if ( maxPrivatePlayers > maxViewers ) {
maxPrivatePlayers = maxViewers;
}
int maxRegularPlayers = maxViewers - maxPrivatePlayers;
int numAvailableSlots = maxRegularPlayers;
if ( isPrivateClient ) {
numAvailableSlots = maxViewers; // with private password, any slot is available
}
if ( numViewers >= numAvailableSlots ) {
if ( numViewers >= maxPrivatePlayers ) {
reason = ALLOWFAIL_SERVERFULL;
return ALLOW_NOTYET;
}
reason = ALLOWFAIL_INVALIDPASSWORD;
return ALLOW_BADPASS;
}
return ALLOW_YES;
}
/*
============
idGameLocal::RepeaterClientBegin
============
*/
void idGameLocal::RepeaterClientBegin( int clientNum ) {
if ( clientNum >= repeaterNetworkInfo.Num() ) {
int oldSize = repeaterNetworkInfo.Num();
repeaterNetworkInfo.SetNum( clientNum + 1 );
for ( int i = oldSize; i <= clientNum; i++ ) {
repeaterNetworkInfo[ i ] = NULL;
}
}
if ( repeaterNetworkInfo[ clientNum ] == NULL ) {
repeaterNetworkInfo[ clientNum ] = new clientNetworkInfo_t();
}
SetupGameStateBase( *repeaterNetworkInfo[ clientNum ] );
SetupEntityStateBase( *repeaterNetworkInfo[ clientNum ] );
// client needs to get this straight away
sdReliableServerMessage ruleMsg( GAME_RELIABLE_SMESSAGE_RULES_DATA );
ruleMsg.WriteLong( sdGameRules::EVENT_CREATE );
ruleMsg.WriteLong( rules->GetType()->typeNum );
ruleMsg.Send( sdReliableMessageClientInfoRepeater( clientNum ) );
rules->WriteInitialReliableMessages( sdReliableMessageClientInfoRepeater( clientNum ) );
}
/*
============
idGameLocal::SetRepeaterState
============
*/
void idGameLocal::SetRepeaterState( bool isRepeater ) {
this->isRepeater = isRepeater;
if ( net_serverDownload.GetInteger() == 3 ) {
networkSystem->HTTPEnable( this->isServer || this->isRepeater );
}
UpdateRepeaterInfo();
}
/*
===========
idGameLocal::UpdateRepeaterInfo
============
*/
void idGameLocal::UpdateRepeaterInfo( void ) {
if ( !isRepeater ) {
return;
}
idDict repeaterInfo;
BuildRepeaterInfo( repeaterInfo );
networkSystem->RepeaterSetInfo( repeaterInfo );
}
/*
===========
idGameLocal::BuildRepeaterInfo
============
*/
void idGameLocal::BuildRepeaterInfo( idDict &repeaterInfo ) {
repeaterInfo = serverInfo;
repeaterInfo.SetBool( "si_tv", true );
repeaterInfo.SetBool( "si_usePass", ri_useViewerPass.GetBool() );
repeaterInfo.SetInt( "si_privateClients", ri_privateViewers.GetInteger() );
const char* ri_name = cvarSystem->GetCVarString( "ri_name" );
if ( *ri_name != '\0' ) {
if ( *serverInfo.GetString( "ri_origName" ) == '\0' ) {
repeaterInfo.Set( "ri_origName", serverInfo.GetString( "si_name" ) );
}
repeaterInfo.Set( "si_name", ri_name );
}
const char *si_serverURL = cvarSystem->GetCVarString( "si_serverURL" );
if ( *si_serverURL != '\0' ) {
if ( *serverInfo.GetString( "ri_origServerURL" ) == '\0' ) {
repeaterInfo.Set( "ri_origServerURL", serverInfo.GetString( "si_serverURL" ) );
}
repeaterInfo.Set( "si_serverURL", si_serverURL );
}
repeaterInfo.Copy( *cvarSystem->MoveCVarsToDict( CVAR_REPEATERINFO ) );
}
/*
===========
idGameLocal::GetNumRepeaterClients
============
*/
int idGameLocal::GetNumRepeaterClients( void ) const {
return repeaterNetworkInfo.Num();
}
/*
===========
idGameLocal::IsRepeaterClientConnected
============
*/
bool idGameLocal::IsRepeaterClientConnected( int clientNum ) const {
return repeaterNetworkInfo[ clientNum ] != NULL;
}
/*
===========
idGameLocal::ShutdownRepeatersNetworkStates
============
*/
void idGameLocal::ShutdownRepeatersNetworkStates( void ) {
for ( int i = 0; i < repeaterNetworkInfo.Num(); i++ ) {
ShutdownRepeatersNetworkState( i );
}
}
/*
===========
idGameLocal::ShutdownRepeatersNetworkState
============
*/
void idGameLocal::ShutdownRepeatersNetworkState( int clientNum ) {
if ( repeaterNetworkInfo[ clientNum ] != NULL ) {
repeaterNetworkInfo[ clientNum ]->Reset();
delete repeaterNetworkInfo[ clientNum ];
repeaterNetworkInfo[ clientNum ] = NULL;
}
}
/*
================
idGameLocal::RepeaterApplySnapshot
================
*/
bool idGameLocal::RepeaterApplySnapshot( int clientNum, int sequence ) {
return ApplySnapshot( GetRepeaterNetworkInfo( clientNum ), sequence );
}
/*
================
idGameLocal::RepeaterProcessReliableMessage
================
*/
void idGameLocal::RepeaterProcessReliableMessage( int clientNum, const idBitMsg &msg ) {
gameReliableClientMessage_t id = static_cast< gameReliableClientMessage_t >( msg.ReadBits( idMath::BitsForInteger( GAME_RELIABLE_CMESSAGE_NUM_MESSAGES ) ) );
switch( id ) {
case GAME_RELIABLE_CMESSAGE_CHAT:
case GAME_RELIABLE_CMESSAGE_TEAM_CHAT: {
case GAME_RELIABLE_CMESSAGE_FIRETEAM_CHAT:
if ( g_noTVChat.GetBool() ) {
break;
}
wchar_t text[ 128 ];
msg.ReadString( text, sizeof( text ) / sizeof( wchar_t ) );
const idDict& clientInfo = networkSystem->RepeaterGetClientInfo( clientNum );
idStr playerName = clientInfo.GetString( "ui_name" );
idStr cleanName = playerName;
cleanName.RemoveColors();
cleanName.StripLeadingWhiteSpace();
cleanName.StripTrailingWhiteSpace();
if ( cleanName.IsEmpty() ) {
playerName = "Player";
}
sdReliableServerMessage outMsg( GAME_RELIABLE_SMESSAGE_REPEATER_CHAT );
outMsg.WriteString( playerName.c_str(), 128, false );
outMsg.WriteLong( clientNum );
outMsg.WriteString( text, 128 );
outMsg.Send( sdReliableMessageClientInfoRepeaterLocal() );
break;
}
}
}
#endif // SD_SUPPORT_REPEATER