Lesson 35 - Get Compute Auth Token Working

This commit is contained in:
Norman Lansing
2026-02-28 12:32:28 -05:00
parent 1d477ee42a
commit 4fde462bce
7743 changed files with 1397833 additions and 18 deletions

View File

@@ -0,0 +1,63 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using UnrealBuildTool;
using System.IO;
namespace UnrealBuildTool.Rules
{
public class GameLiftCore : ModuleRules
{
public GameLiftCore(ReadOnlyTargetRules Target)
: base(Target)
{
PrivateIncludePaths.AddRange(
new string[]
{
"GameLiftCore/Private",
"AWSSDK",
"CoreSDK",
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"AWSSDK",
"CoreSDK",
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"InputCore",
"Slate",
"UnrealEd",
"Projects",
"DesktopPlatform",
"ApplicationCore",
"AutomationDriver",
"EngineSettings",
}
);
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Public"));
PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "Private"));
PublicDefinitions.Add("USE_IMPORT_EXPORT");
if (Target.Platform == UnrealTargetPlatform.Win64)
{
PublicDefinitions.Add("WITH_BASE=1");
}
else
{
PublicDefinitions.Add("WITH_BASE=0");
}
}
}
}

View File

@@ -0,0 +1,159 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "AWSBootstrapProfile.h"
#include "AwsAccount/AwsAccountInstanceManager.h"
#include "GameLiftCoreLog.h"
#include "GameLiftCoreConstants.h"
#include "IGameLiftCoreModule.h"
#include "Utils/StringPaths.h"
#include "Utils/LogMessageStorage.h"
#include "Utils/NativeLogPrinter.h"
#include "aws/gamelift/core/exports.h"
#include "aws/gamelift/core/errors.h"
#include "AwsErrors/Converter.h"
namespace AwsBootstrapInternal
{
static Logs::MessageStorage sLatestDeploymentLogErrorMessage = {};
void LogCallback(unsigned int InLevel, const char* InMessage, int InSize)
{
auto Level = Logs::PrintAwsLog(InLevel, InMessage, InSize, Bootstrap::Logs::kLogReceived);
if (Level == ELogVerbosity::Error)
{
sLatestDeploymentLogErrorMessage.Set(InMessage);
}
}
class EmptyAccount : public IAWSAccountInstance
{
public:
bool IsValid() const override { return false; }
void* GetInstance() const override { return nullptr; }
FString GetBucketName() const override { return FString(); }
const char* GetGameName() const override { return ""; }
const char* GetAccountId() const override { return ""; }
const char* GetBuildConfiguration() const override { return ""; }
FString GetLastErrorMessage() const override { return FString(); }
};
void ReceiveResult(DISPATCH_RECEIVER_HANDLE DispatchReceiver, const char* BucketName)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("%s %s"), Bootstrap::Logs::kReceiveBucketNameCallback, *FString(BucketName));
((AwsAccountInstanceManager*)DispatchReceiver)->SetBucketName(BucketName);
}
} // namespace AwsBootstrapInternal
#define LOCTEXT_NAMESPACE "AWSBootstrapProfile"
AWSBootstrapProfile::AWSBootstrapProfile() :
AwsAccountInstance(MakeUnique<AwsBootstrapInternal::EmptyAccount>())
{
}
bool AWSBootstrapProfile::ConfigureAccount(const FString& ProfileName,
TSharedRef<IAWSConfigFileProfile> ProfileReader, const FString& ExistingBucketName)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("%s"), Bootstrap::Logs::kBootstrapStarted);
AwsBootstrapInternal::sLatestDeploymentLogErrorMessage.Clear();
AwsAccountInstance = MakeUnique<AwsBootstrapInternal::EmptyAccount>();
TUniquePtr<AwsAccountInstanceManager> AccountInstance = MakeUnique<AwsAccountInstanceManager>();
FString PluginRootPath = Paths::ScenarioPath("scenario_common");
FString GameLiftRootPath = Paths::ScenarioInstancePath("scenario_common");
LastError = AccountInstance->BuildInstance(ProfileName, ProfileReader, ExistingBucketName, GameLiftRootPath, PluginRootPath);
if (LastError != GameLift::GAMELIFT_SUCCESS)
{
AwsBootstrapInternal::sLatestDeploymentLogErrorMessage.Set(AccountInstance->GetLastErrorMessage());
UE_LOG(GameLiftCoreLog, Warning, TEXT("%s %s."), Bootstrap::Logs::kBootstrapFailedCreateAccount, *GameLiftErrorAsString::Convert(LastError));
return false;
}
AccountInstance->SetBucketName(ExistingBucketName);
AwsAccountInstance = std::move(AccountInstance);
return true;
}
FString AWSBootstrapProfile::GetDefaultBucketName(const FString& ProfileName,
TSharedRef<IAWSConfigFileProfile> ProfileReader) const
{
// Generate bootstrap bucket name with the following format:
// do-not-delete-gamelift-<env>-<5_letter_aws_region_code>-<base36_account_id>
TUniquePtr<AwsAccountInstanceManager> AccountInstance = MakeUnique<AwsAccountInstanceManager>();
FString PluginRootPath = Paths::ScenarioPath("scenario_common");
FString GameLiftRootPath = Paths::ScenarioInstancePath("scenario_common");
int Result = AccountInstance->BuildInstance(ProfileName, ProfileReader, "", GameLiftRootPath, PluginRootPath);
FString DefaultBucketName = GameLiftAccountGetDefaultBucketName(AccountInstance->GetInstance());
// If the profile is invalid, <base36_account_id> is empty
// Handle this edge case by removing the trailing '-'
if (Result != GameLift::GAMELIFT_SUCCESS)
{
DefaultBucketName.RemoveFromEnd("-");
}
return DefaultBucketName;
}
bool AWSBootstrapProfile::Bootstrap(const FString& NewBucketName)
{
AwsBootstrapInternal::sLatestDeploymentLogErrorMessage.Clear();
if (AwsAccountInstance->IsValid())
{
if (!NewBucketName.IsEmpty())
{
std::string bootstrapBucketName = Convertors::FSToStdS(NewBucketName);
GameLiftAccountSetBucketName(AwsAccountInstance->GetInstance(), bootstrapBucketName.c_str());
}
// If bucket name was not provided during ConfigureAccount
// or this method, a default bucket name will be used
LastError = GameLiftAccountInstanceBootstrap(AwsAccountInstance->GetInstance(), AwsAccountInstance.Get(), &AwsBootstrapInternal::ReceiveResult);
if (LastError == GameLift::GAMELIFT_SUCCESS)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("%s"), Bootstrap::Logs::kBootstrapCompleted);
return true;
}
else
{
UE_LOG(GameLiftCoreLog, Warning, TEXT("%s %s."), Bootstrap::Logs::kBootstrapFailedBootstrap, *GameLiftErrorAsString::Convert(LastError));
return false;
}
}
LastError = GameLift::GAMELIFT_ERROR_GENERAL;
UE_LOG(GameLiftCoreLog, Warning, TEXT("%s"), Bootstrap::Logs::kBootstrapFailedAccountNotValid);
return false;
}
FString AWSBootstrapProfile::GetLastError() const
{
return GameLiftErrorAsString::Convert(LastError);
}
FString AWSBootstrapProfile::GetLastErrorMessage() const
{
return AwsBootstrapInternal::sLatestDeploymentLogErrorMessage.Get();
}
IAWSAccountInstance* AWSBootstrapProfile::GetAccountInstance()
{
return AwsAccountInstance.Get();
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,23 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IAWSBootstrapProfile.h"
class AWSBootstrapProfile : public IAWSBootstrapProfile
{
public:
AWSBootstrapProfile();
bool ConfigureAccount(const FString& ProfileName, TSharedRef<IAWSConfigFileProfile> ProfileReader, const FString& ExistingBucketName = "") override;
bool Bootstrap(const FString& NewBucketName = "") override;
FString GetLastError() const override;
FString GetLastErrorMessage() const override;
FString GetDefaultBucketName(const FString& ProfileName, TSharedRef<IAWSConfigFileProfile> ProfileReader) const override;
IAWSAccountInstance* GetAccountInstance() override;
private:
int LastError = 0;
TUniquePtr<IAWSAccountInstance> AwsAccountInstance;
};

View File

@@ -0,0 +1,110 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "AWSConfigFileProfile.h"
#include "GameLiftCoreLog.h"
#include "Utils/StringConvertors.h"
#define LOCTEXT_NAMESPACE "AWSConfigFileProfile"
AWSConfigFileProfile::AWSConfigFileProfile()
{
auto LogProxy = [](unsigned int InLevel, const char* InMessage, int InSize)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("********* %s"), UTF8_TO_TCHAR(InMessage));
};
ConfigManagerInstance = GameLiftConfigManagerInstanceCreate(LogProxy);
}
AWSConfigFileProfile::~AWSConfigFileProfile()
{
GameLiftConfigManagerInstanceRelease(ConfigManagerInstance);
ConfigManagerInstance = nullptr;
}
TArray<FString> AWSConfigFileProfile::GetProfileNames() const
{
TArray<FString> ProfilesNames;
auto ProfileNameCallback = [](DISPATCH_RECEIVER_HANDLE ProfileNamesArray, const char* ProfileName)
{
((TArray<FString>*)(ProfileNamesArray))->Emplace(Convertors::ASToFS(ProfileName));
};
GameLiftConfigManagerGetProfileNames(ConfigManagerInstance, (void*)(&ProfilesNames), ProfileNameCallback);
return ProfilesNames;
}
void AWSConfigFileProfile::CreateProfile(const FString& ProfileName)
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
GameLiftConfigManagerCreateProfile(ConfigManagerInstance, StdProfileName.c_str());
}
void AWSConfigFileProfile::RenameProfile(const FString& ProfileName, const FString& NewProfileName)
{
auto StdProfileName = Convertors::FSToStdS(ProfileName);
auto stdNewProfileName = Convertors::FSToStdS(NewProfileName);
GameLiftConfigManagerRenameProfile(ConfigManagerInstance, StdProfileName.c_str(), stdNewProfileName.c_str());
}
FString AWSConfigFileProfile::GetAccessKey(const FString& ProfileName) const
{
auto StdProfileName = Convertors::FSToStdS(ProfileName);
return Convertors::ASToFS(GameLiftConfigManagerGetAccessKey(ConfigManagerInstance, StdProfileName.c_str()));
}
void AWSConfigFileProfile::SetAccessKey(const FString& ProfileName, const FString& AccessKey)
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
std::string stdAccessKey = Convertors::FSToStdS(AccessKey);
GameLiftConfigManagerSetAccessKey(ConfigManagerInstance, StdProfileName.c_str(), stdAccessKey.c_str());
}
FString AWSConfigFileProfile::GetSecretAccessKey(const FString& ProfileName) const
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
return Convertors::ASToFS(GameLiftConfigManagerGetSecretAccessKey(ConfigManagerInstance, StdProfileName.c_str()));
}
void AWSConfigFileProfile::SetSecretAccessKey(const FString& ProfileName, const FString& SecretAccessKey)
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
std::string stdSecretKey = Convertors::FSToStdS(SecretAccessKey);
GameLiftConfigManagerSetSecretAccessKey(ConfigManagerInstance, StdProfileName.c_str(), stdSecretKey.c_str());
}
FString AWSConfigFileProfile::GetSessionToken(const FString& ProfileName) const
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
return Convertors::ASToFS(GameLiftConfigManagerGetSessionToken(ConfigManagerInstance, StdProfileName.c_str()));
}
void AWSConfigFileProfile::SetSessionToken(const FString& ProfileName, const FString& SessionToken)
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
std::string stdSessionToken = Convertors::FSToStdS(SessionToken);
GameLiftConfigManagerSetSessionToken(ConfigManagerInstance, StdProfileName.c_str(), stdSessionToken.c_str());
}
FString AWSConfigFileProfile::GetRegion(const FString& ProfileName) const
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
return Convertors::ASToFS(GameLiftConfigManagerGetRegion(ConfigManagerInstance, StdProfileName.c_str()));
}
void AWSConfigFileProfile::SetRegion(const FString& ProfileName, const FString& Region)
{
std::string StdProfileName = Convertors::FSToStdS(ProfileName);
std::string StdRegion = Convertors::FSToStdS(Region);
GameLiftConfigManagerSetRegion(ConfigManagerInstance, StdProfileName.c_str(), StdRegion.c_str());
}
void AWSConfigFileProfile::Save()
{
GameLiftConfigManagerSave(ConfigManagerInstance);
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,34 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IAWSConfigFileProfile.h"
#include "aws/gamelift/core/config/exports.h"
class AWSConfigFileProfile : public IAWSConfigFileProfile
{
public:
AWSConfigFileProfile();
virtual ~AWSConfigFileProfile() override;
virtual TArray<FString> GetProfileNames() const override;
virtual void CreateProfile(const FString& ProfileName) override;
virtual void RenameProfile(const FString& ProfileName, const FString& NewProfileName) override;
virtual FString GetAccessKey(const FString& ProfileName) const override;
virtual void SetAccessKey(const FString& ProfileName, const FString& AccessKey) override;
virtual FString GetSecretAccessKey(const FString& ProfileName) const override;
virtual void SetSecretAccessKey(const FString& ProfileName, const FString& SecretAccessKey) override;
virtual FString GetSessionToken(const FString& ProfileName) const override;
virtual void SetSessionToken(const FString& ProfileName, const FString& SessionToken) override;
virtual FString GetRegion(const FString& ProfileName) const override;
virtual void SetRegion(const FString& ProfileName, const FString& Region) override;
virtual void Save() override;
private:
GAMELIFT_CONFIGMANAGER_INSTANCE_HANDLE ConfigManagerInstance;
};

View File

@@ -0,0 +1,565 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "AWSScenariosDeployer.h"
#include "Misc/FileHelper.h"
#include "Misc/EngineVersionComparison.h"
#include "aws/gamelift/core/exports.h"
#include "aws/gamelift/core/errors.h"
#include "GameLiftCoreLog.h"
#include "GameLiftCoreConstants.h"
#include "AwsAccount/AwsAccountCredentials.h"
#include "AwsAccount/AwsAccountInstanceManager.h"
#include "AwsAccount/AwsAccountInfo.h"
#include "Utils/StringPaths.h"
#include "Utils/StringConvertors.h"
#include "Utils/LogMessageStorage.h"
#include "Utils/NativeLogPrinter.h"
#include "Utils/UnrealVersion.h"
#include "AwsErrors/Converter.h"
#include "AwsScenarios/ContainerFlexMatch.h"
#include "AwsScenarios/ContainerSingleRegionFleet.h"
#include "AwsScenarios/FlexMatch.h"
#include "AwsScenarios/SingleRegionFleet.h"
#include "AwsScenarios/CustomScenario.h"
#define LOCTEXT_NAMESPACE "AWSScenariosDeployer"
namespace AwsDeployerInternal
{
static Logs::MessageStorage sLatestDeploymentLogErrorMessage = {};
void LogCallback(unsigned int InLevel, const char* InMessage, int InSize)
{
auto Level = Logs::PrintAwsLog(InLevel, InMessage, InSize, Deploy::Logs::kLogReceived);
if (Level == ELogVerbosity::Error)
{
sLatestDeploymentLogErrorMessage.Set(InMessage);
}
}
void ReceiveReplacementId(DISPATCH_RECEIVER_HANDLE DispatchReceiver, const char* ReplacementId)
{
UE_LOG(GameLiftCoreLog, Verbose, TEXT("%s %s"), Deploy::Logs::kReceiveReplacementIdCallback, *Convertors::ASToFS(ReplacementId));
((AWSScenariosDeployer*)DispatchReceiver)->SetMainFunctionsReplacementId(ReplacementId);
}
void ReceiveClientConfigPath(DISPATCH_RECEIVER_HANDLE DispatchReceiver, const char* ConfigPath)
{
UE_LOG(GameLiftCoreLog, Verbose, TEXT("%s %s"), Deploy::Logs::kReceiveClientConfigPathCallback, *Convertors::ASToFS(ConfigPath));
((AWSScenariosDeployer*)DispatchReceiver)->SetClientConfigPath(ConfigPath);
}
auto BuildAwsScenarios(const IAWSScenariosCategory Category)
{
TMap<FString, TUniquePtr<AwsScenarios::IAWSScenario>> ScenarioMap;
switch (Category)
{
case IAWSScenariosCategory::ManagedEC2:
{
ScenarioMap.Add(AwsScenarios::SingleRegionFleet::Name().ToString(),
AwsScenarios::SingleRegionFleet::Create());
ScenarioMap.Add(AwsScenarios::FlexMatch::Name().ToString(),
AwsScenarios::FlexMatch::Create());
break;
}
case IAWSScenariosCategory::Containers:
{
ScenarioMap.Add(AwsScenarios::ContainersSingleRegionFleet::Name().ToString(),
AwsScenarios::ContainersSingleRegionFleet::Create());
ScenarioMap.Add(AwsScenarios::ContainersFlexMatch::Name().ToString(),
AwsScenarios::ContainersFlexMatch::Create());
break;
}
}
return ScenarioMap;
}
const auto& GetAwsScenarios(const IAWSScenariosCategory Category)
{
static TMap<FString, TUniquePtr<AwsScenarios::IAWSScenario>>
ManagedEC2ScenarioMap(BuildAwsScenarios(IAWSScenariosCategory::ManagedEC2));
static TMap<FString, TUniquePtr<AwsScenarios::IAWSScenario>>
ContainersScenarioMap(BuildAwsScenarios(IAWSScenariosCategory::Containers));
switch (Category)
{
case IAWSScenariosCategory::ManagedEC2:
{
return ManagedEC2ScenarioMap;
}
case IAWSScenariosCategory::Containers:
{
return ContainersScenarioMap;
}
default:
{
static TMap<FString, TUniquePtr<AwsScenarios::IAWSScenario>> DefaultMap = {};
return DefaultMap;
}
}
}
AwsScenarios::IAWSScenario* GetAwsScenarioByName(const FText& ScenarioName, const IAWSScenariosCategory Category)
{
auto Invariant = FText::AsCultureInvariant(ScenarioName);
return GetAwsScenarios(Category).FindChecked(Invariant.ToString()).Get();
}
FString ExtractYamlValue(const TArray<FString>& YamlStrings, const char* Name)
{
for (const FString& Line : YamlStrings)
{
auto FoundPosition = Line.Find(Name);
if (FoundPosition >= 0)
{
FoundPosition += strlen(Name);
return Line.RightChop(FoundPosition + 1);
}
}
return FString();
}
class ResourcesInstanceGuard
{
public:
ResourcesInstanceGuard(IAWSAccountInstance* AwsAccountInstance) :
Instance(GameLiftAccountCreateGameLiftResourcesInstance(AwsAccountInstance->GetInstance()))
{
}
~ResourcesInstanceGuard()
{
GameLiftResourcesInstanceRelease(Instance);
}
GAMELIFT_FEATURERESOURCES_INSTANCE_HANDLE Get()
{
return Instance;
}
private:
GAMELIFT_FEATURERESOURCES_INSTANCE_HANDLE Instance;
};
bool IsDeployedSuccessfully(const std::string& StackStatus)
{
static std::unordered_set<std::string> SuccessfulStatuses
{
Aws::Status::kStackUpdateComplete, Aws::Status::kStackCreateComplete
};
return SuccessfulStatuses.find(StackStatus) != SuccessfulStatuses.end();
}
} // namespace AwsDeployerInternal
void AWSScenariosDeployer::SetMainFunctionsReplacementId(const char* ReplacementId)
{
MainFunctionsReplacementId = ReplacementId;
}
void AWSScenariosDeployer::SetClientConfigPath(const char* ConfigPath)
{
ClientConfigPath = Convertors::ASToFS(ConfigPath);
}
void AWSScenariosDeployer::SetLastCognitoClientId(const FString& ClientId)
{
LastCognitoClientId = ClientId;
}
void AWSScenariosDeployer::SetLastApiGatewayEndpoint(const FString& ApiGateway)
{
LastApiGatewayEndpoint = ApiGateway;
}
/**
* Returns the Unreal Engine version used to package the game server build
*
* @param AwsAccountInstance Pointer to AwsAccountInstance to call APIs
* @param BuildFilePath Path to the packaged game server executable
* @return PackagedVersion Unreal Engine version used to package the game server build
*/
UnrealVersion::Version GetUnrealPackagedBuildVersion(IAWSAccountInstance* AwsAccountInstance, const FString& BuildFilePath)
{
AwsDeployerInternal::ResourcesInstanceGuard ResourcesInstance(AwsAccountInstance);
std::string ExecutablePath = Convertors::FSToStdS(BuildFilePath);
FString PackagedVersionString = Convertors::ASToFS(GameLiftResourcesGetUnrealPackagedBuildVersion(ResourcesInstance.Get(), ExecutablePath));
UnrealVersion::Version PackagedVersion = UnrealVersionUtils::ParseVersionString(PackagedVersionString);
if (PackagedVersion == UnrealVersion::INVALID_VERSION) {
// We failed to determine version, proceed with deployment without copying dependencies
UE_LOG(GameLiftCoreLog, Log, TEXT("Failed to determine version from %s"), *BuildFilePath);
}
else {
UE_LOG(GameLiftCoreLog, Log, TEXT("Detected game server build packaged with Unreal Version %s from game server executable path %s"),
*UnrealVersionUtils::GetVersionString(PackagedVersion), *BuildFilePath);
}
return PackagedVersion;
}
/**
* Sets extra server resources path for older Unreal Engine versions if needed
* For UE versions older than 5.6.0, we need to copy additional dependencies
*
* @param ExtraServerResources Path Path to the extra resources that may need to be copied
* @param Params Deployment parameters to be updated with extra resources path if needed
* @return True if extra server resources path was set
*/
bool SetExtraServerResourcesPath(UnrealVersion::Version PackagedVersion, const FString& ExtraServerResourcesPath, AwsScenarios::ManagedEC2InstanceTemplateParams& Params)
{
// UE5.6.0 does not require extra dependencies
if (PackagedVersion < UnrealVersion::UE5_6_0) {
UE_LOG(GameLiftCoreLog, Log, TEXT("Required dependencies will automatically be copied from %s since game server packaged version is < 5.6.0"),
*ExtraServerResourcesPath);
Params.ExtraServerResourcesPath = Convertors::FSToStdS(ExtraServerResourcesPath);
return true;
}
return false;
}
bool AWSScenariosDeployer::DeployManagedEC2Scenario(
const FText& Scenario,
IAWSAccountInstance* AwsAccountInstance,
const FString& GameName,
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
const FString& OutConfigFilePath,
const FString& ExtraServerResourcesPath,
bool EnableMetrics
)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("%s %s"), Deploy::Logs::kRunAwsScenario, *Scenario.ToString());
AwsScenarios::IAWSScenario* BaseAwsScenario = AwsDeployerInternal::GetAwsScenarioByName(Scenario, IAWSScenariosCategory::ManagedEC2);
AwsScenarios::ScenarioWithGameServer* AwsScenario = static_cast<AwsScenarios::ScenarioWithGameServer*>(BaseAwsScenario);
std::string stdLaunchPathParameter;
AwsScenario->CreateLaunchPathParameter(BuildOperatingSystem, BuildFolderPath, BuildFilePath, stdLaunchPathParameter);
AwsScenarios::ManagedEC2InstanceTemplateParams Params;
Params.GameNameParameter = Convertors::FSToStdS(GameName);
Params.BuildFolderPath = Convertors::FSToStdS(BuildFolderPath);
UnrealVersion::Version PackagedVersion = GetUnrealPackagedBuildVersion(AwsAccountInstance, BuildFilePath);
SetExtraServerResourcesPath(PackagedVersion, ExtraServerResourcesPath, Params);
Params.BuildOperatingSystemParameter = Convertors::FSToStdS(BuildOperatingSystem);
Params.LaunchPathParameter = stdLaunchPathParameter;
Params.EnableMetricsParameter = EnableMetrics ? "true" : "false";
return DeployScenarioImpl(AwsAccountInstance, AwsScenario, Params, OutConfigFilePath);
}
bool AWSScenariosDeployer::DeployCustomScenario(
const FString& CustomScenarioPath,
IAWSAccountInstance* AwsAccountInstance,
const FString& GameName,
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
const FString& OutConfigFilePath,
const FString& ExtraServerResourcesPath
)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("%s %s"), Deploy::Logs::kRunCustomScenario, *CustomScenarioPath);
TUniquePtr<AwsScenarios::CustomScenario> AwsScenario = AwsScenarios::CustomScenario::Create(CustomScenarioPath);
std::string stdLaunchPathParameter;
AwsScenario->CreateLaunchPathParameter(BuildOperatingSystem, BuildFolderPath, BuildFilePath, stdLaunchPathParameter);
AwsScenarios::ManagedEC2InstanceTemplateParams Params;
Params.GameNameParameter = Convertors::FSToStdS(GameName);
Params.BuildFolderPath = Convertors::FSToStdS(BuildFolderPath);
Params.ExtraServerResourcesPath = Convertors::FSToStdS(ExtraServerResourcesPath);
Params.BuildOperatingSystemParameter = Convertors::FSToStdS(BuildOperatingSystem);
Params.LaunchPathParameter = stdLaunchPathParameter;
return DeployScenarioImpl(AwsAccountInstance, AwsScenario.Get(), Params, OutConfigFilePath);
}
bool AWSScenariosDeployer::DeployContainerScenario(
const FText& Scenario, IAWSAccountInstance* AwsAccountInstance, const FString& ContainerGroupDefinitionName,
const FString& ContainerImageName, const FString& ContainerImageUri, const FString& IntraContainerLaunchPath,
const FString& GameName, const FString& OutConfigFilePath, const FText& ConnectionPortRange, const FString& TotalVcpuLimit,
const FString& TotalMemoryLimit, bool EnableMetrics)
{
AwsScenarios::IAWSScenario* AwsScenario = AwsDeployerInternal::GetAwsScenarioByName(
Scenario,
IAWSScenariosCategory::Containers);
auto StdBootstrapBucketName = Convertors::FSToStdS(AwsAccountInstance->GetBucketName());
AwsScenarios::ContainerInstanceTemplateParams Params;
Params.GameNameParameter = Convertors::FSToStdS(GameName);
Params.ContainerGroupDefinitionNameParameter = Convertors::FSToStdS(ContainerGroupDefinitionName);
Params.ContainerImageNameParameter = Convertors::FSToStdS(ContainerImageName);
Params.ContainerImageUriParameter = Convertors::FSToStdS(ContainerImageUri);
Params.LaunchPathParameter = Convertors::FSToStdS(IntraContainerLaunchPath);
FString FleetUdpFromPort;
FString FleetUdpToPort;
ConnectionPortRange.ToString().Split("-", &FleetUdpFromPort, &FleetUdpToPort);
Params.FleetUdpFromPortParameter = Convertors::FSToStdS(FleetUdpFromPort);
Params.FleetUdpToPortParameter = Convertors::FSToStdS(FleetUdpToPort);
Params.TotalVcpuLimitParameter = Convertors::FSToStdS(TotalVcpuLimit);
Params.TotalMemoryLimitParameter = Convertors::FSToStdS(TotalMemoryLimit);
Params.EnableMetricsParameter = EnableMetrics ? "true" : "false";
return DeployScenarioImpl(AwsAccountInstance, AwsScenario, Params, OutConfigFilePath);
}
bool AWSScenariosDeployer::StopDeployment(IAWSAccountInstance* AwsAccountInstance)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("%s"), Deploy::Logs::kDeploymentStop);
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Clear();
if (!AwsAccountInstance->IsValid())
{
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Set(Deploy::Errors::kAccountIsInvalidText);
return false;
}
AwsDeployerInternal::ResourcesInstanceGuard ResourcesInstance(AwsAccountInstance);
std::string StackStatus = GameLiftResourcesGetCurrentStackStatus(ResourcesInstance.Get());
if (StackStatus.compare(Aws::Status::kStackUndeployed) == 0)
{
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Set(Deploy::Errors::kNoStacksToStopDeployment);
return false;
}
ShouldBeStopped = true;
bool IsStopped = GameLiftResourcesInstanceCancelUpdateStack(ResourcesInstance.Get()) == GameLift::GAMELIFT_SUCCESS;
if (!IsStopped)
{
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Set(Deploy::Errors::kUnableToStopDeployment);
}
return IsStopped;
}
bool AWSScenariosDeployer::DeployScenarioImpl(
IAWSAccountInstance* AwsAccountInstance,
AwsScenarios::IAWSScenario* AwsScenario,
AwsScenarios::BaseInstanceTemplateParams& Params,
const FString& OutConfigFilePath
)
{
constexpr auto DeployAbortResult = false;
constexpr auto DeployCompletedResult = true;
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Clear();
ShouldBeStopped = false;
auto AccountHandle = AwsAccountInstance->GetInstance();
if (AccountHandle == nullptr)
{
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Set(Deploy::Errors::kAccountIsInvalidText);
LastAwsError = GameLift::GAMELIFT_ERROR_GENERAL;
UE_LOG(GameLiftCoreLog, Error, TEXT("%s"), Deploy::Logs::kAccountInstanceIsNull);
return DeployAbortResult;
}
if (Params.GameNameParameter.size() > Deploy::kMaxGameNameWithPrefixLength)
{
AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Set(Deploy::Errors::kGameNameIsTooLongText);
LastAwsError = GameLift::GAMELIFT_ERROR_GENERAL;
return DeployAbortResult;
}
GameLiftAccountSetGameName(AccountHandle, Params.GameNameParameter.c_str());
auto ScenarioPath = AwsScenario->GetScenarioPath();
auto StdScenarioPath = Convertors::FSToStdS(ScenarioPath);
GameLiftAccountSetPluginRootPath(AccountHandle, StdScenarioPath.c_str());
auto ScenarioInstancePath = AwsScenario->GetScenarioInstancePath();
auto StdScenarioInstancePath = Convertors::FSToStdS(ScenarioInstancePath);
GameLiftAccountSetRootPath(AccountHandle, StdScenarioInstancePath.c_str());
std::string StdAwsAccountId = GameLiftGetAwsAccountIdByAccountInstance(AccountHandle);
if (ShouldBeStopped)
{
LastAwsError = GameLift::GAMELIFT_ERROR_GENERAL;
UE_LOG(GameLiftCoreLog, Error, TEXT("%s"), Deploy::Logs::kDeploymentHasBeenStopped);
return DeployAbortResult;
}
auto ShouldDeployBeAborted = [this](int ErrorCode, auto&& ErrorDebugString)
{
LastAwsError = ErrorCode;
if (LastAwsError != GameLift::GAMELIFT_SUCCESS)
{
UE_LOG(GameLiftCoreLog, Error, TEXT("%s %s"), ErrorDebugString, *GameLiftErrorAsString::Convert(LastAwsError));
return true;
}
if (ShouldBeStopped)
{
LastAwsError = GameLift::GAMELIFT_ERROR_GENERAL;
UE_LOG(GameLiftCoreLog, Error, TEXT("%s"), Deploy::Logs::kDeploymentHasBeenStopped);
return true;
}
return false;
};
if (ShouldDeployBeAborted(GameLiftAccountCreateAndSetFunctionsReplacementId(AccountHandle), Deploy::Logs::kCreateAndSetFunctionsReplacementIdFailed))
{
return DeployAbortResult;
}
if (ShouldDeployBeAborted(GameLiftAccountGetMainFunctionsReplacementId(AccountHandle, this, AwsDeployerInternal::ReceiveReplacementId),
Deploy::Logs::kGetMainFunctionsReplacementIdFailed))
{
return DeployAbortResult;
}
auto StdBootstrapBucketName = Convertors::FSToStdS(AwsAccountInstance->GetBucketName());
if (ShouldDeployBeAborted(AwsScenario->UploadGameServer(AwsAccountInstance, Params.BuildFolderPath.c_str(), Params.ExtraServerResourcesPath.c_str()),
Deploy::Logs::kUploadGameServerFailed))
{
return DeployAbortResult;
}
Params.AccountId = StdAwsAccountId;
Params.ApiGatewayStageNameParameter = AwsAccountInstance->GetBuildConfiguration();
Params.BuildS3BucketParameter = StdBootstrapBucketName;
Params.LambdaZipS3BucketParameter = StdBootstrapBucketName;
Params.LambdaZipS3KeyParameter = AwsScenarios::GetLambdaS3Key(Params.GameNameParameter, MainFunctionsReplacementId);
Params.UnrealEngineVersionParameter = Convertors::FSToStdS(UnrealVersionUtils::GetCurrentEngineVersion());
if (ShouldDeployBeAborted(AwsScenario->SaveFeatureInstanceTemplate(AwsAccountInstance, Params.ToMap()),
Deploy::Logs::kSaveFeatureInstanceTemplatesFailed))
{
return DeployAbortResult;
}
if (ShouldDeployBeAborted(GameLiftAccountUploadFunctions(AccountHandle), Deploy::Logs::kAccountUploadFunctionsFailed))
{
return DeployAbortResult;
}
if (ShouldDeployBeAborted(GameLiftAccountCreateOrUpdateMainStack(AccountHandle), Deploy::Logs::kCreateOrUpdateMainStackFailed))
{
return DeployAbortResult;
}
if (ShouldDeployBeAborted(GameLiftAccountDeployApiGatewayStage(AccountHandle), Deploy::Logs::kDeployApiGatewayStageFailed))
{
return DeployAbortResult;
}
if (ShouldDeployBeAborted(UpdateDeploymentResults(AwsAccountInstance, ScenarioInstancePath, FString(Params.GameNameParameter.c_str()), AwsAccountInstance->GetBucketName(), OutConfigFilePath),
Deploy::Logs::kDeploymentStackStatusFailed))
{
return DeployAbortResult;
}
return DeployCompletedResult;
}
int AWSScenariosDeployer::UpdateDeploymentResults(IAWSAccountInstance* AwsAccountInstance, const FString& ScenarioInstancePath, const FString& GameName, const FString& BucketName, const FString& OutConfigFilePath)
{
AwsDeployerInternal::ResourcesInstanceGuard ResourcesInstance(AwsAccountInstance);
// Result will be stored to ClientConfigPath with sync call.
GameLiftResourcesGetInstanceClientConfigPath(ResourcesInstance.Get(), this, AwsDeployerInternal::ReceiveClientConfigPath);
std::string StackStatus = GameLiftResourcesGetCurrentStackStatus(ResourcesInstance.Get());
UE_LOG(GameLiftCoreLog, Log, TEXT("%s %s"), Deploy::Logs::kDeploymentStackStatus, *Convertors::ASToFS(StackStatus.c_str()));
auto CurrentScenarioInstancePath = Paths::ScenarioInstancePath(Menu::DeploymentServer::kCurrentScenarioFolder);
FString ConfigPathPart, ConfigFilenamePart, ConfigExtensionPart;
FPaths::Split(ClientConfigPath, ConfigPathPart, ConfigFilenamePart, ConfigExtensionPart);
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
PlatformFile.DeleteDirectoryRecursively(*CurrentScenarioInstancePath);
PlatformFile.CopyDirectoryTree(*CurrentScenarioInstancePath, *ConfigPathPart, true);
FString DestinationFileName = ConfigFilenamePart + "." + ConfigExtensionPart;
PlatformFile.CreateDirectoryTree(*OutConfigFilePath);
PlatformFile.CopyFile(*FPaths::Combine(OutConfigFilePath, DestinationFileName), *ClientConfigPath);
FString UUID;
FString Temp;
BucketName.Split("-", &Temp, &UUID, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
FString Region;
Temp.Split("-", &Temp, &Region, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
FString DestinationFileNameExtra = GameName + "_" + UUID + "_" + Region + "_" + ConfigFilenamePart + "." + ConfigExtensionPart;
PlatformFile.CopyFile(*FPaths::Combine(OutConfigFilePath, DestinationFileNameExtra), *ClientConfigPath);
TArray<FString> YamlStrings;
FFileHelper::LoadANSITextFileToStrings(*ClientConfigPath, NULL, YamlStrings);
LastCognitoClientId = AwsDeployerInternal::ExtractYamlValue(YamlStrings, Aws::Config::kUserPoolClientIdYamlName).TrimStartAndEnd();
LastApiGatewayEndpoint = AwsDeployerInternal::ExtractYamlValue(YamlStrings, Aws::Config::kApiGatewayEndpointYamlName).TrimStartAndEnd();
return AwsDeployerInternal::IsDeployedSuccessfully(StackStatus) ?
GameLift::GAMELIFT_SUCCESS : GameLift::GAMELIFT_ERROR_GENERAL;
}
FString AWSScenariosDeployer::GetLastCognitoClientId() const
{
return LastCognitoClientId;
}
FString AWSScenariosDeployer::GetLastApiGatewayEndpoint() const
{
return LastApiGatewayEndpoint;
}
FString AWSScenariosDeployer::GetLastError() const
{
return GameLiftErrorAsString::Convert(LastAwsError);
}
FString AWSScenariosDeployer::GetLastErrorMessage() const
{
return AwsDeployerInternal::sLatestDeploymentLogErrorMessage.Get();
}
TArray<FText> AWSScenariosDeployer::GetScenarios(const IAWSScenariosCategory Category) const
{
TArray<FText> Result;
const auto& Scenarios = AwsDeployerInternal::GetAwsScenarios(Category);
Result.Reserve(Scenarios.Num());
for (const auto& Item : Scenarios)
{
Result.Add(Item.Value->GetUserName());
}
return Result;
}
FText AWSScenariosDeployer::GetToolTip(const FText& ScenarioName, const IAWSScenariosCategory Category) const
{
return AwsDeployerInternal::GetAwsScenarioByName(ScenarioName, Category)->GetTooltip();
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,86 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IAWSScenariosDeployer.h"
#include "aws/gamelift/core/errors.h"
#include "AwsScenarios/IAWSScenario.h"
class AWSScenariosDeployer : public IAWSScenariosDeployer
{
public:
bool DeployManagedEC2Scenario(
const FText& Scenario,
IAWSAccountInstance* AccountInstance,
const FString& GameName,
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
const FString& OutConfigFilePath,
const FString& ExtraServerResourcesPath,
bool EnableMetrics
) override;
bool DeployCustomScenario(
const FString& CustomScenarioPath,
IAWSAccountInstance* AccountInstance,
const FString& GameName,
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
const FString& OutConfigFilePath,
const FString& ExtraServerResourcesPath
) override;
bool DeployContainerScenario(
const FText& Scenario,
IAWSAccountInstance* AwsAccountInstance,
const FString& ContainerGroupDefinitionName,
const FString& ContainerImageName,
const FString& ContainerImageUri,
const FString& IntraContainerLaunchPath,
const FString& GameName,
const FString& OutConfigFilePath,
const FText& ConnectionPortRange,
const FString& TotalVcpuLimit,
const FString& TotalMemoryLimit,
bool EnableMetrics
) override;
bool StopDeployment(IAWSAccountInstance* AwsAccountInstance) override;
FString GetLastCognitoClientId() const override;
FString GetLastApiGatewayEndpoint() const override;
FString GetLastError() const override;
FString GetLastErrorMessage() const override;
TArray<FText> GetScenarios(const IAWSScenariosCategory Category) const override;
FText GetToolTip(const FText& ScenarioName, const IAWSScenariosCategory Category) const override;
void SetMainFunctionsReplacementId(const char* ReplacementId);
void SetLastCognitoClientId(const FString& ClientId);
void SetLastApiGatewayEndpoint(const FString& ApiGateway);
void SetClientConfigPath(const char* ConfigPath);
private:
bool DeployScenarioImpl(
IAWSAccountInstance* AccountInstance,
AwsScenarios::IAWSScenario* AwsScenario, AwsScenarios::BaseInstanceTemplateParams& Params, const FString&
OutConfigFilePath
);
int UpdateDeploymentResults(
IAWSAccountInstance* AccountInstance,
const FString& ScenarioInstancePath,
const FString& GameName,
const FString& BucketName,
const FString& OutConfigFilePath
);
private:
std::string MainFunctionsReplacementId;
int LastAwsError = GameLift::GAMELIFT_ERROR_GENERAL;
FString LastCognitoClientId;
FString LastApiGatewayEndpoint;
FString ClientConfigPath;
FThreadSafeBool ShouldBeStopped{ false };
};

View File

@@ -0,0 +1,271 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "GameLiftAnywhereHandler.h"
#include "aws/gamelift/core/exports.h"
#include "aws/gamelift/GameLiftClient.h"
#include "GameLiftCoreConstants.h"
#include "GameLiftCoreLog.h"
#include "IGameLiftCoreModule.h"
#include "Utils/StringConvertors.h"
#include "Utils/UnrealVersion.h"
#define LOCTEXT_NAMESPACE "GameLiftAnywhereHandler"
namespace GameLiftAnywhereHandlerInternal
{
FuncErrorCallback ErrorCallback = [](DISPATCH_RECEIVER_HANDLE ErrorReceiver, GAMELIFT_ERROR_INFO* ErrorInfo) -> void
{
FString* Error = reinterpret_cast<FString*>(ErrorReceiver);
*Error = ErrorInfo->errorMessage;
};
} // namespace GameLiftAnywhereHandlerInternal
GameLiftAnywhereCreateLocationResult GameLiftAnywhereHandler::CreateCustomLocation(const FString& InRegion)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
FString CustomLocationName = FString::Format(TEXT("{0}-{1}"), { Anywhere::kCustomLocationPrefix, InRegion });
std::string StdCustomLocationName = Convertors::FSToStdS(CustomLocationName);
GAMELIFT_ANYWHERE_CREATE_LOCATION_REQUEST Request;
Request.customLocation = StdCustomLocationName.c_str();
Request.succeedIfExisting = true;
FString ErrorMessageReceiver;
Request.errorCb = GameLiftAnywhereHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GameLiftAnywhereCreateLocationResult Result;
Result.bIsSuccessful = GameLiftAnywhereCreateCustomLocation(AccountInstance->GetInstance(), &Request);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully created the custom location: %s"), *CustomLocationName);
Result.LocationName = CustomLocationName;
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to create a custom location '%s' - %s"), *CustomLocationName, *(Result.ErrorMessage));
}
return Result;
}
GameLiftAnywhereAddFleetLocationResult GameLiftAnywhereHandler::AddFleetLocation(const FString& InFleetId, const FString& InCustomLocation)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
std::string StdCustomLocationName = Convertors::FSToStdS(InCustomLocation);
std::string StdFleetId = Convertors::FSToStdS(InFleetId);
GAMELIFT_ANYWHERE_ADD_FLEET_LOCATION_REQUEST Request;
Request.customLocation = StdCustomLocationName.c_str();
Request.fleetId = StdFleetId.c_str();
Request.succeedIfExisting = true;
FString ErrorMessageReceiver;
Request.errorCb = GameLiftAnywhereHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GameLiftAnywhereAddFleetLocationResult Result;
Result.bIsSuccessful = GameLiftAnywhereAddFleetLocation(AccountInstance->GetInstance(), &Request);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully added the custom location: %s to fleet: %s"), *InCustomLocation, *InFleetId);
Result.LocationName = InCustomLocation;
Result.FleetId = InFleetId;
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to add a custom location '%s' to fleet '%s' - %s"), *InCustomLocation, *InFleetId, *(Result.ErrorMessage));
}
return Result;
}
GameLiftAnywhereCreateFleetResult GameLiftAnywhereHandler::CreateFleet(const FString& InFleetName, const FString& InCustomLocation)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
FString CurrentVersion = UnrealVersionUtils::GetCurrentEngineVersion();
FString FleetDescriptionWithVersion = FString::Format(TEXT("{0} Using Unreal Engine Version {1}"), { Anywhere::kAnywhereFleetDescription, CurrentVersion });
std::string StdFleetName = Convertors::FSToStdS(InFleetName);
std::string StdCustomLocation = Convertors::FSToStdS(InCustomLocation);
std::string StdFleetDescription = Convertors::FSToStdS(FleetDescriptionWithVersion);
std::string StdTagKey = Convertors::FSToStdS(FString(Anywhere::kAnywhereFleetTagKey));
std::string StdTagValue = Convertors::FSToStdS(FString(Anywhere::kAnywhereFleetTagValue));
GAMELIFT_ANYWHERE_CREATE_FLEET_REQUEST Request;
Request.fleetName = StdFleetName.c_str();
Request.customLocation = StdCustomLocation.c_str();
Request.fleetDescription = StdFleetDescription.c_str();
Request.tagKey = StdTagKey.c_str();
Request.tagValue = StdTagValue.c_str();
FString ErrorMessageReceiver;
Request.errorCb = GameLiftAnywhereHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GAMELIFT_ANYWHERE_FLEET_INFO FleetInfo;
GameLiftAnywhereCreateFleetResult Result;
Result.bIsSuccessful = GameLiftAnywhereCreateFleet(AccountInstance->GetInstance(), &Request, &FleetInfo);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
FString FleetIdString = FString(FleetInfo.fleetId);
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully created the Anywhere fleet: %s (id: %s)"), *InFleetName, *FleetIdString);
Result.FleetId = FleetIdString;
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to create an Anywhere fleet '%s' - %s"), *InFleetName, *(Result.ErrorMessage));
}
return Result;
}
GameLiftAnywhereDescribeFleetsResult GameLiftAnywhereHandler::DescribeAnywhereFleets()
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
GAMELIFT_ANYWHERE_DESCRIBE_FLEETS_REQUEST Request;
FString ErrorMessageReceiver;
Request.errorCb = GameLiftAnywhereHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GAMELIFT_ANYWHERE_DESCRIBE_FLEETS_INFO DescribeFleetsInfo;
GameLiftAnywhereDescribeFleetsResult Result;
if (AccountInstance->GetInstance())
{
Result.bIsSuccessful = GameLiftAnywhereDescribeFleets(AccountInstance->GetInstance(), &Request, &DescribeFleetsInfo);
Result.ErrorMessage = ErrorMessageReceiver;
}
else
{
Result.bIsSuccessful = false;
}
if (Result.bIsSuccessful)
{
// Fill rest of Result info
for (int i = 0; i < DescribeFleetsInfo.numFleets; i++)
{
auto& fleetInfo = DescribeFleetsInfo.fleets[i];
Result.Fleets.Add({ FString(fleetInfo.fleetName), FString(fleetInfo.fleetId) });
}
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully retrieved Anywhere fleet info"));
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to retrieve Anywhere fleet ifno - %s"), *(Result.ErrorMessage));
}
return Result;
}
GameLiftAnywhereRegisterComputeResult GameLiftAnywhereHandler::RegisterCompute(const FString& InComputeName, const FString& InIPAddress, const FString& InFleetId, const FString& InCustomLocation)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
std::string StdComputeName = Convertors::FSToStdS(InComputeName).c_str();
std::string StdFleetId = Convertors::FSToStdS(InFleetId).c_str();
std::string StdIPAddress = Convertors::FSToStdS(InIPAddress).c_str();
std::string StdCustomLocation = Convertors::FSToStdS(InCustomLocation).c_str();
GAMELIFT_ANYWHERE_REGISTER_COMPUTE_REQUEST Request;
Request.computeName = StdComputeName.c_str();
Request.fleetId = StdFleetId.c_str();
Request.ipAddress = StdIPAddress.c_str();
Request.customLocation = StdCustomLocation.c_str();
FString ErrorMessageReceiver;
Request.errorCb = GameLiftAnywhereHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GameLiftAnywhereRegisterComputeResult Result;
Result.bIsSuccessful = GameLiftAnywhereRegisterCompute(AccountInstance->GetInstance(), &Request);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully registered the Anywhere compute: %s (%s) for fleet '%s'"), *InComputeName, *InIPAddress, *InFleetId);
Result.ComputeName = InComputeName;
Result.LinkedFleetId = InFleetId;
Result.RegisteredIPAddress = InIPAddress;
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to register an Anywhere compute '%s' for fleet '%s' - %s"),
*InComputeName, *InFleetId, *(Result.ErrorMessage));
}
return Result;
}
GameLiftAnywhereAuthTokenResult GameLiftAnywhereHandler::GenerateAuthToken(const FString& InFleetId, const FString& InComputeName)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
std::string StdFleetId = Convertors::FSToStdS(InFleetId).c_str();
std::string StdComputeName = Convertors::FSToStdS(InComputeName).c_str();
GAMELIFT_ANYWHERE_GENERATE_AUTH_TOKEN_REQUEST Request;
Request.computeName = StdComputeName.c_str();
Request.fleetId = StdFleetId.c_str();
FString ErrorMessageReceiver;
Request.errorCb = GameLiftAnywhereHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GAMELIFT_ANYWHERE_AUTH_TOKEN_INFO AuthTokenInfo;
GameLiftAnywhereAuthTokenResult Result;
Result.bIsSuccessful = GameLiftAnywhereGenerateAuthToken(AccountInstance->GetInstance(), &Request, &AuthTokenInfo);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
FDateTime ExpirationTime = FDateTime::FromUnixTimestamp(AuthTokenInfo.milisecondsSinceEpoch / 1000);
FString LocalExpirationTimeString = FText::AsDateTime(ExpirationTime).ToString();
FString AuthTokenString = FString(AuthTokenInfo.authToken);
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully generate an auth token: %s (valid until %s)"), *AuthTokenString, *LocalExpirationTimeString);
Result.AuthToken = AuthTokenString;
Result.ExpirationTime = ExpirationTime;
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to generate an auth token for fleet '%s' and compute '%s' - %s"),
*InFleetId, *InComputeName, *(Result.ErrorMessage));
}
return Result;
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,24 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IGameLiftAnywhereHandler.h"
class GameLiftAnywhereHandler : public IGameLiftAnywhereHandler
{
public:
GameLiftAnywhereHandler() = default;
GameLiftAnywhereCreateLocationResult CreateCustomLocation(const FString& InRegion) override;
GameLiftAnywhereCreateFleetResult CreateFleet(const FString& InFleetName, const FString& InCustomLocation) override;
GameLiftAnywhereAddFleetLocationResult AddFleetLocation(const FString& InFleetId, const FString& InCustomLocation) override;
GameLiftAnywhereDescribeFleetsResult DescribeAnywhereFleets() override;
GameLiftAnywhereRegisterComputeResult RegisterCompute(const FString& InComputeName, const FString& InIPAddress, const FString& InFleetId, const FString& InCustomLocation) override;
GameLiftAnywhereAuthTokenResult GenerateAuthToken(const FString& InFleetId, const FString& InComputeName) override;
};

