Started working on a SteamWorks integration

This commit is contained in:
2026-04-13 23:30:43 +01:00
parent 3e348a68b9
commit f0ea613a26
16 changed files with 787 additions and 92 deletions
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="singleClickDiffPreview" value="1" />
<option name="vcsConfiguration" value="3" />
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+73
View File
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="5e7ebcb0-c206-47f1-82b0-7bb7fa7d8ea5" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/OmegaLeo.HelperLib.sln" beforeDir="false" afterPath="$PROJECT_DIR$/OmegaLeo.HelperLib.sln" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CopilotPersistence">
<persistenceIdMap>
<entry key="_/media/omegaleo/Development/Library Dev/HelperLib" value="3CJh8xvOxVDl1aFwhckQNmfBnrf" />
</persistenceIdMap>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="GitHubPullRequestSearchHistory"><![CDATA[{
"lastFilter": {
"state": "OPEN",
"assignee": "omegaleo"
}
}]]></component>
<component name="GithubPullRequestsUISettings"><![CDATA[{
"selectedUrlAndAccountId": {
"url": "git@github.com:omegaleo/HelperLib.git",
"accountId": "c9aecefe-01cd-41e3-bbf8-a1cef71d68f2"
}
}]]></component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 1
}]]></component>
<component name="ProjectId" id="3CJh8xvOxVDl1aFwhckQNmfBnrf" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "dev",
"nodejs_package_manager_path": "npm",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="5e7ebcb0-c206-47f1-82b0-7bb7fa7d8ea5" name="Changes" comment="" />
<created>1776109424996</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1776109424996</updated>
<workItem from="1776109425603" duration="12000" />
</task>
<servers />
</component>
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
</component>
<component name="github-copilot-workspace">
<instructionFileLocations>
<option value=".github/instructions" />
</instructionFileLocations>
<promptFileLocations>
<option value=".github/prompts" />
</promptFileLocations>
</component>
</project>
+1
View File
@@ -0,0 +1 @@
{}
@@ -2,14 +2,21 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\OmegaLeo.HelperLib.Changelog\OmegaLeo.HelperLib.Changelog.csproj" />
<ProjectReference Include="..\OmegaLeo.HelperLib.Steamworks\OmegaLeo.HelperLib.Steamworks.csproj" />
<ProjectReference Include="..\OmegaLeo.HelperLib\OmegaLeo.HelperLib.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="steam_appid.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+17 -90
View File
@@ -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";
public static void Main()
{
SteamManager.ConfigureAppId(480); // 480 is the AppId for Spacewar, a test app provided by Valve
var steam = SteamManager.Instance;
if (steam.IsSteamworksInitialized)
{
Console.WriteLine($"Welcome {steam.GetSteamName()}");
}
var git = new GitClient(repo);
// Call this in your game loop (Unity Update, Godot _Process, etc.)
steam.Update();
var result = BenchmarkUtility.Record(() =>
{
var changes = git.GetChanges();
//var achievements = new AchievementManager();
//achievements.UnlockAchievement("ACH_FIRST_WIN");
if (changes.FolderName.IsNotNullOrEmpty())
{
RecursiveOutput(new List<ChangeFolder>() { changes });
var option = 99;
while (option != 0)
{
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;
steam.Shutdown();
}
}
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<ChangeFolder> 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);
}
foreach (var change in folder.ChangesInFolder)
{
Console.WriteLine($"{new string('\t', depth + 1)}>{Path.GetFileName(change.Path)} ({change.Status})");
}
}
}
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");
}
@@ -0,0 +1 @@
480
+1
View File
@@ -0,0 +1 @@
runtimes/
@@ -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;
}
}
}
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>9</LangVersion>
</PropertyGroup>
<!-- Add this entire ItemGroup section -->
<ItemGroup>
<!-- Define the native libraries and their paths -->
<Content Include="runtimes\**\*.dll;runtimes\**\*.so;runtimes\**\*.dylib">
<Pack>true</Pack>
<PackagePath>runtimes\%(RecursiveDir)%(Filename)%(Extension)</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
+49
View File
@@ -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.
@@ -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";
}
}
}
@@ -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<SteamApiInitDelegate>("SteamAPI_Init")
?? Bind<SteamApiInitDelegate>("SteamAPI_InitSafe");
_steamApiShutdown = Bind<SteamApiVoidDelegate>("SteamAPI_Shutdown");
_steamApiRunCallbacks = Bind<SteamApiVoidDelegate>("SteamAPI_RunCallbacks");
_steamFriendsAccessor = BindInterfaceAccessor<SteamFriendsAccessorDelegate>("SteamFriends", "ISteamFriends");
_steamUserStatsAccessor = BindInterfaceAccessor<SteamUserStatsAccessorDelegate>("SteamUserStats", "ISteamUserStats");
_steamFriendsGetPersonaName = Bind<SteamFriendsGetPersonaNameDelegate>("SteamAPI_ISteamFriends_GetPersonaName");
_steamUserStatsSetAchievement = Bind<SteamUserStatsSetAchievementDelegate>("SteamAPI_ISteamUserStats_SetAchievement");
_steamUserStatsStoreStats = Bind<SteamUserStatsStoreStatsDelegate>("SteamAPI_ISteamUserStats_StoreStats");
_steamUserStatsGetAchievement = Bind<SteamUserStatsGetAchievementDelegate>("SteamAPI_ISteamUserStats_GetAchievement");
}
private static T Bind<T>(string exportName) where T : class
{
return TryGetExport(_libraryHandle, exportName, out var export)
? Marshal.GetDelegateForFunctionPointer(export, typeof(T)) as T
: null;
}
private static T BindInterfaceAccessor<T>(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;
}
}
+91 -1
View File
@@ -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}
+3
View File
@@ -1,7 +1,10 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fmedia_002Fomegaleo_002FDevelopment_002FLibrary_0020Dev_002FHelperLib_002FOmegaLeo_002EHelperLib_002ESteamworks_002Fruntimes_002Fwin_002Dx64_002Fnative_002Fsteam_005Fapi64_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fmedia_002Fomegaleo_002FDevelopment_002FLibrary_0020Dev_002FHelperLib_002FOmegaLeo_002EHelperLib_002ESteamworks_002Fruntimes_002Fwin_002Dx86_002Fnative_002Fsteam_005Fapi_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADocumentationDescription_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe7ce68ea4d3540e4bc8ef1bd962ca30b3a00_003F46_003F1f9d3ace_003FDocumentationDescription_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADocumentationHelperTool_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F165936b93b8c4f33b6ee955456d3fd6a3c00_003F08_003F718f7e37_003FDocumentationHelperTool_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fbf9021a960b74107a7e141aa06bc9d8a0a53c929178c2fb95b1597be8af8dc_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9ee76fb4aded5e9da6e66cc2dcb127fac08d3ec5ac84fc6db9d4ee1d2e38_003FMonitor_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9ee76fb4aded5e9da6e66cc2dcb127fac08d3ec5ac84fc6db9d4ee1d2e38_003FMonitor_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARuntimeHandles_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F42d5e9d0d54843a23887036cb9c33c9ce48bbc6f7c35ed3759154a95456c796_003FRuntimeHandles_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARuntimeModule_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fomegaleo_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F47104fb3abb717b489a79c6abfd53988baac74c62be2ae237abd31518850e2_003FRuntimeModule_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>