DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

sys_session_callbacks.cpp (16339B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 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.
     25 
     26 ===========================================================================
     27 */
     28 #pragma hdrstop
     29 #include "../idlib/precompiled.h"
     30 #include "../framework/Common_local.h"
     31 #include "sys_session_local.h"
     32 
     33 // The more the idLobby class needs to call back into this class, the more likely we're doing something wrong, and there is a better way.
     34 
     35 /*
     36 ========================
     37 idSessionLocalCallbacks::BecomingHost
     38 This is called when 
     39 ========================
     40 */
     41 bool idSessionLocalCallbacks::BecomingHost( idLobby & lobby ) {
     42 	if ( lobby.lobbyType == idLobby::TYPE_GAME ) {
     43 		if ( sessionLocal->GetActivePlatformLobby() != &lobby ) {
     44 			idLib::Printf( "BecomingHost: Must be past the party lobby to become host of a game lobby.\n" );
     45 			return false;
     46 		}
     47 		if ( sessionLocal->localState == idSessionLocal::STATE_INGAME || sessionLocal->localState == idSessionLocal::STATE_LOADING ) {
     48 			// If we are in a game, go back to the lobby before becoming the new host of a game lobby
     49 			sessionLocal->SetState( idSessionLocal::STATE_GAME_LOBBY_PEER );
     50 
     51 			// session mgr housekeeping that would usually be done through the standard EndMatch path
     52 			sessionLocal->EndMatchForMigration();
     53 		}
     54 	}
     55 
     56 	return true;
     57 }
     58 
     59 /*
     60 ========================
     61 idSessionLocalCallbacks::BecameHost
     62 ========================
     63 */
     64 void idSessionLocalCallbacks::BecameHost( idLobby & lobby ) {
     65 	// If we were in the lobby when we switched to host, then set the right state
     66 	if ( lobby.lobbyType == idLobby::TYPE_PARTY && sessionLocal->localState == idSessionLocal::STATE_PARTY_LOBBY_PEER ) {
     67 		sessionLocal->SetState( idSessionLocal::STATE_PARTY_LOBBY_HOST );
     68 	} else if ( lobby.lobbyType == idLobby::TYPE_GAME && sessionLocal->localState == idSessionLocal::STATE_GAME_LOBBY_PEER ) {
     69 		sessionLocal->SetState( idSessionLocal::STATE_GAME_LOBBY_HOST );
     70 	}
     71 }
     72 
     73 /*
     74 ========================
     75 idSessionLocalCallbacks::BecomingPeer
     76 ========================
     77 */
     78 bool idSessionLocalCallbacks::BecomingPeer( idLobby & lobby ) {
     79 	if ( lobby.lobbyType == idLobby::TYPE_GAME ) {
     80 		if ( sessionLocal->localState == idSessionLocal::STATE_INGAME || sessionLocal->localState == idSessionLocal::STATE_LOADING ) {
     81 			// Go to the party lobby while we try to connect to the new host
     82 			// This isn't totally necessary but we want to end the current game now and go to some screen.
     83 			// When the connection goes through or fails will send the session mgr to the appropriate state (game lobby or main menu)
     84 
     85 			// What happens if we got the game migration before the party migration?
     86 			sessionLocal->SetState( sessionLocal->GetPartyLobby().IsHost() ? idSessionLocal::STATE_PARTY_LOBBY_HOST : idSessionLocal::STATE_PARTY_LOBBY_PEER );
     87 			
     88 			// session mgr housekeeping that would usually be done through the standard EndMatch path
     89 			sessionLocal->EndMatchForMigration();
     90 
     91 			return true; // return true tells the session that we want him to tell us when the connects/fails
     92 		}
     93 	}
     94 	return false;
     95 }
     96 
     97 /*
     98 ========================
     99 idSessionLocalCallbacks::BecamePeer
    100 ========================
    101 */
    102 void idSessionLocalCallbacks::BecamePeer( idLobby & lobby ) {
    103 	if ( lobby.lobbyType == idLobby::TYPE_GAME ) {
    104 		sessionLocal->SetState( idSessionLocal::STATE_GAME_LOBBY_PEER );
    105 	}
    106 }
    107 
    108 /*
    109 ========================
    110 idSessionLocalCallbacks::FailedGameMigration
    111 ========================
    112 */
    113 void idSessionLocalCallbacks::FailedGameMigration( idLobby & lobby ) {
    114 	// We failed to complete a game migration this could happen for a couple reasons:
    115 	// -The network invites failed / failed to join migrated session
    116 	// -There was nobody to invite
    117 	lobby.ResetAllMigrationState();
    118 	if ( lobby.lobbyType == idLobby::TYPE_GAME ) { // this check is a  redundant since we should only get this CB from the game session
    119 
    120 		sessionLocal->SetState( idSessionLocal::STATE_GAME_LOBBY_HOST );
    121 
    122 		// Make sure the sessions are joinable again
    123 		sessionLocal->EndSessions();
    124 	}
    125 }
    126 
    127 /*
    128 ========================
    129 idSessionLocalCallbacks::MigrationEnded
    130 ========================
    131 */
    132 void idSessionLocalCallbacks::MigrationEnded( idLobby & lobby ) {
    133 	if ( lobby.migrationInfo.persistUntilGameEndsData.wasMigratedGame ) {
    134 #if 1
    135 		if ( lobby.lobbyType == idLobby::TYPE_GAME || ( lobby.lobbyType == idLobby::TYPE_PARTY && session->GetState() <= idSession::PARTY_LOBBY ) ) {
    136 			common->Dialog().ClearDialog( GDM_MIGRATING );
    137 			common->Dialog().ClearDialog( GDM_MIGRATING_WAITING );
    138 			common->Dialog().ClearDialog( GDM_MIGRATING_RELAUNCHING );
    139 
    140 			if ( lobby.GetNumLobbyUsers() <= 1 ) {
    141 				if ( MatchTypeHasStats( lobby.parms.matchFlags ) ) {
    142 					common->Dialog().AddDialog( GDM_MIGRATING_FAILED_DISBANDED_STATS, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );		// Game has disbanded
    143 				} else {
    144 					common->Dialog().AddDialog( GDM_MIGRATING_FAILED_DISBANDED, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );		// Game has disbanded
    145 				}
    146 			} else {
    147 				//common->Dialog().AddDialog( GDM_MIGRATING_FAILED_CONNECTION, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );		// Lost connection to game
    148 				if ( lobby.lobbyType == idLobby::TYPE_GAME && MatchTypeHasStats( lobby.parms.matchFlags ) ) {
    149 					// This means we came from a public match, so tell them they didn't lose stats
    150 					common->Dialog().AddDialog( GDM_HOST_CONNECTION_LOST_STATS, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );		// The connection to the host has been lost. This game will not count towards your ranking.
    151 				} else {
    152 					// This means we came from a private match, just say host quit
    153 					common->Dialog().AddDialog( GDM_HOST_CONNECTION_LOST, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );			// The connection to the host has been lost.
    154 				}
    155 			}
    156 
    157 			lobby.ResetAllMigrationState();
    158 				
    159 			// Make sure the sessions are joinable again
    160 			sessionLocal->EndSessions();
    161 		}
    162 #else
    163 		// If we get here, we migrated from a game
    164 		if ( lobby.GetNumLobbyUsers() <= 1 && lobby.lobbyType == idLobby::TYPE_GAME ) {
    165 			if ( !MatchTypeIsJoinInProgress( lobby.parms.matchFlags ) ) {
    166 				// Handles 'soft' failed game migration where we migrated from a game and are now alone
    167 				gameDialogMessages_t errorDlg = GDM_INVALID;
    168 				lobby.migrationInfo.persistUntilGameEndsData.hasGameData = false; // never restart the game if we are by ourselves
    169 				if ( lobby.migrationInfo.invites.Num() > 0 ) {
    170 					// outstanding invites: migration failed
    171 					errorDlg = ( MatchTypeHasStats( lobby.migrateMsgFlags ) && ( sessionLocal->GetFlushedStats() == false ) ) ? GDM_MIGRATING_FAILED_CONNECTION_STATS : GDM_MIGRATING_FAILED_CONNECTION;
    172 				} else {
    173 					// there was no one to invite
    174 					errorDlg = ( MatchTypeHasStats( lobby.migrateMsgFlags ) && ( sessionLocal->GetFlushedStats() == false ) ) ? GDM_MIGRATING_FAILED_DISBANDED_STATS : GDM_MIGRATING_FAILED_DISBANDED;
    175 				}
    176 				if ( errorDlg != GDM_INVALID ) {
    177 					common->Dialog().AddDialog( errorDlg, DIALOG_ACCEPT, NULL, NULL, false );
    178 				}
    179 				common->Dialog().ClearDialog( GDM_MIGRATING );
    180 				common->Dialog().ClearDialog( GDM_MIGRATING_WAITING );
    181 				common->Dialog().ClearDialog( GDM_MIGRATING_RELAUNCHING );
    182 
    183 				FailedGameMigration( lobby );
    184 			}
    185 		} else if ( lobby.lobbyType == idLobby::TYPE_PARTY ) {
    186 			if ( session->GetState() <= idSession::PARTY_LOBBY ) {
    187 				// We got dropped the party lobby, let them know what happened
    188 				common->Dialog().ClearDialog( GDM_MIGRATING );
    189 				common->Dialog().ClearDialog( GDM_MIGRATING_WAITING );
    190 				common->Dialog().ClearDialog( GDM_MIGRATING_RELAUNCHING );
    191 
    192 				if ( lobby.GetNumLobbyUsers() <= 1 ) {
    193 					common->Dialog().AddDialog( GDM_MIGRATING_FAILED_DISBANDED, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );		// Game has disbanded
    194 				} else {
    195 					//common->Dialog().AddDialog( GDM_MIGRATING_FAILED_CONNECTION, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );	// Lost connection to game
    196 					common->Dialog().AddDialog( GDM_HOST_CONNECTION_LOST_STATS, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );
    197 				}
    198 
    199 				lobby.ResetAllMigrationState();
    200 				
    201 				// Make sure the sessions are joinable again
    202 				sessionLocal->EndSessions();
    203 			}
    204 		}
    205 #endif
    206 	} else if ( lobby.GetNumLobbyUsers() <= 1 && session->GetState() == idSession::PARTY_LOBBY ) {
    207 		// If they didn't come from a game, and are by themselves, just show the lobby disband msg
    208 		common->Dialog().AddDialog( GDM_LOBBY_DISBANDED, DIALOG_ACCEPT, NULL, NULL, false, "", 0, true );				// The lobby you were previously in has disbanded
    209 
    210 		// Make sure the sessions are joinable again
    211 		sessionLocal->EndSessions();
    212 	}
    213 }
    214 
    215 /*
    216 ========================
    217 idSessionLocalCallbacks::GoodbyeFromHost
    218 ========================
    219 */
    220 void idSessionLocalCallbacks::GoodbyeFromHost( idLobby & lobby, int peerNum, const lobbyAddress_t & remoteAddress, int msgType ) {
    221 	sessionLocal->GoodbyeFromHost( lobby, peerNum, remoteAddress, msgType );	
    222 }
    223 
    224 /*
    225 ========================
    226 idSessionLocalCallbacks::AnyPeerHasAddress
    227 ========================
    228 */
    229 bool idSessionLocalCallbacks::AnyPeerHasAddress( const lobbyAddress_t & remoteAddress ) const { 
    230 	return sessionLocal->GetPartyLobby().FindAnyPeer( remoteAddress ) || sessionLocal->GetGameLobby().FindAnyPeer( remoteAddress ); 
    231 }
    232 
    233 /*
    234 ========================
    235 idSessionLocalCallbacks::RecvLeaderboardStats
    236 ========================
    237 */
    238 void idSessionLocalCallbacks::RecvLeaderboardStats( idBitMsg & msg ) {
    239 	// Steam and PS3 just write them as they come per player, they don't need to flush
    240 	sessionLocal->RecvLeaderboardStatsForPlayer( msg );
    241 }
    242 
    243 /*
    244 ========================
    245 idSessionLocalCallbacks::ReceivedFullSnap
    246 ========================
    247 */
    248 void idSessionLocalCallbacks::ReceivedFullSnap() {
    249 	// If we received a full snap, then we can transition into the INGAME state
    250 	sessionLocal->numFullSnapsReceived++;
    251 
    252 	if ( sessionLocal->numFullSnapsReceived < 2 ) {
    253 		return;
    254 	}
    255 
    256 	if ( sessionLocal->localState != idSessionLocal::STATE_INGAME ) {
    257 		sessionLocal->GetActingGameStateLobby().QueueReliableMessage( sessionLocal->GetActingGameStateLobby().host, idLobby::RELIABLE_IN_GAME );		// Let host know we are in game now
    258 		sessionLocal->SetState( idSessionLocal::STATE_INGAME );
    259 	}
    260 }
    261 
    262 /*
    263 ========================
    264 idSessionLocalCallbacks::LeaveGameLobby
    265 ========================
    266 */
    267 void idSessionLocalCallbacks::LeaveGameLobby() {
    268 	
    269 	// Make sure we're in the game lobby
    270 	if ( session->GetState() != idSession::GAME_LOBBY ) {
    271 		return;
    272 	}
    273 
    274 	// If we're the host of the party, only we are allowed to make this call
    275 	if ( sessionLocal->GetPartyLobby().IsHost() ) {
    276 		return;
    277 	}
    278 
    279 	sessionLocal->GetGameLobby().Shutdown();
    280 	sessionLocal->SetState( idSessionLocal::STATE_PARTY_LOBBY_PEER );
    281 }
    282 
    283 /*
    284 ========================
    285 idSessionLocalCallbacks::PrePickNewHost
    286 This is called when we have determined that we need to pick a new host.
    287 Call PickNewHostInternal to continue on with the host picking process.
    288 ========================
    289 */
    290 void idSessionLocalCallbacks::PrePickNewHost( idLobby & lobby, bool forceMe, bool inviteOldHost ) {
    291 	sessionLocal->PrePickNewHost( lobby, forceMe, inviteOldHost );
    292 }
    293 
    294 /*
    295 ========================
    296 idSessionLocalCallbacks::PreMigrateInvite
    297 This is called just before we get invited to a migrated session
    298 If we return false, the invite will be ignored
    299 ========================
    300 */
    301 bool idSessionLocalCallbacks::PreMigrateInvite( idLobby & lobby ) {
    302 	return sessionLocal->PreMigrateInvite( lobby );
    303 }
    304 
    305 /*
    306 ========================
    307 idSessionLocalCallbacks::ConnectAndMoveToLobby
    308 ========================
    309 */
    310 void idSessionLocalCallbacks::ConnectAndMoveToLobby( idLobby::lobbyType_t destLobbyType, const lobbyConnectInfo_t & connectInfo, bool waitForPartyOk ) {
    311 	
    312 	// See if we are already in the game lobby
    313 	idLobby * lobby = sessionLocal->GetLobbyFromType( destLobbyType );
    314 
    315 	if ( lobby == NULL ) {
    316 		idLib::Printf( "RELIABLE_CONNECT_AND_MOVE_TO_LOBBY: Invalid lobby type.\n" ); 
    317 		return;
    318 	}
    319 
    320 	if ( lobby->lobbyBackend != NULL && lobby->lobbyBackend->IsOwnerOfConnectInfo( connectInfo ) ) {
    321 		idLib::Printf( "RELIABLE_CONNECT_AND_MOVE_TO_LOBBY: Already in lobby.\n" ); 
    322 		return;
    323 	}
    324 
    325 	// See if we are in a game, or loading into a game.  If so, ignore invites from our party host
    326 	if ( destLobbyType == idLobby::TYPE_GAME || destLobbyType == idLobby::TYPE_GAME_STATE ) { 
    327 		if ( GetState() == idSession::INGAME || GetState() == idSession::LOADING ) {
    328 			idLib::Printf( "RELIABLE_CONNECT_AND_MOVE_TO_LOBBY: In a different game, ignoring.\n" ); 
    329 			return;
    330 		}
    331 	}
    332 
    333 	// End current game lobby
    334 	lobby->Shutdown();
    335 
    336 	// waitForPartyOk will be true if the party host wants us to wait for his ok to stay in the lobby
    337 	lobby->waitForPartyOk = waitForPartyOk;
    338 		
    339 	// Connect to new game lobby
    340 	sessionLocal->ConnectAndMoveToLobby( *lobby, connectInfo, true );		// Consider this an invite if party host told us to connect
    341 }
    342 
    343 /*
    344 ========================
    345 idSessionLocalCallbacks::HandleServerQueryRequest
    346 ========================
    347 */
    348 void idSessionLocalCallbacks::HandleServerQueryRequest( lobbyAddress_t & remoteAddr, idBitMsg & msg, int msgType ) {
    349 	sessionLocal->HandleServerQueryRequest( remoteAddr, msg, msgType );
    350 }
    351 
    352 /*
    353 ========================
    354 idSessionLocalCallbacks::HandleServerQueryAck
    355 ========================
    356 */
    357 void idSessionLocalCallbacks::HandleServerQueryAck( lobbyAddress_t & remoteAddr, idBitMsg & msg ) {
    358 	sessionLocal->HandleServerQueryAck( remoteAddr, msg );
    359 }
    360 
    361 extern idCVar net_headlessServer;
    362 
    363 /*
    364 ========================
    365 idSessionLocalCallbacks::HandlePeerMatchParamUpdate
    366 ========================
    367 */
    368 void idSessionLocalCallbacks::HandlePeerMatchParamUpdate( int peer, int msg ) {
    369 	if ( net_headlessServer.GetBool() ) {
    370 		sessionLocal->storedPeer = peer;
    371 		sessionLocal->storedMsgType = msg;
    372 	}
    373 }
    374 
    375 /*
    376 ========================
    377 idSessionLocalCallbacks::CreateLobbyBackend
    378 ========================
    379 */
    380 idLobbyBackend * idSessionLocalCallbacks::CreateLobbyBackend( const idMatchParameters & p, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType ) {
    381 	return sessionLocal->CreateLobbyBackend( p, skillLevel, lobbyType );
    382 }
    383 
    384 /*
    385 ========================
    386 idSessionLocalCallbacks::FindLobbyBackend
    387 ========================
    388 */
    389 idLobbyBackend * idSessionLocalCallbacks::FindLobbyBackend( const idMatchParameters & p, int numPartyUsers, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType ) {
    390 	return sessionLocal->FindLobbyBackend( p, numPartyUsers, skillLevel, lobbyType );
    391 }
    392 
    393 /*
    394 ========================
    395 idSessionLocalCallbacks::JoinFromConnectInfo
    396 ========================
    397 */
    398 idLobbyBackend * idSessionLocalCallbacks::JoinFromConnectInfo( const lobbyConnectInfo_t & connectInfo , idLobbyBackend::lobbyBackendType_t lobbyType ) {
    399 	return sessionLocal->JoinFromConnectInfo( connectInfo, lobbyType );
    400 }
    401 
    402 /*
    403 ========================
    404 idSessionLocalCallbacks::DestroyLobbyBackend
    405 ========================
    406 */
    407 void idSessionLocalCallbacks::DestroyLobbyBackend( idLobbyBackend * lobbyBackend ) {
    408 	sessionLocal->DestroyLobbyBackend( lobbyBackend );
    409 }