View File

@@ -0,0 +1,63 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "AwsAccountCredentials.h"
#include <future>
#include "aws/gamelift/core/exports.h"
#include "GameLiftCoreLog.h"
#include "GameLiftCoreConstants.h"
#include "Utils/NativeLogPrinter.h"
#include "AwsErrors/Converter.h"
namespace AwsAccountCredentialsInternal
{
void LogCallback(unsigned int InLevel, const char* InMessage, int InSize)
{
auto Level = Logs::PrintAwsLog(InLevel, InMessage, InSize, Credentials::Logs::kLogReceived);
}
} // namespace AwsAccountCredentialsInternal
inline AwsAccountCredentials::AwsAccountCredentials(const FString& ProfileName, TSharedRef<IAWSConfigFileProfile> ProfileReader)
{
StdRegion = Convertors::FSToStdS(ProfileReader->GetRegion(ProfileName));
StdAccessKey = Convertors::FSToStdS(ProfileReader->GetAccessKey(ProfileName));
StdSecretKey = Convertors::FSToStdS(ProfileReader->GetSecretAccessKey(ProfileName));
}
int AwsAccountCredentials::BuildCredentials()
{
std::promise<std::string> Promise;
CharPtrCallback DispatchReceiver = [](DISPATCH_RECEIVER_HANDLE InPromise, const char* CharPtr)
{
((std::promise<std::string>*) InPromise)->set_value(CharPtr);
};
unsigned int Status = GameLiftGetAwsAccountId(&Promise, DispatchReceiver, StdAccessKey.c_str(),
StdSecretKey.c_str(), &AwsAccountCredentialsInternal::LogCallback);
if (Status != GameLift::GAMELIFT_SUCCESS)
{
UE_LOG(GameLiftCoreLog, Error, TEXT("%s %s"), Credentials::Logs::kUnableToGetAccountId, *GameLiftErrorAsString::Convert(Status));
return Status;
}
StdAccountId = Promise.get_future().get();
return Status;
}
GameLift::AccountCredentials AwsAccountCredentials::GetCredentials() const
{
GameLift::AccountCredentials GameLiftCredentials;
GameLiftCredentials.region = StdRegion.c_str();
GameLiftCredentials.accessKey = StdAccessKey.c_str();
GameLiftCredentials.accessSecret = StdSecretKey.c_str();
GameLiftCredentials.accountId = StdAccountId.c_str();
return GameLiftCredentials;
}

