Skip to content

Commit

Permalink
Add project files.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeon8 committed Dec 10, 2024
1 parent 88c9d96 commit 40835ed
Show file tree
Hide file tree
Showing 17 changed files with 418 additions and 0 deletions.
27 changes: 27 additions & 0 deletions Hoi3Launcher.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hoi3Launcher", "src\Hoi3Launcher\Hoi3Launcher.csproj", "{9F24DCCA-7D85-4A9F-9EE9-8E9172C15A9C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{544CA754-645F-43BF-9B8C-CE769E4CB20C}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9F24DCCA-7D85-4A9F-9EE9-8E9172C15A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F24DCCA-7D85-4A9F-9EE9-8E9172C15A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F24DCCA-7D85-4A9F-9EE9-8E9172C15A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F24DCCA-7D85-4A9F-9EE9-8E9172C15A9C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
13 changes: 13 additions & 0 deletions src/Hoi3Launcher/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Hoi3Launcher.App"
xmlns:sty="using:FluentAvalonia.Styling"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->

<Application.Styles>
<ClassicTheme />
<!--<SimpleTheme />-->
<!--<sty:FluentAvaloniaTheme />-->
</Application.Styles>
</Application>
48 changes: 48 additions & 0 deletions src/Hoi3Launcher/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Linq;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using Hoi3Launcher.ViewModels;
using Hoi3Launcher.Views;

namespace Hoi3Launcher
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}

base.OnFrameworkInitializationCompleted();
}

private void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove =
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();

// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
}
}
Binary file added src/Hoi3Launcher/Assets/avalonia-logo.ico
Binary file not shown.
31 changes: 31 additions & 0 deletions src/Hoi3Launcher/Hoi3Launcher.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<PublishAot>true</PublishAot>
</PropertyGroup>

<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
<PackageReference Include="Classic.Avalonia.Theme" Version="11.2.0.6" />
</ItemGroup>

<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions src/Hoi3Launcher/Models/Dlc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hoi3Launcher.Models
{
public record Dlc(string Name, string ExecutableName, IEnumerable<Mod> Mods);
}
13 changes: 13 additions & 0 deletions src/Hoi3Launcher/Models/Mod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hoi3Launcher.Models
{
public record Mod(string Name, string Path)
{
public bool IsEnabled { get; set; }
}
}
22 changes: 22 additions & 0 deletions src/Hoi3Launcher/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using Avalonia;

namespace Hoi3Launcher
{
internal sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);

// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}
}
8 changes: 8 additions & 0 deletions src/Hoi3Launcher/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"profiles": {
"Hoi3Launcher": {
"commandName": "Project",
"workingDirectory": "E:\\Games\\Hearts of Iron III"
}
}
}
62 changes: 62 additions & 0 deletions src/Hoi3Launcher/Services/LastModsService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Hoi3Launcher.Models;

namespace Hoi3Launcher.Services;

public class LastModsService
{
public void Load(IEnumerable<Dlc> dlcs)
{
string path = GetPath();
if (!File.Exists(path))
return;

JsonNode? json = JsonNode.Parse(File.ReadAllText(path));
if (json is null)
return;

foreach (Dlc dlc in dlcs)
{
JsonNode? modsNode = json[dlc.Name];
if (modsNode is null)
continue;

HashSet<string> mods = modsNode.AsArray()
.Select(m => m!.AsValue().GetValue<string>())
.ToHashSet();

foreach (Mod mod in dlc.Mods)
{
if (mods.Contains(mod.Name))
mod.IsEnabled = true;
}
}
}

private static string GetPath()
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Hoi3Launcher/mods.json");
}

public Task Save(IEnumerable<Dlc> dlcs)
{
JsonNode node = new JsonObject();
foreach (Dlc dlc in dlcs)
{
JsonValue[] jsonMods = (from m in dlc.Mods
where m.IsEnabled
select JsonValue.Create(m.Name)).ToArray();
string name = dlc.Name;
JsonNode[] items = jsonMods;
node[name] = new JsonArray(items);
}
string path = GetPath();
Directory.CreateDirectory(Path.GetDirectoryName(path));
return File.WriteAllTextAsync(path, node.ToJsonString());
}
}
24 changes: 24 additions & 0 deletions src/Hoi3Launcher/Services/Launcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Diagnostics;
using System.Linq;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Hoi3Launcher.Models;

namespace Hoi3Launcher.Services;

public class Launcher
{
public void LaunchGame(Dlc dlc)
{
Process.Start(dlc.ExecutableName, dlc.Mods.Select(m => $"-mod={m.Path}"));
}

public void CloseApplication()
{
Application application = Application.Current!;
if (application.ApplicationLifetime is ClassicDesktopStyleApplicationLifetime lifetime)
{
lifetime.Shutdown(0);
}
}
}
28 changes: 28 additions & 0 deletions src/Hoi3Launcher/Services/ModScanner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO;
using Hoi3Launcher.Models;
using Hoi3Launcher.Utils;

namespace Hoi3Launcher.Services;

public class ModScanner
{
public IEnumerable<Mod> LoadMods(string path)
{
if (!Directory.Exists(path))
return [];

var mods = new List<Mod>();
var folder = new DirectoryInfo(path);
foreach (FileInfo file in folder.EnumerateFiles())
{
if (!(file.Extension != ".mod"))
{
string name = ScriptUtils.ParseValue(File.ReadAllText(file.FullName), "name");
mods.Add(new Mod(name, "mod/" + file.Name));
}
}
return mods;
}
}
13 changes: 13 additions & 0 deletions src/Hoi3Launcher/Utils/ScriptUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Hoi3Launcher.Utils
{
public static class ScriptUtils
{
public static string ParseValue(string text, string key)
{
var startPosition = text.IndexOf(key);
var startQuote = text.IndexOf('"', startPosition) + 1;
var endQuote = text.IndexOf('"', startQuote);
return text[startQuote..endQuote];
}
}
}
44 changes: 44 additions & 0 deletions src/Hoi3Launcher/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Hoi3Launcher.Models;
using Hoi3Launcher.Services;

namespace Hoi3Launcher.ViewModels;

public partial class MainWindowViewModel : ViewModelBase
{
[ObservableProperty]
private Dlc? _selectedDlc;

private readonly ModScanner _modScanner = new();
private readonly LastModsService _lastModsService = new();
private readonly Launcher _launcher = new();

public ObservableCollection<Dlc> Dlcs { get; } = new ObservableCollection<Dlc>();

public void Load()
{
Dlcs.Add(new Dlc("Their Finest Hour", "hoi3_tfh.exe", _modScanner.LoadMods("tfh/mod/")));
Dlcs.Add(new Dlc("For the Motherland", "hoi3game.exe", _modScanner.LoadMods("mod/")));
_lastModsService.Load(Dlcs);
SelectedDlc = Dlcs.First();
}

[RelayCommand]
public async Task Launch()
{
if (SelectedDlc is null)
return;

await _lastModsService.Save(Dlcs);
_launcher.LaunchGame(SelectedDlc);
_launcher.CloseApplication();
}
}
7 changes: 7 additions & 0 deletions src/Hoi3Launcher/ViewModels/ViewModelBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using CommunityToolkit.Mvvm.ComponentModel;

namespace Hoi3Launcher.ViewModels;

public class ViewModelBase : ObservableObject
{
}
Loading

0 comments on commit 40835ed

Please sign in to comment.