/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "Multiplayer_precompiled.h" #include #include #include #include #include #include #include #include #include #include #include "Multiplayer/IMultiplayerGem.h" #include "Multiplayer/MultiplayerLobbyServiceWrapper/MultiplayerLobbyLANServiceWrapper.h" #include "Source/Canvas/MultiplayerDedicatedHostTypeSelectionCanvas.h" #include "Source/Canvas/MultiplayerGameLiftLobbyCanvas.h" #include "Source/Canvas/MultiplayerLANGameLobbyCanvas.h" #include "Source/Canvas/MultiplayerBusyAndErrorCanvas.h" #include "Multiplayer/MultiplayerLobbyComponent.h" #include #include "Multiplayer/MultiplayerUtils.h" #include namespace Platform { bool ListServers(const AZStd::string& actionName, const AZ::EntityId& entityId, Multiplayer::MultiplayerLobbyServiceWrapper*& multiplayerLobbyServiceWrapper); } namespace Multiplayer { void MultiplayerLobbyComponent::Reflect(AZ::ReflectContext* reflectContext) { AZ::SerializeContext* serialize = azrtti_cast(reflectContext); if (serialize) { serialize->Class() ->Version(1) ->Field("MaxPlayers",&MultiplayerLobbyComponent::m_maxPlayers) ->Field("Port",&MultiplayerLobbyComponent::m_port) ->Field("EnableDisconnectDetection",&MultiplayerLobbyComponent::m_enableDisconnectDetection) ->Field("ConnectionTimeout",&MultiplayerLobbyComponent::m_connectionTimeoutMS) ->Field("DefaultMap",&MultiplayerLobbyComponent::m_defaultMap) ->Field("DefaultServer",&MultiplayerLobbyComponent::m_defaultServerName) ->Field("DefaultMatchmakingConfig",&MultiplayerLobbyComponent::m_defaultMatchmakingConfig) ; AZ::EditContext* editContext = serialize->GetEditContext(); if (editContext) { editContext->Class("Multiplayer Lobby Component","This component will load up and manage a simple lobby for connecting for LAN and GameLift sessions.") ->ClassElement(AZ::Edit::ClassElements::EditorData,"") ->Attribute(AZ::Edit::Attributes::Category,"MultiplayerSample") ->Attribute(AZ::Edit::Attributes::AutoExpand,true) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game")) ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_maxPlayers,"Max Players","The total number of players that can join in the game.") ->Attribute(AZ::Edit::Attributes::Min,0) ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_port,"Port","The port on which the game service will create connections through.") ->Attribute(AZ::Edit::Attributes::Min,1) ->Attribute(AZ::Edit::Attributes::Max,65534) ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_enableDisconnectDetection,"Enable Disconnect Detection","Enables disconnecting players if they do not respond within the Timeout window.") ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_connectionTimeoutMS,"Timeout","The length of time a client has to respond before being disconnected(if disconnection detection is enabled.") ->Attribute(AZ::Edit::Attributes::Suffix,"ms") ->Attribute(AZ::Edit::Attributes::Min,0) ->Attribute(AZ::Edit::Attributes::Max,60000) ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_defaultMap,"DefaultMap", "The default value that will be added to the map field when loading the lobby.") ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_defaultServerName,"DefaultServerName","The default value that will be added to the server name field when loading the lobby.") ->DataElement(AZ::Edit::UIHandlers::Default, &MultiplayerLobbyComponent::m_defaultMatchmakingConfig,"DefaultMatchmaking","The default value that will be used for matchmaking in the GameLift lobby.") ; } } } MultiplayerLobbyComponent::MultiplayerLobbyComponent() : m_maxPlayers(8) , m_port(SERVER_DEFAULT_PORT) , m_enableDisconnectDetection(true) , m_connectionTimeoutMS(500) , m_defaultMap("") , m_defaultServerName("MyServer") , m_defaultMatchmakingConfig("MyConfig") , m_unregisterGameliftServiceOnErrorDismiss(false) , m_hasGameliftSession(false) , m_lobbyMode(LobbyMode::Unknown) , m_listSearch(nullptr) , m_multiplayerLobbyServiceWrapper(nullptr) , m_gameliftCreationSearch(nullptr) { } MultiplayerLobbyComponent::~MultiplayerLobbyComponent() { } void MultiplayerLobbyComponent::Activate() { Multiplayer::MultiplayerLobbyBus::Handler::BusConnect(GetEntityId()); MultiplayerDedicatedHostTypeSelectionCanvasContext dedicatedHostTypeSelectionCanvasContext; dedicatedHostTypeSelectionCanvasContext.OnLANButtonClicked = std::bind(&MultiplayerLobbyComponent::SelectLANServerType, this); dedicatedHostTypeSelectionCanvasContext.OnGameLiftConnectButtonClicked = std::bind(&MultiplayerLobbyComponent::SelectGameLiftServerType, this); m_dedicatedHostTypeSelectionCanvas = aznew MultiplayerDedicatedHostTypeSelectionCanvas(dedicatedHostTypeSelectionCanvasContext); MultiplayerLANGameLobbyCanvasContext lanGameLobbyCanvasContext; lanGameLobbyCanvasContext.CreateServerViewContext.OnCreateServerButtonClicked = std::bind(&MultiplayerLobbyComponent::CreateServer, this); lanGameLobbyCanvasContext.OnReturnButtonClicked = std::bind(&MultiplayerLobbyComponent::ShowSelectionLobby, this); lanGameLobbyCanvasContext.JoinServerViewContext.OnJoinButtonClicked = std::bind(&MultiplayerLobbyComponent::JoinServer, this); lanGameLobbyCanvasContext.JoinServerViewContext.OnRefreshButtonClicked = std::bind(&MultiplayerLobbyComponent::ListServers, this); lanGameLobbyCanvasContext.CreateServerViewContext.DefaultMapName = m_defaultMap; lanGameLobbyCanvasContext.CreateServerViewContext.DefaultServerName = m_defaultServerName; m_lanGameLobbyCanvas = aznew MultiplayerLANGameLobbyCanvas(lanGameLobbyCanvasContext); m_lanGameLobbyCanvas->Hide(); MultiplayerGameLiftLobbyCanvasContext gameLiftLobbyCanvasContext; gameLiftLobbyCanvasContext.CreateServerViewContext.OnCreateServerButtonClicked = std::bind(&MultiplayerLobbyComponent::CreateServer, this); gameLiftLobbyCanvasContext.OnReturnButtonClicked = std::bind(&MultiplayerLobbyComponent::ShowSelectionLobby, this); gameLiftLobbyCanvasContext.JoinServerViewContext.OnJoinButtonClicked = std::bind(&MultiplayerLobbyComponent::JoinServer, this); gameLiftLobbyCanvasContext.JoinServerViewContext.OnRefreshButtonClicked = std::bind(&MultiplayerLobbyComponent::ListServers, this); #if defined(BUILD_GAMELIFT_CLIENT) gameLiftLobbyCanvasContext.GameLiftFlexMatchViewContext.OnStartMatchmakingButtonClicked = std::bind(&MultiplayerLobbyComponent::StartGameLiftMatchmaking, this); #endif gameLiftLobbyCanvasContext.CreateServerViewContext.DefaultMapName = m_defaultMap; gameLiftLobbyCanvasContext.CreateServerViewContext.DefaultServerName = m_defaultServerName; gameLiftLobbyCanvasContext.GameLiftFlexMatchViewContext.DefaultMatchmakingConfig = m_defaultMatchmakingConfig; m_gameLiftLobbyCanvas = aznew MultiplayerGameLiftLobbyCanvas(gameLiftLobbyCanvasContext); m_gameLiftLobbyCanvas->Hide(); MultiplayerBusyAndErrorCanvasContext busyAndErrorCanvasContext; busyAndErrorCanvasContext.OnDismissErrroWindowButtonClicked = std::bind(&MultiplayerLobbyComponent::DismissError, this, false); m_busyAndErrorCanvas = aznew MultiplayerBusyAndErrorCanvas(busyAndErrorCanvasContext); ShowSelectionLobby(); UiCursorBus::Broadcast(&UiCursorInterface::IncrementVisibleCounter); if (gEnv->pNetwork) { GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); if (gridMate) { GridMate::SessionEventBus::Handler::BusConnect(gridMate); } } AZ_TRAIT_MULTIPLAYER_LOBBY_SERVICE_ASSIGN_DEFAULT_PORT(AZ_TRAIT_MULTIPLAYER_LOBBY_SERVICE_ASSIGN_DEFAULT_PORT_VALUE); } void MultiplayerLobbyComponent::Deactivate() { GridMate::SessionEventBus::Handler::BusDisconnect(); delete m_dedicatedHostTypeSelectionCanvas; m_dedicatedHostTypeSelectionCanvas = nullptr; delete m_lanGameLobbyCanvas; m_lanGameLobbyCanvas = nullptr; delete m_gameLiftLobbyCanvas; m_gameLiftLobbyCanvas = nullptr; UiCursorBus::Broadcast(&UiCursorInterface::DecrementVisibleCounter); ClearSearches(); delete m_multiplayerLobbyServiceWrapper; m_multiplayerLobbyServiceWrapper = nullptr; } void MultiplayerLobbyComponent::SelectLANServerType() { if (m_multiplayerLobbyServiceWrapper) { delete m_multiplayerLobbyServiceWrapper; } m_multiplayerLobbyServiceWrapper = aznew MultiplayerLobbyLANServiceWrapper(GetEntityId()); ShowLobby(LobbyMode::ServiceWrapperLobby); } void MultiplayerLobbyComponent::SelectGameLiftServerType() { #if defined(BUILD_GAMELIFT_CLIENT) ShowLobby(LobbyMode::GameliftLobby); #else AZ_Assert(false, "Trying to use GameLift on unsupported Platform."); #endif } void MultiplayerLobbyComponent::OnSessionCreated(GridMate::GridSession* session) { GridMate::GridSession* gridSession = nullptr; EBUS_EVENT_RESULT(gridSession,Multiplayer::MultiplayerRequestBus,GetSession); if (gridSession == session && session->IsHost()) { Multiplayer::Utils::SynchronizeSessionState(session); } } void MultiplayerLobbyComponent::OnSessionError(GridMate::GridSession* session,const GridMate::string& errorMsg) { ShowError(errorMsg.c_str()); } void MultiplayerLobbyComponent::OnGridSearchComplete(GridMate::GridSearch* search) { if (search == m_gameliftCreationSearch) { DismissBusyScreen(); GridMate::Network* network = static_cast(gEnv->pNetwork); if (network) { if (search->GetNumResults() == 0) { ShowError("Error creating GameLift Session"); } else { const GridMate::SearchInfo* searchInfo = m_gameliftCreationSearch->GetResult(0); JoinSession(searchInfo); } } m_gameliftCreationSearch->Release(); m_gameliftCreationSearch = nullptr; } else if (search == m_listSearch) { if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { m_lanGameLobbyCanvas->DisplaySearchResults(m_listSearch); } else if(m_lobbyMode == LobbyMode::GameliftLobby) { m_gameLiftLobbyCanvas->DisplaySearchResults(m_listSearch); } DismissBusyScreen(); } } int MultiplayerLobbyComponent::GetGamePort() const { return m_port; } void MultiplayerLobbyComponent::ConfigureSessionParams(GridMate::SessionParams& sessionParams) { sessionParams.m_topology = GridMate::ST_CLIENT_SERVER; sessionParams.m_numPublicSlots = m_maxPlayers + (gEnv->IsDedicated() ? 1 : 0); // One slot for server member. sessionParams.m_numPrivateSlots = 0; sessionParams.m_peerToPeerTimeout = 60000; sessionParams.m_flags = 0; sessionParams.m_numParams = 0; sessionParams.m_params[sessionParams.m_numParams].m_id = "sv_name"; sessionParams.m_params[sessionParams.m_numParams].SetValue(GetServerName().c_str()); sessionParams.m_numParams++; sessionParams.m_params[sessionParams.m_numParams].m_id = "sv_map"; sessionParams.m_params[sessionParams.m_numParams].SetValue(GetMapName().c_str()); sessionParams.m_numParams++; } void MultiplayerLobbyComponent::ShowSelectionLobby() { const bool forceHide = true; if (m_lobbyMode != LobbyMode::LobbySelection) { ClearSearches(); StopSessionService(); if (m_multiplayerLobbyServiceWrapper) { delete m_multiplayerLobbyServiceWrapper; m_multiplayerLobbyServiceWrapper = nullptr; } HideLobby(); m_lobbyMode = LobbyMode::LobbySelection; m_dedicatedHostTypeSelectionCanvas->Show(); DismissError(forceHide); DismissBusyScreen(forceHide); } } void MultiplayerLobbyComponent::ShowLobby(LobbyMode lobbyMode) { if (lobbyMode == LobbyMode::LobbySelection) { ShowSelectionLobby(); } else if (m_lobbyMode == LobbyMode::LobbySelection) { bool showLobby = StartSessionService(lobbyMode); if (showLobby) { HideLobby(); m_lobbyMode = lobbyMode; if (lobbyMode == LobbyMode::ServiceWrapperLobby) { m_lanGameLobbyCanvas->ClearSearchResults(); m_lanGameLobbyCanvas->Show(); } else if (lobbyMode == LobbyMode::GameliftLobby) { m_gameLiftLobbyCanvas->ClearSearchResults(); m_gameLiftLobbyCanvas->Show(); } const bool forceHide = true; DismissError(forceHide); DismissBusyScreen(forceHide); } } } void MultiplayerLobbyComponent::HideLobby() { switch (m_lobbyMode) { case LobbyMode::ServiceWrapperLobby: m_lanGameLobbyCanvas->Hide(); break; case LobbyMode::GameliftLobby: m_gameLiftLobbyCanvas->Hide(); break; case LobbyMode::LobbySelection: m_dedicatedHostTypeSelectionCanvas->Hide(); break; default: break; } m_lobbyMode = LobbyMode::Unknown; } bool MultiplayerLobbyComponent::StartSessionService(LobbyMode lobbyMode) { bool startedService = false; if (lobbyMode == LobbyMode::ServiceWrapperLobby) { if (gEnv->pNetwork && gEnv->pNetwork->GetGridMate()) { if (SanityCheckWrappedSessionService()) { startedService = m_multiplayerLobbyServiceWrapper->StartSessionService(gEnv->pNetwork->GetGridMate()); } } } else if (lobbyMode == LobbyMode::GameliftLobby) { #if defined(BUILD_GAMELIFT_CLIENT) startedService = StartGameLiftSession(); #else startedService = false; #endif } return startedService; } void MultiplayerLobbyComponent::StopSessionService() { // Stop whatever session we may have been using, if any if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { if (gEnv->pNetwork && gEnv->pNetwork->GetGridMate()) { if (SanityCheckWrappedSessionService()) { m_multiplayerLobbyServiceWrapper->StopSessionService(gEnv->pNetwork->GetGridMate()); } } } else if (m_lobbyMode == LobbyMode::GameliftLobby) { #if defined(BUILD_GAMELIFT_CLIENT) StopGameLiftSession(); m_hasGameliftSession = false; #else AZ_Assert(false,"Trying to use Gamelift on Unsupported platform."); #endif } } void MultiplayerLobbyComponent::CreateServer() { if (m_lobbyMode == LobbyMode::LobbySelection) { return; } else if (SanityCheck()) { if (GetMapName().empty()) { ShowError("Invalid Map Name"); } else if (GetServerName().empty()) { ShowError("Invalid Server Name"); } else { bool netSecEnabled = false; EBUS_EVENT_RESULT(netSecEnabled, Multiplayer::MultiplayerRequestBus,IsNetSecEnabled); if (netSecEnabled) { if (!NetSec::CanCreateSecureSocketForHosting()) { ShowError("Invalid Secure Socket configuration given for hosting a session.\nEnsure that a Public and Private key are being supplied."); return; } } if (m_lobbyMode == LobbyMode::GameliftLobby) { #if defined(BUILD_GAMELIFT_CLIENT) if (SanityCheckGameLift()) { CreateServerForGameLift(); } #else AZ_Assert(false,"Trying to use Gamelift on unsupported platform."); #endif } else if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { if (SanityCheckWrappedSessionService()) { CreateServerForWrappedService(); } } } } } void MultiplayerLobbyComponent::ListServers() { if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { m_lanGameLobbyCanvas->ClearSearchResults(); } else if (m_lobbyMode == LobbyMode::GameliftLobby) { m_gameLiftLobbyCanvas->ClearSearchResults(); } if (m_lobbyMode == LobbyMode::GameliftLobby) { #if defined(BUILD_GAMELIFT_CLIENT) if (SanityCheckGameLift()) { ListServersForGameLift(); } #else AZ_Assert(false,"Trying to use Gamelift lobby on unsupported platform.") #endif } else if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { ListServersForWrappedService(); } } void MultiplayerLobbyComponent::ClearSearches() { if (m_listSearch) { if (!m_listSearch->IsDone()) { m_listSearch->AbortSearch(); } m_listSearch->Release(); m_listSearch = nullptr; } if (m_gameliftCreationSearch) { if (!m_gameliftCreationSearch->IsDone()) { m_gameliftCreationSearch->AbortSearch(); } m_gameliftCreationSearch->Release(); m_gameliftCreationSearch = nullptr; } } void MultiplayerLobbyComponent::JoinServer() { if (m_lobbyMode == LobbyMode::LobbySelection) { return; } int selectedServerResult = -1; if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { selectedServerResult = m_lanGameLobbyCanvas->GetSelectedServerResult(); } else if (m_lobbyMode == LobbyMode::GameliftLobby) { selectedServerResult = m_gameLiftLobbyCanvas->GetSelectedServerResult(); } if ( m_listSearch == nullptr || !m_listSearch->IsDone() || selectedServerResult < 0 || m_listSearch->GetNumResults() <= selectedServerResult) { ShowError("No Server Selected to Join."); return; } const GridMate::SearchInfo* searchInfo = m_listSearch->GetResult(selectedServerResult); if (!SanityCheck()) { return; } else if (searchInfo == nullptr) { ShowError("Invalid Server Selection."); return; } else { bool netSecEnabled = false; EBUS_EVENT_RESULT(netSecEnabled, Multiplayer::MultiplayerRequestBus,IsNetSecEnabled); if (netSecEnabled) { if (!NetSec::CanCreateSecureSocketForJoining()) { ShowError("Invalid Secure Socket configuration given for joining an encrypted session.\nEnsure that a Certificate Authority is being supplied."); return; } } if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { if (!SanityCheckWrappedSessionService()) { return; } } else if (m_lobbyMode == LobbyMode::GameliftLobby) { #if defined(BUILD_GAMELIFT_CLIENT) if (!SanityCheckGameLift()) { return; } #else AZ_Assert(false,"Trying to use Gamelift lobby on unsupported platform.") return; #endif } } ShowBusyScreen(); if (!JoinSession(searchInfo)) { ShowError("Found a game session, but failed to join."); } } bool MultiplayerLobbyComponent::JoinSession(const GridMate::SearchInfo* searchInfo) { GridMate::GridSession* session = nullptr; GridMate::CarrierDesc carrierDesc; Multiplayer::Utils::InitCarrierDesc(carrierDesc); Multiplayer::NetSec::ConfigureCarrierDescForJoin(carrierDesc); GridMate::JoinParams joinParams; if (m_lobbyMode == LobbyMode::ServiceWrapperLobby) { if (SanityCheckWrappedSessionService()) { session = m_multiplayerLobbyServiceWrapper->JoinSession(gEnv->pNetwork->GetGridMate(),carrierDesc,searchInfo); } } else if (m_lobbyMode == LobbyMode::GameliftLobby) { #if defined(BUILD_GAMELIFT_CLIENT) const GridMate::GameLiftSearchInfo& gameliftSearchInfo = static_cast(*searchInfo); EBUS_EVENT_ID_RESULT(session, gEnv->pNetwork->GetGridMate(), GridMate::GameLiftClientServiceBus, JoinSessionBySearchInfo, gameliftSearchInfo, carrierDesc); #endif } if (session != nullptr) { EBUS_EVENT(Multiplayer::MultiplayerRequestBus,RegisterSession,session); } else { Multiplayer::NetSec::OnSessionFailedToCreate(carrierDesc); } return session != nullptr; } bool MultiplayerLobbyComponent::SanityCheck() { if (gEnv->IsEditor()) { ShowError("Unsupported action inside of Editor."); return false; } else if (gEnv->pNetwork == nullptr) { ShowError("Network Environment is null"); return false; } else { GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); if (gridMate == nullptr) { ShowError("GridMate is null."); return false; } } return true; } bool MultiplayerLobbyComponent::SanityCheckWrappedSessionService() { return m_multiplayerLobbyServiceWrapper != nullptr; } void MultiplayerLobbyComponent::CreateServerForWrappedService() { GridMate::GridSession* gridSession = nullptr; EBUS_EVENT_RESULT(gridSession,Multiplayer::MultiplayerRequestBus,GetSession); GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); if (!gridSession && SanityCheckWrappedSessionService()) { GridMate::CarrierDesc carrierDesc; Multiplayer::Utils::InitCarrierDesc(carrierDesc); Multiplayer::NetSec::ConfigureCarrierDescForHost(carrierDesc); carrierDesc.m_port = m_port; carrierDesc.m_enableDisconnectDetection = m_enableDisconnectDetection; carrierDesc.m_connectionTimeoutMS = m_connectionTimeoutMS; carrierDesc.m_threadUpdateTimeMS = 30; ShowBusyScreen(); GridMate::GridSession* session = m_multiplayerLobbyServiceWrapper->CreateServer(gridMate,carrierDesc); if (session == nullptr) { Multiplayer::NetSec::OnSessionFailedToCreate(carrierDesc); ShowError("Error while hosting Session."); } else { EBUS_EVENT(Multiplayer::MultiplayerRequestBus,RegisterSession,session); } } else { ShowError("Invalid Gem Session"); } } void MultiplayerLobbyComponent::ListServersForWrappedService() { GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); if (gridMate && SanityCheck() && SanityCheckWrappedSessionService()) { ShowBusyScreen(); if (m_listSearch) { m_listSearch->AbortSearch(); m_listSearch->Release(); m_listSearch = nullptr; } m_listSearch = m_multiplayerLobbyServiceWrapper->ListServers(gridMate); if (m_listSearch == nullptr) { ShowError("ListServers failed to start a GridSearch."); } } else { ShowError("Missing Online Service."); } } bool MultiplayerLobbyComponent::SanityCheckGameLift() { #if defined(BUILD_GAMELIFT_CLIENT) if (!ValidateGameLiftConfig()) { return false; } GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); // This should already be errored by the previous sanity check. if (gridMate == nullptr) { return false; } else if (!GridMate::HasGridMateService(gridMate)) { ShowError("MultiplayerService is missing."); return false; } return true; #else return false; #endif } bool MultiplayerLobbyComponent::ValidateGameLiftConfig() { const AZStd::string fleetId = GetConsoleVarValue("gamelift_fleet_id"); const AZStd::string aliasId = GetConsoleVarValue("gamelift_alias_id"); const AZStd::string queueName = GetConsoleVarValue("gamelift_queue_name"); //Validation on inputs. //Service still supports the use of developers credentials on top of the player credentials. if (fleetId.empty() && aliasId.empty() && queueName.empty()) { AZ_TracePrintf("GameLift", "You need to provide at least [gamelift_aliasid, gamelift_aws_access_key, gamelift_aws_secret_key] or [gamelift_fleetid, gamelift_aws_access_key, gamelift_aws_secret_key] or [gamelift_queue_name, gamelift_aws_access_key, gamelift_aws_secret_key]\n"); return false; } if (!fleetId.empty()) { if (!aliasId.empty() || !queueName.empty()) { AZ_TracePrintf("GameLift", "Initialize failed. Cannot use fleet id with aliasId/queueName.\n"); return false; } } if (!aliasId.empty()) { if (!fleetId.empty() || !queueName.empty()) { AZ_TracePrintf("GameLift", "Initialize failed. Cannot use alias id with fleetId/queueName.\n"); return false; } } //If the using queues. if (!queueName.empty()) { if (!fleetId.empty() || !aliasId.empty()) { AZ_TracePrintf("GameLift", "Initialize failed. Cannot use queue name with fleetId/aliasId.\n"); return false; } } return true; } #if defined(BUILD_GAMELIFT_CLIENT) bool MultiplayerLobbyComponent::StartGameLiftSession() { GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); // Not sure what happens if we start this once and it fails to be created... // calling it again causes an assert. if (gridMate && !m_hasGameliftSession) { ShowBusyScreen(); GridMate::GameLiftClientServiceEventsBus::Handler::BusConnect(gridMate); GridMate::GameLiftClientServiceDesc serviceDesc; serviceDesc.m_accessKey = GetConsoleVarValue("gamelift_aws_access_key"); serviceDesc.m_secretKey = GetConsoleVarValue("gamelift_aws_secret_key"); serviceDesc.m_endpoint = GetConsoleVarValue("gamelift_endpoint"); serviceDesc.m_region = GetConsoleVarValue("gamelift_aws_region"); serviceDesc.m_playerId = GetConsoleVarValue("gamelift_player_id"); serviceDesc.m_useGameLiftLocalServer = GetGetConsoleVarBoolValue("gamelift_uselocalserver"); EBUS_EVENT(GameLift::GameLiftRequestBus, StartClientService, serviceDesc); } return m_hasGameliftSession; } void MultiplayerLobbyComponent::StopGameLiftSession() { EBUS_EVENT(GameLift::GameLiftRequestBus, StopClientService); } void MultiplayerLobbyComponent::StartGameLiftMatchmaking() { GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); if (m_gameliftCreationSearch) { m_gameliftCreationSearch->AbortSearch(); m_gameliftCreationSearch->Release(); m_gameliftCreationSearch = nullptr; } ShowBusyScreen(); EBUS_EVENT_ID_RESULT(m_gameliftCreationSearch, gridMate, GridMate::GameLiftClientServiceBus, StartMatchmaking, GetConsoleVarValue("gamelift_matchmaking_config_name")); } void MultiplayerLobbyComponent::CreateServerForGameLift() { GridMate::IGridMate* gridMate = gEnv->pNetwork->GetGridMate(); if (m_gameliftCreationSearch) { m_gameliftCreationSearch->AbortSearch(); m_gameliftCreationSearch->Release(); m_gameliftCreationSearch = nullptr; } GridMate::GameLiftSessionRequestParams reqParams; ConfigureSessionParams(reqParams); reqParams.m_instanceName = m_gameLiftLobbyCanvas->GetServerName().c_str(); reqParams.m_fleetId = GetConsoleVarValue("gamelift_fleet_id"); reqParams.m_queueName = GetConsoleVarValue("gamelift_queue_name"); reqParams.m_aliasId = GetConsoleVarValue("gamelift_alias_id"); reqParams.m_useFleetId = !reqParams.m_fleetId.empty(); ShowBusyScreen(); EBUS_EVENT_ID_RESULT(m_gameliftCreationSearch, gridMate, GridMate::GameLiftClientServiceBus, RequestSession, reqParams); if (m_gameliftCreationSearch == nullptr) { ShowError("Failed to create Server for GameLift"); } } void MultiplayerLobbyComponent::ListServersForGameLift() { ShowBusyScreen(); GridMate::Network* network = static_cast(gEnv->pNetwork); GridMate::IGridMate* gridMate = network->GetGridMate(); if (m_listSearch) { m_listSearch->AbortSearch(); m_listSearch->Release(); m_listSearch = nullptr; } GridMate::GameLiftSearchParams searchParams; searchParams.m_fleetId = GetConsoleVarValue("gamelift_fleet_id"); searchParams.m_queueName = GetConsoleVarValue("gamelift_queue_name"); searchParams.m_aliasId = GetConsoleVarValue("gamelift_alias_id"); searchParams.m_useFleetId = !searchParams.m_fleetId.empty(); EBUS_EVENT_ID_RESULT(m_listSearch,gridMate,GridMate::GameLiftClientServiceBus, StartSearch, searchParams); if (m_listSearch == nullptr) { ShowError("Failed to start a GridSearch"); } } void MultiplayerLobbyComponent::OnGameLiftSessionServiceReady(GridMate::GameLiftClientService* service) { AZ_UNUSED(service); DismissBusyScreen(); m_hasGameliftSession = true; ShowLobby(LobbyMode::GameliftLobby); } void MultiplayerLobbyComponent::OnGameLiftSessionServiceFailed(GridMate::GameLiftClientService* service, const AZStd::string& message) { AZ_UNUSED(service); DismissBusyScreen(); m_hasGameliftSession = false; m_unregisterGameliftServiceOnErrorDismiss = true; AZStd::string errorMessage("GameLift Error: "); errorMessage += message; ShowError(errorMessage.c_str()); } #endif void MultiplayerLobbyComponent::ShowError(const char* error) { m_busyAndErrorCanvas->ShowError(error); } void MultiplayerLobbyComponent::DismissError(bool force) { m_busyAndErrorCanvas->DismissError(); if (m_unregisterGameliftServiceOnErrorDismiss) { m_unregisterGameliftServiceOnErrorDismiss = false; #if defined(BUILD_GAMELIFT_CLIENT) StopGameLiftSession(); #endif } } void MultiplayerLobbyComponent::ShowBusyScreen() { m_busyAndErrorCanvas->ShowBusyScreen(); } void MultiplayerLobbyComponent::DismissBusyScreen(bool force) { m_busyAndErrorCanvas->DismissBusyScreen(force); } LyShine::StringType MultiplayerLobbyComponent::GetMapName() const { switch (m_lobbyMode) { case LobbyMode::ServiceWrapperLobby: return m_lanGameLobbyCanvas->GetMapName(); case LobbyMode::GameliftLobby: return m_gameLiftLobbyCanvas->GetMapName(); default: return ""; } } LyShine::StringType MultiplayerLobbyComponent::GetServerName() const { switch (m_lobbyMode) { case LobbyMode::ServiceWrapperLobby: return m_lanGameLobbyCanvas->GetServerName(); case LobbyMode::GameliftLobby: return m_gameLiftLobbyCanvas->GetServerName(); default: return ""; } } }