View File

@@ -0,0 +1,26 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <string>
#include "IAWSConfigFileProfile.h"
#include "Utils/StringConvertors.h"
#include "aws/gamelift/core/model/account_credentials.h"
class AwsAccountCredentials
{
public:
AwsAccountCredentials(const FString& ProfileName, TSharedRef<IAWSConfigFileProfile> ProfileReader);
GameLift::AccountCredentials GetCredentials() const;
int BuildCredentials();
private:
std::string StdRegion;
std::string StdAccessKey;
std::string StdSecretKey;
std::string StdAccountId;
};

View File

@@ -0,0 +1,85 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "AwsAccountInfo.h"
#include "GameLiftCoreLog.h"
#include "GameLiftCoreConstants.h"
#include <Misc/App.h>
#include <Interfaces/IPluginManager.h>
#include <Runtime/EngineSettings/Classes/GeneralProjectSettings.h>
#include "aws/gamelift/core/exports.h"
namespace AwsAccountInfoInternal
{
void LogCallback(unsigned int InLevel, const char* InMessage, int InSize)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("AwsAccountInfo: %s"), *FString(InMessage));
}
} // namespace AwsAccountInfoInternal
int AwsAccountInfo::BuildAccountInfo(std::string BootstrapBucketName)
{
StdGameName = Convertors::FSToStdS(FApp::GetName());
StdBuildConfiguration = "dev";
StdBucketName = BootstrapBucketName;
UGeneralProjectSettings* ProjectSettings = GetMutableDefault<UGeneralProjectSettings>();
StdCompanyName = Convertors::FSToStdS(ProjectSettings->CompanyName);
return GameLift::GAMELIFT_SUCCESS;
}
void AwsAccountInfo::SetGameName(std::string NewGameName)
{
StdGameName = NewGameName;
}
void AwsAccountInfo::SetBucketName(std::string BucketName)
{
StdBucketName = BucketName;
}
GameLift::AccountInfo AwsAccountInfo::GetAccountInfo() const
{
auto GetCString = [&](const std::string& StdString) -> const char*
{
return StdString.length() > 1 ? StdString.c_str() : "";
};
GameLift::AccountInfo GameLiftAccountInfo;
GameLiftAccountInfo.environment = GetCString(StdBuildConfiguration);
GameLiftAccountInfo.accountId = GetCString(StdAccountId);
GameLiftAccountInfo.companyName = GetCString(StdCompanyName);
GameLiftAccountInfo.gameName = GetCString(StdGameName);
GameLiftAccountInfo.bucketName = GetCString(StdBucketName);
return GameLiftAccountInfo;
}
const std::string& AwsAccountInfo::GetAccountId() const
{
return StdAccountId;
}
const std::string& AwsAccountInfo::GetBucketName() const
{
return StdBucketName;
}
const std::string& AwsAccountInfo::GetBuildConfiguration() const
{
return StdBuildConfiguration;
}
const std::string& AwsAccountInfo::GetCompanyName() const
{
return StdCompanyName;
}
const std::string& AwsAccountInfo::GetGameName() const
{
return StdGameName;
}

