123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "AsyncNetwork.h"
- idAsyncServer idAsyncNetwork::server;
- idAsyncClient idAsyncNetwork::client;
- idCVar idAsyncNetwork::verbose( "net_verbose", "0", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "1 = verbose output, 2 = even more verbose output", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
- idCVar idAsyncNetwork::allowCheats( "net_allowCheats", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_NETWORKSYNC, "Allow cheats in network game" );
- #ifdef ID_DEDICATED
- // dedicated executable can only have a value of 1 for net_serverDedicated
- idCVar idAsyncNetwork::serverDedicated( "net_serverDedicated", "1", CVAR_SERVERINFO | CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT | CVAR_ROM, "" );
- #else
- idCVar idAsyncNetwork::serverDedicated( "net_serverDedicated", "0", CVAR_SERVERINFO | CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "1 = text console dedicated server, 2 = graphical dedicated server", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
- #endif
- idCVar idAsyncNetwork::serverSnapshotDelay( "net_serverSnapshotDelay", "50", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "delay between snapshots in milliseconds" );
- idCVar idAsyncNetwork::serverMaxClientRate( "net_serverMaxClientRate", "16000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE | CVAR_NOCHEAT, "maximum rate to a client in bytes/sec" );
- idCVar idAsyncNetwork::clientMaxRate( "net_clientMaxRate", "16000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE | CVAR_NOCHEAT, "maximum rate requested by client from server in bytes/sec" );
- idCVar idAsyncNetwork::serverMaxUsercmdRelay( "net_serverMaxUsercmdRelay", "5", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "maximum number of usercmds from other clients the server relays to a client", 1, MAX_USERCMD_RELAY, idCmdSystem::ArgCompletion_Integer<1,MAX_USERCMD_RELAY> );
- idCVar idAsyncNetwork::serverZombieTimeout( "net_serverZombieTimeout", "5", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "disconnected client timeout in seconds" );
- idCVar idAsyncNetwork::serverClientTimeout( "net_serverClientTimeout", "40", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "client time out in seconds" );
- idCVar idAsyncNetwork::clientServerTimeout( "net_clientServerTimeout", "40", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "server time out in seconds" );
- idCVar idAsyncNetwork::serverDrawClient( "net_serverDrawClient", "-1", CVAR_SYSTEM | CVAR_INTEGER, "number of client for which to draw view on server" );
- idCVar idAsyncNetwork::serverRemoteConsolePassword( "net_serverRemoteConsolePassword", "", CVAR_SYSTEM | CVAR_NOCHEAT, "remote console password" );
- idCVar idAsyncNetwork::clientPrediction( "net_clientPrediction", "16", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "additional client side prediction in milliseconds" );
- idCVar idAsyncNetwork::clientMaxPrediction( "net_clientMaxPrediction", "1000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "maximum number of milliseconds a client can predict ahead of server." );
- idCVar idAsyncNetwork::clientUsercmdBackup( "net_clientUsercmdBackup", "5", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "number of usercmds to resend" );
- idCVar idAsyncNetwork::clientRemoteConsoleAddress( "net_clientRemoteConsoleAddress", "localhost", CVAR_SYSTEM | CVAR_NOCHEAT, "remote console address" );
- idCVar idAsyncNetwork::clientRemoteConsolePassword( "net_clientRemoteConsolePassword", "", CVAR_SYSTEM | CVAR_NOCHEAT, "remote console password" );
- idCVar idAsyncNetwork::master0( "net_master0", IDNET_HOST ":" IDNET_MASTER_PORT, CVAR_SYSTEM | CVAR_ROM, "idnet master server address" );
- idCVar idAsyncNetwork::master1( "net_master1", "", CVAR_SYSTEM | CVAR_ARCHIVE, "1st master server address" );
- idCVar idAsyncNetwork::master2( "net_master2", "", CVAR_SYSTEM | CVAR_ARCHIVE, "2nd master server address" );
- idCVar idAsyncNetwork::master3( "net_master3", "", CVAR_SYSTEM | CVAR_ARCHIVE, "3rd master server address" );
- idCVar idAsyncNetwork::master4( "net_master4", "", CVAR_SYSTEM | CVAR_ARCHIVE, "4th master server address" );
- idCVar idAsyncNetwork::LANServer( "net_LANServer", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_NOCHEAT, "config LAN games only - affects clients and servers" );
- idCVar idAsyncNetwork::serverReloadEngine( "net_serverReloadEngine", "0", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "perform a full reload on next map restart (including flushing referenced pak files) - decreased if > 0" );
- idCVar idAsyncNetwork::serverAllowServerMod( "net_serverAllowServerMod", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_NOCHEAT, "allow server-side mods" );
- idCVar idAsyncNetwork::idleServer( "si_idleServer", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_INIT | CVAR_SERVERINFO, "game clients are idle" );
- idCVar idAsyncNetwork::clientDownload( "net_clientDownload", "1", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE, "client pk4 downloads policy: 0 - never, 1 - ask, 2 - always (will still prompt for binary code)" );
- int idAsyncNetwork::realTime;
- master_t idAsyncNetwork::masters[ MAX_MASTER_SERVERS ];
- /*
- ==================
- idAsyncNetwork::idAsyncNetwork
- ==================
- */
- idAsyncNetwork::idAsyncNetwork( void ) {
- }
- /*
- ==================
- idAsyncNetwork::Init
- ==================
- */
- void idAsyncNetwork::Init( void ) {
- realTime = 0;
- memset( masters, 0, sizeof( masters ) );
- masters[0].var = &master0;
- masters[1].var = &master1;
- masters[2].var = &master2;
- masters[3].var = &master3;
- masters[4].var = &master4;
- #ifndef ID_DEMO_BUILD
- cmdSystem->AddCommand( "spawnServer", SpawnServer_f, CMD_FL_SYSTEM, "spawns a server", idCmdSystem::ArgCompletion_MapName );
- cmdSystem->AddCommand( "nextMap", NextMap_f, CMD_FL_SYSTEM, "loads the next map on the server" );
- cmdSystem->AddCommand( "connect", Connect_f, CMD_FL_SYSTEM, "connects to a server" );
- cmdSystem->AddCommand( "reconnect", Reconnect_f, CMD_FL_SYSTEM, "reconnect to the last server we tried to connect to" );
- cmdSystem->AddCommand( "serverInfo", GetServerInfo_f, CMD_FL_SYSTEM, "shows server info" );
- cmdSystem->AddCommand( "LANScan", GetLANServers_f, CMD_FL_SYSTEM, "scans LAN for servers" );
- cmdSystem->AddCommand( "listServers", ListServers_f, CMD_FL_SYSTEM, "lists scanned servers" );
- cmdSystem->AddCommand( "rcon", RemoteConsole_f, CMD_FL_SYSTEM, "sends remote console command to server" );
- cmdSystem->AddCommand( "heartbeat", Heartbeat_f, CMD_FL_SYSTEM, "send a heartbeat to the the master servers" );
- cmdSystem->AddCommand( "kick", Kick_f, CMD_FL_SYSTEM, "kick a client by connection number" );
- cmdSystem->AddCommand( "checkNewVersion", CheckNewVersion_f, CMD_FL_SYSTEM, "check if a new version of the game is available" );
- cmdSystem->AddCommand( "updateUI", UpdateUI_f, CMD_FL_SYSTEM, "internal - cause a sync down of game-modified userinfo" );
- #endif
- }
- /*
- ==================
- idAsyncNetwork::GetMasterAddress
- ==================
- */
- netadr_t idAsyncNetwork::GetMasterAddress( void ) {
- netadr_t ret;
- GetMasterAddress( 0, ret );
- return masters[ 0 ].address;
- }
- /*
- ==================
- idAsyncNetwork::GetMasterAddress
- ==================
- */
- bool idAsyncNetwork::GetMasterAddress( int index, netadr_t &adr ) {
- if ( !masters[ index ].var ) {
- return false;
- }
- if ( masters[ index ].var->GetString()[0] == '\0' ) {
- return false;
- }
- if ( !masters[ index ].resolved || masters[ index ].var->IsModified() ) {
- masters[ index ].var->ClearModified();
- if ( !Sys_StringToNetAdr( masters[ index ].var->GetString(), &masters[ index ].address, true ) ) {
- common->Printf( "Failed to resolve master%d: %s\n", index, masters[ index ].var->GetString() );
- memset( &masters[ index ].address, 0, sizeof( netadr_t ) );
- masters[ index ].resolved = true;
- return false;
- }
- if ( masters[ index ].address.port == 0 ) {
- masters[ index ].address.port = atoi( IDNET_MASTER_PORT );
- }
- masters[ index ].resolved = true;
- }
- adr = masters[ index ].address;
- return true;
- }
- /*
- ==================
- idAsyncNetwork::Shutdown
- ==================
- */
- void idAsyncNetwork::Shutdown( void ) {
- client.serverList.Shutdown();
- client.DisconnectFromServer();
- client.ClearServers();
- client.ClosePort();
- server.Kill();
- server.ClosePort();
- }
- /*
- ==================
- idAsyncNetwork::RunFrame
- ==================
- */
- void idAsyncNetwork::RunFrame( void ) {
- if ( console->Active() ) {
- Sys_GrabMouseCursor( false );
- usercmdGen->InhibitUsercmd( INHIBIT_ASYNC, true );
- } else {
- Sys_GrabMouseCursor( true );
- usercmdGen->InhibitUsercmd( INHIBIT_ASYNC, false );
- }
- client.RunFrame();
- server.RunFrame();
- }
- /*
- ==================
- idAsyncNetwork::WriteUserCmdDelta
- ==================
- */
- void idAsyncNetwork::WriteUserCmdDelta( idBitMsg &msg, const usercmd_t &cmd, const usercmd_t *base ) {
- if ( base ) {
- msg.WriteDeltaLongCounter( base->gameTime, cmd.gameTime );
- msg.WriteDeltaByte( base->buttons, cmd.buttons );
- msg.WriteDeltaShort( base->mx, cmd.mx );
- msg.WriteDeltaShort( base->my, cmd.my );
- msg.WriteDeltaChar( base->forwardmove, cmd.forwardmove );
- msg.WriteDeltaChar( base->rightmove, cmd.rightmove );
- msg.WriteDeltaChar( base->upmove, cmd.upmove );
- msg.WriteDeltaShort( base->angles[0], cmd.angles[0] );
- msg.WriteDeltaShort( base->angles[1], cmd.angles[1] );
- msg.WriteDeltaShort( base->angles[2], cmd.angles[2] );
- return;
- }
- msg.WriteLong( cmd.gameTime );
- msg.WriteByte( cmd.buttons );
- msg.WriteShort( cmd.mx );
- msg.WriteShort( cmd.my );
- msg.WriteChar( cmd.forwardmove );
- msg.WriteChar( cmd.rightmove );
- msg.WriteChar( cmd.upmove );
- msg.WriteShort( cmd.angles[0] );
- msg.WriteShort( cmd.angles[1] );
- msg.WriteShort( cmd.angles[2] );
- }
- /*
- ==================
- idAsyncNetwork::ReadUserCmdDelta
- ==================
- */
- void idAsyncNetwork::ReadUserCmdDelta( const idBitMsg &msg, usercmd_t &cmd, const usercmd_t *base ) {
- memset( &cmd, 0, sizeof( cmd ) );
- if ( base ) {
- cmd.gameTime = msg.ReadDeltaLongCounter( base->gameTime );
- cmd.buttons = msg.ReadDeltaByte( base->buttons );
- cmd.mx = msg.ReadDeltaShort( base->mx );
- cmd.my = msg.ReadDeltaShort( base->my );
- cmd.forwardmove = msg.ReadDeltaChar( base->forwardmove );
- cmd.rightmove = msg.ReadDeltaChar( base->rightmove );
- cmd.upmove = msg.ReadDeltaChar( base->upmove );
- cmd.angles[0] = msg.ReadDeltaShort( base->angles[0] );
- cmd.angles[1] = msg.ReadDeltaShort( base->angles[1] );
- cmd.angles[2] = msg.ReadDeltaShort( base->angles[2] );
- return;
- }
- cmd.gameTime = msg.ReadLong();
- cmd.buttons = msg.ReadByte();
- cmd.mx = msg.ReadShort();
- cmd.my = msg.ReadShort();
- cmd.forwardmove = msg.ReadChar();
- cmd.rightmove = msg.ReadChar();
- cmd.upmove = msg.ReadChar();
- cmd.angles[0] = msg.ReadShort();
- cmd.angles[1] = msg.ReadShort();
- cmd.angles[2] = msg.ReadShort();
- }
- /*
- ==================
- idAsyncNetwork::DuplicateUsercmd
- ==================
- */
- bool idAsyncNetwork::DuplicateUsercmd( const usercmd_t &previousUserCmd, usercmd_t ¤tUserCmd, int frame, int time ) {
- if ( currentUserCmd.gameTime <= previousUserCmd.gameTime ) {
- currentUserCmd = previousUserCmd;
- currentUserCmd.gameFrame = frame;
- currentUserCmd.gameTime = time;
- currentUserCmd.duplicateCount++;
- if ( currentUserCmd.duplicateCount > MAX_USERCMD_DUPLICATION ) {
- currentUserCmd.buttons &= ~BUTTON_ATTACK;
- if ( abs( currentUserCmd.forwardmove ) > 2 ) currentUserCmd.forwardmove >>= 1;
- if ( abs( currentUserCmd.rightmove ) > 2 ) currentUserCmd.rightmove >>= 1;
- if ( abs( currentUserCmd.upmove ) > 2 ) currentUserCmd.upmove >>= 1;
- }
- return true;
- }
- return false;
- }
- /*
- ==================
- idAsyncNetwork::UsercmdInputChanged
- ==================
- */
- bool idAsyncNetwork::UsercmdInputChanged( const usercmd_t &previousUserCmd, const usercmd_t ¤tUserCmd ) {
- return previousUserCmd.buttons != currentUserCmd.buttons ||
- previousUserCmd.forwardmove != currentUserCmd.forwardmove ||
- previousUserCmd.rightmove != currentUserCmd.rightmove ||
- previousUserCmd.upmove != currentUserCmd.upmove ||
- previousUserCmd.angles[0] != currentUserCmd.angles[0] ||
- previousUserCmd.angles[1] != currentUserCmd.angles[1] ||
- previousUserCmd.angles[2] != currentUserCmd.angles[2];
- }
- /*
- ==================
- idAsyncNetwork::SpawnServer_f
- ==================
- */
- void idAsyncNetwork::SpawnServer_f( const idCmdArgs &args ) {
- if(args.Argc() > 1) {
- cvarSystem->SetCVarString("si_map", args.Argv(1));
- }
- // don't let a server spawn with singleplayer game type - it will crash
- if ( idStr::Icmp( cvarSystem->GetCVarString( "si_gameType" ), "singleplayer" ) == 0 ) {
- cvarSystem->SetCVarString( "si_gameType", "deathmatch" );
- }
- com_asyncInput.SetBool( false );
- // make sure the current system state is compatible with net_serverDedicated
- switch ( cvarSystem->GetCVarInteger( "net_serverDedicated" ) ) {
- case 0:
- case 2:
- if ( !renderSystem->IsOpenGLRunning() ) {
- common->Warning( "OpenGL is not running, net_serverDedicated == %d", cvarSystem->GetCVarInteger( "net_serverDedicated" ) );
- }
- break;
- case 1:
- if ( renderSystem->IsOpenGLRunning() ) {
- Sys_ShowConsole( 1, false );
- renderSystem->ShutdownOpenGL();
- }
- soundSystem->SetMute( true );
- soundSystem->ShutdownHW();
- break;
- }
- // use serverMapRestart if we already have a running server
- if ( server.IsActive() ) {
- cmdSystem->BufferCommandText( CMD_EXEC_NOW, "serverMapRestart" );
- } else {
- server.Spawn();
- }
- }
- /*
- ==================
- idAsyncNetwork::NextMap_f
- ==================
- */
- void idAsyncNetwork::NextMap_f( const idCmdArgs &args ) {
- server.ExecuteMapChange();
- }
- /*
- ==================
- idAsyncNetwork::Connect_f
- ==================
- */
- void idAsyncNetwork::Connect_f( const idCmdArgs &args ) {
- if ( server.IsActive() ) {
- common->Printf( "already running a server\n" );
- return;
- }
- if ( args.Argc() != 2 ) {
- common->Printf( "USAGE: connect <serverName>\n" );
- return;
- }
- com_asyncInput.SetBool( false );
- client.ConnectToServer( args.Argv( 1 ) );
- }
- /*
- ==================
- idAsyncNetwork::Reconnect_f
- ==================
- */
- void idAsyncNetwork::Reconnect_f( const idCmdArgs &args ) {
- client.Reconnect();
- }
- /*
- ==================
- idAsyncNetwork::GetServerInfo_f
- ==================
- */
- void idAsyncNetwork::GetServerInfo_f( const idCmdArgs &args ) {
- client.GetServerInfo( args.Argv( 1 ) );
- }
- /*
- ==================
- idAsyncNetwork::GetLANServers_f
- ==================
- */
- void idAsyncNetwork::GetLANServers_f( const idCmdArgs &args ) {
- client.GetLANServers();
- }
- /*
- ==================
- idAsyncNetwork::ListServers_f
- ==================
- */
- void idAsyncNetwork::ListServers_f( const idCmdArgs &args ) {
- client.ListServers();
- }
- /*
- ==================
- idAsyncNetwork::RemoteConsole_f
- ==================
- */
- void idAsyncNetwork::RemoteConsole_f( const idCmdArgs &args ) {
- client.RemoteConsole( args.Args() );
- }
- /*
- ==================
- idAsyncNetwork::Heartbeat_f
- ==================
- */
- void idAsyncNetwork::Heartbeat_f( const idCmdArgs &args ) {
- if ( !server.IsActive() ) {
- common->Printf( "server is not running\n" );
- return;
- }
- server.MasterHeartbeat( true );
- }
- /*
- ==================
- idAsyncNetwork::Kick_f
- ==================
- */
- void idAsyncNetwork::Kick_f( const idCmdArgs &args ) {
- idStr clientId;
- int iclient;
- if ( !server.IsActive() ) {
- common->Printf( "server is not running\n" );
- return;
- }
- clientId = args.Argv( 1 );
- if ( !clientId.IsNumeric() ) {
- common->Printf( "usage: kick <client number>\n" );
- return;
- }
- iclient = atoi( clientId );
-
- if ( server.GetLocalClientNum() == iclient ) {
- common->Printf( "can't kick the host\n" );
- return;
- }
- server.DropClient( iclient, "#str_07134" );
- }
- /*
- ==================
- idAsyncNetwork::GetNETServers
- ==================
- */
- void idAsyncNetwork::GetNETServers( ) {
- client.GetNETServers();
- }
- /*
- ==================
- idAsyncNetwork::CheckNewVersion_f
- ==================
- */
- void idAsyncNetwork::CheckNewVersion_f( const idCmdArgs &args ) {
- client.SendVersionCheck();
- }
- /*
- ==================
- idAsyncNetwork::ExecuteSessionCommand
- ==================
- */
- void idAsyncNetwork::ExecuteSessionCommand( const char *sessCmd ) {
- if ( sessCmd[ 0 ] ) {
- if ( !idStr::Icmp( sessCmd, "game_startmenu" ) ) {
- session->SetGUI( game->StartMenu(), NULL );
- }
- }
- }
- /*
- =================
- idAsyncNetwork::UpdateUI_f
- =================
- */
- void idAsyncNetwork::UpdateUI_f( const idCmdArgs &args ) {
- if ( args.Argc() != 2 ) {
- common->Warning( "idAsyncNetwork::UpdateUI_f: wrong arguments\n" );
- return;
- }
- if ( !server.IsActive() ) {
- common->Warning( "idAsyncNetwork::UpdateUI_f: server is not active\n" );
- return;
- }
- int clientNum = atoi( args.Args( 1 ) );
- server.UpdateUI( clientNum );
- }
- /*
- ===============
- idAsyncNetwork::BuildInvalidKeyMsg
- ===============
- */
- void idAsyncNetwork::BuildInvalidKeyMsg( idStr &msg, bool valid[ 2 ] ) {
- if ( !valid[ 0 ] ) {
- msg += common->GetLanguageDict()->GetString( "#str_07194" );
- }
- if ( fileSystem->HasD3XP() && !valid[ 1 ] ) {
- if ( msg.Length() ) {
- msg += "\n";
- }
- msg += common->GetLanguageDict()->GetString( "#str_07195" );
- }
- msg += "\n";
- msg += common->GetLanguageDict()->GetString( "#str_04304" );
- }
|