// Fill out your copyright notice in the Description page of Project Settings. #include "Game/ShooterGameMode.h" #include "Logging/LogMacros.h" #if WITH_GAMELIFT #include "GameLiftServerSDK.h" #endif DEFINE_LOG_CATEGORY(LogShooterGameMode) AShooterGameMode::AShooterGameMode() { UE_LOG(LogShooterGameMode, Log, TEXT("Initializing ShooterGameMode...")); } void AShooterGameMode::BeginPlay() { Super::BeginPlay(); #if WITH_GAMELIFT InitGameLift(); #endif } void AShooterGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) { Super::InitGame(MapName, Options, ErrorMessage); UE_LOG(LogShooterGameMode, Log, TEXT("[%s] Parsing CLI"), *FDateTime::UtcNow().ToString(TEXT("%Y%m%d-%H%M%S"))); CachedCommandLine = FCommandLine::Get(); bool bIsCriticalError = false; // Parsing of Command Line bDebugMode = FParse::Param(*CachedCommandLine, TEXT("Debug")); if (bDebugMode) { UE_LOG(LogShooterGameMode, Log, TEXT("Debug mode: ENABLED")); #if UE_BUILD_DEBUG UE_LOG(LogShooterGameMode, Log, TEXT("Command Line Arguments: %s"), *CachedCommandLine); #endif } ServerPort = GetConfiguredOrDefaultPort(); bIsAnywhereFleet = FParse::Param(*CachedCommandLine, TEXT("glAnywhere")); if (bIsAnywhereFleet) { UE_LOG(LogShooterGameMode, Log, TEXT("GameLift Anywhere Fleet Command Line Parsing")); UE_LOG(LogShooterGameMode, Log, TEXT("======Command Line Parameters======")); if (!FParse::Value(*CachedCommandLine, TEXT("fleetID="), FleetId)) { UE_LOG(LogShooterGameMode, Error, TEXT("FleetId Missing in Command Line")); bIsCriticalError = true; } else { UE_LOG(LogShooterGameMode, Log, TEXT("Fleet ID: %s"), *FleetId); } if (!FParse::Value(*CachedCommandLine, TEXT("authtoken="), AuthToken)) { UE_LOG(LogShooterGameMode, Error, TEXT("AuthToken Missing in Command Line")); bIsCriticalError = true; } else { if (bDebugMode) { FString TokenHash = GetSHA256Hash(AuthToken); UE_LOG(LogShooterGameMode, Log, TEXT("AuthToken: %s"), *TokenHash); } else { UE_LOG(LogShooterGameMode, Log, TEXT("AuthToken Length: %d"), AuthToken.Len()); } } if (!FParse::Value(*CachedCommandLine, TEXT("hostId="), HostId)) { UE_LOG(LogShooterGameMode, Error, TEXT("HostId Missing in Command Line")); bIsCriticalError = true; } else { UE_LOG(LogShooterGameMode, Log, TEXT("Host ID: %s"), *HostId); } if (!FParse::Value(*CachedCommandLine, TEXT("websocketUrl="), WebSocketUrl)) { UE_LOG(LogShooterGameMode, Error, TEXT("WebSocketUrl Missing in Command Line")); bIsCriticalError = true; } else { UE_LOG(LogShooterGameMode, Log, TEXT("Websocket URL: %s"), *WebSocketUrl); bool bValidWebSocket = WebSocketUrl.StartsWith(TEXT("wss://")) || WebSocketUrl.StartsWith(TEXT("ws://")); if (bValidWebSocket) { int32 ColonPos = WebSocketUrl.Find(TEXT(":"), ESearchCase::CaseSensitive); int32 SlashPos = WebSocketUrl.Find(TEXT("/"), ESearchCase::CaseSensitive, ESearchDir::FromStart, ColonPos + 1); int32 ParsedPort = 443; // Default wss if (WebSocketUrl.StartsWith(TEXT("ws://"))) ParsedPort = 80; if (ColonPos != INDEX_NONE && SlashPos != INDEX_NONE) { FString PortStr = WebSocketUrl.Mid(ColonPos + 1, SlashPos - ColonPos - 1); int32 ExplicitPort = FCString::Atoi(*PortStr); if (ExplicitPort > 1024 && ExplicitPort <= 65535) // Privileged ports OK for servers { ParsedPort = ExplicitPort; } else { bValidWebSocket = false; // Invalid explicit port } } UE_LOG(LogShooterGameMode, Log, TEXT("WebSocket Parsed Port: %d"), ParsedPort); } if (!bValidWebSocket) { UE_LOG(LogShooterGameMode, Error, TEXT("Invalid WebSocketUrl: %s"), *WebSocketUrl); bIsCriticalError = true; } } if (ServerPort == 0) { UE_LOG(LogShooterGameMode, Error, TEXT("Invalid or Missing Server Port Number. Shutting Down.")); bIsCriticalError = true; } else { UE_LOG(LogShooterGameMode, Log, TEXT("Port: %d"), ServerPort); } if (!FParse::Value(*CachedCommandLine, TEXT("serverRegion="), ServerRegion)) { UE_LOG(LogShooterGameMode, Warning, TEXT("ServerRegion Missing in Command Line")); } else { UE_LOG(LogShooterGameMode, Log, TEXT(">>>Server Region: %s"), *ServerRegion); } UE_LOG(LogShooterGameMode, Log, TEXT("===================================")); } else { UE_LOG(LogShooterGameMode, Log, TEXT("GameLift EC2 Fleet")); if (ServerPort == 0) { UE_LOG(LogShooterGameMode, Error, TEXT("Invalid or Missing Server Port Number. Shutting Down.")); bIsCriticalError = true; } else { UE_LOG(LogShooterGameMode, Log, TEXT("Port: %d"), ServerPort); } } if (bIsCriticalError) { UE_LOG(LogShooterGameMode, Error, TEXT("Critical Missing or Invalid Arguments in Command Line. Shutting Down.")); FPlatformMisc::RequestExit(true); } else { UE_LOG(LogShooterGameMode, Log, TEXT("Command Line Parsed Successfully.")); } } int32 AShooterGameMode::GetConfiguredOrDefaultPort() const { // Default Unreal Engine listen/dedicated server port int32 Port = 7777; // Check if a port was passed via command line: -port=xxxx int32 CmdPort = 0; if (FParse::Value(*CachedCommandLine, TEXT("port="), CmdPort)) { if (CmdPort > 1024 && CmdPort <= 65535) { Port = CmdPort; } else { Port = 0; } } return Port; } FString AShooterGameMode::GetSHA256Hash(const FString& Input) { FTCHARToUTF8 Utf8Input(Input); FSHA256Signature Hash; if (FPlatformMisc::GetSHA256Signature(reinterpret_cast(Utf8Input.Get()), Utf8Input.Length(), Hash)) { return Hash.ToString(); } return FString::Printf(TEXT("Fail_%dbytes"), Input.Len()); } void AShooterGameMode::InitGameLift() { //TODO: Need to write later, working on parser first. }