Decompiled source of Performance Traffic Control v1.0.0

BepInEx/plugins/PerformanceTrafficControl/PerformanceTrafficControl.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Enemies;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using PerformanceTrafficControl.Api;
using PerformanceTrafficControl.Core;
using PerformanceTrafficControl.Modules;
using PerformanceTrafficControl.Optimization;
using PerformanceTrafficControl.Performance;
using UnityEngine;
using UnityEngine.Rendering;
using WindVolume;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Performance Traffic Control")]
[assembly: AssemblyProduct("Performance Traffic Control")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.1.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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;
		}
	}
}
namespace PerformanceTrafficControl.Performance
{
	internal sealed class AdaptivePerformanceModule : TrafficControlModuleBase
	{
		private const float SampleInterval = 0.25f;

		private const float InitialWarmupSeconds = 5f;

		private const float EnvironmentCheckInterval = 10f;

		private const float MaximumValidSampleSeconds = 1.5f;

		private const float MinimumValidFps = 5f;

		private const float MaximumValidFps = 500f;

		private const float FpsSmoothingAlpha = 0.35f;

		private const float DefaultHighTriggerRatio = 0.85f;

		private const float DefaultCriticalTriggerRatio = 0.75f;

		private const float HighRecoveryRatio = 0.9f;

		private const float CriticalRecoveryRatio = 0.86f;

		private const int HighEnterSampleCount = 6;

		private const int CriticalEnterSampleCount = 3;

		private const int HighRecoverySampleCount = 32;

		private const int CriticalRecoverySampleCount = 20;

		private const int BaselineSamplesPerWindow = 8;

		private const int BaselineWindowCapacity = 20;

		private const int MinimumBaselineWindowCount = 12;

		private const float StableWindowLowerRatio = 0.82f;

		private const float StableWindowUpperRatio = 1.18f;

		private const float BaselinePercentile = 0.65f;

		private const float BaselinePersistInterval = 60f;

		private const float AudioStatePruneInterval = 10f;

		private const float DiagnosticInterval = 30f;

		private readonly float[] _stableBaselineWindows = new float[20];

		private readonly float[] _baselineSortScratch = new float[20];

		private TrafficControlConfig? _config;

		private bool _profileInitialized;

		private bool _sampleAnchorSet;

		private string _environmentFingerprint = string.Empty;

		private float _monitoringStartsAt;

		private float _nextSampleAt;

		private float _nextEnvironmentCheckAt;

		private float _lastSampleRealtime;

		private int _lastSampleFrame;

		private float _latestWindowFps;

		private float _smoothedFps;

		private float _baselineFps;

		private float _lastPersistedBaselineFps;

		private float _nextBaselinePersistAt;

		private float _baselineWindowFpsSum;

		private float _baselineWindowMinFps;

		private float _baselineWindowMaxFps;

		private int _baselineWindowSampleCount;

		private int _stableBaselineWindowCount;

		private int _stableBaselineWindowWriteIndex;

		private int _highPressureSamples;

		private int _criticalPressureSamples;

		private int _recoverySamples;

		private float _nextAudioStatePruneAt;

		private float _nextDiagnosticAt;

		public override string Name => "Adaptive performance pressure";

		private bool AdaptivePerformanceEnabled => _config?.AdaptivePerformanceEnabled.Value ?? true;

		private float HighTriggerRatio
		{
			get
			{
				float num = _config?.HighTriggerRatio.Value ?? 0.85f;
				if (!float.IsNaN(num))
				{
					return Mathf.Clamp(num, 0.5f, 0.95f);
				}
				return 0.85f;
			}
		}

		private float CriticalTriggerRatio
		{
			get
			{
				float num = _config?.CriticalTriggerRatio.Value ?? 0.75f;
				if (!float.IsNaN(num))
				{
					return Mathf.Clamp(num, 0.3f, HighTriggerRatio - 0.05f);
				}
				return 0.75f;
			}
		}

		public override void Initialize(TrafficControlModuleContext context)
		{
			_config = context.Config;
			_config.AdaptivePerformanceEnabled.SettingChanged += delegate
			{
				HandleAdaptiveSettingsChanged();
			};
			_config.HighTriggerRatio.SettingChanged += delegate
			{
				ResetPressureCounters();
			};
			_config.CriticalTriggerRatio.SettingChanged += delegate
			{
				ResetPressureCounters();
			};
			_config.ResetLearnedBaseline.SettingChanged += delegate
			{
				HandleResetRequested();
			};
			HandleResetRequested();
		}

		public override void Tick(float now, bool isInLevel)
		{
			if (!isInLevel || !AdaptivePerformanceEnabled)
			{
				SetLevel(PerformancePressureLevel.Normal, isInLevel ? "adaptive performance disabled" : "outside an active level");
				SuspendSampling();
			}
			else if (!_profileInitialized)
			{
				InitializeEnvironmentProfile(now);
			}
			else if (_monitoringStartsAt <= 0f)
			{
				_monitoringStartsAt = now + 5f;
				_nextSampleAt = _monitoringStartsAt;
			}
			else
			{
				if (now < _monitoringStartsAt || now < _nextSampleAt)
				{
					return;
				}
				_nextSampleAt = now + 0.25f;
				if (!Application.isFocused)
				{
					ResetSampleAnchor();
					ResetPressureCounters();
					return;
				}
				if (now >= _nextEnvironmentCheckAt)
				{
					_nextEnvironmentCheckAt = now + 10f;
					string text = BuildEnvironmentFingerprint();
					if (!string.Equals(text, _environmentFingerprint, StringComparison.Ordinal))
					{
						InitializeEnvironmentProfile(now, text);
						return;
					}
				}
				SamplePerformance(now);
				RunMaintenance(now);
			}
		}

		public override void OnLevelEntered()
		{
			_monitoringStartsAt = 0f;
			_nextSampleAt = 0f;
			_nextDiagnosticAt = 0f;
			_nextAudioStatePruneAt = 0f;
			ResetSampleAnchor();
			ResetPressureCounters();
			ResetBaselineAccumulator();
		}

		public override void OnLevelExited()
		{
			PersistLearnedProfile(float.MaxValue, force: true);
			SetLevel(PerformancePressureLevel.Normal, "level exited");
			SuspendSampling();
			ResetPressureCounters();
			ResetBaselineAccumulator();
			TrafficControlPerformance.ResetForLevelExit();
			TrafficControlPerformance.UpdateMeasurements(0f, _baselineFps);
		}

		private void SamplePerformance(float now)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			int frameCount = Time.frameCount;
			if (!_sampleAnchorSet)
			{
				_sampleAnchorSet = true;
				_lastSampleRealtime = realtimeSinceStartup;
				_lastSampleFrame = frameCount;
				return;
			}
			float num = realtimeSinceStartup - _lastSampleRealtime;
			int num2 = frameCount - _lastSampleFrame;
			_lastSampleRealtime = realtimeSinceStartup;
			_lastSampleFrame = frameCount;
			if (num <= 0.05f || num > 1.5f || num2 <= 0)
			{
				ResetPressureCounters();
				ResetBaselineAccumulator();
				return;
			}
			float num3 = (float)num2 / num;
			if (num3 < 5f || num3 > 500f)
			{
				ResetPressureCounters();
				ResetBaselineAccumulator();
				return;
			}
			_latestWindowFps = num3;
			_smoothedFps = ((_smoothedFps <= 0.01f) ? num3 : Mathf.Lerp(_smoothedFps, num3, 0.35f));
			TrafficControlPerformance.UpdateMeasurements(_smoothedFps, _baselineFps);
			AccumulateBaselineSample(num3, now);
			if (_baselineFps > 0f)
			{
				EvaluatePressure();
			}
		}

