Files
BSO-Launcher/Services/Game.cs
T
MrMahoandClaude Opus 5.5 b69b9638ff Erste Version
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:26:25 +01:00

119 lines
5.8 KiB
C#

using System.Diagnostics;
using System.IO.Compression;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace BSO.Launcher;
/// <summary>
/// Bus-Simulator 2012 finden (alle Steam-Bibliotheken), BSO in den Spielordner installieren (dinput8.dll + BSO\),
/// BSO.json fuer die Mod schreiben (Name = Kontoname, Server) und das Spiel ueber Steam starten.
/// </summary>
public static class Game
{
public const string SteamAppId = "253770";
const string GameFolderName = "Bus-Simulator 2012";
const string BinFolder = "Bin_High_Win64"; // BSO laeuft nur in der 64-Bit-Version
const string ExeName = "BusSimulator2012.exe";
/// <summary>Spielordner (der mit Bin_High_Win64) oder null.</summary>
public static string? FindFolder(Settings settings)
{
if (IsGameFolder(settings.GameFolder)) return settings.GameFolder;
foreach (string library in SteamLibraries())
{
string folder = Path.Combine(library, "steamapps", "common", GameFolderName);
if (IsGameFolder(folder)) return folder;
}
return null;
}
public static bool IsGameFolder(string? folder) =>
!string.IsNullOrEmpty(folder) && File.Exists(Path.Combine(folder, BinFolder, ExeName));
public static string Bin(string folder) => Path.Combine(folder, BinFolder);
static IEnumerable<string> SteamLibraries()
{
string? steam = null;
try { steam = Registry.CurrentUser.OpenSubKey(@"Software\Valve\Steam")?.GetValue("SteamPath") as string; } catch { }
steam ??= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Steam");
steam = steam.Replace('/', '\\');
yield return steam;
string vdf = Path.Combine(steam, "steamapps", "libraryfolders.vdf");
if (!File.Exists(vdf)) yield break;
foreach (Match m in Regex.Matches(File.ReadAllText(vdf), "\"path\"\\s+\"([^\"]+)\""))
yield return m.Groups[1].Value.Replace(@"\\", @"\");
}
/// <summary>Installierte BSO-Version (aus BSO.dll) oder null.</summary>
public static string? ModVersion(string folder)
{
string dll = Path.Combine(Bin(folder), "BSO", "BSO.dll");
if (!File.Exists(dll) || !File.Exists(Path.Combine(Bin(folder), "dinput8.dll"))) return null;
return FileVersionInfo.GetVersionInfo(dll).ProductVersion?.Split('+')[0];
}
/// <summary>Die Mod braucht die .NET 10 Runtime (x64) - der Launcher selbst bringt seine mit, die Mod nicht.</summary>
public static bool DotnetInstalled()
{
string shared = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "dotnet", "shared", "Microsoft.NETCore.App");
return Directory.Exists(shared) && Directory.GetDirectories(shared, "10.*").Length > 0;
}
public const string DotnetDownload = "https://dotnet.microsoft.com/download/dotnet/10.0";
public static bool IsRunning() => Process.GetProcessesByName(Path.GetFileNameWithoutExtension(ExeName)).Length > 0;
/// <summary>Mod-Paket (BSO-Mod.zip: dinput8.dll, BSO\*) in den Spielordner entpacken. BSO.json bleibt.</summary>
public static void InstallMod(string folder, byte[] zip)
{
if (IsRunning()) throw new Exception("Erst Bus-Simulator 2012 schliessen - solange es laeuft, sind die Mod-Dateien gesperrt");
string bin = Bin(folder);
using var archive = new ZipArchive(new MemoryStream(zip), ZipArchiveMode.Read);
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith('/')) continue;
string target = Path.GetFullPath(Path.Combine(bin, entry.FullName));
if (!target.StartsWith(Path.GetFullPath(bin) + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
throw new Exception("Ungueltiger Pfad im Mod-Paket: " + entry.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(target)!);
entry.ExtractToFile(target, true);
}
LauncherLog.Info("BSO installiert nach " + bin);
}
/// <summary>Einstellungen der Mod (BSO\BSO.json) - Name = Kontoname, Server, automatisch verbinden.</summary>
public static void WriteModConfig(string folder, string? name, string server, bool autoConnect)
{
string file = Path.Combine(Bin(folder), "BSO", "BSO.json");
JsonObject json;
try { json = File.Exists(file) ? JsonNode.Parse(File.ReadAllText(file)) as JsonObject ?? new JsonObject() : new JsonObject(); }
catch { json = new JsonObject(); }
if (!string.IsNullOrEmpty(name)) json["Name"] = name;
json["Server"] = server;
json["AutoConnect"] = autoConnect;
Directory.CreateDirectory(Path.GetDirectoryName(file)!);
File.WriteAllText(file, json.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
}
/// <summary>Ueber Steam starten (Overlay, Steam-Anmeldung des Spiels).</summary>
public static void Launch() =>
Process.Start(new ProcessStartInfo("steam://rungameid/" + SteamAppId) { UseShellExecute = true });
/// <summary>BSO aus dem Spielordner entfernen (Deinstallieren). Gibt Probleme als Text zurueck.</summary>
public static List<string> RemoveBso(Settings settings)
{
var problems = new List<string>();
string? folder = FindFolder(settings);
if (folder == null) return problems;
string bin = Bin(folder);
try { File.Delete(Path.Combine(bin, "dinput8.dll")); } catch (Exception e) { problems.Add("dinput8.dll: " + e.Message); }
try { if (Directory.Exists(Path.Combine(bin, "BSO"))) Directory.Delete(Path.Combine(bin, "BSO"), true); }
catch (Exception e) { problems.Add("BSO-Ordner: " + e.Message); }
return problems;
}
}