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);
}
}
}
}
}