		private void EvaluatePressure()
		{
			float num = _baselineFps * HighTriggerRatio;
			float num2 = _baselineFps * CriticalTriggerRatio;
			_highPressureSamples = ((_smoothedFps < num) ? (_highPressureSamples + 1) : 0);
			_criticalPressureSamples = ((_smoothedFps < num2) ? (_criticalPressureSamples + 1) : 0);
			switch (TrafficControlPerformance.Level)
			{
			case PerformancePressureLevel.Normal:
				_recoverySamples = 0;
				if (_criticalPressureSamples >= 3)
				{
					SetLevel(PerformancePressureLevel.Critical, "FPS stayed below the learned critical ratio");
				}
				else if (_highPressureSamples >= 6)
				{
					SetLevel(PerformancePressureLevel.High, "FPS stayed below the learned high ratio");
				}
				break;
			case PerformancePressureLevel.High:
				if (_criticalPressureSamples >= 3)
				{
					SetLevel(PerformancePressureLevel.Critical, "FPS stayed below the learned critical ratio");
					break;
				}
				_recoverySamples = ((_smoothedFps >= _baselineFps * 0.9f) ? (_recoverySamples + 1) : 0);
				if (_recoverySamples >= 32)
				{
					SetLevel(PerformancePressureLevel.Normal, "FPS recovered toward the learned baseline");
				}
				break;
			case PerformancePressureLevel.Critical:
				_recoverySamples = ((_smoothedFps >= _baselineFps * 0.86f) ? (_recoverySamples + 1) : 0);
				if (_recoverySamples >= 20)
				{
					SetLevel(PerformancePressureLevel.High, "FPS recovered from critical pressure");
				}
				break;
			}
		}

		private void AccumulateBaselineSample(float windowFps, float now)
		{
			if (_baselineWindowSampleCount == 0)
			{
				_baselineWindowMinFps = windowFps;
				_baselineWindowMaxFps = windowFps;
			}
			else
			{
				_baselineWindowMinFps = Mathf.Min(_baselineWindowMinFps, windowFps);
				_baselineWindowMaxFps = Mathf.Max(_baselineWindowMaxFps, windowFps);
			}
			_baselineWindowFpsSum += windowFps;
			_baselineWindowSampleCount++;
			if (_baselineWindowSampleCount < 8)
			{
				return;
			}
			float num = _baselineWindowFpsSum / (float)_baselineWindowSampleCount;
			bool num2 = _baselineWindowMinFps >= num * 0.82f && _baselineWindowMaxFps <= num * 1.18f;
			ResetBaselineAccumulator();
			if (!num2)
			{
				return;
			}
			_stableBaselineWindows[_stableBaselineWindowWriteIndex] = num;
			_stableBaselineWindowWriteIndex = (_stableBaselineWindowWriteIndex + 1) % 20;
			_stableBaselineWindowCount = Math.Min(20, _stableBaselineWindowCount + 1);
			if (_stableBaselineWindowCount >= 12)
			{
				float num3 = CalculateBaselineCandidate();
				if (_baselineFps <= 0f)
				{
					_baselineFps = num3;
					TrafficControlPerformance.UpdateMeasurements(_smoothedFps, _baselineFps);
					PersistLearnedProfile(now, force: true);
					TrafficControlLog.Info($"[PTC_PERF] Learned initial baseline {_baselineFps:0.0} FPS. " + $"High<{_baselineFps * HighTriggerRatio:0.0} Critical<{_baselineFps * CriticalTriggerRatio:0.0}.");
				}
				else if (!(num3 <= _baselineFps * 1.01f))
				{
					float num4 = Mathf.Max(0.5f, _baselineFps * 0.005f);
					_baselineFps = Mathf.Min(num3, _baselineFps + num4);
					TrafficControlPerformance.UpdateMeasurements(_smoothedFps, _baselineFps);
					PersistLearnedProfile(now, force: false);
				}
			}
		}

		private float CalculateBaselineCandidate()
		{
			for (int i = 0; i < _stableBaselineWindowCount; i++)
			{
				_baselineSortScratch[i] = _stableBaselineWindows[i];
			}
			Array.Sort(_baselineSortScratch, 0, _stableBaselineWindowCount);
			int num = Mathf.RoundToInt((float)(_stableBaselineWindowCount - 1) * 0.65f);
			return Mathf.Clamp(_baselineSortScratch[num], 5f, 500f);
		}

		private void InitializeEnvironmentProfile(float now, string? fingerprint = null)
		{
			if (fingerprint == null)
			{
				fingerprint = BuildEnvironmentFingerprint();
			}
			string b = _config?.LearnedProfileFingerprint.Value ?? string.Empty;
			float num = _config?.LearnedBaselineFps.Value ?? 0f;
			bool flag = string.Equals(fingerprint, b, StringComparison.Ordinal) && !float.IsNaN(num) && num >= 5f;
			_environmentFingerprint = fingerprint;
			_profileInitialized = true;
			_baselineFps = (flag ? Mathf.Clamp(num, 5f, 500f) : 0f);
			_lastPersistedBaselineFps = _baselineFps;
			_latestWindowFps = 0f;
			_smoothedFps = 0f;
			_monitoringStartsAt = now + 5f;
			_nextSampleAt = _monitoringStartsAt;
			_nextEnvironmentCheckAt = now + 10f;
			_nextBaselinePersistAt = now + 60f;
			ResetSampleAnchor();
			ResetPressureCounters();
			ClearBaselineLearningState();
			SetLevel(PerformancePressureLevel.Normal, flag ? "performance profile initialized" : "graphics profile changed; learning a new baseline");
			TrafficControlPerformance.UpdateMeasurements(0f, _baselineFps);
			if (!flag && _config != null)
			{
				_config.LearnedBaselineFps.Value = 0f;
				_config.LearnedProfileFingerprint.Value = fingerprint;
			}
			TrafficControlLog.Info(flag ? $"[PTC_PERF] Loaded baseline {_baselineFps:0.0} FPS; sampling at 4 Hz." : "[PTC_PERF] No matching graphics profile; learning a baseline after warmup.");
		}

