Decompiled source of ValheimPerformanceAnalyzer v1.0.1

BepInEx/plugins/ValheimPerformanceAnalyzer/ValheimPerformanceAnalyzer.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ValheimPerformanceAnalyzer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("ValheimPerformanceAnalyzer")]
[assembly: AssemblyTitle("ValheimPerformanceAnalyzer")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimPerformanceAnalyzer
{
	internal static class CaptureStatusBuff
	{
		private const float RefreshInterval = 0.5f;

		private static StatusEffect _statusEffect;

		private static Texture2D _iconTexture;

		private static Sprite _icon;

		private static Character _appliedTo;

		private static double _nextRefresh;

		private static bool _wasCapturing;

		internal static void Update(bool capturing)
		{
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			if (capturing == _wasCapturing && realtimeSinceStartupAsDouble < _nextRefresh)
			{
				return;
			}
			_wasCapturing = capturing;
			_nextRefresh = realtimeSinceStartupAsDouble + 0.5;
			Player localPlayer = Player.m_localPlayer;
			if (!capturing || (Object)(object)localPlayer == (Object)null)
			{
				if (!capturing)
				{
					RemoveFrom((Character)(((object)localPlayer) ?? ((object)_appliedTo)));
				}
				return;
			}
			double num = Math.Max(0.0, (double)ProfilerCollector.DurationLimitSeconds - ProfilerCollector.ElapsedSeconds);
			if (num <= 0.0)
			{
				return;
			}
			SEMan sEMan = ((Character)localPlayer).GetSEMan();
			if (sEMan != null)
			{
				StatusEffect val = EnsureStatusEffect(num);
				int num2 = val.NameHash();
				if ((Object)(object)_appliedTo != (Object)(object)localPlayer || !sEMan.HaveStatusEffect(num2))
				{
					RemoveFrom(_appliedTo);
					val.m_ttl = (float)num;
					sEMan.AddStatusEffect(val, true, 0, 0f, (short)0);
					_appliedTo = (Character)(object)localPlayer;
				}
			}
		}

		internal static void Clear()
		{
			RemoveFrom((Character)(((object)_appliedTo) ?? ((object)Player.m_localPlayer)));
			if ((Object)(object)_icon != (Object)null)
			{
				Object.Destroy((Object)(object)_icon);
			}
			if ((Object)(object)_iconTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_iconTexture);
			}
			_icon = null;
			_iconTexture = null;
			_statusEffect = null;
			_appliedTo = null;
			_wasCapturing = false;
			_nextRefresh = 0.0;
		}

		private static StatusEffect EnsureStatusEffect(double remaining)
		{
			if ((Object)(object)_statusEffect != (Object)null)
			{
				return _statusEffect;
			}
			_statusEffect = ScriptableObject.CreateInstance<StatusEffect>();
			((Object)_statusEffect).name = "ValheimPerformanceAnalyzer_CaptureStatus";
			_statusEffect.m_name = ProfilerTranslations.Text("capture_buff");
			_statusEffect.m_tooltip = ProfilerTranslations.Text("capture_buff_tooltip");
			_statusEffect.m_ttl = (float)remaining;
			_statusEffect.m_icon = EnsureIcon();
			_statusEffect.m_hidden = false;
			_statusEffect.m_flashIcon = false;
			_statusEffect.m_cooldownIcon = false;
			_statusEffect.m_startMessage = string.Empty;
			_statusEffect.m_stopMessage = string.Empty;
			_statusEffect.m_repeatMessage = string.Empty;
			return _statusEffect;
		}

		private static void RemoveFrom(Character character)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)_statusEffect == (Object)null)
			{
				return;
			}
			try
			{
				SEMan sEMan = character.GetSEMan();
				if (sEMan != null)
				{
					sEMan.RemoveStatusEffect(_statusEffect.NameHash(), true);
				}
			}
			catch
			{
			}
			if ((Object)(object)_appliedTo == (Object)(object)character)
			{
				_appliedTo = null;
			}
		}

		private static Sprite EnsureIcon()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_icon != (Object)null)
			{
				return _icon;
			}
			_iconTexture = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				name = "ValheimPerformanceAnalyzer_CaptureIcon",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			Color32[] array = (Color32[])(object)new Color32[1024];
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = (float)j - 15.5f;
					float num2 = (float)i - 15.5f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					int num4 = i * 32 + j;
					if (num3 <= 14f && num3 >= 10.5f)
					{
						array[num4] = new Color32((byte)70, (byte)205, (byte)224, byte.MaxValue);
					}
					else if (num3 < 10.5f)
					{
						array[num4] = new Color32((byte)20, (byte)47, (byte)62, byte.MaxValue);
					}
					bool flag = j >= 15 && j <= 16 && i >= 16 && i <= 23;
					bool flag2 = i >= 15 && i <= 16 && j >= 15 && j <= 22;
					if (num3 <= 10.5f && (flag || flag2))
					{
						array[num4] = new Color32((byte)245, (byte)249, (byte)252, byte.MaxValue);
					}
				}
			}
			_iconTexture.SetPixels32(array);
			_iconTexture.Apply(false, false);
			_icon = Sprite.Create(_iconTexture, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f);
			((Object)_icon).name = "ValheimPerformanceAnalyzer_CaptureIcon";
			((Object)_icon).hideFlags = (HideFlags)61;
			return _icon;
		}
	}
	internal static class OverlayInputGuard
	{
		private static readonly BindingFlags MethodFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static Harmony _harmony;

		private static bool _eventSystemUpdatePatched;

		internal static void Install(Harmony harmony)
		{
			if (harmony != null)
			{
				_harmony = harmony;
				_eventSystemUpdatePatched = false;
				Patch(harmony, "GetButtonDown", new Type[1] { typeof(string) }, "BlockBoolean");
				Patch(harmony, "GetButtonUp", new Type[1] { typeof(string) }, "BlockBoolean");
				Patch(harmony, "GetButton", new Type[1] { typeof(string) }, "BlockBoolean");
				Patch(harmony, "GetMouseButtonDown", new Type[1] { typeof(int) }, "BlockBoolean");
				Patch(harmony, "GetMouseButtonUp", new Type[1] { typeof(int) }, "BlockBoolean");
				Patch(harmony, "GetMouseButton", new Type[1] { typeof(int) }, "BlockBoolean");
				Patch(harmony, "GetMouseDelta", Type.EmptyTypes, "BlockVector2");
				Patch(harmony, "Internal_GetMouseDelta", Type.EmptyTypes, "BlockVector2");
				Patch(harmony, "GetMouseScrollWheel", Type.EmptyTypes, "BlockFloat");
				PatchPlayerControls(harmony);
				PatchEventSystemUpdate();
			}
		}

		private static void PatchPlayerControls(Harmony harmony)
		{
			try
			{
				Type typeFromHandle = typeof(Player);
				PatchPlayerMethod(harmony, typeFromHandle, "TakeInput", Type.EmptyTypes, "BlockPlayerInput");
				PatchPlayerMethod(harmony, typeFromHandle, "PlayerAttackInput", new Type[1] { typeof(float) }, "BlockPlayerAction");
				PatchPlayerMethod(harmony, typeFromHandle, "Interact", new Type[3]
				{
					typeof(GameObject),
					typeof(bool),
					typeof(bool)
				}, "BlockPlayerAction");
				PatchPlayerMethod(harmony, typeFromHandle, "UseHotbarItem", new Type[1] { typeof(int) }, "BlockPlayerAction");
				PatchPlayerMethod(harmony, typeFromHandle, "Dodge", new Type[1] { typeof(Vector3) }, "BlockPlayerAction");
				PatchPlayerMethod(harmony, typeFromHandle, "UpdateBuildGuiInput", Type.EmptyTypes, "BlockPlayerAction");
				PatchPlayerMethod(harmony, typeFromHandle, "UpdateBuildGuiInputAlternative1", Type.EmptyTypes, "BlockPlayerAction");
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Input guard não conseguiu bloquear as ações do personagem: " + ex.GetType().Name));
				}
			}
		}

		private static void PatchPlayerMethod(Harmony harmony, Type playerType, string methodName, Type[] parameters, string prefixName)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			try
			{
				MethodInfo method = playerType.GetMethod(methodName, MethodFlags, null, parameters, null);
				MethodInfo method2 = typeof(OverlayInputGuard).GetMethod(prefixName, BindingFlags.Static | BindingFlags.NonPublic);
				if (method != null && method2 != null)
				{
					harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					return;
				}
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("Input guard: método Player não encontrado: " + methodName));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Input guard não conseguiu aplicar " + methodName + ": " + ex.GetType().Name));
				}
			}
		}

		private static void Patch(Harmony harmony, string methodName, Type[] parameters, string prefixName)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			try
			{
				MethodInfo method = typeof(ZInput).GetMethod(methodName, MethodFlags, null, parameters, null);
				MethodInfo method2 = typeof(OverlayInputGuard).GetMethod(prefixName, BindingFlags.Static | BindingFlags.NonPublic);
				if (method != null && method2 != null)
				{
					harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					return;
				}
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Input guard: método ZInput não encontrado: " + methodName));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Input guard não conseguiu aplicar " + methodName + ": " + ex.GetType().Name));
				}
			}
		}

		[HarmonyPriority(800)]
		private static bool BlockBoolean(ref bool __result)
		{
			if ((Object)(object)Plugin.Runner == (Object)null || !Plugin.Runner.OverlayVisible)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPriority(800)]
		private static bool BlockVector2(ref Vector2 __result)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Plugin.Runner == (Object)null || !Plugin.Runner.OverlayVisible)
			{
				return true;
			}
			__result = Vector2.zero;
			return false;
		}

		[HarmonyPriority(800)]
		private static bool BlockFloat(ref float __result)
		{
			if ((Object)(object)Plugin.Runner == (Object)null || !Plugin.Runner.OverlayVisible)
			{
				return true;
			}
			__result = 0f;
			return false;
		}

		internal static void Update()
		{
			PatchEventSystemUpdate();
		}

		private static void PatchEventSystemUpdate()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			if (_eventSystemUpdatePatched || _harmony == null)
			{
				return;
			}
			try
			{
				Type type = ResolveEventSystemType();
				if (!(type == null))
				{
					MethodInfo method = type.GetMethod("Update", MethodFlags, null, Type.EmptyTypes, null);
					MethodInfo method2 = typeof(OverlayInputGuard).GetMethod("BlockEventSystemUpdate", BindingFlags.Static | BindingFlags.NonPublic);
					if (!(method == null) && !(method2 == null))
					{
						_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						_eventSystemUpdatePatched = true;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Input guard não conseguiu proteger o EventSystem: " + ex.GetType().Name));
				}
			}
		}

		[HarmonyPriority(800)]
		private static bool BlockEventSystemUpdate()
		{
			if (!((Object)(object)Plugin.Runner == (Object)null))
			{
				return !Plugin.Runner.OverlayVisible;
			}
			return true;
		}

		[HarmonyPriority(800)]
		private static bool BlockPlayerInput(ref bool __result)
		{
			if ((Object)(object)Plugin.Runner == (Object)null || !Plugin.Runner.OverlayVisible)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPriority(800)]
		private static bool BlockPlayerAction()
		{
			if (!((Object)(object)Plugin.Runner == (Object)null))
			{
				return !Plugin.Runner.OverlayVisible;
			}
			return true;
		}

		private static Type ResolveEventSystemType()
		{
			Type type = Type.GetType("UnityEngine.EventSystems.EventSystem, UnityEngine.UI", throwOnError: false);
			if (type != null)
			{
				return type;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					type = assembly.GetType("UnityEngine.EventSystems.EventSystem", throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}
	}
	internal sealed class PerformanceOverlay : MonoBehaviour
	{
		private const int WindowId = 827164;

		private const int ResizeControlId = 827165;

		private const float ResizeEdgeSize = 9f;

		private const int ResizeLeft = 1;

		private const int ResizeRight = 2;

		private const int ResizeTop = 4;

		private const int ResizeBottom = 8;

		private const float MinimumWindowWidth = 940f;

		private const float MinimumWindowHeight = 420f;

		private Rect _window = new Rect(24f, 24f, 1120f, 735f);

		private Vector2 _scroll;

		private bool _resizing;

		private int _resizeEdges;

		private Vector2 _resizeStartMouse;

		private Rect _resizeStartWindow;

		private int _tab;

		private int _visibleObjectsPage;

		private int _visibleObjectIdsPage;

		private string _expandedVisibleObjectKey;

		private bool _visible = true;

		private readonly HashSet<string> _expandedAssemblies = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, int> ExpandedMethodPages = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private static int _modsPage;

		private const int VisibleObjectsPageSize = 50;

		private const int VisibleObjectIdsPageSize = 30;

		private const int ExpandedMethodsPageSize = 50;

		private const int ExpandedMethodsRenderBudget = 50;

		private static Texture2D _windowTexture;

		private static Texture2D _surfaceTexture;

		private static Texture2D _raisedTexture;

		private static Texture2D _headerTexture;

		private static Texture2D _stripeTexture;

		private static Texture2D _accentTexture;

		private static Texture2D _goodTexture;

		private static Texture2D _warnTexture;

		private static Texture2D _badTexture;

		private static Texture2D _buttonHoverTexture;

		private static Texture2D _buttonPressedTexture;

		private static GUIStyle _windowStyle;

		private static GUIStyle _surfaceStyle;

		private static GUIStyle _accentCardStyle;

		private static GUIStyle _goodCardStyle;

		private static GUIStyle _warnCardStyle;

		private static GUIStyle _badCardStyle;

		private static GUIStyle _headerStyle;

		private static GUIStyle _rowStyle;

		private static GUIStyle _alternateRowStyle;

		private static GUIStyle _labelStyle;

		private static GUIStyle _mutedStyle;

		private static GUIStyle _titleStyle;

		private static GUIStyle _sectionStyle;

		private static GUIStyle _buttonStyle;

		private static GUIStyle _objectCaptureOptionalStyle;

		private static GUIStyle _objectCaptureEnabledStyle;

		private static GUIStyle _startButtonStyle;

		private static GUIStyle _tabStyle;

		private static GUIStyle _activeTabStyle;

		private static GUIStyle _goodStyle;

		private static GUIStyle _warnStyle;

		private static GUIStyle _badStyle;

		private static GUIStyle _metricStyle;

		private static GUIStyle _closeButtonStyle;

		private static GUIStyle _captureTimerPanelStyle;

		private static GUIStyle _captureTimerLabelStyle;

		private static GUIStyle _captureTimerValueStyle;

		private static GUIStyle _tooltipStyle;

		internal void SetVisible(bool visible)
		{
			_visible = visible;
		}

		private void OnGUI()
		{
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			if (_visible)
			{
				EnsureStyles();
				float num = Mathf.Min(940f, Mathf.Max(580f, (float)Screen.width - 16f));
				float num2 = Mathf.Min(420f, Mathf.Max(340f, (float)Screen.height - 16f));
				((Rect)(ref _window)).width = Mathf.Clamp(((Rect)(ref _window)).width, num, Mathf.Max(num, (float)Screen.width - 16f));
				((Rect)(ref _window)).height = Mathf.Clamp(((Rect)(ref _window)).height, num2, Mathf.Max(num2, (float)Screen.height - 16f));
				((Rect)(ref _window)).x = Mathf.Clamp(((Rect)(ref _window)).x, 4f, Mathf.Max(4f, (float)Screen.width - ((Rect)(ref _window)).width - 4f));
				((Rect)(ref _window)).y = Mathf.Clamp(((Rect)(ref _window)).y, 4f, Mathf.Max(4f, (float)Screen.height - ((Rect)(ref _window)).height - 4f));
				HandleResizeInput(num, num2);
				GUI.color = Color.white;
				_window = GUI.Window(827164, _window, new WindowFunction(DrawWindow), GUIContent.none, _windowStyle);
			}
		}

		private void HandleResizeInput(float minimumWidth, float minimumHeight)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Invalid comparison between Unknown and I4
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			Event current = Event.current;
			if (current == null || (Object)(object)Plugin.Runner == (Object)null || !Plugin.Runner.MouseReleased)
			{
				return;
			}
			Vector2 mousePosition = current.mousePosition;
			if (!_resizing && (int)current.type == 0 && current.button == 0)
			{
				bool num = mousePosition.x >= ((Rect)(ref _window)).x - 9f && mousePosition.x <= ((Rect)(ref _window)).xMax + 9f;
				bool flag = mousePosition.y >= ((Rect)(ref _window)).y - 9f && mousePosition.y <= ((Rect)(ref _window)).yMax + 9f;
				if (num && flag)
				{
					if (Mathf.Abs(mousePosition.x - ((Rect)(ref _window)).x) <= 9f)
					{
						_resizeEdges |= 1;
					}
					if (Mathf.Abs(mousePosition.x - ((Rect)(ref _window)).xMax) <= 9f)
					{
						_resizeEdges |= 2;
					}
					if (Mathf.Abs(mousePosition.y - ((Rect)(ref _window)).y) <= 9f)
					{
						_resizeEdges |= 4;
					}
					if (Mathf.Abs(mousePosition.y - ((Rect)(ref _window)).yMax) <= 9f)
					{
						_resizeEdges |= 8;
					}
					if (_resizeEdges != 0)
					{
						_resizing = true;
						_resizeStartMouse = mousePosition;
						_resizeStartWindow = _window;
						GUIUtility.hotControl = 827165;
						current.Use();
					}
				}
			}
			else
			{
				if (!_resizing || GUIUtility.hotControl != 827165)
				{
					return;
				}
				if ((int)current.type == 3)
				{
					float num2 = mousePosition.x - _resizeStartMouse.x;
					float num3 = mousePosition.y - _resizeStartMouse.y;
					float num4 = ((Rect)(ref _resizeStartWindow)).x;
					float num5 = ((Rect)(ref _resizeStartWindow)).y;
					float num6 = ((Rect)(ref _resizeStartWindow)).width;
					float num7 = ((Rect)(ref _resizeStartWindow)).height;
					if ((_resizeEdges & 1) != 0)
					{
						num4 += num2;
						num6 -= num2;
					}
					if ((_resizeEdges & 2) != 0)
					{
						num6 += num2;
					}
					if ((_resizeEdges & 4) != 0)
					{
						num5 += num3;
						num7 -= num3;
					}
					if ((_resizeEdges & 8) != 0)
					{
						num7 += num3;
					}
					if (num6 < minimumWidth)
					{
						if ((_resizeEdges & 1) != 0)
						{
							num4 = ((Rect)(ref _resizeStartWindow)).xMax - minimumWidth;
						}
						num6 = minimumWidth;
					}
					if (num7 < minimumHeight)
					{
						if ((_resizeEdges & 4) != 0)
						{
							num5 = ((Rect)(ref _resizeStartWindow)).yMax - minimumHeight;
						}
						num7 = minimumHeight;
					}
					num6 = Mathf.Min(num6, Mathf.Max(minimumWidth, (float)Screen.width - 8f));
					num7 = Mathf.Min(num7, Mathf.Max(minimumHeight, (float)Screen.height - 8f));
					num4 = Mathf.Clamp(num4, 4f, Mathf.Max(4f, (float)Screen.width - num6 - 4f));
					num5 = Mathf.Clamp(num5, 4f, Mathf.Max(4f, (float)Screen.height - num7 - 4f));
					_window = new Rect(num4, num5, num6, num7);
					current.Use();
				}
				else if ((int)current.type == 1 && current.button == 0)
				{
					_resizing = false;
					_resizeEdges = 0;
					GUIUtility.hotControl = 0;
					current.Use();
				}
			}
		}

		private void DrawWindow(int id)
		{
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(_headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) });
			GUILayout.Label("VALHEIM PERFORMANCE ANALYZER", _titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.Label("F9  " + ProfilerTranslations.Text("panel_short"), _mutedStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("×", _closeButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(32f),
				GUILayout.Height(27f)
			}))
			{
				Plugin.Runner?.CloseOverlay();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
			DrawToolbar();
			DrawStatus();
			GUILayout.Space(7f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			float width = Mathf.Clamp((((Rect)(ref _window)).width - 290f) / 5f, 116f, 138f);
			DrawTab(0, "tab_summary", width);
			DrawTab(1, "tab_callbacks", width);
			DrawTab(2, "tab_mods", width);
			DrawTab(3, "tab_components", width);
			DrawTab(4, "tab_visible_objects", width);
			if (GUILayout.Button((Plugin.HideValheimCallbacks.Value ? "[x]  " : "[ ]  ") + ProfilerTranslations.Text("hide_valheim_callbacks"), Plugin.HideValheimCallbacks.Value ? _activeTabStyle : _tabStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(220f),
				GUILayout.Height(32f)
			}))
			{
				Plugin.HideValheimCallbacks.Value = !Plugin.HideValheimCallbacks.Value;
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
			_scroll = GUILayout.BeginScrollView(_scroll, false, true, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			ProfilerSnapshot snapshot = (((Object)(object)Plugin.Instance == (Object)null) ? null : GetSnapshot());
			if (_tab == 0)
			{
				DrawSummary(snapshot, ((Rect)(ref _window)).width);
			}
			else if (_tab == 1)
			{
				DrawMethods(snapshot);
			}
			else if (_tab == 2)
			{
				DrawGroups(snapshot, _expandedAssemblies, 100);
			}
			else if (_tab == 3)
			{
				DrawPrefabs(snapshot);
			}
			else
			{
				DrawVisibleObjects(snapshot);
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			DrawHoverTooltip();
			GUI.DragWindow(new Rect(0f, 0f, Mathf.Max(100f, ((Rect)(ref _window)).width - 76f), 34f));
		}

		private static ProfilerSnapshot GetSnapshot()
		{
			if (!((Object)(object)Plugin.Runner == (Object)null))
			{
				return Plugin.Runner.DisplaySnapshot;
			}
			return ProfilerCollector.GetLastSnapshot();
		}

		private void DrawToolbar()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (ProfilerCollector.IsCapturing)
			{
				GUILayout.Label(ProfilerTranslations.Text("capturing"), _badStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(125f) });
				DrawCaptureTimer();
				if (GUILayout.Button(ProfilerTranslations.Text("stop"), _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(165f) }))
				{
					Plugin.StopCapture();
				}
			}
			else
			{
				if (GUILayout.Button(ProfilerTranslations.Text("start"), _startButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(165f) }))
				{
					Plugin.StartCapture();
				}
				GUILayout.Label(ProfilerTranslations.Format("duration", Plugin.CaptureDurationSeconds.Value), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) });
				if (GUILayout.Button("−", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(32f),
					GUILayout.Height(28f)
				}))
				{
					Plugin.CaptureDurationSeconds.Value = Math.Max(5, Plugin.CaptureDurationSeconds.Value - 5);
				}
				if (GUILayout.Button("+", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(32f),
					GUILayout.Height(28f)
				}))
				{
					Plugin.CaptureDurationSeconds.Value = Math.Min(300, Plugin.CaptureDurationSeconds.Value + 5);
				}
				bool flag = Plugin.CaptureLoadedObjects != null && Plugin.CaptureLoadedObjects.Value;
				string text = (flag ? "[X] " : "[ ] ") + ProfilerTranslations.Text("capture_objects");
				GUIStyle val = (flag ? _objectCaptureEnabledStyle : _objectCaptureOptionalStyle);
				if (GUILayout.Button(text, val, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(250f),
					GUILayout.Height(32f)
				}) && Plugin.CaptureLoadedObjects != null)
				{
					Plugin.CaptureLoadedObjects.Value = !flag;
				}
			}
			if (GUILayout.Button(ProfilerTranslations.Text("export"), _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }))
			{
				bool flag2 = ProfilerCollector.GetLastSnapshot() != null;
				string text2 = Plugin.ExportLastReport();
				Plugin.NotifyChat((!string.IsNullOrEmpty(text2)) ? ProfilerTranslations.Format("report_saved", Plugin.GetChatReportPath(text2)) : ProfilerTranslations.Text(flag2 ? "report_failed" : "report_no_capture"));
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
		}

		private static void DrawCaptureTimer()
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Invalid comparison between Unknown and I4
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			double num = Math.Max(1.0, ProfilerCollector.DurationLimitSeconds);
			double num2 = Math.Min(num, Math.Max(0.0, ProfilerCollector.ElapsedSeconds));
			float num3 = Mathf.Clamp01((float)(num2 / num));
			GUILayout.BeginVertical(_captureTimerPanelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(235f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(ProfilerTranslations.Text("elapsed_short"), _captureTimerLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(88f),
				GUILayout.Height(16f)
			});
			GUILayout.FlexibleSpace();
			GUILayout.Label(FormatCaptureTime(num2) + " / " + FormatCaptureTime(num), _captureTimerValueStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(16f) });
			GUILayout.EndHorizontal();
			Rect rect = GUILayoutUtility.GetRect(1f, 4f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (Event.current != null && (int)Event.current.type == 7)
			{
				GUI.DrawTexture(rect, (Texture)(object)_raisedTexture);
				((Rect)(ref rect)).width = ((Rect)(ref rect)).width * num3;
				if (((Rect)(ref rect)).width > 0f)
				{
					GUI.DrawTexture(rect, (Texture)(object)_accentTexture);
				}
			}
			GUILayout.EndVertical();
		}

		private static string FormatCaptureTime(double seconds)
		{
			int num = (int)Math.Max(0.0, Math.Floor(seconds));
			return (num / 60).ToString("00", CultureInfo.InvariantCulture) + ":" + (num % 60).ToString("00", CultureInfo.InvariantCulture);
		}

		private static void DrawStatus()
		{
			bool isCapturing = ProfilerCollector.IsCapturing;
			GUILayout.BeginHorizontal(isCapturing ? _badStyle : _surfaceStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("●", isCapturing ? _badStyle : _goodStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) });
			GUILayout.Label(ProfilerTranslations.Text(isCapturing ? "active_status" : "ready_status"), _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
		}

		private void DrawTab(int index, string key, float width)
		{
			if (GUILayout.Button(ProfilerTranslations.Text(key), (_tab == index) ? _activeTabStyle : _tabStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.Height(32f)
			}))
			{
				_tab = index;
			}
		}

		private static void DrawSummary(ProfilerSnapshot snapshot, float windowWidth)
		{
			if (snapshot == null)
			{
				BeginCard();
				GUILayout.Label(ProfilerTranslations.Text("no_report"), _sectionStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label(ProfilerTranslations.Text("report_directory"), _mutedStyle, Array.Empty<GUILayoutOption>());
				EndCard();
				DrawLiveServerSummary(windowWidth);
				DrawLiveObjectSummary(null);
				return;
			}
			float width = Mathf.Max(150f, (windowWidth - 76f) / 3f);
			ProfilerDataView.GetMethods(snapshot);
			double frameBudgetPercent = ProfilerDataView.GetFrameBudgetPercent(snapshot);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawMetricCard(ProfilerTranslations.Text("fps"), snapshot.FramesPerSecond.ToString("0.0", CultureInfo.CurrentCulture), ProfilerTranslations.Text("last_capture") + ": " + snapshot.StartedAtUtc.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture), _accentTexture, width);
			DrawMetricCard(ProfilerTranslations.Text("frame"), snapshot.AverageFrameMilliseconds.ToString("0.00", CultureInfo.CurrentCulture) + " ms", ProfilerTranslations.Text("minmax") + ": " + snapshot.MinFrameMilliseconds.ToString("0.00", CultureInfo.CurrentCulture) + " / " + snapshot.MaxFrameMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _raisedTexture, width);
			DrawMetricCard(ProfilerTranslations.Text("callback_share"), frameBudgetPercent.ToString("0.0", CultureInfo.CurrentCulture) + "%", ProfilerTranslations.Text("share_help"), ImpactTexture(frameBudgetPercent), width);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			string value = (snapshot.CpuAvailable ? (snapshot.CpuPercentAverage.ToString("0.0", CultureInfo.CurrentCulture) + "% / " + snapshot.CpuPercentMaximum.ToString("0.0", CultureInfo.CurrentCulture) + "%") : "—");
			DrawMetricCard(ProfilerTranslations.Text("cpu_process"), value, ProfilerTranslations.Text("avg_peak"), _raisedTexture, width, 136f);
			string value2 = (snapshot.ProcessRamAvailable ? (FormatMegabytes(snapshot.ProcessRamAverageMegabytes) + " / " + FormatMegabytes(snapshot.ProcessRamMaximumMegabytes)) : "—");
			string detail = ProfilerTranslations.Text("managed_heap") + ": " + FormatMegabytes(snapshot.ManagedHeapAverageMegabytes);
			DrawMetricCard(ProfilerTranslations.Text("ram_process"), value2, detail, _accentTexture, width, 136f);
			string value3 = (snapshot.GpuUsageAvailable ? (snapshot.GpuUsageAveragePercent.ToString("0.0", CultureInfo.CurrentCulture) + "% / " + snapshot.GpuUsageMaximumPercent.ToString("0.0", CultureInfo.CurrentCulture) + "%") : "—");
			string text = (string.IsNullOrEmpty(snapshot.GpuDeviceName) ? string.Empty : snapshot.GpuDeviceName);
			if (snapshot.GpuMemoryUsedAvailable)
			{
				text = text + ((text.Length == 0) ? string.Empty : " · ") + ProfilerTranslations.Text("gpu_vram_used") + ": " + FormatMegabytes(snapshot.GpuMemoryUsedAverageMegabytes) + " / " + FormatMegabytes(snapshot.GpuMemoryUsedMaximumMegabytes);
			}
			if (snapshot.GpuMemoryMegabytes > 0)
			{
				text = text + ((text.Length == 0) ? string.Empty : " · ") + ProfilerTranslations.Text("gpu_memory") + ": " + FormatMegabytes(snapshot.GpuMemoryMegabytes);
			}
			text = text + ((text.Length == 0) ? string.Empty : " · ") + ProfilerTranslations.Text("gpu_frame_time") + ": " + (snapshot.GpuFrameTimingAvailable ? (snapshot.GpuFrameTimeAverageMilliseconds.ToString("0.00", CultureInfo.CurrentCulture) + " / " + snapshot.GpuFrameTimeMaximumMilliseconds.ToString("0.00", CultureInfo.CurrentCulture) + " ms") : ProfilerTranslations.Text("gpu_unavailable"));
			DrawMetricCard(ProfilerTranslations.Text("gpu_usage"), value3, text, _raisedTexture, width, 136f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			string value4 = (snapshot.ProcessIoAvailable ? (snapshot.IoReadMegabytes.ToString("0.0", CultureInfo.CurrentCulture) + " / " + snapshot.IoWriteMegabytes.ToString("0.0", CultureInfo.CurrentCulture) + " MB") : "—");
			string detail2 = (snapshot.ProcessIoAvailable ? (ProfilerTranslations.Text("read_write_rate") + ": " + snapshot.IoReadRateAverageMegabytesPerSecond.ToString("0.00", CultureInfo.CurrentCulture) + " / " + snapshot.IoWriteRateAverageMegabytesPerSecond.ToString("0.00", CultureInfo.CurrentCulture)) : "—");
			DrawMetricCard(ProfilerTranslations.Text("storage_io"), value4, detail2, _raisedTexture, width);
			ServerTelemetry currentRemoteServerTelemetry = GetCurrentRemoteServerTelemetry();
			bool flag = currentRemoteServerTelemetry != null;
			bool flag2 = snapshot.RemoteServerMetricSamples > 0 || flag;
			bool flag3 = snapshot.IsServerRuntime && snapshot.FixedUpdatesPerSecondAverage > 0.0;
			string value5 = ((!flag2) ? (flag3 ? (snapshot.FixedUpdatesPerSecondAverage.ToString("0.0", CultureInfo.CurrentCulture) + " / " + snapshot.FixedUpdatesPerSecondMinimum.ToString("0.0", CultureInfo.CurrentCulture) + " / " + snapshot.FixedUpdatesPerSecondMaximum.ToString("0.0", CultureInfo.CurrentCulture)) : "—") : ((flag && snapshot.RemoteServerMetricSamples <= 0) ? currentRemoteServerTelemetry.FixedUpdatesPerSecond.ToString("0.0", CultureInfo.CurrentCulture) : (snapshot.RemoteServerTicksAverage.ToString("0.0", CultureInfo.CurrentCulture) + " / " + snapshot.RemoteServerTicksMinimum.ToString("0.0", CultureInfo.CurrentCulture) + " / " + snapshot.RemoteServerTicksMaximum.ToString("0.0", CultureInfo.CurrentCulture))));
			string detail3 = ((!flag2) ? (flag3 ? ProfilerTranslations.Format("server_detail", snapshot.TargetFixedUpdatesPerSecond.ToString("0.0", CultureInfo.CurrentCulture), snapshot.CpuPercentAverage.ToString("0.0", CultureInfo.CurrentCulture), FormatMegabytes(snapshot.ProcessRamAverageMegabytes)) : GetServerAccessHelp()) : ((flag && snapshot.RemoteServerMetricSamples <= 0) ? ProfilerTranslations.Format("server_detail", currentRemoteServerTelemetry.TargetFixedUpdatesPerSecond.ToString("0.0", CultureInfo.CurrentCulture), currentRemoteServerTelemetry.CpuPercent.ToString("0.0", CultureInfo.CurrentCulture), FormatMegabytes(currentRemoteServerTelemetry.WorkingSetMegabytes)) : ProfilerTranslations.Format("server_detail", snapshot.RemoteServerTargetTicks.ToString("0.0", CultureInfo.CurrentCulture), snapshot.RemoteServerCpuAverage.ToString("0.0", CultureInfo.CurrentCulture), FormatMegabytes(snapshot.RemoteServerRamAverageMegabytes))));
			DrawMetricCard(ProfilerTranslations.Text("server_ticks"), value5, detail3, (flag2 || flag3) ? _accentTexture : _raisedTexture, width);
			DrawMetricCard(ProfilerTranslations.Text("memory"), FormatMegabytes((double)snapshot.ManagedMemoryBefore / 1048576.0) + " → " + FormatMegabytes((double)snapshot.ManagedMemoryAfter / 1048576.0), ProfilerTranslations.Text("gc"), _raisedTexture, width);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawInfoCard(ProfilerTranslations.Text("slow_frames") + ": " + snapshot.SlowFramesOver33Ms.ToString("N0", CultureInfo.CurrentCulture) + " / " + snapshot.SlowFramesOver50Ms.ToString("N0", CultureInfo.CurrentCulture));
			DrawInfoCard(ProfilerTranslations.Text("measured_calls") + ": " + ProfilerDataView.GetTotalCalls(snapshot).ToString("N0", CultureInfo.CurrentCulture));
			DrawInfoCard(ProfilerTranslations.Text("gc") + ": " + snapshot.Gen0Collections + " / " + snapshot.Gen1Collections + " / " + snapshot.Gen2Collections);
			GUILayout.EndHorizontal();
			DrawLiveObjectSummary(snapshot);
			GUILayout.Space(8f);
			GUILayout.Label(ProfilerTranslations.Text("top_callbacks"), _sectionStyle, Array.Empty<GUILayoutOption>());
			DrawMethodRows(snapshot, 5);
			GUILayout.Space(12f);
			GUILayout.Label(ProfilerTranslations.Text("tab_mods"), _sectionStyle, Array.Empty<GUILayoutOption>());
			DrawGroups(snapshot, null, 4);
		}

		private static string FormatMegabytes(double megabytes)
		{
			if (!(megabytes >= 1024.0))
			{
				return megabytes.ToString("0.0", CultureInfo.CurrentCulture) + " MB";
			}
			return (megabytes / 1024.0).ToString("0.00", CultureInfo.CurrentCulture) + " GB";
		}

		private static void DrawLiveServerSummary(float windowWidth)
		{
			ServerTelemetry currentRemoteServerTelemetry = GetCurrentRemoteServerTelemetry();
			float width = Mathf.Max(150f, (windowWidth - 76f) / 3f);
			string value = ((currentRemoteServerTelemetry == null) ? "—" : currentRemoteServerTelemetry.FixedUpdatesPerSecond.ToString("0.0", CultureInfo.CurrentCulture));
			string detail = ((currentRemoteServerTelemetry == null) ? GetServerAccessHelp() : ProfilerTranslations.Format("server_detail", currentRemoteServerTelemetry.TargetFixedUpdatesPerSecond.ToString("0.0", CultureInfo.CurrentCulture), currentRemoteServerTelemetry.CpuPercent.ToString("0.0", CultureInfo.CurrentCulture), FormatMegabytes(currentRemoteServerTelemetry.WorkingSetMegabytes)));
			DrawMetricCard(ProfilerTranslations.Text("server_ticks"), value, detail, (currentRemoteServerTelemetry == null) ? _raisedTexture : _accentTexture, width);
		}

		private static ServerTelemetry GetCurrentRemoteServerTelemetry()
		{
			ServerTelemetry latest = ServerTelemetryRpc.Latest;
			if (ServerTelemetryRpc.ServerAdminAccess != true || latest == null)
			{
				return null;
			}
			if (!(Time.realtimeSinceStartupAsDouble - latest.ReceivedAt <= 8.0))
			{
				return null;
			}
			return latest;
		}

		private static string GetServerAccessHelp()
		{
			if (ServerTelemetryRpc.ServerAdminAccess != false)
			{
				return ProfilerTranslations.Text("server_missing");
			}
			return ProfilerTranslations.Text("server_admin_required");
		}

		private static void DrawMethods(ProfilerSnapshot snapshot)
		{
			if (snapshot == null)
			{
				GUILayout.Label(ProfilerTranslations.Text("no_snapshot"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			BeginCard();
			GUILayout.Label(ProfilerTranslations.Text("exclusive_help"), _mutedStyle, Array.Empty<GUILayoutOption>());
			EndCard();
			DrawMethodRows(snapshot, 60);
		}

		private static void DrawMethodRows(ProfilerSnapshot snapshot, int limit)
		{
			List<MethodMetric> list = ((snapshot == null) ? null : ProfilerDataView.GetMethods(snapshot));
			if (list == null || list.Count == 0)
			{
				GUILayout.Label((snapshot != null && Plugin.HideValheimCallbacks.Value) ? ProfilerTranslations.Text("no_visible_calls") : ProfilerTranslations.Text("no_calls"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.BeginHorizontal(_headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(30f) });
			GUILayout.Label(ProfilerTranslations.Text("callback_type"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) });
			GUILayout.Label(ProfilerTranslations.Text("assembly"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) });
			GUILayout.Label(ProfilerTranslations.Text("calls"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label(ProfilerTranslations.Text("self_ms"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(75f) });
			GUILayout.Label(ProfilerTranslations.Text("per_frame"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label(ProfilerTranslations.Text("budget"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			GUILayout.Label(ProfilerTranslations.Text("average"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
			GUILayout.Label(ProfilerTranslations.Text("maximum"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
			GUILayout.EndHorizontal();
			int num = Math.Min(limit, list.Count);
			for (int i = 0; i < num; i++)
			{
				MethodMetric methodMetric = list[i];
				GUILayout.BeginHorizontal((i % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
				GUILayout.Label(TruncatedContent(methodMetric.Label, 42), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) });
				GUILayout.Label(TruncatedContent(methodMetric.AssemblyName, 19), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) });
				GUILayout.Label(methodMetric.Calls.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
				GUILayout.Label(methodMetric.SelfMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(75f) });
				GUILayout.Label(methodMetric.AverageFrameShareMilliseconds(snapshot).ToString("0.000", CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
				double percent = methodMetric.FrameBudgetPercent(snapshot);
				GUILayout.Label(percent.ToString("0.0", CultureInfo.CurrentCulture) + "%", ImpactStyle(percent), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
				GUILayout.Label(methodMetric.AverageMilliseconds.ToString("0.000", CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
				GUILayout.Label(methodMetric.MaxMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
				GUILayout.EndHorizontal();
			}
		}

		private static void DrawPrefabs(ProfilerSnapshot snapshot)
		{
			if (snapshot == null)
			{
				GUILayout.Label(ProfilerTranslations.Text("no_snapshot"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			BeginCard();
			GUILayout.Label(ProfilerTranslations.Text("components_help"), _mutedStyle, Array.Empty<GUILayoutOption>());
			EndCard();
			DrawPrefabRows(snapshot, 60);
			GUILayout.Space(12f);
			GUILayout.Label(ProfilerTranslations.Text("individual_instances"), _sectionStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(_headerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(ProfilerTranslations.Text("object_component"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
			GUILayout.Label(ProfilerTranslations.Text("assembly"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.Label(ProfilerTranslations.Text("calls"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			GUILayout.Label(ProfilerTranslations.Text("self_ms"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			GUILayout.EndHorizontal();
			List<ObjectMetric> objects = ProfilerDataView.GetObjects(snapshot);
			int num = Math.Min(40, objects.Count);
			for (int i = 0; i < num; i++)
			{
				ObjectMetric objectMetric = objects[i];
				GUILayout.BeginHorizontal((i % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
				GUILayout.Label(TruncatedContent(objectMetric.ObjectName + "  •  " + objectMetric.ComponentType, 64), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
				GUILayout.Label(TruncatedContent(objectMetric.AssemblyName, 20), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				GUILayout.Label(objectMetric.Calls.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
				GUILayout.Label(objectMetric.SelfMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
				GUILayout.EndHorizontal();
			}
		}

		private void DrawVisibleObjects(ProfilerSnapshot snapshot)
		{
			VisibleObjectScan latest = VisibleObjectScanner.Latest;
			bool flag = latest?.Available ?? false;
			if ((snapshot == null || !snapshot.VisibleObjectScanAvailable) && !flag)
			{
				BeginCard();
				GUILayout.Label(ProfilerTranslations.Text((!ProfilerCollector.IsCapturing || !Plugin.IncludeLoadedObjectsInCurrentCapture) ? "object_scan_policy" : ((latest == null) ? "object_scan_pending" : "visible_unavailable")), _mutedStyle, Array.Empty<GUILayoutOption>());
				EndCard();
				return;
			}
			List<VisibleObjectMetric> visibleObjectsForHud = ProfilerDataView.GetVisibleObjectsForHud(snapshot, latest);
			int objectCount = SumVisibleObjectQuantities(visibleObjectsForHud);
			BeginCard();
			GUILayout.Label(FormatObjectCountSummary(objectCount), _sectionStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(ProfilerTranslations.Text("visible_help"), _mutedStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(ProfilerTranslations.Text("object_scan_policy"), _mutedStyle, Array.Empty<GUILayoutOption>());
			EndCard();
			if (visibleObjectsForHud.Count == 0)
			{
				GUILayout.Label(ProfilerTranslations.Text("no_visible_objects"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.BeginHorizontal(_headerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(ProfilerTranslations.Text("object_component"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
			GUILayout.Label(ProfilerTranslations.Text("assembly"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) });
			GUILayout.Label(ProfilerTranslations.Text("quantity"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
			GUILayout.EndHorizontal();
			int num = Math.Max(1, (visibleObjectsForHud.Count + 50 - 1) / 50);
			_visibleObjectsPage = Mathf.Clamp(_visibleObjectsPage, 0, num - 1);
			int num2 = _visibleObjectsPage * 50;
			int num3 = Math.Min(visibleObjectsForHud.Count, num2 + 50);
			for (int i = num2; i < num3; i++)
			{
				VisibleObjectMetric visibleObjectMetric = visibleObjectsForHud[i];
				string visibleObjectKey = GetVisibleObjectKey(visibleObjectMetric);
				bool flag2 = string.Equals(_expandedVisibleObjectKey, visibleObjectKey, StringComparison.Ordinal);
				GUILayout.BeginHorizontal(((i - num2) % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
				if (GUILayout.Button(flag2 ? "▾" : "▸", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(28f),
					GUILayout.Height(23f)
				}))
				{
					_expandedVisibleObjectKey = (flag2 ? null : visibleObjectKey);
					_visibleObjectIdsPage = 0;
				}
				GUILayout.Label(TruncatedContent(visibleObjectMetric.ObjectName, 54), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(402f) });
				GUILayout.Label(TruncatedContent(ProfilerDataView.IsVanillaAssembly(visibleObjectMetric.AssemblyName) ? ProfilerTranslations.Text("vanilla_game") : visibleObjectMetric.AssemblyName, 30), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) });
				GUILayout.Label(visibleObjectMetric.CurrentInstances.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
				GUILayout.EndHorizontal();
				if (flag2)
				{
					DrawVisibleObjectIds(visibleObjectMetric, i - num2);
				}
			}
			if (num > 1)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("‹", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(34f),
					GUILayout.Height(27f)
				}))
				{
					_visibleObjectsPage = Math.Max(0, _visibleObjectsPage - 1);
				}
				GUILayout.Label((_visibleObjectsPage + 1).ToString(CultureInfo.CurrentCulture) + " / " + num.ToString(CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(70f),
					GUILayout.Height(27f)
				});
				if (GUILayout.Button("›", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(34f),
					GUILayout.Height(27f)
				}))
				{
					_visibleObjectsPage = Math.Min(num - 1, _visibleObjectsPage + 1);
				}
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
			}
		}

		private static void DrawLiveObjectSummary(ProfilerSnapshot snapshot)
		{
			VisibleObjectScan latest = VisibleObjectScanner.Latest;
			if (latest != null && latest.Available)
			{
				int objectCount = SumVisibleObjectQuantities(ProfilerDataView.GetVisibleObjectsForHud(snapshot, latest));
				BeginCard();
				GUILayout.Label(FormatObjectCountSummary(objectCount), _labelStyle, Array.Empty<GUILayoutOption>());
				EndCard();
			}
		}

		private static string FormatObjectCountSummary(int objectCount)
		{
			return ProfilerTranslations.Text("tab_visible_objects") + ": " + objectCount.ToString("N0", CultureInfo.CurrentCulture);
		}

		private static int SumVisibleObjectQuantities(List<VisibleObjectMetric> objects)
		{
			int num = 0;
			for (int i = 0; i < objects.Count; i++)
			{
				num += objects[i].CurrentInstances;
			}
			return num;
		}

		private static string GetVisibleObjectKey(VisibleObjectMetric metric)
		{
			return metric.Key ?? ((metric.AssemblyName ?? string.Empty) + "\0" + (metric.ObjectName ?? string.Empty));
		}

		private void DrawVisibleObjectIds(VisibleObjectMetric metric, int rowIndex)
		{
			List<int> instanceIds = metric.InstanceIds;
			if (instanceIds == null || instanceIds.Count == 0)
			{
				return;
			}
			int num = Math.Max(1, (instanceIds.Count + 30 - 1) / 30);
			_visibleObjectIdsPage = Mathf.Clamp(_visibleObjectIdsPage, 0, num - 1);
			int num2 = _visibleObjectIdsPage * 30;
			int num3 = Math.Min(instanceIds.Count, num2 + 30);
			StringBuilder stringBuilder = new StringBuilder((num3 - num2) * 12);
			for (int i = num2; i < num3; i++)
			{
				if (i > num2)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(instanceIds[i].ToString(CultureInfo.InvariantCulture));
			}
			GUILayout.BeginHorizontal((rowIndex % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(28f) });
			GUILayout.Space(28f);
			GUILayout.Label(ProfilerTranslations.Text("object_ids") + ": " + stringBuilder, _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (num > 1)
			{
				if (GUILayout.Button("‹", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(28f),
					GUILayout.Height(24f)
				}))
				{
					_visibleObjectIdsPage = Math.Max(0, _visibleObjectIdsPage - 1);
				}
				GUILayout.Label((_visibleObjectIdsPage + 1).ToString(CultureInfo.CurrentCulture) + " / " + num.ToString(CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(54f) });
				if (GUILayout.Button("›", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(28f),
					GUILayout.Height(24f)
				}))
				{
					_visibleObjectIdsPage = Math.Min(num - 1, _visibleObjectIdsPage + 1);
				}
			}
			GUILayout.EndHorizontal();
		}

		private static void DrawPrefabRows(ProfilerSnapshot snapshot, int limit)
		{
			List<PrefabMetric> list = ((snapshot == null) ? null : ProfilerDataView.GetPrefabs(snapshot));
			if (list == null || list.Count == 0)
			{
				GUILayout.Label(ProfilerTranslations.Text("no_components"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.BeginHorizontal(_headerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(ProfilerTranslations.Text("object_component"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
			GUILayout.Label(ProfilerTranslations.Text("assembly"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.Label(ProfilerTranslations.Text("instances"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			GUILayout.Label(ProfilerTranslations.Text("calls"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			GUILayout.Label(ProfilerTranslations.Text("self_ms"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			GUILayout.EndHorizontal();
			int num = Math.Min(limit, list.Count);
			for (int i = 0; i < num; i++)
			{
				PrefabMetric prefabMetric = list[i];
				GUILayout.BeginHorizontal((i % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
				GUILayout.Label(TruncatedContent(prefabMetric.ObjectName + "  •  " + prefabMetric.ComponentType, 64), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
				GUILayout.Label(TruncatedContent(prefabMetric.AssemblyName, 20), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				GUILayout.Label(prefabMetric.Instances.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
				GUILayout.Label(prefabMetric.Calls.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
				GUILayout.Label(prefabMetric.SelfMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
				GUILayout.EndHorizontal();
			}
		}

		private static void DrawMetricCard(string title, string value, string detail, Texture2D accent, float width, float minimumHeight = 110f)
		{
			GUILayout.BeginVertical(((Object)(object)accent == (Object)(object)_badTexture) ? _badCardStyle : (((Object)(object)accent == (Object)(object)_warnTexture) ? _warnCardStyle : (((Object)(object)accent == (Object)(object)_goodTexture) ? _goodCardStyle : (((Object)(object)accent == (Object)(object)_raisedTexture) ? _surfaceStyle : _accentCardStyle))), (GUILayoutOption[])(object)new GUILayoutOption[3]
			{
				GUILayout.Width(width),
				GUILayout.MinHeight(minimumHeight),
				GUILayout.ExpandHeight(true)
			});
			GUILayout.Label(title, _mutedStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(value, _metricStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(detail, _mutedStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
		}

		private static void DrawInfoCard(string text)
		{
			GUILayout.BeginVertical(_surfaceStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.MinHeight(40f)
			});
			GUILayout.Label(text, _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
		}

		private static void BeginCard()
		{
			GUILayout.BeginVertical(_surfaceStyle, Array.Empty<GUILayoutOption>());
		}

		private static void EndCard()
		{
			GUILayout.EndVertical();
		}

		private static GUIStyle ImpactStyle(double percent)
		{
			if (percent >= 25.0)
			{
				return _badStyle;
			}
			if (percent >= 10.0)
			{
				return _warnStyle;
			}
			return _goodStyle;
		}

		private static void DrawGroups(ProfilerSnapshot snapshot, HashSet<string> expanded, int limit)
		{
			if (snapshot == null)
			{
				GUILayout.Label(ProfilerTranslations.Text("no_snapshot"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			List<AssemblyGroupMetric> groups = ProfilerDataView.GetGroups(snapshot);
			if (groups.Count == 0)
			{
				GUILayout.Label(ProfilerDataView.HideVanilla ? ProfilerTranslations.Text("no_visible_calls") : ProfilerTranslations.Text("no_calls"), _mutedStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.BeginHorizontal(_headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(30f) });
			GUILayout.Label(ProfilerTranslations.Text("mod_or_game"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(410f) });
			GUILayout.Label(ProfilerTranslations.Text("calls"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) });
			GUILayout.Label(ProfilerTranslations.Text("self_ms"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) });
			GUILayout.Label(ProfilerTranslations.Text("budget"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(135f) });
			GUILayout.EndHorizontal();
			int num = ((expanded == null) ? limit : 50);
			int num2 = Math.Max(1, (groups.Count + num - 1) / num);
			if (expanded != null)
			{
				_modsPage = Mathf.Clamp(_modsPage, 0, num2 - 1);
			}
			int num3 = ((expanded != null) ? (_modsPage * num) : 0);
			int num4 = Math.Min(groups.Count, num3 + num);
			int num5 = 50;
			for (int i = num3; i < num4; i++)
			{
				AssemblyGroupMetric assemblyGroupMetric = groups[i];
				bool flag = expanded?.Contains(assemblyGroupMetric.Key) ?? false;
				GUILayout.BeginHorizontal(((i - num3) % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(31f) });
				if (expanded != null && GUILayout.Button((flag ? "▾  " : "▸  ") + GroupDisplayName(assemblyGroupMetric), _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(410f),
					GUILayout.Height(27f)
				}))
				{
					if (flag)
					{
						expanded.Remove(assemblyGroupMetric.Key);
						ExpandedMethodPages.Remove(assemblyGroupMetric.Key);
					}
					else
					{
						expanded.Clear();
						ExpandedMethodPages.Clear();
						expanded.Add(assemblyGroupMetric.Key);
					}
				}
				else if (expanded == null)
				{
					GUILayout.Label("•  " + GroupDisplayName(assemblyGroupMetric), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(410f) });
				}
				GUILayout.Label(assemblyGroupMetric.Calls.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) });
				GUILayout.Label(assemblyGroupMetric.SelfMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) });
				double percent = assemblyGroupMetric.FrameBudgetPercent(snapshot);
				GUILayout.Label(percent.ToString("0.0", CultureInfo.CurrentCulture) + "%", ImpactStyle(percent), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(135f) });
				GUILayout.EndHorizontal();
				if (!flag)
				{
					continue;
				}
				int num6 = Math.Max(1, (assemblyGroupMetric.Methods.Count + 50 - 1) / 50);
				ExpandedMethodPages.TryGetValue(assemblyGroupMetric.Key, out var value);
				value = Mathf.Clamp(value, 0, num6 - 1);
				ExpandedMethodPages[assemblyGroupMetric.Key] = value;
				int num7 = value * 50;
				int num8 = Math.Min(assemblyGroupMetric.Methods.Count, num7 + Math.Min(50, num5));
				for (int j = num7; j < num8; j++)
				{
					MethodMetric methodMetric = assemblyGroupMetric.Methods[j];
					GUILayout.BeginHorizontal(((j - num7) % 2 == 0) ? _rowStyle : _alternateRowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
					GUILayout.Space(24f);
					GUILayout.Label(TruncatedContent(methodMetric.Label, 54), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(386f) });
					GUILayout.Label(methodMetric.Calls.ToString("N0", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) });
					GUILayout.Label(methodMetric.SelfMilliseconds.ToString("0.00", CultureInfo.CurrentCulture), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) });
					double percent2 = methodMetric.FrameBudgetPercent(snapshot);
					GUILayout.Label(percent2.ToString("0.0", CultureInfo.CurrentCulture) + "%", ImpactStyle(percent2), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(135f) });
					GUILayout.EndHorizontal();
				}
				num5 -= num8 - num7;
				if (num6 > 1)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Space(24f);
					if (GUILayout.Button("‹", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(30f),
						GUILayout.Height(25f)
					}))
					{
						ExpandedMethodPages[assemblyGroupMetric.Key] = Math.Max(0, value - 1);
					}
					GUILayout.Label((value + 1).ToString(CultureInfo.CurrentCulture) + " / " + num6.ToString(CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(70f),
						GUILayout.Height(25f)
					});
					if (GUILayout.Button("›", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(30f),
						GUILayout.Height(25f)
					}))
					{
						ExpandedMethodPages[assemblyGroupMetric.Key] = Math.Min(num6 - 1, value + 1);
					}
					GUILayout.EndHorizontal();
				}
			}
			if (expanded != null && num2 > 1)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("‹", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(34f),
					GUILayout.Height(27f)
				}))
				{
					_modsPage = Math.Max(0, _modsPage - 1);
				}
				GUILayout.Label((_modsPage + 1).ToString(CultureInfo.CurrentCulture) + " / " + num2.ToString(CultureInfo.CurrentCulture), _mutedStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(70f),
					GUILayout.Height(27f)
				});
				if (GUILayout.Button("›", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(34f),
					GUILayout.Height(27f)
				}))
				{
					_modsPage = Math.Min(num2 - 1, _modsPage + 1);
				}
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
			}
		}

		private static string GroupDisplayName(AssemblyGroupMetric group)
		{
			if (!group.IsVanilla)
			{
				return group.AssemblyName;
			}
			return ProfilerTranslations.Text("vanilla_game");
		}

		private static Texture2D ImpactTexture(double percent)
		{
			if (percent >= 25.0)
			{
				return _badTexture;
			}
			if (percent >= 10.0)
			{
				return _warnTexture;
			}
			return _goodTexture;
		}

		private static string Shorten(string value, int maxLength)
		{
			if (string.IsNullOrEmpty(value) || value.Length <= maxLength)
			{
				return value ?? string.Empty;
			}
			return "…" + value.Substring(value.Length - maxLength + 1);
		}

		private static GUIContent TruncatedContent(string value, int maxLength)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			string text = value ?? string.Empty;
			if (text.Length <= maxLength)
			{
				return new GUIContent(text);
			}
			return new GUIContent(Shorten(text, maxLength), text);
		}

		private void DrawHoverTooltip()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			if (Event.current != null && (int)Event.current.type == 7 && !string.IsNullOrEmpty(GUI.tooltip))
			{
				string tooltip = GUI.tooltip;
				float num = Mathf.Max(180f, Mathf.Min(460f, ((Rect)(ref _window)).width - 28f));
				GUIContent val = new GUIContent(tooltip);
				Vector2 val2 = _tooltipStyle.CalcSize(val);
				float num2 = Mathf.Min(num, Mathf.Max(180f, val2.x + (float)_tooltipStyle.padding.horizontal));
				float num3 = Mathf.Min(240f, _tooltipStyle.CalcHeight(val, num2));
				Vector2 mousePosition = Event.current.mousePosition;
				float num4 = mousePosition.x + 16f;
				float num5 = mousePosition.y + 18f;
				if (num4 + num2 > ((Rect)(ref _window)).width - 8f)
				{
					num4 = mousePosition.x - num2 - 12f;
				}
				if (num5 + num3 > ((Rect)(ref _window)).height - 8f)
				{
					num5 = mousePosition.y - num3 - 12f;
				}
				num4 = Mathf.Clamp(num4, 8f, Mathf.Max(8f, ((Rect)(ref _window)).width - num2 - 8f));
				num5 = Mathf.Clamp(num5, 8f, Mathf.Max(8f, ((Rect)(ref _window)).height - num3 - 8f));
				GUI.Box(new Rect(num4, num5, num2, num3), val, _tooltipStyle);
			}
		}

		private static void EnsureStyles()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Expected O, but got Unknown
			//IL_01dd: Expected O, but got Unknown
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Expected O, but got Unknown
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Expected O, but got Unknown
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Expected O, but got Unknown
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Expected O, but got Unknown
			//IL_049a: Expected O, but got Unknown
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Expected O, but got Unknown
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Expected O, but got Unknown
			//IL_0564: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0591: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_062c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0654: Unknown result type (might be due to invalid IL or missing references)
			//IL_0659: Unknown result type (might be due to invalid IL or missing references)
			if (_windowStyle == null)
			{
				_windowTexture = Pixel(Color32.op_Implicit(new Color32((byte)16, (byte)22, (byte)30, byte.MaxValue)));
				_surfaceTexture = Pixel(Color32.op_Implicit(new Color32((byte)27, (byte)37, (byte)49, byte.MaxValue)));
				_raisedTexture = Pixel(Color32.op_Implicit(new Color32((byte)34, (byte)48, (byte)63, byte.MaxValue)));
				_headerTexture = Pixel(Color32.op_Implicit(new Color32((byte)25, (byte)44, (byte)61, byte.MaxValue)));
				_stripeTexture = Pixel(Color32.op_Implicit(new Color32((byte)22, (byte)30, (byte)40, byte.MaxValue)));
				_accentTexture = Pixel(Color32.op_Implicit(new Color32((byte)35, (byte)91, (byte)119, byte.MaxValue)));
				_goodTexture = Pixel(Color32.op_Implicit(new Color32((byte)31, (byte)91, (byte)71, byte.MaxValue)));
				_warnTexture = Pixel(Color32.op_Implicit(new Color32((byte)127, (byte)85, (byte)24, byte.MaxValue)));
				_badTexture = Pixel(Color32.op_Implicit(new Color32((byte)128, (byte)48, (byte)47, byte.MaxValue)));
				_buttonHoverTexture = Pixel(Color32.op_Implicit(new Color32((byte)47, (byte)102, (byte)128, byte.MaxValue)));
				_buttonPressedTexture = Pixel(Color32.op_Implicit(new Color32((byte)25, (byte)60, (byte)79, byte.MaxValue)));
				GUIStyle val = new GUIStyle(GUI.skin.window);
				val.normal.background = _windowTexture;
				val.normal.textColor = Color.white;
				val.onNormal.background = _windowTexture;
				val.onNormal.textColor = Color.white;
				val.border = new RectOffset(10, 10, 10, 10);
				val.padding = new RectOffset(14, 14, 10, 12);
				_windowStyle = val;
				_surfaceStyle = BoxStyle(_surfaceTexture, 10, 10, 7, 7);
				_accentCardStyle = BoxStyle(_accentTexture, 10, 10, 7, 7);
				_goodCardStyle = BoxStyle(_goodTexture, 10, 10, 7, 7);
				_warnCardStyle = BoxStyle(_warnTexture, 10, 10, 7, 7);
				_badCardStyle = BoxStyle(_badTexture, 10, 10, 7, 7);
				_headerStyle = BoxStyle(_headerTexture, 8, 8, 5, 5);
				_rowStyle = BoxStyle(_surfaceTexture, 6, 6, 2, 2);
				_alternateRowStyle = BoxStyle(_stripeTexture, 6, 6, 2, 2);
				_labelStyle = LabelStyle(Color32.op_Implicit(new Color32((byte)239, (byte)244, (byte)249, byte.MaxValue)), 14, (FontStyle)0);
				_mutedStyle = LabelStyle(Color32.op_Implicit(new Color32((byte)174, (byte)190, (byte)205, byte.MaxValue)), 13, (FontStyle)0);
				_titleStyle = LabelStyle(Color32.op_Implicit(new Color32((byte)240, (byte)247, (byte)252, byte.MaxValue)), 18, (FontStyle)1);
				_sectionStyle = LabelStyle(Color32.op_Implicit(new Color32((byte)100, (byte)205, (byte)223, byte.MaxValue)), 16, (FontStyle)1);
				_metricStyle = LabelStyle(Color32.op_Implicit(new Color32((byte)249, (byte)252, byte.MaxValue, byte.MaxValue)), 23, (FontStyle)1);
				_captureTimerPanelStyle = BoxStyle(_surfaceTexture, 8, 8, 2, 2);
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3,
					wordWrap = false
				};
				val2.normal.textColor = Color32.op_Implicit(new Color32((byte)112, (byte)198, (byte)218, byte.MaxValue));
				_captureTimerLabelStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)5,
					wordWrap = false
				};
				val3.normal.textColor = Color32.op_Implicit(new Color32((byte)242, (byte)247, (byte)252, byte.MaxValue));
				_captureTimerValueStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.box);
				val4.normal.background = _headerTexture;
				val4.normal.textColor = Color32.op_Implicit(new Color32((byte)245, (byte)249, (byte)252, byte.MaxValue));
				val4.alignment = (TextAnchor)0;
				val4.wordWrap = true;
				val4.fontSize = 13;
				val4.padding = new RectOffset(10, 10, 7, 7);
				val4.border = new RectOffset(8, 8, 8, 8);
				_tooltipStyle = val4;
				_buttonStyle = ButtonStyle(_raisedTexture, Color32.op_Implicit(new Color32((byte)244, (byte)247, (byte)250, byte.MaxValue)));
				_objectCaptureOptionalStyle = ButtonStyle(_warnTexture, Color32.op_Implicit(new Color32(byte.MaxValue, (byte)238, (byte)192, byte.MaxValue)));
				_objectCaptureOptionalStyle.fontSize = 12;
				_objectCaptureOptionalStyle.padding = new RectOffset(5, 5, 4, 4);
				_objectCaptureEnabledStyle = ButtonStyle(_goodTexture, Color32.op_Implicit(new Color32((byte)207, byte.MaxValue, (byte)226, byte.MaxValue)));
				_objectCaptureEnabledStyle.fontSize = 12;
				_objectCaptureEnabledStyle.padding = new RectOffset(5, 5, 4, 4);
				_startButtonStyle = ButtonStyle(_accentTexture, Color.white);
				_tabStyle = ButtonStyle(_surfaceTexture, Color32.op_Implicit(new Color32((byte)190, (byte)205, (byte)218, byte.MaxValue)));
				_activeTabStyle = ButtonStyle(_accentTexture, Color.white);
				_goodStyle = ButtonStyle(_goodTexture, Color32.op_Implicit(new Color32((byte)207, byte.MaxValue, (byte)226, byte.MaxValue)));
				_warnStyle = ButtonStyle(_warnTexture, Color32.op_Implicit(new Color32(byte.MaxValue, (byte)238, (byte)192, byte.MaxValue)));
				_badStyle = ButtonStyle(_badTexture, Color32.op_Implicit(new Color32(byte.MaxValue, (byte)214, (byte)207, byte.MaxValue)));
				_closeButtonStyle = ButtonStyle(_surfaceTexture, Color32.op_Implicit(new Color32((byte)238, (byte)245, (byte)251, byte.MaxValue)));
			}
		}

		private static GUIStyle BoxStyle(Texture2D texture, int left, int right, int top, int bottom)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_005a: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.box);
			val.normal.background = texture;
			val.normal.textColor = Color.white;
			val.padding = new RectOffset(left, right, top, bottom);
			val.margin = new RectOffset(2, 2, 2, 2);
			val.border = new RectOffset(5, 5, 5, 5);
			return val;
		}

		private static GUIStyle ButtonStyle(Texture2D texture, Color textColor)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.button)
			{
				fontSize = 14,
				fontStyle = (FontStyle)1,
				padding = new RectOffset(9, 9, 6, 6)
			};
			val.normal.background = texture;
			val.normal.textColor = textColor;
			val.hover.background = _buttonHoverTexture;
			val.hover.textColor = Color.white;
			val.active.background = _buttonPressedTexture;
			val.active.textColor = Color.white;
			val.focused.background = texture;
			val.focused.textColor = Color.white;
			return val;
		}

		private static GUIStyle LabelStyle(Color color, int size, FontStyle weight)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = size,
				fontStyle = weight,
				wordWrap = true
			};
			val.normal.textColor = color;
			val.hover.textColor = color;
			return val;
		}

		private static Texture2D Pixel(Color color)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61,
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			val.SetPixel(0, 0, color);
			val.Apply(false, true);
			return val;
		}

		private void OnDestroy()
		{
			DestroyTexture(_windowTexture);
			DestroyTexture(_surfaceTexture);
			DestroyTexture(_raisedTexture);
			DestroyTexture(_headerTexture);
			DestroyTexture(_stripeTexture);
			DestroyTexture(_accentTexture);
			DestroyTexture(_goodTexture);
			DestroyTexture(_warnTexture);
			DestroyTexture(_badTexture);
			DestroyTexture(_buttonHoverTexture);
			DestroyTexture(_buttonPressedTexture);
			_windowStyle = null;
		}

		private static void DestroyTexture(Texture2D texture)
		{
			if ((Object)(object)texture != (Object)null)
			{
				Object.Destroy((Object)(object)texture);
			}
		}
	}
	internal static class PerformanceReporter
	{
		internal static string Export(ProfilerSnapshot snapshot)
		{
			if (snapshot == null)
			{
				return null;
			}
			try
			{
				string text = Path.Combine(Paths.ConfigPath, "ValheimPerformanceAnalyzer", "Reports");
				Directory.CreateDirectory(text);
				string path = "Valheim-Profile-" + snapshot.StartedAtUtc.ToLocalTime().ToString("yyyyMMdd-HHmmss-fff", CultureInfo.InvariantCulture);
				string text2 = Path.Combine(text, path);
				Directory.CreateDirectory(text2);
				string text3 = Path.Combine(text2, "index.html");
				File.WriteAllText(text3, BuildHtml(snapshot), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				return text3;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Falha ao salvar o relatório do profiler: " + ex));
				}
				return null;
			}
		}

		private static string BuildHtml(ProfilerSnapshot snapshot)
		{
			CultureInfo numberCulture = ProfilerTranslations.NumberCulture;
			List<AssemblyGroupMetric> groups = ProfilerDataView.GetGroups(snapshot);
			List<PrefabMetric> prefabs = ProfilerDataView.GetPrefabs(snapshot);
			List<ObjectMetric> objects = ProfilerDataView.GetObjects(snapshot);
			List<VisibleObjectMetric> visibleObjects = ProfilerDataView.GetVisibleObjects(snapshot);
			double totalSelfMilliseconds = ProfilerDataView.GetTotalSelfMilliseconds(snapshot);
			StringBuilder stringBuilder = new StringBuilder(30000);
			stringBuilder.AppendLine("<!doctype html>");
			stringBuilder.Append("<html lang=\"").Append(Html(numberCulture.Name)).AppendLine("\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
			stringBuilder.Append("<title>").Append(Html("Valheim Performance Analyzer")).AppendLine("</title>");
			stringBuilder.AppendLine("<style>");
			stringBuilder.AppendLine("* { box-sizing: border-box; }\nbody { margin: 0; background: #0d141c; color: #e7eef5; font: 15px/1.45 Segoe UI, Arial, sans-serif; }\nmain { max-width: 1500px; margin: auto; padding: 24px; }\nh1 { margin: 0 0 8px; color: #f4f8fb; font-size: 25px; }\nh2 { margin: 30px 0 10px; color: #55c4df; font-size: 19px; }\n.hint { margin: 0 0 20px; color: #aebecd; }\n.toolbar { padding: 10px 0; background: #0d141c; }\ninput { width: min(420px, 100%); padding: 9px 12px; border: 1px solid #405163; border-radius: 4px; background: #1b2531; color: #eef5fb; }\n.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }\n.card { min-height: 80px; padding: 12px 14px; border-left: 3px solid #2686a5; background: #1b2531; }\n.card b { display: block; color: #9bb2c6; font-size: 13px; font-weight: 500; }\n.card strong { display: block; margin-top: 3px; font-size: 22px; }\n.card small { color: #93a9bd; }\n.table-wrap { overflow: auto; border: 1px solid #263545; }\ntable { width: 100%; min-width: 760px; border-collapse: collapse; background: #131c26; }\nth, td { padding: 9px 11px; border-bottom: 1px solid #2b3948; text-align: left; vertical-align: top; }\nth { background: #1a3042; color: #dce9f3; user-select: none; cursor: pointer; white-space: nowrap; }\nth:hover { background: #28536c; }\nth[draggable=true] { cursor: grab; }\nth[draggable=true]:active { cursor: grabbing; }\ntbody tr:nth-child(even) { background: #19232e; }\ntbody tr:hover { background: #202d3a; }\n.number { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }\n.good { color: #8af0b7; }\n.warn { color: #ffd779; }\n.bad { color: #ffaaa1; }\ndetails > summary { color: #e9f2f9; font-weight: 600; cursor: pointer; }\ndetails > summary:hover { color: #55c4df; }\n.nested { max-width: 1200px; margin-top: 12px; }\n.nested table { min-width: 740px; font-size: 13px; }\n.empty { padding: 14px; color: #aebecd; }\n.foot { margin: 24px 0 8px; color: #8298ab; font-size: 13px; }\n@media (max-width: 700px) {\n    main { padding: 12px; }\n    h1 { font-size: 21px; }\n    .summary { grid-template-columns: 1fr 1fr; }\n}");
			stringBuilder.AppendLine("</style></head><body><main>");
			stringBuilder.Append("<h1>").Append(Html("Valheim Performance Analyzer")).AppendLine("</h1>");
			stringBuilder.Append("<p class=\"hint\">").Append(Html(ProfilerTranslations.Text("report_table_help"))).AppendLine("</p>");
			stringBuilder.Append("<div class=\"toolbar\"><input id=\"filter\" type=\"search\" placeholder=\"").Append(Html(ProfilerTranslations.Text("report_search"))).AppendLine("\"></div>");
			stringBuilder.Append("<h2>").Append(Html(ProfilerTranslations.Text("tab_summary"))).AppendLine("</h2><div class=\"summary\">");
			Card(stringBuilder, ProfilerTranslations.Text("last_capture"), snapshot.StartedAtUtc.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss", numberCulture));
			Card(stringBuilder, ProfilerTranslations.Text("duration_label"), snapshot.DurationSeconds.ToString("0.0", numberCulture) + " s");
			Card(stringBuilder, ProfilerTranslations.Text("fps"), Format(snapshot.FramesPerSecond));
			Card(stringBuilder, ProfilerTranslations.Text("frame"), Format(snapshot.AverageFrameMilliseconds) + " ms (" + ProfilerTranslations.Text("minmax") + ": " + Format(snapshot.MinFrameMilliseconds) + " / " + Format(snapshot.MaxFrameMilliseconds) + ")");
			Card(stringBuilder, ProfilerTranslations.Text("callback_share"), Format(ProfilerDataView.GetFrameBudgetPercent(snapshot)) + "%", ProfilerTranslations.Text("share_help"));
			Card(stringBuilder, ProfilerTranslations.Text("measured_calls"), ProfilerDataView.GetTotalCalls(snapshot).ToString("N0", numberCulture));
			Card(stringBuilder, ProfilerTranslations.Text("slow_frames"), snapshot.SlowFramesOver33Ms.ToString("N0", numberCulture) + " / " + snapshot.SlowFramesOver50Ms.ToString("N0", numberCulture));
			Card(stringBuilder, ProfilerTranslations.Text("memory"), Format((double)snapshot.ManagedMemoryBefore / 1048576.0) + " → " + Format((double)snapshot.ManagedMemoryAfter / 1048576.0) + " MB");
			Card(stringBuilder, ProfilerTranslations.Text("gc"), snapshot.Gen0Collections + " / " + snapshot.Gen1Collections + " / " + snapshot.Gen2Collections);
			Card(stringBuilder, ProfilerTranslations.Text("cpu_process"), snapshot.CpuAvailable ? (Format(snapshot.CpuPercentAverage) + "% / " + Format(snapshot.CpuPercentMaximum) + "%") : "—", ProfilerTranslations.Text("avg_peak"));
			Card(stringBuilder, ProfilerTranslations.Text("ram_process"), snapshot.ProcessRamAvailable ? (FormatMemory(snapshot.ProcessRamAverageMegabytes) + " / " + FormatMemory(snapshot.ProcessRamMaximumMegabytes)) : "—", ProfilerTranslations.Text("managed_heap") + ": " + FormatMemory(snapshot.ManagedHeapAverageMegabytes));
			string value = (snapshot.GpuUsageAvailable ? (Format(snapshot.GpuUsageAveragePercent) + "% / " + Format(snapshot.GpuUsageMaximumPercent) + "%") : "—");
			string text = snapshot.GpuDeviceName;
			if (snapshot.GpuMemoryUsedAvailable)
			{
				text = text + ((text.Length == 0) ? string.Empty : " · ") + ProfilerTranslations.Text("gpu_vram_used") + ": " + FormatMemory(snapshot.GpuMemoryUsedAverageMegabytes) + " / " + FormatMemory(snapshot.GpuMemoryUsedMaximumMegabytes);
			}
			if (snapshot.GpuMemoryMegabytes > 0)
			{
				text = text + ((text.Length == 0) ? string.Empty : " · ") + ProfilerTranslations.Text("gpu_memory") + ": " + FormatMemory(snapshot.GpuMemoryMegabytes);
			}
			text = text + ((text.Length == 0) ? string.Empty : " · ") + ProfilerTranslations.Text("gpu_frame_time") + ": " + (snapshot.GpuFrameTimingAvailable ? (Format(snapshot.GpuFrameTimeAverageMilliseconds) + " / " + Format(snapshot.GpuFrameTimeMaximumMilliseconds) + " ms") : ProfilerTranslations.Text("gpu_unavailable"));
			Card(stringBuilder, ProfilerTranslations.Text("gpu_usage"), value, text);
			string value2 = (snapshot.ProcessIoAvailable ? (Format(snapshot.IoReadMegabytes) + " / " + Format(snapshot.IoWriteMegabytes) + " MB") : "—");
			string detail = (snapshot.ProcessIoAvailable ? (ProfilerTranslations.Text("read_write_rate") + ": " + Format(snapshot.IoReadRateAverageMegabytesPerSecond) + " / " + Format(snapshot.IoWriteRateAverageMegabytesPerSecond)) : "—");
			Card(stringBuilder, ProfilerTranslations.Text("storage_io"), value2, detail);
			bool flag = snapshot.RemoteServerMetricSamples > 0;
			bool flag2 = snapshot.IsServerRuntime && snapshot.FixedUpdatesPerSecondAverage > 0.0;
			string value3 = (flag ? (Format(snapshot.RemoteServerTicksAverage) + " / " + Format(snapshot.RemoteServerTicksMinimum) + " / " + Format(snapshot.RemoteServerTicksMaximum)) : (flag2 ? (Format(snapshot.FixedUpdatesPerSecondAverage) + " / " + Format(snapshot.FixedUpdatesPerSecondMinimum) + " / " + Format(snapshot.FixedUpdatesPerSecondMaximum)) : "—"));
			string detail2 = (flag ? ProfilerTranslations.Format("server_detail", Format(snapshot.RemoteServerTargetTicks), Format(snapshot.RemoteServerCpuAverage), FormatMemory(snapshot.RemoteServerRamAverageMegabytes)) : (flag2 ? ProfilerTranslations.Format("server_detail", Format(snapshot.TargetFixedUpdatesPerSecond), Format(snapshot.CpuPercentAverage), FormatMemory(snapshot.ProcessRamAverageMegabytes)) : ProfilerTranslations.Text("server_missing")));
			Card(stringBuilder, ProfilerTranslations.Text("server_ticks"), value3, detail2);
			Card(stringBuilder, "Valheim", Html(snapshot.RuntimeVersion));
			Card(stringBuilder, ProfilerTranslations.Text("hide_valheim_callbacks"), ProfilerTranslations.Text(ProfilerDataView.HideVanilla ? "yes" : "no"));
			int num = 0;
			for (int i = 0; i < visibleObjects.Count; i++)
			{
				num += visibleObjects[i].CurrentInstances;
			}
			Card(stringBuilder, ProfilerTranslations.Text("tab_visible_objects"), snapshot.VisibleObjectScanAvailable ? num.ToString("N0", numberCulture) : "—", snapshot.VisibleObjectScanAvailable ? (ProfilerTranslations.Text("tab_visible_objects") + ": " + num.ToString("N0", numberCulture)) : ProfilerTranslations.Text("object_scan_policy"));
			stringBuilder.AppendLine("</div>");
			stringBuilder.Append("<h2>").Append(Html(ProfilerTranslations.Text("mod_cost_heading"))).AppendLine("</h2>");
			stringBuilder.Append("<p class=\"hint\">").Append(Html(ProfilerTranslations.Text("mods_help"))).AppendLine("</p>");
			stringBuilder.AppendLine("<div class=\"table-wrap\"><table class=\"interactive\"><thead><tr>");
			Header(stringBuilder, ProfilerTranslations.Text("mod_or_game"));
			Header(stringBuilder, ProfilerTranslations.Text("calls"), numeric: true);
			Header(stringBuilder, ProfilerTranslations.Text("self_ms"), numeric: true);
			Header(stringBuilder, ProfilerTranslations.Text("budget"), numeric: true);
			Header(stringBuilder, ProfilerTranslations.Text("measured_share_short"), numeric: true);
			stringBuilder.AppendLine("</tr></thead><tbody>");
			for (int j = 0; j < groups.Count; j++)
			{
				AssemblyGroupMetric assemblyGroupMetric = groups[j];
				string value4 = (assemblyGroupMetric.IsVanilla ? ProfilerTranslations.Text("vanilla_game") : assemblyGroupMetric.AssemblyName);
				double num2 = assemblyGroupMetric.FrameBudgetPercent(snapshot);
				double value5 = ((totalSelfMilliseconds <= 0.0) ? 0.0 : (assemblyGroupMetric.SelfMilliseconds * 100.0 / totalSelfMilliseconds));
				stringBuilder.AppendLine("<tr>");
				stringBuilder.Append("<td data-sort=\"").Append(Html(value4)).Append("\"><details><summary>")
					.Append(Html(value4))
					.AppendLine("</summary><div class=\"nested\">");
				AppendCallbackTable(stringBuilder, assemblyGroupMetric, snapshot);
				stringBuilder.AppendLine("</div></details></td>");
				Cell(stringBuilder, assemblyGroupMetric.Calls.ToString("N0", numberCulture), assemblyGroupMetric.Calls.ToString(CultureInfo.InvariantCulture), "number");
				Cell(stringBuilder, Format(assemblyGroupMetric.SelfMilliseconds), assemblyGroupMetric.SelfMilliseconds.ToString("0.000000", CultureInfo.InvariantCulture), "number");
				Cell(stringBuilder, Format(num2) + "%", num2.ToString("0.000000", CultureInfo.InvariantCulture), "number " + ImpactClass(num2