View File

@@ -0,0 +1,37 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <string>
#include "IAWSConfigFileProfile.h"
#include "Utils/StringConvertors.h"
#include "aws/gamelift/core/model/account_info.h"
class AwsAccountInfo
{
public:
AwsAccountInfo(const char* AccountId = "") : StdAccountId(AccountId) {}
GameLift::AccountInfo GetAccountInfo() const;
int BuildAccountInfo(std::string BootstrapBucketName = "");
void SetGameName(std::string NewGameName);
void SetBucketName(std::string NewBucketName);
const std::string& GetAccountId() const;
const std::string& GetBucketName() const;
const std::string& GetBuildConfiguration() const;
const std::string& GetCompanyName() const;
const std::string& GetGameName() const;
private:
std::string StdAccountId;
std::string StdBucketName;
std::string StdBuildConfiguration;
std::string StdCompanyName;
std::string StdGameName;
};

View File

@@ -0,0 +1,133 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "AwsAccountInstanceManager.h"
#include "GameLiftCoreLog.h"
#include "GameLiftCoreConstants.h"
#include "aws/gamelift/core/errors.h"
#include "aws/gamelift/core/exports.h"
#include "AwsAccount/AwsAccountCredentials.h"
#include "AwsAccount/AwsAccountInfo.h"
#include "Utils/StringPaths.h"
#include "Utils/NativeLogPrinter.h"
#include "Utils/LogMessageStorage.h"
namespace AwsAccountInstanceInternal
{
static Logs::MessageStorage sLatestAccountConfigurationLogErrorMessage = {};
void LogCallback(unsigned int InLevel, const char* InMessage, int InSize)
{
auto Level = Logs::PrintAwsLog(InLevel, InMessage, InSize, Account::Logs::kLogReceived);
if (Level == ELogVerbosity::Error)
{
sLatestAccountConfigurationLogErrorMessage.Set(InMessage);
}
}
} // namespace AwsAccountInstanceInternal
AwsAccountInstanceManager::AwsAccountInstanceManager()
: AccountInstance(nullptr)
{
}
AwsAccountInstanceManager::~AwsAccountInstanceManager()
{
ReleaseInstance();
}
bool AwsAccountInstanceManager::IsValid() const
{
return GameLiftAccountHasValidCredentials(static_cast<GAMELIFT_ACCOUNT_INSTANCE_HANDLE>(AccountInstance));
}
FString AwsAccountInstanceManager::GetBucketName() const
{
return BucketName;
}
int AwsAccountInstanceManager::BuildInstance(const FString& InProfile, TSharedRef<IAWSConfigFileProfile> InProfileReader, const FString& InExistingBucketName, const FString& InRootPath, const FString& InPluginRootPath)
{
ReleaseInstance();
std::string StdBucketName = Convertors::FSToStdS(InExistingBucketName);
auto result = AccountInfo.BuildAccountInfo(StdBucketName);
if (result != GameLift::GAMELIFT_SUCCESS)
{
UE_LOG(GameLiftCoreLog, Warning, TEXT("%s"), Account::Logs::kUnableToBuildAccountInfo);
return result;
}
GameLift::AccountInfo AccountInfoData = AccountInfo.GetAccountInfo();
std::string StdRootPath = Convertors::FSToStdS(InRootPath);
std::string StdPluginRootPath = Convertors::FSToStdS(InPluginRootPath);
std::string ProfileName = Convertors::FSToStdS(InProfile);
AccountInstance = GameLiftAccountInstanceCreateWithRootPathsAndProfile(
AccountInfoData,
ProfileName.c_str(),
StdRootPath.c_str(),
StdPluginRootPath.c_str(),
&AwsAccountInstanceInternal::LogCallback
);
if (AccountInstance == nullptr)
{
UE_LOG(GameLiftCoreLog, Warning, TEXT("%s"), Account::Logs::kAccountIsNotCreated);
return GameLift::GAMELIFT_ERROR_GENERAL;
}
if (!IsValid())
{
UE_LOG(GameLiftCoreLog, Warning, TEXT("%s"), Account::Logs::kAccountIsInvalid);
return GameLift::GAMELIFT_ERROR_GENERAL;
}
return GameLift::GAMELIFT_SUCCESS;
}
void AwsAccountInstanceManager::ReleaseInstance()
{
AwsAccountInstanceInternal::sLatestAccountConfigurationLogErrorMessage.Clear();
if (AccountInstance != nullptr)
{
GameLiftAccountInstanceRelease(AccountInstance);
}
}
void AwsAccountInstanceManager::SetBucketName(const FString& NewBucketName)
{
BucketName = NewBucketName;
}
void* AwsAccountInstanceManager::GetInstance() const
{
return AccountInstance;
}
const char* AwsAccountInstanceManager::GetGameName() const
{
return AccountInfo.GetGameName().c_str();
}
const char* AwsAccountInstanceManager::GetAccountId() const
{
return AccountInfo.GetAccountId().c_str();
}
const char* AwsAccountInstanceManager::GetBuildConfiguration() const
{
return AccountInfo.GetBuildConfiguration().c_str();
}
FString AwsAccountInstanceManager::GetLastErrorMessage() const
{
return AwsAccountInstanceInternal::sLatestAccountConfigurationLogErrorMessage.Get();
}

View File

@@ -0,0 +1,32 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IAWSAccountInstance.h"
#include "AwsAccount/AwsAccountInfo.h"
class AwsAccountInstanceManager : public IAWSAccountInstance
{
public:
AwsAccountInstanceManager();
virtual ~AwsAccountInstanceManager();
int BuildInstance(const FString& Profile, TSharedRef<IAWSConfigFileProfile> ProfileReader, const FString& ExistingBucketName, const FString& RootPath, const FString& PluginRootPath);
void ReleaseInstance();
void SetBucketName(const FString& NewBucketName);
virtual void* GetInstance() const override;
virtual bool IsValid() const override;
virtual FString GetBucketName() const override;
virtual const char* GetGameName() const override;
virtual const char* GetAccountId() const override;
virtual const char* GetBuildConfiguration() const override;
virtual FString GetLastErrorMessage() const override;
private:
AwsAccountInfo AccountInfo;
void* AccountInstance;
FString BucketName;
};

View File

@@ -0,0 +1,129 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "Converter.h"
#include "aws/gamelift/core/errors.h"
#include "Containers/Map.h"
namespace Internal
{
TMap<unsigned int, FString> InitMap()
{
return TMap<unsigned int, FString>(
{
// Standard status codes (0-500)
{ GameLift::GAMELIFT_SUCCESS, "SUCCESS" },
{ GameLift::GAMELIFT_ERROR_INVALID_PROVIDER, "INVALID PROVIDER" },
{ GameLift::GAMELIFT_ERROR_PARAMETERS_FILE_SAVE_FAILED, "PARAMETERS FILE SAVE FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_FILE_SAVE_FAILED, "CLOUDFORMATION FILE SAVE FAILED" },
{ GameLift::GAMELIFT_ERROR_FUNCTIONS_COPY_FAILED, "FUNCTIONS COPY FAILED" },
{ GameLift::GAMELIFT_ERROR_SETTINGS_FILE_SAVE_FAILED, "SETTINGS FILE SAVE FAILED" },
{ GameLift::GAMELIFT_ERROR_NO_ID_TOKEN, "NO ID TOKEN" },
{ GameLift::GAMELIFT_ERROR_HTTP_REQUEST_FAILED, "HTTP REQUEST FAILED" },
{ GameLift::GAMELIFT_ERROR_PARSE_JSON_FAILED, "PARSE JSON FAILED" },
{ GameLift::GAMELIFT_ERROR_SIGN_REQUEST_FAILED, "SIGN REQUEST FAILED" },
{ GameLift::GAMELIFT_ERROR_SETTINGS_FILE_READ_FAILED, "SETTINGS FILE READ FAILED" },
{ GameLift::GAMELIFT_ERROR_FILE_OPEN_FAILED, "FILE OPEN FAILED" },
{ GameLift::GAMELIFT_ERROR_FILE_WRITE_FAILED, "FILE WRITE FAILED" },
{ GameLift::GAMELIFT_ERROR_FILE_READ_FAILED, "FILE READ FAILED" },
{ GameLift::GAMELIFT_ERROR_DIRECTORY_CREATE_FAILED, "DIRECTORY CREATE FAILED" },
{ GameLift::GAMELIFT_ERROR_DIRECTORY_NOT_FOUND, "DIRECTORY NOT FOUND" },
{ GameLift::GAMELIFT_ERROR_METHOD_NOT_IMPLEMENTED, "METHOD NOT IMPLEMENTED" },
{ GameLift::GAMELIFT_ERROR_GENERAL, "GAMELIFT ERROR GENERAL" },
{ GameLift::GAMELIFT_ERROR_REGION_CODE_CONVERSION_FAILED, "REGION CODE CONVERSION FAILED" },
// Bootstrapping status codes (501-1000)
{ GameLift::GAMELIFT_ERROR_BOOTSTRAP_BUCKET_LOOKUP_FAILED, "BOOTSTRAP BUCKET LOOKUP FAILED" },
{ GameLift::GAMELIFT_ERROR_BOOTSTRAP_BUCKET_CREATION_FAILED, "BOOTSTRAP BUCKET CREATION FAILED" },
{ GameLift::GAMELIFT_ERROR_BOOTSTRAP_INVALID_REGION_CODE, "BOOTSTRAP INVALID REGION CODE" },
{ GameLift::GAMELIFT_ERROR_BOOTSTRAP_MISSING_PLUGIN_ROOT, "BOOTSTRAP MISSING PLUGIN ROOT" },
{ GameLift::GAMELIFT_ERROR_BOOTSTRAP_REGION_CODE_CONVERSION_FAILED, "BOOTSTRAP REGION CODE CONVERSION FAILED" },
// Resource creation status codes (1001-1500)
{ GameLift::GAMELIFT_ERROR_FUNCTIONS_PATH_NOT_FOUND, "FUNCTIONS PATH NOT FOUND" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_PATH_NOT_FOUND, "CLOUDFORMATION PATH NOT FOUND" },
{ GameLift::GAMELIFT_ERROR_FUNCTION_ZIP_INIT_FAILED, "FUNCTION ZIP INIT FAILED" },
{ GameLift::GAMELIFT_ERROR_FUNCTION_ZIP_WRITE_FAILED, "FUNCTION ZIP WRITE FAILED" },
{ GameLift::GAMELIFT_ERROR_PARAMSTORE_WRITE_FAILED, "PARAMSTORE WRITE FAILED" },
{ GameLift::GAMELIFT_ERROR_BOOTSTRAP_BUCKET_UPLOAD_FAILED, "BOOTSTRAP BUCKET UPLOAD FAILED" },
{ GameLift::GAMELIFT_ERROR_SECRETSMANAGER_WRITE_FAILED, "SECRETSMANAGER WRITE FAILED"},
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_STACK_CREATION_FAILED, "CLOUDFORMATION STACK CREATION FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_STACK_UPDATE_FAILED, "CLOUDFORMATION_STACK_CREATION FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_RESOURCE_CREATION_FAILED, "CLOUDFORMATION RESOURCE CREATION_FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_STACK_DELETE_FAILED, "CLOUDFORMATION STACK DELETE FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_DESCRIBE_RESOURCE_FAILED, "CLOUDFORMATION DESCRIBE RESOURCE FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_DESCRIBE_STACKS_FAILED, "CLOUDFORMATION DESCRIBE STACKS FAILED" },
{ GameLift::GAMELIFT_ERROR_APIGATEWAY_DEPLOYMENT_CREATION_FAILED, "APIGATEWAY DEPLOYMENT CREATION FAILED" },
{ GameLift::GAMELIFT_ERROR_APIGATEWAY_STAGE_DEPLOYMENT_FAILED, "APIGATEWAY STAGE DEPLOYMENT FAILED" },
{ GameLift::GAMELIFT_ERROR_LAYERS_PATH_NOT_FOUND, "LAYERS PATH NOT FOUND" },
{ GameLift::GAMELIFT_ERROR_LAYER_ZIP_INIT_FAILED, "LAYER ZIP INIT FAILED" },
{ GameLift::GAMELIFT_ERROR_LAYER_ZIP_WRITE_FAILED, "LAYER ZIP WRITE FAILED" },
{ GameLift::GAMELIFT_ERROR_LAYER_CREATION_FAILED, "LAYER CREATION FAILED" },
{ GameLift::GAMELIFT_ERROR_CLOUDFORMATION_GET_TEMPLATE_FAILED, "CLOUDFORMATION GET TEMPLATE FAILED" },
{ GameLift::GAMELIFT_ERROR_PARAMSTORE_READ_FAILED, "PARAMSTORE READ FAILED" },
{ GameLift::GAMELIFT_ERROR_GAME_SERVER_PATH_NOT_FOUND, "GAME SERVER PATH NOT FOUND" },
{ GameLift::GAMELIFT_ERROR_GAME_SERVER_ZIP_INIT_FAILED, "GAME SERVER ZIP INIT FAILED" },
{ GameLift::GAMELIFT_ERROR_GAME_SERVER_ZIP_WRITE_FAILED, "GAME SERVER ZIP WRITE FAILED" },
{ GameLift::GAMELIFT_ERROR_GAME_SERVER_ZIP_READ_FAILED, "GAME SERVER ZIP READ FAILED" },
// Identity status codes (0x10000 - 0x103FF)
{ GameLift::GAMELIFT_ERROR_REGISTER_USER_FAILED, "REGISTER USER FAILED" },
{ GameLift::GAMELIFT_ERROR_CONFIRM_REGISTRATION_FAILED, "CONFIRM REGISTRATION FAILED" },
{ GameLift::GAMELIFT_ERROR_RESEND_CONFIRMATION_CODE_FAILED, "RESEND CONFIRMATION CODE FAILED" },
{ GameLift::GAMELIFT_ERROR_LOGIN_FAILED, "LOGIN FAILED" },
{ GameLift::GAMELIFT_ERROR_FORGOT_PASSWORD_FAILED, "FORGOT PASSWORD FAILED" },
{ GameLift::GAMELIFT_ERROR_CONFIRM_FORGOT_PASSWORD_FAILED, "CONFIRM FORGOT PASSWORD FAILED" },
{ GameLift::GAMELIFT_ERROR_GET_USER_FAILED, "GET USER FAILED" },
{ GameLift::GAMELIFT_ERROR_LOGOUT_FAILED, "LOGOUT FAILED" },
{ GameLift::GAMELIFT_ERROR_MALFORMED_USERNAME, "MALFORMED USERNAME" },
{ GameLift::GAMELIFT_ERROR_MALFORMED_PASSWORD, "MALFORMED PASSWORD" },
{ GameLift::GAMELIFT_ERROR_INVALID_FEDERATED_IDENTITY_PROVIDER, "INVALID FEDERATED IDENTITY PROVIDER" },
// Achievements status codes (0x10800 - 0x10BFF)
{ GameLift::GAMELIFT_ERROR_ACHIEVEMENTS_ICON_UPLOAD_FAILED, "ACHIEVEMENTS ICON UPLOAD FAILED"},
{ GameLift::GAMELIFT_ERROR_ACHIEVEMENTS_INVALID_ID, "ACHIEVEMENTS INVALID ID" },
// User Gameplay Data status codes (0x10C00 - 0x10FFF)
{ GameLift::GAMELIFT_ERROR_USER_GAMEPLAY_DATA_PAYLOAD_INVALID, "USER GAMEPLAY DATA PAYLOAD INVALID"},
{ GameLift::GAMELIFT_ERROR_USER_GAMEPLAY_DATA_API_CALL_FAILED, "USER GAMEPLAY DATA API CALL FAILED"},
{ GameLift::GAMELIFT_ERROR_USER_GAMEPLAY_DATA_API_CALL_DROPPED, "USER GAMEPLAY DATA API CALL DROPPED"},
{ GameLift::GAMELIFT_WARNING_USER_GAMEPLAY_DATA_API_CALL_ENQUEUED, "GAMELIFT WARNING USER GAMEPLAY DATA API CALL ENQUEUED"},
{ GameLift::GAMELIFT_ERROR_MALFORMED_BUNDLE_NAME, "MALFORMED BUNDLE NAME"},
{ GameLift::GAMELIFT_ERROR_MALFORMED_BUNDLE_ITEM_KEY, "MALFORMED BUNDLE ITEM KEY"},
{ GameLift::GAMELIFT_ERROR_USER_GAMEPLAY_DATA_CACHE_WRITE_FAILED, "USER GAMEPLAY DATA CACHE WRITE FAILED"},
{ GameLift::GAMELIFT_ERROR_USER_GAMEPLAY_DATA_CACHE_READ_FAILED, "USER GAMEPLAY DATA CACHE READ FAILED"},
// Game Saving status codes (0x11000 - 0x113FF)
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_SLOT_NOT_FOUND, "GAME SAVING SLOT NOT FOUND" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_CLOUD_SLOT_IS_NEWER, "GAME SAVING CLOUD SLOT IS NEWER" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_SYNC_CONFLICT, "GAME SAVING SYNC CONFLICT" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_DOWNLOAD_SLOT_ALREADY_IN_SYNC, "GAME SAVING DOWNLOAD SLOT ALREADY IN SYNC" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_UPLOAD_SLOT_ALREADY_IN_SYNC, "GAME SAVING UPLOAD SLOT ALREADY IN SYNC" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_EXCEEDED_MAX_SIZE, "GAME SAVING EXCEEDED MAX SIZE" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_FILE_EMPTY, "GAME SAVING FILE EMPTY" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_FILE_FAILED_TO_OPEN, "GAME SAVING FILE FAILED TO OPEN" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_LOCAL_SLOT_IS_NEWER, "GAME SAVING LOCAL SLOT IS NEWER" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_SLOT_UNKNOWN_SYNC_STATUS, "GAME SAVING SLOT UNKNOWN SYNC STATUS" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_MALFORMED_SLOT_NAME, "GAME SAVING MALFORMED SLOT_NAME" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_MISSING_SHA, "GAME SAVING MISSING SHA" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_SLOT_TAMPERED, "GAME SAVING SLOT TAMPERED" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_BUFFER_TOO_SMALL, "GAME SAVING BUFFER TOO SMALL" },
{ GameLift::GAMELIFT_ERROR_GAME_SAVING_MAX_CLOUD_SLOTS_EXCEEDED, "GAME SAVING MAX CLOUD SLOTSEXCEEDED" }
});
}
} // namespace Internal
namespace GameLiftErrorAsString
{
FString Convert(unsigned int ErrorCode)
{
static auto ErrorCodeMap = Internal::InitMap();
if (ErrorCodeMap.Contains(ErrorCode))
{
return ErrorCodeMap[ErrorCode];
}
return FString("GAMELIFT ERROR GENERAL");
}
} // namespace GameLiftErrorAsString

