using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using BalrondVisualOptimizer.Compatibility; using BalrondVisualOptimizer.Config; using BalrondVisualOptimizer.Core; using BalrondVisualOptimizer.Patches.ArmorStandOptimizations; using BalrondVisualOptimizer.Patches.CookingStationOptimizations; using BalrondVisualOptimizer.Patches.CraftingStationOptimizations; using BalrondVisualOptimizer.Patches.EffectFadeOptimizations; using BalrondVisualOptimizer.Patches.FireplaceOptimizations; using BalrondVisualOptimizer.Patches.ItemStandOptimizations; using BalrondVisualOptimizer.Patches.LightFlickerOptimizations; using BalrondVisualOptimizer.Patches.LightLodOptimizations; using BalrondVisualOptimizer.Patches.LineConnectOptimizations; using BalrondVisualOptimizer.Patches.MaterialFaderOptimizations; using BalrondVisualOptimizer.Patches.PieceOptimizations; using BalrondVisualOptimizer.Patches.PrivateAreaOptimizations; using BalrondVisualOptimizer.Patches.SmelterOptimizations; using BalrondVisualOptimizer.Patches.SmokeRendererOptimizations; using BalrondVisualOptimizer.Patches.StationExtensionOptimizations; using BalrondVisualOptimizer.Patches.TeleportWorldOptimizations; using BalrondVisualOptimizer.Patches.VagonOptimizations; using BalrondVisualOptimizer.Patches.VisEquipmentOptimizations; using BalrondVisualOptimizer.Patches.WindmillOptimizations; using BalrondVisualOptimizer.Patches.ZSFXOptimizations; using BalrondVisualOptimizer.Services; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("BalrondVisualOptimizer")] [assembly: AssemblyDescription("Publicized event/cache/dormancy presentation optimizer for Valheim")] [assembly: AssemblyCompany("Balrond")] [assembly: AssemblyProduct("BalrondVisualOptimizer")] [assembly: ComVisible(false)] [assembly: Guid("14f622c7-d1e8-44ec-b28b-86f0d5543b4b")] [assembly: AssemblyFileVersion("0.1.4.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.4.0")] [module: UnverifiableCode] namespace BalrondVisualOptimizer { [BepInPlugin("balrond.astafaraios.BalrondCoreOptimizer", "BalrondCoreOptimizer", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Launch : BaseUnityPlugin { public const string PluginGuid = "balrond.astafaraios.BalrondCoreOptimizer"; public const string PluginName = "BalrondCoreOptimizer"; public const string PluginVersion = "0.1.0"; internal static Launch Instance; internal static OptimizerConfig Settings; private Harmony harmony; private PatchInstaller patchInstaller; private float nextCompatibilityCheck; private float nextStatsLog; private bool refreshRequested; private bool lastDiagnostics; private void Awake() { //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown Instance = this; try { Settings = new OptimizerConfig(((BaseUnityPlugin)this).Config); RuntimeTuning.Refresh(Settings); RuntimeStats.Enabled = Settings.Diagnostics.Value; RuntimeStats.ResetBaseline(); lastDiagnostics = RuntimeStats.Enabled; ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)"BalrondCoreOptimizer 0.1.0 starting (publicized fast-path build)."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("assembly_valheim MVID: " + GameAssemblyGuard.CurrentValheimMvid.ToString() + " (audited: " + GameAssemblyGuard.ExpectedValheimMvid.ToString() + ").")); if (Application.isBatchMode) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dedicated/batch mode detected. Client presentation patches are not installed."); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Compatibility: BetterBuild=" + ModCompatibility.BetterBuildInstalled + ", FiresGhettoNetworking=" + ModCompatibility.FiresGhettoNetworkingInstalled + ".")); harmony = new Harmony("balrond.astafaraios.BalrondCoreOptimizer"); patchInstaller = new PatchInstaller(harmony, Settings); VanillaCollectionRegistry.Initialize(); ArmorStandPatches.Install(patchInstaller); ItemStandPatches.Install(patchInstaller); PrivateAreaPatches.Install(patchInstaller); TeleportWorldPatches.Install(patchInstaller); VisEquipmentPatches.Install(patchInstaller); SmelterPatches.Install(patchInstaller); FireplacePatches.Install(patchInstaller); CookingStationPatches.Install(patchInstaller); CraftingStationDormancyPatches.Install(patchInstaller); LightFlickerPatches.Install(patchInstaller); LightLodPatches.Install(patchInstaller); SmokeRendererPatches.Install(patchInstaller); WindmillPatches.Install(patchInstaller); VagonPatches.Install(patchInstaller); EffectFadePatches.Install(patchInstaller); MaterialFaderPatches.Install(patchInstaller); ZSFXPatches.Install(patchInstaller); LineConnectPatches.Install(patchInstaller); PiecePatches.Install(patchInstaller); CraftingStationPatches.Install(patchInstaller); StationExtensionPatches.Install(patchInstaller); RefreshSubsystemOwnership(); nextCompatibilityCheck = Time.unscaledTime + Settings.CompatibilityRecheckSeconds.Value; nextStatsLog = Time.unscaledTime + Settings.DiagnosticsIntervalSeconds.Value; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[patches] " + patchInstaller.BuildStatusSummary())); ((BaseUnityPlugin)this).Logger.LogInfo((object)"BalrondCoreOptimizer initialization complete."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Fatal initialization error. Rolling back BVO and restoring vanilla dispatch: " + ex)); ShutdownSubsystems(); try { if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Rollback failed: " + ex2.Message)); } patchInstaller = null; } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { refreshRequested = true; } private void Update() { if (Settings != null) { float unscaledTime = Time.unscaledTime; if (patchInstaller != null && (refreshRequested || unscaledTime >= nextCompatibilityCheck)) { refreshRequested = false; RuntimeTuning.Refresh(Settings); patchInstaller.RefreshAll(); RefreshSubsystemOwnership(); nextCompatibilityCheck = unscaledTime + Mathf.Max(2f, Settings.CompatibilityRecheckSeconds.Value); } LightLodScheduler.Tick(Time.deltaTime); ZSFXPatches.Tick(unscaledTime); bool value = Settings.Diagnostics.Value; if (value != lastDiagnostics) { lastDiagnostics = value; RuntimeStats.Enabled = value; RuntimeStats.ResetBaseline(); nextStatsLog = unscaledTime + Mathf.Max(10f, Settings.DiagnosticsIntervalSeconds.Value); } if (value && unscaledTime >= nextStatsLog) { float num = Mathf.Max(10f, Settings.DiagnosticsIntervalSeconds.Value); nextStatsLog = unscaledTime + num; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[stats] " + RuntimeStats.BuildDeltaSummary(num))); } } } private static void RefreshSubsystemOwnership() { CraftingStationDormancyPatches.RefreshDormancy(); EffectFadePatches.RefreshDormancy(); MaterialFaderPatches.RefreshDormancy(); ZSFXPatches.RefreshDormancy(); LightLodPatches.RefreshScheduler(); } private static void ShutdownSubsystems() { try { LightLodScheduler.RestoreVanilla(); } catch { } try { CraftingStationDormancyPatches.Shutdown(); } catch { } try { EffectFadePatches.Shutdown(); } catch { } try { MaterialFaderPatches.Shutdown(); } catch { } try { ZSFXPatches.Shutdown(); } catch { } } private void OnDestroy() { if (((BaseUnityPlugin)this).Config != null) { ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; } ShutdownSubsystems(); try { if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to unpatch cleanly: " + ex.Message)); } Instance = null; } internal static void LogInfo(object message) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo(message); } } internal static void LogWarning(object message) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning(message); } } internal static void LogError(object message) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogError(message); } } } } namespace BalrondVisualOptimizer.Services { internal static class LightLodScheduler { private sealed class Entry { internal LightLod Lod; internal int Index; internal bool TargetLight; internal bool TargetShadow; internal bool Fading; } private static readonly List Entries = new List(); private static readonly Dictionary Map = new Dictionary(); private static readonly List Fading = new List(); private static int cursor; private static bool enabled; internal static void SetEnabled(bool value) { if (enabled != value) { enabled = value; if (enabled) { TakeOwnershipOfExisting(); } else { RestoreVanilla(); } } } internal static void Register(LightLod lod) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!enabled || (Object)(object)lod == (Object)null) { return; } int instanceID = ((Object)lod).GetInstanceID(); if (!Map.ContainsKey(instanceID)) { Entry entry = new Entry { Lod = lod, Index = Entries.Count }; Entries.Add(entry); Map[instanceID] = entry; if (TryGetReferencePoint(out var point)) { Evaluate(entry, point); } } } internal static void Unregister(LightLod lod) { if (!((Object)(object)lod == (Object)null) && Map.TryGetValue(((Object)lod).GetInstanceID(), out var value)) { RemoveEntry(value); } } internal static void Tick(float dt) { //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (!enabled || Entries.Count == 0) { return; } if (TryGetReferencePoint(out var point)) { float num = Mathf.Max(0.25f, RuntimeTuning.LightLodDecisionInterval); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)Entries.Count * Mathf.Min(0.25f, Mathf.Max(0f, dt)) / num)); int num3 = Mathf.Min(Entries.Count, Mathf.Min(RuntimeTuning.LightLodChecksPerFrame, num2)); for (int i = 0; i < num3; i++) { if (Entries.Count <= 0) { break; } if (cursor >= Entries.Count) { cursor = 0; } Entry entry = Entries[cursor++]; if ((Object)(object)entry.Lod == (Object)null || !((Behaviour)entry.Lod).enabled || !((Component)entry.Lod).gameObject.activeInHierarchy) { RemoveEntry(entry); continue; } Evaluate(entry, point); RuntimeStats.Inc(ref RuntimeStats.LightLodDecisionChecks); } } for (int num4 = Fading.Count - 1; num4 >= 0; num4--) { Entry entry2 = Fading[num4]; if (!entry2.Fading) { Fading.RemoveAt(num4); } else if ((Object)(object)entry2.Lod == (Object)null || !((Behaviour)entry2.Lod).enabled || !((Component)entry2.Lod).gameObject.activeInHierarchy) { entry2.Fading = false; Fading.RemoveAt(num4); } else if (AdvanceFade(entry2, dt)) { entry2.Fading = false; Fading.RemoveAt(num4); } } } internal static void RestoreVanilla() { for (int i = 0; i < Entries.Count; i++) { LightLod lod = Entries[i].Lod; if ((Object)(object)lod != (Object)null && ((Behaviour)lod).enabled && ((Component)lod).gameObject.activeInHierarchy) { ((MonoBehaviour)lod).StopCoroutine("UpdateLoop"); ((MonoBehaviour)lod).StartCoroutine("UpdateLoop"); } } Entries.Clear(); Map.Clear(); Fading.Clear(); cursor = 0; } private static void TakeOwnershipOfExisting() { foreach (LightLod light in LightLod.m_lights) { if (!((Object)(object)light == (Object)null) && ((Behaviour)light).enabled && ((Component)light).gameObject.activeInHierarchy) { ((MonoBehaviour)light).StopCoroutine("UpdateLoop"); Register(light); } } } private static bool TryGetReferencePoint(out Vector3 point) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0041: Unknown result type (might be due to invalid IL or missing references) Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera == (Object)null) { point = Vector3.zero; return false; } point = ((GameCamera.InFreeFly() || (Object)(object)Player.m_localPlayer == (Object)null) ? ((Component)mainCamera).transform.position : ((Component)Player.m_localPlayer).transform.position); return true; } private static void Evaluate(Entry e, Vector3 reference) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) LightLod lod = e.Lod; if (!((Object)(object)lod == (Object)null) && !((Object)(object)lod.m_light == (Object)null)) { Vector3 val = ((Component)lod).transform.position - reference; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; bool flag = !lod.m_lightLod || (sqrMagnitude < lod.m_lightDistance * lod.m_lightDistance && (lod.m_lightPrio < LightLod.m_lightLimit || LightLod.m_lightLimit < 0)); bool flag2 = !lod.m_shadowLod || (sqrMagnitude < lod.m_shadowDistance * lod.m_shadowDistance && (lod.m_lightPrio < LightLod.m_shadowLimit || LightLod.m_shadowLimit < 0)); bool flag3 = e.TargetLight != flag || e.TargetShadow != flag2; e.TargetLight = flag; e.TargetShadow = flag2; if (flag3 || !IsSettled(e)) { AddFading(e); } } } private static bool AdvanceFade(Entry e, float dt) { LightLod lod = e.Lod; Light light = lod.m_light; if ((Object)(object)light == (Object)null) { return true; } if (lod.m_lightLod) { if (e.TargetLight) { ((Behaviour)light).enabled = true; light.range = Mathf.Min(lod.m_baseRange, light.range + dt * lod.m_baseRange); } else { light.range = Mathf.Max(0f, light.range - dt * lod.m_baseRange); if (light.range <= 0f) { ((Behaviour)light).enabled = false; } } } if (lod.m_shadowLod) { if (e.TargetShadow) { light.shadows = (LightShadows)2; light.shadowStrength = Mathf.Min(lod.m_baseShadowStrength, light.shadowStrength + dt * lod.m_baseShadowStrength); } else { light.shadowStrength = Mathf.Max(0f, light.shadowStrength - dt * lod.m_baseShadowStrength); if (light.shadowStrength <= 0f) { light.shadows = (LightShadows)0; } } } return IsSettled(e); } private static bool IsSettled(Entry e) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) LightLod lod = e.Lod; Light val = (((Object)(object)lod == (Object)null) ? null : lod.m_light); if ((Object)(object)val == (Object)null) { return true; } bool flag = true; if (lod.m_lightLod) { flag = ((!e.TargetLight) ? (!((Behaviour)val).enabled && val.range <= 0f) : (((Behaviour)val).enabled && val.range >= lod.m_baseRange)); } bool flag2 = true; if (lod.m_shadowLod) { flag2 = ((!e.TargetShadow) ? ((int)val.shadows == 0 && val.shadowStrength <= 0f) : ((int)val.shadows != 0 && val.shadowStrength >= lod.m_baseShadowStrength)); } return flag && flag2; } private static void AddFading(Entry e) { if (!e.Fading) { e.Fading = true; Fading.Add(e); } } private static void RemoveEntry(Entry e) { if (e != null && e.Index >= 0 && e.Index < Entries.Count) { int num = ((!((Object)(object)e.Lod == (Object)null)) ? ((Object)e.Lod).GetInstanceID() : 0); int index = Entries.Count - 1; Entry entry = Entries[index]; Entries[e.Index] = entry; entry.Index = e.Index; Entries.RemoveAt(index); if (num != 0) { Map.Remove(num); } e.Index = -1; e.Fading = false; if (cursor > Entries.Count) { cursor = Entries.Count; } } } } internal static class RuntimeTuning { internal static float VisualSafety; internal static float StaticVisualSafety; internal static float ArmorClothInterval; internal static float LightNearSqr; internal static float LightMidSqr; internal static float LightFarSqr; internal static float LightMidInterval; internal static float LightFarInterval; internal static float LightDistantInterval; internal static float LightDistanceCheckInterval; internal static float LightLodDecisionInterval; internal static int LightLodChecksPerFrame; internal static float SmokeRendererInterval; internal static float WindmillAudioInterval; internal static float VagonAudioInterval; internal static void Refresh(OptimizerConfig c) { VisualSafety = Mathf.Max(5f, c.VisualSafetyRefreshSeconds.Value); StaticVisualSafety = Mathf.Max(10f, c.StaticVisualSafetyRefreshSeconds.Value); ArmorClothInterval = UpdateRateLimiter.IntervalFromRate(c.ArmorStandClothRate.Value); float num = Mathf.Max(0f, c.LightFlickerNearDistance.Value); float num2 = Mathf.Max(num, c.LightFlickerMidDistance.Value); float num3 = Mathf.Max(num2, c.LightFlickerFarDistance.Value); LightNearSqr = num * num; LightMidSqr = num2 * num2; LightFarSqr = num3 * num3; LightMidInterval = UpdateRateLimiter.IntervalFromRate(c.LightFlickerMidRate.Value); LightFarInterval = UpdateRateLimiter.IntervalFromRate(c.LightFlickerFarRate.Value); LightDistantInterval = UpdateRateLimiter.IntervalFromRate(c.LightFlickerDistantRate.Value); LightDistanceCheckInterval = UpdateRateLimiter.IntervalFromRate(c.LightFlickerDistanceCheckRate.Value); LightLodDecisionInterval = UpdateRateLimiter.IntervalFromRate(c.LightLodDistanceCheckRate.Value); LightLodChecksPerFrame = Mathf.Clamp(c.LightLodChecksPerFrame.Value, 32, 4096); SmokeRendererInterval = UpdateRateLimiter.IntervalFromRate(c.SmokeRendererRate.Value); WindmillAudioInterval = UpdateRateLimiter.IntervalFromRate(c.WindmillAudioRate.Value); VagonAudioInterval = UpdateRateLimiter.IntervalFromRate(c.VagonAudioRate.Value); } } internal static class UpdateRateLimiter { internal static float IntervalFromRate(float updatesPerSecond) { return 1f / Mathf.Max(0.01f, updatesPerSecond); } internal static bool IsDue(ref float nextTime, float interval, float now, int phaseSeed) { if (interval <= 0f) { nextTime = now; return true; } if (nextTime <= 0f) { nextTime = now + interval * Phase01(phaseSeed); return true; } if (now < nextTime) { return false; } nextTime = now + interval; return true; } internal static float StaggeredSafetyDeadline(float now, float maximumInterval, int phaseSeed) { if (maximumInterval <= 0f) { return now; } float num = 0.75f + 0.25f * Phase01(phaseSeed); return now + maximumInterval * num; } internal static bool IsDiscontinuous(ref float lastSeenTime, float now, float maximumGap) { bool result = lastSeenTime > 0f && (now < lastSeenTime || now - lastSeenTime > maximumGap); lastSeenTime = now; return result; } internal static float Phase01Public(int seed) { return Phase01(seed); } private static float Phase01(int seed) { uint num = (uint)seed; num ^= num >> 16; num *= 2146121005; num ^= num >> 15; num *= 2221713035u; num ^= num >> 16; return (float)(num & 0xFFFFFF) / 16777215f; } } internal static class VanillaCollectionRegistry { internal static List Pieces { get; private set; } internal static HashSet ComfortPieces { get; private set; } internal static List CraftingStations { get; private set; } internal static List StationExtensions { get; private set; } internal static int GhostLayer { get; private set; } internal static void Initialize() { Pieces = Piece.s_allPieces; ComfortPieces = Piece.s_allComfortPieces; CraftingStations = CraftingStation.m_allStations; StationExtensions = StationExtension.m_allExtensions; GhostLayer = LayerMask.NameToLayer("ghost"); } } internal static class WeakStateStore where TKey : class where TState : class, new() { private static readonly ConditionalWeakTable States = new ConditionalWeakTable(); internal static TState Get(TKey key) { return States.GetValue(key, Create); } internal static bool TryGet(TKey key, out TState state) { state = null; return key != null && States.TryGetValue(key, out state); } private static TState Create(TKey key) { return new TState(); } internal static void Remove(TKey key) { if (key != null) { States.Remove(key); } } } internal sealed class WeakUnityRegistry where T : Object { private readonly Dictionary entries = new Dictionary(); private readonly List dead = new List(); internal int Count => entries.Count; internal void Add(T value) { if (!((Object)(object)value == (Object)null)) { int instanceID = ((Object)value).GetInstanceID(); entries[instanceID] = new WeakReference(value); } } internal void Remove(T value) { if ((Object)(object)value != (Object)null) { entries.Remove(((Object)value).GetInstanceID()); } } internal void ForEachAlive(Action action) { dead.Clear(); foreach (KeyValuePair entry in entries) { object? target = entry.Value.Target; T val = (T)((target is T) ? target : null); if ((Object)(object)val == (Object)null) { dead.Add(entry.Key); } else { action(val); } } for (int i = 0; i < dead.Count; i++) { entries.Remove(dead[i]); } } internal void Clear() { entries.Clear(); dead.Clear(); } } } namespace BalrondVisualOptimizer.Patches.ZSFXOptimizations { internal static class ZSFXPatches { private static readonly WeakUnityRegistry Sleepers = new WeakUnityRegistry(); private static readonly List UnexpectedPlayers = new List(); private static PatchRuntimeGate updateGate; private static PatchRuntimeGate playGate; private static PatchRuntimeGate fadeGate; private static float nextWatchdog; private static bool CanSleep => updateGate != null && playGate != null && fadeGate != null && updateGate.Enabled && playGate.Enabled && fadeGate.Enabled; internal static void Install(PatchInstaller installer) { updateGate = installer.Install("ZSFX.CustomUpdate idle dormancy", AccessTools.Method(typeof(ZSFX), "CustomUpdate", new Type[2] { typeof(float), typeof(float) }, (Type[])null), null, AccessTools.Method(typeof(ZSFXPatches), "UpdatePostfix", (Type[])null, (Type[])null), Launch.Settings.ZsfxDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); playGate = installer.Install("ZSFX.Play wake hook", AccessTools.Method(typeof(ZSFX), "Play", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(ZSFXPatches), "WakePrefix", (Type[])null, (Type[])null), null, Launch.Settings.ZsfxDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); fadeGate = installer.Install("ZSFX.FadeOut wake hook", AccessTools.Method(typeof(ZSFX), "FadeOut", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(ZSFXPatches), "WakePrefix", (Type[])null, (Type[])null), null, Launch.Settings.ZsfxDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static void UpdatePostfix(ZSFX __instance) { if (CanSleep && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_audioSource == (Object)null) && !__instance.m_audioSource.loop && !__instance.m_audioSource.isPlaying && (!__instance.m_playOnAwake || !(__instance.m_delay >= 0f)) && !(__instance.m_fadeOutTimer >= 0f) && !(__instance.m_fadeInTimer >= 0f) && ZSFX.Instances.Remove((IMonoUpdater)(object)__instance)) { Sleepers.Add(__instance); RuntimeStats.Inc(ref RuntimeStats.ZsfxDormantFrames); } } private static void WakePrefix(ZSFX __instance) { if (!((Object)(object)__instance == (Object)null) && CanSleep) { Wake(__instance); } } private static void Wake(ZSFX instance) { if (!((Object)(object)instance == (Object)null)) { if (((Behaviour)instance).enabled && ((Component)instance).gameObject.activeInHierarchy && !ZSFX.Instances.Contains((IMonoUpdater)(object)instance)) { ZSFX.Instances.Add((IMonoUpdater)(object)instance); } Sleepers.Remove(instance); } } internal static void Tick(float now) { if (!CanSleep || now < nextWatchdog || Sleepers.Count == 0) { return; } nextWatchdog = now + 1f; UnexpectedPlayers.Clear(); Sleepers.ForEachAlive(delegate(ZSFX s) { if (((Behaviour)s).enabled && ((Component)s).gameObject.activeInHierarchy && (Object)(object)s.m_audioSource != (Object)null && s.m_audioSource.isPlaying) { UnexpectedPlayers.Add(s); } }); for (int num = 0; num < UnexpectedPlayers.Count; num++) { Wake(UnexpectedPlayers[num]); } UnexpectedPlayers.Clear(); } internal static void RefreshDormancy() { if (!CanSleep) { WakeAll(); } } internal static void Shutdown() { WakeAll(); } private static void WakeAll() { Sleepers.ForEachAlive(delegate(ZSFX s) { if (((Behaviour)s).enabled && ((Component)s).gameObject.activeInHierarchy && !ZSFX.Instances.Contains((IMonoUpdater)(object)s)) { ZSFX.Instances.Add((IMonoUpdater)(object)s); } }); Sleepers.Clear(); UnexpectedPlayers.Clear(); nextWatchdog = 0f; } } } namespace BalrondVisualOptimizer.Patches.WindmillOptimizations { internal static class WindmillPatches { private sealed class State { internal int Epoch; internal float NextUpdate; internal float AccumulatedDelta; internal float LastSeenTime; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("Windmill.UpdateAudio throttle", AccessTools.Method(typeof(Windmill), "UpdateAudio", new Type[1] { typeof(float) }, (Type[])null), AccessTools.Method(typeof(WindmillPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.WindmillAudio, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(Windmill __instance, ref float dt) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { Reset(state, gate.Epoch); } float windmillAudioInterval = RuntimeTuning.WindmillAudioInterval; float time = Time.time; if (UpdateRateLimiter.IsDiscontinuous(ref state.LastSeenTime, time, Mathf.Max(1f, windmillAudioInterval * 3f))) { state.NextUpdate = 0f; state.AccumulatedDelta = 0f; } if (UpdateRateLimiter.IsDue(ref state.NextUpdate, windmillAudioInterval, time, ((Object)__instance).GetInstanceID())) { if (state.AccumulatedDelta > 0f) { dt += state.AccumulatedDelta; state.AccumulatedDelta = 0f; } return true; } state.AccumulatedDelta += dt; RuntimeStats.Inc(ref RuntimeStats.WindmillAudioSkips); return false; } private static void Reset(State state, int epoch) { state.Epoch = epoch; state.NextUpdate = 0f; state.AccumulatedDelta = 0f; state.LastSeenTime = 0f; } } } namespace BalrondVisualOptimizer.Patches.VisEquipmentOptimizations { internal static class VisEquipmentPatches { private struct EquipmentSignature { internal int Left; internal int Right; internal int Chest; internal int Legs; internal int Helmet; internal int Shoulder; internal int Utility; internal int Trinket; internal int Beard; internal int Hair; internal int LeftBack; internal int RightBack; internal int ShoulderVariant; internal int LeftVariant; internal int LeftBackVariant; internal bool SameAs(EquipmentSignature other) { return Left == other.Left && Right == other.Right && Chest == other.Chest && Legs == other.Legs && Helmet == other.Helmet && Shoulder == other.Shoulder && Utility == other.Utility && Trinket == other.Trinket && Beard == other.Beard && Hair == other.Hair && LeftBack == other.LeftBack && RightBack == other.RightBack && ShoulderVariant == other.ShoulderVariant && LeftVariant == other.LeftVariant && LeftBackVariant == other.LeftBackVariant; } } private sealed class State { internal int EquipmentEpoch; internal uint EquipmentRevision = uint.MaxValue; internal EquipmentSignature Equipment; internal bool HasEquipment; internal float EquipmentSafetyRefresh; internal int ColorEpoch; internal Vector3 SkinColor; internal Vector3 HairColor; internal bool HasColors; internal float ColorSafetyRefresh; internal uint ColorRevision = uint.MaxValue; internal int BeardInstanceId; internal int HairInstanceId; internal int ModelIndex = int.MinValue; } private static PatchRuntimeGate equipmentGate; private static PatchRuntimeGate colorGate; internal static void Install(PatchInstaller installer) { equipmentGate = installer.Install("VisEquipment.UpdateEquipmentVisuals signature gate", AccessTools.Method(typeof(VisEquipment), "UpdateEquipmentVisuals", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(VisEquipmentPatches), "EquipmentPrefix", (Type[])null, (Type[])null), null, Launch.Settings.VisEquipmentEquipment, requiresKnownBuild: true, strictForeignPatchCheck: true); colorGate = installer.Install("VisEquipment.UpdateColors signature gate", AccessTools.Method(typeof(VisEquipment), "UpdateColors", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(VisEquipmentPatches), "ColorPrefix", (Type[])null, (Type[])null), null, Launch.Settings.VisEquipmentColors, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool EquipmentPrefix(VisEquipment __instance) { if (equipmentGate == null || !equipmentGate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } State state = WeakStateStore.Get(__instance); if (state.EquipmentEpoch != equipmentGate.Epoch) { state.EquipmentEpoch = equipmentGate.Epoch; state.HasEquipment = false; state.EquipmentRevision = uint.MaxValue; state.EquipmentSafetyRefresh = 0f; } float unscaledTime = Time.unscaledTime; uint dataRevision = zDO.DataRevision; int num = (__instance.m_isPlayer ? zDO.GetInt(ZDOVars.s_shoulderItemVariant, 0) : __instance.m_shoulderItemVariant); int num2 = (__instance.m_isPlayer ? zDO.GetInt(ZDOVars.s_leftItemVariant, 0) : __instance.m_leftItemVariant); int num3 = (__instance.m_isPlayer ? zDO.GetInt(ZDOVars.s_leftBackItemVariant, 0) : __instance.m_leftBackItemVariant); if (state.HasEquipment && dataRevision == state.EquipmentRevision && state.Equipment.ShoulderVariant == num && state.Equipment.LeftVariant == num2 && state.Equipment.LeftBackVariant == num3 && unscaledTime < state.EquipmentSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.VisEquipmentEquipmentSkips); return false; } EquipmentSignature equipmentSignature = ReadEquipmentSignature(__instance, zDO, num, num2, num3); bool flag = !state.HasEquipment || !state.Equipment.SameAs(equipmentSignature); state.EquipmentRevision = dataRevision; if (!flag && unscaledTime < state.EquipmentSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.VisEquipmentEquipmentSkips); return false; } state.Equipment = equipmentSignature; state.HasEquipment = true; state.EquipmentSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.VisualSafety, ((Object)__instance).GetInstanceID()); return true; } private static EquipmentSignature ReadEquipmentSignature(VisEquipment instance, ZDO zdo, int shoulderVariant, int leftVariant, int leftBackVariant) { EquipmentSignature result = new EquipmentSignature { Left = zdo.GetInt(ZDOVars.s_leftItem, 0), Right = zdo.GetInt(ZDOVars.s_rightItem, 0), Chest = zdo.GetInt(ZDOVars.s_chestItem, 0), Legs = zdo.GetInt(ZDOVars.s_legItem, 0), Helmet = zdo.GetInt(ZDOVars.s_helmetItem, 0), Shoulder = zdo.GetInt(ZDOVars.s_shoulderItem, 0), Utility = zdo.GetInt(ZDOVars.s_utilityItem, 0), Trinket = zdo.GetInt(ZDOVars.s_trinketItem, 0), ShoulderVariant = shoulderVariant, LeftVariant = leftVariant, LeftBackVariant = leftBackVariant }; if (instance.m_isPlayer) { if (!instance.m_isArmorStand) { result.Beard = zdo.GetInt(ZDOVars.s_beardItem, 0); result.Hair = zdo.GetInt(ZDOVars.s_hairItem, 0); } result.LeftBack = zdo.GetInt(ZDOVars.s_leftBackItem, 0); result.RightBack = zdo.GetInt(ZDOVars.s_rightBackItem, 0); } return result; } private static bool ColorPrefix(VisEquipment __instance) { //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) if (colorGate == null || !colorGate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } State state = WeakStateStore.Get(__instance); if (state.ColorEpoch != colorGate.Epoch) { state.ColorEpoch = colorGate.Epoch; state.HasColors = false; state.ColorRevision = uint.MaxValue; state.ColorSafetyRefresh = 0f; state.BeardInstanceId = 0; state.HairInstanceId = 0; } float unscaledTime = Time.unscaledTime; uint dataRevision = zDO.DataRevision; int num = ((!((Object)(object)__instance.m_beardItemInstance == (Object)null)) ? ((Object)__instance.m_beardItemInstance).GetInstanceID() : 0); int num2 = ((!((Object)(object)__instance.m_hairItemInstance == (Object)null)) ? ((Object)__instance.m_hairItemInstance).GetInstanceID() : 0); int num3 = zDO.GetInt(ZDOVars.s_modelIndex, __instance.m_modelIndex); bool flag = state.BeardInstanceId == num && state.HairInstanceId == num2 && state.ModelIndex == num3; if (state.HasColors && state.ColorRevision == dataRevision && flag && unscaledTime < state.ColorSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.VisEquipmentColorSkips); return false; } Vector3 vec = zDO.GetVec3(ZDOVars.s_skinColor, Vector3.one); Vector3 vec2 = zDO.GetVec3(ZDOVars.s_hairColor, Vector3.one); if (state.HasColors && flag && state.SkinColor == vec && state.HairColor == vec2 && unscaledTime < state.ColorSafetyRefresh) { state.ColorRevision = dataRevision; RuntimeStats.Inc(ref RuntimeStats.VisEquipmentColorSkips); return false; } state.SkinColor = vec; state.HairColor = vec2; state.ColorRevision = dataRevision; state.BeardInstanceId = num; state.HairInstanceId = num2; state.ModelIndex = num3; state.HasColors = true; state.ColorSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.VisualSafety, ((Object)__instance).GetInstanceID() ^ 0x51C0); return true; } } } namespace BalrondVisualOptimizer.Patches.VagonOptimizations { internal static class VagonPatches { private sealed class AudioState { internal int Epoch; internal float NextUpdate; internal float AccumulatedDelta; internal float LastSeenTime; } private static PatchRuntimeGate audioGate; private static PatchRuntimeGate tetherGate; internal static void Install(PatchInstaller installer) { audioGate = installer.Install("Vagon.UpdateAudio throttle", AccessTools.Method(typeof(Vagon), "UpdateAudio", new Type[1] { typeof(float) }, (Type[])null), AccessTools.Method(typeof(VagonPatches), "AudioPrefix", (Type[])null, (Type[])null), null, Launch.Settings.VagonAudio, requiresKnownBuild: true, strictForeignPatchCheck: true); tetherGate = installer.Install("Vagon.LateUpdate parked tether no-op gate", AccessTools.Method(typeof(Vagon), "LateUpdate", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(VagonPatches), "LateUpdatePrefix", (Type[])null, (Type[])null), null, Launch.Settings.VagonIdleTether, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool AudioPrefix(Vagon __instance, ref float dt) { if (audioGate == null || !audioGate.Enabled || (Object)(object)__instance == (Object)null) { return true; } AudioState audioState = WeakStateStore.Get(__instance); if (audioState.Epoch != audioGate.Epoch) { Reset(audioState, audioGate.Epoch); } float vagonAudioInterval = RuntimeTuning.VagonAudioInterval; float time = Time.time; if (UpdateRateLimiter.IsDiscontinuous(ref audioState.LastSeenTime, time, Mathf.Max(1f, vagonAudioInterval * 3f))) { audioState.NextUpdate = 0f; audioState.AccumulatedDelta = 0f; } if (UpdateRateLimiter.IsDue(ref audioState.NextUpdate, vagonAudioInterval, time, ((Object)__instance).GetInstanceID())) { if (audioState.AccumulatedDelta > 0f) { dt += audioState.AccumulatedDelta; audioState.AccumulatedDelta = 0f; } return true; } audioState.AccumulatedDelta += dt; RuntimeStats.Inc(ref RuntimeStats.VagonAudioSkips); return false; } private static bool LateUpdatePrefix(Vagon __instance) { if (tetherGate == null || !tetherGate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_attachJoin == (Object)null && (Object)(object)__instance.m_lineRenderer != (Object)null && !((Renderer)__instance.m_lineRenderer).enabled) { RuntimeStats.Inc(ref RuntimeStats.VagonTetherSkips); return false; } return true; } private static void Reset(AudioState state, int epoch) { state.Epoch = epoch; state.NextUpdate = 0f; state.AccumulatedDelta = 0f; state.LastSeenTime = 0f; } } } namespace BalrondVisualOptimizer.Patches.TeleportWorldOptimizations { internal static class TeleportWorldPatches { private sealed class State { internal int Epoch; internal bool HasTarget; internal float NextSafety; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("TeleportWorld.Update stable emission gate", AccessTools.Method(typeof(TeleportWorld), "Update", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(TeleportWorldPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.PortalStableEmission, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(TeleportWorld __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } float num = (__instance.m_hadTarget ? 1f : 0f); if (!Mathf.Approximately(__instance.m_colorAlpha, num)) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.HasTarget = !__instance.m_hadTarget; state.NextSafety = 0f; } float unscaledTime = Time.unscaledTime; if (state.HasTarget == __instance.m_hadTarget && unscaledTime < state.NextSafety) { RuntimeStats.Inc(ref RuntimeStats.PortalVisualSkips); return false; } state.HasTarget = __instance.m_hadTarget; state.NextSafety = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.StaticVisualSafety, ((Object)__instance).GetInstanceID()); return true; } } } namespace BalrondVisualOptimizer.Patches.StationExtensionOptimizations { internal static class StationExtensionPatches { private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("StationExtension.OtherExtensionInRange squared-distance query", AccessTools.Method(typeof(StationExtension), "OtherExtensionInRange", new Type[1] { typeof(float) }, (Type[])null), AccessTools.Method(typeof(StationExtensionPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.StationExtensionSquaredDistanceQuery, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(StationExtension __instance, float radius, ref bool __result) { //IL_0060: 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) //IL_009a: 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) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) List stationExtensions = VanillaCollectionRegistry.StationExtensions; if (gate == null || !gate.Enabled || stationExtensions == null || (Object)(object)__instance == (Object)null) { return true; } if (!(radius > 0f) || float.IsNaN(radius)) { __result = false; return false; } float num = radius * radius; Vector3 position = ((Component)__instance).transform.position; for (int i = 0; i < stationExtensions.Count; i++) { StationExtension val = stationExtensions[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)__instance)) { Vector3 val2 = ((Component)val).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude < num) { __result = true; RuntimeStats.Inc(ref RuntimeStats.StationExtensionQueryReplacements); return false; } } } __result = false; RuntimeStats.Inc(ref RuntimeStats.StationExtensionQueryReplacements); return false; } } } namespace BalrondVisualOptimizer.Patches.SmokeRendererOptimizations { internal static class SmokeRendererPatches { private sealed class State { internal int Epoch; internal float NextUpdate; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("SmokeRenderer.LateUpdate presentation throttle", AccessTools.Method(typeof(SmokeRenderer), "LateUpdate", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(SmokeRendererPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.SmokeRenderer, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(SmokeRenderer __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.NextUpdate = 0f; } if (!UpdateRateLimiter.IsDue(ref state.NextUpdate, RuntimeTuning.SmokeRendererInterval, Time.time, ((Object)__instance).GetInstanceID())) { if (__instance.m_chunkedSmoke != null && __instance.m_chunkedSmoke.Count > 0) { RuntimeStats.Inc(ref RuntimeStats.SmokeRendererSkips); } return false; } return true; } } } namespace BalrondVisualOptimizer.Patches.SmelterOptimizations { internal static class SmelterPatches { private struct Signature { internal bool Active; internal bool HasFuel; internal bool HasOre; internal bool AnimationActive; internal bool SameAs(Signature other) { return Active == other.Active && HasFuel == other.HasFuel && HasOre == other.HasOre && AnimationActive == other.AnimationActive; } } private sealed class State { internal int Epoch; internal bool HasValue; internal uint Revision = uint.MaxValue; internal bool HaveRoof; internal bool BlockedSmoke; internal bool AnimationWindow; internal Signature Value; internal float NextSafetyRefresh; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("Smelter.UpdateState visual signature gate", AccessTools.Method(typeof(Smelter), "UpdateState", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(SmelterPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.SmelterVisualState, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(Smelter __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.HasValue = false; state.Revision = uint.MaxValue; state.NextSafetyRefresh = 0f; } float unscaledTime = Time.unscaledTime; bool flag = __instance.m_addOreAnimationDuration > 0f && Time.time - __instance.m_addedOreTime < __instance.m_addOreAnimationDuration; uint dataRevision = zDO.DataRevision; if (state.HasValue && dataRevision == state.Revision && state.HaveRoof == __instance.m_haveRoof && state.BlockedSmoke == __instance.m_blockedSmoke && state.AnimationWindow == flag && unscaledTime < state.NextSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.SmelterStateSkips); return false; } float num = zDO.GetFloat(ZDOVars.s_fuel, 0f); int num2 = zDO.GetInt(ZDOVars.s_queued, 0); bool flag2 = num > 0f; bool flag3 = num2 > 0; bool flag4 = (__instance.m_maxFuel == 0 || flag2) && (__instance.m_maxOre == 0 || flag3) && (!__instance.m_requiresRoof || __instance.m_haveRoof) && !__instance.m_blockedSmoke; Signature signature = new Signature { Active = flag4, HasFuel = flag2, HasOre = flag3, AnimationActive = (flag4 || flag) }; if (state.HasValue && state.Value.SameAs(signature) && unscaledTime < state.NextSafetyRefresh) { state.Revision = dataRevision; state.HaveRoof = __instance.m_haveRoof; state.BlockedSmoke = __instance.m_blockedSmoke; state.AnimationWindow = flag; RuntimeStats.Inc(ref RuntimeStats.SmelterStateSkips); return false; } state.Value = signature; state.HasValue = true; state.Revision = dataRevision; state.HaveRoof = __instance.m_haveRoof; state.BlockedSmoke = __instance.m_blockedSmoke; state.AnimationWindow = flag; state.NextSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.VisualSafety, ((Object)__instance).GetInstanceID()); return true; } } } namespace BalrondVisualOptimizer.Patches.PrivateAreaOptimizations { internal static class PrivateAreaPatches { private sealed class State { internal int Epoch; internal bool HasValue; internal bool Enabled; internal float NextSafety; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("PrivateArea.UpdateStatus stable visual gate", AccessTools.Method(typeof(PrivateArea), "UpdateStatus", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(PrivateAreaPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.PrivateAreaStatusVisual, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(PrivateArea __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } __instance.m_flashAvailable = true; bool flag = __instance.IsEnabled(); State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.HasValue = false; state.NextSafety = 0f; } float unscaledTime = Time.unscaledTime; if (state.HasValue && state.Enabled == flag && unscaledTime < state.NextSafety) { RuntimeStats.Inc(ref RuntimeStats.PrivateAreaVisualSkips); return false; } state.HasValue = true; state.Enabled = flag; state.NextSafety = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.StaticVisualSafety, ((Object)__instance).GetInstanceID()); return true; } } } namespace BalrondVisualOptimizer.Patches.PieceOptimizations { internal static class PiecePatches { private static PatchRuntimeGate allPiecesGate; private static PatchRuntimeGate comfortPiecesGate; internal static void Install(PatchInstaller installer) { allPiecesGate = installer.Install("Piece.GetAllPiecesInRadius squared-distance query", AccessTools.Method(typeof(Piece), "GetAllPiecesInRadius", new Type[3] { typeof(Vector3), typeof(float), typeof(List) }, (Type[])null), AccessTools.Method(typeof(PiecePatches), "AllPiecesPrefix", (Type[])null, (Type[])null), null, Launch.Settings.PieceSquaredDistanceQueries, requiresKnownBuild: true, strictForeignPatchCheck: true); comfortPiecesGate = installer.Install("Piece.GetAllComfortPiecesInRadius squared-distance query", AccessTools.Method(typeof(Piece), "GetAllComfortPiecesInRadius", new Type[3] { typeof(Vector3), typeof(float), typeof(List) }, (Type[])null), AccessTools.Method(typeof(PiecePatches), "ComfortPiecesPrefix", (Type[])null, (Type[])null), null, Launch.Settings.PieceSquaredDistanceQueries, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool AllPiecesPrefix(Vector3 p, float radius, List pieces) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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) List pieces2 = VanillaCollectionRegistry.Pieces; if (allPiecesGate == null || !allPiecesGate.Enabled || pieces2 == null || pieces == null) { return true; } if (!(radius > 0f) || float.IsNaN(radius)) { return false; } float num = radius * radius; int ghostLayer = VanillaCollectionRegistry.GhostLayer; for (int i = 0; i < pieces2.Count; i++) { Piece val = pieces2[i]; if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.layer != ghostLayer) { Vector3 val2 = ((Component)val).transform.position - p; if (((Vector3)(ref val2)).sqrMagnitude < num) { pieces.Add(val); } } } RuntimeStats.Inc(ref RuntimeStats.PieceQueryReplacements); return false; } private static bool ComfortPiecesPrefix(Vector3 p, float radius, List pieces) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) HashSet comfortPieces = VanillaCollectionRegistry.ComfortPieces; if (comfortPiecesGate == null || !comfortPiecesGate.Enabled || comfortPieces == null || pieces == null) { return true; } if (!(radius > 0f) || float.IsNaN(radius)) { return false; } float num = radius * radius; int ghostLayer = VanillaCollectionRegistry.GhostLayer; foreach (Piece item in comfortPieces) { if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.layer != ghostLayer) { Vector3 val = ((Component)item).transform.position - p; if (((Vector3)(ref val)).sqrMagnitude < num) { pieces.Add(item); } } } RuntimeStats.Inc(ref RuntimeStats.PieceQueryReplacements); return false; } } } namespace BalrondVisualOptimizer.Patches.MaterialFaderOptimizations { internal static class MaterialFaderPatches { private static readonly WeakUnityRegistry Sleepers = new WeakUnityRegistry(); private static PatchRuntimeGate updateGate; private static PatchRuntimeGate triggerGate; private static bool CanSleep => updateGate != null && triggerGate != null && updateGate.Enabled && triggerGate.Enabled; internal static void Install(PatchInstaller installer) { updateGate = installer.Install("MaterialFader.Update endpoint dormancy", AccessTools.Method(typeof(MaterialFader), "Update", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(MaterialFaderPatches), "UpdatePrefix", (Type[])null, (Type[])null), null, Launch.Settings.MaterialFaderDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); triggerGate = installer.Install("MaterialFader.TriggerFade wake hook", AccessTools.Method(typeof(MaterialFader), "TriggerFade", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(MaterialFaderPatches), "TriggerPrefix", (Type[])null, (Type[])null), null, Launch.Settings.MaterialFaderDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool UpdatePrefix(MaterialFader __instance) { if (!CanSleep || (Object)(object)__instance == (Object)null) { return true; } if (!__instance.m_started) { Sleep(__instance); return false; } bool flag = __instance.m_fadeProperties != null; if (flag) { for (int i = 0; i < __instance.m_fadeProperties.Count; i++) { if (!__instance.m_fadeProperties[i].m_finished) { flag = false; break; } } } if (!flag) { return true; } Sleep(__instance); return false; } private static void TriggerPrefix(MaterialFader __instance) { if (!((Object)(object)__instance == (Object)null) && CanSleep) { Sleepers.Remove(__instance); if (!((Behaviour)__instance).enabled) { ((Behaviour)__instance).enabled = true; } } } private static void Sleep(MaterialFader instance) { Sleepers.Add(instance); ((Behaviour)instance).enabled = false; RuntimeStats.Inc(ref RuntimeStats.MaterialFaderDormantFrames); } internal static void RefreshDormancy() { if (CanSleep) { return; } Sleepers.ForEachAlive(delegate(MaterialFader f) { if (!((Behaviour)f).enabled) { ((Behaviour)f).enabled = true; } }); Sleepers.Clear(); } internal static void Shutdown() { Sleepers.ForEachAlive(delegate(MaterialFader f) { if (!((Behaviour)f).enabled) { ((Behaviour)f).enabled = true; } }); Sleepers.Clear(); } } } namespace BalrondVisualOptimizer.Patches.LineConnectOptimizations { internal static class LineConnectPatches { private sealed class State { internal int Epoch; internal bool HiddenNoConnection; internal uint Revision = uint.MaxValue; internal float NextSafety; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("LineConnect.LateUpdate stable no-connection gate", AccessTools.Method(typeof(LineConnect), "LateUpdate", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(LineConnectPatches), "Prefix", (Type[])null, (Type[])null), AccessTools.Method(typeof(LineConnectPatches), "Postfix", (Type[])null, (Type[])null), Launch.Settings.LineConnectStableNoConnection, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(LineConnect __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { if ((Object)(object)__instance.m_lineRenderer != (Object)null && !((Renderer)__instance.m_lineRenderer).enabled) { RuntimeStats.Inc(ref RuntimeStats.LineConnectSkips); return false; } return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.HiddenNoConnection = false; state.Revision = uint.MaxValue; state.NextSafety = 0f; } float unscaledTime = Time.unscaledTime; if (state.HiddenNoConnection && state.Revision == zDO.DataRevision && unscaledTime < state.NextSafety) { RuntimeStats.Inc(ref RuntimeStats.LineConnectSkips); return false; } return true; } private static void Postfix(LineConnect __instance) { if (gate != null && gate.Enabled && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid()) { ZDO zDO = __instance.m_nview.GetZDO(); if (zDO != null) { State state = WeakStateStore.Get(__instance); state.HiddenNoConnection = __instance.m_hideIfNoConnection && (Object)(object)__instance.m_lineRenderer != (Object)null && !((Renderer)__instance.m_lineRenderer).enabled; state.Revision = zDO.DataRevision; state.NextSafety = Time.unscaledTime + 1f * (0.75f + 0.25f * UpdateRateLimiter.Phase01Public(((Object)__instance).GetInstanceID())); } } } } } namespace BalrondVisualOptimizer.Patches.LightLodOptimizations { internal static class LightLodPatches { private static PatchRuntimeGate enableGate; private static PatchRuntimeGate disableGate; internal static bool CanManage { get { if (enableGate == null || disableGate == null || !enableGate.Enabled || !disableGate.Enabled) { return false; } if (Launch.Settings != null && Launch.Settings.DisableOnForeignHarmonyPatches.Value && HarmonyConflictService.TryGetFirstForeignOwner(AccessTools.Method(typeof(LightLod), "UpdateLoop", Type.EmptyTypes, (Type[])null), out var _)) { return false; } return true; } } internal static void Install(PatchInstaller installer) { enableGate = installer.Install("LightLod.OnEnable central scheduler hook", AccessTools.Method(typeof(LightLod), "OnEnable", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(LightLodPatches), "OnEnablePrefix", (Type[])null, (Type[])null), null, Launch.Settings.LightLodCentralScheduler, requiresKnownBuild: true, strictForeignPatchCheck: true); disableGate = installer.Install("LightLod.OnDisable central scheduler hook", AccessTools.Method(typeof(LightLod), "OnDisable", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(LightLodPatches), "OnDisablePrefix", (Type[])null, (Type[])null), null, Launch.Settings.LightLodCentralScheduler, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool OnEnablePrefix(LightLod __instance) { if (!CanManage || (Object)(object)__instance == (Object)null) { return true; } LightLodScheduler.Register(__instance); RuntimeStats.Inc(ref RuntimeStats.LightLodCoroutineReplacements); return false; } private static bool OnDisablePrefix(LightLod __instance) { if (!CanManage || (Object)(object)__instance == (Object)null) { return true; } LightLodScheduler.Unregister(__instance); return false; } internal static void RefreshScheduler() { LightLodScheduler.SetEnabled(CanManage); } } } namespace BalrondVisualOptimizer.Patches.LightFlickerOptimizations { internal static class LightFlickerPatches { private sealed class State { internal int Epoch; internal float NextUpdate; internal float NextDistanceCheck; internal float CachedInterval; internal bool HasDistanceTier; internal float AccumulatedDelta; internal float LastInternalTime; internal bool HasInternalTime; internal float LastSeenTime; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("LightFlicker.CustomUpdate persistent distance throttle", AccessTools.Method(typeof(LightFlicker), "CustomUpdate", new Type[2] { typeof(float), typeof(float) }, (Type[])null), AccessTools.Method(typeof(LightFlickerPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.LightFlicker, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(LightFlicker __instance, ref float deltaTime) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_light == (Object)null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { Reset(state, gate.Epoch); } if (!((Behaviour)__instance.m_light).enabled) { state.NextUpdate = 0f; state.AccumulatedDelta = 0f; state.LastSeenTime = 0f; state.LastInternalTime = __instance.m_time; state.HasInternalTime = true; return false; } if (state.HasInternalTime && __instance.m_time < state.LastInternalTime) { state.NextUpdate = 0f; state.AccumulatedDelta = 0f; state.LastSeenTime = 0f; state.NextDistanceCheck = 0f; state.HasDistanceTier = false; } state.LastInternalTime = __instance.m_time; state.HasInternalTime = true; if (__instance.m_ttl > 0f || (__instance.m_fadeInDuration > 0f && __instance.m_time < __instance.m_fadeInDuration)) { return FlushAndRunVanilla(state, ref deltaTime); } float time = Time.time; if (!state.HasDistanceTier || time >= state.NextDistanceCheck) { state.CachedInterval = DetermineInterval(__instance); state.HasDistanceTier = true; state.NextDistanceCheck = time + RuntimeTuning.LightDistanceCheckInterval * (0.75f + 0.25f * UpdateRateLimiter.Phase01Public(((Object)__instance).GetInstanceID() ^ 0x3A71)); } float cachedInterval = state.CachedInterval; if (cachedInterval <= 0f) { state.LastSeenTime = time; return FlushAndRunVanilla(state, ref deltaTime); } if (UpdateRateLimiter.IsDiscontinuous(ref state.LastSeenTime, time, Mathf.Max(1f, cachedInterval * 3f))) { state.NextUpdate = 0f; state.AccumulatedDelta = 0f; } if (UpdateRateLimiter.IsDue(ref state.NextUpdate, cachedInterval, time, ((Object)__instance).GetInstanceID())) { if (state.AccumulatedDelta > 0f) { deltaTime += state.AccumulatedDelta; state.AccumulatedDelta = 0f; } return true; } state.AccumulatedDelta += deltaTime; RuntimeStats.Inc(ref RuntimeStats.LightFlickerSkips); return false; } private static float DetermineInterval(LightFlicker instance) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_005d: Unknown result type (might be due to invalid IL or missing references) Vector3 position; if ((Object)(object)Player.m_localPlayer != (Object)null) { position = ((Component)Player.m_localPlayer).transform.position; } else { Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera == (Object)null) { return 0f; } position = ((Component)mainCamera).transform.position; } Vector3 val = ((Component)instance).transform.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= RuntimeTuning.LightNearSqr) { return 0f; } if (sqrMagnitude <= RuntimeTuning.LightMidSqr) { return RuntimeTuning.LightMidInterval; } if (sqrMagnitude <= RuntimeTuning.LightFarSqr) { return RuntimeTuning.LightFarInterval; } return RuntimeTuning.LightDistantInterval; } private static bool FlushAndRunVanilla(State state, ref float deltaTime) { if (state.AccumulatedDelta > 0f) { deltaTime += state.AccumulatedDelta; state.AccumulatedDelta = 0f; } state.NextUpdate = 0f; return true; } private static void Reset(State state, int epoch) { state.Epoch = epoch; state.NextUpdate = 0f; state.NextDistanceCheck = 0f; state.CachedInterval = 0f; state.HasDistanceTier = false; state.AccumulatedDelta = 0f; state.LastInternalTime = 0f; state.HasInternalTime = false; state.LastSeenTime = 0f; } } } namespace BalrondVisualOptimizer.Patches.ItemStandOptimizations { internal static class ItemStandPatches { private sealed class State { internal int Epoch; internal uint Revision = uint.MaxValue; internal float NextSafetyRefresh; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("ItemStand.UpdateVisual revision gate", AccessTools.Method(typeof(ItemStand), "UpdateVisual", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(ItemStandPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.ItemStandVisualRevision, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(ItemStand __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.Revision = uint.MaxValue; state.NextSafetyRefresh = 0f; } float unscaledTime = Time.unscaledTime; uint dataRevision = zDO.DataRevision; if (dataRevision == state.Revision && unscaledTime < state.NextSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.ItemStandVisualSkips); return false; } state.Revision = dataRevision; state.NextSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.StaticVisualSafety, ((Object)__instance).GetInstanceID()); return true; } } } namespace BalrondVisualOptimizer.Patches.FireplaceOptimizations { internal static class FireplacePatches { private struct Signature { internal bool Burning; internal bool Wet; internal bool FuelAtLeastHalf; internal bool Empty; internal bool SameAs(Signature other) { return Burning == other.Burning && Wet == other.Wet && FuelAtLeastHalf == other.FuelAtLeastHalf && Empty == other.Empty; } } private sealed class State { internal int Epoch; internal bool HasValue; internal Signature Value; internal float NextSafetyRefresh; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("Fireplace.UpdateState visual signature gate", AccessTools.Method(typeof(Fireplace), "UpdateState", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(FireplacePatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.FireplaceVisualState, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(Fireplace __instance) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } bool flag = __instance.IsBurning(); if (flag && __instance.m_canTurnOff && __instance.m_wet && __instance.m_nview.IsOwner() && zDO.GetInt(ZDOVars.s_state, 1) == 1) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.HasValue = false; state.NextSafetyRefresh = 0f; } float num = zDO.GetFloat(ZDOVars.s_fuel, 0f); Signature signature = new Signature { Burning = flag, Wet = __instance.m_wet, FuelAtLeastHalf = (num >= __instance.m_halfThreshold), Empty = (num <= 0f) }; float unscaledTime = Time.unscaledTime; if (state.HasValue && state.Value.SameAs(signature) && unscaledTime < state.NextSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.FireplaceStateSkips); return false; } state.Value = signature; state.HasValue = true; state.NextSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.VisualSafety, ((Object)__instance).GetInstanceID()); return true; } } } namespace BalrondVisualOptimizer.Patches.EffectFadeOptimizations { internal static class EffectFadePatches { private sealed class State { internal int Epoch; internal bool SeenUpdate; internal bool Sleeping; } private static readonly WeakUnityRegistry Sleepers = new WeakUnityRegistry(); private static PatchRuntimeGate updateGate; private static PatchRuntimeGate setActiveGate; private static bool CanSleep => updateGate != null && setActiveGate != null && updateGate.Enabled && setActiveGate.Enabled; internal static void Install(PatchInstaller installer) { updateGate = installer.Install("EffectFade.Update endpoint dormancy", AccessTools.Method(typeof(EffectFade), "Update", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(EffectFadePatches), "UpdatePrefix", (Type[])null, (Type[])null), null, Launch.Settings.EffectFadeDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); setActiveGate = installer.Install("EffectFade.SetActive wake hook", AccessTools.Method(typeof(EffectFade), "SetActive", new Type[1] { typeof(bool) }, (Type[])null), AccessTools.Method(typeof(EffectFadePatches), "SetActivePrefix", (Type[])null, (Type[])null), null, Launch.Settings.EffectFadeDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool UpdatePrefix(EffectFade __instance) { if (!CanSleep || (Object)(object)__instance == (Object)null) { return true; } State state = WeakStateStore.Get(__instance); int num = updateGate.Epoch ^ (setActiveGate.Epoch << 1); if (state.Epoch != num) { state.Epoch = num; state.SeenUpdate = false; state.Sleeping = false; } float num2 = (__instance.m_active ? 1f : 0f); bool flag = Mathf.Approximately(__instance.m_intensity, num2); if (!state.SeenUpdate) { state.SeenUpdate = true; return true; } if (!flag) { return true; } state.Sleeping = true; Sleepers.Add(__instance); ((Behaviour)__instance).enabled = false; RuntimeStats.Inc(ref RuntimeStats.EffectFadeDormantFrames); return false; } private static void SetActivePrefix(EffectFade __instance, bool active) { if (!((Object)(object)__instance == (Object)null) && CanSleep && __instance.m_active != active) { State state = WeakStateStore.Get(__instance); state.SeenUpdate = false; state.Sleeping = false; Sleepers.Remove(__instance); if (!((Behaviour)__instance).enabled) { ((Behaviour)__instance).enabled = true; } } } internal static void RefreshDormancy() { if (CanSleep) { return; } Sleepers.ForEachAlive(delegate(EffectFade f) { if (!((Behaviour)f).enabled) { ((Behaviour)f).enabled = true; } if (WeakStateStore.TryGet(f, out var state)) { state.Sleeping = false; state.SeenUpdate = false; } }); Sleepers.Clear(); } internal static void Shutdown() { Sleepers.ForEachAlive(delegate(EffectFade f) { if (!((Behaviour)f).enabled) { ((Behaviour)f).enabled = true; } }); Sleepers.Clear(); } } } namespace BalrondVisualOptimizer.Patches.CraftingStationOptimizations { internal static class CraftingStationDormancyPatches { private static readonly WeakUnityRegistry Sleepers = new WeakUnityRegistry(); private static PatchRuntimeGate updateGate; private static PatchRuntimeGate pokeGate; private static PatchRuntimeGate extensionsGate; private static bool CanSleep => updateGate != null && pokeGate != null && extensionsGate != null && updateGate.Enabled && pokeGate.Enabled && extensionsGate.Enabled; internal static void Install(PatchInstaller installer) { updateGate = installer.Install("CraftingStation.CustomUpdate idle dormancy replacement", AccessTools.Method(typeof(CraftingStation), "CustomUpdate", new Type[2] { typeof(float), typeof(float) }, (Type[])null), AccessTools.Method(typeof(CraftingStationDormancyPatches), "UpdatePrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationIdleDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); pokeGate = installer.Install("CraftingStation.PokeInUse wake hook", AccessTools.Method(typeof(CraftingStation), "PokeInUse", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(CraftingStationDormancyPatches), "PokePrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationIdleDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); extensionsGate = installer.Install("CraftingStation.GetExtensions wake hook", AccessTools.Method(typeof(CraftingStation), "GetExtensions", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(CraftingStationDormancyPatches), "ExtensionsPrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationIdleDormancy, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool UpdatePrefix(CraftingStation __instance, float deltaTime) { if (!CanSleep || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return false; } __instance.m_useTimer = Mathf.Min(1f, __instance.m_useTimer + deltaTime); __instance.m_updateExtensionTimer = Mathf.Min(2f, __instance.m_updateExtensionTimer + deltaTime); if ((Object)(object)__instance.m_inUseObject != (Object)null) { bool flag = __instance.m_useTimer < 1f; if (__instance.m_inUseObject.activeSelf != flag) { __instance.m_inUseObject.SetActive(flag); } } if (__instance.m_useTimer >= 1f && __instance.m_updateExtensionTimer >= 2f && ((Object)(object)__instance.m_inUseObject == (Object)null || !__instance.m_inUseObject.activeSelf) && CraftingStation.Instances.Remove((IMonoUpdater)(object)__instance)) { Sleepers.Add(__instance); RuntimeStats.Inc(ref RuntimeStats.CraftingStationDormantFrames); } return false; } private static void PokePrefix(CraftingStation __instance) { if ((Object)(object)__instance != (Object)null && CanSleep) { Wake(__instance); } } private static void ExtensionsPrefix(CraftingStation __instance) { if ((Object)(object)__instance != (Object)null && CanSleep) { Wake(__instance); } } private static void Wake(CraftingStation station) { if (((Behaviour)station).enabled && ((Component)station).gameObject.activeInHierarchy && !CraftingStation.Instances.Contains((IMonoUpdater)(object)station)) { CraftingStation.Instances.Add((IMonoUpdater)(object)station); } Sleepers.Remove(station); } internal static void RefreshDormancy() { if (CanSleep) { return; } Sleepers.ForEachAlive(delegate(CraftingStation s) { if (((Behaviour)s).enabled && ((Component)s).gameObject.activeInHierarchy && !CraftingStation.Instances.Contains((IMonoUpdater)(object)s)) { CraftingStation.Instances.Add((IMonoUpdater)(object)s); } }); Sleepers.Clear(); } internal static void Shutdown() { Sleepers.ForEachAlive(delegate(CraftingStation s) { if (((Behaviour)s).enabled && ((Component)s).gameObject.activeInHierarchy && !CraftingStation.Instances.Contains((IMonoUpdater)(object)s)) { CraftingStation.Instances.Add((IMonoUpdater)(object)s); } }); Sleepers.Clear(); } } internal static class CraftingStationPatches { private static PatchRuntimeGate knownGate; private static PatchRuntimeGate haveGate; private static PatchRuntimeGate findGate; private static PatchRuntimeGate closestGate; internal static void Install(PatchInstaller installer) { knownGate = installer.Install("CraftingStation.UpdateKnownStationsInRange squared-distance query", AccessTools.Method(typeof(CraftingStation), "UpdateKnownStationsInRange", new Type[1] { typeof(Player) }, (Type[])null), AccessTools.Method(typeof(CraftingStationPatches), "UpdateKnownStationsPrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationSquaredDistanceQueries, requiresKnownBuild: true, strictForeignPatchCheck: true); haveGate = installer.Install("CraftingStation.HaveBuildStationInRange squared-distance query", AccessTools.Method(typeof(CraftingStation), "HaveBuildStationInRange", new Type[2] { typeof(string), typeof(Vector3) }, (Type[])null), AccessTools.Method(typeof(CraftingStationPatches), "HaveBuildStationPrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationSquaredDistanceQueries, requiresKnownBuild: true, strictForeignPatchCheck: true); findGate = installer.Install("CraftingStation.FindStationsInRange squared-distance query", AccessTools.Method(typeof(CraftingStation), "FindStationsInRange", new Type[4] { typeof(string), typeof(Vector3), typeof(float), typeof(List) }, (Type[])null), AccessTools.Method(typeof(CraftingStationPatches), "FindStationsPrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationSquaredDistanceQueries, requiresKnownBuild: true, strictForeignPatchCheck: true); closestGate = installer.Install("CraftingStation.FindClosestStationInRange squared-distance query", AccessTools.Method(typeof(CraftingStation), "FindClosestStationInRange", new Type[3] { typeof(string), typeof(Vector3), typeof(float) }, (Type[])null), AccessTools.Method(typeof(CraftingStationPatches), "FindClosestStationPrefix", (Type[])null, (Type[])null), null, Launch.Settings.CraftingStationSquaredDistanceQueries, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool UpdateKnownStationsPrefix(Player player) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_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_0082: Unknown result type (might be due to invalid IL or missing references) List craftingStations = VanillaCollectionRegistry.CraftingStations; if (knownGate == null || !knownGate.Enabled || craftingStations == null || (Object)(object)player == (Object)null) { return true; } Vector3 position = ((Component)player).transform.position; for (int i = 0; i < craftingStations.Count; i++) { CraftingStation val = craftingStations[i]; if ((Object)(object)val == (Object)null) { continue; } float discoverRange = val.m_discoverRange; if (discoverRange > 0f) { Vector3 val2 = ((Component)val).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude < discoverRange * discoverRange) { player.AddKnownStation(val); } } } RuntimeStats.Inc(ref RuntimeStats.CraftingQueryReplacements); return false; } private static bool HaveBuildStationPrefix(string name, Vector3 point, ref CraftingStation __result) { //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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) List craftingStations = VanillaCollectionRegistry.CraftingStations; if (haveGate == null || !haveGate.Enabled || craftingStations == null) { return true; } for (int i = 0; i < craftingStations.Count; i++) { CraftingStation val = craftingStations[i]; if ((Object)(object)val == (Object)null || val.m_name != name) { continue; } float stationBuildRange = val.GetStationBuildRange(); if (stationBuildRange > 0f) { Vector3 val2 = point; val2.y = ((Component)val).transform.position.y; Vector3 val3 = ((Component)val).transform.position - val2; if (((Vector3)(ref val3)).sqrMagnitude < stationBuildRange * stationBuildRange) { __result = val; RuntimeStats.Inc(ref RuntimeStats.CraftingQueryReplacements); return false; } } } __result = null; RuntimeStats.Inc(ref RuntimeStats.CraftingQueryReplacements); return false; } private static bool FindStationsPrefix(string name, Vector3 point, float range, List stations) { //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) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) List craftingStations = VanillaCollectionRegistry.CraftingStations; if (findGate == null || !findGate.Enabled || craftingStations == null || stations == null) { return true; } if (!(range > 0f) || float.IsNaN(range)) { return false; } float num = range * range; for (int i = 0; i < craftingStations.Count; i++) { CraftingStation val = craftingStations[i]; if (!((Object)(object)val == (Object)null) && !(val.m_name != name)) { Vector3 val2 = ((Component)val).transform.position - point; if (((Vector3)(ref val2)).sqrMagnitude < num) { stations.Add(val); } } } RuntimeStats.Inc(ref RuntimeStats.CraftingQueryReplacements); return false; } private static bool FindClosestStationPrefix(string name, Vector3 point, float range, ref CraftingStation __result) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) List craftingStations = VanillaCollectionRegistry.CraftingStations; if (closestGate == null || !closestGate.Enabled || craftingStations == null) { return true; } if (!(range > 0f) || float.IsNaN(range)) { __result = null; return false; } float num = range * range; float num2 = float.PositiveInfinity; CraftingStation val = null; for (int i = 0; i < craftingStations.Count; i++) { CraftingStation val2 = craftingStations[i]; if (!((Object)(object)val2 == (Object)null) && !(val2.m_name != name)) { Vector3 val3 = ((Component)val2).transform.position - point; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num && (sqrMagnitude < num2 || (Object)(object)val == (Object)null)) { val = val2; num2 = sqrMagnitude; } } } __result = val; RuntimeStats.Inc(ref RuntimeStats.CraftingQueryReplacements); return false; } } } namespace BalrondVisualOptimizer.Patches.CookingStationOptimizations { internal static class CookingStationPatches { private sealed class State { internal int Epoch; internal uint Revision = uint.MaxValue; internal int[] SlotKeyHashes; internal int[] StatusKeyHashes; internal string[] Items; internal int[] Statuses; internal bool HasValue; internal bool FireLit; internal bool HasFuel; internal float NextSafetyRefresh; } private static PatchRuntimeGate gate; internal static void Install(PatchInstaller installer) { gate = installer.Install("CookingStation.UpdateVisual signature gate", AccessTools.Method(typeof(CookingStation), "UpdateVisual", new Type[1] { typeof(bool) }, (Type[])null), AccessTools.Method(typeof(CookingStationPatches), "Prefix", (Type[])null, (Type[])null), null, Launch.Settings.CookingStationVisual, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool Prefix(CookingStation __instance, bool fireLit) { if (gate == null || !gate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || __instance.m_slots == null) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } State state = WeakStateStore.Get(__instance); if (state.Epoch != gate.Epoch) { state.Epoch = gate.Epoch; state.HasValue = false; state.Revision = uint.MaxValue; state.NextSafetyRefresh = 0f; } EnsureArrays(state, __instance.m_slots.Length); float unscaledTime = Time.unscaledTime; uint dataRevision = zDO.DataRevision; if (state.HasValue && state.Revision == dataRevision && state.FireLit == fireLit && unscaledTime < state.NextSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.CookingStationVisualSkips); return false; } bool flag = !state.HasValue || state.FireLit != fireLit; bool flag2 = __instance.m_useFuel && zDO.GetFloat(ZDOVars.s_fuel, 0f) > 0f; if (!state.HasValue || state.HasFuel != flag2) { flag = true; } for (int i = 0; i < state.Items.Length; i++) { string text = zDO.GetString(state.SlotKeyHashes[i], ""); int num = zDO.GetInt(state.StatusKeyHashes[i], 0); if (!string.Equals(text, state.Items[i], StringComparison.Ordinal) || num != state.Statuses[i]) { flag = true; } state.Items[i] = text; state.Statuses[i] = num; } state.Revision = dataRevision; if (!flag && unscaledTime < state.NextSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.CookingStationVisualSkips); return false; } state.FireLit = fireLit; state.HasFuel = flag2; state.HasValue = true; state.NextSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.VisualSafety, ((Object)__instance).GetInstanceID()); return true; } private static void EnsureArrays(State state, int count) { if (state.Items == null || state.Items.Length != count) { state.SlotKeyHashes = new int[count]; state.StatusKeyHashes = new int[count]; state.Items = new string[count]; state.Statuses = new int[count]; for (int i = 0; i < count; i++) { state.SlotKeyHashes[i] = StringExtensionMethods.GetStableHashCode("slot" + i); state.StatusKeyHashes[i] = StringExtensionMethods.GetStableHashCode("slotstatus" + i); } state.HasValue = false; } } } } namespace BalrondVisualOptimizer.Patches.ArmorStandOptimizations { internal static class ArmorStandPatches { private sealed class VisualState { internal int Epoch; internal uint Revision = uint.MaxValue; internal float NextSafetyRefresh; } private sealed class ClothState { internal int Epoch; internal float NextUpdate; } private static PatchRuntimeGate visualGate; private static PatchRuntimeGate clothGate; internal static void Install(PatchInstaller installer) { visualGate = installer.Install("ArmorStand.UpdateVisual revision gate", AccessTools.Method(typeof(ArmorStand), "UpdateVisual", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(ArmorStandPatches), "UpdateVisualPrefix", (Type[])null, (Type[])null), null, Launch.Settings.ArmorStandVisualRevision, requiresKnownBuild: true, strictForeignPatchCheck: true); clothGate = installer.Install("ArmorStand.Update publicized cloth replacement", AccessTools.Method(typeof(ArmorStand), "Update", Type.EmptyTypes, (Type[])null), AccessTools.Method(typeof(ArmorStandPatches), "UpdatePrefix", (Type[])null, (Type[])null), null, Launch.Settings.ArmorStandCloth, requiresKnownBuild: true, strictForeignPatchCheck: true); } private static bool UpdateVisualPrefix(ArmorStand __instance) { if (visualGate == null || !visualGate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return true; } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO == null) { return true; } VisualState visualState = WeakStateStore.Get(__instance); if (visualState.Epoch != visualGate.Epoch) { visualState.Epoch = visualGate.Epoch; visualState.Revision = uint.MaxValue; visualState.NextSafetyRefresh = 0f; } float unscaledTime = Time.unscaledTime; uint dataRevision = zDO.DataRevision; if (dataRevision == visualState.Revision && unscaledTime < visualState.NextSafetyRefresh) { RuntimeStats.Inc(ref RuntimeStats.ArmorStandVisualSkips); return false; } visualState.Revision = dataRevision; visualState.NextSafetyRefresh = UpdateRateLimiter.StaggeredSafetyDeadline(unscaledTime, RuntimeTuning.StaticVisualSafety, ((Object)__instance).GetInstanceID()); return true; } private static bool UpdatePrefix(ArmorStand __instance) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (clothGate == null || !clothGate.Enabled || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)Player.m_localPlayer == (Object)null || __instance.m_cloths == null || __instance.m_cloths.Length == 0) { return false; } ClothState clothState = WeakStateStore.Get(__instance); if (clothState.Epoch != clothGate.Epoch) { clothState.Epoch = clothGate.Epoch; clothState.NextUpdate = 0f; } float time = Time.time; if (!UpdateRateLimiter.IsDue(ref clothState.NextUpdate, RuntimeTuning.ArmorClothInterval, time, ((Object)__instance).GetInstanceID())) { RuntimeStats.Inc(ref RuntimeStats.ArmorStandClothSkips); return false; } float num = __instance.m_clothSimLodDistance * QualitySettings.lodBias; Vector3 val = ((Component)Player.m_localPlayer).transform.position - ((Component)__instance).transform.position; bool flag = ((Vector3)(ref val)).sqrMagnitude > num * num; if (__instance.m_clothLodded == flag) { return false; } __instance.m_clothLodded = flag; Cloth[] cloths = __instance.m_cloths; foreach (Cloth val2 in cloths) { if ((Object)(object)val2 != (Object)null) { val2.enabled = !flag; } } return false; } } } namespace BalrondVisualOptimizer.Core { internal static class GameAssemblyGuard { internal static readonly Guid ExpectedValheimMvid = new Guid("E4CFC702-61AB-46D1-9F39-CC2DEB9BC839"); private static readonly Guid currentValheimMvid = ResolveCurrentMvid(); internal static Guid CurrentValheimMvid => currentValheimMvid; internal static bool IsExpectedBuild => currentValheimMvid == ExpectedValheimMvid; private static Guid ResolveCurrentMvid() { try { return typeof(ZNet).Assembly.ManifestModule.ModuleVersionId; } catch { return Guid.Empty; } } } internal static class HarmonyConflictService { internal static bool TryGetFirstForeignOwner(MethodBase target, out string owner) { owner = null; Patches patchInfo = GetPatchInfo(target); if (patchInfo == null || patchInfo.Owners == null) { return false; } foreach (string owner2 in patchInfo.Owners) { if (string.IsNullOrEmpty(owner2) || owner2 == "balrond.astafaraios.BalrondCoreOptimizer") { continue; } owner = owner2; return true; } return false; } internal static bool HasOwner(MethodBase target, string owner) { if (string.IsNullOrEmpty(owner)) { return false; } Patches patchInfo = GetPatchInfo(target); if (patchInfo == null || patchInfo.Owners == null) { return false; } foreach (string owner2 in patchInfo.Owners) { if (owner2 == owner) { return true; } } return false; } private static Patches GetPatchInfo(MethodBase target) { return (target == null) ? null : Harmony.GetPatchInfo(target); } } internal sealed class PatchInstaller { private readonly Harmony harmony; private readonly OptimizerConfig config; private readonly List gates = new List(); internal PatchInstaller(Harmony harmony, OptimizerConfig config) { this.harmony = harmony; this.config = config; } internal PatchRuntimeGate Install(string name, MethodBase target, MethodInfo prefix, MethodInfo postfix, ConfigEntry toggle, bool requiresKnownBuild, bool strictForeignPatchCheck) { PatchRuntimeGate patchRuntimeGate = new PatchRuntimeGate(name, target, prefix, postfix, toggle, requiresKnownBuild, strictForeignPatchCheck); gates.Add(patchRuntimeGate); if (target == null) { patchRuntimeGate.BlockPermanently("target method not found"); Launch.LogWarning(name + " disabled: target method not found."); return patchRuntimeGate; } if (prefix == null && postfix == null) { patchRuntimeGate.BlockPermanently("patch method not found"); Launch.LogWarning(name + " disabled: no prefix/postfix method was resolved."); return patchRuntimeGate; } if (CompatibilityPolicy.IsProtectedTarget(target, out var reason)) { patchRuntimeGate.BlockPermanently(reason); Launch.LogWarning(name + " refused by compatibility policy: " + reason + "."); return patchRuntimeGate; } ReconcileGate(patchRuntimeGate, initial: true); return patchRuntimeGate; } internal void RefreshAll() { for (int i = 0; i < gates.Count; i++) { ReconcileGate(gates[i], initial: false); } } internal string BuildStatusSummary() { int num = 0; int num2 = 0; int num3 = 0; string text = null; for (int i = 0; i < gates.Count; i++) { PatchRuntimeGate patchRuntimeGate = gates[i]; if (patchRuntimeGate.Enabled && patchRuntimeGate.Installed) { num++; } else if (patchRuntimeGate.PermanentlyBlocked) { num2++; } else { num3++; } if (text == null && !patchRuntimeGate.Enabled && !string.IsNullOrEmpty(patchRuntimeGate.DisabledReason)) { text = patchRuntimeGate.Name + ": " + patchRuntimeGate.DisabledReason; } } string text2 = "patches active=" + num + "/" + gates.Count + ", disabled=" + num3 + ", permanently-blocked=" + num2; if (text != null) { text2 = text2 + ", first-disabled=[" + text + "]"; } return text2; } private void ReconcileGate(PatchRuntimeGate gate, bool initial) { if (gate == null) { return; } SynchronizeObservedInstallState(gate); string owner; if (gate.PermanentlyBlocked) { EnsureUninstalled(gate, gate.PermanentBlockReason, log: false); } else if (!config.Enabled.Value) { EnsureUninstalled(gate, "master switch disabled", !initial); } else if (gate.Toggle == null || !gate.Toggle.Value) { EnsureUninstalled(gate, "feature disabled in config", !initial); } else if (gate.RequiresKnownBuild && !GameAssemblyGuard.IsExpectedBuild && !config.AllowUnknownGameBuild.Value) { EnsureUninstalled(gate, "unknown assembly_valheim MVID", !initial); if (initial) { Launch.LogWarning(gate.Name + " disabled: assembly_valheim MVID " + GameAssemblyGuard.CurrentValheimMvid.ToString() + " does not match audited MVID " + GameAssemblyGuard.ExpectedValheimMvid.ToString() + "."); } } else if (gate.StrictForeignPatchCheck && config.DisableOnForeignHarmonyPatches.Value && HarmonyConflictService.TryGetFirstForeignOwner(gate.Target, out owner)) { bool installed = gate.Installed; EnsureUninstalled(gate, "foreign Harmony patch: " + owner, log: false); if (initial || installed) { Launch.LogWarning(gate.Name + " disabled because target " + Describe(gate.Target) + " is patched by " + owner + "."); } } else if (!gate.Installed) { TryInstall(gate); } else { gate.Set(value: true, null); } } private void TryInstall(PatchRuntimeGate gate) { //IL_0040: 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) try { if (HarmonyConflictService.HasOwner(gate.Target, "balrond.astafaraios.BalrondCoreOptimizer")) { gate.MarkInstalled(); gate.Set(value: true, null); return; } HarmonyMethod val = ((gate.Prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(gate.Prefix)); HarmonyMethod val2 = ((gate.Postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(gate.Postfix)); if (val != null) { val.priority = 0; } if (val2 != null) { val2.priority = 0; } harmony.Patch(gate.Target, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); gate.MarkInstalled(); gate.Set(value: true, null); Launch.LogInfo("Installed " + gate.Name + " -> " + Describe(gate.Target)); } catch (Exception ex) { gate.BlockPermanently("patch install exception"); TryRemoveExactPatchMethods(gate, "cleanup after failed install"); SynchronizeObservedInstallState(gate); Launch.LogError(gate.Name + " failed to install and is disabled for this session: " + ex); } } private void EnsureUninstalled(PatchRuntimeGate gate, string reason, bool log) { gate.Set(value: false, reason); if (!HarmonyConflictService.HasOwner(gate.Target, "balrond.astafaraios.BalrondCoreOptimizer")) { gate.MarkUninstalled(); return; } TryRemoveExactPatchMethods(gate, "runtime disable"); if (!HarmonyConflictService.HasOwner(gate.Target, "balrond.astafaraios.BalrondCoreOptimizer")) { gate.MarkUninstalled(); if (log) { Launch.LogInfo("Uninstalled " + gate.Name + ": " + reason + "."); } } } private void TryRemoveExactPatchMethods(PatchRuntimeGate gate, string context) { try { if (gate.Prefix != null) { harmony.Unpatch(gate.Target, gate.Prefix); } if (gate.Postfix != null) { harmony.Unpatch(gate.Target, gate.Postfix); } } catch (Exception ex) { Launch.LogWarning("Could not physically unpatch " + gate.Name + " (" + context + "); runtime gate is disabled and vanilla remains authoritative. " + ex.Message); } } private static void SynchronizeObservedInstallState(PatchRuntimeGate gate) { if (!(gate.Target == null)) { bool flag = HarmonyConflictService.HasOwner(gate.Target, "balrond.astafaraios.BalrondCoreOptimizer"); if (flag && !gate.Installed) { gate.MarkInstalled(); } else if (!flag && gate.Installed) { gate.MarkUninstalled(); } } } private static string Describe(MethodBase method) { if (method == null) { return ""; } return (method.DeclaringType == null) ? method.Name : (method.DeclaringType.FullName + "." + method.Name); } } internal sealed class PatchRuntimeGate { private bool enabled; private bool installed; private int epoch; internal string Name { get; private set; } internal MethodBase Target { get; private set; } internal MethodInfo Prefix { get; private set; } internal MethodInfo Postfix { get; private set; } internal ConfigEntry Toggle { get; private set; } internal bool RequiresKnownBuild { get; private set; } internal bool StrictForeignPatchCheck { get; private set; } internal string DisabledReason { get; private set; } internal string PermanentBlockReason { get; private set; } internal bool PermanentlyBlocked => !string.IsNullOrEmpty(PermanentBlockReason); internal bool Installed => installed; internal bool Enabled => enabled; internal int Epoch => epoch; internal PatchRuntimeGate(string name, MethodBase target, MethodInfo prefix, MethodInfo postfix, ConfigEntry toggle, bool requiresKnownBuild, bool strictForeignPatchCheck) { Name = name; Target = target; Prefix = prefix; Postfix = postfix; Toggle = toggle; RequiresKnownBuild = requiresKnownBuild; StrictForeignPatchCheck = strictForeignPatchCheck; } internal void MarkInstalled() { if (!installed) { installed = true; epoch++; } } internal void MarkUninstalled() { if (installed) { installed = false; epoch++; } } internal void BlockPermanently(string reason) { PermanentBlockReason = reason; Set(value: false, reason); } internal void Set(bool value, string reason) { enabled = value; DisabledReason = (value ? null : reason); } } internal static class RuntimeStats { private struct Snapshot { internal long ArmorStandVisualSkips; internal long ArmorStandClothSkips; internal long ItemStandVisualSkips; internal long PrivateAreaVisualSkips; internal long PortalVisualSkips; internal long VisEquipmentEquipmentSkips; internal long VisEquipmentColorSkips; internal long SmelterStateSkips; internal long FireplaceStateSkips; internal long CookingStationVisualSkips; internal long CraftingStationDormantFrames; internal long LightFlickerSkips; internal long LightLodCoroutineReplacements; internal long LightLodDecisionChecks; internal long SmokeRendererSkips; internal long WindmillAudioSkips; internal long VagonAudioSkips; internal long VagonTetherSkips; internal long EffectFadeDormantFrames; internal long MaterialFaderDormantFrames; internal long ZsfxDormantFrames; internal long LineConnectSkips; internal long PieceQueryReplacements; internal long CraftingQueryReplacements; internal long StationExtensionQueryReplacements; internal Snapshot Subtract(Snapshot p) { Snapshot result = this; result.ArmorStandVisualSkips -= p.ArmorStandVisualSkips; result.ArmorStandClothSkips -= p.ArmorStandClothSkips; result.ItemStandVisualSkips -= p.ItemStandVisualSkips; result.PrivateAreaVisualSkips -= p.PrivateAreaVisualSkips; result.PortalVisualSkips -= p.PortalVisualSkips; result.VisEquipmentEquipmentSkips -= p.VisEquipmentEquipmentSkips; result.VisEquipmentColorSkips -= p.VisEquipmentColorSkips; result.SmelterStateSkips -= p.SmelterStateSkips; result.FireplaceStateSkips -= p.FireplaceStateSkips; result.CookingStationVisualSkips -= p.CookingStationVisualSkips; result.CraftingStationDormantFrames -= p.CraftingStationDormantFrames; result.LightFlickerSkips -= p.LightFlickerSkips; result.LightLodCoroutineReplacements -= p.LightLodCoroutineReplacements; result.LightLodDecisionChecks -= p.LightLodDecisionChecks; result.SmokeRendererSkips -= p.SmokeRendererSkips; result.WindmillAudioSkips -= p.WindmillAudioSkips; result.VagonAudioSkips -= p.VagonAudioSkips; result.VagonTetherSkips -= p.VagonTetherSkips; result.EffectFadeDormantFrames -= p.EffectFadeDormantFrames; result.MaterialFaderDormantFrames -= p.MaterialFaderDormantFrames; result.ZsfxDormantFrames -= p.ZsfxDormantFrames; result.LineConnectSkips -= p.LineConnectSkips; result.PieceQueryReplacements -= p.PieceQueryReplacements; result.CraftingQueryReplacements -= p.CraftingQueryReplacements; result.StationExtensionQueryReplacements -= p.StationExtensionQueryReplacements; return result; } } internal static bool Enabled; internal static long ArmorStandVisualSkips; internal static long ArmorStandClothSkips; internal static long ItemStandVisualSkips; internal static long PrivateAreaVisualSkips; internal static long PortalVisualSkips; internal static long VisEquipmentEquipmentSkips; internal static long VisEquipmentColorSkips; internal static long SmelterStateSkips; internal static long FireplaceStateSkips; internal static long CookingStationVisualSkips; internal static long CraftingStationDormantFrames; internal static long LightFlickerSkips; internal static long LightLodCoroutineReplacements; internal static long LightLodDecisionChecks; internal static long SmokeRendererSkips; internal static long WindmillAudioSkips; internal static long VagonAudioSkips; internal static long VagonTetherSkips; internal static long EffectFadeDormantFrames; internal static long MaterialFaderDormantFrames; internal static long ZsfxDormantFrames; internal static long LineConnectSkips; internal static long PieceQueryReplacements; internal static long CraftingQueryReplacements; internal static long StationExtensionQueryReplacements; private static Snapshot previous; internal static void Inc(ref long value) { if (Enabled) { Interlocked.Increment(ref value); } } internal static string BuildDeltaSummary(float seconds) { Snapshot snapshot = Capture(); Snapshot snapshot2 = snapshot.Subtract(previous); previous = snapshot; return "delta/" + seconds.ToString("0.0") + "s: ArmorVisual=" + snapshot2.ArmorStandVisualSkips + ", ArmorCloth=" + snapshot2.ArmorStandClothSkips + ", ItemStand=" + snapshot2.ItemStandVisualSkips + ", Ward=" + snapshot2.PrivateAreaVisualSkips + ", Portal=" + snapshot2.PortalVisualSkips + ", VisEquip=" + snapshot2.VisEquipmentEquipmentSkips + ", VisColor=" + snapshot2.VisEquipmentColorSkips + ", Smelter=" + snapshot2.SmelterStateSkips + ", Fireplace=" + snapshot2.FireplaceStateSkips + ", Cooking=" + snapshot2.CookingStationVisualSkips + ", StationSleep=" + snapshot2.CraftingStationDormantFrames + ", Flicker=" + snapshot2.LightFlickerSkips + ", LightLod=" + snapshot2.LightLodDecisionChecks + ", Smoke=" + snapshot2.SmokeRendererSkips + ", WindAudio=" + snapshot2.WindmillAudioSkips + ", VagonAudio=" + snapshot2.VagonAudioSkips + ", Tether=" + snapshot2.VagonTetherSkips + ", EffectFade=" + snapshot2.EffectFadeDormantFrames + ", MaterialFader=" + snapshot2.MaterialFaderDormantFrames + ", ZSFX=" + snapshot2.ZsfxDormantFrames + ", LineConnect=" + snapshot2.LineConnectSkips + ", PieceQuery=" + snapshot2.PieceQueryReplacements + ", StationQuery=" + snapshot2.CraftingQueryReplacements + ", ExtQuery=" + snapshot2.StationExtensionQueryReplacements; } internal static void ResetBaseline() { previous = Capture(); } private static Snapshot Capture() { return new Snapshot { ArmorStandVisualSkips = Interlocked.Read(in ArmorStandVisualSkips), ArmorStandClothSkips = Interlocked.Read(in ArmorStandClothSkips), ItemStandVisualSkips = Interlocked.Read(in ItemStandVisualSkips), PrivateAreaVisualSkips = Interlocked.Read(in PrivateAreaVisualSkips), PortalVisualSkips = Interlocked.Read(in PortalVisualSkips), VisEquipmentEquipmentSkips = Interlocked.Read(in VisEquipmentEquipmentSkips), VisEquipmentColorSkips = Interlocked.Read(in VisEquipmentColorSkips), SmelterStateSkips = Interlocked.Read(in SmelterStateSkips), FireplaceStateSkips = Interlocked.Read(in FireplaceStateSkips), CookingStationVisualSkips = Interlocked.Read(in CookingStationVisualSkips), CraftingStationDormantFrames = Interlocked.Read(in CraftingStationDormantFrames), LightFlickerSkips = Interlocked.Read(in LightFlickerSkips), LightLodCoroutineReplacements = Interlocked.Read(in LightLodCoroutineReplacements), LightLodDecisionChecks = Interlocked.Read(in LightLodDecisionChecks), SmokeRendererSkips = Interlocked.Read(in SmokeRendererSkips), WindmillAudioSkips = Interlocked.Read(in WindmillAudioSkips), VagonAudioSkips = Interlocked.Read(in VagonAudioSkips), VagonTetherSkips = Interlocked.Read(in VagonTetherSkips), EffectFadeDormantFrames = Interlocked.Read(in EffectFadeDormantFrames), MaterialFaderDormantFrames = Interlocked.Read(in MaterialFaderDormantFrames), ZsfxDormantFrames = Interlocked.Read(in ZsfxDormantFrames), LineConnectSkips = Interlocked.Read(in LineConnectSkips), PieceQueryReplacements = Interlocked.Read(in PieceQueryReplacements), CraftingQueryReplacements = Interlocked.Read(in CraftingQueryReplacements), StationExtensionQueryReplacements = Interlocked.Read(in StationExtensionQueryReplacements) }; } } } namespace BalrondVisualOptimizer.Config { internal sealed class OptimizerConfig { internal ConfigEntry Enabled; internal ConfigEntry AllowUnknownGameBuild; internal ConfigEntry DisableOnForeignHarmonyPatches; internal ConfigEntry CompatibilityRecheckSeconds; internal ConfigEntry VisualSafetyRefreshSeconds; internal ConfigEntry StaticVisualSafetyRefreshSeconds; internal ConfigEntry ArmorStandVisualRevision; internal ConfigEntry ArmorStandCloth; internal ConfigEntry ArmorStandClothRate; internal ConfigEntry ItemStandVisualRevision; internal ConfigEntry PrivateAreaStatusVisual; internal ConfigEntry PortalStableEmission; internal ConfigEntry VisEquipmentEquipment; internal ConfigEntry VisEquipmentColors; internal ConfigEntry SmelterVisualState; internal ConfigEntry FireplaceVisualState; internal ConfigEntry CookingStationVisual; internal ConfigEntry CraftingStationIdleDormancy; internal ConfigEntry LightFlicker; internal ConfigEntry LightFlickerNearDistance; internal ConfigEntry LightFlickerMidDistance; internal ConfigEntry LightFlickerFarDistance; internal ConfigEntry LightFlickerMidRate; internal ConfigEntry LightFlickerFarRate; internal ConfigEntry LightFlickerDistantRate; internal ConfigEntry LightFlickerDistanceCheckRate; internal ConfigEntry LightLodCentralScheduler; internal ConfigEntry LightLodDistanceCheckRate; internal ConfigEntry LightLodChecksPerFrame; internal ConfigEntry SmokeRenderer; internal ConfigEntry SmokeRendererRate; internal ConfigEntry WindmillAudio; internal ConfigEntry WindmillAudioRate; internal ConfigEntry VagonAudio; internal ConfigEntry VagonAudioRate; internal ConfigEntry VagonIdleTether; internal ConfigEntry EffectFadeDormancy; internal ConfigEntry MaterialFaderDormancy; internal ConfigEntry ZsfxDormancy; internal ConfigEntry LineConnectStableNoConnection; internal ConfigEntry PieceSquaredDistanceQueries; internal ConfigEntry CraftingStationSquaredDistanceQueries; internal ConfigEntry StationExtensionSquaredDistanceQuery; internal ConfigEntry Diagnostics; internal ConfigEntry DiagnosticsIntervalSeconds; internal OptimizerConfig(ConfigFile config) { Enabled = Bind(config, "0 General", "Enabled", value: true, "Master switch for all optimizer patches. Runtime changes are reconciled without requiring a restart."); AllowUnknownGameBuild = Bind(config, "0 General", "Allow Unknown Game Build", value: false, "UNSAFE development override. Keep false for normal play. Exact/private replacements are not installed on an unaudited assembly_valheim build."); DisableOnForeignHarmonyPatches = Bind(config, "0 General", "Disable On Foreign Harmony Patches", value: true, "Recommended. Disable an optimization when another Harmony owner patches the exact same target method."); CompatibilityRecheckSeconds = Bind(config, "0 General", "Compatibility Recheck Seconds", 60f, "Background interval for late Harmony-conflict checks. Config changes request an immediate reconciliation.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 120f)); VisualSafetyRefreshSeconds = Bind(config, "0 General", "Visual Safety Refresh Seconds", 30f, "Fallback reconciliation interval for dynamic cached presentation state.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 120f)); StaticVisualSafetyRefreshSeconds = Bind(config, "0 General", "Static Visual Safety Refresh Seconds", 30f, "Fallback reconciliation interval for static network-backed visuals such as ItemStand and ArmorStand.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 180f)); ArmorStandVisualRevision = Bind(config, "1 Static Visuals", "ArmorStand Revision Gate", value: true, "Skip ArmorStand.UpdateVisual while its network-backed data revision is unchanged."); ArmorStandCloth = Bind(config, "1 Static Visuals", "ArmorStand Cloth Throttling", value: true, "Reduce how often armor stands check distance to enable or disable Cloth simulation."); ArmorStandClothRate = Bind(config, "1 Static Visuals", "ArmorStand Cloth Checks Per Second", 10f, "Frequency of the armor-stand cloth distance check.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 30f)); ItemStandVisualRevision = Bind(config, "1 Static Visuals", "ItemStand Revision Gate", value: true, "Skip ItemStand.UpdateVisual while its network-backed data revision is unchanged."); PrivateAreaStatusVisual = Bind(config, "1 Static Visuals", "PrivateArea Status Visual Gate", value: true, "Avoid repeated Ward SetActive/material emission writes while the enabled state is unchanged."); PortalStableEmission = Bind(config, "1 Static Visuals", "Portal Stable Emission Gate", value: true, "Skip TeleportWorld emission-color writes after the connected/unconnected fade reaches its endpoint."); VisEquipmentEquipment = Bind(config, "2 Character Visuals", "VisEquipment Equipment Signature Gate", value: true, "Skip repeated equipment reconstruction checks while all relevant equipped-item values remain unchanged."); VisEquipmentColors = Bind(config, "2 Character Visuals", "VisEquipment Color Signature Gate", value: true, "Skip repeated skin/hair material color writes while colors, model and visual instances remain unchanged."); SmelterVisualState = Bind(config, "3 Production Visuals", "Smelter Visual State Gate", value: true, "Cache only Smelter.UpdateState visual/animation state. Fuel, ore, roof, smoke and production simulation remain vanilla."); FireplaceVisualState = Bind(config, "3 Production Visuals", "Fireplace Visual State Gate", value: true, "Cache only Fireplace.UpdateState visual tiers. Fuel consumption, environment checks, smoke blockage and toggle gameplay remain vanilla."); CookingStationVisual = Bind(config, "3 Production Visuals", "CookingStation Visual Signature Gate", value: true, "Skip UpdateVisual while slot item/status, fire state and fuel-visible state are unchanged. Cooking timers remain vanilla."); CraftingStationIdleDormancy = Bind(config, "3 Production Visuals", "CraftingStation Idle Dormancy", value: true, "Remove completely idle crafting stations from Valheim's per-frame CraftingStation updater list and wake them on use/extension refresh."); LightFlicker = Bind(config, "4 Continuous Presentation", "Light Flicker Distance Throttling", value: true, "Reduce update rate of persistent light flicker by distance. Temporary/fading TTL lights remain vanilla."); LightFlickerNearDistance = Bind(config, "4 Continuous Presentation", "Light Flicker Near Distance", 40f, "Within this distance vanilla flicker frequency is preserved.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 100f)); LightFlickerMidDistance = Bind(config, "4 Continuous Presentation", "Light Flicker Mid Distance", 60f, "Mid distance threshold.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 150f)); LightFlickerFarDistance = Bind(config, "4 Continuous Presentation", "Light Flicker Far Distance", 100f, "Far distance threshold.", (AcceptableValueBase)(object)new AcceptableValueRange(20f, 250f)); LightFlickerMidRate = Bind(config, "4 Continuous Presentation", "Light Flicker Mid Updates Per Second", 10f, "Persistent-light update rate between near and mid distance.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 60f)); LightFlickerFarRate = Bind(config, "4 Continuous Presentation", "Light Flicker Far Updates Per Second", 5f, "Persistent-light update rate between mid and far distance.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 30f)); LightFlickerDistantRate = Bind(config, "4 Continuous Presentation", "Light Flicker Distant Updates Per Second", 2f, "Persistent-light update rate beyond the far distance threshold.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 10f)); LightFlickerDistanceCheckRate = Bind(config, "4 Continuous Presentation", "Light Flicker Distance Checks Per Second", 2f, "How often a persistent light recomputes its player-distance tier.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 10f)); LightLodCentralScheduler = Bind(config, "4 Continuous Presentation", "LightLod Central Scheduler", value: true, "Replace one coroutine per LightLod with one time-sliced client scheduler while preserving vanilla distance/priority/fade behavior."); LightLodDistanceCheckRate = Bind(config, "4 Continuous Presentation", "LightLod Distance Checks Per Second", 1f, "Target cadence for LightLod distance decisions.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 4f)); LightLodChecksPerFrame = Bind(config, "4 Continuous Presentation", "LightLod Checks Per Frame", 512, "Maximum LightLod objects whose distance target is refreshed in one frame.", (AcceptableValueBase)(object)new AcceptableValueRange(32, 4096)); SmokeRenderer = Bind(config, "4 Continuous Presentation", "Smoke Renderer Throttling", value: true, "Reduce only SmokeRenderer visual refresh frequency. Smoke spawning/blockage simulation is untouched."); SmokeRendererRate = Bind(config, "4 Continuous Presentation", "Smoke Renderer Updates Per Second", 10f, "Visual SmokeRenderer refresh frequency.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 60f)); WindmillAudio = Bind(config, "4 Continuous Presentation", "Windmill Audio Throttling", value: true, "Reduce only Windmill.UpdateAudio frequency. Windmill movement and smelter power remain vanilla."); WindmillAudioRate = Bind(config, "4 Continuous Presentation", "Windmill Audio Updates Per Second", 10f, "Frequency of Windmill.UpdateAudio.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 30f)); VagonAudio = Bind(config, "4 Continuous Presentation", "Vagon Audio Throttling", value: true, "Reduce only Vagon.UpdateAudio frequency. Cart physics and attachment logic remain vanilla."); VagonAudioRate = Bind(config, "4 Continuous Presentation", "Vagon Audio Updates Per Second", 10f, "Frequency of Vagon.UpdateAudio.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 30f)); VagonIdleTether = Bind(config, "4 Continuous Presentation", "Vagon Idle Tether Visual Gate", value: true, "Skip Vagon.LateUpdate when the cart is detached and its tether LineRenderer is already disabled."); EffectFadeDormancy = Bind(config, "4 Continuous Presentation", "EffectFade Endpoint Dormancy", value: true, "Disable EffectFade.Update after a fade reaches a stable endpoint; SetActive wakes it immediately."); MaterialFaderDormancy = Bind(config, "4 Continuous Presentation", "MaterialFader Endpoint Dormancy", value: true, "Disable MaterialFader.Update when all fade properties have finished; TriggerFade wakes it immediately."); ZsfxDormancy = Bind(config, "4 Continuous Presentation", "ZSFX Idle Dormancy", value: true, "Remove completely idle non-looping ZSFX from the per-frame audio updater list; Play/FadeOut wakes them immediately."); LineConnectStableNoConnection = Bind(config, "4 Continuous Presentation", "LineConnect Stable No-Connection Gate", value: true, "Short-cache LineConnect no-connection results using ZDO revision, avoiding repeated ZNetScene lookups while safely reconciling every second."); PieceSquaredDistanceQueries = Bind(config, "5 Safe Query Micro-Optimizations", "Piece Squared Distance Queries", value: true, "Replace two Piece radius scans with equivalent squared-distance comparisons."); CraftingStationSquaredDistanceQueries = Bind(config, "5 Safe Query Micro-Optimizations", "CraftingStation Squared Distance Queries", value: true, "Use squared-distance comparisons in selected CraftingStation global-list range queries."); StationExtensionSquaredDistanceQuery = Bind(config, "5 Safe Query Micro-Optimizations", "StationExtension Squared Distance Query", value: true, "Use squared-distance comparisons in StationExtension.OtherExtensionInRange."); Diagnostics = Bind(config, "9 Diagnostics", "Runtime Statistics", value: false, "Collect and periodically log optimizer counters. Keep disabled for normal gameplay."); DiagnosticsIntervalSeconds = Bind(config, "9 Diagnostics", "Statistics Interval Seconds", 30f, "Statistics log interval while Runtime Statistics is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 300f)); } private static ConfigEntry Bind(ConfigFile config, string section, string key, T value, string description) { return config.Bind(section, key, value, description); } private static ConfigEntry Bind(ConfigFile config, string section, string key, T value, string description, AcceptableValueBase acceptable) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config.Bind(section, key, value, new ConfigDescription(description, acceptable, Array.Empty())); } } } namespace BalrondVisualOptimizer.Compatibility { internal static class CompatibilityPolicy { internal static bool IsProtectedTarget(MethodBase target, out string reason) { reason = null; if (target == null || target.DeclaringType == null) { return false; } Type declaringType = target.DeclaringType; string name = declaringType.Name; switch (name) { default: if (!(name == "MonoUpdaters")) { if (name == "WearNTear" || name == "WearNTearUpdater") { reason = "structural integrity is reserved for BalrondBetterBuild"; return true; } switch (name) { default: if (!(name == "Procreation")) { return false; } goto case "BaseAI"; case "BaseAI": case "MonsterAI": case "AnimalAI": case "SpawnSystem": reason = "AI/spawn gameplay simulation is outside the optimizer safety scope"; return true; } } goto case "ZDOMan"; case "ZDOMan": case "ZNetScene": case "ZRoutedRpc": case "ZRpc": case "ZNet": case "ZDO": case "ZNetView": case "ZSyncTransform": case "ZSyncAnimation": case "ZSteamSocket": case "ZPlayFabSocket": reason = "network/dispatcher infrastructure is reserved for vanilla/FiresGhettoNetworking"; return true; } } } internal static class ModCompatibility { internal const string BetterBuildGuid = "balrond.astafaraios.BalrondBetterBuild"; internal const string FiresGhettoNetworkingGuid = "com.Fire.FiresGhettoNetworkMod"; internal static bool BetterBuildInstalled => Chainloader.PluginInfos.ContainsKey("balrond.astafaraios.BalrondBetterBuild"); internal static bool FiresGhettoNetworkingInstalled => Chainloader.PluginInfos.ContainsKey("com.Fire.FiresGhettoNetworkMod"); } }