		private static string BuildEnvironmentFingerprint()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return $"GPU={SystemInfo.graphicsDeviceName}|Screen={Screen.width}x{Screen.height}|" + $"Display={Screen.currentResolution}|Fullscreen={Screen.fullScreen}|" + $"Quality={QualitySettings.GetQualityLevel()}|VSync={QualitySettings.vSyncCount}|" + $"Target={Application.targetFrameRate}";
			}
			catch (Exception ex)
			{
				TrafficControlLog.InfoRateLimited("Performance:EnvironmentFingerprint", "[PTC_PERF] Could not read graphics profile: " + ex.Message, 30f);
				return "GraphicsEnvironmentUnavailable";
			}
		}

		private void PersistLearnedProfile(float now, bool force)
		{
			if (_config == null || !_profileInitialized || _baselineFps < 5f)
			{
				return;
			}
			bool flag = _lastPersistedBaselineFps <= 0f || Mathf.Abs(_baselineFps - _lastPersistedBaselineFps) >= Mathf.Max(2f, _lastPersistedBaselineFps * 0.02f);
			if (force || (!(now < _nextBaselinePersistAt) && flag))
			{
				if (!string.Equals(_config.LearnedProfileFingerprint.Value, _environmentFingerprint, StringComparison.Ordinal))
				{
					_config.LearnedProfileFingerprint.Value = _environmentFingerprint;
				}
				if (Mathf.Abs(_config.LearnedBaselineFps.Value - _baselineFps) >= 0.05f)
				{
					_config.LearnedBaselineFps.Value = _baselineFps;
				}
				_lastPersistedBaselineFps = _baselineFps;
				_nextBaselinePersistAt = now + 60f;
			}
		}

		private void RunMaintenance(float now)
		{
			if (now >= _nextAudioStatePruneAt)
			{
				_nextAudioStatePruneAt = now + 10f;
				TrafficControlPerformance.PruneAudioState(now, 10f);
			}
			TrafficControlConfig? config = _config;
			if (config != null && config.PerformanceDiagnosticsEnabled.Value && !(now < _nextDiagnosticAt))
			{
				_nextDiagnosticAt = now + 30f;
				float num = Mathf.Clamp01((float)_stableBaselineWindowCount / 12f) * 100f;
				TrafficControlLog.Info($"[PTC_PERF] Level={TrafficControlPerformance.Level} FPS={_smoothedFps:0.0} " + $"WindowFPS={_latestWindowFps:0.0} Baseline={_baselineFps:0.0} Confidence={num:0}% " + $"DeniedPhysics={TrafficControlPerformance.DeniedPhysicsQueries} " + $"DeniedVisual={TrafficControlPerformance.DeniedVisualSpawns} " + $"DeniedAudio={TrafficControlPerformance.DeniedAudioEvents}.");
			}
		}

		private void HandleAdaptiveSettingsChanged()
		{
			ResetPressureCounters();
			SuspendSampling();
			if (!AdaptivePerformanceEnabled)
			{
				SetLevel(PerformancePressureLevel.Normal, "disabled by config");
			}
		}

		private void HandleResetRequested()
		{
			TrafficControlConfig? config = _config;
			if (config != null && config.ResetLearnedBaseline.Value)
			{
				ClearLearnedProfile("config reset requested");
				_config.ResetLearnedBaseline.Value = false;
			}
		}

		private void ClearLearnedProfile(string reason)
		{
			_profileInitialized = false;
			_environmentFingerprint = string.Empty;
			_baselineFps = 0f;
			_lastPersistedBaselineFps = 0f;
			_latestWindowFps = 0f;
			_smoothedFps = 0f;
			SuspendSampling();
			ResetPressureCounters();
			ClearBaselineLearningState();
			if (_config != null)
			{
				_config.LearnedBaselineFps.Value = 0f;
				_config.LearnedProfileFingerprint.Value = string.Empty;
			}
			SetLevel(PerformancePressureLevel.Normal, reason);
			TrafficControlPerformance.UpdateMeasurements(0f, 0f);
			TrafficControlLog.Info("[PTC_PERF] Cleared learned baseline. Reason=" + reason + ".");
		}

		private void SuspendSampling()
		{
			_monitoringStartsAt = 0f;
			_nextSampleAt = 0f;
			ResetSampleAnchor();
			ResetBaselineAccumulator();
		}

		private void ResetSampleAnchor()
		{
			_sampleAnchorSet = false;
			_lastSampleRealtime = 0f;
			_lastSampleFrame = 0;
		}

		private void ResetPressureCounters()
		{
			_highPressureSamples = 0;
			_criticalPressureSamples = 0;
			_recoverySamples = 0;
		}

		private void ResetBaselineAccumulator()
		{
			_baselineWindowFpsSum = 0f;
			_baselineWindowMinFps = 0f;
			_baselineWindowMaxFps = 0f;
			_baselineWindowSampleCount = 0;
		}

		private void ClearBaselineLearningState()
		{
			ResetBaselineAccumulator();
			Array.Clear(_stableBaselineWindows, 0, _stableBaselineWindows.Length);
			Array.Clear(_baselineSortScratch, 0, _baselineSortScratch.Length);
			_stableBaselineWindowCount = 0;
			_stableBaselineWindowWriteIndex = 0;
		}

		private void SetLevel(PerformancePressureLevel level, string reason)
		{
			if (TrafficControlPerformance.Level != level)
			{
				PerformancePressureLevel level2 = TrafficControlPerformance.Level;
				ResetPressureCounters();
				TrafficControlPerformance.UpdateMeasurements(_smoothedFps, _baselineFps);
				TrafficControlPerformance.SetPressure(level);
				TrafficControlLog.Info($"[PTC_PERF] Pressure {level2} -> {level}. FPS={_smoothedFps:0.0}, " + $"Baseline={_baselineFps:0.0}. Reason={reason}.");
			}
		}
	}
}
namespace PerformanceTrafficControl.Optimization
{
	internal sealed class EnemyVisualOptimizationModule : TrafficControlModuleBase
	{
		public override string Name => "Adaptive enemy visual optimization";

		public override void Initialize(TrafficControlModuleContext context)
		{
			EnemyVisualRuntime.Configure(context.Config);
			context.Harmony.PatchAll(typeof(EnemyVisualPatches));
		}

		public override void OnLevelEntered()
		{
			EnemyVisualRuntime.OnLevelEntered();
		}

		public override void OnLevelExited()
		{
			EnemyVisualRuntime.OnLevelExited();
		}
	}
	internal static class EnemyVisualRuntime
	{
		private sealed class EnemyVisualState
		{
			private readonly RendererEntry[] _renderers;

			private bool _shadowsSuppressed;

			internal EnemyAgent Enemy { get; set; }

			internal bool Alive { get; set; }

			internal bool Active { get; set; }

			private EnemyVisualState(EnemyAgent enemy, RendererEntry[] renderers)
			{
				Enemy = enemy;
				_renderers = renderers;
				Alive = IsEnemyAlive(enemy);
			}

			internal static EnemyVisualState Capture(EnemyAgent enemy)
			{
				try
				{
					Il2CppArrayBase<Renderer> componentsInChildren = ((Component)enemy).GetComponentsInChildren<Renderer>(true);
					RendererEntry[] array = new RendererEntry[componentsInChildren.Length];
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						array[i] = new RendererEntry(componentsInChildren[i]);
					}
					return new EnemyVisualState(enemy, array);
				}
				catch (Exception ex)
				{
					TrafficControlLog.InfoRateLimited("EnemyVisuals:Capture", "[EnemyVisuals] Failed to cache enemy renderers: " + ex.Message, 2f);
					return new EnemyVisualState(enemy, Array.Empty<RendererEntry>());
				}
			}