View File

@@ -0,0 +1,9 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
namespace GameLiftErrorAsString
{
FString Convert(unsigned int ErrorCode);
} // namespace GameLiftErrorAsString

View File

@@ -0,0 +1,77 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Base/ScenarioWithGameServer.h"
#include "GameLiftCoreConstants.h"
#include "ScenarioWithParameters.h"
#include "GameLiftCore/Private/AwsScenarios/IAwsScenario.h"
#include "GameLiftCore/Public/IAWSAccountInstance.h"
#include "aws/gamelift/core/errors.h"
namespace AwsScenarios
{
class ScenarioWithContainerParameters : public ScenarioWithParameters
{
public:
virtual const char* const* GetParamNames() const override
{
static const char* paramNames[] =
{
"AccountId",
"ApiGatewayStageNameParameter",
"ContainerGroupDefinitionNameParameter",
"ContainerImageNameParameter",
"ContainerImageUriParameter",
"GameNameParameter",
"LambdaZipS3BucketParameter",
"LambdaZipS3KeyParameter",
"LaunchPathParameter",
"FleetUdpFromPortParameter",
"FleetUdpToPortParameter",
"TotalVcpuLimitParameter",
"TotalMemoryLimitParameter",
"UnrealEngineVersionParameter",
"EnableMetricsParameter"
};
return paramNames;
}
virtual int SaveFeatureInstanceTemplate(IAWSAccountInstance* AwsAccountInstance,
const TMap<FString, FString>& InParams) override
{
ContainerInstanceTemplateParams TemplateParams;
TemplateParams.FromMap(InParams);
const char* ParamValues[] =
{
TemplateParams.AccountId.c_str(),
TemplateParams.ApiGatewayStageNameParameter.c_str(),
TemplateParams.ContainerGroupDefinitionNameParameter.c_str(),
TemplateParams.ContainerImageNameParameter.c_str(),
TemplateParams.ContainerImageUriParameter.c_str(),
TemplateParams.GameNameParameter.c_str(),
TemplateParams.LambdaZipS3BucketParameter.c_str(),
TemplateParams.LambdaZipS3KeyParameter.c_str(),
TemplateParams.LaunchPathParameter.c_str(),
TemplateParams.FleetUdpFromPortParameter.c_str(),
TemplateParams.FleetUdpToPortParameter.c_str(),
TemplateParams.TotalVcpuLimitParameter.c_str(),
TemplateParams.TotalMemoryLimitParameter.c_str(),
TemplateParams.UnrealEngineVersionParameter.c_str(),
TemplateParams.EnableMetricsParameter.c_str()
};
auto* ParamNames = GetParamNames();
size_t Size = sizeof(ParamValues) / sizeof(*ParamValues);
return GameLiftAccountSaveFeatureInstanceTemplates(AwsAccountInstance->GetInstance(), ParamNames, ParamValues, Size);
}
virtual int UploadGameServer(IAWSAccountInstance* AwsAccountInstance, const std::string& ServerFolderPath, const std::string& ExtraServerResourcesPath) override
{
return GameLift::GAMELIFT_SUCCESS;
};
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,71 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "ScenarioWithParameters.h"
#include <regex>
#include "aws/gamelift/core/exports.h"
namespace AwsScenarios
{
class ScenarioWithGameServer : public ScenarioWithParameters
{
public:
virtual int UploadGameServer(
IAWSAccountInstance* AwsAccountInstance,
const std::string& ServerFolderPath,
const std::string& ExtraServerResourcesPath
) override
{
auto Callback = [](DISPATCH_RECEIVER_HANDLE DispatchReceiver, const char* CharPtr)
{
static_cast<ScenarioWithGameServer*>(DispatchReceiver)->SetBuildS3Path(CharPtr);
};
return GameLiftAccountUploadGameServerEx(AwsAccountInstance->GetInstance(), ServerFolderPath.c_str(), ExtraServerResourcesPath.c_str(), this, Callback);
}
int CreateLaunchPathParameter(
const FString& InBuildOperatingSystem,
const FString& InBuildFolderPath,
const FString& InBuildFilePath,
std::string& InStdLaunchPathParameter
)
{
FString RelativePath = InBuildFilePath;
if (!FPaths::IsUnderDirectory(InBuildFilePath, InBuildFolderPath) || !FPaths::MakePathRelativeTo(RelativePath, *InBuildFolderPath))
{
UE_LOG(GameLiftCoreLog, Error, TEXT("%s."), Deploy::Logs::kInvalidServerFilePath);
return GameLift::GAMELIFT_ERROR_GENERAL;
}
auto StdServerFileRelPath = Convertors::FSToStdS(RelativePath);
auto StdServerFileRelPathPosition = StdServerFileRelPath.find("/");
if (StdServerFileRelPathPosition == std::string::npos)
{
UE_LOG(GameLiftCoreLog, Error, TEXT("%s."), Deploy::Logs::kInvalidServerFilePath);
return GameLift::GAMELIFT_ERROR_GENERAL;
}
if (InBuildOperatingSystem.StartsWith(TEXT("WINDOWS")))
{
// Windows
InStdLaunchPathParameter = "C:/game/" + StdServerFileRelPath.substr(StdServerFileRelPathPosition + 1);
// Convert forward slashes to back slashes ( / -> \ )
InStdLaunchPathParameter = std::regex_replace(InStdLaunchPathParameter, std::regex("/"), "\\\\");
}
else
{
// Linux
InStdLaunchPathParameter = "/local/game/" + StdServerFileRelPath.substr(StdServerFileRelPathPosition + 1);
}
return GameLift::GAMELIFT_SUCCESS;
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,80 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "AwsScenarios/IAWSScenario.h"
#include "aws/gamelift/core/exports.h"
namespace AwsScenarios
{
class ScenarioWithParameters : public IAWSScenario
{
public:
virtual ~ScenarioWithParameters() = default;
virtual const char* const* GetParamNames() const override
{
static const char* paramNames[] =
{
"GameNameParameter",
"BuildOperatingSystemParameter",
"BuildS3BucketParameter",
"LambdaZipS3BucketParameter",
"LambdaZipS3KeyParameter",
"ApiGatewayStageNameParameter",
"AccountId",
"LaunchPathParameter",
"BuildS3KeyParameter",
"UnrealEngineVersionParameter",
"EnableMetricsParameter"
};
return paramNames;
}
virtual int SaveFeatureInstanceTemplate(IAWSAccountInstance* AwsAccountInstance, const TMap<FString, FString>& InParams) override
{
ManagedEC2InstanceTemplateParams TemplateParams;
TemplateParams.FromMap(InParams);
const char* ParamValues[] =
{
TemplateParams.GameNameParameter.c_str(),
TemplateParams.BuildOperatingSystemParameter.c_str(),
TemplateParams.BuildS3BucketParameter.c_str(),
TemplateParams.LambdaZipS3BucketParameter.c_str(),
TemplateParams.LambdaZipS3KeyParameter.c_str(),
TemplateParams.ApiGatewayStageNameParameter.c_str(),
TemplateParams.AccountId.c_str(),
TemplateParams.LaunchPathParameter.c_str(),
BuildS3Path.c_str(),
TemplateParams.UnrealEngineVersionParameter.c_str(),
TemplateParams.EnableMetricsParameter.c_str()
};
auto* ParamNames = GetParamNames();
size_t Size = sizeof(ParamValues) / sizeof(*ParamValues);
return GameLiftAccountSaveFeatureInstanceTemplates(AwsAccountInstance->GetInstance(), ParamNames, ParamValues, Size);
}
virtual FString GetScenarioPath() const override
{
return Paths::ScenarioPath(GetFolderName());
}
virtual FString GetScenarioInstancePath() const override
{
return Paths::ScenarioInstancePath(GetFolderName());
}
void SetBuildS3Path(const std::string& NewBuildS3Path)
{
BuildS3Path = NewBuildS3Path;
}
private:
std::string BuildS3Path;
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,35 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "ScenarioWithParameters.h"
#include "aws/gamelift/core/errors.h"
namespace AwsScenarios
{
class ScenarioWithoutGameServer : public ScenarioWithParameters
{
public:
virtual int UploadGameServer(
IAWSAccountInstance* AwsAccountInstance,
const std::string& ServerFolderPath,
const std::string& ExtraServerResourcesPath
) override
{
return GameLift::GAMELIFT_SUCCESS;
}
virtual int CreateLaunchPathParameter(
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
std::string& StdLaunchPathParameter
) override
{
StdLaunchPathParameter = "";
return GameLift::GAMELIFT_SUCCESS;
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "GameLiftCoreConstants.h"
#include "Base/ScenarioWithContainerParameters.h"
namespace AwsScenarios
{
class ContainersFlexMatch : public ScenarioWithContainerParameters
{
public:
static const FText& Name()
{
return Menu::DeploymentServer::kContainersFlexMatch;
}
static TUniquePtr<IAWSScenario> Create()
{
return MakeUnique<ContainersFlexMatch>();
}
virtual FText GetTooltip() const override
{
return Menu::DeploymentServer::kContainersFlexMatchTooltip;
}
virtual FString GetFolderName() const override
{
return Menu::DeploymentServer::kContainersFlexMatchFolder;
}
virtual FText GetUserName() const override
{
return Name();
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "GameLiftCoreConstants.h"
#include "Base/ScenarioWithContainerParameters.h"
namespace AwsScenarios
{
class ContainersSingleRegionFleet : public ScenarioWithContainerParameters
{
public:
static const FText& Name()
{
return Menu::DeploymentServer::kContainersSingleRegionFleet;
}
static TUniquePtr<IAWSScenario> Create()
{
return MakeUnique<ContainersSingleRegionFleet>();
}
virtual FText GetTooltip() const override
{
return Menu::DeploymentServer::kContainersSingleRegionFleetTooltip;
}
virtual FString GetFolderName() const override
{
return Menu::DeploymentServer::kContainersSingleRegionFleetFolder;
}
virtual FText GetUserName() const override
{
return Name();
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,51 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Base/ScenarioWithGameServer.h"
#include "GameLiftCoreConstants.h"
namespace AwsScenarios
{
class CustomScenario : public ScenarioWithGameServer
{
public:
static const FText& Name()
{
return Menu::DeploymentServer::kCustom;
}
static TUniquePtr<CustomScenario> Create(const FString& CustomScenarioPath)
{
return MakeUnique<CustomScenario>(CustomScenarioPath);
}
CustomScenario(const FString& CustomScenarioPath) : Path(CustomScenarioPath)
{
}
virtual FText GetTooltip() const override
{
return Menu::DeploymentServer::kCustomTooltip;
}
virtual FString GetFolderName() const override
{
return Menu::DeploymentServer::kCustomScenarioFolder;
}
virtual FText GetUserName() const override
{
return Name();
}
virtual FString GetScenarioPath() const override
{
return Path;
}
private:
FString Path;
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Base/ScenarioWithGameServer.h"
#include "GameLiftCoreConstants.h"
namespace AwsScenarios
{
class FlexMatch : public ScenarioWithGameServer
{
public:
static const FText& Name()
{
return Menu::DeploymentServer::kFlexMatch;
}
static TUniquePtr<IAWSScenario> Create()
{
return MakeUnique<FlexMatch>();
}
virtual FText GetTooltip() const override
{
return Menu::DeploymentServer::kFlexMatchTooltip;
}
virtual FString GetFolderName() const override
{
return Menu::DeploymentServer::kFlexMatchFolder;
}
virtual FText GetUserName() const override
{
return Name();
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,193 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <sstream>
#include <string>
#include "IAWSAccountInstance.h"
#include "aws/gamelift/core/enums.h"
#include "Utils/StringConvertors.h"
namespace AwsScenarios
{
inline std::string GetLambdaS3Key(const std::string& GameName, const std::string& FunctionsReplacementId)
{
std::stringstream StringStream;
StringStream << GameName;
StringStream << "/functions/" << GameLift::GetFeatureTypeString(GameLift::FeatureType::Main);
StringStream << "/" << "requests" << "." << FunctionsReplacementId << ".zip";
return StringStream.str();
}
struct BaseInstanceTemplateParams
{
std::string AccountId;
std::string ApiGatewayStageNameParameter;
std::string BuildFolderPath;
std::string BuildS3BucketParameter;
std::string ExtraServerResourcesPath;
std::string GameNameParameter;
std::string LambdaZipS3BucketParameter;
std::string LambdaZipS3KeyParameter;
std::string LaunchPathParameter;
std::string UnrealEngineVersionParameter;
std::string EnableMetricsParameter;
virtual ~BaseInstanceTemplateParams() = default;
virtual void FromMap(const TMap<FString, FString>& InMap) = 0;
virtual TMap<FString, FString> ToMap() const = 0;
};
struct ManagedEC2InstanceTemplateParams : BaseInstanceTemplateParams
{
std::string BuildOperatingSystemParameter;
ManagedEC2InstanceTemplateParams() = default;
virtual void FromMap(const TMap<FString, FString>& InMap) override
{
const FString* InGameNameParameter = InMap.Find("GameNameParameter");
const FString* InBuildOperatingSystemParameter = InMap.Find("BuildOperatingSystemParameter");
const FString* InBuildS3BucketParameter = InMap.Find("BuildS3BucketParameter");
const FString* InLambdaZipS3BucketParameter = InMap.Find("LambdaZipS3BucketParameter");
const FString* InLambdaZipS3KeyParameter = InMap.Find("LambdaZipS3KeyParameter");
const FString* InApiGatewayStageNameParameter = InMap.Find("ApiGatewayStageNameParameter");
const FString* InAccountId = InMap.Find("AccountId");
const FString* InLaunchPathParameter = InMap.Find("LaunchPathParameter");
const FString* InUnrealEngineVersionParameter = InMap.Find("UnrealEngineVersionParameter");
const FString* InEnableMetricsParameter = InMap.Find("EnableMetricsParameter");
if (InGameNameParameter && InBuildOperatingSystemParameter && InBuildS3BucketParameter
&& InLambdaZipS3BucketParameter && InLambdaZipS3KeyParameter && InApiGatewayStageNameParameter
&& InApiGatewayStageNameParameter && InAccountId && InLaunchPathParameter && InUnrealEngineVersionParameter
&& InEnableMetricsParameter)
{
GameNameParameter = Convertors::FSToStdS(*InGameNameParameter);
BuildOperatingSystemParameter = Convertors::FSToStdS(*InBuildOperatingSystemParameter);
BuildS3BucketParameter = Convertors::FSToStdS(*InBuildS3BucketParameter);
LambdaZipS3BucketParameter = Convertors::FSToStdS(*InLambdaZipS3BucketParameter);
LambdaZipS3KeyParameter = Convertors::FSToStdS(*InLambdaZipS3KeyParameter);
ApiGatewayStageNameParameter = Convertors::FSToStdS(*InApiGatewayStageNameParameter);
AccountId = Convertors::FSToStdS(*InAccountId);
LaunchPathParameter = Convertors::FSToStdS(*InLaunchPathParameter);
UnrealEngineVersionParameter = Convertors::FSToStdS(*InUnrealEngineVersionParameter);
EnableMetricsParameter = Convertors::FSToStdS(*InEnableMetricsParameter);
}
}
virtual TMap<FString, FString> ToMap() const override
{
TMap<FString, FString> ParamsMap = {};
ParamsMap.Emplace("GameNameParameter", GameNameParameter.c_str());
ParamsMap.Emplace("BuildOperatingSystemParameter", BuildOperatingSystemParameter.c_str());
ParamsMap.Emplace("BuildS3BucketParameter", BuildS3BucketParameter.c_str());
ParamsMap.Emplace("LambdaZipS3BucketParameter", LambdaZipS3BucketParameter.c_str());
ParamsMap.Emplace("LambdaZipS3KeyParameter", LambdaZipS3KeyParameter.c_str());
ParamsMap.Emplace("ApiGatewayStageNameParameter", ApiGatewayStageNameParameter.c_str());
ParamsMap.Emplace("AccountId", AccountId.c_str());
ParamsMap.Emplace("LaunchPathParameter", LaunchPathParameter.c_str());
ParamsMap.Emplace("UnrealEngineVersionParameter", UnrealEngineVersionParameter.c_str());
ParamsMap.Emplace("EnableMetricsParameter", EnableMetricsParameter.c_str());
return ParamsMap;
}
};
struct ContainerInstanceTemplateParams : BaseInstanceTemplateParams
{
std::string ContainerGroupDefinitionNameParameter;
std::string ContainerImageNameParameter;
std::string ContainerImageUriParameter;
std::string FleetUdpFromPortParameter;
std::string FleetUdpToPortParameter;
std::string TotalVcpuLimitParameter;
std::string TotalMemoryLimitParameter;
ContainerInstanceTemplateParams() = default;
virtual void FromMap(const TMap<FString, FString>& InMap) override
{
const FString* InAccountId = InMap.Find("AccountId");
const FString* InApiGatewayStageNameParameter = InMap.Find("ApiGatewayStageNameParameter");
const FString* InContainerGroupDefinitionNameParameter = InMap.Find("ContainerGroupDefinitionNameParameter");
const FString* InContainerImageNameParameter = InMap.Find("ContainerImageNameParameter");
const FString* InContainerImageUriParameter = InMap.Find("ContainerImageUriParameter");
const FString* InGameNameParameter = InMap.Find("GameNameParameter");
const FString* InLambdaZipS3BucketParameter = InMap.Find("LambdaZipS3BucketParameter");
const FString* InLambdaZipS3KeyParameter = InMap.Find("LambdaZipS3KeyParameter");
const FString* InLaunchPathParameter = InMap.Find("LaunchPathParameter");
const FString* InFleetUdpFromPortParameter = InMap.Find("FleetUdpFromPortParameter");
const FString* InFleetUdpToPortParameter = InMap.Find("FleetUdpToPortParameter");
const FString* InTotalVcpuLimitParameter = InMap.Find("TotalVcpuLimitParameter");
const FString* InTotalMemoryLimitParameter = InMap.Find("TotalMemoryLimitParameter");
const FString* InUnrealEngineVersionParameter = InMap.Find("UnrealEngineVersionParameter");
const FString* InEnableMetricsParameter = InMap.Find("EnableMetricsParameter");
if (InAccountId && InApiGatewayStageNameParameter && InContainerGroupDefinitionNameParameter
&& InContainerImageNameParameter && InContainerImageUriParameter && InGameNameParameter
&& InLambdaZipS3BucketParameter && InLambdaZipS3KeyParameter && InLaunchPathParameter
&& InFleetUdpFromPortParameter && InFleetUdpToPortParameter && InTotalVcpuLimitParameter
&& InTotalMemoryLimitParameter && InUnrealEngineVersionParameter && InEnableMetricsParameter)
{
AccountId = Convertors::FSToStdS(*InAccountId);
ApiGatewayStageNameParameter = Convertors::FSToStdS(*InApiGatewayStageNameParameter);
ContainerGroupDefinitionNameParameter = Convertors::FSToStdS(*InContainerGroupDefinitionNameParameter);
ContainerImageNameParameter = Convertors::FSToStdS(*InContainerImageNameParameter);
ContainerImageUriParameter = Convertors::FSToStdS(*InContainerImageUriParameter);
GameNameParameter = Convertors::FSToStdS(*InGameNameParameter);
LambdaZipS3BucketParameter = Convertors::FSToStdS(*InLambdaZipS3BucketParameter);
LambdaZipS3KeyParameter = Convertors::FSToStdS(*InLambdaZipS3KeyParameter);
LaunchPathParameter = Convertors::FSToStdS(*InLaunchPathParameter);
FleetUdpFromPortParameter = Convertors::FSToStdS(*InFleetUdpFromPortParameter);
FleetUdpToPortParameter = Convertors::FSToStdS(*InFleetUdpToPortParameter);
TotalVcpuLimitParameter = Convertors::FSToStdS(*InTotalVcpuLimitParameter);
TotalMemoryLimitParameter = Convertors::FSToStdS(*InTotalMemoryLimitParameter);
UnrealEngineVersionParameter = Convertors::FSToStdS(*InUnrealEngineVersionParameter);
EnableMetricsParameter = Convertors::FSToStdS(*InEnableMetricsParameter);
}
}
virtual TMap<FString, FString> ToMap() const override
{
TMap<FString, FString> ParamsMap = {};
ParamsMap.Emplace("AccountId", AccountId.c_str());
ParamsMap.Emplace("ApiGatewayStageNameParameter", ApiGatewayStageNameParameter.c_str());
ParamsMap.Emplace("ContainerGroupDefinitionNameParameter", ContainerGroupDefinitionNameParameter.c_str());
ParamsMap.Emplace("ContainerImageNameParameter", ContainerImageNameParameter.c_str());
ParamsMap.Emplace("ContainerImageUriParameter", ContainerImageUriParameter.c_str());
ParamsMap.Emplace("GameNameParameter", GameNameParameter.c_str());
ParamsMap.Emplace("LambdaZipS3BucketParameter", LambdaZipS3BucketParameter.c_str());
ParamsMap.Emplace("LambdaZipS3KeyParameter", LambdaZipS3KeyParameter.c_str());
ParamsMap.Emplace("LaunchPathParameter", LaunchPathParameter.c_str());
ParamsMap.Emplace("FleetUdpFromPortParameter", FleetUdpFromPortParameter.c_str());
ParamsMap.Emplace("FleetUdpToPortParameter", FleetUdpToPortParameter.c_str());
ParamsMap.Emplace("TotalVcpuLimitParameter", TotalVcpuLimitParameter.c_str());
ParamsMap.Emplace("TotalMemoryLimitParameter", TotalMemoryLimitParameter.c_str());
ParamsMap.Emplace("UnrealEngineVersionParameter", UnrealEngineVersionParameter.c_str());
ParamsMap.Emplace("EnableMetricsParameter", EnableMetricsParameter.c_str());
return ParamsMap;
}
};
class IAWSScenario
{
public:
virtual ~IAWSScenario() = default;
virtual const char* const* GetParamNames() const = 0;
virtual FText GetTooltip() const = 0;
virtual FString GetFolderName() const = 0;
virtual FText GetUserName() const = 0;
virtual FString GetScenarioPath() const = 0;
virtual FString GetScenarioInstancePath() const = 0;
virtual int SaveFeatureInstanceTemplate(IAWSAccountInstance* AwsAccountInstance, const TMap<FString, FString>& InParams) = 0;
virtual int UploadGameServer(IAWSAccountInstance* AwsAccountInstance, const std::string& ServerFolderPath, const std::string& ExtraServerResourcesPath) = 0;
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Base/ScenarioWithGameServer.h"
#include "GameLiftCoreConstants.h"
namespace AwsScenarios
{
class SingleRegionFleet : public ScenarioWithGameServer
{
public:
static const FText& Name()
{
return Menu::DeploymentServer::kSingleRegionFleet;
}
static TUniquePtr<IAWSScenario> Create()
{
return MakeUnique<SingleRegionFleet>();
}
virtual FText GetTooltip() const override
{
return Menu::DeploymentServer::kSingleRegionFleetTooltip;
}
virtual FString GetFolderName() const override
{
return Menu::DeploymentServer::kSingleRegionFleetFolder;
}
virtual FText GetUserName() const override
{
return Name();
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Base/ScenarioWithGameServer.h"
#include "GameLiftCoreConstants.h"
namespace AwsScenarios
{
class SpotFleets : public ScenarioWithGameServer
{
public:
static const FText& Name()
{
return Menu::DeploymentServer::kSpotFleets;
}
static TUniquePtr<IAWSScenario> Create()
{
return MakeUnique<SpotFleets>();
}
virtual FText GetTooltip() const override
{
return Menu::DeploymentServer::kSpotFleetsTooltip;
}
virtual FString GetFolderName() const override
{
return Menu::DeploymentServer::kSpotFleetsFolder;
}
virtual FText GetUserName() const override
{
return Name();
}
};
} // namespace AwsScenarios

View File

@@ -0,0 +1,296 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "GameLiftContainersHandler.h"
#include "aws/gamelift/core/exports.h"
#include "aws/gamelift/GameLiftClient.h"
#include "GameLiftCoreConstants.h"
#include "GameLiftCoreLog.h"
#include "IGameLiftCoreModule.h"
#include "Utils/StringConvertors.h"
#include <Utils/StringPaths.h>
using namespace Aws::GameLift::Model::ContainerFleetBillingTypeMapper;
using namespace Aws::GameLift::Model::ContainerFleetStatusMapper;
#define LOCTEXT_NAMESPACE "GameLiftContainersHandler"
namespace GameLiftContainersHandlerInternal
{
ECRFuncErrorCallback ErrorCallback = [](DISPATCH_RECEIVER_HANDLE ErrorReceiver, ECR_ERROR_INFO* ErrorInfo) -> void
{
FString* Error = reinterpret_cast<FString*>(ErrorReceiver);
*Error = ErrorInfo->errorMessage;
};
FuncErrorCallback GameLiftErrorCallback = [](DISPATCH_RECEIVER_HANDLE ErrorReceiver, GAMELIFT_ERROR_INFO* ErrorInfo) -> void
{
FString* Error = reinterpret_cast<FString*>(ErrorReceiver);
*Error = ErrorInfo->errorMessage;
};
} // namespace GameLiftContainersHandlerInternal
void GameLiftContainersHandler::SetupContainersDirectory(const FString BuildDirectory, const FString GameExecutable, const FString ContainersDestinationDirectory)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Setting up containers directory"));
// Unreal file I/O interface
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
// Prepare directory
FString BuildDestinationDirectory = FPaths::Combine(*ContainersDestinationDirectory, TEXT("gamebuild"));
if (FPaths::DirectoryExists(*ContainersDestinationDirectory))
{
PlatformFile.DeleteDirectoryRecursively(*ContainersDestinationDirectory);
}
PlatformFile.CreateDirectoryTree(*ContainersDestinationDirectory);
PlatformFile.CreateDirectoryTree(*BuildDestinationDirectory);
// Copy the build directory to destination folder
FString BuildDirectoryName = FPaths::GetCleanFilename(BuildDirectory);
BuildDestinationDirectory = FPaths::Combine(*BuildDestinationDirectory, *BuildDirectoryName);
PlatformFile.CreateDirectoryTree(*BuildDestinationDirectory);
PlatformFile.CopyDirectoryTree(*BuildDestinationDirectory, *BuildDirectory, true);
// Copy Dockerfile
auto DockerfileTemplatePath = Paths::ContainersTemplatePath();
PlatformFile.CopyFile(*FPaths::Combine(*ContainersDestinationDirectory, TEXT("Dockerfile")), *DockerfileTemplatePath);
}
GameLiftECRCreateRepositoryResult GameLiftContainersHandler::CreateRepository(const FString& InRepositoryName)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
std::string StdRepositoryName = Convertors::FSToStdS(InRepositoryName);
GAMELIFT_ECR_REPO_URI ECRRepoUri;
GAMELIFT_ECR_CREATE_REPO_REQUEST Request;
Request.repositoryName = StdRepositoryName.c_str();
FString ErrorMessageReceiver;
Request.errorCb = GameLiftContainersHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GameLiftECRCreateRepositoryResult Result;
Result.bIsSuccessful = GameLiftECRCreateRepository(AccountInstance->GetInstance(), &Request, &ECRRepoUri);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully created ECR Repository: %s"), *InRepositoryName);
Result.RepoUri = FString(ECRRepoUri.repoUri);
Result.RepositoryName = InRepositoryName;
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to create ECR Repository '%s' - %s"), *InRepositoryName, *(Result.ErrorMessage));
}
return Result;
}
GameLiftECRDescribeRepositoriesResult GameLiftContainersHandler::DescribeRepositories()
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
GAMELIFT_ECR_DESCRIBE_REPOSITORIES_REQUEST Request;
FString ErrorMessageReceiver;
Request.errorCb = GameLiftContainersHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GAMELIFT_ECR_DESCRIBE_REPO_INFO DescribeReposInfo;
GameLiftECRDescribeRepositoriesResult Result;
if (AccountInstance->GetInstance())
{
Result.bIsSuccessful = GameLiftECRDescribeRepositories(AccountInstance->GetInstance(), &Request, &DescribeReposInfo);
Result.ErrorMessage = ErrorMessageReceiver;
}
else
{
Result.bIsSuccessful = false;
}
if (Result.bIsSuccessful)
{
for (int i = 0; i < DescribeReposInfo.numRepos; i++)
{
auto& repoInfo = DescribeReposInfo.repos[i];
Result.Repos.Add({ FString(repoInfo.repoName), FString(repoInfo.repoUri) });
}
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully retrieved ECR Repositories info"));
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to retrieve ECR Repositories info - %s"), *(Result.ErrorMessage));
}
return Result;
}
GameLiftECRListImagesResult GameLiftContainersHandler::ListImages(const FString& InRepositoryName)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
std::string StdRepositoryName = Convertors::FSToStdS(InRepositoryName);
GAMELIFT_ECR_LIST_IMAGES_REQUEST Request;
Request.repositoryName = StdRepositoryName.c_str();
FString ErrorMessageReceiver;
Request.errorCb = GameLiftContainersHandlerInternal::ErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GAMELIFT_ECR_LIST_IMAGES_INFO ListImagesInfo;
GameLiftECRListImagesResult Result;
if (AccountInstance->GetInstance())
{
Result.bIsSuccessful = GameLiftECRListImages(AccountInstance->GetInstance(), &Request, &ListImagesInfo);
Result.ErrorMessage = ErrorMessageReceiver;
}
else
{
Result.bIsSuccessful = false;
}
if (Result.bIsSuccessful)
{
for (int i = 0; i < ListImagesInfo.numImages; i++)
{
auto& imageInfo = ListImagesInfo.images[i];
Result.Images.Add({ FString(imageInfo.imageDigest), FString(imageInfo.imageTag) });
}
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully listed ECR Images info"));
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to list ECR iamges info - %s"), *(Result.ErrorMessage));
}
return Result;
}
GameLiftContainersListCgdsResult GameLiftContainersHandler::ListCgds()
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
GAMELIFT_CONTAINERS_LIST_CGDS_REQUEST Request;
FString ErrorMessageReceiver;
Request.errorCb = GameLiftContainersHandlerInternal::GameLiftErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GAMELIFT_CONTAINERS_LIST_CGD_INFO ListCgdInfo;
GameLiftContainersListCgdsResult Result;
if (AccountInstance->GetInstance())
{
Result.bIsSuccessful = GameLiftContainersListCgds(AccountInstance->GetInstance(), &Request, &ListCgdInfo);
Result.ErrorMessage = ErrorMessageReceiver;
}
else
{
Result.bIsSuccessful = false;
}
if (Result.bIsSuccessful)
{
for (int i = 0; i < ListCgdInfo.numCgds; i++)
{
auto& cgdInfo = ListCgdInfo.cgds[i];
Result.Cgds.Add({ FString(cgdInfo.cgdName) });
}
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully retrieved container group definitions info"));
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to retrieve container group definitions info - %s"), *(Result.ErrorMessage));
}
return Result;
}
GameLiftDescribeCgdResult GameLiftContainersHandler::DescribeCgd(const FString& InCgdName)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
std::string StdCgdName = Convertors::FSToStdS(InCgdName);
GAMELIFT_CONTAINERS_DESCRIBE_CGD_INFO DescribeCgdInfo;
GAMELIFT_CONTAINERS_DESCRIBE_CGD_REQUEST Request;
Request.cgdName = StdCgdName.c_str();
FString ErrorMessageReceiver;
Request.errorCb = GameLiftContainersHandlerInternal::GameLiftErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GameLiftDescribeCgdResult Result;
Result.bIsSuccessful = GameLiftContainersDescribeCgd(AccountInstance->GetInstance(), &Request, &DescribeCgdInfo);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully described container group definition: %s"), *InCgdName);
Result.CgdVersion = FString::FromInt(DescribeCgdInfo.cgdVersion);
Result.CgdStatus = FString(DescribeCgdInfo.cgdStatus);
UE_LOG(GameLiftCoreLog, Log, TEXT("Container group definition status is: %s"), *Result.CgdStatus);
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to described container group definition '%s' - %s"), *InCgdName, *(Result.ErrorMessage));
}
return Result;
}
GameLiftDescribeContainerFleetResult GameLiftContainersHandler::DescribeContainerFleet(const FString& GameName)
{
IAWSAccountInstance* AccountInstance = IGameLiftCoreModule::Get().GetProfileBootstrap().GetAccountInstance();
check(AccountInstance);
check(AccountInstance->GetInstance());
auto AccountHandle = AccountInstance->GetInstance();
GAMELIFT_CONTAINERS_DESCRIBE_CONTAINER_FLEET_INFO DescribeContainerFleetInfo;
GAMELIFT_CONTAINERS_DESCRIBE_CONTAINER_FLEET_REQUEST Request;
FString ErrorMessageReceiver;
Request.errorCb = GameLiftContainersHandlerInternal::GameLiftErrorCallback;
Request.errorReceiver = &ErrorMessageReceiver;
GameLiftDescribeContainerFleetResult Result;
std::string StdGameName = Convertors::FSToStdS(GameName);
GameLiftAccountSetGameName(AccountHandle, StdGameName.c_str()); // game name needed to get the stack name
Result.bIsSuccessful = GameLiftContainersDescribeContainerFleet(AccountHandle, &Request, &DescribeContainerFleetInfo);
Result.ErrorMessage = ErrorMessageReceiver;
if (Result.bIsSuccessful)
{
auto fleetStatusStd = GetNameForContainerFleetStatus(DescribeContainerFleetInfo.containerFleetStatus);
auto FleetTypeStd = GetNameForContainerFleetBillingType(DescribeContainerFleetInfo.containerFleetBillingType);
auto InstanceTypeStd = DescribeContainerFleetInfo.instanceType;
Result.FleetId = FString(DescribeContainerFleetInfo.fleetId);
Result.FleetStatus = FString(fleetStatusStd.c_str());
Result.FleetType = FString(FleetTypeStd.c_str());
Result.InstanceType = FString(InstanceTypeStd.c_str());
UE_LOG(GameLiftCoreLog, Log, TEXT("Successfully described container fleet: %s"), *Result.FleetId);
}
else
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Failed to described container fleet - %s"), *(Result.ErrorMessage));
}
return Result;
}

View File

@@ -0,0 +1,26 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IGameLiftContainersHandler.h"
class GameLiftContainersHandler : public IGameLiftContainersHandler
{
public:
GameLiftContainersHandler() = default;
void SetupContainersDirectory(const FString BuildZipSource, const FString GameExecutable, const FString ContainersDestinationDirectory) override;
GameLiftECRCreateRepositoryResult CreateRepository(const FString& InRepositoryName) override;
GameLiftECRDescribeRepositoriesResult DescribeRepositories() override;
GameLiftECRListImagesResult ListImages(const FString& InRepositoryName) override;
GameLiftContainersListCgdsResult ListCgds() override;
GameLiftDescribeCgdResult DescribeCgd(const FString& InCgdName) override;
GameLiftDescribeContainerFleetResult DescribeContainerFleet(const FString& GameName) override;
};

View File

@@ -0,0 +1,139 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "FGameLiftCoreModule.h"
#include "CoreMinimal.h"
#include "GameLiftCoreProc.h"
#include "AWSScenariosDeployer.h"
#include "AWSConfigFileProfile.h"
#include "AWSBootstrapProfile.h"
#include "Anywhere/GameLiftAnywhereHandler.h"
#include "Containers/GameLiftContainersHandler.h"
#if PLATFORM_WINDOWS
#include "Windows/AllowWindowsPlatformTypes.h"
#endif
#include "aws/core/Aws.h"
#include <aws/core/client/ClientConfiguration.h>
#include <aws/core/client/AWSClient.h>
#include <aws/core/client/AWSErrorMarshaller.h>
#include <aws/gamelift/core/gamelift_account.h>
#include <aws/gamelift/core/exports.h>
#if PLATFORM_WINDOWS
#include "Windows/HideWindowsPlatformTypes.h"
#endif
#include "GameLiftCoreLog.h"
namespace Internal
{
void LogCallback(unsigned int Level, const char* Message, int Size)
{
std::cout << __FUNCTION__ << ": level [" << Level << "], message [" << Message << "], size [" << Size << "]\n";
}
class SimpleCaller
{
public:
virtual void OnHandleResult(const char* Result)
{
std::cout << "GameLiftGetAwsAccountId result : " << Result << std::endl;
}
static void OnCallback(void* DispatchReceiver, const char* CharPtr)
{
SimpleCaller* Instance = static_cast<SimpleCaller*>(DispatchReceiver);
return Instance->OnHandleResult(CharPtr);
}
};
} // namespace Internal
#define LOCTEXT_NAMESPACE "FGameLiftCoreModule"
static void TestGameLiftCore()
{
const char* AccessKey = nullptr;
const char* SecretKey = nullptr; // Use your secret.
Internal::SimpleCaller Caller;
unsigned int result = GameLiftGetAwsAccountId(&Caller, &Internal::SimpleCaller::OnCallback, AccessKey, SecretKey, Internal::LogCallback);
}
//***************************************************************************************************************************
static class UUserWidget* CreatedWidget;
FGameLiftCoreModule::FGameLiftCoreModule()
: Deployer(new AWSScenariosDeployer), ProfileBootstrap(new AWSBootstrapProfile), AnywhereHandler(new GameLiftAnywhereHandler), ContainersHandler(new GameLiftContainersHandler)
{
}
void FGameLiftCoreModule::StartupModule()
{
UE_LOG(GameLiftCoreLog, Display, TEXT("%s"), Core::Logs::kStartupModule);
// TEST : AWS Core Library ...
//TestGameLiftCore();
auto LogProxy = [](unsigned int InLevel, const char* InMessage, int InSize)
{
UE_LOG(GameLiftCoreLog, Log, TEXT(">>>>> %s"), UTF8_TO_TCHAR(InMessage));
};
GameLift::AwsApiInitializer::Initialize(LogProxy, this);
UE_LOG(GameLiftCoreLog, Display, TEXT("%s"), Core::Logs::kDllLoaded);
}
void FGameLiftCoreModule::ShutdownModule()
{
UE_LOG(GameLiftCoreLog, Display, TEXT("%s"), Core::Logs::kShutdownModule);
FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(GameLiftCoreTabName);
GameLift::AwsApiInitializer::Shutdown();
}
bool FGameLiftCoreModule::SupportsDynamicReloading()
{
return true;
}
TSharedRef<IGameLiftCoreProc> FGameLiftCoreModule::MakeRunner()
{
return MakeShared<GameLiftCoreProc>();
}
IAWSScenariosDeployer& FGameLiftCoreModule::GetScenarioDeployer()
{
return *Deployer;
}
IAWSBootstrapProfile& FGameLiftCoreModule::GetProfileBootstrap()
{
return *ProfileBootstrap;
}
IGameLiftAnywhereHandler& FGameLiftCoreModule::GetGameLiftAnywhereHandler()
{
return *AnywhereHandler;
}
IGameLiftContainersHandler& FGameLiftCoreModule::GetGameLiftContainersHandler()
{
return *ContainersHandler;
}
TSharedRef<IAWSConfigFileProfile> FGameLiftCoreModule::MakeAWSConfigFileProfile()
{
return MakeShared<AWSConfigFileProfile>();
}
IMPLEMENT_MODULE(FGameLiftCoreModule, GameLiftCore);
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,53 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IGameLiftCoreModule.h"
const FName GameLiftCoreTabName{ Core::sGameLiftPluginName };
/**
* Implements the GameLiftCore module.
*/
class FGameLiftCoreModule : public IGameLiftCoreModule
{
public:
FGameLiftCoreModule();
//~ Begin IModuleInterface Interface
virtual void StartupModule() override;
virtual void ShutdownModule() override;
virtual bool SupportsDynamicReloading() override;
//~ End IModuleInterface Interface
//~ Begin IGameLiftCoreModule Interface
virtual TSharedRef<IGameLiftCoreProc> MakeRunner() override;
virtual IAWSScenariosDeployer& GetScenarioDeployer() override;
virtual IGameLiftAnywhereHandler& GetGameLiftAnywhereHandler() override;
virtual IGameLiftContainersHandler& GetGameLiftContainersHandler() override;
//~ End IGameLiftCoreModule Interface
virtual IAWSBootstrapProfile& GetProfileBootstrap() override;
//~ End IModuleInterface Interface
TSharedRef<IAWSConfigFileProfile> MakeAWSConfigFileProfile() override;
private:
//Stored slate widget that was loaded
class UUserWidget* CreatedWidget;
private:
TSharedRef<IAWSScenariosDeployer> Deployer;
TSharedRef<IAWSBootstrapProfile> ProfileBootstrap;
TSharedRef<IGameLiftAnywhereHandler> AnywhereHandler;
TSharedRef<IGameLiftContainersHandler> ContainersHandler;
bool bShowDetails;
};

View File

@@ -0,0 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "GameLiftCoreLog.h"
DEFINE_LOG_CATEGORY(GameLiftCoreLog);

View File

@@ -0,0 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
DECLARE_LOG_CATEGORY_EXTERN(GameLiftCoreLog, Log, All);

View File

@@ -0,0 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Platforms/GameLiftCoreProcImpl.h"

View File

@@ -0,0 +1,11 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "GameLiftExports.h"
#include "IGameLiftCoreModule.h"
FString UGameLiftExports::GetGameLiftPluginName()
{
return FString(Core::sGameLiftPluginName);
}

View File

@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if PLATFORM_WINDOWS || PLATFORM_HOLOLENS
#include "Windows/WinGameLiftCoreProc.h"
#elif PLATFORM_MAC
#include "Mac/MacGameLiftCoreProc.h"
#elif PLATFORM_LINUX
#include "Linux/LinuxGameLiftCoreProc.h"
#endif

View File

@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "LinuxGameLiftCoreProc.h"
bool GameLiftCoreProc::LaunchProcess(const FString& Path, TArray<FString> Arguments)
{
ensure(false);
return false;
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,16 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if !PLATFORM_LINUX
#error Only Linux platform is supported
#endif
#include "IGameLiftCoreProc.h"
class GameLiftCoreProc : public IGameLiftCoreProc
{
public:
bool LaunchProcess(const FString& Path, TArray<FString> Arguments) override;
};

View File

@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "MacGameLiftCoreProc.h"
bool GameLiftCoreProc::LaunchProcess(const FString& Path, TArray<FString> Arguments)
{
ensure(false);
return false;
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,16 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if !PLATFORM_MAC
#error Only Mac platform is supported
#endif
#include "IGameLiftCoreProc.h"
class GameLiftCoreProc : public IGameLiftCoreProc
{
public:
bool LaunchProcess(const FString& path, TArray<FString> arguments) override;
};

View File

@@ -0,0 +1,132 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "WinGameLiftCoreProc.h"
#include "Misc/InteractiveProcess.h"
#include "Interfaces/IPluginManager.h"
#include "Utils/StringPaths.h"
#include "GameLiftCoreLog.h"
#include "GameLiftCoreConstants.h"
#include "Windows/AllowWindowsPlatformTypes.h"
#include <shellapi.h>
#include <ShlObj.h>
#include <LM.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include "Windows/HideWindowsPlatformTypes.h"
#include "Windows/WindowsPlatformMisc.h"
#define LOCTEXT_NAMESPACE "GameLiftCoreProc"
namespace Internal
{
bool IsCmd(const FString& Path)
{
return Path.Contains("cmd");
}
std::pair<bool, FProcHandle> RunExe(const FString& Path, const FString& Params = "")
{
UE_LOG(GameLiftCoreLog, Log, TEXT("Launch process %s : %s"), *Path, *Params);
if (!IsCmd(Path) && !FPaths::FileExists(Path))
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Launch process failed %s : %s. File not found"), *Path, *Params);
return { false, {} };
}
auto Proc = FPlatformProcess::CreateProc(*Path, *Params, true, false, false, nullptr, 0, nullptr, nullptr);
if (!Proc.IsValid())
{
FPlatformProcess::CloseProc(Proc);
return { false, Proc };
}
return { true, Proc };
}
FString ArgumentArrayToString(TArray<FString> Arguments)
{
FString Params;
for (const auto& Arg : Arguments)
{
Params += " " + Arg;
}
return Params;
}
std::pair<bool, FProcHandle> LaunchWindowsCmd(const FString& Path, TArray<FString> Arguments)
{
if (!FPaths::FileExists(Path))
{
UE_LOG(GameLiftCoreLog, Error, TEXT("Launch process failed %s. File not found"), *Path);
return { false, {} };
}
auto CmdParams = "start cmd.exe @cmd /k \"" + Path + "\"";
CmdParams += ArgumentArrayToString(Arguments);
return RunExe(FString("cmd.exe"), CmdParams);
}
auto IsWinProcRunning(FProcHandle& ProcessHandle, unsigned int WaitMs = 0)
{
bool bApplicationRunning = true;
uint32 WaitResult = ::WaitForSingleObject(ProcessHandle.Get(), WaitMs);
if (WaitResult != WAIT_TIMEOUT)
{
FPlatformProcess::CloseProc(ProcessHandle);
bApplicationRunning = false;
}
return bApplicationRunning;
}
bool ValidateProcessOutput(const FString& Path, TArray<FString> Arguments, const FString& ExpectedValue)
{
if (Path.IsEmpty())
{
return false;
}
FString Output;
FInteractiveProcess process(Path, ArgumentArrayToString(Arguments), true);
process.OnOutput().BindLambda([&Output](const FString& stdOut)
{
Output += stdOut;
});
process.Launch();
auto processHandle = process.GetProcessHandle();
::WaitForSingleObject(processHandle.Get(), Process::kWaitForProcMs);
return Output.Contains(ExpectedValue);
}
}
bool GameLiftCoreProc::LaunchProcess(const FString& Path, TArray<FString> Arguments)
{
static const auto kWaitMs = 500;
bool IsLaunched = false;
auto Status = Internal::LaunchWindowsCmd(Path, Arguments);
if (Status.first)
{
IsLaunched = Internal::IsWinProcRunning(Status.second, kWaitMs);
}
return IsLaunched;
}
#undef LOCTEXT_NAMESPACE
GameLiftCoreProc::GameLiftCoreProc()
{
}

View File

@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if !PLATFORM_WINDOWS && !PLATFORM_HOLOLENS
#error Only Widows platform is supported
#endif
#include "IGameLiftCoreProc.h"
class GameLiftCoreProc : public IGameLiftCoreProc
{
public:
GameLiftCoreProc();
bool LaunchProcess(const FString& Path, TArray<FString> Arguments) override;
};

View File

@@ -0,0 +1,29 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <Logging/LogVerbosity.h>
#include "aws/gamelift/core/logging.h"
namespace Convertors
{
inline ELogVerbosity::Type FromAwsLogLevelToUe(unsigned int AwsLogLevel)
{
using namespace GameLift::Logger;
Level EnumAwsLogLevel = Level(AwsLogLevel);
switch (AwsLogLevel)
{
case Level::Verbose: return ELogVerbosity::Log;
case Level::Info: return ELogVerbosity::Display;
case Level::Warning: return ELogVerbosity::Warning;
case Level::Error: return ELogVerbosity::Error;
default:
break;
}
return ELogVerbosity::VeryVerbose;
}
} // namespace Convertors

View File

@@ -0,0 +1,47 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <mutex>
namespace Logs
{
class MessageStorage
{
public:
void Set(const char* NewMessage)
{
std::lock_guard<std::mutex> Guard(Mutex);
Message = Convertors::ASToFS(NewMessage);
}
void Set(FString&& NewMessage)
{
std::lock_guard<std::mutex> Guard(Mutex);
Message = std::move(NewMessage);
}
void Set(const FText& NewMessage)
{
std::lock_guard<std::mutex> Guard(Mutex);
Message = NewMessage.ToString();
}
FString Get()
{
std::lock_guard<std::mutex> Guard(Mutex);
return Message;
}
void Clear()
{
std::lock_guard<std::mutex> Guard(Mutex);
Message.Reset();
}
private:
FString Message = {};
std::mutex Mutex = {};
};
} // namespace Logs

View File

@@ -0,0 +1,29 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Utils/LogLevelConvertors.h"
namespace Logs
{
template<typename TextChar>
inline auto PrintAwsLog(unsigned int Level, const char* Message, int Size, TextChar* Tag)
{
#define PRINT_LOG_AND_EXIT(__x__) UE_LOG(GameLiftCoreLog, __x__, TEXT("%s %s"), Tag, *FString(Message)); return UeLogLevel
auto UeLogLevel = Convertors::FromAwsLogLevelToUe(Level);
switch (UeLogLevel)
{
case ELogVerbosity::Log: PRINT_LOG_AND_EXIT(Log);
case ELogVerbosity::Display: PRINT_LOG_AND_EXIT(Display);
case ELogVerbosity::Warning: PRINT_LOG_AND_EXIT(Warning);
case ELogVerbosity::Error: PRINT_LOG_AND_EXIT(Error);
}
PRINT_LOG_AND_EXIT(VeryVerbose);
#undef PRINT_LOG
}
} // namespace Logs

View File

@@ -0,0 +1,27 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <string>
#include <Containers/StringConv.h>
namespace Convertors
{
inline std::string FSToStdS(const FString & String)
{
if (String.IsEmpty())
{
return {};
}
auto CastedString = StringCast<ANSICHAR>(*String);
auto* Chars = CastedString.Get();
return std::string(Chars, strlen(Chars));
}
inline FString ASToFS(const char* RawString)
{
return FString(StringCast<TCHAR>(RawString).Get());
}
} // namespace Convertors

View File

@@ -0,0 +1,61 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <string>
#include <Interfaces/IPluginManager.h>
#include "GameLiftCoreConstants.h"
namespace Paths
{
inline const auto& PluginRootPath()
{
static FString PluginRootPath =
FPaths::ConvertRelativePathToFull(*IPluginManager::Get().FindPlugin(Core::sGameLiftPluginName)->GetBaseDir());
return PluginRootPath;
}
inline const auto& CloudFormationRootPath()
{
static FString CloudFormationRootPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(
PluginRootPath(),
TEXT("Resources"),
TEXT("CloudFormation")
));
return CloudFormationRootPath;
}
inline const auto& IntermediateCloudFormationRootPath()
{
static FString CloudFormationRootPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(
PluginRootPath(),
TEXT("Intermediate"),
TEXT("CloudFormation")
));
return CloudFormationRootPath;
}
inline const auto& ContainersTemplatePath()
{
static FString ContainersTemplateRootPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(
PluginRootPath(),
TEXT("Resources"),
TEXT("Containers"),
TEXT("SampleDockerfile")
));
return ContainersTemplateRootPath;
}
inline const auto ScenarioPath(const FString& Scenario)
{
return FPaths::Combine(CloudFormationRootPath(), Scenario);
}
inline const auto ScenarioInstancePath(const FString& Scenario)
{
return FPaths::Combine(IntermediateCloudFormationRootPath(), TEXT("instance"), Scenario);
}
} // namespace Paths

View File

@@ -0,0 +1,104 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "CoreMinimal.h"
#include "Misc/EngineVersion.h"
namespace UnrealVersion
{
/**
* Represents a semantic version with Major, Minor, and Patch components
*/
struct Version {
int32 Major;
int32 Minor;
int32 Patch;
bool IsOlderThan(const Version& Other) const
{
if (Major != Other.Major) return Major < Other.Major;
if (Minor != Other.Minor) return Minor < Other.Minor;
return Patch < Other.Patch;
}
bool IsSameAs(const Version& Other) const
{
return Major == Other.Major &&
Minor == Other.Minor &&
Patch == Other.Patch;
}
bool IsNewerThan(const Version& Other) const
{
if (Major != Other.Major) return Major > Other.Major;
if (Minor != Other.Minor) return Minor > Other.Minor;
return Patch > Other.Patch;
}
// Operator overloads
bool operator<(const Version& Other) const { return IsOlderThan(Other); }
bool operator>(const Version& Other) const { return IsNewerThan(Other); }
bool operator==(const Version& Other) const { return IsSameAs(Other); }
bool operator!=(const Version& Other) const { return !IsSameAs(Other); }
bool operator<=(const Version& Other) const { return IsOlderThan(Other) || IsSameAs(Other); }
bool operator>=(const Version& Other) const { return IsNewerThan(Other) || IsSameAs(Other); }
};
// Predefine Unreal Versions
inline const Version INVALID_VERSION{ 0, 0, 0 };
inline const Version UE5_6_0{ 5, 6, 0 };
}; // namespace UnrealVersion
namespace UnrealVersionUtils
{
/**
* Gets the current Unreal Engine version
* @return The current engine version
*/
inline const FString GetCurrentEngineVersion()
{
FEngineVersion CurrentVersion = FEngineVersion::Current();
FString VersionString = FString::Printf(TEXT("%d.%d.%d"),
CurrentVersion.GetMajor(),
CurrentVersion.GetMinor(),
CurrentVersion.GetPatch());
return VersionString;
}
inline UnrealVersion::Version ParseVersionString(FString& unrealStr)
{
TArray<FString> parts;
unrealStr.ParseIntoArray(parts, TEXT("."), true);
if (parts.Num() != 3)
{
return UnrealVersion::INVALID_VERSION;
}
// Convert strings to integers
int32 major = FCString::Atoi(*parts[0]);
int32 minor = FCString::Atoi(*parts[1]);
int32 patch = FCString::Atoi(*parts[2]);
return UnrealVersion::Version{ major, minor, patch };
}
/**
* Converts a Version to a string representation
* @param Version The version to convert
* @return Version as a string in format "Major.Minor.Patch"
*/
inline FString GetVersionString(UnrealVersion::Version& version) {
FString VersionString = FString::Printf(TEXT("%d.%d.%d"),
version.Major,
version.Minor,
version.Patch);
return VersionString;
}
} // namespace UnrealVersionUtils

View File

@@ -0,0 +1,162 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "CoreMinimal.h"
namespace Menu
{
namespace DeploymentServer
{
static const auto kSingleRegionFleet = NSLOCTEXT("SGameLiftDeploymentMenu", "SingleRegionFleet_Scenario", "Single-region fleet");
static const auto kSpotFleets = NSLOCTEXT("SGameLiftDeploymentMenu", "SpotFleets_Scenario", "Spot fleet");
static const auto kFlexMatch = NSLOCTEXT("SGameLiftDeploymentMenu", "FlexMath_Scenario", "FlexMatch fleet");
static const auto kContainersSingleRegionFleet = NSLOCTEXT("SGameLiftDeploymentMenu", "ContainersSingleRegionFleet_Scenario", "Single-region Containers Fleet");
static const auto kContainersFlexMatch = NSLOCTEXT("SGameLiftDeploymentMenu", "ContainersFlexMath_Scenario", "FlexMatch Containers Fleet");
static const auto kCustom = NSLOCTEXT("SGameLiftDeploymentMenu", "Custom_Scenario", "Custom");
static const auto kSingleRegionFleetTooltip = NSLOCTEXT("SGameLiftDeploymentMenu", "SingleRegionFleet_ToolTip",
"Use this scenario to deploy a minimal managed EC2 fleet for your game server. This scenario also sets up player authentication for your game and creates a backend service for game clients to start and join game sessions.");
static const auto kSpotFleetsTooltip = NSLOCTEXT("SGameLiftDeploymentMenu", "SpotFleets_ToolTip",
"Forms matches by using Amazon GameLift queues and a custom matchmaker and configures three fleets.");
static const auto kFlexMatchTooltip = NSLOCTEXT("SGameLiftDeploymentMenu", "FlexMath_ToolTip",
"Use this scenario to deploy a fully configured set of managed EC2 fleets with matchmaking. This scenario also sets up a queue to manage game session placement across Spot and On-Demand fleets, handles player authentication and creates a backend service for game clients to request matchmaking and join matches.");
static const auto kContainersSingleRegionFleetTooltip = NSLOCTEXT("SGameLiftDeploymentMenu", "ContainersSingleRegionFleet_ToolTip",
"Creates a game backend service with a single Amazon GameLift Containers fleet.");
static const auto kContainersFlexMatchTooltip = NSLOCTEXT("SGameLiftDeploymentMenu", "ContainersFlexMath_ToolTip",
"Uses FlexMatch, a managed matchmaking service, to match game players together across Amazon GameLift Containers fleets.");
static const auto kCustomTooltip = NSLOCTEXT("SGameLiftDeploymentMenu", "Custom_ToolTip",
"This is a custom user scenario.");
static const auto kSingleRegionFleetFolder = TEXT("scenario1_single_fleet");
static const auto kSpotFleetsFolder = TEXT("scenario2_spot_fleets");
static const auto kFlexMatchFolder = TEXT("scenario3_flexmatch");
static const auto kContainersSingleRegionFleetFolder = TEXT("scenario3_containers_single_fleet");
static const auto kContainersFlexMatchFolder = TEXT("scenario4_containers_flexmatch");
static const auto kCurrentScenarioFolder = TEXT("scenario_current");
static const auto kCustomScenarioFolder = TEXT("scenario_custom");
}
} // namespace Menu
namespace Bootstrap
{
namespace Logs
{
static const auto kLogReceived = TEXT("Native log message: ");
static const auto kReceiveBucketNameCallback = TEXT("AWSBootstrapProfile: Received a bucket name:");
static const auto kBootstrapStarted = TEXT("AWSBootstrapProfile: Bootstrapping.........");
static const auto kBootstrapCompleted = TEXT("AWSBootstrapProfile: Bootstrapped.");
static const auto kBootstrapFailedCreateAccount = TEXT("AWSBootstrapProfile: Unable to create AWS credentials profile with an error: ");
static const auto kBootstrapFailedBootstrap = TEXT("AWSBootstrapProfile:Unable to bootstrap account with an error: ");
static const auto kBootstrapFailedAccountNotValid = TEXT("AWSBootstrapProfile: Account does not contain valid data.");
}
} // namespace Bootstrap
namespace Deploy
{
static const auto kMaxGameNameWithPrefixLength = 30;
namespace Logs
{
static const auto kLogReceived = TEXT("Native log message:");
static const auto kReceiveReplacementIdCallback = TEXT("AWSScenariosDeployer: Received a function replacement id:");
static const auto kReceiveClientConfigPathCallback = TEXT("AWSScenariosDeployer: Received a client config path:");
static const auto kRunAwsScenario = TEXT("AWSScenariosDeployer: Run scenario:");
static const auto kRunCustomScenario = TEXT("AWSScenariosDeployer: Run custom scenario path:");
static const auto kAccountInstanceIsNull = TEXT("AWSScenariosDeployer: Invalid account instance, bootstrap is required.");
static const auto kCreateAndSetFunctionsReplacementIdFailed = TEXT("GameLiftAccountCreateAndSetFunctionsReplacementId failed with error:");
static const auto kGetMainFunctionsReplacementIdFailed = TEXT("kGetMainFunctionsReplacementIdFailed failed with error:");
static const auto kCreateLaunchPathParameterFailed = TEXT("CreateLaunchPathParameter failed with error:");
static const auto kInvalidServerFilePath = TEXT("Game Server File Path has to be a subpath of Game Server Build Folder.");
static const auto kSaveFeatureInstanceTemplatesFailed = TEXT("GameLiftAccountSaveFeatureInstanceTemplates failed with error:");
static const auto kAccountUploadFunctionsFailed = TEXT("GameLiftAccountUploadFunctions failed with error:");
static const auto kUploadGameServerFailed = TEXT("GameLiftAccountUploadGameServer failed with error:");
static const auto kCreateOrUpdateMainStackFailed = TEXT("GameLiftAccountCreateOrUpdateMainStack failed with error:");
static const auto kDeployApiGatewayStageFailed = TEXT("GameLiftAccountDeployApiGatewayStage failed with error:");
static const auto kDeploymentStackStatusFailed = TEXT("Deployment stack status failed with error:");
static const auto kDeploymentHasBeenStopped = TEXT("Deployment has been cancelled by user.");
static const auto kDeploymentStackStatus = TEXT("Deployment stack status is:");
static const auto kDeploymentStop = TEXT("Stop deployment...");
}
namespace Errors
{
static const auto kAccountIsInvalidText = NSLOCTEXT("SGameLiftDeploymentMenu", "AccountIsInvalidText", "This account is invalid. Please check your credentials.");
static const auto kGameNameIsTooLongText = NSLOCTEXT("SGameLiftDeploymentMenu", "GameNameIsTooLongText", "Game name is too long. Game name must have 1-16 characters.");
static const auto kNoStacksToStopDeployment = NSLOCTEXT("SGameLiftDeploymentMenu", "kNoStacksToStopDeployment", "Currently no active stacks are available.");
static const auto kUnableToStopDeployment = NSLOCTEXT("SGameLiftDeploymentMenu", "kUnableToStopDeployment", "Currently it is not possible to stop deployment.");
}
} // namespace Deploy
namespace Account
{
namespace Logs
{
static const auto kLogReceived = TEXT("Native log message: ");
static const auto kUnableToBuildCredentials = TEXT("AwsAccountInstanceManager: Unable to build credentials.");
static const auto kUnableToBuildAccountInfo = TEXT("AwsAccountInstanceManager: Unable to build account info.");
static const auto kAccountIsNotCreated = TEXT("AwsAccountInstanceManager: Account is not created.");
static const auto kAccountIsInvalid = TEXT("AwsAccountInstanceManager: Account is invalid.");
}
} // namespace Account
namespace Credentials
{
namespace Logs
{
static const auto kLogReceived = TEXT("Native log message: ");
static const auto kUnableToGetAccountId = TEXT("AwsAccountCredentials: Unable to get account id with an error:");
}
} // namespace Credentials
namespace Aws
{
namespace Config
{
static const auto kUserPoolClientIdYamlName = "user_pool_client_id";
static const auto kApiGatewayEndpointYamlName = "identity_api_gateway_base_url";
}
namespace Status
{
static const auto kStackUndeployed = "UNDEPLOYED";
static const auto kStackUpdateComplete = "UPDATE_COMPLETE";
static const auto kStackCreateComplete = "CREATE_COMPLETE";
}
} // namespace Aws
namespace Process
{
static const auto kWaitForProcMs = 5000;
} // namespace Process
namespace Core
{
static const auto sGameLiftCoreName = TEXT("GameLiftCore");
static const auto sGameLiftPluginName = TEXT("GameLiftPlugin");
namespace Logs
{
static const auto kStartupModule = TEXT("FGameLiftCoreModule StartupModule");
static const auto kShutdownModule = TEXT("FGameLiftCoreModule Shutting down");
static const auto kDllLoaded = TEXT("DLL loaded");
}
} // namespace Core
namespace Anywhere
{
static const auto kCustomLocationPrefix = TEXT("custom-location-unreal");
static const auto kAnywhereFleetDescription = TEXT("Deployed by the Amazon GameLift Plug-in for Unreal.");
static const auto kAnywhereFleetTagKey = TEXT("CreatedBy");
static const auto kAnywhereFleetTagValue = TEXT("AmazonGameLiftUnrealPlugin");
}

View File

@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GameLiftExports.generated.h"
UCLASS()
class GAMELIFTCORE_API UGameLiftExports : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, Category = "GameLiftExports")
static FString GetGameLiftPluginName();
};

View File

@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
class IAWSAccountInstance
{
public:
virtual ~IAWSAccountInstance() = default;
virtual bool IsValid() const = 0;
virtual void* GetInstance() const = 0;
virtual FString GetBucketName() const = 0;
virtual const char* GetGameName() const = 0;
virtual const char* GetAccountId() const = 0;
virtual const char* GetBuildConfiguration() const = 0;
virtual FString GetLastErrorMessage() const = 0;
};

View File

@@ -0,0 +1,22 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IAWSConfigFileProfile.h"
class FString;
class IAWSAccountInstance;
class IAWSBootstrapProfile
{
public:
virtual ~IAWSBootstrapProfile() = default;
virtual bool ConfigureAccount(const FString& ProfileName, TSharedRef<IAWSConfigFileProfile> ProfileReader, const FString& ExistingBucketName = "") = 0;
virtual bool Bootstrap(const FString& NewBucketName = "") = 0;
virtual FString GetLastError() const = 0;
virtual FString GetLastErrorMessage() const = 0;
virtual FString GetDefaultBucketName(const FString& ProfileName, TSharedRef<IAWSConfigFileProfile> ProfileReader) const = 0;
virtual IAWSAccountInstance* GetAccountInstance() = 0;
};

View File

@@ -0,0 +1,30 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Containers/UnrealString.h"
#include "Containers/Array.h"
class IAWSConfigFileProfile
{
public:
virtual ~IAWSConfigFileProfile() = default;
virtual TArray<FString> GetProfileNames() const = 0;
virtual void CreateProfile(const FString& ProfileName) = 0;
virtual void RenameProfile(const FString& ProfileName, const FString& NewProfileName) = 0;
virtual FString GetAccessKey(const FString& ProfileName) const = 0;
virtual void SetAccessKey(const FString& ProfileName, const FString& accessKey) = 0;
virtual FString GetSecretAccessKey(const FString& ProfileName) const = 0;
virtual void SetSecretAccessKey(const FString& ProfileName, const FString& secretAccessKey) = 0;
virtual FString GetSessionToken(const FString& ProfileName) const = 0;
virtual void SetSessionToken(const FString& ProfileName, const FString& sessionToken) = 0;
virtual FString GetRegion(const FString& ProfileName) const = 0;
virtual void SetRegion(const FString& ProfileName, const FString& region) = 0;
virtual void Save() = 0;
};

View File

@@ -0,0 +1,62 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IAWSAccountInstance.h"
enum class IAWSScenariosCategory : unsigned int
{
ManagedEC2 = 0,
Containers = 1
};
class IAWSScenariosDeployer
{
public:
virtual ~IAWSScenariosDeployer() = default;
virtual bool DeployManagedEC2Scenario(
const FText& Scenario,
IAWSAccountInstance* AccountInstance,
const FString& GameName,
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
const FString& OutConfigFilePath,
const FString& ExtraServerResourcesPath,
bool EnableMetrics
) = 0;
virtual bool DeployCustomScenario(
const FString& CustomScenarioPath,
IAWSAccountInstance* AccountInstance,
const FString& GameName,
const FString& BuildOperatingSystem,
const FString& BuildFolderPath,
const FString& BuildFilePath,
const FString& OutConfigFilePath,
const FString& ExtraServerResourcesPath
) = 0;
virtual bool DeployContainerScenario(
const FText& Scenario,
IAWSAccountInstance* AccountInstance,
const FString& ContainerGroupDefinitionName,
const FString& ContainerImageName,
const FString& ContainerImageUri,
const FString& IntraContainerLaunchPath,
const FString& GameName, const FString& OutConfigFilePath,
const FText& ConnectionPortRange,
const FString& TotalVcpuLimit,
const FString& TotalMemoryLimit,
bool EnableMetrics
) = 0;
virtual bool StopDeployment(IAWSAccountInstance* AwsAccountInstance) = 0;
virtual FString GetLastCognitoClientId() const = 0;
virtual FString GetLastApiGatewayEndpoint() const = 0;
virtual FString GetLastError() const = 0;
virtual FString GetLastErrorMessage() const = 0;
virtual TArray<FText> GetScenarios(const IAWSScenariosCategory Category) const = 0;
virtual FText GetToolTip(const FText& ScenarioName, const IAWSScenariosCategory Category) const = 0;
};

View File

@@ -0,0 +1,72 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Containers/UnrealString.h"
#include "Containers/Array.h"
struct GameLiftAnywhereResult
{
bool bIsSuccessful;
FString ErrorMessage;
};
struct GameLiftAnywhereCreateLocationResult : public GameLiftAnywhereResult
{
FString LocationName;
};
struct GameLiftAnywhereCreateFleetResult : public GameLiftAnywhereResult
{
FString FleetName;
FString FleetId;
};
struct GameLiftAnywhereAddFleetLocationResult : public GameLiftAnywhereResult
{
FString LocationName;
FString FleetId;
};
struct GameLiftAnywhereDescribeFleetsResult : public GameLiftAnywhereResult
{
struct FleetAttributes
{
FString FleetName;
FString FleetId;
};
TArray<FleetAttributes> Fleets;
};
struct GameLiftAnywhereRegisterComputeResult : public GameLiftAnywhereResult
{
FString ComputeName;
FString LinkedFleetId;
FString RegisteredIPAddress;
};
struct GameLiftAnywhereAuthTokenResult : public GameLiftAnywhereResult
{
FString AuthToken;
FDateTime ExpirationTime;
};
class IGameLiftAnywhereHandler
{
public:
virtual ~IGameLiftAnywhereHandler() = default;
virtual GameLiftAnywhereCreateLocationResult CreateCustomLocation(const FString& InRegion) = 0;
virtual GameLiftAnywhereCreateFleetResult CreateFleet(const FString& InFleetName, const FString& InCustomLocation) = 0;
virtual GameLiftAnywhereAddFleetLocationResult AddFleetLocation(const FString& InFleetId, const FString& InCustomLocation) = 0;
virtual GameLiftAnywhereDescribeFleetsResult DescribeAnywhereFleets() = 0;
virtual GameLiftAnywhereRegisterComputeResult RegisterCompute(const FString& InComputeName, const FString& InIPAddress, const FString& InFleetId, const FString& InCustomLocation) = 0;
virtual GameLiftAnywhereAuthTokenResult GenerateAuthToken(const FString& InFleetId, const FString& InComputeName) = 0;
};

View File

@@ -0,0 +1,88 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
struct GameLiftECRResult
{
bool bIsSuccessful;
FString ErrorMessage;
};
struct GameLiftContainersResult
{
bool bIsSuccessful;
FString ErrorMessage;
};
struct GameLiftECRCreateRepositoryResult : public GameLiftECRResult
{
FString RepositoryName;
FString RepoUri;
};
struct GameLiftDescribeCgdResult : public GameLiftContainersResult
{
FString CgdVersion;
FString CgdStatus;
};
struct GameLiftDescribeContainerFleetResult : public GameLiftContainersResult
{
FString FleetId;
FString FleetStatus;
FString FleetType;
FString InstanceType;
};
struct GameLiftContainersCreateCgdResult : public GameLiftContainersResult
{
FString CgdName;
};
struct GameLiftContainersListCgdsResult : public GameLiftContainersResult
{
struct CgdAttributes
{
FString CgdName;
};
TArray<CgdAttributes> Cgds;
};
struct GameLiftECRDescribeRepositoriesResult : public GameLiftECRResult
{
struct RepositoryAttributes
{
FString RepositoryName;
FString RepositoryUri;
};
TArray<RepositoryAttributes> Repos;
};
struct GameLiftECRListImagesResult : public GameLiftECRResult
{
struct ImageDetailAttributes
{
FString ImageDigest;
FString ImageTag;
};
TArray<ImageDetailAttributes> Images;
};
class IGameLiftContainersHandler
{
public:
virtual ~IGameLiftContainersHandler() = default;
virtual void SetupContainersDirectory(const FString BuildZipSource, const FString GameExecutable, const FString ContainersDestinationDirectory) = 0;
virtual GameLiftECRCreateRepositoryResult CreateRepository(const FString& InRepositoryName) = 0;
virtual GameLiftECRDescribeRepositoriesResult DescribeRepositories() = 0;
virtual GameLiftECRListImagesResult ListImages(const FString& InRepositoryName) = 0;
virtual GameLiftContainersListCgdsResult ListCgds() = 0;
virtual GameLiftDescribeCgdResult DescribeCgd(const FString& InCgdName) = 0;
virtual GameLiftDescribeContainerFleetResult DescribeContainerFleet(const FString& GameName) = 0;
};

View File

@@ -0,0 +1,57 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "IGameLiftCoreProc.h"
#include "IAWSScenariosDeployer.h"
#include "IAWSConfigFileProfile.h"
#include "IAWSBootstrapProfile.h"
#include "IGameLiftAnywhereHandler.h"
#include "IGameLiftContainersHandler.h"
#include "GameLiftCoreConstants.h"
#include "Templates/SharedPointer.h"
/**
* Interface for the ObjectBrowser module.
*/
class IGameLiftCoreModule : public IModuleInterface
{
public:
/**
* Singleton-like access to this module's interface. This is just for convenience!
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
*
* @return Returns singleton instance, loading the module on demand if needed
*/
static inline IGameLiftCoreModule& Get()
{
return FModuleManager::LoadModuleChecked<IGameLiftCoreModule>(Core::sGameLiftCoreName);
}
/**
* Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
*
* @return True if the module is loaded and ready to use
*/
static inline bool IsAvailable()
{
return FModuleManager::Get().IsModuleLoaded(Core::sGameLiftCoreName);
}
public:
virtual TSharedRef<IGameLiftCoreProc> MakeRunner() = 0;
virtual IAWSScenariosDeployer& GetScenarioDeployer() = 0;
virtual IAWSBootstrapProfile& GetProfileBootstrap() = 0;
virtual IGameLiftAnywhereHandler& GetGameLiftAnywhereHandler() = 0;
virtual IGameLiftContainersHandler& GetGameLiftContainersHandler() = 0;
virtual TSharedRef<IAWSConfigFileProfile> MakeAWSConfigFileProfile() = 0;
/**
* Virtual destructor
*/
virtual ~IGameLiftCoreModule() { }
};

View File

@@ -0,0 +1,11 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
class IGameLiftCoreProc
{
public:
virtual ~IGameLiftCoreProc() = default;
virtual bool LaunchProcess(const FString& path, TArray<FString> arguments) = 0;
};