Add GameLift matchmaking backfill server support (#4622)
* Add GameLift matchmaking backfill server support Signed-off-by: onecent1101 <liug@amazon.com>
This commit is contained in:
@@ -22,6 +22,7 @@ namespace AzFramework
|
||||
->Field("terminationTime", &SessionConfig::m_terminationTime)
|
||||
->Field("creatorId", &SessionConfig::m_creatorId)
|
||||
->Field("sessionProperties", &SessionConfig::m_sessionProperties)
|
||||
->Field("matchmakingData", &SessionConfig::m_matchmakingData)
|
||||
->Field("sessionId", &SessionConfig::m_sessionId)
|
||||
->Field("sessionName", &SessionConfig::m_sessionName)
|
||||
->Field("dnsName", &SessionConfig::m_dnsName)
|
||||
@@ -46,6 +47,8 @@ namespace AzFramework
|
||||
"CreatorId", "A unique identifier for a player or entity creating the session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionProperties,
|
||||
"SessionProperties", "A collection of custom properties for a session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_matchmakingData,
|
||||
"MatchmakingData", "The matchmaking process information that was used to create the session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionId,
|
||||
"SessionId", "A unique identifier for the session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionName,
|
||||
|
||||
@@ -35,6 +35,9 @@ namespace AzFramework
|
||||
|
||||
// A collection of custom properties for a session.
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
|
||||
|
||||
// The matchmaking process information that was used to create the session.
|
||||
AZStd::string m_matchmakingData;
|
||||
|
||||
// A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
@@ -41,6 +41,11 @@ namespace AzFramework
|
||||
// OnDestroySessionBegin is fired at the beginning of session termination
|
||||
// @return The result of all OnDestroySessionBegin notifications
|
||||
virtual bool OnDestroySessionBegin() = 0;
|
||||
|
||||
// OnUpdateSessionBegin is fired at the beginning of session update
|
||||
// @param sessionConfig The properties to describe a session
|
||||
// @param updateReason The reason for session update
|
||||
virtual void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) = 0;
|
||||
};
|
||||
using SessionNotificationBus = AZ::EBus<SessionNotifications>;
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -15,10 +15,11 @@ ly_add_target(
|
||||
awsgamelift_client_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
../AWSGameLiftCommon/Include
|
||||
Include
|
||||
PRIVATE
|
||||
Source
|
||||
../AWSGameLiftCommon/Source
|
||||
Source
|
||||
COMPILE_DEFINITIONS
|
||||
PRIVATE
|
||||
${awsgameliftclient_compile_definition}
|
||||
@@ -78,10 +79,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
awsgamelift_client_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
../AWSGameLiftCommon/Include
|
||||
../AWSGameLiftCommon/Source
|
||||
Include
|
||||
Tests
|
||||
Source
|
||||
../AWSGameLiftCommon/Source
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzCore
|
||||
|
||||
+3
-27
@@ -10,36 +10,12 @@
|
||||
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#include <AzFramework/Matchmaking/MatchmakingRequests.h>
|
||||
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
|
||||
namespace AWSGameLift
|
||||
{
|
||||
//! AWSGameLiftPlayerInformation
|
||||
//! Information on each player to be matched
|
||||
//! This information must include a player ID, and may contain player attributes and latency data to be used in the matchmaking process
|
||||
//! After a successful match, Player objects contain the name of the team the player is assigned to
|
||||
struct AWSGameLiftPlayerInformation
|
||||
{
|
||||
AZ_RTTI(AWSGameLiftPlayerInformation, "{B62C118E-C55D-4903-8ECB-E58E8CA613C4}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AWSGameLiftPlayerInformation() = default;
|
||||
virtual ~AWSGameLiftPlayerInformation() = default;
|
||||
|
||||
// A map of region names to latencies in millseconds, that indicates
|
||||
// the amount of latency that a player experiences when connected to AWS Regions
|
||||
AZStd::unordered_map<AZStd::string, int> m_latencyInMs;
|
||||
// A collection of key:value pairs containing player information for use in matchmaking
|
||||
// Player attribute keys must match the playerAttributes used in a matchmaking rule set
|
||||
// Example: {"skill": "{\"N\": \"23\"}", "gameMode": "{\"S\": \"deathmatch\"}"}
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_playerAttributes;
|
||||
// A unique identifier for a player
|
||||
AZStd::string m_playerId;
|
||||
// Name of the team that the player is assigned to in a match
|
||||
AZStd::string m_team;
|
||||
};
|
||||
|
||||
//! AWSGameLiftStartMatchmakingRequest
|
||||
//! GameLift start matchmaking request which corresponds to Amazon GameLift
|
||||
//! Uses FlexMatch to create a game match for a group of players based on custom matchmaking rules
|
||||
@@ -57,6 +33,6 @@ namespace AWSGameLift
|
||||
// Name of the matchmaking configuration to use for this request
|
||||
AZStd::string m_configurationName;
|
||||
// Information on each player to be matched
|
||||
AZStd::vector<AWSGameLiftPlayerInformation> m_players;
|
||||
AZStd::vector<AWSGameLiftPlayer> m_players;
|
||||
};
|
||||
} // namespace AWSGameLift
|
||||
|
||||
@@ -210,6 +210,7 @@ namespace AWSGameLift
|
||||
->Property("SessionId", BehaviorValueProperty(&AzFramework::SessionConfig::m_sessionId))
|
||||
->Property("SessionName", BehaviorValueProperty(&AzFramework::SessionConfig::m_sessionName))
|
||||
->Property("SessionProperties", BehaviorValueProperty(&AzFramework::SessionConfig::m_sessionProperties))
|
||||
->Property("MatchmakingData", BehaviorValueProperty(&AzFramework::SessionConfig::m_matchmakingData))
|
||||
->Property("Status", BehaviorValueProperty(&AzFramework::SessionConfig::m_status))
|
||||
->Property("StatusReason", BehaviorValueProperty(&AzFramework::SessionConfig::m_statusReason))
|
||||
->Property("TerminationTime", BehaviorValueProperty(&AzFramework::SessionConfig::m_terminationTime))
|
||||
|
||||
+1
@@ -105,6 +105,7 @@ namespace AWSGameLift
|
||||
session.m_status = AWSGameLiftSessionStatusNames[(int)gameSession.GetStatus()];
|
||||
session.m_statusReason = AWSGameLiftSessionStatusReasons[(int)gameSession.GetStatusReason()];
|
||||
session.m_terminationTime = gameSession.GetTerminationTime().Millis();
|
||||
session.m_matchmakingData = gameSession.GetMatchmakerData().c_str();
|
||||
// TODO: Update the AWS Native SDK to get the new game session attributes.
|
||||
//session.m_dnsName = gameSession.GetDnsName();
|
||||
|
||||
|
||||
+3
-2
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <Activity/AWSGameLiftActivityUtils.h>
|
||||
#include <Activity/AWSGameLiftStartMatchmakingActivity.h>
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
#include <AWSGameLiftSessionConstants.h>
|
||||
|
||||
#include <aws/core/utils/Outcome.h>
|
||||
@@ -29,7 +30,7 @@ namespace AWSGameLift
|
||||
}
|
||||
|
||||
Aws::Vector<Aws::GameLift::Model::Player> players;
|
||||
for (const AWSGameLiftPlayerInformation& playerInfo : startMatchmakingRequest.m_players)
|
||||
for (const AWSGameLiftPlayer& playerInfo : startMatchmakingRequest.m_players)
|
||||
{
|
||||
Aws::GameLift::Model::Player player;
|
||||
if (!playerInfo.m_playerId.empty())
|
||||
@@ -109,7 +110,7 @@ namespace AWSGameLift
|
||||
|
||||
if (isValid)
|
||||
{
|
||||
for (const AWSGameLiftPlayerInformation& playerInfo : gameliftStartMatchmakingRequest->m_players)
|
||||
for (const AWSGameLiftPlayer& playerInfo : gameliftStartMatchmakingRequest->m_players)
|
||||
{
|
||||
isValid &= !playerInfo.m_playerId.empty();
|
||||
isValid &= AWSGameLiftActivityUtils::ValidatePlayerAttributes(playerInfo.m_playerAttributes);
|
||||
|
||||
+1
-44
@@ -14,53 +14,10 @@
|
||||
|
||||
namespace AWSGameLift
|
||||
{
|
||||
void AWSGameLiftPlayerInformation::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AWSGameLiftPlayerInformation>()
|
||||
->Version(0)
|
||||
->Field("latencyInMs", &AWSGameLiftPlayerInformation::m_latencyInMs)
|
||||
->Field("playerAttributes", &AWSGameLiftPlayerInformation::m_playerAttributes)
|
||||
->Field("playerId", &AWSGameLiftPlayerInformation::m_playerId)
|
||||
->Field("team", &AWSGameLiftPlayerInformation::m_team);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<AWSGameLiftPlayerInformation>("AWSGameLiftPlayerInformation", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_latencyInMs, "LatencyInMs",
|
||||
"A set of values, expressed in milliseconds, that indicates the amount of latency that"
|
||||
"a player experiences when connected to AWS Regions")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_playerAttributes, "PlayerAttributes",
|
||||
"A collection of key:value pairs containing player information for use in matchmaking")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_playerId, "PlayerId",
|
||||
"A unique identifier for a player")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_team, "Team",
|
||||
"Name of the team that the player is assigned to in a match");
|
||||
}
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<AWSGameLiftPlayerInformation>("AWSGameLiftPlayerInformation")
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->Property("LatencyInMs", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_latencyInMs))
|
||||
->Property("PlayerAttributes", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_playerAttributes))
|
||||
->Property("PlayerId", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_playerId))
|
||||
->Property("Team", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_team));
|
||||
}
|
||||
}
|
||||
|
||||
void AWSGameLiftStartMatchmakingRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AzFramework::StartMatchmakingRequest::Reflect(context);
|
||||
AWSGameLiftPlayerInformation::Reflect(context);
|
||||
AWSGameLiftPlayer::Reflect(context);
|
||||
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
|
||||
@@ -208,6 +208,7 @@ protected:
|
||||
sessionConfig.m_terminationTime = 0;
|
||||
sessionConfig.m_creatorId = "dummyCreatorId";
|
||||
sessionConfig.m_sessionProperties["dummyKey"] = "dummyValue";
|
||||
sessionConfig.m_matchmakingData = "dummyMatchmakingData";
|
||||
sessionConfig.m_sessionId = "dummyGameSessionId";
|
||||
sessionConfig.m_sessionName = "dummyGameSessionName";
|
||||
sessionConfig.m_ipAddress = "dummyIpAddress";
|
||||
@@ -232,7 +233,7 @@ protected:
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
request.m_ticketId = DummyMatchmakingTicketId;
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"N\": \"1\"}";
|
||||
player.m_playerId = DummyPlayerId;
|
||||
player.m_latencyInMs["us-east-1"] = 10;
|
||||
@@ -813,7 +814,7 @@ TEST_F(AWSGameLiftClientManagerTest, StartMatchmaking_CallWithInvalidRequest_Get
|
||||
{
|
||||
AWSGameLiftStartMatchmakingRequest request;
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"A\": \"1\"}";
|
||||
request.m_players.emplace_back(player);
|
||||
|
||||
@@ -855,7 +856,7 @@ TEST_F(AWSGameLiftClientManagerTest, StartMatchmakingAsync_CallWithInvalidReques
|
||||
{
|
||||
AWSGameLiftStartMatchmakingRequest request;
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"A\": \"1\"}";
|
||||
request.m_players.emplace_back(player);
|
||||
|
||||
|
||||
+7
-6
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <Activity/AWSGameLiftStartMatchmakingActivity.h>
|
||||
#include <AWSGameLiftClientFixture.h>
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
|
||||
#include <aws/gamelift/model/StartMatchmakingRequest.h>
|
||||
|
||||
@@ -21,7 +22,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, BuildAWSGameLiftStartMatchmaking
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
request.m_ticketId = "dummyTicketId";
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}";
|
||||
player.m_playerId = "dummyPlayerId";
|
||||
player.m_team = "dummyTeam";
|
||||
@@ -58,7 +59,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_
|
||||
AWSGameLiftStartMatchmakingRequest request;
|
||||
request.m_ticketId = "dummyTicketId";
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}";
|
||||
player.m_playerId = "dummyPlayerId";
|
||||
player.m_team = "dummyTeam";
|
||||
@@ -89,7 +90,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
request.m_ticketId = "dummyTicketId";
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}";
|
||||
player.m_team = "dummyTeam";
|
||||
player.m_latencyInMs["us-east-1"] = 10;
|
||||
@@ -107,7 +108,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
request.m_ticketId = "dummyTicketId";
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"A\": \"test\"}";
|
||||
player.m_playerId = "dummyPlayerId";
|
||||
player.m_team = "dummyTeam";
|
||||
@@ -125,7 +126,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_
|
||||
AWSGameLiftStartMatchmakingRequest request;
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}";
|
||||
player.m_playerId = "dummyPlayerId";
|
||||
player.m_team = "dummyTeam";
|
||||
@@ -142,7 +143,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_
|
||||
request.m_ticketId = "dummyTicketId";
|
||||
request.m_configurationName = "dummyConfiguration";
|
||||
|
||||
AWSGameLiftPlayerInformation player;
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}";
|
||||
player.m_playerId = "dummyPlayerId";
|
||||
player.m_team = "dummyTeam";
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../AWSGameLiftCommon/Include/AWSGameLiftPlayer.h
|
||||
../AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp
|
||||
../AWSGameLiftCommon/Source/AWSGameLiftSessionConstants.h
|
||||
Include/Request/AWSGameLiftAcceptMatchRequest.h
|
||||
Include/Request/AWSGameLiftCreateSessionOnQueueRequest.h
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AWSGameLift
|
||||
{
|
||||
//! AWSGameLiftPlayer
|
||||
//! Information on each player to be matched
|
||||
//! This information must include a player ID, and may contain player attributes and latency data to be used in the matchmaking process
|
||||
//! After a successful match, Player objects contain the name of the team the player is assigned to
|
||||
struct AWSGameLiftPlayer
|
||||
{
|
||||
AZ_RTTI(AWSGameLiftPlayer, "{B62C118E-C55D-4903-8ECB-E58E8CA613C4}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AWSGameLiftPlayer() = default;
|
||||
virtual ~AWSGameLiftPlayer() = default;
|
||||
|
||||
// A map of region names to latencies in millseconds, that indicates
|
||||
// the amount of latency that a player experiences when connected to AWS Regions
|
||||
AZStd::unordered_map<AZStd::string, int> m_latencyInMs;
|
||||
|
||||
// A collection of key:value pairs containing player information for use in matchmaking
|
||||
// Player attribute keys must match the playerAttributes used in a matchmaking rule set
|
||||
// Example: {"skill": "{\"N\": 23}", "gameMode": "{\"S\": \"deathmatch\"}"}
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_playerAttributes;
|
||||
|
||||
// A unique identifier for a player
|
||||
AZStd::string m_playerId;
|
||||
|
||||
// Name of the team that the player is assigned to in a match
|
||||
AZStd::string m_team;
|
||||
};
|
||||
} // namespace AWSGameLift
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
|
||||
namespace AWSGameLift
|
||||
{
|
||||
void AWSGameLiftPlayer::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AWSGameLiftPlayer>()
|
||||
->Version(0)
|
||||
->Field("latencyInMs", &AWSGameLiftPlayer::m_latencyInMs)
|
||||
->Field("playerAttributes", &AWSGameLiftPlayer::m_playerAttributes)
|
||||
->Field("playerId", &AWSGameLiftPlayer::m_playerId)
|
||||
->Field("team", &AWSGameLiftPlayer::m_team);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<AWSGameLiftPlayer>("AWSGameLiftPlayer", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_latencyInMs, "LatencyInMs",
|
||||
"A set of values, expressed in milliseconds, that indicates the amount of latency that"
|
||||
"a player experiences when connected to AWS Regions")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_playerAttributes, "PlayerAttributes",
|
||||
"A collection of key:value pairs containing player information for use in matchmaking")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_playerId, "PlayerId",
|
||||
"A unique identifier for a player")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_team, "Team",
|
||||
"Name of the team that the player is assigned to in a match");
|
||||
}
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<AWSGameLiftPlayer>("AWSGameLiftPlayer")
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->Property("LatencyInMs", BehaviorValueProperty(&AWSGameLiftPlayer::m_latencyInMs))
|
||||
->Property("PlayerAttributes", BehaviorValueProperty(&AWSGameLiftPlayer::m_playerAttributes))
|
||||
->Property("PlayerId", BehaviorValueProperty(&AWSGameLiftPlayer::m_playerId))
|
||||
->Property("Team", BehaviorValueProperty(&AWSGameLiftPlayer::m_team));
|
||||
}
|
||||
}
|
||||
} // namespace AWSGameLift
|
||||
@@ -17,6 +17,7 @@ ly_add_target(
|
||||
awsgamelift_server_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
../AWSGameLiftCommon/Include
|
||||
Include
|
||||
PRIVATE
|
||||
../AWSGameLiftCommon/Source
|
||||
@@ -54,6 +55,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
awsgamelift_server_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
../AWSGameLiftCommon/Include
|
||||
../AWSGameLiftCommon/Source
|
||||
Tests
|
||||
Source
|
||||
BUILD_DEPENDENCIES
|
||||
|
||||
+18
-3
@@ -9,9 +9,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Session/ISessionRequests.h>
|
||||
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
|
||||
namespace AWSGameLift
|
||||
{
|
||||
@@ -26,8 +28,21 @@ namespace AWSGameLift
|
||||
virtual ~IAWSGameLiftServerRequests() = default;
|
||||
|
||||
//! Notify GameLift that the server process is ready to host a game session.
|
||||
//! @return Whether the ProcessReady notification is sent to GameLift.
|
||||
//! @return True if the ProcessReady notification is sent to GameLift successfully, false otherwise
|
||||
virtual bool NotifyGameLiftProcessReady() = 0;
|
||||
|
||||
//! Sends a request to find new players for open slots in a game session created with FlexMatch.
|
||||
//! @param ticketId Unique identifier for match backfill request ticket
|
||||
//! @param players A set of data representing all players who are currently in the game session,
|
||||
//! if not provided, system will use lazy loaded game session data which is not guaranteed to
|
||||
//! be accurate (no latency data either)
|
||||
//! @return True if StartMatchBackfill succeeds, false otherwise
|
||||
virtual bool StartMatchBackfill(const AZStd::string& ticketId, const AZStd::vector<AWSGameLiftPlayer>& players) = 0;
|
||||
|
||||
//! Cancels an active match backfill request that was created with StartMatchBackfill
|
||||
//! @param ticketId Unique identifier of the backfill request ticket to be canceled
|
||||
//! @return True if StopMatchBackfill succeeds, false otherwise
|
||||
virtual bool StopMatchBackfill(const AZStd::string& ticketId) = 0;
|
||||
};
|
||||
|
||||
// IAWSGameLiftServerRequests EBus wrapper for scripting
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/Jobs/JobManagerBus.h>
|
||||
#include <AzCore/JSON/error/en.h>
|
||||
#include <AzCore/JSON/stringbuffer.h>
|
||||
#include <AzCore/JSON/writer.h>
|
||||
#include <AzCore/std/bind/bind.h>
|
||||
#include <AzFramework/Session/SessionNotifications.h>
|
||||
|
||||
@@ -112,6 +115,7 @@ namespace AWSGameLift
|
||||
{
|
||||
propertiesOutput = propertiesOutput.substr(0, propertiesOutput.size() - 1); // Trim last comma to fit array format
|
||||
}
|
||||
sessionConfig.m_matchmakingData = gameSession.GetMatchmakerData().c_str();
|
||||
sessionConfig.m_sessionId = gameSession.GetGameSessionId().c_str();
|
||||
sessionConfig.m_ipAddress = gameSession.GetIpAddress().c_str();
|
||||
sessionConfig.m_maxPlayer = gameSession.GetMaximumPlayerSessionCount();
|
||||
@@ -133,6 +137,276 @@ namespace AWSGameLift
|
||||
return sessionConfig;
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::BuildServerMatchBackfillPlayer(
|
||||
const AWSGameLiftPlayer& player, Aws::GameLift::Server::Model::Player& outBackfillPlayer)
|
||||
{
|
||||
outBackfillPlayer.SetPlayerId(player.m_playerId.c_str());
|
||||
outBackfillPlayer.SetTeam(player.m_team.c_str());
|
||||
for (auto latencyPair : player.m_latencyInMs)
|
||||
{
|
||||
outBackfillPlayer.AddLatencyInMs(latencyPair.first.c_str(), latencyPair.second);
|
||||
}
|
||||
|
||||
for (auto attributePair : player.m_playerAttributes)
|
||||
{
|
||||
Aws::GameLift::Server::Model::AttributeValue playerAttribute;
|
||||
rapidjson::Document attributeDocument;
|
||||
rapidjson::ParseResult parseResult = attributeDocument.Parse(attributePair.second.c_str());
|
||||
// player attribute json content should always be a single member object
|
||||
if (parseResult && attributeDocument.IsObject() && attributeDocument.MemberCount() == 1)
|
||||
{
|
||||
if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSTypeName) ||
|
||||
attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSServerTypeName)) &&
|
||||
attributeDocument.MemberBegin()->value.IsString())
|
||||
{
|
||||
playerAttribute = Aws::GameLift::Server::Model::AttributeValue(
|
||||
attributeDocument.MemberBegin()->value.GetString());
|
||||
}
|
||||
else if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeNTypeName) ||
|
||||
attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeNServerTypeName)) &&
|
||||
attributeDocument.MemberBegin()->value.IsNumber())
|
||||
{
|
||||
playerAttribute = Aws::GameLift::Server::Model::AttributeValue(
|
||||
attributeDocument.MemberBegin()->value.GetDouble());
|
||||
}
|
||||
else if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSDMTypeName) ||
|
||||
attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSDMServerTypeName)) &&
|
||||
attributeDocument.MemberBegin()->value.IsObject())
|
||||
{
|
||||
playerAttribute = Aws::GameLift::Server::Model::AttributeValue::ConstructStringDoubleMap();
|
||||
for (auto iter = attributeDocument.MemberBegin()->value.MemberBegin();
|
||||
iter != attributeDocument.MemberBegin()->value.MemberEnd(); iter++)
|
||||
{
|
||||
if (iter->name.IsString() && iter->value.IsNumber())
|
||||
{
|
||||
playerAttribute.AddStringAndDouble(iter->name.GetString(), iter->value.GetDouble());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage,
|
||||
player.m_playerId.c_str(), "String double map key must be string type and value must be number type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSLTypeName) ||
|
||||
attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSLServerTypeName)) &&
|
||||
attributeDocument.MemberBegin()->value.IsArray())
|
||||
{
|
||||
playerAttribute = Aws::GameLift::Server::Model::AttributeValue::ConstructStringList();
|
||||
for (auto iter = attributeDocument.MemberBegin()->value.Begin();
|
||||
iter != attributeDocument.MemberBegin()->value.End(); iter++)
|
||||
{
|
||||
if (iter->IsString())
|
||||
{
|
||||
playerAttribute.AddString(iter->GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage,
|
||||
player.m_playerId.c_str(), "String list element must be string type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage,
|
||||
player.m_playerId.c_str(), "S, N, SDM or SLM is expected as attribute type.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage,
|
||||
player.m_playerId.c_str(), rapidjson::GetParseError_En(parseResult.Code()));
|
||||
return false;
|
||||
}
|
||||
outBackfillPlayer.AddPlayerAttribute(attributePair.first.c_str(), playerAttribute);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AZStd::vector<AWSGameLiftPlayer> AWSGameLiftServerManager::GetActiveServerMatchBackfillPlayers()
|
||||
{
|
||||
AZStd::vector<AWSGameLiftPlayer> activePlayers;
|
||||
// Keep processing only when game session has matchmaking data
|
||||
if (IsMatchmakingDataValid())
|
||||
{
|
||||
auto activePlayerSessions = GetActivePlayerSessions();
|
||||
for (auto playerSession : activePlayerSessions)
|
||||
{
|
||||
AWSGameLiftPlayer player;
|
||||
if (BuildActiveServerMatchBackfillPlayer(playerSession.GetPlayerId().c_str(), player))
|
||||
{
|
||||
activePlayers.push_back(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
return activePlayers;
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::IsMatchmakingDataValid()
|
||||
{
|
||||
return m_matchmakingData.IsObject() &&
|
||||
m_matchmakingData.HasMember(AWSGameLiftMatchmakingConfigurationKeyName) &&
|
||||
m_matchmakingData.HasMember(AWSGameLiftMatchmakingTeamsKeyName);
|
||||
}
|
||||
|
||||
AZStd::vector<Aws::GameLift::Server::Model::PlayerSession> AWSGameLiftServerManager::GetActivePlayerSessions()
|
||||
{
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsRequest describeRequest;
|
||||
describeRequest.SetGameSessionId(m_gameSession.GetGameSessionId());
|
||||
describeRequest.SetPlayerSessionStatusFilter(
|
||||
Aws::GameLift::Server::Model::PlayerSessionStatusMapper::GetNameForPlayerSessionStatus(
|
||||
Aws::GameLift::Server::Model::PlayerSessionStatus::ACTIVE));
|
||||
int maxPlayerSession = m_gameSession.GetMaximumPlayerSessionCount();
|
||||
|
||||
AZStd::vector<Aws::GameLift::Server::Model::PlayerSession> activePlayerSessions;
|
||||
if (maxPlayerSession <= AWSGameLiftDescribePlayerSessionsPageSize)
|
||||
{
|
||||
describeRequest.SetLimit(maxPlayerSession);
|
||||
auto outcome = m_gameLiftServerSDKWrapper->DescribePlayerSessions(describeRequest);
|
||||
if (outcome.IsSuccess())
|
||||
{
|
||||
for (auto playerSession : outcome.GetResult().GetPlayerSessions())
|
||||
{
|
||||
activePlayerSessions.push_back(playerSession);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftDescribePlayerSessionsErrorMessage,
|
||||
outcome.GetError().GetErrorMessage().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
describeRequest.SetLimit(AWSGameLiftDescribePlayerSessionsPageSize);
|
||||
while (true)
|
||||
{
|
||||
auto outcome = m_gameLiftServerSDKWrapper->DescribePlayerSessions(describeRequest);
|
||||
if (outcome.IsSuccess())
|
||||
{
|
||||
for (auto playerSession : outcome.GetResult().GetPlayerSessions())
|
||||
{
|
||||
activePlayerSessions.push_back(playerSession);
|
||||
}
|
||||
if (outcome.GetResult().GetNextToken().empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
describeRequest.SetNextToken(outcome.GetResult().GetNextToken());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
activePlayerSessions.clear();
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftDescribePlayerSessionsErrorMessage,
|
||||
outcome.GetError().GetErrorMessage().c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return activePlayerSessions;
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::BuildActiveServerMatchBackfillPlayer(const AZStd::string& playerId, AWSGameLiftPlayer& outPlayer)
|
||||
{
|
||||
// As data is from GameLift service, assume it is always in correct format
|
||||
rapidjson::Value& teams = m_matchmakingData[AWSGameLiftMatchmakingTeamsKeyName];
|
||||
|
||||
// Iterate through teams to find target player
|
||||
for (rapidjson::SizeType teamIndex = 0; teamIndex < teams.Size(); ++teamIndex)
|
||||
{
|
||||
rapidjson::Value& players = teams[teamIndex][AWSGameLiftMatchmakingPlayersKeyName];
|
||||
|
||||
// Iterate through players under the team to find target player
|
||||
for (rapidjson::SizeType playerIndex = 0; playerIndex < players.Size(); ++playerIndex)
|
||||
{
|
||||
if (std::strcmp(players[playerIndex][AWSGameLiftMatchmakingPlayerIdKeyName].GetString(), playerId.c_str()) == 0)
|
||||
{
|
||||
outPlayer.m_playerId = playerId;
|
||||
outPlayer.m_team = teams[teamIndex][AWSGameLiftMatchmakingTeamNameKeyName].GetString();
|
||||
// Get player attributes if target player has
|
||||
if (players[playerIndex].HasMember(AWSGameLiftMatchmakingPlayerAttributesKeyName))
|
||||
{
|
||||
BuildServerMatchBackfillPlayerAttributes(
|
||||
players[playerIndex][AWSGameLiftMatchmakingPlayerAttributesKeyName], outPlayer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AWSGameLiftServerManager::BuildServerMatchBackfillPlayerAttributes(
|
||||
const rapidjson::Value& playerAttributes, AWSGameLiftPlayer& outPlayer)
|
||||
{
|
||||
for (auto iter = playerAttributes.MemberBegin(); iter != playerAttributes.MemberEnd(); iter++)
|
||||
{
|
||||
AZStd::string attributeName = iter->name.GetString();
|
||||
|
||||
rapidjson::StringBuffer jsonStringBuffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(jsonStringBuffer);
|
||||
iter->value[AWSGameLiftMatchmakingPlayerAttributeValueKeyName].Accept(writer);
|
||||
AZStd::string attributeType = iter->value[AWSGameLiftMatchmakingPlayerAttributeTypeKeyName].GetString();
|
||||
AZStd::string attributeValue = AZStd::string::format("{\"%s\": %s}",
|
||||
attributeType.c_str(), jsonStringBuffer.GetString());
|
||||
|
||||
outPlayer.m_playerAttributes.emplace(attributeName, attributeValue);
|
||||
}
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::BuildStartMatchBackfillRequest(
|
||||
const AZStd::string& ticketId,
|
||||
const AZStd::vector<AWSGameLiftPlayer>& players,
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest& outRequest)
|
||||
{
|
||||
outRequest.SetGameSessionArn(m_gameSession.GetGameSessionId());
|
||||
outRequest.SetMatchmakingConfigurationArn(m_matchmakingData[AWSGameLiftMatchmakingConfigurationKeyName].GetString());
|
||||
if (!ticketId.empty())
|
||||
{
|
||||
outRequest.SetTicketId(ticketId.c_str());
|
||||
}
|
||||
|
||||
AZStd::vector<AWSGameLiftPlayer> requestPlayers(players);
|
||||
if (players.size() == 0)
|
||||
{
|
||||
requestPlayers = GetActiveServerMatchBackfillPlayers();
|
||||
}
|
||||
for (auto player : requestPlayers)
|
||||
{
|
||||
Aws::GameLift::Server::Model::Player backfillPlayer;
|
||||
if (BuildServerMatchBackfillPlayer(player, backfillPlayer))
|
||||
{
|
||||
outRequest.AddPlayer(backfillPlayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AWSGameLiftServerManager::BuildStopMatchBackfillRequest(
|
||||
const AZStd::string& ticketId, Aws::GameLift::Server::Model::StopMatchBackfillRequest& outRequest)
|
||||
{
|
||||
outRequest.SetGameSessionArn(m_gameSession.GetGameSessionId());
|
||||
outRequest.SetMatchmakingConfigurationArn(m_matchmakingData[AWSGameLiftMatchmakingConfigurationKeyName].GetString());
|
||||
if (!ticketId.empty())
|
||||
{
|
||||
outRequest.SetTicketId(ticketId.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::Path AWSGameLiftServerManager::GetExternalSessionCertificate()
|
||||
{
|
||||
// TODO: Add support to get TLS cert file path
|
||||
@@ -238,7 +512,7 @@ namespace AWSGameLift
|
||||
|
||||
Aws::GameLift::Server::ProcessParameters processReadyParameter = Aws::GameLift::Server::ProcessParameters(
|
||||
AZStd::bind(&AWSGameLiftServerManager::OnStartGameSession, this, AZStd::placeholders::_1),
|
||||
AZStd::bind(&AWSGameLiftServerManager::OnUpdateGameSession, this),
|
||||
AZStd::bind(&AWSGameLiftServerManager::OnUpdateGameSession, this, AZStd::placeholders::_1),
|
||||
AZStd::bind(&AWSGameLiftServerManager::OnProcessTerminate, this),
|
||||
AZStd::bind(&AWSGameLiftServerManager::OnHealthCheck, this), desc.m_port,
|
||||
Aws::GameLift::Server::LogParameters(logPaths));
|
||||
@@ -260,6 +534,7 @@ namespace AWSGameLift
|
||||
|
||||
void AWSGameLiftServerManager::OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& gameSession)
|
||||
{
|
||||
UpdateGameSessionData(gameSession);
|
||||
AzFramework::SessionConfig sessionConfig = BuildSessionConfig(gameSession);
|
||||
|
||||
bool createSessionResult = true;
|
||||
@@ -311,10 +586,19 @@ namespace AWSGameLift
|
||||
return m_serverSDKInitialized && healthCheckResult;
|
||||
}
|
||||
|
||||
void AWSGameLiftServerManager::OnUpdateGameSession()
|
||||
void AWSGameLiftServerManager::OnUpdateGameSession(const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession)
|
||||
{
|
||||
// TODO: Perform game-specific tasks to prep for newly matched players
|
||||
return;
|
||||
Aws::GameLift::Server::Model::UpdateReason updateReason = updateGameSession.GetUpdateReason();
|
||||
if (updateReason == Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED)
|
||||
{
|
||||
UpdateGameSessionData(updateGameSession.GetGameSession());
|
||||
}
|
||||
AzFramework::SessionConfig sessionConfig = BuildSessionConfig(updateGameSession.GetGameSession());
|
||||
|
||||
AzFramework::SessionNotificationBus::Broadcast(
|
||||
&AzFramework::SessionNotifications::OnUpdateSessionBegin,
|
||||
sessionConfig,
|
||||
Aws::GameLift::Server::Model::UpdateReasonMapper::GetNameForUpdateReason(updateReason).c_str());
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::RemoveConnectedPlayer(uint32_t playerConnectionId, AZStd::string& outPlayerSessionId)
|
||||
@@ -340,6 +624,92 @@ namespace AWSGameLift
|
||||
m_gameLiftServerSDKWrapper = AZStd::move(gameLiftServerSDKWrapper);
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::StartMatchBackfill(const AZStd::string& ticketId, const AZStd::vector<AWSGameLiftPlayer>& players)
|
||||
{
|
||||
if (!m_serverSDKInitialized)
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerSDKNotInitErrorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMatchmakingDataValid())
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingDataMissingErrorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest request;
|
||||
if (!BuildStartMatchBackfillRequest(ticketId, players, request))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ_TracePrintf(AWSGameLiftServerManagerName, "Starting match backfill %s ...", ticketId.c_str());
|
||||
auto outcome = m_gameLiftServerSDKWrapper->StartMatchBackfill(request);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftStartMatchBackfillErrorMessage,
|
||||
outcome.GetError().GetErrorMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(AWSGameLiftServerManagerName, "StartMatchBackfill request against Amazon GameLift service is complete.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::StopMatchBackfill(const AZStd::string& ticketId)
|
||||
{
|
||||
if (!m_serverSDKInitialized)
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerSDKNotInitErrorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMatchmakingDataValid())
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingDataMissingErrorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
Aws::GameLift::Server::Model::StopMatchBackfillRequest request;
|
||||
BuildStopMatchBackfillRequest(ticketId, request);
|
||||
|
||||
AZ_TracePrintf(AWSGameLiftServerManagerName, "Stopping match backfill %s ...", ticketId.c_str());
|
||||
auto outcome = m_gameLiftServerSDKWrapper->StopMatchBackfill(request);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftStopMatchBackfillErrorMessage,
|
||||
outcome.GetError().GetErrorMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(AWSGameLiftServerManagerName, "StopMatchBackfill request against Amazon GameLift service is complete.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void AWSGameLiftServerManager::UpdateGameSessionData(const Aws::GameLift::Server::Model::GameSession& gameSession)
|
||||
{
|
||||
AZ_TracePrintf(AWSGameLiftServerManagerName, "Lazy loading game session and matchmaking data from Amazon GameLift service ...");
|
||||
m_gameSession = Aws::GameLift::Server::Model::GameSession(gameSession);
|
||||
if (m_gameSession.GetMatchmakerData().empty())
|
||||
{
|
||||
m_matchmakingData.Parse("{}");
|
||||
}
|
||||
else
|
||||
{
|
||||
rapidjson::ParseResult parseResult = m_matchmakingData.Parse(m_gameSession.GetMatchmakerData().c_str());
|
||||
if (!parseResult)
|
||||
{
|
||||
AZ_Error(AWSGameLiftServerManagerName, false,
|
||||
AWSGameLiftMatchmakingDataInvalidErrorMessage, rapidjson::GetParseError_En(parseResult.Code()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AWSGameLiftServerManager::ValidatePlayerJoinSession(const AzFramework::PlayerConnectionConfig& playerConnectionConfig)
|
||||
{
|
||||
uint32_t playerConnectionId = playerConnectionConfig.m_playerConnectionId;
|
||||
|
||||
@@ -11,11 +11,15 @@
|
||||
#include <aws/gamelift/server/GameLiftServerAPI.h>
|
||||
#include <aws/gamelift/server/model/GameSession.h>
|
||||
|
||||
#include <AzCore/JSON/rapidjson.h>
|
||||
#include <AzCore/JSON/document.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzFramework/Session/ISessionHandlingRequests.h>
|
||||
#include <AzFramework/Session/SessionConfig.h>
|
||||
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
#include <Request/IAWSGameLiftServerRequests.h>
|
||||
|
||||
namespace AWSGameLift
|
||||
@@ -66,6 +70,36 @@ namespace AWSGameLift
|
||||
"Invalid player connection config, player connection id: %d, player session id: %s";
|
||||
static constexpr const char AWSGameLiftServerRemovePlayerSessionErrorMessage[] =
|
||||
"Failed to notify GameLift that the player with the player session id %s has disconnected from the server process. ErrorMessage: %s";
|
||||
static constexpr const char AWSGameLiftMatchmakingDataInvalidErrorMessage[] =
|
||||
"Failed to parse GameLift matchmaking data. ErrorMessage: %s";
|
||||
static constexpr const char AWSGameLiftMatchmakingDataMissingErrorMessage[] =
|
||||
"GameLift matchmaking data is missing or invalid to parse.";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage[] =
|
||||
"Failed to build player %s attributes. ErrorMessage: %s";
|
||||
static constexpr const char AWSGameLiftDescribePlayerSessionsErrorMessage[] =
|
||||
"Failed to describe player sessions. ErrorMessage: %s";
|
||||
static constexpr const char AWSGameLiftStartMatchBackfillErrorMessage[] =
|
||||
"Failed to start match backfill. ErrorMessage: %s";
|
||||
static constexpr const char AWSGameLiftStopMatchBackfillErrorMessage[] =
|
||||
"Failed to stop match backfill. ErrorMessage: %s";
|
||||
|
||||
static constexpr const char AWSGameLiftMatchmakingConfigurationKeyName[] = "matchmakingConfigurationArn";
|
||||
static constexpr const char AWSGameLiftMatchmakingTeamsKeyName[] = "teams";
|
||||
static constexpr const char AWSGameLiftMatchmakingTeamNameKeyName[] = "name";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayersKeyName[] = "players";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerIdKeyName[] = "playerId";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributesKeyName[] = "attributes";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeTypeKeyName[] = "attributeType";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeValueKeyName[] = "valueAttribute";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSTypeName[] = "S";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSServerTypeName[] = "STRING";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeNTypeName[] = "N";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeNServerTypeName[] = "NUMBER";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSLTypeName[] = "SL";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSLServerTypeName[] = "STRING_LIST";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSDMTypeName[] = "SDM";
|
||||
static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSDMServerTypeName[] = "STRING_DOUBLE_MAP";
|
||||
static constexpr const uint16_t AWSGameLiftDescribePlayerSessionsPageSize = 30;
|
||||
|
||||
AWSGameLiftServerManager();
|
||||
virtual ~AWSGameLiftServerManager();
|
||||
@@ -78,6 +112,8 @@ namespace AWSGameLift
|
||||
|
||||
// AWSGameLiftServerRequestBus interface implementation
|
||||
bool NotifyGameLiftProcessReady() override;
|
||||
bool StartMatchBackfill(const AZStd::string& ticketId, const AZStd::vector<AWSGameLiftPlayer>& players) override;
|
||||
bool StopMatchBackfill(const AZStd::string& ticketId) override;
|
||||
|
||||
// ISessionHandlingProviderRequests interface implementation
|
||||
void HandleDestroySession() override;
|
||||
@@ -92,18 +128,48 @@ namespace AWSGameLift
|
||||
//! Add connected player session id.
|
||||
bool AddConnectedPlayer(const AzFramework::PlayerConnectionConfig& playerConnectionConfig);
|
||||
|
||||
//! Get active server player data from lazy loaded game session for server match backfill
|
||||
AZStd::vector<AWSGameLiftPlayer> GetActiveServerMatchBackfillPlayers();
|
||||
|
||||
//! Update local game session data to latest one
|
||||
void UpdateGameSessionData(const Aws::GameLift::Server::Model::GameSession& gameSession);
|
||||
|
||||
private:
|
||||
//! Build the serverProcessDesc with appropriate server port number and log paths.
|
||||
GameLiftServerProcessDesc BuildGameLiftServerProcessDesc();
|
||||
|
||||
//! Build active server player data from lazy loaded game session based on player id
|
||||
bool BuildActiveServerMatchBackfillPlayer(const AZStd::string& playerId, AWSGameLiftPlayer& outPlayer);
|
||||
|
||||
//! Build server player attribute data from lazy load matchmaking data
|
||||
void BuildServerMatchBackfillPlayerAttributes(const rapidjson::Value& playerAttributes, AWSGameLiftPlayer& outPlayer);
|
||||
|
||||
//! Build server player data for server match backfill
|
||||
bool BuildServerMatchBackfillPlayer(const AWSGameLiftPlayer& player, Aws::GameLift::Server::Model::Player& outBackfillPlayer);
|
||||
|
||||
//! Build start match backfill request for StartMatchBackfill operation
|
||||
bool BuildStartMatchBackfillRequest(
|
||||
const AZStd::string& ticketId,
|
||||
const AZStd::vector<AWSGameLiftPlayer>& players,
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest& outRequest);
|
||||
|
||||
//! Build stop match backfill request for StopMatchBackfill operation
|
||||
void BuildStopMatchBackfillRequest(const AZStd::string& ticketId, Aws::GameLift::Server::Model::StopMatchBackfillRequest& outRequest);
|
||||
|
||||
//! Build session config by using AWS GameLift Server GameSession Model.
|
||||
AzFramework::SessionConfig BuildSessionConfig(const Aws::GameLift::Server::Model::GameSession& gameSession);
|
||||
|
||||
//! Check whether matchmaking data is in proper format
|
||||
bool IsMatchmakingDataValid();
|
||||
|
||||
//! Fetch active player sessions in game session.
|
||||
AZStd::vector<Aws::GameLift::Server::Model::PlayerSession> GetActivePlayerSessions();
|
||||
|
||||
//! Callback function that the GameLift service invokes to activate a new game session.
|
||||
void OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& gameSession);
|
||||
|
||||
//! Callback function that the GameLift service invokes to pass an updated game session object to the server process.
|
||||
void OnUpdateGameSession();
|
||||
void OnUpdateGameSession(const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession);
|
||||
|
||||
//! Callback function that the server process or GameLift service invokes to force the server process to shut down.
|
||||
void OnProcessTerminate();
|
||||
@@ -125,5 +191,12 @@ namespace AWSGameLift
|
||||
using PlayerConnectionId = uint32_t;
|
||||
using PlayerSessionId = AZStd::string;
|
||||
AZStd::unordered_map<PlayerConnectionId, PlayerSessionId> m_connectedPlayers;
|
||||
|
||||
// Lazy loaded game session and matchmaking data
|
||||
Aws::GameLift::Server::Model::GameSession m_gameSession;
|
||||
// Matchmaking data contains a unique match ID, it identifies the matchmaker that created the match
|
||||
// and describes the teams, team assignments, and players.
|
||||
// Reference https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-server.html#match-server-data
|
||||
rapidjson::Document m_matchmakingData;
|
||||
};
|
||||
} // namespace AWSGameLift
|
||||
|
||||
@@ -22,6 +22,12 @@ namespace AWSGameLift
|
||||
return Aws::GameLift::Server::ActivateGameSession();
|
||||
}
|
||||
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome GameLiftServerSDKWrapper::DescribePlayerSessions(
|
||||
const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest& describePlayerSessionsRequest)
|
||||
{
|
||||
return Aws::GameLift::Server::DescribePlayerSessions(describePlayerSessionsRequest);
|
||||
}
|
||||
|
||||
Aws::GameLift::Server::InitSDKOutcome GameLiftServerSDKWrapper::InitSDK()
|
||||
{
|
||||
return Aws::GameLift::Server::InitSDK();
|
||||
@@ -69,4 +75,17 @@ namespace AWSGameLift
|
||||
{
|
||||
return Aws::GameLift::Server::RemovePlayerSession(playerSessionId.c_str());
|
||||
}
|
||||
|
||||
Aws::GameLift::StartMatchBackfillOutcome GameLiftServerSDKWrapper::StartMatchBackfill(
|
||||
const Aws::GameLift::Server::Model::StartMatchBackfillRequest& startMatchBackfillRequest)
|
||||
{
|
||||
return Aws::GameLift::Server::StartMatchBackfill(startMatchBackfillRequest);
|
||||
}
|
||||
|
||||
Aws::GameLift::GenericOutcome GameLiftServerSDKWrapper::StopMatchBackfill(
|
||||
const Aws::GameLift::Server::Model::StopMatchBackfillRequest& stopMatchBackfillRequest)
|
||||
{
|
||||
return Aws::GameLift::Server::StopMatchBackfill(stopMatchBackfillRequest);
|
||||
}
|
||||
|
||||
} // namespace AWSGameLift
|
||||
|
||||
@@ -33,6 +33,14 @@ namespace AWSGameLift
|
||||
//! @return Returns a generic outcome consisting of success or failure with an error message.
|
||||
virtual Aws::GameLift::GenericOutcome ActivateGameSession();
|
||||
|
||||
//! Retrieves player session data, including settings, session metadata, and player data.
|
||||
//! Use this action to get information for a single player session,
|
||||
//! for all player sessions in a game session, or for all player sessions associated with a single player ID.
|
||||
//! @param describePlayerSessionsRequest The request object describing which player sessions to retrieve.
|
||||
//! @return If successful, returns a DescribePlayerSessionsOutcome object containing a set of player session objects that fit the request parameters.
|
||||
virtual Aws::GameLift::DescribePlayerSessionsOutcome DescribePlayerSessions(
|
||||
const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest& describePlayerSessionsRequest);
|
||||
|
||||
//! Initializes the GameLift SDK.
|
||||
//! Should be called when the server starts, before any GameLift-dependent initialization happens.
|
||||
//! @return If successful, returns an InitSdkOutcome object indicating that the server process is ready to call ProcessReady().
|
||||
@@ -56,5 +64,16 @@ namespace AWSGameLift
|
||||
//! @param playerSessionId Unique ID issued by the Amazon GameLift service in response to a call to the AWS SDK Amazon GameLift API action CreatePlayerSession.
|
||||
//! @return Returns a generic outcome consisting of success or failure with an error message.
|
||||
virtual Aws::GameLift::GenericOutcome RemovePlayerSession(const AZStd::string& playerSessionId);
|
||||
|
||||
//! Sends a request to find new players for open slots in a game session created with FlexMatch.
|
||||
//! When the match has been successfully, backfilled updated matchmaker data will be sent to the OnUpdateGameSession callback.
|
||||
//! @param startMatchBackfillRequest This data type is used to send a matchmaking backfill request.
|
||||
//! @return Returns a StartMatchBackfillOutcome object with the match backfill ticket or failure with an error message.
|
||||
virtual Aws::GameLift::StartMatchBackfillOutcome StartMatchBackfill(const Aws::GameLift::Server::Model::StartMatchBackfillRequest& startMatchBackfillRequest);
|
||||
|
||||
//! Cancels an active match backfill request that was created with StartMatchBackfill
|
||||
//! @param stopMatchBackfillRequest This data type is used to cancel a matchmaking backfill request.
|
||||
//! @return Returns a generic outcome consisting of success or failure with an error message.
|
||||
virtual Aws::GameLift::GenericOutcome StopMatchBackfill(const Aws::GameLift::Server::Model::StopMatchBackfillRequest& stopMatchBackfillRequest);
|
||||
};
|
||||
} // namespace AWSGameLift
|
||||
|
||||
@@ -16,6 +16,136 @@
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
static constexpr const char TEST_SERVER_MATCHMAKING_DATA[] =
|
||||
R"({
|
||||
"matchId":"testmatchid",
|
||||
"matchmakingConfigurationArn":"testmatchconfig",
|
||||
"teams":[
|
||||
{"name":"testteam",
|
||||
"players":[
|
||||
{"playerId":"testplayer",
|
||||
"attributes":{
|
||||
"skills":{
|
||||
"attributeType":"STRING_DOUBLE_MAP",
|
||||
"valueAttribute":{"test1":10.0,"test2":20.0,"test3":30.0,"test4":40.0}
|
||||
},
|
||||
"mode":{
|
||||
"attributeType":"STRING",
|
||||
"valueAttribute":"testmode"
|
||||
},
|
||||
"level":{
|
||||
"attributeType":"NUMBER",
|
||||
"valueAttribute":10.0
|
||||
},
|
||||
"items":{
|
||||
"attributeType":"STRING_LIST",
|
||||
"valueAttribute":["test1","test2","test3"]
|
||||
}
|
||||
}}
|
||||
]}
|
||||
]
|
||||
})";
|
||||
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest GetTestStartMatchBackfillRequest()
|
||||
{
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest request;
|
||||
request.SetMatchmakingConfigurationArn("testmatchconfig");
|
||||
Aws::GameLift::Server::Model::Player player;
|
||||
player.SetPlayerId("testplayer");
|
||||
player.SetTeam("testteam");
|
||||
player.AddPlayerAttribute("mode", Aws::GameLift::Server::Model::AttributeValue("testmode"));
|
||||
player.AddPlayerAttribute("level", Aws::GameLift::Server::Model::AttributeValue(10.0));
|
||||
auto sdmValue = Aws::GameLift::Server::Model::AttributeValue::ConstructStringDoubleMap();
|
||||
sdmValue.AddStringAndDouble("test1", 10.0);
|
||||
player.AddPlayerAttribute("skills", sdmValue);
|
||||
auto slValue = Aws::GameLift::Server::Model::AttributeValue::ConstructStringList();
|
||||
slValue.AddString("test1");
|
||||
player.AddPlayerAttribute("items", slValue);
|
||||
player.AddLatencyInMs("testregion", 10);
|
||||
request.AddPlayer(player);
|
||||
request.SetTicketId("testticket");
|
||||
return request;
|
||||
}
|
||||
|
||||
AWSGameLiftPlayer GetTestGameLiftPlayer()
|
||||
{
|
||||
AWSGameLiftPlayer player;
|
||||
player.m_team = "testteam";
|
||||
player.m_playerId = "testplayer";
|
||||
player.m_playerAttributes.emplace("mode", "{\"S\": \"testmode\"}");
|
||||
player.m_playerAttributes.emplace("level", "{\"N\": 10.0}");
|
||||
player.m_playerAttributes.emplace("skills", "{\"SDM\": {\"test1\":10.0}}");
|
||||
player.m_playerAttributes.emplace("items", "{\"SL\": [\"test1\"]}");
|
||||
player.m_latencyInMs.emplace("testregion", 10);
|
||||
return player;
|
||||
}
|
||||
|
||||
MATCHER_P(StartMatchBackfillRequestMatcher, expectedRequest, "")
|
||||
{
|
||||
// Custome matcher for checking the SearchSessionsResponse type argument.
|
||||
AZ_UNUSED(result_listener);
|
||||
if (strcmp(arg.GetGameSessionArn().c_str(), expectedRequest.GetGameSessionArn().c_str()) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (strcmp(arg.GetMatchmakingConfigurationArn().c_str(), expectedRequest.GetMatchmakingConfigurationArn().c_str()) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (strcmp(arg.GetTicketId().c_str(), expectedRequest.GetTicketId().c_str()) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (arg.GetPlayers().size() != expectedRequest.GetPlayers().size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int playerIndex = 0; playerIndex < expectedRequest.GetPlayers().size(); playerIndex++)
|
||||
{
|
||||
auto actualPlayerAttributes = arg.GetPlayers()[playerIndex].GetPlayerAttributes();
|
||||
auto expectedPlayerAttributes = expectedRequest.GetPlayers()[playerIndex].GetPlayerAttributes();
|
||||
if (actualPlayerAttributes.size() != expectedPlayerAttributes.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (auto attributePair : expectedPlayerAttributes)
|
||||
{
|
||||
if (actualPlayerAttributes.find(attributePair.first) == actualPlayerAttributes.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(attributePair.second.GetType() == actualPlayerAttributes[attributePair.first].GetType() &&
|
||||
(attributePair.second.GetS() == actualPlayerAttributes[attributePair.first].GetS() ||
|
||||
attributePair.second.GetN() == actualPlayerAttributes[attributePair.first].GetN() ||
|
||||
attributePair.second.GetSL() == actualPlayerAttributes[attributePair.first].GetSL() ||
|
||||
attributePair.second.GetSDM() == actualPlayerAttributes[attributePair.first].GetSDM())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto actualLatencies = arg.GetPlayers()[playerIndex].GetLatencyInMs();
|
||||
auto expectedLatencies = expectedRequest.GetPlayers()[playerIndex].GetLatencyInMs();
|
||||
if (actualLatencies.size() != expectedLatencies.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (auto latencyPair : expectedLatencies)
|
||||
{
|
||||
if (actualLatencies.find(latencyPair.first) == actualLatencies.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (latencyPair.second != actualLatencies[latencyPair.first])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class SessionNotificationsHandlerMock
|
||||
: public AzFramework::SessionNotificationBus::Handler
|
||||
{
|
||||
@@ -33,6 +163,7 @@ namespace UnitTest
|
||||
MOCK_METHOD0(OnSessionHealthCheck, bool());
|
||||
MOCK_METHOD1(OnCreateSessionBegin, bool(const AzFramework::SessionConfig&));
|
||||
MOCK_METHOD0(OnDestroySessionBegin, bool());
|
||||
MOCK_METHOD2(OnUpdateSessionBegin, void(const AzFramework::SessionConfig&, const AZStd::string&));
|
||||
};
|
||||
|
||||
class GameLiftServerManagerTest
|
||||
@@ -228,6 +359,64 @@ namespace UnitTest
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithUnknownReason_OnUpdateSessionBeginGetCalledOnce)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->NotifyGameLiftProcessReady();
|
||||
SessionNotificationsHandlerMock handlerMock;
|
||||
EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1);
|
||||
|
||||
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc(
|
||||
Aws::GameLift::Server::Model::UpdateGameSession(
|
||||
Aws::GameLift::Server::Model::GameSession(),
|
||||
Aws::GameLift::Server::Model::UpdateReason::UNKNOWN,
|
||||
"testticket"));
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithEmptyMatchmakingData_OnUpdateSessionBeginGetCalledOnce)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->NotifyGameLiftProcessReady();
|
||||
SessionNotificationsHandlerMock handlerMock;
|
||||
EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1);
|
||||
|
||||
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc(
|
||||
Aws::GameLift::Server::Model::UpdateGameSession(
|
||||
Aws::GameLift::Server::Model::GameSession(),
|
||||
Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED,
|
||||
"testticket"));
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithValidMatchmakingData_OnUpdateSessionBeginGetCalledOnce)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->NotifyGameLiftProcessReady();
|
||||
SessionNotificationsHandlerMock handlerMock;
|
||||
EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1);
|
||||
|
||||
Aws::GameLift::Server::Model::GameSession gameSession;
|
||||
gameSession.SetMatchmakerData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc(
|
||||
Aws::GameLift::Server::Model::UpdateGameSession(
|
||||
gameSession, Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED, "testticket"));
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithInvalidMatchmakingData_OnUpdateSessionBeginGetCalledOnce)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->NotifyGameLiftProcessReady();
|
||||
SessionNotificationsHandlerMock handlerMock;
|
||||
EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1);
|
||||
|
||||
Aws::GameLift::Server::Model::GameSession gameSession;
|
||||
gameSession.SetMatchmakerData("{invalid}");
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc(
|
||||
Aws::GameLift::Server::Model::UpdateGameSession(
|
||||
gameSession, Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED, "testticket"));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, ValidatePlayerJoinSession_CallWithInvalidConnectionConfig_GetFalseResultAndExpectedErrorLog)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
@@ -425,4 +614,331 @@ namespace UnitTest
|
||||
}
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(testThreadNumber - 1); // The player is only disconnected once.
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, UpdateGameSessionData_CallWithInvalidMatchmakingData_GetExpectedError)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_serverManager->SetupTestMatchmakingData("{invalid}");
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithInvalidMatchmakingData_GetEmptyResult)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_serverManager->SetupTestMatchmakingData("{invalid}");
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
EXPECT_TRUE(actualResult.empty());
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithEmptyMatchmakingData_GetEmptyResult)
|
||||
{
|
||||
m_serverManager->SetupTestMatchmakingData("");
|
||||
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
EXPECT_TRUE(actualResult.empty());
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallButDescribePlayerError_GetEmptyResult)
|
||||
{
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
Aws::GameLift::GameLiftError error;
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome errorOutcome(error);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(errorOutcome));
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_TRUE(actualResult.empty());
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallButNoActivePlayer_GetEmptyResult)
|
||||
{
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsResult result;
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(successOutcome));
|
||||
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
EXPECT_TRUE(actualResult.empty());
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithValidMatchmakingData_GetExpectedResult)
|
||||
{
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
Aws::GameLift::Server::Model::PlayerSession playerSession;
|
||||
playerSession.SetPlayerId("testplayer");
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsResult result;
|
||||
result.AddPlayerSessions(playerSession);
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(successOutcome));
|
||||
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
EXPECT_TRUE(actualResult.size() == 1);
|
||||
EXPECT_TRUE(actualResult[0].m_team == "testteam");
|
||||
EXPECT_TRUE(actualResult[0].m_playerId == "testplayer");
|
||||
EXPECT_TRUE(actualResult[0].m_playerAttributes.size() == 4);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithMultiDescribePlayerButError_GetEmptyResult)
|
||||
{
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA, 50);
|
||||
|
||||
Aws::GameLift::GameLiftError error;
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome errorOutcome(error);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(errorOutcome));
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_TRUE(actualResult.empty());
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithMultiDescribePlayer_GetExpectedResult)
|
||||
{
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA, 50);
|
||||
|
||||
Aws::GameLift::Server::Model::PlayerSession playerSession1;
|
||||
playerSession1.SetPlayerId("testplayer");
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsResult result1;
|
||||
result1.AddPlayerSessions(playerSession1);
|
||||
result1.SetNextToken("testtoken");
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome successOutcome1(result1);
|
||||
|
||||
Aws::GameLift::Server::Model::PlayerSession playerSession2;
|
||||
playerSession2.SetPlayerId("playernotinmatch");
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsResult result2;
|
||||
result2.AddPlayerSessions(playerSession2);
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome successOutcome2(result2);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.WillOnce(Return(successOutcome1))
|
||||
.WillOnce(Return(successOutcome2));
|
||||
|
||||
auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers();
|
||||
EXPECT_TRUE(actualResult.size() == 1);
|
||||
EXPECT_TRUE(actualResult[0].m_team == "testteam");
|
||||
EXPECT_TRUE(actualResult[0].m_playerId == "testplayer");
|
||||
EXPECT_TRUE(actualResult[0].m_playerAttributes.size() == 4);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_SDKNotInitialized_GetExpectedError)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", {});
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithEmptyMatchmakingData_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData("");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", {});
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithInvalidPlayerAttribute_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer();
|
||||
testPlayer.m_playerAttributes.clear();
|
||||
testPlayer.m_playerAttributes.emplace("invalidattribute", "{invalid}");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithWrongPlayerAttributeType_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer();
|
||||
testPlayer.m_playerAttributes.clear();
|
||||
testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"SDM\": [\"test1\"]}");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithUnexpectedPlayerAttributeType_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer();
|
||||
testPlayer.m_playerAttributes.clear();
|
||||
testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"UNEXPECTED\": [\"test1\"]}");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithWrongSLPlayerAttributeValue_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer();
|
||||
testPlayer.m_playerAttributes.clear();
|
||||
testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"SL\": [10.0]}");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithWrongSDMPlayerAttributeValue_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer();
|
||||
testPlayer.m_playerAttributes.clear();
|
||||
testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"SDM\": {10.0: \"test1\"}}");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithValidPlayersData_GetExpectedResult)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillResult backfillResult;
|
||||
Aws::GameLift::StartMatchBackfillOutcome backfillSuccessOutcome(backfillResult);
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest request = GetTestStartMatchBackfillRequest();
|
||||
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StartMatchBackfill(StartMatchBackfillRequestMatcher(request)))
|
||||
.Times(1)
|
||||
.WillOnce(Return(backfillSuccessOutcome));
|
||||
|
||||
AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer();
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", {testPlayer});
|
||||
EXPECT_TRUE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithoutGivingPlayersData_GetExpectedResult)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
Aws::GameLift::Server::Model::PlayerSession playerSession;
|
||||
playerSession.SetPlayerId("testplayer");
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsResult result;
|
||||
result.AddPlayerSessions(playerSession);
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(successOutcome));
|
||||
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillResult backfillResult;
|
||||
Aws::GameLift::StartMatchBackfillOutcome backfillSuccessOutcome(backfillResult);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StartMatchBackfill(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(backfillSuccessOutcome));
|
||||
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", {});
|
||||
EXPECT_TRUE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallButStartBackfillFail_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
Aws::GameLift::Server::Model::PlayerSession playerSession;
|
||||
playerSession.SetPlayerId("testplayer");
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsResult result;
|
||||
result.AddPlayerSessions(playerSession);
|
||||
Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(successOutcome));
|
||||
|
||||
Aws::GameLift::GameLiftError error;
|
||||
Aws::GameLift::StartMatchBackfillOutcome errorOutcome(error);
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StartMatchBackfill(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(errorOutcome));
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StartMatchBackfill("testticket", {});
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StopMatchBackfill_SDKNotInitialized_GetExpectedError)
|
||||
{
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StopMatchBackfill("testticket");
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StopMatchBackfill_CallWithEmptyMatchmakingData_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData("");
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StopMatchBackfill("testticket");
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StopMatchBackfill_CallAndSuccessOutcome_GetExpectedResult)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StopMatchBackfill(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(Aws::GameLift::GenericOutcome(nullptr)));
|
||||
|
||||
auto actualResult = m_serverManager->StopMatchBackfill("testticket");
|
||||
EXPECT_TRUE(actualResult);
|
||||
}
|
||||
|
||||
TEST_F(GameLiftServerManagerTest, StopMatchBackfill_CallButErrorOutcome_GetExpectedError)
|
||||
{
|
||||
m_serverManager->InitializeGameLiftServerSDK();
|
||||
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA);
|
||||
|
||||
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StopMatchBackfill(testing::_))
|
||||
.Times(1)
|
||||
.WillOnce(Return(Aws::GameLift::GenericOutcome()));
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
auto actualResult = m_serverManager->StopMatchBackfill("testticket");
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
EXPECT_FALSE(actualResult);
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AWSGameLiftPlayer.h>
|
||||
#include <AWSGameLiftServerSystemComponent.h>
|
||||
#include <AWSGameLiftServerManager.h>
|
||||
#include <GameLiftServerSDKWrapper.h>
|
||||
@@ -40,17 +41,25 @@ namespace UnitTest
|
||||
|
||||
MOCK_METHOD1(AcceptPlayerSession, GenericOutcome(const std::string&));
|
||||
MOCK_METHOD0(ActivateGameSession, GenericOutcome());
|
||||
MOCK_METHOD1(DescribePlayerSessions, DescribePlayerSessionsOutcome(
|
||||
const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest&));
|
||||
MOCK_METHOD0(InitSDK, Server::InitSDKOutcome());
|
||||
MOCK_METHOD1(ProcessReady, GenericOutcome(const Server::ProcessParameters& processParameters));
|
||||
MOCK_METHOD0(ProcessEnding, GenericOutcome());
|
||||
MOCK_METHOD1(RemovePlayerSession, GenericOutcome(const AZStd::string& playerSessionId));
|
||||
MOCK_METHOD0(GetTerminationTime, AZStd::string());
|
||||
MOCK_METHOD1(StartMatchBackfill, StartMatchBackfillOutcome(
|
||||
const Aws::GameLift::Server::Model::StartMatchBackfillRequest&));
|
||||
MOCK_METHOD1(StopMatchBackfill, GenericOutcome(
|
||||
const Aws::GameLift::Server::Model::StopMatchBackfillRequest&));
|
||||
|
||||
|
||||
GenericOutcome ProcessReadyMock(const Server::ProcessParameters& processParameters)
|
||||
{
|
||||
m_healthCheckFunc = processParameters.getOnHealthCheck();
|
||||
m_onStartGameSessionFunc = processParameters.getOnStartGameSession();
|
||||
m_onProcessTerminateFunc = processParameters.getOnProcessTerminate();
|
||||
m_onUpdateGameSessionFunc = processParameters.getOnUpdateGameSession();
|
||||
|
||||
GenericOutcome successOutcome(nullptr);
|
||||
return successOutcome;
|
||||
@@ -59,6 +68,7 @@ namespace UnitTest
|
||||
AZStd::function<bool()> m_healthCheckFunc;
|
||||
AZStd::function<void()> m_onProcessTerminateFunc;
|
||||
AZStd::function<void(Aws::GameLift::Server::Model::GameSession)> m_onStartGameSessionFunc;
|
||||
AZStd::function<void(Aws::GameLift::Server::Model::UpdateGameSession)> m_onUpdateGameSessionFunc;
|
||||
};
|
||||
|
||||
class AWSGameLiftServerManagerMock
|
||||
@@ -78,12 +88,25 @@ namespace UnitTest
|
||||
m_gameLiftServerSDKWrapperMockPtr = nullptr;
|
||||
}
|
||||
|
||||
void SetupTestMatchmakingData(const AZStd::string& matchmakingData, int maxPlayer = 10)
|
||||
{
|
||||
m_testGameSession.SetMatchmakerData(matchmakingData.c_str());
|
||||
m_testGameSession.SetMaximumPlayerSessionCount(maxPlayer);
|
||||
UpdateGameSessionData(m_testGameSession);
|
||||
}
|
||||
|
||||
bool AddConnectedTestPlayer(const AzFramework::PlayerConnectionConfig& playerConnectionConfig)
|
||||
{
|
||||
return AddConnectedPlayer(playerConnectionConfig);
|
||||
}
|
||||
|
||||
AZStd::vector<AWSGameLiftPlayer> GetTestServerMatchBackfillPlayers()
|
||||
{
|
||||
return GetActiveServerMatchBackfillPlayers();
|
||||
}
|
||||
|
||||
NiceMock<GameLiftServerSDKWrapperMock>* m_gameLiftServerSDKWrapperMockPtr;
|
||||
Aws::GameLift::Server::Model::GameSession m_testGameSession;
|
||||
};
|
||||
|
||||
class AWSGameLiftServerSystemComponentMock
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../AWSGameLiftCommon/Include/AWSGameLiftPlayer.h
|
||||
../AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp
|
||||
../AWSGameLiftCommon/Source/AWSGameLiftSessionConstants.h
|
||||
Include/Request/IAWSGameLiftServerRequests.h
|
||||
Source/AWSGameLiftServerManager.cpp
|
||||
|
||||
@@ -308,6 +308,12 @@ namespace Multiplayer
|
||||
return true;
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::OnUpdateSessionBegin(const AzFramework::SessionConfig& sessionConfig, const AZStd::string& updateReason)
|
||||
{
|
||||
AZ_UNUSED(sessionConfig);
|
||||
AZ_UNUSED(updateReason);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
|
||||
{
|
||||
const AZ::TimeMs deltaTimeMs = aznumeric_cast<AZ::TimeMs>(static_cast<int32_t>(deltaTime * 1000.0f));
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace Multiplayer
|
||||
bool OnSessionHealthCheck() override;
|
||||
bool OnCreateSessionBegin(const AzFramework::SessionConfig& sessionConfig) override;
|
||||
bool OnDestroySessionBegin() override;
|
||||
void OnUpdateSessionBegin(const AzFramework::SessionConfig& sessionConfig, const AZStd::string& updateReason) override;
|
||||
//! @}
|
||||
|
||||
//! AZ::TickBus::Handler overrides.
|
||||
|
||||
Reference in New Issue
Block a user