@@ -0,0 +1,118 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user