Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions Source/FicsitRemoteMonitoring/Private/FRMConfigInitSubsystem.cpp
Original file line number Diff line number Diff line change
@@ -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<UConfigManager>();
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;
}
66 changes: 36 additions & 30 deletions Source/FicsitRemoteMonitoring/Private/FicsitRemoteMonitoring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<UFRMConfigInitSubsystem>();
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()
Expand Down Expand Up @@ -1082,4 +1083,9 @@ void AFicsitRemoteMonitoring::HandleEndpoint(FString InEndpoint, FRequestData Re
TSharedPtr<FJsonObject> FirstJsonObject = JsonValues[0]->AsObject();
Out_Data = UFRM_RequestLibrary::JsonObjectToString(FirstJsonObject, JSONDebugMode);
}
}

void AFicsitRemoteMonitoring::SetAuthToken(const FString& Token)
{
AuthenticationToken = Token;
}
33 changes: 33 additions & 0 deletions Source/FicsitRemoteMonitoring/Public/FRMConfigInitSubsystem.h
Original file line number Diff line number Diff line change
@@ -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);
};
5 changes: 5 additions & 0 deletions Source/FicsitRemoteMonitoring/Public/FicsitRemoteMonitoring.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class FICSITREMOTEMONITORING_API AFicsitRemoteMonitoring : public AModSubsystem
bool JSONDebugMode = false;
bool bShouldStop = false;
bool bHasRunningPushDataLoop = false;

FString AuthenticationToken;

friend class UFGPowerCircuitGroup;

Expand All @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down