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 RumbleReShaded v1.1.0
Mods/RumbleReShaded.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.Json; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppRUMBLE.MoveSystem; using Il2CppSystem; using Il2CppSystem.IO; using Il2CppSystem.Reflection; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using RumbleReShaded; using RumbleReShaded.Api; using UIFramework; using UIFramework.UiExtensions; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.RenderGraphModule.Util; using UnityEngine.Rendering.RendererUtils; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; using UnityEngine.XR; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(RumbleReShadedMod), "RumbleReShaded", "1.2.0-dev.1", "Pepuldo", null)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: MelonAdditionalDependencies(new string[] { "UIFramework" })] [assembly: AssemblyTitle("RumbleReShaded")] [assembly: AssemblyDescription("Loads community shader packs and applies them as VR-safe post effects")] [assembly: AssemblyProduct("RumbleReShaded")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: ComVisible(false)] [assembly: Guid("9d54c1aa-3e87-4f60-92cb-7b18e5a0d427")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("1.2.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 RumbleReShaded { internal static class CategoryRecolor { private sealed class CategoryPass { public uint Bit; public string Name; public MelonPreferences_Entry<bool> Enabled; public MelonPreferences_Entry<float> Red; public MelonPreferences_Entry<float> Green; public MelonPreferences_Entry<float> Blue; public RenderObjectsPass Pass; public Material Material; public float Dr; public float Dg; public float Db; public RenderQueueType Queue; } private static readonly List<CategoryPass> passes = new List<CategoryPass>(); private static bool failed; public static RenderPassEvent PassEvent = (RenderPassEvent)302; public static bool ForceAllForSandwich; public static bool MaskColours; private static readonly string[] ShaderTags = new string[4] { "UniversalForward", "UniversalForwardOnly", "SRPDefaultUnlit", "LightweightForward" }; private static Color MaskColourFor(uint bit) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) return (Color)(bit switch { 32u => new Color(1f, 0f, 0f, 1f), 16u => new Color(0f, 1f, 0f, 1f), 8u => new Color(0f, 0f, 1f, 1f), 64u => new Color(1f, 1f, 0f, 1f), _ => new Color(0f, 0f, 0f, 1f), }); } public static void BuildSettings(MelonPreferences_Category cat) { Add(cat, 32u, "Map", 0f, 0f, 0f, (RenderQueueType)0); Add(cat, 16u, "Players", 0.5f, 0.5f, 0.5f, (RenderQueueType)0); Add(cat, 8u, "Structures", 1f, 1f, 1f, (RenderQueueType)0); Add(cat, 64u, "Effects", 1f, 0f, 1f, (RenderQueueType)1); } private static void Add(MelonPreferences_Category cat, uint bit, string name, float r, float g, float b, RenderQueueType queue = (RenderQueueType)0) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown CategoryPass categoryPass = new CategoryPass { Bit = bit, Name = name, Queue = queue, Dr = r, Dg = g, Db = b }; categoryPass.Enabled = cat.CreateEntry<bool>("Recolor" + name, false, "Recolour " + name, "Draw all " + name.ToLowerInvariant() + " geometry in a flat colour. Requires 'Tag renderer categories' first.", false, false, (ValueValidator)null, (string)null); categoryPass.Red = cat.CreateEntry<float>("Recolor" + name + "R", r, name + " red", "Red 0-1", false, false, (ValueValidator)new SliderDescriptor { Min = 0f, Max = 1f, DecimalPlaces = 2 }); categoryPass.Green = cat.CreateEntry<float>("Recolor" + name + "G", g, name + " green", "Green 0-1", false, false, (ValueValidator)new SliderDescriptor { Min = 0f, Max = 1f, DecimalPlaces = 2 }); categoryPass.Blue = cat.CreateEntry<float>("Recolor" + name + "B", b, name + " blue", "Blue 0-1", false, false, (ValueValidator)new SliderDescriptor { Min = 0f, Max = 1f, DecimalPlaces = 2 }); passes.Add(categoryPass); } public static void BuildDebugPasses() { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected I4, but got Unknown if (passes.Count <= 0) { AddDebug(32u, "Map", 0f, 0f, 0f, (RenderQueueType)0); AddDebug(16u, "Players", 0.5f, 0.5f, 0.5f, (RenderQueueType)0); AddDebug(8u, "Structures", 1f, 1f, 1f, (RenderQueueType)0); AddDebug(64u, "Effects", 1f, 0f, 1f, (RenderQueueType)1); MelonLogger.Msg($"[diag] Category recolour: built {passes.Count} menu-less category passes for sandwich step 2, at event {(int)PassEvent}."); } } private static void AddDebug(uint bit, string name, float r, float g, float b, RenderQueueType queue = (RenderQueueType)0) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) passes.Add(new CategoryPass { Bit = bit, Name = name, Queue = queue, Dr = r, Dg = g, Db = b }); } public static bool AnyEnabled() { foreach (CategoryPass pass in passes) { if (pass.Enabled != null && pass.Enabled.Value) { return true; } } return false; } public static void Enqueue(ScriptableRenderer renderer) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (failed || renderer == null) { return; } try { foreach (CategoryPass pass in passes) { if ((ForceAllForSandwich || (pass.Enabled != null && pass.Enabled.Value)) && EnsureBuilt(pass)) { pass.Material.color = (Color)(MaskColours ? MaskColourFor(pass.Bit) : ((pass.Enabled != null) ? new Color(pass.Red.Value, pass.Green.Value, pass.Blue.Value, 1f) : new Color(pass.Dr, pass.Dg, pass.Db, 1f))); renderer.EnqueuePass((ScriptableRenderPass)(object)pass.Pass); } } } catch (Exception ex) { failed = true; MelonLogger.Error($"Category recolour failed and is now disabled for this session: {ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}"); } } private static bool EnsureBuilt(CategoryPass cp) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0075: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (cp.Pass != null) { return true; } Shader val = Shader.Find("Universal Render Pipeline/Unlit"); if ((Object)(object)val == (Object)null) { MelonLogger.Warning("Category recolour: 'Universal Render Pipeline/Unlit' not found at runtime. The 2026-08-05 scene survey saw 57 renderers using it, so this is unexpected — a game update may have stripped it."); failed = true; return false; } cp.Material = new Material(val) { hideFlags = (HideFlags)61 }; cp.Pass = new RenderObjectsPass("RRS Recolor " + cp.Name, PassEvent, new Il2CppStringArray(ShaderTags), cp.Queue, -1, new CustomCameraSettings()); cp.Pass.overrideMaterial = cp.Material; cp.Pass.overrideMaterialPassIndex = 0; FilteringSettings filteringSettings = cp.Pass.m_FilteringSettings; ((FilteringSettings)(ref filteringSettings)).renderingLayerMask = cp.Bit; ((FilteringSettings)(ref filteringSettings)).layerMask = -1; ((FilteringSettings)(ref filteringSettings)).renderQueueRange = (((int)cp.Queue == 1) ? RenderQueueRange.transparent : RenderQueueRange.opaque); cp.Pass.m_FilteringSettings = filteringSettings; MelonLogger.Msg($"Category recolour: '{cp.Name}' pass built (renderingLayerMask bit {cp.Bit})."); return true; } } internal static class CategoryTagger { public const int FirstBit = 3; public const uint Structures = 8u; public const uint Players = 16u; public const uint Map = 32u; public const uint Effects = 64u; public const uint OwnedBits = 120u; private static readonly (uint Bit, string Name)[] Names = new(uint, string)[4] { (8u, "structures"), (16u, "players"), (32u, "map"), (64u, "effects") }; private static bool warnedNoAccess; public static void Retag() { MelonLogger.Msg("Category tagging: scanning scene…"); Renderer[] array; try { array = Il2CppArrayBase<Renderer>.op_Implicit(Resources.FindObjectsOfTypeAll<Renderer>()); } catch (Exception ex) { MelonLogger.Error("Category tagging failed to enumerate renderers: " + ex.GetType().Name + ": " + ex.Message); return; } int num = 0; int num2 = 0; int num3 = 0; Dictionary<uint, int> dictionary = new Dictionary<uint, int>(); foreach (Renderer val in array) { if ((Object)(object)val == (Object)null) { continue; } GameObject gameObject; try { gameObject = ((Component)val).gameObject; } catch { num3++; continue; } if ((Object)(object)gameObject == (Object)null) { continue; } if (!InScene(gameObject)) { num2++; continue; } uint num4 = ((IsParticleRenderer(val) || IsHiddenShader(val)) ? 64u : Classify(gameObject)); if (num4 == 0) { num2++; continue; } if (!ApplyBits(val, num4)) { num3++; continue; } num++; dictionary.TryGetValue(num4, out var value); dictionary[num4] = value + 1; } StringBuilder stringBuilder = new StringBuilder(); (uint, string)[] names = Names; for (int j = 0; j < names.Length; j++) { var (key, value2) = names[j]; dictionary.TryGetValue(key, out var value3); StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(3, 2, stringBuilder2); handler.AppendFormatted(value2); handler.AppendLiteral(" "); handler.AppendFormatted(value3); handler.AppendLiteral(", "); stringBuilder2.Append(ref handler); } MelonLogger.Msg($"Category tagging: {num} renderer(s) tagged ({stringBuilder}untagged {num2}" + ((num3 > 0) ? $", {num3} unreadable" : "") + $") out of {array.Length} scanned."); } public static void ClearAll() { Renderer[] array; try { array = Il2CppArrayBase<Renderer>.op_Implicit(Resources.FindObjectsOfTypeAll<Renderer>()); } catch { return; } int num = 0; foreach (Renderer val in array) { if ((Object)(object)val == (Object)null) { continue; } try { uint renderingLayerMask = val.renderingLayerMask; uint num2 = renderingLayerMask & 0xFFFFFF87u; if (num2 != renderingLayerMask) { val.renderingLayerMask = num2; num++; } } catch { } } MelonLogger.Msg($"Category tagging cleared from {num} renderer(s)."); } private static uint Classify(GameObject go) { if ((Object)(object)Safe(() => go.GetComponentInParent<Structure>(true), Safe(() => go.GetComponentInParent<Structure>(), null)) != (Object)null) { return 8u; } int num = Safe(() => go.layer, -1); if (num == 23 || num == 18) { return 16u; } if (RootName(go) == "SCENE") { return 32u; } return 0u; } private static bool ApplyBits(Renderer r, uint category) { try { uint renderingLayerMask = r.renderingLayerMask; r.renderingLayerMask = (renderingLayerMask & 0xFFFFFF87u) | category; return true; } catch (Exception ex) { if (!warnedNoAccess) { warnedNoAccess = true; MelonLogger.Warning("RumbleReShaded: Renderer.renderingLayerMask is not writable in this build (" + ex.GetType().Name + ") — category masking cannot work. This was probed OK on 2026-08-05, so suspect a game update."); } return false; } } private static string RootName(GameObject go) { return Safe(() => ((Object)go.transform.root).name, ""); } private static bool IsHiddenShader(Renderer r) { return Safe(() => (!((Object)(object)r.sharedMaterial != (Object)null) || !((Object)(object)r.sharedMaterial.shader != (Object)null)) ? "" : ((Object)r.sharedMaterial.shader).name, "").StartsWith("Hidden/", StringComparison.Ordinal); } private static bool IsParticleRenderer(Renderer r) { string text = Safe(() => ((MemberInfo)((Object)r).GetIl2CppType()).Name, ""); if (!(text == "VFXRenderer")) { return text == "ParticleSystemRenderer"; } return true; } private static bool InScene(GameObject go) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) try { Scene scene = go.scene; return ((Scene)(ref scene)).IsValid(); } catch { return true; } } private static T Safe<T>(Func<T> get, T fallback) { try { return get(); } catch { return fallback; } } } internal static class EventBuffer { private sealed class LiveEvent { public float ChannelId; public Vector3 Position; public float Radius; public float Strength; public float Duration; public float StartTime; } public const int MaxEvents = 32; private static readonly Il2CppStructArray<Vector4> posArray = new Il2CppStructArray<Vector4>(32L); private static readonly Il2CppStructArray<Vector4> dataArray = new Il2CppStructArray<Vector4>(32L); private static readonly List<LiveEvent> live = new List<LiveEvent>(32); private static readonly Stack<LiveEvent> pool = new Stack<LiveEvent>(32); private static readonly object gate = new object(); private static readonly HashSet<string> warned = new HashSet<string>(); private static bool pushedOnce; private static readonly string[] availableEffects = new string[0]; private static readonly HashSet<string> seenChannels = new HashSet<string>(); public static int LiveCount { get { lock (gate) { return live.Count; } } } public static IReadOnlyList<string> AvailableEffects => availableEffects; public static void Fire(string channel, Vector3 worldPos, float radius, float strength, float duration) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!ValidateName(channel, "channel")) { return; } if (duration <= 0f) { duration = 0.001f; } float channelId = ChannelId(channel); float time = Time.time; LogFirstUse(channel, channelId, worldPos); lock (gate) { LiveEvent liveEvent; if (live.Count >= 32) { liveEvent = live[0]; live.RemoveAt(0); } else { liveEvent = ((pool.Count > 0) ? pool.Pop() : new LiveEvent()); } liveEvent.ChannelId = channelId; liveEvent.Position = worldPos; liveEvent.Radius = radius; liveEvent.Strength = strength; liveEvent.Duration = duration; liveEvent.StartTime = time; live.Add(liveEvent); } } public static void SetGlobal(string key, float value) { if (ValidateName(key, "global key")) { Shader.SetGlobalFloat("_RRS_" + key, value); } } public static void PlayNotImplemented(string effectId) { WarnOnce("play:" + effectId, "RumbleReShaded: RRS.Play(\"" + effectId + "\") ignored — no built-in effects ship in this build yet. Check RRS.AvailableEffects (currently empty) before calling."); } public static void PushGlobals() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; int num = 0; lock (gate) { for (int num2 = live.Count - 1; num2 >= 0; num2--) { LiveEvent liveEvent = live[num2]; if (time - liveEvent.StartTime >= liveEvent.Duration) { live.RemoveAt(num2); pool.Push(liveEvent); } } num = live.Count; for (int i = 0; i < num; i++) { LiveEvent liveEvent2 = live[i]; ((Il2CppArrayBase<Vector4>)(object)posArray)[i] = new Vector4(liveEvent2.Position.x, liveEvent2.Position.y, liveEvent2.Position.z, liveEvent2.Radius); ((Il2CppArrayBase<Vector4>)(object)dataArray)[i] = new Vector4(time - liveEvent2.StartTime, liveEvent2.Duration, liveEvent2.ChannelId, liveEvent2.Strength); } } Shader.SetGlobalVectorArray("_RRSEventPos", posArray); Shader.SetGlobalVectorArray("_RRSEventData", dataArray); Shader.SetGlobalFloat("_RRSEventCount", (float)num); if (!pushedOnce) { pushedOnce = true; MelonLogger.Msg($"[diag] Event globals pushed for the first time ({32} slots, {num} live)."); } } public static float ChannelId(string channel) { uint num = 2166136261u; string text = channel.ToLowerInvariant(); for (int i = 0; i < text.Length; i++) { num ^= text[i]; num *= 16777619; } return num & 0x3FFFFF; } private static bool ValidateName(string name, string what) { if (string.IsNullOrEmpty(name)) { WarnOnce("<empty>", "RumbleReShaded: empty " + what + " ignored."); return false; } int num = name.IndexOf('.'); if (num <= 0 || num >= name.Length - 1) { WarnOnce(name, $"RumbleReShaded: {what} '{name}' is not namespaced and was ignored. " + "Use \"modid.name\" (e.g. \"mymod.hit\") so two mods can't collide. 'rrs.*' is reserved."); return false; } return true; } private static void LogFirstUse(string channel, float channelId, Vector3 worldPos) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) lock (gate) { if (!seenChannels.Add(channel)) { return; } } MelonLogger.Msg($"[event] first '{channel}' fired at {worldPos} (channel id {channelId}). " + "A pack reacts to it only if its manifest lists this exact name in \"listen\"."); } private static void WarnOnce(string key, string message) { lock (gate) { if (!warned.Add(key)) { return; } } MelonLogger.Warning(message); } } internal static class Hooks { [HarmonyPatch(typeof(Structure), "OnCollisionEnter")] private static class StructureCollisionPatch { private static void Postfix(Structure __instance, Collision collision) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_00ae: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return; } Vector3 currentVelocity = __instance.CurrentVelocity; float magnitude = ((Vector3)(ref currentVelocity)).magnitude; if (magnitude < 1.5f) { return; } ProbeCollision(collision, currentVelocity.y, magnitude); int num = HitLayer(collision); if (num >= 0) { if (num != 9) { return; } } else if (currentVelocity.y > -0.5f) { return; } Vector3 position = ((Component)__instance).transform.position; if (!(position == Vector3.zero)) { float num2 = Mathf.InverseLerp(1.5f, 3.6f, magnitude); float strength = Mathf.Lerp(0.4f, 1f, num2); LogSampled("OnCollisionEnter", position, magnitude, strength); RRS.Fire("rrs.structure.landed", position, 8f, strength, 1.2f); } } catch (Exception e) { WarnOnce("OnCollisionEnter", e); } } } [HarmonyPatch(typeof(Structure), "OnPreInterpolatedDestroy")] private static class StructureDestroyPatch { private static void Postfix(Structure __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)__instance == (Object)null)) { Vector3 position = ((Component)__instance).transform.position; if (!(position == Vector3.zero)) { RRS.Fire("rrs.structure.destroyed", position, 4f, 1f, 0.8f); } } } catch (Exception e) { WarnOnce("OnPreInterpolatedDestroy", e); } } } public const string StructureLanded = "rrs.structure.landed"; public const string StructureDestroyed = "rrs.structure.destroyed"; private static bool warned; private const float LogInterval = 1f; private static readonly Dictionary<string, float> lastLogged = new Dictionary<string, float>(); private static bool probeFailed; private static float lastProbeLog; private const float MinImpactSpeed = 1.5f; private const float MinDownwardSpeed = 0.5f; private const float HardLandingSpeed = 3.6f; private const float MinLandingStrength = 0.4f; private const float LandingRadius = 8f; private const float LandingDuration = 1.2f; private const int CombatFloorLayer = 9; private static int HitLayer(Collision collision) { if (probeFailed || collision == null) { return -1; } try { GameObject gameObject = collision.gameObject; return ((Object)(object)gameObject == (Object)null) ? (-1) : gameObject.layer; } catch { probeFailed = true; return -1; } } private static void ProbeCollision(Collision collision, float velocityY, float speed) { if (probeFailed || collision == null) { return; } float time = Time.time; if (time - lastProbeLog < 0.4f) { return; } lastProbeLog = time; try { GameObject gameObject = collision.gameObject; if (!((Object)(object)gameObject == (Object)null)) { int layer = gameObject.layer; MelonLogger.Msg($"[probe] structure hit '{((Object)gameObject).name}' layer {layer} ('{LayerMask.LayerToName(layer)}'), vel.y {velocityY:F1}, speed {speed:F1} m/s."); } } catch (Exception ex) { probeFailed = true; MelonLogger.Warning($"RumbleReShaded: collision probe unavailable ({ex.GetType().Name}: {ex.Message}) — Collision.gameObject is stripped in this " + "build, so the floor-vs-player filter needs a different source. Events are unaffected."); } } private static void LogSampled(string hook, Vector3 pos, float speed, float strength) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (!lastLogged.TryGetValue(hook, out var value) || !(time - value < 1f)) { lastLogged[hook] = time; MelonLogger.Msg($"[event] {hook}: structure at {pos}, speed {speed:F1} m/s -> strength {strength:F2}, {EventBuffer.LiveCount}/{32} slots live."); } } private static void WarnOnce(string where, Exception e) { if (!warned) { warned = true; MelonLogger.Warning($"RumbleReShaded: built-in trigger hook '{where}' threw and will be reported only once: {e.GetType().Name}: {e.Message}\n{e.StackTrace}\n" + "Events from it may be missing; the rest of the mod is unaffected."); } } } public static class BuildInfo { public const string ModName = "RumbleReShaded"; public const string ModVersion = "1.2.0-dev.1"; public const string Description = "Loads community shader packs from UserData and applies them as VR-safe post effects. Make your own with the RumbleShade template!"; public const string Author = "Pepuldo"; } public class RRSRenderPass : ScriptableRenderPass { public RRSRenderPass(IntPtr ptr) : base(ptr) { } public RRSRenderPass() : base(ClassInjector.DerivedConstructorPointer<RRSRenderPass>()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { if (RumbleReShadedMod.RenderFailed) { return; } try { Record(renderGraph, frameData); } catch (Exception e) { RumbleReShadedMod.ReportRenderFailure("RecordRenderGraph threw while building the pack passes.", e); } } private void Record(RenderGraph renderGraph, ContextContainer frameData) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Expected O, but got Unknown //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) UniversalResourceData val = frameData.Get<UniversalResourceData>(); if (val == null) { return; } TextureHandle activeColorTexture = val.activeColorTexture; if (!((TextureHandle)(ref activeColorTexture)).IsValid()) { return; } TextureDesc textureDesc = renderGraph.GetTextureDesc(ref activeColorTexture); textureDesc.msaaSamples = (MSAASamples)1; textureDesc.bindTextureMS = false; textureDesc.depthBufferBits = (DepthBits)0; textureDesc.clearBuffer = false; textureDesc.name = "RRS_Copy"; TextureDesc textureDesc2 = renderGraph.GetTextureDesc(ref activeColorTexture); textureDesc2.msaaSamples = (MSAASamples)1; textureDesc2.bindTextureMS = false; textureDesc2.depthBufferBits = (DepthBits)0; textureDesc2.clearBuffer = false; textureDesc2.format = (GraphicsFormat)48; textureDesc2.name = "RRS_Inter"; if (!RumbleReShadedMod.passDiagLogged) { RumbleReShadedMod.passDiagLogged = true; MelonLogger.Msg($"[diag] RRSRenderPass: activeColor {textureDesc.width}x{textureDesc.height} dim={textureDesc.dimension} slices={textureDesc.slices} srcMSAA={renderGraph.GetTextureDesc(ref activeColorTexture).msaaSamples}."); } if (textureDesc.width <= 0 || textureDesc.height <= 0 || textureDesc.slices <= 0) { RumbleReShadedMod.ReportRenderFailure($"the camera colour target has an unusable descriptor: {textureDesc.width}x{textureDesc.height}, slices={textureDesc.slices}, dim={textureDesc.dimension}. Nothing was drawn.", null); return; } int num = 0; foreach (ShaderPack pack in RumbleReShadedMod.Packs) { if (pack.IsEnabled && pack.EnsureLoaded()) { pack.ApplyParameters(); TextureHandle val2 = renderGraph.CreateTexture(ref textureDesc); RenderGraphUtils.AddBlitPass(renderGraph, activeColorTexture, val2, Vector2.one, Vector2.zero, 0, 0, -1, 0, 0, 1, (BlitFilterMode)1, "RRS Copy " + pack.Name, false, "", 0); for (int i = 0; i < pack.Passes; i++) { TextureHandle val3 = ((i == pack.Passes - 1) ? activeColorTexture : renderGraph.CreateTexture(ref textureDesc2)); BlitMaterialParameters val4 = new BlitMaterialParameters(val2, val3, pack.Material, i); string text = ((pack.Passes > 1) ? $"RRS {pack.Name} pass {i}" : ("RRS " + pack.Name)); IBaseRenderGraphBuilder obj = RenderGraphUtils.AddBlitPass(renderGraph, val4, text, true, "", 0); obj.UseAllGlobalTextures(true); ((Il2CppObjectBase)obj).Cast<IDisposable>().Dispose(); val2 = val3; } num++; } } } } public class RumbleReShadedMod : MelonMod { private static MelonPreferences_Entry<bool> masterEnabled; private static readonly List<ShaderPack> packs = new List<ShaderPack>(); private static bool hooked; private static RRSRenderPass pass; private static RRSMaskPass maskPass; private static RRSSandwichSavePass sandwichSave; private static RRSSandwichRestorePass sandwichRestore; private static RRSSandwichMaskPass sandwichMask; internal static bool passDiagLogged; private static bool enqueueDiagLogged; private const int MaxRenderAttempts = 3; private static int renderFailureCount; internal static bool ApiReady; private static Vector3 lastCameraPos; public const bool DebugSolidFill = false; public const bool ForceRenderFailure = false; private static readonly List<int> lastOrder = new List<int>(); public static IReadOnlyList<ShaderPack> Packs => packs; internal static bool RenderFailed { get; private set; } private static string PacksRoot => Path.Combine(MelonEnvironment.UserDataDirectory, "RumbleReShaded"); internal static void ReportRenderFailure(string what, Exception e) { if (!RenderFailed) { RenderFailed = true; renderFailureCount++; bool num = renderFailureCount < 3; MelonLogger.Error($"RumbleReShaded has switched its render pass off ({renderFailureCount}/{3}) — " + what); if (e != null) { MelonLogger.Error(e.ToString()); } if (num) { MelonLogger.Warning("The game keeps running with no shader effects, and the pass will retry by itself on the next scene load. Nothing to do."); return; } MelonLogger.Warning($"That was attempt {3} of {3}, so the pass now " + "stays off until you restart the game. It keeps running with no shader effects. To stop it trying at all, set Enabled = false under [RumbleReShaded] in UserData/MelonPreferences.cfg. Please report this with your MelonLoader/Latest.log."); } } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (RenderFailed && renderFailureCount < 3) { RenderFailed = false; passDiagLogged = false; MelonLogger.Msg($"RumbleReShaded: retrying the render pass after loading '{sceneName}' (attempt {renderFailureCount + 1} of {3})."); } } public override void OnInitializeMelon() { try { ClassInjector.RegisterTypeInIl2Cpp<RRSRenderPass>(); } catch (Exception ex) { MelonLogger.Warning("RRSRenderPass already registered or registration failed: " + ex.Message); } try { ClassInjector.RegisterTypeInIl2Cpp<RRSMaskPass>(); ClassInjector.RegisterTypeInIl2Cpp<RRSMaskPass.MaskPassData>(); } catch (Exception ex2) { MelonLogger.Warning("RRSMaskPass registration failed: " + ex2.Message); } try { ClassInjector.RegisterTypeInIl2Cpp<RRSSandwichSavePass>(); ClassInjector.RegisterTypeInIl2Cpp<RRSSandwichRestorePass>(); ClassInjector.RegisterTypeInIl2Cpp<RRSSandwichMaskPass>(); } catch (Exception ex3) { MelonLogger.Warning("Mask sandwich pass registration failed: " + ex3.Message); } ApiReady = true; MelonLogger.Msg($"RumbleReShaded initialising. Trigger API v{RRS.ApiVersion} ready ({32} event slots); shader packs are collected after all mods have loaded."); } private void BuildSettings() { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Expected O, but got Unknown List<MelonPreferences_Category> list = new List<MelonPreferences_Category>(); MelonPreferences_Category val = MelonPreferences.CreateCategory("RumbleReShaded", "RumbleReShaded"); masterEnabled = val.CreateEntry<bool>("Enabled", true, "Enabled", "Master switch for all shader packs.", false, false, (ValueValidator)null, (string)null); UI.CreateButtonEntry(val, "Reload", "Reload packs", "Re-read all shader pack bundles (from disk, or from memory for packs supplied by other mods).", (Action)delegate { foreach (ShaderPack pack in packs) { pack.Unload(); } MelonLogger.Msg("Shader packs will reload."); }); RRSMaskPass.DebugMode = 0; list.Add(val); foreach (ShaderPack pack2 in packs) { MelonPreferences_Category val2 = MelonPreferences.CreateCategory(pack2.SettingsCategoryId, pack2.Name); string value = ((pack2.Author.Length > 0) ? (" by " + pack2.Author) : ((pack2.OwnerModId != null) ? (" from " + pack2.OwnerModId) : "")); pack2.EnabledSetting = val2.CreateEntry<bool>("Enabled", true, "Enabled", $"Enable the '{pack2.Name}' shader pack{value}.", false, false, (ValueValidator)null, (string)null); pack2.OrderSetting = val2.CreateEntry<float>("Order", pack2.DefaultOrder, "Apply order", "Higher = applied later, on top of other packs (default from the pack's manifest).", false, false, (ValueValidator)new SliderDescriptor { Min = 0f, Max = 20f, DecimalPlaces = 0 }); foreach (PackParameter parameter in pack2.Parameters) { parameter.Setting = val2.CreateEntry<float>(parameter.Property, parameter.Default, parameter.Label, $"{parameter.Label} ({parameter.Min} to {parameter.Max})", false, false, (ValueValidator)new SliderDescriptor { Min = parameter.Min, Max = parameter.Max, DecimalPlaces = 2 }); } ShaderPack target = pack2; UI.CreateButtonEntry(val2, "Reset", "Reset to defaults", "Put every '" + pack2.Name + "' slider back to its manifest default.", (Action)delegate { target.ResetParameters(); MelonLogger.Msg("Shader pack '" + target.Name + "': parameters reset to defaults."); }); list.Add(val2); } UI.RegisterMelon((MelonBase)(object)this, list.ToArray()); MelonLogger.Msg("RumbleReShaded settings registered with UIFramework."); } private static void CollectPacks() { packs.Clear(); Directory.CreateDirectory(PacksRoot); string[] directories = Directory.GetDirectories(PacksRoot); foreach (string text in directories) { ShaderPack shaderPack = ShaderPack.FromFolder(text); if (shaderPack != null && TryAdd(shaderPack, text)) { MelonLogger.Msg($"Found shader pack '{shaderPack.Name}'{((shaderPack.Author.Length > 0) ? (" by " + shaderPack.Author) : "")} {shaderPack.Version}"); } } int num = 0; foreach (ShaderPack item in PackRegistry.Close()) { if (TryAdd(item, item.SourceLabel)) { num++; } } SortPacks(); MelonLogger.Msg($"{packs.Count} shader pack(s): {packs.Count - num} from UserData, {num} supplied by other mods."); } private static void SortPacks() { packs.Sort(delegate(ShaderPack a, ShaderPack b) { int num = a.EffectiveQueue.CompareTo(b.EffectiveQueue); return (num == 0) ? string.CompareOrdinal(a.Id, b.Id) : num; }); } private static void ResortIfOrderChanged() { bool flag = lastOrder.Count != packs.Count; if (!flag) { for (int i = 0; i < packs.Count; i++) { if (lastOrder[i] != packs[i].EffectiveQueue) { flag = true; break; } } } if (!flag) { return; } SortPacks(); lastOrder.Clear(); foreach (ShaderPack pack in packs) { lastOrder.Add(pack.EffectiveQueue); if ((Object)(object)pack.Material != (Object)null) { pack.Material.renderQueue = pack.EffectiveQueue; } } } private static bool TryAdd(ShaderPack pack, string source) { if (packs.Exists((ShaderPack p) => p.Id == pack.Id)) { MelonLogger.Warning($"Duplicate shader pack '{pack.Id}' — skipping {source}. Pack names must be unique."); return false; } packs.Add(pack); return true; } public override void OnLateInitializeMelon() { CollectPacks(); BuildSettings(); if (!hooked) { hooked = true; pass = new RRSRenderPass(); ((ScriptableRenderPass)pass).renderPassEvent = (RenderPassEvent)500; ((ScriptableRenderPass)pass).requiresIntermediateTexture = true; ((ScriptableRenderPass)pass).ConfigureInput((ScriptableRenderPassInput)1); maskPass = new RRSMaskPass(); ((ScriptableRenderPass)maskPass).renderPassEvent = (RenderPassEvent)300; ((ScriptableRenderPass)maskPass).requiresIntermediateTexture = true; sandwichSave = new RRSSandwichSavePass(); ((ScriptableRenderPass)sandwichSave).renderPassEvent = (RenderPassEvent)299; ((ScriptableRenderPass)sandwichSave).requiresIntermediateTexture = true; sandwichRestore = new RRSSandwichRestorePass(); ((ScriptableRenderPass)sandwichRestore).renderPassEvent = (RenderPassEvent)301; ((ScriptableRenderPass)sandwichRestore).requiresIntermediateTexture = true; sandwichMask = new RRSSandwichMaskPass(); ((ScriptableRenderPass)sandwichMask).renderPassEvent = (RenderPassEvent)303; ((ScriptableRenderPass)sandwichMask).requiresIntermediateTexture = true; RenderPipelineManager.beginCameraRendering += Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)OnBeginCameraRendering); } } private static bool AnyPackEnabled() { foreach (ShaderPack pack in packs) { if (pack.IsEnabled) { return true; } } return false; } private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera cam) { try { BeginCameraRendering(cam); } catch (Exception e) { ReportRenderFailure("the per-camera setup threw before the pass was enqueued.", e); } } private static void BeginCameraRendering(Camera cam) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cam == (Object)null || (Object)(object)cam.targetTexture != (Object)null || !cam.stereoEnabled) { return; } lastCameraPos = ((Component)cam).transform.position; if (masterEnabled == null || !masterEnabled.Value || RenderFailed) { return; } EventBuffer.PushGlobals(); UniversalAdditionalCameraData component = ((Component)cam).GetComponent<UniversalAdditionalCameraData>(); ScriptableRenderer val = (((Object)(object)component != (Object)null) ? component.scriptableRenderer : null); MaskSandwich.PrepareCategoryDraws(); if (val != null) { CategoryRecolor.Enqueue(val); } if (val != null) { MaskSandwich.Enqueue(val, sandwichSave, sandwichRestore, sandwichMask); } if (!AnyPackEnabled()) { return; } ResortIfOrderChanged(); UniversalAdditionalCameraData component2 = ((Component)cam).GetComponent<UniversalAdditionalCameraData>(); if ((Object)(object)component2 == (Object)null) { return; } ScriptableRenderer scriptableRenderer = component2.scriptableRenderer; if (scriptableRenderer != null) { scriptableRenderer.EnqueuePass((ScriptableRenderPass)(object)pass); if (!enqueueDiagLogged) { enqueueDiagLogged = true; MelonLogger.Msg($"[diag] EnqueuePass on '{((Object)cam).name}' (stereo={cam.stereoEnabled}, XR={XRSettings.enabled}). " + "Pass will run inside URP's RenderGraph."); } } } } internal static class MaskSandwich { private static MelonPreferences_Entry<float> rungSetting; private static MelonPreferences_Entry<float> startupRungSetting; public const int MaxRung = 13; public const RenderPassEvent Step3SaveEvent = (RenderPassEvent)301; public const RenderPassEvent Step3DrawEvent = (RenderPassEvent)302; public const RenderPassEvent Step3MaskEvent = (RenderPassEvent)303; public const RenderPassEvent Step3RestoreEvent = (RenderPassEvent)304; private static int maskGlobalId; private static RenderTexture maskRT; private static RTHandle maskHandle; private static int maskW; private static int maskH; private static int maskSlices; private static GraphicsFormat maskFormat; private static bool maskDiagLogged; public const int Rung11 = 11; public const RenderPassEvent Rung10SaveEvent = (RenderPassEvent)301; public const RenderPassEvent Rung10RestoreEvent = (RenderPassEvent)303; public const RenderPassEvent Rung10DrawEvent = (RenderPassEvent)302; public const RenderPassEvent Rung9SaveEvent = (RenderPassEvent)301; public const RenderPassEvent Rung9RestoreEvent = (RenderPassEvent)302; private static int activeSaveEvent = 299; private static int activeRestoreEvent = 301; private static int sandwichGlobalId; private static int lockedRung = -1; private static int lastRefusedRung = -1; private static TextureHandle saved; private static int savedFrame = -1; private static RenderTexture ownedRT; private static RTHandle ownedHandle; private static int ownedW; private static int ownedH; private static int ownedSlices; private static GraphicsFormat ownedFormat; private const bool GraphDumpEnabled = false; private static bool dumpRequested; private static MelonPreferences_Entry<bool> disableCullingSetting; private static MelonPreferences_Entry<bool> disableMergingSetting; private static MelonPreferences_Entry<bool> disableCachingSetting; private static bool cachingDefault; private static bool cachingDefaultKnown; private static bool cachingWriteFailed; private static bool failed; private static bool diagLogged; private static bool restoreDiagLogged; private static bool skipDiagLogged; private static int diagRung = -1; private static int MaskGlobalId { get { if (maskGlobalId == 0) { return maskGlobalId = Shader.PropertyToID("_RRSCategoryMask"); } return maskGlobalId; } } private static int SandwichGlobalId { get { if (sandwichGlobalId == 0) { return sandwichGlobalId = Shader.PropertyToID("_RRSSandwichSave"); } return sandwichGlobalId; } } private static string DebugFlagState { get { bool flag = disableCullingSetting != null && disableCullingSetting.Value; bool flag2 = disableMergingSetting != null && disableMergingSetting.Value; bool flag3 = disableCachingSetting != null && disableCachingSetting.Value; int num = (flag ? 1 : 0) + (flag2 ? 1 : 0) + (flag3 ? 1 : 0); if (num == 0) { return "nothing disabled — the shipping path"; } string text = $"culling={(flag ? "OFF" : "on")} merging={(flag2 ? "OFF" : "on")} caching={(flag3 ? "OFF" : "on")}"; if (num <= 1) { return text; } return text + " — MORE THAN ONE DISABLED, THIS RUN ISOLATES NOTHING"; } } public static int Rung { get { if (rungSetting == null) { return 0; } int num = Mathf.Clamp((int)rungSetting.Value, 0, 13); if (lockedRung < 0) { if (num == 0) { return 0; } lockedRung = num; MelonLogger.Msg($"[diag] Mask sandwich: rung {lockedRung} is now LOCKED for " + "this session. To test a different rung, RESTART THE GAME — switching rungs in-session produces results that look real and are not."); return lockedRung; } if (num == 0) { return 0; } if (num != lockedRung) { if (lastRefusedRung != num) { lastRefusedRung = num; MelonLogger.Warning($"Mask sandwich: REFUSED rung {num} — this session is locked to rung {lockedRung}. Restart the game to test another rung. Switching in-session is what made rung {lockedRung} " + "read clean once and black afterwards with nothing else changed."); } rungSetting.Value = 0f; return 0; } return lockedRung; } } public static bool Enabled => Rung > 0; internal static bool IsStep3(int rung) { if (rung != 12) { return rung == 13; } return true; } public static void BuildSettings(MelonPreferences_Category cat) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown rungSetting = cat.CreateEntry<float>("MaskSandwich", 0f, "Mask sandwich test (rung)", "Experimental, blits only. 0 = off, 1 = save only, 2 = one pass at 299, 3 = split via a transient texture (UNRELIABLE — memory-pool dependent), 4 = one pass at 301, 5 = split, mod-owned texture, imported twice (works, but only with the culling flag below), 6 = KNOWN BAD, kept for numbering only, 7 = rung 5 plus the save published as a global, 8 = rung 7 plus a global-state-modification declaration, 9 = rung 5 with both halves moved to 301/302 so nothing of URP's sits between them, 10 = STEP 2 (save@301, category draws@302, restore@303 — expect NO change), 11 = step 2 with the restore suppressed (expect VISIBLE flat colours — RUN THIS ONE FIRST, and press 'Tag renderer categories' before judging either), 12 = STEP 3 (blank + id-colour draws + mask copy published as _RRSCategoryMask + restore — expect NO change), 13 = step 3 with the restore suppressed so YOU SEE THE MASK (black world, RED map, GREEN players, BLUE structures) — RUN 13 BEFORE 12. ⚠ THE FIRST RUNG YOU PICK LOCKS FOR THE SESSION — to test another one, RESTART THE GAME. Switching rungs in-session gives results that look real and are not. You can always go back to 0 to switch it off. Correct result on every rung is NO visible change. Resets to 0 on restart.", false, false, (ValueValidator)new SliderDescriptor { Min = 0f, Max = 13f, DecimalPlaces = 0 }); startupRungSetting = cat.CreateEntry<float>("StartupRung", 0f, "Rung at next startup", "Arms a rung to run automatically on the NEXT launch, so testing needs no menu trip. Cleared as soon as it is used — each arm is good for exactly one run, which is also exactly the one-rung-per-session protocol. 0 = don't arm anything.", false, false, (ValueValidator)new SliderDescriptor { Min = 0f, Max = 13f, DecimalPlaces = 0 }); int num = Mathf.Clamp((int)startupRungSetting.Value, 0, 13); if (num > 0) { try { startupRungSetting.Value = 0f; MelonPreferences.Save(); } catch (Exception ex) { MelonLogger.Warning("Mask sandwich: could not clear the startup arming " + $"({ex.GetType().Name}: {ex.Message}). Set 'Rung at next startup' back to 0 " + "by hand, or this rung will run again next launch."); } lockedRung = num; rungSetting.Value = num; MelonLogger.Msg($"[diag] Mask sandwich: rung {num} ARMED AT STARTUP and locked " + "for this session. The arming has been cleared — the next launch is rung 0 unless you arm another one."); } else { rungSetting.Value = 0f; } UI.CreateButtonEntry(cat, "DumpRenderGraph", "Dump render graph (1 frame)", "Writes RenderGraph's own compiled pass and resource list to Player.log for one frame. Needs the rung slider above 0, since that is what puts our passes in the graph. Look for 'RRS Sandwich' entries.", (Action)delegate { RequestGraphDump(); }); disableCullingSetting = cat.CreateEntry<bool>("DisablePassCulling", false, "Disable pass culling (debug)", "Stops RenderGraph culling ANY pass, not just ours. If this makes every rung stable, culling is proven to be the cause. Costs performance. Resets off on restart.", false, false, (ValueValidator)null, (string)null); disableCullingSetting.Value = false; disableMergingSetting = cat.CreateEntry<bool>("DisablePassMerging", false, "Disable pass merging (debug)", "Stops RenderGraph merging adjacent passes into one native render pass. Run rung 5 or 7 with ONLY this ticked and the culling one OFF. Costs performance. Resets off on restart.", false, false, (ValueValidator)null, (string)null); disableMergingSetting.Value = false; disableCachingSetting = cat.CreateEntry<bool>("DisableCompilationCaching", false, "Disable graph compilation caching (debug)", "Stops RenderGraph reusing a previously compiled graph. This is what the other two toggles disable as a SIDE EFFECT. Run rung 5 with ONLY this ticked. If that is clean, caching is the real mechanism. Resets off on restart.", false, false, (ValueValidator)null, (string)null); disableCachingSetting.Value = false; } public static void RequestGraphDump() { MelonLogger.Warning("Render graph dump is DISABLED — it crashed the game on 2026-08-06 (uninitialised RenderGraphLogger; see MaskSandwich.GraphDumpEnabled). Nothing was armed."); } private static void ApplyDebugParams(RenderGraph renderGraph) { try { RenderGraphDebugParams debugParams = renderGraph.debugParams; if (debugParams != null) { debugParams.disablePassCulling = disableCullingSetting != null && disableCullingSetting.Value; debugParams.disablePassMerging = disableMergingSetting != null && disableMergingSetting.Value; ApplyCompilationCaching(renderGraph); } } catch (Exception ex) { dumpRequested = false; MelonLogger.Warning("Mask sandwich: could not reach renderGraph.debugParams " + $"({ex.GetType().Name}: {ex.Message}). Dump and culling toggles are inert."); } } private static string DescribeActive(RenderGraph renderGraph, TextureHandle handle) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) try { TextureDesc textureDesc = renderGraph.GetTextureDesc(ref handle); return $"'{textureDesc.name}' {textureDesc.width}x{textureDesc.height} slices={textureDesc.slices} {textureDesc.format} msaa={textureDesc.msaaSamples}"; } catch (Exception ex) { return "<desc unavailable: " + ex.GetType().Name + ">"; } } private static void ApplyCompilationCaching(RenderGraph renderGraph) { if (cachingWriteFailed || disableCachingSetting == null) { return; } try { if (!cachingDefaultKnown) { cachingDefault = renderGraph.m_EnableCompilationCaching; cachingDefaultKnown = true; MelonLogger.Msg("[diag] Mask sandwich: RenderGraph compilation caching was " + (cachingDefault ? "ON" : "off") + " by default on this build."); } renderGraph.m_EnableCompilationCaching = cachingDefault && !disableCachingSetting.Value; } catch (Exception ex) { cachingWriteFailed = true; MelonLogger.Warning("Mask sandwich: could not reach " + $"RenderGraph.m_EnableCompilationCaching ({ex.GetType().Name}: {ex.Message}). " + "The caching toggle is inert for this session; the other two are unaffected."); } } private static void NoteRung(int rung) { if (diagRung != rung) { diagRung = rung; diagLogged = false; restoreDiagLogged = false; skipDiagLogged = false; } } public static void Enqueue(ScriptableRenderer renderer, RRSSandwichSavePass save, RRSSandwichRestorePass restore, RRSSandwichMaskPass mask) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected I4, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected I4, but got Unknown if (failed || !Enabled || renderer == null || save == null || restore == null) { return; } try { int rung = Rung; bool flag = rung == 10 || rung == 11; bool flag2 = IsStep3(rung); ((ScriptableRenderPass)save).renderPassEvent = (RenderPassEvent)(flag2 ? 301 : (flag ? 301 : ((rung == 9) ? 301 : 299))); ((ScriptableRenderPass)restore).renderPassEvent = (RenderPassEvent)(flag2 ? 304 : (flag ? 303 : ((rung == 9) ? 302 : 301))); activeSaveEvent = (int)((ScriptableRenderPass)save).renderPassEvent; activeRestoreEvent = (int)((ScriptableRenderPass)restore).renderPassEvent; renderer.EnqueuePass((ScriptableRenderPass)(object)save); if (flag2 && mask != null) { ((ScriptableRenderPass)mask).renderPassEvent = (RenderPassEvent)303; renderer.EnqueuePass((ScriptableRenderPass)(object)mask); } renderer.EnqueuePass((ScriptableRenderPass)(object)restore); } catch (Exception ex) { failed = true; MelonLogger.Error("Mask sandwich failed and is now disabled for this session: " + $"{ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}"); } } public static void PrepareCategoryDraws() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) int rung = Rung; bool flag = rung == 10 || rung == 11; bool flag2 = IsStep3(rung); if (failed || (!flag && !flag2)) { CategoryRecolor.ForceAllForSandwich = false; CategoryRecolor.MaskColours = false; return; } CategoryRecolor.PassEvent = (RenderPassEvent)(flag2 ? 302 : 302); CategoryRecolor.MaskColours = flag2; CategoryRecolor.BuildDebugPasses(); CategoryRecolor.ForceAllForSandwich = true; } internal static void RecordSave(RenderGraph renderGraph, ContextContainer frameData) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) if (failed) { return; } int rung = Rung; if (rung == 0) { return; } NoteRung(rung); ApplyDebugParams(renderGraph); UniversalResourceData val = frameData.Get<UniversalResourceData>(); if (val == null || rung == 4) { return; } TextureHandle activeColorTexture = val.activeColorTexture; if (!((TextureHandle)(ref activeColorTexture)).IsValid()) { return; } if (rung >= 5) { TextureDesc textureDesc = renderGraph.GetTextureDesc(ref activeColorTexture); if (EnsureOwnedTarget(textureDesc.width, textureDesc.height, textureDesc.slices, textureDesc.format)) { TextureHandle destination = renderGraph.ImportTexture(ownedHandle); BlitNoCull(renderGraph, activeColorTexture, destination, "RRS Sandwich Save (owned)", (rung == 7 || rung == 8) ? SandwichGlobalId : 0, rung == 8); if (IsStep3(rung)) { TextureDesc textureDesc2 = renderGraph.GetTextureDesc(ref activeColorTexture); textureDesc2.msaaSamples = (MSAASamples)1; textureDesc2.bindTextureMS = false; textureDesc2.depthBufferBits = (DepthBits)0; textureDesc2.clearBuffer = true; textureDesc2.clearColor = Color.black; textureDesc2.name = "RRS_MaskBlank"; TextureHandle source = renderGraph.CreateTexture(ref textureDesc2); BlitNoCull(renderGraph, source, activeColorTexture, "RRS Sandwich Blank (step 3)"); } if (rung == 6) { saved = destination; } savedFrame = Time.frameCount; if (!diagLogged) { diagLogged = true; string value = rung switch { 6 => "handle stashed for the restore pass", 7 => $"global published as _RRSSandwichSave (id {SandwichGlobalId})", 8 => "global published + global-state-modification declared", 9 => "events moved so nothing of URP's sits between the halves", 10 => "STEP 2 — category draws bracketed at 302; run rung 11 FIRST to prove the draws land", 11 => "STEP 2 PROOF — draws at 302, restore SUPPRESSED; expect VISIBLE flat category colours", _ => "restore will re-import", }; MelonLogger.Msg($"[diag] Mask sandwich rung {rung} recording SAVE into the owned target ({value}). save@{activeSaveEvent} restore@{activeRestoreEvent}. RenderGraph debug flags: {DebugFlagState}. activeColor AT SAVE: {DescribeActive(renderGraph, activeColorTexture)}. " + "Expect NO visible change."); } } } else { Save(renderGraph, activeColorTexture, rung, "RRS Sandwich Save"); if (rung != 1 && rung == 2) { Restore(renderGraph, activeColorTexture, "RRS Sandwich Restore (same pass)"); } } } private static void BlitNoCull(RenderGraph renderGraph, TextureHandle source, TextureHandle destination, string passName, int publishGlobalId = 0, bool declareGlobalStateModification = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) IBaseRenderGraphBuilder val = RenderGraphUtils.AddBlitPass(renderGraph, source, destination, Vector2.one, Vector2.zero, 0, 0, -1, 0, 0, 1, (BlitFilterMode)1, passName, true, "", 0); if (val != null) { val.AllowPassCulling(false); if (publishGlobalId != 0) { val.SetGlobalTextureAfterPass(ref destination, publishGlobalId); } if (declareGlobalStateModification) { val.AllowGlobalStateModification(true); } ((Il2CppObjectBase)val).Cast<IDisposable>().Dispose(); } } private static bool EnsureMaskTarget(int width, int height, int slices, GraphicsFormat format) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) slices = Mathf.Max(1, slices); if ((Object)(object)maskRT != (Object)null && maskRT.IsCreated() && maskW == width && maskH == height && maskSlices == slices && maskFormat == format) { return true; } ReleaseMaskTarget(); try { maskRT = new RenderTexture(width, height, 0, format); ((Object)maskRT).name = "RRS_CategoryMask"; ((Texture)maskRT).dimension = (TextureDimension)((slices > 1) ? 5 : 2); maskRT.volumeDepth = slices; maskRT.antiAliasing = 1; maskRT.useMipMap = false; maskRT.autoGenerateMips = false; if (!maskRT.Create()) { MelonLogger.Error("Mask sandwich step 3: mask RenderTexture.Create() returned false. Step 3 is unavailable; the other rungs are unaffected."); ReleaseMaskTarget(); return false; } maskHandle = RTHandles.Alloc(maskRT, false); } catch (Exception ex) { MelonLogger.Error("Mask sandwich step 3 could not allocate its mask target: " + ex.GetType().Name + ": " + ex.Message); ReleaseMaskTarget(); return false; } maskW = width; maskH = height; maskSlices = slices; maskFormat = format; MelonLogger.Msg($"[diag] Mask sandwich step 3 allocated the mask target: {width}x{height} slices={slices} {format}, dimension={((Texture)maskRT).dimension}, msaa=1."); return true; } private static void ReleaseMaskTarget() { try { if (maskHandle != null) { RTHandles.Release(maskHandle); } } catch (Exception ex) { MelonLogger.Warning("Mask sandwich: mask RTHandle release failed (" + ex.GetType().Name + ")."); } maskHandle = null; if ((Object)(object)maskRT != (Object)null) { try { maskRT.Release(); } catch { } try { Object.Destroy((Object)(object)maskRT); } catch { } maskRT = null; } maskW = (maskH = (maskSlices = 0)); } private static bool EnsureOwnedTarget(int width, int height, int slices, GraphicsFormat format) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) slices = Mathf.Max(1, slices); if ((Object)(object)ownedRT != (Object)null && ownedRT.IsCreated() && ownedW == width && ownedH == height && ownedSlices == slices && ownedFormat == format) { return true; } ReleaseOwnedTarget(); try { ownedRT = new RenderTexture(width, height, 0, format); ((Object)ownedRT).name = "RRS_SandwichSaveOwned"; ((Texture)ownedRT).dimension = (TextureDimension)((slices > 1) ? 5 : 2); ownedRT.volumeDepth = slices; ownedRT.antiAliasing = 1; ownedRT.useMipMap = false; ownedRT.autoGenerateMips = false; if (!ownedRT.Create()) { MelonLogger.Error("Mask sandwich rung 5: RenderTexture.Create() returned false. Rung 5 is unavailable; the other rungs are unaffected."); ReleaseOwnedTarget(); return false; } ownedHandle = RTHandles.Alloc(ownedRT, false); } catch (Exception ex) { MelonLogger.Error("Mask sandwich rung 5 could not allocate its owned target: " + ex.GetType().Name + ": " + ex.Message); ReleaseOwnedTarget(); return false; } ownedW = width; ownedH = height; ownedSlices = slices; ownedFormat = format; MelonLogger.Msg($"[diag] Mask sandwich rung {Rung} allocated an owned save target: {width}x{height} slices={slices} {format}, dimension={((Texture)ownedRT).dimension}, msaa=1."); return true; } private static void ReleaseOwnedTarget() { try { if (ownedHandle != null) { RTHandles.Release(ownedHandle); } } catch (Exception ex) { MelonLogger.Warning("Mask sandwich: RTHandle release failed (" + ex.GetType().Name + ")."); } ownedHandle = null; if ((Object)(object)ownedRT != (Object)null) { try { ownedRT.Release(); Object.Destroy((Object)(object)ownedRT); } catch (Exception ex2) { MelonLogger.Warning("Mask sandwich: RenderTexture release failed (" + ex2.GetType().Name + ")."); } ownedRT = null; } ownedW = (ownedH = (ownedSlices = 0)); } private static void Save(RenderGraph renderGraph, TextureHandle activeColor, int rung, string passName) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) TextureDesc textureDesc = renderGraph.GetTextureDesc(ref activeColor); textureDesc.msaaSamples = (MSAASamples)1; textureDesc.bindTextureMS = false; textureDesc.depthBufferBits = (DepthBits)0; textureDesc.clearBuffer = false; textureDesc.name = "RRS_SandwichSave"; saved = renderGraph.CreateTexture(ref textureDesc); BlitNoCull(renderGraph, activeColor, saved, passName); savedFrame = Time.frameCount; if (!diagLogged) { diagLogged = true; MelonLogger.Msg($"[diag] Mask sandwich rung {rung} recording SAVE ('{passName}'). save@{299} restore@{301} (AfterRenderingOpaques={300}); saved {textureDesc.width}x{textureDesc.height} slices={textureDesc.slices} msaa={textureDesc.msaaSamples}. " + "Expect NO visible change on every rung."); } } internal static void RecordMask(RenderGraph renderGraph, ContextContainer frameData) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if (failed) { return; } int rung = Rung; if (!IsStep3(rung)) { return; } ApplyDebugParams(renderGraph); UniversalResourceData val = frameData.Get<UniversalResourceData>(); if (val == null) { return; } TextureHandle activeColorTexture = val.activeColorTexture; if (!((TextureHandle)(ref activeColorTexture)).IsValid()) { return; } TextureDesc textureDesc = renderGraph.GetTextureDesc(ref activeColorTexture); if (EnsureMaskTarget(textureDesc.width, textureDesc.height, textureDesc.slices, textureDesc.format)) { TextureHandle destination = renderGraph.ImportTexture(maskHandle); BlitNoCull(renderGraph, activeColorTexture, destination, "RRS Sandwich Mask Copy", MaskGlobalId); if (!maskDiagLogged) { maskDiagLogged = true; MelonLogger.Msg($"[diag] Mask sandwich rung {rung} recorded MASK COPY at {303} and published it as _RRSCategoryMask (id {MaskGlobalId}). activeColor AT MASK: {DescribeActive(renderGraph, activeColorTexture)}. " + "Encoding: R=map G=players B=structures R+G=effects, black=untagged."); } } } internal static void RecordRestore(RenderGraph renderGraph, ContextContainer frameData) { //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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) if (failed) { return; } int rung = Rung; if (rung == 0) { return; } ApplyDebugParams(renderGraph); if (rung == 1 || rung == 2 || rung == 11 || rung == 13) { if (rung == 11 && !restoreDiagLogged) { restoreDiagLogged = true; MelonLogger.Msg("[diag] Mask sandwich rung 11: restore deliberately SKIPPED. The category draws should be VISIBLE — map black, players grey, structures white, effects magenta. If the view is unchanged, the renderers are not tagged: press 'Tag renderer categories'."); } else if (rung == 13 && !restoreDiagLogged) { restoreDiagLogged = true; MelonLogger.Msg("[diag] Mask sandwich rung 13: restore deliberately SKIPPED — YOU ARE LOOKING AT THE MASK ITSELF. Expect a BLACK world with flat RED map, GREEN players and BLUE structures, and nothing else. Any real scene detail still visible means the blank blit did not land; any colour outside pure R/G/B means the mask is not decodable."); } return; } NoteRung(rung); UniversalResourceData val = frameData.Get<UniversalResourceData>(); if (val == null) { return; } TextureHandle activeColorTexture = val.activeColorTexture; if (!((TextureHandle)(ref activeColorTexture)).IsValid()) { return; } if (rung == 4) { Save(renderGraph, activeColorTexture, rung, "RRS Sandwich Save (restore pass)"); Restore(renderGraph, activeColorTexture, "RRS Sandwich Restore (same pass, @301)"); } else if (rung >= 5) { if (ownedHandle == null || savedFrame != Time.frameCount) { if (!skipDiagLogged) { skipDiagLogged = true; MelonLogger.Warning($"[diag] Mask sandwich rung {rung} SKIPPED the restore: ownedHandle={((ownedHandle == null) ? "null" : "ok")} savedFrame={savedFrame} Time.frameCount={Time.frameCount}."); } return; } TextureHandle val2 = ((rung == 6) ? saved : renderGraph.ImportTexture(ownedHandle)); if (rung == 6 && !((TextureHandle)(ref val2)).IsValid()) { if (!skipDiagLogged) { skipDiagLogged = true; MelonLogger.Warning("[diag] Mask sandwich rung 6: the stashed handle is invalid; a TextureHandle does not survive between recordings even when imported."); } return; } RenderGraphUtils.AddBlitPass(renderGraph, val2, activeColorTexture, Vector2.one, Vector2.zero, 0, 0, -1, 0, 0, 1, (BlitFilterMode)1, "RRS Sandwich Restore (owned)", false, "", 0); savedFrame = -1; if (!restoreDiagLogged) { restoreDiagLogged = true; MelonLogger.Msg($"[diag] Mask sandwich rung {rung} recorded RESTORE from the owned target ({((rung == 6) ? "stashed handle" : "re-imported")}). RenderGraph debug flags: {DebugFlagState}. activeColor AT RESTORE: {DescribeActive(renderGraph, activeColorTexture)}. " + "⚠ COMPARE THIS WITH THE 'activeColor AT SAVE' LINE ABOVE — if the name or format differs, the two passes are not looking at the same target and that alone explains the black."); } } else if (savedFrame != Time.frameCount || !((TextureHandle)(ref saved)).IsValid()) { if (!skipDiagLogged) { skipDiagLogged = true; MelonLogger.Warning($"[diag] Mask sandwich rung 3 SKIPPED the restore: savedFrame={savedFrame} Time.frameCount={Time.frameCount} savedValid={((TextureHandle)(ref saved)).IsValid()}. The save and restore passes are not " + "recording in the same frame — that, not the blit, is the bug."); } } else { Restore(renderGraph, activeColorTexture, "RRS Sandwich Restore"); } } private static void Restore(RenderGraph renderGraph, TextureHandle activeColor, string passName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) RenderGraphUtils.AddBlitPass(renderGraph, saved, activeColor, Vector2.one, Vector2.zero, 0, 0, -1, 0, 0, 1, (BlitFilterMode)1, passName, false, "", 0); savedFrame = -1; if (!restoreDiagLogged) { restoreDiagLogged = true; MelonLogger.Msg($"[diag] Mask sandwich rung {Rung} recorded RESTORE ('{passName}')."); } } } public class RRSSandwichSavePass : ScriptableRenderPass { public const RenderPassEvent Event = (RenderPassEvent)299; public RRSSandwichSavePass(IntPtr ptr) : base(ptr) { } public RRSSandwichSavePass() : base(ClassInjector.DerivedConstructorPointer<RRSSandwichSavePass>()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { MaskSandwich.RecordSave(renderGraph, frameData); } } public class RRSSandwichMaskPass : ScriptableRenderPass { public const RenderPassEvent Event = (RenderPassEvent)303; public RRSSandwichMaskPass(IntPtr ptr) : base(ptr) { } public RRSSandwichMaskPass() : base(ClassInjector.DerivedConstructorPointer<RRSSandwichMaskPass>()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { MaskSandwich.RecordMask(renderGraph, frameData); } } public class RRSSandwichRestorePass : ScriptableRenderPass { public const RenderPassEvent Event = (RenderPassEvent)301; public RRSSandwichRestorePass(IntPtr ptr) : base(ptr) { } public RRSSandwichRestorePass() : base(ClassInjector.DerivedConstructorPointer<RRSSandwichRestorePass>()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { MaskSandwich.RecordRestore(renderGraph, frameData); } } internal static class PackRegistry { private static readonly List<ShaderPack> pending = new List<ShaderPack>(); private static readonly object gate = new object(); private static bool closed; public static bool Register(string modId, string manifestJson, byte[] bundle) { if (!ValidateModId(modId)) { return false; } if (string.IsNullOrEmpty(manifestJson)) { MelonLogger.Warning("RumbleReShaded: '" + modId + "' registered a pack with an empty manifest — ignored."); return false; } if (bundle == null || bundle.Length == 0) { MelonLogger.Warning("RumbleReShaded: '" + modId + "' registered a pack with no bundle bytes — ignored. If you are loading it from an embedded resource, check the resource name (Assembly.GetManifestResourceNames() lists what actually got compiled in)."); return false; } lock (gate) { if (closed) { MelonLogger.Warning("RumbleReShaded: '" + modId + "' tried to register a shader pack too late — ignored. Registration closes once the settings menu is built. Call RRS.RegisterPack from your mod's OnInitializeMelon (not OnLateInitializeMelon, not from a scene load)."); return false; } } ShaderPack pack = ShaderPack.FromMemory(modId, manifestJson, bundle); if (pack == null) { return false; } lock (gate) { if (pending.Exists((ShaderPack p) => p.Id == pack.Id)) { MelonLogger.Warning($"RumbleReShaded: '{modId}' registered two packs named '{pack.Name}' — " + "keeping the first. Pack names must be unique within a mod."); return false; } pending.Add(pack); } MelonLogger.Msg($"Shader pack '{pack.Name}' registered by '{modId}' ({bundle.Length / 1024} KB, in memory)."); return true; } public static bool RegisterFromAssembly(string modId, Assembly asm, string manifestResource, string bundleResource) { if (asm == null) { MelonLogger.Warning("RumbleReShaded: '" + modId + "' passed a null assembly to RegisterPack — ignored."); return false; } byte[] array = ReadResource(modId, asm, manifestResource, "manifest"); byte[] array2 = ReadResource(modId, asm, bundleResource, "bundle"); if (array == null || array2 == null) { return false; } string manifestJson = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false).GetString(array).TrimStart('\ufeff'); return Register(modId, manifestJson, array2); } private static byte[] ReadResource(string modId, Assembly asm, string nameOrSuffix, string what) { string[] manifestResourceNames = asm.GetManifestResourceNames(); string text = null; int num = 0; string[] array = manifestResourceNames; foreach (string text2 in array) { if (text2 == nameOrSuffix || text2.EndsWith("." + nameOrSuffix, StringComparison.OrdinalIgnoreCase) || text2.EndsWith(nameOrSuffix, StringComparison.OrdinalIgnoreCase)) { if (text2 == nameOrSuffix) { text = text2; num = 1; break; } text = text2; num++; } } if (num == 0) { MelonLogger.Warning($"RumbleReShaded: '{modId}' has no embedded {what} resource matching '{nameOrSuffix}'. Embedded resources in that DLL: " + ((manifestResourceNames.Length == 0) ? "(none — is Build Action set to EmbeddedResource?)" : string.Join(", ", manifestResourceNames))); return null; } if (num > 1) { MelonLogger.Warning($"RumbleReShaded: '{modId}' has {num} embedded resources ending in '{nameOrSuffix}' — ambiguous, ignored. Pass the full resource name instead."); return null; } try { using Stream stream = asm.GetManifestResourceStream(text); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } catch (Exception ex) { MelonLogger.Warning($"RumbleReShaded: '{modId}' — failed to read embedded {what} '{text}': {ex.Message}"); return null; } } public static List<ShaderPack> Close() { lock (gate) { closed = true; List<ShaderPack> result = new List<ShaderPack>(pending); pending.Clear(); return result; } } private static bool ValidateModId(string modId) { if (string.IsNullOrEmpty(modId)) { MelonLogger.Warning("RumbleReShaded: RegisterPack called with an empty mod id — ignored. Pass a short stable id for your mod (e.g. \"smudgemod\")."); return false; } foreach (char c in modId) { if (!char.IsLetterOrDigit(c) && c != '_' && c != '-') { MelonLogger.Warning($"RumbleReShaded: mod id '{modId}' contains '{c}' — ignored. " + "Use letters, digits, '_' or '-' only (it becomes part of a settings category id)."); return false; } } if (modId.StartsWith("rrs", StringComparison.OrdinalIgnoreCase) && modId.Length == 3) { MelonLogger.Warning("RumbleReShaded: mod id 'rrs' is reserved for built-in packs — ignored."); return false; } return true; } } public class RRSMaskPass : ScriptableRenderPass { public class MaskPassData : Object { public RendererListHandle List; public MaskPassData(IntPtr ptr) : base(ptr) { } public MaskPassData() : base(ClassInjector.DerivedConstructorPointer<MaskPassData>()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } } public static int DebugMode; public const bool RenderGraphRouteEnabled = false; public const int MaxSafeRung = 2; private static bool failed; private static bool loggedOnce; private static RendererListHandle pendingList; private static Action<CopyPassData, RasterGraphContext> managedRenderFunc; private static BaseRenderFunc<CopyPassData, RasterGraphContext> convertedRenderFunc; private static bool executedOnce; private static Material maskMaterial; private static BaseRenderFunc<CopyPassData, RasterGraphContext> RenderFunc { get { if ((Delegate)(object)convertedRenderFunc == (Delegate)null) { managedRenderFunc = Execute; convertedRenderFunc = DelegateSupport.ConvertDelegate<BaseRenderFunc<CopyPassData, RasterGraphContext>>((Delegate)managedRenderFunc); MelonLogger.Msg("[diag] Mask render callback converted to an Il2Cpp delegate (once)."); } return convertedRenderFunc; } } private static Material MaskMaterial { get { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)maskMaterial != (Object)null) { return maskMaterial; } Shader val = Shader.Find("Universal Render Pipeline/Unlit"); if ((Object)(object)val == (Object)null) { MelonLogger.Warning("RRSMaskPass: 'Universal Render Pipeline/Unlit' not found at runtime, despite the scene survey seeing 57 renderers using it. Mask pass cannot draw."); return null; } maskMaterial = new Material(val) { hideFlags = (HideFlags)61 }; maskMaterial.color = Color.red; return maskMaterial; } } public RRSMaskPass(IntPtr ptr) : base(ptr) { } public RRSMaskPass() : base(ClassInjector.DerivedConstructorPointer<RRSMaskPass>()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (DebugMode == 0 || failed) { return; } try { UniversalResourceData val = frameData.Get<UniversalResourceData>(); UniversalCameraData val2 = frameData.Get<UniversalCameraData>(); if (val == null || val2 == null) { return; } TextureHandle activeColorTexture = val.activeColorTexture; if (((TextureHandle)(ref activeColorTexture)).IsValid()) { TextureDesc textureDesc = renderGraph.GetTextureDesc(ref activeColorTexture); textureDesc.msaaSamples = (MSAASamples)1; textureDesc.bindTextureMS = false; textureDesc.depthBufferBits = (DepthBits)0; textureDesc.format = (GraphicsFormat)8; textureDesc.clearBuffer = true; textureDesc.clearColor = ((DebugMode == 1) ? Color.red : Color.black); textureDesc.name = "RRS_CategoryMask"; TextureHandle val3 = renderGraph.CreateTexture(ref textureDesc); if (DebugMode >= 2) { RecordRasterPass(renderGraph, val3, frameData, val2); } RenderGraphUtils.AddBlitPass(renderGraph, val3, activeColorTexture, Vector2.one, Vector2.zero, 0, 0, -1, 0, 0, 1, (BlitFilterMode)0, "RRS Mask Debug View", false, "", 0); if (!loggedOnce) { loggedOnce = true; MelonLogger.Msg($"[diag] RRSMaskPass recorded (rung {DebugMode}, {textureDesc.width}x{textureDesc.height} slices={textureDesc.slices}). Reaching this line means recording did not crash."); } } } catch (Exception ex) { failed = true; MelonLogger.Error($"RRSMaskPass failed and is now DISABLED for this session: {ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}"); } } private static void RecordRasterPass(RenderGraph renderGraph, TextureHandle mask, ContextContainer frameData, UniversalCameraData cameraData) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) CopyPassData val2 = default(CopyPassData); IRasterRenderGraphBuilder val = renderGraph.AddRasterRenderPass<CopyPassData>("RRS Category Mask", ref val2, "", 0); RenderGraphBuilders val3 = ((Il2CppObjectBase)val).Cast<RenderGraphBuilders>(); val3.SetRenderAttachment(mask, 0, (AccessFlags)2, 0, -1); if (DebugMode >= 4) { UniversalRenderingData val4 = frameData.Get<UniversalRenderingData>(); RendererListDesc val5 = new RendererListDesc(new ShaderTagId("UniversalForward"), val4.cullResults, cameraData.camera) { renderQueueRange = RenderQueueRange.opaque, sortingCriteria = (SortingCriteria)59, renderingLayerMask = 8u, overrideMaterial = MaskMaterial, overrideMaterialPassIndex = 0 }; pendingList = renderGraph.CreateRendererList(ref val5); RendererListHandle val6 = pendingList; val3.UseRendererList(ref val6); } if (DebugMode >= 3) { val.SetRenderFunc<CopyPassData>(RenderFunc); } ((Il2CppObjectBase)val).Cast<IDisposable>().Dispose(); } private static void Execute(CopyPassData data, RasterGraphContext context) { //IL_003f: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { if (!executedOnce) { executedOnce = true; MelonLogger.Msg("[diag] Mask render callback EXECUTED — Il2Cpp delegate marshalling works."); } if (DebugMode == 3) { context.cmd.ClearRenderTarget((RTClearFlags)1, Color.green, 1f, 0u); return; } context.cmd.ClearRenderTarget((RTClearFlags)1, Color.black, 1f, 0u); if (((RendererListHandle)(ref pendingList)).IsValid()) { context.cmd.DrawRendererList(RendererListHandle.op_Implicit(pendingList)); } } catch (Exception ex) { failed = true; MelonLogger.Error("RRSMaskPass render callback threw: " + ex.GetType().Name + ": " + ex.Message); } } } internal static class SceneSurvey { private static bool running; public static void Run() { if (running) { MelonLogger.Warning("Scene survey already running."); return; } running = true; try { Survey(); } catch (Exception ex) { MelonLogger.Error($"Scene survey failed: {ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}"); } finally { running = false; } } private static void Survey() { //IL_0056: 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_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(65536); DateTime now = DateTime.Now; stringBuilder.AppendLine("RumbleReShaded scene survey"); stringBuilder.AppendLine("Taken: " + now.ToString("yyyy-MM-dd HH:mm:ss")); stringBuilder.AppendLine("Unity: " + Application.unityVersion); Scene activeScene = SceneManager.GetActiveScene(); stringBuilder.AppendLine("Scene: " + ((Scene)(ref activeScene)).name); stringBuilder.AppendLine(new string('=', 78)); stringBuilder.AppendLine(); ProbeRenderingLayerMask(stringBuilder); Renderer[] array; StringBuilder stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler; try { array = Il2CppArrayBase<Renderer>.op_Implicit(Object.FindObjectsOfType<Renderer>()); } catch (Exception ex) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(47, 2, stringBuilder2); handler.AppendLiteral("FATAL: FindObjectsOfType<Renderer>() threw — "); handler.AppendFormatted(ex.GetType().Name); handler.AppendLiteral(": "); handler.AppendFormatted(ex.Message); stringBuilder3.AppendLine(ref handler); Write(stringBuilder, now); return; } stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2); handler.AppendLiteral("## Renderers found: "); handler.AppendFormatted(array.Length); stringBuilder4.AppendLine(ref handler); stringBuilder.AppendLine(); Dictionary<string, int> d = new Dictionary<string, int>(); Dictionary<string, int> d2 = new Dictionary<string, int>(); Dictionary<string, int> d3 = new Dictionary<string, int>(); Dictionary<string, int> d4 = new Dictionary<string, int>(); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; List<string> list = new List<string>(array.Length); foreach (Renderer r in array) { if ((Object)(object)r == (Object)null) { continue; } Safe(() => ((Object)r).name, "?"); GameObject go = Safe(() => ((Component)r).gameObject, null); if ((Object)(object)go == (Object)null) { continue; } int layer = Safe(() => go.layer, -1); string value = ((layer >= 0) ? Safe(() => LayerMask.LayerToName(layer), "?") : "?"); string key = $"{layer} ({value})"; string text = HierarchyPath(go); string key2 = text.Split('/')[0]; string text2 = Safe(() => ((MemberInfo)((Object)r).GetIl2CppType()).Name, "Renderer"); string text3 = Safe(() => (!((Object)(object)r.sharedMaterial != (Object)null) || !((Object)(object)r.sharedMaterial.shader != (Object)null)) ? "(none)" : ((Object)r.sharedMaterial.shader).name, "(unreadable)"); uint num8 = Safe(() => r.renderingLayerMask, uint.MaxValue); bool flag = Safe(() => go.activeInHierarchy, fallback: false); bool flag2 = Safe(() => r.enabled, fallback: false); Vector3 val = Safe(delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = r.bounds; return ((Bounds)(ref bounds)).center; }, new Vector3(-9999f, -9999f, -9999f)); string value2 = (flag ? "A" : "-") + (flag2 ? "E" : "-"); bool flag3 = Safe(() => (Object)(object)go.GetComponentInParent<Structure>(true) != (Object)null, Safe(() => (Object)(object)go.GetComponentInParent<Structure>() != (Object)null, fallback: false)); if (flag3) { num++; if (flag && flag2) { num3++; } } else { num2++; } if (num8 != uint.MaxValue) { if ((num8 & 8) != 0) { num4++; } else if ((num8 & 0x10) != 0) { num5++; } else if ((num8 & 0x20) != 0) { num6++; } else { num7++; } } Bump(d, key); Bump(d2, key2); Bump(d3, text3); Bump(d4, text2); list.Add($"{(flag3 ? "STRUCT" : " ")} | {value2} | ({val.x,8:F2},{val.y,7:F2},{val.z,8:F2}) | L{layer,-3} {value,-24} | rlm {((num8 == uint.MaxValue) ? "n/a" : num8.ToString()),-10} | {text2,-18} | {text3,-46} | {text}"); } stringBuilder.AppendLine("## Renderers by Unity layer"); stringBuilder.AppendLine(" (physics layers — NEVER retag these; Stage 3 uses renderingLayerMask)"); AppendSorted(stringBuilder, d); stringBuilder.AppendLine("## Renderers by hierarchy root"); stringBuilder.AppendLine(" (a clean split here means classification can key off the root object)"); AppendSorted(stringBuilder, d2); stringBuilder.AppendLine("## Renderers by renderer type"); AppendSorted(stringBuilder, d4); stringBuilder.AppendLine("## Renderers by shader"); stringBuilder.AppendLine(" (a player-only or structure-only shader would be another free classifier)"); AppendSorted(stringBuilder, d3); stringBuilder.AppendLine("## Structure-component test — THE key result"); stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(78, 1, stringBuilder2); handler.AppendLiteral(" renderers with an Il2CppRUMBLE.MoveSystem.Structure in their parent chain: "); handler.AppendFormatted(num); stringBuilder5.AppendLine(ref handler); stringBuilder2 = stringBuilder; StringBuilder stringBuilder6 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(77, 1, stringBuilder2); handler.AppendLiteral(" ...of those, ACTIVE and ENABLED (i.e. actually drawing): "); handler.AppendFormatted(num3); stringBuilder6.AppendLine(ref handler); stringBuilder2 = stringBuilder; StringBuilder stringBuilder7 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(78, 1, stringBuilder2); handler.AppendLiteral(" renderers without one: "); handler.AppendFormatted(num2); stringBuilder7.AppendLine(ref handler); stringBuilder.AppendLine(" RUMBLE pools structures and never reparents them, so the first number counts"); stringBuilder.AppendLine(" parked pool instances too. The SECOND number is the one to compare against"); stringBuilder.AppendLine(" how many structures are really on the field."); stringBuilder.AppendLine(" If pool instances persist and are reused, classification can be done ONCE at"); stringBuilder.AppendLine(" load instead of on every spawn."); stringBuilder.AppendL