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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions SAM.API/SAM.API.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Company>Gibbed</Company>
<Authors>Gibbed</Authors>
Expand All @@ -18,14 +18,15 @@
<RepositoryType>Git</RepositoryType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<LangVersion>9.0</LangVersion>
<TargetFramework>net8.0-windows</TargetFramework>
<LangVersion>latest</LangVersion>
<Platforms>x86</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<UseWindowsForms>true</UseWindowsForms>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>

</Project>
31 changes: 24 additions & 7 deletions SAM.API/Steam.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2024 Rick (rick 'at' gibbed 'dot' us)
/* Copyright (c) 2024 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand Down Expand Up @@ -112,16 +112,33 @@ public static bool Load()
return true;
}

string path = GetInstallPath();
if (path == null)
// 1. Try Local Folder First (Nuclear Strategy)
string localPath = AppDomain.CurrentDomain.BaseDirectory;
string dllPath = Path.Combine(localPath, "steamclient.dll");

IntPtr module = IntPtr.Zero;
if (File.Exists(dllPath))
{
return false;
// Load dependencies first
Native.LoadLibraryEx(Path.Combine(localPath, "tier0_s.dll"), IntPtr.Zero, Native.LoadWithAlteredSearchPath);
Native.LoadLibraryEx(Path.Combine(localPath, "vstdlib_s.dll"), IntPtr.Zero, Native.LoadWithAlteredSearchPath);
module = Native.LoadLibraryEx(dllPath, IntPtr.Zero, Native.LoadWithAlteredSearchPath);
}

Native.SetDllDirectory(path + ";" + Path.Combine(path, "bin"));
// 2. Fallback to Registry if local fails
if (module == IntPtr.Zero)
{
string path = GetInstallPath();
if (path != null)
{
Native.SetDllDirectory(path);
Native.LoadLibraryEx(Path.Combine(path, "tier0_s.dll"), IntPtr.Zero, Native.LoadWithAlteredSearchPath);
Native.LoadLibraryEx(Path.Combine(path, "vstdlib_s.dll"), IntPtr.Zero, Native.LoadWithAlteredSearchPath);
dllPath = Path.Combine(path, "steamclient.dll");
module = Native.LoadLibraryEx(dllPath, IntPtr.Zero, Native.LoadWithAlteredSearchPath);
}
}

path = Path.Combine(path, "steamclient.dll");
IntPtr module = Native.LoadLibraryEx(path, IntPtr.Zero, Native.LoadWithAlteredSearchPath);
if (module == IntPtr.Zero)
{
return false;
Expand Down
57 changes: 54 additions & 3 deletions SAM.Game/Manager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2024 Rick (rick 'at' gibbed 'dot' us)
/* Copyright (c) 2024 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand Down Expand Up @@ -133,6 +133,17 @@ private void OnIconDownload(object sender, DownloadDataCompletedEventArgs e)
stream.Write(e.Result, 0, e.Result.Length);
bitmap = new(stream);
}

string iconName = info.IsAchieved == true ? info.IconNormal : info.IconLocked;
if (!string.IsNullOrEmpty(iconName))
{
string cachedPath = GetCacheFilePath(iconName);
try
{
File.WriteAllBytes(cachedPath, e.Result);
}
catch { }
}
}
catch (Exception)
{
Expand Down Expand Up @@ -582,17 +593,57 @@ private void GetStatistics()
}
}

private string GetCacheFilePath(string iconName)
{
string cacheDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache", "achievements", this._GameId.ToString());
if (!Directory.Exists(cacheDir))
{
try
{
Directory.CreateDirectory(cacheDir);
}
catch { }
}
return Path.Combine(cacheDir, iconName);
}

private void AddAchievementToIconQueue(Stats.AchievementInfo info, bool startDownload)
{
int imageIndex = this._AchievementImageList.Images.IndexOfKey(
info.IsAchieved == true ? info.IconNormal : info.IconLocked);
string iconName = info.IsAchieved == true ? info.IconNormal : info.IconLocked;

if (string.IsNullOrEmpty(iconName))
{
info.ImageIndex = 0;
return;
}

int imageIndex = this._AchievementImageList.Images.IndexOfKey(iconName);

if (imageIndex >= 0)
{
info.ImageIndex = imageIndex;
}
else
{
// Check disk cache first
string cachedPath = GetCacheFilePath(iconName);
if (File.Exists(cachedPath))
{
try
{
using (var stream = new FileStream(cachedPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var bitmap = new Bitmap(stream);
this.AddAchievementIcon(info, bitmap);
}
return; // Successfully loaded from cache
}
catch
{
try { File.Delete(cachedPath); } catch { }
}
}

this._IconQueue.Add(info);

if (startDownload == true)
Expand Down
36 changes: 11 additions & 25 deletions SAM.Game/SAM.Game.csproj
Original file line number Diff line number Diff line change
@@ -1,41 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>x86</Platforms>
<Platform>x86</Platform>
<LangVersion>latest</LangVersion>
<Platforms>x86</Platforms>
<PlatformTarget>x86</PlatformTarget>
<AssemblyTitle>Steam Achievement Manager</AssemblyTitle>
<Company>Gibbed</Company>
<Authors>Gibbed</Authors>
<Description>A manager for game achievements in Steam.</Description>
<Copyright>Copyright © Gibbed 2019</Copyright>
</PropertyGroup>
<PropertyGroup>
<Version>7.0.0</Version>
<AssemblyVersion>7.0.0.0</AssemblyVersion>
<FileVersion>7.0.0.0</FileVersion>
</PropertyGroup>
<PropertyGroup>
<Version>7.0.42</Version>
<ApplicationIcon>Blank.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<RepositoryUrl>https://github.com/gibbed/SteamAchievementManager/</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
</PropertyGroup>
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net48</TargetFramework>
<LangVersion>9.0</LangVersion>
<Platforms>x86</Platforms>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>..\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>..\upload\</OutputPath>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms" />
</ItemGroup>

<ItemGroup>
<Compile Update="DoubleBufferedListView.cs">
<SubType>Component</SubType>
Expand Down
69 changes: 69 additions & 0 deletions SAM.Picker/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<Application x:Class="SAM.Picker.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<!-- Modern Colors -->
<Color x:Key="PrimaryBackgroundColor">#121212</Color>
<Color x:Key="SecondaryBackgroundColor">#1E1E1E</Color>
<Color x:Key="AccentColor">#0078D4</Color>
<Color x:Key="TextColor">#FFFFFF</Color>
<Color x:Key="TextSecondaryColor">#B0B0B0</Color>

<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="{StaticResource PrimaryBackgroundColor}"/>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="{StaticResource SecondaryBackgroundColor}"/>
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}"/>
<SolidColorBrush x:Key="TextBrush" Color="{StaticResource TextColor}"/>
<SolidColorBrush x:Key="TextSecondaryBrush" Color="{StaticResource TextSecondaryColor}"/>

<!-- Modern Styles -->
<Style TargetType="TextBox">
<Setter Property="Background" Value="#252525"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="10,5"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#333333"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border x:Name="border" CornerRadius="4"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style TargetType="Button">
<Setter Property="Background" Value="#333333"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="15,8"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" CornerRadius="4"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#444444"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background" Value="#222222"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
42 changes: 42 additions & 0 deletions SAM.Picker/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Configuration;
using System.Data;
using System.Windows;

namespace SAM.Picker;

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : System.Windows.Application
{
public App()
{
// Register handlers FIRST, before anything else
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
this.DispatcherUnhandledException += OnDispatcherUnhandledException;

try {
System.IO.File.WriteAllText("start_log.txt", "App Starting...");
InitializeComponent();
} catch (Exception ex) {
System.Windows.MessageBox.Show($"Startup Error: {ex.Message}");
}
}

private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
string msg = $"Fatal Error: {ex?.Message}\n\nStack Trace:\n{ex?.StackTrace}";
System.IO.File.AppendAllText("start_log.txt", "\nFATAL: " + msg);
System.Windows.MessageBox.Show(msg, "Universal Crash Handler", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
}

private void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
string msg = $"UI Error: {e.Exception.Message}";
System.IO.File.AppendAllText("start_log.txt", "\nUI ERROR: " + msg);
System.Windows.MessageBox.Show(msg, "Universal Crash Handler", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
e.Handled = true;
}
}

10 changes: 10 additions & 0 deletions SAM.Picker/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Windows;

[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
6 changes: 1 addition & 5 deletions SAM.Picker/GameInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2024 Rick (rick 'at' gibbed 'dot' us)
/* Copyright (c) 2024 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand All @@ -21,8 +21,6 @@
*/

using System.Globalization;
using System.Windows.Forms;

namespace SAM.Picker
{
internal class GameInfo
Expand All @@ -41,8 +39,6 @@ public string Name

public string ImageUrl;

public ListViewItem Item;

public GameInfo(uint id, string type)
{
this.Id = id;
Expand Down
Loading