using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using REPOFidelity.Patches; using REPOFidelity.Shaders; using REPOFidelity.Upscalers; using TMPro; using Unity.Profiling; using Unity.Profiling.LowLevel.Unsafe; using UnityEngine; using UnityEngine.Profiling; using UnityEngine.Rendering; using UnityEngine.Rendering.PostProcessing; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("Vippy")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.6.3.0")] [assembly: AssemblyInformationalVersion("1.6.3+5b124e5e41855e590e49024ae9fec305860b5997")] [assembly: AssemblyProduct("REPOFidelity")] [assembly: AssemblyTitle("REPOFidelity")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.6.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOFidelity { internal static class BuildInfo { public const string Version = "1.6.3"; } internal class CostProbe : MonoBehaviour { private class CamTiming { public readonly Stopwatch Sw = new Stopwatch(); public double TotalMs; public int Frames; } internal static class ScriptTiming { internal class Acc { public long Ticks; public int Calls; } private static readonly Dictionary _accs = new Dictionary(); internal static void Clear() { _accs.Clear(); } internal static void Reset() { foreach (Acc value in _accs.Values) { value.Ticks = 0L; value.Calls = 0; } } internal static void Register(MethodInfo m) { if (!_accs.ContainsKey(m)) { _accs[m] = new Acc(); } } internal static (long ticks, int calls) Read(MethodInfo m) { if (_accs.TryGetValue(m, out Acc value)) { return (value.Ticks, value.Calls); } return (0L, 0); } public static void Prefix(out long __state) { __state = Stopwatch.GetTimestamp(); } public static void Postfix(MethodBase __originalMethod, long __state) { if (_accs.TryGetValue(__originalMethod, out Acc value)) { value.Ticks += Stopwatch.GetTimestamp() - __state; value.Calls++; } } } private struct Sample { public float AvgFps; public float AvgMs; public float P1Low; public float P01Low; public int FrameCount; } private struct RendererBreakdown { public int Total; public int Visible; public int ShadowCasting; public int ShadowCastingHidden; public int NoLODGroup; } private struct LightBreakdown { public int Active; public int Shadowing; public int Directional; public int PointShadow; public int SpotShadow; } private struct LightInfo { public string Name; public string Type; public string ShadowMode; public float Range; public int Resolution; public float CostScore; } private struct SceneMetrics { public RendererBreakdown Renderers; public LightBreakdown Lights; public long TotalSceneTris; public int SkinnedRenderers; public int TotalParticles; public int ActiveParticles; public int ActiveParticleCount; public int ReflectionProbes; public int TrailRenderers; public int LineRenderers; public int AudioSources; public int AudioSourcesPlaying; public int UpdatingBehaviours; public int LateUpdatingBehaviours; public int FixedUpdatingBehaviours; public List LightDetail; public List<(string typeName, int count)> TopBehaviourTypes; } [CompilerGenerated] private sealed class <>c__DisplayClass39_0 { public double tickToMsMod; public int baselineFrames; public List<(string name, string cat, double n)> countStats; public StringBuilder report; public bool anyCount; public int cellIdx; public int totalCells; public Sample autoSample; public Sample vanillaSample; internal (string name, double ms, float callsPerFrame, int calls) b__3((string name, long ticks, int calls) r) { return (r.name, (double)r.ticks * tickToMsMod / (double)baselineFrames, (float)r.calls / (float)baselineFrames, r.calls); } internal void b__9(Sample v) { autoSample = v; } internal void b__10(Sample v) { vanillaSample = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass39_1 { public HashSet topSet; internal bool b__18(Type t) { return topSet.Contains(t.Name); } } [CompilerGenerated] private sealed class <>c__DisplayClass39_2 { public Sample s; internal void b__21(Sample v) { s = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass39_3 { public Sample ps; internal void b__22(Sample v) { ps = v; } } [CompilerGenerated] private sealed class d__39 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CostProbe <>4__this; private <>c__DisplayClass39_0 <>8__1; private <>c__DisplayClass39_2 <>8__2; private <>c__DisplayClass39_3 <>8__3; private CursorLockMode 5__2; private bool 5__3; private QualityPreset 5__4; private UpscaleMode 5__5; private float 5__6; private bool 5__7; private List<(ProfilerRecorder rec, string name, string cat)> 5__8; private List<(ProfilerRecorder rec, string name, string cat)> 5__9; private List<(ProfilerRecorder rec, string name, string cat)> 5__10; private double[] 5__11; private long[] 5__12; private long[] 5__13; private int 5__14; private int 5__15; private long 5__16; private float 5__17; private List 5__18; private float 5__19; private List<(string name, long ticks, int calls)> 5__20; private List<(string name, string cat, double ms)> 5__21; private List<(string name, string cat, double bytes)> 5__22; private float[] 5__23; private float[] 5__24; private float[] 5__25; private int[] 5__26; private long[] 5__27; private bool[] 5__28; private List<(string name, string cat, double bytes)> 5__29; private SceneMetrics 5__30; private List<(string label, double totalMs, double perCallUs, int calls)> 5__31; private List 5__32; private QualityPreset[] 5__33; private float[] 5__34; private List<(string label, float ms, float shadowD, float lightD, bool isActive)> 5__35; private Sample 5__36; private int 5__37; private int 5__38; private long 5__39; private float 5__40; private List 5__41; private float 5__42; private Harmony 5__43; private List 5__44; private List.Enumerator <>7__wrap44; private UpscaleMode 5__46; private float[] <>7__wrap46; private QualityPreset[] <>7__wrap47; private QualityPreset

5__49; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__39(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 12) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; <>8__2 = null; <>8__3 = null; 5__8 = null; 5__9 = null; 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; 5__18 = null; 5__20 = null; 5__21 = null; 5__22 = null; 5__23 = null; 5__24 = null; 5__25 = null; 5__26 = null; 5__27 = null; 5__28 = null; 5__29 = null; 5__30 = default(SceneMetrics); 5__31 = null; 5__32 = null; 5__33 = null; 5__34 = null; 5__35 = null; 5__41 = null; 5__43 = null; 5__44 = null; <>7__wrap44 = default(List.Enumerator); <>7__wrap46 = null; <>7__wrap47 = null; <>1__state = -2; } private bool MoveNext() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_25d8: Unknown result type (might be due to invalid IL or missing references) //IL_25e2: Expected O, but got Unknown //IL_2a6f: Unknown result type (might be due to invalid IL or missing references) //IL_2a79: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0742: Unknown result type (might be due to invalid IL or missing references) //IL_074c: Expected O, but got Unknown //IL_074c: Unknown result type (might be due to invalid IL or missing references) //IL_0756: Expected O, but got Unknown //IL_0762: Unknown result type (might be due to invalid IL or missing references) //IL_076c: Expected O, but got Unknown //IL_076c: Unknown result type (might be due to invalid IL or missing references) //IL_0776: Expected O, but got Unknown //IL_265d: Unknown result type (might be due to invalid IL or missing references) //IL_2667: Expected O, but got Unknown //IL_2da6: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Expected O, but got Unknown //IL_03ee: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Expected I4, but got Unknown //IL_2816: Unknown result type (might be due to invalid IL or missing references) //IL_2820: Expected O, but got Unknown //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Expected O, but got Unknown //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Expected O, but got Unknown //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Expected O, but got Unknown //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04e3: Expected O, but got Unknown //IL_04e9: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Expected O, but got Unknown //IL_2977: Unknown result type (might be due to invalid IL or missing references) //IL_2981: Expected O, but got Unknown //IL_2de6: Unknown result type (might be due to invalid IL or missing references) //IL_2df0: Expected O, but got Unknown //IL_0d38: Unknown result type (might be due to invalid IL or missing references) //IL_0d42: Expected O, but got Unknown //IL_24fa: Unknown result type (might be due to invalid IL or missing references) //IL_2504: Expected O, but got Unknown //IL_1eb1: Unknown result type (might be due to invalid IL or missing references) //IL_1ebb: Expected O, but got Unknown //IL_1eeb: Unknown result type (might be due to invalid IL or missing references) //IL_1ef2: Expected O, but got Unknown //IL_1ef2: Unknown result type (might be due to invalid IL or missing references) //IL_1ef9: Expected O, but got Unknown //IL_1fde: Unknown result type (might be due to invalid IL or missing references) //IL_1fe8: Expected O, but got Unknown try { int num = <>1__state; CostProbe costProbe = <>4__this; Sample sample; double num10; int num11; (ProfilerRecorder, string, string) tuple3; int num18; int num19; long monoUsedSizeLong; int num20; Sample sample2; double num24; double num25; double num26; double num27; string text6; long num28; float num29; float num30; float num31; float num32; float num33; long num34; long num35; float num36; int num38; List<(string, double, float, int)> list; switch (num) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass39_0(); Running = true; Progress = 0f; costProbe._camTimings.Clear(); <>2__current = costProbe.WaitForAutotuneIfActive(); <>1__state = 1; return true; case 1: { <>1__state = -1; 5__2 = Cursor.lockState; 5__3 = Cursor.visible; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; 5__4 = Settings.Preset; 5__5 = Settings.UpscaleModeSetting; 5__6 = Settings.FogDistanceMultiplier; 5__7 = Settings.ModEnabled; if (!5__7) { Settings.ModEnabled = true; SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); } <>8__1.report = new StringBuilder(); <>8__1.report.AppendLine(string.Format("== REPOFidelity frame cost — {0:yyyy-MM-dd HH:mm:ss} (v{1}) ==", DateTime.Now, "1.6.3")); <>8__1.report.AppendLine($"GPU: {SystemInfo.graphicsDeviceName} ({SystemInfo.graphicsMemorySize}MB, {SystemInfo.graphicsDeviceType})"); <>8__1.report.AppendLine($"CPU: {SystemInfo.processorType} ({SystemInfo.processorCount} cores, {SystemInfo.systemMemorySize}MB RAM)"); <>8__1.report.AppendLine("OS: " + SystemInfo.operatingSystem); StringBuilder report = <>8__1.report; object[] obj = new object[4] { Screen.width, Screen.height, null, null }; Resolution currentResolution = Screen.currentResolution; RefreshRate refreshRateRatio = ((Resolution)(ref currentResolution)).refreshRateRatio; obj[2] = ((RefreshRate)(ref refreshRateRatio)).value; obj[3] = (Screen.fullScreen ? "fullscreen" : "windowed"); report.AppendLine(string.Format("Screen: {0}x{1} @ {2:F0}Hz ({3})", obj)); <>8__1.report.AppendLine($"Mod: [{Settings.Preset}] upscaler={Settings.ResolvedUpscaleMode} " + $"scale={Settings.ResolvedRenderScale}% shadowQ={Settings.ResolvedShadowQuality} " + $"shadowD={Settings.ResolvedShadowDistance:F0}m lights={Settings.ResolvedPixelLightCount} " + $"lod={Settings.ResolvedLODBias:F1} AF={Settings.ResolvedAnisotropicFiltering}x"); <>8__1.report.AppendLine($"Range: fog={Settings.ResolvedFogMultiplier:F2}x " + $"effectiveFogEnd={Settings.ResolvedEffectiveFogEnd:F0}m " + $"lightD={Settings.ResolvedLightDistance:F0}m shadowBudget={Settings.ResolvedShadowBudget}"); <>8__1.report.AppendLine($"Flags: modEnabled={Settings.ModEnabled} optEnabled={Settings.OptimizationsEnabled} cpuPatches={Settings.CpuPatchesActive}"); <>8__1.report.AppendLine(); Status = "Measuring (all markers + per-camera + scene)"; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 2; return true; } case 2: { <>1__state = -1; List list3 = new List(); ProfilerRecorderHandle.GetAvailable(list3); 5__8 = new List<(ProfilerRecorder, string, string)>(); 5__9 = new List<(ProfilerRecorder, string, string)>(); 5__10 = new List<(ProfilerRecorder, string, string)>(); foreach (ProfilerRecorderHandle item13 in list3) { ProfilerRecorderDescription description = ProfilerRecorderHandle.GetDescription(item13); ProfilerRecorder item11 = ProfilerRecorder.StartNew(((ProfilerRecorderDescription)(ref description)).Category, ((ProfilerRecorderDescription)(ref description)).Name, 256, (ProfilerRecorderOptions)24); string name = ((ProfilerRecorderDescription)(ref description)).Name; ProfilerCategory category = ((ProfilerRecorderDescription)(ref description)).Category; (ProfilerRecorder, string, string) item12 = (item11, name, ((object)(ProfilerCategory)(ref category)).ToString()); ProfilerMarkerDataUnit unitType = ((ProfilerRecorderDescription)(ref description)).UnitType; switch (unitType - 1) { case 0: 5__8.Add(item12); break; case 2: 5__9.Add(item12); break; case 1: 5__10.Add(item12); break; } } Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(costProbe.OnCamPre)); Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(costProbe.OnCamPost)); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 3; return true; } case 3: <>1__state = -1; Progress = 0.03f; 5__11 = new double[5__8.Count]; 5__12 = new long[5__9.Count]; 5__13 = new long[5__10.Count]; 5__14 = GC.CollectionCount(0); 5__15 = GC.CollectionCount(1); 5__16 = Profiler.GetMonoUsedSizeLong(); 5__17 = 0f; ModTiming.Reset(); 5__18 = new List(2048); 5__19 = 0f; goto IL_06f2; case 4: <>1__state = -1; goto IL_06f2; case 5: <>1__state = -1; 5__38 = GC.CollectionCount(1); 5__39 = Profiler.GetMonoUsedSizeLong(); 5__40 = 0f; 5__41 = new List(2048); 5__42 = 0f; goto IL_0e1b; case 6: <>1__state = -1; goto IL_0e1b; case 7: <>1__state = -1; ScriptTiming.Reset(); 5__37 = 0; 5__42 = 0f; goto IL_2073; case 8: <>1__state = -1; goto IL_2073; case 9: <>1__state = -1; <>8__1.autoSample = default(Sample); <>2__current = costProbe.SampleFrames(3f, delegate(Sample v) { <>8__1.autoSample = v; }); <>1__state = 10; return true; case 10: <>1__state = -1; 5__35.Add(("Auto", <>8__1.autoSample.AvgMs, Settings.ResolvedShadowDistance, Settings.ResolvedLightDistance, 5__4 == QualityPreset.Auto)); SweepProgress(); Settings.ApplyPreset(QualityPreset.Ultra); Settings.ResolvedUpscaleMode = UpscaleMode.DLAA; Settings.ResolvedRenderScale = 100; Settings.ResolvedFogMultiplier = 1f; QualityPatch.ApplyFogAndDrawDistance(); SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 11; return true; case 11: <>1__state = -1; <>7__wrap44 = 5__32.GetEnumerator(); <>1__state = -3; goto IL_2737; case 12: <>1__state = -3; <>8__2.s = default(Sample); <>2__current = costProbe.SampleFrames(3f, delegate(Sample v) { <>8__2.s = v; }); <>1__state = 13; return true; case 13: <>1__state = -3; 5__35.Add(($"{5__46}", <>8__2.s.AvgMs, Settings.ResolvedShadowDistance, Settings.ResolvedLightDistance, 5__46 == 5__5 && 5__4 == Settings.Preset)); SweepProgress(); <>8__2 = null; goto IL_2737; case 14: <>1__state = -1; <>8__3.ps = default(Sample); <>2__current = costProbe.SampleFrames(3f, delegate(Sample v) { <>8__3.ps = v; }); <>1__state = 15; return true; case 15: <>1__state = -1; 5__35.Add(($"{

5__49}@{5__42:F1}x", <>8__3.ps.AvgMs, Settings.ResolvedShadowDistance, Settings.ResolvedLightDistance, false)); if (

5__49 == QualityPreset.Potato && Mathf.Approximately(5__42, 1.1f)) { 5__36 = <>8__3.ps; } SweepProgress(); <>8__3 = null; 5__38++; goto IL_2915; case 16: <>1__state = -1; <>8__1.vanillaSample = default(Sample); <>2__current = costProbe.SampleFrames(3f, delegate(Sample v) { <>8__1.vanillaSample = v; }); <>1__state = 17; return true; case 17: <>1__state = -1; 5__35.Add(("Vanilla (F10)", <>8__1.vanillaSample.AvgMs, QualitySettings.shadowDistance, 0f, false)); SweepProgress(); Settings.ModEnabled = 5__7; Settings.Preset = 5__4; Settings.UpscaleModeSetting = 5__5; Settings.FogDistanceMultiplier = 5__6; SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); QualityPatch.ApplyFogAndDrawDistance(); costProbe.RestoreFrameLimit(); costProbe.RestorePresetRevertSuppression(); costProbe._sweepSmoothActive = false; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 18; return true; case 18: { <>1__state = -1; float num2 = 5__35.Min<(string, float, float, float, bool)>(((string label, float ms, float shadowD, float lightD, bool isActive) r) => r.ms); foreach (var item14 in 5__35) { string item = item14.label; float item2 = item14.ms; float item3 = item14.shadowD; float item4 = item14.lightD; string text = (item14.isActive ? " (active)" : ""); string text2 = (Mathf.Approximately(item2, num2) ? " ← fastest" : $" {item2 - num2:+0.00;-0.00}"); string text3 = ((item4 > 0f) ? $" shadowD={item3:F0}m lightD={item4:F0}m" : $" shadowD={item3:F0}m"); <>8__1.report.AppendLine($" {item,-16} {item2,6:F2} ms{text3}{text}{text2}"); } float num3 = 5__35.Where<(string, float, float, float, bool)>(((string label, float ms, float shadowD, float lightD, bool isActive) r) => r.label != "Vanilla (F10)").Min<(string, float, float, float, bool)>(((string label, float ms, float shadowD, float lightD, bool isActive) r) => r.ms) - <>8__1.vanillaSample.AvgMs; float num4 = 5__36.AvgMs - <>8__1.vanillaSample.AvgMs; <>8__1.report.AppendLine($" Mod overhead vs vanilla (best mod mode): {num3:+0.00;-0.00} ms"); <>8__1.report.AppendLine($" Potato vs vanilla: {num4:+0.00;-0.00} ms (negative = Potato wins)"); <>8__1.report.AppendLine(); <>8__1.report.AppendLine("== Optimization opportunities (ranked by likely impact) =="); BuildOpportunities(<>8__1.report, 5__21, <>8__1.countStats, 5__29, 5__30, 5__31); <>8__1.report.AppendLine(); AppendConfigFiles(<>8__1.report); string text4 = <>8__1.report.ToString(); bool flag = false; try { File.AppendAllText(OutputPath, text4); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Cost probe save failed: " + ex.Message)); } try { flag = TrySystemClipboard(text4); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Clipboard copy failed: " + ex2.Message)); } Plugin.Log.LogInfo((object)(flag ? ("Cost probe: appended to " + OutputPath + " (copied to clipboard)") : ("Cost probe: appended to " + OutputPath + " (clipboard unavailable — read the file)"))); Cursor.lockState = 5__2; Cursor.visible = 5__3; Status = (flag ? "Done (clipboard)" : "Done (file only)"); Progress = 1f; Running = false; <>2__current = (object)new WaitForSeconds(5f); <>1__state = 19; return true; } case 19: { <>1__state = -1; Status = ""; return false; } IL_2737: if (<>7__wrap44.MoveNext()) { 5__46 = <>7__wrap44.Current; <>8__2 = new <>c__DisplayClass39_2(); Status = $"Sweep: {5__46}"; Settings.UpscaleModeSetting = 5__46; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 12; return true; } <>m__Finally1(); <>7__wrap44 = default(List.Enumerator); 5__36 = default(Sample); <>7__wrap46 = 5__34; 5__37 = 0; goto IL_293d; IL_0e1b: if (5__42 < 8f) { float unscaledDeltaTime = Time.unscaledDeltaTime; 5__41.Add(unscaledDeltaTime); 5__42 += unscaledDeltaTime; float num5 = unscaledDeltaTime * 1000f; if (num5 > 5__40) { 5__40 = num5; } Progress = 0.25f + 0.04f * ((float)(5__37 - 1) + 5__42 / 8f); <>2__current = null; <>1__state = 6; return true; } sample = ComputeSample(5__41); 5__23[5__37] = sample.AvgMs; 5__24[5__37] = sample.AvgFps; 5__25[5__37] = 5__40; 5__26[5__37] = GC.CollectionCount(1) - 5__38; 5__27[5__37] = (Profiler.GetMonoUsedSizeLong() - 5__39) / 1024; 5__41 = null; 5__37++; goto IL_0ec6; IL_293d: if (5__37 < <>7__wrap46.Length) { 5__42 = <>7__wrap46[5__37]; <>7__wrap47 = 5__33; 5__38 = 0; goto IL_2915; } <>7__wrap46 = null; Status = "Sweep: Vanilla (mod OFF)"; Settings.ModEnabled = false; QualityPatch.RestoreVanillaQuality(); SceneOptimizer.Apply(); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 16; return true; IL_2915: if (5__38 < <>7__wrap47.Length) {

5__49 = <>7__wrap47[5__38]; <>8__3 = new <>c__DisplayClass39_3(); Status = $"Sweep: {

5__49} @ fog {5__42:F1}x"; Settings.ApplyPreset(

5__49); Settings.ResolvedFogMultiplier = 5__42; QualityPatch.ApplyFogAndDrawDistance(); SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 14; return true; } <>7__wrap47 = null; 5__37++; goto IL_293d; IL_220b: <>8__1.report.AppendLine($"== Script cost per type (Harmony-instrumented, {4f:F0}s, top {20} types) =="); if (5__31.Count == 0) { <>8__1.report.AppendLine(" (no script methods captured)"); } else { <>8__1.report.AppendLine(" ms/frame calls/f µs/call method"); foreach (var (text5, num6, num7, num8) in 5__31) { <>8__1.report.AppendLine($" {num6,7:F3} {num8,5} {num7,7:F2} {text5}"); } double num9 = 5__31.Sum<(string, double, double, int)>(((string label, double totalMs, double perCallUs, int calls) x) => x.totalMs); <>8__1.report.AppendLine(" ──────"); <>8__1.report.AppendLine($" {num9,7:F3} (sum of instrumented methods)"); } <>8__1.report.AppendLine(); costProbe._savedVSyncCount = QualitySettings.vSyncCount; costProbe._savedTargetFrameRate = Application.targetFrameRate; QualitySettings.vSyncCount = 0; Application.targetFrameRate = -1; costProbe._frameLimitUncapped = true; Settings.PushPresetRevertSuppression(); costProbe._presetRevertSuppressed = true; Status = "Sweep: Auto / DLSS / FSR / Off / Potato / Vanilla"; <>8__1.report.AppendLine($"== Sweep (Auto = autotune's picks; rest normalized Ultra + DLAA + fog 1.0×, VSync off + uncapped, {3f}s each) =="); 5__32 = new List(); if (GPUDetector.IsUpscalerSupported(UpscaleMode.DLSS)) { 5__32.Add(UpscaleMode.DLSS); } if (GPUDetector.IsUpscalerSupported(UpscaleMode.FSR_Temporal)) { 5__32.Add(UpscaleMode.FSR_Temporal); } 5__32.Add(UpscaleMode.Off); 5__33 = new QualityPreset[5] { QualityPreset.Potato, QualityPreset.Low, QualityPreset.Medium, QualityPreset.High, QualityPreset.Ultra }; 5__34 = new float[2] { 1.1f, 0.3f }; 5__35 = new List<(string, float, float, float, bool)>(); <>8__1.totalCells = 1 + 5__32.Count + 5__33.Length * 5__34.Length + 1; <>8__1.cellIdx = 0; costProbe._sweepStartProgress = 0.38f; costProbe._sweepEndProgress = 0.98f; costProbe._sweepExpectedDuration = (float)<>8__1.totalCells * 4.5f; costProbe._sweepStartTime = Time.unscaledTime; costProbe._sweepSmoothActive = true; Status = "Sweep: Auto (autotune's picks)"; Settings.ApplyPreset(QualityPreset.Auto); QualityPatch.ApplyFogAndDrawDistance(); SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 9; return true; IL_2073: if (5__42 < 4f) { 5__42 += Time.unscaledDeltaTime; 5__37++; Progress = 0.28f + 0.09f * (5__42 / 4f); <>2__current = null; <>1__state = 8; return true; } foreach (MethodInfo item15 in 5__44) { try { 5__43.Unpatch((MethodBase)item15, (HarmonyPatchType)1, 5__43.Id); } catch { } try { 5__43.Unpatch((MethodBase)item15, (HarmonyPatchType)2, 5__43.Id); } catch { } } num10 = 1000.0 / (double)Stopwatch.Frequency; num11 = Mathf.Max(1, 5__37); foreach (MethodInfo item16 in 5__44) { var (num12, num13) = ScriptTiming.Read(item16); if (num13 != 0) { double item5 = (double)num12 * num10 / (double)num11; double item6 = ((num13 == 0) ? 0.0 : ((double)num12 * 1000000.0 / (double)Stopwatch.Frequency / (double)num13)); string item7 = item16.DeclaringType.Name + "." + item16.Name; 5__31.Add((item7, item5, item6, num13 / num11)); } } 5__31.Sort(((string label, double totalMs, double perCallUs, int calls) a, (string label, double totalMs, double perCallUs, int calls) b) => b.totalMs.CompareTo(a.totalMs)); ScriptTiming.Clear(); 5__43 = null; 5__44 = null; goto IL_220b; IL_06f2: if (5__19 < 8f) { float unscaledDeltaTime2 = Time.unscaledDeltaTime; 5__18.Add(unscaledDeltaTime2); 5__19 += unscaledDeltaTime2; float num14 = unscaledDeltaTime2 * 1000f; if (num14 > 5__17) { 5__17 = num14; } Progress = 0.03f + 0.22f * (5__19 / 8f); for (int i = 0; i < 5__8.Count; i++) { ref double reference = ref 5__11[i]; double num15 = reference; tuple3 = 5__8[i]; reference = num15 + (double)((ProfilerRecorder)(ref tuple3.Item1)).LastValue; } for (int j = 0; j < 5__9.Count; j++) { ref long reference2 = ref 5__12[j]; long num16 = reference2; tuple3 = 5__9[j]; reference2 = num16 + ((ProfilerRecorder)(ref tuple3.Item1)).LastValue; } for (int k = 0; k < 5__10.Count; k++) { ref long reference3 = ref 5__13[k]; long num17 = reference3; tuple3 = 5__10[k]; reference3 = num17 + ((ProfilerRecorder)(ref tuple3.Item1)).LastValue; } <>2__current = null; <>1__state = 4; return true; } 5__20 = ModTiming.Read().ToList(); num18 = GC.CollectionCount(0) - 5__14; num19 = GC.CollectionCount(1) - 5__15; monoUsedSizeLong = Profiler.GetMonoUsedSizeLong(); Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(costProbe.OnCamPre)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(costProbe.OnCamPost)); Progress = 0.25f; num20 = Mathf.Max(1, 5__18.Count); 5__21 = new List<(string, string, double)>(5__8.Count); <>8__1.countStats = new List<(string, string, double)>(5__9.Count); 5__22 = new List<(string, string, double)>(5__10.Count); for (int l = 0; l < 5__8.Count; l++) { 5__21.Add((5__8[l].name, 5__8[l].cat, 5__11[l] / (double)num20 / 1000000.0)); } for (int m = 0; m < 5__9.Count; m++) { <>8__1.countStats.Add((5__9[m].name, 5__9[m].cat, (double)5__12[m] / (double)num20)); } for (int n = 0; n < 5__10.Count; n++) { 5__22.Add((5__10[n].name, 5__10[n].cat, (double)5__13[n] / (double)num20)); } for (int num21 = 0; num21 < 5__8.Count; num21++) { tuple3 = 5__8[num21]; ((ProfilerRecorder)(ref tuple3.Item1)).Dispose(); } for (int num22 = 0; num22 < 5__9.Count; num22++) { tuple3 = 5__9[num22]; ((ProfilerRecorder)(ref tuple3.Item1)).Dispose(); } for (int num23 = 0; num23 < 5__10.Count; num23++) { tuple3 = 5__10[num23]; ((ProfilerRecorder)(ref tuple3.Item1)).Dispose(); } sample2 = ComputeSample(5__18); 5__21.Sort(((string name, string cat, double ms) a, (string name, string cat, double ms) b) => b.ms.CompareTo(a.ms)); <>8__1.countStats.Sort(((string name, string cat, double n) a, (string name, string cat, double n) b) => b.n.CompareTo(a.n)); 5__22.Sort(((string name, string cat, double bytes) a, (string name, string cat, double bytes) b) => b.bytes.CompareTo(a.bytes)); num24 = LookupMs(5__21, "CPU Main Thread Frame Time"); num25 = LookupMs(5__21, "CPU Render Thread Frame Time"); num26 = LookupMs(5__21, "CPU Total Frame Time"); num27 = LookupMs(5__21, "GPU Frame Time"); if (num27 > 100.0 || num27 < 0.0) { num27 = 0.0; } text6 = ((num27 <= 0.0) ? "CPU (main thread) [GPU marker unavailable]" : ((num27 > num24 + 0.2) ? "GPU" : ((num24 > num27 + 0.2) ? "CPU (main thread)" : "balanced CPU/GPU"))); <>8__1.report.AppendLine($"Baseline: {sample2.AvgMs:F2} ms ({sample2.AvgFps:F0} fps) 1%={sample2.P1Low:F0} fps 0.1%={sample2.P01Low:F0} fps worstFrame={5__17:F1} ms ({sample2.FrameCount} frames)"); if (num26 > 0.0) { <>8__1.report.AppendLine($"CPU total: {num26:F2} ms main={num24:F2} render={num25:F2}"); } if (num27 > 0.0) { <>8__1.report.AppendLine($"GPU total: {num27:F2} ms"); } <>8__1.report.AppendLine("Bottleneck: " + text6); num28 = (monoUsedSizeLong - 5__16) / 1024; num29 = (float)num18 / 8f; <>8__1.report.AppendLine($"GC: gen0={num18} gen1={num19} over {8f:F0}s ({num29:F2}/s) mono Δ={num28:+0;-0} KB"); <>8__1.report.AppendLine(); 5__23 = new float[4] { sample2.AvgMs, 0f, 0f, 0f }; 5__24 = new float[4] { sample2.AvgFps, 0f, 0f, 0f }; 5__25 = new float[4] { 5__17, 0f, 0f, 0f }; 5__26 = new int[4] { num19, 0, 0, 0 }; 5__27 = new long[4] { num28, 0L, 0L, 0L }; 5__28 = new bool[4] { true, false, true, false }; 5__37 = 1; goto IL_0ec6; IL_0ec6: if (5__37 < 4) { Status = string.Format("A/B sample {0}/4 (patches {1})", 5__37 + 1, 5__28[5__37] ? "ON" : "OFF"); Settings.AllocationFixesEnabled = 5__28[5__37]; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 5; return true; } Settings.AllocationFixesEnabled = true; num30 = (5__23[0] + 5__23[2]) / 2f; num31 = (5__23[1] + 5__23[3]) / 2f; num32 = (5__25[0] + 5__25[2]) / 2f; num33 = (5__25[1] + 5__25[3]) / 2f; num34 = (5__27[0] + 5__27[2]) / 2; num35 = (5__27[1] + 5__27[3]) / 2; num36 = 5__23[2] - 5__23[0]; <>8__1.report.AppendLine("== A/B compare (allocation patches on/off, ON-OFF-ON-OFF, same scene) =="); for (int num37 = 0; num37 < 4; num37++) { string text7 = (5__28[num37] ? "ON " : "OFF"); <>8__1.report.AppendLine($" #{num37 + 1} {text7}: {5__23[num37]:F2} ms ({5__24[num37]:F0} fps) worst={5__25[num37]:F1} gen1={5__26[num37]} mono Δ={5__27[num37]:+0;-0} KB"); } <>8__1.report.AppendLine($" ON avg : {num30:F2} ms worst {num32:F1} mono {num34:+0;-0} KB"); <>8__1.report.AppendLine($" OFF avg : {num31:F2} ms worst {num33:F1} mono {num35:+0;-0} KB"); <>8__1.report.AppendLine($" Patches effect (OFF − ON): {num31 - num30:+0.00;-0.00} ms worst {num33 - num32:+0.0;-0.0} ms mono {num35 - num34:+0;-0} KB (positive = patches helped)"); <>8__1.report.AppendLine($" Order bias check (ON#2 − ON#1): {num36:+0.00;-0.00} ms (large negative = consistent second-window-faster bias, treat OFF − ON delta with caution)"); <>8__1.report.AppendLine(); <>8__1.report.AppendLine("== Frame cost — profiler markers ranked highest→lowest (ms/frame) =="); num38 = 0; foreach (var (arg, arg2, num39) in 5__21) { if (!(num39 < 0.01)) { <>8__1.report.AppendLine($" {num39,7:F2} ms [{arg2,-12}] {arg}"); if (++num38 >= 80) { break; } } } if (num38 == 0) { <>8__1.report.AppendLine(" (no profiler time markers captured — Unity build may strip them)"); } <>8__1.report.AppendLine(); <>8__1.tickToMsMod = 1000.0 / (double)Stopwatch.Frequency; <>8__1.baselineFrames = Mathf.Max(1, 5__18.Count); list = (from r in 5__20 select (r.name, (double)r.ticks * <>8__1.tickToMsMod / (double)<>8__1.baselineFrames, (float)r.calls / (float)<>8__1.baselineFrames, r.calls) into r where r.calls > 0 orderby r.ms descending select r).ToList(); <>8__1.report.AppendLine($"== Mod-internal cost (Stopwatch spans over {8f:F0}s baseline, ms/frame) =="); if (list.Count == 0) { <>8__1.report.AppendLine(" (no mod spans hit — mod may be disabled or pipeline idle)"); } else { <>8__1.report.AppendLine(" ms/frame calls/f name"); double num40 = 0.0; foreach (var item17 in list) { <>8__1.report.AppendLine(string.Format(" {0,7:F3} {1,5:F1} {2}", item17.Item2, item17.Item3, item17.Item1.Substring("REPOFidelity.".Length))); num40 += item17.Item2; } <>8__1.report.AppendLine(" ──────"); <>8__1.report.AppendLine($" {num40,7:F3} (sum of instrumented mod spans)"); } <>8__1.report.AppendLine(); <>8__1.report.AppendLine("== Draw stats (per frame avg) =="); <>8__1.anyCount = false; EmitCount("Draw calls:", "Draw Calls Count"); EmitCount("Batches:", "Batches Count"); EmitCount("SetPass calls:", "SetPass Calls Count"); EmitCount("Triangles:", "Triangles Count"); EmitCount("Vertices:", "Vertices Count"); EmitCount("Shadow casters:", "Shadow Casters Count"); EmitCount("Used textures:", "Used Textures Count"); EmitCount("Render textures:", "Render Textures Count"); if (!<>8__1.anyCount) { <>8__1.report.AppendLine(" (no count markers captured)"); } <>8__1.report.AppendLine(); if (<>8__1.countStats.Count > 0) { <>8__1.report.AppendLine("== All count markers, ranked (top 20) =="); int num41 = 0; foreach (var (arg3, arg4, num42) in <>8__1.countStats) { if (!(num42 < 1.0)) { <>8__1.report.AppendLine($" {FmtBig(num42),10} [{arg4,-12}] {arg3}"); if (++num41 >= 20) { break; } } } <>8__1.report.AppendLine(); } 5__29 = 5__22.Where<(string, string, double)>(((string name, string cat, double bytes) x) => x.name.IndexOf("In Frame", StringComparison.OrdinalIgnoreCase) >= 0 || x.name.IndexOf("Alloc", StringComparison.OrdinalIgnoreCase) >= 0).ToList(); if (5__29.Count > 0) { <>8__1.report.AppendLine("== Allocations per frame (GC / buffer uploads) =="); foreach (var (arg5, arg6, num43) in 5__29) { if (!(num43 < 1.0)) { <>8__1.report.AppendLine($" {FmtBytes(num43),10} [{arg6,-12}] {arg5}"); } } <>8__1.report.AppendLine(); } <>8__1.report.AppendLine("== Per-camera render cost (CPU Stopwatch around onPreRender/onPostRender) =="); if (costProbe._camTimings.Count == 0) { <>8__1.report.AppendLine(" (no camera events fired during sample — unusual)"); } else { foreach (var item18 in (from kv in costProbe._camTimings select (kv.Key, kv.Value.TotalMs / (double)Mathf.Max(1, kv.Value.Frames), kv.Value.Frames) into x orderby x.ms descending select x).ToList()) { Camera item8 = item18.Item1; double item9 = item18.Item2; int item10 = item18.Item3; string arg7 = (((Object)(object)item8 != (Object)null) ? ((Object)item8).name : "(destroyed)"); <>8__1.report.AppendLine($" {item9,7:F2} ms {arg7} ({item10} renders)"); } } costProbe._camTimings.Clear(); <>8__1.report.AppendLine(); 5__30 = GatherSceneMetrics(); <>8__1.report.AppendLine("== Scene composition =="); <>8__1.report.AppendLine($" Renderers: {5__30.Renderers.Total}"); <>8__1.report.AppendLine($" Visible: {5__30.Renderers.Visible} ({Pct(5__30.Renderers.Visible, 5__30.Renderers.Total)})"); <>8__1.report.AppendLine($" Shadow casting: {5__30.Renderers.ShadowCasting} ({Pct(5__30.Renderers.ShadowCasting, 5__30.Renderers.Total)})"); <>8__1.report.AppendLine($" Shadow casting + off-screen: {5__30.Renderers.ShadowCastingHidden} ({Pct(5__30.Renderers.ShadowCastingHidden, 5__30.Renderers.Total)}) ← off-screen shadow work"); <>8__1.report.AppendLine($" No LODGroup: {5__30.Renderers.NoLODGroup} ({Pct(5__30.Renderers.NoLODGroup, 5__30.Renderers.Total)})"); <>8__1.report.AppendLine(" Tris (sum of sharedMesh): " + FmtBig(5__30.TotalSceneTris)); <>8__1.report.AppendLine($" Skinned mesh renderers: {5__30.SkinnedRenderers}"); <>8__1.report.AppendLine($" Particle systems: {5__30.TotalParticles} total, {5__30.ActiveParticles} emitting, {FmtBig(5__30.ActiveParticleCount)} particles alive"); <>8__1.report.AppendLine($" Reflection probes: {5__30.ReflectionProbes}"); <>8__1.report.AppendLine($" Trail / Line renderers: {5__30.TrailRenderers} / {5__30.LineRenderers}"); <>8__1.report.AppendLine($" Audio sources (playing): {5__30.AudioSourcesPlaying} / {5__30.AudioSources}"); <>8__1.report.AppendLine($" Lights: {5__30.Lights.Active} active, {5__30.Lights.Shadowing} casting shadow"); <>8__1.report.AppendLine($" Directional + shadow: {5__30.Lights.Directional}"); <>8__1.report.AppendLine($" Point + shadow: {5__30.Lights.PointShadow} (×6 cubemap faces)"); <>8__1.report.AppendLine($" Spot + shadow: {5__30.Lights.SpotShadow}"); <>8__1.report.AppendLine($" MonoBehaviours w/ Update: {5__30.UpdatingBehaviours}"); <>8__1.report.AppendLine($" MonoBehaviours w/ LateUpdate: {5__30.LateUpdatingBehaviours}"); <>8__1.report.AppendLine($" MonoBehaviours w/ FixedUpdate: {5__30.FixedUpdatingBehaviours}"); <>8__1.report.AppendLine(); AppendMultiplayerSection(<>8__1.report); if (5__30.TopBehaviourTypes.Count > 0) { <>8__1.report.AppendLine("== MonoBehaviour types with Update, ranked by live instance count (top 20) =="); foreach (var (arg8, num44) in 5__30.TopBehaviourTypes.Take(20)) { <>8__1.report.AppendLine($" {num44,5}× {arg8}"); } <>8__1.report.AppendLine(); } if (5__30.LightDetail.Count > 0) { <>8__1.report.AppendLine("== Per-light shadow cost proxy, ranked (top 20) =="); <>8__1.report.AppendLine(" score type range res shadow name"); foreach (LightInfo item19 in 5__30.LightDetail.OrderByDescending((LightInfo x) => x.CostScore).Take(20)) { <>8__1.report.AppendLine($" {item19.CostScore,5:F0} {item19.Type,-12} {item19.Range,5:F0}m {item19.Resolution,5} {item19.ShadowMode,-8} {item19.Name}"); } <>8__1.report.AppendLine(" (proxy = faces × res² × range² for shadowers, 0 otherwise — higher = more shadow map work)"); <>8__1.report.AppendLine(); } 5__31 = new List<(string, double, double, int)>(); if (5__30.TopBehaviourTypes.Count > 0) { <>c__DisplayClass39_1 CS$<>8__locals0 = new <>c__DisplayClass39_1(); Status = "Script profiling (Harmony)"; List list2 = new List(); MonoBehaviour[] array = Object.FindObjectsOfType(); foreach (MonoBehaviour val in array) { if (((Behaviour)val).isActiveAndEnabled) { Type type = ((object)val).GetType(); if (!list2.Contains(type)) { list2.Add(type); } } } CS$<>8__locals0.topSet = (from x in 5__30.TopBehaviourTypes.Take(20) select x.typeName).ToHashSet(); list2 = list2.Where((Type t) => CS$<>8__locals0.topSet.Contains(t.Name)).ToList(); 5__43 = new Harmony("REPOFidelity.CostProbe.ScriptTiming"); MethodInfo method = typeof(ScriptTiming).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public); MethodInfo? method2 = typeof(ScriptTiming).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public); HarmonyMethod prefix = new HarmonyMethod(method); HarmonyMethod postfix = new HarmonyMethod(method2); ScriptTiming.Clear(); 5__44 = new List(); foreach (Type item20 in list2) { PatchIfPresent(item20, "Update", 5__43, prefix, postfix, 5__44); } foreach (Type item21 in list2) { PatchIfPresent(item21, "LateUpdate", 5__43, prefix, postfix, 5__44); } foreach (Type item22 in list2) { PatchIfPresent(item22, "FixedUpdate", 5__43, prefix, postfix, 5__44); } <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 7; return true; } goto IL_220b; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } void EmitCount(string label, string marker) { double num46 = LookupCount(((<>c__DisplayClass39_0)this).countStats, marker); if (!(num46 <= 0.0)) { ((<>c__DisplayClass39_0)this).report.AppendLine($" {label,-22} {FmtBig(num46)}"); ((<>c__DisplayClass39_0)this).anyCount = true; } } void SweepProgress() { ((<>c__DisplayClass39_0)this).cellIdx++; Progress = 0.38f + 0.6f * ((float)((<>c__DisplayClass39_0)this).cellIdx / (float)((<>c__DisplayClass39_0)this).totalCells); } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap44).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__36 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CostProbe <>4__this; private IEnumerator 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__36(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown int num = <>1__state; CostProbe costProbe = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; 5__2 = costProbe.Run(); } bool flag; try { flag = 5__2.MoveNext(); } catch (Exception arg) { Plugin.Log.LogError((object)$"Cost probe failed: {arg}"); Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(costProbe.OnCamPre)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(costProbe.OnCamPost)); costProbe.RestoreFrameLimit(); costProbe.RestorePresetRevertSuppression(); Settings.AllocationFixesEnabled = true; Running = false; Status = "ERROR"; return false; } if (!flag) { return false; } <>2__current = 5__2.Current; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__52 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float seconds; public Action onDone; private List 5__2; private float 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__52(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 1; return true; case 1: <>1__state = -1; 5__2 = new List(512); 5__3 = 0f; break; case 2: <>1__state = -1; break; } if (5__3 < seconds) { float unscaledDeltaTime = Time.unscaledDeltaTime; 5__2.Add(unscaledDeltaTime); 5__3 += unscaledDeltaTime; <>2__current = null; <>1__state = 2; return true; } onDone(ComputeSample(5__2)); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__29 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__29(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!UpscalerManager.BenchmarkActive) { return false; } Status = "Waiting for autotune to finish"; goto IL_004e; case 1: <>1__state = -1; goto IL_004e; case 2: { <>1__state = -1; return false; } IL_004e: if (UpscalerManager.BenchmarkActive) { <>2__current = null; <>1__state = 1; return true; } <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static string Status = ""; internal static float Progress; private const float WarmupSeconds = 1.5f; private const float SampleSeconds = 8f; private const float SettleSeconds = 1.5f; private const float UpscalerSampleSeconds = 3f; private const float ScriptSampleSeconds = 4f; private const int ScriptTopN = 20; private static readonly string OutputPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "frame_cost.txt"); private readonly Dictionary _camTimings = new Dictionary(); private int _savedVSyncCount; private int _savedTargetFrameRate; private bool _frameLimitUncapped; private bool _presetRevertSuppressed; private float _sweepStartTime; private float _sweepExpectedDuration; private float _sweepStartProgress; private float _sweepEndProgress; private bool _sweepSmoothActive; private static readonly Dictionary _methodCache = new Dictionary(); internal static CostProbe? Instance { get; private set; } internal static bool Running { get; private set; } internal static void Toggle() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if (Running) { Abort(); return; } if ((Object)(object)Instance == (Object)null) { GameObject val = new GameObject("REPOFidelity_CostProbe"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent(); } ((MonoBehaviour)Instance).StartCoroutine(Instance.RunSafe()); } [IteratorStateMachine(typeof(d__29))] private IEnumerator WaitForAutotuneIfActive() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__29(0); } internal static void Abort() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown if (Running) { if ((Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StopAllCoroutines(); Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(Instance.OnCamPre)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(Instance.OnCamPost)); Instance._camTimings.Clear(); Instance.RestoreFrameLimit(); Instance.RestorePresetRevertSuppression(); Settings.AllocationFixesEnabled = true; } Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; Running = false; Status = ""; Plugin.Log.LogInfo((object)"Cost probe cancelled"); } } private void RestoreFrameLimit() { if (_frameLimitUncapped) { QualitySettings.vSyncCount = _savedVSyncCount; Application.targetFrameRate = _savedTargetFrameRate; _frameLimitUncapped = false; } } private void RestorePresetRevertSuppression() { if (_presetRevertSuppressed) { Settings.PopPresetRevertSuppression(); _presetRevertSuppressed = false; } } private static void AppendConfigFiles(StringBuilder report) { string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ""; AppendFileSection(report, "autotune.json", Path.Combine(path, "autotune.json")); AppendFileSection(report, "settings.json", Path.Combine(path, "settings.json")); } private static void AppendFileSection(StringBuilder report, string label, string path) { report.AppendLine("== " + label + " =="); try { report.AppendLine(File.Exists(path) ? File.ReadAllText(path).TrimEnd() : "(missing)"); } catch (Exception ex) { report.AppendLine("(read failed: " + ex.Message + ")"); } report.AppendLine(); } private void Update() { if (!Running) { return; } if ((Object)(object)GameDirector.instance != (Object)null) { GameDirector.instance.SetDisableInput(1f); } if (_sweepSmoothActive && _sweepExpectedDuration > 0f) { float num = Mathf.Clamp01((Time.unscaledTime - _sweepStartTime) / _sweepExpectedDuration); float num2 = Mathf.Lerp(_sweepStartProgress, _sweepEndProgress, num); if (num2 > Progress) { Progress = num2; } } } [IteratorStateMachine(typeof(d__36))] private IEnumerator RunSafe() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__36(0) { <>4__this = this }; } private void OnCamPre(Camera cam) { if (Running && !((Object)(object)cam == (Object)null)) { if (!_camTimings.TryGetValue(cam, out CamTiming value)) { value = new CamTiming(); _camTimings[cam] = value; } value.Sw.Restart(); } } private void OnCamPost(Camera cam) { if (Running && !((Object)(object)cam == (Object)null) && _camTimings.TryGetValue(cam, out CamTiming value)) { value.Sw.Stop(); value.TotalMs += value.Sw.Elapsed.TotalMilliseconds; value.Frames++; } } [IteratorStateMachine(typeof(d__39))] private IEnumerator Run() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__39(0) { <>4__this = this }; } private static bool TrySystemClipboard(string text) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 GUIUtility.systemCopyBuffer = text; if (GUIUtility.systemCopyBuffer == text) { return true; } if ((int)Application.platform == 13) { return TryLinuxClipboardFallback(text); } return false; } private static bool TryLinuxClipboardFallback(string text) { (string, string)[] array = new(string, string)[3] { ("wl-copy", ""), ("xclip", "-selection clipboard"), ("xsel", "--clipboard --input") }; for (int i = 0; i < array.Length; i++) { var (fileName, arguments) = array[i]; try { using Process process = Process.Start(new ProcessStartInfo(fileName, arguments) { RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true }); if (process != null) { process.StandardInput.Write(text); process.StandardInput.Close(); if (process.WaitForExit(2000) && process.ExitCode == 0) { return true; } } } catch { } } return false; } private static void PatchIfPresent(Type type, string methodName, Harmony harmony, HarmonyMethod prefix, HarmonyMethod postfix, List patched) { MethodInfo method = type.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null) { return; } try { ScriptTiming.Register(method); harmony.Patch((MethodBase)method, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patched.Add(method); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Probe: can't patch " + type.Name + "." + methodName + ": " + ex.Message)); } } private static void AppendMultiplayerSection(StringBuilder report) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar[] array = Object.FindObjectsOfType(); if (array.Length == 0) { return; } Camera main = Camera.main; Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.position : Vector3.zero); float resolvedEffectiveFogEnd = Settings.ResolvedEffectiveFogEnd; float num = ((resolvedEffectiveFogEnd > 0f) ? (resolvedEffectiveFogEnd * 1.1f) : float.PositiveInfinity); report.AppendLine($"== Multiplayer / per-player (fog cutoff {num:F0}m) =="); report.AppendLine($" PlayerAvatars: {array.Length}"); int num2 = 0; int num3 = 0; PlayerAvatar[] array2 = array; foreach (PlayerAvatar val2 in array2) { if ((Object)(object)val2 == (Object)null) { continue; } float num4 = (((Object)(object)main != (Object)null) ? Vector3.Distance(((Component)val2).transform.position, val) : 0f); bool flag = num4 > num; if (flag) { num2++; } int num5 = 0; Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren.Length; j++) { if ((int)componentsInChildren[j].shadowCastingMode != 0) { num5++; } } num3 += num5; string text = (val2.isLocal ? "local" : "remote"); string text2 = (flag ? " past-fog" : ""); report.AppendLine(string.Format(" [{0,-6}] {1,-20} {2,5:F0}m {3,3} casters{4}", text, val2.playerName ?? "(unknown)", num4, num5, text2)); } report.AppendLine($" Total shadow-casting player renderers: {num3} ({num2} players past fog)"); FlashlightController[] array3 = Object.FindObjectsOfType(); if (array3.Length != 0) { List<(FlashlightController, float)> list = new List<(FlashlightController, float)>(); FlashlightController[] array4 = array3; foreach (FlashlightController val3 in array4) { if (!((Object)(object)val3.spotlight == (Object)null)) { float item = (((Object)(object)main != (Object)null) ? Vector3.Distance(((Component)val3.spotlight).transform.position, val) : 0f); list.Add((val3, item)); } } list.Sort(((FlashlightController fl, float dist) a, (FlashlightController fl, float dist) b) => a.dist.CompareTo(b.dist)); int num6 = 0; int num7 = 0; int num8 = 0; foreach (var item2 in list) { if (item2.Item2 > num) { num8++; } else if (num6 < 4) { num6++; } else { num7++; } } report.AppendLine($" Flashlights: {list.Count} total — {num6} within budget, {num7} culled over budget, {num8} past fog"); } int num9 = Object.FindObjectsOfType().Length; int num10 = Object.FindObjectsOfType().Length; int num11 = Object.FindObjectsOfType().Length; report.AppendLine($" Cosmetic components: Eyelids×{num9} Expression×{num10} Overcharge×{num11}"); report.AppendLine(" (components past fog cutoff skip their Update — see per-player distances above)"); report.AppendLine(); } private static double LookupMs(List<(string name, string cat, double ms)> list, string marker) { foreach (var (text, _, result) in list) { if (text == marker) { return result; } } return 0.0; } private static double LookupCount(List<(string name, string cat, double n)> list, string marker) { foreach (var (text, _, result) in list) { if (text == marker) { return result; } } return 0.0; } private static double LookupBytes(List<(string name, string cat, double bytes)> list, string marker) { foreach (var (text, _, result) in list) { if (text == marker) { return result; } } return 0.0; } private static string FmtBig(double n) { if (n >= 1000000.0) { return $"{n / 1000000.0:F2}M"; } if (n >= 1000.0) { return $"{n / 1000.0:F1}K"; } return $"{n:F0}"; } private static string FmtBytes(double b) { if (b >= 1048576.0) { return $"{b / 1048576.0:F2} MB"; } if (b >= 1024.0) { return $"{b / 1024.0:F1} KB"; } return $"{b:F0} B"; } private static string Pct(int n, int total) { if (total <= 0) { return "-"; } return $"{100.0 * (double)n / (double)total:F0}%"; } [IteratorStateMachine(typeof(d__52))] private IEnumerator SampleFrames(float seconds, Action onDone) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__52(0) { seconds = seconds, onDone = onDone }; } private static Sample ComputeSample(List frames) { if (frames.Count == 0) { return default(Sample); } float num = 0f; for (int i = 0; i < frames.Count; i++) { num += frames[i]; } float num2 = num / (float)frames.Count * 1000f; frames.Sort(); Sample result = default(Sample); result.AvgFps = 1000f / num2; result.AvgMs = num2; result.P1Low = PercentileLow(frames, 0.01f); result.P01Low = PercentileLow(frames, 0.001f); result.FrameCount = frames.Count; return result; } private static float PercentileLow(List sorted, float percentile) { int num = Mathf.Max(1, Mathf.CeilToInt((float)sorted.Count * percentile)); float num2 = 0f; for (int num3 = sorted.Count - 1; num3 >= sorted.Count - num; num3--) { num2 += sorted[num3]; } return 1f / (num2 / (float)num); } private static (bool upd, bool late, bool fixedU) GetMethodFlags(Type t) { if (_methodCache.TryGetValue(t, out (bool, bool, bool) value)) { return value; } bool flag = false; bool flag2 = false; bool flag3 = false; Type type = t; while (type != null && type != typeof(MonoBehaviour) && type != typeof(Behaviour) && type != typeof(object)) { if (!flag && type.GetMethod("Update", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) != null) { flag = true; } if (!flag2 && type.GetMethod("LateUpdate", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) != null) { flag2 = true; } if (!flag3 && type.GetMethod("FixedUpdate", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) != null) { flag3 = true; } if (flag && flag2 && flag3) { break; } type = type.BaseType; } (bool, bool, bool) tuple = (flag, flag2, flag3); _methodCache[t] = tuple; return tuple; } private static SceneMetrics GatherSceneMetrics() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Invalid comparison between Unknown and I4 //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected I4, but got Unknown //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Invalid comparison between Unknown and I4 //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Expected I4, but got Unknown //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Invalid comparison between Unknown and I4 //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Invalid comparison between Unknown and I4 //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) SceneMetrics sceneMetrics = default(SceneMetrics); sceneMetrics.LightDetail = new List(); sceneMetrics.TopBehaviourTypes = new List<(string, int)>(); SceneMetrics result = sceneMetrics; MeshRenderer[] array = Object.FindObjectsOfType(); foreach (MeshRenderer obj in array) { result.Renderers.Total++; bool isVisible = ((Renderer)obj).isVisible; bool num = (int)((Renderer)obj).shadowCastingMode > 0; if (isVisible) { result.Renderers.Visible++; } if (num) { result.Renderers.ShadowCasting++; } if (num && !isVisible) { result.Renderers.ShadowCastingHidden++; } if ((Object)(object)((Component)obj).GetComponentInParent() == (Object)null) { result.Renderers.NoLODGroup++; } MeshFilter component = ((Component)obj).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { Mesh sharedMesh = component.sharedMesh; long num2 = 0L; for (int j = 0; j < sharedMesh.subMeshCount; j++) { num2 += sharedMesh.GetIndexCount(j); } result.TotalSceneTris += num2 / 3; } } result.SkinnedRenderers = Object.FindObjectsOfType().Length; ParticleSystem[] array2 = Object.FindObjectsOfType(); foreach (ParticleSystem val in array2) { result.TotalParticles++; if (val.isPlaying && val.particleCount > 0) { result.ActiveParticles++; result.ActiveParticleCount += val.particleCount; } } result.ReflectionProbes = Object.FindObjectsOfType().Length; result.TrailRenderers = Object.FindObjectsOfType().Length; result.LineRenderers = Object.FindObjectsOfType().Length; AudioSource[] array3 = Object.FindObjectsOfType(); foreach (AudioSource obj2 in array3) { result.AudioSources++; if (obj2.isPlaying) { result.AudioSourcesPlaying++; } } Light[] array4 = Object.FindObjectsOfType(); foreach (Light val2 in array4) { if (!((Behaviour)val2).enabled || !((Component)val2).gameObject.activeInHierarchy) { continue; } result.Lights.Active++; bool flag = (int)val2.shadows > 0; if (flag) { result.Lights.Shadowing++; } LightType type = val2.type; switch ((int)type) { case 1: if (flag) { result.Lights.Directional++; } break; case 2: if (flag) { result.Lights.PointShadow++; } break; case 0: if (flag) { result.Lights.SpotShadow++; } break; } int num3 = val2.shadowCustomResolution; if (num3 <= 0) { LightShadowResolution shadowResolution = val2.shadowResolution; num3 = (int)shadowResolution switch { 3 => 4096, 2 => 2048, 1 => 1024, 0 => 512, _ => 1024, }; } float num4 = (((int)val2.type == 2) ? 6f : (((int)val2.type == 1) ? ((float)QualitySettings.shadowCascades) : 1f)); float num5 = (((int)val2.type == 1) ? 2500f : (val2.range * val2.range)); float costScore = (flag ? (num4 * ((float)num3 / 1024f) * ((float)num3 / 1024f) * (num5 / 100f)) : 0f); List lightDetail = result.LightDetail; LightInfo item = new LightInfo { Name = ((Object)val2).name }; type = val2.type; item.Type = ((object)(LightType)(ref type)).ToString(); item.Range = val2.range; item.Resolution = num3; object shadowMode; if (!flag) { shadowMode = "Off"; } else { LightShadows shadows = val2.shadows; shadowMode = ((object)(LightShadows)(ref shadows)).ToString(); } item.ShadowMode = (string)shadowMode; item.CostScore = costScore; lightDetail.Add(item); } Dictionary dictionary = new Dictionary(); MonoBehaviour[] array5 = Object.FindObjectsOfType(); foreach (MonoBehaviour val3 in array5) { if (!((Behaviour)val3).isActiveAndEnabled) { continue; } Type type2 = ((object)val3).GetType(); var (flag2, flag3, flag4) = GetMethodFlags(type2); if (flag2) { result.UpdatingBehaviours++; } if (flag3) { result.LateUpdatingBehaviours++; } if (flag4) { result.FixedUpdatingBehaviours++; } if (flag2) { if (!dictionary.TryGetValue(type2, out var value)) { value = 0; } dictionary[type2] = value + 1; } } foreach (KeyValuePair item2 in dictionary.OrderByDescending((KeyValuePair k) => k.Value)) { result.TopBehaviourTypes.Add((item2.Key.Name, item2.Value)); } return result; } private static void BuildOpportunities(StringBuilder r, List<(string name, string cat, double ms)> timeStats, List<(string name, string cat, double n)> countStats, List<(string name, string cat, double bytes)> memStats, SceneMetrics scene, List<(string label, double totalMs, double perCallUs, int calls)> scriptTimings) { List<(double, string)> list = new List<(double, string)>(); double num = LookupMs(timeStats, "Physics.Simulate") + LookupMs(timeStats, "FixedUpdate.PhysicsFixedUpdate"); double num2 = LookupMs(timeStats, "Animators.Update"); double num3 = LookupMs(timeStats, "Particles.Update"); double num4 = LookupMs(timeStats, "Camera.ImageEffects"); double num5 = LookupBytes(memStats, "GC Allocated In Frame"); int num6 = 0; foreach (var (text, num7, num8, num9) in scriptTimings) { if (num7 < 0.05 || num6 >= 3) { break; } list.Add((num7 * 200.0, $"Top script cost: {text} — {num7:F3} ms/frame ({num9} calls at {num8:F1} µs each). " + "Rate-limit, cache, or Harmony-prefix-skip when state hasn't changed.")); num6++; } if (scene.Renderers.ShadowCastingHidden > 0 && scene.Renderers.Total > 0) { double num10 = (double)scene.Renderers.ShadowCastingHidden / (double)scene.Renderers.Total; list.Add((num10 * 300.0, $"{scene.Renderers.ShadowCastingHidden} off-screen shadow casters ({num10 * 100.0:F0}% of scene renderers). " + "Prefabs that don't need to cast shadows should set shadowCastingMode=Off — cost isn't directly visible in retail markers but cubemap passes are real.")); } if (scene.Renderers.NoLODGroup > 300) { list.Add(((double)scene.Renderers.NoLODGroup / 4.0, $"{scene.Renderers.NoLODGroup} renderers have no LODGroup ({Pct(scene.Renderers.NoLODGroup, scene.Renderers.Total)}). Distant small objects render at full detail — most impactful when main-cam render cost is high.")); } if (scene.Lights.PointShadow > 8) { list.Add((scene.Lights.PointShadow * 10, $"{scene.Lights.PointShadow} point lights with shadows × 6 faces = {scene.Lights.PointShadow * 6} cubemap passes/frame. Shadow budget + resolution tiering are the highest-leverage knobs.")); } if (num > 0.3) { list.Add((num * 70.0, $"Physics costs {num:F2} ms/frame. Trim layer collision matrix, raise fixed timestep interval, switch non-dynamic rigidbodies to kinematic.")); } if (num2 > 0.2) { list.Add((num2 * 60.0, $"Animators.Update costs {num2:F2} ms/frame across {scene.SkinnedRenderers} skinned renderers. Set Animator.cullingMode=BasedOnRenderers / CullCompletely on distant characters.")); } if (num3 > 0.2) { list.Add((num3 * 60.0, $"Particles.Update costs {num3:F2} ms/frame across {scene.ActiveParticles} active systems ({FmtBig(scene.ActiveParticleCount)} particles alive). Distance-cull emit rate.")); } if (num4 > 0.3) { list.Add((num4 * 50.0, $"Camera.ImageEffects (post-processing stack) costs {num4:F2} ms/frame. Audit which OnRenderImage passes are doing work.")); } if (num5 > 1024.0) { list.Add((num5 / 64.0, "GC allocates " + FmtBytes(num5) + "/frame — hunt per-frame boxing, closures, and ToArray/ToList calls.")); } double num11 = LookupCount(countStats, "Draw Calls Count"); if (num11 > 1500.0) { list.Add((num11 / 40.0, $"{num11:F0} draw calls / frame. Static batching or GPU instancing on recurring prefabs would cut CPU cost.")); } if (scene.ReflectionProbes > 1) { list.Add((scene.ReflectionProbes * 3, $"{scene.ReflectionProbes} reflection probes — each realtime probe updating adds CPU+GPU cost. Mark as baked or type=Custom when possible.")); } if (list.Count == 0) { r.AppendLine(" (no high-cost categories detected — baseline looks clean)"); return; } list.Sort(((double priority, string text) a, (double priority, string text) b) => b.priority.CompareTo(a.priority)); int num12 = 1; foreach (var item2 in list) { string item = item2.Item2; r.AppendLine($" {num12++}. {item}"); } } } internal static class DLSSDownloader { private const string DllName = "nvngx_dlss.dll"; private const int MinDllSize = 10000000; internal static string GetDllPath() { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "nvngx_dlss.dll"); } internal static bool EnsureAvailable() { string dllPath = GetDllPath(); int num; if (File.Exists(dllPath)) { num = ((new FileInfo(dllPath).Length >= 10000000) ? 1 : 0); if (num != 0) { Plugin.Log.LogDebug((object)$"DLSS DLL: {dllPath} ({new FileInfo(dllPath).Length / 1024 / 1024}MB)"); return (byte)num != 0; } } else { num = 0; } Plugin.Log.LogWarning((object)"nvngx_dlss.dll missing or invalid — DLSS/DLAA disabled. Reinstall the mod."); return (byte)num != 0; } } internal static class FrameTimeMeter { internal class Meter { public readonly string Name; public readonly string ShortName; private readonly float[] _samples; private int _index; private int _count; private float _sum; public float LastUs; public float AverageUs { get { if (_count <= 0) { return 0f; } return _sum / (float)_count; } } public float AverageMs => AverageUs / 1000f; public Meter(string name, string shortName, int windowSize = 120) { Name = name; ShortName = shortName; _samples = new float[windowSize]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Record(float microseconds) { LastUs = microseconds; _sum -= _samples[_index]; _samples[_index] = microseconds; _sum += microseconds; _index = (_index + 1) % _samples.Length; if (_count < _samples.Length) { _count++; } } } private static readonly Stopwatch _sw = Stopwatch.StartNew(); internal static readonly Meter EnemyDirector = new Meter("EnemyDirector Throttle", "EnemyDir"); internal static readonly Meter RoomVolumeCheck = new Meter("RoomVolume NonAlloc", "RoomVol"); internal static readonly Meter SemiFuncCache = new Meter("SemiFunc Cache", "SemiFunc"); internal static readonly Meter PhysGrabObjectFix = new Meter("PhysGrabObject Fix", "PhysGrab"); internal static readonly Meter LightManagerBatch = new Meter("LightManager Batch", "LightMgr"); internal static readonly Meter SceneApply = new Meter("SceneOptimizer Apply", "SceneApl"); internal static readonly Meter[] All = new Meter[6] { EnemyDirector, RoomVolumeCheck, SemiFuncCache, PhysGrabObjectFix, LightManagerBatch, SceneApply }; internal static bool Active { get { if (!Settings.DebugOverlay) { return OptimizerBenchmark.Running; } return true; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static long Begin() { if (!Active) { return 0L; } return _sw.ElapsedTicks; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void End(Meter meter, long startTicks) { if (startTicks != 0L) { float microseconds = (float)((double)(_sw.ElapsedTicks - startTicks) / 10.0); meter.Record(microseconds); } } } internal enum GpuVendor { Nvidia, Amd, Intel, Apple, Unknown } internal enum GpuTier { High, Mid, Low } internal static class GPUDetector { private static readonly Regex ArcDiscretePattern = new Regex("\\b[AB]\\d{3}\\b", RegexOptions.Compiled); public static string GpuName { get; private set; } = "Unknown"; public static GpuVendor Vendor { get; private set; } = GpuVendor.Unknown; public static GpuTier Tier { get; private set; } = GpuTier.Low; public static bool DlssAvailable { get; private set; } public static int VramMb { get; private set; } public static bool IsD3D11 { get; private set; } public static bool IsIntegratedGpu { get; private set; } public static void Detect() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_00c4: Unknown result type (might be due to invalid IL or missing references) GpuName = SystemInfo.graphicsDeviceName ?? "Unknown"; VramMb = SystemInfo.graphicsMemorySize; Vendor = DetectVendor(GpuName, SystemInfo.graphicsDeviceVendor); Tier = DetectTier(VramMb); IsD3D11 = (int)SystemInfo.graphicsDeviceType == 2; IsIntegratedGpu = DetectIntegrated(GpuName, VramMb, Vendor); DlssAvailable = Vendor == GpuVendor.Nvidia && IsD3D11 && !IsIntegratedGpu && GpuName.ToUpperInvariant().Contains("RTX"); Plugin.Log.LogInfo((object)($"GPU: {GpuName} | Vendor: {Vendor} | VRAM: {VramMb}MB | " + $"API: {SystemInfo.graphicsDeviceType} | iGPU: {IsIntegratedGpu} | Tier: {Tier}")); } public static bool IsUpscalerSupported(UpscaleMode mode) { switch (mode) { case UpscaleMode.Auto: return true; case UpscaleMode.Off: return true; case UpscaleMode.DLAA: case UpscaleMode.DLSS: return DlssAvailable; case UpscaleMode.FSR_Temporal: return true; default: return false; } } public static string[] GetAvailableUpscalerNames() { List list = new List(); foreach (UpscaleMode value in Enum.GetValues(typeof(UpscaleMode))) { if (value != UpscaleMode.FSR && value != UpscaleMode.FSR4 && value != UpscaleMode.DLAA && IsUpscalerSupported(value)) { string item = ((value == UpscaleMode.FSR_Temporal) ? "FSR" : value.ToString()); list.Add(item); } } return list.ToArray(); } private static GpuVendor DetectVendor(string name, string vendorString) { string text = (name + " " + vendorString).ToUpperInvariant(); if (text.Contains("NVIDIA")) { return GpuVendor.Nvidia; } if (text.Contains("AMD") || text.Contains("ATI")) { return GpuVendor.Amd; } if (text.Contains("INTEL")) { return GpuVendor.Intel; } if (text.Contains("APPLE")) { return GpuVendor.Apple; } return GpuVendor.Unknown; } private static GpuTier DetectTier(int vramMb) { if (vramMb >= 8000) { return GpuTier.High; } if (vramMb >= 6000) { return GpuTier.Mid; } return GpuTier.Low; } private static bool DetectIntegrated(string name, int vramMb, GpuVendor vendor) { string text = name.ToUpperInvariant(); if (vendor == GpuVendor.Intel && (text.Contains("UHD") || text.Contains("IRIS") || text.Contains("HD GRAPHICS") || (text.Contains("ARC") && !ArcDiscretePattern.IsMatch(text)))) { return true; } if (vendor == GpuVendor.Amd && ((text.Contains("VEGA") && !text.Contains("VEGA 56") && !text.Contains("VEGA 64")) || (text.Contains("RADEON GRAPHICS") && !text.Contains("RX")))) { return true; } if (vramMb > 0 && vramMb < 2048) { return true; } return false; } } internal static class LightDiagnostics { private struct LightEntry { public string Name; public LightType Type; public LightShadows ShadowMode; public int ShadowRes; public ShadowResolution GlobalShadowRes; public int EffectiveRes; public float Range; public float Intensity; public Color Color; public bool Enabled; public bool CastsShadows; public LightRenderMode RenderMode; public bool HasLightAnimator; public bool HasItemLight; public bool HasFlashlight; public bool HasExplosion; public int ShadowFaces; public float ShadowCost; public int RenderersInRange; public int EstDrawCalls; } private static readonly string OutputPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "light_diagnostics.txt"); internal static void Run() { //IL_0051: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Invalid comparison between Unknown and I4 //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected I4, but got Unknown //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Expected I4, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0830: Unknown result type (might be due to invalid IL or missing references) //IL_0849: Unknown result type (might be due to invalid IL or missing references) //IL_088d: Unknown result type (might be due to invalid IL or missing references) //IL_08a1: Unknown result type (might be due to invalid IL or missing references) //IL_08b5: Unknown result type (might be due to invalid IL or missing references) //IL_08f8: Unknown result type (might be due to invalid IL or missing references) Light[] array = Object.FindObjectsOfType(); if (array.Length == 0) { Plugin.Log.LogInfo((object)"Light diagnostics: no lights found"); return; } List list = new List(); Light[] array2 = array; foreach (Light val in array2) { LightEntry lightEntry = default(LightEntry); lightEntry.Name = GetPath(((Component)val).transform); lightEntry.Type = val.type; lightEntry.ShadowMode = val.shadows; lightEntry.ShadowRes = val.shadowCustomResolution; lightEntry.GlobalShadowRes = QualitySettings.shadowResolution; lightEntry.Range = val.range; lightEntry.Intensity = val.intensity; lightEntry.Color = val.color; lightEntry.Enabled = ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy; lightEntry.CastsShadows = (int)val.shadows > 0; lightEntry.RenderMode = val.renderMode; LightEntry item = lightEntry; GameObject gameObject = ((Component)val).gameObject; item.HasLightAnimator = (Object)(object)gameObject.GetComponent() != (Object)null; item.HasItemLight = (Object)(object)gameObject.GetComponent() != (Object)null; item.HasFlashlight = (Object)(object)gameObject.GetComponent() != (Object)null; item.HasExplosion = (Object)(object)gameObject.GetComponentInParent() != (Object)null; LightType type = val.type; item.ShadowFaces = (int)type switch { 2 => 6, 0 => 1, 1 => QualitySettings.shadowCascades, _ => 0, }; int num = (item.EffectiveRes = ((item.ShadowRes > 0) ? item.ShadowRes : GlobalResValue())); if (item.CastsShadows && item.Enabled) { item.ShadowCost = (float)item.ShadowFaces * ((float)num * (float)num / 1048576f); } else { item.ShadowCost = 0f; } if (item.CastsShadows && item.Enabled) { int num2 = 0; Collider[] array3 = Physics.OverlapSphere(((Component)val).transform.position, val.range); HashSet hashSet = new HashSet(); Collider[] array4 = array3; for (int j = 0; j < array4.Length; j++) { Renderer component = ((Component)array4[j]).GetComponent(); if ((Object)(object)component != (Object)null && (int)component.shadowCastingMode != 0 && hashSet.Add(component)) { num2++; } } item.RenderersInRange = num2; item.EstDrawCalls = num2 * item.ShadowFaces; } list.Add(item); } list.Sort((LightEntry a, LightEntry b) => b.ShadowCost.CompareTo(a.ShadowCost)); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("══════════════════════════════════════════════════════════════"); stringBuilder.AppendLine($" LIGHT DIAGNOSTICS — {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); stringBuilder.AppendLine("══════════════════════════════════════════════════════════════"); stringBuilder.AppendLine(); stringBuilder.AppendLine($" Total lights: {array.Length}"); int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; int num8 = 0; int num9 = 0; int num10 = 0; int num11 = 0; int num12 = 0; int num13 = 0; float num14 = 0f; int num15 = 0; foreach (LightEntry item2 in list) { if (item2.Enabled) { num3++; } if (item2.CastsShadows && item2.Enabled) { num4++; } LightType type = item2.Type; switch ((int)type) { case 2: num5++; break; case 0: num6++; break; case 1: num7++; break; default: num8++; break; } if (item2.HasLightAnimator) { num9++; } else if (item2.HasItemLight) { num10++; } else if (item2.HasFlashlight) { num11++; } else if (item2.HasExplosion) { num12++; } else { num13++; } num14 += item2.ShadowCost; num15 += item2.EstDrawCalls; } stringBuilder.AppendLine($" Active: {num3}"); stringBuilder.AppendLine($" Casting shadows: {num4}"); stringBuilder.AppendLine(); stringBuilder.AppendLine($" By type: Point={num5} Spot={num6} Directional={num7} Area={num8}"); stringBuilder.AppendLine($" By component: Plain={num13} LightAnimator={num9} ItemLight={num10} Flashlight={num11} Explosion={num12}"); stringBuilder.AppendLine(); stringBuilder.AppendLine($" Global shadow res: {QualitySettings.shadowResolution}"); stringBuilder.AppendLine($" Shadow distance: {QualitySettings.shadowDistance:F0}m"); stringBuilder.AppendLine($" Shadow cascades: {QualitySettings.shadowCascades}"); stringBuilder.AppendLine(); stringBuilder.AppendLine($" Total shadow cost: {num14:F1} (relative units: faces x res²/1M)"); stringBuilder.AppendLine($" Est shadow draw calls:{num15}"); stringBuilder.AppendLine(); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); stringBuilder.AppendLine(" COST BY CATEGORY"); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); float num16 = 0f; float num17 = 0f; float num18 = 0f; float num19 = 0f; float num20 = 0f; int num21 = 0; int num22 = 0; int num23 = 0; int num24 = 0; int num25 = 0; foreach (LightEntry item3 in list) { if (item3.HasLightAnimator) { num17 += item3.ShadowCost; num22 += item3.EstDrawCalls; } else if (item3.HasItemLight) { num18 += item3.ShadowCost; num23 += item3.EstDrawCalls; } else if (item3.HasFlashlight) { num19 += item3.ShadowCost; num24 += item3.EstDrawCalls; } else if (item3.HasExplosion) { num20 += item3.ShadowCost; num25 += item3.EstDrawCalls; } else { num16 += item3.ShadowCost; num21 += item3.EstDrawCalls; } } stringBuilder.AppendLine($" Plain Light: cost={num16,8:F1} est draw calls={num21,6}"); stringBuilder.AppendLine($" LightAnimator: cost={num17,8:F1} est draw calls={num22,6}"); stringBuilder.AppendLine($" ItemLight: cost={num18,8:F1} est draw calls={num23,6}"); stringBuilder.AppendLine($" Flashlight: cost={num19,8:F1} est draw calls={num24,6}"); stringBuilder.AppendLine($" Explosion: cost={num20,8:F1} est draw calls={num25,6}"); stringBuilder.AppendLine(); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); stringBuilder.AppendLine(" PER-LIGHT DETAIL (sorted by shadow cost, descending)"); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); foreach (LightEntry item4 in list) { string text = ((!item4.Enabled) ? "INACTIVE" : (item4.CastsShadows ? "SHADOW" : "noshadow")); string text2 = (item4.HasLightAnimator ? "[Animator]" : (item4.HasItemLight ? "[ItemLight]" : (item4.HasFlashlight ? "[Flashlight]" : (item4.HasExplosion ? "[Explosion]" : "[Plain]")))); stringBuilder.AppendLine(); stringBuilder.AppendLine(" " + item4.Name); stringBuilder.AppendLine($" {item4.Type} {text2} {text} render={item4.RenderMode}"); stringBuilder.AppendLine($" range={item4.Range:F1}m intensity={item4.Intensity:F2} color=({item4.Color.r:F2},{item4.Color.g:F2},{item4.Color.b:F2})"); if (item4.CastsShadows && item4.Enabled) { stringBuilder.AppendLine($" shadow={item4.ShadowMode} res={item4.EffectiveRes} (custom={item4.ShadowRes}) faces={item4.ShadowFaces}"); stringBuilder.AppendLine($" renderers in range={item4.RenderersInRange} est draw calls={item4.EstDrawCalls} cost={item4.ShadowCost:F1}"); } } stringBuilder.AppendLine(); string text3 = stringBuilder.ToString(); try { File.AppendAllText(OutputPath, text3); GUIUtility.systemCopyBuffer = text3; Plugin.Log.LogInfo((object)("Light diagnostics appended to " + OutputPath + " (copied to clipboard)")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Light diagnostics save failed: " + ex.Message)); } Plugin.Log.LogInfo((object)$"Light diagnostics: {array.Length} lights, {num4} shadowing, cost={num14:F1}"); } private static int GlobalResValue() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001c: Expected I4, but got Unknown ShadowResolution shadowResolution = QualitySettings.shadowResolution; return (int)shadowResolution switch { 0 => 256, 1 => 512, 2 => 1024, 3 => 2048, _ => 1024, }; } private static string GetPath(Transform t) { if ((Object)(object)t.parent != (Object)null) { return ((Object)t.parent).name + "/" + ((Object)t).name; } return ((Object)t).name; } } [HarmonyPatch] internal static class MenuIntegration { private class StatusTicker : MonoBehaviour { private float _t; private void Update() { _t += Time.unscaledDeltaTime; if (!(_t < 0.25f)) { _t = 0f; RefreshDynamicLabels(); } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ScrollViewBuilderDelegate <>9__71_0; public static Action <>9__71_1; public static Action <>9__71_41; public static Action <>9__71_2; public static Action <>9__71_3; public static Action <>9__71_42; public static Action <>9__71_4; public static Action <>9__71_5; public static Action <>9__71_43; public static Action <>9__71_6; public static Action <>9__71_7; public static Action <>9__71_8; public static Action <>9__71_9; public static Action <>9__71_10; public static Action <>9__71_11; public static Action <>9__71_12; public static Action <>9__71_13; public static Action <>9__71_14; public static Action <>9__71_15; public static Action <>9__71_16; public static Action <>9__71_17; public static Action <>9__71_18; public static Action <>9__71_19; public static Action <>9__71_20; public static Action <>9__71_21; public static Action <>9__71_22; public static Action <>9__71_23; public static Action <>9__71_24; public static Action <>9__71_25; public static Action <>9__71_26; public static Action <>9__71_27; public static Action <>9__71_64; public static Action <>9__71_28; public static Action <>9__71_65; public static Action <>9__71_29; public static Action <>9__71_30; public static Action <>9__71_31; public static Action <>9__71_32; public static Action <>9__71_33; public static Action <>9__71_34; public static Action <>9__71_35; public static Action <>9__71_36; public static Action <>9__71_37; public static Action <>9__71_38; public static Action <>9__71_39; public static Action <>9__71_40; internal RectTransform b__71_0(Transform sv) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) REPOLabel obj = MenuAPI.CreateREPOLabel("", sv, new Vector2(0f, 0f)); _statusText = ((Component)obj).GetComponentInChildren(); return ((REPOElement)obj).rectTransform; } internal void b__71_1() { Settings.Preset = QualityPreset.High; SyncAll(); } internal void b__71_2(string s) { GameSet((Setting)24, (s == "Windowed") ? 1 : 0, delegate { GraphicsManager.instance.UpdateWindowMode(true); }); } internal void b__71_41() { GraphicsManager.instance.UpdateWindowMode(true); } internal void b__71_3(string s) { if (!_syncing) { Settings.SetResolution(s); } } internal void b__71_4(bool b) { GameSet((Setting)12, b ? 1 : 0, delegate { GraphicsManager.instance.UpdateVsync(); }); } internal void b__71_42() { GraphicsManager.instance.UpdateVsync(); } internal void b__71_5(string s) { if (!_syncing) { int num = ((s == "Unlimited") ? (-1) : int.Parse(s)); DataDirector.instance.SettingValueSet((Setting)19, num); GraphicsManager.instance.UpdateMaxFPS(); DataDirector.instance.SaveSettings(); } } internal void b__71_6(int v) { GameSet((Setting)29, v, delegate { GraphicsManager.instance.UpdateGamma(); }); } internal void b__71_43() { GraphicsManager.instance.UpdateGamma(); } internal void b__71_7(int v) { ModSet(new <>c__DisplayClass71_1 { v = v }.b__44); } internal void b__71_8(bool b) { ModSet(new <>c__DisplayClass71_2 { b = b }.b__45); } internal void b__71_9(string s) { if (!_syncing) { Settings.Preset = Enum.Parse(s); } } internal void b__71_10(string s) { ModSet(new <>c__DisplayClass71_3 { enumName = ((s == "FSR") ? "FSR_Temporal" : s) }.b__46); } internal void b__71_11(int v) { ModSet(new <>c__DisplayClass71_4 { v = v }.b__47); } internal void b__71_12(float v) { ModSet(new <>c__DisplayClass71_5 { v = v }.b__48); } internal void b__71_13(string s) { ModSet(new <>c__DisplayClass71_6 { s = s }.b__49); } internal void b__71_14(string s) { ModSet(new <>c__DisplayClass71_7 { s = s }.b__50); } internal void b__71_15(float v) { ModSet(new <>c__DisplayClass71_8 { v = v }.b__51); } internal void b__71_16(int v) { ModSet(new <>c__DisplayClass71_9 { v = v }.b__52); } internal void b__71_17(float v) { ModSet(new <>c__DisplayClass71_10 { v = v }.b__53); } internal void b__71_18(int v) { ModSet(new <>c__DisplayClass71_11 { v = v }.b__54); } internal void b__71_19(string s) { ModSet(new <>c__DisplayClass71_12 { s = s }.b__55); } internal void b__71_20(string s) { ModSet(new <>c__DisplayClass71_13 { s = s }.b__56); } internal void b__71_21(float v) { ModSet(new <>c__DisplayClass71_14 { v = v }.b__57); } internal void b__71_22(float v) { ModSet(new <>c__DisplayClass71_15 { v = v }.b__58); } internal void b__71_23(float v) { ModSet(new <>c__DisplayClass71_16 { v = v }.b__59); } internal void b__71_24(bool b) { ModSet(new <>c__DisplayClass71_17 { b = b }.b__60); } internal void b__71_25(bool b) { ModSet(new <>c__DisplayClass71_18 { b = b }.b__61); } internal void b__71_26(bool b) { ModSet(new <>c__DisplayClass71_19 { b = b }.b__62); } internal void b__71_27(bool b) { ModSet(new <>c__DisplayClass71_20 { b = b }.b__63); } internal void b__71_28(bool b) { GameSet((Setting)16, b ? 1 : 0, delegate { GraphicsManager.instance.UpdateBloom(); }); } internal void b__71_64() { GraphicsManager.instance.UpdateBloom(); } internal void b__71_29(bool b) { GameSet((Setting)26, b ? 1 : 0, delegate { GraphicsManager.instance.UpdateGlitchLoop(); }); } internal void b__71_65() { GraphicsManager.instance.UpdateGlitchLoop(); } internal void b__71_30(bool b) { ModSet(new <>c__DisplayClass71_21 { b = b }.b__66); } internal void b__71_31() { if (_benchmarkQueued) { _benchmarkQueued = false; Settings.Preset = QualityPreset.High; RefreshDynamicLabels(); SyncAll(); return; } Settings.Preset = QualityPreset.Auto; if (SemiFunc.RunIsLevel()) { _page.ClosePage(false); if ((Object)(object)MenuManager.instance != (Object)null) { MenuManager.instance.PageCloseAllAddedOnTop(); } Settings.InvalidateAutoTune(); Settings.BenchmarkMode = true; } else { Settings.InvalidateAutoTune(); _benchmarkQueued = true; RefreshDynamicLabels(); } } internal void b__71_32(int v) { ModSet(new <>c__DisplayClass71_22 { v = v }.b__67); } internal void b__71_33(int v) { ModSet(new <>c__DisplayClass71_23 { v = v }.b__68); } internal void b__71_34(int v) { ModSet(new <>c__DisplayClass71_24 { v = v }.b__69); } internal void b__71_35(int v) { ModSet(new <>c__DisplayClass71_25 { v = v }.b__70); } internal void b__71_36(int v) { ModSet(new <>c__DisplayClass71_26 { v = v }.b__71); } internal void b__71_37(int v) { ModSet(new <>c__DisplayClass71_27 { v = v }.b__72); } internal void b__71_38(bool b) { ModSet(new <>c__DisplayClass71_28 { b = b }.b__73); } internal void b__71_39(bool b) { ModSet(new <>c__DisplayClass71_29 { b = b }.b__74); } internal void b__71_40(bool b) { ModSet(new <>c__DisplayClass71_30 { b = b }.b__75); } } [CompilerGenerated] private sealed class <>c__DisplayClass71_1 { public int v; internal void b__44() { Settings.VerticalFovOverride = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_10 { public float v; internal void b__53() { Settings.LightDistance = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_11 { public int v; internal void b__54() { Settings.PixelLightCount = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_12 { public string s; internal void b__55() { Settings.TextureQuality = TexValues[Array.IndexOf(TexOptions, s)]; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_13 { public string s; internal void b__56() { Settings.AnisotropicFiltering = AfValues[Array.IndexOf(AfOptions, s)]; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_14 { public float v; internal void b__57() { Settings.LODBias = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_15 { public float v; internal void b__58() { Settings.FogDistanceMultiplier = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_16 { public float v; internal void b__59() { Settings.ViewDistance = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_17 { public bool b; internal void b__60() { Settings.MotionBlurOverride = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_18 { public bool b; internal void b__61() { Settings.ChromaticAberration = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_19 { public bool b; internal void b__62() { Settings.LensDistortion = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_2 { public bool b; internal void b__45() { Settings.UltrawideUiFix = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_20 { public bool b; internal void b__63() { Settings.FilmGrain = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_21 { public bool b; internal void b__66() { Settings.Pixelation = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_22 { public int v; internal void b__67() { Settings.PerfExplosionShadows = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_23 { public int v; internal void b__68() { Settings.PerfItemLightShadows = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_24 { public int v; internal void b__69() { Settings.PerfAnimatedLightShadows = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_25 { public int v; internal void b__70() { Settings.PerfParticleShadows = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_26 { public int v; internal void b__71() { Settings.PerfTinyRendererCulling = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_27 { public int v; internal void b__72() { Settings.PerfPointLightShadows = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_28 { public bool b; internal void b__73() { Settings.ExtractionPointFlicker = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_29 { public bool b; internal void b__74() { Settings.DebugOverlay = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_3 { public string enumName; internal void b__46() { Settings.UpscaleModeSetting = Enum.Parse(enumName); } } [CompilerGenerated] private sealed class <>c__DisplayClass71_30 { public bool b; internal void b__75() { Settings.DiagnosticsEnabled = b; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_4 { public int v; internal void b__47() { Settings.RenderScale = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_5 { public float v; internal void b__48() { Settings.Sharpening = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_6 { public string s; internal void b__49() { Settings.AntiAliasingMode = Enum.Parse(s); } } [CompilerGenerated] private sealed class <>c__DisplayClass71_7 { public string s; internal void b__50() { Settings.ShadowQualitySetting = Enum.Parse(s); } } [CompilerGenerated] private sealed class <>c__DisplayClass71_8 { public float v; internal void b__51() { Settings.ShadowDistance = v; } } [CompilerGenerated] private sealed class <>c__DisplayClass71_9 { public int v; internal void b__52() { Settings.ShadowBudget = v; } } private static REPOPopupPage? _page; private static bool _initialized; private static bool _syncing; private static REPOSlider? _presetSlider; private static REPOSlider? _upscalerSlider; private static REPOSlider? _renderScaleSlider; private static REPOSlider? _sharpeningSlider; private static REPOSlider? _aaSlider; private static REPOToggle? _pixelationToggle; private static REPOSlider? _shadowQualitySlider; private static REPOSlider? _shadowDistanceSlider; private static REPOSlider? _shadowBudgetSlider; private static REPOSlider? _lodSlider; private static REPOSlider? _afSlider; private static REPOSlider? _lightsSlider; private static REPOSlider? _textureSlider; private static REPOSlider? _lightDistSlider; private static REPOSlider? _fogSlider; private static REPOSlider? _viewDistSlider; private static REPOToggle? _motionBlurToggle; private static REPOToggle? _caToggle; private static REPOToggle? _lensToggle; private static REPOToggle? _grainToggle; private static REPOToggle? _flickerToggle; private static REPOToggle? _overlayToggle; private static REPOToggle? _diagnosticsToggle; private static REPOSlider? _windowModeSlider; private static REPOSlider? _resolutionSlider; private static REPOSlider? _fpsSlider; private static REPOSlider? _gammaSlider; private static REPOSlider? _fovSlider; private static REPOToggle? _ultrawideUiToggle; private static REPOToggle? _vsyncToggle; private static REPOToggle? _bloomToggle; private static REPOToggle? _glitchToggle; private static REPOSlider? _perfExplosionSlider; private static REPOSlider? _perfItemLightSlider; private static REPOSlider? _perfAnimLightSlider; private static REPOSlider? _perfParticleSlider; private static REPOSlider? _perfTinySlider; private static REPOSlider? _perfPointLightSlider; private static Text? _statusText; private static Text? _autoTuneText; private static bool _benchmarkQueued; private static StatusTicker? _ticker; private static readonly string[] FpsOptions; private static readonly string[] PerfOptions; private static readonly int[] PerfValues; private static readonly string[] AfOptions; private static readonly int[] AfValues; private static readonly string[] TexOptions; private static readonly TextureRes[] TexValues; internal static bool IsGraphicsPageOpen { get; private set; } static MenuIntegration() { PerfOptions = new string[3] { "Auto", "Keep", "Disable" }; PerfValues = new int[3] { -1, 0, 1 }; AfOptions = new string[5] { "Off", "2x", "4x", "8x", "16x" }; AfValues = new int[5] { 0, 2, 4, 8, 16 }; TexOptions = new string[3] { "Quarter", "Half", "Full" }; TexValues = new TextureRes[3] { TextureRes.Quarter, TextureRes.Half, TextureRes.Full }; FpsOptions = new string[332]; for (int i = 0; i < 331; i++) { FpsOptions[i] = (30 + i).ToString(); } FpsOptions[331] = "Unlimited"; } internal static void Initialize() { _initialized = true; Settings.OnSettingsChanged += SyncModSettings; } [HarmonyPrefix] [HarmonyPatch(typeof(MenuPageSettings), "ButtonEventGraphics")] public static bool PrefixGraphics() { if (!_initialized) { return true; } MenuManager.instance.PageCloseAllAddedOnTop(); OpenPage(); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(MenuPageSettings), "ButtonEventAudio")] public static void PrefixAudio() { ClosePage(); } [HarmonyPrefix] [HarmonyPatch(typeof(MenuPageSettings), "ButtonEventGameplay")] public static void PrefixGameplay() { ClosePage(); } [HarmonyPrefix] [HarmonyPatch(typeof(MenuPageSettings), "ButtonEventControls")] public static void PrefixControls() { ClosePage(); } [HarmonyPrefix] [HarmonyPatch(typeof(MenuPageSettings), "ButtonEventBack")] public static void PrefixBack() { ClosePage(); } private static void ClosePage() { try { REPOPopupPage? page = _page; if (page != null) { page.ClosePage(true); } } catch { } StopTicker(); IsGraphicsPageOpen = false; } private static void OpenPage() { if ((Object)(object)_page == (Object)null) { CreatePage(); } _page.OpenPage(true); _page.menuPage.addedPageOnTop = true; SyncAll(); RefreshDynamicLabels(); StartTicker(); IsGraphicsPageOpen = true; } private static void StartTicker() { //IL_0013: 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_001e: Expected O, but got Unknown if (!((Object)(object)_ticker != (Object)null)) { GameObject val = new GameObject("REPOFidelity_MenuStatus"); Object.DontDestroyOnLoad((Object)val); _ticker = val.AddComponent(); } } private static void StopTicker() { if (!((Object)(object)_ticker == (Object)null)) { Object.Destroy((Object)(object)((Component)_ticker).gameObject); _ticker = null; } } private static string BuildStatusLine() { int outputWidth = Settings.OutputWidth; int outputHeight = Settings.OutputHeight; int resolvedRenderScale = Settings.ResolvedRenderScale; int num = Mathf.Max(1, outputWidth * resolvedRenderScale / 100); int num2 = Mathf.Max(1, outputHeight * resolvedRenderScale / 100); string text = Settings.ResolvedUpscaleMode switch { UpscaleMode.DLAA => "DLAA", UpscaleMode.DLSS => "DLSS", UpscaleMode.FSR_Temporal => "FSR", UpscaleMode.Off => "native", _ => Settings.ResolvedUpscaleMode.ToString(), }; string text2 = ((resolvedRenderScale == 100) ? $"{outputWidth}×{outputHeight} {text}" : $"{outputWidth}×{outputHeight} → {num}×{num2} ({text} {resolvedRenderScale}%)"); float smoothFps = Overlay.SmoothFps; float smoothMs = Overlay.SmoothMs; string text3; if (!SemiFunc.RunIsLevel() || smoothFps < 1f) { text3 = "waiting for gameplay"; } else { string arg = (Settings.CpuBound ? "CPU-bound" : "GPU-bound"); text3 = $"{arg} • {smoothMs:F1} ms / {smoothFps:F0} fps"; } return text3 + " • " + text2; } private static string BuildAutoTuneLabel() { if (_benchmarkQueued) { return "AUTO-TUNE QUEUED (WILL RUN ON NEXT LEVEL)"; } if (SemiFunc.RunIsLevel()) { return "AUTO-TUNE BENCHMARK (15s)"; } return "AUTO-TUNE — WILL QUEUE (START A GAME)"; } private static void RefreshDynamicLabels() { if ((Object)(object)_statusText != (Object)null) { _statusText.text = " " + BuildStatusLine(); } if ((Object)(object)_autoTuneText != (Object)null) { _autoTuneText.text = BuildAutoTuneLabel(); } } private static void CreatePage() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0ba4: Unknown result type (might be due to invalid IL or missing references) _page = MenuAPI.CreateREPOPopupPage("Graphics", true, false, 2f, (Vector2?)new Vector2(0f, 0f)); REPOPopupPage? page = _page; object obj = <>c.<>9__71_0; if (obj == null) { ScrollViewBuilderDelegate val = delegate(Transform sv) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) REPOLabel obj2 = MenuAPI.CreateREPOLabel("", sv, new Vector2(0f, 0f)); _statusText = ((Component)obj2).GetComponentInChildren(); return ((REPOElement)obj2).rectTransform; }; <>c.<>9__71_0 = val; obj = (object)val; } page.AddElementToScrollView((ScrollViewBuilderDelegate)obj, 0f, 0f); AddButton("RESET TO DEFAULT SETTINGS", delegate { Settings.Preset = QualityPreset.High; SyncAll(); }); AddLabel("Display"); AddStringSlider("Window Mode", "", new string[2] { "Fullscreen", "Windowed" }, "Fullscreen", delegate(string s) { GameSet((Setting)24, (s == "Windowed") ? 1 : 0, delegate { GraphicsManager.instance.UpdateWindowMode(true); }); }, out _windowModeSlider); int currentIndex; string[] availableResolutions = Settings.GetAvailableResolutions(out currentIndex); AddStringSlider("Resolution", "", availableResolutions, availableResolutions[currentIndex], delegate(string s) { if (!_syncing) { Settings.SetResolution(s); } }, out _resolutionSlider); AddModToggle("VSync", def: false, delegate(bool b) { GameSet((Setting)12, b ? 1 : 0, delegate { GraphicsManager.instance.UpdateVsync(); }); }, out _vsyncToggle); int num = DataDirector.instance.SettingValueFetch((Setting)19); string def = ((num <= 0) ? "Unlimited" : Mathf.Clamp(num, 30, 360).ToString()); AddStringSlider("Max FPS", "", FpsOptions, def, delegate(string s) { if (!_syncing) { int num8 = ((s == "Unlimited") ? (-1) : int.Parse(s)); DataDirector.instance.SettingValueSet((Setting)19, num8); GraphicsManager.instance.UpdateMaxFPS(); DataDirector.instance.SaveSettings(); } }, out _fpsSlider); AddIntSlider("Gamma", "Brightness", 0, 100, 40, "", delegate(int v) { GameSet((Setting)29, v, delegate { GraphicsManager.instance.UpdateGamma(); }); }, out _gammaSlider); AddIntSlider("Vertical FOV (0 = game default)", "Higher = wider view; lower = zoomed in", 0, 110, Settings.VerticalFovOverride, "°", delegate(int v) { ModSet(delegate { Settings.VerticalFovOverride = v; }); }, out _fovSlider); AddModToggle("Ultra-Wide UI Fix", Settings.UltrawideUiFix, delegate(bool b) { ModSet(delegate { Settings.UltrawideUiFix = b; }); }, out _ultrawideUiToggle); AddLabel("Quality"); string[] options = new string[7] { "Auto", "Potato", "Low", "Medium", "High", "Ultra", "Custom" }; AddStringSlider("Quality Preset", "Sets all options below", options, Settings.Preset.ToString(), delegate(string s) { if (!_syncing) { Settings.Preset = Enum.Parse(s); } }, out _presetSlider); AddLabel("Upscaling"); string[] availableUpscalerNames = GPUDetector.GetAvailableUpscalerNames(); string text = Settings.UpscaleModeSetting.ToString(); if (text == "DLAA") { text = "DLSS"; } if (text == "FSR_Temporal") { text = "FSR"; } if (Array.IndexOf(availableUpscalerNames, text) < 0) { text = "Auto"; } AddStringSlider("Upscaler", "DLSS at 100% = DLAA (native AA)", availableUpscalerNames, text, delegate(string s) { string enumName = ((s == "FSR") ? "FSR_Temporal" : s); ModSet(delegate { Settings.UpscaleModeSetting = Enum.Parse(enumName); }); }, out _upscalerSlider); AddIntSlider("Render Scale", "Resolution % before upscaling", 33, 100, Settings.RenderScale, "%", delegate(int v) { ModSet(delegate { Settings.RenderScale = v; }); }, out _renderScaleSlider); AddFloatSlider("Sharpening", "Post-upscale CAS", 0f, 1f, 2, Settings.Sharpening, "", delegate(float v) { ModSet(delegate { Settings.Sharpening = v; }); }, out _sharpeningSlider); string[] array = new string[4] { "Auto", "SMAA", "FXAA", "Off" }; string text2 = Settings.AntiAliasingMode.ToString(); if (Array.IndexOf(array, text2) < 0) { text2 = "Auto"; } AddStringSlider("Anti-Aliasing", "SMAA / FXAA", array, text2, delegate(string s) { string s5 = s; ModSet(delegate { Settings.AntiAliasingMode = Enum.Parse(s5); }); }, out _aaSlider); AddLabel("Shadows & Lighting"); AddStringSlider("Shadow Quality", "Shadow map resolution", Enum.GetNames(typeof(ShadowQuality)), Settings.ShadowQualitySetting.ToString(), delegate(string s) { string s4 = s; ModSet(delegate { Settings.ShadowQualitySetting = Enum.Parse(s4); }); }, out _shadowQualitySlider); AddFloatSlider("Shadow Distance", "", 5f, 200f, 0, Settings.ShadowDistance, "m", delegate(float v) { ModSet(delegate { Settings.ShadowDistance = v; }); }, out _shadowDistanceSlider); AddIntSlider("Shadow Limit (0 = unlimited)", "Caps nearby shadow-casting lights", 0, 50, Settings.ResolvedShadowBudget, "", delegate(int v) { ModSet(delegate { Settings.ShadowBudget = v; }); }, out _shadowBudgetSlider); AddFloatSlider("Light Distance", "", 10f, 100f, 0, Settings.LightDistance, "m", delegate(float v) { ModSet(delegate { Settings.LightDistance = v; }); }, out _lightDistSlider); AddIntSlider("Max Lights", "Per object", 1, 16, Settings.PixelLightCount, "", delegate(int v) { ModSet(delegate { Settings.PixelLightCount = v; }); }, out _lightsSlider); AddLabel("Textures & Detail"); int num2 = Array.IndexOf(TexValues, Settings.TextureQuality); if (num2 < 0) { num2 = 2; } AddStringSlider("Texture Quality", "", TexOptions, TexOptions[num2], delegate(string s) { string s3 = s; ModSet(delegate { Settings.TextureQuality = TexValues[Array.IndexOf(TexOptions, s3)]; }); }, out _textureSlider); int num3 = Array.IndexOf(AfValues, Settings.AnisotropicFiltering); if (num3 < 0) { num3 = 4; } AddStringSlider("Texture Filtering", "Anisotropic filtering", AfOptions, AfOptions[num3], delegate(string s) { string s2 = s; ModSet(delegate { Settings.AnisotropicFiltering = AfValues[Array.IndexOf(AfOptions, s2)]; }); }, out _afSlider); AddFloatSlider("Detail Distance", "LOD bias", 0.5f, 4f, 1, Settings.LODBias, "x", delegate(float v) { ModSet(delegate { Settings.LODBias = v; }); }, out _lodSlider); AddLabel("Environment"); AddFloatSlider("Fog Distance", "1.0 = vanilla; lower pulls fog closer for perf", 0.3f, 1.1f, 2, Settings.FogDistanceMultiplier, "x", delegate(float v) { ModSet(delegate { Settings.FogDistanceMultiplier = v; }); }, out _fogSlider); AddFloatSlider("Draw Distance (0 = auto)", "Camera far clip", 0f, 500f, 0, Settings.ViewDistance, "m", delegate(float v) { ModSet(delegate { Settings.ViewDistance = v; }); }, out _viewDistSlider); AddLabel("Post Processing"); AddModToggle("Motion Blur", Settings.MotionBlurOverride, delegate(bool b) { ModSet(delegate { Settings.MotionBlurOverride = b; }); }, out _motionBlurToggle); AddModToggle("Chromatic Aberration", Settings.ChromaticAberration, delegate(bool b) { ModSet(delegate { Settings.ChromaticAberration = b; }); }, out _caToggle); AddModToggle("Lens Distortion", Settings.LensDistortion, delegate(bool b) { ModSet(delegate { Settings.LensDistortion = b; }); }, out _lensToggle); AddModToggle("Film Grain", Settings.FilmGrain, delegate(bool b) { ModSet(delegate { Settings.FilmGrain = b; }); }, out _grainToggle); AddModToggle("Bloom", def: true, delegate(bool b) { GameSet((Setting)16, b ? 1 : 0, delegate { GraphicsManager.instance.UpdateBloom(); }); }, out _bloomToggle); AddModToggle("Glitch Loop", def: true, delegate(bool b) { GameSet((Setting)26, b ? 1 : 0, delegate { GraphicsManager.instance.UpdateGlitchLoop(); }); }, out _glitchToggle); AddModToggle("Pixelation (retro style)", Settings.Pixelation, delegate(bool b) { ModSet(delegate { Settings.Pixelation = b; }); }, out _pixelationToggle); AddLabel("Performance"); AddDynamicButton(BuildAutoTuneLabel(), delegate { if (_benchmarkQueued) { _benchmarkQueued = false; Settings.Preset = QualityPreset.High; RefreshDynamicLabels(); SyncAll(); } else { Settings.Preset = QualityPreset.Auto; if (SemiFunc.RunIsLevel()) { _page.ClosePage(false); if ((Object)(object)MenuManager.instance != (Object)null) { MenuManager.instance.PageCloseAllAddedOnTop(); } Settings.InvalidateAutoTune(); Settings.BenchmarkMode = true; } else { Settings.InvalidateAutoTune(); _benchmarkQueued = true; RefreshDynamicLabels(); } } }, out _autoTuneText); AddPerfSlider("Explosion Shadows", "Disable shadows on explosion lights", Settings.PerfExplosionShadows, delegate(int v) { ModSet(delegate { Settings.PerfExplosionShadows = v; }); }, out _perfExplosionSlider); AddPerfSlider("Item Light Shadows", "Disable shadows on handheld item lights", Settings.PerfItemLightShadows, delegate(int v) { ModSet(delegate { Settings.PerfItemLightShadows = v; }); }, out _perfItemLightSlider); AddPerfSlider("Animated Light Shadows", "Disable shadows on animated lights", Settings.PerfAnimatedLightShadows, delegate(int v) { ModSet(delegate { Settings.PerfAnimatedLightShadows = v; }); }, out _perfAnimLightSlider); AddPerfSlider("Particle Shadows", "Disable shadow casting on particles", Settings.PerfParticleShadows, delegate(int v) { ModSet(delegate { Settings.PerfParticleShadows = v; }); }, out _perfParticleSlider); AddPerfSlider("Small Object Shadows", "Disable shadows on tiny objects", Settings.PerfTinyRendererCulling, delegate(int v) { ModSet(delegate { Settings.PerfTinyRendererCulling = v; }); }, out _perfTinySlider); AddPerfSlider("Point Light Shadows", "Cull distant point-light shadows beyond fog", Settings.PerfPointLightShadows, delegate(int v) { ModSet(delegate { Settings.PerfPointLightShadows = v; }); }, out _perfPointLightSlider); AddModToggle("Fix Extraction Flicker", Settings.ExtractionPointFlicker, delegate(bool b) { ModSet(delegate { Settings.ExtractionPointFlicker = b; }); }, out _flickerToggle); AddModToggle("Debug Overlay", Settings.DebugOverlay, delegate(bool b) { ModSet(delegate { Settings.DebugOverlay = b; }); }, out _overlayToggle); AddModToggle("F9 Cost Probe", Settings.DiagnosticsEnabled, delegate(bool b) { ModSet(delegate { Settings.DiagnosticsEnabled = b; }); }, out _diagnosticsToggle); string[] keyOpts = new string[6] { "F10", "F9", "F8", "F7", "F6", "F5" }; KeyCode[] array2 = new KeyCode[6]; RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); KeyCode[] keyVals = (KeyCode[])(object)array2; int num4 = Array.IndexOf(keyVals, Settings.ToggleKey); if (num4 < 0) { num4 = 0; } AddStringSlider("Mod Toggle Key", "Disables mod for vanilla comparison", keyOpts, keyOpts[num4], delegate(string s) { int num7 = Array.IndexOf(keyOpts, s); if (num7 >= 0) { Settings.ToggleKey = keyVals[num7]; } }, out REPOSlider r); string[] f11Opts = new string[3] { "Full Opt Layer", "CPU Patches", "Light Diagnostics" }; F11Target[] f11Vals = new F11Target[3] { F11Target.FullOptLayer, F11Target.CpuPatches, F11Target.LightDiagnostics }; int num5 = Array.IndexOf(f11Vals, Settings.F11TargetSetting); if (num5 < 0) { num5 = 0; } AddStringSlider("F11 Target", "Which feature F11 toggles for A/B", f11Opts, f11Opts[num5], delegate(string s) { int num6 = Array.IndexOf(f11Opts, s); if (num6 >= 0) { Settings.F11TargetSetting = f11Vals[num6]; } }, out r); } private static void ModSet(Action a) { if (!_syncing) { a(); } } private static void GameSet(Setting setting, int value, Action update) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!_syncing) { DataDirector.instance.SettingValueSet(setting, value); update(); DataDirector.instance.SaveSettings(); } } private static void AddLabel(string text) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown string text2 = text; _page.AddElementToScrollView((ScrollViewBuilderDelegate)((Transform sv) => ((REPOElement)MenuAPI.CreateREPOLabel(text2, sv, Vector2.zero)).rectTransform), 0f, 0f); } private static void AddButton(string text, Action onClick, float xOffset = 38f) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown string text2 = text; Action onClick2 = onClick; _page.AddElementToScrollView((ScrollViewBuilderDelegate)((Transform sv) => ((REPOElement)MenuAPI.CreateREPOButton(text2, onClick2, sv, new Vector2(xOffset, 0f))).rectTransform), 0f, 0f); } private static void AddDynamicButton(string text, Action onClick, out Text? textOut, float xOffset = 38f) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown string text2 = text; Action onClick2 = onClick; Text captured = null; _page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(text2, onClick2, sv, new Vector2(xOffset, 0f)); captured = ((Component)val).GetComponentInChildren(); return ((REPOElement)val).rectTransform; }, 0f, 0f); textOut = captured; } private static void AddStringSlider(string text, string desc, string[] options, string def, Action cb, out REPOSlider? r) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown string text2 = text; string desc2 = desc; Action cb2 = cb; string[] options2 = options; string def2 = def; REPOSlider s = null; _page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) s = MenuAPI.CreateREPOSlider(text2, desc2, (Action)delegate(string v) { cb2(v); }, sv, options2, def2, Vector2.zero, "", "", (BarBehavior)0); return ((REPOElement)s).rectTransform; }, 0f, 0f); r = s; } private static void AddIntSlider(string text, string desc, int min, int max, int def, string post, Action cb, out REPOSlider? r) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown string text2 = text; string desc2 = desc; Action cb2 = cb; string post2 = post; REPOSlider s = null; _page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) s = MenuAPI.CreateREPOSlider(text2, desc2, (Action)delegate(int v) { cb2(v); }, sv, Vector2.zero, min, max, def, "", post2, (BarBehavior)0); return ((REPOElement)s).rectTransform; }, 0f, 0f); r = s; } private static void AddFloatSlider(string text, string desc, float min, float max, int prec, float def, string post, Action cb, out REPOSlider? r) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown string text2 = text; string desc2 = desc; Action cb2 = cb; string post2 = post; REPOSlider s = null; _page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) s = MenuAPI.CreateREPOSlider(text2, desc2, (Action)delegate(float v) { cb2(v); }, sv, Vector2.zero, min, max, prec, def, "", post2, (BarBehavior)0); return ((REPOElement)s).rectTransform; }, 0f, 0f); r = s; } private static void AddPerfSlider(string text, string desc, int current, Action cb, out REPOSlider? r) { Action cb2 = cb; int num = Array.IndexOf(PerfValues, current); if (num < 0) { num = 0; } AddStringSlider(text, desc, PerfOptions, PerfOptions[num], delegate(string s) { int num2 = Array.IndexOf(PerfOptions, s); if (num2 >= 0) { cb2(PerfValues[num2]); } }, out r); } private static void AddModToggle(string text, bool def, Action cb, out REPOToggle? r) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown string text2 = text; Action cb2 = cb; REPOToggle t = null; _page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform sv) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) t = MenuAPI.CreateREPOToggle(text2, (Action)delegate(bool b) { cb2(b); }, sv, Vector2.zero, "ON", "OFF", def); return ((REPOElement)t).rectTransform; }, 0f, 0f); r = t; } private static void SyncAll() { _syncing = true; try { SyncGame(); SyncMod(); } finally { _syncing = false; } } private static void SyncModSettings() { if ((Object)(object)_page == (Object)null) { return; } _syncing = true; try { SyncMod(); } finally { _syncing = false; } } private static void SyncGame() { int num = DataDirector.instance.SettingValueFetch((Setting)24); SetStr(_windowModeSlider, (num == 1) ? "Windowed" : "Fullscreen"); SetStr(_resolutionSlider, $"{Settings.OutputWidth}x{Settings.OutputHeight}"); REPOToggle? vsyncToggle = _vsyncToggle; if (vsyncToggle != null) { vsyncToggle.SetState(DataDirector.instance.SettingValueFetch((Setting)12) == 1, false); } int num2 = DataDirector.instance.SettingValueFetch((Setting)19); SetStr(_fpsSlider, (num2 <= 0) ? "Unlimited" : Mathf.Clamp(num2, 30, 360).ToString()); SetNum(_gammaSlider, DataDirector.instance.SettingValueFetch((Setting)29)); REPOToggle? bloomToggle = _bloomToggle; if (bloomToggle != null) { bloomToggle.SetState(DataDirector.instance.SettingValueFetch((Setting)16) == 1, false); } REPOToggle? glitchToggle = _glitchToggle; if (glitchToggle != null) { glitchToggle.SetState(DataDirector.instance.SettingValueFetch((Setting)26) == 1, false); } } private static void SyncMod() { SetStr(_presetSlider, Settings.Preset.ToString()); string text = Settings.UpscaleModeSetting.ToString(); if (text == "DLAA") { text = "DLSS"; } if (text == "FSR_Temporal") { text = "FSR"; } SetStr(_upscalerSlider, text); SetNum(_renderScaleSlider, Settings.ResolvedRenderScale); SetNum(_sharpeningSlider, Settings.Sharpening); string opt = ((Settings.AntiAliasingMode == AAMode.TAA) ? Settings.ResolvedAAMode.ToString() : Settings.AntiAliasingMode.ToString()); SetStr(_aaSlider, opt); REPOToggle? pixelationToggle = _pixelationToggle; if (pixelationToggle != null) { pixelationToggle.SetState(Settings.Pixelation, false); } SetStr(_shadowQualitySlider, Settings.ShadowQualitySetting.ToString()); SetNum(_shadowDistanceSlider, Settings.ShadowDistance); SetNum(_shadowBudgetSlider, Settings.ResolvedShadowBudget); SetNum(_lodSlider, Settings.LODBias); int num = Array.IndexOf(AfValues, Settings.AnisotropicFiltering); if (num >= 0) { SetStr(_afSlider, AfOptions[num]); } SetNum(_lightsSlider, Settings.PixelLightCount); int num2 = Array.IndexOf(TexValues, Settings.TextureQuality); if (num2 >= 0) { SetStr(_textureSlider, TexOptions[num2]); } SetNum(_lightDistSlider, Settings.LightDistance); SetNum(_fogSlider, Settings.FogDistanceMultiplier); SetNum(_viewDistSlider, Settings.ViewDistance); REPOToggle? motionBlurToggle = _motionBlurToggle; if (motionBlurToggle != null) { motionBlurToggle.SetState(Settings.MotionBlurOverride, false); } REPOToggle? caToggle = _caToggle; if (caToggle != null) { caToggle.SetState(Settings.ChromaticAberration, false); } REPOToggle? lensToggle = _lensToggle; if (lensToggle != null) { lensToggle.SetState(Settings.LensDistortion, false); } REPOToggle? grainToggle = _grainToggle; if (grainToggle != null) { grainToggle.SetState(Settings.FilmGrain, false); } REPOToggle? flickerToggle = _flickerToggle; if (flickerToggle != null) { flickerToggle.SetState(Settings.ExtractionPointFlicker, false); } REPOToggle? overlayToggle = _overlayToggle; if (overlayToggle != null) { overlayToggle.SetState(Settings.DebugOverlay, false); } REPOToggle? diagnosticsToggle = _diagnosticsToggle; if (diagnosticsToggle != null) { diagnosticsToggle.SetState(Settings.DiagnosticsEnabled, false); } SetNum(_fovSlider, Settings.VerticalFovOverride); REPOToggle? ultrawideUiToggle = _ultrawideUiToggle; if (ultrawideUiToggle != null) { ultrawideUiToggle.SetState(Settings.UltrawideUiFix, false); } SyncPerf(_perfExplosionSlider, Settings.PerfExplosionShadows); SyncPerf(_perfItemLightSlider, Settings.PerfItemLightShadows); SyncPerf(_perfAnimLightSlider, Settings.PerfAnimatedLightShadows); SyncPerf(_perfParticleSlider, Settings.PerfParticleShadows); SyncPerf(_perfTinySlider, Settings.PerfTinyRendererCulling); SyncPerf(_perfPointLightSlider, Settings.PerfPointLightShadows); } private static void SyncPerf(REPOSlider? s, int value) { int num = Array.IndexOf(PerfValues, value); if (num >= 0) { SetStr(s, PerfOptions[num]); } } private static void SetNum(REPOSlider? s, float v) { if (s != null) { s.SetValue(v, false); } } private static void SetStr(REPOSlider? s, string opt) { if (((s != null) ? s.stringOptions : null) != null) { int num = Array.IndexOf(s.stringOptions, opt); if (num >= 0) { s.SetValue((float)num, false); } } } } internal static class ModTiming { internal class Acc { public long Ticks; public int Calls; } internal struct Scope : IDisposable { private readonly Acc _acc; private readonly long _start; internal Scope(Acc acc) { _acc = acc; _start = Stopwatch.GetTimestamp(); } public void Dispose() { if (_acc != null) { _acc.Ticks += Stopwatch.GetTimestamp() - _start; _acc.Calls++; } } } [CompilerGenerated] private sealed class d__3 : IEnumerable<(string name, long ticks, int calls)>, IEnumerable, IEnumerator<(string name, long ticks, int calls)>, IEnumerator, IDisposable { private int <>1__state; private (string name, long ticks, int calls) <>2__current; private int <>l__initialThreadId; private Dictionary.Enumerator <>7__wrap1; (string, long, int) IEnumerator<(string, long, int)>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = default(Dictionary.Enumerator); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = _accs.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { KeyValuePair current = <>7__wrap1.Current; <>2__current = (current.Key, current.Value.Ticks, current.Value.Calls); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = default(Dictionary.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<(string name, long ticks, int calls)> IEnumerable<(string, long, int)>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__3(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<(string, long, int)>)this).GetEnumerator(); } } private static readonly Dictionary _accs = new Dictionary(); internal static void Reset() { foreach (Acc value in _accs.Values) { value.Ticks = 0L; value.Calls = 0; } } [IteratorStateMachine(typeof(d__3))] internal static IEnumerable<(string name, long ticks, int calls)> Read() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(-2); } internal static Scope Begin(string name) { if (!_accs.TryGetValue(name, out Acc value)) { value = new Acc(); _accs[name] = value; } return new Scope(value); } } internal class OptimizerBenchmark : MonoBehaviour { private class Result { public float AvgMs; public float AvgFps; public float P1Low; public readonly List Frames = new List(); public void Compute() { if (Frames.Count != 0) { float num = 0f; for (int i = 0; i < Frames.Count; i++) { num += Frames[i]; } AvgMs = num / (float)Frames.Count * 1000f; AvgFps = 1000f / AvgMs; Frames.Sort(); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)Frames.Count * 0.01f)); float num3 = 0f; for (int num4 = Frames.Count - 1; num4 >= Frames.Count - num2; num4--) { num3 += Frames[num4]; } P1Low = 1f / (num3 / (float)num2); } } } private class Accum { private readonly List _all = new List(); public void Add(Result r) { _all.AddRange(r.Frames); } public Result Compute() { Result result = new Result(); result.Frames.AddRange(_all); result.Compute(); return result; } } [CompilerGenerated] private sealed class d__28 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Result result; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0f; break; case 1: <>1__state = -1; break; } if (5__2 < 15f) { result.Frames.Add(Time.unscaledDeltaTime); 5__2 += Time.unscaledDeltaTime; <>2__current = null; <>1__state = 1; return true; } result.Compute(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__24 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OptimizerBenchmark <>4__this; private Accum 5__2; private Accum 5__3; private Accum 5__4; private int 5__5; private int 5__6; private int 5__7; private string 5__8; private Result 5__9; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; 5__4 = null; 5__8 = null; 5__9 = null; <>1__state = -2; } private bool MoveNext() { //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Expected O, but got Unknown int num = <>1__state; OptimizerBenchmark optimizerBenchmark = <>4__this; Result vanilla; Result gpuGc; Result allOn; string text; string path; switch (num) { default: return false; case 0: <>1__state = -1; Running = true; Save(); Plugin.Log.LogInfo((object)$"=== FIDELITY BENCHMARK ({2}x {15f}s) ==="); 5__2 = new Accum(); 5__3 = new Accum(); 5__4 = new Accum(); 5__5 = 6; 5__6 = 0; optimizerBenchmark._benchStartTime = Time.unscaledTime; optimizerBenchmark._benchExpectedDuration = (float)5__5 * 18f; 5__7 = 0; goto IL_033b; case 1: <>1__state = -1; 5__9 = new Result(); <>2__current = optimizerBenchmark.Measure(5__9); <>1__state = 2; return true; case 2: <>1__state = -1; 5__2.Add(5__9); 5__6++; Settings.ModEnabled = true; ForceCpu(on: false); SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); Glitch(); Status = 5__8 + ": GPU/GC only"; Progress = (float)5__6 / (float)5__5; Plugin.Log.LogInfo((object)Status); <>2__current = optimizerBenchmark.Settle(); <>1__state = 3; return true; case 3: <>1__state = -1; 5__9 = new Result(); <>2__current = optimizerBenchmark.Measure(5__9); <>1__state = 4; return true; case 4: <>1__state = -1; 5__3.Add(5__9); 5__6++; Settings.ModEnabled = true; ForceCpu(on: true); SceneOptimizer.Apply(); Glitch(); Status = 5__8 + ": All ON"; Progress = (float)5__6 / (float)5__5; Plugin.Log.LogInfo((object)Status); <>2__current = optimizerBenchmark.Settle(); <>1__state = 5; return true; case 5: <>1__state = -1; 5__9 = new Result(); <>2__current = optimizerBenchmark.Measure(5__9); <>1__state = 6; return true; case 6: <>1__state = -1; 5__4.Add(5__9); 5__6++; 5__8 = null; 5__9 = null; 5__7++; goto IL_033b; case 7: { <>1__state = -1; Status = ""; return false; } IL_033b: if (5__7 < 2) { 5__8 = $"Pass {5__7 + 1}/{2}"; Settings.ModEnabled = false; ForceCpu(on: false); SceneOptimizer.Apply(); Glitch(); Status = 5__8 + ": Vanilla (mod OFF)"; Progress = (float)5__6 / (float)5__5; Plugin.Log.LogInfo((object)Status); <>2__current = optimizerBenchmark.Settle(); <>1__state = 1; return true; } Restore(); SceneOptimizer.Apply(); if (Settings.ModEnabled) { QualityPatch.ApplyQualitySettings(); } Glitch(); vanilla = 5__2.Compute(); gpuGc = 5__3.Compute(); allOn = 5__4.Compute(); text = BuildReport(vanilla, gpuGc, allOn); path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "optimizer_benchmark.txt"); try { File.WriteAllText(path, text); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Report save failed: " + ex.Message)); } Plugin.Log.LogInfo((object)("\n" + text)); Status = "Done! optimizer_benchmark.txt"; Progress = 1f; Running = false; <>2__current = (object)new WaitForSeconds(5f); <>1__state = 7; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__23 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OptimizerBenchmark <>4__this; private IEnumerator 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; OptimizerBenchmark optimizerBenchmark = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; 5__2 = optimizerBenchmark.Run(); } bool flag; try { flag = 5__2.MoveNext(); } catch (Exception arg) { Plugin.Log.LogError((object)$"Benchmark failed: {arg}"); Restore(); Running = false; Status = "ERROR"; return false; } if (!flag) { return false; } <>2__current = 5__2.Current; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__27 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__27(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0; goto IL_0052; case 1: <>1__state = -1; 5__2++; goto IL_0052; case 2: { <>1__state = -1; return false; } IL_0052: if (5__2 < 5) { <>2__current = null; <>1__state = 1; return true; } <>2__current = (object)new WaitForSeconds(3f); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static string Status = ""; internal static float Progress; private const float WarmupSeconds = 3f; private const float MeasureSeconds = 15f; private const int Passes = 2; private static bool _savedModEnabled; private static int _savedCpuMode; private float _benchStartTime; private float _benchExpectedDuration; internal static OptimizerBenchmark? Instance { get; private set; } internal static bool Running { get; private set; } private void Update() { if (Running && !(_benchExpectedDuration <= 0f)) { float num = Mathf.Clamp01((Time.unscaledTime - _benchStartTime) / _benchExpectedDuration); if (num > Progress) { Progress = num; } } } internal static void Launch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (!Running) { if ((Object)(object)Instance == (Object)null) { GameObject val = new GameObject("REPOFidelity_OptimizerBenchmark"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent(); } ((MonoBehaviour)Instance).StartCoroutine(Instance.RunSafe()); } } internal static void Abort() { if (Running) { if ((Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StopAllCoroutines(); } Restore(); Running = false; Status = "Aborted"; } } private static void Save() { _savedModEnabled = Settings.ModEnabled; _savedCpuMode = Settings.CpuPatchMode; } private static void Restore() { Settings.ModEnabled = _savedModEnabled; Settings.CpuPatchMode = _savedCpuMode; Settings.UpdateCpuGate(); } private static void ForceCpu(bool on) { Settings.CpuPatchMode = (on ? 1 : 0); Settings.UpdateCpuGate(); } [IteratorStateMachine(typeof(d__23))] private IEnumerator RunSafe() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0) { <>4__this = this }; } [IteratorStateMachine(typeof(d__24))] private IEnumerator Run() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__24(0) { <>4__this = this }; } private static string BuildReport(Result vanilla, Result gpuGc, Result allOn) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("╔══════════════════════════════════════════════════════════════╗"); stringBuilder.AppendLine("║ REPO FIDELITY — FULL BENCHMARK REPORT ║"); stringBuilder.AppendLine("╚══════════════════════════════════════════════════════════════╝"); stringBuilder.AppendLine(); stringBuilder.AppendLine($" Date: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); stringBuilder.AppendLine(" GPU: " + SystemInfo.graphicsDeviceName); stringBuilder.AppendLine($" VRAM: {SystemInfo.graphicsMemorySize}MB"); stringBuilder.AppendLine($" API: {SystemInfo.graphicsDeviceType}"); stringBuilder.AppendLine($" CPU: {SystemInfo.processorType} ({SystemInfo.processorCount} threads)"); stringBuilder.AppendLine($" RAM: {SystemInfo.systemMemorySize}MB"); stringBuilder.AppendLine($" Platform: {Application.platform}"); stringBuilder.AppendLine($" Resolution: {Screen.width}x{Screen.height}"); stringBuilder.AppendLine($" Passes: {2} x {15f}s (warmup {3f}s)"); stringBuilder.AppendLine(" CPU gate: " + ((Settings.CpuPatchMode == -1) ? "Auto (>8ms)" : ((Settings.CpuPatchMode == 1) ? "Forced ON" : "Forced OFF"))); stringBuilder.AppendLine(); float num = vanilla.AvgMs - gpuGc.AvgMs; float num2 = gpuGc.AvgMs - allOn.AvgMs; float num3 = vanilla.AvgMs - allOn.AvgMs; float num4 = allOn.AvgFps - vanilla.AvgFps; float num5 = ((vanilla.AvgMs > 0f) ? (num3 / vanilla.AvgMs * 100f) : 0f); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); stringBuilder.AppendLine(" RESULTS (averaged across passes)"); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); stringBuilder.AppendLine($" Vanilla (mod OFF): {vanilla.AvgFps,6:F1} FPS {vanilla.AvgMs,7:F2}ms 1%low: {vanilla.P1Low,5:F1} N={vanilla.Frames.Count}"); stringBuilder.AppendLine($" GPU/GC only: {gpuGc.AvgFps,6:F1} FPS {gpuGc.AvgMs,7:F2}ms 1%low: {gpuGc.P1Low,5:F1} N={gpuGc.Frames.Count}"); stringBuilder.AppendLine($" All ON: {allOn.AvgFps,6:F1} FPS {allOn.AvgMs,7:F2}ms 1%low: {allOn.P1Low,5:F1} N={allOn.Frames.Count}"); stringBuilder.AppendLine(); stringBuilder.AppendLine($" GPU/GC savings: {num:+0.000;-0.000}ms ({vanilla.AvgFps:F1} -> {gpuGc.AvgFps:F1} FPS)"); stringBuilder.AppendLine($" CPU patch savings: {num2:+0.000;-0.000}ms ({gpuGc.AvgFps:F1} -> {allOn.AvgFps:F1} FPS)"); stringBuilder.AppendLine($" Total improvement: {num3:+0.000;-0.000}ms ({num4:+0.0;-0.0} FPS, {num5:+0.0;-0.0}%)"); stringBuilder.AppendLine(); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); stringBuilder.AppendLine(" OPTIMIZATIONS INCLUDED"); stringBuilder.AppendLine("──────────────────────────────────────────────────────────────"); stringBuilder.AppendLine(" GPU/GC:"); stringBuilder.AppendLine(" GPU instancing, shadow culling, layer distance culling"); stringBuilder.AppendLine(" GrabberComponentCache, RayCheck/ForceGrab NonAlloc"); stringBuilder.AppendLine(" Quality overrides (shadows, LOD, AF, lights, fog)"); stringBuilder.AppendLine(" CPU (auto-enabled when frame time > 8ms):"); stringBuilder.AppendLine(" EnemyDirector throttle, RoomVolume NonAlloc"); stringBuilder.AppendLine(" SemiFunc cache, PhysGrab fix, LightManager batch"); stringBuilder.AppendLine(); return stringBuilder.ToString(); } private static void Glitch() { CameraGlitch instance = CameraGlitch.Instance; if (!((Object)(object)instance == (Object)null)) { if ((Object)(object)instance.ActiveParent != (Object)null) { instance.ActiveParent.SetActive(true); } instance.PlayShort(); } } [IteratorStateMachine(typeof(d__27))] private IEnumerator Settle() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__27(0); } [IteratorStateMachine(typeof(d__28))] private IEnumerator Measure(Result result) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__28(0) { result = result }; } } internal static class Overlay { private struct NativeLine { public GameObject Go; public TextMeshProUGUI Text; public RectTransform Rt; public RectTransform? ScanRt; public float CurrentY; public float TargetY; public bool WasVisible; } private struct LineData { public string Text; public Col Color; public LineData(string text, Col color) { Text = text; Color = color; } } private enum Col { White, Title, Info, Warn, Dim } private static GameObject? _root; private static readonly List _nativeLines = new List(); private static RectTransform? _rootRt; private static RectTransform? _progressBgNative; private static RectTransform? _progressFillNative; private static Image? _progressFillImg; private static TMP_FontAsset? _gameFont; private static Sprite? _scanlineSprite; private static bool _nativeActive; private static readonly List _lines = new List(); private static bool _showProgress; private static float _progress; private static Color _progressColor; private static float _fpsAccum; private static float _fpsTimer; private static int _fpsFrames; private static float _smoothFps; private static float _smoothMs; private const float SlideSpeed = 6f; private const float HideOffsetY = -40f; private const float FontSize = 14f; private const float LineH = 20f; private const float TextWidth = 500f; private const float BaseX = 12f; private const float BaseY = 110f; private static GUIStyle? _styleTitle; private static GUIStyle? _shadowTitle; private static GUIStyle? _styleInfo; private static GUIStyle? _shadowInfo; private static GUIStyle? _styleWarn; private static GUIStyle? _shadowWarn; private static GUIStyle? _styleDim; private static GUIStyle? _shadowDim; private static int _lastScreenH; internal static float SmoothFps => _smoothFps; internal static float SmoothMs => _smoothMs; internal static void UpdateLines() { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) _fpsAccum += Time.unscaledDeltaTime; _fpsFrames++; _fpsTimer += Time.unscaledDeltaTime; if (_fpsTimer >= 0.5f) { _smoothMs = _fpsAccum / (float)_fpsFrames * 1000f; _smoothFps = 1000f / Mathf.Max(_smoothMs, 0.001f); _fpsAccum = 0f; _fpsFrames = 0; _fpsTimer = 0f; } _lines.Clear(); _showProgress = false; if (UpscalerManager.RepoHdDetected) { _lines.Add(new LineData("REPO HD DETECTED - REMOVE", Col.Warn)); } if (UpscalerManager.BenchmarkActive) { _showProgress = true; _progress = UpscalerManager.BenchmarkProgress; _progressColor = new Color(0.9f, 0.35f, 0.35f); string text = (UpscalerManager.AutoBenchmarkRunning ? "AUTO-TUNING" : "BENCHMARKING"); _lines.Add(new LineData($"{text} {Mathf.RoundToInt(_progress * 100f)}% {_smoothFps:F0} FPS {_smoothMs:F1}ms", Col.Warn)); } if (OptimizerBenchmark.Running || !string.IsNullOrEmpty(OptimizerBenchmark.Status)) { _lines.Add(new LineData("OPTIMIZER " + OptimizerBenchmark.Status, Col.Info)); if (OptimizerBenchmark.Running) { _showProgress = true; _progress = OptimizerBenchmark.Progress; _progressColor = new Color(0.35f, 0.85f, 0.4f); } } if (CostProbe.Running || !string.IsNullOrEmpty(CostProbe.Status)) { _lines.Add(new LineData(CostProbe.Status, Col.Info)); if (CostProbe.Running) { _showProgress = true; _progress = CostProbe.Progress; _progressColor = new Color(0.4f, 0.7f, 0.95f); } _nativeActive = TryUpdateNative(); return; } if (!Settings.ModEnabled) { _lines.Add(new LineData($"FIDELITY OFF ({Settings.ToggleKey}) {_smoothFps:F0} FPS {_smoothMs:F1}ms", Col.Warn)); } else if (!Settings.OptimizationsEnabled) { _lines.Add(new LineData($"OPTIMIZATIONS OFF (F11) {_smoothFps:F0} FPS {_smoothMs:F1}ms", Col.Warn)); } else if (Settings.CpuPatchesF11Disabled) { _lines.Add(new LineData($"CPU PATCHES OFF (F11) {_smoothFps:F0} FPS {_smoothMs:F1}ms", Col.Warn)); } if (Settings.ModEnabled && Settings.DebugOverlay) { string text2 = Settings.Preset.ToString().ToUpper(); string text3 = Settings.ResolvedUpscaleMode.ToString(); string text4 = ((Settings.ResolvedAAMode != AAMode.Off) ? $" {Settings.ResolvedAAMode}" : ""); string text5 = ((UpscalerManager.BenchmarkActive || OptimizerBenchmark.Running) ? "" : $" {_smoothFps:F0} FPS {_smoothMs:F1}ms"); _lines.Add(new LineData("[" + text2 + "] " + text3 + text4 + text5, Col.Title)); string text6 = (Settings.CpuPatchesActive ? "ON" : "OFF"); string text7 = Settings.CpuPatchMode switch { 1 => "FORCED", 0 => "FORCED", _ => "AUTO", }; _lines.Add(new LineData($"SH:{Settings.ResolvedShadowQuality}/{Settings.ResolvedShadowDistance:F0}m " + $"L:{Settings.ResolvedPixelLightCount} LOD:{Settings.ResolvedLODBias:F1} CPU:{text6}({text7})", Col.Dim)); } _nativeActive = TryUpdateNative(); } internal static void Draw() { if (!_nativeActive && _lines.Count != 0) { DrawOnGUI(); } } private static bool TryUpdateNative() { //IL_00eb: 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_0200: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)HUDCanvas.instance == (Object)null) { ClearNative(); return false; } if ((Object)(object)_root == (Object)null) { _nativeLines.Clear(); BuildNative(); } if ((Object)(object)_root == (Object)null) { return false; } while (_nativeLines.Count < _lines.Count) { _nativeLines.Add(CreateNativeLine(_nativeLines.Count)); } float unscaledDeltaTime = Time.unscaledDeltaTime; float num = (_showProgress ? 10f : 0f); for (int i = 0; i < _nativeLines.Count; i++) { NativeLine value = _nativeLines[i]; bool num2 = i < _lines.Count; if (num2) { value.Go.SetActive(true); ((TMP_Text)value.Text).text = _lines[i].Text; ((Graphic)value.Text).color = GetColor(_lines[i].Color); float num3 = (value.TargetY = num + 110f + (float)(_lines.Count - 1 - i) * 20f); if (!value.WasVisible) { value.CurrentY = num3 + -40f; } value.WasVisible = true; } else { value.TargetY = value.CurrentY + -40f; if (value.WasVisible) { value.WasVisible = false; } } value.CurrentY = Mathf.Lerp(value.CurrentY, value.TargetY, unscaledDeltaTime * 6f); if (!num2 && Mathf.Abs(value.CurrentY - value.TargetY) < 0.5f) { value.Go.SetActive(false); continue; } value.Rt.anchoredPosition = new Vector2(0f, value.CurrentY); if ((Object)(object)value.ScanRt != (Object)null && ((TMP_Text)value.Text).preferredWidth > 0f) { value.ScanRt.sizeDelta = new Vector2(((TMP_Text)value.Text).preferredWidth + 4f, 0f); } _nativeLines[i] = value; } _root.SetActive(_lines.Count > 0 || AnyAnimating()); if ((Object)(object)_progressBgNative != (Object)null) { ((Component)_progressBgNative).gameObject.SetActive(_showProgress); if (_showProgress && (Object)(object)_progressFillNative != (Object)null && (Object)(object)_progressFillImg != (Object)null) { _progressFillNative.anchorMax = new Vector2(Mathf.Clamp01(_progress), 1f); ((Graphic)_progressFillImg).color = _progressColor; } } return true; } private static bool AnyAnimating() { for (int i = 0; i < _nativeLines.Count; i++) { if (_nativeLines[i].Go.activeSelf) { return true; } } return false; } private static void BuildNative() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_005e: 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_007c: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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) //IL_010b: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)HUDCanvas.instance == (Object)null)) { FindGameAssets(); if (!((Object)(object)_gameFont == (Object)null)) { _root = new GameObject("FidelityOverlay"); _root.transform.SetParent((Transform)(object)HUDCanvas.instance.rect, false); _rootRt = _root.AddComponent(); _rootRt.anchorMin = Vector2.zero; _rootRt.anchorMax = Vector2.zero; _rootRt.pivot = Vector2.zero; _rootRt.anchoredPosition = new Vector2(12f, 0f); _rootRt.sizeDelta = new Vector2(520f, 200f); GameObject val = new GameObject("ProgressBg"); val.transform.SetParent((Transform)(object)_rootRt, false); _progressBgNative = val.AddComponent(); _progressBgNative.anchorMin = Vector2.zero; _progressBgNative.anchorMax = new Vector2(0f, 0f); _progressBgNative.pivot = Vector2.zero; _progressBgNative.anchoredPosition = new Vector2(0f, 102f); _progressBgNative.sizeDelta = new Vector2(220f, 3f); Image obj = val.AddComponent(); ((Graphic)obj).color = new Color(0.15f, 0.15f, 0.15f, 0.5f); ((Graphic)obj).raycastTarget = false; val.SetActive(false); GameObject val2 = new GameObject("Fill"); val2.transform.SetParent((Transform)(object)_progressBgNative, false); _progressFillNative = val2.AddComponent(); _progressFillNative.anchorMin = Vector2.zero; _progressFillNative.anchorMax = new Vector2(0f, 1f); _progressFillNative.pivot = new Vector2(0f, 0.5f); _progressFillNative.offsetMin = Vector2.zero; _progressFillNative.offsetMax = Vector2.zero; _progressFillImg = val2.AddComponent(); ((Graphic)_progressFillImg).raycastTarget = false; Plugin.Log.LogInfo((object)"Overlay: native HUD created"); } } } private static NativeLine CreateNativeLine(int index) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0034: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"FidelityLine{index}"); val.transform.SetParent(_root.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.zero; val2.pivot = new Vector2(0f, 0f); val2.anchoredPosition = new Vector2(0f, -40f); val2.sizeDelta = new Vector2(500f, 20f); TextMeshProUGUI val3 = val.AddComponent(); ((TMP_Text)val3).font = _gameFont; ((TMP_Text)val3).fontSize = 14f; ((TMP_Text)val3).fontStyle = (FontStyles)1; ((TMP_Text)val3).alignment = (TextAlignmentOptions)1025; ((TMP_Text)val3).overflowMode = (TextOverflowModes)0; ((Graphic)val3).raycastTarget = false; ((TMP_Text)val3).enableWordWrapping = false; RectTransform val4 = null; if ((Object)(object)_scanlineSprite != (Object)null) { GameObject val5 = new GameObject("Scanlines"); val5.transform.SetParent(val.transform, false); val4 = val5.AddComponent(); val4.anchorMin = Vector2.zero; val4.anchorMax = new Vector2(0f, 1f); val4.pivot = new Vector2(0f, 0.5f); val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; val4.sizeDelta = new Vector2(10f, 0f); Image obj = val5.AddComponent(); obj.sprite = _scanlineSprite; obj.type = (Type)2; ((Graphic)obj).raycastTarget = false; val5.AddComponent(); } NativeLine result = default(NativeLine); result.Go = val; result.Text = val3; result.Rt = val2; result.ScanRt = val4; result.CurrentY = -40f; result.TargetY = -40f; result.WasVisible = false; return result; } private static void FindGameAssets() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_gameFont != (Object)null) { return; } TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll(); foreach (TextMeshProUGUI val in array) { if ((Object)(object)((TMP_Text)val).font != (Object)null) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).isLoaded) { _gameFont = ((TMP_Text)val).font; break; } } } UIScanlines[] array2 = Resources.FindObjectsOfTypeAll(); for (int i = 0; i < array2.Length; i++) { Image component = ((Component)array2[i]).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null) { _scanlineSprite = component.sprite; Plugin.Log.LogInfo((object)("Overlay: scanline sprite '" + ((Object)_scanlineSprite).name + "'")); break; } } if ((Object)(object)_gameFont != (Object)null) { Plugin.Log.LogInfo((object)("Overlay: game font '" + ((Object)_gameFont).name + "'")); } } private static void ClearNative() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; _nativeLines.Clear(); } private static void DrawOnGUI() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) EnsureOnGUIStyles(); float num = Mathf.Max((float)Screen.height / 1080f, 0.5f); float num2 = 20f * num; float num3 = 28f * num; float num4 = 1.5f * num; float num5 = (float)_lines.Count * num3 + (_showProgress ? (10f * num) : 0f); float num6 = (float)Screen.height - num5 - 50f * num; Rect val = default(Rect); for (int i = 0; i < _lines.Count; i++) { GetOnGUIStyles(_lines[i].Color, out GUIStyle text, out GUIStyle shadow); ((Rect)(ref val))..ctor(num2, num6, (float)Screen.width * 0.5f, num3); GUI.Label(new Rect(((Rect)(ref val)).x + num4, ((Rect)(ref val)).y + num4, ((Rect)(ref val)).width, ((Rect)(ref val)).height), _lines[i].Text, shadow); GUI.Label(val, _lines[i].Text, text); num6 += num3; } if (_showProgress) { float num7 = 220f * num; GUI.DrawTexture(new Rect(num2, num6 + 4f * num, num7, 3f * num), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, false, 0f, new Color(0.1f, 0.1f, 0.1f, 0.5f), 0f, 0f); GUI.DrawTexture(new Rect(num2, num6 + 4f * num, num7 * Mathf.Clamp01(_progress), 3f * num), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, false, 0f, _progressColor, 0f, 0f); } } private static Color GetColor(Col c) { //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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) return (Color)(c switch { Col.Title => new Color(0.3f, 0.92f, 0.4f), Col.Info => new Color(0.35f, 0.88f, 0.45f), Col.Warn => new Color(0.95f, 0.35f, 0.3f), Col.Dim => new Color(0.45f, 0.52f, 0.45f), _ => new Color(0.9f, 0.95f, 0.9f), }); } private static void EnsureOnGUIStyles() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (_styleTitle == null || _lastScreenH != Screen.height) { _lastScreenH = Screen.height; float num = Mathf.Max((float)Screen.height / 1080f, 0.5f); int size = Mathf.Max(Mathf.RoundToInt(16f * num), 11); int size2 = Mathf.Max(Mathf.RoundToInt(13f * num), 10); MakePair(size, GetColor(Col.Title), out _styleTitle, out _shadowTitle); MakePair(size, GetColor(Col.Info), out _styleInfo, out _shadowInfo); MakePair(size, GetColor(Col.Warn), out _styleWarn, out _shadowWarn); MakePair(size2, GetColor(Col.Dim), out _styleDim, out _shadowDim); } } private static void MakePair(int size, Color color, out GUIStyle text, out GUIStyle shadow) { //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_000d: 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_001c: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) text = new GUIStyle { fontSize = size, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; text.normal.textColor = color; shadow = new GUIStyle(text); shadow.normal.textColor = new Color(0f, 0f, 0f, 0.55f); } private static void GetOnGUIStyles(Col c, out GUIStyle text, out GUIStyle shadow) { (text, shadow) = c switch { Col.Title => (_styleTitle, _shadowTitle), Col.Info => (_styleInfo, _shadowInfo), Col.Warn => (_styleWarn, _shadowWarn), Col.Dim => (_styleDim, _shadowDim), _ => (_styleTitle, _shadowTitle), }; } } [BepInPlugin("Vippy.REPOFidelity", "REPO Fidelity", "1.6.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "Vippy.REPOFidelity"; public const string PluginName = "REPO Fidelity"; internal static ManualLogSource Log; internal static Plugin Instance; private Harmony? _harmony; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Instance = this; if (Chainloader.PluginInfos.ContainsKey("BlueAmulet.REPO_HD")) { Log.LogWarning((object)"REPO_HD detected! REPO Fidelity covers all REPO_HD features. Please remove REPO_HD to avoid conflicts."); } ((BaseUnityPlugin)this).Config.Bind("_", "Hidden", true, new ConfigDescription("", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" })); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; Settings.Init(); GPUDetector.Detect(); Settings.ResolveAutoDefaults(); _harmony = new Harmony("Vippy.REPOFidelity"); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { try { _harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogWarning((object)("Harmony patch failed for " + type.Name + ": " + ex.Message)); } } Log.LogInfo((object)"REPO Fidelity v1.6.3 loaded"); Log.LogInfo((object)$"GPU: {GPUDetector.GpuName} ({GPUDetector.Vendor}, Tier: {GPUDetector.Tier}, VRAM: {GPUDetector.VramMb}MB)"); Log.LogInfo((object)$"CPU: {SystemInfo.processorType} ({SystemInfo.processorCount} threads)"); Log.LogInfo((object)$"RAM: {SystemInfo.systemMemorySize}MB | Platform: {Application.platform} | API: {SystemInfo.graphicsDeviceType}"); Log.LogInfo((object)$"DLSS Available: {GPUDetector.DlssAvailable}"); if (Chainloader.PluginInfos.ContainsKey("nickklmao.menulib")) { MenuIntegration.Initialize(); Log.LogInfo((object)"MenuLib detected — settings added to graphics menu"); } } private void LateUpdate() { Settings.UpdateCpuGate(); Overlay.UpdateLines(); } private void OnGUI() { Overlay.Draw(); } } internal enum QualityPreset { Potato, Low, Medium, High, Ultra, Custom, Auto } internal enum UpscaleMode { Auto, DLAA, DLSS, FSR4, FSR_Temporal, FSR, Off } internal enum AAMode { Auto, TAA, SMAA, FXAA, Off } internal enum ShadowQuality { Low, Medium, High, Ultra } internal enum TextureRes { Full, Half, Quarter } internal enum F11Target { FullOptLayer, CpuPatches, LightDiagnostics } internal static class Settings { internal enum PerfOpt { ExplosionShadows, ParticleShadows, ItemLightShadows, TinyRendererCulling, AnimatedLightShadows, DistanceShadowCulling, FlashlightShadowBudget, PointLightShadows } private enum UpscaleTier { Budget, Quality, NativeAA } [CompilerGenerated] private sealed class d__184 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int targetW; public int targetH; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__184(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0; break; case 1: <>1__state = -1; 5__2++; break; } if (5__2 < 30 && (Screen.width != targetW || Screen.height != targetH)) { <>2__current = null; <>1__state = 1; return true; } OnChanged(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static SettingsFile _file = null; private static bool _initComplete; internal static bool ModEnabled = true; internal static bool OptimizationsEnabled = true; internal static bool AllocationFixesEnabled = true; internal static bool CpuPatchesF11Disabled; private static bool _cpuPatchesActiveRaw = true; private static float _cpuGateTimer; private static float _cpuGateAccum; private static int _cpuGateFrames; private const float CpuGateThresholdMs = 8f; internal static int ResolvedShadowBudget; internal const float PlayableFogFloor = 0.5f; internal static UpscaleMode ResolvedUpscaleMode; internal static int ResolvedRenderScale; internal static AAMode ResolvedAAMode; internal static ShadowQuality ResolvedShadowQuality; internal static float ResolvedShadowDistance; internal static float ResolvedLODBias; internal static int ResolvedPixelLightCount; internal static float ResolvedLightDistance; internal static float ResolvedFogMultiplier; internal static float ResolvedEffectiveFogEnd; internal static float ResolvedViewDistance; internal static int ResolvedAnisotropicFiltering; internal static TextureRes ResolvedTextureQuality; private static AutoTuneData _autoTune = new AutoTuneData(); private static string _autoTunePath = ""; private static int _suppressTweakRevert; private static SettingsData D => _file.Data; internal static QualityPreset Preset { get { return (QualityPreset)D.preset; } set { D.preset = (int)value; _file.Save(); OnChanged(); } } internal static int OutputWidth { get { if (D.resWidth <= 0) { return Screen.width; } return D.resWidth; } set { D.resWidth = value; _file.Save(); OnChanged(); } } internal static int OutputHeight { get { if (D.resHeight <= 0) { return Screen.height; } return D.resHeight; } set { D.resHeight = value; _file.Save(); OnChanged(); } } internal static UpscaleMode UpscaleModeSetting { get { return (UpscaleMode)D.upscaler; } set { D.upscaler = (int)value; _file.Save(); OnSettingTweaked(); } } internal static int RenderScale { get { return D.renderScale; } set { D.renderScale = Mathf.Clamp(value, 33, 100); _file.Save(); OnSettingTweaked(); } } internal static float Sharpening { get { return D.sharpening; } set { D.sharpening = Mathf.Clamp(value, 0f, 1f); _file.Save(); if (_initComplete && Preset != QualityPreset.Custom) { _file.SuppressEvents(delegate { D.preset = 5; }); _file.Save(); } } } internal static AAMode AntiAliasingMode { get { return (AAMode)D.aaMode; } set { D.aaMode = (int)value; _file.Save(); OnSettingTweaked(); } } internal static bool Pixelation { get { return D.pixelation; } set { D.pixelation = value; _file.Save(); OnSettingTweaked(); } } internal static ShadowQuality ShadowQualitySetting { get { return (ShadowQuality)D.shadowQuality; } set { D.shadowQuality = (int)value; _file.Save(); OnSettingTweaked(); } } internal static float ShadowDistance { get { return D.shadowDistance; } set { D.shadowDistance = Mathf.Clamp(value, 5f, 200f); _file.Save(); OnSettingTweaked(); } } internal static float LODBias { get { return D.lodBias; } set { D.lodBias = Mathf.Clamp(value, 0.5f, 4f); _file.Save(); OnSettingTweaked(); } } internal static int AnisotropicFiltering { get { return D.anisotropicFiltering; } set { D.anisotropicFiltering = value; _file.Save(); OnSettingTweaked(); } } internal static int PixelLightCount { get { return D.pixelLightCount; } set { D.pixelLightCount = Mathf.Clamp(value, 1, 16); _file.Save(); OnSettingTweaked(); } } internal static TextureRes TextureQuality { get { return (TextureRes)D.textureQuality; } set { D.textureQuality = (int)value; _file.Save(); OnSettingTweaked(); } } internal static float LightDistance { get { return D.lightDistance; } set { D.lightDistance = Mathf.Clamp(value, 10f, 100f); _file.Save(); OnSettingTweaked(); } } internal static float FogDistanceMultiplier { get { return D.fogMultiplier; } set { D.fogMultiplier = Mathf.Clamp(value, 0.3f, 1.1f); _file.Save(); OnSettingTweaked(); } } internal static float ViewDistance { get { return D.viewDistance; } set { D.viewDistance = Mathf.Clamp(value, 0f, 500f); _file.Save(); OnSettingTweaked(); } } internal static bool MotionBlurOverride { get { return D.motionBlur; } set { D.motionBlur = value; _file.Save(); OnSettingTweaked(); } } internal static bool ChromaticAberration { get { return D.chromaticAberration; } set { D.chromaticAberration = value; _file.Save(); OnSettingTweaked(); } } internal static bool LensDistortion { get { return D.lensDistortion; } set { D.lensDistortion = value; _file.Save(); OnSettingTweaked(); } } internal static bool FilmGrain { get { return D.filmGrain; } set { D.filmGrain = value; _file.Save(); OnSettingTweaked(); } } internal static bool ExtractionPointFlicker { get { return D.extractionFlickerFix; } set { D.extractionFlickerFix = value; _file.Save(); OnSettingTweaked(); } } internal static int VerticalFovOverride { get { return D.verticalFovOverride; } set { D.verticalFovOverride = Mathf.Clamp(value, 0, 110); _file.Save(); OnSettingTweaked(); } } internal static bool UltrawideUiFix { get { return D.ultrawideUiFix; } set { D.ultrawideUiFix = value; _file.Save(); OnSettingTweaked(); } } internal static KeyCode ToggleKey { get { return (KeyCode)D.toggleKey; } set { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected I4, but got Unknown D.toggleKey = (int)value; _file.Save(); } } internal static F11Target F11TargetSetting { get { return (F11Target)D.f11Target; } set { D.f11Target = (int)value; _file.Save(); } } internal static bool DebugOverlay { get { return D.debugOverlay; } set { D.debugOverlay = value; _file.Save(); } } internal static bool BenchmarkMode { get { return D.benchmark; } set { D.benchmark = value; _file.Save(); } } internal static bool AutoConfigured => !_autoTune.IsStale(); internal static bool OptimizationsActive { get { if (ModEnabled) { return OptimizationsEnabled; } return false; } } internal static bool CpuBound { get { if (!_autoTune.IsStale()) { return _autoTune.cpuBound; } return true; } } internal static int CpuPatchMode { get { return D.cpuPatchMode; } set { D.cpuPatchMode = value; _file.Save(); } } internal static bool CpuPatchesActive { get { if (_cpuPatchesActiveRaw && OptimizationsActive) { return !CpuPatchesF11Disabled; } return false; } } internal static int ShadowBudget { get { return D.shadowBudget; } set { D.shadowBudget = value; _file.Save(); OnSettingTweaked(); } } internal static int PerfExplosionShadows { get { return D.perfExplosionShadows; } set { D.perfExplosionShadows = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfItemLightShadows { get { return D.perfItemLightShadows; } set { D.perfItemLightShadows = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfAnimatedLightShadows { get { return D.perfAnimatedLightShadows; } set { D.perfAnimatedLightShadows = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfParticleShadows { get { return D.perfParticleShadows; } set { D.perfParticleShadows = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfTinyRendererCulling { get { return D.perfTinyRendererCulling; } set { D.perfTinyRendererCulling = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfDistanceShadowCulling { get { return D.perfDistanceShadowCulling; } set { D.perfDistanceShadowCulling = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfFlashlightShadowBudget { get { return D.perfFlashlightShadowBudget; } set { D.perfFlashlightShadowBudget = value; _file.Save(); _file.NotifyChanged(); } } internal static int PerfPointLightShadows { get { return D.perfPointLightShadows; } set { D.perfPointLightShadows = value; _file.Save(); _file.NotifyChanged(); } } internal static bool DiagnosticsEnabled { get { return D.diagnosticsEnabled; } set { D.diagnosticsEnabled = value; _file.Save(); } } internal static bool AutoTuneNeedsBenchmark => _autoTune.IsStale(); internal static bool AutoTuneNeedsInitialBenchmark { get { if (_autoTune.revision >= 7) { return _autoTune.gpuName != SystemInfo.graphicsDeviceName; } return true; } } internal static bool PresetRevertSuppressed => _suppressTweakRevert > 0; internal static event Action? OnSettingsChanged; internal static void InvalidateAutoTune() { _autoTune.version = ""; } internal static void UpdateCpuGate() { if (CpuPatchMode == 1) { _cpuPatchesActiveRaw = true; return; } if (CpuPatchMode == 0) { _cpuPatchesActiveRaw = false; return; } _cpuGateAccum += Time.unscaledDeltaTime; _cpuGateFrames++; _cpuGateTimer += Time.unscaledDeltaTime; if (_cpuGateTimer >= 0.5f && _cpuGateFrames > 0) { _cpuPatchesActiveRaw = _cpuGateAccum / (float)_cpuGateFrames * 1000f >= 8f; _cpuGateTimer = 0f; _cpuGateAccum = 0f; _cpuGateFrames = 0; } } internal static bool ShouldOptimize(PerfOpt opt) { if (!OptimizationsActive) { return false; } if (Preset == QualityPreset.Custom) { switch (opt switch { PerfOpt.ExplosionShadows => D.perfExplosionShadows, PerfOpt.ParticleShadows => D.perfParticleShadows, PerfOpt.ItemLightShadows => D.perfItemLightShadows, PerfOpt.TinyRendererCulling => D.perfTinyRendererCulling, PerfOpt.AnimatedLightShadows => D.perfAnimatedLightShadows, PerfOpt.DistanceShadowCulling => D.perfDistanceShadowCulling, PerfOpt.FlashlightShadowBudget => D.perfFlashlightShadowBudget, PerfOpt.PointLightShadows => D.perfPointLightShadows, _ => -1, }) { case 0: return false; case 1: return true; } } int num = Preset switch { QualityPreset.Ultra => 0, QualityPreset.High => 1, QualityPreset.Medium => 2, QualityPreset.Auto => _autoTune.perfLevel, QualityPreset.Custom => ResolvedShadowQuality switch { ShadowQuality.Ultra => 0, ShadowQuality.High => 1, ShadowQuality.Medium => 2, _ => 3, }, _ => 3, }; return opt switch { PerfOpt.ExplosionShadows => num >= 1, PerfOpt.ParticleShadows => num >= 1, PerfOpt.ItemLightShadows => num >= 2, PerfOpt.TinyRendererCulling => num >= 2, PerfOpt.AnimatedLightShadows => num >= 3, PerfOpt.DistanceShadowCulling => num >= 0, PerfOpt.FlashlightShadowBudget => num >= 0, PerfOpt.PointLightShadows => num >= 2, _ => false, }; } internal static void Init() { string? obj = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ""; _file = new SettingsFile(Path.Combine(obj, "settings.json")); _file.Changed += delegate { ResolveAutoDefaults(); Settings.OnSettingsChanged?.Invoke(); }; _autoTunePath = Path.Combine(obj, "autotune.json"); LoadAutoTune(); _initComplete = true; MigrateOldConfig(obj); ValidateResolutionForCurrentMonitor(); } private static void ValidateResolutionForCurrentMonitor() { //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) int num = ((Display.main != null) ? Display.main.systemWidth : 0); int num2 = ((Display.main != null) ? Display.main.systemHeight : 0); if (num <= 0 || num2 <= 0) { return; } if (D.resWidth <= 0 || D.resHeight <= 0) { D.resWidth = num; D.resHeight = num2; _file.Save(); return; } float num3 = (float)D.resWidth / (float)D.resHeight; float num4 = (float)num / (float)num2; if (Mathf.Abs(num3 - num4) > 0.05f) { Plugin.Log.LogWarning((object)$"[settings] resolution {D.resWidth}x{D.resHeight} (aspect {num3:F2}) mismatches monitor {num}x{num2} (aspect {num4:F2}); resetting to native"); D.resWidth = num; D.resHeight = num2; _file.Save(); Screen.SetResolution(num, num2, Screen.fullScreenMode); return; } long num5 = (long)D.resWidth * (long)D.resHeight; long num6 = (long)num * (long)num2; if (num5 < num6 / 2) { Plugin.Log.LogWarning((object)$"[settings] resolution {D.resWidth}x{D.resHeight} is <50% of monitor native {num}x{num2}; resetting to native"); D.resWidth = num; D.resHeight = num2; _file.Save(); Screen.SetResolution(num, num2, Screen.fullScreenMode); } } private static void LoadAutoTune() { if (!File.Exists(_autoTunePath)) { return; } try { AutoTuneData autoTuneData = JsonUtility.FromJson(File.ReadAllText(_autoTunePath)); if (autoTuneData != null) { _autoTune = autoTuneData; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to load autotune: " + ex.Message)); } } internal static void SaveAutoTune(AutoTuneData data) { _autoTune = data; try { File.WriteAllText(_autoTunePath, JsonUtility.ToJson((object)data, true)); Plugin.Log.LogInfo((object)"Auto-tune profile saved"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to save autotune: " + ex.Message)); } if (Preset == QualityPreset.Auto) { ResolveAutoDefaults(); Settings.OnSettingsChanged?.Invoke(); } } private static void MigrateOldConfig(string pluginDir) { try { string path = Path.Combine(pluginDir, "..", "..", "config", "Vippy.REPOFidelity.cfg"); if (File.Exists(path)) { File.Delete(path); Plugin.Log.LogInfo((object)"Deleted old BepInEx config"); } } catch { } } private static void OnChanged() { if (_initComplete) { _file.NotifyChanged(); } } internal static void PushPresetRevertSuppression() { _suppressTweakRevert++; } internal static void PopPresetRevertSuppression() { _suppressTweakRevert = Math.Max(0, _suppressTweakRevert - 1); } private static void OnSettingTweaked() { if (!_initComplete) { return; } if (_suppressTweakRevert > 0) { _file.NotifyChanged(); return; } if (Preset != QualityPreset.Custom) { _file.SuppressEvents(delegate { D.preset = 5; }); _file.Save(); } _file.NotifyChanged(); } internal static void BatchUpdate(Action action) { _file.SuppressEvents(action); _file.Save(); ResolveAutoDefaults(); Settings.OnSettingsChanged?.Invoke(); } public static void ResolveAutoDefaults() { QualityPreset preset = Preset; if (preset != QualityPreset.Custom) { ApplyPreset(preset); SyncCustomToResolved(); } else { ResolvedUpscaleMode = UpscaleModeSetting switch { UpscaleMode.Auto => BestUpscaler(UpscaleTier.Quality), UpscaleMode.FSR => UpscaleMode.FSR_Temporal, UpscaleMode.FSR4 => UpscaleMode.FSR_Temporal, _ => UpscaleModeSetting, }; if (!GPUDetector.IsUpscalerSupported(ResolvedUpscaleMode)) { Plugin.Log.LogWarning((object)$"{ResolvedUpscaleMode} not supported — falling back to Auto"); ResolvedUpscaleMode = BestUpscaler(UpscaleTier.Quality); } int num = MinRenderScale(ResolvedUpscaleMode); if (ResolvedUpscaleMode == UpscaleMode.DLSS && RenderScale >= 100) { ResolvedUpscaleMode = UpscaleMode.DLAA; } if (ResolvedUpscaleMode == UpscaleMode.DLAA) { ResolvedRenderScale = 100; } else { ResolvedRenderScale = Mathf.Clamp(RenderScale, num, 100); } UpscaleMode resolvedUpscaleMode = ResolvedUpscaleMode; bool flag = (((uint)(resolvedUpscaleMode - 1) <= 1u || resolvedUpscaleMode == UpscaleMode.FSR_Temporal) ? true : false); bool flag2 = flag; if (AntiAliasingMode == AAMode.Auto) { ResolvedAAMode = (flag2 ? AAMode.Off : AAMode.SMAA); } else if (AntiAliasingMode == AAMode.TAA) { ResolvedAAMode = (flag2 ? AAMode.Off : AAMode.SMAA); } else { ResolvedAAMode = AntiAliasingMode; } ResolvedShadowQuality = ShadowQualitySetting; ResolvedShadowDistance = ShadowDistance; ResolvedLODBias = LODBias; ResolvedPixelLightCount = PixelLightCount; ResolvedLightDistance = LightDistance; ResolvedFogMultiplier = FogDistanceMultiplier; ResolvedViewDistance = ViewDistance; ResolvedAnisotropicFiltering = AnisotropicFiltering; ResolvedTextureQuality = TextureQuality; int resolvedShadowBudget = ((ShadowBudget != -1) ? ShadowBudget : (ResolvedShadowQuality switch { ShadowQuality.Ultra => 25, ShadowQuality.High => 20, ShadowQuality.Medium => 15, _ => 10, })); ResolvedShadowBudget = resolvedShadowBudget; } ApplyFogClamps(); Plugin.Log.LogInfo((object)($"Resolved [{preset}]: {ResolvedUpscaleMode} {ResolvedRenderScale}% " + $"AA={ResolvedAAMode} shadows={ResolvedShadowQuality}/{ResolvedShadowDistance}m " + $"LOD={ResolvedLODBias} lights={ResolvedPixelLightCount} " + $"fogEnd={ResolvedEffectiveFogEnd:F0}m lightDist={ResolvedLightDistance:F0}m")); } internal static void ApplyFogClamps() { if (UpscalerManager._vanillaSaved) { ResolvedEffectiveFogEnd = UpscalerManager._vanillaFogEnd * ResolvedFogMultiplier; } float resolvedEffectiveFogEnd = ResolvedEffectiveFogEnd; if (!(resolvedEffectiveFogEnd <= 0f)) { ResolvedShadowDistance = Mathf.Min(ResolvedShadowDistance, resolvedEffectiveFogEnd * 1.1f); ResolvedLightDistance = Mathf.Min(ResolvedLightDistance, resolvedEffectiveFogEnd * 1.2f); } } private static void SyncCustomToResolved() { _file.SuppressEvents(delegate { UpscaleMode upscaler = ((ResolvedUpscaleMode == UpscaleMode.DLAA) ? UpscaleMode.DLSS : ResolvedUpscaleMode); D.upscaler = (int)upscaler; D.renderScale = ResolvedRenderScale; D.aaMode = (int)ResolvedAAMode; D.shadowQuality = (int)ResolvedShadowQuality; D.shadowDistance = ResolvedShadowDistance; D.lodBias = ResolvedLODBias; D.pixelLightCount = ResolvedPixelLightCount; D.lightDistance = ResolvedLightDistance; D.fogMultiplier = ResolvedFogMultiplier; D.viewDistance = ResolvedViewDistance; SettingsData d = D; d.sharpening = Preset switch { QualityPreset.Potato => 0f, QualityPreset.Low => 0f, QualityPreset.Medium => 0f, QualityPreset.High => 0.5f, QualityPreset.Ultra => 0.3f, QualityPreset.Auto => _autoTune.sharpening, _ => D.sharpening, }; D.anisotropicFiltering = ResolvedAnisotropicFiltering; D.textureQuality = (int)ResolvedTextureQuality; D.shadowBudget = ResolvedShadowBudget; }); _file.Save(); } internal static string[] GetAvailableResolutions(out int currentIndex) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) Resolution val; int num; if (Display.main == null || Display.main.systemWidth <= 0) { val = Screen.currentResolution; num = ((Resolution)(ref val)).width; } else { num = Display.main.systemWidth; } int width = num; int num2; if (Display.main == null || Display.main.systemHeight <= 0) { val = Screen.currentResolution; num2 = ((Resolution)(ref val)).height; } else { num2 = Display.main.systemHeight; } int height = num2; val = default(Resolution); ((Resolution)(ref val)).width = width; ((Resolution)(ref val)).height = height; Resolution val2 = val; float num3 = (float)((Resolution)(ref val2)).width / (float)((Resolution)(ref val2)).height; int num4 = 720; HashSet hashSet = new HashSet(); List list = new List(); Resolution[] resolutions = Screen.resolutions; for (int i = 0; i < resolutions.Length; i++) { Resolution val3 = resolutions[i]; if (((Resolution)(ref val3)).height >= num4 && !(Mathf.Abs((float)((Resolution)(ref val3)).width / (float)((Resolution)(ref val3)).height - num3) > 0.05f)) { string item = $"{((Resolution)(ref val3)).width}x{((Resolution)(ref val3)).height}"; if (hashSet.Add(item)) { list.Add(item); } } } float[] array = new float[4] { 0.5f, 0.6667f, 0.75f, 0.8333f }; foreach (float num5 in array) { int num6 = Mathf.RoundToInt((float)((Resolution)(ref val2)).width * num5 / 8f) * 8; int num7 = Mathf.RoundToInt((float)num6 / num3 / 8f) * 8; if (num7 >= num4) { string item2 = $"{num6}x{num7}"; if (hashSet.Add(item2)) { list.Add(item2); } } } string item3 = $"{((Resolution)(ref val2)).width}x{((Resolution)(ref val2)).height}"; if (!hashSet.Contains(item3)) { list.Add(item3); } list.Sort(delegate(string a, string b) { int num8 = int.Parse(a.Split('x')[0]); int value = int.Parse(b.Split('x')[0]); return num8.CompareTo(value); }); string item4 = $"{OutputWidth}x{OutputHeight}"; currentIndex = list.IndexOf(item4); if (currentIndex < 0) { currentIndex = 0; } return list.ToArray(); } internal static void SetResolution(string wxh) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) string[] array = wxh.Split('x'); if (array.Length == 2) { int num = int.Parse(array[0]); int num2 = int.Parse(array[1]); D.resWidth = num; D.resHeight = num2; _file.Save(); Screen.SetResolution(num, num2, Screen.fullScreenMode); Plugin.Log.LogInfo((object)$"Resolution: {num}x{num2}"); if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(WaitForResolutionThenChange(num, num2)); } else { OnChanged(); } } } [IteratorStateMachine(typeof(d__184))] private static IEnumerator WaitForResolutionThenChange(int targetW, int targetH) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__184(0) { targetW = targetW, targetH = targetH }; } internal static int MinRenderScale(UpscaleMode mode) { return mode switch { UpscaleMode.DLSS => 33, UpscaleMode.DLAA => 100, UpscaleMode.FSR4 => 50, UpscaleMode.FSR_Temporal => 50, UpscaleMode.FSR => 50, UpscaleMode.Off => 50, _ => 50, }; } private static UpscaleMode BestUpscaler(UpscaleTier tier) { return tier switch { UpscaleTier.Budget => GPUDetector.IsIntegratedGpu ? UpscaleMode.Off : UpscaleMode.FSR_Temporal, UpscaleTier.NativeAA => GPUDetector.DlssAvailable ? UpscaleMode.DLAA : UpscaleMode.FSR_Temporal, _ => GPUDetector.DlssAvailable ? UpscaleMode.DLSS : UpscaleMode.FSR_Temporal, }; } internal static void ApplyPreset(QualityPreset preset) { bool cpuBound = CpuBound; switch (preset) { case QualityPreset.Potato: ResolvedUpscaleMode = UpscaleMode.Off; ResolvedRenderScale = 50; ResolvedAAMode = AAMode.Off; ResolvedShadowQuality = ShadowQuality.Low; ResolvedShadowDistance = 10f; ResolvedLODBias = 0.5f; ResolvedPixelLightCount = 2; ResolvedLightDistance = 10f; ResolvedFogMultiplier = 0.85f; ResolvedViewDistance = 0f; ResolvedAnisotropicFiltering = 2; ResolvedTextureQuality = TextureRes.Full; ResolvedShadowBudget = 5; break; case QualityPreset.Low: ResolvedUpscaleMode = UpscaleMode.Off; ResolvedRenderScale = (cpuBound ? 100 : 50); ResolvedAAMode = AAMode.SMAA; ResolvedShadowQuality = ShadowQuality.Low; ResolvedShadowDistance = 20f; ResolvedLODBias = 1f; ResolvedPixelLightCount = 4; ResolvedLightDistance = 20f; ResolvedFogMultiplier = 1f; ResolvedViewDistance = 0f; ResolvedAnisotropicFiltering = 4; ResolvedTextureQuality = TextureRes.Full; ResolvedShadowBudget = 10; break; case QualityPreset.Medium: ResolvedUpscaleMode = UpscaleMode.Off; ResolvedRenderScale = (cpuBound ? 100 : 75); ResolvedAAMode = AAMode.SMAA; ResolvedShadowQuality = ShadowQuality.Medium; ResolvedShadowDistance = 30f; ResolvedLODBias = 1.5f; ResolvedPixelLightCount = 6; ResolvedLightDistance = 25f; ResolvedFogMultiplier = 1f; ResolvedViewDistance = 0f; ResolvedAnisotropicFiltering = 8; ResolvedTextureQuality = TextureRes.Full; ResolvedShadowBudget = 15; break; case QualityPreset.High: if (cpuBound) { ResolvedUpscaleMode = (GPUDetector.DlssAvailable ? UpscaleMode.DLAA : UpscaleMode.Off); ResolvedRenderScale = 100; ResolvedAAMode = (GPUDetector.DlssAvailable ? AAMode.Off : AAMode.SMAA); } else { ResolvedUpscaleMode = BestUpscaler(UpscaleTier.Quality); ResolvedRenderScale = 75; ResolvedAAMode = AAMode.Off; } ResolvedShadowQuality = ShadowQuality.High; ResolvedShadowDistance = 85f; ResolvedLODBias = 3f; ResolvedPixelLightCount = 8; ResolvedLightDistance = 45f; ResolvedFogMultiplier = 1.1f; ResolvedViewDistance = 0f; ResolvedAnisotropicFiltering = 16; ResolvedTextureQuality = TextureRes.Full; ResolvedShadowBudget = 20; break; case QualityPreset.Ultra: if (cpuBound) { ResolvedUpscaleMode = (GPUDetector.DlssAvailable ? UpscaleMode.DLAA : UpscaleMode.Off); ResolvedRenderScale = 100; ResolvedAAMode = (GPUDetector.DlssAvailable ? AAMode.Off : AAMode.SMAA); } else { ResolvedUpscaleMode = BestUpscaler(UpscaleTier.NativeAA); ResolvedRenderScale = 100; ResolvedAAMode = AAMode.Off; } ResolvedShadowQuality = ShadowQuality.Ultra; ResolvedShadowDistance = 150f; ResolvedLODBias = 4f; ResolvedPixelLightCount = 16; ResolvedLightDistance = 75f; ResolvedFogMultiplier = 1.1f; ResolvedViewDistance = 0f; ResolvedAnisotropicFiltering = 16; ResolvedTextureQuality = TextureRes.Full; ResolvedShadowBudget = 25; break; case QualityPreset.Auto: ApplyAutoTune(); break; case QualityPreset.Custom: break; } } private static void ApplyAutoTune() { if (_autoTune.IsStale()) { Plugin.Log.LogInfo((object)"Auto: no valid autotune profile, using High as fallback"); ApplyPreset(QualityPreset.High); return; } AutoTuneData autoTune = _autoTune; ResolvedUpscaleMode = (UpscaleMode)autoTune.upscaler; ResolvedRenderScale = autoTune.renderScale; ResolvedAAMode = (AAMode)autoTune.aaMode; ResolvedShadowQuality = (ShadowQuality)autoTune.shadowQuality; ResolvedShadowDistance = autoTune.shadowDistance; ResolvedLODBias = autoTune.lodBias; ResolvedPixelLightCount = autoTune.pixelLightCount; ResolvedLightDistance = autoTune.lightDistance; ResolvedFogMultiplier = autoTune.fogMultiplier; ResolvedViewDistance = autoTune.viewDistance; ResolvedAnisotropicFiltering = autoTune.anisotropicFiltering; ResolvedTextureQuality = TextureRes.Full; ResolvedShadowBudget = ResolvedShadowQuality switch { ShadowQuality.Ultra => 25, ShadowQuality.High => 20, ShadowQuality.Medium => 15, _ => 10, }; if (autoTune.cpuBound) { ResolvedShadowBudget = Mathf.Max(ResolvedShadowBudget - 7, 8); } } internal static void AutoSelectPreset(float avgFpsRaw, float low1Fps, float low01Fps, bool cpuBound = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) Resolution currentResolution = Screen.currentResolution; RefreshRate refreshRateRatio = ((Resolution)(ref currentResolution)).refreshRateRatio; int num = Mathf.Max((int)Mathf.Round((float)((RefreshRate)(ref refreshRateRatio)).value), 60); float target = num; float num2 = ((low01Fps > 0f) ? low01Fps : low1Fps); float num3 = avgFpsRaw * 0.5f + low1Fps * 0.3f + num2 * 0.2f; int num4 = Object.FindObjectsOfType().Length; float num5 = Mathf.Clamp(3000f / Mathf.Max((float)num4, 1500f), 0.85f, 1f); float num6 = num3 * num5 * 0.92f; Plugin.Log.LogInfo((object)($"Auto-tune inputs: avg={avgFpsRaw:F0} 1%={low1Fps:F0} 0.1%={num2:F0} " + $"renderers={num4} weighted={num3:F0} sceneFactor={num5:F2} " + string.Format("primary={0:F0} target={1}Hz {2}", num6, target, cpuBound ? "CPU-BOUND" : "gpu-bound"))); int scale = 100; ShadowQuality shQ = ShadowQuality.Ultra; float shD = 150f; float lod = 4f; float lDist = 75f; float sharpening = 0.3f; float fog = 1.1f; int lights = 16; int af = 16; TextureRes tex = TextureRes.Full; UpscaleMode upscaleMode; AAMode aAMode; if (cpuBound) { if (GPUDetector.DlssAvailable) { upscaleMode = UpscaleMode.DLAA; aAMode = AAMode.Off; Plugin.Log.LogInfo((object)"CPU-bound + NVIDIA: using DLAA"); } else if (GPUDetector.IsUpscalerSupported(UpscaleMode.FSR_Temporal) && avgFpsRaw / target >= 1.1f) { upscaleMode = UpscaleMode.FSR_Temporal; aAMode = AAMode.Off; Plugin.Log.LogInfo((object)$"CPU-bound + headroom: using FSR Temporal (headroom={avgFpsRaw / target:F2})"); } else { upscaleMode = UpscaleMode.Off; aAMode = AAMode.SMAA; Plugin.Log.LogInfo((object)"CPU-bound: using SMAA"); } } else { upscaleMode = BestUpscaler(UpscaleTier.Quality); aAMode = AAMode.Off; } float ultraCost = GpuCost(scale, shQ, shD, lod, lights, lDist, af, tex, fog); float num7 = GpuCost(ResolvedRenderScale, ResolvedShadowQuality, ResolvedShadowDistance, ResolvedLODBias, ResolvedPixelLightCount, ResolvedLightDistance, ResolvedAnisotropicFiltering, ResolvedTextureQuality, ResolvedFogMultiplier); float estUltra = num6 * (num7 / ultraCost); float num8 = estUltra / target; int num9 = MinRenderScale(upscaleMode); if (cpuBound) { float num10 = num6 / target; Plugin.Log.LogInfo((object)$"CPU-bound: headroom={num10:F2} (avgFps={num6:F0} target={target:F0})"); if (num10 < 0.95f) { shD = 100f; if (num10 < 0.9f) { lDist = 50f; } if (num10 < 0.8f) { shD = 75f; lights = 12; } if (num10 < 0.7f) { shD = 50f; lights = 10; } if (num10 < 0.6f) { shD = 35f; lights = 8; lDist = 35f; } if (num10 < 0.5f) { shD = 25f; lights = 6; lDist = 25f; } if (num10 < 0.4f) { shD = 15f; lights = 4; lDist = 15f; shQ = ShadowQuality.High; lod = 2f; af = 8; } if (num10 < 0.3f) { shQ = ShadowQuality.Medium; lod = 1f; af = 4; } if (num10 < 0.2f) { shQ = ShadowQuality.Low; if (upscaleMode == UpscaleMode.Off || upscaleMode == UpscaleMode.DLAA) { upscaleMode = BestUpscaler(UpscaleTier.Quality); aAMode = AAMode.Off; num9 = MinRenderScale(upscaleMode); } scale = Mathf.Clamp(Mathf.RoundToInt(75f * Mathf.Sqrt(Mathf.Max(num10, 0.1f) / 0.2f)), num9, 80); } } else if (num10 > 1.15f) { sharpening = 0.4f; if (num10 > 1.3f) { lod = 5f; } if (num10 > 1.5f) { lod = 6f; shD = 175f; } if (num10 > 1.8f) { shD = 200f; } } } else { if (num8 < 1f) { af = 8; num8 = Rebudget(); } if (num8 < 1f) { fog = 1f; num8 = Rebudget(); } if (num8 < 1f) { lod = 2f; num8 = Rebudget(); } if (num8 < 1f) { lDist = 35f; num8 = Rebudget(); } if (num8 < 1f) { lights = 8; num8 = Rebudget(); } if (num8 < 1f) { shD = 50f; num8 = Rebudget(); } if (num8 < 1f) { shQ = ShadowQuality.High; num8 = Rebudget(); } if (num8 < 1f) { shQ = ShadowQuality.Medium; num8 = Rebudget(); } if (num8 < 1f) { if (upscaleMode == UpscaleMode.Off) { upscaleMode = BestUpscaler(UpscaleTier.Quality); aAMode = AAMode.Off; num9 = MinRenderScale(upscaleMode); } scale = Mathf.Clamp(Mathf.RoundToInt(100f * Mathf.Sqrt(num8)), num9, 100); num8 = Rebudget(); } if (num8 < 0.8f) { shQ = ShadowQuality.Low; shD = 25f; lights = 4; lDist = 15f; af = 4; lod = 1f; scale = Mathf.Clamp(Mathf.RoundToInt((float)scale * 0.8f), num9, 100); } if (num8 < 0.5f) { upscaleMode = BestUpscaler(UpscaleTier.Budget); num9 = MinRenderScale(upscaleMode); scale = Mathf.Clamp(Mathf.RoundToInt((float)scale * 0.7f), num9, 100); shQ = ShadowQuality.Low; shD = 10f; lights = 2; lDist = 10f; af = 2; lod = 0.5f; aAMode = AAMode.Off; sharpening = 0f; } if (scale >= 100) { upscaleMode = BestUpscaler(UpscaleTier.NativeAA); aAMode = AAMode.Off; } if (num8 > 1.3f) { shD = 200f; num8 = Rebudget(); } if (num8 > 1.3f) { lDist = 100f; num8 = Rebudget(); } if (num8 > 1.5f) { lod = 5f; num8 = Rebudget(); } if (num8 > 1.5f) { sharpening = 0.4f; } } int num11 = ((!cpuBound) ? (shQ switch { ShadowQuality.Ultra => 0, ShadowQuality.High => 1, ShadowQuality.Medium => 2, _ => 3, }) : 3); int num12 = num11; Plugin.Log.LogInfo((object)($"Auto-tune result: {upscaleMode} {scale}% AA={aAMode} shQ={shQ} shD={shD} " + $"lod={lod} lights={lights} lDist={lDist} af={af} tex={tex} fog={fog} perfLevel={num12}")); SaveAutoTune(new AutoTuneData { version = "1.6.3", revision = 7, gpuName = (SystemInfo.graphicsDeviceName ?? ""), resWidth = Screen.width, resHeight = Screen.height, cpuBound = cpuBound, upscaler = (int)upscaleMode, renderScale = scale, sharpening = sharpening, aaMode = (int)aAMode, shadowQuality = (int)shQ, shadowDistance = shD, lodBias = lod, pixelLightCount = lights, lightDistance = lDist, fogMultiplier = fog, anisotropicFiltering = af, perfLevel = num12 }); float Rebudget() { float num13 = GpuCost(scale, shQ, shD, lod, lights, lDist, af, tex, fog); return estUltra / (num13 / ultraCost) / target; } } private static float GpuCost(int scale, ShadowQuality shQ, float shD, float lod, int lights, float lDist, int af, TextureRes tex, float fog) { float num = (float)scale / 100f; float num2 = num * num * 0.45f; float num3 = num2 + shQ switch { ShadowQuality.Ultra => 0.25f, ShadowQuality.High => 0.15f, ShadowQuality.Medium => 0.08f, _ => 0.03f, } + Mathf.Min(shD, 150f) / 200f * 0.08f + (float)lights / 16f * 0.03f + lDist / 100f * 0.02f + lod / 4f * 0.02f; return Mathf.Max(num3 + tex switch { TextureRes.Full => 0.04f, TextureRes.Half => 0.02f, _ => 0.01f, } + (float)af / 16f * 0.01f + Mathf.Max(fog - 1f, 0f) / 4f * 0.03f, 0.05f); } } internal class SettingsFile { private readonly string _path; private SettingsData _data; private bool _suppressSave; internal SettingsData Data => _data; internal event Action? Changed; internal SettingsFile(string path) { _path = path; _data = new SettingsData(); Load(); } internal void Load() { if (!File.Exists(_path)) { return; } try { SettingsData settingsData = JsonUtility.FromJson(File.ReadAllText(_path)); if (settingsData != null) { _data = settingsData; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to load settings: " + ex.Message)); } } internal void Save() { if (_suppressSave) { return; } try { string directoryName = Path.GetDirectoryName(_path); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(_path, JsonUtility.ToJson((object)_data, true)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to save settings: " + ex.Message)); } } internal void NotifyChanged() { if (!_suppressSave) { this.Changed?.Invoke(); } } internal void SuppressEvents(Action action) { _suppressSave = true; try { action(); } finally { _suppressSave = false; } } } [Serializable] internal class AutoTuneData { public string version = ""; public string gpuName = ""; public int resWidth; public int resHeight; public bool cpuBound; public int upscaler; public int renderScale = 100; public float sharpening = 0.3f; public int aaMode = 4; public int shadowQuality = 3; public float shadowDistance = 150f; public float lodBias = 4f; public int pixelLightCount = 16; public float lightDistance = 75f; public float fogMultiplier = 1.1f; public float viewDistance; public int anisotropicFiltering = 16; public int perfLevel; internal const int AutoTuneRevision = 7; public int revision; internal bool IsStale() { if (revision >= 7 && !(gpuName != SystemInfo.graphicsDeviceName)) { if (resWidth > 0) { if (resWidth == Screen.width) { return resHeight != Screen.height; } return true; } return false; } return true; } } [Serializable] internal class SettingsData { public int preset = 6; public int resWidth; public int resHeight; public int upscaler; public int renderScale = 67; public float sharpening = 0.5f; public int aaMode; public bool pixelation; public int shadowQuality = 3; public float shadowDistance = 75f; public float lodBias = 3f; public int anisotropicFiltering = 16; public int pixelLightCount = 6; public int textureQuality; public float lightDistance = 30f; public float fogMultiplier = 1f; public float viewDistance; public bool motionBlur; public bool chromaticAberration; public bool lensDistortion; public bool filmGrain = true; public bool extractionFlickerFix = true; public int verticalFovOverride; public bool ultrawideUiFix = true; public int shadowBudget = -1; public int perfExplosionShadows = -1; public int perfItemLightShadows = -1; public int perfAnimatedLightShadows = -1; public int perfParticleShadows = -1; public int perfTinyRendererCulling = -1; public int perfDistanceShadowCulling = -1; public int perfFlashlightShadowBudget = -1; public int perfPointLightShadows = -1; public bool diagnosticsEnabled; public bool cpuBound = true; public int cpuPatchMode = -1; public int toggleKey = 291; public int f11Target; public bool debugOverlay; public bool benchmark; public bool autoConfigured; public string autoConfigVersion = ""; } internal class UpscalerManager : MonoBehaviour { internal enum RenderTier { Passthrough, NativeScaling, Upscaler } [CompilerGenerated] private sealed class d__85 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public UpscalerManager <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__85(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; UpscalerManager upscalerManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: { <>1__state = -1; Settings.ModEnabled = true; Plugin.Log.LogInfo((object)"Mod ENABLED"); upscalerManager.Reinitialize(); RenderTexturePatch.ReapplyModCameraSettings(); if ((Object)(object)upscalerManager._renderTextureMain != (Object)null) { upscalerManager._renderTextureMain.textureWidthOriginal = Settings.OutputWidth; upscalerManager._renderTextureMain.textureHeightOriginal = Settings.OutputHeight; RenderTexture renderTexture = upscalerManager._renderTextureMain.renderTexture; if ((Object)(object)renderTexture != (Object)null && upscalerManager.CurrentTier != RenderTier.Upscaler && (((Texture)renderTexture).width != upscalerManager._outputWidth || ((Texture)renderTexture).height != upscalerManager._outputHeight)) { renderTexture.Release(); ((Texture)renderTexture).width = upscalerManager._outputWidth; ((Texture)renderTexture).height = upscalerManager._outputHeight; renderTexture.Create(); } } float resolvedFogMultiplier = Settings.ResolvedFogMultiplier; if (_vanillaSaved && resolvedFogMultiplier != 1f && !SemiFunc.MenuLevel()) { RenderSettings.fogStartDistance = _vanillaFogStart * resolvedFogMultiplier; RenderSettings.fogEndDistance = _vanillaFogEnd * resolvedFogMultiplier; SetModFarClip(upscalerManager._camera, RenderSettings.fogEndDistance + 10f); } if (_vanillaSaved) { Settings.ResolvedEffectiveFogEnd = _vanillaFogEnd * resolvedFogMultiplier; Settings.ApplyFogClamps(); } SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); PlayerAvatarMenuAAPatch.ReapplyAll(); upscalerManager._togglePending = false; if (Settings.UltrawideUiFix) { UltrawideCanvasFix.RefreshAll(); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private IUpscaler? _upscaler; private RenderTextureMain? _renderTextureMain; private Camera? _camera; private RenderTexture? _outputRT; private int _inputWidth; private int _inputHeight; private int _outputWidth; private int _outputHeight; private bool _useCameraCallback; private bool _repoHdDetected; private int _jitterIndex; private Matrix4x4 _savedProjectionMatrix; private bool _jitterApplied; private static readonly float[] HaltonX = GenerateHalton(2, 32); private static readonly float[] HaltonY = GenerateHalton(3, 32); private bool _togglePending; private bool _benchmarkActive; private bool _autoBenchmark; private float _benchmarkTimer; private float _benchmarkWarmup; private readonly List _benchmarkFrameTimes = new List(); private int _benchmarkVsyncPrev; private int _benchmarkPhase; private float _lowGpuFps; private int _savedRenderScale; private const float BenchmarkDuration = 15f; private const float AutoBenchmarkDuration = 12f; private const float Phase0Duration = 4f; private const float WarmupDuration = 3f; private const float ThermalSafetyFactor = 0.9f; private float _shadowBudgetTimer; private const float ShadowBudgetInterval = 0.1f; private const string MarkTick = "REPOFidelity.Tick"; private const string MarkTickShadowBudget = "REPOFidelity.Tick.ShadowBudget"; private const string MarkTickDistCull = "REPOFidelity.Tick.DistanceShadowCull"; private const string MarkTickFlashBudget = "REPOFidelity.Tick.FlashlightBudget"; private const string MarkTickAvatarCull = "REPOFidelity.Tick.PlayerAvatarShadowCull"; private const string MarkTickPointLight = "REPOFidelity.Tick.PointLightShadowCull"; private const string MarkLateUpdate = "REPOFidelity.LateUpdate"; private const string MarkProcessFrame = "REPOFidelity.ProcessFrame"; private const string MarkApplyCAS = "REPOFidelity.ApplyCAS"; private const string MarkPreRenderJitter = "REPOFidelity.Cam.PreRenderJitter"; private const string MarkPostRenderRestore = "REPOFidelity.Cam.PostRenderRestore"; private const string MarkPostRenderCallback = "REPOFidelity.Cam.PostRenderCallback"; private int _benchmarkFpsPrev; internal static float _vanillaFogStart; internal static float _vanillaFogEnd; internal static bool _vanillaSaved; internal static int _environmentSetupCount; internal static float _lastEnvironmentSetupTime; internal static readonly Dictionary _vanillaFarClipByCam = new Dictionary(); internal RenderTier CurrentTier { get; private set; } internal static UpscalerManager? Instance { get; private set; } internal static bool RepoHdDetected { get { if ((Object)(object)Instance != (Object)null) { return Instance._repoHdDetected; } return false; } } internal static bool BenchmarkActive { get { if ((Object)(object)Instance != (Object)null) { return Instance._benchmarkActive; } return false; } } internal static bool AutoBenchmarkRunning { get { if ((Object)(object)Instance != (Object)null) { return Instance._autoBenchmark; } return false; } } internal static float BenchmarkProgress { get { if ((Object)(object)Instance == (Object)null || !Instance._benchmarkActive) { return 0f; } float num = 4f; float num2 = (Instance._autoBenchmark ? 12f : 15f); float num3 = 3f + num + 3f + num2; float num4 = ((Instance._benchmarkPhase != 0) ? (3f + num + (3f - Instance._benchmarkWarmup) + ((Instance._benchmarkWarmup > 0f) ? 0f : Instance._benchmarkTimer)) : (3f - Instance._benchmarkWarmup + ((Instance._benchmarkWarmup > 0f) ? 0f : Instance._benchmarkTimer))); return Mathf.Clamp01(num4 / num3); } } internal float JitterX { get; private set; } internal float JitterY { get; private set; } private void Awake() { Instance = this; Settings.OnSettingsChanged += Reinitialize; _repoHdDetected = Chainloader.PluginInfos.ContainsKey("BlueAmulet.REPO_HD"); } internal void Reinitialize() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (!((Object)(object)_renderTextureMain == (Object)null) && !((Object)(object)_camera == (Object)null)) { Plugin.Log.LogDebug((object)"Reinitializing upscaler pipeline..."); Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnPreRenderJitter)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRenderRestore)); if (_useCameraCallback) { Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRenderCallback)); } _upscaler?.Dispose(); _upscaler = null; if ((Object)(object)_camera != (Object)null) { _camera.targetTexture = null; } ReleaseRT(ref _outputRT); _useCameraCallback = false; if ((Object)(object)_renderTextureMain != (Object)null && (Object)(object)_camera != (Object)null) { Setup(_renderTextureMain, _camera); } QualityPatch.ApplyQualitySettings(); RenderTexturePatch.ReapplyModCameraSettings(); } } internal void Setup(RenderTextureMain rtMain, Camera camera) { _renderTextureMain = rtMain; _camera = camera; _outputWidth = Settings.OutputWidth; _outputHeight = Settings.OutputHeight; _upscaler = Settings.ResolvedUpscaleMode switch { UpscaleMode.FSR_Temporal => new TemporalUpscaler(), UpscaleMode.DLSS => new DLSSUpscaler(), UpscaleMode.DLAA => new DLSSUpscaler(dlaaMode: true), _ => null, }; if (_upscaler != null && !_upscaler.IsAvailable) { Plugin.Log.LogWarning((object)(_upscaler.Name + " unavailable — falling back to FSR Temporal")); _upscaler = new TemporalUpscaler(); Settings.ResolvedUpscaleMode = UpscaleMode.FSR_Temporal; if (!_upscaler.IsAvailable) { Plugin.Log.LogWarning((object)"FSR also unavailable — no upscaling"); _upscaler = null; Settings.ResolvedUpscaleMode = UpscaleMode.Off; if (Settings.ResolvedRenderScale < 100) { Plugin.Log.LogWarning((object)"No upscaler available — forcing native render scale"); Settings.ResolvedRenderScale = 100; } } } bool flag = Settings.Sharpening > 0.01f; bool flag2 = Settings.ResolvedRenderScale < 100; if (_upscaler != null) { CurrentTier = RenderTier.Upscaler; } else if (flag || flag2) { CurrentTier = RenderTier.NativeScaling; } else { CurrentTier = RenderTier.Passthrough; } _useCameraCallback = _upscaler is DLSSUpscaler; switch (CurrentTier) { case RenderTier.Passthrough: SetupPassthrough(rtMain); break; case RenderTier.NativeScaling: SetupNativeScaling(rtMain); break; case RenderTier.Upscaler: SetupUpscaler(rtMain, camera); break; } } private void SetupPassthrough(RenderTextureMain rtMain) { if ((Object)(object)_camera != (Object)null && (Object)(object)rtMain.renderTexture != (Object)null) { _camera.targetTexture = rtMain.renderTexture; } Plugin.Log.LogDebug((object)"Passthrough mode"); } private void SetupNativeScaling(RenderTextureMain rtMain) { if ((Object)(object)_camera != (Object)null && (Object)(object)rtMain.renderTexture != (Object)null) { _camera.targetTexture = rtMain.renderTexture; } Plugin.Log.LogDebug((object)"NativeScaling mode"); } private void SetupUpscaler(RenderTextureMain rtMain, Camera camera) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_006a: 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_007d: Expected O, but got Unknown //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Expected O, but got Unknown float renderScale = RenderTexturePatch.GetRenderScale(); _inputWidth = Mathf.Max(Mathf.RoundToInt((float)_outputWidth * renderScale), 1); _inputHeight = Mathf.Max(Mathf.RoundToInt((float)_outputHeight * renderScale), 1); RenderTexture renderTexture = rtMain.renderTexture; RenderTextureFormat val = (RenderTextureFormat)((!((Object)(object)renderTexture != (Object)null)) ? 9 : ((int)renderTexture.format)); _outputRT = new RenderTexture(_inputWidth, _inputHeight, 24, val) { filterMode = (FilterMode)1, enableRandomWrite = true }; _outputRT.Create(); camera.targetTexture = _outputRT; if ((Object)(object)renderTexture != (Object)null) { renderTexture.Release(); ((Texture)renderTexture).width = _outputWidth; ((Texture)renderTexture).height = _outputHeight; renderTexture.Create(); } Plugin.Log.LogDebug((object)$"Upscaler: {_inputWidth}x{_inputHeight} -> {_outputWidth}x{_outputHeight}"); if (_upscaler != null && (Object)(object)_camera != (Object)null) { _upscaler.Initialize(_camera, _inputWidth, _inputHeight, _outputWidth, _outputHeight); Plugin.Log.LogInfo((object)("Upscaler active: " + _upscaler.Name)); } if (_upscaler != null && (Object)(object)_camera != (Object)null) { Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnPreRenderJitter)); Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRenderRestore)); } if (_useCameraCallback && (Object)(object)_camera != (Object)null) { Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRenderCallback)); } } private void OnPreRenderJitter(Camera cam) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) using (ModTiming.Begin("REPOFidelity.Cam.PreRenderJitter")) { if (!((Object)(object)cam != (Object)(object)_camera) && _upscaler != null && Settings.ModEnabled && _inputWidth > 0 && _inputHeight > 0) { _jitterIndex = (_jitterIndex + 1) % HaltonX.Length; JitterX = (HaltonX[_jitterIndex] - 0.5f) / (float)_inputWidth; JitterY = (HaltonY[_jitterIndex] - 0.5f) / (float)_inputHeight; cam.ResetProjectionMatrix(); _savedProjectionMatrix = cam.projectionMatrix; cam.nonJitteredProjectionMatrix = _savedProjectionMatrix; Matrix4x4 savedProjectionMatrix = _savedProjectionMatrix; savedProjectionMatrix.m02 += JitterX * 2f; savedProjectionMatrix.m12 += JitterY * 2f; cam.projectionMatrix = savedProjectionMatrix; _jitterApplied = true; } } } private void OnPostRenderRestore(Camera cam) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) using (ModTiming.Begin("REPOFidelity.Cam.PostRenderRestore")) { if (!((Object)(object)cam != (Object)(object)_camera) && _jitterApplied) { cam.projectionMatrix = _savedProjectionMatrix; _jitterApplied = false; } } } private void OnPostRenderCallback(Camera cam) { using (ModTiming.Begin("REPOFidelity.Cam.PostRenderCallback")) { if (!((Object)(object)cam != (Object)(object)_camera)) { ProcessFrame(); } } } private static float[] GenerateHalton(int baseVal, int count) { float[] array = new float[count]; for (int i = 0; i < count; i++) { float num = 1f; float num2 = 0f; for (int num3 = i + 1; num3 > 0; num3 /= baseVal) { num /= (float)baseVal; num2 += num * (float)(num3 % baseVal); } array[i] = num2; } return array; } private void LateUpdate() { using (ModTiming.Begin("REPOFidelity.LateUpdate")) { if (!Settings.ModEnabled || (Object)(object)_renderTextureMain == (Object)null || CurrentTier == RenderTier.Passthrough) { return; } int outputWidth = Settings.OutputWidth; int outputHeight = Settings.OutputHeight; if (outputWidth != _outputWidth || outputHeight != _outputHeight) { _outputWidth = outputWidth; _outputHeight = outputHeight; HandleResolutionChange(); } if (CurrentTier == RenderTier.NativeScaling) { if (Settings.Sharpening > 0.01f) { RenderTexture renderTexture = _renderTextureMain.renderTexture; if ((Object)(object)renderTexture != (Object)null) { ApplyCAS(renderTexture); } } } else { if ((Object)(object)_camera != (Object)null && (Object)(object)_outputRT != (Object)null && (Object)(object)_camera.targetTexture != (Object)(object)_outputRT) { _camera.targetTexture = _outputRT; } if (!_useCameraCallback) { ProcessFrame(); } } } } private void ProcessFrame() { using (ModTiming.Begin("REPOFidelity.ProcessFrame")) { if ((Object)(object)_renderTextureMain == (Object)null || _upscaler == null || (Object)(object)_outputRT == (Object)null || !_outputRT.IsCreated()) { return; } RenderTexture renderTexture = _renderTextureMain.renderTexture; if (!((Object)(object)renderTexture == (Object)null) && renderTexture.IsCreated()) { _upscaler.OnRenderImage(_outputRT, renderTexture); if (!(_upscaler is DLSSUpscaler) && Settings.Sharpening > 0.01f) { ApplyCAS(renderTexture); } } } } private static void ApplyCAS(RenderTexture target) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) using (ModTiming.Begin("REPOFidelity.ApplyCAS")) { if (!((Object)(object)target == (Object)null) && target.IsCreated()) { RenderTexture temporary = RenderTexture.GetTemporary(((Texture)target).width, ((Texture)target).height, 0, target.format); CASShader.Apply(target, temporary, Settings.Sharpening); Graphics.Blit((Texture)(object)temporary, target); RenderTexture.ReleaseTemporary(temporary); } } } private void Update() { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Invalid comparison between Unknown and I4 //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Invalid comparison between Unknown and I4 //IL_017d: Unknown result type (might be due to invalid IL or missing references) _shadowBudgetTimer += Time.unscaledDeltaTime; if (_shadowBudgetTimer >= 0.1f) { _shadowBudgetTimer = 0f; using (ModTiming.Begin("REPOFidelity.Tick")) { using (ModTiming.Begin("REPOFidelity.Tick.ShadowBudget")) { SceneOptimizer.UpdateShadowBudget(_camera); } using (ModTiming.Begin("REPOFidelity.Tick.DistanceShadowCull")) { SceneOptimizer.UpdateDistanceShadowCull(_camera); } using (ModTiming.Begin("REPOFidelity.Tick.FlashlightBudget")) { SceneOptimizer.UpdateFlashlightShadowBudget(_camera); } using (ModTiming.Begin("REPOFidelity.Tick.PlayerAvatarShadowCull")) { SceneOptimizer.UpdatePlayerAvatarShadowCull(_camera); } using (ModTiming.Begin("REPOFidelity.Tick.PointLightShadowCull")) { SceneOptimizer.UpdatePointLightShadowCull(_camera); } } } if (Input.GetKeyDown((KeyCode)290) && (int)Settings.ToggleKey != 290 && Settings.DiagnosticsEnabled && (CostProbe.Running || IsInGameplayLevel())) { CostProbe.Toggle(); } if (Input.GetKeyDown((KeyCode)292) && (int)Settings.ToggleKey != 292) { DispatchF11(); } UltrawideCompareResolution.TickEnforcement(); UltrawideMenuTweaks.Tick(); if (!_benchmarkActive && !_togglePending && !MenuIntegration.IsGraphicsPageOpen && Input.GetKeyDown(Settings.ToggleKey)) { bool num = !Settings.ModEnabled; PlayGlitch(); if (!num) { Settings.ModEnabled = false; Plugin.Log.LogInfo((object)"Mod DISABLED"); SceneOptimizer.LogRestoreState("pre-disable"); SceneOptimizer.Apply(); _upscaler?.Dispose(); _upscaler = null; if ((Object)(object)_camera != (Object)null && (Object)(object)_renderTextureMain != (Object)null) { _camera.targetTexture = _renderTextureMain.renderTexture; } RenderTexturePatch.RestoreVanillaResolution(); RenderTexturePatch.RestoreVanillaCameraSettings(); RestoreVanillaSettings(); QualityPatch.RestoreVanillaQuality(); PlayerAvatarMenuAAPatch.RestoreAvatarRt(); if ((Object)(object)GraphicsManager.instance != (Object)null) { GraphicsManager.instance.UpdateAll(); } if ((Object)(object)_camera != (Object)null) { _camera.layerCullDistances = new float[32]; } UltrawideCompareResolution.HandleToggle(enabling: false); SceneOptimizer.LogRestoreState("post-disable"); } else { _togglePending = true; ((MonoBehaviour)this).StartCoroutine(DeferredEnable()); UltrawideCompareResolution.HandleToggle(enabling: true); } } if (_benchmarkActive && !IsInGameplayLevel()) { if (_benchmarkPhase == 0) { ApplyBenchmarkScale(_savedRenderScale); } _benchmarkActive = false; _autoBenchmark = false; QualitySettings.vSyncCount = _benchmarkVsyncPrev; Application.targetFrameRate = _benchmarkFpsPrev; Settings.BenchmarkMode = false; } if (Settings.ModEnabled && Settings.AutoTuneNeedsInitialBenchmark && !_benchmarkActive && !_autoBenchmark && _vanillaSaved && IsInGameplayLevel() && (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && Time.unscaledTime - _lastEnvironmentSetupTime >= 10f) { _autoBenchmark = true; StartBenchmark(); Plugin.Log.LogInfo((object)"=== AUTO-BENCHMARK: autotune profile stale, re-detecting ==="); } if (Settings.BenchmarkMode && !_benchmarkActive) { _autoBenchmark = false; StartBenchmark(); Plugin.Log.LogInfo((object)"=== BENCHMARK STARTED ==="); } if (!_benchmarkActive) { return; } if (_benchmarkWarmup > 0f) { _benchmarkWarmup -= Time.unscaledDeltaTime; return; } _benchmarkTimer += Time.unscaledDeltaTime; float num2 = Time.unscaledDeltaTime * 1000f; if (num2 > 0.01f && num2 < 500f) { _benchmarkFrameTimes.Add(num2); } if (_benchmarkPhase == 0) { bool num3 = _benchmarkTimer >= 4f && _benchmarkFrameTimes.Count > 30; bool flag = _benchmarkTimer >= 12f; if (num3 || flag) { FinishPhase0(); } return; } float num4 = (_autoBenchmark ? 12f : 15f); bool num5 = _benchmarkTimer >= num4 && _benchmarkFrameTimes.Count > 30; bool flag2 = _benchmarkTimer >= num4 * 2f; if (num5 || flag2) { FinishBenchmark(); } } private static void PlayGlitch() { CameraGlitch instance = CameraGlitch.Instance; if (!((Object)(object)instance == (Object)null)) { if ((Object)(object)instance.ActiveParent != (Object)null) { instance.ActiveParent.SetActive(true); } instance.PlayShort(); } } private static void DispatchF11() { switch (Settings.F11TargetSetting) { case F11Target.FullOptLayer: Settings.OptimizationsEnabled = !Settings.OptimizationsEnabled; Plugin.Log.LogInfo((object)("F11: Optimizations " + (Settings.OptimizationsEnabled ? "ENABLED" : "DISABLED"))); if (!Settings.OptimizationsEnabled) { SceneOptimizer.LogRestoreState("pre-opt-disable"); } SceneOptimizer.Apply(); QualityPatch.ApplyQualitySettings(); if (!Settings.OptimizationsEnabled) { SceneOptimizer.LogRestoreState("post-opt-disable"); } break; case F11Target.CpuPatches: Settings.CpuPatchesF11Disabled = !Settings.CpuPatchesF11Disabled; Plugin.Log.LogInfo((object)("F11: CPU patches " + (Settings.CpuPatchesF11Disabled ? "DISABLED" : "ENABLED"))); break; case F11Target.LightDiagnostics: Plugin.Log.LogInfo((object)"F11: Running light diagnostics"); LightDiagnostics.Run(); break; } } [IteratorStateMachine(typeof(d__85))] private IEnumerator DeferredEnable() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__85(0) { <>4__this = this }; } private void HandleResolutionChange() { //IL_0070: 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_0085: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown if (CurrentTier == RenderTier.Upscaler) { float renderScale = RenderTexturePatch.GetRenderScale(); _inputWidth = Mathf.Max(Mathf.RoundToInt((float)_outputWidth * renderScale), 1); _inputHeight = Mathf.Max(Mathf.RoundToInt((float)_outputHeight * renderScale), 1); RenderTexture val = _renderTextureMain?.renderTexture; ReleaseRT(ref _outputRT); RenderTextureFormat val2 = (RenderTextureFormat)((!((Object)(object)val != (Object)null)) ? 9 : ((int)val.format)); _outputRT = new RenderTexture(_inputWidth, _inputHeight, 24, val2) { filterMode = (FilterMode)1, enableRandomWrite = true }; _outputRT.Create(); if ((Object)(object)_camera != (Object)null) { _camera.targetTexture = _outputRT; } if ((Object)(object)val != (Object)null) { val.Release(); ((Texture)val).width = _outputWidth; ((Texture)val).height = _outputHeight; val.Create(); } if (_upscaler != null) { _upscaler.OnResolutionChanged(_inputWidth, _inputHeight, _outputWidth, _outputHeight); } } } private void StartBenchmark() { _benchmarkActive = true; _benchmarkTimer = 0f; _benchmarkWarmup = 3f; _benchmarkFrameTimes.Clear(); _benchmarkPhase = 0; _lowGpuFps = 0f; _benchmarkVsyncPrev = QualitySettings.vSyncCount; _benchmarkFpsPrev = Application.targetFrameRate; QualitySettings.vSyncCount = 0; Application.targetFrameRate = -1; _savedRenderScale = Settings.ResolvedRenderScale; ApplyBenchmarkScale(25); PlayGlitch(); } private void FinishPhase0() { _benchmarkFrameTimes.Sort(); int count = _benchmarkFrameTimes.Count; float median = _benchmarkFrameTimes[count / 2]; List list = _benchmarkFrameTimes.FindAll((float t) => t <= median * 3f); if (list.Count < 10) { _lowGpuFps = 0f; } else { float num = 0f; for (int i = 0; i < list.Count; i++) { num += list[i]; } _lowGpuFps = 1000f / (num / (float)list.Count); } Plugin.Log.LogInfo((object)$"Phase 0 (CPU ceiling): {_lowGpuFps:F0} FPS at 25% scale"); ApplyBenchmarkScale(_savedRenderScale); PlayGlitch(); _benchmarkPhase = 1; _benchmarkTimer = 0f; _benchmarkWarmup = 3f; _benchmarkFrameTimes.Clear(); } private void ApplyBenchmarkScale(int scale) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown Settings.ResolvedRenderScale = scale; int num = Mathf.Max(Mathf.RoundToInt((float)(_outputWidth * scale) / 100f), 1); int num2 = Mathf.Max(Mathf.RoundToInt((float)(_outputHeight * scale) / 100f), 1); if (num == _inputWidth && num2 == _inputHeight) { return; } _inputWidth = num; _inputHeight = num2; if (CurrentTier == RenderTier.Upscaler) { ReleaseRT(ref _outputRT); RenderTexture val = _renderTextureMain?.renderTexture; RenderTextureFormat val2 = (RenderTextureFormat)((!((Object)(object)val != (Object)null)) ? 9 : ((int)val.format)); _outputRT = new RenderTexture(num, num2, 24, val2) { filterMode = (FilterMode)1 }; _outputRT.Create(); if ((Object)(object)_camera != (Object)null) { _camera.targetTexture = _outputRT; } if (_upscaler != null) { _upscaler.OnResolutionChanged(num, num2, _outputWidth, _outputHeight); } } } private void FinishBenchmark() { //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Invalid comparison between Unknown and I4 //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Invalid comparison between Unknown and I4 //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) try { _benchmarkFrameTimes.Sort(); int count = _benchmarkFrameTimes.Count; float median = _benchmarkFrameTimes[count / 2]; List list = _benchmarkFrameTimes.FindAll((float t) => t <= median * 3f); int count2 = list.Count; if (count2 < 10) { Plugin.Log.LogWarning((object)"Benchmark: too few valid frames — skipping auto-tune"); return; } float num = 0f; for (int i = 0; i < count2; i++) { num += list[i]; } float num2 = num / (float)count2; float num3 = 1000f / num2; int num4 = Mathf.Max(count2 / 100, 1); float num5 = 0f; for (int j = count2 - num4; j < count2; j++) { num5 += list[j]; } float num6 = num5 / (float)num4; float num7 = 1000f / num6; float num8 = 0f; if (count2 >= 1000) { int num9 = Mathf.Max(count2 / 1000, 1); float num10 = 0f; for (int k = count2 - num9; k < count2; k++) { num10 += list[k]; } num8 = 1000f / (num10 / (float)num9); } string text = Settings.Preset.ToString(); string text2 = ((_upscaler != null) ? _upscaler.Name : "Off"); string text3 = ((CurrentTier == RenderTier.Upscaler) ? $"{_inputWidth}x{_inputHeight}" : "native"); int num11 = count - count2; bool flag = true; if (_lowGpuFps > 0f && num3 > 0f) { float num12 = num3 / _lowGpuFps; float num13 = ((num3 > 120f) ? 0.95f : 0.85f); flag = num12 >= num13; Plugin.Log.LogInfo((object)$" Ratio: {num12:P1}, threshold: {num13:P0} (fps={num3:F0})"); Resolution currentResolution = Screen.currentResolution; RefreshRate refreshRateRatio = ((Resolution)(ref currentResolution)).refreshRateRatio; float num14 = Mathf.Max((float)((RefreshRate)(ref refreshRateRatio)).value, 60f); bool flag2 = (int)Application.platform == 13 || (int)SystemInfo.graphicsDeviceType == 21; if (!flag && _lowGpuFps < num14) { flag = true; Plugin.Log.LogInfo((object)($" Bottleneck override: CPU ceiling ({_lowGpuFps:F0}) < target ({num14:F0}) " + "-> CPU-BOUND (CPU can't sustain target even at minimum GPU load)")); } else if (!flag && flag2 && num12 < 0.95f) { flag = true; Plugin.Log.LogInfo((object)(" Bottleneck override: translation layer detected " + $"({Application.platform}/{SystemInfo.graphicsDeviceType}), " + $"ratio {num12:P0} < 95% -> CPU-BOUND")); } Plugin.Log.LogInfo((object)($" Bottleneck: {num3:F0} / {_lowGpuFps:F0} ceiling = {num12:P0} " + "-> " + (flag ? "CPU-BOUND" : "GPU-bound"))); } Plugin.Log.LogInfo((object)"=== BENCHMARK RESULTS ==="); Plugin.Log.LogInfo((object)$" Preset: {text} | Upscaler: {text2} | Render: {text3} -> {_outputWidth}x{_outputHeight}"); Plugin.Log.LogInfo((object)$" CPU: {SystemInfo.processorType} ({SystemInfo.processorCount} threads)"); Plugin.Log.LogInfo((object)$" RAM: {SystemInfo.systemMemorySize}MB | Platform: {Application.platform} | API: {SystemInfo.graphicsDeviceType}"); Plugin.Log.LogInfo((object)$" Frames: {count2} measured, {num11} outliers discarded"); Plugin.Log.LogInfo((object)$" Avg: {num3:F1} FPS ({num2:F1}ms)"); Plugin.Log.LogInfo((object)$" 1% Low: {num7:F1} FPS ({num6:F1}ms)"); if (num8 > 0f) { Plugin.Log.LogInfo((object)$" 0.1% Low: {num8:F1} FPS"); } Plugin.Log.LogInfo((object)$" CPU ceiling (25% scale): {_lowGpuFps:F1} FPS | Full scale: {num3:F1} FPS | Ratio: {num3 / Mathf.Max(_lowGpuFps, 1f):P0}"); Plugin.Log.LogInfo((object)"========================="); Settings.AutoSelectPreset(num3, num7, num8, flag); PlayGlitch(); } finally { QualitySettings.vSyncCount = _benchmarkVsyncPrev; Application.targetFrameRate = _benchmarkFpsPrev; if (_autoBenchmark) { _autoBenchmark = false; } _benchmarkActive = false; Settings.BenchmarkMode = false; } } private static bool IsInGameplayLevel() { if ((Object)(object)RunManager.instance == (Object)null) { return false; } return SemiFunc.RunIsLevel(); } private static void ReleaseRT(ref RenderTexture? rt) { if ((Object)(object)rt != (Object)null) { rt.Release(); Object.Destroy((Object)(object)rt); rt = null; } } internal static void SetModFarClip(Camera? cam, float newValue) { if (!((Object)(object)cam == (Object)null) && (!((Object)(object)SpectateCamera.instance != (Object)null) || !SpectateCamera.instance.CheckState((State)0))) { if (!_vanillaFarClipByCam.ContainsKey(cam)) { _vanillaFarClipByCam[cam] = cam.farClipPlane; } cam.farClipPlane = newValue; } } internal static float GetVanillaFarClip(Camera? cam) { if ((Object)(object)cam == (Object)null) { return 0f; } if (!_vanillaFarClipByCam.TryGetValue(cam, out var value)) { return cam.farClipPlane; } return value; } internal static void SaveVanillaFog(EnvironmentDirector env) { _vanillaFogStart = env.FogStartDistance; _vanillaFogEnd = env.FogEndDistance; _vanillaSaved = true; _environmentSetupCount++; _lastEnvironmentSetupTime = Time.unscaledTime; Settings.ResolvedEffectiveFogEnd = _vanillaFogEnd * Settings.ResolvedFogMultiplier; Settings.ApplyFogClamps(); Plugin.Log.LogDebug((object)$"Vanilla fog: start={_vanillaFogStart:F0}m end={_vanillaFogEnd:F0}m (env #{_environmentSetupCount})"); } private void RestoreVanillaSettings() { if (_vanillaSaved) { RenderSettings.fogStartDistance = _vanillaFogStart; RenderSettings.fogEndDistance = _vanillaFogEnd; } foreach (KeyValuePair item in _vanillaFarClipByCam) { if ((Object)(object)item.Key != (Object)null) { item.Key.farClipPlane = item.Value; } } _vanillaFarClipByCam.Clear(); Plugin.Log.LogInfo((object)"Vanilla settings restored"); } private void OnDestroy() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown Settings.OnSettingsChanged -= Reinitialize; Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnPreRenderJitter)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRenderRestore)); if (_useCameraCallback) { Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRenderCallback)); } _upscaler?.Dispose(); if ((Object)(object)_camera != (Object)null && (Object)(object)_renderTextureMain != (Object)null) { _camera.targetTexture = _renderTextureMain.renderTexture; } ReleaseRT(ref _outputRT); Instance = null; } } } namespace REPOFidelity.Upscalers { internal class DLSSUpscaler : IUpscaler { [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void GetDeviceDelegate(IntPtr self, out IntPtr device); private readonly bool _dlaaMode; private bool _probed; private bool _available; private Camera? _camera; private IntPtr _dlssHandle; private IntPtr _evalParams; private int _inputWidth; private int _inputHeight; private int _outputWidth; private int _outputHeight; private RenderTexture? _dlssOutputRT; private RenderTexture? _depthRT; private RenderTexture? _motionVectorRT; private CommandBuffer? _depthCopyCmd; private CommandBuffer? _mvCopyCmd; private int _evalFailCount; private int _evalSuccessLogged; private bool _needsReset; public string Name { get { if (!_dlaaMode) { return "DLSS"; } return "DLAA"; } } public bool IsAvailable { get { if (!_probed) { Probe(); } return _available; } } public DLSSUpscaler(bool dlaaMode = false) { _dlaaMode = dlaaMode; } private void Probe() { //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_0098: Expected O, but got Unknown if (_probed) { return; } _probed = true; try { if (!DLSSDownloader.EnsureAvailable()) { Plugin.Log.LogWarning((object)"DLSS: nvngx_dlss.dll not available — DLSS disabled"); return; } if (!NGXBridge.Preload()) { Plugin.Log.LogWarning((object)"DLSS: ngx_bridge.dll not available"); return; } NGXBridge.HookLog(); if (NGXBridge.NGXBridge_Load() == 0) { Plugin.Log.LogWarning((object)"DLSS: ngx_bridge failed to load _nvngx.dll"); return; } Texture2D val = new Texture2D(1, 1); IntPtr nativeTexturePtr = ((Texture)val).GetNativeTexturePtr(); Marshal.GetDelegateForFunctionPointer(Marshal.ReadIntPtr(Marshal.ReadIntPtr(nativeTexturePtr), 3 * IntPtr.Size))(nativeTexturePtr, out var device); Object.Destroy((Object)val); if (device == IntPtr.Zero) { Plugin.Log.LogWarning((object)"DLSS: Could not extract D3D11 device"); return; } Plugin.Log.LogDebug((object)$"DLSS: D3D11 device: 0x{device:X}"); if (NGXBridge.NGXBridge_InitD3D11(device) == 0) { Plugin.Log.LogWarning((object)"DLSS: NGX D3D11 base init failed"); return; } if (NGXBridge.NGXBridge_InitD3D12() == 0) { Plugin.Log.LogWarning((object)"DLSS: NGX D3D12 interop init failed"); return; } _available = NGXBridge.NGXBridge_IsDLSSAvailable_D3D12() != 0; Plugin.Log.LogDebug((object)$"DLSS: available = {_available}"); } catch (DllNotFoundException) { Plugin.Log.LogWarning((object)"DLSS: ngx_bridge.dll not found — DLSS disabled"); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("DLSS probe failed: " + ex2.GetType().Name + ": " + ex2.Message)); } } public void Initialize(Camera camera, int inputWidth, int inputHeight, int outputWidth, int outputHeight) { //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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) _camera = camera; _inputWidth = (_dlaaMode ? outputWidth : inputWidth); _inputHeight = (_dlaaMode ? outputHeight : inputHeight); _outputWidth = outputWidth; _outputHeight = outputHeight; NGXBridge.NGXBridge_ClearSharedCache(); if ((Object)(object)_dlssOutputRT != (Object)null) { _dlssOutputRT.Release(); Object.Destroy((Object)(object)_dlssOutputRT); } _dlssOutputRT = new RenderTexture(_outputWidth, _outputHeight, 0, (RenderTextureFormat)0) { filterMode = (FilterMode)1, enableRandomWrite = true }; _dlssOutputRT.Create(); RenderTexture active = RenderTexture.active; RenderTexture.active = _dlssOutputRT; GL.Clear(false, true, Color.black); RenderTexture.active = active; SetupCapture(_inputWidth, _inputHeight); _evalParams = NGXBridge.NGXBridge_AllocParams_D3D12(); if (_evalParams == IntPtr.Zero) { Plugin.Log.LogError((object)"DLSS: params alloc failed"); return; } NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "Width", (uint)_inputWidth); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "Height", (uint)_inputHeight); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "OutWidth", (uint)_outputWidth); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "OutHeight", (uint)_outputHeight); NGXBridge.NGXBridge_ParamSetInt(_evalParams, "PerfQualityValue", GetQualityMode()); int val = ((!_dlaaMode) ? 2 : 0); NGXBridge.NGXBridge_ParamSetInt(_evalParams, "DLSS.Feature.Create.Flags", val); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Hint.Render.Preset.DLAA", 5u); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Hint.Render.Preset.Quality", 5u); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Hint.Render.Preset.Balanced", 5u); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Hint.Render.Preset.Performance", 5u); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Hint.Render.Preset.UltraPerformance", 5u); _dlssHandle = NGXBridge.NGXBridge_CreateDLSS_D3D12(_evalParams); if (_dlssHandle == IntPtr.Zero) { Plugin.Log.LogError((object)"DLSS: Feature creation failed"); return; } _needsReset = true; Plugin.Log.LogDebug((object)$"DLSS initialized: {_inputWidth}x{_inputHeight} -> {_outputWidth}x{_outputHeight}"); } public void OnRenderImage(RenderTexture source, RenderTexture destination) { if (_dlssHandle == IntPtr.Zero || _evalParams == IntPtr.Zero) { Graphics.Blit((Texture)(object)source, destination); return; } if (((Texture)source).width != _inputWidth || ((Texture)source).height != _inputHeight) { Graphics.Blit((Texture)(object)source, destination); return; } NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Render.Subrect.Dimensions.Width", (uint)((Texture)source).width); NGXBridge.NGXBridge_ParamSetUInt(_evalParams, "DLSS.Render.Subrect.Dimensions.Height", (uint)((Texture)source).height); NGXBridge.NGXBridge_ParamSetFloat(_evalParams, "MV.Scale.X", 0f - (float)_inputWidth); NGXBridge.NGXBridge_ParamSetFloat(_evalParams, "MV.Scale.Y", 0f - (float)_inputHeight); NGXBridge.NGXBridge_ParamSetFloat(_evalParams, "Jitter.Offset.X", 0f); NGXBridge.NGXBridge_ParamSetFloat(_evalParams, "Jitter.Offset.Y", 0f); NGXBridge.NGXBridge_ParamSetFloat(_evalParams, "Sharpness", 0f); NGXBridge.NGXBridge_ParamSetFloat(_evalParams, "FrameTimeDeltaInMsec", Time.unscaledDeltaTime * 1000f); NGXBridge.NGXBridge_ParamSetInt(_evalParams, "Reset", _needsReset ? 1 : 0); RenderTexture val = _dlssOutputRT ?? destination; if (NGXBridge.NGXBridge_EvalDLSS_D3D12(_dlssHandle, _evalParams, ((Texture)source).GetNativeTexturePtr(), ((Object)(object)_depthRT != (Object)null) ? ((Texture)_depthRT).GetNativeTexturePtr() : IntPtr.Zero, ((Object)(object)_motionVectorRT != (Object)null) ? ((Texture)_motionVectorRT).GetNativeTexturePtr() : IntPtr.Zero, ((Texture)val).GetNativeTexturePtr()) == 0) { if (_evalFailCount++ < 5) { Plugin.Log.LogWarning((object)($"DLSS D3D12 eval failed (frame {_evalFailCount}) " + $"src={((Texture)source).width}x{((Texture)source).height} out={((Texture)val).width}x{((Texture)val).height}")); } Graphics.Blit((Texture)(object)source, destination); return; } _needsReset = false; if ((Object)(object)_dlssOutputRT != (Object)null) { Graphics.Blit((Texture)(object)_dlssOutputRT, destination); } if (_evalSuccessLogged++ < 3) { Plugin.Log.LogDebug((object)$"DLSS D3D12 eval OK — {((Texture)source).width}x{((Texture)source).height} -> {((Texture)destination).width}x{((Texture)destination).height}"); } } public void OnResolutionChanged(int inputWidth, int inputHeight, int outputWidth, int outputHeight) { NGXBridge.NGXBridge_ClearSharedCache(); CleanupFeature(); if ((Object)(object)_camera != (Object)null) { Initialize(_camera, inputWidth, inputHeight, outputWidth, outputHeight); } } public void Dispose() { CleanupCapture(); CleanupFeature(); if ((Object)(object)_dlssOutputRT != (Object)null) { _dlssOutputRT.Release(); Object.Destroy((Object)(object)_dlssOutputRT); _dlssOutputRT = null; } if (_evalParams != IntPtr.Zero) { NGXBridge.NGXBridge_DestroyParams_D3D12(_evalParams); _evalParams = IntPtr.Zero; } } private void CleanupFeature() { if (_dlssHandle != IntPtr.Zero) { NGXBridge.NGXBridge_ReleaseDLSS_D3D12(_dlssHandle); _dlssHandle = IntPtr.Zero; } } private void SetupCapture(int width, int height) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_008d: 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_00a2: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) CleanupCapture(); _depthRT = new RenderTexture(width, height, 0, (RenderTextureFormat)14) { filterMode = (FilterMode)0, enableRandomWrite = true }; _depthRT.Create(); _depthCopyCmd = new CommandBuffer { name = "DLSS Depth" }; _depthCopyCmd.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)3), RenderTargetIdentifier.op_Implicit((Texture)(object)_depthRT)); _motionVectorRT = new RenderTexture(width, height, 0, (RenderTextureFormat)13) { filterMode = (FilterMode)0, enableRandomWrite = true }; _motionVectorRT.Create(); _mvCopyCmd = new CommandBuffer { name = "DLSS MV" }; _mvCopyCmd.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)15), RenderTargetIdentifier.op_Implicit((Texture)(object)_motionVectorRT)); if ((Object)(object)_camera != (Object)null) { _camera.AddCommandBuffer((CameraEvent)1, _depthCopyCmd); _camera.AddCommandBuffer((CameraEvent)20, _mvCopyCmd); } } private void CleanupCapture() { if ((Object)(object)_camera != (Object)null) { if (_depthCopyCmd != null) { _camera.RemoveCommandBuffer((CameraEvent)1, _depthCopyCmd); } if (_mvCopyCmd != null) { _camera.RemoveCommandBuffer((CameraEvent)20, _mvCopyCmd); } } CommandBuffer? depthCopyCmd = _depthCopyCmd; if (depthCopyCmd != null) { depthCopyCmd.Dispose(); } _depthCopyCmd = null; CommandBuffer? mvCopyCmd = _mvCopyCmd; if (mvCopyCmd != null) { mvCopyCmd.Dispose(); } _mvCopyCmd = null; if ((Object)(object)_depthRT != (Object)null) { _depthRT.Release(); Object.Destroy((Object)(object)_depthRT); _depthRT = null; } if ((Object)(object)_motionVectorRT != (Object)null) { _motionVectorRT.Release(); Object.Destroy((Object)(object)_motionVectorRT); _motionVectorRT = null; } } private int GetQualityMode() { if (_dlaaMode) { return 5; } int resolvedRenderScale = Settings.ResolvedRenderScale; if (resolvedRenderScale >= 59) { if (resolvedRenderScale >= 77) { return 2; } return 1; } if (resolvedRenderScale >= 45) { return 0; } return 3; } } internal interface IUpscaler { string Name { get; } bool IsAvailable { get; } void Initialize(Camera camera, int inputWidth, int inputHeight, int outputWidth, int outputHeight); void OnRenderImage(RenderTexture source, RenderTexture destination); void OnResolutionChanged(int inputWidth, int inputHeight, int outputWidth, int outputHeight); void Dispose(); } internal static class NGXBridge { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void LogCallbackDelegate([MarshalAs(UnmanagedType.LPStr)] string message); private const string DLL = "ngx_bridge"; internal const int DLSS_MaxPerf = 0; internal const int DLSS_Balanced = 1; internal const int DLSS_MaxQuality = 2; internal const int DLSS_UltraPerformance = 3; internal const int DLSS_UltraQuality = 4; internal const int DLSS_DLAA = 5; private static LogCallbackDelegate? _logDelegate; private static bool _logHooked; private static bool _preloaded; [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_SetLogCallback(LogCallbackDelegate cb); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern int NGXBridge_Load(); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern int NGXBridge_InitD3D11(IntPtr device); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern int NGXBridge_InitD3D12(); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_ParamSetInt(IntPtr p, [MarshalAs(UnmanagedType.LPStr)] string name, int val); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_ParamSetUInt(IntPtr p, [MarshalAs(UnmanagedType.LPStr)] string name, uint val); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_ParamSetFloat(IntPtr p, [MarshalAs(UnmanagedType.LPStr)] string name, float val); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_Shutdown(); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern int NGXBridge_IsDLSSAvailable_D3D12(); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr NGXBridge_AllocParams_D3D12(); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_DestroyParams_D3D12(IntPtr p); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr NGXBridge_CreateDLSS_D3D12(IntPtr parameters); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_ReleaseDLSS_D3D12(IntPtr handle); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern int NGXBridge_EvalDLSS_D3D12(IntPtr handle, IntPtr parameters, IntPtr color, IntPtr depth, IntPtr motion, IntPtr output); [DllImport("ngx_bridge", CallingConvention = CallingConvention.Cdecl)] internal static extern void NGXBridge_ClearSharedCache(); [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibraryW(string path); internal static bool Preload() { if (_preloaded) { return true; } _preloaded = true; string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "ngx_bridge.dll"); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("ngx_bridge.dll not found at: " + text)); return false; } if (LoadLibraryW(text) == IntPtr.Zero) { Plugin.Log.LogWarning((object)$"Failed to preload ngx_bridge.dll (error {Marshal.GetLastWin32Error()})"); return false; } Plugin.Log.LogDebug((object)("Preloaded ngx_bridge.dll from: " + text)); return true; } internal static void HookLog() { if (!_logHooked) { _logHooked = true; _logDelegate = delegate(string msg) { Plugin.Log.LogDebug((object)("[NGX] " + msg)); }; NGXBridge_SetLogCallback(_logDelegate); } } } internal class TemporalUpscaler : IUpscaler { private bool _shaderChecked; private Material? _material; private Camera? _camera; private RenderTexture? _historyRT; private int _inputWidth; private int _inputHeight; private int _outputWidth; private int _outputHeight; private bool _needsReset = true; private RenderTexture? _motionVectorRT; private CommandBuffer? _mvCopyCmd; private static readonly int PrevTexId = Shader.PropertyToID("_PrevTex"); private static readonly int MotionVectorTexId = Shader.PropertyToID("_MotionVectorTex"); private static readonly int DepthTexId = Shader.PropertyToID("_DepthTex"); private static readonly int OutputSizeId = Shader.PropertyToID("_OutputSize"); private static readonly int InputSizeId = Shader.PropertyToID("_InputSize"); private static readonly int JitterId = Shader.PropertyToID("_Jitter"); private static readonly int ResetId = Shader.PropertyToID("_Reset"); public string Name => "FSR Temporal"; public bool IsAvailable { get { //IL_003b: 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_004d: Expected O, but got Unknown if ((Object)(object)_material == (Object)null && !_shaderChecked) { _shaderChecked = true; Shader val = ShaderBundle.LoadShader("Hidden/REPOFidelity/FSR_Temporal"); if ((Object)(object)val != (Object)null && val.isSupported) { _material = new Material(val) { hideFlags = (HideFlags)61 }; } } return (Object)(object)_material != (Object)null; } } public void Initialize(Camera camera, int inputWidth, int inputHeight, int outputWidth, int outputHeight) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown _camera = camera; _inputWidth = inputWidth; _inputHeight = inputHeight; _outputWidth = outputWidth; _outputHeight = outputHeight; _needsReset = true; if ((Object)(object)_material == (Object)null) { Plugin.Log.LogWarning((object)"Temporal upscale shader not available"); return; } _historyRT = new RenderTexture(outputWidth, outputHeight, 0, (RenderTextureFormat)9) { filterMode = (FilterMode)1 }; _historyRT.Create(); SetupMotionVectorCapture(inputWidth, inputHeight); Plugin.Log.LogDebug((object)$"Temporal upscaler initialized: {inputWidth}x{inputHeight} -> {outputWidth}x{outputHeight}"); } public void OnRenderImage(RenderTexture source, RenderTexture destination) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_material == (Object)null || (Object)(object)_historyRT == (Object)null) { Graphics.Blit((Texture)(object)source, destination); return; } _material.SetTexture(PrevTexId, (Texture)(object)_historyRT); if ((Object)(object)_motionVectorRT != (Object)null) { _material.SetTexture(MotionVectorTexId, (Texture)(object)_motionVectorRT); } _material.SetVector(OutputSizeId, new Vector4((float)_outputWidth, (float)_outputHeight, 1f / (float)_outputWidth, 1f / (float)_outputHeight)); _material.SetVector(InputSizeId, new Vector4((float)_inputWidth, (float)_inputHeight, 1f / (float)_inputWidth, 1f / (float)_inputHeight)); UpscalerManager instance = UpscalerManager.Instance; float num = (((Object)(object)instance != (Object)null) ? (instance.JitterX * (float)_inputWidth) : 0f); float num2 = (((Object)(object)instance != (Object)null) ? (instance.JitterY * (float)_inputHeight) : 0f); _material.SetVector(JitterId, Vector4.op_Implicit(new Vector2(num, num2))); _material.SetFloat(ResetId, _needsReset ? 1f : 0f); _needsReset = false; Graphics.Blit((Texture)(object)source, destination, _material); Graphics.Blit((Texture)(object)destination, _historyRT); } public void OnResolutionChanged(int inputWidth, int inputHeight, int outputWidth, int outputHeight) { Dispose(); if ((Object)(object)_camera != (Object)null) { Initialize(_camera, inputWidth, inputHeight, outputWidth, outputHeight); } } public void Dispose() { CleanupMotionVectorCapture(); if ((Object)(object)_historyRT != (Object)null) { _historyRT.Release(); Object.Destroy((Object)(object)_historyRT); _historyRT = null; } } private void SetupMotionVectorCapture(int width, int height) { //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_001d: Expected O, but got Unknown //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_003f: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) CleanupMotionVectorCapture(); _motionVectorRT = new RenderTexture(width, height, 0, (RenderTextureFormat)12) { filterMode = (FilterMode)0 }; _motionVectorRT.Create(); _mvCopyCmd = new CommandBuffer { name = "FSR Temporal MV Copy" }; _mvCopyCmd.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)15), RenderTargetIdentifier.op_Implicit((Texture)(object)_motionVectorRT)); if ((Object)(object)_camera != (Object)null) { _camera.AddCommandBuffer((CameraEvent)20, _mvCopyCmd); } } private void CleanupMotionVectorCapture() { if ((Object)(object)_camera != (Object)null && _mvCopyCmd != null) { _camera.RemoveCommandBuffer((CameraEvent)20, _mvCopyCmd); } CommandBuffer? mvCopyCmd = _mvCopyCmd; if (mvCopyCmd != null) { mvCopyCmd.Dispose(); } _mvCopyCmd = null; if ((Object)(object)_motionVectorRT != (Object)null) { _motionVectorRT.Release(); Object.Destroy((Object)(object)_motionVectorRT); _motionVectorRT = null; } } } } namespace REPOFidelity.Shaders { internal static class CASShader { private static Material? _material; private static bool _initialized; private static readonly int SharpnessId = Shader.PropertyToID("_Sharpness"); private static void Init() { //IL_003b: 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_004d: Expected O, but got Unknown if (!_initialized) { _initialized = true; Shader val = ShaderBundle.LoadShader("Hidden/REPOFidelity/CAS"); if ((Object)(object)val == (Object)null || !val.isSupported) { Plugin.Log.LogWarning((object)"CAS shader unavailable"); return; } _material = new Material(val) { hideFlags = (HideFlags)61 }; Plugin.Log.LogInfo((object)"CAS shader loaded"); } } public static void Apply(RenderTexture source, RenderTexture destination, float sharpness) { Init(); if ((Object)(object)_material == (Object)null) { Graphics.Blit((Texture)(object)source, destination); return; } _material.SetFloat(SharpnessId, sharpness); Graphics.Blit((Texture)(object)source, destination, _material); } } internal static class FSRShaders { private static Material? _easuMaterial; private static Material? _rcasMaterial; private static bool _initialized; private static void Init() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_006c: Expected O, but got Unknown if (!_initialized) { _initialized = true; Shader val = ShaderBundle.LoadShader("Hidden/REPOFidelity/FSR_EASU"); if ((Object)(object)val != (Object)null && val.isSupported) { _easuMaterial = new Material(val) { hideFlags = (HideFlags)61 }; } Shader val2 = ShaderBundle.LoadShader("Hidden/REPOFidelity/FSR_RCAS"); if ((Object)(object)val2 != (Object)null && val2.isSupported) { _rcasMaterial = new Material(val2) { hideFlags = (HideFlags)61 }; } if ((Object)(object)_easuMaterial != (Object)null) { Plugin.Log.LogInfo((object)"FSR shaders loaded from bundle"); } else { Plugin.Log.LogWarning((object)"FSR EASU shader unavailable — FSR upscaling disabled"); } } } public static Material? GetEASUMaterial() { Init(); return _easuMaterial; } public static Material? GetRCASMaterial() { Init(); return _rcasMaterial; } } internal static class ShaderBundle { private static AssetBundle? _bundle; private static bool _loadAttempted; private static Shader?[]? _allShaders; public static Shader? LoadShader(string name) { Shader[] allShaders; if (!_loadAttempted) { _loadAttempted = true; _bundle = TryLoadBundle(); if ((Object)(object)_bundle != (Object)null) { _allShaders = _bundle.LoadAllAssets(); Plugin.Log.LogDebug((object)$"Loaded {_allShaders.Length} shader(s) from bundle"); allShaders = _allShaders; foreach (Shader val in allShaders) { if ((Object)(object)val != (Object)null) { Plugin.Log.LogDebug((object)(" Shader: " + ((Object)val).name)); } } } } if (_allShaders == null) { return null; } allShaders = _allShaders; foreach (Shader val2 in allShaders) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == name) { return val2; } } Plugin.Log.LogWarning((object)("Shader '" + name + "' not found in bundle")); return null; } private static AssetBundle? TryLoadBundle() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (directoryName == null) { return null; } string text = Path.Combine(directoryName, "repofidelity_shaders"); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("Shader bundle not found at: " + text)); Plugin.Log.LogWarning((object)"FSR and CAS shaders unavailable. Build the shader bundle in Unity Editor."); return null; } AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Failed to load shader AssetBundle"); return null; } Plugin.Log.LogDebug((object)"Shader bundle loaded successfully"); return val; } } } namespace REPOFidelity.Patches { [HarmonyPatch(typeof(PhysGrabObjectGrabArea), "Update")] internal static class GrabAreaIdleSkipPatch { private static bool Prefix(PhysGrabObjectGrabArea __instance) { if (!Settings.ModEnabled || !Settings.AllocationFixesEnabled) { return true; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return false; } List list = (((Object)(object)__instance.physGrabObject != (Object)null) ? __instance.physGrabObject.playerGrabbing : __instance.staticGrabObject?.playerGrabbing); if (list != null && list.Count > 0) { return true; } if (__instance.listOfAllGrabbers.Count > 0) { return true; } return false; } } [HarmonyPatch(typeof(AudioListenerFollow), "Update")] internal static class AudioListenerFollowNonAllocPatch { private static readonly Collider[] _buf = (Collider[])(object)new Collider[8]; private static int _triggerMask = -1; private static bool Prefix(AudioListenerFollow __instance) { //IL_005c: 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_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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ModEnabled || !Settings.AllocationFixesEnabled) { return true; } if (!Object.op_Implicit((Object)(object)__instance.TargetPositionTransform)) { return false; } bool num = Object.op_Implicit((Object)(object)SpectateCamera.instance) && SpectateCamera.instance.CheckState((State)0); Transform targetPositionTransform = __instance.TargetPositionTransform; if (num) { ((Component)__instance).transform.position = targetPositionTransform.position; } else { ((Component)__instance).transform.position = targetPositionTransform.position + targetPositionTransform.forward * AssetManager.instance.mainCamera.nearClipPlane; } Transform targetRotationTransform = __instance.TargetRotationTransform; if (!Object.op_Implicit((Object)(object)targetRotationTransform)) { return false; } ((Component)__instance).transform.rotation = targetRotationTransform.rotation; if (!GameDirector.instance.fpsImpulse15) { return false; } if (_triggerMask < 0) { _triggerMask = LayerMask.GetMask(new string[1] { "LowPassTrigger" }); } __instance.lowPassTrigger = null; if (Physics.OverlapSphereNonAlloc(((Component)__instance).transform.position, 0.1f, _buf, _triggerMask, (QueryTriggerInteraction)2) > 0) { Collider val = _buf[0]; __instance.lowPassTrigger = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent(); } return false; } } [HarmonyPatch(typeof(EnemyDirector), "Update")] internal static class EnemyDirectorThrottlePatch { private static int _frameSkip; private static float _cachedActionDelta; private static bool Prefix(EnemyDirector __instance) { //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Invalid comparison between Unknown and I4 //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Invalid comparison between Unknown and I4 //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Invalid comparison between Unknown and I4 if (!Settings.ModEnabled || !Settings.CpuPatchesActive) { return true; } long startTicks = FrameTimeMeter.Begin(); if (LevelGenerator.Instance.Generated && __instance.spawnIdlePauseTimer > 0f) { bool flag = true; foreach (EnemyParent item in __instance.enemiesSpawned) { if (Object.op_Implicit((Object)(object)item) && !item.firstSpawnPointUsed) { flag = false; break; } } if (flag) { __instance.spawnIdlePauseTimer -= Time.deltaTime; } if (__instance.debugNoSpawnIdlePause) { __instance.spawnIdlePauseTimer = 0f; } } __instance.despawnedDecreaseTimer -= Time.deltaTime; if (__instance.despawnedDecreaseTimer <= 0f) { __instance.despawnedDecreaseMultiplier -= __instance.despawnedDecreasePercent; if (__instance.despawnedDecreaseMultiplier < 0f) { __instance.despawnedDecreaseMultiplier = 0f; } __instance.despawnedDecreaseTimer = 60f * __instance.despawnedDecreaseMinutes; } if (RoundDirector.instance.allExtractionPointsCompleted) { foreach (EnemyParent item2 in __instance.enemiesSpawned) { if (Object.op_Implicit((Object)(object)item2) && item2.DespawnedTimer > 30f) { item2.DespawnedTimerSet(0f, false); } } RunExtractionLogic(__instance); } _frameSkip = (_frameSkip + 1) % 3; if (_frameSkip == 0) { float num = 0f; foreach (EnemyParent item3 in __instance.enemiesSpawned) { if (Object.op_Implicit((Object)(object)item3) && item3.Spawned && item3.playerClose && !item3.forceLeave && CheckRoomOverlap(item3.currentRooms)) { Difficulty difficulty = item3.difficulty; float num2 = (((int)difficulty == 1) ? 1f : (((int)difficulty != 2) ? 0.5f : 2f)); float num3 = num2; num += num3 * item3.actionMultiplier; } } _cachedActionDelta = num; } if (_cachedActionDelta > 0f) { __instance.enemyActionAmount += _cachedActionDelta * Time.deltaTime; } else { __instance.enemyActionAmount -= 0.1f * Time.deltaTime; __instance.enemyActionAmount = Mathf.Max(0f, __instance.enemyActionAmount); } float num4 = (__instance.debugShortActionTimer ? 5f : 120f); if (__instance.enemyActionAmount > num4) { __instance.enemyActionAmount = 0f; LevelPoint val = SemiFunc.LevelPointGetFurthestFromPlayer(((Component)__instance).transform.position, 5f); if (Object.op_Implicit((Object)(object)val)) { __instance.SetInvestigate(((Component)val).transform.position, float.MaxValue, true); } if (RoundDirector.instance.allExtractionPointsCompleted && (int)__instance.extractionsDoneState == 1) { __instance.investigatePointTimer = 60f; } foreach (EnemyParent item4 in __instance.enemiesSpawned) { if (Object.op_Implicit((Object)(object)item4) && item4.Spawned) { item4.forceLeave = true; } } } FrameTimeMeter.End(FrameTimeMeter.EnemyDirector, startTicks); return false; } private static void RunExtractionLogic(EnemyDirector inst) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (inst.investigatePointTimer <= 0f) { if ((int)inst.extractionsDoneState == 0) { inst.enemyActionAmount = 0f; inst.despawnedDecreaseMultiplier = 0f; if (inst.extractionDoneStateImpulse) { inst.extractionDoneStateTimer = 10f; inst.extractionDoneStateImpulse = false; foreach (EnemyParent item in inst.enemiesSpawned) { if (Object.op_Implicit((Object)(object)item) && item.Spawned && !item.playerClose) { item.SpawnedTimerPause(0f); item.SpawnedTimerSet(0f); } } } inst.investigatePointTimer = inst.investigatePointTime; List list = SemiFunc.LevelPointsGetInStartRoom(); if (list.Count > 0) { SemiFunc.EnemyInvestigate(((Component)list[Random.Range(0, list.Count)]).transform.position, 100f, true); } inst.extractionDoneStateTimer -= inst.investigatePointTime; if (inst.extractionDoneStateTimer <= 0f) { inst.extractionsDoneState = (ExtractionsDoneState)1; } } else { List list2 = SemiFunc.LevelPointsGetInPlayerRooms(); if (list2.Count > 0) { SemiFunc.EnemyInvestigate(((Component)list2[Random.Range(0, list2.Count)]).transform.position, 100f, true); } inst.investigatePointTimer = inst.investigatePointTime; inst.investigatePointTime = Mathf.Min(inst.investigatePointTime + 2f, 30f); } } else { inst.investigatePointTimer -= Time.deltaTime; } } private static bool CheckRoomOverlap(List enemyRooms) { foreach (PlayerAvatar item in SemiFunc.PlayerGetList()) { foreach (RoomVolume currentRoom in item.RoomVolumeCheck.CurrentRooms) { foreach (RoomVolume enemyRoom in enemyRooms) { if ((Object)(object)currentRoom == (Object)(object)enemyRoom) { return true; } } } } return false; } internal static void ResetCache() { _cachedActionDelta = 0f; } } [HarmonyPatch(typeof(SemiFunc), "EnemyGetNearestPhysObject")] internal static class SemiFuncCachePatch { private static readonly Collider[] _buf = (Collider[])(object)new Collider[32]; private static int _mask = -1; private static readonly Dictionary _cache = new Dictionary(); private static bool Prefix(Enemy enemy, ref Vector3 __result) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_0128: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ModEnabled || !Settings.CpuPatchesActive) { return true; } long startTicks = FrameTimeMeter.Begin(); int instanceID = ((Object)enemy).GetInstanceID(); float time = Time.time; if (_cache.TryGetValue(instanceID, out (Vector3, float) value) && time - value.Item2 < 0.25f) { (__result, _) = value; FrameTimeMeter.End(FrameTimeMeter.SemiFuncCache, startTicks); return false; } if (_mask < 0) { _mask = LayerMask.GetMask(new string[1] { "PhysGrabObject" }); } int num = Physics.OverlapSphereNonAlloc(enemy.CenterTransform.position, 3f, _buf, _mask); PhysGrabObject val = null; float num2 = 9999f; for (int i = 0; i < num; i++) { PhysGrabObject componentInParent = ((Component)_buf[i]).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent) && !Object.op_Implicit((Object)(object)((Component)componentInParent).GetComponent())) { float num3 = Vector3.Distance(enemy.CenterTransform.position, componentInParent.centerPoint); if (num3 < num2) { num2 = num3; val = componentInParent; } } } __result = (((Object)(object)val != (Object)null) ? val.centerPoint : Vector3.zero); _cache[instanceID] = (__result, time); FrameTimeMeter.End(FrameTimeMeter.SemiFuncCache, startTicks); return false; } internal static void ClearCache() { _cache.Clear(); } } [HarmonyPatch(typeof(PhysGrabObject), "Update")] internal static class PhysGrabObjectFixPatch { private static readonly Dictionary _rbCache = new Dictionary(); internal static void ClearRbCache() { _rbCache.Clear(); } private static bool Prefix(PhysGrabObject __instance) { if (!Settings.ModEnabled || !Settings.CpuPatchesActive) { return true; } if (!__instance.grabbed) { if (!_rbCache.TryGetValue(__instance, out Rigidbody value)) { value = ((Component)__instance).GetComponent(); _rbCache[__instance] = value; } if ((Object)(object)value != (Object)null && value.IsSleeping()) { return false; } return true; } long startTicks = FrameTimeMeter.Begin(); for (int num = __instance.playerGrabbing.Count - 1; num >= 0; num--) { PhysGrabber val = __instance.playerGrabbing[num]; if (!Object.op_Implicit((Object)(object)val) || !val.grabbed) { __instance.playerGrabbing.RemoveAt(num); } } FrameTimeMeter.End(FrameTimeMeter.PhysGrabObjectFix, startTicks); return true; } } [HarmonyPatch(typeof(LightManager), "UpdateLights")] internal static class LightManagerBatchPatch { private static bool Prefix(LightManager __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ModEnabled || !Settings.CpuPatchesActive) { return true; } long startTicks = FrameTimeMeter.Begin(); __instance.lastCheckPos = __instance.lightCullTarget.position; List propLights = __instance.propLights; for (int num = propLights.Count - 1; num >= 0; num--) { PropLight val = propLights[num]; if (Object.op_Implicit((Object)(object)val)) { __instance.HandleLightActivation(val); } else { propLights.RemoveAt(num); } } List propEmissions = __instance.propEmissions; for (int num2 = propEmissions.Count - 1; num2 >= 0; num2--) { PropLightEmission val2 = propEmissions[num2]; if (Object.op_Implicit((Object)(object)val2)) { __instance.HandleEmissionActivation(val2); } else { propEmissions.RemoveAt(num2); } } FrameTimeMeter.End(FrameTimeMeter.LightManagerBatch, startTicks); return false; } } [HarmonyPatch(typeof(LevelGenerator), "GenerateDone")] internal static class ClearCpuCachesOnLevel { private static void Postfix() { SemiFuncCachePatch.ClearCache(); EnemyDirectorThrottlePatch.ResetCache(); PlayerCosmeticThrottle.ResetCamera(); PlayerCosmeticThrottle.ClearAvatarCache(); } } internal static class PlayerCosmeticThrottle { private static Camera? _cam; private static readonly Dictionary _isWorldAvatar = new Dictionary(); internal static bool ShouldSkip(Transform t) { //IL_0087: 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) //IL_009b: 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) if (!Settings.CpuPatchesActive) { return false; } if (!_isWorldAvatar.TryGetValue(t, out var value)) { value = (Object)(object)((Component)t).GetComponentInParent() != (Object)null; _isWorldAvatar[t] = value; } if (!value) { return false; } float resolvedEffectiveFogEnd = Settings.ResolvedEffectiveFogEnd; if (resolvedEffectiveFogEnd <= 0f) { return false; } if ((Object)(object)_cam == (Object)null || (Object)(object)((Component)_cam).transform == (Object)null) { _cam = Camera.main; } if ((Object)(object)_cam == (Object)null) { return false; } float num = resolvedEffectiveFogEnd * 1.1f; Vector3 val = t.position - ((Component)_cam).transform.position; return ((Vector3)(ref val)).sqrMagnitude > num * num; } internal static void ResetCamera() { _cam = null; } internal static void ClearAvatarCache() { _isWorldAvatar.Clear(); } } [HarmonyPatch(typeof(PlayerAvatarEyelids), "Update")] internal static class PlayerAvatarEyelidsThrottlePatch { private static bool Prefix(PlayerAvatarEyelids __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(PlayerExpression), "Update")] internal static class PlayerExpressionThrottlePatch { private static bool Prefix(PlayerExpression __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(PlayerAvatarOverchargeVisuals), "Update")] internal static class PlayerAvatarOverchargeVisualsThrottlePatch { private static bool Prefix(PlayerAvatarOverchargeVisuals __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(AnimNoise), "Update")] internal static class AnimNoiseThrottlePatch { private static bool Prefix(AnimNoise __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(FlashlightLightAim), "Update")] internal static class FlashlightLightAimThrottlePatch { private static bool Prefix(FlashlightLightAim __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(FlashlightTilt), "Update")] internal static class FlashlightTiltThrottlePatch { private static bool Prefix(FlashlightTilt __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(PlayerDeathEffects), "Update")] internal static class PlayerDeathEffectsThrottlePatch { private static bool Prefix(PlayerDeathEffects __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(PlayerReviveEffects), "Update")] internal static class PlayerReviveEffectsThrottlePatch { private static bool Prefix(PlayerReviveEffects __instance) { return !PlayerCosmeticThrottle.ShouldSkip(((Component)__instance).transform); } } [HarmonyPatch(typeof(ExtractionPoint))] internal static class ExtractionPointPatch { [HarmonyPrefix] [HarmonyPatch("Start")] public static void PrefixStart(ExtractionPoint __instance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (Settings.ExtractionPointFlicker) { TextMeshPro haulGoalScreen = __instance.haulGoalScreen; if (!((Object)(object)((haulGoalScreen != null) ? haulGoalScreen.transform : null) == (Object)null)) { Transform transform = __instance.haulGoalScreen.transform; transform.localPosition += new Vector3(0f, 0f, -0.002f); } } } } internal static class PhysicsBuffers { internal static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[64]; internal static readonly RaycastHit[] Hits2 = (RaycastHit[])(object)new RaycastHit[32]; internal static readonly Collider[] Overlaps = (Collider[])(object)new Collider[32]; private static int _physGrabMask = -1; internal static int PhysGrabMask { get { if (_physGrabMask < 0) { _physGrabMask = LayerMask.GetMask(new string[1] { "PhysGrabObject" }); } return _physGrabMask; } } } [HarmonyPatch(typeof(PhysGrabber), "RayCheck")] internal static class RayCheckDiscoveryPatch { private static void Prefix(PhysGrabber __instance, bool _grab) { //IL_0034: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ModEnabled || _grab || __instance.playerAvatar.isDisabled || __instance.playerAvatar.deadSet) { return; } Transform transform = ((Component)__instance.playerCamera).transform; int num = Physics.SphereCastNonAlloc(transform.position, 1f, transform.forward, PhysicsBuffers.Hits, 10f, LayerMask.op_Implicit(__instance.mask), (QueryTriggerInteraction)2); for (int i = 0; i < num; i++) { ValuableObject component = ((Component)((RaycastHit)(ref PhysicsBuffers.Hits[i])).transform).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || (component.discovered && !component.discoveredReminder)) { continue; } Vector3 val = ((RaycastHit)(ref PhysicsBuffers.Hits[i])).point; int num2 = Physics.OverlapSphereNonAlloc(val, 0.01f, PhysicsBuffers.Overlaps, LayerMask.op_Implicit(__instance.mask)); bool flag = false; for (int j = 0; j < num2; j++) { if ((Object)(object)((Component)((Component)PhysicsBuffers.Overlaps[j]).transform).GetComponentInParent() != (Object)(object)component) { flag = true; break; } } if (flag && Object.op_Implicit((Object)(object)component.physGrabObject)) { val = Vector3.MoveTowards(val, component.physGrabObject.centerPoint, 0.1f); } Vector3 val2 = transform.position - val; if (!component.discovered) { int num3 = Physics.SphereCastNonAlloc(val, 0.01f, val2, PhysicsBuffers.Hits2, ((Vector3)(ref val2)).magnitude, LayerMask.op_Implicit(__instance.mask), (QueryTriggerInteraction)2); bool flag2 = true; for (int k = 0; k < num3; k++) { if (!((Component)((RaycastHit)(ref PhysicsBuffers.Hits2[k])).transform).CompareTag("Player") && (Object)(object)((RaycastHit)(ref PhysicsBuffers.Hits2[k])).transform != (Object)(object)((RaycastHit)(ref PhysicsBuffers.Hits[i])).transform) { flag2 = false; break; } } if (flag2) { component.Discover((State)0); } } else { if (!component.discoveredReminder) { continue; } int num4 = Physics.RaycastNonAlloc(val, val2, PhysicsBuffers.Hits2, ((Vector3)(ref val2)).magnitude, LayerMask.op_Implicit(__instance.mask), (QueryTriggerInteraction)2); bool flag3 = true; for (int l = 0; l < num4; l++) { if (((Component)((Component)((RaycastHit)(ref PhysicsBuffers.Hits2[l])).collider).transform).CompareTag("Wall")) { flag3 = false; break; } } if (flag3) { component.discoveredReminder = false; component.Discover((State)1); } } } } } [HarmonyPatch(typeof(PhysGrabber), "ForceGrabPhysObject")] internal static class ForceGrabPatch { private static bool Prefix(PhysGrabber __instance, PhysGrabObject _physObject) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ModEnabled) { return true; } if ((Object)(object)__instance.playerCamera == (Object)null || (Object)(object)_physObject == (Object)null) { return true; } Vector3 val = _physObject.midPoint - ((Component)__instance.playerCamera).transform.position; int num = Physics.RaycastNonAlloc(((Component)__instance.playerCamera).transform.position, ((Vector3)(ref val)).normalized, PhysicsBuffers.Hits, ((Vector3)(ref val)).magnitude, PhysicsBuffers.PhysGrabMask, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { if (!Object.op_Implicit((Object)(object)_physObject)) { continue; } Collider collider = ((RaycastHit)(ref PhysicsBuffers.Hits[i])).collider; if ((Object)(object)((collider != null) ? ((Component)collider).GetComponentInParent() : null) == (Object)(object)_physObject) { if (__instance.grabbed) { __instance.ReleaseObject(-1, 0.1f); } __instance.StartGrabbingPhysObject(PhysicsBuffers.Hits[i], _physObject); if (!__instance.grabbed) { break; } __instance.toggleGrab = true; return false; } } return false; } } [HarmonyPatch(typeof(GraphicsManager))] internal static class GraphicsPatch { [HarmonyPrefix] [HarmonyPatch("UpdateRenderSize")] public static bool PrefixUpdateRenderSize() { if (!Settings.ModEnabled) { return true; } return Settings.Pixelation; } } [HarmonyPatch(typeof(ParticlePrefabExplosion), "Start")] internal static class ExplosionShadowPatch { private static void Postfix(ParticlePrefabExplosion __instance) { if (Settings.ShouldOptimize(Settings.PerfOpt.ExplosionShadows) && (Object)(object)__instance.light != (Object)null) { __instance.light.shadows = (LightShadows)0; } } } [HarmonyPatch(typeof(ItemLight), "Start")] internal static class ItemLightShadowPatch { private static void Postfix(ItemLight __instance) { if (Settings.ShouldOptimize(Settings.PerfOpt.ItemLightShadows) && (Object)(object)__instance.itemLight != (Object)null) { __instance.itemLight.shadows = (LightShadows)0; } } } [HarmonyPatch(typeof(SpectateCamera), "LateUpdate")] internal static class SpectateShadowPatch { private static void Postfix() { if (QualitySettings.shadowDistance > Settings.ResolvedShadowDistance) { QualitySettings.shadowDistance = Settings.ResolvedShadowDistance; } } } internal static class SceneOptimizer { private static readonly Dictionary _tinyRendererOrig = new Dictionary(); private static readonly Dictionary _animatedLightOrig = new Dictionary(); private static readonly Dictionary _zeroIntensityOrig = new Dictionary(); private static readonly Dictionary _gpuInstancingOrig = new Dictionary(); private static readonly Dictionary _particleCullOrig = new Dictionary(); private static readonly HashSet _localAvatarRendererSet = new HashSet(); private static readonly List _distanceCullWatchlist = new List(); private static readonly Dictionary _distanceCullOrig = new Dictionary(); private static readonly Dictionary _flashlightBudgetOrig = new Dictionary(); private static readonly List _flashlightControllers = new List(); private static readonly List _pointLightWatchlist = new List(); private static readonly Dictionary _pointLightShadowOrig = new Dictionary(); private static readonly List<(Light light, float distSq)> _flashlightSorted = new List<(Light, float)>(); private static readonly List _playerAvatarRenderers = new List(); private static readonly Dictionary _playerAvatarShadowOrig = new Dictionary(); private static readonly Dictionary _playerAvatarSmrUpdateOrig = new Dictionary(); private static int _distanceCullCursor; private const int DistanceCullChunkSize = 1000; private static readonly List _shadowBudgetWatchlist = new List(); private static readonly List<(Light light, float dist)> _budgetCandidates = new List<(Light, float)>(); private static readonly Dictionary _shadowStrengths = new Dictionary(); private const float FadeSpeed = 3f; internal static void Apply() { using (ModTiming.Begin("REPOFidelity.SceneOptimizer.Apply")) { long startTicks = FrameTimeMeter.Begin(); _shadowStrengths.Clear(); ApplyGpuInstancing(Settings.OptimizationsActive); ApplyZeroIntensityShadows(Settings.OptimizationsActive); ApplyParticleAutoCull(Settings.OptimizationsActive); SetParticleShadows(!Settings.ShouldOptimize(Settings.PerfOpt.ParticleShadows)); ApplyTinyRendererCull(Settings.ShouldOptimize(Settings.PerfOpt.TinyRendererCulling)); ApplyAnimatedLightCull(Settings.ShouldOptimize(Settings.PerfOpt.AnimatedLightShadows)); SetItemLightShadows(!Settings.ShouldOptimize(Settings.PerfOpt.ItemLightShadows)); SetExplosionLightShadows(!Settings.ShouldOptimize(Settings.PerfOpt.ExplosionShadows)); ApplyPointLightShadowCull(Settings.ShouldOptimize(Settings.PerfOpt.PointLightShadows)); CaptureDistanceCullWatchlist(); CapturePlayerAvatarRenderers(); CaptureFlashlightControllers(); CaptureShadowBudgetWatchlist(); if (!Settings.ShouldOptimize(Settings.PerfOpt.FlashlightShadowBudget)) { RestoreFlashlightBudget(); } FrameTimeMeter.End(FrameTimeMeter.SceneApply, startTicks); } } private static void CapturePlayerAvatarRenderers() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) RestorePlayerAvatarRenderers(); _playerAvatarRenderers.Clear(); if (!Settings.OptimizationsActive) { return; } int num = 0; PlayerAvatar[] array = Object.FindObjectsOfType(); foreach (PlayerAvatar val in array) { if (val.isLocal) { continue; } Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if ((int)val2.shadowCastingMode != 0) { _playerAvatarShadowOrig[val2] = val2.shadowCastingMode; _playerAvatarRenderers.Add(val2); SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val2 is SkinnedMeshRenderer) ? val2 : null); if (val3 != null && val3.updateWhenOffscreen) { _playerAvatarSmrUpdateOrig[val3] = true; val3.updateWhenOffscreen = false; num++; } } } } if (num > 0) { Plugin.Log.LogDebug((object)$"player avatar: forced updateWhenOffscreen=false on {num} skinned meshes"); } } internal static void UpdatePlayerAvatarShadowCull(Camera? cam) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_007f: Unknown result type (might be due to invalid IL or missing references) //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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Invalid comparison between Unknown and I4 //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cam == (Object)null || _playerAvatarRenderers.Count == 0 || !Settings.OptimizationsActive) { return; } float resolvedEffectiveFogEnd = Settings.ResolvedEffectiveFogEnd; if (resolvedEffectiveFogEnd <= 0f) { return; } float num = resolvedEffectiveFogEnd * 1.1f; float num2 = num * num; float num3 = num * 0.9f * (num * 0.9f); Vector3 position = ((Component)cam).transform.position; for (int i = 0; i < _playerAvatarRenderers.Count; i++) { Renderer val = _playerAvatarRenderers[i]; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; bool flag = (int)val.shadowCastingMode == 0; if (flag && sqrMagnitude < num3 && _playerAvatarShadowOrig.TryGetValue(val, out var value)) { val.shadowCastingMode = value; } else if (!flag && sqrMagnitude > num2) { val.shadowCastingMode = (ShadowCastingMode)0; } } } } private static void RestorePlayerAvatarRenderers() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in _playerAvatarShadowOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.shadowCastingMode = item.Value; } } _playerAvatarShadowOrig.Clear(); foreach (KeyValuePair item2 in _playerAvatarSmrUpdateOrig) { if ((Object)(object)item2.Key != (Object)null) { item2.Key.updateWhenOffscreen = item2.Value; } } _playerAvatarSmrUpdateOrig.Clear(); } private static void RefreshLocalAvatarRendererSet() { _localAvatarRendererSet.Clear(); PlayerAvatar[] array = Object.FindObjectsOfType(); foreach (PlayerAvatar val in array) { if (val.isLocal) { PlayerAvatarVisuals playerAvatarVisuals = val.playerAvatarVisuals; AddRenderersFromRoot((playerAvatarVisuals != null) ? ((Component)playerAvatarVisuals).transform : null); FlashlightController flashlightController = val.flashlightController; AddRenderersFromRoot((flashlightController != null) ? ((Component)flashlightController).transform : null); PlayerCosmetics val2 = val.playerAvatarVisuals?.playerCosmetics; if ((Object)(object)val2 != (Object)null) { AddRenderersFromRoot(((Component)val2).transform); PlayerCrown playerCrown = val2.playerCrown; AddRenderersFromRoot((playerCrown != null) ? ((Component)playerCrown).transform : null); } } } } private static void AddRenderersFromRoot(Transform? root) { if ((Object)(object)root == (Object)null) { return; } Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null) { _localAvatarRendererSet.Add(val); } } } private static int ResolveFlashlightBudgetN() { if (Settings.Preset != 0) { return 4; } return 0; } private static void CaptureDistanceCullWatchlist() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0090: Unknown result type (might be due to invalid IL or missing references) RestoreDistanceCullWatchlist(); _distanceCullWatchlist.Clear(); _distanceCullCursor = 0; if (!Settings.ShouldOptimize(Settings.PerfOpt.DistanceShadowCulling)) { return; } float num = ((Settings.Preset == QualityPreset.Potato) ? 5f : 3f); RefreshLocalAvatarRendererSet(); int num2 = 0; MeshRenderer[] array = Object.FindObjectsOfType(); foreach (MeshRenderer val in array) { if ((int)((Renderer)val).shadowCastingMode != 0) { Bounds bounds = ((Renderer)val).bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).magnitude >= num) && !_localAvatarRendererSet.Contains((Renderer)(object)val)) { _distanceCullWatchlist.Add((Renderer)(object)val); _distanceCullOrig[(Renderer)(object)val] = ((Renderer)val).shadowCastingMode; num2++; } } } if (num2 > 0) { Plugin.Log.LogDebug((object)$"distance cull watchlist: {num2} small renderers"); } } internal static void UpdateDistanceShadowCull(Camera? cam) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Invalid comparison between Unknown and I4 //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010a->IL010a: Incompatible stack types: O vs I4 //IL_0108->IL010a: Incompatible stack types: I4 vs O //IL_0108->IL010a: Incompatible stack types: O vs I4 if ((Object)(object)cam == (Object)null || _distanceCullWatchlist.Count == 0) { return; } if (!Settings.ShouldOptimize(Settings.PerfOpt.DistanceShadowCulling)) { RestoreDistanceCullWatchlist(); return; } float resolvedEffectiveFogEnd = Settings.ResolvedEffectiveFogEnd; if (resolvedEffectiveFogEnd <= 0f) { return; } float num = resolvedEffectiveFogEnd * ((Settings.Preset == QualityPreset.Potato) ? 1f : 1.1f); float num2 = num * num; float num3 = num * 0.9f; float num4 = num3 * num3; Vector3 position = ((Component)cam).transform.position; int count = _distanceCullWatchlist.Count; int num5 = Mathf.Min(1000, count); if (_distanceCullCursor >= count) { _distanceCullCursor = 0; } for (int i = 0; i < num5; i++) { int num6 = _distanceCullCursor + i; if (num6 >= count) { num6 -= count; } Renderer val = _distanceCullWatchlist[num6]; if ((Object)(object)val == (Object)null) { continue; } Vector3 val2 = ((Component)val).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; bool flag = (int)val.shadowCastingMode == 0; if (flag && sqrMagnitude < num4) { object obj = val; int num7; if (_distanceCullOrig.TryGetValue(val, out var value)) { obj = value; num7 = (int)obj; } else { num7 = 1; obj = num7; num7 = (int)obj; } ((Renderer)num7).shadowCastingMode = (ShadowCastingMode)obj; } else if (!flag && sqrMagnitude > num2) { val.shadowCastingMode = (ShadowCastingMode)0; } } _distanceCullCursor = (_distanceCullCursor + num5) % count; } private static void RestoreDistanceCullWatchlist() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d->IL002d: Incompatible stack types: O vs I4 //IL_002c->IL002d: Incompatible stack types: I4 vs O //IL_002c->IL002d: Incompatible stack types: O vs I4 for (int i = 0; i < _distanceCullWatchlist.Count; i++) { Renderer val = _distanceCullWatchlist[i]; if (!((Object)(object)val == (Object)null)) { object obj = val; int num; if (_distanceCullOrig.TryGetValue(val, out var value)) { obj = value; num = (int)obj; } else { num = 1; obj = num; num = (int)obj; } ((Renderer)num).shadowCastingMode = (ShadowCastingMode)obj; } } _distanceCullOrig.Clear(); } private static void ApplyPointLightShadowCull(bool enable) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) RestorePointLightShadows(); _pointLightWatchlist.Clear(); if (!enable) { return; } Light[] array = Object.FindObjectsOfType(); foreach (Light val in array) { if ((int)val.type == 2 && (int)val.shadows != 0 && !(val.range <= 3f)) { _pointLightWatchlist.Add(val); } } if (_pointLightWatchlist.Count > 0) { Plugin.Log.LogDebug((object)$"point-light watchlist: {_pointLightWatchlist.Count} shadowed point lights"); } } internal static void UpdatePointLightShadowCull(Camera? cam) { //IL_0039: 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_0078: 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_0083: 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_0095: Invalid comparison between Unknown and I4 //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cam == (Object)null || _pointLightWatchlist.Count == 0) { return; } if (!Settings.ShouldOptimize(Settings.PerfOpt.PointLightShadows)) { RestorePointLightShadows(); return; } float resolvedEffectiveFogEnd = Settings.ResolvedEffectiveFogEnd; if (resolvedEffectiveFogEnd <= 0f) { return; } Vector3 position = ((Component)cam).transform.position; for (int i = 0; i < _pointLightWatchlist.Count; i++) { Light val = _pointLightWatchlist[i]; if ((Object)(object)val == (Object)null) { continue; } float num = resolvedEffectiveFogEnd + val.range; float num2 = num * 0.9f; Vector3 val2 = ((Component)val).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; bool flag = (int)val.shadows == 0; if (flag && sqrMagnitude < num2 * num2) { if (_pointLightShadowOrig.TryGetValue(val, out var value)) { val.shadows = value; _pointLightShadowOrig.Remove(val); } } else if (!flag && sqrMagnitude > num * num) { _pointLightShadowOrig[val] = val.shadows; val.shadows = (LightShadows)0; } } } private static void RestorePointLightShadows() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in _pointLightShadowOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.shadows = item.Value; } } _pointLightShadowOrig.Clear(); } internal static void UpdateFlashlightShadowBudget(Camera? cam) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0175: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cam == (Object)null) { return; } if (!Settings.ShouldOptimize(Settings.PerfOpt.FlashlightShadowBudget)) { RestoreFlashlightBudget(); return; } _flashlightSorted.Clear(); Vector3 position = ((Component)cam).transform.position; for (int num = _flashlightControllers.Count - 1; num >= 0; num--) { FlashlightController val = _flashlightControllers[num]; if ((Object)(object)val == (Object)null) { _flashlightControllers.RemoveAt(num); } else { Light spotlight = val.spotlight; if (!((Object)(object)spotlight == (Object)null) && ((Behaviour)spotlight).isActiveAndEnabled) { Vector3 val2 = ((Component)spotlight).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; _flashlightSorted.Add((spotlight, sqrMagnitude)); } } } _flashlightSorted.Sort(((Light light, float distSq) a, (Light light, float distSq) b) => a.distSq.CompareTo(b.distSq)); float resolvedEffectiveFogEnd = Settings.ResolvedEffectiveFogEnd; float num2 = ((resolvedEffectiveFogEnd > 0f) ? (resolvedEffectiveFogEnd * 1.1f * (resolvedEffectiveFogEnd * 1.1f)) : float.PositiveInfinity); int num3 = ResolveFlashlightBudgetN(); int num4 = 0; for (int i = 0; i < _flashlightSorted.Count; i++) { (Light light, float distSq) tuple = _flashlightSorted[i]; Light item = tuple.light; bool num5 = tuple.distSq > num2; bool flag = num4 < num3; if (!num5 && flag) { num4++; if (_flashlightBudgetOrig.TryGetValue(item, out var value)) { item.shadows = value; _flashlightBudgetOrig.Remove(item); } } else if ((int)item.shadows != 0) { if (!_flashlightBudgetOrig.ContainsKey(item)) { _flashlightBudgetOrig[item] = item.shadows; } item.shadows = (LightShadows)0; } } } private static void RestoreFlashlightBudget() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in _flashlightBudgetOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.shadows = item.Value; } } _flashlightBudgetOrig.Clear(); } private static void CaptureFlashlightControllers() { _flashlightControllers.Clear(); FlashlightController[] array = Object.FindObjectsOfType(); foreach (FlashlightController item in array) { _flashlightControllers.Add(item); } } internal static void ResetShadowBudget() { _shadowStrengths.Clear(); } private static void CaptureShadowBudgetWatchlist() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 _shadowBudgetWatchlist.Clear(); if (!Settings.OptimizationsActive) { return; } Light[] array = Object.FindObjectsOfType(); foreach (Light val in array) { if ((int)val.type == 2 && !(val.intensity >= 1f) && !(val.range >= 5f)) { _shadowBudgetWatchlist.Add(val); } } if (_shadowBudgetWatchlist.Count > 0) { Plugin.Log.LogDebug((object)$"shadow budget watchlist: {_shadowBudgetWatchlist.Count} item glow lights"); } } internal static void UpdateShadowBudget(Camera? cam) { //IL_002d: 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_00a7: 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) if ((Object)(object)cam == (Object)null) { return; } if (!Settings.OptimizationsActive) { RestoreManagedLights(); return; } int resolvedShadowBudget = Settings.ResolvedShadowBudget; if (resolvedShadowBudget <= 0) { RestoreManagedLights(); return; } Vector3 position = ((Component)cam).transform.position; float resolvedShadowDistance = Settings.ResolvedShadowDistance; float dt = 0.1f; _budgetCandidates.Clear(); for (int num = _shadowBudgetWatchlist.Count - 1; num >= 0; num--) { Light val = _shadowBudgetWatchlist[num]; if ((Object)(object)val == (Object)null) { _shadowBudgetWatchlist.RemoveAt(num); } else if (((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy && !(val.intensity <= 0f)) { float num2 = Vector3.Distance(position, ((Component)val).transform.position); if (num2 > resolvedShadowDistance) { FadeLight(val, 0f, dt); } else { _budgetCandidates.Add((val, num2)); } } } _budgetCandidates.Sort(((Light light, float dist) a, (Light light, float dist) b) => a.dist.CompareTo(b.dist)); for (int i = 0; i < _budgetCandidates.Count; i++) { Light item = _budgetCandidates[i].light; float target = ((i < resolvedShadowBudget) ? 1f : 0f); FadeLight(item, target, dt); } } private static void RestoreManagedLights() { if (_shadowStrengths.Count == 0) { return; } for (int num = _shadowBudgetWatchlist.Count - 1; num >= 0; num--) { Light val = _shadowBudgetWatchlist[num]; if ((Object)(object)val == (Object)null) { _shadowBudgetWatchlist.RemoveAt(num); } else if (((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy) { val.shadows = (LightShadows)2; val.shadowStrength = 1f; } } _shadowStrengths.Clear(); } private static void FadeLight(Light light, float target, float dt) { //IL_0017: 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_0050: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)light).GetInstanceID(); float value; float num = Mathf.MoveTowards(_shadowStrengths.TryGetValue(instanceID, out value) ? value : (((int)light.shadows != 0) ? 1f : 0f), target, 3f * dt); _shadowStrengths[instanceID] = num; if (num <= 0.01f) { if ((int)light.shadows != 0) { light.shadows = (LightShadows)0; } light.shadowStrength = 0f; } else { if ((int)light.shadows == 0) { light.shadows = (LightShadows)2; } light.shadowStrength = num; } } private static void ApplyZeroIntensityShadows(bool enable) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in _zeroIntensityOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.shadows = item.Value; } } _zeroIntensityOrig.Clear(); if (!enable) { return; } HashSet hashSet = new HashSet(); FlashlightController[] array = Object.FindObjectsOfType(); foreach (FlashlightController val in array) { if ((Object)(object)val.spotlight != (Object)null) { hashSet.Add(val.spotlight); } } int num = 0; Light[] array2 = Object.FindObjectsOfType(); foreach (Light val2 in array2) { if (!hashSet.Contains(val2) && val2.intensity <= 0f && (int)val2.shadows != 0) { _zeroIntensityOrig[val2] = val2.shadows; val2.shadows = (LightShadows)0; num++; } } if (num > 0) { Plugin.Log.LogDebug((object)$"disabled shadows on {num} zero-intensity lights"); } } private static void SetParticleShadows(bool on) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) int num = 0; ParticleSystemRenderer[] array = Object.FindObjectsOfType(); foreach (ParticleSystemRenderer val in array) { if (on && (int)((Renderer)val).shadowCastingMode == 0) { ((Renderer)val).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)val).receiveShadows = true; num++; } else if (!on && (int)((Renderer)val).shadowCastingMode != 0) { ((Renderer)val).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val).receiveShadows = false; num++; } } if (num > 0) { Plugin.Log.LogDebug((object)string.Format("{0} shadows on {1} particle renderers", on ? "restored" : "disabled", num)); } } private static void ApplyParticleAutoCull(bool enable) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0082: 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_0096: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in _particleCullOrig) { if ((Object)(object)item.Key != (Object)null) { MainModule main = item.Key.main; ((MainModule)(ref main)).cullingMode = item.Value; } } _particleCullOrig.Clear(); if (!enable) { return; } int num = 0; ParticleSystem[] array = Object.FindObjectsOfType(); foreach (ParticleSystem val in array) { MainModule main2 = val.main; if ((int)((MainModule)(ref main2)).cullingMode != 0) { _particleCullOrig[val] = ((MainModule)(ref main2)).cullingMode; ((MainModule)(ref main2)).cullingMode = (ParticleSystemCullingMode)0; num++; } } if (num > 0) { Plugin.Log.LogDebug((object)$"particle auto-cull: enabled on {num} systems"); } } private static void ApplyGpuInstancing(bool enable) { foreach (KeyValuePair item in _gpuInstancingOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.enableInstancing = item.Value; } } _gpuInstancingOrig.Clear(); if (!enable) { return; } int num = 0; HashSet hashSet = new HashSet(); MeshRenderer[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { Material[] sharedMaterials = ((Renderer)array[i]).sharedMaterials; foreach (Material val in sharedMaterials) { if (!((Object)(object)val == (Object)null) && !hashSet.Contains(val)) { hashSet.Add(val); if ((Object)(object)val.shader != (Object)null && !val.enableInstancing) { _gpuInstancingOrig[val] = val.enableInstancing; val.enableInstancing = true; num++; } } } } if (num > 0) { Plugin.Log.LogDebug((object)$"enabled GPU instancing on {num} materials"); } } private static void ApplyTinyRendererCull(bool enable) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_009d: Invalid comparison between Unknown and I4 //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00af: 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) foreach (KeyValuePair item in _tinyRendererOrig) { if ((Object)(object)item.Key != (Object)null) { ((Renderer)item.Key).shadowCastingMode = item.Value; } } _tinyRendererOrig.Clear(); if (!enable) { return; } float num = ((Settings.Preset == QualityPreset.Potato) ? 1f : 0.5f); RefreshLocalAvatarRendererSet(); int num2 = 0; MeshRenderer[] array = Object.FindObjectsOfType(); foreach (MeshRenderer val in array) { if ((int)((Renderer)val).shadowCastingMode != 0 && (int)((Renderer)val).shadowCastingMode != 3) { Bounds bounds = ((Renderer)val).bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).magnitude >= num) && !_localAvatarRendererSet.Contains((Renderer)(object)val)) { _tinyRendererOrig[val] = ((Renderer)val).shadowCastingMode; ((Renderer)val).shadowCastingMode = (ShadowCastingMode)0; num2++; } } } if (num2 > 0) { Plugin.Log.LogDebug((object)$"disabled shadow casting on {num2} tiny renderers"); } } private static void SetItemLightShadows(bool on) { ItemLight[] array = Object.FindObjectsOfType(); foreach (ItemLight val in array) { if (!((Object)(object)val.itemLight == (Object)null)) { val.itemLight.shadows = (LightShadows)(on ? 2 : 0); } } } private static void SetExplosionLightShadows(bool on) { ParticlePrefabExplosion[] array = Object.FindObjectsOfType(); foreach (ParticlePrefabExplosion val in array) { if (!((Object)(object)val.light == (Object)null)) { val.light.shadows = (LightShadows)(on ? 2 : 0); } } } private static void ApplyAnimatedLightCull(bool enable) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) foreach (KeyValuePair item in _animatedLightOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.shadows = item.Value; } } _animatedLightOrig.Clear(); if (!enable) { return; } int num = 0; LightAnimator[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { Light component = ((Component)array[i]).GetComponent(); if ((Object)(object)component != (Object)null && (int)component.shadows != 0) { _animatedLightOrig[component] = component.shadows; component.shadows = (LightShadows)0; num++; } } if (num > 0) { Plugin.Log.LogDebug((object)$"disabled shadows on {num} animated lights"); } } internal static void LogRestoreState(string tag) { int shadowResOrigCount = QualityPatch.ShadowResOrigCount; int avatarRtOrigCount = PlayerAvatarMenuAAPatch.AvatarRtOrigCount; int avatarPplCount = PlayerAvatarMenuAAPatch.AvatarPplCount; int num = _tinyRendererOrig.Count + _animatedLightOrig.Count + _zeroIntensityOrig.Count + _gpuInstancingOrig.Count + _particleCullOrig.Count + shadowResOrigCount + avatarRtOrigCount + avatarPplCount + _flashlightBudgetOrig.Count + _pointLightShadowOrig.Count + _playerAvatarShadowOrig.Count + _playerAvatarSmrUpdateOrig.Count; string arg = ((num == 0) ? "OK" : "LEAK"); Plugin.Log.LogInfo((object)($"[restore-state:{tag}] {arg} mutations={num} " + $"tinyRend={_tinyRendererOrig.Count} " + $"animLight={_animatedLightOrig.Count} " + $"zeroInt={_zeroIntensityOrig.Count} " + $"gpuInst={_gpuInstancingOrig.Count} " + $"particleCull={_particleCullOrig.Count} " + $"shadowRes={shadowResOrigCount} " + $"avatarRt={avatarRtOrigCount} " + $"avatarPpl={avatarPplCount} " + $"flashBudget={_flashlightBudgetOrig.Count} " + $"pointLight={_pointLightShadowOrig.Count} " + $"playerShadow={_playerAvatarShadowOrig.Count} " + $"playerSmr={_playerAvatarSmrUpdateOrig.Count} " + $"watchlist={_distanceCullWatchlist.Count}")); } } [HarmonyPatch(typeof(LevelGenerator), "GenerateDone")] internal static class LevelOptimizationPatch { private static void Postfix() { SceneOptimizer.Apply(); PhysGrabObjectFixPatch.ClearRbCache(); } } [HarmonyPatch(typeof(PlayerAvatar), "Start")] internal static class PlayerAvatarStartPatch { private static void Postfix() { SceneOptimizer.Apply(); } } [HarmonyPatch(typeof(PlayerAvatarMenu), "Start")] internal static class PlayerAvatarMenuAAPatch { internal struct PplState { internal bool AttachedByUs; internal Antialiasing OriginalAa; } private const int TargetRtSize = 1024; private const int MaxLongDim = 2048; private const int TargetMsaa = 4; internal static readonly Dictionary _rtOrig = new Dictionary(); internal static readonly Dictionary _pplState = new Dictionary(); internal static int AvatarRtOrigCount => _rtOrig.Count; internal static int AvatarPplCount => _pplState.Count; private static void Postfix(PlayerAvatarMenu __instance) { if (Settings.ModEnabled) { ApplyToMenu(__instance); } } internal static void ApplyToMenu(PlayerAvatarMenu __instance) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) if (__instance.expressionAvatar) { return; } int num = 0; PlayerAvatarMenu[] array = Object.FindObjectsOfType(); foreach (PlayerAvatarMenu val in array) { if (!val.expressionAvatar && !val.worldAvatar && !val.iconMakerAvatar && !((Object)(object)val.parentPage == (Object)null) && ((Component)val.parentPage).gameObject.activeInHierarchy && ++num > 2) { return; } } if ((Object)(object)__instance.cameraAndStuff == (Object)null) { return; } Camera componentInChildren = ((Component)__instance.cameraAndStuff).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { Plugin.Log.LogInfo((object)("avatar preview: no Camera under cameraAndStuff on '" + ((Object)__instance).name + "'")); return; } componentInChildren.allowMSAA = true; PostProcessLayer component = ((Component)componentInChildren).GetComponent(); if ((Object)(object)component != (Object)null) { if (!_pplState.ContainsKey(componentInChildren)) { _pplState[componentInChildren] = new PplState { AttachedByUs = false, OriginalAa = component.antialiasingMode }; } component.antialiasingMode = (Antialiasing)2; component.fastApproximateAntialiasing.keepAlpha = true; } else { Camera main = Camera.main; PostProcessLayer val2 = ((main != null) ? ((Component)main).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { object? obj = typeof(PostProcessLayer).GetField("m_Resources", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val2); PostProcessResources val3 = (PostProcessResources)((obj is PostProcessResources) ? obj : null); if ((Object)(object)val3 != (Object)null) { PostProcessLayer obj2 = ((Component)componentInChildren).gameObject.AddComponent(); obj2.Init(val3); obj2.volumeTrigger = ((Component)componentInChildren).transform; obj2.antialiasingMode = (Antialiasing)2; obj2.fastApproximateAntialiasing.keepAlpha = true; _pplState[componentInChildren] = new PplState { AttachedByUs = true, OriginalAa = (Antialiasing)0 }; Plugin.Log.LogDebug((object)("avatar preview: attached PostProcessLayer with SMAA to '" + ((Object)componentInChildren).name + "'")); } else { Plugin.Log.LogInfo((object)("avatar preview: main PPL has no resources — SMAA unavailable on '" + ((Object)componentInChildren).name + "'")); } } } RenderTexture targetTexture = componentInChildren.targetTexture; if ((Object)(object)targetTexture != (Object)null) { bool num2 = ((Texture)targetTexture).width < 1024 && ((Texture)targetTexture).height < 1024; bool flag = targetTexture.antiAliasing < 4; if ((num2 || flag) && !_rtOrig.ContainsKey(targetTexture)) { _rtOrig[targetTexture] = (((Texture)targetTexture).width, ((Texture)targetTexture).height, targetTexture.antiAliasing); int num3 = Mathf.Min(((Texture)targetTexture).width, ((Texture)targetTexture).height); float num4 = ((num3 < 1024) ? (1024f / (float)num3) : 1f); int num5 = Mathf.RoundToInt((float)((Texture)targetTexture).width * num4); int num6 = Mathf.RoundToInt((float)((Texture)targetTexture).height * num4); int num7 = Mathf.Max(num5, num6); if (num7 > 2048) { float num8 = 2048f / (float)num7; num5 = Mathf.RoundToInt((float)num5 * num8); num6 = Mathf.RoundToInt((float)num6 * num8); } bool num9 = targetTexture.IsCreated(); if (num9) { targetTexture.Release(); } ((Texture)targetTexture).width = num5; ((Texture)targetTexture).height = num6; targetTexture.antiAliasing = 4; if (num9) { targetTexture.Create(); } Plugin.Log.LogDebug((object)($"avatar preview: RT '{((Object)targetTexture).name}' bumped {_rtOrig[targetTexture].w}x{_rtOrig[targetTexture].h} " + $"aa={_rtOrig[targetTexture].aa} → {num5}x{num6} aa={4}")); } } AvatarCameraGate avatarCameraGate = ((Component)componentInChildren).gameObject.GetComponent(); if ((Object)(object)avatarCameraGate == (Object)null) { avatarCameraGate = ((Component)componentInChildren).gameObject.AddComponent(); } avatarCameraGate.menu = __instance; avatarCameraGate.cam = componentInChildren; } internal static void RestoreAvatarRt() { //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) if (_rtOrig.Count == 0) { return; } List list = new List(); Camera[] array = Object.FindObjectsOfType(); foreach (Camera val in array) { if ((Object)(object)val.targetTexture != (Object)null && _rtOrig.ContainsKey(val.targetTexture)) { ((Behaviour)val).enabled = false; list.Add(val); } } foreach (KeyValuePair item in _rtOrig) { RenderTexture key = item.Key; if (!((Object)(object)key == (Object)null)) { bool num = key.IsCreated(); if (num) { key.Release(); } ((Texture)key).width = item.Value.Item1; ((Texture)key).height = item.Value.Item2; key.antiAliasing = item.Value.Item3; if (num) { key.Create(); } } } _rtOrig.Clear(); foreach (KeyValuePair item2 in _pplState) { Camera key2 = item2.Key; if ((Object)(object)key2 == (Object)null) { continue; } PostProcessLayer component = ((Component)key2).GetComponent(); if (!((Object)(object)component == (Object)null)) { if (item2.Value.AttachedByUs) { Object.Destroy((Object)(object)component); } else { component.antialiasingMode = item2.Value.OriginalAa; } } } _pplState.Clear(); foreach (Camera item3 in list) { ((Behaviour)item3).enabled = true; AvatarCameraGate component2 = ((Component)item3).GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } } internal static void ReapplyAll() { PlayerAvatarMenu[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { ApplyToMenu(array[i]); } } } internal class AvatarCameraGate : MonoBehaviour { internal PlayerAvatarMenu? menu; internal Camera? cam; private void LateUpdate() { if ((Object)(object)cam == (Object)null) { Object.Destroy((Object)(object)this); return; } if (!Settings.ModEnabled) { if (!((Behaviour)cam).enabled) { ((Behaviour)cam).enabled = true; } return; } bool flag = (Object)(object)menu != (Object)null && (Object)(object)menu.parentPage != (Object)null && ((Component)menu.parentPage).gameObject.activeInHierarchy; if (((Behaviour)cam).enabled != flag) { ((Behaviour)cam).enabled = flag; } } } internal static class PerfSettingsWatcher { private static bool _registered; private static int _lastPreset = -1; private static int _lastShadowQ = -1; private static int _lastShadowBudget; private static int _lastPerfExp; private static int _lastPerfItem; private static int _lastPerfAnim; private static int _lastPerfPart; private static int _lastPerfTiny; private static int _lastPerfDist; private static int _lastPerfFlash; private static bool _lastModEnabled = true; internal static void Register() { if (!_registered) { _registered = true; SnapshotState(); Settings.OnSettingsChanged += OnChanged; } } private static void OnChanged() { if (Settings.ModEnabled != _lastModEnabled || Settings.Preset != (QualityPreset)_lastPreset || Settings.ResolvedShadowQuality != (ShadowQuality)_lastShadowQ || Settings.ResolvedShadowBudget != _lastShadowBudget || Settings.PerfExplosionShadows != _lastPerfExp || Settings.PerfItemLightShadows != _lastPerfItem || Settings.PerfAnimatedLightShadows != _lastPerfAnim || Settings.PerfParticleShadows != _lastPerfPart || Settings.PerfTinyRendererCulling != _lastPerfTiny || Settings.PerfDistanceShadowCulling != _lastPerfDist || Settings.PerfFlashlightShadowBudget != _lastPerfFlash) { if (Settings.ResolvedShadowBudget != _lastShadowBudget) { SceneOptimizer.ResetShadowBudget(); } SnapshotState(); SceneOptimizer.Apply(); } } private static void SnapshotState() { _lastModEnabled = Settings.ModEnabled; _lastPreset = (int)Settings.Preset; _lastShadowQ = (int)Settings.ResolvedShadowQuality; _lastShadowBudget = Settings.ResolvedShadowBudget; _lastPerfExp = Settings.PerfExplosionShadows; _lastPerfItem = Settings.PerfItemLightShadows; _lastPerfAnim = Settings.PerfAnimatedLightShadows; _lastPerfPart = Settings.PerfParticleShadows; _lastPerfTiny = Settings.PerfTinyRendererCulling; _lastPerfDist = Settings.PerfDistanceShadowCulling; _lastPerfFlash = Settings.PerfFlashlightShadowBudget; } } internal static class GrabberComponentCache { private class CachedRenderers { public Material? beam; public Material? point1; public Material? point2; public Material? rotate; public Light? grabLight; public Material? orb0; public Material? orb1; public bool valid; } private static readonly ConditionalWeakTable _cache = new ConditionalWeakTable(); internal static void CacheFor(PhysGrabber g) { if (_cache.TryGetValue(g, out CachedRenderers _)) { return; } CachedRenderers cachedRenderers = new CachedRenderers(); try { if ((Object)(object)g.physGrabBeam != (Object)null) { LineRenderer component = g.physGrabBeam.GetComponent(); cachedRenderers.beam = ((component != null) ? ((Renderer)component).material : null); } if ((Object)(object)g.physGrabPointVisual1 != (Object)null) { MeshRenderer component2 = g.physGrabPointVisual1.GetComponent(); cachedRenderers.point1 = ((component2 != null) ? ((Renderer)component2).material : null); } if ((Object)(object)g.physGrabPointVisual2 != (Object)null) { MeshRenderer component3 = g.physGrabPointVisual2.GetComponent(); cachedRenderers.point2 = ((component3 != null) ? ((Renderer)component3).material : null); } if ((Object)(object)g.physGrabPointVisualRotate != (Object)null) { MeshRenderer component4 = ((Component)g.physGrabPointVisualRotate).GetComponent(); cachedRenderers.rotate = ((component4 != null) ? ((Renderer)component4).material : null); } PlayerAvatarRightArm val = g.playerAvatar?.playerAvatarVisuals?.playerAvatarRightArm; if ((Object)(object)val != (Object)null) { cachedRenderers.grabLight = val.grabberLight; if (val.grabberOrbSpheres != null && val.grabberOrbSpheres.Length >= 2) { GameObject obj = val.grabberOrbSpheres[0]; object orb; if (obj == null) { orb = null; } else { MeshRenderer component5 = obj.GetComponent(); orb = ((component5 != null) ? ((Renderer)component5).material : null); } cachedRenderers.orb0 = (Material?)orb; GameObject obj2 = val.grabberOrbSpheres[1]; object orb2; if (obj2 == null) { orb2 = null; } else { MeshRenderer component6 = obj2.GetComponent(); orb2 = ((component6 != null) ? ((Renderer)component6).material : null); } cachedRenderers.orb1 = (Material?)orb2; } } cachedRenderers.valid = true; } catch { cachedRenderers.valid = false; } _cache.AddOrUpdate(g, cachedRenderers); } internal static bool TryApplyColor(PhysGrabber g, Color main, Color emission) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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) if (!_cache.TryGetValue(g, out CachedRenderers value)) { return false; } if (!value.valid) { return false; } g.currentBeamColor = main; SetColor(value.beam, main, emission); SetColor(value.point1, main, emission); SetColor(value.point2, main, emission); SetColor(value.rotate, main, emission); if ((Object)(object)value.grabLight != (Object)null) { value.grabLight.color = main; } SetColor(value.orb0, main, emission); SetColor(value.orb1, main, emission); return true; } private static void SetColor(Material? mat, Color main, Color emission) { //IL_000b: 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) if (!((Object)(object)mat == (Object)null)) { mat.color = main; mat.SetColor("_EmissionColor", emission); } } } [HarmonyPatch(typeof(PhysGrabber), "Start")] internal static class CacheGrabberOnStart { private static void Postfix(PhysGrabber __instance) { GrabberComponentCache.CacheFor(__instance); } } [HarmonyPatch(typeof(PhysGrabber), "ColorStateSetColor")] internal static class SkipGrabberGetComponent { private static bool Prefix(PhysGrabber __instance, Color mainColor, Color emissionColor) { //IL_000a: 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) if (!Settings.ModEnabled) { return true; } return !GrabberComponentCache.TryApplyColor(__instance, mainColor, emissionColor); } } [HarmonyPatch(typeof(LevelGenerator), "GenerateDone")] internal static class RegisterPerfWatcher { private static void Postfix() { PerfSettingsWatcher.Register(); } } [HarmonyPatch] internal static class QualityPatch { private static readonly HashSet _flashlightLights = new HashSet(); private static readonly Dictionary _shadowResOrig = new Dictionary(); private static ShadowResolution _vanillaShadowRes; private static float _vanillaShadowDist; private static float _vanillaLodBias; private static int _vanillaPixelLights; private static AnisotropicFiltering _vanillaAF; private static int _vanillaTexMip; private static bool _vanillaQualitySaved; internal static int ShadowResOrigCount => _shadowResOrig.Count; internal static void SaveVanillaQuality() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) if (!_vanillaQualitySaved) { _vanillaShadowRes = QualitySettings.shadowResolution; _vanillaShadowDist = QualitySettings.shadowDistance; _vanillaLodBias = QualitySettings.lodBias; _vanillaPixelLights = QualitySettings.pixelLightCount; _vanillaAF = QualitySettings.anisotropicFiltering; _vanillaTexMip = QualitySettings.globalTextureMipmapLimit; _vanillaQualitySaved = true; Plugin.Log.LogInfo((object)($"Vanilla defaults: shadows={_vanillaShadowRes}/{_vanillaShadowDist}m " + $"LOD={_vanillaLodBias} lights={_vanillaPixelLights} AF={_vanillaAF} texMip={_vanillaTexMip}")); } } internal static void RestoreVanillaQuality() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (_vanillaQualitySaved) { QualitySettings.shadowResolution = _vanillaShadowRes; QualitySettings.shadowDistance = _vanillaShadowDist; QualitySettings.lodBias = _vanillaLodBias; QualitySettings.pixelLightCount = _vanillaPixelLights; QualitySettings.anisotropicFiltering = _vanillaAF; QualitySettings.globalTextureMipmapLimit = _vanillaTexMip; if (UpscalerManager._vanillaSaved) { RenderSettings.fogStartDistance = UpscalerManager._vanillaFogStart; RenderSettings.fogEndDistance = UpscalerManager._vanillaFogEnd; } RestoreRangeTieredLightShadows(); } } private static void RestoreRangeTieredLightShadows() { foreach (KeyValuePair item in _shadowResOrig) { if ((Object)(object)item.Key != (Object)null) { item.Key.shadowCustomResolution = item.Value; } } _shadowResOrig.Clear(); } [HarmonyPostfix] [HarmonyPatch(typeof(GraphicsManager), "UpdateAll")] public static void PostfixUpdateAll() { ApplyQualitySettings(); } [HarmonyPostfix] [HarmonyPatch(typeof(GraphicsManager), "UpdateLightDistance")] public static void PostfixUpdateLightDistance(GraphicsManager __instance) { if (Settings.ModEnabled) { float lightDistance = __instance.lightDistance; __instance.lightDistance = Settings.ResolvedLightDistance; if (__instance.lightDistance > lightDistance && (Object)(object)LightManager.instance != (Object)null) { LightManager.instance.UpdateInstant(); } } } [HarmonyPostfix] [HarmonyPatch(typeof(GraphicsManager), "UpdateMotionBlur")] public static void PostfixUpdateMotionBlur() { if (Settings.ModEnabled && !Settings.MotionBlurOverride && (Object)(object)PostProcessing.Instance != (Object)null) { ((PostProcessEffectSettings)PostProcessing.Instance.motionBlur).active = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(GraphicsManager), "UpdateChromaticAberration")] public static void PostfixChromaticAberration() { if (Settings.ModEnabled && !Settings.ChromaticAberration && (Object)(object)PostProcessing.Instance != (Object)null) { ((PostProcessEffectSettings)PostProcessing.Instance.chromaticAberration).active = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(GraphicsManager), "UpdateLensDistortion")] public static void PostfixLensDistortion() { if (Settings.ModEnabled && !Settings.LensDistortion && (Object)(object)PostProcessing.Instance != (Object)null) { ((PostProcessEffectSettings)PostProcessing.Instance.lensDistortion).active = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(GraphicsManager), "UpdateGrain")] public static void PostfixGrain() { if (Settings.ModEnabled && !Settings.FilmGrain && (Object)(object)PostProcessing.Instance != (Object)null) { ((PostProcessEffectSettings)PostProcessing.Instance.grain).active = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(EnvironmentDirector), "Setup")] public static void PostfixEnvironmentSetup(EnvironmentDirector __instance) { UpscalerManager.SaveVanillaFog(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(EnvironmentDirector), "FogLogic")] public static void PostfixFogLogic(EnvironmentDirector __instance) { if (Settings.ModEnabled) { float resolvedFogMultiplier = Settings.ResolvedFogMultiplier; if (resolvedFogMultiplier != 1f) { RenderSettings.fogStartDistance *= resolvedFogMultiplier; RenderSettings.fogEndDistance *= resolvedFogMultiplier; } Settings.ResolvedEffectiveFogEnd = RenderSettings.fogEndDistance; Settings.ApplyFogClamps(); float resolvedViewDistance = Settings.ResolvedViewDistance; if (resolvedViewDistance > 0f) { UpscalerManager.SetModFarClip(__instance.MainCamera, resolvedViewDistance); } else { float num = RenderSettings.fogEndDistance + 10f; num = Mathf.Max(num, UpscalerManager.GetVanillaFarClip(__instance.MainCamera)); UpscalerManager.SetModFarClip(__instance.MainCamera, num); } Plugin.Log.LogDebug((object)($"Fog: {RenderSettings.fogStartDistance:F0}-{RenderSettings.fogEndDistance:F0}m, " + $"clip: {__instance.MainCamera.farClipPlane:F0}m")); } } internal static void ApplyFogAndDrawDistance() { if (!Settings.ModEnabled || !UpscalerManager._vanillaSaved) { return; } float resolvedFogMultiplier = Settings.ResolvedFogMultiplier; RenderSettings.fogStartDistance = UpscalerManager._vanillaFogStart * resolvedFogMultiplier; RenderSettings.fogEndDistance = UpscalerManager._vanillaFogEnd * resolvedFogMultiplier; Settings.ResolvedEffectiveFogEnd = RenderSettings.fogEndDistance; Settings.ApplyFogClamps(); float resolvedViewDistance = Settings.ResolvedViewDistance; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { if (resolvedViewDistance > 0f) { UpscalerManager.SetModFarClip(main, resolvedViewDistance); } else { float num = RenderSettings.fogEndDistance + 10f; num = Mathf.Max(num, UpscalerManager.GetVanillaFarClip(main)); UpscalerManager.SetModFarClip(main, num); } } if ((Object)(object)GraphicsManager.instance != (Object)null) { GraphicsManager.instance.lightDistance = Settings.ResolvedLightDistance; } if ((Object)(object)LightManager.instance != (Object)null) { LightManager.instance.UpdateInstant(); } ApplyLayerCulling(main); } private static void ApplyLayerCulling(Camera? cam) { if ((Object)(object)cam == (Object)null) { return; } float fogEndDistance = RenderSettings.fogEndDistance; float[] array = new float[32]; for (int i = 8; i < 32; i++) { string text = LayerMask.LayerToName(i); if (!string.IsNullOrEmpty(text) && !text.Contains("Player") && !text.Contains("Enemy") && !text.Contains("Interact") && !text.Contains("Trigger") && !text.Contains("PhysGrab") && !text.Contains("Valuable")) { array[i] = fogEndDistance + 5f; } } cam.layerCullDistances = array; } internal static void ApplyQualitySettings() { if (!Settings.ModEnabled) { return; } SaveVanillaQuality(); try { QualityPreset preset = Settings.Preset; ApplyShadowResolution(); QualitySettings.shadowDistance = Settings.ResolvedShadowDistance; QualitySettings.lodBias = Settings.ResolvedLODBias; QualitySettings.pixelLightCount = Settings.ResolvedPixelLightCount; int resolvedAnisotropicFiltering = Settings.ResolvedAnisotropicFiltering; int resolvedTextureQuality = (int)Settings.ResolvedTextureQuality; ApplyAnisotropicFiltering(resolvedAnisotropicFiltering); QualitySettings.globalTextureMipmapLimit = resolvedTextureQuality; if ((Object)(object)GraphicsManager.instance != (Object)null) { GraphicsManager.instance.lightDistance = Settings.ResolvedLightDistance; } ApplyFogAndDrawDistance(); Plugin.Log.LogInfo((object)($"[{preset}] shadows={Settings.ResolvedShadowQuality}/{Settings.ResolvedShadowDistance}m " + $"LOD={Settings.ResolvedLODBias} AF={resolvedAnisotropicFiltering} lights={Settings.ResolvedPixelLightCount} " + $"lightDist={Settings.ResolvedLightDistance}m tex={resolvedTextureQuality}")); } catch (Exception arg) { Plugin.Log.LogError((object)$"QualityPatch failed: {arg}"); } } private static void ApplyShadowResolution() { switch (Settings.ResolvedShadowQuality) { case ShadowQuality.Low: QualitySettings.shadowResolution = (ShadowResolution)0; QualitySettings.shadowCascades = 1; break; case ShadowQuality.Medium: QualitySettings.shadowResolution = (ShadowResolution)1; QualitySettings.shadowCascades = 2; break; case ShadowQuality.High: QualitySettings.shadowResolution = (ShadowResolution)2; QualitySettings.shadowCascades = 4; break; case ShadowQuality.Ultra: QualitySettings.shadowResolution = (ShadowResolution)3; QualitySettings.shadowCascades = 4; break; } ApplyRangeTieredLightShadows(); } private static void RefreshFlashlightLights() { _flashlightLights.Clear(); FlashlightController[] array = Object.FindObjectsOfType(); foreach (FlashlightController val in array) { if ((Object)(object)val.spotlight != (Object)null) { _flashlightLights.Add(val.spotlight); } } } private static void ApplyRangeTieredLightShadows() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 RestoreRangeTieredLightShadows(); if (!Settings.OptimizationsActive) { return; } RefreshFlashlightLights(); bool flag = Settings.ResolvedShadowQuality == ShadowQuality.Ultra; int num = ((Settings.Preset == QualityPreset.Potato) ? 1024 : 4096); int num2 = 0; Light[] array = Object.FindObjectsOfType(); foreach (Light val in array) { if ((int)val.type == 1) { _shadowResOrig[val] = val.shadowCustomResolution; val.shadowCustomResolution = 0; continue; } if (flag && _flashlightLights.Contains(val)) { _shadowResOrig[val] = val.shadowCustomResolution; val.shadowCustomResolution = 4096; num2++; continue; } float range = val.range; int num3 = ((range < 5f) ? 256 : ((range < 10f) ? 512 : ((!(range < 20f)) ? 2048 : 1024))); int num4 = num3; _shadowResOrig[val] = val.shadowCustomResolution; val.shadowCustomResolution = Mathf.Min(num4, num); num2++; } if (num2 > 0) { Plugin.Log.LogDebug((object)$"shadow-res: tiered {num2} lights (flashlights={_flashlightLights.Count}, cap={num})"); } } private static void ApplyAnisotropicFiltering(int level) { if (level <= 0) { QualitySettings.anisotropicFiltering = (AnisotropicFiltering)0; return; } QualitySettings.anisotropicFiltering = (AnisotropicFiltering)2; Texture.SetGlobalAnisotropicFilteringLimits(level, level); } } [HarmonyPatch(typeof(RenderTextureMain))] internal static class RenderTexturePatch { internal static DepthTextureMode OriginalDepthMode; internal static Antialiasing[] OriginalAAModes; internal static float VanillaWidthSmall; internal static float VanillaHeightSmall; [HarmonyPostfix] [HarmonyPatch("Start")] public static void PostfixStart(RenderTextureMain __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_006d: Expected I4, but got O //IL_0117: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_006c->IL006c: Incompatible stack types: O vs I4 //IL_0065->IL006c: Incompatible stack types: I4 vs O //IL_0065->IL006c: Incompatible stack types: O vs I4 Camera val = null; if (__instance.cameras.Count > 0) { OriginalDepthMode = __instance.cameras[0].depthTextureMode; OriginalAAModes = (Antialiasing[])(object)new Antialiasing[__instance.cameras.Count]; for (int i = 0; i < __instance.cameras.Count; i++) { PostProcessLayer component = ((Component)__instance.cameras[i]).GetComponent(); object obj = OriginalAAModes; int num = i; int num2; if (!((Object)(object)component != (Object)null)) { num2 = 0; obj = num2; num2 = (int)obj; } else { obj = component.antialiasingMode; num2 = (int)obj; } ((int[])num2)[num] = (int)obj; } } for (int j = 0; j < __instance.cameras.Count; j++) { Camera val2 = __instance.cameras[j]; if (j == 0) { val = val2; UpscaleMode resolvedUpscaleMode = Settings.ResolvedUpscaleMode; if (((uint)(resolvedUpscaleMode - 1) <= 1u || resolvedUpscaleMode == UpscaleMode.FSR_Temporal) ? true : false) { val2.depthTextureMode = (DepthTextureMode)(val2.depthTextureMode | 1); val2.depthTextureMode = (DepthTextureMode)(val2.depthTextureMode | 4); } } PostProcessLayer component2 = ((Component)val2).GetComponent(); if ((Object)(object)component2 != (Object)null) { PostProcessLayer val3 = component2; val3.antialiasingMode = (Antialiasing)(Settings.ResolvedAAMode switch { AAMode.TAA => 2, AAMode.SMAA => 2, AAMode.FXAA => 1, AAMode.Off => 0, _ => component2.antialiasingMode, }); component2.fastApproximateAntialiasing.keepAlpha = true; Plugin.Log.LogDebug((object)$"AA on {((Object)val2).name}: {component2.antialiasingMode}"); } } VanillaWidthSmall = __instance.textureWidthSmall; VanillaHeightSmall = __instance.textureHeightSmall; int outputWidth = Settings.OutputWidth; int outputHeight = Settings.OutputHeight; __instance.textureWidthOriginal = outputWidth; __instance.textureHeightOriginal = outputHeight; __instance.textureWidth = outputWidth; __instance.textureHeight = outputHeight; if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.AddComponent().Setup(__instance, val); } } [HarmonyPrefix] [HarmonyPatch("Update")] public static void PrefixUpdate(RenderTextureMain __instance) { if (!Settings.ModEnabled || Settings.Pixelation) { return; } UpscalerManager instance = UpscalerManager.Instance; float num = (((Object)(object)instance != (Object)null && instance.CurrentTier == UpscalerManager.RenderTier.NativeScaling) ? GetRenderScale() : 1f); int outputWidth = Settings.OutputWidth; int outputHeight = Settings.OutputHeight; __instance.textureWidthOriginal = Mathf.Max(Mathf.RoundToInt((float)outputWidth * num), 1); __instance.textureHeightOriginal = Mathf.Max(Mathf.RoundToInt((float)outputHeight * num), 1); if (__instance.cameras.Count > 0) { RenderTexture targetTexture = __instance.cameras[0].targetTexture; if ((Object)(object)targetTexture != (Object)null) { __instance.textureWidth = ((Texture)targetTexture).width; __instance.textureHeight = ((Texture)targetTexture).height; } else { __instance.textureWidth = outputWidth; __instance.textureHeight = outputHeight; } } } internal static void RestoreVanillaResolution() { if (!((Object)(object)RenderTextureMain.instance == (Object)null)) { RenderTextureMain instance = RenderTextureMain.instance; instance.textureWidthOriginal = VanillaWidthSmall; instance.textureHeightOriginal = VanillaHeightSmall; instance.textureWidth = VanillaWidthSmall; instance.textureHeight = VanillaHeightSmall; } } internal static void RestoreVanillaCameraSettings() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)RenderTextureMain.instance == (Object)null) { return; } List cameras = RenderTextureMain.instance.cameras; if (cameras.Count > 0) { cameras[0].depthTextureMode = OriginalDepthMode; } if (OriginalAAModes == null) { return; } for (int i = 0; i < cameras.Count && i < OriginalAAModes.Length; i++) { PostProcessLayer component = ((Component)cameras[i]).GetComponent(); if ((Object)(object)component != (Object)null) { component.antialiasingMode = OriginalAAModes[i]; } } } internal static void ReapplyModCameraSettings() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00c0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)RenderTextureMain.instance == (Object)null) { return; } List cameras = RenderTextureMain.instance.cameras; if (cameras.Count > 0) { UpscaleMode resolvedUpscaleMode = Settings.ResolvedUpscaleMode; if (((uint)(resolvedUpscaleMode - 1) <= 1u || resolvedUpscaleMode == UpscaleMode.FSR_Temporal) ? true : false) { Camera obj = cameras[0]; obj.depthTextureMode = (DepthTextureMode)(obj.depthTextureMode | 1); Camera obj2 = cameras[0]; obj2.depthTextureMode = (DepthTextureMode)(obj2.depthTextureMode | 4); } } for (int i = 0; i < cameras.Count; i++) { PostProcessLayer component = ((Component)cameras[i]).GetComponent(); if ((Object)(object)component != (Object)null) { PostProcessLayer val = component; val.antialiasingMode = (Antialiasing)(Settings.ResolvedAAMode switch { AAMode.TAA => 2, AAMode.SMAA => 2, AAMode.FXAA => 1, AAMode.Off => 0, _ => component.antialiasingMode, }); component.fastApproximateAntialiasing.keepAlpha = true; } } } internal static float GetRenderScale() { return (float)Settings.ResolvedRenderScale / 100f; } } [HarmonyPatch(typeof(RoomVolumeCheck), "Check")] internal static class RoomVolumeCheckPatch { [CompilerGenerated] private sealed class d__4 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public RoomVolumeCheck instance; private PlayerAvatar 5__2; private LayerMask 5__3; private WaitForSeconds 5__4; private WaitForSeconds 5__5; private Vector3 5__6; private bool 5__7; private int 5__8; private List 5__9; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__4 = null; 5__5 = null; 5__9 = null; <>1__state = -2; } private bool MoveNext() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_003c: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_004c; case 1: <>1__state = -1; goto IL_004c; case 2: { <>1__state = -1; Traverse val = Traverse.Create((object)instance); 5__2 = val.Field("player").Value; 5__3 = val.Field("Mask").Value; 5__4 = new WaitForSeconds(0.1f); 5__5 = new WaitForSeconds(0.5f); 5__6 = Vector3.zero; 5__7 = false; 5__8 = 0; 5__9 = new List(4); break; } case 3: <>1__state = -1; break; case 4: { <>1__state = -1; break; } IL_004c: if (!LevelGenerator.Instance.Generated) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 2; return true; } if (instance.PauseCheckTimer > 0f) { RoomVolumeCheck obj = instance; obj.PauseCheckTimer -= 0.5f; <>2__current = 5__5; <>1__state = 3; return true; } long startTicks = FrameTimeMeter.Begin(); RunCheck(instance, 5__2, 5__3, ref 5__6, ref 5__7, ref 5__8, 5__9); FrameTimeMeter.End(FrameTimeMeter.RoomVolumeCheck, startTicks); if (!instance.Continuous) { return false; } <>2__current = (Object.op_Implicit((Object)(object)5__2) ? 5__4 : 5__5); <>1__state = 4; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int StickyMaxTicks = 3; private static readonly Collider[] _overlapBuf = (Collider[])(object)new Collider[32]; private static readonly RaycastHit[] _sweepBuf = (RaycastHit[])(object)new RaycastHit[32]; private static bool Prefix(RoomVolumeCheck __instance, ref IEnumerator __result) { if (!Settings.ModEnabled) { return true; } __result = OptimizedCheck(__instance); return false; } [IteratorStateMachine(typeof(d__4))] private static IEnumerator OptimizedCheck(RoomVolumeCheck instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0) { instance = instance }; } private static void RunCheck(RoomVolumeCheck instance, PlayerAvatar player, LayerMask mask, ref Vector3 lastPos, ref bool hasLastPos, ref int stickyTicks, List cachedRooms) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_024a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = instance.currentSize; if (val == Vector3.zero) { val = ((Component)instance).transform.localScale; } Vector3 val2 = val * 0.5f; Vector3 val3 = ((Component)instance).transform.position + ((Component)instance).transform.rotation * instance.CheckPosition; Quaternion rotation = ((Component)instance).transform.rotation; if (hasLastPos && instance.wasInRoom && stickyTicks == 0) { Vector3 val4 = val3 - lastPos; if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f) { ApplyGameLogicTail(instance, player); return; } } instance.inTruck = false; instance.inExtractionPoint = false; instance.CurrentRooms.Clear(); int num = Physics.OverlapBoxNonAlloc(val3, val2, _overlapBuf, rotation, LayerMask.op_Implicit(mask)); for (int i = 0; i < num; i++) { AddRoom(instance, _overlapBuf[i]); } if ((instance.CurrentRooms.Count == 0) & hasLastPos) { Vector3 val5 = val3 - lastPos; float magnitude = ((Vector3)(ref val5)).magnitude; if (magnitude > 0.01f) { int num2 = Physics.BoxCastNonAlloc(lastPos, val2, val5 / magnitude, _sweepBuf, rotation, magnitude, LayerMask.op_Implicit(mask)); for (int j = 0; j < num2; j++) { AddRoom(instance, ((RaycastHit)(ref _sweepBuf[j])).collider); } } } bool flag = false; if (instance.CurrentRooms.Count == 0 && instance.wasInRoom && stickyTicks < 3) { for (int k = 0; k < cachedRooms.Count; k++) { RoomVolume val6 = cachedRooms[k]; if (!((Object)(object)val6 == (Object)null)) { instance.CurrentRooms.Add(val6); if (val6.Truck) { instance.inTruck = true; } if (val6.Extraction) { instance.inExtractionPoint = true; } } } if (instance.CurrentRooms.Count > 0) { stickyTicks++; flag = true; } } if (!flag) { stickyTicks = 0; } if (!flag && instance.CurrentRooms.Count > 0) { cachedRooms.Clear(); for (int l = 0; l < instance.CurrentRooms.Count; l++) { cachedRooms.Add(instance.CurrentRooms[l]); } } ApplyGameLogicTail(instance, player); lastPos = val3; hasLastPos = true; } private static void AddRoom(RoomVolumeCheck instance, Collider col) { if ((Object)(object)col == (Object)null) { return; } RoomVolume val = ((Component)((Component)col).transform).GetComponent(); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)((Component)col).transform).GetComponentInParent(); } if (Object.op_Implicit((Object)(object)val) && !instance.CurrentRooms.Contains(val)) { instance.CurrentRooms.Add(val); if (val.Truck) { instance.inTruck = true; } if (val.Extraction) { instance.inExtractionPoint = true; } } } private static void ApplyGameLogicTail(RoomVolumeCheck instance, PlayerAvatar player) { //IL_009f: 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) if (Object.op_Implicit((Object)(object)player) && instance.CurrentRooms.Count > 0) { bool flag = true; MapModule mapModule = instance.CurrentRooms[0].MapModule; for (int i = 1; i < instance.CurrentRooms.Count; i++) { if ((Object)(object)mapModule != (Object)(object)instance.CurrentRooms[i].MapModule) { flag = false; break; } } if (flag && instance.CurrentRooms[0].SetExplored() && player.isLocal && Object.op_Implicit((Object)(object)TruckSafetySpawnPoint.instance) && Object.op_Implicit((Object)(object)ProgressionManager.instance)) { float num = Vector3.Distance(player.playerTransform.position, ((Component)TruckSafetySpawnPoint.instance).transform.position) / 20f; ProgressionManager instance2 = ProgressionManager.instance; instance2.roundPointsScouting += 100f * num; } } instance.wasInRoom = instance.CurrentRooms.Count > 0; instance.TutorialExtractionReminderLogic(); } } internal static class CameraZoomFovOverride { [CompilerGenerated] private sealed class d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float duration; public CameraZoom cz; public float startFov; public float targetFov; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0f; break; case 1: <>1__state = -1; break; } if (5__2 < duration && (Object)(object)cz != (Object)null) { 5__2 += Time.deltaTime; float num = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(5__2 / duration)); WriteFovImmediate(cz, Mathf.Lerp(startFov, targetFov, num)); <>2__current = null; <>1__state = 1; return true; } if ((Object)(object)cz != (Object)null) { WriteFovImmediate(cz, targetFov); _activeAnims.Remove(cz); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly Dictionary _originals = new Dictionary(); private static readonly Dictionary _activeAnims = new Dictionary(); private const float AnimDuration = 0.25f; internal static void Apply(CameraZoom cz) { if ((Object)(object)cz == (Object)null) { return; } if (!Settings.ModEnabled) { Restore(cz); return; } if (!_originals.ContainsKey(cz)) { _originals[cz] = cz.playerZoomDefault; } float targetFov = ((Settings.VerticalFovOverride > 0) ? ((float)Settings.VerticalFovOverride) : ComputeAspectAwareDefault(_originals[cz])); StartFovAnim(cz, targetFov); } internal static float ComputeAspectAwareDefault(float vanilla16x9Fov) { if (Screen.height == 0) { return vanilla16x9Fov; } float num = (float)Screen.width / (float)Screen.height; if (num <= 1.7877778f) { return vanilla16x9Fov; } if (num <= 2.389f) { return Mathf.Lerp(vanilla16x9Fov, 80f, Mathf.InverseLerp(1.7777778f, 2.389f, num)); } if (num <= 3.5555556f) { return Mathf.Lerp(80f, 90f, Mathf.InverseLerp(2.389f, 3.5555556f, num)); } return 90f; } internal static void Restore(CameraZoom cz) { if (!((Object)(object)cz == (Object)null) && _originals.TryGetValue(cz, out var value)) { StartFovAnim(cz, value); } } internal static void RestoreAll() { foreach (KeyValuePair original in _originals) { if ((Object)(object)original.Key != (Object)null) { StartFovAnim(original.Key, original.Value); } } } internal static void RefreshAll() { CameraZoom[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { Apply(array[i]); } } private static void StartFovAnim(CameraZoom cz, float targetFov) { if ((Object)(object)Plugin.Instance == (Object)null) { WriteFovImmediate(cz, targetFov); return; } if (_activeAnims.TryGetValue(cz, out Coroutine value) && value != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(value); } float playerZoomDefault = cz.playerZoomDefault; if (!Mathf.Approximately(playerZoomDefault, targetFov)) { _activeAnims[cz] = ((MonoBehaviour)Plugin.Instance).StartCoroutine(AnimateFov(cz, playerZoomDefault, targetFov, 0.25f)); } } private static void WriteFovImmediate(CameraZoom cz, float fov) { cz.playerZoomDefault = fov; cz.zoomPrev = fov; cz.zoomNew = fov; cz.zoomLerp = 1f; } [IteratorStateMachine(typeof(d__10))] private static IEnumerator AnimateFov(CameraZoom cz, float startFov, float targetFov, float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { cz = cz, startFov = startFov, targetFov = targetFov, duration = duration }; } } [HarmonyPatch(typeof(CameraZoom), "Awake")] internal static class CameraZoomAwakePatch { [HarmonyPostfix] private static void Postfix(CameraZoom __instance) { CameraZoomFovOverride.Apply(__instance); } } internal static class MenuCameraFovOverride { private static Camera? _trackedCam; private static float _vanillaFov; private static bool _captured; internal static void Apply() { if (!Settings.ModEnabled) { Restore(); return; } CameraNoPlayerTarget instance = CameraNoPlayerTarget.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.cam == (Object)null) { return; } Camera cam = instance.cam; if (!(cam.fieldOfView < 5f)) { if (!_captured || (Object)(object)_trackedCam != (Object)(object)cam) { _trackedCam = cam; _vanillaFov = cam.fieldOfView; _captured = true; } float num = ApplyAspectCorrection(_vanillaFov); if (!Mathf.Approximately(cam.fieldOfView, num)) { cam.fieldOfView = num; } } } internal static void Restore() { if (_captured && (Object)(object)_trackedCam != (Object)null) { _trackedCam.fieldOfView = _vanillaFov; } _captured = false; _trackedCam = null; } private static float ApplyAspectCorrection(float baseFov) { if (Screen.height == 0) { return baseFov; } float num = (float)Screen.width / (float)Screen.height; if (num <= 1.7877778f) { return baseFov; } float num2 = Mathf.Clamp01((num / 1.7777778f - 1f) * 1.5f); if (num2 <= 0f) { return baseFov; } float num3 = baseFov * (MathF.PI / 180f); float num4 = 2f * Mathf.Atan(Mathf.Tan(num3 / 2f) * 1.7777778f / num); return Mathf.Lerp(baseFov, num4 * 57.29578f, num2); } } [HarmonyPatch(typeof(CameraNoPlayerTarget), "Awake")] internal static class CameraNoPlayerTargetAwakePatch { [HarmonyPostfix] private static void Postfix() { MenuCameraFovOverride.Apply(); } } internal static class UltrawideMenuTweaks { private const float FogMult = 0.6f; private const int StabilizationFrames = 30; private static bool _applied; private static Camera? _trackedCam; private static float _vanillaFogStart; private static float _vanillaFogEnd; private static int _menuFrames; internal static void Tick() { CameraNoPlayerTarget instance = CameraNoPlayerTarget.instance; Camera val = (((Object)(object)instance != (Object)null) ? instance.cam : null); if (Settings.ModEnabled && Settings.UltrawideUiFix && Screen.height > 0 && (float)Screen.width / (float)Screen.height > 1.7877778f && SemiFunc.MenuLevel() && (Object)(object)val != (Object)null) { _menuFrames++; if (_menuFrames >= 30) { if (!_applied || (Object)(object)_trackedCam != (Object)(object)val) { ApplyOnce(val); } EnforceEachFrame(); } return; } _menuFrames = 0; if (_applied) { if (SemiFunc.MenuLevel() && (Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)_trackedCam) { Restore(); } else { ClearWithoutRestoringRenderSettings(); } } } private static void ApplyOnce(Camera cam) { float fogStartDistance = RenderSettings.fogStartDistance; float fogEndDistance = RenderSettings.fogEndDistance; if (!(fogEndDistance <= 1f)) { _trackedCam = cam; _vanillaFogStart = fogStartDistance; _vanillaFogEnd = fogEndDistance; _applied = true; } } private static void EnforceEachFrame() { RenderSettings.fogStartDistance = _vanillaFogStart * 0.6f; RenderSettings.fogEndDistance = _vanillaFogEnd * 0.6f; } private static void Restore() { RenderSettings.fogStartDistance = _vanillaFogStart; RenderSettings.fogEndDistance = _vanillaFogEnd; _applied = false; _trackedCam = null; } private static void ClearWithoutRestoringRenderSettings() { _applied = false; _trackedCam = null; } } internal static class UltrawideCompareResolution { private static bool _active; private static bool _savedUiFix; internal static bool IsCompareActive => _active; internal static void HandleToggle(bool enabling) { if (Screen.height <= 0) { return; } float num = (float)Screen.width / (float)Screen.height; if (!enabling) { if (!_active && !(num <= 1.7877778f)) { _savedUiFix = Settings.UltrawideUiFix; Settings.UltrawideUiFix = false; ApplyAspectOverrideToAllCameras(1.7777778f); _active = true; } } else if (_active) { ResetAspectOnAllCameras(); Settings.UltrawideUiFix = _savedUiFix; _active = false; } } internal static void TickEnforcement() { if (_active) { ApplyAspectOverrideToAllCameras(1.7777778f); } } private static void ApplyAspectOverrideToAllCameras(float aspect) { if ((Object)(object)Camera.main != (Object)null) { Camera.main.aspect = aspect; } RenderTextureMain instance = RenderTextureMain.instance; if ((Object)(object)instance != (Object)null && instance.cameras != null) { foreach (Camera camera in instance.cameras) { if ((Object)(object)camera != (Object)null) { camera.aspect = aspect; } } } CameraNoPlayerTarget instance2 = CameraNoPlayerTarget.instance; if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.cam != (Object)null) { instance2.cam.aspect = aspect; } } private static void ResetAspectOnAllCameras() { if ((Object)(object)Camera.main != (Object)null) { Camera.main.ResetAspect(); } RenderTextureMain instance = RenderTextureMain.instance; if ((Object)(object)instance != (Object)null && instance.cameras != null) { foreach (Camera camera in instance.cameras) { if ((Object)(object)camera != (Object)null) { camera.ResetAspect(); } } } CameraNoPlayerTarget instance2 = CameraNoPlayerTarget.instance; if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.cam != (Object)null) { instance2.cam.ResetAspect(); } } } internal static class UltrawideCanvasFix { private const float WideThreshold = 1.85f; private const float NarrowThreshold = 1.768f; private static GameObject? _ultrawideUnderlay; private static GameObject? _underlayCanvasGo; private static RawImage? _underlayRawImage; private static RawImage? _hiddenMainImage; private static bool _hiddenMainImageWasEnabled; private static Image? _hiddenBackground; private static bool _hiddenBackgroundWasEnabled; private static RawImage? _hiddenOverlayRawImage; private static bool _hiddenOverlayWasEnabled; private static GameObject? _ultrawidePostFx; private static RawImage? _postFxRawImage; internal static void RefreshAll() { if (!Settings.ModEnabled || !Settings.UltrawideUiFix || !RequiresAspectFix()) { RestoreAll(); } else { EnsureUltrawideUnderlay(); } } internal static bool IsUltrawide() { if (Screen.height > 0) { return (float)Screen.width / (float)Screen.height > 1.85f; } return false; } internal static bool RequiresAspectFix() { if (Screen.height == 0) { return false; } float num = (float)Screen.width / (float)Screen.height; if (!(num > 1.85f)) { return num < 1.768f; } return true; } private static void EnsureUltrawideUnderlay() { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) RenderTextureMain instance = RenderTextureMain.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.overlayRawImage == (Object)null) { return; } Transform parent = ((Transform)((Graphic)instance.overlayRawImage).rectTransform).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val == (Object)null) { return; } RawImage component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { return; } RenderTexture renderTexture = instance.renderTexture; if ((Object)(object)renderTexture == (Object)null) { return; } if ((Object)(object)_underlayCanvasGo != (Object)null && (Object)(object)_underlayRawImage != (Object)null) { if ((Object)(object)_underlayRawImage.texture != (Object)(object)renderTexture) { _underlayRawImage.texture = (Texture)(object)renderTexture; ((Graphic)_underlayRawImage).SetMaterialDirty(); } if (((Behaviour)component).enabled) { HideMainImage(component); } HideCanvasBackgroundIfPresent(component); RouteOverlayThroughUnderlay(instance); return; } _underlayCanvasGo = new GameObject("REPOFidelity Ultrawide Canvas", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); Object.DontDestroyOnLoad((Object)(object)_underlayCanvasGo); Canvas component2 = _underlayCanvasGo.GetComponent(); component2.renderMode = (RenderMode)0; component2.sortingOrder = 0; _underlayCanvasGo.GetComponent().uiScaleMode = (ScaleMode)0; _ultrawideUnderlay = new GameObject("REPOFidelity Ultrawide Underlay", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(RawImage) }); _ultrawideUnderlay.transform.SetParent(_underlayCanvasGo.transform, false); RectTransform component3 = _ultrawideUnderlay.GetComponent(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.pivot = new Vector2(0.5f, 0.5f); component3.anchoredPosition = Vector2.zero; component3.sizeDelta = Vector2.zero; _underlayRawImage = _ultrawideUnderlay.GetComponent(); _underlayRawImage.texture = (Texture)(object)renderTexture; ((Graphic)_underlayRawImage).color = Color.white; ((Graphic)_underlayRawImage).raycastTarget = false; HideMainImage(component); HideCanvasBackgroundIfPresent(component); RouteOverlayThroughUnderlay(instance); } private static void HideMainImage(RawImage mainImage) { if ((Object)(object)_hiddenMainImage != (Object)(object)mainImage) { _hiddenMainImage = mainImage; _hiddenMainImageWasEnabled = ((Behaviour)mainImage).enabled; } ((Behaviour)mainImage).enabled = false; } private static void HideCanvasBackgroundIfPresent(RawImage mainImage) { Canvas componentInParent = ((Component)mainImage).GetComponentInParent(); Transform val = ((componentInParent != null) ? ((Component)componentInParent).transform : null); if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.Find("Background"); if ((Object)(object)val2 == (Object)null) { return; } Image component = ((Component)val2).GetComponent(); if (!((Object)(object)component == (Object)null)) { if ((Object)(object)_hiddenBackground != (Object)(object)component) { _hiddenBackground = component; _hiddenBackgroundWasEnabled = ((Behaviour)component).enabled; } if (((Behaviour)component).enabled) { ((Behaviour)component).enabled = false; } } } private static void RouteOverlayThroughUnderlay(RenderTextureMain rtm) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) RawImage overlayRawImage = rtm.overlayRawImage; if ((Object)(object)overlayRawImage == (Object)null) { return; } if ((Object)(object)_hiddenOverlayRawImage != (Object)(object)overlayRawImage) { _hiddenOverlayRawImage = overlayRawImage; _hiddenOverlayWasEnabled = ((Behaviour)overlayRawImage).enabled; } Texture texture = overlayRawImage.texture; Material material = ((Graphic)overlayRawImage).material; if (((Behaviour)overlayRawImage).enabled) { ((Behaviour)overlayRawImage).enabled = false; } if ((Object)(object)_underlayCanvasGo == (Object)null) { return; } if ((Object)(object)_ultrawidePostFx == (Object)null) { _ultrawidePostFx = new GameObject("REPOFidelity Ultrawide PostFx", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(RawImage) }); _ultrawidePostFx.transform.SetParent(_underlayCanvasGo.transform, false); RectTransform component = _ultrawidePostFx.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = Vector2.zero; component.sizeDelta = Vector2.zero; _postFxRawImage = _ultrawidePostFx.GetComponent(); ((Graphic)_postFxRawImage).raycastTarget = false; ((Graphic)_postFxRawImage).color = Color.white; } if ((Object)(object)_postFxRawImage != (Object)null) { if ((Object)(object)_postFxRawImage.texture != (Object)(object)texture) { _postFxRawImage.texture = texture; } if ((Object)(object)((Graphic)_postFxRawImage).material != (Object)(object)material) { ((Graphic)_postFxRawImage).material = material; } } } internal static void RestoreAll() { if ((Object)(object)_hiddenMainImage != (Object)null) { ((Behaviour)_hiddenMainImage).enabled = _hiddenMainImageWasEnabled; _hiddenMainImage = null; } if ((Object)(object)_hiddenBackground != (Object)null) { ((Behaviour)_hiddenBackground).enabled = _hiddenBackgroundWasEnabled; _hiddenBackground = null; } if ((Object)(object)_hiddenOverlayRawImage != (Object)null) { ((Behaviour)_hiddenOverlayRawImage).enabled = _hiddenOverlayWasEnabled; _hiddenOverlayRawImage = null; } if ((Object)(object)_ultrawidePostFx != (Object)null) { Object.Destroy((Object)(object)_ultrawidePostFx); } if ((Object)(object)_underlayCanvasGo != (Object)null) { Object.Destroy((Object)(object)_underlayCanvasGo); } if ((Object)(object)_ultrawideUnderlay != (Object)null) { Object.Destroy((Object)(object)_ultrawideUnderlay); } _ultrawidePostFx = null; _postFxRawImage = null; _underlayCanvasGo = null; _ultrawideUnderlay = null; _underlayRawImage = null; } } [HarmonyPatch(typeof(MenuPage), "Awake")] internal static class MenuPageAwakeUltrawidePatch { [HarmonyPostfix] private static void Postfix() { UltrawideCanvasFix.RefreshAll(); MenuCameraFovOverride.Apply(); } } [HarmonyPatch(typeof(LevelGenerator), "GenerateDone")] internal static class LevelGeneratorUltrawidePatch { [HarmonyPostfix] private static void Postfix() { UltrawideCanvasFix.RefreshAll(); CameraZoomFovOverride.RefreshAll(); UltrawideSettingsWatcher.Register(); } } internal static class UltrawideSettingsWatcher { private static bool _registered; internal static void Register() { if (!_registered) { _registered = true; Settings.OnSettingsChanged += OnChanged; } } private static void OnChanged() { try { UltrawideCanvasFix.RefreshAll(); } catch (Exception arg) { Plugin.Log.LogError((object)$"[ultrawide] canvas RefreshAll threw: {arg}"); } try { CameraZoomFovOverride.RefreshAll(); } catch (Exception arg2) { Plugin.Log.LogError((object)$"[ultrawide] FOV RefreshAll threw: {arg2}"); } try { MenuCameraFovOverride.Apply(); } catch (Exception arg3) { Plugin.Log.LogError((object)$"[ultrawide] menu FOV Apply threw: {arg3}"); } } } }