			internal void SuppressShadows()
			{
				//IL_001e: 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)
				for (int i = 0; i < _renderers.Length; i++)
				{
					RendererEntry rendererEntry = _renderers[i];
					Renderer renderer = rendererEntry.Renderer;
					if ((Object)(object)renderer != (Object)null && (int)renderer.shadowCastingMode != 0)
					{
						if (!_shadowsSuppressed)
						{
							rendererEntry.ShadowMode = renderer.shadowCastingMode;
						}
						renderer.shadowCastingMode = (ShadowCastingMode)0;
					}
				}
				_shadowsSuppressed = true;
			}

			internal void RestoreShadows()
			{
				//IL_002a: 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_003e: Unknown result type (might be due to invalid IL or missing references)
				if (!_shadowsSuppressed)
				{
					return;
				}
				for (int i = 0; i < _renderers.Length; i++)
				{
					RendererEntry rendererEntry = _renderers[i];
					if ((Object)(object)rendererEntry.Renderer != (Object)null && rendererEntry.Renderer.shadowCastingMode != rendererEntry.ShadowMode)
					{
						rendererEntry.Renderer.shadowCastingMode = rendererEntry.ShadowMode;
					}
				}
				_shadowsSuppressed = false;
			}
		}

		private sealed class RagdollState
		{
			internal ES_Dead DeadState { get; }

			internal LinkedListNode<ulong> Node { get; }

			internal RagdollState(ES_Dead deadState, LinkedListNode<ulong> node)
			{
				DeadState = deadState;
				Node = node;
			}
		}

		private sealed class RendererEntry
		{
			internal Renderer Renderer { get; }

			internal ShadowCastingMode ShadowMode { get; set; }

