//------------------------------------------------------------------------- bool CCryLobbySessionHandler::ShouldCallMapCommand( const char *pLevelName, const char *pGameRules ) { bool result = false; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { result = pGameLobby->ShouldCallMapCommand(pLevelName, pGameRules); if(result) { IPlatformOS* pPlatform = gEnv->pSystem->GetPlatformOS(); SStreamingInstallProgress progress; pPlatform->QueryStreamingInstallProgressForLevel(pLevelName, &progress); const bool bLevelReady = SStreamingInstallProgress::eState_Completed == progress.m_state; if(!bLevelReady) { // we can jump directly into MP from system game invitation avoiding frontend, so update streaming install priorities here pPlatform->SwitchStreamingInstallPriorityToLevel(pLevelName); gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent( ESYSTEM_EVENT_LEVEL_NOT_READY, (UINT_PTR)pLevelName, 0 ); } return bLevelReady; } } return result; }
void CUILobbyMP::WriteLeaderBoard() { ICryLobby *Lobby = gEnv->pNetwork->GetLobby(); CGameLobby* pGameLobby = g_pGame->GetGameLobby(); ICryLobbyService *Service = (Lobby) ? Lobby->GetLobbyService() : NULL; ICryStats *Stats = (Service != NULL) ? Service->GetStats() : NULL; unsigned int user = g_pGame->GetPlayerProfileManager()->GetExclusiveControllerDeviceIndex(); CryUserID userID = Service->GetUserID(user); ECryLobbyError Error; SCryStatsLeaderBoardWrite leaderboard; leaderboard.id = 0; leaderboard.data.numColumns = 0; leaderboard.data.pColumns = NULL; leaderboard.data.score.score = 311; leaderboard.data.score.id = 0; Error = Stats->StatsWriteLeaderBoards(pGameLobby->GetCurrentSessionHandle(), user, &leaderboard, 1, NULL, CUILobbyMP::WriteLeaderboardCallback, this); }
int CDLCManager::GetNamesStringOfPlayersMissingDLCsForLevel(const char* pLevelName, stack_string* pPlayersString) { CGameLobby* pGameLobby = g_pGame->GetGameLobby(); CRY_ASSERT(pGameLobby); CRY_ASSERT(pGameLobby->IsServer()); int count = 0; uint32 requiredDLCs = GetRequiredDLCsForLevel(pLevelName); const SSessionNames& lobbySessNames = pGameLobby->GetSessionNames(); const int nameSize = lobbySessNames.Size(); for (int i=0; i<nameSize; ++i) { const SSessionNames::SSessionName& player = lobbySessNames.m_sessionNames[i]; const uint32 loadedDLC = (uint32) player.m_userData[eLUD_LoadedDLCs]; if (!MeetsDLCRequirements(requiredDLCs, loadedDLC)) { CryLog("CDLCManager::GetNamesStringOfPlayersMissingDLCsForLevel: '%s' does not meet DLC requirements for level '%s'", player.m_name, pLevelName); count++; if (!pPlayersString->empty()) { pPlayersString->append(", "); } pPlayersString->append(player.m_name); } } return count; }
//------------------------------------------------------------------------- void CCryLobbySessionHandler::JoinSessionFromConsole(CrySessionID session) { CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { pGameLobby->JoinServer(session, "JoinSessionFromConsole", CryMatchMakingInvalidConnectionUID, true); } }
//------------------------------------------------------------------------ void CGameRules::StoreMigratingPlayer(IActor* pActor) { if (pActor == NULL) { GameWarning("Invalid data for migrating player"); return; } IEntity* pEntity = pActor->GetEntity(); EntityId id = pEntity->GetId(); bool registered = false; uint16 channelId = pActor->GetChannelId(); CRY_ASSERT(channelId); bool bShouldAdd = true; CGameLobby *pGameLobby = g_pGame->GetGameLobby(); CRY_ASSERT(pGameLobby); if (pGameLobby) { SCryMatchMakingConnectionUID conId = pGameLobby->GetConnectionUIDFromChannelID((int) channelId); if (pGameLobby->GetSessionNames().Find(conId) == SSessionNames::k_unableToFind) { CryLog("CGameRules::StoreMigratingPlayer() player %s (channelId=%u) has already left the game, not storing", pEntity->GetName(), channelId); bShouldAdd = false; } } if (bShouldAdd && (!m_hostMigrationCachedEntities.empty())) { if (!stl::find(m_hostMigrationCachedEntities, pActor->GetEntityId())) { bShouldAdd = false; } } if (bShouldAdd) { for (uint32 index = 0; index < m_migratingPlayerMaxCount; ++index) { if (!m_pMigratingPlayerInfo[index].InUse()) { m_pMigratingPlayerInfo[index].SetData(pEntity->GetName(), id, GetTeam(id), pEntity->GetWorldPos(), pEntity->GetWorldAngles(), pActor->GetHealth()); m_pMigratingPlayerInfo[index].SetChannelID(channelId); registered = true; break; } } } pEntity->Hide(true); // Hide the player, they will be unhidden when they rejoin if (!registered && bShouldAdd) { GameWarning("Too many migrating players!"); } }
void CUILobbyMP::LeaveGame() { CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { pGameLobby->LeaveSession(true); pGameLobby->SetMatchmakingGame(false); } }
void CAntiCheatManager::KickPlayer(uint16 channelId, EDisconnectionCause reason, int nConfidence) { CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryUserID userId = pGameLobby->GetUserIDFromChannelID(channelId); KickPlayer(userId, reason, nConfidence); } }
void CUIMultiPlayer::OnSendChatMessage( const string& message ) { //chat to all #if ENABLE_CHAT_MESSAGES CGameLobby* lobby = g_pGame->GetGameLobby(); if(lobby) { lobby->SendChatMessage(false, message.c_str()); } #endif }
//------------------------------------------------------------------------- bool CCryLobbySessionHandler::IsGameSessionMigratable() const { bool result = false; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { result = pGameLobby->IsSessionMigratable(); } return result; }
//------------------------------------------------------------------------- int CCryLobbySessionHandler::GetNumberOfExpectedClients() { int result = 0; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { result = pGameLobby->GetNumberOfExpectedClients(); } return result; }
//------------------------------------------------------------------------- bool CCryLobbySessionHandler::ShouldMigrateNub() const { bool bResult = true; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { bResult = pGameLobby->ShouldMigrateNub(); } return bResult; }
//------------------------------------------------------------------------- CrySessionHandle CCryLobbySessionHandler::GetGameSessionHandle() const { CrySessionHandle result = CrySessionInvalidHandle; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { result = pGameLobby->GetCurrentSessionHandle(); } return result; }
//------------------------------------------------------------------------- bool CCryLobbySessionHandler::ShouldCallMapCommand( const char *pLevelName, const char *pGameRules ) { bool result = false; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { result = pGameLobby->ShouldCallMapCommand(pLevelName, pGameRules); } return result; }
void CUILobbyMP::WriteLeaderboardCallback(CryLobbyTaskID TaskID, ECryLobbyError Error, void *Arg) { if (Error > eCLE_SuccessContinue) GameWarning("CQuerySystem::WriteLeaderboardCallback: Failed to write, code: %i", Error); //test CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { pGameLobby->LeaveSession(true); pGameLobby->SetMatchmakingGame(false); } }
void CUILobbyMP::GetPlayerList() { CGameLobby* pGameLobby = g_pGame->GetGameLobby(); SSessionNames sessions = pGameLobby->GetSessionNames(); SUIArguments players, ids; for (uint i = 0; i < sessions.Size(); i++) { SSessionNames::SSessionName &player = sessions.m_sessionNames[i]; players.AddArgument( string(player.m_name) ); ids.AddArgument(player.m_conId.m_uid); } PlayerListReturn(players, ids); }
void CGameLocalizationManager::LoadTag( ELocalizationTag tag ) { if(gEnv->IsEditor())// in editor all loca files are loaded during level load to get the info in the log return; switch(tag) { case eLT_Init: { LoadTagInternal(tag, "init"); } break; case eLT_GameType: { LoadTagInternal(tag, gEnv->bMultiplayer ? "multiplayer" : "singleplayer"); } break; case eLT_Level: { if(gEnv->bMultiplayer) { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { const char* pGameRules = pGameLobby->GetCurrentGameModeName(NULL); if(pGameRules) { LoadTagInternal(tag, pGameRules); } } } else { LoadTagInternal(tag, gEnv->pGame->GetIGameFramework()->GetLevelName()); } } break; case eLT_Credits: { LoadTagInternal(tag, "credits"); } break; default: CRY_ASSERT_MESSAGE(0, "Unknown GameLocalizationManger Tag"); break; } }
void CAntiCheatManager::BanPlayer_Internal(uint16 channelId, float timeout, int nConfidence) { CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryUserID userId = pGameLobby->GetUserIDFromChannelID(channelId); if (userId.IsValid()) { ICryLobby *pLobby = gEnv->pNetwork->GetLobby(); if (pLobby) { ICryMatchMaking *pMatchmaking = pLobby->GetMatchMaking(); if (pMatchmaking) { pMatchmaking->Ban(&userId, timeout); } } } } }
uint32 CDLCManager::GetRequiredDLCs() { stack_string sCurrentLevelName; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { // This is the map currently selected in the game lobby sCurrentLevelName = pGameLobby->GetCurrentLevelName(); } else { // This is the fallback if the lobby can't be found sCurrentLevelName = gEnv->pConsole->GetCVar("sv_map")->GetString(); } if (strcmp(sCurrentLevelName.c_str(), m_prevLevelName.c_str()) != 0) { m_prevLevelName = sCurrentLevelName.c_str(); m_requiredDLCs = GetRequiredDLCsForLevel(sCurrentLevelName.c_str()); } return m_requiredDLCs; }
void CUILobbyMP::JoinGame(int sessionID) { bool result = false; CGameLobby *pGameLobby = g_pGame->GetGameLobby(); CGameLobbyManager *pGameLobbyMgr = g_pGame->GetGameLobbyManager(); CSquadManager *pSquadMgr = g_pGame->GetSquadManager(); if(pGameLobbyMgr) { pGameLobbyMgr->SetMultiplayer(true); } if(pSquadMgr) { pSquadMgr->SetMultiplayer(true); } if(pGameLobby && m_FoundServers.size() > sessionID) result = pGameLobby->JoinServer(m_FoundServers[sessionID].m_id, m_FoundServers[sessionID].m_data.m_name, CryMatchMakingInvalidConnectionUID, false); return; }
//------------------------------------------------------------------------ void CPlaylistActivityTracker::Update( float dt ) { //update downloadable resources for( int i = 0; i < eRTT_MaxCount; i++ ) { if( m_downloadableResources[ i ] != NULL ) { m_downloadableResources[ i ]->DispatchCallbacks(); } } if( m_state != eATS_Idle ) { //check conditions if( m_state == eATS_OnPlaylist ) { CGameLobby* pLobby = g_pGame->GetGameLobby(); if( !pLobby || pLobby->GetState() == eLS_None ) { //game lobby isn't active so this must be the wrong state we're in //set us back to get activity because we're still in multiplayer m_state = eATS_GetActivity; //small delay on next poll in case other things are going on m_timeUntilNextAction = 10.0f; } } m_timeUntilNextAction -= dt; if( m_timeUntilNextAction <= 0.0f ) { switch( m_state ) { case eATS_GetActivity: { //we're in some state where we want a regular update of the playlist activity //e.g. on the multiplayer menus, ask for the data again RequestCurrentActivity(); m_timeUntilNextAction = k_activityUpdateFrequency; break; } case eATS_OnPlaylist: { //re-send the on a playlist info CPlaylistManager* pPlaylists = g_pGame->GetPlaylistManager(); if( const SPlaylist* pCurrentPlaylist = pPlaylists->GetCurrentPlaylist() ) { int variantIndex = pPlaylists->GetActiveVariantIndex(); JoinedPlaylist( pCurrentPlaylist->id, variantIndex ); } m_timeUntilNextAction = k_onPlaylistUpdateFrequency; break; } } } } }
//------------------------------------------------------------------------ void CMatchMakingHandler::OnSearchResult( SCrySessionSearchResult* pSession ) { //session will expire at the end of the callback //so copy it into a results structure (we need lots of details to pass to the matchmaking part //store it in a map (indexed via sessionID?) //pass the index to the lua CGameLobbyManager* pLobbyManager = g_pGame->GetGameLobbyManager(); if( pLobbyManager ) { CGameLobby* pLobby = pLobbyManager->GetGameLobby(); //first check if this result refers to a lobby we're in/hosting if( pLobby->IsCurrentSessionId( pSession->m_id ) ) { //this is the session for the lobby we are in, early out return; } //also check secondary lobby if( CGameLobby* pSecondaryLobby = pLobbyManager->GetNextGameLobby() ) { if( ( pSecondaryLobby->IsCurrentSessionId( pSession->m_id ) ) ) { //this is the session for the lobby we are going to, early out return; } } const CGameLobby::EActiveStatus activeStatus = (CGameLobby::EActiveStatus) GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_ACTIVE ); bool bIsBadServer = pLobby->IsBadServer( pSession->m_id ); const int skillRank = pLobby->CalculateAverageSkill(); const int sessionSkillRank = GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_SKILL ); const int sessionLanguageId = GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_LANGUAGE ); float sessionScore = LegacyC2MatchMakingScore( pSession, pLobby, false ); int32 region = 0; #if GAMELOBBY_USE_COUNTRY_FILTERING region = GameLobbyData::GetSearchResultsData( pSession, LID_MATCHDATA_COUNTRY ); #endif //GAMELOBBY_USE_COUNTRY_FILTERING #if defined(TRACK_MATCHMAKING) if( CMatchmakingTelemetry* pMMTel = g_pGame->GetMatchMakingTelemetry() ) { pMMTel->AddEvent( SMMFoundSessionEvent( pSession, activeStatus, skillRank - sessionSkillRank, region, sessionLanguageId, bIsBadServer, sessionScore ) ); } #endif //defined(TRACK_MATCHMAKING) HSCRIPTFUNCTION scriptFunction; if( m_pScript->GetValue( "OnSearchResult", scriptFunction ) ) { //Make a table to hold the search result SmartScriptTable result( gEnv->pScriptSystem ); SessionDetails newSession; newSession.m_id = pSession->m_id; cry_strcpy( newSession.m_name, pSession->m_data.m_name ); //capture the session ID in a map std::pair< TSessionIdMap::iterator, bool > insertResult = m_sessionIdMap.insert( std::make_pair( m_sessionIdIndex++, newSession ) ); if( insertResult.second ) { CryLog( "MMLua: Adding a server with parameters ping %d, status %d, avSkill %d", pSession->m_ping, activeStatus, sessionSkillRank ); result->SetValue( "SessionId", insertResult.first->first ); result->SetValue( "SearchId", s_currentMMSearchID ); float timeSinceStarted = gEnv->pTimer->GetFrameStartTime().GetSeconds() - m_startTime; result->SetValue( "TimeFound", timeSinceStarted ); //make a sub table to hold all the known session parameters SmartScriptTable parameters( gEnv->pScriptSystem ); result->SetValue( "Parameters", parameters ); parameters->SetValue( "ActiveStatus", activeStatus ); parameters->SetValue( "ServerAvSkill", sessionSkillRank ); parameters->SetValue( "Region", region ); parameters->SetValue( "Language", sessionLanguageId ); parameters->SetValue( "BadServer", bIsBadServer ); parameters->SetValue( "Ping", pSession->m_ping ); parameters->SetValue( "FilledSlots", pSession->m_numFilledSlots ); Script::Call( gEnv->pScriptSystem, scriptFunction, m_pScript, result ); gEnv->pScriptSystem->ReleaseFunc( scriptFunction ); } } } }
//------------------------------------------------------------------------- void CGameRulesStandardState::Update( float frameTime ) { if (gEnv->bServer) { if(m_state == EGRS_Intro) { // We assume there is an intro, if we reach this point and an intro hasnt been registered, we know there isn't one. Onwards and upwards. if(!m_pGameRules->IsIntroSequenceRegistered()) { ChangeState(EGRS_PreGame); } } if (m_state == EGRS_PreGame) { if (m_isStarting) { const float remainingTime = m_pGameRules->GetRemainingStartTimer(); if (remainingTime <= 0.f) { CryLog("CGameRulesStandardState::Update(), starting game"); ChangeState(EGRS_InGame); } } else { bool bOk = true; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); const int numPlayers = m_pGameRules->GetPlayerCount(true); if (pGameLobby) { if (m_isWaitingForOverrideTimer) { //-- test override timer m_startTimerOverrideWait -= frameTime; bOk = (m_startTimerOverrideWait <= 0.0f); if (!bOk) { bOk = true; //-- testing min player count doesn't apply to private games const bool publicGame = !pGameLobby->IsPrivateGame(); const bool onlineGame = pGameLobby->IsOnlineGame(); if (publicGame && onlineGame) { // Start only when we have enough players if (m_pGameRules->GetTeamCount() > 1) { //-- team game, insist at least 1 player per team const int numPlayersPerTeamMin = g_pGameCVars->g_gameRules_startTimerMinPlayersPerTeam; const int numPlayersTeam1 = m_pGameRules->GetTeamPlayerCount(1, true); const int numPlayersTeam2 = m_pGameRules->GetTeamPlayerCount(2, true); bOk = ((numPlayersTeam1 >= numPlayersPerTeamMin) && (numPlayersTeam2 >= numPlayersPerTeamMin)); } else { //-- not a team game, so just insist on minimum 2 players const int numPlayersMin = g_pGameCVars->g_gameRules_startTimerMinPlayers; bOk = (numPlayers >= numPlayersMin); } const int numPlayersInLobby = pGameLobby->GetSessionNames().Size(); bOk |= (numPlayersInLobby == numPlayers); } if (bOk) { //-- Enforce a percentage of lobby players in game before starting countdown bOk = (!gEnv->IsClient() || (g_pGame->GetClientActorId() != 0)) && CheckInitialChannelPlayers(); } } } else { bOk = false; if (numPlayers) { //-- Start the override timer. m_startTimerOverrideWait = g_pGameCVars->g_gameRules_startTimerOverrideWait; m_isWaitingForOverrideTimer = true; } } } if (bOk) { CryLog("CGameRulesStandardState::Update(), we have %i players, starting the game", numPlayers); float startTimeLength = #if !defined(_RELEASE) g_pGameCVars->g_gameRules_skipStartTimer ? 0.0f : #endif g_pGameCVars->g_gameRules_startTimerLength; #if USE_PC_PREMATCH bool bDoPCPrematch = false; CGameRules::EPrematchState prematchState = m_pGameRules->GetPrematchState(); if (prematchState==CGameRules::ePS_Prematch) { int numRequiredPlayers = g_pGameCVars->g_minPlayersForRankedGame - m_pGameRules->GetPlayerCount(true); if ((numRequiredPlayers > 0) || (pGameLobby && pGameLobby->UseLobbyTeamBalancing() && !pGameLobby->IsGameBalanced())) { bDoPCPrematch = true; CPlaylistManager *pPlaylistManager = g_pGame->GetPlaylistManager(); if (pGameLobby && pPlaylistManager) { if (!pGameLobby->IsRankedGame() || pPlaylistManager->IsUsingCustomVariant()) { // Private games don't do prematch bDoPCPrematch = false; } } if (bDoPCPrematch) { // If we are waiting for players on pc, spawn ingame and set a prematch state which waits for players. m_pGameRules->StartPrematch(); startTimeLength = 0.f; } } if (!bDoPCPrematch) { m_pGameRules->SkipPrematch(); } } #endif m_pGameRules->ResetGameStartTimer(startTimeLength); StartCountdown(true); } } } else if (m_state == EGRS_PostGame) { const float prevUpdateStamp = m_timeInPostGame; const float timeInPost = (prevUpdateStamp + frameTime); const float timeToShowHUDMessage = g_pGameCVars->g_gameRules_postGame_HUDMessageTime; const float timeToShowTop3 = g_pGameCVars->g_gameRules_postGame_Top3Time; const float timeToShowScoreboard = g_pGameCVars->g_gameRules_postGame_ScoreboardTime; float killcamLength = m_pGameRules->GameEndedByWinningKill() ? g_pGameCVars->kc_length : 0.f; if (g_pGameCVars->kc_showHighlightsAtEndOfGame) { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if(pRecordingSystem) { killcamLength += pRecordingSystem->GetHighlightsReelLength(); killcamLength = min(killcamLength, 20.f); } } const float totalPostGameTime = timeToShowHUDMessage + timeToShowTop3 + timeToShowScoreboard + killcamLength; if (timeInPost > totalPostGameTime) { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (!pRecordingSystem || (!pRecordingSystem->IsPlaybackQueued() && !pRecordingSystem->IsPlayingBack())) { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] Server trying to return to lobby"); pGameLobby->SvFinishedGame(frameTime); } } else if(pRecordingSystem) { pRecordingSystem->StopHighlightReel(); } } m_timeInPostGame = timeInPost; } } CPlayer * pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetClientActor()); if((pPlayer && pPlayer->ShouldPlayIntro() || gEnv->bServer) && m_pGameRules->IsIntroSequenceRegistered() && !m_bHaveNotifiedIntroListeners) { // All flowgraph nodes that want to listen, should be created at this point OnIntroStart_NotifyListeners(); } #ifndef _RELEASE if(g_pGameCVars->g_hud_postgame_debug) { const char* stateName = ""; switch(m_state) { case EGRS_Reset: { stateName = "EGRS_Reset"; break;} case EGRS_Intro: { stateName = "EGRS_Intro"; break;} case EGRS_PreGame: { stateName = "EGRS_PreGame"; break;} case EGRS_InGame: { stateName = "EGRS_InGame"; break;} case EGRS_PostGame: { stateName = "EGRS_PostGame"; break;} case EGRS_MAX: { stateName = "EGRS_MAX"; break;} } CryWatch("GameRulesStandardState - State = %s", stateName); if(m_state == EGRS_PostGame) { const char* postGameStateName = ""; switch(m_postGameState) { case ePGS_Unknown: { postGameStateName = "ePGS_Unknown"; break; } case ePGS_Starting: { postGameStateName = "ePGS_Starting"; break; } case ePGS_HudMessage: { postGameStateName = "ePGS_HudMessage"; break; } case ePGS_FinalKillcam: { postGameStateName = "ePGS_FinalKillcam"; break; } case ePGS_HighlightReel: { postGameStateName = "ePGS_HighlightReel"; break; } case ePGS_Top3: { postGameStateName = "ePGS_Top3"; break; } case ePGS_Scoreboard: { postGameStateName = "ePGS_Scoreboard"; break; } } CryWatch("GameRulesStandardState -PostGameState = %s", postGameStateName); } } #endif if (gEnv->IsClient()) { if (m_state == EGRS_PreGame) { if( !gEnv->IsDedicated() ) { if (m_isStarting) { const float timeTillStartInSeconds = m_pGameRules->GetRemainingStartTimer(); SHUDEventWrapper::UpdateGameStartCountdown( ePreGameCountdown_MatchStarting, timeTillStartInSeconds ); } else { SHUDEventWrapper::UpdateGameStartCountdown( ePreGameCountdown_WaitingForPlayers, 0.0f ); } } } else if (m_state == EGRS_InGame && !gEnv->IsDedicated() ) { if (m_introMessageShown == false) // Show only once { CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules && pGameRules->HasGameActuallyStarted()) { if (EntityId localPlayerId = g_pGame->GetIGameFramework()->GetClientActorId()) { int teamId = g_pGame->GetGameRules()->GetTeam(localPlayerId); bool bTeamGame = (pGameRules->GetTeamCount() > 1); IActor *pActor = g_pGame->GetIGameFramework()->GetClientActor(); if (pActor->GetSpectatorMode()==CActor::eASM_None && !pActor->IsDead() && (!bTeamGame || teamId!=0)) { if (IGameRulesPlayerStatsModule *statsModule = pGameRules->GetPlayerStatsModule()) { const SGameRulesPlayerStat *stats = statsModule->GetPlayerStats(localPlayerId); if (stats->deaths <= 0) // Not died ever { if (m_startMatchString.empty() == false) { const char* gamemodeName = g_pGame->GetGameRules()->GetEntity()->GetClass()->GetName(); CryFixedStringT<32> strSignalName; strSignalName.Format("StartGame%s", gamemodeName); TAudioSignalID signalId = g_pGame->GetGameAudio()->GetSignalID(strSignalName); CryFixedStringT<64> localisedStartString = CHUDUtils::LocalizeString( m_startMatchString.c_str() ); if (bTeamGame) { CryFixedStringT<16> strTeamName; strTeamName.Format("@ui_hud_team_%d", teamId); SHUDEventWrapper::TeamMessage(strTeamName.c_str(), teamId, SHUDEventWrapper::SMsgAudio(signalId), false, true); SHUDEventWrapper::SimpleBannerMessage(localisedStartString.c_str(), SHUDEventWrapper::kMsgAudioNULL); } else { SHUDEventWrapper::RoundMessageNotify(localisedStartString.c_str(), SHUDEventWrapper::SMsgAudio(signalId)); } } } } m_introMessageShown = true; // Or not if has already died, but don't check again anyway. } } } } } else if(m_state == EGRS_PostGame && !gEnv->IsDedicated()) { if (!gEnv->bServer) { m_timeInPostGame += frameTime; } m_timeInCurrentPostGameState += frameTime; switch (m_postGameState) { case ePGS_Starting: { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (pRecordingSystem != NULL && (pRecordingSystem->IsPlayingBack() || pRecordingSystem->IsPlaybackQueued())) { // Currently showing a killcam, skip to the killcam stage of the postgame flow EnterPostGameState(ePGS_FinalKillcam); } else { if (m_pGameRules->GetRoundsModule()) { EnterPostGameState(ePGS_Top3); } else { EnterPostGameState(ePGS_HudMessage); } } break; } case ePGS_HudMessage: { if (m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_HUDMessageTime) { EnterPostGameState(ePGS_FinalKillcam); } break; } case ePGS_FinalKillcam: { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (!pRecordingSystem || !(pRecordingSystem->IsPlayingBack() || (pRecordingSystem->IsPlaybackQueued() && pRecordingSystem->HasWinningKillcam()))) { EnterPostGameState(ePGS_Top3); } #ifndef _RELEASE else if(g_pGameCVars->g_hud_postgame_debug && pRecordingSystem) { CryWatch("PostGameState - Waiting for final killcam to end:"); CryWatch("IsPlaybackQueued: %s, IsPlayingBack: %s", pRecordingSystem->IsPlaybackQueued() ? "True" : "False", pRecordingSystem->IsPlayingBack() ? "True" : "False"); } #endif break; } case ePGS_HighlightReel: { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (!pRecordingSystem || (!pRecordingSystem->IsPlaybackQueued() && !pRecordingSystem->IsPlayingBack())) { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] Client trying to return to lobby"); pGameLobby->SvFinishedGame(frameTime); EnterPostGameState(ePGS_LeavingGame); } } #ifndef _RELEASE else if(g_pGameCVars->g_hud_postgame_debug && pRecordingSystem) { CryWatch("PostGameState - Waiting for highlight reel to end:"); CryWatch("IsPlaybackQueued: %s, IsPlayingBack: %s, IsPlayingHighlightsReel: %s", pRecordingSystem->IsPlaybackQueued() ? "True" : "False", pRecordingSystem->IsPlayingBack() ? "True" : "False", pRecordingSystem->IsPlayingHighlightsReel() ? "True" : "False"); } #endif break; } case ePGS_Top3: { if (m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_Top3Time) { EnterPostGameState(ePGS_Scoreboard); } break; } case ePGS_Scoreboard: { if(m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_ScoreboardTime) { if(!m_bHasShownHighlightReel && g_pGameCVars->kc_showHighlightsAtEndOfGame) { EnterPostGameState(ePGS_HighlightReel); } else { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] Client trying to return to lobby [No highlight reel]"); pGameLobby->SvFinishedGame(frameTime); } } } break; } } } } }
//------------------------------------------------------------------------- void CGameRulesStandardState::ChangeState( EGR_GameState newState ) { if (gEnv->bServer) { if (newState == EGRS_InGame) { CCCPOINT(GameRulesStandardState_EnterInGame); #if !defined(_RELEASE) || defined(PERFORMANCE_BUILD) if (m_state != EGRS_InGame) { if (g_pGameCVars->g_gameRules_startCmd[0] != '\0') { gEnv->pConsole->ExecuteString(g_pGameCVars->g_gameRules_startCmd, false, true); } } #endif // #if !defined(_RELEASE) || defined(PERFORMANCE_BUILD) m_pGameRules->ResetGameTime(); IGameRulesStatsRecording *st=m_pGameRules->GetStatsRecordingModule(); if (st) { st->OnInGameBegin(); } } else if (newState == EGRS_PostGame) { m_timeInPostGame = 0.0f; IGameRulesStatsRecording *st=m_pGameRules->GetStatsRecordingModule(); if (st) { st->OnPostGameBegin(); } #if defined(DEDICATED_SERVER) if ( gEnv->bMultiplayer ) { // Stop cvar probes. CGameRules::TPlayers players; m_pGameRules->GetPlayers(players); const int numPlayers = players.size(); for (int i = 0; i < numPlayers; ++ i) { const EntityId playerId = players[i]; IActor * pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(playerId); if ( pActor ) { IGameObject * pGameObject = NULL; INetChannel * pNetChannel = NULL; IDefenceContext * pDefenceContext = NULL; if ( (pGameObject = pActor->GetGameObject()) ) { if ( (pNetChannel = pGameObject->GetNetChannel()) ) { if ( (pDefenceContext = pNetChannel->GetDefenceContext()) ) { pDefenceContext->EndCvarRequests(); } } } } } } #endif CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] GameFinished, telling clients"); pGameLobby->SvFinishedGame(0.0f); } } } const bool bIsClient = gEnv->IsClient(); if (bIsClient) { if (newState == EGRS_PostGame) { m_timeInPostGame = 0.0f; EnterPostGameState(ePGS_Starting); } else if (newState == EGRS_InGame) { CHUDEventDispatcher::CallEvent( SHUDEvent(eHUDEvent_OnGameStart) ); } else if (newState == EGRS_Reset) { m_introMessageShown = false; } ClientChangeStateFeedback(newState); } m_state = newState; OnStateEntered_NotifyListeners(); if (newState == EGRS_PostGame) { m_pGameRules->FreezeInput(true); g_pGame->GetUI()->ActivateDefaultState(); // must be after settings newState to pick endgame OnGameEnd_NotifyListeners(); } else if (newState == EGRS_InGame) { OnGameStart_NotifyListeners(); if (bIsClient && g_pGameCVars->g_gameRules_preGame_StartSpawnedFrozen) { g_pGameActions->FilterMPPreGameFreeze()->Enable(false); g_pGame->GetUI()->ActivateDefaultState(); // must be after settings newState } // Have to explicitly call the spawning module, can't use the listener since that would make the modules // dependent on the initialisation order - which comes from xml IGameRulesSpawningModule *pSpawningModule = m_pGameRules->GetSpawningModule(); if (pSpawningModule) { pSpawningModule->OnInGameBegin(); } } if (gEnv->bServer) { CHANGED_NETWORK_STATE(m_pGameRules, STANDARD_STATE_ASPECT); if (m_state == EGRS_InGame) { // Revive players - has to be done after setting m_state since we don't revive players in PreGame IGameRulesSpawningModule *pSpawningModule = m_pGameRules->GetSpawningModule(); if (pSpawningModule) { const bool bOnlyIfDead = (g_pGameCVars->g_gameRules_preGame_StartSpawnedFrozen!=0); pSpawningModule->ReviveAllPlayers(false, bOnlyIfDead); } } } }
//------------------------------------------------------------------------ bool CGameRules::OnPromoteToServer(SHostMigrationInfo& hostMigrationInfo, uint32& state) { if (!g_pGame->GetIGameFramework()->ShouldMigrateNub(hostMigrationInfo.m_session)) { return true; } CryLogAlways("[Host Migration]: CGameRules::OnPromoteToServer() started"); // Server time will change after we migrate (change from old server time to new server time) m_gameStartedTime.SetValue(m_gameStartedTime.GetValue() - m_cachedServerTime.GetValue()); m_gameStartTime.SetValue(m_gameStartTime.GetValue() - m_cachedServerTime.GetValue()); // If this migration has reset (we're not the original anticipated host, remove any entities from the first attempt if (!m_hostMigrationCachedEntities.empty()) { HostMigrationRemoveDuplicateDynamicEntities(); } // Now we know we're the server, remove the actors for anyone we know isn't going to migrate CGameLobby *pGameLobby = g_pGame->GetGameLobby(); CRY_ASSERT(pGameLobby); if (pGameLobby) { TPlayers playersToRemove; IActorSystem *pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); playersToRemove.reserve(pActorSystem->GetActorCount()); IActorIteratorPtr actorIt = pActorSystem->CreateActorIterator(); IActor *pActor; while (pActor = actorIt->Next()) { if (pActor->IsPlayer()) { CRY_ASSERT(pActor->GetChannelId()); SCryMatchMakingConnectionUID conId = pGameLobby->GetConnectionUIDFromChannelID((int) pActor->GetChannelId()); if (pGameLobby->GetSessionNames().Find(conId) == SSessionNames::k_unableToFind) { CryLog(" player '%s' has not got a corresponding CGameLobby entry, removing actor", pActor->GetEntity()->GetName()); playersToRemove.push_back(pActor->GetEntityId()); } } } const int numPlayersToRemove = playersToRemove.size(); for (int i = 0; i < numPlayersToRemove; ++ i) { FakeDisconnectPlayer(playersToRemove[i]); } } for (uint32 i = 0; i < MAX_PLAYERS; ++ i) { m_migratedPlayerChannels[i] = 0; } IItemSystem *pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem(); IEntityItPtr it = gEnv->pEntitySystem->GetEntityIterator(); it->MoveFirst(); for (uint32 i = 0; i < m_hostMigrationItemMaxCount; ++ i) { m_pHostMigrationItemInfo[i].Reset(); } uint32 itemIndex = 0; IEntity *pEntity = NULL; while (pEntity = it->Next()) { IItem *pItem = pItemSystem->GetItem(pEntity->GetId()); if (pItem) { if (pItem->GetOwnerId()) { IEntity *pOwner = gEnv->pEntitySystem->GetEntity(pItem->GetOwnerId()); if (pOwner) { EntityId currentItemId = 0; IActor *pOwnerActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pOwner->GetId()); if (pOwnerActor) { IItem *pCurrentItem = pOwnerActor->GetCurrentItem(); currentItemId = pCurrentItem ? pCurrentItem->GetEntityId() : 0; } CryLog("[CG] Item '%s' is owned by '%s'", pEntity->GetName(), pOwner->GetName()); //m_pHostMigrationItemInfo[itemIndex].Set(pEntity->GetId(), pOwner->GetId(), pItem->IsUsed(), (pItem->GetEntityId() == currentItemId)); itemIndex ++; if (itemIndex >= m_hostMigrationItemMaxCount) { CRY_ASSERT(itemIndex < m_hostMigrationItemMaxCount); break; } } } } // Tell entities that we're host migrating // - Currently only used by ForbiddenArea but may well be needed for other entities later // - Currently only called on the new server, add to OnDemoteToClient if we need to use this on a client IScriptTable *pScript = pEntity->GetScriptTable(); if (pScript != NULL && pScript->GetValueType("OnHostMigration") == svtFunction) { m_pScriptSystem->BeginCall(pScript, "OnHostMigration"); m_pScriptSystem->PushFuncParam(pScript); m_pScriptSystem->PushFuncParam(true); m_pScriptSystem->EndCall(); } } // This needs initialising on the new server otherwise the respawn timer will be counting down // from uninitialised data. Likewise for the pre-round timer. ResetReviveCycleTime(); const int numRespawnParams = m_respawndata.size(); for (int i = 0; i < numRespawnParams; ++ i) { SEntityRespawnData *pData = &m_respawndata[i]; pEntity = gEnv->pEntitySystem->GetEntity(pData->m_currentEntityId); if (pEntity == NULL) { CryLog(" detected respawn entity (id=%u) is not present, scheduling for respawn", pData->m_currentEntityId); ScheduleEntityRespawn(pData->m_currentEntityId, false, g_pGameCVars->g_defaultItemRespawnTimer); } } CryLog("[Host Migration]: CGameRules::OnPromoteToServer() finished"); CCCPOINT(HostMigration_OnPromoteToServer); return true; }