Decompiled source of FusOpt v1.0.1

Mods\FusOpt.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using FusOpt;
using FusOpt.Systems;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using LabFusion.Network;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Scripting;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "FusOpt", "1.0.1", "ZVatnikV", "https://github.com/ZVatnikV/FusOpt")]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonColor(255, 40, 200, 230)]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib", "LabFusion" })]
[assembly: MelonPriority(500)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FusOpt
{
	public static class BoneMenuUI
	{
		private static Page _root;

		private static FunctionElement _status;

		public static void Setup()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0105: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_0580: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_root = Page.Root.CreatePage("FusOpt", new Color(0.15f, 0.85f, 0.95f), 0, true);
				_root.CreateBool("Enabled", Color.white, Config.Enabled.Value, (Action<bool>)delegate(bool v)
				{
					Config.Enabled.Value = v;
					Config.Save();
					if (!v)
					{
						Core.Instance.Props.RestoreAll();
					}
					else
					{
						Core.Instance.Quality.ApplyStaticTweaks();
					}
					RefreshStatus();
				});
				_root.CreateInt("Preset", new Color(1f, 0.85f, 0.2f), Config.Preset.Value, 1, 0, 3, (Action<int>)delegate(int v)
				{
					Config.ApplyPreset(v);
					Core.Instance.Quality.ApplyStaticTweaks();
					RefreshStatus();
				});
				_status = _root.CreateFunction("Status", Color.gray, (Action)RefreshStatus);
				Page obj = _root.CreatePage("Client Optimizations", new Color(0.4f, 0.9f, 0.6f), 0, true);
				obj.CreateBool("Prop Cull", Color.white, Config.PropCull.Value, (Action<bool>)delegate(bool v)
				{
					Config.PropCull.Value = v;
					Config.Save();
				});
				obj.CreateBool("Rigidbody Sleep", Color.white, Config.RigidbodySleep.Value, (Action<bool>)delegate(bool v)
				{
					Config.RigidbodySleep.Value = v;
					Config.Save();
				});
				obj.CreateBool("Particle Cull", Color.white, Config.ParticleCull.Value, (Action<bool>)delegate(bool v)
				{
					Config.ParticleCull.Value = v;
					Config.Save();
				});
				obj.CreateBool("Shadow Cull", Color.white, Config.ShadowCull.Value, (Action<bool>)delegate(bool v)
				{
					Config.ShadowCull.Value = v;
					Config.Save();
				});
				obj.CreateBool("Quality Tweaks", Color.white, Config.QualityTweaks.Value, (Action<bool>)delegate(bool v)
				{
					Config.QualityTweaks.Value = v;
					Config.Save();
					if (v)
					{
						Core.Instance.Quality.ApplyStaticTweaks();
					}
				});
				obj.CreateBool("Adaptive Quality", Color.white, Config.AdaptiveQuality.Value, (Action<bool>)delegate(bool v)
				{
					Config.AdaptiveQuality.Value = v;
					Config.Save();
				});
				obj.CreateBool("Incremental GC", Color.white, Config.IncrementalGc.Value, (Action<bool>)delegate(bool v)
				{
					Config.IncrementalGc.Value = v;
					Config.Save();
					if (v)
					{
						Core.Instance.Quality.ApplyStaticTweaks();
					}
				});
				obj.CreateBool("Occlusion Culling", Color.white, Config.OcclusionCulling.Value, (Action<bool>)delegate(bool v)
				{
					Config.OcclusionCulling.Value = v;
					Config.Save();
					if (v)
					{
						Core.Instance.Quality.ApplyOcclusion();
					}
				});
				obj.CreateFloat("Near Distance", Color.cyan, Config.NearDistance.Value, 1f, 4f, 60f, (Action<float>)delegate(float v)
				{
					Config.NearDistance.Value = v;
					Config.Save();
				});
				obj.CreateFloat("Far Distance", Color.cyan, Config.FarDistance.Value, 1f, 10f, 120f, (Action<float>)delegate(float v)
				{
					Config.FarDistance.Value = v;
					Config.Save();
				});
				obj.CreateFloat("Scan Interval", Color.yellow, Config.ScanInterval.Value, 0.05f, 0.1f, 2f, (Action<float>)delegate(float v)
				{
					Config.ScanInterval.Value = v;
					Config.Save();
				});
				obj.CreateInt("Max Active Props", Color.yellow, Config.MaxActiveProps.Value, 5, 20, 300, (Action<int>)delegate(int v)
				{
					Config.MaxActiveProps.Value = v;
					Config.Save();
				});
				obj.CreateFloat("Target FPS", Color.green, Config.TargetFps.Value, 1f, 30f, 144f, (Action<float>)delegate(float v)
				{
					Config.TargetFps.Value = v;
					Config.Save();
				});
				Page obj2 = _root.CreatePage("Host Tools", new Color(1f, 0.45f, 0.35f), 0, true);
				obj2.CreateBool("Auto Clean", Color.white, Config.HostAutoClean.Value, (Action<bool>)delegate(bool v)
				{
					Config.HostAutoClean.Value = v;
					Config.Save();
				});
				obj2.CreateFloat("Clean Interval (s)", Color.yellow, Config.HostCleanInterval.Value, 10f, 30f, 900f, (Action<float>)delegate(float v)
				{
					Config.HostCleanInterval.Value = v;
					Config.Save();
				});
				obj2.CreateInt("Prop Threshold", Color.yellow, Config.HostPropThreshold.Value, 10, 40, 500, (Action<int>)delegate(int v)
				{
					Config.HostPropThreshold.Value = v;
					Config.Save();
				});
				obj2.CreateBool("Memory Clean After", Color.white, Config.HostMemoryClean.Value, (Action<bool>)delegate(bool v)
				{
					Config.HostMemoryClean.Value = v;
					Config.Save();
				});
				obj2.CreateFunction("Clean Server Now (wipes props)", new Color(1f, 0.3f, 0.3f), (Action)delegate
				{
					Core.Instance.Host.CleanNow("menu");
					RefreshStatus();
				});
				obj2.CreateFunction("Memory Clean Only", new Color(0.8f, 0.6f, 1f), (Action)delegate
				{
					Core.Instance.Host.MemoryCleanOnly();
					RefreshStatus();
				});
				_root.CreateFunction("Apply Preset Now", new Color(0.5f, 0.8f, 1f), (Action)delegate
				{
					Config.ApplyPreset(Config.Preset.Value);
					Core.Instance.Quality.ApplyStaticTweaks();
					RefreshStatus();
				});
				RefreshStatus();
			}
			catch (Exception ex)
			{
				Core.Log.Warning("BoneMenu setup failed: " + ex.Message);
			}
		}

		public static void RefreshStatus()
		{
			if (_status == null)
			{
				return;
			}
			try
			{
				string value = Config.PresetName(Config.Preset.Value);
				string value2 = (Core.Instance.Host.CanHostAct() ? "HOST" : "client");
				((Element)_status).ElementName = $"FPS {Core.Instance.CurrentFps:0} | props {Core.Instance.Props.TrackedCount} (culled {Core.Instance.Props.CulledCount}) | {value} | {value2}";
			}
			catch
			{
			}
		}
	}
	public static class BuildInfo
	{
		public const string Name = "FusOpt";

		public const string Description = "Open-source Fusion lobby optimizer for crowded BONELAB servers";

		public const string Author = "ZVatnikV";

		public const string Version = "1.0.1";

		public const string DownloadLink = "https://github.com/ZVatnikV/FusOpt";
	}
	public static class Config
	{
		public static MelonPreferences_Category Category;

		public static MelonPreferences_Entry<bool> Enabled;

		public static MelonPreferences_Entry<int> Preset;

		public static MelonPreferences_Entry<bool> PropCull;

		public static MelonPreferences_Entry<bool> RigidbodySleep;

		public static MelonPreferences_Entry<bool> ParticleCull;

		public static MelonPreferences_Entry<bool> ShadowCull;

		public static MelonPreferences_Entry<bool> QualityTweaks;

		public static MelonPreferences_Entry<bool> AdaptiveQuality;

		public static MelonPreferences_Entry<bool> IncrementalGc;

		public static MelonPreferences_Entry<bool> OcclusionCulling;

		public static MelonPreferences_Entry<float> NearDistance;

		public static MelonPreferences_Entry<float> FarDistance;

		public static MelonPreferences_Entry<float> ScanInterval;

		public static MelonPreferences_Entry<int> MaxActiveProps;

		public static MelonPreferences_Entry<float> TargetFps;

		public static MelonPreferences_Entry<bool> HostAutoClean;

		public static MelonPreferences_Entry<float> HostCleanInterval;

		public static MelonPreferences_Entry<int> HostPropThreshold;

		public static MelonPreferences_Entry<bool> HostMemoryClean;

		public static void Setup()
		{
			Category = MelonPreferences.CreateCategory("FusOpt");
			Enabled = Category.CreateEntry<bool>("Enabled", true, "Master enable", (string)null, false, false, (ValueValidator)null, (string)null);
			Preset = Category.CreateEntry<int>("Preset", 2, "0 Balanced, 1 Performance, 2 Crowded, 3 Extreme", (string)null, false, false, (ValueValidator)null, (string)null);
			PropCull = Category.CreateEntry<bool>("PropCull", true, "Cull distant prop renderers", (string)null, false, false, (ValueValidator)null, (string)null);
			RigidbodySleep = Category.CreateEntry<bool>("RigidbodySleep", true, "Sleep distant rigidbodies", (string)null, false, false, (ValueValidator)null, (string)null);
			ParticleCull = Category.CreateEntry<bool>("ParticleCull", true, "Pause distant particles", (string)null, false, false, (ValueValidator)null, (string)null);
			ShadowCull = Category.CreateEntry<bool>("ShadowCull", true, "Disable distant shadows", (string)null, false, false, (ValueValidator)null, (string)null);
			QualityTweaks = Category.CreateEntry<bool>("QualityTweaks", true, "Apply crowded-lobby quality tweaks", (string)null, false, false, (ValueValidator)null, (string)null);
			AdaptiveQuality = Category.CreateEntry<bool>("AdaptiveQuality", true, "Scale quality from FPS", (string)null, false, false, (ValueValidator)null, (string)null);
			IncrementalGc = Category.CreateEntry<bool>("IncrementalGC", true, "Use incremental GC", (string)null, false, false, (ValueValidator)null, (string)null);
			OcclusionCulling = Category.CreateEntry<bool>("OcclusionCulling", true, "Force occlusion culling", (string)null, false, false, (ValueValidator)null, (string)null);
			NearDistance = Category.CreateEntry<float>("NearDistance", 18f, "Full detail distance", (string)null, false, false, (ValueValidator)null, (string)null);
			FarDistance = Category.CreateEntry<float>("FarDistance", 55f, "Cull / sleep distance", (string)null, false, false, (ValueValidator)null, (string)null);
			ScanInterval = Category.CreateEntry<float>("ScanInterval", 0.35f, "Seconds between prop scans", (string)null, false, false, (ValueValidator)null, (string)null);
			MaxActiveProps = Category.CreateEntry<int>("MaxActiveProps", 80, "Soft budget for nearby props", (string)null, false, false, (ValueValidator)null, (string)null);
			TargetFps = Category.CreateEntry<float>("TargetFPS", 72f, "Adaptive quality target FPS", (string)null, false, false, (ValueValidator)null, (string)null);
			HostAutoClean = Category.CreateEntry<bool>("HostAutoClean", false, "Host: auto despawn clutter", (string)null, false, false, (ValueValidator)null, (string)null);
			HostCleanInterval = Category.CreateEntry<float>("HostCleanInterval", 180f, "Host: auto clean seconds", (string)null, false, false, (ValueValidator)null, (string)null);
			HostPropThreshold = Category.CreateEntry<int>("HostPropThreshold", 120, "Host: clean when prop count exceeds", (string)null, false, false, (ValueValidator)null, (string)null);
			HostMemoryClean = Category.CreateEntry<bool>("HostMemoryClean", true, "Unload unused assets after clean", (string)null, false, false, (ValueValidator)null, (string)null);
			ApplyPreset(Preset.Value, writeDistances: false);
		}

		public static void Save()
		{
			try
			{
				MelonPreferences.Save();
			}
			catch
			{
			}
		}

		public static void ApplyPreset(int preset, bool writeDistances = true)
		{
			Preset.Value = preset;
			switch (preset)
			{
			case 0:
				if (writeDistances)
				{
					NearDistance.Value = 24f;
					FarDistance.Value = 70f;
					MaxActiveProps.Value = 120;
				}
				PropCull.Value = true;
				RigidbodySleep.Value = true;
				ParticleCull.Value = true;
				ShadowCull.Value = true;
				QualityTweaks.Value = true;
				AdaptiveQuality.Value = false;
				break;
			case 1:
				if (writeDistances)
				{
					NearDistance.Value = 20f;
					FarDistance.Value = 60f;
					MaxActiveProps.Value = 90;
				}
				PropCull.Value = true;
				RigidbodySleep.Value = true;
				ParticleCull.Value = true;
				ShadowCull.Value = true;
				QualityTweaks.Value = true;
				AdaptiveQuality.Value = true;
				break;
			case 3:
				if (writeDistances)
				{
					NearDistance.Value = 12f;
					FarDistance.Value = 35f;
					MaxActiveProps.Value = 40;
				}
				PropCull.Value = true;
				RigidbodySleep.Value = true;
				ParticleCull.Value = true;
				ShadowCull.Value = true;
				QualityTweaks.Value = true;
				AdaptiveQuality.Value = true;
				break;
			default:
				if (writeDistances)
				{
					NearDistance.Value = 16f;
					FarDistance.Value = 48f;
					MaxActiveProps.Value = 70;
				}
				PropCull.Value = true;
				RigidbodySleep.Value = true;
				ParticleCull.Value = true;
				ShadowCull.Value = true;
				QualityTweaks.Value = true;
				AdaptiveQuality.Value = true;
				break;
			}
			Save();
		}

		public static string PresetName(int preset)
		{
			return preset switch
			{
				0 => "Balanced", 
				1 => "Performance", 
				3 => "Extreme", 
				_ => "Crowded", 
			};
		}
	}
	public class Core : MelonMod
	{
		private float _fpsAccum;

		private int _fpsFrames;

		private float _fpsTimer;

		private float _statusTimer;

		private float _adaptiveTimer;

		public static Core Instance { get; private set; }

		public static Instance Log { get; private set; }

		public PropCuller Props { get; private set; }

		public QualityOptimizer Quality { get; private set; }

		public HostCleaner Host { get; private set; }

		public float CurrentFps { get; private set; } = 72f;

		public override void OnInitializeMelon()
		{
			Instance = this;
			Log = ((MelonBase)this).LoggerInstance;
			Log.Msg("========================================");
			Log.Msg("  FusOpt — Fusion Lobby Optimizer");
			Log.Msg("  v1.0.1  |  open source");
			Log.Msg("========================================");
			Config.Setup();
			Props = new PropCuller();
			Quality = new QualityOptimizer();
			Host = new HostCleaner();
			Quality.ApplyStaticTweaks();
			BoneMenuUI.Setup();
			try
			{
				Hooking.OnLevelLoaded += delegate
				{
					OnLevelReady();
				};
			}
			catch (Exception ex)
			{
				Log.Warning("BoneLib level hook failed: " + ex.Message);
			}
			Log.Msg("FusOpt ready. Open BoneMenu → FusOpt");
		}

		private void OnLevelReady()
		{
			Props.OnLevelLoaded();
			Quality.ApplyStaticTweaks();
			Quality.ApplyOcclusion();
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Props.OnLevelLoaded();
			Quality.ApplyOcclusion();
		}

		public override void OnUpdate()
		{
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			_fpsAccum += unscaledDeltaTime;
			_fpsFrames++;
			_fpsTimer += unscaledDeltaTime;
			if (_fpsTimer >= 0.5f)
			{
				CurrentFps = (float)_fpsFrames / Mathf.Max(_fpsAccum, 0.0001f);
				_fpsFrames = 0;
				_fpsAccum = 0f;
				_fpsTimer = 0f;
			}
			Host.Tick();
			_adaptiveTimer += unscaledDeltaTime;
			if (_adaptiveTimer >= 1f)
			{
				_adaptiveTimer = 0f;
				float playerScale = EstimatePlayers();
				Quality.TickAdaptive(CurrentFps, playerScale);
			}
			Transform viewer = GetViewer();
			if ((Object)(object)viewer != (Object)null)
			{
				Props.Tick(Time.unscaledTime, viewer);
			}
			_statusTimer += unscaledDeltaTime;
			if (_statusTimer >= 2f)
			{
				_statusTimer = 0f;
				BoneMenuUI.RefreshStatus();
			}
		}

		private static float EstimatePlayers()
		{
			try
			{
				if (!NetworkInfo.HasServer)
				{
					return 1f;
				}
			}
			catch
			{
				return 1f;
			}
			return 12f;
		}

		private static Transform GetViewer()
		{
			try
			{
				if ((Object)(object)Player.Head != (Object)null)
				{
					return Player.Head;
				}
			}
			catch
			{
			}
			try
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					return ((Component)main).transform;
				}
			}
			catch
			{
			}
			return null;
		}
	}
}
namespace FusOpt.Systems
{
	public sealed class HostCleaner
	{
		private float _lastClean = -1f;

