2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
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 .
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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# include "sys_session_local.h"
# include "sys_voicechat.h"
# include "sys_dedicated_server_search.h"
idCVar ui_skinIndex ( " ui_skinIndex " , " 0 " , CVAR_ARCHIVE , " Selected skin index " ) ;
idCVar ui_autoSwitch ( " ui_autoSwitch " , " 1 " , CVAR_ARCHIVE | CVAR_BOOL , " auto switch weapon " ) ;
idCVar ui_autoReload ( " ui_autoReload " , " 1 " , CVAR_ARCHIVE | CVAR_BOOL , " auto reload weapon " ) ;
idCVar net_maxSearchResults ( " net_maxSearchResults " , " 25 " , CVAR_INTEGER , " Max results that are allowed to be returned in a search request " ) ;
idCVar net_maxSearchResultsToTry ( " net_maxSearchResultsToTry " , " 5 " , CVAR_INTEGER , " Max results to try before giving up. " ) ; // At 15 second timeouts per, 1 min 15 worth of connecting attempt time
idCVar net_LobbyCoalesceTimeInSeconds ( " net_LobbyCoalesceTimeInSeconds " , " 30 " , CVAR_INTEGER , " Time in seconds when a lobby will try to coalesce with another lobby when there is only one user. " ) ;
idCVar net_LobbyRandomCoalesceTimeInSeconds ( " net_LobbyRandomCoalesceTimeInSeconds " , " 3 " , CVAR_INTEGER , " Random time to add to net_LobbyCoalesceTimeInSeconds " ) ;
idCVar net_useGameStateLobby ( " net_useGameStateLobby " , " 0 " , CVAR_BOOL , " " ) ;
//idCVar net_useGameStateLobby( "net_useGameStateLobby", "1", CVAR_BOOL, "" );
# if !defined( ID_RETAIL ) || defined( ID_RETAIL_INTERNAL )
idCVar net_ignoreTitleStorage ( " net_ignoreTitleStorage " , " 0 " , CVAR_BOOL , " Ignore title storage " ) ;
# endif
idCVar net_maxLoadResourcesTimeInSeconds ( " net_maxLoadResourcesTimeInSeconds " , " 0 " , CVAR_INTEGER , " How long, in seconds, clients have to load resources. Used for loose asset builds. " ) ;
idCVar net_migrateHost ( " net_migrateHost " , " -1 " , CVAR_INTEGER , " Become host of session (0 = party, 1 = game) for testing purposes " ) ;
extern idCVar net_debugBaseStates ;
idCVar net_testPartyMemberConnectFail ( " net_testPartyMemberConnectFail " , " -1 " , CVAR_INTEGER , " Force this party member index to fail to connect to games. " ) ;
//FIXME: this could use a better name.
2012-11-28 15:47:07 +00:00
idCVar net_offlineTransitionThreshold ( " net_offlineTransitionThreshold " , " 1000 " , CVAR_INTEGER , " Time, in milliseconds, to wait before kicking back to the main menu when a profile losses backend connection during an online game " ) ;
2012-11-26 18:58:24 +00:00
idCVar net_port ( " net_port " , " 27015 " , CVAR_INTEGER , " host port number " ) ; // Port to host when using dedicated servers, port to broadcast on when looking for a dedicated server to connect to
idCVar net_headlessServer ( " net_headlessServer " , " 0 " , CVAR_BOOL , " toggle to automatically host a game and allow peer[0] to control menus " ) ;
2012-11-28 15:47:07 +00:00
const char * idSessionLocal : : stateToString [ NUM_STATES ] =
{
2012-11-26 18:58:24 +00:00
ASSERT_ENUM_STRING ( STATE_PRESS_START , 0 ) ,
ASSERT_ENUM_STRING ( STATE_IDLE , 1 ) ,
ASSERT_ENUM_STRING ( STATE_PARTY_LOBBY_HOST , 2 ) ,
ASSERT_ENUM_STRING ( STATE_PARTY_LOBBY_PEER , 3 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_LOBBY_HOST , 4 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_LOBBY_PEER , 5 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_STATE_LOBBY_HOST , 6 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_STATE_LOBBY_PEER , 7 ) ,
ASSERT_ENUM_STRING ( STATE_CREATE_AND_MOVE_TO_PARTY_LOBBY , 8 ) ,
ASSERT_ENUM_STRING ( STATE_CREATE_AND_MOVE_TO_GAME_LOBBY , 9 ) ,
ASSERT_ENUM_STRING ( STATE_CREATE_AND_MOVE_TO_GAME_STATE_LOBBY , 10 ) ,
ASSERT_ENUM_STRING ( STATE_FIND_OR_CREATE_MATCH , 11 ) ,
ASSERT_ENUM_STRING ( STATE_CONNECT_AND_MOVE_TO_PARTY , 12 ) ,
ASSERT_ENUM_STRING ( STATE_CONNECT_AND_MOVE_TO_GAME , 13 ) ,
ASSERT_ENUM_STRING ( STATE_CONNECT_AND_MOVE_TO_GAME_STATE , 14 ) ,
ASSERT_ENUM_STRING ( STATE_BUSY , 15 ) ,
ASSERT_ENUM_STRING ( STATE_LOADING , 16 ) ,
ASSERT_ENUM_STRING ( STATE_INGAME , 17 ) ,
} ;
2012-11-28 15:47:07 +00:00
struct netVersion_s
{
netVersion_s ( )
{
sprintf ( string , " %s.%d " , ENGINE_VERSION , BUILD_NUMBER ) ;
}
2012-11-26 18:58:24 +00:00
char string [ 256 ] ;
} netVersion ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
NetGetVersionChecksum
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-12 11:11:55 +00:00
// RB: 64 bit fixes, changed long to int
unsigned int NetGetVersionChecksum ( )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
#if 0
return idStr ( com_version . GetString ( ) ) . Hash ( ) ;
# else
2012-12-12 11:11:55 +00:00
unsigned int ret = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
CRC32_InitChecksum ( ret ) ;
CRC32_UpdateChecksum ( ret , netVersion . string , idStr : : Length ( netVersion . string ) ) ;
CRC32_FinishChecksum ( ret ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NetGetVersionChecksum - string : %s \n " , netVersion . string ) ;
NET_VERBOSE_PRINT ( " NetGetVersionChecksum - checksum : %i \n " , ret ) ;
2012-11-28 15:47:07 +00:00
return ret ;
2012-11-26 18:58:24 +00:00
# endif
}
2012-12-12 11:11:55 +00:00
// RB end
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : idSessionLocal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
idSessionLocal : : idSessionLocal ( ) :
2012-11-28 15:47:07 +00:00
processorSaveFiles ( new ( TAG_SAVEGAMES ) idSaveGameProcessorSaveFiles ) ,
processorLoadFiles ( new ( TAG_SAVEGAMES ) idSaveGameProcessorLoadFiles ) ,
processorDelete ( new ( TAG_SAVEGAMES ) idSaveGameProcessorDelete ) ,
processorEnumerate ( new ( TAG_SAVEGAMES ) idSaveGameProcessorEnumerateGames )
{
2012-11-26 18:58:24 +00:00
InitBaseState ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : idSessionLocal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSessionLocal : : ~ idSessionLocal ( )
{
2012-11-26 18:58:24 +00:00
delete processorSaveFiles ;
delete processorLoadFiles ;
delete processorDelete ;
delete processorEnumerate ;
delete sessionCallbacks ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : InitBaseState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : InitBaseState ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
//assert( mem.IsGlobalHeap() );
2012-11-26 18:58:24 +00:00
localState = STATE_PRESS_START ;
sessionOptions = 0 ;
currentID = 0 ;
2012-11-28 15:47:07 +00:00
sessionCallbacks = new ( TAG_NETWORKING ) idSessionLocalCallbacks ( this ) ;
2012-11-26 18:58:24 +00:00
connectType = CONNECT_NONE ;
connectTime = 0 ;
upstreamDropRate = 0.0f ;
upstreamDropRateTime = 0 ;
upstreamQueueRate = 0.0f ;
upstreamQueueRateTime = 0 ;
queuedBytes = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastVoiceSendtime = 0 ;
hasShownVoiceRestrictionDialog = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
isSysUIShowing = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pendingInviteDevice = 0 ;
pendingInviteMode = PENDING_INVITE_NONE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
downloadedContent . Clear ( ) ;
marketplaceHasNewContent = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
offlineTransitionTimerStart = 0 ;
showMigratingInfoStartTime = 0 ;
nextGameCoalesceTime = 0 ;
gameLobbyWasCoalesced = false ;
numFullSnapsReceived = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
flushedStats = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
titleStorageLoaded = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
droppedByHost = false ;
loadingID = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
storedPeer = - 1 ;
storedMsgType = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inviteInfoRequested = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
enumerationHandle = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
waitingOnGameStateMembersToLeaveTime = 0 ;
waitingOnGameStateMembersToJoinTime = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : FinishDisconnect
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : FinishDisconnect ( )
{
GetPort ( ) . Close ( ) ;
while ( sendQueue . Peek ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
sendQueue . RemoveFirst ( ) ;
}
2012-11-28 15:47:07 +00:00
while ( recvQueue . Peek ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
recvQueue . RemoveFirst ( ) ;
}
}
//====================================================================================
idCVar net_connectTimeoutInSeconds ( " net_connectTimeoutInSeconds " , " 15 " , CVAR_INTEGER , " timeout (in seconds) while connecting " ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : CreatePartyLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : CreatePartyLobby ( const idMatchParameters & parms_ )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: CreatePartyLobby \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Shutdown any possible party lobby
GetPartyLobby ( ) . Shutdown ( ) ;
GetPartyLobby ( ) . ResetAllMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Shutdown any possible game lobby
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Start hosting a new party lobby
GetPartyLobby ( ) . StartHosting ( parms_ ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectType = CONNECT_NONE ;
connectTime = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Wait for it to complete
SetState ( STATE_CREATE_AND_MOVE_TO_PARTY_LOBBY ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : CreateMatch
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : CreateMatch ( const idMatchParameters & p )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: CreateMatch \n " ) ;
2012-11-28 15:47:07 +00:00
if ( ( p . matchFlags & MATCH_PARTY_INVITE_PLACEHOLDER ) & & ! GetPartyLobby ( ) . IsLobbyActive ( ) )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: CreateMatch MATCH_PARTY_INVITE_PLACEHOLDER \n " ) ;
CreatePartyLobby ( p ) ;
connectType = CONNECT_NONE ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Shutdown any possible game lobby
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
GetGameLobby ( ) . ResetAllMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Start hosting a new game lobby
GetGameLobby ( ) . StartHosting ( p ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectType = CONNECT_NONE ;
connectTime = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Wait for it to complete
SetState ( STATE_CREATE_AND_MOVE_TO_GAME_LOBBY ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : CreateGameStateLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : CreateGameStateLobby ( const idMatchParameters & p )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: CreateGameStateLobby \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Shutdown any possible game state lobby
GetGameStateLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . ResetAllMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Start hosting a new game lobby
GetGameStateLobby ( ) . StartHosting ( p ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectType = CONNECT_NONE ;
connectTime = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
waitingOnGameStateMembersToLeaveTime = 0 ; // Make sure to reset
waitingOnGameStateMembersToJoinTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Wait for it to complete
SetState ( STATE_CREATE_AND_MOVE_TO_GAME_STATE_LOBBY ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : FindOrCreateMatch
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : FindOrCreateMatch ( const idMatchParameters & p )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: FindOrCreateMatch \n " ) ;
2012-11-28 15:47:07 +00:00
if ( ( p . matchFlags & MATCH_PARTY_INVITE_PLACEHOLDER ) & & ! GetPartyLobby ( ) . IsLobbyActive ( ) )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: FindOrCreateMatch MATCH_PARTY_INVITE_PLACEHOLDER \n " ) ;
CreatePartyLobby ( p ) ;
connectType = CONNECT_FIND_OR_CREATE ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Shutdown any possible game lobby
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
GetGameLobby ( ) . ResetAllMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Start searching for a game
GetGameLobby ( ) . StartFinding ( p ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectType = CONNECT_FIND_OR_CREATE ;
connectTime = Sys_Milliseconds ( ) ;
gameLobbyWasCoalesced = false ;
numFullSnapsReceived = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Wait for searching to complete
SetState ( STATE_FIND_OR_CREATE_MATCH ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : StartLoading
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : StartLoading ( )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: StartLoading \n " ) ;
2012-11-28 15:47:07 +00:00
if ( MatchTypeIsOnline ( GetActingGameStateLobby ( ) . parms . matchFlags ) )
{
if ( ! GetActingGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " Ignoring call to StartLoading because we are not the host. state is %s " , stateToString [ localState ] ) ;
return ;
}
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
if ( GetActingGameStateLobby ( ) . peers [ p ] . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . QueueReliableMessage ( p , idLobby : : RELIABLE_START_LOADING ) ;
GetActingGameStateLobby ( ) . peers [ p ] . startResourceLoadTime = Sys_Milliseconds ( ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
VerifySnapshotInitialState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetState ( STATE_LOADING ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : StartMatch
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : StartMatch ( )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: StartMatch \n " ) ;
2012-11-28 15:47:07 +00:00
if ( net_headlessServer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
StartLoading ( ) ; // This is so we can force start matches on headless servers to test performance using bots
return ;
}
2012-11-28 15:47:07 +00:00
if ( localState ! = STATE_GAME_LOBBY_HOST )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " idSessionLocal::StartMatch called when not hosting game lobby " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! GetGameStateLobby ( ) . IsLobbyActive ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make absolutely sure we only call StartMatch once per migrate
GetGameLobby ( ) . migrationInfo . persistUntilGameEndsData . hasRelaunchedMigratedGame = true ;
// Clear snap ack queue between games
GetGameLobby ( ) . snapDeltaAckQueue . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
extern idCVar net_bw_challenge_enable ;
2012-11-28 15:47:07 +00:00
if ( session - > GetTitleStorageBool ( " net_bw_challenge_enable " , net_bw_challenge_enable . GetBool ( ) ) & & GetGameLobby ( ) . HasActivePeers ( ) )
{
GetGameLobby ( ) . bandwidthChallengeFinished = false ;
2012-11-26 18:58:24 +00:00
StartOrContinueBandwidthChallenge ( false ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . BandwidthTestStarted ( ) )
{
// Put session in busy state
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: StartMatch -> Start Bandwidth Challenge \n " ) ;
SetState ( STATE_BUSY ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Start loading
StartLoading ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetBackState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSessionLocal : : sessionState_t idSessionLocal : : GetBackState ( )
{
2012-11-26 18:58:24 +00:00
sessionState_t currentState = GetState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool isInGameLobby = currentState = = GAME_LOBBY ;
const bool isInPartyLobby = currentState = = PARTY_LOBBY ;
const bool isInGame = currentState = = INGAME | | currentState = = LOADING ; // Counting loading as ingame as far as what back state to go to
2012-11-28 15:47:07 +00:00
if ( isInGame )
{
2012-11-26 18:58:24 +00:00
return GAME_LOBBY ; // If in the game, go back to game lobby
}
2012-11-28 15:47:07 +00:00
if ( ! isInPartyLobby & & isInGameLobby & & ShouldHavePartyLobby ( ) )
{
2012-11-26 18:58:24 +00:00
return PARTY_LOBBY ; // If in the game lobby, and we should have a party lobby, and we are the host, go back to party lobby
}
2012-11-28 15:47:07 +00:00
if ( currentState ! = IDLE )
{
2012-11-26 18:58:24 +00:00
return IDLE ; // From here, go to idle if we aren't there yet
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return PRESS_START ; // Otherwise, go back to press start
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : Cancel
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : Cancel ( )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: Cancel \n " ) ;
2012-11-28 15:47:07 +00:00
if ( localState = = STATE_PRESS_START )
{
2012-11-26 18:58:24 +00:00
return ; // We're as far back as we can go
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ClearVoiceGroups ( ) ; // this is here as a catch-all
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// See what state we need to go to
2012-11-28 15:47:07 +00:00
switch ( GetBackState ( ) )
{
2012-11-26 18:58:24 +00:00
case GAME_LOBBY :
EndMatch ( ) ; // End current match to go to game lobby
break ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
case PARTY_LOBBY :
2012-11-28 15:47:07 +00:00
if ( GetPartyLobby ( ) . IsHost ( ) )
{
if ( sessionOptions & OPTION_LEAVE_WITH_PARTY )
{
// NOTE - This will send a message on the team lobby channel,
2012-11-26 18:58:24 +00:00
// so it won't be affected by the fact that we're shutting down the game lobby
GetPartyLobby ( ) . NotifyPartyOfLeavingGameLobby ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Host wants to be alone, disconnect all peers from the party
2012-11-28 15:47:07 +00:00
GetPartyLobby ( ) . DisconnectAllPeers ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// End the game lobby, and go back to party lobby as host
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
SetState ( STATE_PARTY_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Always remove this flag. SendGoodbye uses this to determine if we should send a "leave with party"
// and we don't want this flag hanging around, and causing false positives when it's called in the future.
// Make them set this each time.
sessionOptions & = ~ OPTION_LEAVE_WITH_PARTY ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// If we aren't the host of a party and we want to go back to one, we need to create a party now
CreatePartyLobby ( GetPartyLobby ( ) . parms ) ;
}
break ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
case IDLE :
// Go back to main menu
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
GetPartyLobby ( ) . Shutdown ( ) ;
SetState ( STATE_IDLE ) ;
break ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
case PRESS_START :
// Go back to press start/main
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
GetPartyLobby ( ) . Shutdown ( ) ;
SetState ( STATE_PRESS_START ) ;
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Validate the current lobby immediately
ValidateLobbies ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : MoveToPressStart
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : MoveToPressStart ( )
{
if ( localState ! = STATE_PRESS_START )
{
2012-11-26 18:58:24 +00:00
assert ( signInManager ! = NULL ) ;
signInManager - > RemoveAllLocalUsers ( ) ;
hasShownVoiceRestrictionDialog = false ;
MoveToMainMenu ( ) ;
session - > FinishDisconnect ( ) ;
SetState ( STATE_PRESS_START ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ShouldShowMigratingDialog
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : ShouldShowMigratingDialog ( ) const
{
const idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
return activeLobby - > ShouldShowMigratingDialog ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : IsCurrentLobbyMigrating
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : IsCurrentLobbyMigrating ( ) const
{
const idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return activeLobby - > IsMigrating ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : IsLosingConnectionToHost
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : IsLosingConnectionToHost ( ) const
{
2012-11-26 18:58:24 +00:00
return GetActingGameStateLobby ( ) . IsLosingConnectionToHost ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : WasMigrationGame
returns true if we are hosting a migrated game and we had valid migration data
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : WasMigrationGame ( ) const
{
2012-11-26 18:58:24 +00:00
return GetGameLobby ( ) . IsMigratedStatsGame ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ShouldRelaunchMigrationGame
returns true if we are hosting a migrated game and we had valid migration data
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : ShouldRelaunchMigrationGame ( ) const
{
2012-11-26 18:58:24 +00:00
return GetGameLobby ( ) . ShouldRelaunchMigrationGame ( ) & & ! IsCurrentLobbyMigrating ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetMigrationGameData
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : GetMigrationGameData ( idBitMsg & msg , bool reading )
{
2012-11-26 18:58:24 +00:00
return GetGameLobby ( ) . GetMigrationGameData ( msg , reading ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetMigrationGameDataUser
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : GetMigrationGameDataUser ( lobbyUserID_t lobbyUserID , idBitMsg & msg , bool reading )
{
if ( GetGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return GetGameLobby ( ) . GetMigrationGameDataUser ( lobbyUserID , msg , reading ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetMatchParamUpdate
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : GetMatchParamUpdate ( int & peer , int & msg )
{
if ( storedPeer ! = - 1 & & storedMsgType ! = - 1 )
{
2012-11-26 18:58:24 +00:00
peer = storedPeer ;
msg = storedMsgType ;
storedPeer = - 1 ;
storedMsgType = - 1 ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : UpdatePartyParms
Updates the party parameters when in a party lobby OR a game lobby in order to keep them always in sync .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : UpdatePartyParms ( const idMatchParameters & p )
{
if ( ( GetState ( ) ! = PARTY_LOBBY & & GetState ( ) ! = GAME_LOBBY ) | | ! GetPartyLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// NET_VERBOSE_PRINT( "NET: UpdatePartyParms\n" );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetPartyLobby ( ) . UpdateMatchParms ( p ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : UpdateMatchParms
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : UpdateMatchParms ( const idMatchParameters & p )
{
if ( GetState ( ) ! = GAME_LOBBY | | ! GetGameLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: UpdateMatchParms \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetGameLobby ( ) . UpdateMatchParms ( p ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : StartSessions
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : StartSessions ( )
{
if ( GetPartyLobby ( ) . lobbyBackend ! = NULL )
{
2012-11-26 18:58:24 +00:00
GetPartyLobby ( ) . lobbyBackend - > StartSession ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . lobbyBackend ! = NULL )
{
2012-11-26 18:58:24 +00:00
GetGameLobby ( ) . lobbyBackend - > StartSession ( ) ;
}
SetLobbiesAreJoinable ( false ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : EndSessions
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : EndSessions ( )
{
if ( GetPartyLobby ( ) . lobbyBackend ! = NULL )
{
2012-11-26 18:58:24 +00:00
GetPartyLobby ( ) . lobbyBackend - > EndSession ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . lobbyBackend ! = NULL )
{
2012-11-26 18:58:24 +00:00
GetGameLobby ( ) . lobbyBackend - > EndSession ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetLobbiesAreJoinable ( true ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SetLobbiesAreJoinable
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SetLobbiesAreJoinable ( bool joinable )
{
2012-11-26 18:58:24 +00:00
// NOTE - We don't manipulate the joinable state when we are supporting join in progress
// Lobbies will naturally be non searchable when there are no free slots
2012-11-28 15:47:07 +00:00
if ( GetPartyLobby ( ) . lobbyBackend ! = NULL & & ! MatchTypeIsJoinInProgress ( GetPartyLobby ( ) . parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " Party lobbyBackend SetIsJoinable: %d \n " , joinable ) ;
GetPartyLobby ( ) . lobbyBackend - > SetIsJoinable ( joinable ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . lobbyBackend ! = NULL & & ! MatchTypeIsJoinInProgress ( GetGameLobby ( ) . parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
GetGameLobby ( ) . lobbyBackend - > SetIsJoinable ( joinable ) ;
NET_VERBOSE_PRINT ( " Game lobbyBackend SetIsJoinable: %d \n " , joinable ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : MoveToMainMenu
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : MoveToMainMenu ( )
{
2012-11-26 18:58:24 +00:00
GetPartyLobby ( ) . Shutdown ( ) ;
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
SetState ( STATE_IDLE ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleVoiceRestrictionDialog
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : HandleVoiceRestrictionDialog ( )
{
2012-11-26 18:58:24 +00:00
// don't bother complaining about voice restrictions when in a splitscreen lobby
2012-11-28 15:47:07 +00:00
if ( MatchTypeIsLocal ( GetActivePlatformLobby ( ) - > parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Pop a dialog up the first time we are in a lobby and have voice chat restrictions due to account privileges
2012-11-28 15:47:07 +00:00
if ( voiceChat ! = NULL & & voiceChat - > IsRestrictedByPrivleges ( ) & & ! hasShownVoiceRestrictionDialog )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_VOICE_RESTRICTED , DIALOG_ACCEPT , NULL , NULL , false ) ;
hasShownVoiceRestrictionDialog = true ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : WaitOnLobbyCreate
Called from State_Create_And_Move_To_Party_Lobby and State_Create_And_Move_To_Game_Lobby and State_Create_And_Move_To_Game_State_Lobby .
This function will create the lobby , then wait for it to either succeed or fail .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : WaitOnLobbyCreate ( idLobby & lobby )
{
2012-11-26 18:58:24 +00:00
assert ( localState = = STATE_CREATE_AND_MOVE_TO_PARTY_LOBBY | | localState = = STATE_CREATE_AND_MOVE_TO_GAME_LOBBY | | localState = = STATE_CREATE_AND_MOVE_TO_GAME_STATE_LOBBY ) ;
assert ( connectType = = CONNECT_FIND_OR_CREATE | | connectType = = CONNECT_NONE ) ;
2012-11-28 15:47:07 +00:00
if ( lobby . GetState ( ) = = idLobby : : STATE_FAILED )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: idSessionLocal::WaitOnLobbyCreate lobby.GetState() == idLobby::STATE_FAILED (%s) \n " , lobby . GetLobbyName ( ) ) ;
// If we failed to create a lobby, assume connection to backend service was lost
MoveToMainMenu ( ) ;
common - > Dialog ( ) . ClearDialogs ( true ) ;
common - > Dialog ( ) . AddDialog ( GDM_CONNECTION_LOST , DIALOG_ACCEPT , NULL , NULL , true , " " , 0 , true ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
if ( DetectDisconnectFromService ( true ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( lobby . GetState ( ) ! = idLobby : : STATE_IDLE )
{
2012-11-26 18:58:24 +00:00
return false ; // Valid but busy
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: idSessionLocal::WaitOnLobbyCreate SUCCESS (%s) \n " , lobby . GetLobbyName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : DetectDisconnectFromService
Called from CreateMatch / CreatePartyLobby / FindOrCreateMatch state machines
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : DetectDisconnectFromService ( bool cancelAndShowMsg )
{
2012-11-26 18:58:24 +00:00
const int DETECT_SERVICE_DISCONNECT_TIMEOUT_IN_SECONDS = session - > GetTitleStorageInt ( " DETECT_SERVICE_DISCONNECT_TIMEOUT_IN_SECONDS " , 30 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If we are taking too long, cancel the connection
2012-11-28 15:47:07 +00:00
if ( DETECT_SERVICE_DISCONNECT_TIMEOUT_IN_SECONDS > 0 )
{
if ( Sys_Milliseconds ( ) - connectTime > 1000 * DETECT_SERVICE_DISCONNECT_TIMEOUT_IN_SECONDS )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: idSessionLocal::DetectDisconnectFromService timed out \n " ) ;
2012-11-28 15:47:07 +00:00
if ( cancelAndShowMsg )
{
2012-11-26 18:58:24 +00:00
MoveToMainMenu ( ) ;
common - > Dialog ( ) . ClearDialogs ( true ) ;
common - > Dialog ( ) . AddDialog ( GDM_CONNECTION_LOST , DIALOG_ACCEPT , NULL , NULL , false , " " , 0 , true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleConnectionFailed
Called anytime a connection fails , and does the right thing .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : HandleConnectionFailed ( idLobby & lobby , bool wasFull )
{
2012-11-26 18:58:24 +00:00
assert ( localState = = STATE_CONNECT_AND_MOVE_TO_PARTY | | localState = = STATE_CONNECT_AND_MOVE_TO_GAME | | localState = = STATE_CONNECT_AND_MOVE_TO_GAME_STATE ) ;
assert ( connectType = = CONNECT_FIND_OR_CREATE | | connectType = = CONNECT_DIRECT ) ;
bool canPlayOnline = true ;
// Check for online status (this is only a problem on the PS3 at the moment. The 360 LIVE system handles this for us
2012-11-28 15:47:07 +00:00
if ( GetSignInManager ( ) . GetMasterLocalUser ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
canPlayOnline = GetSignInManager ( ) . GetMasterLocalUser ( ) - > CanPlayOnline ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( connectType = = CONNECT_FIND_OR_CREATE )
{
2012-11-26 18:58:24 +00:00
// Clear the "Lobby was Full" dialog in case it's up
// We only want to see this msg when doing a direct connect (CONNECT_DIRECT)
common - > Dialog ( ) . ClearDialog ( GDM_LOBBY_FULL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( localState = = STATE_CONNECT_AND_MOVE_TO_GAME | | localState = = STATE_CONNECT_AND_MOVE_TO_GAME_STATE ) ;
assert ( lobby . lobbyType = = idLobby : : TYPE_GAME ) ;
2012-11-28 15:47:07 +00:00
if ( ! lobby . ConnectToNextSearchResult ( ) )
{
2012-11-26 18:58:24 +00:00
CreateMatch ( GetGameLobby ( ) . parms ) ; // Assume any time we are connecting to a game lobby, it is from a FindOrCreateMatch call, so create a match
}
2012-11-28 15:47:07 +00:00
}
else if ( connectType = = CONNECT_DIRECT )
{
if ( localState = = STATE_CONNECT_AND_MOVE_TO_GAME & & GetPartyLobby ( ) . IsPeer ( ) )
{
2012-11-26 18:58:24 +00:00
int flags = GetPartyLobby ( ) . parms . matchFlags ;
2012-11-28 15:47:07 +00:00
if ( MatchTypeIsOnline ( flags ) & & ( flags & MATCH_REQUIRE_PARTY_LOBBY ) & & ( ( flags & MATCH_PARTY_INVITE_PLACEHOLDER ) = = 0 ) )
{
// We get here when our party host told us to connect to a game, but the game didn't exist.
2012-11-26 18:58:24 +00:00
// Just drop back to the party lobby and wait for further orders.
SetState ( STATE_PARTY_LOBBY_PEER ) ;
return ;
}
}
2012-11-28 15:47:07 +00:00
if ( wasFull )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_LOBBY_FULL , DIALOG_ACCEPT , NULL , NULL , false ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! canPlayOnline )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_PLAY_ONLINE_NO_PROFILE , DIALOG_ACCEPT , NULL , NULL , false ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// TEMP HACK: We detect the steam lobby is full in idLobbyBackendWin, and then STATE_FAILED, which brings us here. Need to find a way to notify
// session local that the game was full so we don't do this check here
// eeubanks: Pollard, how do you think we should handle this?
2012-11-28 15:47:07 +00:00
if ( ! common - > Dialog ( ) . HasDialogMsg ( GDM_LOBBY_FULL , NULL ) )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_INVALID_INVITE , DIALOG_ACCEPT , NULL , NULL , false ) ;
}
}
MoveToMainMenu ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Shouldn't be possible, but just in case
MoveToMainMenu ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleConnectAndMoveToLobby
Called from State_Connect_And_Move_To_Party / State_Connect_And_Move_To_Game
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : HandleConnectAndMoveToLobby ( idLobby & lobby )
{
2012-11-26 18:58:24 +00:00
assert ( localState = = STATE_CONNECT_AND_MOVE_TO_PARTY | | localState = = STATE_CONNECT_AND_MOVE_TO_GAME | | localState = = STATE_CONNECT_AND_MOVE_TO_GAME_STATE ) ;
assert ( connectType = = CONNECT_FIND_OR_CREATE | | connectType = = CONNECT_DIRECT ) ;
2012-11-28 15:47:07 +00:00
if ( lobby . GetState ( ) = = idLobby : : STATE_FAILED )
{
2012-11-26 18:58:24 +00:00
// If we get here, we were trying to connect to a lobby (from state State_Connect_And_Move_To_Party/State_Connect_And_Move_To_Game)
HandleConnectionFailed ( lobby , false ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
if ( lobby . GetState ( ) ! = idLobby : : STATE_IDLE )
{
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ; // Valid but busy
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! GetPartyLobby ( ) . waitForPartyOk ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// Past this point, we've connected to the lobby
//
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If we are connecting to a game lobby, see if we need to keep waiting as either a host or peer while we're confirming all party members made it
2012-11-28 15:47:07 +00:00
if ( lobby . lobbyType = = idLobby : : TYPE_GAME )
{
if ( GetPartyLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
// As a host, wait until all party members make it
assert ( ! GetGameLobby ( ) . waitForPartyOk ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int timeoutMs = session - > GetTitleStorageInt ( " net_connectTimeoutInSeconds " , net_connectTimeoutInSeconds . GetInteger ( ) ) * 1000 ;
2012-11-28 15:47:07 +00:00
if ( timeoutMs ! = 0 & & Sys_Milliseconds ( ) - lobby . helloStartTime > timeoutMs )
{
2012-11-26 18:58:24 +00:00
// Took too long, move to next result, or create a game instead
HandleConnectionFailed ( lobby , false ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numUsersIn = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < GetPartyLobby ( ) . GetNumLobbyUsers ( ) ; i + + )
{
if ( net_testPartyMemberConnectFail . GetInteger ( ) = = i )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool foundUser = false ;
2012-11-28 15:47:07 +00:00
lobbyUser_t * partyUser = GetPartyLobby ( ) . GetLobbyUser ( i ) ;
for ( int j = 0 ; j < GetGameLobby ( ) . GetNumLobbyUsers ( ) ; j + + )
{
lobbyUser_t * gameUser = GetGameLobby ( ) . GetLobbyUser ( j ) ;
if ( GetGameLobby ( ) . IsSessionUserLocal ( gameUser ) | | gameUser - > address . Compare ( partyUser - > address , true ) )
{
2012-11-26 18:58:24 +00:00
numUsersIn + + ;
foundUser = true ;
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ! GetPartyLobby ( ) . IsSessionUserIndexLocal ( i ) | | foundUser ) ;
}
2012-11-28 15:47:07 +00:00
if ( numUsersIn ! = GetPartyLobby ( ) . GetNumLobbyUsers ( ) )
{
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ; // All users not in, keep waiting until all user make it, or we time out
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: All party members made it into the game lobby. \n " ) ;
// Let all the party members know everyone made it, and it's ok to stay at this server
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < GetPartyLobby ( ) . peers . Num ( ) ; i + + )
{
if ( GetPartyLobby ( ) . peers [ i ] . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
GetPartyLobby ( ) . QueueReliableMessage ( i , idLobby : : RELIABLE_PARTY_CONNECT_OK ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( ! verify ( lobby . host ! = - 1 ) )
{
2012-11-26 18:58:24 +00:00
MoveToMainMenu ( ) ;
connectType = CONNECT_NONE ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// As a peer, wait for server to tell us everyone made it
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . waitForPartyOk )
{
2012-11-26 18:58:24 +00:00
const int timeoutMs = session - > GetTitleStorageInt ( " net_connectTimeoutInSeconds " , net_connectTimeoutInSeconds . GetInteger ( ) ) * 1000 ;
2012-11-28 15:47:07 +00:00
if ( timeoutMs ! = 0 & & Sys_Milliseconds ( ) - lobby . helloStartTime > timeoutMs )
{
2012-11-26 18:58:24 +00:00
GetGameLobby ( ) . waitForPartyOk = false ; // Just connect to this game lobby if we haven't heard from the party host for the entire timeout duration
}
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . waitForPartyOk )
{
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ; // Waiting on party host to tell us everyone made it
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Success
2012-11-28 15:47:07 +00:00
switch ( lobby . lobbyType )
{
case idLobby : : TYPE_PARTY :
2012-11-26 18:58:24 +00:00
SetState ( STATE_PARTY_LOBBY_PEER ) ;
break ;
2012-11-28 15:47:07 +00:00
case idLobby : : TYPE_GAME :
2012-11-26 18:58:24 +00:00
SetState ( STATE_GAME_LOBBY_PEER ) ;
break ;
2012-11-28 15:47:07 +00:00
case idLobby : : TYPE_GAME_STATE :
2012-11-26 18:58:24 +00:00
waitingOnGameStateMembersToJoinTime = Sys_Milliseconds ( ) ;
// As a host of the game lobby, it's our duty to notify our members to also join this game state lobby
GetGameLobby ( ) . SendMembersToLobby ( GetGameStateLobby ( ) , false ) ;
SetState ( STATE_GAME_STATE_LOBBY_PEER ) ;
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectType = CONNECT_NONE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Create_And_Move_To_Party_Lobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Create_And_Move_To_Party_Lobby ( )
{
if ( WaitOnLobbyCreate ( GetPartyLobby ( ) ) )
{
if ( GetPartyLobby ( ) . parms . matchFlags & MATCH_PARTY_INVITE_PLACEHOLDER )
{
2012-11-26 18:58:24 +00:00
// If this party lobby was for a placeholder, continue on with either finding or creating a game lobby
2012-11-28 15:47:07 +00:00
if ( connectType = = CONNECT_FIND_OR_CREATE )
{
2012-11-26 18:58:24 +00:00
FindOrCreateMatch ( GetPartyLobby ( ) . parms ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else if ( connectType = = CONNECT_NONE )
{
2012-11-26 18:58:24 +00:00
CreateMatch ( GetPartyLobby ( ) . parms ) ;
return true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Success
SetState ( STATE_PARTY_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ; // Valid but busy
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Create_And_Move_To_Game_Lobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Create_And_Move_To_Game_Lobby ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( WaitOnLobbyCreate ( GetGameLobby ( ) ) )
{
2012-11-26 18:58:24 +00:00
// Success
SetState ( STATE_GAME_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Now that we've created our game lobby, send our own party users to it
// NOTE - We pass in false to wait on party members since we are the host, and we know they can connect to us
GetPartyLobby ( ) . SendMembersToLobby ( GetGameLobby ( ) , false ) ;
2012-11-28 15:47:07 +00:00
return true ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Create_And_Move_To_Game_State_Lobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Create_And_Move_To_Game_State_Lobby ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( WaitOnLobbyCreate ( GetGameStateLobby ( ) ) )
{
2012-11-26 18:58:24 +00:00
// Success
SetState ( STATE_GAME_STATE_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Now that we've created our game state lobby, send our own game users to it
// NOTE - We pass in false to wait on party members since we are the host, and we know they can connect to us
GetGameLobby ( ) . SendMembersToLobby ( GetGameStateLobby ( ) , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If we are the host of a game lobby, we know we are not using dedicated servers, so we want to start the match immediately
// as soon as we detect all users have connected.
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
waitingOnGameStateMembersToJoinTime = Sys_Milliseconds ( ) ;
}
2012-11-28 15:47:07 +00:00
return true ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Find_Or_Create_Match
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Find_Or_Create_Match ( )
{
2012-11-26 18:58:24 +00:00
assert ( connectType = = CONNECT_FIND_OR_CREATE ) ;
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . GetState ( ) = = idLobby : : STATE_FAILED )
{
2012-11-26 18:58:24 +00:00
// Failed to find any games. Create one instead (we're assuming this always gets called from FindOrCreateMatch
CreateMatch ( GetGameLobby ( ) . parms ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
if ( DetectDisconnectFromService ( true ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . GetState ( ) ! = idLobby : : STATE_IDLE )
{
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ; // Valid but busy
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Done searching, connect to the first search result
2012-11-28 15:47:07 +00:00
if ( ! GetGameLobby ( ) . ConnectToNextSearchResult ( ) )
{
2012-11-26 18:58:24 +00:00
// Failed to find any games. Create one instead (we're assuming this always gets called from FindOrCreateMatch
CreateMatch ( GetGameLobby ( ) . parms ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetState ( STATE_CONNECT_AND_MOVE_TO_GAME ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Connect_And_Move_To_Party
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Connect_And_Move_To_Party ( )
{
return HandleConnectAndMoveToLobby ( GetPartyLobby ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Connect_And_Move_To_Game
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Connect_And_Move_To_Game ( )
{
return HandleConnectAndMoveToLobby ( GetGameLobby ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Connect_And_Move_To_Game_State
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Connect_And_Move_To_Game_State ( )
{
return HandleConnectAndMoveToLobby ( GetGameStateLobby ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_InGame
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_InGame ( )
{
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Loading
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Loading ( )
{
2012-11-26 18:58:24 +00:00
HandlePackets ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! GetActingGameStateLobby ( ) . loaded )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetVoiceGroupsToTeams ( ) ;
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
bool everyoneLoaded = true ;
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
idLobby : : peer_t & peer = GetActingGameStateLobby ( ) . peers [ p ] ;
if ( ! peer . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
continue ; // We don't care about peers that aren't connected as a game session
}
2012-11-28 15:47:07 +00:00
if ( ! peer . loaded )
{
2012-11-26 18:58:24 +00:00
everyoneLoaded = false ;
continue ; // Don't waste time sending resources to a peer who hasn't loaded the map yet
}
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . SendResources ( p ) )
{
2012-11-26 18:58:24 +00:00
everyoneLoaded = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if client is taking a LONG time to load up - give them the boot: they're just holding up the lunch line. Useful for loose assets playtesting.
int time = Sys_Milliseconds ( ) ;
int maxLoadTime = net_maxLoadResourcesTimeInSeconds . GetInteger ( ) ;
2012-11-28 15:47:07 +00:00
if ( maxLoadTime > 0 & & peer . startResourceLoadTime + SEC2MS ( maxLoadTime ) < time )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSERESOURCE_PRINT ( " NET: dropping client %i - %s because they took too long to load resources. \n Check 'net_maxLoadResourcesTimeInSeconds' to adjust the time allowed. \n " , p , GetPeerName ( p ) ) ;
GetActingGameStateLobby ( ) . DisconnectPeerFromSession ( p ) ;
continue ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( ! everyoneLoaded )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// not sure how we got there, but we won't be receiving anything that could get us out of this state anymore
// possible step towards fixing the join stalling/disconnect problems
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . peers . Num ( ) = = 0 )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: no peers in idSessionLocal::State_Loading - giving up \n " ) ;
MoveToMainMenu ( ) ;
}
// need at least a peer with a real connection
bool haveOneGoodPeer = false ;
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
if ( GetActingGameStateLobby ( ) . peers [ p ] . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
haveOneGoodPeer = true ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! haveOneGoodPeer )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: no good peers in idSessionLocal::State_Loading - giving up \n " ) ;
MoveToMainMenu ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . ResetBandwidthStats ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we got here then we're the host and everyone indicated map load finished
NET_VERBOSE_PRINT ( " NET: (loading) Starting Game \n " ) ;
SetState ( STATE_INGAME ) ; // NOTE - Only the host is in-game at this point, all peers will start becoming in-game when they receive their first full snap
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Busy
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Busy ( )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
idLib : : Warning ( " No active session lobby when idSessionLocal::State_Busy called " ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( activeLobby - > bandwidthChallengeFinished )
{
2012-11-26 18:58:24 +00:00
// Start loading
NET_VERBOSE_PRINT ( " NET: Bandwidth test finished - Start loading \n " ) ;
StartLoading ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : VerifySnapshotInitialState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : VerifySnapshotInitialState ( )
{
2012-11-26 18:58:24 +00:00
// Verify that snapshot state is reset
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
if ( ! GetActingGameStateLobby ( ) . peers [ p ] . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( GetActingGameStateLobby ( ) . peers [ p ] . snapProc = = NULL ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( GetActingGameStateLobby ( ) . peers [ p ] . snapProc ! = NULL ) ;
2012-11-28 15:47:07 +00:00
if ( ! verify ( GetActingGameStateLobby ( ) . peers [ p ] . needToSubmitPendingSnap = = false ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Error ( " Invalid needToSubmitPendingSnap state \n " ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! verify ( GetActingGameStateLobby ( ) . peers [ p ] . snapProc - > HasPendingSnap ( ) = = false ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Error ( " Invalid HasPendingSnap state \n " ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! verify ( GetActingGameStateLobby ( ) . peers [ p ] . snapProc - > GetSnapSequence ( ) = = idSnapshotProcessor : : INITIAL_SNAP_SEQUENCE ) )
{
idLib : : Error ( " Invalid INITIAL_SNAP_SEQUENCE state %d for peer %d \n " , GetActingGameStateLobby ( ) . peers [ p ] . snapProc - > GetSnapSequence ( ) , p ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ! verify ( GetActingGameStateLobby ( ) . peers [ p ] . snapProc - > GetBaseSequence ( ) = = - 1 ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Error ( " Invalid GetBaseSequence state \n " ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Party_Lobby_Host
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Party_Lobby_Host ( )
{
2012-11-26 18:58:24 +00:00
HandleVoiceRestrictionDialog ( ) ;
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Game_Lobby_Host
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Game_Lobby_Host ( )
{
2012-11-26 18:58:24 +00:00
HandleVoiceRestrictionDialog ( ) ;
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Game_State_Lobby_Host
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Game_State_Lobby_Host ( )
{
2012-11-26 18:58:24 +00:00
HandleVoiceRestrictionDialog ( ) ;
2012-11-28 15:47:07 +00:00
if ( waitingOnGameStateMembersToLeaveTime ! = 0 )
{
2012-11-26 18:58:24 +00:00
const int MAX_LEAVE_WAIT_TIME_IN_SECONDS = 5 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool forceDisconnectMembers = ( Sys_Milliseconds ( ) - waitingOnGameStateMembersToLeaveTime ) > MAX_LEAVE_WAIT_TIME_IN_SECONDS * 1000 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if all peers have finally left
2012-11-28 15:47:07 +00:00
if ( GetGameStateLobby ( ) . GetNumConnectedPeers ( ) = = 0 | | forceDisconnectMembers )
{
2012-11-26 18:58:24 +00:00
//
// All peers left, we can stop waiting
//
2012-11-28 15:47:07 +00:00
waitingOnGameStateMembersToLeaveTime = 0 ;
2012-11-26 18:58:24 +00:00
assert ( ! GetGameLobby ( ) . IsPeer ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
// If we aren't a dedicated game state host, then drop back to the game lobby as host
GetGameStateLobby ( ) . Shutdown ( ) ;
SetState ( STATE_GAME_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// A dedicated game state host will remain in State_Game_State_Lobby_Host mode while waiting for another set of users to join
// DEDICATED_SERVER_FIXME: Notify master server we can server another game now
GetGameStateLobby ( ) . DisconnectAllPeers ( ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// When all the players from the game lobby are in the game state lobby, StartLoading
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsHost ( ) )
{
if ( GetGameStateLobby ( ) . GetNumLobbyUsers ( ) = = GetGameLobby ( ) . GetNumLobbyUsers ( ) )
{
2012-11-26 18:58:24 +00:00
waitingOnGameStateMembersToJoinTime = 0 ;
StartLoading ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// The dedicated server host relies on the game host to say when all users are in
2012-11-28 15:47:07 +00:00
if ( GetGameStateLobby ( ) . startLoadingFromHost )
{
2012-11-26 18:58:24 +00:00
GetGameStateLobby ( ) . startLoadingFromHost = false ;
StartLoading ( ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Party_Lobby_Peer
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Party_Lobby_Peer ( )
{
2012-11-26 18:58:24 +00:00
HandleVoiceRestrictionDialog ( ) ;
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Game_Lobby_Peer
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Game_Lobby_Peer ( )
{
2012-11-26 18:58:24 +00:00
HandleVoiceRestrictionDialog ( ) ;
bool saving = false ;
2012-11-28 15:47:07 +00:00
idPlayerProfile * profile = GetProfileFromMasterLocalUser ( ) ;
if ( profile ! = NULL & & ( profile - > GetState ( ) = = idPlayerProfile : : SAVING | | profile - > GetRequestedState ( ) = = idPlayerProfile : : SAVE_REQUESTED ) )
{
2012-11-26 18:58:24 +00:00
saving = true ;
}
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . startLoadingFromHost & & ! saving )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . ClearDialog ( GDM_HOST_RETURNED_TO_LOBBY ) ;
common - > Dialog ( ) . ClearDialog ( GDM_HOST_RETURNED_TO_LOBBY_STATS_DROPPED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
VerifySnapshotInitialState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set loading flag back to false
GetActingGameStateLobby ( ) . startLoadingFromHost = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set state to loading
SetState ( STATE_LOADING ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
loadingID + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return HandlePackets ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : State_Game_State_Lobby_Peer
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : State_Game_State_Lobby_Peer ( )
{
2012-11-26 18:58:24 +00:00
// We are in charge of telling the dedicated host that all our members are in
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsHost ( ) & & waitingOnGameStateMembersToJoinTime ! = 0 )
{
2012-11-26 18:58:24 +00:00
int foundMembers = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < GetGameLobby ( ) . GetNumLobbyUsers ( ) ; i + + )
{
if ( GetGameStateLobby ( ) . GetLobbyUserByID ( GetGameLobby ( ) . GetLobbyUser ( i ) - > lobbyUserID , true ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
foundMembers + + ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Give all of our game members 10 seconds to join, otherwise start without them
const int MAX_JOIN_WAIT_TIME_IN_SECONDS = 10 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool forceStart = ( Sys_Milliseconds ( ) - waitingOnGameStateMembersToJoinTime ) > MAX_JOIN_WAIT_TIME_IN_SECONDS * 1000 ;
2012-11-28 15:47:07 +00:00
if ( foundMembers = = GetGameLobby ( ) . GetNumLobbyUsers ( ) | | forceStart )
{
2012-11-26 18:58:24 +00:00
byte buffer [ idPacketProcessor : : MAX_PACKET_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idBitMsg msg ( buffer , sizeof ( buffer ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Write match paramaters to the game state host, and tell him to start
GetGameLobby ( ) . parms . Write ( msg ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Tell the game state lobby host we are ready
GetGameStateLobby ( ) . QueueReliableMessage ( GetGameStateLobby ( ) . host , idLobby : : RELIABLE_START_MATCH_GAME_LOBBY_HOST , msg . GetReadData ( ) , msg . GetSize ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
waitingOnGameStateMembersToJoinTime = 0 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return State_Game_Lobby_Peer ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ~ idSession
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSession : : ~ idSession ( )
{
2012-11-26 18:58:24 +00:00
delete signInManager ;
signInManager = NULL ;
delete saveGameManager ;
saveGameManager = NULL ;
delete dedicatedServerSearch ;
dedicatedServerSearch = NULL ;
}
idCVar net_verbose ( " net_verbose " , " 0 " , CVAR_BOOL , " Print a bunch of message about the network session " ) ;
idCVar net_verboseResource ( " net_verboseResource " , " 0 " , CVAR_BOOL , " Prints a bunch of message about network resources " ) ;
idCVar net_verboseReliable ( " net_verboseReliable " , " 0 " , CVAR_BOOL , " Prints the more spammy messages about reliable network msgs " ) ;
idCVar si_splitscreen ( " si_splitscreen " , " 0 " , CVAR_INTEGER , " force splitscreen " ) ;
idCVar net_forceLatency ( " net_forceLatency " , " 0 " , CVAR_INTEGER , " Simulate network latency (milliseconds round trip time - applied equally on the receive and on the send) " ) ;
idCVar net_forceDrop ( " net_forceDrop " , " 0 " , CVAR_INTEGER , " Percentage chance of simulated network packet loss " ) ;
idCVar net_forceUpstream ( " net_forceUpstream " , " 0 " , CVAR_FLOAT , " Force a maximum upstream in kB/s (256kbps <-> 32kB/s) " ) ; // I would much rather deal in kbps but most of the code is written in bytes ..
idCVar net_forceUpstreamQueue ( " net_forceUpstreamQueue " , " 64 " , CVAR_INTEGER , " How much data is queued when enforcing upstream (in kB) " ) ;
idCVar net_verboseSimulatedTraffic ( " net_verboseSimulatedTraffic " , " 0 " , CVAR_BOOL , " Print some stats about simulated traffic (net_force* cvars) " ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : Initialize
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : Initialize ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : Shutdown
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : Shutdown ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSession interface semi - common between platforms ( # ifdef ' s in sys_session_local . cpp )
= = = = = = = = = = = = = = = = = = = = = = = =
*/
idCVar com_deviceZeroOverride ( " com_deviceZeroOverride " , " -1 " , CVAR_INTEGER , " change input routing for device 0 to poll a different device " ) ;
idCVar mp_bot_input_override ( " mp_bot_input_override " , " -1 " , CVAR_INTEGER , " Override local input routing for bot control " ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetInputRouting
This function sets up inputRouting to be a mapping from inputDevice index to session user index .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSessionLocal : : GetInputRouting ( int inputRouting [ MAX_INPUT_DEVICES ] )
{
2012-11-26 18:58:24 +00:00
int numLocalUsers = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_INPUT_DEVICES ; i + + )
{
2012-11-26 18:58:24 +00:00
inputRouting [ i ] = - 1 ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < GetActingGameStateLobby ( ) . GetNumLobbyUsers ( ) ; i + + )
{
if ( GetActingGameStateLobby ( ) . IsSessionUserIndexLocal ( i ) )
{
2012-11-26 18:58:24 +00:00
// Find the local user that this session user maps to
2012-11-28 15:47:07 +00:00
const idLocalUser * localUser = GetActingGameStateLobby ( ) . GetLocalUserFromLobbyUserIndex ( i ) ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( localUser ! = NULL )
{
2012-11-26 18:58:24 +00:00
int localDevice = localUser - > GetInputDevice ( ) ;
2012-11-28 15:47:07 +00:00
if ( localDevice = = 0 & & com_deviceZeroOverride . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
localDevice = com_deviceZeroOverride . GetInteger ( ) ;
}
assert ( localDevice < MAX_INPUT_DEVICES ) ;
// Route the input device that this local user is mapped to
assert ( inputRouting [ localDevice ] = = - 1 ) ; // Make sure to only initialize each entry once
inputRouting [ localDevice ] = i ;
2012-11-28 15:47:07 +00:00
if ( mp_bot_input_override . GetInteger ( ) > = 0 )
{
2012-11-26 18:58:24 +00:00
inputRouting [ localDevice ] = mp_bot_input_override . GetInteger ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numLocalUsers + + ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// For testing swapping controllers
2012-11-28 15:47:07 +00:00
if ( si_splitscreen . GetInteger ( ) = = 2 & & numLocalUsers = = 2 )
{
2012-11-26 18:58:24 +00:00
SwapValues ( inputRouting [ 0 ] , inputRouting [ 1 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return numLocalUsers ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : EndMatch
EndMatch is meant for the host to cleanly end a match and return to the lobby page
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : EndMatch ( bool premature /*=false*/ )
{
if ( verify ( GetActingGameStateLobby ( ) . IsHost ( ) ) )
{
2012-11-26 18:58:24 +00:00
// Host quits back to game lobby, and will notify peers internally to do the same
EndMatchInternal ( premature ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : EndMatch
this is for when the game is over before we go back to lobby . Need this incase the host leaves during this time
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : MatchFinished ( )
{
if ( verify ( GetActingGameStateLobby ( ) . IsHost ( ) ) )
{
2012-11-26 18:58:24 +00:00
// host is putting up end game stats make sure other peers know and clear migration data
MatchFinishedInternal ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : QuitMatch
QuitMatch is considered a premature ending of a match , and does the right thing depending on whether the host or peer is quitting
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : QuitMatch ( )
{
if ( GetActingGameStateLobby ( ) . IsHost ( ) & & ! MatchTypeIsRanked ( GetActingGameStateLobby ( ) . parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
EndMatch ( true ) ; // When host quits private match, takes members back to game lobby
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Quitting a public match (or not being a host) before it ends takes you to an empty party lobby
CreatePartyLobby ( GetActingGameStateLobby ( ) . parms ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : QuitMatchToTitle
QuitMatchToTitle will forcefully quit the match and return to the title screen .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : QuitMatchToTitle ( )
{
2012-11-26 18:58:24 +00:00
MoveToMainMenu ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ClearMigrationState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ClearMigrationState ( )
{
2012-11-26 18:58:24 +00:00
// We are ending the match without migration, so clear that state
GetPartyLobby ( ) . ResetAllMigrationState ( ) ;
GetGameLobby ( ) . ResetAllMigrationState ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : EndMatchInternal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : EndMatchInternal ( bool premature /*=false*/ )
{
2012-11-26 18:58:24 +00:00
assert ( GetGameStateLobby ( ) . IsLobbyActive ( ) = = net_useGameStateLobby . GetBool ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ClearVoiceGroups ( ) ;
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
2012-11-26 18:58:24 +00:00
// If we are the host, increment the session ID. The client will use a rolling check to catch it
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsHost ( ) )
{
if ( GetActingGameStateLobby ( ) . peers [ p ] . IsConnected ( ) )
{
if ( GetActingGameStateLobby ( ) . peers [ p ] . packetProc ! = NULL )
{
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . peers [ p ] . packetProc - > VerifyEmptyReliableQueue ( idLobby : : RELIABLE_GAME_DATA , idLobby : : RELIABLE_DUMMY_MSG ) ;
}
GetActingGameStateLobby ( ) . peers [ p ] . sessionID = GetActingGameStateLobby ( ) . IncrementSessionID ( GetActingGameStateLobby ( ) . peers [ p ] . sessionID ) ;
}
}
GetActingGameStateLobby ( ) . peers [ p ] . ResetMatchData ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . snapDeltaAckQueue . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . loaded = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLobbyWasCoalesced = false ; // Reset this back to false. We use this so the lobby code doesn't randomly choose a map when we coalesce
numFullSnapsReceived = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ClearMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsLobbyActive ( ) & & ( GetActingGameStateLobby ( ) . GetMatchParms ( ) . matchFlags & MATCH_REQUIRE_PARTY_LOBBY ) )
{
2012-11-26 18:58:24 +00:00
// All peers need to remove disconnected users to stay in sync
GetActingGameStateLobby ( ) . CompactDisconnectedUsers ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Go back to the game lobby
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
// We want the game state host to go back to STATE_GAME_STATE_LOBBY_HOST, so he can wait on all his game state peers to leave
SetState ( GetGameStateLobby ( ) . IsHost ( ) ? STATE_GAME_STATE_LOBBY_HOST : STATE_GAME_LOBBY_HOST ) ; // We want the dedicated host to go back to STATE_GAME_STATE_LOBBY_HOST
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_GAME_LOBBY_PEER ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_IDLE ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
// Send a reliable msg to all peers to also "EndMatch"
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . QueueReliableMessage ( p , premature ? idLobby : : RELIABLE_ENDMATCH_PREMATURE : idLobby : : RELIABLE_ENDMATCH ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( premature )
{
2012-11-26 18:58:24 +00:00
// Notify client that host left early and thats why we are back in the lobby
const bool stats = MatchTypeHasStats ( GetActingGameStateLobby ( ) . GetMatchParms ( ) . matchFlags ) & & ( GetFlushedStats ( ) = = false ) ;
common - > Dialog ( ) . AddDialog ( stats ? GDM_HOST_RETURNED_TO_LOBBY_STATS_DROPPED : GDM_HOST_RETURNED_TO_LOBBY , DIALOG_ACCEPT , NULL , NULL , false , __FUNCTION__ , __LINE__ , true ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameStateLobby ( ) . IsLobbyActive ( ) )
{
if ( GetGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
// As a game state host, keep the lobby around, so we can make sure we know when everyone leaves (which means they got the reliable msg to EndMatch)
waitingOnGameStateMembersToLeaveTime = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( GetGameStateLobby ( ) . IsPeer ( ) )
{
2012-11-26 18:58:24 +00:00
// Game state lobby peers should disconnect now
GetGameStateLobby ( ) . Shutdown ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : MatchFinishedInternal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : MatchFinishedInternal ( )
{
2012-11-26 18:58:24 +00:00
ClearMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
// Send a reliable msg to all peers to also "EndMatch"
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . QueueReliableMessage ( p , idLobby : : RELIABLE_MATCHFINISHED ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : EndMatchForMigration
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : EndMatchForMigration ( )
{
ClearVoiceGroups ( ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ShouldHavePartyLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : ShouldHavePartyLobby ( )
{
if ( GetActivePlatformLobby ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
idMatchParameters & parms = GetActivePlatformLobby ( ) - > parms ;
2012-11-26 18:58:24 +00:00
int flags = parms . matchFlags ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Don't we always have a party lobby if we're online? At least in Doom 3?
return MatchTypeIsOnline ( flags ) & & ( ( flags & MATCH_PARTY_INVITE_PLACEHOLDER ) = = 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ValidateLobbies
Determines if any of the session instances need to become the host
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ValidateLobbies ( )
{
if ( localState = = STATE_PRESS_START | | localState = = STATE_IDLE )
{
2012-11-26 18:58:24 +00:00
// At press start or main menu, don't do anything
return ;
}
2012-11-28 15:47:07 +00:00
if ( GetActivePlatformLobby ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
// If we're in between lobbies, don't do anything yet (the state transitioning code will handle error cases)
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Validate lobbies that should be alive and active
2012-11-28 15:47:07 +00:00
if ( ShouldHavePartyLobby ( ) & & GetState ( ) > = idSession : : PARTY_LOBBY )
{
2012-11-26 18:58:24 +00:00
ValidateLobby ( GetPartyLobby ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetState ( ) > = idSession : : GAME_LOBBY & & ! net_headlessServer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
ValidateLobby ( GetGameLobby ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ValidateLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ValidateLobby ( idLobby & lobby )
{
if ( lobby . lobbyBackend = = NULL | | lobby . lobbyBackend - > GetState ( ) = = idLobbyBackend : : STATE_FAILED | | lobby . GetState ( ) = = idLobby : : STATE_FAILED )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: ValidateLobby: FAILED (lobbyType = %i, state = %s) \n " , lobby . lobbyType , stateToString [ localState ] ) ;
2012-11-28 15:47:07 +00:00
if ( lobby . failedReason = = idLobby : : FAILED_MIGRATION_CONNECT_FAILED | | lobby . failedReason = = idLobby : : FAILED_CONNECT_FAILED )
{
2012-11-26 18:58:24 +00:00
MoveToMainMenu ( ) ;
common - > Dialog ( ) . AddDialog ( GDM_INVALID_INVITE , DIALOG_ACCEPT , NULL , NULL , false ) ; // The game session no longer exists
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// If the lobbyBackend goes bad under our feet for no known reason, assume we lost connection to the back end service
MoveToMainMenu ( ) ;
common - > Dialog ( ) . ClearDialogs ( true ) ;
common - > Dialog ( ) . AddDialog ( GDM_CONNECTION_LOST , DIALOG_ACCEPT , NULL , NULL , false ) ; // Lost connection to XBox LIVE
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : Pump
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : Pump ( )
{
2012-11-26 18:58:24 +00:00
SCOPED_PROFILE_EVENT ( " Session::Pump " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static int lastPumpTime = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int time = Sys_Milliseconds ( ) ;
const int elapsedPumpSeconds = ( time - lastPumpTime ) / 1000 ;
2012-11-28 15:47:07 +00:00
if ( lastPumpTime ! = - 1 & & elapsedPumpSeconds > 2 )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " idSessionLocal::Pump was not called for %i seconds " , elapsedPumpSeconds ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastPumpTime = time ;
2012-11-28 15:47:07 +00:00
if ( net_migrateHost . GetInteger ( ) > = 0 )
{
if ( net_migrateHost . GetInteger ( ) < = 2 )
{
if ( net_migrateHost . GetInteger ( ) = = 0 )
{
GetPartyLobby ( ) . PickNewHost ( true , true ) ;
}
else
{
GetGameLobby ( ) . PickNewHost ( true , true ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
}
else
{
GetPartyLobby ( ) . PickNewHost ( true , true ) ;
GetGameLobby ( ) . PickNewHost ( true , true ) ;
2012-11-26 18:58:24 +00:00
}
net_migrateHost . SetInteger ( - 1 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PlatformPump ( ) ;
2012-11-28 15:47:07 +00:00
if ( HasAchievementSystem ( ) )
{
2012-11-26 18:58:24 +00:00
GetAchievementSystem ( ) . Pump ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Send any voice packets if it's time
SendVoiceAudio ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool shouldContinue = true ;
2012-11-28 15:47:07 +00:00
while ( shouldContinue )
{
2012-11-26 18:58:24 +00:00
// Each iteration, validate the session instances
ValidateLobbies ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Pump state
shouldContinue = HandleState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Pump lobbies
PumpLobbies ( ) ;
2012-11-28 15:47:07 +00:00
}
if ( GetPartyLobby ( ) . lobbyBackend ! = NULL )
{
2012-11-26 18:58:24 +00:00
// Make sure game properties aren't set on the lobbyBackend if we aren't in a game lobby.
// This is so we show up properly in search results in Play with Friends option
GetPartyLobby ( ) . lobbyBackend - > SetInGame ( GetGameLobby ( ) . IsLobbyActive ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Temp location
UpdateMasterUserHeadsetState ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Do some last minute checks, make sure everything about the current state and lobbyBackend state is valid, otherwise, take action
ValidateLobbies ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . UpdateSnaps ( ) ;
2012-11-28 15:47:07 +00:00
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
2012-11-26 18:58:24 +00:00
// Pump pings for the active lobby
2012-11-28 15:47:07 +00:00
if ( activeLobby ! = NULL )
{
2012-11-26 18:58:24 +00:00
activeLobby - > PumpPings ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Pump packet processing for all lobbies
GetPartyLobby ( ) . PumpPackets ( ) ;
GetGameLobby ( ) . PumpPackets ( ) ;
GetGameStateLobby ( ) . PumpPackets ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int currentTime = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int SHOW_MIGRATING_INFO_IN_SECONDS = 3 ; // Show for at least this long once we start showing it
2012-11-28 15:47:07 +00:00
if ( ShouldShowMigratingDialog ( ) )
{
2012-11-26 18:58:24 +00:00
showMigratingInfoStartTime = currentTime ;
2012-11-28 15:47:07 +00:00
}
else if ( showMigratingInfoStartTime > 0 & & ( ( currentTime - showMigratingInfoStartTime ) > SHOW_MIGRATING_INFO_IN_SECONDS * 1000 ) )
{
2012-11-26 18:58:24 +00:00
showMigratingInfoStartTime = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool isShowingMigrate = common - > Dialog ( ) . HasDialogMsg ( GDM_MIGRATING , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( showMigratingInfoStartTime ! = 0 )
{
if ( ! isShowingMigrate )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_MIGRATING , DIALOG_WAIT , NULL , NULL , false , " " , 0 , false , false , true ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( isShowingMigrate )
{
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . ClearDialog ( GDM_MIGRATING ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Update possible pending invite
UpdatePendingInvite ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if we should coalesce the lobby
2012-11-28 15:47:07 +00:00
if ( nextGameCoalesceTime ! = 0 )
{
if ( GetGameLobby ( ) . IsLobbyActive ( ) & &
GetGameLobby ( ) . IsHost ( ) & &
GetState ( ) = = idSession : : GAME_LOBBY & &
GetPartyLobby ( ) . GetNumLobbyUsers ( ) < = 1 & &
GetGameLobby ( ) . GetNumLobbyUsers ( ) = = 1 & &
MatchTypeIsRanked ( GetGameLobby ( ) . parms . matchFlags ) & &
Sys_Milliseconds ( ) > nextGameCoalesceTime )
{
2012-11-26 18:58:24 +00:00
// If the player doesn't care about the mode or map,
// make sure the search is broadened.
idMatchParameters newGameParms = GetGameLobby ( ) . parms ;
newGameParms . gameMap = GAME_MAP_RANDOM ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Assume that if the party lobby's mode is random,
// the player chose "Quick Match" and doesn't care about the mode.
// If the player chose "Find Match" and a specific mode,
// the party lobby mode will be set to non-random.
2012-11-28 15:47:07 +00:00
if ( GetPartyLobby ( ) . parms . gameMode = = GAME_MODE_RANDOM )
{
2012-11-26 18:58:24 +00:00
newGameParms . gameMode = GAME_MODE_RANDOM ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FindOrCreateMatch ( newGameParms ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLobbyWasCoalesced = true ; // Remember that this round was coalesced. We so this so main menu doesn't randomize the map, which looks odd
nextGameCoalesceTime = 0 ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ProcessSnapAckQueue
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ProcessSnapAckQueue ( )
{
if ( GetActingGameStateLobby ( ) . IsLobbyActive ( ) )
{
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . ProcessSnapAckQueue ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : UpdatePendingInvite
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : UpdatePendingInvite ( )
{
if ( pendingInviteMode = = PENDING_INVITE_NONE )
{
2012-11-26 18:58:24 +00:00
return ; // No pending invite
}
2012-11-28 15:47:07 +00:00
idLocalUser * masterLocalUser = signInManager - > GetMasterLocalUser ( ) ;
if ( masterLocalUser = = NULL & & signInManager - > IsDeviceBeingRegistered ( pendingInviteDevice ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " masterLocalUser == NULL \n " ) ;
return ; // Waiting on master to sign in to continue with invite
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool wasFromInvite = pendingInviteMode = = PENDING_INVITE_WAITING ; // Remember if this was a real invite, or a self invitation (matters when lobby is invite only)
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// At this point, the invitee should be ready
pendingInviteMode = PENDING_INVITE_NONE ;
2012-11-28 15:47:07 +00:00
if ( masterLocalUser = = NULL | | masterLocalUser - > GetInputDevice ( ) ! = pendingInviteDevice | | ! masterLocalUser - > IsOnline ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " ignoring invite - master local user is not setup properly \n " ) ;
return ; // If there is no master, if the invitee is not online, or different than the current master, then ignore invite
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Clear any current dialogs, as we're going into a state which will be unstable for any current dialogs.
// Do we want to throw an assert if a dialog is currently up?
common - > Dialog ( ) . ClearDialogs ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Everything looks good, let's join the party
ConnectAndMoveToLobby ( GetPartyLobby ( ) , pendingInviteConnectInfo , wasFromInvite ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : HandleState ( )
{
2012-11-26 18:58:24 +00:00
// Handle individual lobby states
GetPartyLobby ( ) . Pump ( ) ;
GetGameLobby ( ) . Pump ( ) ;
GetGameStateLobby ( ) . Pump ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Let IsHost be authoritative on the qualification of peer/host state types
2012-11-28 15:47:07 +00:00
if ( GetPartyLobby ( ) . IsHost ( ) & & localState = = STATE_PARTY_LOBBY_PEER )
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_PARTY_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
}
else if ( GetPartyLobby ( ) . IsPeer ( ) & & localState = = STATE_PARTY_LOBBY_HOST )
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_PARTY_LOBBY_PEER ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Let IsHost be authoritative on the qualification of peer/host state types
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsHost ( ) & & localState = = STATE_GAME_LOBBY_PEER )
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_GAME_LOBBY_HOST ) ;
2012-11-28 15:47:07 +00:00
}
else if ( GetGameLobby ( ) . IsPeer ( ) & & localState = = STATE_GAME_LOBBY_HOST )
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_GAME_LOBBY_PEER ) ;
}
2012-11-28 15:47:07 +00:00
switch ( localState )
{
case STATE_PRESS_START :
return false ;
case STATE_IDLE :
HandlePackets ( ) ;
return false ; // Call handle packets, since packets from old sessions could still be in flight, which need to be emptied
case STATE_PARTY_LOBBY_HOST :
return State_Party_Lobby_Host ( ) ;
case STATE_PARTY_LOBBY_PEER :
return State_Party_Lobby_Peer ( ) ;
case STATE_GAME_LOBBY_HOST :
return State_Game_Lobby_Host ( ) ;
case STATE_GAME_LOBBY_PEER :
return State_Game_Lobby_Peer ( ) ;
case STATE_GAME_STATE_LOBBY_HOST :
return State_Game_State_Lobby_Host ( ) ;
case STATE_GAME_STATE_LOBBY_PEER :
return State_Game_State_Lobby_Peer ( ) ;
case STATE_LOADING :
return State_Loading ( ) ;
case STATE_INGAME :
return State_InGame ( ) ;
case STATE_CREATE_AND_MOVE_TO_PARTY_LOBBY :
return State_Create_And_Move_To_Party_Lobby ( ) ;
case STATE_CREATE_AND_MOVE_TO_GAME_LOBBY :
return State_Create_And_Move_To_Game_Lobby ( ) ;
case STATE_CREATE_AND_MOVE_TO_GAME_STATE_LOBBY :
return State_Create_And_Move_To_Game_State_Lobby ( ) ;
case STATE_FIND_OR_CREATE_MATCH :
return State_Find_Or_Create_Match ( ) ;
case STATE_CONNECT_AND_MOVE_TO_PARTY :
return State_Connect_And_Move_To_Party ( ) ;
case STATE_CONNECT_AND_MOVE_TO_GAME :
return State_Connect_And_Move_To_Game ( ) ;
case STATE_CONNECT_AND_MOVE_TO_GAME_STATE :
return State_Connect_And_Move_To_Game_State ( ) ;
case STATE_BUSY :
return State_Busy ( ) ;
2012-11-26 18:58:24 +00:00
default :
idLib : : Error ( " HandleState: Unknown state in idSessionLocal " ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSessionLocal : : sessionState_t idSessionLocal : : GetState ( ) const
{
2012-11-26 18:58:24 +00:00
// Convert our internal state to one of the external states
2012-11-28 15:47:07 +00:00
switch ( localState )
{
case STATE_PRESS_START :
return PRESS_START ;
case STATE_IDLE :
return IDLE ;
case STATE_PARTY_LOBBY_HOST :
return PARTY_LOBBY ;
case STATE_PARTY_LOBBY_PEER :
return PARTY_LOBBY ;
case STATE_GAME_LOBBY_HOST :
return GAME_LOBBY ;
case STATE_GAME_LOBBY_PEER :
return GAME_LOBBY ;
case STATE_GAME_STATE_LOBBY_HOST :
return GAME_LOBBY ;
case STATE_GAME_STATE_LOBBY_PEER :
return GAME_LOBBY ;
case STATE_LOADING :
return LOADING ;
case STATE_INGAME :
return INGAME ;
case STATE_CREATE_AND_MOVE_TO_PARTY_LOBBY :
return CONNECTING ;
case STATE_CREATE_AND_MOVE_TO_GAME_LOBBY :
return CONNECTING ;
case STATE_CREATE_AND_MOVE_TO_GAME_STATE_LOBBY :
return CONNECTING ;
case STATE_FIND_OR_CREATE_MATCH :
return SEARCHING ;
case STATE_CONNECT_AND_MOVE_TO_PARTY :
return CONNECTING ;
case STATE_CONNECT_AND_MOVE_TO_GAME :
return CONNECTING ;
case STATE_CONNECT_AND_MOVE_TO_GAME_STATE :
return CONNECTING ;
case STATE_BUSY :
return BUSY ;
default :
{
2012-11-26 18:58:24 +00:00
idLib : : Error ( " GetState: Unknown state in idSessionLocal " ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
} ;
}
2012-11-28 15:47:07 +00:00
const char * idSessionLocal : : GetStateString ( ) const
{
static const char * stateToString [ ] =
{
2012-11-26 18:58:24 +00:00
ASSERT_ENUM_STRING ( STATE_PRESS_START , 0 ) ,
ASSERT_ENUM_STRING ( STATE_IDLE , 1 ) ,
ASSERT_ENUM_STRING ( STATE_PARTY_LOBBY_HOST , 2 ) ,
ASSERT_ENUM_STRING ( STATE_PARTY_LOBBY_PEER , 3 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_LOBBY_HOST , 4 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_LOBBY_PEER , 5 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_STATE_LOBBY_HOST , 6 ) ,
ASSERT_ENUM_STRING ( STATE_GAME_STATE_LOBBY_PEER , 7 ) ,
ASSERT_ENUM_STRING ( STATE_CREATE_AND_MOVE_TO_PARTY_LOBBY , 8 ) ,
ASSERT_ENUM_STRING ( STATE_CREATE_AND_MOVE_TO_GAME_LOBBY , 9 ) ,
ASSERT_ENUM_STRING ( STATE_CREATE_AND_MOVE_TO_GAME_STATE_LOBBY , 10 ) ,
ASSERT_ENUM_STRING ( STATE_FIND_OR_CREATE_MATCH , 11 ) ,
ASSERT_ENUM_STRING ( STATE_CONNECT_AND_MOVE_TO_PARTY , 12 ) ,
ASSERT_ENUM_STRING ( STATE_CONNECT_AND_MOVE_TO_GAME , 13 ) ,
ASSERT_ENUM_STRING ( STATE_CONNECT_AND_MOVE_TO_GAME_STATE , 14 ) ,
ASSERT_ENUM_STRING ( STATE_BUSY , 15 ) ,
ASSERT_ENUM_STRING ( STATE_LOADING , 16 ) ,
ASSERT_ENUM_STRING ( STATE_INGAME , 17 )
} ;
return stateToString [ localState ] ;
}
// idSession interface
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : LoadingFinished
Only called by idCommonLocal : : FinalizeMapChange
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : LoadingFinished ( )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: Loading Finished \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( GetState ( ) = = idSession : : LOADING ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . ClearDialog ( GDM_VOICE_RESTRICTED ) ;
GetActingGameStateLobby ( ) . loaded = true ;
2012-11-28 15:47:07 +00:00
if ( MatchTypeIsLocal ( GetActingGameStateLobby ( ) . parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_INGAME ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! GetActingGameStateLobby ( ) . IsHost ( ) ) // Tell game host we're done loading
{
2012-11-26 18:58:24 +00:00
byte buffer [ idPacketProcessor : : MAX_PACKET_SIZE ] ;
idBitMsg msg ( buffer , sizeof ( buffer ) ) ;
GetActingGameStateLobby ( ) . QueueReliableMessage ( GetActingGameStateLobby ( ) . host , idLobby : : RELIABLE_LOADING_DONE , msg . GetReadData ( ) , msg . GetSize ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
SetState ( STATE_INGAME ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetFlushedStats ( false ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SendUsercmds
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SendUsercmds ( idBitMsg & msg )
{
if ( localState ! = STATE_INGAME )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsPeer ( ) )
{
idLobby : : peer_t & hostPeer = GetActingGameStateLobby ( ) . peers [ GetActingGameStateLobby ( ) . host ] ;
2012-11-26 18:58:24 +00:00
// Don't send user cmds if we have unsent packet fragments
// (This can happen if we have packets to send, but SendAnotherFragment got throttled)
2012-11-28 15:47:07 +00:00
if ( hostPeer . packetProc - > HasMoreFragments ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " NET: Client called SendUsercmds while HasMoreFragments(). Skipping userCmds for this frame. " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int sequence = hostPeer . snapProc - > GetLastAppendedSequence ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Add incoming BPS for QoS
float incomingBPS = hostPeer . receivedBps ;
2012-11-28 15:47:07 +00:00
if ( hostPeer . receivedBpsIndex ! = sequence )
{
2012-11-26 18:58:24 +00:00
incomingBPS = idMath : : ClampFloat ( 0.0f , static_cast < float > ( idLobby : : BANDWIDTH_REPORTING_MAX ) , hostPeer . packetProc - > GetIncomingRateBytes ( ) ) ;
hostPeer . receivedBpsIndex = sequence ;
hostPeer . receivedBps = incomingBPS ;
}
uint16 incomingBPS_quantized = idMath : : Ftoi ( incomingBPS * ( ( BIT ( idLobby : : BANDWIDTH_REPORTING_BITS ) - 1 ) / idLobby : : BANDWIDTH_REPORTING_MAX ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
byte buffer [ idPacketProcessor : : MAX_FINAL_PACKET_SIZE ] ;
lzwCompressionData_t lzwData ;
idLZWCompressor lzwCompressor ( & lzwData ) ;
lzwCompressor . Start ( buffer , sizeof ( buffer ) ) ;
lzwCompressor . WriteAgnostic ( sequence ) ;
lzwCompressor . WriteAgnostic ( incomingBPS_quantized ) ;
lzwCompressor . Write ( msg . GetReadData ( ) , msg . GetSize ( ) ) ;
lzwCompressor . End ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetActingGameStateLobby ( ) . ProcessOutgoingMsg ( GetActingGameStateLobby ( ) . host , buffer , lzwCompressor . Length ( ) , false , 0 ) ;
2012-11-28 15:47:07 +00:00
if ( net_debugBaseStates . GetBool ( ) & & sequence < 50 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " NET: Acking snap %d \n " , sequence ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SendSnapshot
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SendSnapshot ( idSnapShot & ss )
{
for ( int p = 0 ; p < GetActingGameStateLobby ( ) . peers . Num ( ) ; p + + )
{
idLobby : : peer_t & peer = GetActingGameStateLobby ( ) . peers [ p ] ;
if ( ! peer . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! peer . loaded )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( peer . pauseSnapshots )
{
2012-11-26 18:58:24 +00:00
continue ;
}
GetActingGameStateLobby ( ) . SendSnapshotToPeer ( ss , p ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : UpdateSignInManager
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : UpdateSignInManager ( )
{
if ( ! HasSignInManager ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( net_headlessServer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: We need to ask the menu system for this info. Just making a best guess for now
// (assume we are allowed to join the party as a splitscreen user if we are in the party lobby)
bool allowJoinParty = ( localState = = STATE_PARTY_LOBBY_HOST | | localState = = STATE_PARTY_LOBBY_PEER ) & & GetPartyLobby ( ) . state = = idLobby : : STATE_IDLE ;
bool allowJoinGame = ( localState = = STATE_GAME_LOBBY_HOST | | localState = = STATE_GAME_LOBBY_PEER ) & & GetGameLobby ( ) . state = = idLobby : : STATE_IDLE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool eitherLobbyRunning = GetActivePlatformLobby ( ) ! = NULL & & ( GetPartyLobby ( ) . IsLobbyActive ( ) | | GetGameLobby ( ) . IsLobbyActive ( ) ) ;
bool onlineMatch = eitherLobbyRunning & & MatchTypeIsOnline ( GetActivePlatformLobby ( ) - > parms . matchFlags ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//=================================================================================
// Get the number of desired signed in local users depending on what mode we're in.
//=================================================================================
int minDesiredUsers = 0 ;
int maxDesiredUsers = Max ( 1 , signInManager - > GetNumLocalUsers ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( si_splitscreen . GetInteger ( ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
// For debugging, force 2 splitscreen players
minDesiredUsers = 2 ;
maxDesiredUsers = 2 ;
allowJoinGame = true ;
2012-11-28 15:47:07 +00:00
}
else if ( onlineMatch | | ( eitherLobbyRunning = = false ) )
{
2012-11-26 18:58:24 +00:00
// If this an online game, then only 1 user can join locally.
// Also, if no sessions are active, remove any extra players.
maxDesiredUsers = 1 ;
2012-11-28 15:47:07 +00:00
}
else if ( allowJoinParty | | allowJoinGame )
{
2012-11-26 18:58:24 +00:00
// If we are in the party lobby, allow 2 splitscreen users to join
maxDesiredUsers = 2 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set the number of desired users
signInManager - > SetDesiredLocalUsers ( minDesiredUsers , maxDesiredUsers ) ;
//=================================================================================
// Update signin manager
//=================================================================================
// Update signin mgr. This manager tracks signed in local users, which the session then uses
// to determine who should be in the lobby.
signInManager - > Pump ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Get the master local user
2012-11-28 15:47:07 +00:00
idLocalUser * masterUser = signInManager - > GetMasterLocalUser ( ) ;
if ( onlineMatch & & masterUser ! = NULL & & ! masterUser - > CanPlayOnline ( ) & & ! masterUser - > HasOwnerChanged ( ) )
{
if ( localState > STATE_IDLE )
{
2012-11-26 18:58:24 +00:00
// User is still valid, just no longer online
2012-11-28 15:47:07 +00:00
if ( offlineTransitionTimerStart = = 0 )
{
2012-11-26 18:58:24 +00:00
offlineTransitionTimerStart = Sys_Milliseconds ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ( Sys_Milliseconds ( ) - offlineTransitionTimerStart ) > net_offlineTransitionThreshold . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
MoveToMainMenu ( ) ;
common - > Dialog ( ) . ClearDialogs ( ) ;
common - > Dialog ( ) . AddDialog ( GDM_CONNECTION_LOST , DIALOG_ACCEPT , NULL , NULL , false , " " , 0 , true ) ;
}
}
return ; // Bail out so signInManager->ValidateLocalUsers below doesn't prematurely remove the master user before we can detect loss of connection
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
offlineTransitionTimerStart = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Remove local users (from the signin manager) who aren't allowed to be online if this is an online match.
// Remove local user (from the signin manager) who are not properly signed into a profile.
signInManager - > ValidateLocalUsers ( onlineMatch ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//=================================================================================
// Check to see if we need to go to "Press Start"
//=================================================================================
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Get the master local user (again, after ValidateOnlineLocalUsers, to make sure he is still valid)
masterUser = signInManager - > GetMasterLocalUser ( ) ;
2012-11-28 15:47:07 +00:00
if ( masterUser = = NULL )
{
2012-11-26 18:58:24 +00:00
// If we don't have a master user at all, then we need to be at "Press Start"
MoveToPressStart ( GDM_SP_SIGNIN_CHANGE_POST ) ;
return ;
2012-11-28 15:47:07 +00:00
}
else if ( localState = = STATE_PRESS_START )
{
2012-11-26 18:58:24 +00:00
// If we have a master user, and we are at press start, move to the menu area
SetState ( STATE_IDLE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// See if the master user either isn't persistent (but needs to be), OR, if the owner changed
// RequirePersistentMaster is poorly named, this really means RequireSignedInMaster
2012-11-28 15:47:07 +00:00
if ( masterUser - > HasOwnerChanged ( ) | | ( RequirePersistentMaster ( ) & & ! masterUser - > IsProfileReady ( ) ) )
{
2012-11-26 18:58:24 +00:00
MoveToPressStart ( GDM_SP_SIGNIN_CHANGE_POST ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//=================================================================================
// Sync lobby users with the signed in users
// The initial list of session users are normally determined at connect or create time.
// These functions allow splitscreen users to join in, or check to see if existing
// users (including the master) need to be removed.
//=================================================================================
GetPartyLobby ( ) . SyncLobbyUsersWithLocalUsers ( allowJoinParty , onlineMatch ) ;
GetGameLobby ( ) . SyncLobbyUsersWithLocalUsers ( allowJoinGame , onlineMatch ) ;
GetGameStateLobby ( ) . SyncLobbyUsersWithLocalUsers ( allowJoinGame , onlineMatch ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetProfileFromMasterLocalUser
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idPlayerProfile * idSessionLocal : : GetProfileFromMasterLocalUser ( )
{
idPlayerProfile * profile = NULL ;
idLocalUser * masterUser = signInManager - > GetMasterLocalUser ( ) ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( masterUser ! = NULL )
{
2012-11-26 18:58:24 +00:00
profile = masterUser - > GetProfile ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( profile = = NULL )
{
2012-11-26 18:58:24 +00:00
// Whoops
profile = signInManager - > GetDefaultProfile ( ) ;
//idLib::Warning( "Returning fake profile until the code is fixed to handle NULL profiles." );
}
return profile ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : MoveToPressStart
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : MoveToPressStart ( gameDialogMessages_t msg )
{
if ( localState ! = STATE_PRESS_START )
{
2012-11-26 18:58:24 +00:00
MoveToPressStart ( ) ;
common - > Dialog ( ) . ClearDialogs ( ) ;
common - > Dialog ( ) . AddDialog ( msg , DIALOG_ACCEPT , NULL , NULL , false , " " , 0 , true ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetPeerName
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idSessionLocal : : GetPeerName ( int peerNum )
{
2012-11-26 18:58:24 +00:00
return GetActingGameStateLobby ( ) . GetPeerName ( peerNum ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SetState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SetState ( state_t newState )
{
2012-11-26 18:58:24 +00:00
assert ( newState < NUM_STATES ) ;
assert ( localState < NUM_STATES ) ;
verify_array_size ( stateToString , NUM_STATES ) ;
2012-11-28 15:47:07 +00:00
if ( newState = = localState )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " NET: SetState: State SAME %s \n " , stateToString [ newState ] ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set the current state
NET_VERBOSE_PRINT ( " NET: SetState: State changing from %s to %s \n " , stateToString [ localState ] , stateToString [ newState ] ) ;
2012-11-28 15:47:07 +00:00
if ( localState < STATE_LOADING & & newState > = STATE_LOADING )
{
2012-11-26 18:58:24 +00:00
// Tell lobby instances that the match has started
StartSessions ( ) ;
// Clear certain dialog boxes we don't want to see in-game
common - > Dialog ( ) . ClearDialog ( GDM_LOBBY_DISBANDED ) ; // The lobby you were previously in has disbanded
2012-11-28 15:47:07 +00:00
}
else if ( localState > = STATE_LOADING & & newState < STATE_LOADING )
{
2012-11-26 18:58:24 +00:00
// Tell lobby instances that the match has ended
2012-11-28 15:47:07 +00:00
if ( ! WasMigrationGame ( ) ) // Don't end the session if we are going right back into the game
{
2012-11-26 18:58:24 +00:00
EndSessions ( ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( newState = = STATE_GAME_LOBBY_HOST | | newState = = STATE_GAME_LOBBY_PEER )
{
2012-11-26 18:58:24 +00:00
ComputeNextGameCoalesceTime ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
localState = newState ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandlePackets
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : HandlePackets ( )
{
2012-11-26 18:58:24 +00:00
SCOPED_PROFILE_EVENT ( " Session::HandlePackets " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
byte packetBuffer [ idPacketProcessor : : MAX_FINAL_PACKET_SIZE ] ;
lobbyAddress_t remoteAddress ;
int recvSize = 0 ;
bool fromDedicated = false ;
2012-11-28 15:47:07 +00:00
while ( ReadRawPacket ( remoteAddress , packetBuffer , recvSize , fromDedicated , sizeof ( packetBuffer ) ) & & recvSize > 0 )
{
2012-11-26 18:58:24 +00:00
// fragMsg will hold the raw packet
idBitMsg fragMsg ;
fragMsg . InitRead ( packetBuffer , recvSize ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Peek at the session ID
idPacketProcessor : : sessionId_t sessionID = idPacketProcessor : : GetSessionID ( fragMsg ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// idLib::Printf( "NET: HandlePackets - session %d, size %d \n", sessionID, recvSize );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure it's valid
2012-11-28 15:47:07 +00:00
if ( sessionID = = idPacketProcessor : : SESSION_ID_INVALID )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " NET: Invalid sessionID %s. \n " , remoteAddress . ToString ( ) ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// Distribute the packet to the proper lobby
//
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int maskedType = sessionID & idPacketProcessor : : LOBBY_TYPE_MASK ;
2012-11-28 15:47:07 +00:00
if ( ! verify ( maskedType > 0 ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
idLobby : : lobbyType_t lobbyType = ( idLobby : : lobbyType_t ) ( maskedType - 1 ) ;
switch ( lobbyType )
{
case idLobby : : TYPE_PARTY :
GetPartyLobby ( ) . HandlePacket ( remoteAddress , fragMsg , sessionID ) ;
break ;
case idLobby : : TYPE_GAME :
GetGameLobby ( ) . HandlePacket ( remoteAddress , fragMsg , sessionID ) ;
break ;
case idLobby : : TYPE_GAME_STATE :
GetGameStateLobby ( ) . HandlePacket ( remoteAddress , fragMsg , sessionID ) ;
break ;
default :
assert ( 0 ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetActivePlatformLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLobby * idSessionLocal : : GetActivePlatformLobby ( )
{
2012-11-26 18:58:24 +00:00
sessionState_t state = GetState ( ) ;
2012-11-28 15:47:07 +00:00
if ( ( state = = GAME_LOBBY ) | | ( state = = BUSY ) | | ( state = = INGAME ) | | ( state = = LOADING ) )
{
2012-11-26 18:58:24 +00:00
return & GetGameLobby ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( state = = PARTY_LOBBY )
{
2012-11-26 18:58:24 +00:00
return & GetPartyLobby ( ) ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetActivePlatformLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idLobby * idSessionLocal : : GetActivePlatformLobby ( ) const
{
2012-11-26 18:58:24 +00:00
sessionState_t state = GetState ( ) ;
2012-11-28 15:47:07 +00:00
if ( ( state = = GAME_LOBBY ) | | ( state = = BUSY ) | | ( state = = INGAME ) | | ( state = = LOADING ) )
{
2012-11-26 18:58:24 +00:00
return & GetGameLobby ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( state = = PARTY_LOBBY )
{
2012-11-26 18:58:24 +00:00
return & GetPartyLobby ( ) ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetActingGameStateLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLobby & idSessionLocal : : GetActingGameStateLobby ( )
{
if ( net_useGameStateLobby . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return GetGameStateLobby ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return GetGameLobby ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetActingGameStateLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idLobby & idSessionLocal : : GetActingGameStateLobby ( ) const
{
if ( net_useGameStateLobby . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return GetGameStateLobby ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return GetGameLobby ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetLobbyFromType
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLobby * idSessionLocal : : GetLobbyFromType ( idLobby : : lobbyType_t lobbyType )
{
switch ( lobbyType )
{
case idLobby : : TYPE_PARTY :
return & GetPartyLobby ( ) ;
case idLobby : : TYPE_GAME :
return & GetGameLobby ( ) ;
case idLobby : : TYPE_GAME_STATE :
return & GetGameStateLobby ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetActivePlatformLobbyBase
This returns the base version for the idSession version
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLobbyBase & idSessionLocal : : GetActivePlatformLobbyBase ( )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby ! = NULL )
{
2012-11-26 18:58:24 +00:00
return * activeLobby ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return stubLobby ; // So we can return at least something
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetLobbyFromLobbyUserID
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLobbyBase & idSessionLocal : : GetLobbyFromLobbyUserID ( lobbyUserID_t lobbyUserID )
{
if ( ! lobbyUserID . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
return stubLobby ; // So we can return at least something
}
2012-11-28 15:47:07 +00:00
idLobby * lobby = GetLobbyFromType ( ( idLobby : : lobbyType_t ) lobbyUserID . GetLobbyType ( ) ) ;
if ( lobby ! = NULL )
{
2012-11-26 18:58:24 +00:00
return * lobby ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return stubLobby ; // So we can return at least something
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : TickSendQueue
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : TickSendQueue ( )
{
2012-11-26 18:58:24 +00:00
assert ( ! sendQueue . IsEmpty ( ) ) ;
int now = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
idQueuePacket * packet = sendQueue . Peek ( ) ;
while ( packet ! = NULL )
{
if ( now < packet - > time )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetPort ( packet - > dedicated ) . SendRawPacket ( packet - > address , packet - > data , packet - > size ) ;
2012-11-28 15:47:07 +00:00
if ( net_forceUpstream . GetFloat ( ) ! = 0.0f & & net_forceUpstreamQueue . GetFloat ( ) ! = 0.0f )
{
2012-11-26 18:58:24 +00:00
// FIXME: no can do both
assert ( net_forceLatency . GetInteger ( ) = = 0 ) ;
// compute / update an added traffic due to the queuing
// we can't piggyback on upstreamDropRate because of the way it's computed and clamped to zero
int time = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
if ( time > upstreamQueueRateTime )
{
2012-11-26 18:58:24 +00:00
upstreamQueueRate - = upstreamQueueRate * ( float ) ( time - upstreamQueueRateTime ) / 1000.0f ;
2012-11-28 15:47:07 +00:00
if ( upstreamQueueRate < 0.0f )
{
2012-11-26 18:58:24 +00:00
upstreamQueueRate = 0.0f ;
}
upstreamQueueRateTime = time ;
}
// update queued bytes
queuedBytes - = packet - > size ;
2012-11-28 15:47:07 +00:00
if ( net_verboseSimulatedTraffic . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " send queued packet size %d to %s \n " , packet - > size , packet - > address . ToString ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
sendQueue . RemoveFirst ( ) ; // we have it already, just push it off the queue before freeing
packetAllocator . Free ( packet ) ;
packet = sendQueue . Peek ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : QueuePacket
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : QueuePacket ( idQueue < idQueuePacket , & idQueuePacket : : queueNode > & queue , int time , const lobbyAddress_t & to , const void * data , int size , bool dedicated )
{
2012-11-26 18:58:24 +00:00
//mem.PushHeap();
2012-11-28 15:47:07 +00:00
idQueuePacket * packet = packetAllocator . Alloc ( ) ;
2012-11-26 18:58:24 +00:00
packet - > address = to ;
packet - > size = size ;
packet - > dedicated = dedicated ;
packet - > time = time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memcpy ( packet - > data , data , size ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
queue . Add ( packet ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//mem.PopHeap();
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ReadRawPacketFromQueue
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : ReadRawPacketFromQueue ( int time , lobbyAddress_t & from , void * data , int & size , bool & outDedicated , int maxSize )
{
idQueuePacket * packet = recvQueue . Peek ( ) ;
if ( packet = = NULL | | time < packet - > time )
{
2012-11-26 18:58:24 +00:00
return false ; // Either there are no packets, or no packet is ready
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idLib::Printf( "NET: Packet recvd: %d ms\n", now );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
from = packet - > address ;
size = packet - > size ;
assert ( size < = maxSize ) ;
outDedicated = packet - > dedicated ;
memcpy ( data , packet - > data , packet - > size ) ;
recvQueue . RemoveFirst ( ) ; // we have it already, just push it off the queue before freeing
packetAllocator . Free ( packet ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SendRawPacket
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SendRawPacket ( const lobbyAddress_t & to , const void * data , int size , bool dedicated )
{
2012-11-26 18:58:24 +00:00
const int now = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
if ( net_forceUpstream . GetFloat ( ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
// the total bandwidth rate at which the networking systems are trying to push data through
2012-11-28 15:47:07 +00:00
float totalOutgoingRate = ( float ) GetActingGameStateLobby ( ) . GetTotalOutgoingRate ( ) ; // B/s
2012-11-26 18:58:24 +00:00
// update the rate at which we have been taking data out by dropping it
int time = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
if ( time > upstreamDropRateTime )
{
2012-11-26 18:58:24 +00:00
upstreamDropRate - = upstreamDropRate * ( float ) ( time - upstreamDropRateTime ) / 1000.0f ;
2012-11-28 15:47:07 +00:00
if ( upstreamDropRate < 0.0f )
{
2012-11-26 18:58:24 +00:00
upstreamDropRate = 0.0f ;
}
upstreamDropRateTime = time ;
}
2012-11-28 15:47:07 +00:00
if ( ( float ) ( totalOutgoingRate - upstreamDropRate + upstreamQueueRate ) > net_forceUpstream . GetFloat ( ) * 1024.0f ) // net_forceUpstream is in kB/s, everything else in B/s
{
if ( net_forceUpstreamQueue . GetFloat ( ) = = 0.0f )
{
2012-11-26 18:58:24 +00:00
// just drop the packet - not representative, but simple
2012-11-28 15:47:07 +00:00
if ( net_verboseSimulatedTraffic . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " drop %d bytes to %s \n " , size , to . ToString ( ) ) ;
}
// increase the instant drop rate with the data we just dropped
upstreamDropRate + = size ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// simulate a network device with a send queue
// do we have room in the queue?
assert ( net_forceUpstreamQueue . GetFloat ( ) > 0.0f ) ;
2012-11-28 15:47:07 +00:00
if ( ( float ) ( queuedBytes + size ) > net_forceUpstreamQueue . GetFloat ( ) * 1024.0f ) // net_forceUpstreamQueue is in kB/s
{
2012-11-26 18:58:24 +00:00
// too much queued, this is still a drop
// FIXME: factorize
// just drop the packet - not representative, but simple
2012-11-28 15:47:07 +00:00
if ( net_verboseSimulatedTraffic . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " full queue: drop %d bytes to %s \n " , size , to . ToString ( ) ) ;
}
// increase the instant drop rate with the data we just dropped
upstreamDropRate + = size ;
return ;
}
// there is room to buffer up in the queue
queuedBytes + = size ;
// with queuedBytes and the current upstream, when should this packet be sent?
2012-11-28 15:47:07 +00:00
int queuedPacketSendDelay = 1000.0f * ( ( float ) queuedBytes / ( net_forceUpstream . GetFloat ( ) * 1024.0f ) ) ; // in ms
2012-11-26 18:58:24 +00:00
// queue for sending
2012-11-28 15:47:07 +00:00
if ( net_verboseSimulatedTraffic . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " queuing packet: %d bytes delayed %d ms \n " , size , queuedPacketSendDelay ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
QueuePacket ( sendQueue , now + queuedPacketSendDelay , to , data , size , dedicated ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// will abuse the forced latency code below to take care of the sending
// FIXME: right now, can't have both on
assert ( net_forceLatency . GetInteger ( ) = = 0 ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// short path
// NOTE: network queuing: will go to tick the queue whenever sendQueue isn't empty, regardless of latency
2012-11-28 15:47:07 +00:00
if ( net_forceLatency . GetInteger ( ) = = 0 & & sendQueue . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
GetPort ( dedicated ) . SendRawPacket ( to , data , size ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( net_forceUpstream . GetFloat ( ) ! = 0.0f & & net_forceUpstreamQueue . GetFloat ( ) ! = 0.0f )
{
2012-11-26 18:58:24 +00:00
// FIXME: not doing both just yet
assert ( net_forceLatency . GetInteger ( ) = = 0 ) ;
TickSendQueue ( ) ;
return ; // we done (at least for queue only path)
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// queue up
assert ( size ! = 0 & & size < = idPacketProcessor : : MAX_FINAL_PACKET_SIZE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
QueuePacket ( sendQueue , now + net_forceLatency . GetInteger ( ) / 2 , to , data , size , dedicated ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
TickSendQueue ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ReadRawPacket
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : ReadRawPacket ( lobbyAddress_t & from , void * data , int & size , bool & outDedicated , int maxSize )
{
2012-11-26 18:58:24 +00:00
SCOPED_PROFILE_EVENT ( " Session::ReadRawPacket " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( maxSize < = idPacketProcessor : : MAX_FINAL_PACKET_SIZE ) ;
2012-11-28 15:47:07 +00:00
if ( ! sendQueue . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
TickSendQueue ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int now = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure we give both ports equal time
static bool currentDedicated = false ;
currentDedicated = ! currentDedicated ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
2012-11-26 18:58:24 +00:00
// BRIAN_FIXME: Dedicated servers fuck up running 2 instances on the same machine
// outDedicated = ( i == 0 ) ? currentDedicated : !currentDedicated;
outDedicated = false ;
2012-11-28 15:47:07 +00:00
if ( GetPort ( outDedicated ) . ReadRawPacket ( from , data , size , maxSize ) )
{
if ( net_forceLatency . GetInteger ( ) = = 0 & & recvQueue . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
// If we aren't forcing latency, and queue is empty, return result immediately
return true ;
}
// the cvar is meant to be a round trip latency so we're applying half on the send and half on the recv
const int time = ( net_forceLatency . GetInteger ( ) = = 0 ) ? 0 : now + net_forceLatency . GetInteger ( ) / 2 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Otherwise, queue result
QueuePacket ( recvQueue , time , from , data , size , outDedicated ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Return any queued results
return ReadRawPacketFromQueue ( now , from , data , size , outDedicated , maxSize ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ConnectAndMoveToLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ConnectAndMoveToLobby ( idLobby & lobby , const lobbyConnectInfo_t & connectInfo , bool fromInvite )
{
2012-11-26 18:58:24 +00:00
// Since we are connecting directly to a lobby, make sure no search results are left over from previous FindOrCreateMatch results
// If we don't do this, we might think we should attempt to connect to an old search result, and we don't want to in this case
lobby . searchResults . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Attempt to connect to the lobby
lobby . ConnectTo ( connectInfo , fromInvite ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectType = CONNECT_DIRECT ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Wait for connection
2012-11-28 15:47:07 +00:00
switch ( lobby . lobbyType )
{
case idLobby : : TYPE_PARTY :
SetState ( STATE_CONNECT_AND_MOVE_TO_PARTY ) ;
break ;
case idLobby : : TYPE_GAME :
SetState ( STATE_CONNECT_AND_MOVE_TO_GAME ) ;
break ;
case idLobby : : TYPE_GAME_STATE :
SetState ( STATE_CONNECT_AND_MOVE_TO_GAME_STATE ) ;
break ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GoodbyeFromHost
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : GoodbyeFromHost ( idLobby & lobby , int peerNum , const lobbyAddress_t & remoteAddress , int msgType )
{
if ( ! verify ( localState > STATE_IDLE ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " NET: Got disconnected from host %s on session %s when we were not in a lobby or game. \n " , remoteAddress . ToString ( ) , lobby . GetLobbyName ( ) ) ;
MoveToMainMenu ( ) ;
return ; // Ignore if we are not past the main menu
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Goodbye from host. See if we were connecting vs connected
2012-11-28 15:47:07 +00:00
if ( ( localState = = STATE_CONNECT_AND_MOVE_TO_PARTY | | localState = = STATE_CONNECT_AND_MOVE_TO_GAME ) & & lobby . peers [ peerNum ] . GetConnectionState ( ) = = idLobby : : CONNECTION_CONNECTING )
{
2012-11-26 18:58:24 +00:00
// We were denied a connection attempt
idLib : : Printf ( " NET: Denied connection attempt from host %s on session %s. MsgType %i. \n " , remoteAddress . ToString ( ) , lobby . GetLobbyName ( ) , msgType ) ;
// This will try to move to the next connection if one exists, otherwise will create a match
HandleConnectionFailed ( lobby , msgType = = idLobby : : OOB_GOODBYE_FULL ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// We were disconnected from a server we were previously connected to
idLib : : Printf ( " NET: Disconnected from host %s on session %s. MsgType %i. \n " , remoteAddress . ToString ( ) , lobby . GetLobbyName ( ) , msgType ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool leaveGameWithParty = ( msgType = = idLobby : : OOB_GOODBYE_W_PARTY ) ;
2012-11-28 15:47:07 +00:00
if ( leaveGameWithParty & & lobby . lobbyType = = idLobby : : TYPE_GAME & & lobby . IsPeer ( ) & & GetState ( ) = = idSession : : GAME_LOBBY & & GetPartyLobby ( ) . host > = 0 & &
lobby . peers [ peerNum ] . address . Compare ( GetPartyLobby ( ) . peers [ GetPartyLobby ( ) . host ] . address , true ) )
{
// If a host is telling us goodbye from a game lobby, and the game host is the same as our party host,
2012-11-26 18:58:24 +00:00
// and we aren't in a game, and the host wants us to leave with him, then do so now
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
SetState ( STATE_PARTY_LOBBY_PEER ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Host left, so pick a new host (possibly even us) for this lobby
lobby . PickNewHost ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : WriteLeaderboardToMsg
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : WriteLeaderboardToMsg ( idBitMsg & msg , const leaderboardDefinition_t * leaderboard , const column_t * stats )
{
2012-11-26 18:58:24 +00:00
assert ( Sys_FindLeaderboardDef ( leaderboard - > id ) = = leaderboard ) ;
msg . WriteLong ( leaderboard - > id ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < leaderboard - > numColumns ; + + i )
{
2012-11-26 18:58:24 +00:00
uint64 value = stats [ i ] . value ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idLib::Printf( "value = %i\n", (int32)value );
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < leaderboard - > columnDefs [ i ] . bits ; j + + )
{
2012-11-26 18:58:24 +00:00
msg . WriteBits ( value & 1 , 1 ) ;
value > > = 1 ;
}
//msg.WriteData( &stats[i].value, sizeof( stats[i].value ) );
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ReadLeaderboardFromMsg
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const leaderboardDefinition_t * idSessionLocal : : ReadLeaderboardFromMsg ( idBitMsg & msg , column_t * stats )
{
2012-11-26 18:58:24 +00:00
int id = msg . ReadLong ( ) ;
2012-11-28 15:47:07 +00:00
const leaderboardDefinition_t * leaderboard = Sys_FindLeaderboardDef ( id ) ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( leaderboard = = NULL )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " NET: Invalid leaderboard id: %i \n " , id ) ;
return NULL ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < leaderboard - > numColumns ; + + i )
{
2012-11-26 18:58:24 +00:00
uint64 value = 0 ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < leaderboard - > columnDefs [ i ] . bits ; j + + )
{
value | = ( uint64 ) ( msg . ReadBits ( 1 ) & 1 ) < < j ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stats [ i ] . value = value ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idLib::Printf( "value = %i\n", (int32)value );
//msg.ReadData( &stats[i].value, sizeof( stats[i].value ) );
}
return leaderboard ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SendLeaderboardStatsToPlayer
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SendLeaderboardStatsToPlayer ( lobbyUserID_t lobbyUserID , const leaderboardDefinition_t * leaderboard , const column_t * stats )
{
2012-11-26 18:58:24 +00:00
const int sessionUserIndex = GetActingGameStateLobby ( ) . GetLobbyUserIndexByID ( lobbyUserID ) ;
2012-11-28 15:47:07 +00:00
if ( GetActingGameStateLobby ( ) . IsLobbyUserDisconnected ( sessionUserIndex ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " Tried to tell disconnected user to report stats " ) ;
return ;
}
const int peerIndex = GetActingGameStateLobby ( ) . PeerIndexFromLobbyUser ( lobbyUserID ) ;
2012-11-28 15:47:07 +00:00
if ( peerIndex = = - 1 )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " Tried to tell invalid peer index to report stats " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! verify ( GetActingGameStateLobby ( ) . IsHost ( ) ) | |
! verify ( peerIndex < GetActingGameStateLobby ( ) . peers . Num ( ) ) | |
! verify ( GetActingGameStateLobby ( ) . peers [ peerIndex ] . IsConnected ( ) ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " Tried to tell invalid peer to report stats " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " Telling sessionUserIndex %i (peer %i) to report stats \n " , sessionUserIndex , peerIndex ) ;
2012-11-28 15:47:07 +00:00
lobbyUser_t * gameUser = GetActingGameStateLobby ( ) . GetLobbyUser ( sessionUserIndex ) ;
if ( ! verify ( gameUser ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
byte buffer [ idPacketProcessor : : MAX_PACKET_SIZE ] ;
idBitMsg msg ( buffer , sizeof ( buffer ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Use the user ID
gameUser - > lobbyUserID . WriteToMsg ( msg ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
WriteLeaderboardToMsg ( msg , leaderboard , stats ) ;
GetActingGameStateLobby ( ) . QueueReliableMessage ( peerIndex , idLobby : : RELIABLE_POST_STATS , msg . GetReadData ( ) , msg . GetSize ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : RecvLeaderboardStatsForPlayer
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : RecvLeaderboardStatsForPlayer ( idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
column_t stats [ MAX_LEADERBOARD_COLUMNS ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lobbyUserID_t lobbyUserID ;
lobbyUserID . ReadFromMsg ( msg ) ;
2012-11-28 15:47:07 +00:00
const leaderboardDefinition_t * leaderboard = ReadLeaderboardFromMsg ( msg , stats ) ;
if ( leaderboard = = NULL )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " RecvLeaderboardStatsForPlayer: Invalid lb. \n " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
LeaderboardUpload ( lobbyUserID , leaderboard , stats ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : RequirePersistentMaster
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : RequirePersistentMaster ( )
{
2012-11-26 18:58:24 +00:00
return signInManager - > RequirePersistentMaster ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
CheckAndUpdateValue
= = = = = = = = = = = = = = = = = = = = = = = =
*/
template < typename T >
2012-11-28 15:47:07 +00:00
bool CheckAndUpdateValue ( T & value , const T & newValue )
{
if ( value = = newValue )
{
2012-11-26 18:58:24 +00:00
return false ;
}
value = newValue ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyUser_t : : UpdateClientMutableData
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool lobbyUser_t : : UpdateClientMutableData ( const idLocalUser * localUser )
{
2012-11-26 18:58:24 +00:00
bool updated = false ;
2012-11-28 15:47:07 +00:00
const idPlayerProfile * profile = localUser - > GetProfile ( ) ;
if ( profile ! = NULL )
{
2012-11-26 18:58:24 +00:00
updated | = CheckAndUpdateValue ( level , profile - > GetLevel ( ) ) ;
}
updated | = CheckAndUpdateValue ( selectedSkin , ui_skinIndex . GetInteger ( ) ) ;
updated | = CheckAndUpdateValue ( weaponAutoSwitch , ui_autoSwitch . GetBool ( ) ) ;
updated | = CheckAndUpdateValue ( weaponAutoReload , ui_autoReload . GetBool ( ) ) ;
return updated ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ComputeNextGameCoalesceTime
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ComputeNextGameCoalesceTime ( )
{
2012-11-26 18:58:24 +00:00
const int coalesceTimeInSeconds = session - > GetTitleStorageInt ( " net_LobbyCoalesceTimeInSeconds " , net_LobbyCoalesceTimeInSeconds . GetInteger ( ) ) ;
const int randomCoalesceTimeInSeconds = session - > GetTitleStorageInt ( " net_LobbyRandomCoalesceTimeInSeconds " , net_LobbyRandomCoalesceTimeInSeconds . GetInteger ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( coalesceTimeInSeconds ! = 0 )
{
2012-11-26 18:58:24 +00:00
static idRandom2 random ( Sys_Milliseconds ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
nextGameCoalesceTime = Sys_Milliseconds ( ) + ( coalesceTimeInSeconds + random . RandomInt ( randomCoalesceTimeInSeconds ) ) * 1000 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
nextGameCoalesceTime = 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyUser_t : : Net_BandwidthChallenge
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND ( Net_BandwidthChallenge , " Test network bandwidth " , 0 )
{
2012-11-26 18:58:24 +00:00
session - > StartOrContinueBandwidthChallenge ( true ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyUser_t : : Net_ThrottlePeer
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND ( Net_ThrottlePeer , " Test network bandwidth " , 0 )
{
2012-11-26 18:58:24 +00:00
int peerNum = - 1 ;
int snapRate = 0 ;
2012-11-28 15:47:07 +00:00
if ( args . Argc ( ) > = 3 )
{
peerNum = atoi ( args . Argv ( 1 ) ) ;
snapRate = atoi ( args . Argv ( 2 ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Note DebugSetPeerSnaprate will handle peerNum=-1 by printing out list of peers
session - > DebugSetPeerSnaprate ( peerNum , snapRate ) ;
}
// FIXME: Move to sys_stats.cpp
2012-11-28 15:47:07 +00:00
idStaticList < leaderboardDefinition_t * , MAX_LEADERBOARDS > registeredLeaderboards ;
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = =
Sys_FindLeaderboardDef
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const leaderboardDefinition_t * Sys_FindLeaderboardDef ( int id )
{
for ( int i = 0 ; i < registeredLeaderboards . Num ( ) ; i + + )
{
if ( registeredLeaderboards [ i ] & & registeredLeaderboards [ i ] - > id = = id )
{
2012-11-26 18:58:24 +00:00
return registeredLeaderboards [ i ] ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
Sys_CreateLeaderboardDef
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
leaderboardDefinition_t * Sys_CreateLeaderboardDef ( int id_ , int numColumns_ , const columnDef_t * columnDefs_ ,
rankOrder_t rankOrder_ , bool supportsAttachments_ , bool checkAgainstCurrent_ )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
leaderboardDefinition_t * newDef = new ( TAG_NETWORKING ) leaderboardDefinition_t ( id_ , numColumns_ , columnDefs_ , rankOrder_ , supportsAttachments_ , checkAgainstCurrent_ ) ;
2012-11-26 18:58:24 +00:00
// try and reuse a free spot
int leaderboardHandle = registeredLeaderboards . FindNull ( ) ;
2012-11-28 15:47:07 +00:00
if ( leaderboardHandle = = - 1 )
{
2012-11-26 18:58:24 +00:00
leaderboardHandle = registeredLeaderboards . Append ( NULL ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
registeredLeaderboards [ leaderboardHandle ] = newDef ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return newDef ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
Sys_CreateLeaderboardDef
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void Sys_DestroyLeaderboardDefs ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
// delete and clear all the contents of the registeredLeaderboards static list.
2012-11-26 18:58:24 +00:00
registeredLeaderboards . DeleteContents ( true ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : StartOrContinueBandwidthChallenge
This will start a bandwidth test if one is not active
returns true if a test has completed
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : StartOrContinueBandwidthChallenge ( bool forceStart )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
idLib : : Warning ( " No active session lobby when idSessionLocal::StartBandwidthChallenge called " ) ;
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
if ( ! forceStart & & activeLobby - > bandwidthChallengeFinished )
{
2012-11-26 18:58:24 +00:00
activeLobby - > bandwidthChallengeFinished = false ;
return true ;
}
2012-11-28 15:47:07 +00:00
if ( ! activeLobby - > BandwidthTestStarted ( ) )
{
2012-11-26 18:58:24 +00:00
activeLobby - > BeginBandwidthTest ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : DebugSetPeerSnaprate
This is debug function for manually setting peer ' s snaprate in game
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : DebugSetPeerSnaprate ( int peerIndex , int snapRateMS )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
idLib : : Warning ( " No active session lobby when idSessionLocal::StartBandwidthChallenge called " ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( peerIndex < 0 | | peerIndex > activeLobby - > peers . Num ( ) )
{
idLib : : Printf ( " Invalid peer %d \n " , peerIndex ) ;
for ( int i = 0 ; i < activeLobby - > peers . Num ( ) ; i + + )
{
idLib : : Printf ( " Peer[%d] %s \n " , i , activeLobby - > GetPeerName ( i ) ) ;
2012-11-26 18:58:24 +00:00
}
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
activeLobby - > peers [ peerIndex ] . throttledSnapRate = snapRateMS * 1000 ;
activeLobby - > peers [ peerIndex ] . receivedThrottle = 0 ;
2012-11-28 15:47:07 +00:00
idLib : : Printf ( " Set peer %s new snapRate: %d \n " , activeLobby - > GetPeerName ( peerIndex ) , activeLobby - > peers [ peerIndex ] . throttledSnapRate ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : DebugSetPeerSnaprate
This is debug function for manually setting peer ' s snaprate in game
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idSessionLocal : : GetIncomingByteRate ( )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
idLib : : Warning ( " No active session lobby when idSessionLocal::GetIncomingByteRate called " ) ;
2012-11-26 18:58:24 +00:00
return 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float total = 0 ;
2012-11-28 15:47:07 +00:00
for ( int p = 0 ; p < activeLobby - > peers . Num ( ) ; p + + )
{
if ( activeLobby - > peers [ p ] . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
total + = activeLobby - > peers [ p ] . packetProc - > GetIncomingRateBytes ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return total ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : OnLocalUserSignin
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : OnLocalUserSignin ( idLocalUser * user )
{
2012-11-26 18:58:24 +00:00
// Do stuff before calling OnMasterLocalUserSignin()
session - > GetAchievementSystem ( ) . RegisterLocalUser ( user ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// We may not have a profile yet, need to call user's version...
user - > LoadProfileSettings ( ) ;
2012-11-28 15:47:07 +00:00
// for all consoles except the PS3 we enumerate right away because they don't
// take such a long time as the PS3. PS3 enumeration is done in the
2012-11-26 18:58:24 +00:00
// background and kicked off when the profile callback is triggered
2012-11-28 15:47:07 +00:00
if ( user = = GetSignInManager ( ) . GetMasterLocalUser ( ) )
{
2012-11-26 18:58:24 +00:00
OnMasterLocalUserSignin ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : OnLocalUserSignout
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : OnLocalUserSignout ( idLocalUser * user )
{
2012-11-26 18:58:24 +00:00
// Do stuff before calling OnMasterLocalUserSignout()
session - > GetAchievementSystem ( ) . RemoveLocalUser ( user ) ;
2012-11-28 15:47:07 +00:00
if ( GetSignInManager ( ) . GetMasterLocalUser ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
OnMasterLocalUserSignout ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : OnMasterLocalUserSignout
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : OnMasterLocalUserSignout ( )
{
2012-11-26 18:58:24 +00:00
CancelSaveGameWithHandle ( enumerationHandle ) ;
enumerationHandle = 0 ;
GetSaveGameManager ( ) . GetEnumeratedSavegamesNonConst ( ) . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : OnMasterLocalUserSignin
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : OnMasterLocalUserSignin ( )
{
2012-11-26 18:58:24 +00:00
enumerationHandle = EnumerateSaveGamesAsync ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : OnLocalUserProfileLoaded
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : OnLocalUserProfileLoaded ( idLocalUser * user )
{
2012-11-26 18:58:24 +00:00
user - > RequestSyncAchievements ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SetVoiceGroupsToTeams
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SetVoiceGroupsToTeams ( )
{
// move voice chat to team
2012-11-26 18:58:24 +00:00
int myTeam = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < GetGameLobby ( ) . GetNumLobbyUsers ( ) ; + + i )
{
const lobbyUser_t * gameUser = GetGameLobby ( ) . GetLobbyUser ( i ) ;
if ( ! verify ( gameUser ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( gameUser - > IsDisconnected ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int userTeam = gameUser - > teamNumber ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
voiceChat - > SetTalkerGroup ( gameUser , GetGameLobby ( ) . lobbyType , userTeam ) ;
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsSessionUserIndexLocal ( i ) )
{
2012-11-26 18:58:24 +00:00
myTeam = userTeam ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetActiveChatGroup ( myTeam ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ClearVoiceGroups
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ClearVoiceGroups ( )
{
for ( int i = 0 ; i < GetGameLobby ( ) . GetNumLobbyUsers ( ) ; + + i )
{
const lobbyUser_t * gameUser = GetGameLobby ( ) . GetLobbyUser ( i ) ;
if ( ! verify ( gameUser ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( gameUser - > IsDisconnected ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
voiceChat - > SetTalkerGroup ( gameUser , GetGameLobby ( ) . lobbyType , 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetActiveChatGroup ( 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SendVoiceAudio
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SendVoiceAudio ( )
{
if ( voiceChat = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
2012-11-26 18:58:24 +00:00
int activeSessionIndex = ( activeLobby ! = NULL ) ? activeLobby - > lobbyType : - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
voiceChat - > SetActiveLobby ( activeSessionIndex ) ;
voiceChat - > Pump ( ) ;
2012-11-28 15:47:07 +00:00
if ( activeLobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int time = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
const int VOICE_THROTTLE_TIME_IN_MS = session - > GetTitleStorageInt ( " VOICE_THROTTLE_TIME_IN_MS " , 33 ) ; // Don't allow faster than 30hz send rate
if ( time - lastVoiceSendtime < VOICE_THROTTLE_TIME_IN_MS )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastVoiceSendtime = time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStaticList < int , MAX_PLAYERS > localTalkers ;
voiceChat - > GetActiveLocalTalkers ( localTalkers ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < localTalkers . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
// NOTE - For 360, we don't need more than XHV_MAX_VOICECHAT_PACKETS * XHV_VOICECHAT_MODE_PACKET_SIZE bytes
const int MAX_VDP_DATA_SIZE = 1000 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
byte buffer [ MAX_VDP_DATA_SIZE ] ;
const int titleStorageDataSize = session - > GetTitleStorageInt ( " MAX_VDP_DATA_SIZE " , 1000 ) ;
const int dataSizeAvailable = Min < int > ( titleStorageDataSize , sizeof ( buffer ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// in-out parameter
int dataSize = dataSizeAvailable ;
2012-11-28 15:47:07 +00:00
if ( ! voiceChat - > GetLocalChatData ( localTalkers [ i ] , buffer , dataSize ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
assert ( dataSize < = sizeof ( buffer ) ) ;
2012-11-28 15:47:07 +00:00
idStaticList < const lobbyAddress_t * , MAX_PLAYERS > recipients ;
2012-11-26 18:58:24 +00:00
voiceChat - > GetRecipientsForTalker ( localTalkers [ i ] , recipients ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < recipients . Num ( ) ; j + + )
{
2012-11-26 18:58:24 +00:00
activeLobby - > SendConnectionLess ( * recipients [ j ] , idLobby : : OOB_VOICE_AUDIO , buffer , dataSize ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleOobVoiceAudio
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : HandleOobVoiceAudio ( const lobbyAddress_t & from , const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( activeLobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
voiceChat - > SetActiveLobby ( activeLobby - > lobbyType ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
voiceChat - > SubmitIncomingChatData ( msg . GetReadData ( ) + msg . GetReadCount ( ) , msg . GetRemainingData ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SetActiveChatGroup
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SetActiveChatGroup ( int groupIndex )
{
2012-11-26 18:58:24 +00:00
voiceChat - > SetActiveChatGroup ( groupIndex ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetLobbyUserVoiceState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
voiceState_t idSessionLocal : : GetLobbyUserVoiceState ( lobbyUserID_t lobbyUserID )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return VOICECHAT_STATE_NOT_TALKING ;
}
2012-11-28 15:47:07 +00:00
const lobbyUser_t * user = activeLobby - > GetLobbyUserByID ( lobbyUserID ) ;
if ( ! verify ( user ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
return VOICECHAT_STATE_NOT_TALKING ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return voiceChat - > GetVoiceState ( user ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetDisplayStateFromVoiceState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
voiceStateDisplay_t idSessionLocal : : GetDisplayStateFromVoiceState ( voiceState_t voiceState ) const
{
if ( ( GetState ( ) = = GAME_LOBBY & & MatchTypeIsLocal ( GetGameLobby ( ) . GetMatchParms ( ) . matchFlags ) )
| | ( GetState ( ) = = PARTY_LOBBY & & MatchTypeIsLocal ( GetPartyLobby ( ) . GetMatchParms ( ) . matchFlags ) ) )
{
2012-11-26 18:58:24 +00:00
return VOICECHAT_DISPLAY_NONE ; // never show voice stuff in splitscreen
}
2012-11-28 15:47:07 +00:00
switch ( voiceState )
{
2012-11-26 18:58:24 +00:00
case VOICECHAT_STATE_MUTED_REMOTE :
case VOICECHAT_STATE_MUTED_LOCAL :
case VOICECHAT_STATE_MUTED_ALL :
return VOICECHAT_DISPLAY_MUTED ;
case VOICECHAT_STATE_NOT_TALKING :
return VOICECHAT_DISPLAY_NOTTALKING ;
case VOICECHAT_STATE_TALKING :
return VOICECHAT_DISPLAY_TALKING ;
case VOICECHAT_STATE_TALKING_GLOBAL :
return VOICECHAT_DISPLAY_TALKING_GLOBAL ;
case VOICECHAT_STATE_NO_MIC :
default :
return VOICECHAT_DISPLAY_NOTTALKING ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ToggleLobbyUserVoiceMute
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ToggleLobbyUserVoiceMute ( lobbyUserID_t lobbyUserID )
{
idLobby * activeLobby = GetActivePlatformLobby ( ) ;
if ( activeLobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Get the master local user
2012-11-28 15:47:07 +00:00
idLocalUser * masterUser = signInManager - > GetMasterLocalUser ( ) ;
if ( masterUser = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const lobbyUser_t * srcUser = activeLobby - > GetLobbyUser ( activeLobby - > GetLobbyUserIndexByLocalUserHandle ( masterUser - > GetLocalUserHandle ( ) ) ) ;
if ( srcUser = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const lobbyUser_t * targetUser = activeLobby - > GetLobbyUserByID ( lobbyUserID ) ;
if ( ! verify ( targetUser ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( srcUser = = targetUser )
{
2012-11-26 18:58:24 +00:00
return ; // Can't toggle yourself
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
voiceChat - > ToggleMuteLocal ( srcUser , targetUser ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : UpdateMasterUserHeadsetState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void idSessionLocal : : UpdateMasterUserHeadsetState ( )
{
2012-11-28 15:47:07 +00:00
if ( GetState ( ) ! = PARTY_LOBBY & & GetState ( ) ! = GAME_LOBBY & & GetState ( ) ! = INGAME )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
lobbyUser_t * user = GetActivePlatformLobby ( ) - > GetSessionUserFromLocalUser ( signInManager - > GetMasterLocalUser ( ) ) ;
2012-11-26 18:58:24 +00:00
// TODO: Is this possible?
2012-11-28 15:47:07 +00:00
if ( user = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int talkerIndex = voiceChat - > FindTalkerByUserId ( user - > lobbyUserID , GetActivePlatformLobby ( ) - > lobbyType ) ;
bool voiceChanged = voiceChat - > HasHeadsetStateChanged ( talkerIndex ) ;
2012-11-28 15:47:07 +00:00
if ( voiceChanged )
{
2012-11-26 18:58:24 +00:00
byte buffer [ idPacketProcessor : : MAX_MSG_SIZE ] ;
idBitMsg msg ( buffer , sizeof ( buffer ) ) ;
msg . WriteLong ( 1 ) ;
user - > lobbyUserID . WriteToMsg ( msg ) ;
msg . WriteBool ( voiceChat - > GetHeadsetState ( talkerIndex ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Sending voicestate %d for user %d %s \n " , voiceChat - > GetHeadsetState ( talkerIndex ) , talkerIndex , user - > gamertag ) ;
2012-11-28 15:47:07 +00:00
if ( GetActivePlatformLobby ( ) - > IsHost ( ) )
{
for ( int p = 0 ; p < GetActivePlatformLobby ( ) - > peers . Num ( ) ; p + + )
{
if ( GetActivePlatformLobby ( ) - > peers [ p ] . IsConnected ( ) )
{
2012-11-26 18:58:24 +00:00
GetActivePlatformLobby ( ) - > QueueReliableMessage ( p , idLobby : : RELIABLE_HEADSET_STATE , msg . GetReadData ( ) , msg . GetSize ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
GetActivePlatformLobby ( ) - > QueueReliableMessage ( GetActivePlatformLobby ( ) - > host , idLobby : : RELIABLE_HEADSET_STATE , msg . GetReadData ( ) , msg . GetSize ( ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetNumContentPackages
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSessionLocal : : GetNumContentPackages ( ) const
{
2012-11-26 18:58:24 +00:00
return downloadedContent . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetContentPackageID
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSessionLocal : : GetContentPackageID ( int contentIndex ) const
{
2012-11-26 18:58:24 +00:00
assert ( contentIndex < MAX_CONTENT_PACKAGES ) ;
2012-11-28 15:47:07 +00:00
if ( downloadedContent [ contentIndex ] . isMounted )
{
2012-11-26 18:58:24 +00:00
return downloadedContent [ contentIndex ] . dlcID ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetContentPackagePath
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idSessionLocal : : GetContentPackagePath ( int contentIndex ) const
{
2012-11-26 18:58:24 +00:00
assert ( contentIndex < MAX_CONTENT_PACKAGES ) ;
2012-11-28 15:47:07 +00:00
if ( downloadedContent [ contentIndex ] . isMounted )
{
2012-11-26 18:58:24 +00:00
return downloadedContent [ contentIndex ] . rootPath . c_str ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : GetContentPackageIndexForID
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSessionLocal : : GetContentPackageIndexForID ( int contentID ) const
{
2012-11-26 18:58:24 +00:00
int contentIndex = - 1 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < downloadedContent . Num ( ) ; i + + )
{
if ( downloadedContent [ i ] . dlcID = = contentID )
{
2012-11-26 18:58:24 +00:00
contentIndex = i ;
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return contentIndex ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : SetLobbyUserRelativeScore
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : SetLobbyUserRelativeScore ( lobbyUserID_t lobbyUserID , int relativeScore , int team )
{
2012-11-26 18:58:24 +00:00
// All platforms but 360 stub this out
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ReadTitleStorage
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ReadTitleStorage ( void * buffer , int bufferLen )
{
2012-11-26 18:58:24 +00:00
// https://ps3.scedev.net/projects/ps3_sdk_docs/docs/ps3-en,NP_Lookup-Reference,sceNpLookupTitleSmallStorageAsync/1
// If the file is not on the server, this will be handled as though a file of 0 bytes were on the server.
// This means that 0 will be set to contentLength and 0 (for normal termination) will return for the return value.
// This situation can occur with problems in actual operation, so the application must be designed not to hang up even in such situations
//bufferLen = 0;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " ReadTitleStorage: %i bytes \n " , bufferLen ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# if !defined( ID_RETAIL ) || defined( ID_RETAIL_INTERNAL )
2012-11-28 15:47:07 +00:00
if ( net_ignoreTitleStorage . GetBool ( ) ) //&& idLib::GetProduction() < PROD_PRODUCTION ) {
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " ReadTitleStorage: *********************** IGNORING ******************** \n " ) ;
return ;
}
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idScopedGlobalHeap everythingHereGoesInTheGlobalHeap;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idParser parser ( LEXFL_NOERRORS | LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT ) ;
parser . LoadMemory ( ( const char * ) buffer , bufferLen , " default.tss " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool valid = true ;
2012-11-28 15:47:07 +00:00
while ( true )
{
2012-11-26 18:58:24 +00:00
idToken token ;
2012-11-28 15:47:07 +00:00
if ( ! parser . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " netvars " ) = = 0 )
{
if ( ! titleStorageVars . Parse ( parser ) )
{
2012-11-26 18:58:24 +00:00
valid = false ;
break ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
valid = false ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( valid )
{
2012-11-26 18:58:24 +00:00
titleStorageLoaded = true ;
idLib : : Printf ( " ReadTitleStorage: SUCCESS \n " ) ;
titleStorageVars . Print ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
titleStorageLoaded = false ;
idLib : : Printf ( " ReadTitleStorage: FAILED \n " ) ;
titleStorageVars . Clear ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ReadDLCInfo
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : ReadDLCInfo ( idDict & dlcInfo , void * buffer , int bufferLen )
{
2012-11-26 18:58:24 +00:00
idParser parser ( LEXFL_NOERRORS | LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT ) ;
parser . LoadMemory ( ( const char * ) buffer , bufferLen , " info.txt " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool valid = true ;
2012-11-28 15:47:07 +00:00
while ( true )
{
2012-11-26 18:58:24 +00:00
idToken token ;
2012-11-28 15:47:07 +00:00
if ( ! parser . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " dlcInfo " ) = = 0 )
{
if ( ! dlcInfo . Parse ( parser ) )
{
2012-11-26 18:58:24 +00:00
valid = false ;
break ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
valid = false ;
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return valid ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : IsPlatformPartyInLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : IsPlatformPartyInLobby ( )
{
idLocalUser * user = session - > GetSignInManager ( ) . GetMasterLocalUser ( ) ;
idLobby * lobby = GetActivePlatformLobby ( ) ;
if ( user = = NULL | | lobby = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( user - > GetPartyCount ( ) > MAX_PLAYERS | | user - > GetPartyCount ( ) < 2 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// TODO: Implement PC
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : PrePickNewHost
This is called when we have determined that we need to pick a new host .
Call PickNewHostInternal to continue on with the host picking process .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : PrePickNewHost ( idLobby & lobby , bool forceMe , bool inviteOldHost )
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: (%s) \n " , lobby . GetLobbyName ( ) ) ;
if ( GetActivePlatformLobby ( ) = = NULL )
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: GetActivePlatformLobby() == NULL (%s) \n " , lobby . GetLobbyName ( ) ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if we can migrate AT ALL
// This is checking for coop, we should make this a specific option (MATCH_ALLOW_MIGRATION)
2012-11-28 15:47:07 +00:00
if ( GetPartyLobby ( ) . parms . matchFlags & MATCH_PARTY_INVITE_PLACEHOLDER )
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: MATCH_PARTY_INVITE_PLACEHOLDER (%s) \n " , lobby . GetLobbyName ( ) ) ;
2012-11-26 18:58:24 +00:00
// Can't migrate, shut both lobbies down, and create a new match using the original parms
GetGameStateLobby ( ) . Shutdown ( ) ;
GetGameLobby ( ) . Shutdown ( ) ;
GetPartyLobby ( ) . Shutdown ( ) ;
// Throw up the appropriate dialog message so the player knows what happeend
2012-11-28 15:47:07 +00:00
if ( localState > = idSessionLocal : : STATE_LOADING )
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: localState >= idSessionLocal::STATE_LOADING (%s) \n " , lobby . GetLobbyName ( ) ) ;
2012-11-26 18:58:24 +00:00
common - > Dialog ( ) . AddDialog ( GDM_BECAME_HOST_GAME_STATS_DROPPED , DIALOG_ACCEPT , NULL , NULL , false , __FUNCTION__ , __LINE__ , true ) ;
}
2012-11-28 15:47:07 +00:00
else
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: localState < idSessionLocal::STATE_LOADING (%s) \n " , lobby . GetLobbyName ( ) ) ;
common - > Dialog ( ) . AddDialog ( GDM_LOBBY_BECAME_HOST_GAME , DIALOG_ACCEPT , NULL , NULL , false , __FUNCTION__ , __LINE__ , true ) ;
}
2012-11-26 18:58:24 +00:00
CreateMatch ( GetActivePlatformLobby ( ) - > parms ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if the match is searchable
2012-11-28 15:47:07 +00:00
if ( GetState ( ) > = idSession : : GAME_LOBBY & & MatchTypeIsSearchable ( GetGameLobby ( ) . parms . matchFlags ) )
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: MatchTypeIsSearchable (%s) \n " , lobby . GetLobbyName ( ) ) ;
2012-11-26 18:58:24 +00:00
// Searchable games migrate lobbies independently, and don't need to stay in sync
2012-11-28 15:47:07 +00:00
lobby . PickNewHostInternal ( forceMe , inviteOldHost ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// Beyond this point, game lobbies must be sync'd with party lobbies as far as host status
// So to enforce that, we pull you out of the game lobby if you are in one when migration occurs
//
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if we should go back to a party lobby
2012-11-28 15:47:07 +00:00
if ( GetBackState ( ) > = idSessionLocal : : PARTY_LOBBY | | GetState ( ) = = idSession : : PARTY_LOBBY )
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: GetBackState() >= idSessionLocal::PARTY_LOBBY || GetState() == idSession::PARTY_LOBBY (%s) \n " , lobby . GetLobbyName ( ) ) ;
2012-11-26 18:58:24 +00:00
// Force the party lobby to start picking a new host if we lost the game lobby host
GetPartyLobby ( ) . PickNewHostInternal ( forceMe , inviteOldHost ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// End the game lobby, and go back to party lobby
GetGameStateLobby ( ) . Shutdown ( ) ;
GetGameLobby ( ) . Shutdown ( ) ;
SetState ( GetPartyLobby ( ) . IsHost ( ) ? idSessionLocal : : STATE_PARTY_LOBBY_HOST : idSessionLocal : : STATE_PARTY_LOBBY_PEER ) ;
2012-11-28 15:47:07 +00:00
}
else
{
NET_VERBOSE_PRINT ( " idSessionLocal::PrePickNewHost: GetBackState() < idSessionLocal::PARTY_LOBBY && GetState() != idSession::PARTY_LOBBY (%s) \n " , lobby . GetLobbyName ( ) ) ;
if ( localState > = idSessionLocal : : STATE_LOADING )
{
common - > Dialog ( ) . AddDialog ( GDM_HOST_QUIT , DIALOG_ACCEPT , NULL , NULL , false , __FUNCTION__ , __LINE__ , true ) ; // The host has quit the session. Returning to the main menu.
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Go back to main menu
GetGameLobby ( ) . Shutdown ( ) ;
GetGameStateLobby ( ) . Shutdown ( ) ;
GetPartyLobby ( ) . Shutdown ( ) ;
SetState ( idSessionLocal : : STATE_IDLE ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : PreMigrateInvite
This is called just before we get invited to a migrated session
If we return false , the invite will be ignored
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSessionLocal : : PreMigrateInvite ( idLobby & lobby )
2012-11-26 18:58:24 +00:00
{
2012-11-28 15:47:07 +00:00
if ( GetActivePlatformLobby ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if we can migrate AT ALL
// This is checking for coop, we should make this a specific option (MATCH_ALLOW_MIGRATION)
2012-11-28 15:47:07 +00:00
if ( ! verify ( ( GetPartyLobby ( ) . parms . matchFlags & MATCH_PARTY_INVITE_PLACEHOLDER ) = = 0 ) )
{
2012-11-26 18:58:24 +00:00
return false ; // Shouldn't get invites for coop (we should make this a specific option (MATCH_ALLOW_MIGRATION))
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Check to see if the match is searchable
2012-11-28 15:47:07 +00:00
if ( MatchTypeIsSearchable ( GetGameLobby ( ) . parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
// Searchable games migrate lobbies independently, and don't need to stay in sync
2012-11-28 15:47:07 +00:00
return true ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// Beyond this point, game lobbies must be sync'd with party lobbies as far as host status
// So to enforce that, we pull you out of the game lobby if you are in one when migration occurs
//
2012-11-28 15:47:07 +00:00
if ( lobby . lobbyType ! = idLobby : : TYPE_PARTY )
{
2012-11-26 18:58:24 +00:00
return false ; // We shouldn't be getting invites from non party lobbies when in a non searchable game
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Non placeholder Party lobbies can always migrate
2012-11-28 15:47:07 +00:00
if ( GetBackState ( ) > = idSessionLocal : : PARTY_LOBBY )
{
2012-11-26 18:58:24 +00:00
// Non searchable games go back to the party lobby
GetGameLobby ( ) . Shutdown ( ) ;
SetState ( GetPartyLobby ( ) . IsHost ( ) ? idSessionLocal : : STATE_PARTY_LOBBY_HOST : idSessionLocal : : STATE_PARTY_LOBBY_PEER ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ; // Non placeholder Party lobby invites joinable
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : lobbyAddress_t
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
lobbyAddress_t : : lobbyAddress_t ( )
{
2012-11-26 18:58:24 +00:00
memset ( & netAddr , 0 , sizeof ( netAddr ) ) ;
netAddr . type = NA_BAD ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : InitFromIPandPort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void lobbyAddress_t : : InitFromIPandPort ( const char * ip , int port )
{
2012-11-26 18:58:24 +00:00
Sys_StringToNetAdr ( ip , & netAddr , true ) ;
2012-11-28 15:47:07 +00:00
if ( ! netAddr . port )
{
2012-11-26 18:58:24 +00:00
netAddr . port = port ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : InitFromNetadr
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void lobbyAddress_t : : InitFromNetadr ( const netadr_t & netadr )
{
2012-11-26 18:58:24 +00:00
assert ( netadr . type ! = NA_BAD ) ;
netAddr = netadr ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : ToString
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * lobbyAddress_t : : ToString ( ) const
{
2012-11-26 18:58:24 +00:00
return Sys_NetAdrToString ( netAddr ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : UsingRelay
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool lobbyAddress_t : : UsingRelay ( ) const
{
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : Compare
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool lobbyAddress_t : : Compare ( const lobbyAddress_t & addr , bool ignoreSessionCheck ) const
{
2012-11-26 18:58:24 +00:00
return Sys_CompareNetAdrBase ( netAddr , addr . netAddr ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : WriteToMsg
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void lobbyAddress_t : : WriteToMsg ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
msg . WriteData ( & netAddr , sizeof ( netAddr ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyAddress_t : : ReadFromMsg
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void lobbyAddress_t : : ReadFromMsg ( idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
msg . ReadData ( & netAddr , sizeof ( netAddr ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort : : idNetSessionPort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
idNetSessionPort : : idNetSessionPort ( ) :
2012-12-11 22:48:55 +00:00
forcePacketDropCurr ( 0.0f ) ,
forcePacketDropPrev ( 0.0f )
2012-11-26 18:58:24 +00:00
{
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort : : InitPort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idNetSessionPort : : InitPort ( int portNumber , bool useBackend )
{
2012-11-26 18:58:24 +00:00
return UDP . InitForPort ( portNumber ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort : : ReadRawPacket
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idNetSessionPort : : ReadRawPacket ( lobbyAddress_t & from , void * data , int & size , int maxSize )
{
2012-11-26 18:58:24 +00:00
bool result = UDP . GetPacket ( from . netAddr , data , size , maxSize ) ;
static idRandom2 random ( Sys_Milliseconds ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( net_forceDrop . GetInteger ( ) ! = 0 )
{
forcePacketDropCurr = random . RandomInt ( 100 ) ;
if ( net_forceDrop . GetInteger ( ) > = forcePacketDropCurr )
{
2012-11-26 18:58:24 +00:00
return false ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return result ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort : : SendRawPacket
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idNetSessionPort : : SendRawPacket ( const lobbyAddress_t & to , const void * data , int size )
{
2012-11-26 18:58:24 +00:00
static idRandom2 random ( Sys_Milliseconds ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( net_forceDrop . GetInteger ( ) ! = 0 & & net_forceDrop . GetInteger ( ) > = random . RandomInt ( 100 ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
assert ( size < = idPacketProcessor : : MAX_FINAL_PACKET_SIZE ) ;
UDP . SendPacket ( to . netAddr , data , size ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort : : IsOpen
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idNetSessionPort : : IsOpen ( )
{
2012-11-26 18:58:24 +00:00
return UDP . IsOpen ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idNetSessionPort : : Close
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idNetSessionPort : : Close ( )
{
2012-11-26 18:58:24 +00:00
UDP . Close ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Commands
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
//====================================================================================
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND ( voicechat_mute , " TEMP " , 0 )
{
if ( args . Argc ( ) ! = 2 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Usage: voicechat_mute <user index> \n " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int i = atoi ( args . Argv ( 1 ) ) ;
session - > ToggleLobbyUserVoiceMute ( session - > GetActivePlatformLobbyBase ( ) . GetLobbyUserIdByOrdinal ( i ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
force_disconnect_all
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND ( force_disconnect_all , " force disconnect on all users " , 0 )
{
2012-11-26 18:58:24 +00:00
session - > GetSignInManager ( ) . RemoveAllLocalUsers ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
void Net_DebugOutputSignedInUsers_f
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void Net_DebugOutputSignedInUsers_f ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
session - > GetSignInManager ( ) . DebugOutputLocalUserInfo ( ) ;
}
idCommandLink Net_DebugOutputSignedInUsers ( " net_debugOutputSignedInUsers " , Net_DebugOutputSignedInUsers_f , " Outputs all the local users and other debugging information from the sign in manager " ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
void Net_RemoveUserFromLobby_f
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void Net_RemoveUserFromLobby_f ( const idCmdArgs & args )
{
if ( args . Argc ( ) > 1 )
{
2012-11-26 18:58:24 +00:00
int localUserNum = atoi ( args . Argv ( 1 ) ) ;
2012-11-28 15:47:07 +00:00
if ( localUserNum < session - > GetSignInManager ( ) . GetNumLocalUsers ( ) )
{
2012-11-26 18:58:24 +00:00
session - > GetSignInManager ( ) . RemoveLocalUserByIndex ( localUserNum ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " This user is not in the lobby \n " ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Usage: net_RemoveUserFromLobby <localUserNum> \n " ) ;
}
}
idCommandLink Net_RemoveUserFromLobby ( " net_removeUserFromLobby " , Net_RemoveUserFromLobby_f , " Removes the given user from the lobby " ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
Net_dropClient
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
CONSOLE_COMMAND ( Net_DropClient , " Drop a client " , 0 )
{
if ( args . Argc ( ) < 3 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " usage: Net_DropClient <clientnum> [<session>] 0/default: drop from game, 1: drop from party, otherwise drop from both \n " ) ;
return ;
}
int lobbyType = 0 ;
2012-11-28 15:47:07 +00:00
if ( args . Argc ( ) > 2 )
{
2012-11-26 18:58:24 +00:00
lobbyType = atoi ( args . Argv ( 2 ) ) ;
}
2012-11-28 15:47:07 +00:00
session - > DropClient ( atoi ( args . Argv ( 1 ) ) , lobbyType ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : DropClient
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : DropClient ( int peerNum , int session )
{
if ( session = = 1 | | session > = 2 )
{
2012-11-26 18:58:24 +00:00
GetPartyLobby ( ) . DisconnectPeerFromSession ( peerNum ) ;
}
2012-11-28 15:47:07 +00:00
if ( session = = 0 | | session > = 2 )
{
2012-11-26 18:58:24 +00:00
GetGameLobby ( ) . DisconnectPeerFromSession ( peerNum ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ListServersCommon
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : ListServersCommon ( )
{
2012-11-26 18:58:24 +00:00
netadr_t broadcast ;
memset ( & broadcast , 0 , sizeof ( broadcast ) ) ;
broadcast . type = NA_BROADCAST ;
broadcast . port = net_port . GetInteger ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lobbyAddress_t address ;
address . InitFromNetadr ( broadcast ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
byte buffer [ idPacketProcessor : : MAX_PACKET_SIZE - 2 ] ;
idBitMsg msg ( buffer , sizeof ( buffer ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Add the current version info to the query
2012-12-11 22:04:53 +00:00
const unsigned int localChecksum = NetGetVersionChecksum ( ) ; // DG: use int instead of long for 64bit compatibility
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " ListServers: Hash checksum: %i, broadcasting to: %s \n " , localChecksum , address . ToString ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteLong ( localChecksum ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GetPort ( ) ;
// Send the query as a broadcast
2012-11-28 15:47:07 +00:00
GetPartyLobby ( ) . SendConnectionLess ( address , idLobby : : OOB_MATCH_QUERY , msg . GetReadData ( ) , msg . GetSize ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleDedicatedServerQueryRequest
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : HandleDedicatedServerQueryRequest ( lobbyAddress_t & remoteAddr , idBitMsg & msg , int msgType )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " HandleDedicatedServerQueryRequest from %s \n " , remoteAddr . ToString ( ) ) ;
bool canJoin = true ;
2012-12-11 22:04:53 +00:00
// DG: use int instead of long for 64bit compatibility
const unsigned int localChecksum = NetGetVersionChecksum ( ) ;
const unsigned int remoteChecksum = msg . ReadLong ( ) ;
// DG end
2012-11-28 15:47:07 +00:00
if ( remoteChecksum ! = localChecksum )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " HandleServerQueryRequest: Invalid version from %s \n " , remoteAddr . ToString ( ) ) ;
canJoin = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure we are the host of this party session
2012-11-28 15:47:07 +00:00
if ( ! GetPartyLobby ( ) . IsHost ( ) )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " HandleServerQueryRequest: Not host of party \n " ) ;
canJoin = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure there is a session active
2012-11-28 15:47:07 +00:00
if ( GetActivePlatformLobby ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
canJoin = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make sure we have enough free slots
2012-11-28 15:47:07 +00:00
if ( GetPartyLobby ( ) . NumFreeSlots ( ) = = 0 | | GetGameLobby ( ) . NumFreeSlots ( ) = = 0 )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " No free slots \n " ) ;
canJoin = false ;
}
2012-11-28 15:47:07 +00:00
if ( MatchTypeInviteOnly ( GetPartyLobby ( ) . parms . matchFlags ) )
{
2012-11-26 18:58:24 +00:00
canJoin = false ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
// Buffer to hold reply msg
byte buffer [ idPacketProcessor : : MAX_PACKET_SIZE - 2 ] ;
idBitMsg retmsg ( buffer , sizeof ( buffer ) ) ;
2012-11-28 15:47:07 +00:00
idLocalUser * masterUser = GetSignInManager ( ) . GetMasterLocalUser ( ) ;
if ( masterUser = = NULL & & ! net_headlessServer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
canJoin = false ;
}
// Send the info about this game session to the caller
retmsg . WriteBool ( canJoin ) ;
2012-11-28 15:47:07 +00:00
if ( canJoin )
{
2012-11-26 18:58:24 +00:00
serverInfo_t serverInfo ;
serverInfo . joinable = ( session - > GetState ( ) > = idSession : : LOADING ) ;
2012-11-28 15:47:07 +00:00
if ( ! net_headlessServer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
serverInfo . serverName = masterUser - > GetGamerTag ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( GetGameLobby ( ) . IsLobbyActive ( ) )
{
2012-11-26 18:58:24 +00:00
serverInfo . gameMap = GetGameLobby ( ) . parms . gameMap ;
serverInfo . gameMode = GetGameLobby ( ) . parms . gameMode ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
serverInfo . gameMode = - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
serverInfo . numPlayers = GetActivePlatformLobby ( ) - > GetNumLobbyUsers ( ) ;
serverInfo . maxPlayers = GetActivePlatformLobby ( ) - > parms . numSlots ;
serverInfo . Write ( retmsg ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < GetActivePlatformLobby ( ) - > GetNumLobbyUsers ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
retmsg . WriteString ( GetActivePlatformLobby ( ) - > GetLobbyUserName ( GetActivePlatformLobby ( ) - > GetLobbyUserIdByOrdinal ( i ) ) ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Send it
2012-11-28 15:47:07 +00:00
GetPartyLobby ( ) . SendConnectionLess ( remoteAddr , idLobby : : OOB_MATCH_QUERY_ACK , retmsg . GetReadData ( ) , retmsg . GetSize ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : HandleDedicatedServerQueryAck
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSessionLocal : : HandleDedicatedServerQueryAck ( lobbyAddress_t & remoteAddr , idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
NET_VERBOSE_PRINT ( " HandleDedicatedServerQueryAck from %s \n " , remoteAddr . ToString ( ) ) ;
dedicatedServerSearch - > HandleQueryAck ( remoteAddr , msg ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionLocal : : ServerPlayerList
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idList < idStr > * idSessionLocal : : ServerPlayerList ( int i )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
lobbyUserID_t : : Serialize
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void lobbyUserID_t : : Serialize ( idSerializer & ser )
{
2012-11-26 18:58:24 +00:00
localUserHandle . Serialize ( ser ) ;
ser . Serialize ( lobbyType ) ;
}