using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LethalBoost.Config;
using LethalBoost.Core;
using LethalBoost.Core.Caching;
using LethalBoost.Core.Monitoring;
using LethalBoost.Core.Throttling;
using LethalBoost.Modules.AI;
using LethalBoost.Modules.Graphics;
using LethalBoost.Modules.Interior;
using LethalBoost.Modules.Physics;
using LethalBoost.Modules.Traps;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;
[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("LethalBoost")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Next-generation performance optimization mod for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LethalBoost")]
[assembly: AssemblyTitle("LethalBoost")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 LethalBoost
{
[BepInPlugin("com.lethalboost.performance", "LethalBoost", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private Harmony _harmony;
private PerformanceMonitor _performanceMonitor;
private ModuleErrorHandler _errorHandler;
private List<IOptimizationModule> _modules;
private Dictionary<IOptimizationModule, string> _moduleNames;
private float _lastCleanupTime;
private const float CLEANUP_INTERVAL = 30f;
public static Plugin Instance { get; private set; }
internal static ManualLogSource Log { get; private set; }
public static ManualLogSource Logger => Log;
public static Harmony Harmony => Instance?._harmony;
public static PerformanceMonitor PerformanceMonitor => Instance?._performanceMonitor;
public static AIOptimizationModule AIOptimizationModule { get; private set; }
public static LightCullingModule LightCullingModule { get; private set; }
public static ParticleModule ParticleModule { get; private set; }
public static RigidbodyModule RigidbodyModule { get; private set; }
public static PhysicsCullingModule PhysicsCullingModule { get; private set; }
public static RoomCullingModule RoomCullingModule { get; private set; }
public static DoorCullingModule DoorCullingModule { get; private set; }
public static InteriorLODModule InteriorLODModule { get; private set; }
public static GrassLODModule GrassLODModule { get; private set; }
public static RocksDebrisLODModule RocksDebrisLODModule { get; private set; }
public static DecalsLODModule DecalsLODModule { get; private set; }
public static ShadowQualityLODModule ShadowQualityLODModule { get; private set; }
public static PostProcessingLODModule PostProcessingLODModule { get; private set; }
public static CameraCullingModule CameraCullingModule { get; private set; }
public static TextureQualityLODModule TextureQualityLODModule { get; private set; }
public static ReflectionProbesLODModule ReflectionProbesLODModule { get; private set; }
public static AnimationCullingModule AnimationCullingModule { get; private set; }
public static NavMeshOptimizationModule NavMeshOptimizationModule { get; private set; }
public static TurretModule TurretModule { get; private set; }
public static LandmineModule LandmineModule { get; private set; }
public static SpikeTrapModule SpikeTrapModule { get; private set; }
public static bool IsServer()
{
if ((Object)(object)GameNetworkManager.Instance != (Object)null)
{
return GameNetworkManager.Instance.isHostingGame;
}
return false;
}
private void Awake()
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: 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_0057: Expected O, but got Unknown
Instance = this;
Log = Logger ?? Logger.CreateLogSource("LethalBoost");
if (Log == null)
{
Debug.LogError((object)"[LethalBoost] Failed to create logger!");
return;
}
Log.LogInfo((object)"=== LethalBoost v1.0.0 Starting ===");
GameObject val = new GameObject("LethalBoost_Core")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<LethalBoostBehaviour>().Initialize(this);
Log.LogInfo((object)"=== LethalBoost v1.0.0 Loaded Successfully ===");
}
internal void InitializeCore()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
try
{
_modules = new List<IOptimizationModule>();
_moduleNames = new Dictionary<IOptimizationModule, string>();
_harmony = new Harmony("com.lethalboost.performance");
ModConfig.Initialize(((BaseUnityPlugin)Instance).Config);
_errorHandler = new ModuleErrorHandler(Log);
CheckModCompatibility();
InitializeCoreSystems();
ApplyHarmonyPatches();
InitializeOptimizationModules();
InitializePerformanceMonitor();
}
catch (Exception ex)
{
Log.LogError((object)("CRITICAL ERROR during initialization: " + ex.Message));
Log.LogError((object)("Stack trace: " + ex.StackTrace));
}
}
private void CheckModCompatibility()
{
Log.LogInfo((object)"Checking mod compatibility...");
Version version = typeof(GameNetworkManager).Assembly.GetName().Version;
if (version != null && version.Major < 80)
{
Log.LogWarning((object)$"Game version mismatch! Expected v{80}+, got {version}. Some features may not work correctly.");
}
else
{
Log.LogInfo((object)$"Game version: {version}");
}
if (Chainloader.PluginInfos.ContainsKey("StaticNetcodeLib"))
{
Log.LogWarning((object)"StaticNetcodeLib detected. Component caching will be disabled.");
}
if (Chainloader.PluginInfos.ContainsKey("LethalOptimizer"))
{
Log.LogWarning((object)"LethalOptimizer detected. Consider using only one optimization mod.");
}
if (Chainloader.PluginInfos.ContainsKey("MoreCompany"))
{
Log.LogInfo((object)"MoreCompany detected. Player position caching will adapt.");
}
Log.LogInfo((object)"Mod compatibility check complete.");
}
private void InitializeCoreSystems()
{
Log.LogInfo((object)"Initializing core systems...");
ObjectPool.Configure(4, 16);
ComponentCache.SetMaxCacheSize(1000);
if (ModConfig.EnableNavMeshCaching.Value)
{
NavMeshCache.SetCacheExpirationTime(5f);
NavMeshCache.SetMaxCacheSize(500);
}
Log.LogInfo((object)"Core systems initialized.");
}
private void ApplyHarmonyPatches()
{
Log.LogInfo((object)"Applying Harmony patches...");
_harmony.PatchAll();
Log.LogInfo((object)"Harmony patches applied.");
}
private void InitializeOptimizationModules()
{
Log.LogInfo((object)"Initializing optimization modules...");
AIOptimizationModule = new AIOptimizationModule();
InitializeModule(AIOptimizationModule, "AI Optimization");
LightCullingModule = new LightCullingModule();
InitializeModule(LightCullingModule, "Light Culling");
ParticleModule = new ParticleModule();
InitializeModule(ParticleModule, "Particle Optimization");
RigidbodyModule = new RigidbodyModule();
InitializeModule(RigidbodyModule, "Rigidbody Freezing");
PhysicsCullingModule = new PhysicsCullingModule();
InitializeModule(PhysicsCullingModule, "Physics Culling");
RoomCullingModule = new RoomCullingModule();
InitializeModule(RoomCullingModule, "Room Culling");
DoorCullingModule = new DoorCullingModule();
InitializeModule(DoorCullingModule, "Door Culling");
InteriorLODModule = new InteriorLODModule();
InitializeModule(InteriorLODModule, "Interior LOD");
GrassLODModule = new GrassLODModule();
InitializeModule(GrassLODModule, "Grass LOD");
RocksDebrisLODModule = new RocksDebrisLODModule();
InitializeModule(RocksDebrisLODModule, "Rocks/Debris LOD");
DecalsLODModule = new DecalsLODModule();
InitializeModule(DecalsLODModule, "Decals LOD");
ShadowQualityLODModule = new ShadowQualityLODModule();
InitializeModule(ShadowQualityLODModule, "Shadow Quality LOD");
PostProcessingLODModule = new PostProcessingLODModule();
InitializeModule(PostProcessingLODModule, "Post-Processing LOD");
CameraCullingModule = new CameraCullingModule();
InitializeModule(CameraCullingModule, "Camera Culling");
TextureQualityLODModule = new TextureQualityLODModule();
InitializeModule(TextureQualityLODModule, "Texture Quality LOD");
ReflectionProbesLODModule = new ReflectionProbesLODModule();
InitializeModule(ReflectionProbesLODModule, "Reflection Probes LOD");
AnimationCullingModule = new AnimationCullingModule();
InitializeModule(AnimationCullingModule, "Animation Culling");
NavMeshOptimizationModule = new NavMeshOptimizationModule();
InitializeModule(NavMeshOptimizationModule, "NavMesh Optimization");
TurretModule = new TurretModule();
InitializeModule(TurretModule, "Turret Optimization");
LandmineModule = new LandmineModule();
InitializeModule(LandmineModule, "Landmine Optimization");
SpikeTrapModule = new SpikeTrapModule();
InitializeModule(SpikeTrapModule, "Spike Trap Optimization");
Log.LogInfo((object)$"Initialized {_modules.Count} optimization modules.");
}
private void InitializeModule(IOptimizationModule module, string moduleName)
{
if (module.IsEnabled)
{
if (_errorHandler.ExecuteModuleInitialize(module, moduleName))
{
_modules.Add(module);
_moduleNames[module] = moduleName;
}
}
else
{
Log.LogInfo((object)(moduleName + " module disabled."));
}
}
private void InitializePerformanceMonitor()
{
_performanceMonitor = new PerformanceMonitor(ModConfig.EnableDetailedMetrics.Value, ModConfig.EnablePerformanceOverlay.Value, ModConfig.EnableDebugLogging.Value);
Log.LogInfo((object)"Performance monitor initialized.");
}
internal void OnUpdate()
{
try
{
_performanceMonitor?.BeginFrame();
if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)RoundManager.Instance == (Object)null)
{
_performanceMonitor?.EndFrame();
return;
}
ComponentCache.EvictLRU();
if (_lastCleanupTime == 0f)
{
_lastCleanupTime = Time.time;
}
if (_modules != null && _moduleNames != null && _errorHandler != null)
{
foreach (IOptimizationModule module in _modules)
{
if (module != null && _moduleNames.ContainsKey(module))
{
_errorHandler.ExecuteModuleUpdate(module, _moduleNames[module], Time.time);
}
}
}
float time = Time.time;
if (time - _lastCleanupTime >= 30f)
{
PerformPeriodicCleanup();
_lastCleanupTime = time;
}
_performanceMonitor?.EndFrame();
}
catch (Exception arg)
{
Log.LogError((object)$"Error in Update loop: {arg}");
}
}
private void PerformPeriodicCleanup()
{
try
{
NavMeshCache.PeriodicCleanup();
if (ModConfig.EnableDebugLogging.Value)
{
(int, int) stats = ComponentCache.GetStats();
Log.LogInfo((object)$"ComponentCache: {stats.Item1}/{stats.Item2} entries");
}
}
catch (Exception arg)
{
Log.LogError((object)$"Error during cleanup: {arg}");
}
}
internal void OnGUIInternal()
{
try
{
_performanceMonitor?.RenderOverlay();
}
catch (Exception arg)
{
Log.LogError((object)$"Error rendering overlay: {arg}");
}
}
internal void Cleanup()
{
Log.LogInfo((object)"LethalBoost is unloading...");
if (_harmony != null)
{
_harmony.UnpatchSelf();
Log.LogInfo((object)"Harmony patches removed.");
}
if (_modules != null && _moduleNames != null && _errorHandler != null)
{
foreach (IOptimizationModule module in _modules)
{
if (module != null && _moduleNames.ContainsKey(module))
{
_errorHandler.ExecuteModuleCleanup(module, _moduleNames[module]);
}
}
_modules.Clear();
_moduleNames.Clear();
}
ComponentCache.Clear();
NavMeshCache.Clear();
ObjectPool.Clear();
_performanceMonitor?.Cleanup();
_errorHandler?.Clear();
Log.LogInfo((object)"LethalBoost unloaded successfully.");
}
}
public class LethalBoostBehaviour : MonoBehaviour
{
private Plugin _plugin;
private bool _initialized;
public void Initialize(Plugin plugin)
{
_plugin = plugin;
_initialized = false;
}
private void Start()
{
if (!_initialized)
{
_initialized = true;
_plugin.InitializeCore();
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)"LethalBoostBehaviour: Core initialized in Start()");
}
}
}
private void Update()
{
_plugin?.OnUpdate();
}
private void OnGUI()
{
_plugin?.OnGUIInternal();
}
private void OnDestroy()
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)"LethalBoostBehaviour: OnDestroy called");
}
_plugin?.Cleanup();
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "com.lethalboost.performance";
public const string PLUGIN_NAME = "LethalBoost";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace LethalBoost.Patches.Traps
{
[HarmonyPatch(typeof(Landmine))]
public class LandminePatches
{
private static LandmineModule _landmineModule;
private static FieldInfo _mineActivatedField;
public static void Initialize(LandmineModule landmineModule)
{
_landmineModule = landmineModule;
_mineActivatedField = AccessTools.Field(typeof(Landmine), "mineActivated");
if (_mineActivatedField == null)
{
Plugin.Logger.LogWarning((object)"Could not find mineActivated field in Landmine class");
}
}
private static bool GetMineActivated(Landmine instance)
{
if (_mineActivatedField == null)
{
return true;
}
return (bool)_mineActivatedField.GetValue(instance);
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(Landmine __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//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_005d: 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)
if (_landmineModule == null || !_landmineModule.IsEnabled)
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (__instance.hasExploded || !GetMineActivated(__instance))
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
bool flag = _landmineModule.ShouldLandmineUpdate(instanceID, position);
return _landmineModule.IsInDangerRadius(position) || flag;
}, "Landmine.Update");
}
[HarmonyPatch("OnTriggerEnter")]
[HarmonyPrefix]
private static bool OnTriggerEnter_Prefix(Landmine __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_002f: 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_003a: 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)
if (_landmineModule == null || !_landmineModule.IsEnabled)
{
return true;
}
if (__instance.hasExploded)
{
return true;
}
Vector3 position = ((Component)__instance).transform.position;
if (_landmineModule.IsInDangerRadius(position))
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
return _landmineModule.ShouldLandmineUpdate(instanceID, position);
}, "Landmine.OnTriggerEnter");
}
[HarmonyPatch("OnTriggerExit")]
[HarmonyPrefix]
private static bool OnTriggerExit_Prefix(Landmine __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_003c: 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_0063: Unknown result type (might be due to invalid IL or missing references)
if (_landmineModule == null || !_landmineModule.IsEnabled)
{
return true;
}
if (__instance.hasExploded || !GetMineActivated(__instance))
{
return true;
}
Vector3 position = ((Component)__instance).transform.position;
if (_landmineModule.IsInDangerRadius(position))
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
return _landmineModule.ShouldLandmineUpdate(instanceID, position);
}, "Landmine.OnTriggerExit");
}
[HarmonyPatch("MineHasLineOfSight")]
[HarmonyPrefix]
private static bool MineHasLineOfSight_Prefix(Landmine __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0020: 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_002b: 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)
if (_landmineModule == null || !_landmineModule.IsEnabled)
{
return true;
}
Vector3 position = ((Component)__instance).transform.position;
if (_landmineModule.IsInDangerRadius(position))
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
return _landmineModule.ShouldLandmineUpdate(instanceID, position);
}, "Landmine.MineHasLineOfSight");
}
public static void CleanupLandmine(Landmine landmine)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_landmineModule != null && (Object)(object)landmine != (Object)null)
{
int instanceID = ((Object)landmine).GetInstanceID();
_landmineModule.ClearLandmineData(instanceID);
}
}, "LandminePatches.CleanupLandmine");
}
}
[HarmonyPatch(typeof(SpikeRoofTrap))]
public class SpikeRoofTrapPatches
{
private static SpikeTrapModule _spikeTrapModule;
public static void Initialize(SpikeTrapModule spikeTrapModule)
{
_spikeTrapModule = spikeTrapModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(SpikeRoofTrap __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//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_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
if (_spikeTrapModule == null || !_spikeTrapModule.IsEnabled)
{
return true;
}
if (!__instance.trapActive || __instance.slammingDown)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
bool flag = _spikeTrapModule.ShouldSpikeTrapUpdate(instanceID, position);
return _spikeTrapModule.IsPlayerNearby(position) || flag;
}, "SpikeRoofTrap.Update");
}
[HarmonyPatch("OnTriggerStay")]
[HarmonyPrefix]
private static bool OnTriggerStay_Prefix(SpikeRoofTrap __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
if (_spikeTrapModule == null || !_spikeTrapModule.IsEnabled)
{
return true;
}
if (!__instance.trapActive)
{
return true;
}
if (__instance.slammingDown)
{
return true;
}
Vector3 position = ((Component)__instance).transform.position;
if (_spikeTrapModule.IsPlayerNearby(position))
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
return _spikeTrapModule.ShouldSpikeTrapUpdate(instanceID, position);
}, "SpikeRoofTrap.OnTriggerStay");
}
[HarmonyPatch("SpikeTrapSlam")]
[HarmonyPostfix]
private static void SpikeTrapSlam_Postfix(SpikeRoofTrap __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_spikeTrapModule != null && _spikeTrapModule.IsEnabled)
{
int instanceID = ((Object)__instance).GetInstanceID();
_spikeTrapModule.ClearSpikeTrapData(instanceID);
}
}, "SpikeRoofTrap.SpikeTrapSlam");
}
public static void CleanupSpikeTrap(SpikeRoofTrap spikeTrap)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_spikeTrapModule != null && (Object)(object)spikeTrap != (Object)null)
{
int instanceID = ((Object)spikeTrap).GetInstanceID();
_spikeTrapModule.ClearSpikeTrapData(instanceID);
}
}, "SpikeRoofTrapPatches.CleanupSpikeTrap");
}
}
[HarmonyPatch(typeof(Turret))]
public class TurretPatches
{
private static TurretModule _turretModule;
public static void Initialize(TurretModule turretModule)
{
_turretModule = turretModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(Turret __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
if (_turretModule == null || !_turretModule.IsEnabled)
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (!__instance.turretActive)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
bool flag = _turretModule.ShouldTurretUpdate(instanceID, position);
return _turretModule.IsInThreatRange(position) || flag;
}, "Turret.Update");
}
[HarmonyPatch("CheckForPlayersInLineOfSight")]
[HarmonyPrefix]
private static bool CheckForPlayersInLineOfSight_Prefix(Turret __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//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_0046: 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)
if (_turretModule == null || !_turretModule.IsEnabled)
{
return true;
}
if (!__instance.turretActive)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _turretModule.IsInThreatRange(position) || _turretModule.ShouldTurretUpdate(instanceID, position);
}, "Turret.CheckForPlayersInLineOfSight");
}
[HarmonyPatch("TurnTowardsTargetIfHasLOS")]
[HarmonyPrefix]
private static bool TurnTowardsTargetIfHasLOS_Prefix(Turret __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if (_turretModule == null || !_turretModule.IsEnabled)
{
return true;
}
if ((Object)(object)__instance.targetPlayerWithRotation != (Object)null)
{
Vector3 position = ((Component)__instance).transform.position;
if (_turretModule.IsInThreatRange(position))
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
return _turretModule.ShouldTurretUpdate(instanceID, position);
}
return true;
}, "Turret.TurnTowardsTargetIfHasLOS");
}
public static void CleanupTurret(Turret turret)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_turretModule != null && (Object)(object)turret != (Object)null)
{
int instanceID = ((Object)turret).GetInstanceID();
_turretModule.ClearTurretData(instanceID);
}
}, "TurretPatches.CleanupTurret");
}
}
}
namespace LethalBoost.Patches.Items
{
[HarmonyPatch(typeof(GrabbableObject))]
public class GrabbableObjectPatches
{
private static RigidbodyModule _rigidbodyModule;
public static void Initialize(RigidbodyModule rigidbodyModule)
{
_rigidbodyModule = rigidbodyModule;
}
private static bool IsFunctionalItem(GrabbableObject item)
{
if ((Object)(object)item == (Object)null)
{
return false;
}
string text = item.itemProperties?.itemName?.ToLower() ?? "";
if (text.Contains("walkie") || text.Contains("radio"))
{
return true;
}
if (text.Contains("flashlight") || text.Contains("lantern") || text.Contains("pro-flashlight") || text.Contains("laser"))
{
return true;
}
if (text.Contains("horn") || text.Contains("clown") || text.Contains("airhorn") || text.Contains("air horn"))
{
return true;
}
if (text.Contains("key") || text.Contains("card"))
{
return true;
}
if (text.Contains("shovel") || text.Contains("sign") || text.Contains("stop sign") || text.Contains("yield"))
{
return true;
}
if (text.Contains("jetpack"))
{
return true;
}
if (text.Contains("spray") || text.Contains("paint"))
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<FlashlightItem>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<WalkieTalkie>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<NoisemakerProp>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<Shovel>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<SprayPaintItem>() != (Object)null)
{
return true;
}
if ((Object)(object)item.itemProperties != (Object)null && item.itemProperties.requiresBattery)
{
return true;
}
return false;
}
[HarmonyPatch("GrabItem")]
[HarmonyPrefix]
public static void GrabItem_Prefix(GrabbableObject __instance)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_rigidbodyModule != null && _rigidbodyModule.IsEnabled && Plugin.IsServer() && !IsFunctionalItem(__instance) && (Object)(object)__instance.itemProperties != (Object)null && __instance.itemProperties.itemSpawnsOnGround)
{
Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
if ((Object)(object)component != (Object)null && component.isKinematic)
{
component.isKinematic = false;
}
}
}, "GrabbableObject.GrabItem");
}
[HarmonyPatch("DiscardItem")]
[HarmonyPostfix]
public static void DiscardItem_Postfix(GrabbableObject __instance)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_rigidbodyModule != null && _rigidbodyModule.IsEnabled && Plugin.IsServer() && !IsFunctionalItem(__instance))
{
Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
if ((Object)(object)component != (Object)null && !component.isKinematic)
{
component.WakeUp();
}
}
}, "GrabbableObject.DiscardItem");
}
[HarmonyPatch("FallWithCurve")]
[HarmonyPrefix]
public static void FallWithCurve_Prefix(GrabbableObject __instance)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_rigidbodyModule != null && _rigidbodyModule.IsEnabled && Plugin.IsServer() && !IsFunctionalItem(__instance))
{
Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
if ((Object)(object)component != (Object)null && component.isKinematic)
{
component.isKinematic = false;
}
}
}, "GrabbableObject.FallWithCurve");
}
}
}
namespace LethalBoost.Patches.Interior
{
[HarmonyPatch]
internal static class DoorPatches
{
private static DoorCullingModule _doorCullingModule;
public static void Initialize(DoorCullingModule doorCullingModule)
{
_doorCullingModule = doorCullingModule;
}
[HarmonyPatch(typeof(DoorLock), "LockDoor")]
[HarmonyPostfix]
private static void LockDoor_Postfix(DoorLock __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_doorCullingModule != null && _doorCullingModule.IsEnabled && !((Object)(object)__instance == (Object)null))
{
_ = (Object)(object)__instance.doorTrigger != (Object)null;
}
}, "DoorLock.LockDoor");
}
[HarmonyPatch(typeof(InteractTrigger), "Interact")]
[HarmonyPrefix]
private static void Interact_Prefix(InteractTrigger __instance)
{
PatchErrorHandler.SafeExecute(delegate
{
if (_doorCullingModule != null && _doorCullingModule.IsEnabled && !((Object)(object)__instance == (Object)null) && (Object)(object)((Component)__instance).GetComponent<DoorLock>() != (Object)null)
{
Renderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Renderer>();
foreach (Renderer val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && !val.enabled)
{
val.enabled = true;
}
}
}
}, "InteractTrigger.Interact");
}
}
[HarmonyPatch]
internal static class InteriorPropPatches
{
private static InteriorLODModule _interiorLODModule;
public static void Initialize(InteriorLODModule interiorLODModule)
{
_interiorLODModule = interiorLODModule;
}
[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
[HarmonyPostfix]
private static void SpawnScrapInLevel_Postfix(RoundManager __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_interiorLODModule != null && _interiorLODModule.IsEnabled)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)"Scrap spawned in level, interior LOD will track new items.");
}
}
}, "RoundManager.SpawnScrapInLevel");
}
[HarmonyPatch(typeof(Terminal), "Start")]
[HarmonyPostfix]
private static void Terminal_Start_Postfix(Terminal __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_interiorLODModule != null && _interiorLODModule.IsEnabled && !((Object)(object)__instance == (Object)null))
{
_interiorLODModule.RegisterProp(((Component)__instance).gameObject, isCritical: true);
}
}, "Terminal.Start");
}
[HarmonyPatch(typeof(DoorLock), "Awake")]
[HarmonyPostfix]
private static void DoorLock_Awake_Postfix(DoorLock __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_interiorLODModule != null && _interiorLODModule.IsEnabled && !((Object)(object)__instance == (Object)null))
{
_interiorLODModule.RegisterProp(((Component)__instance).gameObject, isCritical: true);
}
}, "DoorLock.Awake");
}
[HarmonyPatch(typeof(GrabbableObject), "Start")]
[HarmonyPostfix]
private static void GrabbableObject_Start_Postfix(GrabbableObject __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_interiorLODModule != null && _interiorLODModule.IsEnabled && !((Object)(object)__instance == (Object)null))
{
_interiorLODModule.RegisterProp(((Component)__instance).gameObject, isCritical: true);
}
}, "GrabbableObject.Start");
}
[HarmonyPatch(typeof(EntranceTeleport), "Awake")]
[HarmonyPostfix]
private static void EntranceTeleport_Awake_Postfix(EntranceTeleport __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_interiorLODModule != null && _interiorLODModule.IsEnabled && !((Object)(object)__instance == (Object)null))
{
_interiorLODModule.RegisterProp(((Component)__instance).gameObject, isCritical: true);
}
}, "EntranceTeleport.Awake");
}
private static bool IsInteriorProp(GameObject obj)
{
if ((Object)(object)obj == (Object)null)
{
return false;
}
string text = LayerMask.LayerToName(obj.layer);
if (text.Contains("Room") || text.Contains("Props") || text.Contains("MapProps") || text.Contains("Interior"))
{
return true;
}
Transform val = obj.transform;
while ((Object)(object)val != (Object)null)
{
if (((Object)val).name.Contains("Dungeon") || ((Object)val).name.Contains("Interior") || ((Object)val).name.Contains("Room"))
{
return true;
}
val = val.parent;
}
return false;
}
private static bool IsCriticalProp(GameObject obj)
{
if ((Object)(object)obj == (Object)null)
{
return false;
}
if ((Object)(object)obj.GetComponent<Terminal>() != (Object)null || (Object)(object)obj.GetComponent<DoorLock>() != (Object)null || (Object)(object)obj.GetComponent<InteractTrigger>() != (Object)null || (Object)(object)obj.GetComponent<GrabbableObject>() != (Object)null || (Object)(object)obj.GetComponent<EntranceTeleport>() != (Object)null)
{
return true;
}
string text = ((Object)obj).name.ToLower();
if (text.Contains("terminal") || text.Contains("door") || text.Contains("entrance") || text.Contains("exit") || text.Contains("ladder") || text.Contains("vent") || text.Contains("breaker") || text.Contains("apparatus"))
{
return true;
}
return false;
}
}
[HarmonyPatch]
internal static class RoomPatches
{
private static RoomCullingModule _roomCullingModule;
public static void Initialize(RoomCullingModule roomCullingModule)
{
_roomCullingModule = roomCullingModule;
}
[HarmonyPatch(typeof(AdjacentRoomCullingModified), "AddDungeon")]
[HarmonyPostfix]
private static void AddDungeon_Postfix(AdjacentRoomCullingModified __instance, Dungeon dungeon)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_roomCullingModule != null && _roomCullingModule.IsEnabled && !((Object)(object)dungeon == (Object)null))
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"Dungeon added with {dungeon.AllTiles.Count} tiles.");
}
}
}, "AdjacentRoomCullingModified.AddDungeon");
}
[HarmonyPatch(typeof(RoundManager), "GenerateNewFloor")]
[HarmonyPostfix]
private static void GenerateNewFloor_Postfix(RoundManager __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_roomCullingModule != null && _roomCullingModule.IsEnabled)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)"New floor generated, room culling will rebuild.");
}
}
}, "RoundManager.GenerateNewFloor");
}
[HarmonyPatch(typeof(StartOfRound), "ShipLeave")]
[HarmonyPostfix]
private static void ShipLeave_Postfix(StartOfRound __instance)
{
PatchErrorHandler.ExecutePostfix(delegate
{
if (_roomCullingModule != null && _roomCullingModule.IsEnabled)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)"Ship leaving, room culling state will be cleaned.");
}
}
}, "StartOfRound.ShipLeave");
}
}
}
namespace LethalBoost.Patches.Base
{
[HarmonyPatch]
internal static class LightPatches
{
private static LightCullingModule _lightModule;
private static readonly Dictionary<int, Component> _parentComponentCache = new Dictionary<int, Component>();
private const int CACHE_MAX_SIZE = 500;
private static int _cacheClearCounter = 0;
private const int CACHE_CLEAR_INTERVAL = 1000;
public static void Initialize(LightCullingModule lightModule)
{
_lightModule = lightModule;
_parentComponentCache.Clear();
}
private static T GetComponentInParentCached<T>(GameObject obj) where T : Component
{
if ((Object)(object)obj == (Object)null)
{
return default(T);
}
int key = ((Object)obj).GetInstanceID() ^ typeof(T).GetHashCode();
if (_parentComponentCache.TryGetValue(key, out var value))
{
if ((Object)(object)value != (Object)null && Object.op_Implicit((Object)(object)value))
{
return (T)(object)((value is T) ? value : null);
}
_parentComponentCache.Remove(key);
}
T componentInParent = obj.GetComponentInParent<T>();
if ((Object)(object)componentInParent != (Object)null && _parentComponentCache.Count < 500)
{
_parentComponentCache[key] = (Component)(object)componentInParent;
}
return componentInParent;
}
public static bool IsCriticalLight(Light light)
{
if ((Object)(object)light == (Object)null)
{
return false;
}
GameObject gameObject = ((Component)light).gameObject;
_cacheClearCounter++;
if (_cacheClearCounter >= 1000)
{
_cacheClearCounter = 0;
_parentComponentCache.Clear();
}
if ((Object)(object)GetComponentInParentCached<FlashlightItem>(gameObject) != (Object)null)
{
return true;
}
if ((Object)(object)GetComponentInParentCached<ShipLights>(gameObject) != (Object)null)
{
return true;
}
if ((Object)(object)GetComponentInParentCached<Terminal>(gameObject) != (Object)null)
{
return true;
}
if (((Object)gameObject).name.Contains("Emergency") || ((Object)gameObject).name.Contains("MainLight") || gameObject.CompareTag("ImportantLight"))
{
return true;
}
if (light.intensity > 5f)
{
return true;
}
return false;
}
}
[HarmonyPatch]
internal static class ParticlePatches
{
private static ParticleModule _particleModule;
public static void Initialize(ParticleModule particleModule)
{
_particleModule = particleModule;
}
public static bool IsCriticalParticleSystem(ParticleSystem particleSystem)
{
if ((Object)(object)particleSystem == (Object)null)
{
return false;
}
GameObject gameObject = ((Component)particleSystem).gameObject;
if ((Object)(object)gameObject.GetComponentInParent<PlayerControllerB>() != (Object)null)
{
return true;
}
if ((Object)(object)gameObject.GetComponentInParent<GrabbableObject>() != (Object)null)
{
return true;
}
if (((Object)gameObject).name.Contains("Player") || ((Object)gameObject).name.Contains("Critical") || gameObject.CompareTag("Important"))
{
return true;
}
return false;
}
}
}
namespace LethalBoost.Patches.AI
{
public static class AIPatchManager
{
private static bool _patchesApplied;
public static void ApplyPatches(Harmony harmony, AIOptimizationModule aiModule)
{
if (_patchesApplied)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)"AI patches already applied.");
}
return;
}
if (!ModConfig.EnableAIOptimization.Value)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)"AI optimization disabled in configuration. Skipping AI patches.");
}
return;
}
try
{
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogInfo((object)"Applying AI optimization patches...");
}
EnemyAIPatches.Initialize(aiModule);
harmony.PatchAll(typeof(EnemyAIPatches));
ManualLogSource log4 = Plugin.Log;
if (log4 != null)
{
log4.LogInfo((object)"Applied base EnemyAI patches.");
}
List<Type> list = new List<Type>();
if (ModConfig.OptimizeCoilHead.Value)
{
CoilHeadPatches.Initialize(aiModule);
list.Add(typeof(CoilHeadPatches));
}
if (ModConfig.OptimizeJester.Value)
{
JesterPatches.Initialize(aiModule);
list.Add(typeof(JesterPatches));
}
if (ModConfig.OptimizeThumper.Value)
{
ThumperPatches.Initialize(aiModule);
list.Add(typeof(ThumperPatches));
}
if (ModConfig.OptimizeHoardingBug.Value)
{
HoardingBugPatches.Initialize(aiModule);
list.Add(typeof(HoardingBugPatches));
}
if (ModConfig.OptimizeSporeLizard.Value)
{
SporeLizardPatches.Initialize(aiModule);
list.Add(typeof(SporeLizardPatches));
}
if (ModConfig.OptimizeBunkerSpider.Value)
{
BunkerSpiderPatches.Initialize(aiModule);
list.Add(typeof(BunkerSpiderPatches));
}
if (ModConfig.OptimizeForestKeeper.Value)
{
ForestKeeperPatches.Initialize(aiModule);
list.Add(typeof(ForestKeeperPatches));
}
if (ModConfig.OptimizeEyelessDog.Value)
{
EyelessDogPatches.Initialize(aiModule);
list.Add(typeof(EyelessDogPatches));
}
if (ModConfig.OptimizeBaboonHawk.Value)
{
BaboonHawkPatches.Initialize(aiModule);
list.Add(typeof(BaboonHawkPatches));
}
int count = list.Count;
foreach (Type item in list)
{
harmony.PatchAll(item);
}
_patchesApplied = true;
ManualLogSource log5 = Plugin.Log;
if (log5 != null)
{
log5.LogInfo((object)$"Applied {count} enemy-specific AI patches successfully.");
}
}
catch (Exception arg)
{
ManualLogSource log6 = Plugin.Log;
if (log6 != null)
{
log6.LogError((object)$"Failed to apply AI patches: {arg}");
}
throw;
}
}
public static void RemovePatches(Harmony harmony)
{
if (!_patchesApplied)
{
return;
}
try
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)"Removing AI optimization patches...");
}
harmony.UnpatchSelf();
_patchesApplied = false;
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)"AI optimization patches removed successfully.");
}
}
catch (Exception arg)
{
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogError((object)$"Error removing AI patches: {arg}");
}
}
}
}
[HarmonyPatch(typeof(BaboonBirdAI))]
internal static class BaboonHawkPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(BaboonBirdAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Baboon Hawk"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex >= 1)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "BaboonBirdAI.Update");
}
}
[HarmonyPatch(typeof(SandSpiderAI))]
internal static class BunkerSpiderPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(SandSpiderAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Bunker Spider"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "SandSpiderAI.Update");
}
}
[HarmonyPatch(typeof(SpringManAI))]
internal static class CoilHeadPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(SpringManAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//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_0050: 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)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Coil-Head"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1)
{
return true;
}
Vector3 position = ((Component)__instance).transform.position;
if (DistanceThrottler.GetClosestPlayerDistance(position) < 10f)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "SpringManAI.Update");
}
}
[HarmonyPatch(typeof(EnemyAI))]
internal static class EnemyAIPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(EnemyAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled)
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (__instance.isEnemyDead || __instance.inSpecialAnimation)
{
return true;
}
if ((Object)(object)__instance.enemyType != (Object)null)
{
string enemyName = __instance.enemyType.enemyName;
if (!string.IsNullOrEmpty(enemyName) && !_aiModule.IsEnemyTypeOptimizationEnabled(enemyName))
{
return true;
}
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "EnemyAI.Update");
}
[HarmonyPatch("DoAIInterval")]
[HarmonyPrefix]
private static void DoAIInterval_Prefix(EnemyAI __instance, out float __state)
{
__state = __instance.AIIntervalTime;
PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled)
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (__instance.isEnemyDead || __instance.inSpecialAnimation)
{
return true;
}
if ((Object)(object)__instance.enemyType != (Object)null)
{
string enemyName = __instance.enemyType.enemyName;
if (!string.IsNullOrEmpty(enemyName) && !_aiModule.IsEnemyTypeOptimizationEnabled(enemyName))
{
return true;
}
}
Vector3 position = ((Component)__instance).transform.position;
float aIIntervalMultiplier = _aiModule.GetAIIntervalMultiplier(position);
EnemyType enemyType = __instance.enemyType;
float num = ((enemyType != null && enemyType.isOutsideEnemy) ? 0.1f : 0.2f);
__instance.AIIntervalTime = num * aIIntervalMultiplier;
return true;
}, "EnemyAI.DoAIInterval");
}
[HarmonyPatch("DoAIInterval")]
[HarmonyPostfix]
private static void DoAIInterval_Postfix(EnemyAI __instance, float __state)
{
PatchErrorHandler.ExecutePostfix(delegate
{
__instance.AIIntervalTime = __state;
}, "EnemyAI.DoAIInterval");
}
}
[HarmonyPatch(typeof(MouthDogAI))]
internal static class EyelessDogPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(MouthDogAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0064: 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_0070: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Eyeless Dog"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1 || ((EnemyAI)__instance).currentBehaviourStateIndex == 2)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "MouthDogAI.Update");
}
}
[HarmonyPatch(typeof(ForestGiantAI))]
internal static class ForestKeeperPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(ForestGiantAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Forest Keeper"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "ForestGiantAI.Update");
}
}
[HarmonyPatch(typeof(HoarderBugAI))]
internal static class HoardingBugPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(HoarderBugAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: 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_0068: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Hoarding Bug"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
Vector3 position = ((Component)__instance).transform.position;
int instanceID = ((Object)__instance).GetInstanceID();
bool flag = _aiModule.ShouldEnemyUpdate(instanceID, position);
if (ModConfig.EnableDebugLogging.Value && !flag)
{
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(position);
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"HoardingBug: Throttled (distance={closestPlayerDistance:F1}m)");
}
}
return flag;
}, "HoarderBugAI.Update");
}
}
[HarmonyPatch(typeof(JesterAI))]
internal static class JesterPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(JesterAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Jester"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex >= 1)
{
if (ModConfig.EnableDebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"Jester: In critical state ({((EnemyAI)__instance).currentBehaviourStateIndex}), always updating");
}
}
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(position);
bool flag = _aiModule.ShouldEnemyUpdate(instanceID, position);
if (ModConfig.EnableDebugLogging.Value && !flag)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogDebug((object)$"Jester: Roaming state, distance={closestPlayerDistance:F1}m, throttled");
}
}
return flag;
}, "JesterAI.Update");
}
}
[HarmonyPatch(typeof(PufferAI))]
internal static class SporeLizardPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(PufferAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: 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_008a: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Spore Lizard"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1)
{
if (ModConfig.EnableDebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)"SporeLizard: In puffed state (1), always updating");
}
}
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(position);
bool flag = _aiModule.ShouldEnemyUpdate(instanceID, position);
if (ModConfig.EnableDebugLogging.Value && !flag)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogDebug((object)$"SporeLizard: Distance={closestPlayerDistance:F1}m, state={((EnemyAI)__instance).currentBehaviourStateIndex}, throttled");
}
}
return flag;
}, "PufferAI.Update");
}
}
[HarmonyPatch(typeof(CrawlerAI))]
internal static class ThumperPatches
{
private static AIOptimizationModule _aiModule;
public static void Initialize(AIOptimizationModule aiModule)
{
_aiModule = aiModule;
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
private static bool Update_Prefix(CrawlerAI __instance)
{
return PatchErrorHandler.ExecutePrefix(delegate
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
if (_aiModule == null || !_aiModule.IsEnabled || !_aiModule.IsEnemyTypeOptimizationEnabled("Thumper"))
{
return true;
}
if (!Plugin.IsServer())
{
return true;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1)
{
return true;
}
int instanceID = ((Object)__instance).GetInstanceID();
Vector3 position = ((Component)__instance).transform.position;
return _aiModule.ShouldEnemyUpdate(instanceID, position);
}, "CrawlerAI.Update");
}
}
}
namespace LethalBoost.Modules.Traps
{
public class LandmineModule : TrapOptimizationModuleBase<LandmineModule.LandmineThrottleData>
{
public class LandmineThrottleData
{
public float LastUpdateTime;
public float CurrentUpdateInterval;
public bool IsInDangerRadius;
}
protected override float ThrottleDistance => 15f;
protected override float DangerRange => 3f;
protected override string ModuleName => "Landmine Optimization Module";
public override bool IsEnabled => ModConfig.EnableLandmineOptimization?.Value ?? false;
protected override void InitializeThrottleData(LandmineThrottleData data, float currentTime)
{
data.LastUpdateTime = currentTime - 1f;
data.CurrentUpdateInterval = 0f;
data.IsInDangerRadius = false;
}
protected override bool ShouldCleanupEntry(LandmineThrottleData data, float currentTime)
{
return currentTime - data.LastUpdateTime > 60f;
}
public override bool ShouldTrapUpdate(int landmineInstanceID, Vector3 landminePosition)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
return ShouldLandmineUpdate(landmineInstanceID, landminePosition);
}
public bool ShouldLandmineUpdate(int landmineInstanceID, Vector3 landminePosition)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return true;
}
float time = Time.time;
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(landminePosition);
LandmineThrottleData orCreateThrottleData = GetOrCreateThrottleData(landmineInstanceID, time);
if (orCreateThrottleData.IsInDangerRadius = closestPlayerDistance < DangerRange)
{
orCreateThrottleData.LastUpdateTime = time;
orCreateThrottleData.CurrentUpdateInterval = 1f / 30f;
return true;
}
float num = (orCreateThrottleData.CurrentUpdateInterval = ((!(closestPlayerDistance < ThrottleDistance)) ? 0.2f : (1f / 30f)));
if (time - orCreateThrottleData.LastUpdateTime >= num)
{
orCreateThrottleData.LastUpdateTime = time;
return true;
}
return false;
}
public float GetCollisionSphereMultiplier(Vector3 landminePosition)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return 1f;
}
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(landminePosition);
if (closestPlayerDistance < DangerRange)
{
return 1f;
}
if (closestPlayerDistance < ThrottleDistance)
{
return 0.9f;
}
return 0.75f;
}
public bool IsInDangerRadius(Vector3 landminePosition)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return true;
}
return DistanceThrottler.GetClosestPlayerDistance(landminePosition) < DangerRange;
}
public float GetLandmineIntervalMultiplier(Vector3 landminePosition)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return GetIntervalMultiplier(landminePosition);
}
public void ClearLandmineData(int landmineInstanceID)
{
ClearTrapData(landmineInstanceID);
}
}
public class SpikeTrapModule : TrapOptimizationModuleBase<SpikeTrapModule.SpikeTrapThrottleData>
{
public class SpikeTrapThrottleData
{
public float LastUpdateTime;
public float CurrentUpdateInterval;
public bool IsPlayerNearby;
}
protected override float ThrottleDistance => 15f;
protected override float DangerRange => 15f;
protected override string ModuleName => "Spike Trap Optimization Module";
public override bool IsEnabled => ModConfig.EnableSpikeTrapOptimization?.Value ?? false;
protected override void InitializeThrottleData(SpikeTrapThrottleData data, float currentTime)
{
data.LastUpdateTime = currentTime - 1f;
data.CurrentUpdateInterval = 0f;
data.IsPlayerNearby = false;
}
protected override bool ShouldCleanupEntry(SpikeTrapThrottleData data, float currentTime)
{
return currentTime - data.LastUpdateTime > 60f;
}
public override bool ShouldTrapUpdate(int spikeTrapInstanceID, Vector3 spikeTrapPosition)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
return ShouldSpikeTrapUpdate(spikeTrapInstanceID, spikeTrapPosition);
}
public bool ShouldSpikeTrapUpdate(int spikeTrapInstanceID, Vector3 spikeTrapPosition)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return true;
}
float time = Time.time;
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(spikeTrapPosition);
SpikeTrapThrottleData orCreateThrottleData = GetOrCreateThrottleData(spikeTrapInstanceID, time);
if (orCreateThrottleData.IsPlayerNearby = closestPlayerDistance < ThrottleDistance)
{
orCreateThrottleData.LastUpdateTime = time;
orCreateThrottleData.CurrentUpdateInterval = 1f / 30f;
return true;
}
float num = (orCreateThrottleData.CurrentUpdateInterval = 0.2f);
if (time - orCreateThrottleData.LastUpdateTime >= num)
{
orCreateThrottleData.LastUpdateTime = time;
return true;
}
return false;
}
public float GetCollisionDetectionMultiplier(Vector3 spikeTrapPosition)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return 1f;
}
if (DistanceThrottler.GetClosestPlayerDistance(spikeTrapPosition) < ThrottleDistance)
{
return 1f;
}
return 1f / 6f;
}
public bool IsPlayerNearby(Vector3 spikeTrapPosition)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return true;
}
return DistanceThrottler.GetClosestPlayerDistance(spikeTrapPosition) < ThrottleDistance;
}
public float GetSpikeTrapIntervalMultiplier(Vector3 spikeTrapPosition)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return GetIntervalMultiplier(spikeTrapPosition);
}
public bool ShouldPerformRaycastDetection(int spikeTrapInstanceID, Vector3 spikeTrapPosition)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
return ShouldSpikeTrapUpdate(spikeTrapInstanceID, spikeTrapPosition);
}
public void ClearSpikeTrapData(int spikeTrapInstanceID)
{
ClearTrapData(spikeTrapInstanceID);
}
}
public abstract class TrapOptimizationModuleBase<TThrottleData> : IOptimizationModule where TThrottleData : class, new()
{
protected bool _isInitialized;
protected Dictionary<int, TThrottleData> _trapData;
protected float _lastCleanupTime;
protected const float CLEANUP_INTERVAL = 30f;
protected const float CLEANUP_EXPIRY_TIME = 60f;
public abstract bool IsEnabled { get; }
protected abstract float ThrottleDistance { get; }
protected abstract float DangerRange { get; }
protected abstract string ModuleName { get; }
protected TrapOptimizationModuleBase()
{
_trapData = new Dictionary<int, TThrottleData>();
}
public virtual void Initialize()
{
if (_isInitialized)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)(ModuleName + " already initialized."));
}
return;
}
try
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)("Initializing " + ModuleName + "..."));
}
_trapData.Clear();
_lastCleanupTime = Time.time;
_isInitialized = true;
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogInfo((object)$"{ModuleName} initialized. Throttle distance: {ThrottleDistance}m, Danger range: {DangerRange}m");
}
}
catch (Exception arg)
{
ManualLogSource log4 = Plugin.Log;
if (log4 != null)
{
log4.LogError((object)$"Failed to initialize {ModuleName}: {arg}");
}
throw;
}
}
public virtual void Update()
{
if (!IsEnabled || !_isInitialized || !Plugin.IsServer())
{
return;
}
try
{
DistanceThrottler.UpdatePlayerPositionCache();
float time = Time.time;
if (time - _lastCleanupTime >= 30f)
{
PerformPeriodicCleanup();
_lastCleanupTime = time;
}
}
catch (Exception arg)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)$"Error in {ModuleName} Update: {arg}");
}
}
}
protected virtual void PerformPeriodicCleanup()
{
try
{
float time = Time.time;
List<int> list = new List<int>();
foreach (KeyValuePair<int, TThrottleData> trapDatum in _trapData)
{
if (ShouldCleanupEntry(trapDatum.Value, time))
{
list.Add(trapDatum.Key);
}
}
foreach (int item in list)
{
_trapData.Remove(item);
}
if (ModConfig.EnableDebugLogging.Value && list.Count > 0)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"{ModuleName}: Cleaned up {list.Count} expired entries");
}
}
}
catch (Exception arg)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogError((object)$"Error during {ModuleName} cleanup: {arg}");
}
}
}
protected virtual bool ShouldCleanupEntry(TThrottleData data, float currentTime)
{
return false;
}
protected TThrottleData GetOrCreateThrottleData(int instanceId, float currentTime)
{
if (!_trapData.TryGetValue(instanceId, out var value))
{
value = new TThrottleData();
InitializeThrottleData(value, currentTime);
_trapData[instanceId] = value;
}
return value;
}
protected abstract void InitializeThrottleData(TThrottleData data, float currentTime);
public abstract bool ShouldTrapUpdate(int trapInstanceId, Vector3 trapPosition);
public virtual float GetIntervalMultiplier(Vector3 trapPosition)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return 1f;
}
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(trapPosition);
if (closestPlayerDistance < DangerRange)
{
return 1f;
}
if (closestPlayerDistance < ThrottleDistance)
{
return 1f;
}
return 1f / 6f;
}
public void ClearTrapData(int trapInstanceId)
{
_trapData.Remove(trapInstanceId);
}
public virtual void Cleanup()
{
try
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)("Cleaning up " + ModuleName + "..."));
}
_trapData.Clear();
_isInitialized = false;
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)(ModuleName + " cleaned up successfully."));
}
}
catch (Exception arg)
{
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogError((object)$"Error during {ModuleName} cleanup: {arg}");
}
}
}
public virtual void Reset()
{
try
{
if (!_isInitialized)
{
return;
}
_trapData.Clear();
_lastCleanupTime = Time.time;
if (ModConfig.EnableDebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)(ModuleName + " reset for new level."));
}
}
}
catch (Exception arg)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogError((object)$"Error during {ModuleName} reset: {arg}");
}
}
}
}
public class TurretModule : TrapOptimizationModuleBase<TurretModule.TurretThrottleData>
{
public class TurretThrottleData
{
public float LastUpdateTime;
public float CurrentUpdateInterval;
public bool IsInThreatRange;
}
protected override float ThrottleDistance => 20f;
protected override float DangerRange => 15f;
protected override string ModuleName => "Turret Optimization Module";
public override bool IsEnabled => ModConfig.EnableTurretOptimization?.Value ?? false;
protected override void InitializeThrottleData(TurretThrottleData data, float currentTime)
{
data.LastUpdateTime = currentTime - 1f;
data.CurrentUpdateInterval = 0f;
data.IsInThreatRange = false;
}
protected override bool ShouldCleanupEntry(TurretThrottleData data, float currentTime)
{
return currentTime - data.LastUpdateTime > 60f;
}
public override bool ShouldTrapUpdate(int turretInstanceID, Vector3 turretPosition)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
return ShouldTurretUpdate(turretInstanceID, turretPosition);
}
public bool ShouldTurretUpdate(int turretInstanceID, Vector3 turretPosition)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return true;
}
float time = Time.time;
float closestPlayerDistance = DistanceThrottler.GetClosestPlayerDistance(turretPosition);
TurretThrottleData orCreateThrottleData = GetOrCreateThrottleData(turretInstanceID, time);
if (orCreateThrottleData.IsInThreatRange = closestPlayerDistance < DangerRange)
{
orCreateThrottleData.LastUpdateTime = time;
orCreateThrottleData.CurrentUpdateInterval = 1f / 30f;
return true;
}
float num = (orCreateThrottleData.CurrentUpdateInterval = ((!(closestPlayerDistance < ThrottleDistance)) ? 0.2f : (1f / 30f)));
if (time - orCreateThrottleData.LastUpdateTime >= num)
{
orCreateThrottleData.LastUpdateTime = time;
return true;
}
return false;
}
public float GetTurretIntervalMultiplier(Vector3 turretPosition)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return GetIntervalMultiplier(turretPosition);
}
public bool IsInThreatRange(Vector3 turretPosition)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !_isInitialized)
{
return true;
}
return DistanceThrottler.GetClosestPlayerDistance(turretPosition) < DangerRange;
}
public void ClearTurretData(int turretInstanceID)
{
ClearTrapData(turretInstanceID);
}
}
}
namespace LethalBoost.Modules.Physics
{
public class PhysicsCullingModule : IOptimizationModule
{
private class PhysicsState
{
public bool OriginalSimulated;
public bool IsSimulated;
public float LastStateChangeTime;
public float LastAccessTime;
}
private class RoomOccupancy
{
public string RoomId;
public bool IsOccupied;
public float LastOccupiedTime;
}
private readonly Dictionary<int, PhysicsState> _physicsStates = new Dictionary<int, PhysicsState>();
private readonly Dictionary<string, RoomOccupancy> _roomOccupancy = new Dictionary<string, RoomOccupancy>();
private List<Rigidbody> _cachedRigidbodies = new List<Rigidbody>();
private float _lastScanTime;
private const float SCAN_INTERVAL = 5f;
private const float HYSTERESIS_TIME = 2f;
private const float ROOM_CHECK_RADIUS = 15f;
public bool IsEnabled => ModConfig.EnablePhysicsCulling?.Value ?? false;
public void Initialize()
{
if (!IsEnabled)
{
Plugin.Logger.LogInfo((object)"PhysicsCullingModule: Disabled in configuration");
}
else
{
Plugin.Logger.LogInfo((object)"PhysicsCullingModule: Initialized");
}
}
public void Update()
{
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
if (!IsEnabled || !Plugin.IsServer())
{
return;
}
try
{
PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
if (array == null)
{
return;
}
UpdateRoomOccupancy(array);
float time = Time.time;
if (time - _lastScanTime >= 5f)
{
_lastScanTime = time;
_cachedRigidbodies.Clear();
_cachedRigidbodies.AddRange(Object.FindObjectsOfType<Rigidbody>());
}
foreach (Rigidbody cachedRigidbody in _cachedRigidbodies)
{
if (!((Object)(object)cachedRigidbody == (Object)null) && !((Object)(object)((Component)cachedRigidbody).gameObject == (Object)null) && !ShouldSkipPhysicsObject(cachedRigidbody))
{
int instanceID = ((Object)cachedRigidbody).GetInstanceID();
if (!_physicsStates.ContainsKey(instanceID))
{
_physicsStates[instanceID] = new PhysicsState
{
OriginalSimulated = !cachedRigidbody.isKinematic,
LastStateChangeTime = Time.time
};
}
PhysicsState state = _physicsStates[instanceID];
bool isInOccupiedRoom = IsInOccupiedRoom(((Component)cachedRigidbody).transform.position, array);
ApplyPhysicsCulling(cachedRigidbody, state, isInOccupiedRoom);
}
}
CleanupDeadEntries();
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("PhysicsCullingModule.Update error: " + ex.Message));
}
}
private void UpdateRoomOccupancy(PlayerControllerB[] players)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
_roomOccupancy.Clear();
foreach (PlayerControllerB val in players)
{
if (!((Object)(object)val == (Object)null) && !val.isPlayerDead)
{
string roomId = GetRoomId(((Component)val).transform.position);
if (!_roomOccupancy.ContainsKey(roomId))
{
_roomOccupancy[roomId] = new RoomOccupancy
{
RoomId = roomId,
LastOccupiedTime = Time.time,
IsOccupied = true
};
}
else
{
_roomOccupancy[roomId].LastOccupiedTime = Time.time;
_roomOccupancy[roomId].IsOccupied = true;
}
}
}
}
private string GetRoomId(Vector3 position)
{
//IL_0000: 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_0024: Unknown result type (might be due to invalid IL or missing references)
int num = Mathf.FloorToInt(position.x / 15f);
int num2 = Mathf.FloorToInt(position.y / 15f);
int num3 = Mathf.FloorToInt(position.z / 15f);
return $"{num}_{num2}_{num3}";
}
private bool IsInOccupiedRoom(Vector3 position, PlayerControllerB[] players)
{
//IL_004d: 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_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references)
foreach (PlayerControllerB val in players)
{
if (!((Object)(object)val == (Object)null) && !val.isPlayerDead)
{
Vector3 val2 = ((Component)val).transform.position - position;
if (((Vector3)(ref val2)).sqrMagnitude < 225f)
{
return true;
}
}
}
string roomId = GetRoomId(position);
if (_roomOccupancy.TryGetValue(roomId, out var value))
{
if (!value.IsOccupied)
{
return Time.time - value.LastOccupiedTime < 2f;
}
return true;
}
return false;
}
private bool ShouldSkipPhysicsObject(Rigidbody rb)
{
if ((Object)(object)rb == (Object)null || (Object)(object)((Component)rb).gameObject == (Object)null)
{
return true;
}
if ((Object)(object)((Component)rb).gameObject.GetComponent<PlayerControllerB>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)rb).gameObject.GetComponent<EnemyAI>() != (Object)null)
{
return true;
}
if (rb.isKinematic)
{
return true;
}
GrabbableObject component = ((Component)rb).gameObject.GetComponent<GrabbableObject>();
if ((Object)(object)component != (Object)null && component.isHeld)
{
return true;
}
if ((Object)(object)component != (Object)null && IsFunctionalItem(component))
{
return true;
}
string text = ((Object)((Component)rb).gameObject).name.ToLower();
if (text.Contains("ship") || text.Contains("hangar") || text.Contains("vehicle") || text.Contains("elevator"))
{
return true;
}
Transform parent = ((Component)rb).transform.parent;
while ((Object)(object)parent != (Object)null)
{
string text2 = ((Object)parent).name.ToLower();
if (text2.Contains("ship") || text2.Contains("hangar") || text2.Contains("vehicle") || text2.Contains("elevator"))
{
return true;
}
parent = parent.parent;
}
if ((Object)(object)((Component)rb).gameObject.GetComponent<VehicleController>() != (Object)null || (Object)(object)((Component)rb).gameObject.GetComponentInParent<VehicleController>() != (Object)null)
{
return true;
}
return false;
}
private bool IsFunctionalItem(GrabbableObject item)
{
if ((Object)(object)item == (Object)null)
{
return false;
}
string text = item.itemProperties?.itemName?.ToLower() ?? "";
if (text.Contains("walkie") || text.Contains("radio"))
{
return true;
}
if (text.Contains("flashlight") || text.Contains("lantern") || text.Contains("pro-flashlight") || text.Contains("laser"))
{
return true;
}
if (text.Contains("horn") || text.Contains("clown") || text.Contains("airhorn") || text.Contains("air horn"))
{
return true;
}
if (text.Contains("key") || text.Contains("card"))
{
return true;
}
if (text.Contains("shovel") || text.Contains("sign") || text.Contains("stop sign") || text.Contains("yield"))
{
return true;
}
if (text.Contains("jetpack"))
{
return true;
}
if (text.Contains("spray") || text.Contains("paint"))
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<FlashlightItem>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<WalkieTalkie>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<NoisemakerProp>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<Shovel>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<SprayPaintItem>() != (Object)null)
{
return true;
}
if ((Object)(object)item.itemProperties != (Object)null && item.itemProperties.requiresBattery)
{
return true;
}
return false;
}
private void ApplyPhysicsCulling(Rigidbody rb, PhysicsState state, bool isInOccupiedRoom)
{
if ((Object)(object)rb == (Object)null)
{
return;
}
try
{
if (Time.time - state.LastStateChangeTime < 2f)
{
return;
}
if (isInOccupiedRoom)
{
if (!state.IsSimulated && state.OriginalSimulated)
{
rb.isKinematic = false;
state.IsSimulated = true;
state.LastStateChangeTime = Time.time;
if (ModConfig.EnableDebugLogging.Value)
{
Plugin.Logger.LogDebug((object)("Enabled physics for " + ((Object)((Component)rb).gameObject).name + " (room occupied)"));
}
}
}
else if (state.IsSimulated)
{
rb.isKinematic = true;
state.IsSimulated = false;
state.LastStateChangeTime = Time.time;
if (ModConfig.EnableDebugLogging.Value)
{
Plugin.Logger.LogDebug((object)("Disabled physics for " + ((Object)((Component)rb).gameObject).name + " (room unoccupied)"));
}
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Error applying physics culling: " + ex.Message));
}
}
private void CleanupDeadEntries()
{
List<int> list = new List<int>();
foreach (KeyValuePair<int, PhysicsState> physicsState in _physicsStates)
{
if (physicsState.Value.LastAccessTime < Time.time - 60f)
{
list.Add(physicsState.Key);
}
else
{
physicsState.Value.LastAccessTime = Time.time;
}
}
foreach (int item in list)
{
_physicsStates.Remove(item);
}
}
public void Cleanup()
{
try
{
Rigidbody[] array = Object.FindObjectsOfType<Rigidbody>();
foreach (Rigidbody val in array)
{
if (!((Object)(object)val == (Object)null))
{
int instanceID = ((Object)val).GetInstanceID();
if (_physicsStates.TryGetValue(instanceID, out var value) && value.OriginalSimulated && !value.IsSimulated)
{
val.isKinematic = false;
}
}
}
_physicsStates.Clear();
_roomOccupancy.Clear();
Plugin.Logger.LogInfo((object)"PhysicsCullingModule: Cleaned up");
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("PhysicsCullingModule.Cleanup error: " + ex.Message));
}
}
public void Reset()
{
try
{
_physicsStates.Clear();
_roomOccupancy.Clear();
_cachedRigidbodies.Clear();
_lastScanTime = 0f;
if (ModConfig.EnableDebugLogging.Value)
{
Plugin.Logger.LogDebug((object)"PhysicsCullingModule reset for new level.");
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("PhysicsCullingModule.Reset error: " + ex.Message));
}
}
}
public class RigidbodyModule : IOptimizationModule
{
private class RigidbodyState
{
public bool IsFrozen;
public bool WasKinematic;
public float StationaryTime;
public float LastAccessTime;
}
private readonly Dictionary<int, RigidbodyState> _rigidbodyStates = new Dictionary<int, RigidbodyState>();
private const float VELOCITY_THRESHOLD = 0.01f;
private const float ANGULAR_VELOCITY_THRESHOLD = 0.01f;
private List<Rigidbody> _cachedRigidbodies = new List<Rigidbody>();
private float _lastScanTime;
private const float SCAN_INTERVAL = 5f;
public bool IsEnabled => ModConfig.EnableRigidbodyFreezing?.Value ?? false;
public void Initialize()
{
if (!IsEnabled)
{
Plugin.Logger.LogInfo((object)"RigidbodyModule: Disabled in configuration");
}
else
{
Plugin.Logger.LogInfo((object)"RigidbodyModule: Initialized");
}
}
public void Update()
{
if (!IsEnabled || !Plugin.IsServer())
{
return;
}
try
{
float time = Time.time;
if (time - _lastScanTime >= 5f)
{
_lastScanTime = time;
_cachedRigidbodies.Clear();
_cachedRigidbodies.AddRange(Object.FindObjectsOfType<Rigidbody>());
}
foreach (Rigidbody cachedRigidbody in _cachedRigidbodies)
{
if ((Object)(object)cachedRigidbody == (Object)null || (Object)(object)((Component)cachedRigidbody).gameObject == (Object)null || ShouldSkipRigidbody(cachedRigidbody))
{
continue;
}
int instanceID = ((Object)cachedRigidbody).GetInstanceID();
if (!_rigidbodyStates.ContainsKey(instanceID))
{
_rigidbodyStates[instanceID] = new RigidbodyState();
}
RigidbodyState rigidbodyState = _rigidbodyStates[instanceID];
if (IsBeingInteractedWith(cachedRigidbody))
{
UnfreezeRigidbody(cachedRigidbody, rigidbodyState);
}
else if (IsStationary(cachedRigidbody))
{
rigidbodyState.StationaryTime += Time.deltaTime;
float num = 2f;
if (rigidbodyState.StationaryTime >= num && !rigidbodyState.IsFrozen)
{
FreezeRigidbody(cachedRigidbody, rigidbodyState);
}
}
else
{
rigidbodyState.StationaryTime = 0f;
if (rigidbodyState.IsFrozen)
{
UnfreezeRigidbody(cachedRigidbody, rigidbodyState);
}
}
}
CleanupDeadEntries();
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("RigidbodyModule.Update error: " + ex.Message));
}
}
private bool IsStationary(Rigidbody rb)
{
//IL_000c: 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_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)rb == (Object)null)
{
return false;
}
Vector3 val = rb.velocity;
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = rb.angularVelocity;
return ((Vector3)(ref val)).sqrMagnitude < 0.0001f;
}
return false;
}
private bool ShouldSkipRigidbody(Rigidbody rb)
{
if ((Object)(object)rb == (Object)null || (Object)(object)((Component)rb).gameObject == (Object)null)
{
return true;
}
if ((Object)(object)((Component)rb).gameObject.GetComponent<PlayerControllerB>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)rb).gameObject.GetComponent<EnemyAI>() != (Object)null)
{
return true;
}
if (rb.isKinematic)
{
return true;
}
GrabbableObject component = ((Component)rb).gameObject.GetComponent<GrabbableObject>();
if ((Object)(object)component != (Object)null && IsFunctionalItem(component))
{
return true;
}
return false;
}
private bool IsFunctionalItem(GrabbableObject item)
{
if ((Object)(object)item == (Object)null)
{
return false;
}
string text = item.itemProperties?.itemName?.ToLower() ?? "";
if (text.Contains("walkie") || text.Contains("radio"))
{
return true;
}
if (text.Contains("flashlight") || text.Contains("lantern") || text.Contains("pro-flashlight") || text.Contains("laser"))
{
return true;
}
if (text.Contains("horn") || text.Contains("clown") || text.Contains("airhorn") || text.Contains("air horn"))
{
return true;
}
if (text.Contains("key") || text.Contains("card"))
{
return true;
}
if (text.Contains("shovel") || text.Contains("sign") || text.Contains("stop sign") || text.Contains("yield"))
{
return true;
}
if (text.Contains("jetpack"))
{
return true;
}
if (text.Contains("spray") || text.Contains("paint"))
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<FlashlightItem>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<WalkieTalkie>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<NoisemakerProp>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<Shovel>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)item).GetComponent<SprayPaintItem>() != (Object)null)
{
return true;
}
if ((Object)(object)item.itemProperties != (Object)null && item.itemProperties.requiresBattery)
{
return true;
}
return false;
}
private bool IsBeingInteractedWith(Rigidbody rb)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: 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)
if ((Object)(object)rb == (Object)null || (Object)(object)((Component)rb).gameObject == (Object)null)
{
return false;
}
GrabbableObject component = ((Component)rb).gameObject.GetComponent<GrabbableObject>();
if ((Object)(object)component != (Object)null && component.isHeld)
{
return true;
}
PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
if (array != null)
{
float num = 5f;
PlayerControllerB[] array2 = array;
foreach (PlayerControllerB val in array2)
{
if (!((Object)(object)val == (Object)null) && !val.isPlayerDead)
{
Vector3 val2 = ((Component)val).transform.position - ((Component)rb).transform.position;
if (((Vector3)(ref val2)).sqrMagnitude < num * num)
{
return true;
}
}
}
}
return false;
}
private void FreezeRigidbody(Rigidbody rb, RigidbodyState state)
{
if ((Object)(object)rb == (Object)null || state.IsFrozen)
{
return;
}
try
{
state.WasKinematic = rb.isKinematic;
rb.isKinematic = true;
state.IsFrozen = true;
if (ModConfig.EnableDebugLogging.Value)
{
Plugin.Logger.LogDebug((object)("Froze rigidbody: " + ((Object)((Component)rb).gameObject).name));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Error freezing rigidbody: " + ex.Message));
}
}
private void UnfreezeRigidbody(Rigidbody rb, RigidbodyState state)
{
if ((Object)(object)rb == (Object)null || !state.IsFrozen)
{
return;
}
try
{
rb.isKinematic = state.WasKinematic;
state.IsFrozen = false;
state.StationaryTime = 0f;
if (ModConfig.EnableDebugLogging.Value)
{
Plugin.Logger.LogDebug((object)("Unfroze rigidbody: " + ((Object)((Component)rb).gameObject).name));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Error unfreezing rigidbody: " + ex.Message));
}
}
private void CleanupDeadEntries()
{
List<int> list = new List<int>();
foreach (KeyValuePair<int, RigidbodyState> rigidbodyState in _rigidbodyStates)
{
if (rigidbodyState.Value.LastAccessTime < Time.time - 60f)
{
list.Add(rigidbodyState.Key);
}
else
{
rigidbodyState.Value.LastAccessTime = Time.time;
}
}
foreach (int item in list)
{
_rigidbodyStates.Remove(item);
}
}
public void Cleanup()
{
try
{
Rigidbody[] array = Object.FindObjectsOfType<Rigidbody>();
foreach (Rigidbody val in array)
{
if (!((Object)(object)val == (Object)null))
{
int instanceID = ((Object)val).GetInstanceID();
if (_rigidbodyStates.TryGetValue(instanceID, out var value) && value.IsFrozen)
{
val.isKinematic = value.WasKinematic;
}
}
}
_rigidbodyStates.Clear();
Plugin.Logger.LogInfo((object)"RigidbodyModule: Cleaned up");
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("RigidbodyModule.Cleanup error: " + ex.Message));
}
}
public void Reset()
{
try
{
_rigidbodyStates.Clear();
_cachedRigidbodies.Clear();
_lastScanTime = 0f;
if (ModConfig.EnableDebugLogging.Value)
{
Plugin.Logger.LogDebug((object)"RigidbodyModule reset for new level.");
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("RigidbodyModule.Reset error: " + ex.Message));
}
}
}
}
namespace LethalBoost.Modules.Interior
{
public class DoorCullingModule : IOptimizationModule
{
private class DoorState
{
public Door Door;
public bool IsClosed;
public bool WasClosedLastFrame;
public Tile RoomA;
public Tile RoomB;
public List<Renderer> DoorRenderers = new List<Renderer>();
}
private bool _isInitialized;
private Dictionary<Door, DoorState> _doorStates = new Dictionary<Door, DoorState>();
private List<Door> _allDoors = new List<Door>();
private float _lastUpdateTime;
private const float UPDATE_INTERVAL = 0.3f;
private Dungeon _currentDungeon;
private HashSet<Door> _subscribedDoors = new HashSet<Door>();
public bool IsEnabled => ModConfig.EnableDoorCulling?.Value ?? false;
public void Initialize()
{
if (_isInitialized)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)"DoorCullingModule already initialized.");
}
return;
}
try
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)"Initializing Door Culling Module...");
}
_lastUpdateTime = Time.time;
_isInitialized = true;
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogInfo((object)"Door Culling Module initialized successfully.");
}
}
catch (Exception arg)
{
ManualLogSource log4 = Plugin.Log;
if (log4 != null)
{
log4.LogError((object)$"Failed to initialize Door Culling Module: {arg}");
}
throw;
}
}
public void Update()
{
if (!IsEnabled || !_isInitialized)
{
return;
}
try
{
float time = Time.time;
if (time - _lastUpdateTime < 0.3f)
{
return;
}
_lastUpdateTime = time;
if ((Object)(object)_currentDungeon == (Object)null)
{
FindDungeon();
if ((Object)(object)_currentDungeon == (Object)null)
{
return;
}
}
if (_doorStates.Count == 0)
{
BuildDoorList();
}
UpdateDoorStates();
ApplyDoorCulling();
}
catch (Exception arg)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)$"Error in Door Culling Module Update: {arg}");
}
}
}
private void FindDungeon()
{
try
{
RoundManager instance = RoundManager.Instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
RuntimeDungeon dungeonGenerator = instance.dungeonGenerator;
if (dungeonGenerator == null)
{
obj = null;
}
else
{
DungeonGenerator generator = dungeonGenerator.Generator;
obj = ((generator != null) ? generator.CurrentDungeon : null);
}
}
if ((Object)obj != (Object)null)
{
_currentDungeon = RoundManager.Instance.dungeonGenerator.Generator.CurrentDungeon;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)$"Door Culling: Found dungeon with {_currentDungeon.Doors.Count} doors.");
}
}
}
catch (Exception arg)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogError((object)$"Error finding dungeon: {arg}");
}
}
}
private void BuildDoorList()
{
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Expected O, but got Unknown
if ((Object)(object)_currentDungeon == (Object)null)
{
return;
}
try
{
_doorStates.Clear();
_allDoors.Clear();
foreach (GameObject door in _currentDungeon.Doors)
{
if ((Object)(object)door == (Object)null)
{
continue;
}
Door component = door.GetComponent<Door>();
if ((Object)(object)component == (Object)null)
{
continue;
}
DoorState doorState = new DoorState
{
Door = component,
IsClosed = !component.IsOpen,
WasClosedLastFrame = !component.IsOpen
};
Doorway doorwayA = component.DoorwayA;
if ((Object)(object)((doorwayA != null) ? doorwayA.Tile : null) != (Object)null)
{
doorState.RoomA = component.DoorwayA.Tile;
}
Doorway doorwayB = component.DoorwayB;
if ((Object)(object)((doorwayB != null) ? doorwayB.Tile : null) != (Object)null)
{
doorState.RoomB = component.DoorwayB.Tile;
}
Renderer[] componentsInChildren = ((Component)component).GetComponentsInChildren<Renderer>();
foreach (Renderer val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy)
{
doorState.DoorRenderers.Add(val);
}
}
_doorStates[component] = doorState;
_allDoors.Add(component);
if (!_subscribedDoors.Contains(component))
{
component.OnDoorStateChanged += new DoorStateChangedDelegate(OnDoorStateChanged);
_subscribedDoors.Add(component);
}
}
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)$"Built door list with {_doorStates.Count} doors.");
}
}
catch (Exception arg)
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogError((object)$"Error building door list: {arg}");
}
}
}
private void OnDoorStateChanged(Door door, bool isOpen)
{
if (!_doorStates.TryGetValue(door, out var value))
{
return;
}
value.IsClosed = !isOpen;
if (ModConfig.EnableDebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)("Door state changed: " + (isOpen ? "Opened" : "Closed")));
}
}
}
private void UpdateDoorStates()
{
try
{
_allDoors.RemoveAll((Door d) => (Object)(object)d == (Object)null);
foreach (Door allDoor in _allDoors)
{
if (!((Object)(object)allDoor == (Object)null) && _doorStates.ContainsKey(allDoor))
{
DoorState doorState = _doorStates[allDoor];
doorState.WasClosedLastFrame = doorState.IsClosed;
doorState.IsClosed = !allDoor.IsOpen;
}
}
}
catch (Exception arg)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)$"Error updating door states: {arg}");
}
}
}
private void ApplyDoorCulling()
{
if (!ModConfig.EnableDoorCulling.Value)
{
return;
}
try
{
foreach (KeyValuePair<Door, DoorState> doorState in _doorStates)
{
Door key = doorState.Key;
DoorState value = doorState.Value;
if ((Object)(object)key == (Object)null)
{
continue;
}
bool enabled = ShouldRenderDoor(value);
foreach (Renderer doorRenderer in value.DoorRenderers)
{
if ((Object)(object)doorRenderer != (Object)null)
{
doorRenderer.enabled = enabled;
}
}
}
}
catch (Exception arg)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)$"Error applying door culling: {arg}");
}
}
}
private bool ShouldRenderDoor(DoorState state)
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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)
PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
if (array != null)
{
PlayerControllerB[] array2 = array;
foreach (PlayerControllerB val in array2)
{
if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && val.isInsideFactory)
{
Vector3 val2 = ((Component)val).transform.position - ((Component)state.Door).transform.position;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
float num = 30f;
if (sqrMagnitude < num * num)
{
return true;
}
}
}
}
return false;
}
public bool IsDoorClosed(Door door)
{
if (_doorStates.TryGetValue(door, out var value))
{
return value.IsClosed;
}
return false;
}
public int GetClosedDoorCount()
{
int num = 0;
foreach (DoorState value in _doorStates.Values)
{
if (value.IsClosed)
{
num++;
}
}
return num;
}
public void Cleanup()
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
try
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)"Cleaning up Door Culling Module...");
}
foreach (Door allDoor in _allDoors)
{
if ((Object)(object)allDoor != (Object)null && _subscribedDoors.Contains(allDoor))
{
allDoor.OnDoorStateChanged -= new DoorStateChangedDelegate(OnDoorStateChanged);
}
}