diff --git a/Source/FicsitRemoteMonitoring/Private/FRMConfigInitSubsystem.cpp b/Source/FicsitRemoteMonitoring/Private/FRMConfigInitSubsystem.cpp new file mode 100644 index 00000000..27f5cc9b --- /dev/null +++ b/Source/FicsitRemoteMonitoring/Private/FRMConfigInitSubsystem.cpp @@ -0,0 +1,50 @@ +#include "FRMConfigInitSubsystem.h" +#include "Configuration/ConfigManager.h" +#include "Engine/Engine.h" + +void UFRMConfigInitSubsystem::Initialize(FSubsystemCollectionBase& Collection) +{ + Super::Initialize(Collection); + + UConfigManager* ConfigManager = GetGameInstance()->GetSubsystem(); + if (!ConfigManager) + { + UE_LOG(LogTemp, Error, TEXT("[FRMConfigInitSubsystem] ConfigManager missing.")); + return; + } + + ConfigManager->ReloadModConfigurations(); + + // Now config is loaded and safe to read/write + HttpConfig = FConfig_HTTPStruct::GetActiveConfig(this); + SerialConfig = FConfig_SerialStruct::GetActiveConfig(this); + FactoryConfig = FConfig_FactoryStruct::GetActiveConfig(this); + + if (HttpConfig.Authentication_Token.IsEmpty()) + { + HttpConfig.Authentication_Token = GenerateAuthToken(32); + HttpConfig.Save(GetWorld()); + + UE_LOG(LogTemp, Log, TEXT("[FRMConfigInitSubsystem] Generated and saved new token: %s"), *HttpConfig.Authentication_Token); + } + else + { + UE_LOG(LogTemp, Log, TEXT("[FRMConfigInitSubsystem] Token already exists.")); + } + + AuthenticationToken = HttpConfig.Authentication_Token; +} + +FString UFRMConfigInitSubsystem::GenerateAuthToken(const int32 Length) +{ + const FString Characters = TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + const int32 CharactersCount = Characters.Len(); + + FString RandomString; + for (int32 i = 0; i < Length; ++i) + { + RandomString.AppendChar(Characters[FMath::RandRange(0, CharactersCount - 1)]); + } + + return RandomString; +} diff --git a/Source/FicsitRemoteMonitoring/Private/FicsitRemoteMonitoring.cpp b/Source/FicsitRemoteMonitoring/Private/FicsitRemoteMonitoring.cpp index 34a44246..51e840f3 100644 --- a/Source/FicsitRemoteMonitoring/Private/FicsitRemoteMonitoring.cpp +++ b/Source/FicsitRemoteMonitoring/Private/FicsitRemoteMonitoring.cpp @@ -10,6 +10,7 @@ #include "EventsLibrary.h" #include "FactoryLibrary.h" #include "FicsitRemoteMonitoringModule.h" +#include "FRMConfigInitSubsystem.h" #include "Async/Async.h" #include "FRM_Request.h" #include "Hypertubes.h" @@ -59,46 +60,46 @@ void AFicsitRemoteMonitoring::BeginPlay() { Super::BeginPlay(); - // Load FRM's API Endpoints - InitAPIRegistry(); + // Load FRM's API Endpoints + InitAPIRegistry(); - // get config structs - auto HttpConfig = FConfig_HTTPStruct::GetActiveConfig(GetWorld()); - auto SerialConfig = FConfig_SerialStruct::GetActiveConfig(GetWorld()); - - if (HttpConfig.Web_Autostart) { StartWebSocketServer(); } - if (SerialConfig.COM_Autostart) { InitSerialDevice(); } - - UWorld* World = GetWorld(); + // Get our config subsystem + auto ConfigSubsystem = GetGameInstance()->GetSubsystem(); + if (ConfigSubsystem) + { + SetAuthToken(ConfigSubsystem->GetAuthenticationToken()); + } - // generate new authentication token if no token is available - if (HttpConfig.Authentication_Token.IsEmpty()) + if (!ConfigSubsystem) { - HttpConfig.Authentication_Token = GenerateAuthToken(32); - UE_LOG(LogHttpServer, Warning, TEXT("Authentication Token not set, generated a new token: %s"), *HttpConfig.Authentication_Token); - HttpConfig.Save(World); + UE_LOG(LogTemp, Error, TEXT("[AFicsitRemoteMonitoring] Config subsystem missing!")); + return; } - - // store JSONDebugMode into a local property to prevent crash while access to GetActiveConfig while the EndPlay process - const auto FactoryConfig = FConfig_FactoryStruct::GetActiveConfig(World); - JSONDebugMode = FactoryConfig.JSONDebugMode; - // Register the callback to ensure WebSocket is stopped on crash/exit - FCoreDelegates::OnExit.AddUObject(this, &AFicsitRemoteMonitoring::StopWebSocketServer); -} + // Use cached config values from the subsystem + const auto& HttpConfig = ConfigSubsystem->GetHttpConfig(); + const auto& SerialConfig = ConfigSubsystem->GetSerialConfig(); + const auto& FactoryConfig = ConfigSubsystem->GetFactoryConfig(); -FString AFicsitRemoteMonitoring::GenerateAuthToken(const int32 Length) -{ - const FString Characters = TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); - const int32 CharactersCount = Characters.Len(); + // Save locally + JSONDebugMode = FactoryConfig.JSONDebugMode; - FString RandomString; - for (int32 i = 0; i < Length; ++i) + // Start services based on config + if (HttpConfig.Web_Autostart) { - RandomString.AppendChar(Characters[FMath::RandRange(0, CharactersCount - 1)]); + StartWebSocketServer(); } - return RandomString; + if (SerialConfig.COM_Autostart) + { + InitSerialDevice(); + } + + // Store token for use in auth checks + SetAuthToken(ConfigSubsystem->GetAuthenticationToken()); + + // Register the callback to ensure WebSocket is stopped on crash/exit + FCoreDelegates::OnExit.AddUObject(this, &AFicsitRemoteMonitoring::StopWebSocketServer); } void AFicsitRemoteMonitoring::StartWebSocketPushDataLoop() @@ -1082,4 +1083,9 @@ void AFicsitRemoteMonitoring::HandleEndpoint(FString InEndpoint, FRequestData Re TSharedPtr FirstJsonObject = JsonValues[0]->AsObject(); Out_Data = UFRM_RequestLibrary::JsonObjectToString(FirstJsonObject, JSONDebugMode); } +} + +void AFicsitRemoteMonitoring::SetAuthToken(const FString& Token) +{ + AuthenticationToken = Token; } \ No newline at end of file diff --git a/Source/FicsitRemoteMonitoring/Public/FRMConfigInitSubsystem.h b/Source/FicsitRemoteMonitoring/Public/FRMConfigInitSubsystem.h new file mode 100644 index 00000000..73efc6fb --- /dev/null +++ b/Source/FicsitRemoteMonitoring/Public/FRMConfigInitSubsystem.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "Config_HTTPStruct.h" +#include "Config_SerialStruct.h" +#include "Config_FactoryStruct.h" +#include "FRMConfigInitSubsystem.generated.h" + +UCLASS() +class FICSITREMOTEMONITORING_API UFRMConfigInitSubsystem : public UGameInstanceSubsystem +{ + GENERATED_BODY() + +public: + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + + UFUNCTION(BlueprintCallable, Category = "RemoteMonitoring") + FString GetAuthenticationToken() const { return AuthenticationToken; } + + const FConfig_HTTPStruct& GetHttpConfig() const { return HttpConfig; } + const FConfig_SerialStruct& GetSerialConfig() const { return SerialConfig; } + const FConfig_FactoryStruct& GetFactoryConfig() const { return FactoryConfig; } + +private: + FString AuthenticationToken; + + FConfig_HTTPStruct HttpConfig; + FConfig_SerialStruct SerialConfig; + FConfig_FactoryStruct FactoryConfig; + + FString GenerateAuthToken(int32 Length); +}; diff --git a/Source/FicsitRemoteMonitoring/Public/FicsitRemoteMonitoring.h b/Source/FicsitRemoteMonitoring/Public/FicsitRemoteMonitoring.h index 74d6fb4d..b6f927c1 100644 --- a/Source/FicsitRemoteMonitoring/Public/FicsitRemoteMonitoring.h +++ b/Source/FicsitRemoteMonitoring/Public/FicsitRemoteMonitoring.h @@ -104,6 +104,8 @@ class FICSITREMOTEMONITORING_API AFicsitRemoteMonitoring : public AModSubsystem bool JSONDebugMode = false; bool bShouldStop = false; bool bHasRunningPushDataLoop = false; + + FString AuthenticationToken; friend class UFGPowerCircuitGroup; @@ -112,6 +114,9 @@ class FICSITREMOTEMONITORING_API AFicsitRemoteMonitoring : public AModSubsystem AFicsitRemoteMonitoring(); virtual ~AFicsitRemoteMonitoring(); + void SetAuthToken(const FString& Token); + FString GetAuthToken() const { return AuthenticationToken; } + friend class UFGServerSubsystem; friend class UFGServerAPIManager; diff --git a/Source/FicsitRemoteMonitoringServer/FicsitRemoteMonitoringServer.build.cs b/Source/FicsitRemoteMonitoringServer/FicsitRemoteMonitoringServer.build.cs index e61d8e51..5976b616 100644 --- a/Source/FicsitRemoteMonitoringServer/FicsitRemoteMonitoringServer.build.cs +++ b/Source/FicsitRemoteMonitoringServer/FicsitRemoteMonitoringServer.build.cs @@ -42,9 +42,9 @@ public FicsitRemoteMonitoringServer(ReadOnlyTargetRules Target) : base(Target) public void ApplySMLPatch() { + // Example ModuleDirectory: C:\Modding\Satisfactory\SatisfactoryModLoader\Mods\FicsitRemoteMonitoring\Source\FicsitRemoteMonitoring string patchPath = Path.Combine(ModuleDirectory, "..", "..", "Patches", "FGServerAPIManager-FRM-04162025.patch"); - string headerPath = Path.Combine(ModuleDirectory, "..", "..", "FactoryGame", "Source", "FactoryDedicatedServer", - "Public", "Networking", "FGServerAPIManager.h"); + string headerPath = Path.Combine(ModuleDirectory, "..", "..", "..", "..", "Source", "FactoryDedicatedServer", "Public", "Networking", "FGServerAPIManager.h"); // Check if the target line is still 'private:' before patching bool needsPatch = false;