			internal RendererEntry(Renderer renderer)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				Renderer = renderer;
				ShadowMode = (ShadowCastingMode)(((Object)(object)renderer != (Object)null) ? ((int)renderer.shadowCastingMode) : 0);
			}
		}

		private static readonly Dictionary<ulong, EnemyVisualState> Enemies = new Dictionary<ulong, EnemyVisualState>();

		private static readonly Dictionary<ulong, RagdollState> Ragdolls = new Dictionary<ulong, RagdollState>();

		private static readonly LinkedList<ulong> RagdollOrder = new LinkedList<ulong>();

		private static TrafficControlConfig? s_config;

		private static bool s_levelActive;

		private static bool s_pressureActive;

		private static int s_activeEnemyCount;

		internal static bool Enabled => s_config?.EnemyVisualOptimizationEnabled.Value ?? false;

		internal static int ActiveEnemyCount => s_activeEnemyCount;

		internal static int RagdollCount => Ragdolls.Count;

		private static int MaximumRagdolls => Math.Max(0, s_config?.MaximumRagdollsUnderPressure.Value ?? 12);

		internal static void Configure(TrafficControlConfig config)
		{
			s_config = config;
			TrafficControlPerformance.PressureChanged += OnPressureChanged;
			config.EnemyVisualOptimizationEnabled.SettingChanged += delegate
			{
				OnEnabledSettingChanged();
			};
			config.MaximumRagdollsUnderPressure.SettingChanged += delegate
			{
				ReapplyPressureSettings();
			};
			config.CorpseDecaySecondsUnderPressure.SettingChanged += delegate
			{
				ReapplyPressureSettings();
			};
		}

		internal static void OnLevelEntered()
		{
			s_levelActive = true;
			UpdatePressureMode();
		}

		internal static void OnLevelExited()
		{
			s_levelActive = false;
			s_pressureActive = false;
			RestoreAllShadows();
			Enemies.Clear();
			Ragdolls.Clear();
			RagdollOrder.Clear();
			s_activeEnemyCount = 0;
		}

		internal static void RegisterEnemy(EnemyAgent? enemy)
		{
			if (!Enabled || (Object)(object)enemy == (Object)null)
			{
				return;
			}
			ulong enemyKey = GetEnemyKey(enemy);
			if (enemyKey != 0L)
			{
				if (!Enemies.TryGetValue(enemyKey, out EnemyVisualState value))
				{
					value = EnemyVisualState.Capture(enemy);
					Enemies[enemyKey] = value;
				}
				else
				{
					value.Enemy = enemy;
				}
				SetActiveState(value, IsActiveEnemy(enemy));
				if (s_pressureActive)
				{
					value.SuppressShadows();
				}
			}
		}

		internal static void OnModeChanged(EnemyAI? ai)
		{
			RegisterEnemy((ai != null) ? ai.m_enemyAgent : null);
		}

		internal static void OnEnemyDamaged(EnemyAgent? enemy)
		{
			if (Enabled && !((Object)(object)enemy == (Object)null) && IsEnemyAlive(enemy))
			{
				EnemyVisualState orRegister = GetOrRegister(enemy);
				if (orRegister != null)
				{
					SetActiveState(orRegister, active: true);
				}
			}
		}

		internal static void OnEnemyDead(EnemyAgent? enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				return;
			}
			EnemyVisualState orRegister = GetOrRegister(enemy);
			if (orRegister != null)
			{
				orRegister.Alive = false;
				SetActiveState(orRegister, active: false);
				if (s_pressureActive)
				{
					orRegister.SuppressShadows();
				}
			}
		}

		internal static void OnEnemyDespawned(EnemyAgent? enemy)
		{
			ulong enemyKey = GetEnemyKey(enemy);
			if (enemyKey == 0L)
			{
				return;
			}
			if (Enemies.TryGetValue(enemyKey, out EnemyVisualState value))
			{
				if (value.Active)
				{
					s_activeEnemyCount = Math.Max(0, s_activeEnemyCount - 1);
				}
				value.RestoreShadows();
				Enemies.Remove(enemyKey);
			}
			RemoveRagdoll(enemyKey);
		}

		internal static void AdjustDecayDuration(ref float duration)
		{
			if (s_pressureActive)
			{
				float num = s_config?.CorpseDecaySecondsUnderPressure.Value ?? 0.01f;
				duration = (float.IsNaN(num) ? 0.01f : Mathf.Clamp(num, 0.01f, 30f));
			}
		}

		internal static void OnDeadStateEntered(ES_Dead? deadState)
		{
			if (s_pressureActive)
			{
				GetOrRegister(TryGetDeadEnemy(deadState))?.SuppressShadows();
			}
		}

		internal static void OnRagdollStateChanged(ES_Dead? deadState, bool enabled)
		{
			if (!Enabled || deadState == null)
			{
				return;
			}
			ulong enemyKey = GetEnemyKey(TryGetDeadEnemy(deadState));
			if (enemyKey == 0L)
			{
				return;
			}
			if (!enabled)
			{
				RemoveRagdoll(enemyKey);
				return;
			}
			RemoveRagdoll(enemyKey);
			LinkedListNode<ulong> node = RagdollOrder.AddLast(enemyKey);
			Ragdolls[enemyKey] = new RagdollState(deadState, node);
			if (s_pressureActive)
			{
				TrimRagdolls(MaximumRagdolls, disableRagdoll: true);
			}
			else
			{
				TrimRagdolls(Math.Max(64, MaximumRagdolls * 4), disableRagdoll: false);
			}
		}

		private static void OnPressureChanged(PerformancePressureLevel previous, PerformancePressureLevel current)
		{
			UpdatePressureMode();
		}

		private static void OnEnabledSettingChanged()
		{
			if (!Enabled)
			{
				s_pressureActive = false;
				RestoreAllShadows();
				Enemies.Clear();
				Ragdolls.Clear();
				RagdollOrder.Clear();
				s_activeEnemyCount = 0;
			}
			else
			{
				UpdatePressureMode();
			}
		}

		private static void ReapplyPressureSettings()
		{
			if (s_pressureActive)
			{
				TrimRagdolls(MaximumRagdolls, disableRagdoll: true);
			}
		}

		private static void UpdatePressureMode()
		{
			bool flag = Enabled && s_levelActive && TrafficControlPerformance.IsHighOrWorse;
			if (flag == s_pressureActive)
			{
				return;
			}
			s_pressureActive = flag;
			if (flag)
			{
				foreach (EnemyVisualState value in Enemies.Values)
				{
					value.SuppressShadows();
				}
				TrimRagdolls(MaximumRagdolls, disableRagdoll: true);
				TrafficControlLog.Info($"[EnemyVisuals] Pressure mode enabled. Level={TrafficControlPerformance.Level} " + $"FPS={TrafficControlPerformance.SmoothedFps:0.0}/{TrafficControlPerformance.LearnedBaselineFps:0.0} " + $"ActiveEnemies={s_activeEnemyCount} Ragdolls={Ragdolls.Count}/{MaximumRagdolls}.");
			}
			else
			{
				RestoreAllShadows();
				TrafficControlLog.Info("[EnemyVisuals] Pressure mode disabled; cached shadow modes restored.");
			}
		}

		private static EnemyVisualState? GetOrRegister(EnemyAgent? enemy)
		{
			if (!Enabled || (Object)(object)enemy == (Object)null)
			{
				return null;
			}
			ulong enemyKey = GetEnemyKey(enemy);
			if (enemyKey == 0L)
			{
				return null;
			}
			if (Enemies.TryGetValue(enemyKey, out EnemyVisualState value))
			{
				value.Enemy = enemy;
				return value;
			}
			value = EnemyVisualState.Capture(enemy);
			Enemies[enemyKey] = value;
			return value;
		}

		private static void SetActiveState(EnemyVisualState state, bool active)
		{
			state.Alive = IsEnemyAlive(state.Enemy);
			active &= state.Alive;
			if (state.Active != active)
			{
				state.Active = active;
				s_activeEnemyCount += (active ? 1 : (-1));
				if (s_activeEnemyCount < 0)
				{
					s_activeEnemyCount = 0;
				}
			}
		}

		private static bool IsActiveEnemy(EnemyAgent enemy)
		{
			//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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if (!IsEnemyAlive(enemy) || (Object)(object)enemy.AI == (Object)null)
			{
				return false;
			}
			try
			{
				AgentMode mode = ((AgentAI)enemy.AI).Mode;
				return (int)mode != 4 && (int)mode > 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsEnemyAlive(EnemyAgent? enemy)
		{
			if ((Object)(object)enemy == (Object)null || !((Agent)enemy).Alive)
			{
				return false;
			}
			try
			{
				return (Object)(object)enemy.Damage != (Object)null && ((Dam_SyncedDamageBase)enemy.Damage).Health > 0f;
			}
			catch
			{
				return true;
			}
		}

		private static ulong GetEnemyKey(EnemyAgent? enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				return 0uL;
			}
			try
			{
				return (uint)((Object)enemy).GetInstanceID();
			}
			catch
			{
				return 0uL;
			}
		}

		private static EnemyAgent? TryGetDeadEnemy(ES_Dead? deadState)
		{
			try
			{
				object result;
				if (deadState == null)
				{
					result = null;
				}
				else
				{
					EnemyRagdollBodyController bodyController = deadState.m_bodyController;
					result = ((bodyController != null) ? bodyController.m_owner : null);
				}
				return (EnemyAgent?)result;
			}
			catch
			{
				return null;
			}
		}

		private static void TrimRagdolls(int maximum, bool disableRagdoll)
		{
			while (Ragdolls.Count > maximum && RagdollOrder.First != null)
			{
				ulong value = RagdollOrder.First.Value;
				if (!Ragdolls.TryGetValue(value, out RagdollState value2))
				{
					RagdollOrder.RemoveFirst();
					continue;
				}
				Ragdolls.Remove(value);
				RagdollOrder.Remove(value2.Node);
				if (!disableRagdoll)
				{
					continue;
				}
				try
				{
					if (value2.DeadState != null)
					{
						value2.DeadState.SetRagdollEnabled(false);
					}
				}
				catch (Exception ex)
				{
					TrafficControlLog.InfoRateLimited("EnemyVisuals:RagdollDisable", "[EnemyVisuals] Failed to disable an expired ragdoll: " + ex.Message, 2f);
				}
			}
		}

		private static void RemoveRagdoll(ulong key)
		{
			if (Ragdolls.TryGetValue(key, out RagdollState value))
			{
				Ragdolls.Remove(key);
				RagdollOrder.Remove(value.Node);
			}
		}

		private static void RestoreAllShadows()
		{
			foreach (EnemyVisualState value in Enemies.Values)
			{
				value.RestoreShadows();
			}
		}
	}
	[HarmonyPatch]
	internal static class EnemyVisualPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAgent), "Setup")]
		private static void EnemyAgentSetupPostfix(EnemyAgent __instance)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.RegisterEnemy(__instance);
			}, "register enemy");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAI), "ModeChange")]
		private static void EnemyAiModeChangePostfix(EnemyAI __instance)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.OnModeChanged(__instance);
			}, "update enemy mode");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAgent), "OnTakeDamage")]
		private static void EnemyAgentTakeDamagePostfix(EnemyAgent __instance)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.OnEnemyDamaged(__instance);
			}, "wake damaged enemy");
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(EnemyAgent), "OnDead")]
		private static void EnemyAgentOnDeadPrefix(EnemyAgent __instance)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.OnEnemyDead(__instance);
			}, "record enemy death");
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(EnemyAgent), "OnDeSpawn")]
		private static void EnemyAgentOnDespawnPrefix(EnemyAgent __instance)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.OnEnemyDespawned(__instance);
			}, "remove despawned enemy");
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ES_Dead), "DecayDelayed")]
		private static void EnemyDecayPrefix(ref float duration)
		{
			EnemyVisualRuntime.AdjustDecayDuration(ref duration);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ES_Dead), "CommonEnter")]
		private static void EnemyDeadEnterPostfix(ES_Dead __instance)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.OnDeadStateEntered(__instance);
			}, "suppress corpse shadows");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ES_Dead), "SetRagdollEnabled")]
		private static void EnemyRagdollPostfix(ES_Dead __instance, bool enabled)
		{
			RunSafe(delegate
			{
				EnemyVisualRuntime.OnRagdollStateChanged(__instance, enabled);
			}, "update ragdoll budget");
		}

		private static void RunSafe(Action action, string operation)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				TrafficControlLog.InfoRateLimited("EnemyVisuals:" + operation, "[EnemyVisuals] Failed to " + operation + ": " + ex.Message, 2f);
			}
		}
	}
	internal sealed class WindVolumeCapacityModule : TrafficControlModuleBase
	{
		public override string Name => "WindVolume capacity guard";

		public override void Initialize(TrafficControlModuleContext context)
		{
			WindVolumeCapacityPatches.Configure(context.Config);
			context.Harmony.PatchAll(typeof(WindVolumeCapacityPatches));
		}
	}
	[HarmonyPatch(typeof(WindVolumeCamera), "UpdateVolume")]
	internal static class WindVolumeCapacityPatches
	{
		private static readonly List<WindVolumeAffector> Suppressed = new List<WindVolumeAffector>();

		private static TrafficControlConfig? s_config;

		private static float s_nextReportAt;

		internal static void Configure(TrafficControlConfig config)
		{
			s_config = config;
		}

		[HarmonyPrefix]
		private static void Prefix()
		{
			Suppressed.Clear();
			TrafficControlConfig? trafficControlConfig = s_config;
			if (trafficControlConfig == null || !trafficControlConfig.WindVolumeCapacityGuardEnabled.Value)
			{
				return;
			}
			HashSet<WindVolumeAffector> instances = WindVolumeAffector.instances;
			if (instances == null)
			{
				return;
			}
			int mAX_AFFECTOR_COUNT = WindVolumeCamera.MAX_AFFECTOR_COUNT;
			if (mAX_AFFECTOR_COUNT <= 0 || instances.Count <= mAX_AFFECTOR_COUNT)
			{
				return;
			}
			int num = 0;
			Enumerator<WindVolumeAffector> enumerator = instances.GetEnumerator();
			while (enumerator.MoveNext())
			{
				WindVolumeAffector current = enumerator.Current;
				if (!((Object)(object)current == (Object)null) && num++ >= mAX_AFFECTOR_COUNT)
				{
					Suppressed.Add(current);
				}
			}
			for (int i = 0; i < Suppressed.Count; i++)
			{
				instances.Remove(Suppressed[i]);
			}
			if (Time.unscaledTime >= s_nextReportAt)
			{
				TrafficControlLog.Warning($"[WindVolumeGuard] Affectors={instances.Count + Suppressed.Count}/{mAX_AFFECTOR_COUNT} " + $"suppressed={Suppressed.Count}.");
				s_nextReportAt = Time.unscaledTime + 30f;
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			HashSet<WindVolumeAffector> instances = WindVolumeAffector.instances;
			if (instances != null)
			{
				for (int i = 0; i < Suppressed.Count; i++)
				{
					WindVolumeAffector val = Suppressed[i];
					if ((Object)(object)val != (Object)null)
					{
						instances.Add(val);
					}
				}
			}
			Suppressed.Clear();
		}
	}
}
namespace PerformanceTrafficControl.Modules
{
	internal interface ITrafficControlModule
	{
		string Name { get; }

