diff --git a/.idea/indexLayout.xml b/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/projectSettingsUpdater.xml b/.idea/projectSettingsUpdater.xml
new file mode 100644
index 0000000..64af657
--- /dev/null
+++ b/.idea/projectSettingsUpdater.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..a973b1e
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1776109424996
+
+
+ 1776109424996
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj b/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj
index 649c15b..1c1dae4 100755
--- a/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj
+++ b/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj
@@ -2,14 +2,21 @@
Exe
- net8.0
+ net9.0
enable
enable
+
+
+
+ Always
+
+
+
diff --git a/OmegaLeo.HelperLib.ConsoleApp/Program.cs b/OmegaLeo.HelperLib.ConsoleApp/Program.cs
index e56ba62..8b62339 100755
--- a/OmegaLeo.HelperLib.ConsoleApp/Program.cs
+++ b/OmegaLeo.HelperLib.ConsoleApp/Program.cs
@@ -2,101 +2,28 @@
// /media/omegaleo/Development/Library Dev/HelperLib
-using System.Reflection;
-using OmegaLeo.HelperLib.Extensions;
-using OmegaLeo.HelperLib.Helpers;
-using LibGit2Sharp;
-using OmegaLeo.HelperLib.Changelog.Tools;
-using OmegaLeo.HelperLib.Git;
-using OmegaLeo.HelperLib.Git.Models;
+using System;
+using System.Collections.Generic;
+using OmegaLeo.HelperLib.Steamworks;
-Console.WriteLine("Insert repo path to check changes:");
-var repo = Console.ReadLine();
-
-if (repo.IsNullOrEmpty())
+public class Program
{
- repo = "/media/omegaleo/Development/Library Dev/HelperLib";
-}
-
-var git = new GitClient(repo);
-
-var result = BenchmarkUtility.Record(() =>
-{
- var changes = git.GetChanges();
-
- if (changes.FolderName.IsNotNullOrEmpty())
+ public static void Main()
{
- RecursiveOutput(new List() { changes });
-
- var option = 99;
-
- while (option != 0)
+ SteamManager.ConfigureAppId(480); // 480 is the AppId for Spacewar, a test app provided by Valve
+
+ var steam = SteamManager.Instance;
+ if (steam.IsSteamworksInitialized)
{
- ShowOptions();
- if (option != 99)
- {
- switch (option)
- {
- case 1:
- Console.WriteLine("Write the commit message");
- var msg = Console.ReadLine();
-
- while (msg.IsNullOrEmpty())
- {
- Console.WriteLine("Empty message detected, please write a commit message...");
- msg = Console.ReadLine();
- }
-
- var signature = new Signature("Nuno 'Omega Leo' Diogo", "nunodiogo@omegaleo.pt",
- DateTimeOffset.Now);
- git.Commit(msg, signature);
-
- break;
- case 2:
- git.Push();
- break;
- default:
- Console.WriteLine("Invalid Option!");
- break;
- }
- }
-
- int.TryParse(Console.ReadLine(), out option);
- }
- }
- else
- {
- Console.WriteLine("No changes found in specified repository");
- }
-});
-
-Console.WriteLine($"Time for checking for changes: {result} ms");
-
-Console.ReadLine();
-
-
-void RecursiveOutput(List folders, int depth = 0)
-{
- foreach (var folder in folders)
- {
- Console.WriteLine($"{new string('\t', depth)}>{folder.FolderName}");
- if (folder.SubFolders.Any())
- {
- RecursiveOutput(folder.SubFolders, depth + 1);
+ Console.WriteLine($"Welcome {steam.GetSteamName()}");
}
- foreach (var change in folder.ChangesInFolder)
- {
- Console.WriteLine($"{new string('\t', depth + 1)}>{Path.GetFileName(change.Path)} ({change.Status})");
- }
- }
-}
+ // Call this in your game loop (Unity Update, Godot _Process, etc.)
+ steam.Update();
-void ShowOptions()
-{
- Console.Clear();
- Console.WriteLine(new string('=', 20));
- Console.WriteLine("What do you want to do in this repository?");
- Console.WriteLine("1. Commit all changes");
- Console.WriteLine("2. Push");
+ //var achievements = new AchievementManager();
+ //achievements.UnlockAchievement("ACH_FIRST_WIN");
+
+ steam.Shutdown();
+ }
}
\ No newline at end of file
diff --git a/OmegaLeo.HelperLib.ConsoleApp/steam_appid.txt b/OmegaLeo.HelperLib.ConsoleApp/steam_appid.txt
new file mode 100644
index 0000000..7ad8022
--- /dev/null
+++ b/OmegaLeo.HelperLib.ConsoleApp/steam_appid.txt
@@ -0,0 +1 @@
+480
\ No newline at end of file
diff --git a/OmegaLeo.HelperLib.Steamworks/.gitignore b/OmegaLeo.HelperLib.Steamworks/.gitignore
new file mode 100644
index 0000000..a505c1e
--- /dev/null
+++ b/OmegaLeo.HelperLib.Steamworks/.gitignore
@@ -0,0 +1 @@
+runtimes/
\ No newline at end of file
diff --git a/OmegaLeo.HelperLib.Steamworks/AchievementManager.cs b/OmegaLeo.HelperLib.Steamworks/AchievementManager.cs
new file mode 100644
index 0000000..3d83ee8
--- /dev/null
+++ b/OmegaLeo.HelperLib.Steamworks/AchievementManager.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace OmegaLeo.HelperLib.Steamworks
+{
+ public class AchievementManager
+ {
+ public void UnlockAchievement(string achievementId)
+ {
+ if (SteamManager.Instance.IsSteamworksInitialized)
+ {
+ SteamNativeApi.SetAchievement(achievementId);
+ SteamNativeApi.StoreStats(); // Don't forget to store the stats
+ Console.WriteLine($"Attempting to unlock achievement: {achievementId}");
+ }
+ }
+
+ public bool IsAchievementUnlocked(string achievementId, out bool unlocked)
+ {
+ unlocked = false;
+ if (SteamManager.Instance.IsSteamworksInitialized)
+ {
+ return SteamNativeApi.GetAchievement(achievementId, out unlocked);
+ }
+ return false;
+ }
+ }
+}
diff --git a/OmegaLeo.HelperLib.Steamworks/OmegaLeo.HelperLib.Steamworks.csproj b/OmegaLeo.HelperLib.Steamworks/OmegaLeo.HelperLib.Steamworks.csproj
new file mode 100644
index 0000000..06aa70d
--- /dev/null
+++ b/OmegaLeo.HelperLib.Steamworks/OmegaLeo.HelperLib.Steamworks.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netstandard2.1
+ 9
+
+
+
+
+
+
+ true
+ runtimes\%(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+
+
diff --git a/OmegaLeo.HelperLib.Steamworks/README.md b/OmegaLeo.HelperLib.Steamworks/README.md
new file mode 100644
index 0000000..af56817
--- /dev/null
+++ b/OmegaLeo.HelperLib.Steamworks/README.md
@@ -0,0 +1,49 @@
+# OmegaLeo's Helper Library - Steamworks
+Lightweight Steamworks helper library for C# game projects.
+
+This package provides a simple Steam API wrapper for common tasks like initialization, callback processing, player name lookup, and achievements.
+
+## Features
+- Simple Steam initialization via `SteamManager.Instance`
+- Per-frame callback runner with `SteamManager.Update()`
+- Safe shutdown with `SteamManager.Shutdown()`
+- Player persona name access with `SteamManager.GetSteamName()`
+- Achievement helpers via `AchievementManager`
+- Includes native Steam runtime files in NuGet package `runtimes/`
+
+## Installation
+```bash
+dotnet add package OmegaLeo.HelperLib.Steamworks
+```
+
+## Quick Start
+```cs
+using OmegaLeo.HelperLib.Steamworks;
+
+// Optional but recommended for local/editor runs.
+SteamManager.ConfigureAppId(480); // Replace with your real AppId.
+
+var steam = SteamManager.Instance;
+if (steam.IsSteamworksInitialized)
+{
+ Console.WriteLine($"Welcome {steam.GetSteamName()}");
+}
+
+// Call this in your game loop (Unity Update, Godot _Process, etc.)
+steam.Update();
+
+var achievements = new AchievementManager();
+achievements.UnlockAchievement("ACH_FIRST_WIN");
+
+steam.Shutdown();
+```
+
+## Notes
+- Steam must be running and your app must be launched in a valid Steam context.
+- Configure your AppId before first access to `SteamManager.Instance`.
+- `SteamManager.Update()` should be called continuously during runtime.
+- If Steam is unavailable, `GetSteamName()` falls back to `"Player"`.
+
+## License
+Open source under the AGPL v3 License. See the repository `LICENSE` for details.
+
diff --git a/OmegaLeo.HelperLib.Steamworks/SteamManager.cs b/OmegaLeo.HelperLib.Steamworks/SteamManager.cs
new file mode 100644
index 0000000..22ba6fb
--- /dev/null
+++ b/OmegaLeo.HelperLib.Steamworks/SteamManager.cs
@@ -0,0 +1,79 @@
+using System;
+
+namespace OmegaLeo.HelperLib.Steamworks
+{
+ public class SteamManager
+ {
+ private static SteamManager _instance;
+ private static uint? _configuredAppId;
+ public static SteamManager Instance => _instance ??= new SteamManager();
+
+ public static bool ConfigureAppId(uint appId)
+ {
+ if (appId == 0)
+ {
+ return false;
+ }
+
+ // AppId must be configured before the singleton is created.
+ if (_instance != null)
+ {
+ return false;
+ }
+
+ _configuredAppId = appId;
+ SteamNativeApi.ConfigureAppId(appId);
+ return true;
+ }
+
+ public bool IsSteamworksInitialized { get; private set; }
+
+ private SteamManager()
+ {
+ try
+ {
+ // Attempt to initialize Steamworks
+ if (SteamNativeApi.Initialize(_configuredAppId))
+ {
+ IsSteamworksInitialized = true;
+ Console.WriteLine("Steamworks Initialized Successfully!");
+ }
+ else
+ {
+ Console.WriteLine("Steamworks Initialization Failed. Is Steam running?");
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"An exception occurred during Steamworks initialization: {e.Message}");
+ }
+ }
+
+ // This must be called from your game's main loop (e.g., Update in Unity/Godot)
+ public void Update()
+ {
+ if (IsSteamworksInitialized)
+ {
+ SteamNativeApi.RunCallbacks();
+ }
+ }
+
+ public void Shutdown()
+ {
+ if (IsSteamworksInitialized)
+ {
+ SteamNativeApi.Shutdown();
+ IsSteamworksInitialized = false;
+ }
+ }
+
+ public string GetSteamName()
+ {
+ if (IsSteamworksInitialized)
+ {
+ return SteamNativeApi.GetPersonaName();
+ }
+ return "Player";
+ }
+ }
+}
diff --git a/OmegaLeo.HelperLib.Steamworks/SteamNativeApi.cs b/OmegaLeo.HelperLib.Steamworks/SteamNativeApi.cs
new file mode 100644
index 0000000..1519df1
--- /dev/null
+++ b/OmegaLeo.HelperLib.Steamworks/SteamNativeApi.cs
@@ -0,0 +1,398 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace OmegaLeo.HelperLib.Steamworks
+{
+ internal static class SteamNativeApi
+ {
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private delegate bool SteamApiInitDelegate();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void SteamApiVoidDelegate();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate IntPtr SteamFriendsAccessorDelegate();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate IntPtr SteamUserStatsAccessorDelegate();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate IntPtr SteamFriendsGetPersonaNameDelegate(IntPtr steamFriends);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private delegate bool SteamUserStatsSetAchievementDelegate(IntPtr steamUserStats, [MarshalAs(UnmanagedType.LPStr)] string achievementId);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private delegate bool SteamUserStatsStoreStatsDelegate(IntPtr steamUserStats);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private delegate bool SteamUserStatsGetAchievementDelegate(IntPtr steamUserStats, [MarshalAs(UnmanagedType.LPStr)] string achievementId, [MarshalAs(UnmanagedType.I1)] out bool achieved);
+
+ private static readonly object SyncRoot = new object();
+
+ private static IntPtr _libraryHandle;
+ private static bool _libraryLoaded;
+ private static bool _initialized;
+
+ private static SteamApiInitDelegate _steamApiInit;
+ private static SteamApiVoidDelegate _steamApiShutdown;
+ private static SteamApiVoidDelegate _steamApiRunCallbacks;
+ private static SteamFriendsAccessorDelegate _steamFriendsAccessor;
+ private static SteamUserStatsAccessorDelegate _steamUserStatsAccessor;
+ private static SteamFriendsGetPersonaNameDelegate _steamFriendsGetPersonaName;
+ private static SteamUserStatsSetAchievementDelegate _steamUserStatsSetAchievement;
+ private static SteamUserStatsStoreStatsDelegate _steamUserStatsStoreStats;
+ private static SteamUserStatsGetAchievementDelegate _steamUserStatsGetAchievement;
+
+ private static IntPtr _steamFriends;
+ private static IntPtr _steamUserStats;
+
+ public static bool IsAvailable => EnsureLoaded();
+
+ public static bool Initialize(uint? appId = null)
+ {
+ lock (SyncRoot)
+ {
+ if (appId.HasValue && appId.Value > 0)
+ {
+ ConfigureAppId(appId.Value);
+ }
+
+ if (_initialized)
+ {
+ return true;
+ }
+
+ if (!EnsureLoaded())
+ {
+ return false;
+ }
+
+ if (_steamApiInit == null)
+ {
+ return false;
+ }
+
+ _initialized = _steamApiInit();
+ if (_initialized)
+ {
+ CacheInterfaces();
+ }
+
+ return _initialized;
+ }
+ }
+
+ public static void ConfigureAppId(uint appId)
+ {
+ if (appId == 0)
+ {
+ return;
+ }
+
+ lock (SyncRoot)
+ {
+ ApplyAppIdEnvironment(appId);
+ TryWriteSteamAppIdFile(appId);
+ }
+ }
+
+ public static void Shutdown()
+ {
+ lock (SyncRoot)
+ {
+ if (!_initialized)
+ {
+ return;
+ }
+
+ _steamApiShutdown?.Invoke();
+ _initialized = false;
+ _steamFriends = IntPtr.Zero;
+ _steamUserStats = IntPtr.Zero;
+ }
+ }
+
+ public static void RunCallbacks()
+ {
+ if (!_initialized)
+ {
+ return;
+ }
+
+ _steamApiRunCallbacks?.Invoke();
+ }
+
+ public static string GetPersonaName()
+ {
+ if (!EnsureReady())
+ {
+ return string.Empty;
+ }
+
+ var namePtr = _steamFriendsGetPersonaName?.Invoke(_steamFriends) ?? IntPtr.Zero;
+ return namePtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(namePtr) ?? string.Empty;
+ }
+
+ public static bool SetAchievement(string achievementId)
+ {
+ if (!EnsureReady())
+ {
+ return false;
+ }
+
+ return _steamUserStatsSetAchievement?.Invoke(_steamUserStats, achievementId) ?? false;
+ }
+
+ public static bool StoreStats()
+ {
+ if (!EnsureReady())
+ {
+ return false;
+ }
+
+ return _steamUserStatsStoreStats?.Invoke(_steamUserStats) ?? false;
+ }
+
+ public static bool GetAchievement(string achievementId, out bool achieved)
+ {
+ achieved = false;
+
+ if (!EnsureReady())
+ {
+ return false;
+ }
+
+ return _steamUserStatsGetAchievement?.Invoke(_steamUserStats, achievementId, out achieved) ?? false;
+ }
+
+ private static bool EnsureReady()
+ {
+ if (!EnsureLoaded())
+ {
+ return false;
+ }
+
+ if (!_initialized)
+ {
+ return false;
+ }
+
+ if (_steamFriends == IntPtr.Zero || _steamUserStats == IntPtr.Zero)
+ {
+ CacheInterfaces();
+ }
+
+ return _steamFriends != IntPtr.Zero && _steamUserStats != IntPtr.Zero;
+ }
+
+ private static bool EnsureLoaded()
+ {
+ lock (SyncRoot)
+ {
+ if (_libraryLoaded)
+ {
+ return true;
+ }
+
+ foreach (var candidate in GetLibraryCandidates())
+ {
+ try
+ {
+ _libraryHandle = LoadUnmanagedLibrary(candidate);
+ _libraryLoaded = _libraryHandle != IntPtr.Zero;
+ if (_libraryLoaded)
+ {
+ BindDelegates();
+ return true;
+ }
+ }
+ catch
+ {
+ // Try the next candidate.
+ }
+ }
+
+ return false;
+ }
+ }
+
+ private static void BindDelegates()
+ {
+ _steamApiInit =
+ Bind("SteamAPI_Init")
+ ?? Bind("SteamAPI_InitSafe");
+ _steamApiShutdown = Bind("SteamAPI_Shutdown");
+ _steamApiRunCallbacks = Bind("SteamAPI_RunCallbacks");
+ _steamFriendsAccessor = BindInterfaceAccessor("SteamFriends", "ISteamFriends");
+ _steamUserStatsAccessor = BindInterfaceAccessor("SteamUserStats", "ISteamUserStats");
+ _steamFriendsGetPersonaName = Bind("SteamAPI_ISteamFriends_GetPersonaName");
+ _steamUserStatsSetAchievement = Bind("SteamAPI_ISteamUserStats_SetAchievement");
+ _steamUserStatsStoreStats = Bind("SteamAPI_ISteamUserStats_StoreStats");
+ _steamUserStatsGetAchievement = Bind("SteamAPI_ISteamUserStats_GetAchievement");
+ }
+
+ private static T Bind(string exportName) where T : class
+ {
+ return TryGetExport(_libraryHandle, exportName, out var export)
+ ? Marshal.GetDelegateForFunctionPointer(export, typeof(T)) as T
+ : null;
+ }
+
+ private static T BindInterfaceAccessor(string friendlyName, string interfaceName) where T : class
+ {
+ for (var version = 1; version <= 64; version++)
+ {
+ var exportName = $"SteamAPI_{friendlyName}_v{version:000}";
+ if (TryGetExport(_libraryHandle, exportName, out var export) ||
+ TryGetExport(_libraryHandle, $"SteamAPI_{interfaceName}_v{version:000}", out export))
+ {
+ return Marshal.GetDelegateForFunctionPointer(export, typeof(T)) as T;
+ }
+ }
+
+ return null;
+ }
+
+ private static void CacheInterfaces()
+ {
+ _steamFriends = _steamFriendsAccessor?.Invoke() ?? IntPtr.Zero;
+ _steamUserStats = _steamUserStatsAccessor?.Invoke() ?? IntPtr.Zero;
+ }
+
+ private static string[] GetLibraryCandidates()
+ {
+ var libraryName = GetLibraryFileName();
+ var runtimeIdentifier = GetRuntimeIdentifier();
+
+ return new[]
+ {
+ Path.Combine(AppContext.BaseDirectory, "runtimes", runtimeIdentifier, "native", libraryName),
+ Path.Combine(AppContext.BaseDirectory, libraryName),
+ libraryName
+ };
+ }
+
+ private static string GetRuntimeIdentifier()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return Environment.Is64BitProcess ? "win-x64" : "win-x86";
+ }
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ return Environment.Is64BitProcess ? "osx-x64" : "osx-x86";
+ }
+
+ return Environment.Is64BitProcess ? "linux-x64" : "linux-x86";
+ }
+
+ private static string GetLibraryFileName()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return Environment.Is64BitProcess ? "steam_api64.dll" : "steam_api.dll";
+ }
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ return "libsteam_api.dylib";
+ }
+
+ return "libsteam_api.so";
+ }
+
+ private static void ApplyAppIdEnvironment(uint appId)
+ {
+ var appIdValue = appId.ToString();
+ Environment.SetEnvironmentVariable("SteamAppId", appIdValue);
+ Environment.SetEnvironmentVariable("SteamGameId", appIdValue);
+ }
+
+ private static void TryWriteSteamAppIdFile(uint appId)
+ {
+ var appIdValue = appId.ToString();
+ var candidatePaths = new[]
+ {
+ Path.Combine(AppContext.BaseDirectory, "steam_appid.txt"),
+ Path.Combine(Directory.GetCurrentDirectory(), "steam_appid.txt")
+ };
+
+ foreach (var path in candidatePaths)
+ {
+ try
+ {
+ File.WriteAllText(path, appIdValue);
+ }
+ catch
+ {
+ // Ignore write failures and continue with other candidates.
+ }
+ }
+ }
+
+ private static IntPtr LoadUnmanagedLibrary(string path)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return LoadLibraryWindows(path);
+ }
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ return DlopenMac(path, RtldNow);
+ }
+
+ return DlopenLinux(path, RtldNow);
+ }
+
+ private static bool TryGetExport(IntPtr libraryHandle, string exportName, out IntPtr export)
+ {
+ if (libraryHandle == IntPtr.Zero)
+ {
+ export = IntPtr.Zero;
+ return false;
+ }
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ export = GetProcAddressWindows(libraryHandle, exportName);
+ return export != IntPtr.Zero;
+ }
+
+ export = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
+ ? DlsymMac(libraryHandle, exportName)
+ : DlsymLinux(libraryHandle, exportName);
+ return export != IntPtr.Zero;
+ }
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "LoadLibraryW")]
+ private static extern IntPtr LoadLibraryWindows(string lpFileName);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, EntryPoint = "GetProcAddress")]
+ private static extern IntPtr GetProcAddressWindows(IntPtr hModule, string procName);
+
+ [DllImport("libdl.so.2", EntryPoint = "dlopen")]
+ private static extern IntPtr DlopenLinux(string fileName, int flags);
+
+ [DllImport("libdl.so.2", EntryPoint = "dlsym")]
+ private static extern IntPtr DlsymLinux(IntPtr handle, string symbol);
+
+ [DllImport("libSystem.B.dylib", EntryPoint = "dlopen")]
+ private static extern IntPtr DlopenMac(string fileName, int flags);
+
+ [DllImport("libSystem.B.dylib", EntryPoint = "dlsym")]
+ private static extern IntPtr DlsymMac(IntPtr handle, string symbol);
+
+ private const int RtldNow = 2;
+
+ }
+}
+
diff --git a/OmegaLeo.HelperLib.sln b/OmegaLeo.HelperLib.sln
index 68544d6..6bd1af1 100755
--- a/OmegaLeo.HelperLib.sln
+++ b/OmegaLeo.HelperLib.sln
@@ -25,47 +25,137 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "actions", "actions", "{750F
.github\workflows\dotnet.yml = .github\workflows\dotnet.yml
.github\workflows\nuget-publish.yml = .github\workflows\nuget-publish.yml
.github\workflows\github-publish.yml = .github\workflows\github-publish.yml
- .github\workflows\jetbrains-publish.yml = .github\workflows\jetbrains-publish.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.Documentation", "OmegaLeo.HelperLib.Documentation\OmegaLeo.HelperLib.Documentation.csproj", "{AE69480D-5956-46CB-9028-E4723735E37E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.Shared", "OmegaLeo.HelperLib.Shared\OmegaLeo.HelperLib.Shared.csproj", "{FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.Steamworks", "OmegaLeo.HelperLib.Steamworks\OmegaLeo.HelperLib.Steamworks.csproj", "{23C447DC-3188-4319-8307-E31852EF45C7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.ConsoleApp", "OmegaLeo.HelperLib.ConsoleApp\OmegaLeo.HelperLib.ConsoleApp.csproj", "{C5FD0FDC-0007-48AB-86C7-D8CB05126B86}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|x64.Build.0 = Debug|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|x86.Build.0 = Debug|Any CPU
{A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|x64.ActiveCfg = Release|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|x64.Build.0 = Release|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|x86.ActiveCfg = Release|Any CPU
+ {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|x86.Build.0 = Release|Any CPU
{378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|x64.Build.0 = Debug|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|x86.Build.0 = Debug|Any CPU
{378D8125-66B5-42B8-9881-33F951E5E04A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{378D8125-66B5-42B8-9881-33F951E5E04A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Release|x64.ActiveCfg = Release|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Release|x64.Build.0 = Release|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Release|x86.ActiveCfg = Release|Any CPU
+ {378D8125-66B5-42B8-9881-33F951E5E04A}.Release|x86.Build.0 = Release|Any CPU
{359536F7-02DE-43E9-A383-D83853227B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{359536F7-02DE-43E9-A383-D83853227B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Debug|x64.Build.0 = Debug|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Debug|x86.Build.0 = Debug|Any CPU
{359536F7-02DE-43E9-A383-D83853227B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{359536F7-02DE-43E9-A383-D83853227B0F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Release|x64.ActiveCfg = Release|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Release|x64.Build.0 = Release|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Release|x86.ActiveCfg = Release|Any CPU
+ {359536F7-02DE-43E9-A383-D83853227B0F}.Release|x86.Build.0 = Release|Any CPU
{1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Debug|x64.Build.0 = Debug|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Debug|x86.Build.0 = Debug|Any CPU
{1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Release|x64.ActiveCfg = Release|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Release|x64.Build.0 = Release|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Release|x86.ActiveCfg = Release|Any CPU
+ {1EA64C6B-D5D2-47EB-8255-5BAE2EE1385A}.Release|x86.Build.0 = Release|Any CPU
{488BC3EA-9B7A-4251-B802-22EB098D6494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{488BC3EA-9B7A-4251-B802-22EB098D6494}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Debug|x64.Build.0 = Debug|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Debug|x86.Build.0 = Debug|Any CPU
{488BC3EA-9B7A-4251-B802-22EB098D6494}.Release|Any CPU.ActiveCfg = Release|Any CPU
{488BC3EA-9B7A-4251-B802-22EB098D6494}.Release|Any CPU.Build.0 = Release|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Release|x64.ActiveCfg = Release|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Release|x64.Build.0 = Release|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Release|x86.ActiveCfg = Release|Any CPU
+ {488BC3EA-9B7A-4251-B802-22EB098D6494}.Release|x86.Build.0 = Release|Any CPU
{AE69480D-5956-46CB-9028-E4723735E37E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE69480D-5956-46CB-9028-E4723735E37E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Debug|x64.Build.0 = Debug|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Debug|x86.Build.0 = Debug|Any CPU
{AE69480D-5956-46CB-9028-E4723735E37E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE69480D-5956-46CB-9028-E4723735E37E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Release|x64.ActiveCfg = Release|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Release|x64.Build.0 = Release|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Release|x86.ActiveCfg = Release|Any CPU
+ {AE69480D-5956-46CB-9028-E4723735E37E}.Release|x86.Build.0 = Release|Any CPU
{FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Debug|x64.Build.0 = Debug|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Debug|x86.Build.0 = Debug|Any CPU
{FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Release|x64.ActiveCfg = Release|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Release|x64.Build.0 = Release|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Release|x86.ActiveCfg = Release|Any CPU
+ {FE6CA992-8BEB-41DD-A8E4-60FCEF96C59A}.Release|x86.Build.0 = Release|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Debug|x64.Build.0 = Debug|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Debug|x86.Build.0 = Debug|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Release|x64.ActiveCfg = Release|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Release|x64.Build.0 = Release|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Release|x86.ActiveCfg = Release|Any CPU
+ {23C447DC-3188-4319-8307-E31852EF45C7}.Release|x86.Build.0 = Release|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Debug|x64.Build.0 = Debug|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Debug|x86.Build.0 = Debug|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Release|x64.ActiveCfg = Release|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Release|x64.Build.0 = Release|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Release|x86.ActiveCfg = Release|Any CPU
+ {C5FD0FDC-0007-48AB-86C7-D8CB05126B86}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{750F2E9A-2703-4732-98D7-29C658368E48} = {00CF0543-37F3-41DE-B78F-8ADA6DE796ED}
diff --git a/OmegaLeo.HelperLib.sln.DotSettings.user b/OmegaLeo.HelperLib.sln.DotSettings.user
index b291b2c..6eac453 100755
--- a/OmegaLeo.HelperLib.sln.DotSettings.user
+++ b/OmegaLeo.HelperLib.sln.DotSettings.user
@@ -1,7 +1,10 @@
+ True
+ True
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded