diff --git a/Config/FilterPlugin.ini b/Config/FilterPlugin.ini deleted file mode 100644 index ccebca2..0000000 --- a/Config/FilterPlugin.ini +++ /dev/null @@ -1,8 +0,0 @@ -[FilterPlugin] -; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and -; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. -; -; Examples: -; /README.txt -; /Extras/... -; /Binaries/ThirdParty/*.dll diff --git a/HarmonyLink.uplugin b/HarmonyLink.uplugin new file mode 100644 index 0000000..c69226e --- /dev/null +++ b/HarmonyLink.uplugin @@ -0,0 +1,24 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "HarmonyLink", + "Description": "", + "Category": "Other", + "CreatedBy": "Jordon Brooks", + "CreatedByURL": "https://jordongamedev.co.uk", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": true, + "IsExperimentalVersion": true, + "Installed": false, + "Modules": [ + { + "Name": "HarmonyLink", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ] +} diff --git a/HarmonyLinkUE.uplugin b/HarmonyLinkUE.uplugin deleted file mode 100644 index dd850a1..0000000 --- a/HarmonyLinkUE.uplugin +++ /dev/null @@ -1,26 +0,0 @@ -{ - "FileVersion": 3, - "Version": 1, - "VersionName": "1.0", - "FriendlyName": "HarmonyLinkUE", - "Description": "A plugin that provides real-time device metrics for games running on handheld devices, starting with the Steam Deck.", - "Category": "Handheld", - "CreatedBy": "Jordon Brooks", - "CreatedByURL": "https://jordongamedev.co.uk", - "DocsURL": "", - "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/adec045fde54477a81f7829eb7c46afe", - "SupportURL": "", - "EngineVersion": "5.2.0", - "CanContainContent": false, - "IsBetaVersion": false, - "IsExperimentalVersion": true, - "Installed": false, - "Modules": [ - { - "Name": "HarmonyLinkUE", - "Type": "Runtime", - "LoadingPhase": "PreLoadingScreen", - "WhitelistPlatforms": ["Win64", "Linux"] - } - ] -} diff --git a/Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs b/Source/HarmonyLink/HarmonyLink.Build.cs similarity index 60% rename from Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs rename to Source/HarmonyLink/HarmonyLink.Build.cs index 2c8ad84..ede23b2 100644 --- a/Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs +++ b/Source/HarmonyLink/HarmonyLink.Build.cs @@ -1,10 +1,11 @@ -// Some copyright should be here... +// Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; +using System.IO; -public class HarmonyLinkUE : ModuleRules +public class HarmonyLink : ModuleRules { - public HarmonyLinkUE(ReadOnlyTargetRules Target) : base(Target) + public HarmonyLink(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; @@ -18,6 +19,7 @@ public class HarmonyLinkUE : ModuleRules PrivateIncludePaths.AddRange( new string[] { // ... add other private include paths required here ... + "ThirdParty/HarmonyLinkLib/include" } ); @@ -26,9 +28,9 @@ public class HarmonyLinkUE : ModuleRules new string[] { "Core", - "HTTP", - "Json", - "JsonUtilities" + "CoreUObject", + "Engine", + "Projects" // ... add other public dependencies that you statically link with here ... } ); @@ -37,10 +39,6 @@ public class HarmonyLinkUE : ModuleRules PrivateDependencyModuleNames.AddRange( new string[] { - "CoreUObject", - "Engine", - "Slate", - "SlateCore", // ... add private dependencies that you statically link with here ... } ); @@ -52,5 +50,10 @@ public class HarmonyLinkUE : ModuleRules // ... add any modules that your module loads dynamically here ... } ); + + PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib")); + + + RuntimeDependencies.Add("$(BinaryOutputDir)/HarmonyLinkLib.dll", Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll")); } } diff --git a/Source/HarmonyLink/Private/HarmonyLink.cpp b/Source/HarmonyLink/Private/HarmonyLink.cpp new file mode 100644 index 0000000..da94234 --- /dev/null +++ b/Source/HarmonyLink/Private/HarmonyLink.cpp @@ -0,0 +1,18 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "HarmonyLink.h" +#include "Modules/ModuleManager.h" + +#define LOCTEXT_NAMESPACE "FHarmonyLinkModule" + +void FHarmonyLinkModule::StartupModule() +{ +} + +void FHarmonyLinkModule::ShutdownModule() +{ +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FHarmonyLinkModule, HarmonyLink) diff --git a/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp b/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp new file mode 100644 index 0000000..9a35811 --- /dev/null +++ b/Source/HarmonyLink/Private/HarmonyLinkLibrary.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2023 Jordon Brooks + + +#include "HarmonyLinkLibrary.h" + +#include + +bool UHarmonyLinkLibrary::IsWine() +{ + static bool IsWine_ = HarmonyLinkLib::get_is_wine(); + return IsWine_; +} + +bool UHarmonyLinkLibrary::IsLinux() +{ + static bool IsLinux_ = +#if PLATFORM_WINDOWS + IsWine(); +#elif PLATFORM_LINUX + true; +#else + false; +#endif + + return IsLinux_; +} + +bool UHarmonyLinkLibrary::IsSteamDeck() +{ + static bool IsSteamDeck_ = GetDeviceInfo().Device == EDevice::STEAM_DECK; + return IsSteamDeck_; +} + +FCPUInfo UHarmonyLinkLibrary::GetCPUInfo() +{ + static FCPUInfo CPUInfo(HarmonyLinkLib::get_cpu_info()); + return CPUInfo; +} + +FDevice UHarmonyLinkLibrary::GetDeviceInfo() +{ + return FDevice(); +} + +FOSVerInfo UHarmonyLinkLibrary::GetOSInfo() +{ + return FOSVerInfo(); +} + +FBattery UHarmonyLinkLibrary::GetBatteryStatus() +{ + return FBattery(HarmonyLinkLib::get_battery_status()); +} diff --git a/Source/HarmonyLink/Private/Structs/Battery.cpp b/Source/HarmonyLink/Private/Structs/Battery.cpp new file mode 100644 index 0000000..3978e75 --- /dev/null +++ b/Source/HarmonyLink/Private/Structs/Battery.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2023 Jordon Brooks + +#include "Structs/Battery.h" + +#include + +FBattery::FBattery(HarmonyLinkLib::FBattery* battery) +{ + if (battery) + { + HasBattery = battery->has_battery; + IsACConnected = battery->is_connected_to_ac; + BatteryPercent = battery->battery_percent; + + battery->free(); + } + else + { + UE_LOG(LogTemp, Error, TEXT("Failed to convert FBattery.")) + } +} diff --git a/Source/HarmonyLink/Private/Structs/CPUInfo.cpp b/Source/HarmonyLink/Private/Structs/CPUInfo.cpp new file mode 100644 index 0000000..f075203 --- /dev/null +++ b/Source/HarmonyLink/Private/Structs/CPUInfo.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2023 Jordon Brooks + +#include "Structs/CPUInfo.h" + +FCPUInfo::FCPUInfo(HarmonyLinkLib::FCPUInfo* cpu_info) +{ + if (cpu_info) + { + VendorID = cpu_info->VendorID.c_str(); + ModelName = cpu_info->Model_Name.c_str(); + PhysicalCores = cpu_info->Physical_Cores; + LogicalCores = cpu_info->Logical_Cores; + + for (const HarmonyLinkLib::FString& Flag : cpu_info->Flags) + { + Flags.Add(Flag.c_str()); + } + + cpu_info->free(); + } + else + { + UE_LOG(LogTemp, Error, TEXT("Failed to convert FCPUInfo.")) + } +} diff --git a/Source/HarmonyLink/Public/Enums/Device.h b/Source/HarmonyLink/Public/Enums/Device.h new file mode 100644 index 0000000..066f952 --- /dev/null +++ b/Source/HarmonyLink/Public/Enums/Device.h @@ -0,0 +1,17 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Device.generated.h" + +/** + * + */ +UENUM(BlueprintType) +enum class EDevice : uint8 +{ + DESKTOP UMETA(DisplayName = "Desktop"), + LAPTOP UMETA(DisplayName = "Laptop"), + HANDHELD UMETA(DisplayName = "Handheld"), + + STEAM_DECK UMETA(DisplayName = "Steam Deck") +}; diff --git a/Source/HarmonyLink/Public/Enums/Platform.h b/Source/HarmonyLink/Public/Enums/Platform.h new file mode 100644 index 0000000..492c31b --- /dev/null +++ b/Source/HarmonyLink/Public/Enums/Platform.h @@ -0,0 +1,16 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Platform.generated.h" + +/** + * + */ +UENUM(BlueprintType) +enum class EPlatform : uint8 +{ + WINDOWS UMETA(DisplayName = "Windows"), + LINUX UMETA(DisplayName = "Linux"), + MAC UMETA(DisplayName = "Mac"), + UNIX UMETA(DisplayName = "Unix") +}; diff --git a/Source/HarmonyLinkUE/Public/HarmonyLinkUE.h b/Source/HarmonyLink/Public/HarmonyLink.h similarity index 64% rename from Source/HarmonyLinkUE/Public/HarmonyLinkUE.h rename to Source/HarmonyLink/Public/HarmonyLink.h index d530782..116fad0 100644 --- a/Source/HarmonyLinkUE/Public/HarmonyLinkUE.h +++ b/Source/HarmonyLink/Public/HarmonyLink.h @@ -1,10 +1,10 @@ -// Copyright Jordon Brooks © 2023 +// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Modules/ModuleManager.h" -class FHarmonyLinkUEModule : public IModuleInterface +class FHarmonyLinkModule : public IModuleInterface { public: diff --git a/Source/HarmonyLink/Public/HarmonyLinkLibrary.h b/Source/HarmonyLink/Public/HarmonyLinkLibrary.h new file mode 100644 index 0000000..a9ef618 --- /dev/null +++ b/Source/HarmonyLink/Public/HarmonyLinkLibrary.h @@ -0,0 +1,41 @@ +// Copyright (C) 2023 Jordon Brooks + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Structs/Battery.h" +#include "Structs/CPUInfo.h" +#include "Structs/FDevice.h" +#include "Structs/OSVerInfo.h" +#include "HarmonyLinkLibrary.generated.h" + +/** + * + */ +UCLASS() +class HARMONYLINK_API UHarmonyLinkLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static bool IsWine(); + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static bool IsLinux(); + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static bool IsSteamDeck(); + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static FCPUInfo GetCPUInfo(); + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static FDevice GetDeviceInfo(); + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static FOSVerInfo GetOSInfo(); + + UFUNCTION(BlueprintCallable, Category="HarmonyLink") + static FBattery GetBatteryStatus(); +}; diff --git a/Source/HarmonyLink/Public/Structs/Battery.h b/Source/HarmonyLink/Public/Structs/Battery.h new file mode 100644 index 0000000..fd4c278 --- /dev/null +++ b/Source/HarmonyLink/Public/Structs/Battery.h @@ -0,0 +1,29 @@ +// Copyright (C) 2023 Jordon Brooks +#pragma once + +#include + +#include "CoreMinimal.h" +#include "Battery.generated.h" + +/** + * + */ +USTRUCT(BlueprintType) +struct FBattery +{ + GENERATED_BODY() + + FBattery() {} + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + bool HasBattery = false; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + bool IsACConnected = false; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + int32 BatteryPercent = 0; + + FBattery(HarmonyLinkLib::FBattery* battery); +}; diff --git a/Source/HarmonyLink/Public/Structs/CPUInfo.h b/Source/HarmonyLink/Public/Structs/CPUInfo.h new file mode 100644 index 0000000..97d0f95 --- /dev/null +++ b/Source/HarmonyLink/Public/Structs/CPUInfo.h @@ -0,0 +1,36 @@ +// Copyright (C) 2023 Jordon Brooks + +#pragma once + +#include + +#include "CoreMinimal.h" +#include "CPUInfo.generated.h" + +/** + * + */ +USTRUCT(BlueprintType) +struct FCPUInfo +{ + GENERATED_BODY() + + FCPUInfo() {} + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString VendorID; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString ModelName; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + int32 PhysicalCores = 0; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + int32 LogicalCores = 0; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + TSet Flags; + + FCPUInfo(HarmonyLinkLib::FCPUInfo* cpu_info); +}; diff --git a/Source/HarmonyLink/Public/Structs/FDevice.h b/Source/HarmonyLink/Public/Structs/FDevice.h new file mode 100644 index 0000000..7f54b29 --- /dev/null +++ b/Source/HarmonyLink/Public/Structs/FDevice.h @@ -0,0 +1,22 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Enums/Device.h" +#include "Enums/Platform.h" + +#include "FDevice.generated.h" + +/** + * + */ +USTRUCT(BlueprintType) +struct FDevice +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EPlatform Platform = EPlatform::WINDOWS; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + EDevice Device = EDevice::DESKTOP; +}; diff --git a/Source/HarmonyLink/Public/Structs/OSVerInfo.h b/Source/HarmonyLink/Public/Structs/OSVerInfo.h new file mode 100644 index 0000000..2cce110 --- /dev/null +++ b/Source/HarmonyLink/Public/Structs/OSVerInfo.h @@ -0,0 +1,36 @@ +// Copyright (C) 2023 Jordon Brooks +#pragma once + +#include "CoreMinimal.h" + +#include "OSVerInfo.generated.h" + +/** + * + */ +USTRUCT(BlueprintType) +struct FOSVerInfo +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Name; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + int32 Version = 0; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString ID; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString VersionID; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString VersionCodename; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString PrettyName; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString VariantID; +}; diff --git a/Source/HarmonyLinkUE/Private/DataRefreshActor.cpp b/Source/HarmonyLinkUE/Private/DataRefreshActor.cpp deleted file mode 100644 index fa7c26c..0000000 --- a/Source/HarmonyLinkUE/Private/DataRefreshActor.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// DataRefreshActor.cpp - -#include "DataRefreshActor.h" -#include "HarmonyLinkClient.h" - -// Sets default values -ADataRefreshActor::ADataRefreshActor() -{ - // Set default refresh interval to 1 second - RefreshInterval = 1.0f; - - // Create a SceneComponent for the actor - USceneComponent* SceneComponent = CreateDefaultSubobject(TEXT("DataRefreshSceneComponent")); - SetRootComponent(SceneComponent); -} - -// Called when the game starts or when spawned -void ADataRefreshActor::BeginPlay() -{ - Super::BeginPlay(); - - // Bind the delegate - ServerStatusCallback.BindUFunction(this, FName("OnServerStatusChecked")); - - // Start the timer for data refreshing - GetWorldTimerManager().SetTimer(RefreshTimerHandle, this, &ADataRefreshActor::RefreshData, RefreshInterval, true); -} - -void ADataRefreshActor::Destroyed() -{ - // Unbind the delegate - ServerStatusCallback.Unbind(); - - // Remember to call the parent class's Destroyed function at the end. - Super::Destroyed(); -} - - -// Called every frame -void ADataRefreshActor::Tick(float DeltaTime) -{ - Super::Tick(DeltaTime); - - // ... -} - -void ADataRefreshActor::OnServerStatusChecked(bool connected) -{ - UE_LOG(LogTemp, Display, TEXT("Refreshing")); - if (connected) - { - // Refresh the data and update the cached information - UHarmonyLinkClient::RefreshAllInfo(FDeviceInfoCallback()); - UHarmonyLinkClient::RefreshVersionInfo(FVersionInfoCallback()); - } -} - -// Function to refresh data -void ADataRefreshActor::RefreshData() -{ - // Only refresh data if the Harmony Link library is available - if (UHarmonyLinkClient::StaticClass()) - { - // Check server status asynchronously - UHarmonyLinkClient::CheckServerStatus(ServerStatusCallback); - } -} - - - diff --git a/Source/HarmonyLinkUE/Private/HarmonyLinkClient.cpp b/Source/HarmonyLinkUE/Private/HarmonyLinkClient.cpp deleted file mode 100644 index 83dbdbc..0000000 --- a/Source/HarmonyLinkUE/Private/HarmonyLinkClient.cpp +++ /dev/null @@ -1,289 +0,0 @@ -// .cpp file - -#include "HarmonyLinkClient.h" -#include "Interfaces/IHttpResponse.h" - -FAllInfo UHarmonyLinkClient::CachedAllInfo; -FHarmonyLinkVersionData UHarmonyLinkClient::CachedVersionData; -bool UHarmonyLinkClient::Connected; - -UHarmonyLinkClient::UHarmonyLinkClient(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) -{ - -} - -void UHarmonyLinkClient::CheckServerStatus(FServerStatusCallback Callback) -{ - TSharedPtr Request = FHttpModule::Get().CreateRequest(); - Request->SetURL(TEXT("http://localhost:9000/are_you_there")); - Request->SetVerb(TEXT("GET")); - - Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkClient::OnCheckServerStatusResponseReceived, Callback); - - Request->ProcessRequest(); -} - -void UHarmonyLinkClient::RefreshOSInfo(FOSInfoCallback Callback) -{ - TSharedPtr Request = FHttpModule::Get().CreateRequest(); - Request->SetURL(TEXT("http://localhost:9000/os_info")); - Request->SetVerb(TEXT("GET")); - - Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkClient::OnOSInfoResponseReceived, Callback); - - Request->ProcessRequest(); -} - -void UHarmonyLinkClient::RefreshBatteryInfo(FBatteryInfoCallback Callback) -{ - TSharedPtr Request = FHttpModule::Get().CreateRequest(); - Request->SetURL(TEXT("http://localhost:9000/battery_info")); - Request->SetVerb(TEXT("GET")); - - Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkClient::OnBatteryInfoResponseReceived, Callback); - - Request->ProcessRequest(); -} - -void UHarmonyLinkClient::RefreshAllInfo(FDeviceInfoCallback Callback) -{ - TSharedPtr Request = FHttpModule::Get().CreateRequest(); - Request->SetURL(TEXT("http://localhost:9000/all_info")); - Request->SetVerb(TEXT("GET")); - - Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkClient::OnDeviceInfoResponseReceived, Callback); - - Request->ProcessRequest(); -} - -void UHarmonyLinkClient::RefreshVersionInfo(FVersionInfoCallback Callback) -{ - TSharedPtr Request = FHttpModule::Get().CreateRequest(); - Request->SetURL(TEXT("http://localhost:9000/version_info")); - Request->SetVerb(TEXT("GET")); - - Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkClient::OnVersionInfoResponseReceived, Callback); - - Request->ProcessRequest(); -} - -void UHarmonyLinkClient::OnCheckServerStatusResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FServerStatusCallback Callback) -{ - if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) - { - bool bConnected = Response->GetContentAsString().ToBool(); - - Connected = bConnected; - - Callback.ExecuteIfBound(bConnected); - } - else - { - Connected = false; - - Callback.ExecuteIfBound(false); - // The server returned an error, or the request failed. - // Handle the error here. - } -} - -void UHarmonyLinkClient::OnOSInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FOSInfoCallback Callback) -{ - if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) - { - FString ResponseString = Response->GetContentAsString(); - UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); - - // Parse the JSON response - TSharedPtr JsonObject; - TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); - if (FJsonSerializer::Deserialize(Reader, JsonObject)) - { - // Parse the OSInfo - FOSInfo OSInfo; - if (JsonObject->HasField("os_info")) - { - TSharedPtr OSInfoObject = JsonObject->GetObjectField("os_info"); - OSInfo.OSType = OSInfoObject->GetStringField("os_type"); - OSInfo.OSVersion = OSInfoObject->GetStringField("os_version"); - OSInfo.OSEdition = OSInfoObject->GetStringField("os_edition"); - OSInfo.OSBits = OSInfoObject->GetStringField("os_bits"); - } - - CachedAllInfo.OSInfo = OSInfo; - Callback.ExecuteIfBound(OSInfo); - } - } - else - { - // The server returned an error, or the request failed. - // Handle the error here. - } -} - -void UHarmonyLinkClient::OnBatteryInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FBatteryInfoCallback Callback) -{ - if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) - { - FString ResponseString = Response->GetContentAsString(); - UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); - - // Parse the JSON response - TSharedPtr JsonObject; - TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); - if (FJsonSerializer::Deserialize(Reader, JsonObject)) - { - // Parse the BatteryInfo - FBatteryInfo BatteryInfo; - BatteryInfo.bHasBattery = JsonObject->GetBoolField("has_battery"); - BatteryInfo.BatteryPercent = JsonObject->GetIntegerField("battery_percent"); - FString ChargingStatusString = JsonObject->GetStringField("charging_status"); - if (ChargingStatusString == "charging") - { - BatteryInfo.ChargingStatus = EChargingStatus::Charging; - } - else if (ChargingStatusString == "battery") - { - BatteryInfo.ChargingStatus = EChargingStatus::Battery; - } - else - { - BatteryInfo.ChargingStatus = EChargingStatus::Unknown; - } - - CachedAllInfo.BatteryInfo = BatteryInfo; - - Callback.ExecuteIfBound(BatteryInfo); - } - } - else - { - // The server returned an error, or the request failed. - // Handle the error here. - } -} - -void UHarmonyLinkClient::OnDeviceInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FDeviceInfoCallback Callback) -{ - if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) - { - FString ResponseString = Response->GetContentAsString(); - UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); - - // Parse the JSON response - TSharedPtr JsonObject; - TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); - if (FJsonSerializer::Deserialize(Reader, JsonObject)) - { - // Parse the OSInfo - FOSInfo OSInfo; - if (JsonObject->HasField("os_info")) - { - TSharedPtr OSInfoObject = JsonObject->GetObjectField("os_info"); - OSInfo.OSType = OSInfoObject->GetStringField("os_type"); - OSInfo.OSVersion = OSInfoObject->GetStringField("os_version"); - OSInfo.OSEdition = OSInfoObject->GetStringField("os_edition"); - OSInfo.OSBits = OSInfoObject->GetStringField("os_bits"); - } - - // Parse the Battery_Info - FBatteryInfo BatteryInfo; - const TSharedPtr* BatteryInfoObject = nullptr; - if (JsonObject->HasField("dock_info") && JsonObject->TryGetObjectField("battery_info", BatteryInfoObject)) - { - BatteryInfo.bHasBattery = BatteryInfoObject->Get()->GetBoolField("has_battery"); - BatteryInfo.BatteryPercent = BatteryInfoObject->Get()->GetIntegerField("battery_percent"); - - FString battery = BatteryInfoObject->Get()->GetStringField("charging_status"); - if (battery.ToLower() == "charging") { BatteryInfo.ChargingStatus = EChargingStatus::Charging; } - else if (battery.ToLower() == "battery") { BatteryInfo.ChargingStatus = EChargingStatus::Battery; } - else { BatteryInfo.ChargingStatus = EChargingStatus::Unknown; } - - } - - // Parse the DockInfo - FDockInfo DockInfo; - const TSharedPtr* DockInfoObject = nullptr; - if (JsonObject->HasField("dock_info") && JsonObject->TryGetObjectField("dock_info", DockInfoObject)) - { - const TSharedPtr* DockModelObject = nullptr; - if (DockInfoObject->Get()->HasField("dock_model") && JsonObject->TryGetObjectField("dock_model", DockModelObject)) - { - TSharedPtr DockModelSubObject = DockModelObject->Get()->GetObjectField("dock_model"); - - FString DockModel = DockModelObject->Get()->GetStringField("model"); - if (DockModel == "SteamDeckDock") { DockInfo.DockModel.Model = EDockModel::SteamDeckDock; } - else if (DockModel == "JSAUX") { DockInfo.DockModel.Model = EDockModel::JSAUX; } - else if (DockModel == "Unknown") { DockInfo.DockModel.Model = EDockModel::Unknown; } - - DockInfo.DockModel.Name = DockModelObject->Get()->GetStringField("name"); - } - else - { - // handle case where dock_model is null - DockInfo.DockModel.Model = EDockModel::Unknown; - DockInfo.DockModel.Name = "Unknown"; - } - - DockInfo.bIsDocked = DockInfoObject->Get()->GetBoolField("is_docked"); - DockInfo.bFallbackDetection = DockInfoObject->Get()->GetBoolField("fallback_detection"); - } - - // Create the DeviceInfo struct - FAllInfo AllInfo; - AllInfo.OSInfo = OSInfo; - AllInfo.DockInfo = DockInfo; - AllInfo.BatteryInfo = BatteryInfo; - - CachedAllInfo = AllInfo; - - // Call the callback with the DeviceInfo - Callback.ExecuteIfBound(AllInfo); - - // Handle the DeviceInfo struct as needed - // ... - } - } - else - { - // The server returned an error, or the request failed. - // Handle the error here. - } -} - - -void UHarmonyLinkClient::OnVersionInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FVersionInfoCallback Callback) -{ - if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) - { - FString ResponseString = Response->GetContentAsString(); - UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); - - // Parse the JSON response - TSharedPtr JsonObject; - TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); - if (FJsonSerializer::Deserialize(Reader, JsonObject)) - { - FHarmonyLinkVersionData VersionInfo; - VersionInfo.BuildTimestamp = JsonObject->GetStringField("build_timestamp"); - VersionInfo.GitBranch = JsonObject->GetStringField("git_branch"); - VersionInfo.GitDescribe = JsonObject->GetStringField("git_describe"); - VersionInfo.GitCommitTimestamp = JsonObject->GetStringField("git_commit_timestamp"); - VersionInfo.bDebug = JsonObject->GetBoolField("debug"); - VersionInfo.Version = JsonObject->GetStringField("version"); - VersionInfo.VersionMajor = JsonObject->GetIntegerField("version_major"); - VersionInfo.VersionMinor = JsonObject->GetIntegerField("version_minor"); - VersionInfo.VersionPatch = JsonObject->GetIntegerField("version_patch"); - VersionInfo.VersionPre = JsonObject->GetStringField("version_pre"); - - CachedVersionData = VersionInfo; - Callback.ExecuteIfBound(VersionInfo); - } - } - else - { - // The server returned an error, or the request failed. - // Handle the error here. - } -} diff --git a/Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp b/Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp deleted file mode 100644 index 75162f5..0000000 --- a/Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "HarmonyLinkUE.h" - -#define LOCTEXT_NAMESPACE "FHarmonyLinkUEModule" - -void FHarmonyLinkUEModule::StartupModule() -{ - // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module - -} - -void FHarmonyLinkUEModule::ShutdownModule() -{ - // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, - // we call this function before unloading the module. - -} - -#undef LOCTEXT_NAMESPACE - -IMPLEMENT_MODULE(FHarmonyLinkUEModule, HarmonyLinkUE) \ No newline at end of file diff --git a/Source/HarmonyLinkUE/Public/DataRefreshActor.h b/Source/HarmonyLinkUE/Public/DataRefreshActor.h deleted file mode 100644 index dc51438..0000000 --- a/Source/HarmonyLinkUE/Public/DataRefreshActor.h +++ /dev/null @@ -1,43 +0,0 @@ -// DataRefreshActor.h - -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/Actor.h" -#include "HarmonyLinkClient.h" -#include "DataRefreshActor.generated.h" - -UCLASS() -class HARMONYLINKUE_API ADataRefreshActor : public AActor -{ - GENERATED_BODY() - -public: - // Sets default values for this actor's properties - ADataRefreshActor(); - -protected: - // Called when the game starts or when spawned - virtual void BeginPlay() override; - virtual void Destroyed() override; - - FServerStatusCallback ServerStatusCallback; - - // Function to refresh data - UFUNCTION() - void RefreshData(); - UFUNCTION() - void OnServerStatusChecked(bool connected); - -public: - // Called every frame - virtual void Tick(float DeltaTime) override; - -private: - // Timer interval for data refreshing (in seconds) - UPROPERTY(EditAnywhere, Category = "Data Refresh") - float RefreshInterval; - - // Timer handle for data refreshing - FTimerHandle RefreshTimerHandle; -}; diff --git a/Source/HarmonyLinkUE/Public/HarmonyLinkClient.h b/Source/HarmonyLinkUE/Public/HarmonyLinkClient.h deleted file mode 100644 index 7115edc..0000000 --- a/Source/HarmonyLinkUE/Public/HarmonyLinkClient.h +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright Jordon Brooks © 2023 - -#pragma once - -#include "Kismet/BlueprintFunctionLibrary.h" -#include "Runtime/Online/HTTP/Public/HttpModule.h" -#include "Runtime/Online/HTTP/Public/Interfaces/IHttpRequest.h" -#include "Engine/World.h" -#include "Engine/WorldComposition.h" - -#include "HarmonyLinkClient.generated.h" - -UENUM(BlueprintType) -enum class EDockModel : uint8 -{ - SteamDeckDock, - JSAUX, - Unknown, -}; - -USTRUCT(BlueprintType) -struct FSDock -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - EDockModel Model = EDockModel::Unknown; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString Name = ""; - - void Print() const - { - UE_LOG(LogTemp, Display, TEXT("Dock Model: %s"), *StaticEnum()->GetNameStringByValue(static_cast(Model))); - UE_LOG(LogTemp, Display, TEXT("Name: %s"), *Name); - } -}; - -USTRUCT(BlueprintType) -struct FDockInfo -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FSDock DockModel; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - bool bIsDocked = false; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - bool bFallbackDetection = false; - - void Print() const - { - DockModel.Print(); - UE_LOG(LogTemp, Display, TEXT("IsDocked: %s"), bIsDocked ? TEXT("true") : TEXT("false")); - UE_LOG(LogTemp, Display, TEXT("FallbackDetection: %s"), bFallbackDetection ? TEXT("true") : TEXT("false")); - } -}; - - -USTRUCT(BlueprintType) -struct FOSInfo -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString OSType = "Unknown"; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString OSVersion = ""; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString OSEdition = ""; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString OSBits = "X64"; - - void Print() const - { - UE_LOG(LogTemp, Display, TEXT("OS Type: %s"), *OSType); - UE_LOG(LogTemp, Display, TEXT("OS Version: %s"), *OSVersion); - UE_LOG(LogTemp, Display, TEXT("OS Edition: %s"), *OSEdition); - UE_LOG(LogTemp, Display, TEXT("OS Bits: %s"), *OSBits); - } -}; - -UENUM(BlueprintType) -enum class EChargingStatus : uint8 -{ - Charging, - Battery, - Unknown -}; - -USTRUCT(BlueprintType) -struct FBatteryInfo -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - bool bHasBattery = false; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - int32 BatteryPercent = 0; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - EChargingStatus ChargingStatus = EChargingStatus::Unknown; - - void Print() const - { - UE_LOG(LogTemp, Display, TEXT("Has Battery: %s"), bHasBattery ? TEXT("true") : TEXT("false")); - UE_LOG(LogTemp, Display, TEXT("Battery Percent: %d"), BatteryPercent); - UE_LOG(LogTemp, Display, TEXT("Charging Status: %s"), *StaticEnum()->GetNameStringByValue(static_cast(ChargingStatus))); - } -}; - -USTRUCT(BlueprintType) -struct FHarmonyLinkVersionData -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString BuildTimestamp; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString GitBranch; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString GitDescribe; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString GitCommitTimestamp; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - bool bDebug; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString Version; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - int32 VersionMajor; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - int32 VersionMinor; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - int32 VersionPatch; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FString VersionPre; - - void Print() const - { - UE_LOG(LogTemp, Display, TEXT("Build Timestamp: %s"), *BuildTimestamp); - UE_LOG(LogTemp, Display, TEXT("Git Branch: %s"), *GitBranch); - UE_LOG(LogTemp, Display, TEXT("Git Describe: %s"), *GitDescribe); - UE_LOG(LogTemp, Display, TEXT("Git Commit Timestamp: %s"), *GitCommitTimestamp); - UE_LOG(LogTemp, Display, TEXT("Debug: %s"), bDebug ? TEXT("true") : TEXT("false")); - UE_LOG(LogTemp, Display, TEXT("Version: %s"), *Version); - UE_LOG(LogTemp, Display, TEXT("Version Major: %d"), VersionMajor); - UE_LOG(LogTemp, Display, TEXT("Version Minor: %d"), VersionMinor); - UE_LOG(LogTemp, Display, TEXT("Version Patch: %d"), VersionPatch); - UE_LOG(LogTemp, Display, TEXT("Version Pre: %s"), *VersionPre); - } -}; - -USTRUCT(BlueprintType) -struct FAllInfo -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FOSInfo OSInfo; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FDockInfo DockInfo; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="HarmonyLink") - FBatteryInfo BatteryInfo; - - void Print() const - { - UE_LOG(LogTemp, Display, TEXT("All Info:")); - OSInfo.Print(); - DockInfo.Print(); - BatteryInfo.Print(); - } -}; - -DECLARE_DYNAMIC_DELEGATE_OneParam(FDeviceInfoCallback, const FAllInfo&, DeviceInfo); -DECLARE_DYNAMIC_DELEGATE_OneParam(FOSInfoCallback, const FOSInfo&, OSInfo); -DECLARE_DYNAMIC_DELEGATE_OneParam(FBatteryInfoCallback, const FBatteryInfo&, BatteryInfo); -DECLARE_DYNAMIC_DELEGATE_OneParam(FVersionInfoCallback, const FHarmonyLinkVersionData&, VersionInfo); -DECLARE_DYNAMIC_DELEGATE_OneParam(FServerStatusCallback, const bool, connected); - - -/* -* Function library class. -* Each function in it is expected to be static and represents blueprint node that can be called in any blueprint. -* -* When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable. -* BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins. -* BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins. -* DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu. -* Its lets you name the node using characters not allowed in C++ function names. -* CompactNodeTitle - the word(s) that appear on the node. -* Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu. -* Good example is "Print String" node which you can find also by using keyword "log". -* Category - the category your node will be under in the Blueprint drop-down menu. -* -* For more info on custom blueprint nodes visit documentation: -* https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation -*/ -UCLASS() -class HARMONYLINKUE_API UHarmonyLinkClient : public UBlueprintFunctionLibrary -{ - GENERATED_UCLASS_BODY() - - static bool Connected; - - // Cached DeviceInfo variable - static FAllInfo CachedAllInfo; - - // Cached DeviceInfo variable - static FHarmonyLinkVersionData CachedVersionData; - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static bool GetIsConnected() - { return Connected; } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static void PrintAllInfo() - { CachedAllInfo.Print(); } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static FAllInfo GetAllInfo() - { return CachedAllInfo; } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static FBatteryInfo GetBatteryInfo() - { return CachedAllInfo.BatteryInfo; } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static FDockInfo GetDockInfo() - { return CachedAllInfo.DockInfo; } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static FOSInfo GetOSInfo() - { return CachedAllInfo.OSInfo; } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static FHarmonyLinkVersionData GetVersionInfo() - { return CachedVersionData; } - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static void CheckServerStatus(FServerStatusCallback Callback); - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static void RefreshOSInfo(FOSInfoCallback Callback); - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static void RefreshBatteryInfo(FBatteryInfoCallback Callback); - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static void RefreshAllInfo(FDeviceInfoCallback Callback); - - UFUNCTION(BlueprintCallable, Category = "Harmony Link") - static void RefreshVersionInfo(FVersionInfoCallback Callback); - -private: - static void OnCheckServerStatusResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FServerStatusCallback Callback); - static void OnOSInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FOSInfoCallback Callback); - static void OnBatteryInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FBatteryInfoCallback Callback); - static void OnDeviceInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FDeviceInfoCallback Callback); - static void OnVersionInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FVersionInfoCallback Callback); -}; diff --git a/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so b/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so new file mode 100644 index 0000000..0daf6e2 Binary files /dev/null and b/Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so differ diff --git a/Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll b/Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll new file mode 100644 index 0000000..c020eef Binary files /dev/null and b/Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll differ diff --git a/Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib b/Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib new file mode 100644 index 0000000..ce48844 Binary files /dev/null and b/Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib differ diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Core.h b/Source/ThirdParty/HarmonyLinkLib/include/Core.h new file mode 100644 index 0000000..90d63b4 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Core.h @@ -0,0 +1,14 @@ +// Copyright (C) 2023 Jordon Brooks + +#pragma once + +// Use a preprocessor definition to switch between export and import declarations +#ifdef _WIN32 + #ifdef HARMONYLINKLIB_EXPORTS + #define HARMONYLINKLIB_API __declspec(dllexport) + #else + #define HARMONYLINKLIB_API __declspec(dllimport) + #endif +#else + #define HARMONYLINKLIB_API +#endif diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Enums/EDevice.h b/Source/ThirdParty/HarmonyLinkLib/include/Enums/EDevice.h new file mode 100644 index 0000000..75d3cc5 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Enums/EDevice.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +// Enum class for representing different types of devices +namespace HarmonyLinkLib +{ + enum class EDevice : uint8_t + { + DESKTOP, + LAPTOP, + HANDHELD, + + STEAM_DECK, + // ROG_ALLY + // AYONEO_SLIDE + // etc... + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Enums/EPlatform.h b/Source/ThirdParty/HarmonyLinkLib/include/Enums/EPlatform.h new file mode 100644 index 0000000..c050ca3 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Enums/EPlatform.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +// Enum class for representing different operating platforms +namespace HarmonyLinkLib +{ + enum class EPlatform : uint8_t + { + WINDOWS, + LINUX, + MAC, + UNIX, + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/FString.h b/Source/ThirdParty/HarmonyLinkLib/include/FString.h new file mode 100644 index 0000000..3f23dc1 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/FString.h @@ -0,0 +1,165 @@ +// Copyright (C) 2024 Jordon Brooks + +#pragma once + +#include +#include +#include + +#include "Core.h" // Replace with actual API export macro + +/** + * @file FString.h + * @brief FString Class - Custom String Management for DLL Export + * + * The FString class is a custom string management class designed to safely encapsulate + * string handling and memory management, especially for use in DLLs (Dynamic Link Libraries). + * It resolves the common issue of exporting classes containing standard library types, + * such as std::string, across DLL boundaries, which can lead to compiler warnings or errors. + * + * Features: + * - Implements basic string operations such as construction, destruction, copy, and move semantics. + * - Utilizes smart pointers (std::unique_ptr) for automatic memory management, reducing the risk of memory leaks. + * - Provides a simple interface for interacting with character strings, similar to std::string. + * - Includes both deep copy semantics for safety and move semantics for performance in object transfers. + * + * Usage: + * FString can be used as a safer alternative to std::string for classes that are exported from a DLL. + * It handles memory allocation/deallocation automatically and provides a basic set of string operations. + * + * Example: + * FString myString("Hello, world!"); + * std::cout << myString.c_str() << std::endl; // Output: Hello, world! + * + * Note: + * - The class is currently designed with basic functionality. Additional features such as + * string concatenation, substring, and comparison operations can be added as needed. + * - Ensure that the HarmonyLinkLibApi.h (or equivalent) file correctly defines the export macro + * for DLL usage. + * + */ + namespace HarmonyLinkLib + { + class HARMONYLINKLIB_API FString { + public: + FString() : data_(new char[1]) { + data_[0] = '\0'; + } + + FString(const char* str) { + const size_t len = strlen(str); + data_ = new char[len + 1]; + memcpy(data_, str, len + 1); + } + + // Copy constructor + FString(const FString& other) { + const size_t len = strlen(other.data_); + data_ = new char[len + 1]; + memcpy(data_, other.data_, len + 1); + } + + ~FString() { + delete[] data_; + } + + // Copy assignment operator + FString& operator=(const FString& other) { + if (this != &other) { + delete[] data_; + const size_t len = strlen(other.data_); + data_ = new char[len + 1]; + memcpy(data_, other.data_, len + 1); + } + return *this; + } + + // Concatenation operator for FString objects + FString operator+(const FString& other) const { + size_t thisLen = strlen(this->data_); + size_t otherLen = strlen(other.data_); + char* concatenated = new char[thisLen + otherLen + 1]; + + memcpy(concatenated, this->data_, thisLen); + memcpy(concatenated + thisLen, other.data_, otherLen + 1); + + FString result(concatenated); + delete[] concatenated; + return result; + } + + // Concatenation operator for const char* + FString operator+(const char* other) const { + return *this + FString(other); + } + + // Friend function to allow concatenation with const char* on the left-hand side + friend FString operator+(const char* lhs, const FString& rhs) { + return FString(lhs) + rhs; + } + + // Move constructor + FString(FString&& other) noexcept : data_(other.data_) { + other.data_ = nullptr; + } + + FString(const std::string& str) { + const size_t len = str.length(); + data_ = new char[len + 1]; + memcpy(data_, str.c_str(), len + 1); + } + + // Move assignment operator + FString& operator=(FString&& other) noexcept { + if (this != &other) { + delete[] data_; + data_ = other.data_; + other.data_ = nullptr; + } + return *this; + } + + bool operator==(const FString& other) const { + return strcmp(data_, other.data_) == 0; + } + + // Method to get a lowercase version of the string + static FString to_lower(FString& from) + { + for (size_t i = 0; i < strlen(from.data_); ++i) { + from.data_[i] = static_cast(std::tolower(static_cast(from.data_[i]))); + } + return from; + } + + // Overloaded static method to handle const char* + static FString to_lower(const char* from) { + FString temp_string(from); // Create an FString from const char* + return to_lower(temp_string); // Reuse the existing to_lower method + } + + const char* c_str() const { + return data_; + } + + private: + char* data_ = nullptr; + }; + } + +namespace std { + template<> + struct hash { + size_t operator()(const HarmonyLinkLib::FString& s) const { + size_t hashValue = 5381; // Starting value recommended by the djb2 algorithm + const char* str = s.c_str(); + + for (size_t i = 0; str[i] != '\0'; ++i) { + hashValue = ((hashValue << 5) + hashValue) + static_cast(str[i]); + // Equivalent to hashValue * 33 + str[i] + } + + return hashValue; + } + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/HarmonyLinkLib.h b/Source/ThirdParty/HarmonyLinkLib/include/HarmonyLinkLib.h new file mode 100644 index 0000000..94f07ed --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/HarmonyLinkLib.h @@ -0,0 +1,25 @@ +// Copyright (C) 2023 Jordon Brooks + +#pragma once + +#include "Core.h" +#include "Structs/FBattery.h" +#include "Structs/FCPUInfo.h" +#include "Structs/FDevice.h" +#include "Structs/FOSVerInfo.h" + + +class IPlatformUtilities; + +namespace HarmonyLinkLib +{ + extern "C" HARMONYLINKLIB_API bool get_is_wine(); + + extern "C" HARMONYLINKLIB_API FCPUInfo* get_cpu_info(); + + extern "C" HARMONYLINKLIB_API FDevice* get_device_info(); + + extern "C" HARMONYLINKLIB_API FOSVerInfo* get_os_version(); + + extern "C" HARMONYLINKLIB_API FBattery* get_battery_status(); +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/HarmonyLinkStruct.h b/Source/ThirdParty/HarmonyLinkLib/include/HarmonyLinkStruct.h new file mode 100644 index 0000000..aa4497d --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/HarmonyLinkStruct.h @@ -0,0 +1,13 @@ +#pragma once + +struct HarmonyLinkStruct +{ + // Virtual destructor is important for proper cleanup of derived types + virtual ~HarmonyLinkStruct() = default; + + // Method to deallocate the object + void free() const + { + delete this; + } +}; diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Structs/FBattery.h b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FBattery.h new file mode 100644 index 0000000..6c41595 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FBattery.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +#include "HarmonyLinkStruct.h" + +namespace HarmonyLinkLib +{ + struct FBattery : HarmonyLinkStruct + { + bool has_battery; + bool is_connected_to_ac; + uint8_t battery_percent; + + void to_string() const { + std::wcout << "Battery present: " << (has_battery ? "'Yes'" : "'No'") << '\n'; + std::wcout << "Connected to AC: " << (is_connected_to_ac ? "'Yes'" : "'No'") << '\n'; + std::wcout << "Battery percent: '" << static_cast(battery_percent) << "%'" << '\n'; + } + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Structs/FCPUInfo.h b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FCPUInfo.h new file mode 100644 index 0000000..8694e6a --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FCPUInfo.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include "FString.h" + +#include "HarmonyLinkStruct.h" + +namespace HarmonyLinkLib +{ + struct FCPUInfo : HarmonyLinkStruct + { + FString VendorID; + FString Model_Name; + uint32_t Physical_Cores = 0; + uint32_t Logical_Cores = 0; + std::unordered_set Flags; + + void print() const + { + wprintf(L"VendorID: '%hs'\n", VendorID.c_str()); + wprintf(L"Model_Name: '%hs'\n", Model_Name.c_str()); + wprintf(L"Physical_Cores: '%d'\n", Physical_Cores); + wprintf(L"Logical_Cores: '%d'\n", Logical_Cores); + + // Initialize a string to hold all flags + std::string allFlags; + for (const auto& flag : Flags) { + allFlags += std::string(flag.c_str()) + " "; // Append each flag followed by a space + } + + // Remove the trailing space + if (!allFlags.empty()) { + allFlags.pop_back(); + } + + wprintf(L"Flags: '%hs'\n", allFlags.c_str()); + } + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Structs/FDevice.h b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FDevice.h new file mode 100644 index 0000000..204a5da --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FDevice.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "Enums/EDevice.h" +#include "Enums/EPlatform.h" + +namespace HarmonyLinkLib +{ + // Struct to represent a specific device with both platform and device type + struct FDevice : HarmonyLinkStruct + { + EPlatform platform; + EDevice device; + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Structs/FOSVerInfo.h b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FOSVerInfo.h new file mode 100644 index 0000000..6b62db3 --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Structs/FOSVerInfo.h @@ -0,0 +1,50 @@ +#pragma once + +#include "FString.h" +#include "HarmonyLinkStruct.h" + +namespace HarmonyLinkLib +{ + struct FOSVerInfo : HarmonyLinkStruct { + // 'name' represents the operating system's name, e.g., "Ubuntu" in Linux or "Windows" in Windows systems. + FString name; + + // 'version' is a numerical representation of the OS version. In Linux, it might be the kernel version, + // whereas in Windows, it could be the major version number like 10 for Windows 10. + uint32_t version = 0; + + // 'id' is a unique identifier for the OS. In Linux, it might be a lower-case string like "ubuntu". + // In Windows, this could map to the edition ID, such as "Professional". + FString id; + + // 'version_id' is a string representing the specific version of the OS. + // For example, "20.04" in Ubuntu or "1909" in Windows 10. + FString version_id; + + // 'version_codename' is a codename for the OS version, if available. + // This is common in Linux distributions (e.g., "focal" for Ubuntu 20.04) but not typically used in Windows. + FString version_codename; + + // 'pretty_name' is a more readable version of the name, potentially including the version and codename. + // For example, "Ubuntu 20.04 LTS (Focal Fossa)" or "Windows 10 Pro". + FString pretty_name; + + // 'variant_id' is an identifier for the specific variant of the OS, if available. + // For example, in Linux distributions, this might be "desktop" for the desktop edition, + // "server" for the server edition, or "core" for a minimal installation. It helps distinguish + // between different flavors or editions of the same version. + // On the Steam Deck, this is set to "steamdeck". + FString variant_id; + + void print() const + { + wprintf(L"Name: '%hs'\n", name.c_str()); + wprintf(L"Version: '%d'\n", version); + wprintf(L"ID: '%hs'\n", id.c_str()); + wprintf(L"Version ID: '%hs'\n", version_id.c_str()); + wprintf(L"Version Codename: '%hs'\n", version_codename.c_str()); + wprintf(L"Pretty Name: '%hs'\n", pretty_name.c_str()); + wprintf(L"Variant ID: '%hs'\n", variant_id.c_str()); + } +}; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Version.h b/Source/ThirdParty/HarmonyLinkLib/include/Version.h new file mode 100644 index 0000000..61d6e3f --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Version.h @@ -0,0 +1,45 @@ +// Copyright (C) 2024 Jordon Brooks +#pragma once + +#include "Core.h" +#include + +#include "FString.h" + +namespace HarmonyLinkLib +{ + class HARMONYLINKLIB_API version + { + public: + version() = default; + + static FString ToString() + { + return HARMONYLINK_VERSION; + } + + static FString get_build_timestamp() + { + return {__TIMESTAMP__}; + } + + static FString get_git_branch() + { + return {GIT_BRANCH_NAME}; + } + + static FString get_git_commit_timestamp() + { + return {GIT_COMMIT_TIMESTAMP}; + } + + static bool is_debug() + { +#ifdef DEBUG_MODE + return true; +#else + return false; +#endif + } + }; +} diff --git a/Source/ThirdParty/HarmonyLinkLib/include/Version.h.in b/Source/ThirdParty/HarmonyLinkLib/include/Version.h.in new file mode 100644 index 0000000..4081f8d --- /dev/null +++ b/Source/ThirdParty/HarmonyLinkLib/include/Version.h.in @@ -0,0 +1,11 @@ +// Version.h.in +#pragma once + +#define HARMONYLINK_VERSION_MAJOR @HarmonyLinkLib_VERSION_MAJOR@ +#define HARMONYLINK_VERSION_MINOR @HarmonyLinkLib_VERSION_MINOR@ +#define HARMONYLINK_VERSION_PATCH @HarmonyLinkLib_VERSION_PATCH@ +#define HARMONYLINK_VERSION_TWEAK @HarmonyLinkLib_VERSION_TWEAK@ +#define HARMONYLINK_VERSION "@HarmonyLinkLib_VERSION@" + +#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@" +#define GIT_COMMIT_TIMESTAMP "@GIT_COMMIT_TIMESTAMP@"