		void Initialize(TrafficControlModuleContext context);

		void Tick(float now, bool isInLevel);

		void OnLevelEntered();

		void OnLevelExited();
	}
	internal abstract class TrafficControlModuleBase : ITrafficControlModule
	{
		public abstract string Name { get; }

		public abstract void Initialize(TrafficControlModuleContext context);

		public virtual void Tick(float now, bool isInLevel)
		{
		}

		public virtual void OnLevelEntered()
		{
		}

		public virtual void OnLevelExited()
		{
		}
	}
	internal sealed class TrafficControlModuleContext
	{
		internal Harmony Harmony { get; }

		internal TrafficControlConfig Config { get; }

		internal TrafficControlModuleContext(Harmony harmony, TrafficControlConfig config)
		{
			Harmony = harmony;
			Config = config;
		}
	}
	internal sealed class TrafficControlModuleHost
	{
		private sealed class ModuleSlot
		{
			internal ITrafficControlModule Module { get; }

			internal bool Active { get; set; }

			internal int ConsecutiveFaults { get; set; }

			internal ModuleSlot(ITrafficControlModule module)
			{
				Module = module;
			}
		}

		private readonly List<ModuleSlot> _modules = new List<ModuleSlot>();

		private readonly TrafficControlModuleContext _context;

		internal TrafficControlModuleHost(TrafficControlModuleContext context)
		{
			_context = context;
		}

		internal void Add(ITrafficControlModule module)
		{
			_modules.Add(new ModuleSlot(module));
		}

		internal void Initialize()
		{
			for (int i = 0; i < _modules.Count; i++)
			{
				ModuleSlot moduleSlot = _modules[i];
				try
				{
					moduleSlot.Module.Initialize(_context);
					moduleSlot.Active = true;
					TrafficControlLog.Info("Module initialized: " + moduleSlot.Module.Name + ".");
				}
				catch (Exception exception)
				{
					moduleSlot.Active = false;
					TrafficControlLog.Error("Module initialization failed: " + moduleSlot.Module.Name + ". Other modules will continue.", exception);
				}
			}
		}

		internal void Tick(float now, bool isInLevel)
		{
			for (int i = 0; i < _modules.Count; i++)
			{
				Invoke(_modules[i], delegate(ITrafficControlModule module)
				{
					module.Tick(now, isInLevel);
				}, "tick");
			}
		}

		internal void OnLevelEntered()
		{
			for (int i = 0; i < _modules.Count; i++)
			{
				Invoke(_modules[i], delegate(ITrafficControlModule module)
				{
					module.OnLevelEntered();
				}, "level enter");
			}
		}

		internal void OnLevelExited()
		{
			for (int i = 0; i < _modules.Count; i++)
			{
				Invoke(_modules[i], delegate(ITrafficControlModule module)
				{
					module.OnLevelExited();
				}, "level exit");
			}
			TrafficControlLog.ClearRateLimits();
		}

		private static void Invoke(ModuleSlot slot, Action<ITrafficControlModule> action, string operation)
		{
			if (!slot.Active)
			{
				return;
			}
			try
			{
				action(slot.Module);
				slot.ConsecutiveFaults = 0;
			}
			catch (Exception ex)
			{
				slot.ConsecutiveFaults++;
				TrafficControlLog.InfoRateLimited("ModuleFault:" + slot.Module.Name + ":" + operation, "Module " + slot.Module.Name + " failed during " + operation + ": " + ex.Message, 2f);
				if (slot.ConsecutiveFaults >= 5)
				{
					slot.Active = false;
					TrafficControlLog.Error("Module disabled after repeated " + operation + " failures: " + slot.Module.Name + ".", ex);
				}
			}
		}
	}
}
namespace PerformanceTrafficControl.Core
{
	[BepInPlugin("kain.gtfo.performance.trafficcontrol", "Performance Traffic Control", "0.1.0")]
	public sealed class PerformanceTrafficControlPlugin : BasePlugin
	{
		private TrafficControlModuleHost? _moduleHost;

		private TrafficControlRuntimeDriver? _runtimeDriver;

		private bool _wasInLevel;

		public override void Load()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			TrafficControlLog.Bind(((BasePlugin)this).Log);
			TrafficControlLog.Info("Performance Traffic Control 0.1.0 loading.");
			TrafficControlConfig config = new TrafficControlConfig(((BasePlugin)this).Config);
			Harmony harmony = new Harmony("kain.gtfo.performance.trafficcontrol");
			_moduleHost = new TrafficControlModuleHost(new TrafficControlModuleContext(harmony, config));
			_moduleHost.Add(new AdaptivePerformanceModule());
			_moduleHost.Add(new EnemyVisualOptimizationModule());
			_moduleHost.Add(new WindVolumeCapacityModule());
			_moduleHost.Initialize();
			TrafficControlRuntimeDriver.Plugin = this;
			_runtimeDriver = ((BasePlugin)this).AddComponent<TrafficControlRuntimeDriver>();
			TrafficControlLog.Info("Performance Traffic Control runtime driver registered.");
		}

