From 4b4eebb0e9663a2f2a7868dbfc8e04ffcf85071e Mon Sep 17 00:00:00 2001 From: Mary Date: Sun, 28 Jan 2024 01:14:21 +0200 Subject: [PATCH 1/2] Horrorshow Groundwork for Resource Packs Dumper fix Wow new button in plugins --- Marsey/Config/MarseyConf.cs | 9 +- Marsey/Config/MarseyVars.cs | 18 ++- Marsey/Game/Patches/Dumper/Dumper.cs | 9 +- .../Patches/Dumper/Resource/ResDumpPatches.cs | 9 +- .../Patches/Dumper/Resource/ResourceDumper.cs | 23 +-- .../Game/ResourcePack/Reflection/Patches.cs | 9 ++ .../ResourcePack/Reflection/ResourceTypes.cs | 18 +++ Marsey/Game/ResourcePack/ResMan.cs | 78 ++++++++++ Marsey/Game/ResourcePack/ResourcePack.cs | 33 ++++ Marsey/Game/ResourcePack/RessourceSwapper.cs | 30 ++++ Marsey/Handbreak/Helpers.cs | 8 - Marsey/Handbreak/Manual.cs | 3 +- Marsey/MarseyPatcher.cs | 6 +- Marsey/Misc/Exceptions.cs | 11 ++ Marsey/Misc/FileHandler.cs | 49 ++++-- Marsey/Subversion/Subverse.cs | 3 + SS14.Launcher/LauncherPaths.cs | 15 +- SS14.Launcher/Models/Connector.cs | 11 +- SS14.Launcher/Models/Data/CVars.cs | 5 + .../MainWindowTabs/OptionsTabViewModel.cs | 10 +- .../MainWindowTabs/PatchesTabViewModel.cs | 29 +++- .../Views/MainWindowTabs/OptionsTabView.xaml | 10 +- .../Views/MainWindowTabs/PatchesTabView.xaml | 145 +++++++++++------- 23 files changed, 420 insertions(+), 121 deletions(-) create mode 100644 Marsey/Game/ResourcePack/Reflection/Patches.cs create mode 100644 Marsey/Game/ResourcePack/Reflection/ResourceTypes.cs create mode 100644 Marsey/Game/ResourcePack/ResMan.cs create mode 100644 Marsey/Game/ResourcePack/ResourcePack.cs create mode 100644 Marsey/Game/ResourcePack/RessourceSwapper.cs diff --git a/Marsey/Config/MarseyConf.cs b/Marsey/Config/MarseyConf.cs index 22b3aa9..0ef7ddd 100644 --- a/Marsey/Config/MarseyConf.cs +++ b/Marsey/Config/MarseyConf.cs @@ -37,10 +37,14 @@ public static class MarseyConf /// public static bool ThrowOnFail; + /// + /// Disable strict fork checks when applying resource packs. + /// + public static bool DisableResPackStrict; + /// public static bool ForceHWID; - - + /// public static bool KillRPC; @@ -59,6 +63,7 @@ public static class MarseyConf { "MARSEY_LOADER_DEBUG", value => DebugAllowed = value }, { "MARSEY_THROW_FAIL", value => ThrowOnFail = value }, { "MARSEY_SEPARATE_LOGGER", value => SeparateLogger = value }, + { "MARSEY_DISABLE_STRICT", value => DisableResPackStrict = value}, { "MARSEY_FORCINGHWID", value => ForceHWID = value }, { "MARSEY_DISABLE_PRESENCE", value => KillRPC = value }, { "MARSEY_DUMP_ASSEMBLIES", value => Dumper = value }, diff --git a/Marsey/Config/MarseyVars.cs b/Marsey/Config/MarseyVars.cs index 2a58cf8..419c70c 100644 --- a/Marsey/Config/MarseyVars.cs +++ b/Marsey/Config/MarseyVars.cs @@ -35,17 +35,29 @@ public static class MarseyVars public static readonly int LoopCooldown = 200; /// - /// Marseypatches are saved to this one + /// Name of folder containing files used by Marsey /// - public static readonly string MarseyPatchFolder = "Marsey"; + public static readonly string MarseyFolder = "Marsey"; + + /// + /// Folder containing mods + /// + public static readonly string MarseyPatchFolder = Path.Combine(MarseyFolder, "Mods"); + + /// + /// Folder containing Resource Packs + /// + public static readonly string MarseyResourceFolder = Path.Combine(MarseyFolder, "ResourcePacks"); /// /// Log identified for marseyloader /// public static readonly string MarseyLoggerPrefix = "MARSEY"; + + public static readonly string MarseyLoggerFileName = "client.marsey.log"; /// - /// Refuse to play on servers over this engine version if hidesey is disabled + /// Refuse to play on servers over or equal to this engine version if hidesey is disabled /// /// public static readonly Version Detection = new Version("183.0.0"); diff --git a/Marsey/Game/Patches/Dumper/Dumper.cs b/Marsey/Game/Patches/Dumper/Dumper.cs index 5e9faa9..6524a01 100644 --- a/Marsey/Game/Patches/Dumper/Dumper.cs +++ b/Marsey/Game/Patches/Dumper/Dumper.cs @@ -1,5 +1,5 @@ using System.Reflection; -using Marsey.Stealthsey; +using Marsey.Game.ResourcePack; namespace Marsey.Game.Patches; @@ -8,20 +8,17 @@ namespace Marsey.Game.Patches; /// public static class Dumper { - private static ResourceDumper _res = new ResourceDumper(); public static string path = "marsey"; public static void Start() { - //Preclusion.Trigger("Dumper started."); GetExactPath(); Patch(); } private static void GetExactPath() { - string fork = Environment.GetEnvironmentVariable("MARSEY_DUMP_FORKID") ?? "marsey"; - Envsey.CleanFlag(fork); + string fork = ResMan.GetForkID() ?? "marsey"; string loc = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; path = Path.Combine(loc, "Dumper/", $"{fork}/"); @@ -29,6 +26,6 @@ private static void GetExactPath() private static void Patch() { - _res.Patch(); + ResourceDumper.Patch(); } } \ No newline at end of file diff --git a/Marsey/Game/Patches/Dumper/Resource/ResDumpPatches.cs b/Marsey/Game/Patches/Dumper/Resource/ResDumpPatches.cs index a911701..20a55bb 100644 --- a/Marsey/Game/Patches/Dumper/Resource/ResDumpPatches.cs +++ b/Marsey/Game/Patches/Dumper/Resource/ResDumpPatches.cs @@ -10,12 +10,11 @@ private static void PostfixCFF(ref object __instance, ref dynamic __result) { if (ResourceDumper.CFRMi == null) return; // If FileReader handle is not available, return - FileHandler.CheckRenameDirectory(Dumper.path); - - foreach (dynamic file in __result) + foreach (dynamic file in __result) { - string canonPath = Dumper.path.StartsWith($"/") ? Dumper.path[1..] : Dumper.path; - string fullpath = Path.Combine(Dumper.path, canonPath); + string canonPath = file.CanonPath; + string fixedCanonPath = canonPath.StartsWith($"/") ? canonPath[1..] : canonPath; + string fullpath = Path.Combine(Dumper.path, fixedCanonPath); FileHandler.CreateDir(fullpath); diff --git a/Marsey/Game/Patches/Dumper/Resource/ResourceDumper.cs b/Marsey/Game/Patches/Dumper/Resource/ResourceDumper.cs index 2a9319c..598d80a 100644 --- a/Marsey/Game/Patches/Dumper/Resource/ResourceDumper.cs +++ b/Marsey/Game/Patches/Dumper/Resource/ResourceDumper.cs @@ -1,5 +1,7 @@ using System.Reflection; using HarmonyLib; +using Marsey.Game.ResourcePack; +using Marsey.Game.ResourcePack.Reflection; using Marsey.Handbreak; using Marsey.Misc; @@ -8,35 +10,34 @@ namespace Marsey.Game.Patches; /// /// By complete accident this dumps everything /// -public class ResourceDumper +public static class ResourceDumper { public static MethodInfo? CFRMi; - public void Patch() + public static void Patch() { - Type? ProtoMan = Helpers.TypeFromQualifiedName("Robust.Shared.ContentPack.ResourceManager"); - Type? ResPath = Helpers.TypeFromQualifiedName("Robust.Shared.Utility.ResPath"); - - CFRMi = AccessTools.Method(ProtoMan, "ContentFileRead", new[] { ResPath }); - - if (ProtoMan == null) + FileHandler.CheckRenameDirectory(Dumper.path); + + if (ResourceTypes.ProtoMan == null) { MarseyLogger.Log(MarseyLogger.LogType.ERRO, "PrototypeManager is null."); return; } - if (ResPath == null) + if (ResourceTypes.ResPath == null) { MarseyLogger.Log(MarseyLogger.LogType.ERRO, "ResPath is null."); return; } + CFRMi = AccessTools.Method(ResourceTypes.ProtoMan, "ContentFileRead", new[] { ResourceTypes.ResPath }); + Helpers.PatchMethod( - targetType: ProtoMan, + targetType: ResourceTypes.ProtoMan, targetMethodName: "ContentFindFiles", patchType: typeof(ResDumpPatches), patchMethodName: "PostfixCFF", patchingType: HarmonyPatchType.Postfix, - new Type[]{ ResPath } + new Type[]{ ResourceTypes.ResPath } ); } } \ No newline at end of file diff --git a/Marsey/Game/ResourcePack/Reflection/Patches.cs b/Marsey/Game/ResourcePack/Reflection/Patches.cs new file mode 100644 index 0000000..8648abe --- /dev/null +++ b/Marsey/Game/ResourcePack/Reflection/Patches.cs @@ -0,0 +1,9 @@ +namespace Marsey.Game.ResourcePack.Reflection; + +public static class Patches +{ + private static bool PrefixCFF(ref object __instance, ref dynamic path) + { + return true; + } +} \ No newline at end of file diff --git a/Marsey/Game/ResourcePack/Reflection/ResourceTypes.cs b/Marsey/Game/ResourcePack/Reflection/ResourceTypes.cs new file mode 100644 index 0000000..5614781 --- /dev/null +++ b/Marsey/Game/ResourcePack/Reflection/ResourceTypes.cs @@ -0,0 +1,18 @@ +using Marsey.Handbreak; + +namespace Marsey.Game.ResourcePack.Reflection; + +/// +/// Holds reflection data related to Resources +/// +public static class ResourceTypes +{ + public static Type? ProtoMan { get; private set; } + public static Type? ResPath { get; private set; } + + public static void Initialize() + { + ProtoMan = Helpers.TypeFromQualifiedName("Robust.Shared.ContentPack.ResourceManager"); + ResPath = Helpers.TypeFromQualifiedName("Robust.Shared.Utility.ResPath"); + } +} \ No newline at end of file diff --git a/Marsey/Game/ResourcePack/ResMan.cs b/Marsey/Game/ResourcePack/ResMan.cs new file mode 100644 index 0000000..8172af1 --- /dev/null +++ b/Marsey/Game/ResourcePack/ResMan.cs @@ -0,0 +1,78 @@ +using Marsey.Config; +using Marsey.Game.ResourcePack.Reflection; +using Marsey.Misc; +using Marsey.Serializer; +using Marsey.Stealthsey; + +namespace Marsey.Game.ResourcePack; + +public static class ResMan +{ + public static readonly string MarserializerFile = "rpacks.marsey"; + private static readonly List _resourcePacks = []; + private static string? _fork; + private static readonly string _forkEnvVar = "MARSEY_FORKID"; + + /// + /// Executed by the loader + /// + public static void Initialize() + { + ResourceTypes.Initialize(); + + _fork = Environment.GetEnvironmentVariable(_forkEnvVar) ?? "marsey"; + Envsey.CleanFlag(_forkEnvVar); + + List enabledPacks = Marserializer.Deserialize([MarseyVars.MarseyResourceFolder], MarserializerFile) ?? []; + foreach (string dir in enabledPacks) + { + InitializeRPack(dir, !MarseyConf.DisableResPackStrict); + } + } + + /// + /// Executed by the launcher + /// + public static void LoadDir() + { + _resourcePacks.Clear(); + string[] subDirs = Directory.GetDirectories(MarseyVars.MarseyResourceFolder); + foreach (string subdir in subDirs) + { + InitializeRPack(subdir); + } + } + + /// + /// Creates a ResourcePack object from a given path to a directory + /// + /// resource pack directory + /// match fork id + private static void InitializeRPack(string path, bool strict = false) + { + ResourcePack rpack = new ResourcePack(path); + + try + { + rpack.ParseMeta(); + } + catch (RPackException e) + { + MarseyLogger.Log(MarseyLogger.LogType.FATL, e.ToString()); + return; + } + + AddRPack(rpack, strict); + } + + private static void AddRPack(ResourcePack rpack, bool strict) + { + if (_resourcePacks.Any(rp => rp.Dir == rpack.Dir)) return; + if (strict && rpack.Target != _fork && rpack.Target != "") return; + + _resourcePacks.Add(rpack); + } + + public static List GetRPacks() => _resourcePacks; + public static string? GetForkID() => _fork; +} \ No newline at end of file diff --git a/Marsey/Game/ResourcePack/ResourcePack.cs b/Marsey/Game/ResourcePack/ResourcePack.cs new file mode 100644 index 0000000..05200d8 --- /dev/null +++ b/Marsey/Game/ResourcePack/ResourcePack.cs @@ -0,0 +1,33 @@ +using Marsey.Misc; +using Newtonsoft.Json; + +namespace Marsey.Game.ResourcePack; + +/// +/// Metadata class for Resource Packs +/// +public class ResourcePack(string dir) +{ + public string Dir { get; } = dir; + public string? Name { get; private set; } + public string? Desc { get; private set; } + public string? Target { get; private set; } // Specify fork for which this is used + public bool Enabled { get; set; } + + public void ParseMeta() + { + string metaPath = Path.Combine(Dir, "meta.json"); + if (!File.Exists(metaPath)) + throw new RPackException($"Found folder {Dir}, but it didn't have a meta.json"); + + string jsonData = File.ReadAllText(metaPath); + dynamic? meta = JsonConvert.DeserializeObject(jsonData); + + if (meta == null || meta?.Name == null || meta?.Description == null || meta?.Target == null) + throw new RPackException("Meta.json is incorrectly formatted."); + + Name = meta?.Name ?? string.Empty; + Desc = meta?.Description ?? string.Empty; + Target = meta?.Target ?? string.Empty; + } +} \ No newline at end of file diff --git a/Marsey/Game/ResourcePack/RessourceSwapper.cs b/Marsey/Game/ResourcePack/RessourceSwapper.cs new file mode 100644 index 0000000..45ef199 --- /dev/null +++ b/Marsey/Game/ResourcePack/RessourceSwapper.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using HarmonyLib; +using Marsey.Game.ResourcePack.Reflection; + +namespace Marsey.Game.ResourcePack; + +public static class ResourceSwapper +{ + private static List filepaths = []; + + public static void Start() + { + List RPacks = ResMan.GetRPacks(); + foreach (ResourcePack rpack in RPacks) + PopulateFiles(rpack.Dir); + } + + private static void PopulateFiles(string directory) + { + string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories); + foreach (string file in files) + { + if (file.EndsWith("meta.json")) continue; + string relativePath = file.Replace(directory + Path.DirectorySeparatorChar, ""); + filepaths.Add(relativePath); + } + } + + public static List ResourceFiles() => filepaths; +} \ No newline at end of file diff --git a/Marsey/Handbreak/Helpers.cs b/Marsey/Handbreak/Helpers.cs index a269075..f28e1eb 100644 --- a/Marsey/Handbreak/Helpers.cs +++ b/Marsey/Handbreak/Helpers.cs @@ -106,12 +106,4 @@ private static void LogPatchSuccess(HarmonyPatchType patchingType, string target { MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Handbreak", $"{patchingType}: Patched {targetMethodName} with {patchMethodName}."); } - - public static void HandleFail(string methodName, MethodInfo? method) - { - string message = $"Failed to patch {methodName} using {method?.Name}"; - if (MarseyConf.ThrowOnFail) - throw new HideseyException(message); - MarseyLogger.Log(MarseyLogger.LogType.FATL, message); - } } \ No newline at end of file diff --git a/Marsey/Handbreak/Manual.cs b/Marsey/Handbreak/Manual.cs index 06c1114..319cfae 100644 --- a/Marsey/Handbreak/Manual.cs +++ b/Marsey/Handbreak/Manual.cs @@ -44,12 +44,11 @@ public static bool Patch(MethodInfo? method, MethodInfo? patch, HarmonyPatchType catch (Exception e) { string message = $"Encountered an issue with patching {method?.Name} against {patch?.Name}!\n{e}"; + MarseyLogger.Log(MarseyLogger.LogType.ERRO, "HandBreak", message); if (MarseyConf.ThrowOnFail) throw new HandBreakException(message); - MarseyLogger.Log(MarseyLogger.LogType.ERRO, "HandBreak", message); - return false; } diff --git a/Marsey/MarseyPatcher.cs b/Marsey/MarseyPatcher.cs index d6655b8..f327a40 100644 --- a/Marsey/MarseyPatcher.cs +++ b/Marsey/MarseyPatcher.cs @@ -7,6 +7,7 @@ using Marsey.Game.Managers; using Marsey.Game.Misc; using Marsey.Game.Patches; +using Marsey.Game.ResourcePack; using Marsey.PatchAssembly; using Marsey.Patches; using Marsey.Stealthsey; @@ -79,7 +80,10 @@ public void Preload() // If set - Disable redialing and remote command execution Jammer.Patch(); Blackhole.Patch(); - + + // Prep Resource Manager + ResMan.Initialize(); + // Dump the game, if enabled if (MarseyConf.Dumper) Dumper.Start(); diff --git a/Marsey/Misc/Exceptions.cs b/Marsey/Misc/Exceptions.cs index 45c1e85..6f292a0 100644 --- a/Marsey/Misc/Exceptions.cs +++ b/Marsey/Misc/Exceptions.cs @@ -28,3 +28,14 @@ public override string ToString() return base.ToString(); } } + +public class RPackException : Exception +{ + public RPackException(string message) : base(message) {} + + public override string ToString() + { + MarseyLogger.Log(MarseyLogger.LogType.FATL, Message); + return base.ToString(); + } +} diff --git a/Marsey/Misc/FileHandler.cs b/Marsey/Misc/FileHandler.cs index ebf4c3f..9944bd5 100644 --- a/Marsey/Misc/FileHandler.cs +++ b/Marsey/Misc/FileHandler.cs @@ -1,6 +1,7 @@ using System.Reflection; using Marsey.Config; using Marsey.Game.Patches; +using Marsey.Game.ResourcePack; using Marsey.PatchAssembly; using Marsey.Patches; using Marsey.Serializer; @@ -16,29 +17,32 @@ public abstract class FileHandler { /// /// - /// Serialize enabled patches. + /// Serialize enabled mods. /// Executed by the launcher at connection. /// /// /// - /// We cant directly give marseys to the loader or tell it what patches to load because its started in a separate process. - /// Because of this we leave an array of paths to assemblies to enabled patches for the loader to read. + /// We cant directly give marseys to the loader or tell it what mods to load because its started in a separate process. + /// Because of this we leave an array of paths to assemblies to enabled mods for the loader to read. /// /// - public static void PrepAssemblies(string[]? path = null) + public static void PrepareMods(string[]? path = null) { - path ??= new[] { MarseyVars.MarseyPatchFolder }; + path ??= new[] { MarseyVars.MarseyFolder }; + string[] patchPath = new[] { MarseyVars.MarseyPatchFolder }; + string[] resPath = new[] { MarseyVars.MarseyResourceFolder }; List marseyPatches = Marsyfier.GetMarseyPatches(); List subverterPatches = Subverter.GetSubverterPatches(); + List resourcePacks = ResMan.GetRPacks(); // Serialize preloading MarseyPatches List preloadpaths = marseyPatches - .Where(p => p.Enabled && p.Preload) + .Where(p => p is { Enabled: true, Preload: true }) .Select(p => p.Asmpath) .ToList(); - Marserializer.Serialize(path, Marsyfier.PreloadMarserializerFile, preloadpaths); + Marserializer.Serialize(patchPath, Marsyfier.PreloadMarserializerFile, preloadpaths); // If we actually do have any - remove them from the marseypatch list if (preloadpaths.Count != 0) @@ -46,11 +50,15 @@ public static void PrepAssemblies(string[]? path = null) // Serialize remaining MarseyPatches List marseyAsmpaths = marseyPatches.Where(p => p.Enabled).Select(p => p.Asmpath).ToList(); - Marserializer.Serialize(path, Marsyfier.MarserializerFile, marseyAsmpaths); + Marserializer.Serialize(patchPath, Marsyfier.MarserializerFile, marseyAsmpaths); // Serialize SubverterPatches List subverterAsmpaths = subverterPatches.Where(p => p.Enabled).Select(p => p.Asmpath).ToList(); - Marserializer.Serialize(path, Subverter.MarserializerFile, subverterAsmpaths); + Marserializer.Serialize(patchPath, Subverter.MarserializerFile, subverterAsmpaths); + + // Serialize ResourcePacks + List rpackPaths = resourcePacks.Where(rp => rp.Enabled).Select(rp => rp.Dir).ToList(); + Marserializer.Serialize(resPath, ResMan.MarserializerFile, rpackPaths); } @@ -156,8 +164,27 @@ public static void SaveAssembly(string path, string name, Stream asmStream) /// public static void CheckRenameDirectory(string path) { - if (!Directory.Exists(path)) return; - string newPath = $"{path}_{DateTime.Now:yyyyMMddHHmmss}"; + // GetParent once shows itself, GetParent twice shows the actual parent + + if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) return; + + string dirName = Path.GetFileName(path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)); + string? parentDir = Directory.GetParent(Directory.GetParent(path)?.FullName ?? throw new InvalidOperationException())?.FullName; + MarseyLogger.Log(MarseyLogger.LogType.DEBG, "FileHandler", $"Parentdir is {parentDir}"); + + if (string.IsNullOrEmpty(dirName) || string.IsNullOrEmpty(parentDir)) return; + + string newPath = Path.Combine(parentDir, $"{dirName}{DateTime.Now:yyyyMMddHHmmss}"); + + if (Directory.Exists(newPath)) + { + MarseyLogger.Log(MarseyLogger.LogType.ERRO, "FileHandler", + $"Cannot move directory. Destination {newPath} already exists."); + return; + } + + MarseyLogger.Log(MarseyLogger.LogType.DEBG, "FileHandler", $"Trying to move {path} to {newPath}"); + // Completely evil, do not try-catch this - if it fails - it fails and kills everything. Directory.Move(path, newPath); } diff --git a/Marsey/Subversion/Subverse.cs b/Marsey/Subversion/Subverse.cs index 1813dee..995758f 100644 --- a/Marsey/Subversion/Subverse.cs +++ b/Marsey/Subversion/Subverse.cs @@ -24,6 +24,9 @@ public static class Subverse { private static List? _subverters = null; + /// + /// Check if we have any subversions enabled + /// public static bool CheckSubversions() { _subverters = Marserializer.Deserialize(new string[]{MarseyVars.MarseyPatchFolder}, Subverter.MarserializerFile); diff --git a/SS14.Launcher/LauncherPaths.cs b/SS14.Launcher/LauncherPaths.cs index d090712..bb11b00 100644 --- a/SS14.Launcher/LauncherPaths.cs +++ b/SS14.Launcher/LauncherPaths.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using Marsey.Config; namespace SS14.Launcher; @@ -14,12 +15,10 @@ public static class LauncherPaths public static readonly string EngineModulesDirName = "modules"; public static readonly string ServerContentDirName = "server content"; public static readonly string LogsDirName = "logs"; - public static readonly string MarseyPatchesDirName = "Marsey"; public static readonly string LauncherLogName = "launcher.log"; public static readonly string ClientMacLogName = "client.mac.log"; public static readonly string ClientStdoutLogName = "client.stdout.log"; public static readonly string ClientStderrLogName = "client.stderr.log"; - public static readonly string ClientStdmarseyLogName = "client.marsey.log"; public static readonly string DirLauncherInstall = GetInstallDir(); public static readonly string DirUserData = GetUserDataDir(); public static readonly string DirLocalData = GetLocalUserDataDir(); @@ -28,24 +27,30 @@ public static class LauncherPaths // Legacy server content directory. No longer used except to delete on launch. public static readonly string DirServerContent = Path.Combine(DirUserData, ServerContentDirName); public static readonly string DirLogs = Path.Combine(DirUserData, LogsDirName); - public static readonly string DirPatch = Path.Combine(DirLauncherInstall, MarseyPatchesDirName); public static readonly string PathLauncherLog = Path.Combine(DirLogs, LauncherLogName); public static readonly string PathClientMacLog = Path.Combine(DirLogs, ClientMacLogName); public static readonly string PathClientStdoutLog = Path.Combine(DirLogs, ClientStdoutLogName); public static readonly string PathClientStderrLog = Path.Combine(DirLogs, ClientStderrLogName); - public static readonly string PathClientStdmarseyLog = Path.Combine(DirLogs, ClientStdmarseyLogName); public static readonly string PathPublicKey = Path.Combine(DirLauncherInstall, "signing_key"); public static readonly string PathContentDb = Path.Combine(DirLocalData, "content.db"); public static readonly string PathOverrideAssetsDb = Path.Combine(DirLocalData, "override_assets.db"); + + // MarseyPaths + public static readonly string DirMarsey = Path.Combine(DirLauncherInstall, MarseyVars.MarseyFolder); + public static readonly string DirPatch = Path.Combine(DirLauncherInstall, MarseyVars.MarseyPatchFolder); + public static readonly string DirRPack = Path.Combine(DirLauncherInstall, MarseyVars.MarseyResourceFolder); + public static readonly string PathClientStdmarseyLog = Path.Combine(DirLogs, MarseyVars.MarseyLoggerFileName); public static void CreateDirs() { Ensure(DirLogs); Ensure(DirLocalData); - Ensure(DirPatch); Ensure(DirEngineInstallations); Ensure(DirModuleInstallations); + Ensure(DirMarsey); + Ensure(DirPatch); + Ensure(DirRPack); static void Ensure(string path) => Helpers.EnsureDirectoryExists(path); } diff --git a/SS14.Launcher/Models/Connector.cs b/SS14.Launcher/Models/Connector.cs index 41e39d6..368844e 100644 --- a/SS14.Launcher/Models/Connector.cs +++ b/SS14.Launcher/Models/Connector.cs @@ -569,7 +569,7 @@ private async Task GetLoaderStartInfo(string engineVersion, lo private void Marsify(ProcessStartInfo startInfo) { Log.Debug("Preparing patch assemblies."); - FileHandler.PrepAssemblies(); + FileHandler.PrepareMods(); ConfigureMarsey(startInfo); MarseyCleanup(); @@ -598,10 +598,11 @@ private void ConfigureMarsey(ProcessStartInfo startInfo) else startInfo.EnvironmentVariables["MARSEY_FORCEDHWID"] = _cfg.GetCVar(CVars.ForcedHWId); - // Dumper - if (!MarseyConf.Dumper) return; - startInfo.EnvironmentVariables["MARSEY_DUMP_ASSEMBLIES"] = "true"; - startInfo.EnvironmentVariables["MARSEY_DUMP_FORKID"] = _forkid; + // Resources + startInfo.EnvironmentVariables["MARSEY_FORKID"] = _forkid; + startInfo.EnvironmentVariables["MARSEY_DISABLE_STRICT"] = _cfg.GetCVar(CVars.DisableStrict) ? "true" : null; + if (MarseyConf.Dumper) + startInfo.EnvironmentVariables["MARSEY_DUMP_ASSEMBLIES"] = "true"; } private void MarseyCleanup() diff --git a/SS14.Launcher/Models/Data/CVars.cs b/SS14.Launcher/Models/Data/CVars.cs index 955aa87..08d4643 100644 --- a/SS14.Launcher/Models/Data/CVars.cs +++ b/SS14.Launcher/Models/Data/CVars.cs @@ -124,6 +124,11 @@ public static readonly CVarDef HasDismissedEarlyAccessWarning /// public static readonly CVarDef ThrowPatchFail = CVarDef.Create("ThrowPatchFail", false); + /// + /// Ignore target checks when using a resource pack + /// + public static readonly CVarDef DisableStrict = CVarDef.Create("DisableStrict", false); + /// /// Do we disable RPC? /// diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/OptionsTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/OptionsTabViewModel.cs index 0d1ab2a..0e17c4c 100644 --- a/SS14.Launcher/ViewModels/MainWindowTabs/OptionsTabViewModel.cs +++ b/SS14.Launcher/ViewModels/MainWindowTabs/OptionsTabViewModel.cs @@ -300,7 +300,15 @@ public bool DumpAssemblies set => MarseyConf.Dumper = value; } - + public bool ResourceOverride + { + get => Cfg.GetCVar(CVars.DisableStrict); + set + { + Cfg.SetCVar(CVars.DisableStrict, value); + Cfg.CommitConfig(); + } + } private void OnSetUsernameClick() { diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs index 7d3f511..3581a05 100644 --- a/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs +++ b/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs @@ -9,6 +9,7 @@ using Microsoft.Toolkit.Mvvm.Input; using Serilog; using Marsey.Config; +using Marsey.Game.ResourcePack; using Marsey.Patches; using Marsey.Subversion; using Marsey.Misc; @@ -20,24 +21,28 @@ public class PatchesTabViewModel : MainWindowTabViewModel public override string Name => "Plugins"; public ObservableCollection MarseyPatches { get; } = new ObservableCollection(); public ObservableCollection SubverterPatches { get; } = new ObservableCollection(); - + public ObservableCollection ResourcePacks { get; set; } = new ObservableCollection(); public ICommand OpenPatchDirectoryCommand { get; } public PatchesTabViewModel() { - OpenPatchDirectoryCommand = new RelayCommand(() => OpenPatchDirectory(MarseyVars.MarseyPatchFolder)); - LoadPatches(); + OpenPatchDirectoryCommand = new RelayCommand(() => OpenPatchDirectory(MarseyVars.MarseyFolder)); + ReloadMods(); } - private void LoadPatches() + private void ReloadMods() { + ClearList(); FileHandler.LoadAssemblies(); + ResMan.LoadDir(); List marseys = Marsyfier.GetMarseyPatches(); LoadPatchList(marseys, MarseyPatches, "marseypatches"); List subverters = Subverter.GetSubverterPatches(); LoadPatchList(subverters, SubverterPatches, "subverterpatches"); + + LoadResPacks(ResMan.GetRPacks()); } private void OpenPatchDirectory(string directoryName) @@ -58,6 +63,22 @@ private void LoadPatchList(List patches, ICollection patchList, string Log.Debug($"Refreshed {patchName}, got {patchList.Count}."); } + private void LoadResPacks(List ResPacks) + { + foreach (ResourcePack resource in ResPacks) + { + ResourcePacks.Add(resource); + } + + Log.Debug($"Refreshed resourcepacks, got {ResourcePacks.Count}."); + } + + private void ClearList() + { + ResourcePacks.Clear(); + SubverterPatches.Clear(); + MarseyPatches.Clear(); + } } } diff --git a/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml b/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml index 3277e1f..a21bbb1 100644 --- a/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml +++ b/SS14.Launcher/Views/MainWindowTabs/OptionsTabView.xaml @@ -144,7 +144,7 @@ Text="For when things stop making sense" Margin="8" /> - Separate game and patcher logs + Separate Game/Patcher Logs @@ -160,7 +160,13 @@ - Dump resources + + Resource Pack Strict Override + + + Dump Resources diff --git a/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml b/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml index 4dc3718..f333126 100644 --- a/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml +++ b/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml @@ -16,59 +16,94 @@ - - - - - -