using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ValheimBuildOptimization")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ValheimBuildOptimization")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("be15940e-381c-4623-a8d4-222869a01afc")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace BuildPieceProfiler; [BepInPlugin("valheim.buildpieceprofiler", "Build Piece Profiler", "0.2.0")] public class BuildPieceProfilerPlugin : BaseUnityPlugin { private struct Counts { public int Pieces; public int WearNTear; public int ZNetView; public int MeshRenderer; public int EnabledMeshRenderer; public int VisibleMeshRenderer; public int Collider; public int EnabledCollider; public int LODGroup; public int Light; public int EnabledLight; public int ParticleSystem; public int ActiveParticleSystem; public int AudioSource; public int ActiveRigidbody; public int PieceMeshRenderer; public int PieceEnabledMeshRenderer; public int PieceVisibleMeshRenderer; public int PieceCollider; public int PieceEnabledCollider; public int PieceLODGroup; public int PieceLight; public int PieceEnabledLight; public int PieceParticleSystem; public int PieceActiveParticleSystem; public int PieceAudioSource; public int PieceRigidbody; public int PieceActiveRigidbody; public int PiecesWithinNear; public int PiecesWithinMedium; public int PiecesWithinFar; public int PiecesWithinVeryFar; public int PiecesWithinExtreme; public int PiecesBeyondExtreme; public float NearestPieceDistance; public float FarthestPieceDistance; } public const string PluginGuid = "valheim.buildpieceprofiler"; public const string PluginName = "Build Piece Profiler"; public const string PluginVersion = "0.2.0"; private readonly Rect _windowRectDefault = new Rect(20f, 40f, 520f, 980f); private Rect _windowRect; private Vector2 _scrollPosition = Vector2.zero; private bool _showOverlay; private float _nextPollTime; private Counts _counts = default(Counts); private ConfigEntry _enableProfiler; private ConfigEntry _enableConsoleLogging; private ConfigEntry _showProfilerOnStart; private ConfigEntry _profilerPollInterval; private ConfigEntry _toggleProfilerKey; private ConfigEntry _enableOptimizations; private ConfigEntry _nearDistance; private ConfigEntry _mediumDistance; private ConfigEntry _farDistance; private ConfigEntry _veryFarDistance; private ConfigEntry _extremeDistance; private Texture2D _opaqueBackground; private void Awake() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) _windowRect = _windowRectDefault; _enableProfiler = ((BaseUnityPlugin)this).Config.Bind("Profiler", "EnableProfiler", true, "Enables the profiler system. If false, no polling or overlay drawing is performed."); _enableConsoleLogging = ((BaseUnityPlugin)this).Config.Bind("Profiler", "EnableConsoleLogging", false, "Writes profiler counts to the BepInEx log each poll. Useful for testing, but can create large log files."); _showProfilerOnStart = ((BaseUnityPlugin)this).Config.Bind("Profiler", "ShowProfilerOnStart", true, "Shows the profiler overlay when the world loads."); _profilerPollInterval = ((BaseUnityPlugin)this).Config.Bind("Profiler", "PollIntervalSeconds", 1f, "How often the profiler updates its counts, in seconds. Lower values update faster but cost more performance."); _toggleProfilerKey = ((BaseUnityPlugin)this).Config.Bind("Profiler", "ToggleProfilerKey", (KeyCode)288, "Keyboard key used to toggle the profiler overlay."); _enableOptimizations = ((BaseUnityPlugin)this).Config.Bind("Optimizations", "EnableOptimizations", false, "Master switch for optimization features. Currently reserved for future optimizer systems."); _nearDistance = ((BaseUnityPlugin)this).Config.Bind("DistanceThresholds", "NearDistance", 10f, "Near distance in meters. Pieces within this range should usually remain fully vanilla."); _mediumDistance = ((BaseUnityPlugin)this).Config.Bind("DistanceThresholds", "MediumDistance", 25f, "Medium distance in meters. Good candidate range for safe shadow/effect reductions."); _farDistance = ((BaseUnityPlugin)this).Config.Bind("DistanceThresholds", "FarDistance", 50f, "Far distance in meters. Good candidate range for more aggressive visual optimizations."); _veryFarDistance = ((BaseUnityPlugin)this).Config.Bind("DistanceThresholds", "VeryFarDistance", 100f, "Very far distance in meters. Future proxy/mesh-combining territory."); _extremeDistance = ((BaseUnityPlugin)this).Config.Bind("DistanceThresholds", "ExtremeDistance", 200f, "Extreme distance in meters. Future impostor/proxy-only territory."); _showOverlay = _showProfilerOnStart.Value; _opaqueBackground = MakeTexture(2, 2, new Color(0.05f, 0.05f, 0.05f, 1f)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Build Piece Profiler 0.2.0 loaded."); } private void Update() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!_enableProfiler.Value) { return; } if (Input.GetKeyDown(_toggleProfilerKey.Value)) { _showOverlay = !_showOverlay; } float num = Mathf.Max(0.1f, _profilerPollInterval.Value); if (Time.time >= _nextPollTime) { _nextPollTime = Time.time + num; _counts = PollCounts(); if (_enableConsoleLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)($"Pieces={_counts.Pieces}, " + $"WearNTear={_counts.WearNTear}, " + $"ZNetView={_counts.ZNetView}, " + $"MeshRenderer={_counts.MeshRenderer}, " + $"EnabledMeshRenderer={_counts.EnabledMeshRenderer}, " + $"VisibleMeshRenderer={_counts.VisibleMeshRenderer}, " + $"Collider={_counts.Collider}, " + $"EnabledCollider={_counts.EnabledCollider}, " + $"LODGroup={_counts.LODGroup}, " + $"Light={_counts.Light}, " + $"EnabledLight={_counts.EnabledLight}, " + $"ParticleSystem={_counts.ParticleSystem}, " + $"ActiveParticleSystem={_counts.ActiveParticleSystem}, " + $"AudioSource={_counts.AudioSource}, " + $"ActiveRigidbody={_counts.ActiveRigidbody}, " + $"PieceMeshRenderer={_counts.PieceMeshRenderer}, " + $"PieceEnabledMeshRenderer={_counts.PieceEnabledMeshRenderer}, " + $"PieceVisibleMeshRenderer={_counts.PieceVisibleMeshRenderer}, " + $"PieceCollider={_counts.PieceCollider}, " + $"PieceEnabledCollider={_counts.PieceEnabledCollider}")); } } } private void OnGUI() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (_enableProfiler.Value && _showOverlay) { _windowRect = GUILayout.Window(872391, _windowRect, new WindowFunction(DrawWindow), "Build Piece Profiler", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(520f), GUILayout.Height(940f) }); } } private void DrawWindow(int windowId) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height), (Texture)(object)_opaqueBackground, (ScaleMode)0); _scrollPosition = GUILayout.BeginScrollView(_scrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(500f), GUILayout.Height(1050f) }); GUILayout.Label("Toggle overlay: F7", Array.Empty()); GUILayout.Label($"Poll interval: {_profilerPollInterval.Value:0.0}s", Array.Empty()); GUILayout.Label($"Optimizations enabled: {_enableOptimizations.Value}", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Global Scene Counts", Array.Empty()); GUILayout.Label($"Total Piece count: {_counts.Pieces}", Array.Empty()); GUILayout.Label($"Total WearNTear count: {_counts.WearNTear}", Array.Empty()); GUILayout.Label($"Total ZNetView count: {_counts.ZNetView}", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Global Renderers", Array.Empty()); GUILayout.Label($"Total MeshRenderer count: {_counts.MeshRenderer}", Array.Empty()); GUILayout.Label($"Enabled MeshRenderer count: {_counts.EnabledMeshRenderer}", Array.Empty()); GUILayout.Label($"Visible MeshRenderer count: {_counts.VisibleMeshRenderer}", Array.Empty()); GUILayout.Label($"Total LODGroup count: {_counts.LODGroup}", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Global Physics", Array.Empty()); GUILayout.Label($"Total Collider count: {_counts.Collider}", Array.Empty()); GUILayout.Label($"Enabled Collider count: {_counts.EnabledCollider}", Array.Empty()); GUILayout.Label($"Total active Rigidbody count: {_counts.ActiveRigidbody}", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Global Effects", Array.Empty()); GUILayout.Label($"Total Light count: {_counts.Light}", Array.Empty()); GUILayout.Label($"Enabled Light count: {_counts.EnabledLight}", Array.Empty()); GUILayout.Label($"Total ParticleSystem count: {_counts.ParticleSystem}", Array.Empty()); GUILayout.Label($"Active ParticleSystem count: {_counts.ActiveParticleSystem}", Array.Empty()); GUILayout.Label($"Total AudioSource count: {_counts.AudioSource}", Array.Empty()); GUILayout.Space(12f); GUILayout.Label("Build-Piece-Only Counts", Array.Empty()); GUILayout.Label($"Build-piece MeshRenderer count: {_counts.PieceMeshRenderer}", Array.Empty()); GUILayout.Label($"Build-piece enabled MeshRenderer count: {_counts.PieceEnabledMeshRenderer}", Array.Empty()); GUILayout.Label($"Build-piece visible MeshRenderer count: {_counts.PieceVisibleMeshRenderer}", Array.Empty()); GUILayout.Label($"Build-piece LODGroup count: {_counts.PieceLODGroup}", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Build-Piece Distance Buckets", Array.Empty()); GUILayout.Label($"Pieces within Near ({_nearDistance.Value:0}m): {_counts.PiecesWithinNear}", Array.Empty()); GUILayout.Label($"Pieces within Medium ({_mediumDistance.Value:0}m): {_counts.PiecesWithinMedium}", Array.Empty()); GUILayout.Label($"Pieces within Far ({_farDistance.Value:0}m): {_counts.PiecesWithinFar}", Array.Empty()); GUILayout.Label($"Pieces within Very Far ({_veryFarDistance.Value:0}m): {_counts.PiecesWithinVeryFar}", Array.Empty()); GUILayout.Label($"Pieces within Extreme ({_extremeDistance.Value:0}m): {_counts.PiecesWithinExtreme}", Array.Empty()); GUILayout.Label($"Pieces beyond Extreme: {_counts.PiecesBeyondExtreme}", Array.Empty()); GUILayout.Label($"Nearest piece distance: {_counts.NearestPieceDistance:0.0}m", Array.Empty()); GUILayout.Label($"Farthest piece distance: {_counts.FarthestPieceDistance:0.0}m", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Build-Piece Physics", Array.Empty()); GUILayout.Label($"Build-piece Collider count: {_counts.PieceCollider}", Array.Empty()); GUILayout.Label($"Build-piece enabled Collider count: {_counts.PieceEnabledCollider}", Array.Empty()); GUILayout.Label($"Build-piece Rigidbody count: {_counts.PieceRigidbody}", Array.Empty()); GUILayout.Label($"Build-piece active Rigidbody count: {_counts.PieceActiveRigidbody}", Array.Empty()); GUILayout.Space(8f); GUILayout.Label("Build-Piece Effects", Array.Empty()); GUILayout.Label($"Build-piece Light count: {_counts.PieceLight}", Array.Empty()); GUILayout.Label($"Build-piece enabled Light count: {_counts.PieceEnabledLight}", Array.Empty()); GUILayout.Label($"Build-piece ParticleSystem count: {_counts.PieceParticleSystem}", Array.Empty()); GUILayout.Label($"Build-piece active ParticleSystem count: {_counts.PieceActiveParticleSystem}", Array.Empty()); GUILayout.Label($"Build-piece AudioSource count: {_counts.PieceAudioSource}", Array.Empty()); GUILayout.Space(8f); if (GUILayout.Button("Poll now", Array.Empty())) { _counts = PollCounts(); } GUILayout.EndScrollView(); GUI.DragWindow(); } private Texture2D MakeTexture(int width, int height, Color color) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002e: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = color; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } private Counts PollCounts() { //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) Piece[] array = Object.FindObjectsOfType(); WearNTear[] array2 = Object.FindObjectsOfType(); ZNetView[] array3 = Object.FindObjectsOfType(); MeshRenderer[] array4 = Object.FindObjectsOfType(); Collider[] array5 = Object.FindObjectsOfType(); LODGroup[] array6 = Object.FindObjectsOfType(); Light[] array7 = Object.FindObjectsOfType(); ParticleSystem[] array8 = Object.FindObjectsOfType(); AudioSource[] array9 = Object.FindObjectsOfType(); Rigidbody[] array10 = Object.FindObjectsOfType(); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; MeshRenderer[] array11 = array4; foreach (MeshRenderer val in array11) { if (!((Object)(object)val == (Object)null)) { if (((Renderer)val).enabled && ((Component)val).gameObject.activeInHierarchy) { num++; } if (((Renderer)val).enabled && ((Component)val).gameObject.activeInHierarchy && ((Renderer)val).isVisible) { num2++; } } } Collider[] array12 = array5; foreach (Collider val2 in array12) { if ((Object)(object)val2 != (Object)null && val2.enabled && ((Component)val2).gameObject.activeInHierarchy) { num3++; } } Light[] array13 = array7; foreach (Light val3 in array13) { if ((Object)(object)val3 != (Object)null && ((Behaviour)val3).enabled && ((Component)val3).gameObject.activeInHierarchy) { num4++; } } ParticleSystem[] array14 = array8; foreach (ParticleSystem val4 in array14) { if ((Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeInHierarchy && val4.IsAlive(true)) { num5++; } } Rigidbody[] array15 = array10; foreach (Rigidbody val5 in array15) { if ((Object)(object)val5 != (Object)null && ((Component)val5).gameObject.activeInHierarchy && !val5.IsSleeping()) { num6++; } } int num7 = 0; int num8 = 0; int num9 = 0; int num10 = 0; int num11 = 0; int num12 = 0; int num13 = 0; int num14 = 0; int num15 = 0; int num16 = 0; int num17 = 0; int num18 = 0; int num19 = 0; Vector3 val6 = Vector3.zero; bool flag = (Object)(object)Player.m_localPlayer != (Object)null; if (flag) { val6 = ((Component)Player.m_localPlayer).transform.position; } float num20 = Mathf.Max(1f, _nearDistance.Value); float num21 = Mathf.Max(num20, _mediumDistance.Value); float num22 = Mathf.Max(num21, _farDistance.Value); float num23 = Mathf.Max(num22, _veryFarDistance.Value); float num24 = Mathf.Max(num23, _extremeDistance.Value); int num25 = 0; int num26 = 0; int num27 = 0; int num28 = 0; int num29 = 0; int num30 = 0; float num31 = float.MaxValue; float num32 = 0f; Piece[] array16 = array; foreach (Piece val7 in array16) { if ((Object)(object)val7 == (Object)null) { continue; } if (flag) { float num33 = Vector3.Distance(val6, ((Component)val7).transform.position); if (num33 <= num20) { num25++; } if (num33 <= num21) { num26++; } if (num33 <= num22) { num27++; } if (num33 <= num23) { num28++; } if (num33 <= num24) { num29++; } else { num30++; } if (num33 < num31) { num31 = num33; } if (num33 > num32) { num32 = num33; } } MeshRenderer[] componentsInChildren = ((Component)val7).GetComponentsInChildren(true); Collider[] componentsInChildren2 = ((Component)val7).GetComponentsInChildren(true); LODGroup[] componentsInChildren3 = ((Component)val7).GetComponentsInChildren(true); Light[] componentsInChildren4 = ((Component)val7).GetComponentsInChildren(true); ParticleSystem[] componentsInChildren5 = ((Component)val7).GetComponentsInChildren(true); AudioSource[] componentsInChildren6 = ((Component)val7).GetComponentsInChildren(true); Rigidbody[] componentsInChildren7 = ((Component)val7).GetComponentsInChildren(true); num7 += componentsInChildren.Length; num10 += componentsInChildren2.Length; num12 += componentsInChildren3.Length; num13 += componentsInChildren4.Length; num15 += componentsInChildren5.Length; num17 += componentsInChildren6.Length; num18 += componentsInChildren7.Length; MeshRenderer[] array17 = componentsInChildren; foreach (MeshRenderer val8 in array17) { if (!((Object)(object)val8 == (Object)null)) { if (((Renderer)val8).enabled && ((Component)val8).gameObject.activeInHierarchy) { num8++; } if (((Renderer)val8).enabled && ((Component)val8).gameObject.activeInHierarchy && ((Renderer)val8).isVisible) { num9++; } } } Collider[] array18 = componentsInChildren2; foreach (Collider val9 in array18) { if ((Object)(object)val9 != (Object)null && val9.enabled && ((Component)val9).gameObject.activeInHierarchy) { num11++; } } Light[] array19 = componentsInChildren4; foreach (Light val10 in array19) { if ((Object)(object)val10 != (Object)null && ((Behaviour)val10).enabled && ((Component)val10).gameObject.activeInHierarchy) { num14++; } } ParticleSystem[] array20 = componentsInChildren5; foreach (ParticleSystem val11 in array20) { if ((Object)(object)val11 != (Object)null && ((Component)val11).gameObject.activeInHierarchy && val11.IsAlive(true)) { num16++; } } Rigidbody[] array21 = componentsInChildren7; foreach (Rigidbody val12 in array21) { if ((Object)(object)val12 != (Object)null && ((Component)val12).gameObject.activeInHierarchy && !val12.IsSleeping()) { num19++; } } } if (!flag || array.Length == 0) { num31 = 0f; num32 = 0f; } Counts result = default(Counts); result.Pieces = array.Length; result.WearNTear = array2.Length; result.ZNetView = array3.Length; result.MeshRenderer = array4.Length; result.EnabledMeshRenderer = num; result.VisibleMeshRenderer = num2; result.Collider = array5.Length; result.EnabledCollider = num3; result.LODGroup = array6.Length; result.Light = array7.Length; result.EnabledLight = num4; result.ParticleSystem = array8.Length; result.ActiveParticleSystem = num5; result.AudioSource = array9.Length; result.ActiveRigidbody = num6; result.PieceMeshRenderer = num7; result.PieceEnabledMeshRenderer = num8; result.PieceVisibleMeshRenderer = num9; result.PieceCollider = num10; result.PieceEnabledCollider = num11; result.PieceLODGroup = num12; result.PieceLight = num13; result.PieceEnabledLight = num14; result.PieceParticleSystem = num15; result.PieceActiveParticleSystem = num16; result.PieceAudioSource = num17; result.PieceRigidbody = num18; result.PieceActiveRigidbody = num19; result.PiecesWithinNear = num25; result.PiecesWithinMedium = num26; result.PiecesWithinFar = num27; result.PiecesWithinVeryFar = num28; result.PiecesWithinExtreme = num29; result.PiecesBeyondExtreme = num30; result.NearestPieceDistance = num31; result.FarthestPieceDistance = num32; return result; } }