Files
o3de/Gems/GameLift/Code/Source/Session/GameLiftServerService.cpp
T
2021-03-08 14:30:57 -08:00

326 lines
12 KiB
C++

/*
* 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.
*
*/
#if defined(BUILD_GAMELIFT_SERVER)
#include <AzCore/Component/TickBus.h>
#include <AzCore/Memory/Memory.h>
#include <GameLift/Session/GameLiftServerSDKWrapper.h>
#include <GameLift/Session/GameLiftServerService.h>
#include <GameLift/Session/GameLiftServerSession.h>
namespace GridMate
{
GameLiftServerService::GameLiftServerService(const GameLiftServerServiceDesc& desc)
: SessionService(desc)
, m_serviceDesc(desc)
, m_serverStatus(GameLift_NotInited)
, m_serverInitOutcome(nullptr)
{
m_gameLiftServerSDKWrapper = AZStd::make_shared<GridMate::GameLiftServerSDKWrapper>();
}
GameLiftServerService::~GameLiftServerService()
{
m_gameLiftServerSDKWrapper.reset();
}
void GameLiftServerService::OnServiceRegistered(IGridMate* gridMate)
{
SessionService::OnServiceRegistered(gridMate);
GameLiftServerSession::RegisterReplicaChunks();
Internal::GameLiftServerSystemEventsBus::Handler::BusConnect();
if (!StartGameLiftServer())
{
EBUS_EVENT_ID(m_gridMate, GameLiftServerServiceEventsBus, OnGameLiftSessionServiceFailed, this);
}
GameLiftServerServiceBus::Handler::BusConnect(gridMate);
}
void GameLiftServerService::OnServiceUnregistered(IGridMate* gridMate)
{
GameLiftServerServiceBus::Handler::BusDisconnect();
Internal::GameLiftServerSystemEventsBus::Handler::BusDisconnect();
Internal::GameLiftServerSystemEventsBus::ClearQueuedEvents();
if (m_serverStatus == GameLift_Ready || m_serverStatus == GameLift_Terminated)
{
GetGameLiftServerSDKWrapper().lock()->ProcessEnding();
GetGameLiftServerSDKWrapper().lock()->Destroy();
m_serverStatus = GameLift_NotInited;
}
delete m_serverInitOutcome;
SessionService::OnServiceUnregistered(gridMate);
}
bool GameLiftServerService::StartGameLiftServer()
{
if (m_serverStatus == GameLift_NotInited)
{
Aws::GameLift::Server::InitSDKOutcome initOutcome = GetGameLiftServerSDKWrapper().lock()->InitSDK();
if (initOutcome.IsSuccess())
{
AZ_TracePrintf("GameLift", "InitSDK succeeded.\n");
AZ_Warning("GameLift", m_serviceDesc.m_port != 0, "Server will be listening on ephemeral port");
std::vector<std::string> logPaths;
for (const string& path : m_serviceDesc.m_logPaths)
{
logPaths.push_back(path.c_str());
}
Aws::GameLift::Server::ProcessParameters processParams(
/*
* onStartGameSession
* Invoked when we push a GameSession to the server
*/
[this](const Aws::GameLift::Server::Model::GameSession& gameSession) {
AZ_TracePrintf("GameLift", "On Activate...\n");
// This callback will be called on GameLift thread
EBUS_QUEUE_EVENT(Internal::GameLiftServerSystemEventsBus, OnGameLiftGameSessionStarted, gameSession);
},
/*
* onUpdateGameSession
* Invoked when the game session is updated after backfill
*/
[this](const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession) {
AZ_TracePrintf("GameLift", "On Update Game Session...\n");
EBUS_QUEUE_EVENT(Internal::GameLiftServerSystemEventsBus, OnGameLiftGameSessionUpdated, updateGameSession);
},
/*
* onProcessTerminate
* Invoked when GameLift wants to force kill the server
*/
[this]() {
AZ_TracePrintf("GameLift", "On Terminate invoked\n");
EBUS_QUEUE_EVENT(Internal::GameLiftServerSystemEventsBus, OnGameLiftServerWillTerminate);
},
/*
* onHealthCheck
* Invoked every minute to check on health. This callback must return a boolean.
*/
[]() {
return true;
},
/*
* port
* The port the server will be listening on
*/
m_serviceDesc.m_port,
/*
* logParameters
* A vector of log paths the servers will write to (and uploaded)
*/
Aws::GameLift::Server::LogParameters(logPaths)
);
m_serverInitOutcome = new Aws::GameLift::GenericOutcomeCallable(
GetGameLiftServerSDKWrapper().lock()->ProcessReadyAsync(processParams));
}
else
{
AZ_TracePrintf("GameLift", "InitSDK failed.\n");
m_serverStatus = GameLift_Failed;
}
}
return m_serverStatus != GameLift_Failed;
}
bool GameLiftServerService::IsReady() const
{
return m_serverStatus == GameLift_Ready;
}
void GameLiftServerService::OnGameLiftGameSessionStarted(const Aws::GameLift::Server::Model::GameSession& gameSession)
{
AZ_TracePrintf("GameLift", "Dispatching OnGameLiftGameSessionStarted...\n");
EBUS_EVENT_ID(m_gridMate, GameLiftServerServiceEventsBus, OnGameLiftGameSessionStarted, this, gameSession);
}
void GameLiftServerService::OnGameLiftGameSessionUpdated(const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession)
{
AZ_TracePrintf("GameLift", "Dispatching OnGameLiftGameSessionUpdated...\n");
UpdateGameSession(updateGameSession);
EBUS_EVENT_ID(m_gridMate, GameLiftServerServiceEventsBus, OnGameLiftGameSessionUpdated, this, updateGameSession);
}
void GameLiftServerService::OnGameLiftServerWillTerminate()
{
Internal::GameLiftServerSystemEventsBus::Handler::BusDisconnect();
Internal::GameLiftServerSystemEventsBus::ClearQueuedEvents(); // already terminating, don't need any other events
m_serverStatus = GameLift_Terminated;
EBUS_EVENT_ID(m_gridMate, GameLiftServerServiceEventsBus, OnGameLiftServerWillTerminate, this);
}
void GameLiftServerService::Update()
{
Internal::GameLiftServerSystemEventsBus::ExecuteQueuedEvents();
if (m_serverInitOutcome
&& m_serverInitOutcome->valid()
&& m_serverInitOutcome->wait_for(std::chrono::milliseconds(0)) == std::future_status::ready)
{
auto result = m_serverInitOutcome->get();
if (result.IsSuccess())
{
AZ_TracePrintf("GameLift", "Initialized GameLift server successfully.\n");
m_serverStatus = GameLift_Ready;
if (IsReady())
{
EBUS_EVENT_ID(m_gridMate, GameLiftServerServiceEventsBus, OnGameLiftSessionServiceReady, this);
EBUS_DBG_EVENT(Debug::SessionDrillerBus, OnSessionServiceReady);
EBUS_EVENT_ID(m_gridMate, SessionEventBus, OnSessionServiceReady);
}
}
else
{
AZ_TracePrintf("GameLift", "Failed to initialize GameLift server: %s, %s\n", result.GetError().GetErrorName().c_str(), result.GetError().GetErrorMessage().c_str());
m_serverStatus = GameLift_Failed;
// defer the notification so Gridmate doesn't destroy this service while updating
AZ::TickBus::QueueFunction([this]()
{
GameLiftServerServiceEventsBus::Event(m_gridMate, &GameLiftServerServiceEventsBus::Events::OnGameLiftSessionServiceFailed, this);
});
}
}
SessionService::Update();
}
GameLiftServerSession* GameLiftServerService::QueryGameLiftSession(const GridSession* session)
{
for (GridSession* s : m_sessions)
{
if (s == session)
{
return static_cast<GameLiftServerSession*>(s);
}
}
return nullptr;
}
GridSession* GameLiftServerService::HostSession(const GameLiftSessionParams& params, const CarrierDesc& carrierDesc)
{
AZ_TracePrintf("GameLift", "GameLiftSessionService::HostSession.\n");
if (m_serverStatus != GameLift_Ready)
{
AZ_TracePrintf("GameLift", "Server API is not initialized.\n");
return nullptr;
}
GameLiftServerSession* session = aznew GameLiftServerSession(this);
if (!session->Initialize(params, carrierDesc))
{
AZ_TracePrintf("GameLift", "GameLiftSessionService::HostSession. Could not initialize the session.\n");
delete session;
return nullptr;
}
AZ_TracePrintf("GameLift", "GameLiftSessionService::HostSession. Completed.\n");
return session;
}
void GameLiftServerService::ShutdownSession(const GridSession* gridSession)
{
GameLiftServerSession* session = FindGameLiftServerSession(gridSession->GetId());
if (session)
{
// Shutdown call removes the game session from server service.
session->Shutdown();
delete session;
}
else
{
AZ_TracePrintf("GameLift", "GameSession Failed to Shutdown. No GameLiftServerSession found for :%s", gridSession->GetId().c_str());
}
}
bool GameLiftServerService::StartMatchmakingBackfill(const GridSession* gridSession, AZStd::string& matchmakingTicketId, bool checkForAutoBackfill)
{
GameLiftServerSession* session = FindGameLiftServerSession(gridSession->GetId());
if (session)
{
return session->StartMatchmakingBackfill(matchmakingTicketId, checkForAutoBackfill);
}
else
{
AZ_TracePrintf("GameLift", "GameSession Failed to start backfill. No GameLiftServerSession found for :%s", gridSession->GetId().c_str());
return false;
}
}
bool GameLiftServerService::StopMatchmakingBackfill(const GridSession* gridSession, const AZStd::string& matchmakingTicketId)
{
GameLiftServerSession* session = FindGameLiftServerSession(gridSession->GetId());
if (session)
{
return session->StopMatchmakingBackfill(matchmakingTicketId);
}
else
{
AZ_TracePrintf("GameLift", "GameSession Failed to stop backfill. No GameLiftServerSession found for :%s", gridSession->GetId().c_str());
return false;
}
}
bool GameLiftServerService::UpdateGameSession(const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession)
{
AZStd::string gameSessionId = updateGameSession.GetGameSession().GetGameSessionId().c_str();
GameLiftServerSession* session = FindGameLiftServerSession(gameSessionId);
if (session)
{
return session->GameSessionUpdated(updateGameSession);
}
else
{
AZ_TracePrintf("GameLift", "GameSession Failed to update. No GameLiftServerSession found for :%s", gameSessionId.c_str());
return false;
}
}
AZStd::weak_ptr<GameLiftServerSDKWrapper> GameLiftServerService::GetGameLiftServerSDKWrapper()
{
return m_gameLiftServerSDKWrapper;
}
GameLiftServerSession* GameLiftServerService::FindGameLiftServerSession(const AZStd::string& id)
{
GridSession* gridSession = nullptr;
for (GridSession* session : m_sessions)
{
if (id.compare(session->GetId()) == 0)
{
gridSession = session;
break;
}
}
return static_cast<GameLiftServerSession*>(gridSession);
}
} // namespace GridMate
#endif // BUILD_GAMELIFT_SERVER