		internal void OnRuntimeUpdate()
		{
			if (_moduleHost == null)
			{
				return;
			}
			try
			{
				bool flag = IsInLevel();
				if (flag != _wasInLevel)
				{
					_wasInLevel = flag;
					if (flag)
					{
						_moduleHost.OnLevelEntered();
						TrafficControlLog.Info("Level runtime entered.");
					}
					else
					{
						_moduleHost.OnLevelExited();
						TrafficControlLog.Info("Level runtime exited; module state cleared.");
					}
				}
				_moduleHost.Tick(Time.unscaledTime, flag);
			}
			catch (Exception ex)
			{
				TrafficControlLog.InfoRateLimited("RuntimeDriver:Update", "Runtime update failed: " + ex.Message, 2f);
			}
		}

		internal void OnRuntimeDriverDestroyed(TrafficControlRuntimeDriver driver)
		{
			if (!((Object)(object)_runtimeDriver != (Object)(object)driver))
			{
				if (_wasInLevel)
				{
					_moduleHost?.OnLevelExited();
					_wasInLevel = false;
				}
				_runtimeDriver = null;
				TrafficControlRuntimeDriver.Plugin = null;
				TrafficControlLog.Warning("Performance Traffic Control runtime driver was destroyed.");
			}
		}

		private static bool IsInLevel()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			try
			{
				return GameStateManager.IsInExpedition && (int)GameStateManager.CurrentStateName == 10;
			}
			catch
			{
				return false;
			}
		}
	}
	public static class PluginInfo
	{
		public const string Guid = "kain.gtfo.performance.trafficcontrol";

		public const string Name = "Performance Traffic Control";

		public const string Version = "0.1.0";
	}
	internal sealed class TrafficControlConfig
	{
		internal ConfigEntry<bool> AdaptivePerformanceEnabled { get; }

		internal ConfigEntry<float> HighTriggerRatio { get; }

		internal ConfigEntry<float> CriticalTriggerRatio { get; }

		internal ConfigEntry<bool> ResetLearnedBaseline { get; }

		internal ConfigEntry<bool> PerformanceDiagnosticsEnabled { get; }

		internal ConfigEntry<bool> EnemyVisualOptimizationEnabled { get; }

		internal ConfigEntry<int> MaximumRagdollsUnderPressure { get; }

		internal ConfigEntry<float> CorpseDecaySecondsUnderPressure { get; }

		internal ConfigEntry<bool> WindVolumeCapacityGuardEnabled { get; }

		internal ConfigEntry<float> LearnedBaselineFps { get; }

		internal ConfigEntry<string> LearnedProfileFingerprint { get; }

		internal TrafficControlConfig(ConfigFile config)
		{
			AdaptivePerformanceEnabled = config.Bind<bool>("Performance", "AdaptivePerformanceEnabled", true, "Learn a machine-specific in-level FPS baseline and reduce optional work under sustained pressure.");
			HighTriggerRatio = config.Bind<float>("Performance", "HighTriggerRatio", 0.85f, "Enter High pressure below this fraction of the learned FPS baseline.");
			CriticalTriggerRatio = config.Bind<float>("Performance", "CriticalTriggerRatio", 0.75f, "Enter Critical pressure below this fraction of the learned FPS baseline.");
			ResetLearnedBaseline = config.Bind<bool>("Performance", "ResetLearnedBaseline", false, "Set true once to discard the learned graphics profile and FPS baseline.");
			PerformanceDiagnosticsEnabled = config.Bind<bool>("Performance", "DiagnosticsEnabled", true, "Write a compact performance status line every 30 seconds while in a level.");
			EnemyVisualOptimizationEnabled = config.Bind<bool>("Performance.EnemyVisuals", "Enabled", true, "Under High or Critical pressure, suppress enemy shadows and reduce corpse visual cost.");
			MaximumRagdollsUnderPressure = config.Bind<int>("Performance.EnemyVisuals", "MaximumRagdollsUnderPressure", 12, "Maximum enabled enemy ragdolls while adaptive pressure is High or Critical.");
			CorpseDecaySecondsUnderPressure = config.Bind<float>("Performance.EnemyVisuals", "CorpseDecaySecondsUnderPressure", 0.01f, "Corpse decay delay used while adaptive pressure is High or Critical.");
			WindVolumeCapacityGuardEnabled = config.Bind<bool>("Compatibility", "WindVolumeCapacityGuardEnabled", true, "Temporarily suppress WindVolume affectors beyond the native fixed-capacity buffer.");
			LearnedBaselineFps = config.Bind<float>("Internal", "LearnedBaselineFps", 0f, "Machine-specific FPS baseline maintained by Performance Traffic Control.");
			LearnedProfileFingerprint = config.Bind<string>("Internal", "LearnedProfileFingerprint", string.Empty, "Graphics environment associated with the learned FPS baseline.");
		}
	}
	internal static class TrafficControlLog
	{
		private static readonly Dictionary<string, DateTime> NextLogAt = new Dictionary<string, DateTime>(StringComparer.Ordinal);

		private static ManualLogSource? s_log;

		internal static void Bind(ManualLogSource log)
		{
			s_log = log;
		}

		internal static void Info(string message)
		{
			ManualLogSource? obj = s_log;
			if (obj != null)
			{
				obj.LogInfo((object)message);
			}
		}

		internal static void Warning(string message)
		{
			ManualLogSource? obj = s_log;
			if (obj != null)
			{
				obj.LogWarning((object)message);
			}
		}

		internal static void Error(string message, Exception? exception = null)
		{
			ManualLogSource? obj = s_log;
			if (obj != null)
			{
				obj.LogError((object)((exception == null) ? message : $"{message}\n{exception}"));
			}
		}

		internal static void InfoRateLimited(string key, string message, float intervalSeconds)
		{
			DateTime utcNow = DateTime.UtcNow;
			if (!NextLogAt.TryGetValue(key, out var value) || !(utcNow < value))
			{
				NextLogAt[key] = utcNow.AddSeconds(Math.Max(0.1f, intervalSeconds));
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogInfo((object)message);
				}
			}
		}

		internal static void ClearRateLimits()
		{
			NextLogAt.Clear();
		}
	}
	public sealed class TrafficControlRuntimeDriver : MonoBehaviour
	{
		internal static PerformanceTrafficControlPlugin? Plugin { get; set; }

		public TrafficControlRuntimeDriver(IntPtr pointer)
			: base(pointer)
		{
		}

		public void Update()
		{
			Plugin?.OnRuntimeUpdate();
		}

		public void OnDestroy()
		{
			Plugin?.OnRuntimeDriverDestroyed(this);
		}
	}
}
namespace PerformanceTrafficControl.Api
{
	public enum PerformancePressureLevel
	{
		Normal,
		High,
		Critical
	}
	public static class TrafficControlPerformance
	{
		private static readonly Dictionary<string, float> AudioNextAllowedAt = new Dictionary<string, float>(StringComparer.Ordinal);

		private static readonly List<string> AudioKeysToRemove = new List<string>();

