Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimBuildOptimization v0.3.0
plugins/ValheimBuildOptimization.dll
Decompiled a day agousing System; using System.Collections.Generic; 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; using UnityEngine.Rendering; [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 enum AppliedFireMode { None, StaticLight, FullCull } private class FireCandidate { public Piece Piece; public MeshRenderer[] Renderers; public Light[] OriginalLights; public ParticleSystem[] Particles; } private class FireOptimizationState { public Piece Piece; public AppliedFireMode AppliedMode = AppliedFireMode.None; public readonly Dictionary<Light, bool> OriginalLightEnabled = new Dictionary<Light, bool>(); public readonly Dictionary<ParticleSystem, bool> OriginalParticlePlaying = new Dictionary<ParticleSystem, bool>(); public readonly Dictionary<MeshRenderer, ShadowCastingMode> OriginalShadowModes = new Dictionary<MeshRenderer, ShadowCastingMode>(); public GameObject ProxyLightObject; public Light ProxyLight; public float LastVisibleTime; public float LastIrrelevantTime; } private enum FireCullingMode { Off, StaticLight, FullCull } private struct FireMetrics { public int FireCandidates; public int RendererVisibleFireCandidates; public int OccludedFireCandidates; public int RelevantFireCandidates; public int HiddenOrIrrelevantFireCandidates; public int OptimizedFirePieces; public int StaticLightFirePieces; public int FullCullFirePieces; public int FireProxyLightsActive; public int FireOriginalLightsDisabled; public int FireParticlesStopped; public int FireShadowsDisabled; } 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 int FireCandidates; public int RendererVisibleFireCandidates; public int OccludedFireCandidates; public int RelevantFireCandidates; public int HiddenOrIrrelevantFireCandidates; public int OptimizedFirePieces; public int StaticLightFirePieces; public int FullCullFirePieces; public int FireProxyLightsActive; public int FireOriginalLightsDisabled; public int FireParticlesStopped; public int FireShadowsDisabled; } public const string PluginGuid = "valheim.buildpieceprofiler"; public const string PluginName = "Build Piece Profiler"; public const string PluginVersion = "0.2.0"; private const string StaticFireLightProxyName = "BuildPieceProfiler_StaticFireLightProxy"; 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<bool> _enableProfiler; private ConfigEntry<bool> _enableConsoleLogging; private ConfigEntry<bool> _showProfilerOnStart; private ConfigEntry<float> _profilerPollInterval; private ConfigEntry<KeyCode> _toggleProfilerKey; private ConfigEntry<bool> _enableOptimizations; private ConfigEntry<float> _nearDistance; private ConfigEntry<float> _mediumDistance; private ConfigEntry<float> _farDistance; private ConfigEntry<float> _veryFarDistance; private ConfigEntry<float> _extremeDistance; private readonly Dictionary<Piece, FireOptimizationState> _fireStates = new Dictionary<Piece, FireOptimizationState>(); private readonly List<FireOptimizationState> _activeFireStates = new List<FireOptimizationState>(); private readonly List<FireCandidate> _fireCandidates = new List<FireCandidate>(); private FireMetrics _fireMetrics = default(FireMetrics); private float _nextOptimizerUpdateTime; private float _nextFireCandidateRefreshTime; private bool _optimizationsWereActive; private ConfigEntry<float> _optimizerUpdateInterval; private ConfigEntry<float> _fireCandidateRefreshInterval; private ConfigEntry<FireCullingMode> _fireCullingMode; private ConfigEntry<bool> _useFireVisibilityCulling; private ConfigEntry<float> _fireVisibilityGraceSeconds; private ConfigEntry<float> _neverOptimizeFireWithin; private ConfigEntry<float> _minimumFullCullDistance; private ConfigEntry<float> _fireDistanceCullStart; private ConfigEntry<float> _fireDistanceRestore; private ConfigEntry<float> _staticLightIntensityMultiplier; private ConfigEntry<float> _staticLightRangeMultiplier; private ConfigEntry<bool> _useFireOcclusionCulling; private ConfigEntry<float> _fireOcclusionRayRadius; private ConfigEntry<bool> _debugFireOcclusion; private ConfigEntry<float> _staticLightProxyMaxDistance; private ConfigEntry<float> _staticLightOccludedProxyMaxDistance; private ConfigEntry<float> _fireRestoreGraceSeconds; private Texture2D _opaqueBackground; private bool IsFireCandidate(Light[] lights, ParticleSystem[] particles) { if (lights == null || particles == null || lights.Length == 0 || particles.Length == 0) { return false; } bool flag = false; bool flag2 = false; foreach (Light val in lights) { if ((Object)(object)val != (Object)null) { flag = true; break; } } foreach (ParticleSystem val2 in particles) { if ((Object)(object)val2 != (Object)null) { flag2 = true; break; } } return flag && flag2; } private bool IsPieceVisible(MeshRenderer[] renderers) { if (renderers == null) { return false; } foreach (MeshRenderer val in renderers) { if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled && ((Component)val).gameObject.activeInHierarchy && ((Renderer)val).isVisible) { return true; } } return false; } private void LateUpdate() { if (_enableOptimizations.Value && _fireCullingMode.Value != 0) { EnforceOptimizedFireLightsOnly(); } } private void EnforceOptimizedFireLightsOnly() { for (int num = _activeFireStates.Count - 1; num >= 0; num--) { FireOptimizationState fireOptimizationState = _activeFireStates[num]; if (fireOptimizationState == null || fireOptimizationState.AppliedMode == AppliedFireMode.None) { _activeFireStates.RemoveAt(num); } else { foreach (KeyValuePair<Light, bool> item in fireOptimizationState.OriginalLightEnabled) { Light key = item.Key; if (!((Object)(object)key == (Object)null) && !IsOurProxyLight(key) && ((Behaviour)key).enabled) { ((Behaviour)key).enabled = false; } } if (fireOptimizationState.AppliedMode == AppliedFireMode.FullCull) { DisableProxyLight(fireOptimizationState); } } } } private void RestoreFire(Piece piece) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)piece == (Object)null || !_fireStates.TryGetValue(piece, out var value)) { return; } foreach (KeyValuePair<Light, bool> item in value.OriginalLightEnabled) { if ((Object)(object)item.Key != (Object)null) { ((Behaviour)item.Key).enabled = item.Value; } } foreach (KeyValuePair<MeshRenderer, ShadowCastingMode> originalShadowMode in value.OriginalShadowModes) { if ((Object)(object)originalShadowMode.Key != (Object)null) { ((Renderer)originalShadowMode.Key).shadowCastingMode = originalShadowMode.Value; } } foreach (KeyValuePair<ParticleSystem, bool> item2 in value.OriginalParticlePlaying) { ParticleSystem key = item2.Key; if (!((Object)(object)key == (Object)null)) { if (item2.Value) { key.Play(true); } else { key.Stop(true, (ParticleSystemStopBehavior)0); } } } DisableProxyLight(value); UntrackActiveFireState(value); value.AppliedMode = AppliedFireMode.None; value.OriginalLightEnabled.Clear(); value.OriginalShadowModes.Clear(); value.OriginalParticlePlaying.Clear(); } private void RestoreAllFireOptimizations() { List<Piece> list = new List<Piece>(_fireStates.Keys); foreach (Piece item in list) { RestoreFire(item); } DestroyAllProxyLights(); } private bool HasActiveFireOptimizations() { for (int num = _activeFireStates.Count - 1; num >= 0; num--) { FireOptimizationState fireOptimizationState = _activeFireStates[num]; if (fireOptimizationState != null && fireOptimizationState.AppliedMode != 0) { return true; } _activeFireStates.RemoveAt(num); } return false; } private void TrackActiveFireState(FireOptimizationState state) { if (state != null && state.AppliedMode != 0 && !_activeFireStates.Contains(state)) { _activeFireStates.Add(state); } } private void UntrackActiveFireState(FireOptimizationState state) { if (state != null) { _activeFireStates.Remove(state); } } private void ResetFireCandidateCache() { _fireCandidates.Clear(); _nextFireCandidateRefreshTime = 0f; _fireMetrics = default(FireMetrics); } private void CleanupDestroyedFireStates() { List<KeyValuePair<Piece, FireOptimizationState>> list = null; foreach (KeyValuePair<Piece, FireOptimizationState> fireState in _fireStates) { Piece key = fireState.Key; if (!((Object)(object)key != (Object)null)) { if (list == null) { list = new List<KeyValuePair<Piece, FireOptimizationState>>(); } list.Add(fireState); } } if (list == null) { return; } foreach (KeyValuePair<Piece, FireOptimizationState> item in list) { UntrackActiveFireState(item.Value); _fireStates.Remove(item.Key); } } private void RefreshFireCandidateCache() { _fireCandidates.Clear(); Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0); HashSet<Piece> hashSet = new HashSet<Piece>(); Piece[] array2 = array; foreach (Piece val in array2) { if ((Object)(object)val == (Object)null) { continue; } Light[] originalLights = GetOriginalLights(((Component)val).GetComponentsInChildren<Light>(true)); if (originalLights.Length != 0) { ParticleSystem[] componentsInChildren = ((Component)val).GetComponentsInChildren<ParticleSystem>(true); if (IsFireCandidate(originalLights, componentsInChildren)) { _fireCandidates.Add(new FireCandidate { Piece = val, Renderers = ((Component)val).GetComponentsInChildren<MeshRenderer>(true), OriginalLights = originalLights, Particles = componentsInChildren }); hashSet.Add(val); } } } List<Piece> list = null; foreach (KeyValuePair<Piece, FireOptimizationState> fireState in _fireStates) { Piece key = fireState.Key; FireOptimizationState value = fireState.Value; if (!((Object)(object)key == (Object)null) && value != null && value.AppliedMode != 0 && !hashSet.Contains(key)) { if (list == null) { list = new List<Piece>(); } list.Add(key); } } if (list != null) { foreach (Piece item in list) { RestoreFire(item); } } _nextFireCandidateRefreshTime = Time.time + Mathf.Max(1f, _fireCandidateRefreshInterval.Value); } private void OnDestroy() { RestoreAllFireOptimizations(); } private void ApplyStaticLight(Piece piece, FireOptimizationState state, MeshRenderer[] renderers, Light[] lights, ParticleSystem[] particles, bool useProxyLight, bool stopParticles) { if (state.AppliedMode != AppliedFireMode.StaticLight) { RestoreFire(piece); state = new FireOptimizationState { Piece = piece, LastVisibleTime = Time.time, LastIrrelevantTime = Time.time }; Light[] lights2 = (Light[])(((object)lights) ?? ((object)new Light[0])); StoreOriginalStates(state, renderers, lights2, particles); state.AppliedMode = AppliedFireMode.StaticLight; _fireStates[piece] = state; } TrackActiveFireState(state); Light[] lights3 = (Light[])(((object)lights) ?? ((object)new Light[0])); StoreOriginalStates(state, renderers, lights3, particles); if (useProxyLight) { Light firstUsableLight = GetFirstUsableLight(lights3); if ((Object)(object)firstUsableLight != (Object)null) { EnsureProxyLight(piece, state, firstUsableLight); } else { DisableProxyLight(state); } } else { DisableProxyLight(state); } DisableOriginalLights(lights3); if (stopParticles) { StopParticles(particles); } else { RestoreParticles(state, particles); } DisableShadows(renderers); } private void ApplyFullCull(Piece piece, FireOptimizationState state, MeshRenderer[] renderers, Light[] lights, ParticleSystem[] particles) { if (state.AppliedMode != AppliedFireMode.FullCull) { RestoreFire(piece); state = GetOrCreateFireState(piece); Light[] lights2 = (Light[])(((object)lights) ?? ((object)new Light[0])); StoreOriginalStates(state, renderers, lights2, particles); state.AppliedMode = AppliedFireMode.FullCull; } TrackActiveFireState(state); Light[] lights3 = (Light[])(((object)lights) ?? ((object)new Light[0])); StoreOriginalStates(state, renderers, lights3, particles); DisableProxyLight(state); DisableOriginalLights(lights3); StopParticles(particles); DisableShadows(renderers); } private void StoreOriginalStates(FireOptimizationState state, MeshRenderer[] renderers, Light[] lights, ParticleSystem[] particles) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) foreach (Light val in lights) { if (!((Object)(object)val == (Object)null) && !state.OriginalLightEnabled.ContainsKey(val)) { state.OriginalLightEnabled[val] = ((Behaviour)val).enabled; } } foreach (ParticleSystem val2 in particles) { if (!((Object)(object)val2 == (Object)null) && !state.OriginalParticlePlaying.ContainsKey(val2)) { state.OriginalParticlePlaying[val2] = val2.IsAlive(true); } } foreach (MeshRenderer val3 in renderers) { if (!((Object)(object)val3 == (Object)null) && !state.OriginalShadowModes.ContainsKey(val3)) { state.OriginalShadowModes[val3] = ((Renderer)val3).shadowCastingMode; } } } private void DisableOriginalLights(Light[] lights) { foreach (Light val in lights) { if (!((Object)(object)val == (Object)null)) { ((Behaviour)val).enabled = false; } } } private void DestroyAllProxyLights() { Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0); foreach (Piece val in array) { if ((Object)(object)val == (Object)null) { continue; } Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && ((Object)((Component)val2).gameObject).name == "BuildPieceProfiler_StaticFireLightProxy") { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } } private void RestoreParticles(FireOptimizationState state, ParticleSystem[] particles) { if (state == null || particles == null) { return; } foreach (ParticleSystem val in particles) { if (!((Object)(object)val == (Object)null) && state.OriginalParticlePlaying.TryGetValue(val, out var value) && value && ((Component)val).gameObject.activeInHierarchy && !val.isPlaying) { val.Play(true); } } } private void StopParticles(ParticleSystem[] particles) { foreach (ParticleSystem val in particles) { if (!((Object)(object)val == (Object)null)) { val.Stop(true, (ParticleSystemStopBehavior)0); } } } private void DisableShadows(MeshRenderer[] renderers) { foreach (MeshRenderer val in renderers) { if (!((Object)(object)val == (Object)null)) { ((Renderer)val).shadowCastingMode = (ShadowCastingMode)0; } } } private Light GetFirstUsableLight(Light[] lights) { foreach (Light val in lights) { if ((Object)(object)val != (Object)null) { return val; } } return null; } private void EnsureProxyLight(Piece piece, FireOptimizationState state, Light sourceLight) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown if ((Object)(object)piece == (Object)null || (Object)(object)sourceLight == (Object)null || state == null) { return; } if ((Object)(object)state.ProxyLightObject == (Object)null) { Transform val = ((Component)piece).transform.Find("BuildPieceProfiler_StaticFireLightProxy"); if ((Object)(object)val != (Object)null) { state.ProxyLightObject = ((Component)val).gameObject; state.ProxyLight = state.ProxyLightObject.GetComponent<Light>(); if ((Object)(object)state.ProxyLight == (Object)null) { state.ProxyLight = state.ProxyLightObject.AddComponent<Light>(); } } else { state.ProxyLightObject = new GameObject("BuildPieceProfiler_StaticFireLightProxy"); state.ProxyLightObject.transform.SetParent(((Component)piece).transform, false); state.ProxyLight = state.ProxyLightObject.AddComponent<Light>(); } } state.ProxyLightObject.transform.position = ((Component)sourceLight).transform.position; state.ProxyLightObject.transform.rotation = ((Component)sourceLight).transform.rotation; state.ProxyLightObject.SetActive(true); state.ProxyLight.type = (LightType)2; state.ProxyLight.color = sourceLight.color; state.ProxyLight.intensity = sourceLight.intensity * Mathf.Max(0f, _staticLightIntensityMultiplier.Value); state.ProxyLight.range = sourceLight.range * Mathf.Max(0f, _staticLightRangeMultiplier.Value); state.ProxyLight.shadows = (LightShadows)0; ((Behaviour)state.ProxyLight).enabled = true; } private void DisableProxyLight(FireOptimizationState state) { if ((Object)(object)state.ProxyLight != (Object)null) { ((Behaviour)state.ProxyLight).enabled = false; } if ((Object)(object)state.ProxyLightObject != (Object)null) { state.ProxyLightObject.SetActive(false); } } private FireOptimizationState GetOrCreateFireState(Piece piece) { if (_fireStates.TryGetValue(piece, out var value)) { return value; } value = new FireOptimizationState { Piece = piece, LastVisibleTime = Time.time, LastIrrelevantTime = Time.time }; _fireStates[piece] = value; return value; } private Vector3 GetFireTargetPosition(Piece piece, Light[] lights, MeshRenderer[] renderers) { //IL_0011: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (lights != null && lights.Length != 0) { Vector3 val = Vector3.zero; int num = 0; foreach (Light val2 in lights) { if (!((Object)(object)val2 == (Object)null)) { val += ((Component)val2).transform.position; num++; } } if (num > 0) { return val / (float)num; } } if (renderers != null && renderers.Length != 0) { Bounds bounds = default(Bounds); ((Bounds)(ref bounds))..ctor(((Component)piece).transform.position, Vector3.zero); bool flag = false; foreach (MeshRenderer val3 in renderers) { if (!((Object)(object)val3 == (Object)null)) { if (!flag) { bounds = ((Renderer)val3).bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(((Renderer)val3).bounds); } } } if (flag) { return ((Bounds)(ref bounds)).center; } } return ((Component)piece).transform.position; } private bool IsOurProxyLight(Light light) { if ((Object)(object)light == (Object)null) { return false; } if ((Object)(object)((Component)light).gameObject == (Object)null) { return false; } return ((Object)((Component)light).gameObject).name == "BuildPieceProfiler_StaticFireLightProxy"; } private Light[] GetOriginalLights(Light[] lights) { if (lights == null || lights.Length == 0) { return (Light[])(object)new Light[0]; } List<Light> list = new List<Light>(); foreach (Light val in lights) { if (!((Object)(object)val == (Object)null) && !IsOurProxyLight(val)) { list.Add(val); } } return list.ToArray(); } private bool HitBelongsToPiece(RaycastHit hit, Piece piece) { if ((Object)(object)piece == (Object)null || (Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { return false; } Transform val = ((Component)((RaycastHit)(ref hit)).collider).transform; while ((Object)(object)val != (Object)null) { if ((Object)(object)val == (Object)(object)((Component)piece).transform) { return true; } val = val.parent; } return false; } private bool IsFireOccludedFromCamera(Piece piece, Light[] lights, MeshRenderer[] renderers, Camera mainCamera) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (!_useFireOcclusionCulling.Value) { return false; } if ((Object)(object)piece == (Object)null || (Object)(object)mainCamera == (Object)null) { return false; } Vector3 position = ((Component)mainCamera).transform.position; Vector3 fireTargetPosition = GetFireTargetPosition(piece, lights, renderers); Vector3 val = fireTargetPosition - position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= 0.1f) { return false; } val /= magnitude; float num = Mathf.Max(0f, _fireOcclusionRayRadius.Value); RaycastHit hit = default(RaycastHit); bool flag = ((!(num > 0f)) ? Physics.Raycast(position, val, ref hit, magnitude, -5, (QueryTriggerInteraction)1) : Physics.SphereCast(position, num, val, ref hit, magnitude, -5, (QueryTriggerInteraction)1)); if (_debugFireOcclusion.Value) { Debug.DrawLine(position, fireTargetPosition, flag ? Color.red : Color.green, (_optimizerUpdateInterval != null) ? Mathf.Max(0.1f, _optimizerUpdateInterval.Value) : 0.5f); } if (!flag) { return false; } if (HitBelongsToPiece(hit, piece)) { return false; } return true; } private bool ShouldUseStaticProxyLight(float distance, bool relevant) { if (relevant) { return distance <= Mathf.Max(0f, _staticLightProxyMaxDistance.Value); } return distance <= Mathf.Max(0f, _staticLightOccludedProxyMaxDistance.Value); } private void AddFireOptimizationStateMetrics(ref FireMetrics metrics) { //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Invalid comparison between Unknown and I4 foreach (FireOptimizationState value in _fireStates.Values) { if (value == null || value.AppliedMode == AppliedFireMode.None) { continue; } metrics.OptimizedFirePieces++; if (value.AppliedMode == AppliedFireMode.StaticLight) { metrics.StaticLightFirePieces++; } if (value.AppliedMode == AppliedFireMode.FullCull) { metrics.FullCullFirePieces++; } if ((Object)(object)value.ProxyLight != (Object)null && ((Behaviour)value.ProxyLight).enabled && (Object)(object)value.ProxyLightObject != (Object)null && value.ProxyLightObject.activeInHierarchy) { metrics.FireProxyLightsActive++; } foreach (KeyValuePair<Light, bool> item in value.OriginalLightEnabled) { if ((Object)(object)item.Key != (Object)null && !IsOurProxyLight(item.Key) && !((Behaviour)item.Key).enabled && item.Value) { metrics.FireOriginalLightsDisabled++; } } foreach (KeyValuePair<ParticleSystem, bool> item2 in value.OriginalParticlePlaying) { if ((Object)(object)item2.Key != (Object)null && item2.Value && !item2.Key.IsAlive(true)) { metrics.FireParticlesStopped++; } } foreach (KeyValuePair<MeshRenderer, ShadowCastingMode> originalShadowMode in value.OriginalShadowModes) { if ((Object)(object)originalShadowMode.Key != (Object)null && (int)((Renderer)originalShadowMode.Key).shadowCastingMode == 0 && (int)originalShadowMode.Value > 0) { metrics.FireShadowsDisabled++; } } } } private void UpdateFireOptimizations() { //IL_0072: 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_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) if (_fireCullingMode.Value == FireCullingMode.Off) { if (HasActiveFireOptimizations()) { RestoreAllFireOptimizations(); } ResetFireCandidateCache(); return; } if ((Object)(object)Player.m_localPlayer == (Object)null) { if (HasActiveFireOptimizations()) { RestoreAllFireOptimizations(); } ResetFireCandidateCache(); return; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; Camera main = Camera.main; if (Time.time >= _nextFireCandidateRefreshTime || _fireCandidates.Count == 0) { RefreshFireCandidateCache(); } FireMetrics metrics = default(FireMetrics); for (int num = _fireCandidates.Count - 1; num >= 0; num--) { FireCandidate fireCandidate = _fireCandidates[num]; if (fireCandidate == null || (Object)(object)fireCandidate.Piece == (Object)null) { _fireCandidates.RemoveAt(num); continue; } Piece piece = fireCandidate.Piece; if ((Object)(object)piece == (Object)null) { _fireCandidates.RemoveAt(num); continue; } MeshRenderer[] renderers = fireCandidate.Renderers; Light[] originalLights = fireCandidate.OriginalLights; ParticleSystem[] particles = fireCandidate.Particles; if (!IsFireCandidate(originalLights, particles)) { RestoreFire(piece); _fireCandidates.RemoveAt(num); continue; } bool flag = IsPieceVisible(renderers); bool flag2 = flag && IsFireOccludedFromCamera(piece, originalLights, renderers, main); bool flag3 = flag && !flag2; metrics.FireCandidates++; if (flag) { metrics.RendererVisibleFireCandidates++; } if (flag2) { metrics.OccludedFireCandidates++; } if (flag3) { metrics.RelevantFireCandidates++; } else { metrics.HiddenOrIrrelevantFireCandidates++; } float num2 = Vector3.Distance(position, ((Component)piece).transform.position); FireOptimizationState orCreateFireState = GetOrCreateFireState(piece); if (flag3) { orCreateFireState.LastVisibleTime = Time.time; } else { orCreateFireState.LastIrrelevantTime = Time.time; } bool flag4 = !flag3; bool flag5 = _useFireVisibilityCulling.Value && flag4 && Time.time - orCreateFireState.LastVisibleTime >= Mathf.Max(0f, _fireVisibilityGraceSeconds.Value); bool flag6 = flag3 && Time.time - orCreateFireState.LastIrrelevantTime >= Mathf.Max(0f, _fireRestoreGraceSeconds.Value); bool flag7 = num2 >= Mathf.Max(1f, _fireDistanceCullStart.Value); bool flag8 = num2 <= Mathf.Max(1f, _fireDistanceRestore.Value); bool flag9 = num2 <= Mathf.Max(0f, _neverOptimizeFireWithin.Value); bool flag10 = !flag9 && (flag7 || flag5); bool flag11 = orCreateFireState.AppliedMode != AppliedFireMode.None; bool flag12 = flag6 && (flag8 || !flag7); if (flag9) { RestoreFire(piece); continue; } if (flag11) { if (flag12) { RestoreFire(piece); continue; } } else if (!flag10) { continue; } if (_fireCullingMode.Value == FireCullingMode.StaticLight) { bool useProxyLight = ShouldUseStaticProxyLight(num2, flag3); bool stopParticles = !flag3; ApplyStaticLight(piece, orCreateFireState, renderers, originalLights, particles, useProxyLight, stopParticles); } else if (_fireCullingMode.Value == FireCullingMode.FullCull) { float num3 = Mathf.Max(0f, _minimumFullCullDistance.Value); if (num2 >= num3 || flag7) { ApplyFullCull(piece, orCreateFireState, renderers, originalLights, particles); continue; } bool useProxyLight2 = ShouldUseStaticProxyLight(num2, flag3); bool stopParticles2 = !flag3; ApplyStaticLight(piece, orCreateFireState, renderers, originalLights, particles, useProxyLight2, stopParticles2); } } AddFireOptimizationStateMetrics(ref metrics); _fireMetrics = metrics; CleanupDestroyedFireStates(); } 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_0422: Unknown result type (might be due to invalid IL or missing references) _windowRect = _windowRectDefault; _enableProfiler = ((BaseUnityPlugin)this).Config.Bind<bool>("Profiler", "EnableProfiler", true, "Enables the profiler system. If false, no polling or overlay drawing is performed."); _enableConsoleLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("Profiler", "ShowProfilerOnStart", true, "Shows the profiler overlay when the world loads."); _profilerPollInterval = ((BaseUnityPlugin)this).Config.Bind<float>("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<KeyCode>("Profiler", "ToggleProfilerKey", (KeyCode)288, "Keyboard key used to toggle the profiler overlay."); _enableOptimizations = ((BaseUnityPlugin)this).Config.Bind<bool>("Optimizations", "EnableOptimizations", false, "Master switch for optimization features. Currently reserved for future optimizer systems."); _nearDistance = ((BaseUnityPlugin)this).Config.Bind<float>("DistanceThresholds", "NearDistance", 10f, "Near distance in meters. Pieces within this range should usually remain fully vanilla."); _mediumDistance = ((BaseUnityPlugin)this).Config.Bind<float>("DistanceThresholds", "MediumDistance", 25f, "Medium distance in meters. Good candidate range for safe shadow/effect reductions."); _farDistance = ((BaseUnityPlugin)this).Config.Bind<float>("DistanceThresholds", "FarDistance", 50f, "Far distance in meters. Good candidate range for more aggressive visual optimizations."); _veryFarDistance = ((BaseUnityPlugin)this).Config.Bind<float>("DistanceThresholds", "VeryFarDistance", 100f, "Very far distance in meters. Future proxy/mesh-combining territory."); _extremeDistance = ((BaseUnityPlugin)this).Config.Bind<float>("DistanceThresholds", "ExtremeDistance", 200f, "Extreme distance in meters. Future impostor/proxy-only territory."); _optimizerUpdateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Optimizations", "OptimizerUpdateIntervalSeconds", 0.5f, "How often the optimizer checks fire pieces, in seconds. Lower values react faster but cost more performance."); _fireCandidateRefreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Optimizations", "FireCandidateRefreshIntervalSeconds", 5f, "How often the optimizer does a full scene scan to discover fire pieces. Cached candidates are used between scans."); _fireRestoreGraceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "RestoreGraceSeconds", 1f, "How long a fire must remain relevant/visible before optimized fire effects are restored. Helps prevent flickering near occlusion edges."); _fireCullingMode = ((BaseUnityPlugin)this).Config.Bind<FireCullingMode>("FireCulling", "FireCullingMode", FireCullingMode.StaticLight, "Fire optimization mode. Off = no fire optimization, StaticLight = replace dynamic fire effects with a cheap static light, FullCull = disable fire visuals/effects at distance."); _useFireOcclusionCulling = ((BaseUnityPlugin)this).Config.Bind<bool>("FireCulling", "UseOcclusionCulling", true, "If true, fire candidates that are inside the camera view but blocked by solid geometry are treated as hidden/irrelevant."); _fireOcclusionRayRadius = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "OcclusionRayRadius", 0.05f, "Radius used for fire occlusion spherecasts. 0 uses a normal raycast. Small values like 0.05-0.15 can make occlusion detection more forgiving."); _debugFireOcclusion = ((BaseUnityPlugin)this).Config.Bind<bool>("FireCulling", "DebugFireOcclusion", false, "If true, draws debug rays for fire occlusion checks in the Unity scene view/logical debug view where supported."); _useFireVisibilityCulling = ((BaseUnityPlugin)this).Config.Bind<bool>("FireCulling", "UseVisibilityCulling", true, "If true, fire effects may be optimized when the fire is not visible for a short grace period."); _fireVisibilityGraceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "VisibilityGraceSeconds", 1.5f, "How long a fire must remain not visible before visibility-based optimization can activate."); _neverOptimizeFireWithin = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "NeverOptimizeFireWithin", 2f, "Fire pieces closer than this distance are never optimized."); _minimumFullCullDistance = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "MinimumFullCullDistance", 15f, "Minimum distance required before FullCull mode may fully remove fire light/effects due to visibility."); _fireDistanceCullStart = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "FireDistanceCullStart", 50f, "Distance beyond which fire optimization activates regardless of visibility."); _fireDistanceRestore = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "FireDistanceRestore", 40f, "Distance within which fire optimization restores to normal. Should be lower than FireDistanceCullStart."); _staticLightIntensityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "StaticLightIntensityMultiplier", 0.65f, "Multiplier for proxy static light intensity in StaticLight mode."); _staticLightRangeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "StaticLightRangeMultiplier", 0.85f, "Multiplier for proxy static light range in StaticLight mode."); _staticLightProxyMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "StaticLightProxyMaxDistance", 50f, "Maximum distance at which StaticLight mode may create a proxy light for relevant/visible fires. Beyond this, optimized fires get particles/shadows removed but no replacement light."); _staticLightOccludedProxyMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("FireCulling", "StaticLightOccludedProxyMaxDistance", 25f, "Maximum distance at which StaticLight mode may create a proxy light for hidden or occluded fires. Farther hidden fires receive no proxy light."); _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_001a: Unknown result type (might be due to invalid IL or missing references) if (_enableProfiler.Value) { if (Input.GetKeyDown(_toggleProfilerKey.Value)) { _showOverlay = !_showOverlay; } bool flag = _showOverlay || _enableConsoleLogging.Value; float num = Mathf.Max(0.1f, _profilerPollInterval.Value); if (flag && 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}")); } } } if (!_enableOptimizations.Value || _fireCullingMode.Value == FireCullingMode.Off) { if (_optimizationsWereActive || HasActiveFireOptimizations()) { RestoreAllFireOptimizations(); ResetFireCandidateCache(); } _optimizationsWereActive = false; return; } if (!_optimizationsWereActive) { _nextOptimizerUpdateTime = 0f; _nextFireCandidateRefreshTime = 0f; _optimizationsWereActive = true; } float num2 = Mathf.Max(0.1f, _optimizerUpdateInterval.Value); if (Time.time >= _nextOptimizerUpdateTime) { _nextOptimizerUpdateTime = Time.time + num2; UpdateFireOptimizations(); } } 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<GUILayoutOption>()); GUILayout.Label($"Poll interval: {_profilerPollInterval.Value:0.0}s", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Optimizations enabled: {_enableOptimizations.Value}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Global Scene Counts", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total Piece count: {_counts.Pieces}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total WearNTear count: {_counts.WearNTear}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total ZNetView count: {_counts.ZNetView}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Global Renderers", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total MeshRenderer count: {_counts.MeshRenderer}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Enabled MeshRenderer count: {_counts.EnabledMeshRenderer}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Visible MeshRenderer count: {_counts.VisibleMeshRenderer}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total LODGroup count: {_counts.LODGroup}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Global Physics", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total Collider count: {_counts.Collider}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Enabled Collider count: {_counts.EnabledCollider}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total active Rigidbody count: {_counts.ActiveRigidbody}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Global Effects", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total Light count: {_counts.Light}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Enabled Light count: {_counts.EnabledLight}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total ParticleSystem count: {_counts.ParticleSystem}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Active ParticleSystem count: {_counts.ActiveParticleSystem}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Total AudioSource count: {_counts.AudioSource}", Array.Empty<GUILayoutOption>()); GUILayout.Space(12f); GUILayout.Label("Build-Piece-Only Counts", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece MeshRenderer count: {_counts.PieceMeshRenderer}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece enabled MeshRenderer count: {_counts.PieceEnabledMeshRenderer}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece visible MeshRenderer count: {_counts.PieceVisibleMeshRenderer}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece LODGroup count: {_counts.PieceLODGroup}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Build-Piece Distance Buckets", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Pieces within Near ({_nearDistance.Value:0}m): {_counts.PiecesWithinNear}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Pieces within Medium ({_mediumDistance.Value:0}m): {_counts.PiecesWithinMedium}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Pieces within Far ({_farDistance.Value:0}m): {_counts.PiecesWithinFar}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Pieces within Very Far ({_veryFarDistance.Value:0}m): {_counts.PiecesWithinVeryFar}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Pieces within Extreme ({_extremeDistance.Value:0}m): {_counts.PiecesWithinExtreme}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Pieces beyond Extreme: {_counts.PiecesBeyondExtreme}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Nearest piece distance: {_counts.NearestPieceDistance:0.0}m", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Farthest piece distance: {_counts.FarthestPieceDistance:0.0}m", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Build-Piece Physics", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece Collider count: {_counts.PieceCollider}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece enabled Collider count: {_counts.PieceEnabledCollider}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece Rigidbody count: {_counts.PieceRigidbody}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece active Rigidbody count: {_counts.PieceActiveRigidbody}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Build-Piece Effects", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece Light count: {_counts.PieceLight}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece enabled Light count: {_counts.PieceEnabledLight}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece ParticleSystem count: {_counts.PieceParticleSystem}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece active ParticleSystem count: {_counts.PieceActiveParticleSystem}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Build-piece AudioSource count: {_counts.PieceAudioSource}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label("Fire Optimization Candidates", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Fire candidates: {_counts.FireCandidates}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Renderer-visible fire candidates: {_counts.RendererVisibleFireCandidates}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Occluded fire candidates: {_counts.OccludedFireCandidates}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Relevant fire candidates: {_counts.RelevantFireCandidates}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Hidden/irrelevant fire candidates: {_counts.HiddenOrIrrelevantFireCandidates}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Fire culling mode: {_fireCullingMode.Value}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Visibility culling: {_useFireVisibilityCulling.Value}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Occlusion culling: {_useFireOcclusionCulling.Value}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Optimized fire pieces: {_counts.OptimizedFirePieces}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"StaticLight fire pieces: {_counts.StaticLightFirePieces}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"FullCull fire pieces: {_counts.FullCullFirePieces}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Fire proxy lights active: {_counts.FireProxyLightsActive}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Original fire lights disabled: {_counts.FireOriginalLightsDisabled}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Fire particles stopped: {_counts.FireParticlesStopped}", Array.Empty<GUILayoutOption>()); GUILayout.Label($"Fire shadows disabled: {_counts.FireShadowsDisabled}", Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); if (GUILayout.Button("Poll now", Array.Empty<GUILayoutOption>())) { _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_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_037b: 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) Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0); WearNTear[] array2 = Object.FindObjectsByType<WearNTear>((FindObjectsSortMode)0); ZNetView[] array3 = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0); MeshRenderer[] array4 = Object.FindObjectsByType<MeshRenderer>((FindObjectsSortMode)0); Collider[] array5 = Object.FindObjectsByType<Collider>((FindObjectsSortMode)0); LODGroup[] array6 = Object.FindObjectsByType<LODGroup>((FindObjectsSortMode)0); Light[] array7 = Object.FindObjectsByType<Light>((FindObjectsSortMode)0); ParticleSystem[] array8 = Object.FindObjectsByType<ParticleSystem>((FindObjectsSortMode)0); AudioSource[] array9 = Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0); Rigidbody[] array10 = Object.FindObjectsByType<Rigidbody>((FindObjectsSortMode)0); 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; int num33 = 0; int num34 = 0; int num35 = 0; int num36 = 0; int num37 = 0; bool flag2 = _enableOptimizations.Value && _fireCullingMode.Value != FireCullingMode.Off; Camera mainCamera = (flag2 ? null : Camera.main); Piece[] array16 = array; foreach (Piece val7 in array16) { if ((Object)(object)val7 == (Object)null) { continue; } if (flag) { float num38 = Vector3.Distance(val6, ((Component)val7).transform.position); if (num38 <= num20) { num25++; } if (num38 <= num21) { num26++; } if (num38 <= num22) { num27++; } if (num38 <= num23) { num28++; } if (num38 <= num24) { num29++; } else { num30++; } if (num38 < num31) { num31 = num38; } if (num38 > num32) { num32 = num38; } } MeshRenderer[] componentsInChildren = ((Component)val7).GetComponentsInChildren<MeshRenderer>(true); Collider[] componentsInChildren2 = ((Component)val7).GetComponentsInChildren<Collider>(true); LODGroup[] componentsInChildren3 = ((Component)val7).GetComponentsInChildren<LODGroup>(true); Light[] componentsInChildren4 = ((Component)val7).GetComponentsInChildren<Light>(true); ParticleSystem[] componentsInChildren5 = ((Component)val7).GetComponentsInChildren<ParticleSystem>(true); if (!flag2) { Light[] originalLights = GetOriginalLights(componentsInChildren4); if (IsFireCandidate(originalLights, componentsInChildren5)) { num33++; bool flag3 = IsPieceVisible(componentsInChildren); bool flag4 = flag3 && IsFireOccludedFromCamera(val7, originalLights, componentsInChildren, mainCamera); bool flag5 = flag3 && !flag4; if (flag3) { num34++; } if (flag4) { num35++; } if (flag5) { num36++; } else { num37++; } } } AudioSource[] componentsInChildren6 = ((Component)val7).GetComponentsInChildren<AudioSource>(true); Rigidbody[] componentsInChildren7 = ((Component)val7).GetComponentsInChildren<Rigidbody>(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; } FireMetrics fireMetrics2; if (!flag2) { FireMetrics fireMetrics = default(FireMetrics); fireMetrics.FireCandidates = num33; fireMetrics.RendererVisibleFireCandidates = num34; fireMetrics.OccludedFireCandidates = num35; fireMetrics.RelevantFireCandidates = num36; fireMetrics.HiddenOrIrrelevantFireCandidates = num37; fireMetrics2 = fireMetrics; } else { fireMetrics2 = _fireMetrics; } FireMetrics metrics = fireMetrics2; if (!flag2) { AddFireOptimizationStateMetrics(ref metrics); } 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; result.FireCandidates = metrics.FireCandidates; result.RendererVisibleFireCandidates = metrics.RendererVisibleFireCandidates; result.OccludedFireCandidates = metrics.OccludedFireCandidates; result.RelevantFireCandidates = metrics.RelevantFireCandidates; result.HiddenOrIrrelevantFireCandidates = metrics.HiddenOrIrrelevantFireCandidates; result.OptimizedFirePieces = metrics.OptimizedFirePieces; result.StaticLightFirePieces = metrics.StaticLightFirePieces; result.FullCullFirePieces = metrics.FullCullFirePieces; result.FireProxyLightsActive = metrics.FireProxyLightsActive; result.FireOriginalLightsDisabled = metrics.FireOriginalLightsDisabled; result.FireParticlesStopped = metrics.FireParticlesStopped; result.FireShadowsDisabled = metrics.FireShadowsDisabled; return result; } }