		private float _lastThresholdCheck;

		private bool _autoWasEnabled;

		public float SecondsUntilClean
		{
			get
			{
				if (!Config.HostAutoClean.Value || _lastClean < 0f)
				{
					return -1f;
				}
				float num = Config.HostCleanInterval.Value - (Time.unscaledTime - _lastClean);
				return Mathf.Max(0f, num);
			}
		}

		public bool CanHostAct()
		{
			try
			{
				return NetworkInfo.HasServer && NetworkInfo.IsHost;
			}
			catch
			{
				return false;
			}
		}

		public void Tick()
		{
			if (!Config.Enabled.Value)
			{
				_autoWasEnabled = false;
				return;
			}
			if (Config.HostAutoClean.Value && !_autoWasEnabled)
			{
				_lastClean = Time.unscaledTime;
				_autoWasEnabled = true;
				Core.Log.Msg("[Host] Auto clean armed — waiting for first interval.");
			}
			else if (!Config.HostAutoClean.Value)
			{
				_autoWasEnabled = false;
			}
			if (!Config.HostAutoClean.Value || !CanHostAct())
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - _lastThresholdCheck >= 5f)
			{
				_lastThresholdCheck = unscaledTime;
				int num = EstimatePropCount();
				if (num >= Config.HostPropThreshold.Value)
				{
					Core.Log.Msg($"[Host] Prop threshold hit ({num}). Cleaning...");
					CleanNow("threshold");
					return;
				}
			}
			if (_lastClean >= 0f && unscaledTime - _lastClean >= Mathf.Max(30f, Config.HostCleanInterval.Value))
			{
				CleanNow("interval");
			}
		}