		private static PerformancePressureLevel s_level;

		private static int s_budgetFrame = -1;

		private static int s_physicsQueriesRemaining;

		private static int s_visualSpawnsRemaining;

		private static int s_audioEventsRemaining;

		public static PerformancePressureLevel Level => s_level;

		public static bool IsHighOrWorse => s_level >= PerformancePressureLevel.High;

		public static bool IsCritical => s_level == PerformancePressureLevel.Critical;

		public static float SmoothedFps { get; private set; }

		public static float LearnedBaselineFps { get; private set; }

		public static float SmoothedFrameMilliseconds
		{
			get
			{
				if (!(SmoothedFps > 0.01f))
				{
					return 0f;
				}
				return 1000f / SmoothedFps;
			}
		}

		public static long DeniedPhysicsQueries { get; private set; }

		public static long DeniedVisualSpawns { get; private set; }

		public static long DeniedAudioEvents { get; private set; }

		public static int TransientVisualLimit => s_level switch
		{
			PerformancePressureLevel.Critical => 16, 
			PerformancePressureLevel.High => 32, 
			_ => 64, 
		};

		public static int RegisteredLightLimit => s_level switch
		{
			PerformancePressureLevel.Critical => 2, 
			PerformancePressureLevel.High => 6, 
			_ => 16, 
		};

		public static float VisualLifetimeScale => s_level switch
		{
			PerformancePressureLevel.Critical => 0.55f, 
			PerformancePressureLevel.High => 0.78f, 
			_ => 1f, 
		};

		public static float ParticleEmissionScale => s_level switch
		{
			PerformancePressureLevel.Critical => 0.3f, 
			PerformancePressureLevel.High => 0.62f, 
			_ => 1f, 
		};

		public static event Action<PerformancePressureLevel, PerformancePressureLevel>? PressureChanged;

		public static bool TryConsumePhysicsQueries(int cost = 1, bool essential = false)
		{
			if (essential || cost <= 0)
			{
				return true;
			}
			EnsureFrameBudgets();
			if (s_physicsQueriesRemaining >= cost)
			{
				s_physicsQueriesRemaining -= cost;
				return true;
			}
			DeniedPhysicsQueries += cost;
			return false;
		}

		public static int ClaimPhysicsQueries(int requested)
		{
			if (requested <= 0)
			{
				return 0;
			}
			EnsureFrameBudgets();
			int num = Math.Min(requested, Math.Max(0, s_physicsQueriesRemaining));
			s_physicsQueriesRemaining -= num;
			DeniedPhysicsQueries += requested - num;
			return num;
		}

		public static bool TryConsumeVisualSpawn(int cost = 1, bool essential = false)
		{
			if (essential || cost <= 0)
			{
				return true;
			}
			EnsureFrameBudgets();
			if (s_visualSpawnsRemaining >= cost)
			{
				s_visualSpawnsRemaining -= cost;
				return true;
			}
			DeniedVisualSpawns += cost;
			return false;
		}

		public static bool TryConsumeAudio(string key, float minimumInterval = 0f, bool essential = false)
		{
			if (essential)
			{
				return true;
			}
			EnsureFrameBudgets();
			float unscaledTime = Time.unscaledTime;
			float num = Mathf.Max(minimumInterval, s_level switch
			{
				PerformancePressureLevel.Critical => 0.22f, 
				PerformancePressureLevel.High => 0.1f, 
				_ => 0f, 
			});
			if (AudioNextAllowedAt.TryGetValue(key, out var value) && unscaledTime < value)
			{
				DeniedAudioEvents++;
				return false;
			}
			if (s_audioEventsRemaining <= 0)
			{
				DeniedAudioEvents++;
				return false;
			}
			s_audioEventsRemaining--;
			AudioNextAllowedAt[key] = unscaledTime + num;
			return true;
		}

		public static float GetUiInterval(float normalInterval)
		{
			return s_level switch
			{
				PerformancePressureLevel.Critical => Mathf.Max(normalInterval, 0.25f), 
				PerformancePressureLevel.High => Mathf.Max(normalInterval, 0.12f), 
				_ => normalInterval, 
			};
		}

		public static int GetVisualComplexity(int normal, int high, int critical)
		{
			return s_level switch
			{
				PerformancePressureLevel.Critical => critical, 
				PerformancePressureLevel.High => high, 
				_ => normal, 
			};
		}

		internal static void UpdateMeasurements(float smoothedFps, float learnedBaselineFps)
		{
			SmoothedFps = smoothedFps;
			LearnedBaselineFps = learnedBaselineFps;
		}

		internal static void SetPressure(PerformancePressureLevel level)
		{
			if (s_level != level)
			{
				PerformancePressureLevel previous = s_level;
				s_level = level;
				s_budgetFrame = -1;
				EnsureFrameBudgets();
				RaisePressureChanged(previous, level);
			}
		}

		internal static void PruneAudioState(float now, float staleAfterSeconds)
		{
			AudioKeysToRemove.Clear();
			foreach (KeyValuePair<string, float> item in AudioNextAllowedAt)
			{
				if (now - item.Value > staleAfterSeconds)
				{
					AudioKeysToRemove.Add(item.Key);
				}
			}
			for (int i = 0; i < AudioKeysToRemove.Count; i++)
			{
				AudioNextAllowedAt.Remove(AudioKeysToRemove[i]);
			}
			AudioKeysToRemove.Clear();
		}

		internal static void ResetForLevelExit()
		{
			SetPressure(PerformancePressureLevel.Normal);
			SmoothedFps = 0f;
			DeniedPhysicsQueries = 0L;
			DeniedVisualSpawns = 0L;
			DeniedAudioEvents = 0L;
			AudioNextAllowedAt.Clear();
			AudioKeysToRemove.Clear();
			s_budgetFrame = -1;
			EnsureFrameBudgets();
		}

		private static void EnsureFrameBudgets()
		{
			int frameCount = Time.frameCount;
			if (s_budgetFrame != frameCount)
			{
				s_budgetFrame = frameCount;
				switch (s_level)
				{
				case PerformancePressureLevel.Critical:
					s_physicsQueriesRemaining = 24;
					s_visualSpawnsRemaining = 3;
					s_audioEventsRemaining = 3;
					break;
				case PerformancePressureLevel.High:
					s_physicsQueriesRemaining = 48;
					s_visualSpawnsRemaining = 8;
					s_audioEventsRemaining = 6;
					break;
				default:
					s_physicsQueriesRemaining = 96;
					s_visualSpawnsRemaining = 24;
					s_audioEventsRemaining = 12;
					break;
				}
			}
		}

		private static void RaisePressureChanged(PerformancePressureLevel previous, PerformancePressureLevel current)
		{
			Action<PerformancePressureLevel, PerformancePressureLevel> pressureChanged = TrafficControlPerformance.PressureChanged;
			if (pressureChanged == null)
			{
				return;
			}
			Delegate[] invocationList = pressureChanged.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<PerformancePressureLevel, PerformancePressureLevel>)obj)(previous, current);
				}
				catch (Exception ex)
				{
					TrafficControlLog.InfoRateLimited("PerformanceApi:PressureChanged", "A performance pressure subscriber failed: " + ex.Message, 2f);
				}
			}
		}
	}
}