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 RumbleReplay v1.1.3
Mods/RumbleReplayMod.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppRUMBLE.Players; using Il2CppRUMBLE.Players.Scaling; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Text; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using RumbleModdingAPI; using RumbleReplay; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(RumbleReplayModClass), "RumbleReplay", "1.1.3", "Blank", null)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: MelonAdditionalDependencies(new string[] { "RumbleModdingAPI" })] [assembly: MelonColor(255, 255, 170, 238)] [assembly: AssemblyTitle("RumbleReplay")] [assembly: AssemblyDescription("Generates Replay Files for use in blender or other supported programs")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RumbleReplay")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("7eebd5a9-aa24-4565-9bca-aad698946213")] [assembly: AssemblyFileVersion("1.1.3")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.1.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RumbleReplay { public static class BuildInfo { public const string Name = "RumbleReplay"; public const string Author = "Blank"; public const string Version = "1.1.3"; } public sealed class RumbleReplayModClass : MelonMod { public sealed class ReplayPlayerData { public string Name = "Unknown"; public int Battlepoints; public string PlayfabID = "Unknown"; public string Cosmetics = PlayerVisualData.DefaultFemale.ToPlayfabDataString(); } public sealed class ReplayHeader { public readonly string Version = "1.1.3"; public ReplayPlayerData LocalPlayer = new ReplayPlayerData(); public ReplayPlayerData RemotePlayer = new ReplayPlayerData(); public string Scene = "Unknown"; public readonly string Date = DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss"); } private readonly GameObject[] _poolObjects = (GameObject[])(object)new GameObject[8]; private readonly int[][] _cullers = new int[8][]; private readonly List<byte> _writebuffer = new List<byte>(); private MelonPreferences_Category _rumbleReplayPreferences; private MelonPreferences_Entry<int> _playerUpdateInterval; private MelonPreferences_Entry<int> _basicStructureUpdateInterval; private MelonPreferences_Entry<bool> _enabled; public bool Recording; public short FrameCounter; private string _currentScene; private FileStream _replayFile; private BinaryWriter _replayWriter; private static List<byte> SerializeTransform(Transform transform, bool includeRotation = true, bool includePosition = true, bool includeScale = false) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) List<byte> list = new List<byte>(); if (includePosition) { list.AddRange(BitConverter.GetBytes(transform.position.x)); list.AddRange(BitConverter.GetBytes(transform.position.y)); list.AddRange(BitConverter.GetBytes(transform.position.z)); } if (includeRotation) { list.AddRange(BitConverter.GetBytes(transform.rotation.w)); list.AddRange(BitConverter.GetBytes(transform.rotation.y)); list.AddRange(BitConverter.GetBytes(transform.rotation.x)); list.AddRange(BitConverter.GetBytes(transform.rotation.z)); } if (includeScale) { list.AddRange(BitConverter.GetBytes(transform.localScale.x)); list.AddRange(BitConverter.GetBytes(transform.localScale.y)); list.AddRange(BitConverter.GetBytes(transform.localScale.z)); } return list; } public void NewReplay(string scene, ReplayPlayerData localPlayer, ReplayPlayerData remotePlayer) { if (_enabled.Value) { ReplayHeader replayHeader = new ReplayHeader { LocalPlayer = localPlayer, RemotePlayer = remotePlayer, Scene = scene }; string text = JsonConvert.SerializeObject((object)replayHeader); if (_replayFile != null) { StopReplay(); } ((MelonBase)this).LoggerInstance.Msg("Recording Started"); if (!Directory.Exists("UserData/Replays")) { Directory.CreateDirectory("UserData/Replays"); } _replayFile = File.Create("UserData/Replays/" + localPlayer.Name + "-Vs-" + remotePlayer.Name + " On " + scene + "-" + Path.GetRandomFileName() + ".rr"); _replayWriter = new BinaryWriter(_replayFile); byte[] buffer = new byte[2] { 82, 82 }; _replayWriter.Write(buffer); _replayWriter.Write((short)text.Length); _replayWriter.Write(Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)Encoding.UTF8.GetBytes(text))); Recording = true; } } public void StopReplay() { if (_replayFile == null) { ((MelonBase)this).LoggerInstance.Warning("StopReplay with null replay file"); return; } _replayWriter.Write(_writebuffer.ToArray()); _writebuffer.Clear(); Recording = false; FrameCounter = 0; ((MelonBase)this).LoggerInstance.Msg("Recording Stopped"); _replayFile.Close(); _replayFile = null; _replayWriter = null; } public override void OnLateInitializeMelon() { Calls.onMapInitialized += MapReady; } public override void OnInitializeMelon() { _rumbleReplayPreferences = MelonPreferences.CreateCategory("RumbleReplaySettings"); _rumbleReplayPreferences.SetFilePath("UserData/RumbleReplay.cfg"); _playerUpdateInterval = _rumbleReplayPreferences.CreateEntry<int>("PlayerUpdate_Interval", 4, (string)null, "The interval we create updates for the players Hands and Head", false, false, (ValueValidator)null, (string)null); _basicStructureUpdateInterval = _rumbleReplayPreferences.CreateEntry<int>("BasicStructureUpdate_Interval", 1, (string)null, "the interval structure positions and rotations are updated (Leave at 1 for 1 update every physics frame, 2 for one update every 2 and so on)", false, false, (ValueValidator)null, (string)null); _enabled = _rumbleReplayPreferences.CreateEntry<bool>("RecordingEnabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _rumbleReplayPreferences.SaveToFile(true); ((MelonBase)this).LoggerInstance.Msg($"PlayerUpdate_Interval={_playerUpdateInterval.Value}"); ((MelonBase)this).LoggerInstance.Msg($"BasicStructureUpdate_Interval={_basicStructureUpdateInterval.Value}"); ((MelonBase)this).LoggerInstance.Msg($"Enabled {_enabled.Value}"); } public override void OnSceneWasLoaded(int _, string sceneName) { if (Recording) { StopReplay(); } _currentScene = sceneName; } private void MapReady() { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (!(_currentScene != "Loader") || !(_currentScene != "Park") || !(_currentScene != "Gym")) { return; } ((MelonBase)this).LoggerInstance.Msg("Loaded scene: " + _currentScene); _poolObjects[0] = Structures.GetPoolBall(); _poolObjects[1] = Structures.GetPoolBoulderBall(); _poolObjects[2] = Structures.GetPoolCube(); _poolObjects[3] = Structures.GetPoolDisc(); _poolObjects[4] = Structures.GetPoolLargeRock(); _poolObjects[5] = Structures.GetPoolPillar(); _poolObjects[6] = Structures.GetPoolWall(); _poolObjects[7] = Structures.GetPoolSmallRock(); for (ushort num = 0; num < _poolObjects.Length; num++) { GameObject val = _poolObjects[num]; _cullers[num] = new int[val.transform.GetChildCount()]; ((MelonBase)this).LoggerInstance.Msg((object)_cullers[num].Length); ((MelonBase)this).LoggerInstance.Msg(((Object)val.transform.GetChild(0)).name); for (ushort num2 = 0; num2 < val.transform.GetChildCount(); num2++) { GameObject gameObject = ((Component)val.transform.GetChild((int)num2)).gameObject; int[] obj = _cullers[num]; ushort num3 = num2; Vector3 position = gameObject.transform.position; obj[num3] = ((object)(Vector3)(ref position)).GetHashCode(); } } ReplayPlayerData replayPlayerData = new ReplayPlayerData(); Player localPlayer = Managers.GetPlayerManager().LocalPlayer; replayPlayerData.Name = Regex.Replace(((localPlayer != null) ? localPlayer.Data.GeneralData.PublicUsername : null) ?? "Unknown", "<.*?>|[^a-zA-Z0-9_ ]", ""); Player localPlayer2 = Managers.GetPlayerManager().LocalPlayer; replayPlayerData.Battlepoints = ((localPlayer2 != null) ? localPlayer2.Data.GeneralData.BattlePoints : 0); Player localPlayer3 = Managers.GetPlayerManager().LocalPlayer; replayPlayerData.PlayfabID = ((localPlayer3 != null) ? localPlayer3.Data.GeneralData.PlayFabMasterId : null) ?? "Unknown"; Player localPlayer4 = Managers.GetPlayerManager().LocalPlayer; replayPlayerData.Cosmetics = ((localPlayer4 != null) ? localPlayer4.Data.VisualData.ToPlayfabDataString() : null) ?? PlayerVisualData.DefaultFemale.ToPlayfabDataString(); ReplayPlayerData replayPlayerData2 = replayPlayerData; ReplayPlayerData replayPlayerData3 = new ReplayPlayerData(); Player? obj2 = Players.GetEnemyPlayers().FirstOrDefault(); replayPlayerData3.Name = Regex.Replace(((obj2 != null) ? obj2.Data.GeneralData.PublicUsername : null) ?? "Unknown", "<.*?>|[^a-zA-Z0-9_ ]", ""); Player? obj3 = Players.GetEnemyPlayers().FirstOrDefault(); replayPlayerData3.Battlepoints = ((obj3 != null) ? obj3.Data.GeneralData.BattlePoints : 0); Player? obj4 = Players.GetEnemyPlayers().FirstOrDefault(); replayPlayerData3.PlayfabID = ((obj4 != null) ? obj4.Data.GeneralData.PlayFabMasterId : null) ?? "Unknown"; Player? obj5 = Players.GetEnemyPlayers().FirstOrDefault(); replayPlayerData3.Cosmetics = ((obj5 != null) ? obj5.Data.VisualData.ToPlayfabDataString() : null) ?? PlayerVisualData.DefaultFemale.ToPlayfabDataString(); ReplayPlayerData replayPlayerData4 = replayPlayerData3; ((MelonBase)this).LoggerInstance.Msg(replayPlayerData2.Name); ((MelonBase)this).LoggerInstance.Msg(replayPlayerData4.Name); NewReplay(_currentScene, replayPlayerData2, replayPlayerData4); } public override void OnApplicationQuit() { if (Recording) { StopReplay(); } } private static List<byte> _createPlayerUpdate() { int num = 0; List<byte> list = new List<byte>(); Enumerator<Player> enumerator = Managers.GetPlayerManager().AllPlayers.GetEnumerator(); while (enumerator.MoveNext()) { Player current = enumerator.Current; RigDefinition val = ((current != null) ? ((Component)current.Controller).GetComponentInChildren<RigDefinition>() : null); Transform transform = val.headDefinition.Transform; Transform transform2 = val.spineDefinition.Transform; Transform transform3 = val.leftHandDefinition.Transform; Transform transform4 = val.rightHandDefinition.Transform; Transform transform5 = val.leftFootDefinition.Transform; Transform transform6 = val.rightFootDefinition.Transform; list.Add((byte)num); list.AddRange(SerializeTransform(transform)); list.AddRange(SerializeTransform(transform2)); list.AddRange(SerializeTransform(transform3)); list.AddRange(SerializeTransform(transform4)); list.AddRange(SerializeTransform(transform5)); list.AddRange(SerializeTransform(transform6)); num++; } return list; } private List<byte> _createBasicStructureUpdate() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) List<byte> list = new List<byte>(); for (ushort num = 0; num < _poolObjects.Length; num++) { GameObject val = _poolObjects[num]; for (ushort num2 = 0; num2 < _cullers[num].Length; num2++) { GameObject gameObject = ((Component)val.transform.GetChild((int)num2)).gameObject; int num3 = _cullers[num][num2]; Vector3 position = gameObject.transform.position; if (num3 != ((object)(Vector3)(ref position)).GetHashCode()) { int[] obj = _cullers[num]; ushort num4 = num2; position = gameObject.transform.position; obj[num4] = ((object)(Vector3)(ref position)).GetHashCode(); list.Add((byte)num); list.Add((byte)num2); Transform transform = gameObject.transform; if (!gameObject.active) { transform.position = new Vector3(0f, -300f, 0f); } list.AddRange(SerializeTransform(transform)); } } } return list; } public override void OnFixedUpdate() { if (Recording) { List<byte> list = new List<byte>(); if (FrameCounter % _playerUpdateInterval.Value == 0) { list.AddRange(_createPlayerUpdate()); } List<byte> list2 = new List<byte>(); if (FrameCounter % _basicStructureUpdateInterval.Value == 0) { list2.AddRange(_createBasicStructureUpdate()); } if (list2.Count != 0) { _writebuffer.AddRange(BitConverter.GetBytes((short)list2.Count)); _writebuffer.AddRange(BitConverter.GetBytes(FrameCounter)); _writebuffer.Add(0); _writebuffer.AddRange(list2); } if (list.Count != 0) { _writebuffer.AddRange(BitConverter.GetBytes((short)list.Count)); _writebuffer.AddRange(BitConverter.GetBytes(FrameCounter)); _writebuffer.Add(2); _writebuffer.AddRange(list); } FrameCounter++; if (_writebuffer.Count >= 1000) { _replayWriter.Write(_writebuffer.ToArray()); _writebuffer.Clear(); } } } } }