		public void CleanNow(string reason = "manual")
		{
			if (!CanHostAct())
			{
				Core.Log.Warning("Host clean requires Fusion host privileges.");
				return;
			}
			try
			{
				PooleeUtilities.DespawnAll();
				_lastClean = Time.unscaledTime;
				Core.Log.Msg("[Host] DespawnAll completed (" + reason + ").");
				if (Config.HostMemoryClean.Value)
				{
					Core.Instance.Quality.SoftMemoryClean();
				}
			}
			catch (Exception ex)
			{
				Core.Log.Error("Host clean failed: " + ex.Message);
			}
		}

		public void MemoryCleanOnly()
		{
			Core.Instance.Quality.SoftMemoryClean();
			Core.Log.Msg("Memory clean requested.");
		}

		private static int EstimatePropCount()
		{
			try
			{
				Rigidbody[] array = Il2CppArrayBase<Rigidbody>.op_Implicit(Object.FindObjectsOfType<Rigidbody>());
				if (array == null)
				{
					return 0;
				}
				int num = 0;
				foreach (Rigidbody val in array)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					try
					{
						Transform transform = ((Component)val).transform;
						if (!((Object)(object)transform == (Object)null))
						{
							string text = (((Object)transform).name ?? string.Empty).ToLowerInvariant();
							if (!text.Contains("rigmanager") && !text.Contains("playerrep") && !text.Contains("controller") && (!val.isKinematic || !(val.mass > 80f)))
							{
								num++;
							}
						}
					}
					catch
					{
					}
				}
				return num;
			}
			catch
			{
				return 0;
			}
		}
	}
	public sealed class PropCuller
	{
		private sealed class TrackedProp
		{
			public int Id;

			public Rigidbody Body;

			public Renderer[] Renderers;

			public ParticleSystem[] Particles;

			public bool Culled;

			public bool ShadowsOff;

			public bool ParticlesPaused;

			public ShadowCastingMode[] OriginalShadows;

			public bool[] OriginalRendererEnabled;

			public bool WasKinematic;

			public bool StoredKinematic;
		}

		private readonly Dictionary<int, TrackedProp> _byId = new Dictionary<int, TrackedProp>(256);

		private readonly List<TrackedProp> _props = new List<TrackedProp>(256);

		private float _nextScan;

		private float _nextRefresh = -1f;

		private Vector3 _viewer;

		private int _culledCount;

		private int _trackedCount;

		public int CulledCount => _culledCount;

		public int TrackedCount => _trackedCount;

		public void OnLevelLoaded()
		{
			RestoreAll();
			_byId.Clear();
			_props.Clear();
			_nextRefresh = 0f;
			_nextScan = 0f;
			_culledCount = 0;
			_trackedCount = 0;
		}

		public void Tick(float now, Transform viewer)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (Config.Enabled.Value && !((Object)(object)viewer == (Object)null))
			{
				_viewer = viewer.position;
				if (now >= _nextRefresh)
				{
					RefreshCache();
					_nextRefresh = now + 2.5f;
				}
				if (!(now < _nextScan))
				{
					_nextScan = now + Mathf.Max(0.1f, Config.ScanInterval.Value);
					Evaluate();
				}
			}
		}

		private void RefreshCache()
		{
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected I4, but got Unknown
			Rigidbody[] array;
			try
			{
				array = Il2CppArrayBase<Rigidbody>.op_Implicit(Object.FindObjectsOfType<Rigidbody>());
			}
			catch
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			foreach (Rigidbody val in array)
			{
				try
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					GameObject gameObject = ((Component)val).gameObject;
					if ((Object)(object)gameObject == (Object)null || !gameObject.activeInHierarchy || IsProtectedName(((Object)gameObject).name ?? string.Empty) || IsUnderPlayerHierarchy(gameObject.transform) || (val.isKinematic && val.mass > 80f))
					{
						continue;
					}
					int instanceID = ((Object)val).GetInstanceID();
					hashSet.Add(instanceID);
					if (_byId.TryGetValue(instanceID, out var value) && (Object)(object)value.Body == (Object)(object)val)
					{
						value.Body = val;
						continue;
					}
					Renderer[] array2 = Il2CppArrayBase<Renderer>.op_Implicit(gameObject.GetComponentsInChildren<Renderer>(true));
					if (array2 == null || array2.Length == 0)
					{
						continue;
					}
					TrackedProp trackedProp = new TrackedProp
					{
						Id = instanceID,
						Body = val,
						Renderers = array2,
						Particles = Il2CppArrayBase<ParticleSystem>.op_Implicit(gameObject.GetComponentsInChildren<ParticleSystem>(true)),
						Culled = false,
						ShadowsOff = false,
						ParticlesPaused = false,
						OriginalShadows = (ShadowCastingMode[])(object)new ShadowCastingMode[array2.Length],
						OriginalRendererEnabled = new bool[array2.Length]
					};
					for (int j = 0; j < array2.Length; j++)
					{
						Renderer val2 = array2[j];
						if (!((Object)(object)val2 == (Object)null))
						{
							trackedProp.OriginalShadows[j] = (ShadowCastingMode)(int)val2.shadowCastingMode;
							trackedProp.OriginalRendererEnabled[j] = val2.enabled;
						}
					}
					_byId[instanceID] = trackedProp;
				}
				catch
				{
				}
			}
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, TrackedProp> item in _byId)
			{
				if (!hashSet.Contains(item.Key))
				{
					try
					{
						ApplyCull(item.Value, cull: false);
						ApplyShadows(item.Value, off: false);
						ApplyParticles(item.Value, pause: false);
					}
					catch
					{
					}
					list.Add(item.Key);
				}
			}
			for (int k = 0; k < list.Count; k++)
			{
				_byId.Remove(list[k]);
			}
			_props.Clear();
			foreach (TrackedProp value2 in _byId.Values)
			{
				_props.Add(value2);
			}
			_trackedCount = _props.Count;
		}

		private void Evaluate()
		{
			float num = Mathf.Max(4f, Config.NearDistance.Value);
			float num2 = Mathf.Max(num + 2f, Config.FarDistance.Value);
			int num3 = Mathf.Max(10, Config.MaxActiveProps.Value);
			_props.Sort((TrackedProp a, TrackedProp b) => DistanceSq(a).CompareTo(DistanceSq(b)));
			int num4 = 0;
			int num5 = 0;
			for (int num6 = 0; num6 < _props.Count; num6++)
			{
				TrackedProp trackedProp = _props[num6];
				if (!((Object)(object)trackedProp.Body == (Object)null))
				{
					float num7 = Mathf.Sqrt(DistanceSq(trackedProp));
					bool flag = num7 <= num;
					bool flag2 = !flag && num4 >= num3;
					bool flag3 = num7 > num2;
					bool flag4 = num7 > num;
					bool flag5 = Config.PropCull.Value && !flag && (flag3 || flag2);
					bool flag6 = Config.RigidbodySleep.Value && !flag && (flag3 || flag2);
					bool off = Config.ShadowCull.Value && !flag && (flag4 || flag2);
					bool pause = Config.ParticleCull.Value && !flag && (flag4 || flag2);
					if (flag6 && IsMoving(trackedProp.Body))
					{
						flag6 = false;
					}
					ApplyCull(trackedProp, flag5);
					ApplySleep(trackedProp, flag6);
					ApplyShadows(trackedProp, off);
					ApplyParticles(trackedProp, pause);
					if (flag5)
					{
						num5++;
					}
					else
					{
						num4++;
					}
				}
			}
			_culledCount = num5;
		}

		private float DistanceSq(TrackedProp prop)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Vector3 val = prop.Body.worldCenterOfMass - _viewer;
				return ((Vector3)(ref val)).sqrMagnitude;
			}
			catch
			{
				return float.MaxValue;
			}
		}

		private static bool IsMoving(Rigidbody rb)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Vector3 val = rb.velocity;
				int result;
				if (!(((Vector3)(ref val)).sqrMagnitude > 0.05f))
				{
					val = rb.angularVelocity;
					result = ((((Vector3)(ref val)).sqrMagnitude > 0.05f) ? 1 : 0);
				}
				else
				{
					result = 1;
				}
				return (byte)result != 0;
			}
			catch
			{
				return true;
			}
		}

		private static void ApplyCull(TrackedProp prop, bool cull)
		{
			if (prop.Culled == cull)
			{
				return;
			}
			for (int i = 0; i < prop.Renderers.Length; i++)
			{
				Renderer val = prop.Renderers[i];
				if (!((Object)(object)val == (Object)null))
				{
					if (cull)
					{
						val.enabled = false;
					}
					else
					{
						val.enabled = prop.OriginalRendererEnabled[i];
					}
				}
			}
			prop.Culled = cull;
		}

		private static void ApplySleep(TrackedProp prop, bool sleep)
		{
			Rigidbody body = prop.Body;
			if ((Object)(object)body == (Object)null)
			{
				return;
			}
			try
			{
				if (sleep)
				{
					if (!prop.StoredKinematic)
					{
						prop.WasKinematic = body.isKinematic;
						prop.StoredKinematic = true;
					}
					if (!body.IsSleeping())
					{
						body.Sleep();
					}
				}
				else if (prop.StoredKinematic)
				{
					if (!prop.WasKinematic)
					{
						body.WakeUp();
					}
					prop.StoredKinematic = false;
				}
			}
			catch
			{
			}
		}

		private static void ApplyShadows(TrackedProp prop, bool off)
		{
			if (prop.ShadowsOff == off)
			{
				return;
			}
			for (int i = 0; i < prop.Renderers.Length; i++)
			{
				Renderer val = prop.Renderers[i];
				if (!((Object)(object)val == (Object)null))
				{
					if (off)
					{
						val.shadowCastingMode = (ShadowCastingMode)0;
					}
					else
					{
						val.shadowCastingMode = prop.OriginalShadows[i];
					}
				}
			}
			prop.ShadowsOff = off;
		}

		private static void ApplyParticles(TrackedProp prop, bool pause)
		{
			if (prop.Particles == null || prop.Particles.Length == 0 || prop.ParticlesPaused == pause)
			{
				return;
			}
			for (int i = 0; i < prop.Particles.Length; i++)
			{
				ParticleSystem val = prop.Particles[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					if (pause)
					{
						val.Pause(true);
					}
					else
					{
						val.Play(true);
					}
				}
				catch
				{
				}
			}
			prop.ParticlesPaused = pause;
		}

		private static bool IsProtectedName(string name)
		{
			string text = name.ToLowerInvariant();
			if (!text.Contains("rigmanager") && !text.Contains("[rigmanager]") && !text.Contains("playerrep") && !text.Contains("controller") && !text.Contains("hand") && !text.Contains("pelvis") && !text.Contains("avatar"))
			{
				return text.Contains("spectator");
			}
			return true;
		}

		private static bool IsUnderPlayerHierarchy(Transform t)
		{
			int num = 0;
			while ((Object)(object)t != (Object)null && num < 12)
			{
				string text = (((Object)t).name ?? string.Empty).ToLowerInvariant();
				if (text.Contains("rigmanager") || text.Contains("[rigmanager]") || text.Contains("playerrep"))
				{
					return true;
				}
				t = t.parent;
				num++;
			}
			return false;
		}

		public void RestoreAll()
		{
			foreach (TrackedProp value in _byId.Values)
			{
				if (value != null)
				{
					ApplyCull(value, cull: false);
					ApplyShadows(value, off: false);
					ApplyParticles(value, pause: false);
					ApplySleep(value, sleep: false);
				}
			}
			for (int i = 0; i < _props.Count; i++)
			{
				TrackedProp trackedProp = _props[i];
				if (trackedProp != null)
				{
					ApplyCull(trackedProp, cull: false);
					ApplyShadows(trackedProp, off: false);
					ApplyParticles(trackedProp, pause: false);
					ApplySleep(trackedProp, sleep: false);
				}
			}
		}
	}
	public sealed class QualityOptimizer
	{
		private float _appliedShadowDistance = -1f;

		private int _appliedPixelLights = -1;

		public void ApplyStaticTweaks()
		{
			if (!Config.Enabled.Value || !Config.QualityTweaks.Value)
			{
				return;
			}
			try
			{
				QualitySettings.vSyncCount = 0;
				Application.targetFrameRate = -1;
				Application.backgroundLoadingPriority = (ThreadPriority)0;
				QualitySettings.asyncUploadTimeSlice = 2;
				QualitySettings.asyncUploadBufferSize = 32;
				QualitySettings.asyncUploadPersistentBuffer = true;
				QualitySettings.particleRaycastBudget = 128;
				QualitySettings.shadowCascades = 1;
				QualitySettings.softParticles = false;
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Quality static tweaks failed: " + ex.Message);
			}
			if (!Config.IncrementalGc.Value)
			{
				return;
			}
			try
			{
				GarbageCollector.GCMode = (Mode)1;
				GarbageCollector.incrementalTimeSliceNanoseconds = 2000000uL;
			}
			catch (Exception ex2)
			{
				Core.Log.Warning("Incremental GC unavailable: " + ex2.Message);
			}
		}

		public void ApplyOcclusion()
		{
			if (!Config.Enabled.Value || !Config.OcclusionCulling.Value)
			{
				return;
			}
			try
			{
				Il2CppReferenceArray<Camera> allCameras = Camera.allCameras;
				for (int i = 0; i < ((Il2CppArrayBase<Camera>)(object)allCameras).Length; i++)
				{
					Camera val = ((Il2CppArrayBase<Camera>)(object)allCameras)[i];
					if ((Object)(object)val != (Object)null && ((Behaviour)val).enabled)
					{
						val.useOcclusionCulling = true;
					}
				}
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Occlusion tweak failed: " + ex.Message);
			}
		}

		public void TickAdaptive(float fps, float playerScale)
		{
			if (!Config.Enabled.Value || !Config.QualityTweaks.Value)
			{
				return;
			}
			float num = Mathf.Max(30f, Config.TargetFps.Value);
			float num2 = 1f;
			if (Config.AdaptiveQuality.Value)
			{
				num2 = Mathf.Clamp(num / Mathf.Max(fps, 1f), 0.65f, 1.75f);
				num2 *= Mathf.Lerp(1f, 1.35f, Mathf.Clamp01((playerScale - 8f) / 20f));
			}
			float num3 = Mathf.Clamp(55f / num2, 12f, 70f);
			int num4 = ((num2 > 1.25f) ? 1 : ((num2 > 1.05f) ? 2 : 4));
			if (Mathf.Abs(num3 - _appliedShadowDistance) > 0.5f)
			{
				try
				{
					QualitySettings.shadowDistance = num3;
					_appliedShadowDistance = num3;
				}
				catch
				{
				}
			}
			if (num4 == _appliedPixelLights)
			{
				return;
			}
			try
			{
				QualitySettings.pixelLightCount = num4;
				_appliedPixelLights = num4;
			}
			catch
			{
			}
		}

		public void SoftMemoryClean()
		{
			try
			{
				Resources.UnloadUnusedAssets();
				GC.Collect(0);
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Memory clean failed: " + ex.Message);
			}
		}
	}
}