RUMBLE does not support other mod managers. If you want to use a manager, you must use the RUMBLE Mod Manager, a manager specifically designed for this game.
Decompiled source of LinuxControllerFix v1.0.0
Plugins/LinuxControllerFix.dll
Decompiled 2 months agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using LinuxControllerFix; using MelonLoader; using MelonLoader.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "LinuxControllerFix", "1.0.0", "Supercopia", null)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: MelonColor(255, 100, 200, 100)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("LinuxControllerFix")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+fe3de839b1893d4f3390067b933aa70958589a4e")] [assembly: AssemblyProduct("LinuxControllerFix")] [assembly: AssemblyTitle("LinuxControllerFix")] [assembly: AssemblyVersion("1.0.0.0")] namespace LinuxControllerFix; public class Core : MelonPlugin { private const string TargetExtension = "XR_META_touch_controller_plus"; private const string PatchedExtension = "AR_META_touch_controller_plus"; private string _assetsPath; private long _patchOffset = -1L; private bool _patched; public override void OnPreInitialization() { _assetsPath = FindAssetsFile(); if (_assetsPath == null) { ((MelonBase)this).LoggerInstance.Warning("Could not find globalgamemanagers.assets — skipping patch."); return; } _patchOffset = FindStringOffset(_assetsPath, "XR_META_touch_controller_plus"); if (_patchOffset >= 0) { PatchByte(_assetsPath, _patchOffset, 65); _patched = true; ((MelonBase)this).LoggerInstance.Msg($"Patched {"XR_META_touch_controller_plus"} at offset {_patchOffset} (X -> A)."); } else { long num = FindStringOffset(_assetsPath, "AR_META_touch_controller_plus"); if (num >= 0) { _patchOffset = num; _patched = true; ((MelonBase)this).LoggerInstance.Msg("Extension already patched from a previous run — will restore on exit."); } else { ((MelonBase)this).LoggerInstance.Msg("XR_META_touch_controller_plus not found in assets — nothing to patch."); } } } public override void OnApplicationQuit() { RestorePatch(); } public override void OnDeinitializeMelon() { RestorePatch(); } private void RestorePatch() { if (!_patched || _patchOffset < 0) { return; } try { PatchByte(_assetsPath, _patchOffset, 88); ((MelonBase)this).LoggerInstance.Msg($"Restored {"XR_META_touch_controller_plus"} at offset {_patchOffset} (A -> X)."); _patched = false; } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Failed to restore patch: " + ex.Message); } } private static string FindAssetsFile() { string text = Path.Combine(MelonEnvironment.GameRootDirectory, "RUMBLE_Data", "globalgamemanagers.assets"); if (File.Exists(text)) { return text; } text = Path.Combine("RUMBLE_Data", "globalgamemanagers.assets"); if (File.Exists(text)) { return text; } return null; } private static long FindStringOffset(string filePath, string target) { byte[] bytes = Encoding.ASCII.GetBytes(target); byte[] array = new byte[65536]; int num = bytes.Length; using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); long length = fileStream.Length; int num3; int num4; for (long num2 = 0L; num2 < length; num2 += num4 - ((num2 > 0) ? num3 : 0)) { num3 = ((num2 > 0) ? (num - 1) : 0); if (num3 > 0) { fileStream.Position = num2 - num3; } else { fileStream.Position = num2; } num4 = fileStream.Read(array, 0, array.Length); if (num4 == 0) { break; } int num5 = ((num2 > 0) ? num3 : 0); for (int i = num5; i <= num4 - num; i++) { bool flag = true; for (int j = 0; j < num; j++) { if (array[i + j] != bytes[j]) { flag = false; break; } } if (flag) { return ((num2 > 0) ? (num2 - num3) : 0) + i; } } } return -1L; } private static void PatchByte(string filePath, long offset, byte value) { using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite); fileStream.Position = offset; fileStream.WriteByte(value); } }