using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Mirror;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TimeStepStabilizer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TimeStepStabilizer")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("bb671ece-09f3-4584-ad0c-c15b01188054")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.yourname.TimeStepStabilizer", "Enhanced TimeStep Stabilizer", "1.2.0")]
public class TimeStepStabilizer : BaseUnityPlugin
{
	public GameMaster gameMaster;
	public GeneralManager generalManager;
	public MultiplayerRoomManager roomManager;
	public List<float> fpsHistory = new List<float>();
	public FieldInfo fpsField;
	public MethodInfo setTimeScaleMethod;
	public FieldInfo currentGameSpeedField;
	public float baseTimeScale = 1f;
	public float baseFixedDeltaTime;
	private Coroutine adjustCoroutine;
	private bool showMenu = false;
	private InputAction toggleMenuAction;
	private ConfigEntry<int> configSendRate;
	private ConfigEntry<int> configFPSHistorySize;
	private ConfigEntry<float> configMinFPSThreshold;
	private ConfigEntry<float> configAdjustmentStep;
	private ConfigEntry<float> configMaxFixedDeltaTime;
	public static TimeStepStabilizer Instance { get; private set; }
	public int SendRate { get; private set; } = 60;
	public int FPSHistorySize { get; private set; } = 10;
	public float MinFPSThreshold { get; private set; } = 29f;
	public float AdjustmentStep { get; private set; } = 0.001f;
	public float MaxFixedDeltaTime { get; private set; } = 0.015f;
	private void Awake()
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Expected O, but got Unknown
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Expected O, but got Unknown
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Expected O, but got Unknown
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Expected O, but got Unknown
		((Object)Chainloader.ManagerObject).hideFlags = (HideFlags)61;
		Instance = this;
		Harmony.CreateAndPatchAll(typeof(TimeStepStabilizer), (string)null);
		SceneManager.sceneLoaded += OnSceneLoaded;
		configSendRate = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "SendRate", 60, new ConfigDescription("Network send rate (ticks per second)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>()));
		configFPSHistorySize = ((BaseUnityPlugin)this).Config.Bind<int>("Stabilization", "FPSHistorySize", 10, new ConfigDescription("Number of FPS samples to average", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 30), Array.Empty<object>()));
		configMinFPSThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Stabilization", "MinFPSThreshold", 29f, new ConfigDescription("FPS threshold for stabilization activation", (AcceptableValueBase)(object)new AcceptableValueRange<float>(15f, 60f), Array.Empty<object>()));
		configAdjustmentStep = ((BaseUnityPlugin)this).Config.Bind<float>("Stabilization", "AdjustmentStep", 0.001f, new ConfigDescription("FixedDeltaTime adjustment step size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 0.1f), Array.Empty<object>()));
		configMaxFixedDeltaTime = ((BaseUnityPlugin)this).Config.Bind<float>("Stabilization", "MaxFixedDeltaTime", 0.015f, new ConfigDescription("Maximum allowed FixedDeltaTime value", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.1f), Array.Empty<object>()));
		LoadConfig();
		toggleMenuAction = new InputAction("ToggleMenu", (InputActionType)1, "<Keyboard>/f8", (string)null, (string)null, (string)null);
		toggleMenuAction.performed += delegate
		{
			showMenu = !showMenu;
		};
		toggleMenuAction.Enable();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Enhanced TimeStep Stabilizer initialized");
	}
	private void OnDestroy()
	{
		toggleMenuAction.Disable();
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}
	private void LoadConfig()
	{
		SendRate = configSendRate.Value;
		FPSHistorySize = configFPSHistorySize.Value;
		MinFPSThreshold = configMinFPSThreshold.Value;
		AdjustmentStep = configAdjustmentStep.Value;
		MaxFixedDeltaTime = configMaxFixedDeltaTime.Value;
		ApplyNetworkSettings();
	}
	private void SaveConfig()
	{
		configSendRate.Value = SendRate;
		configFPSHistorySize.Value = FPSHistorySize;
		configMinFPSThreshold.Value = MinFPSThreshold;
		configAdjustmentStep.Value = AdjustmentStep;
		configMaxFixedDeltaTime.Value = MaxFixedDeltaTime;
		((BaseUnityPlugin)this).Config.Save();
		ApplyNetworkSettings();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuration saved");
	}
	private void ApplyNetworkSettings()
	{
		roomManager = Object.FindObjectOfType<MultiplayerRoomManager>(true);
		if ((Object)(object)roomManager != (Object)null)
		{
			((NetworkManager)roomManager).sendRate = SendRate;
		}
		else
		{
			Debug.LogError((object)"MultiplayerRoomManager NOT FOUND");
		}
	}
	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name));
		fpsHistory.Clear();
		if (adjustCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(adjustCoroutine);
			adjustCoroutine = null;
		}
		((MonoBehaviour)this).StartCoroutine(DelayedSetup());
	}
	private IEnumerator DelayedSetup()
	{
		yield return (object)new WaitForSeconds(0.5f);
		gameMaster = Object.FindObjectOfType<GameMaster>();
		generalManager = Object.FindObjectOfType<GeneralManager>();
		roomManager = Object.FindObjectOfType<MultiplayerRoomManager>(true);
		if ((Object)(object)gameMaster == (Object)null || (Object)(object)generalManager == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("GameMaster, RoomManager or GeneralManager not found." + ((Object)gameMaster).name + ((Object)generalManager).name + ((Object)roomManager).name));
			yield break;
		}
		LoadConfig();
		fpsField = typeof(GeneralManager).GetField("fps", BindingFlags.Instance | BindingFlags.NonPublic);
		setTimeScaleMethod = typeof(GameMaster).GetMethod("SetTimeScale", BindingFlags.Instance | BindingFlags.NonPublic);
		currentGameSpeedField = typeof(GameMaster).GetField("currentGameSpeed", BindingFlags.Instance | BindingFlags.NonPublic);
		if (currentGameSpeedField != null)
		{
			baseFixedDeltaTime = Time.fixedDeltaTime;
			baseTimeScale = (float)currentGameSpeedField.GetValue(gameMaster);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Base TimeScale: {baseTimeScale:F2}");
		}
		for (int i = 0; i < FPSHistorySize; i++)
		{
			fpsHistory.Add(30f);
		}
		adjustCoroutine = ((MonoBehaviour)this).StartCoroutine(AdjustTimeScaleCoroutine());
	}
	private IEnumerator AdjustTimeScaleCoroutine()
	{
		while (true)
		{
			yield return (object)new WaitForSecondsRealtime(1f);
			if ((Object)(object)generalManager == (Object)null || (Object)(object)gameMaster == (Object)null || fpsField == null)
			{
				continue;
			}
			int currentFps = (int)fpsField.GetValue(generalManager);
			fpsHistory.Add(currentFps);
			while (fpsHistory.Count > FPSHistorySize)
			{
				fpsHistory.RemoveAt(0);
			}
			float avgFps = fpsHistory.Average();
			Time.fixedDeltaTime = baseFixedDeltaTime;
			if (avgFps < MinFPSThreshold && baseFixedDeltaTime < MaxFixedDeltaTime)
			{
				float adjustment = AdjustmentStep * (MinFPSThreshold / avgFps);
				float newFixedDeltaTime2 = baseFixedDeltaTime + adjustment;
				if (newFixedDeltaTime2 > MaxFixedDeltaTime)
				{
					newFixedDeltaTime2 = MaxFixedDeltaTime;
				}
				newFixedDeltaTime2 = (float)Math.Round(newFixedDeltaTime2, 5);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Low FPS ({avgFps:F2} < {MinFPSThreshold}), adjusting FixedDeltaTime to: {newFixedDeltaTime2:F5}");
				baseFixedDeltaTime = newFixedDeltaTime2;
				fpsHistory.Add(50f);
				fpsHistory.RemoveAt(0);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Current FixedDeltaTime: {Time.fixedDeltaTime:F5}");
		}
	}
	private void OnGUI()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
		if (showMenu)
		{
			int num = 430;
			GUI.Box(new Rect(10f, (float)num, 400f, 430f), "TimeStep Stabilizer ModMenu");
			num += 30;
			GUI.Label(new Rect(20f, (float)num, 360f, 20f), "Network Send Rate: " + SendRate);
			SendRate = (int)GUI.HorizontalSlider(new Rect(20f, (float)(num + 20), 360f, 20f), (float)SendRate, 1f, 60f);
			num += 50;
			GUI.Label(new Rect(20f, (float)num, 360f, 20f), $"FPS History Size: {FPSHistorySize}");
			FPSHistorySize = (int)GUI.HorizontalSlider(new Rect(20f, (float)(num + 20), 360f, 20f), (float)FPSHistorySize, 5f, 30f);
			num += 50;
			GUI.Label(new Rect(20f, (float)num, 360f, 20f), $"Min FPS Threshold: {MinFPSThreshold:F1} ... increase for more FPS");
			MinFPSThreshold = GUI.HorizontalSlider(new Rect(20f, (float)(num + 20), 360f, 20f), MinFPSThreshold, 15f, 60f);
			num += 50;
			GUI.Label(new Rect(20f, (float)num, 360f, 20f), $"Adjustment Step: {AdjustmentStep:F4}");
			AdjustmentStep = GUI.HorizontalSlider(new Rect(20f, (float)(num + 20), 360f, 20f), AdjustmentStep, 0.0001f, 0.01f);
			AdjustmentStep = (float)Math.Round(AdjustmentStep, 4);
			num += 50;
			GUI.Label(new Rect(20f, (float)num, 360f, 20f), $"Max FixedDeltaTime: {MaxFixedDeltaTime:F4}");
			MaxFixedDeltaTime = GUI.HorizontalSlider(new Rect(20f, (float)(num + 20), 360f, 20f), MaxFixedDeltaTime, 0.01f, 0.05f);
			MaxFixedDeltaTime = (float)Math.Round(MaxFixedDeltaTime, 4);
			num += 50;
			float num2 = (fpsHistory.Any() ? fpsHistory.Average() : 0f);
			GUI.Label(new Rect(20f, (float)num, 360f, 20f), "Current FPS: " + ((fpsField != null && (Object)(object)generalManager != (Object)null) ? fpsField.GetValue(generalManager).ToString() : "N/A"));
			GUI.Label(new Rect(20f, (float)(num + 20), 360f, 20f), $"Average FPS: {num2:F1}");
			GUI.Label(new Rect(20f, (float)(num + 40), 360f, 20f), $"FixedDeltaTime: {Time.fixedDeltaTime:F5}");
			num += 70;
			if (GUI.Button(new Rect(20f, (float)num, 170f, 30f), "Apply Settings"))
			{
				SaveConfig();
			}
			if (GUI.Button(new Rect(200f, (float)num, 170f, 30f), "Reset to Default"))
			{
				SendRate = 60;
				FPSHistorySize = 10;
				MinFPSThreshold = 29f;
				AdjustmentStep = 0.001f;
				MaxFixedDeltaTime = 0.015f;
				SaveConfig();
			}
		}
	}
}