From 2b5c8b8e0dee4efcdf2446a6eba77d8d7c3db24e Mon Sep 17 00:00:00 2001 From: Mary Date: Tue, 26 Dec 2023 22:35:12 +0200 Subject: [PATCH 1/2] Integrate subversion, entrypoint support for subversions --- Marsey/MarseyPatcher.cs | 12 +- Marsey/Misc/FileHandler.cs | 5 +- Marsey/PatchAssembly/AssemblyFieldHandler.cs | 2 +- Marsey/PatchAssembly/AssemblyInitializer.cs | 4 - Marsey/Subversion/Subverse.cs | 134 +++++++----------- Marsey/Subversion/Subverter.cs | 6 - .../MainWindowTabs/PatchesTabViewModel.cs | 26 ---- .../ViewModels/MainWindowViewModel.cs | 1 - .../Views/MainWindowTabs/PatchesTabView.xaml | 3 +- 9 files changed, 56 insertions(+), 137 deletions(-) diff --git a/Marsey/MarseyPatcher.cs b/Marsey/MarseyPatcher.cs index a8483a1..b6099f6 100644 --- a/Marsey/MarseyPatcher.cs +++ b/Marsey/MarseyPatcher.cs @@ -41,7 +41,8 @@ public static void CreateInstance(Assembly? robClientAssembly) _instance = new MarseyPatcher(robClientAssembly); } - + + /// Excepts if Robust.Client assembly is null private MarseyPatcher(Assembly? robClientAssembly) { if (robClientAssembly == null) throw new Exception("Robust.Client was null."); @@ -62,18 +63,13 @@ private MarseyPatcher(Assembly? robClientAssembly) /// /// Executed by the loader. /// - /// Excepts if Robust.Client assembly is null public void Boot() { // Preload marseypatches, if available Marsyfier.Preload(); - // Initialize subverter if enabled and present - if (MarseyVars.Subverter && Subverse.InitSubverter()) - { - // Side-load custom code - Subverse.PatchSubverter(); - } + // Side-load custom code + Subverse.PatchSubverter(); // Manage game assemblies GameAssemblyManager.GetGameAssemblies(out Assembly? clientAss, out Assembly? robustSharedAss, out Assembly? clientSharedAss); diff --git a/Marsey/Misc/FileHandler.cs b/Marsey/Misc/FileHandler.cs index 858e4c3..91483a1 100644 --- a/Marsey/Misc/FileHandler.cs +++ b/Marsey/Misc/FileHandler.cs @@ -97,10 +97,7 @@ public static void LoadExactAssembly(string file) } catch (FileNotFoundException) { - if (!file.EndsWith(Subverse.SubverterFile)) - { - MarseyLogger.Log(MarseyLogger.LogType.DEBG, $"{file} could not be found"); - } + MarseyLogger.Log(MarseyLogger.LogType.DEBG, $"{file} could not be found"); } catch (PatchAssemblyException ex) { diff --git a/Marsey/PatchAssembly/AssemblyFieldHandler.cs b/Marsey/PatchAssembly/AssemblyFieldHandler.cs index 84eac60..57081a7 100644 --- a/Marsey/PatchAssembly/AssemblyFieldHandler.cs +++ b/Marsey/PatchAssembly/AssemblyFieldHandler.cs @@ -174,7 +174,7 @@ private static void SetupLogger(Assembly patch) /// /// Get methodhandle for the entrypoint function in patch /// - private static MethodInfo? GetEntry(Assembly patch, Type entryType) + public static MethodInfo? GetEntry(Assembly patch, Type entryType) { MethodInfo? entry = entryType.GetMethod("Entry", BindingFlags.Public | BindingFlags.Static); return entry; diff --git a/Marsey/PatchAssembly/AssemblyInitializer.cs b/Marsey/PatchAssembly/AssemblyInitializer.cs index 40c4816..30dd353 100644 --- a/Marsey/PatchAssembly/AssemblyInitializer.cs +++ b/Marsey/PatchAssembly/AssemblyInitializer.cs @@ -94,10 +94,6 @@ private static void ProcessDataType(Assembly assembly, Type dataType) break; } - case "SubverterPatch" when Subverse.CheckSubverterPresent() && Subverse.CheckSubverterDuplicate(assembly): - MarseyLogger.Log(MarseyLogger.LogType.FATL, - $"{Path.GetFileName(assembly.Location)}: Tried to create a SubverterPatch with the same assembly as Subverter!"); - return; } AssemblyFieldHandler.GetFields(dataType, out string name, out string description); diff --git a/Marsey/Subversion/Subverse.cs b/Marsey/Subversion/Subverse.cs index 56d3dba..5c528b1 100644 --- a/Marsey/Subversion/Subverse.cs +++ b/Marsey/Subversion/Subverse.cs @@ -3,10 +3,14 @@ using System.IO; using System.Linq; using System.Reflection; +using HarmonyLib; using Marsey.Config; using Marsey.GameAssembly; +using Marsey.Handbrake; using Marsey.Stealthsey; using Marsey.Misc; +using Marsey.PatchAssembly; +using Marsey.Serializer; using Marsey.Stealthsey.Reflection; namespace Marsey.Subversion; @@ -17,63 +21,6 @@ namespace Marsey.Subversion; /// public static class Subverse { - public static string SubverterFile = "Subverter.dll"; - private static SubverterPatch? _subverter = null; - - /// - /// Initializes the subverter library. - /// - /// True if the library was initialized successfully. - public static bool InitSubverter() - { - string path = Path.Combine(Directory.GetCurrentDirectory(), SubverterFile); - FileHandler.LoadExactAssembly(path); - - List patches = Subverter.GetSubverterPatches(); - SubverterPatch? subverterPatch = patches.FirstOrDefault(p => p.Name == "Subverter"); - - if (subverterPatch == null) return false; - - AssignSubverter(subverterPatch); - SetHidesey(); - patches.Clear(); - - return true; - } - - private static void SetHidesey() - { - if (_subverter == null) return; - - Type? subverterPatchType = _subverter.Asm.GetType("SubverterPatch"); - MethodInfo? hideMethod = typeof(Subverter).GetMethod("Hide", BindingFlags.NonPublic | BindingFlags.Static); - FieldInfo? hideDelegateField = subverterPatchType?.GetField("hideDelegate", BindingFlags.Public | BindingFlags.Static); - - if (subverterPatchType == null || hideMethod == null || hideDelegateField == null) - { - List missingComps = new List(); - if (subverterPatchType == null) missingComps.Add("subverterPatchType"); - if (hideMethod == null) missingComps.Add("hideMethod"); - if (hideDelegateField == null) missingComps.Add("hideDelegateField"); - - string missingCompStr = string.Join(", ", missingComps); - - MarseyLogger.Log(MarseyLogger.LogType.FATL, $"Failed to connect patch to subverter. Missing components: {missingCompStr}."); - return; - } - - try - { - Delegate logDelegate = Delegate.CreateDelegate(hideDelegateField.FieldType, hideMethod); - hideDelegateField.SetValue(null, logDelegate); - } - catch (Exception e) - { - MarseyLogger.Log(MarseyLogger.LogType.FATL, $"Failed to to assign hide delegate: {e.Message}"); - } - } - - /// /// Enables subverter if any of the of the subverter patches are enabled /// Used by the launcher to determine if it should load subversions @@ -91,44 +38,61 @@ public static void CheckEnabled() MarseyVars.Subverter = false; } - + /// - /// Check if a patch is loaded from the same place subverter is + /// Patches subverter ahead of everything else + /// This is done as we attach to the assembly loading function /// - /// - public static bool CheckSubverterDuplicate(SubverterPatch subverter) - { - if (CheckSubverterPresent()) - return CheckSubverterDuplicate(subverter.Asm); - - return false; - } - - public static bool CheckSubverterDuplicate(Assembly assembly) + public static void PatchSubverter() { - return assembly == _subverter?.Asm; + MethodInfo Target = AccessTools.Method(AccessTools.TypeByName("Robust.Shared.ContentPack.ModLoader"), "TryLoadModules"); + MethodInfo Prefix = typeof(Subverse).GetMethod("Prefix", BindingFlags.NonPublic | BindingFlags.Static)!; + + MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Subversion", $"Hooking {Target.Name} with {Prefix.Name}"); + + Manual.Patch(Target, Prefix, HarmonyPatchType.Prefix); } - /// - /// Check if subverter is already defined. - /// Used by the launcher in the plugins/patches tab. - /// - public static bool CheckSubverterPresent() + private static bool Prefix(object __instance) { - return _subverter != null; + MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Subversion", "Detour"); + MethodInfo? loadGameAssemblyMethod = AccessTools.Method(AccessTools.TypeByName("Robust.Shared.ContentPack.BaseModLoader"), "InitMod"); + + foreach (string path in GetSubverters()) + { + Assembly subverterAssembly = Assembly.LoadFrom(path); + MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Subversion", $"Sideloading {path}"); + loadGameAssemblyMethod.Invoke(__instance, new object[] { subverterAssembly }); + + MethodInfo? Entry = CheckEntry(subverterAssembly); + if (Entry != null) + Doorbreak.Enter(Entry); + + Hidesey.HidePatch(subverterAssembly); + } + + return true; } - /// - /// Patches subverter ahead of everything else - /// This is done as we attach to the assembly loading function - /// - public static void PatchSubverter() + private static IEnumerable GetSubverters() { - if (_subverter != null) GamePatcher.Patch(new List() { _subverter }); + string directoryPath = Path.Combine(Directory.GetCurrentDirectory(), "Marsey"); + MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Subversion", $"Loading from {directoryPath}"); + + List patches = Marserializer.Deserialize(new string[] { directoryPath }, Subverter.MarserializerFile) ?? new List(); + + foreach (string filePath in patches) + { + yield return filePath; + } } - - private static void AssignSubverter(SubverterPatch subverter) + + private static MethodInfo? CheckEntry(Assembly assembly) { - _subverter = subverter; + Type? entryType = assembly.GetType("MarseyEntry"); + if (entryType == null) return null; + + MethodInfo? entryMethod = AssemblyFieldHandler.GetEntry(assembly, entryType); + return entryMethod != null ? entryMethod : null; } } \ No newline at end of file diff --git a/Marsey/Subversion/Subverter.cs b/Marsey/Subversion/Subverter.cs index 2fc84f9..f64f8b2 100644 --- a/Marsey/Subversion/Subverter.cs +++ b/Marsey/Subversion/Subverter.cs @@ -44,11 +44,5 @@ public SubverterPatch(string asmpath, Assembly asm, string name, string desc) Name = name; Desc = desc; Asm = asm; - - if (Subverse.CheckSubverterDuplicate(this)) - { - throw new PatchAssemblyException( - "Tried to create a SubverterPatch that is the same as Subverter! Remove Subverter.dll from the patches folder!"); - } } } \ No newline at end of file diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs index cba3641..7d3f511 100644 --- a/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs +++ b/SS14.Launcher/ViewModels/MainWindowTabs/PatchesTabViewModel.cs @@ -18,7 +18,6 @@ namespace SS14.Launcher.ViewModels.MainWindowTabs public class PatchesTabViewModel : MainWindowTabViewModel { public override string Name => "Plugins"; - public bool SubverterPresent { get; set; } public ObservableCollection MarseyPatches { get; } = new ObservableCollection(); public ObservableCollection SubverterPatches { get; } = new ObservableCollection(); @@ -26,7 +25,6 @@ public class PatchesTabViewModel : MainWindowTabViewModel public PatchesTabViewModel() { - SubverterPresent = Subverse.CheckSubverterPresent(); OpenPatchDirectoryCommand = new RelayCommand(() => OpenPatchDirectory(MarseyVars.MarseyPatchFolder)); LoadPatches(); } @@ -38,8 +36,6 @@ private void LoadPatches() List marseys = Marsyfier.GetMarseyPatches(); LoadPatchList(marseys, MarseyPatches, "marseypatches"); - if (!SubverterPresent) return; - List subverters = Subverter.GetSubverterPatches(); LoadPatchList(subverters, SubverterPatches, "subverterpatches"); } @@ -79,28 +75,6 @@ public class PathToFileNameConverter : IValueConverter } } -public class BooleanToVisibilityConverter : IValueConverter -{ - public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value is bool booleanValue) - { - return booleanValue; - } - throw new InvalidOperationException("Invalid boolean value"); - } - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value == null) throw new ArgumentNullException(nameof(value)); - if (value is bool visibilityValue) - { - return visibilityValue; - } - throw new InvalidOperationException("Invalid visibility value"); - } -} - public class BooleanToPreloadConverter : IValueConverter { public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) diff --git a/SS14.Launcher/ViewModels/MainWindowViewModel.cs b/SS14.Launcher/ViewModels/MainWindowViewModel.cs index fdc8b0a..b400960 100644 --- a/SS14.Launcher/ViewModels/MainWindowViewModel.cs +++ b/SS14.Launcher/ViewModels/MainWindowViewModel.cs @@ -53,7 +53,6 @@ public MainWindowViewModel() HarmonyManager.Init(new Harmony(MarseyVars.Identifier)); Hidesey.Initialize(); - Subverse.InitSubverter(); ServersTab = new ServerListTabViewModel(this); NewsTab = new NewsTabViewModel(); diff --git a/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml b/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml index df675fc..4dc3718 100644 --- a/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml +++ b/SS14.Launcher/Views/MainWindowTabs/PatchesTabView.xaml @@ -8,7 +8,6 @@ x:Class="SS14.Launcher.Views.MainWindowTabs.PatchesTabView" Name="PatchesTab"> - @@ -46,7 +45,7 @@ - + From f23f0f349d4d0e5392722555a1e6f38944abec97 Mon Sep 17 00:00:00 2001 From: Mary Date: Tue, 26 Dec 2023 22:39:21 +0200 Subject: [PATCH 2/2] Update readme to fit reality --- Readme.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Readme.md b/Readme.md index 6c11d18..beee4cb 100644 --- a/Readme.md +++ b/Readme.md @@ -10,13 +10,17 @@ Space Station 14 launcher with client-side modding/patching support. * **Integration with the Harmony patching library.** * * Full functionality regarding methods in client/shared content/engine assemblies. -* * Sideloading custom code using [Subverter](https://github.com/Subversionary/Subverter) +* * Sideloading custom code as part of the game * * Win/Mac/Linux support * * No injectors used, entirely based on reflection * * Patches are hidden from game * Enabled multiaccount +* Privacy changes * * Tokens are updated only on connect or account switch to evade alt detection -* Locally change username for screenshots (This doesn't change your username in-game) +* * HWId spoofing +* * Forcibly disable Discord RPC +* * Wizden hub mirror set as default hub +* * Locally change username for screenshots (This doesn't change your username in-game) * Marsey. ### Contributing @@ -36,20 +40,14 @@ Marseyloader uses the [Harmony](https://github.com/pardeike/Harmony) patching li Example patches can be found in the [ExampleMarseyPatch](https://github.com/ValidHunters/ExampleMarseyPatch) repository. -Additionally, custom code can be loaded to the game using the [Subverter](https://github.com/Subversionary/Subverter) helper patch. - ### FAQ #### Where do I ask for help? - Github issues or on the [discord server](https://discord.gg/5RjbK7EzEm). #### How do I make a patch? [Example Marseypatches](https://github.com/ValidHunters/ExampleMarseyPatch) -#### How do I enable subversion? -Compile [Subverter](https://github.com/Subversionary/Subverter), put "Subverter.dll" in the directory with the executable. - #### What is subversion for? Subversion is used for adding your custom code (and not patching existing code) to the game, like custom commands and what not that can fully interact with the game as if they were part of the original code.