using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using SpaceCraft; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")] [assembly: AssemblyCompany("AFKResourcePreserver")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+87efc3bba54d9be5bac599b91ab55d137c16b97f")] [assembly: AssemblyProduct("AFKResourcePreserver")] [assembly: AssemblyTitle("AFKResourcePreserver")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AFKResourcePreserver { [HarmonyPatch] internal static class PassiveDepletionPatch { internal static MethodBase TargetMethod() { return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(PlayerGaugesHandler), "GaugesTick", new Type[1] { typeof(float) }, (Type[])null)) ?? throw new MissingMethodException("PlayerGaugesHandler.GaugesTick iterator was not found."); } internal static IEnumerable Transpiler(IEnumerable source) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(PlayerGaugesHandler), "AddHealth", new Type[1] { typeof(float) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerGaugesHandler), "AddWater", new Type[1] { typeof(float) }, (Type[])null); List list = new List(); int num = 0; int num2 = 0; foreach (CodeInstruction item in source) { CodeInstruction val = new CodeInstruction(item); if (CodeInstructionExtensions.Calls(val, methodInfo)) { val.opcode = OpCodes.Call; val.operand = AccessTools.Method(typeof(PassiveDepletionPatch), "ApplyHunger", (Type[])null, (Type[])null); num++; } else if (CodeInstructionExtensions.Calls(val, methodInfo2)) { val.opcode = OpCodes.Call; val.operand = AccessTools.Method(typeof(PassiveDepletionPatch), "ApplyThirst", (Type[])null, (Type[])null); num2++; } list.Add(val); } if (num != 1 || num2 != 1) { throw new InvalidOperationException($"Expected one passive hunger and one thirst call; found {num}/{num2}."); } return list; } internal static void ApplyHunger(PlayerGaugesHandler gauges, float delta) { Plugin instance = Plugin.Instance; if (instance == null || !instance.ShouldSuppress(gauges, delta, isHunger: true)) { gauges.AddHealth(delta); } } internal static void ApplyThirst(PlayerGaugesHandler gauges, float delta) { Plugin instance = Plugin.Instance; if (instance == null || !instance.ShouldSuppress(gauges, delta, isHunger: false)) { gauges.AddWater(delta); } } } [HarmonyPatch(typeof(PlayerMainController), "SetPlayerPlacement")] internal static class PlacementResetPatch { private static void Prefix(PlayerMainController __instance) { Plugin.Instance?.ResetPlayer(__instance); } } [HarmonyPatch(typeof(PlayerStatus), "DieAndRespawn")] internal static class RespawnResetPatch { private static void Prefix(PlayerStatus __instance) { Plugin.Instance?.ResetPlayer(((Component)__instance).GetComponent()); } } [BepInPlugin("noxie.planetcrafter.afkresourcepreserver", "AFK Resource Preserver", "1.0.0")] [BepInProcess("Planet Crafter.exe")] public sealed class Plugin : BaseUnityPlugin { private sealed class RemoteState { internal PlayerMainController Player; internal readonly RemoteProtection Protection = new RemoteProtection(); internal bool ReportedActive; } public const string Id = "noxie.planetcrafter.afkresourcepreserver"; internal static Plugin Instance; private const string StateMessage = "noxie.planetcrafter.afkresourcepreserver.state.v1"; private const string AckMessage = "noxie.planetcrafter.afkresourcepreserver.ack.v1"; private ConfigEntry enabledSetting; private ConfigEntry hunger; private ConfigEntry thirst; private ConfigEntry delay; private ConfigEntry threshold; private Harmony harmony; private bool ready; private bool configDirty; private bool warnedHost; private readonly StationaryTracker local = new StationaryTracker(); private PlayerMainController localPlayer; private NetworkManager network; private CustomMessagingManager messaging; private double lastSend = -100.0; private double lastAck = -100.0; private double connectedSince; private double nextError; private int lastMask = -1; private readonly Dictionary remotes = new Dictionary(); private readonly List expired = new List(); private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown Instance = this; enabledSetting = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enable preservation for this player. On a host, false also disables remote preservation."); delay = ((BaseUnityPlugin)this).Config.Bind("Detection", "AfkDelaySeconds", 30f, new ConfigDescription("Continuous stationary seconds before preservation starts.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 3600f), Array.Empty())); threshold = ((BaseUnityPlugin)this).Config.Bind("Detection", "MovementThreshold", 0.02f, new ConfigDescription("World-space distance from the stationary anchor. Includes vertical movement; ignores camera rotation.", (AcceptableValueBase)(object)new AcceptableValueRange(0.001f, 1f), Array.Empty())); hunger = ((BaseUnityPlugin)this).Config.Bind("Preservation", "PreserveHunger", true, "Pause passive food drain only; damage and healing remain normal."); thirst = ((BaseUnityPlugin)this).Config.Bind("Preservation", "PreserveThirst", true, "Pause passive thirst drain only; drinking remains normal."); ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; harmony = new Harmony("noxie.planetcrafter.afkresourcepreserver"); try { harmony.PatchAll(typeof(Plugin).Assembly); ready = true; SceneManager.activeSceneChanged += OnSceneChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)"AFK Resource Preserver 1.0.0 loaded. Applied GaugesTick.MoveNext depletion transpiler and placement/respawn reset prefixes. Oxygen and damage untouched."); } catch (Exception ex) { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("Unsupported game or patch conflict; all AFK Resource Preserver patches removed. " + ex)); } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { configDirty = true; } private void OnSceneChanged(Scene oldScene, Scene newScene) { ResetLocal("scene transition"); remotes.Clear(); lastSend = -100.0; } private void Update() { if (!ready) { return; } try { double unscaledTimeAsDouble = Time.unscaledTimeAsDouble; RefreshNetwork(unscaledTimeAsDouble); if (configDirty) { configDirty = false; ResetLocal("configuration changed"); remotes.Clear(); lastSend = -100.0; } SampleLocal(unscaledTimeAsDouble); if ((Object)(object)network != (Object)null && network.IsServer) { expired.Clear(); foreach (KeyValuePair remote in remotes) { if (!network.ConnectedClients.ContainsKey(remote.Key) || !remote.Value.Protection.Fresh(unscaledTimeAsDouble)) { expired.Add(remote.Key); } else { SampleRemote(remote.Value, unscaledTimeAsDouble); } } foreach (ulong item in expired) { remotes.Remove(item); } } SendLocalState(unscaledTimeAsDouble); } catch (Exception ex) { FailOpen(ex); } } private void LateUpdate() { if (!ready) { return; } try { SampleLocal(Time.unscaledTimeAsDouble); SendLocalState(Time.unscaledTimeAsDouble); } catch (Exception ex) { FailOpen(ex); } } private bool WorldReady() { PlanetLoader manager = Managers.GetManager(); if ((Object)(object)manager != (Object)null && manager.GetIsLoaded()) { return manager.GetIsInitialLoadingSequenceCompleted(); } return false; } private void SampleLocal(double now) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) PlayersManager manager = Managers.GetManager(); PlayerMainController val = (((Object)(object)manager != (Object)null) ? manager.GetActivePlayerController() : null); if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).IsOwner || !((NetworkBehaviour)val).IsSpawned || !((Component)val).gameObject.activeInHierarchy || !WorldReady()) { ResetLocal("local player unavailable/loading"); return; } if ((Object)(object)localPlayer != (Object)(object)val) { ResetLocal("local player changed"); localPlayer = val; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Local player acquired (owner " + ((NetworkBehaviour)val).OwnerClientId + ").")); } PlayerGaugesHandler playerGaugesHandler = val.GetPlayerGaugesHandler(); PlayerCanAct playerCanAct = val.GetPlayerCanAct(); if (!enabledSetting.Value || !StationaryTracker.ValidSettings(delay.Value, threshold.Value) || (Object)(object)playerGaugesHandler == (Object)null || playerGaugesHandler.GetPauseConsumption() || playerGaugesHandler.GetPlayerIsDying() || (Object)(object)playerCanAct == (Object)null || !playerCanAct.GetCanMoveAfterStart()) { ResetLocalTimer("disabled/loading/respawning"); return; } bool active = local.Active; Vector3 position = ((Component)val).transform.position; local.Sample(position.x, position.y, position.z, now, delay.Value, threshold.Value); if (active != local.Active) { ((BaseUnityPlugin)this).Logger.LogInfo((object)((!local.Active) ? "AFK protection deactivated following movement or interrupted sampling; timer reset." : (((Object)(object)network != (Object)null && network.IsServer) ? "AFK protection activated for the local player." : "AFK stationary delay reached; preservation requested (co-op requires host support)."))); } } private void SampleRemote(RemoteState state, double now) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) RemoteProtection protection = state.Protection; PlayerMainController player = state.Player; if (!enabledSetting.Value || (Object)(object)player == (Object)null || !((NetworkBehaviour)player).IsSpawned || !((Component)player).gameObject.activeInHierarchy || !WorldReady()) { protection.Reset(); state.ReportedActive = false; return; } PlayerGaugesHandler playerGaugesHandler = player.GetPlayerGaugesHandler(); if ((Object)(object)playerGaugesHandler == (Object)null || !((NetworkBehaviour)playerGaugesHandler).IsServer || !playerGaugesHandler.HasStarted() || playerGaugesHandler.GetPauseConsumption() || playerGaugesHandler.GetPlayerIsDying()) { protection.Reset(); state.ReportedActive = false; return; } Vector3 position = ((Component)player).transform.position; protection.Tracker.Sample(position.x, position.y, position.z, now, protection.Delay, protection.Threshold); bool flag = protection.Suppress(-1f, hunger: true, now) || protection.Suppress(-1f, hunger: false, now); if (state.ReportedActive != flag) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("AFK protection " + (flag ? "activated" : "deactivated following movement/reset") + " for owner " + ((NetworkBehaviour)player).OwnerClientId + ".")); } state.ReportedActive = flag; } internal bool ShouldSuppress(PlayerGaugesHandler gauges, float delta, bool isHunger) { if (!ready || !enabledSetting.Value || delta >= 0f || (Object)(object)gauges == (Object)null || !((NetworkBehaviour)gauges).IsServer || !((NetworkBehaviour)gauges).IsSpawned) { return false; } try { double unscaledTimeAsDouble = Time.unscaledTimeAsDouble; if (((NetworkBehaviour)gauges).IsOwner) { SampleLocal(unscaledTimeAsDouble); return (Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.GetPlayerGaugesHandler() == (Object)(object)gauges && StationaryTracker.Suppress(delta, enabledSetting.Value, local.Active, isHunger ? hunger.Value : thirst.Value); } if (remotes.TryGetValue(((NetworkBehaviour)gauges).OwnerClientId, out var value) && value.Protection.Fresh(unscaledTimeAsDouble) && (Object)(object)value.Player != (Object)null && (Object)(object)value.Player.GetPlayerGaugesHandler() == (Object)(object)gauges) { SampleRemote(value, unscaledTimeAsDouble); return value.Protection.Suppress(delta, isHunger, unscaledTimeAsDouble); } } catch (Exception ex) { FailOpen(ex); } return false; } private void RefreshNetwork(double now) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = (((Object)(object)singleton != (Object)null && singleton.IsListening) ? singleton.CustomMessagingManager : null); if (val != messaging || !((Object)(object)singleton == (Object)(object)network)) { DetachNetwork(); ResetLocal("network session changed"); remotes.Clear(); network = singleton; messaging = val; lastAck = -100.0; lastSend = -100.0; lastMask = -1; warnedHost = false; connectedSince = now; if (messaging != null) { messaging.RegisterNamedMessageHandler("noxie.planetcrafter.afkresourcepreserver.state.v1", new HandleNamedMessageDelegate(ReceiveState)); messaging.RegisterNamedMessageHandler("noxie.planetcrafter.afkresourcepreserver.ack.v1", new HandleNamedMessageDelegate(ReceiveAck)); network.OnClientDisconnectCallback += OnDisconnect; } } } private unsafe void SendLocalState(double now) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) if (messaging == null || (Object)(object)network == (Object)null || network.IsServer || !network.IsConnectedClient) { return; } int num = (((Object)(object)localPlayer != (Object)null && enabledSetting.Value) ? ((int)((hunger.Value ? 1u : 0u) | (uint)(thirst.Value ? 2 : 0)) | (local.Active ? 4 : 0)) : 0); if (num != lastMask || now - lastSend >= 5.0) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); float value = delay.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref value, default(ForPrimitives)); value = threshold.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref value, default(ForPrimitives)); messaging.SendNamedMessage("noxie.planetcrafter.afkresourcepreserver.state.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } lastMask = num; lastSend = now; } if (!warnedHost && now - connectedSince > 10.0 && now - lastAck > 10.0) { warnedHost = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"Host has not acknowledged AFK Resource Preserver. Install/enable v1.0.0 on the host too; client-only installation cannot stop server survival drain."); } } private unsafe void ReceiveState(ulong sender, FastBufferReader reader) { //IL_004c: 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_005f: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: 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) try { if (!ready || (Object)(object)network == (Object)null || !network.IsServer || !network.ConnectedClients.ContainsKey(sender) || ((FastBufferReader)(ref reader)).Length != 12) { return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); if (num < 0 || num > 7 || !StationaryTracker.ValidSettings(num2, num3)) { return; } PlayersManager manager = Managers.GetManager(); PlayerMainController val = (((Object)(object)manager != (Object)null) ? manager.GetOwnedPlayerController(sender) : null); if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).IsSpawned || ((NetworkBehaviour)val).OwnerClientId != sender) { return; } if (!remotes.TryGetValue(sender, out var value) || (Object)(object)value.Player != (Object)(object)val) { value = new RemoteState { Player = val }; remotes[sender] = value; ((BaseUnityPlugin)this).Logger.LogInfo((object)("AFK-capable co-op player registered (owner " + sender + ").")); } value.Protection.Receive(num, num2, num3, Time.unscaledTimeAsDouble); SampleRemote(value, Time.unscaledTimeAsDouble); int num4 = (enabledSetting.Value ? 1 : 0); FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref num4, default(ForPrimitives)); messaging.SendNamedMessage("noxie.planetcrafter.afkresourcepreserver.ack.v1", sender, val2, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception ex) { FailOpen(ex); } } private void ReceiveAck(ulong sender, FastBufferReader reader) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)network == (Object)null || network.IsServer || sender != 0L || ((FastBufferReader)(ref reader)).Length != 4) { return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); if (num == 1) { if (lastAck < 0.0 || warnedHost) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Host confirmed AFK Resource Preserver support."); } lastAck = Time.unscaledTimeAsDouble; warnedHost = false; } } internal void ResetPlayer(PlayerMainController player) { if (!((Object)(object)player == (Object)null)) { if ((Object)(object)player == (Object)(object)localPlayer) { ResetLocalTimer("placement/respawn"); lastSend = -100.0; } if (remotes.TryGetValue(((NetworkBehaviour)player).OwnerClientId, out var value)) { value.Protection.Reset(); } } } private void ResetLocalTimer(string reason) { if (local.Active) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("AFK protection deactivated: " + reason + ".")); } local.Reset(); } private void ResetLocal(string reason) { ResetLocalTimer(reason); localPlayer = null; } private void OnDisconnect(ulong id) { remotes.Remove(id); if ((Object)(object)network != (Object)null && id == network.LocalClientId) { ResetLocal("disconnected"); } } private void FailOpen(Exception ex) { ResetLocal("runtime error"); remotes.Clear(); if (!(Time.unscaledTimeAsDouble < nextError)) { nextError = Time.unscaledTimeAsDouble + 30.0; ((BaseUnityPlugin)this).Logger.LogError((object)("Preservation reset; normal survival continues. " + ex)); } } private void DetachNetwork() { if ((Object)(object)network != (Object)null) { network.OnClientDisconnectCallback -= OnDisconnect; } if (messaging != null) { messaging.UnregisterNamedMessageHandler("noxie.planetcrafter.afkresourcepreserver.state.v1"); messaging.UnregisterNamedMessageHandler("noxie.planetcrafter.afkresourcepreserver.ack.v1"); } messaging = null; network = null; } private void OnDestroy() { ready = false; ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; SceneManager.activeSceneChanged -= OnSceneChanged; DetachNetwork(); remotes.Clear(); local.Reset(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal sealed class RemoteProtection { internal readonly StationaryTracker Tracker = new StationaryTracker(); internal float Delay { get; private set; } internal float Threshold { get; private set; } internal int Mask { get; private set; } internal double Received { get; private set; } = -100.0; internal bool Receive(int mask, float delay, float threshold, double now) { if (mask < 0 || mask > 7 || !StationaryTracker.ValidSettings(delay, threshold) || !StationaryTracker.Finite(now)) { return false; } if (Delay != delay || Threshold != threshold || (Mask & 3) != (mask & 3) || ((Mask & 4) != 0 && (mask & 4) == 0) || !Fresh(now)) { Tracker.Reset(); } Delay = delay; Threshold = threshold; Mask = mask; Received = now; return true; } internal bool Fresh(double now) { if (now >= Received) { return now - Received <= 15.0; } return false; } internal bool Suppress(float delta, bool hunger, double now) { if (Fresh(now)) { return StationaryTracker.Suppress(delta, enabled: true, Tracker.Active && (Mask & 4) != 0, (Mask & (hunger ? 1 : 2)) != 0); } return false; } internal void Reset() { Tracker.Reset(); Mask &= 3; } } internal sealed class StationaryTracker { private bool sampled; private double anchorX; private double anchorY; private double anchorZ; private double since; private double lastSample; internal bool Active { get; private set; } internal void Reset() { sampled = false; Active = false; } internal bool Sample(double x, double y, double z, double now, double delay, double threshold) { if (!Finite(x) || !Finite(y) || !Finite(z) || !Finite(now) || !ValidSettings(delay, threshold)) { Reset(); return false; } double num = x - anchorX; double num2 = y - anchorY; double num3 = z - anchorZ; if (!sampled || now < lastSample || now - lastSample > 2.0 || num * num + num2 * num2 + num3 * num3 > threshold * threshold) { anchorX = x; anchorY = y; anchorZ = z; since = now; sampled = true; Active = false; } else { Active = now - since >= delay; } lastSample = now; return Active; } internal static bool Finite(double value) { if (!double.IsNaN(value)) { return !double.IsInfinity(value); } return false; } internal static bool ValidSettings(double delay, double threshold) { if (Finite(delay) && delay >= 1.0 && delay <= 3600.0 && Finite(threshold) && threshold >= 0.001) { return threshold <= 1.0; } return false; } internal static bool Suppress(float delta, bool enabled, bool active, bool preserve) { return delta < 0f && enabled && active && preserve; } } }