Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Dismantleheim v0.1.0
Dismantleheim.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dismantleheim.Core; using Dismantleheim.Input; using Dismantleheim.Install; using Dismantleheim.Integration; using Dismantleheim.Removal; using Dismantleheim.Selection; using Dismantleheim.UI; using HarmonyLib; using Jotunn.Configs; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Dismantleheim")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+8ecd339e038533b99f6b98fdebb101cdbc119c52")] [assembly: AssemblyProduct("Dismantleheim")] [assembly: AssemblyTitle("Dismantleheim")] [assembly: AssemblyVersion("0.1.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 Dismantleheim { [BepInPlugin("com.sonicdm.valheim.dismantleheim", "Dismantleheim", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class DismantleheimPlugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__56_0; internal void <RegisterCommands>b__56_0(ConsoleEventArgs args) { DismantleSession session = Session; if (session == null) { PrintCmd("Dismantleheim session unavailable."); return; } if (!PatchesReady && !GUIManager.IsHeadless()) { PrintCmd("Dismantleheim patches failed; activation closed."); return; } if (!IsModEnabled()) { PrintCmd("Dismantleheim disabled in config."); return; } switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "status") { case "mode": { string text = ((args.Length > 2) ? args[2] : string.Empty); if (!OperationModeUtil.TryParse(text, out var mode)) { PrintCmd("Usage: dismantleheim mode dismantle|delete"); break; } session.SetMode(mode, "command"); PrintCmd("Dismantleheim mode=" + OperationModeUtil.ShortName(session.ActiveMode) + " active=" + session.IsActive); break; } case "activate": { if (session.TryActivate(GetDefaultMode(), "command", out var reject)) { PrintCmd("Dismantleheim activated mode=" + OperationModeUtil.ShortName(session.ActiveMode)); } else { PrintCmd("Dismantleheim activate rejected: " + (reject ?? "unknown") + " (equip Hammer / enter place mode)."); } break; } case "deactivate": case "off": session.Deactivate("command"); PrintCmd("Dismantleheim deactivated."); break; case "clear": session.Queue.Clear(); session.SyncStateAfterSelectionChange(); PrintCmd("Dismantleheim selection cleared."); break; case "why": PrintCmd(session.LastRejectReason ?? "(no recent reject)"); break; default: PrintCmd("state=" + session.StateMachine.State.ToString() + " mode=" + OperationModeUtil.ShortName(session.ActiveMode) + " queue=" + session.Queue.Count + " filter=" + (session.Sampler.ActiveFilter ?? "(none)") + " dryRun=" + (DryRunOnly != null && DryRunOnly.Value) + " patches=" + PatchesReady); break; } } } public const string PluginGuid = "com.sonicdm.valheim.dismantleheim"; public const string PluginName = "Dismantleheim"; public const string PluginVersion = "0.1.0"; internal const string ActivateButtonName = "Dismantleheim_Activate"; internal static ManualLogSource ModLogger; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<KeyCode> ActivateKey; internal static ConfigEntry<float> ConfirmHoldSeconds; internal static ConfigEntry<bool> ShowRing; internal static ConfigEntry<bool> ShowSelectedCount; internal static ConfigEntry<bool> AllowEnvironmentWithFilter; internal static ConfigEntry<bool> ClearQueueOnToolSwitch; internal static ConfigEntry<string> ExtraDenyPrefabs; internal static ConfigEntry<string> ExtraAllowPrefabs; internal static ConfigEntry<bool> InstallInfinityHammerTool; internal static ConfigEntry<bool> PreferInfinityHammerOnly; internal static ConfigEntry<bool> DryRunOnly; internal static ConfigEntry<string> DefaultMode; internal static ConfigEntry<bool> ShowActiveMode; internal static ConfigEntry<bool> PreserveSelectionOnModeSwitch; internal static ConfigEntry<int> MaximumTargets; internal static ConfigEntry<float> DragSelectRadius; internal static ConfigEntry<bool> WarnWhenDeletingOccupiedContainers; internal static ConfigEntry<bool> RefuseUnknownDeleteTargets; private Harmony _harmony; private ButtonConfig _activateButton; private bool _clientSystemsStarted; private bool _ihToolsInstallDone; private static bool _commandsRegistered; internal static bool DebugEnabled { get { if (DebugLogging != null) { return DebugLogging.Value; } return false; } } internal static DismantleSession Session { get; private set; } internal static bool PatchesReady { get; private set; } private void Awake() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; BindConfig(); Session = new DismantleSession(); RegisterCommands(); if (GUIManager.IsHeadless()) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dismantleheim 0.1.0 skipped client systems on headless server."); return; } RegisterActivateButton(); if (ActivateKey != null) { ActivateKey.SettingChanged += OnActivateKeyChanged; } if (Enabled != null) { Enabled.SettingChanged += OnEnabledChanged; } TryInstallInfinityHammerTools(forceRetry: false); _harmony = new Harmony("com.sonicdm.valheim.dismantleheim"); try { _harmony.PatchAll(typeof(DismantleheimPlugin).Assembly); PatchesReady = true; _clientSystemsStarted = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dismantleheim 0.1.0 loaded."); } catch (Exception ex) { PatchesReady = false; ((BaseUnityPlugin)this).Logger.LogError((object)("Dismantleheim failed to patch (fail-closed): " + ex)); try { _harmony.UnpatchSelf(); } catch { } } } private void Start() { if (!GUIManager.IsHeadless() && !_ihToolsInstallDone) { TryInstallInfinityHammerTools(forceRetry: true); } } private void TryInstallInfinityHammerTools(bool forceRetry) { if (InstallInfinityHammerTool == null || !InstallInfinityHammerTool.Value) { _ihToolsInstallDone = true; } else { if (_ihToolsInstallDone && !forceRetry) { return; } if (InfinityHammerDetector.IsInstalled(out var guid, out var version)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Infinity Hammer detected (" + guid + " " + version + ").")); } else { if (!forceRetry) { return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Infinity Hammer not detected; writing owned tools YAML for next IH load. ActivateKey/console remain available."); } if (YamlToolInstallerBridge.TryInstall(((BaseUnityPlugin)this).Logger, out var destPath, out var wroteBytes)) { _ihToolsInstallDone = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)(wroteBytes ? ("Dismantleheim: wrote owned IH tools file " + destPath) : ("Dismantleheim: owned IH tools file already current " + destPath))); } } } private void OnDestroy() { if (ActivateKey != null) { ActivateKey.SettingChanged -= OnActivateKeyChanged; } if (Enabled != null) { Enabled.SettingChanged -= OnEnabledChanged; } if (Session != null && Session.IsActive) { Session.ResetHard("unload"); } HoverHighlighter.ClearAll(); ContextualInputRouter.ResetLatches(); DragBoxSelector.Cancel(); if (_harmony != null) { try { _harmony.UnpatchSelf(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Unpatch failed: " + ex.Message)); } _harmony = null; } PatchesReady = false; _activateButton = null; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dismantleheim unloaded (ScriptEngine-safe)."); } private void RegisterActivateButton() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0015: 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) KeyCode key = (KeyCode)((ActivateKey == null) ? 127 : ((int)ActivateKey.Value)); string key2 = "Dismantleheim_Activate!com.sonicdm.valheim.dismantleheim"; try { if (AccessTools.Field(typeof(InputManager), "Buttons")?.GetValue(null) is Dictionary<string, ButtonConfig> dictionary && dictionary.TryGetValue(key2, out var value) && value != null) { value.Key = key; _activateButton = value; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Reused Jotunn activate button after reload."); return; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Activate button reuse failed: " + ex.Message)); } _activateButton = new ButtonConfig { Name = "Dismantleheim_Activate", Key = key, ActiveInGUI = false, ActiveInCustomGUI = false }; InputManager.Instance.AddButton("com.sonicdm.valheim.dismantleheim", _activateButton); } internal static bool WasActivatePressed() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) ButtonConfig value = null; try { if (AccessTools.Field(typeof(InputManager), "Buttons")?.GetValue(null) is Dictionary<string, ButtonConfig> dictionary) { dictionary.TryGetValue("Dismantleheim_Activate!com.sonicdm.valheim.dismantleheim", out value); } } catch { } if (value != null && ZInput.GetButtonDown(value.Name)) { return true; } if (ZInput.GetButtonDown("Dismantleheim_Activate")) { return true; } KeyCode val = (KeyCode)((ActivateKey == null) ? 127 : ((int)ActivateKey.Value)); return Input.GetKeyDown(val); } private void OnActivateKeyChanged(object sender, EventArgs e) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (_activateButton != null && ActivateKey != null) { _activateButton.Key = ActivateKey.Value; } } private void OnEnabledChanged(object sender, EventArgs e) { if (!IsModEnabled() && Session != null && Session.IsActive) { Session.ResetHard("disabled"); } } private void BindConfig() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Dismantleheim."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", true, "Write diagnostic lines to BepInEx LogOutput.log. Default on while debugging selection."); DefaultMode = ((BaseUnityPlugin)this).Config.Bind<string>("Modes", "DefaultMode", "MassDismantle", "Mode entered by ActivateKey / activate command: MassDismantle or MassDelete."); ShowActiveMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Modes", "ShowActiveMode", true, "Show MASS DISMANTLE / MASS DELETE banner near the cursor."); PreserveSelectionOnModeSwitch = ((BaseUnityPlugin)this).Config.Bind<bool>("Modes", "PreserveSelectionOnModeSwitch", true, "Keep the queue when switching between Mass Dismantle and Mass Delete (revalidated; never executes)."); ActivateKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "ActivateKey", (KeyCode)127, "Toggle DefaultMode session on/off. Default: Delete. Does not switch modes."); ConfirmHoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Confirm", "HoldSeconds", 1f, new ConfigDescription("Seconds to hold Mouse3 to confirm.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>())); ShowRing = ((BaseUnityPlugin)this).Config.Bind<bool>("Confirm", "ShowRing", true, "Draw the confirmation progress ring around the cursor."); ShowSelectedCount = ((BaseUnityPlugin)this).Config.Bind<bool>("Confirm", "ShowSelectedCount", true, "Show selected object count near the reticle."); AllowEnvironmentWithFilter = ((BaseUnityPlugin)this).Config.Bind<bool>("Selection", "AllowEnvironmentWithFilter", true, "Mass Delete only: when a prefab filter is sampled, allow matching rocks/trees into the queue."); DragSelectRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Selection", "DragSelectRadius", 40f, new ConfigDescription("Unused legacy key (box-select removed). Mass-select is Satisfactory-style Ctrl + aim paint.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>())); ClearQueueOnToolSwitch = ((BaseUnityPlugin)this).Config.Bind<bool>("Selection", "ClearQueueOnToolSwitch", true, "Clear the pending selection when leaving Dismantleheim mode."); MaximumTargets = ((BaseUnityPlugin)this).Config.Bind<int>("Selection", "MaximumTargets", 50, new ConfigDescription("Maximum queued targets.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>())); ExtraDenyPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("Selection", "ExtraDenyPrefabs", "", "Comma-separated prefab names never selectable."); ExtraAllowPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("Selection", "ExtraAllowPrefabs", "", "Comma-separated prefab names that ignore ExtraDeny only. Does not bypass type/removability/environment rules."); WarnWhenDeletingOccupiedContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "WarnWhenDeletingOccupiedContainers", true, "Mass Delete: show contents-loss warning when queued containers hold items."); RefuseUnknownDeleteTargets = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "RefuseUnknownDeleteTargets", true, "Mass Delete: skip unsupported/unknown targets instead of forcing network destroy."); InstallInfinityHammerTool = ((BaseUnityPlugin)this).Config.Bind<bool>("Integration", "InstallInfinityHammerTool", true, "Write owned infinity_tools_dismantleheim.yaml (two Tools entries) when Infinity Hammer is installed."); PreferInfinityHammerOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Integration", "PreferInfinityHammerOnly", true, "Architecture: never spawn an extra inventory Hammer; Tools YAML + ActivateKey/console only."); DryRunOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Removal", "DryRunOnly", false, "When true, confirmation only logs the plan — no world deletes. Default false (live remove). Enable for safe testing."); } internal static OperationMode GetDefaultMode() { if (DefaultMode != null && OperationModeUtil.TryParse(DefaultMode.Value, out var mode)) { return mode; } return OperationMode.MassDismantle; } private void Update() { if (_clientSystemsStarted && PatchesReady && IsModEnabled() && Session != null && !GUIManager.IsHeadless()) { ContextualInputRouter.Tick(Session); HoverHighlighter.Tick(Session); ConfirmationRing.Tick(Session); } } private void OnGUI() { if (_clientSystemsStarted && PatchesReady && IsModEnabled() && Session != null && Session.IsActive) { DragBoxSelector.DrawGui(); ConfirmationRing.DrawGui(Session); } } internal static float GetDragSelectRadius() { if (DragSelectRadius == null) { return 40f; } return Mathf.Clamp(DragSelectRadius.Value, 5f, 120f); } internal static bool IsModEnabled() { if (Enabled != null) { return Enabled.Value; } return true; } internal static void DebugLog(string message) { if (DebugEnabled && ModLogger != null) { ModLogger.LogInfo((object)("Dismantleheim debug: " + message)); } } internal static float GetHoldSeconds() { if (ConfirmHoldSeconds == null) { return 1f; } float value = ConfirmHoldSeconds.Value; if (value < 0.2f) { return 0.2f; } if (value > 5f) { return 5f; } return value; } private void RegisterCommands() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown if (_commandsRegistered) { return; } _commandsRegistered = true; object obj = <>c.<>9__56_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { DismantleSession session = Session; if (session == null) { PrintCmd("Dismantleheim session unavailable."); } else if (!PatchesReady && !GUIManager.IsHeadless()) { PrintCmd("Dismantleheim patches failed; activation closed."); } else if (!IsModEnabled()) { PrintCmd("Dismantleheim disabled in config."); } else { switch ((args.Length > 1) ? args[1].ToLowerInvariant() : "status") { case "mode": { string text = ((args.Length > 2) ? args[2] : string.Empty); if (!OperationModeUtil.TryParse(text, out var mode)) { PrintCmd("Usage: dismantleheim mode dismantle|delete"); } else { session.SetMode(mode, "command"); PrintCmd("Dismantleheim mode=" + OperationModeUtil.ShortName(session.ActiveMode) + " active=" + session.IsActive); } break; } case "activate": { if (session.TryActivate(GetDefaultMode(), "command", out var reject)) { PrintCmd("Dismantleheim activated mode=" + OperationModeUtil.ShortName(session.ActiveMode)); } else { PrintCmd("Dismantleheim activate rejected: " + (reject ?? "unknown") + " (equip Hammer / enter place mode)."); } break; } case "deactivate": case "off": session.Deactivate("command"); PrintCmd("Dismantleheim deactivated."); break; case "clear": session.Queue.Clear(); session.SyncStateAfterSelectionChange(); PrintCmd("Dismantleheim selection cleared."); break; case "why": PrintCmd(session.LastRejectReason ?? "(no recent reject)"); break; default: PrintCmd("state=" + session.StateMachine.State.ToString() + " mode=" + OperationModeUtil.ShortName(session.ActiveMode) + " queue=" + session.Queue.Count + " filter=" + (session.Sampler.ActiveFilter ?? "(none)") + " dryRun=" + (DryRunOnly != null && DryRunOnly.Value) + " patches=" + PatchesReady); break; } } }; <>c.<>9__56_0 = val; obj = (object)val; } new ConsoleCommand("dismantleheim", "Dismantleheim: mode dismantle|delete | activate|deactivate|status|clear|why", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void PrintCmd(string msg) { if ((Object)(object)Console.instance != (Object)null) { Console.instance.Print(msg); } ManualLogSource modLogger = ModLogger; if (modLogger != null) { modLogger.LogInfo((object)msg); } } } } namespace Dismantleheim.Core { public sealed class ConfirmationHold { private float _startTime = -1f; private bool _armed = true; private bool _holding; public bool IsHolding => _holding; public float Progress { get; private set; } public bool CompletedThisFrame { get; private set; } public void Begin(float nowSeconds) { CompletedThisFrame = false; if (_armed) { _holding = true; _startTime = nowSeconds; Progress = 0f; } } public void Update(float nowSeconds, float holdSeconds) { CompletedThisFrame = false; if (_holding && _armed) { float num = ((holdSeconds <= 0.01f) ? 0.01f : holdSeconds); float num2 = nowSeconds - _startTime; if (num2 < 0f) { num2 = 0f; } Progress = num2 / num; if (Progress >= 1f) { Progress = 1f; CompletedThisFrame = true; _holding = false; _armed = false; } } } public void Cancel() { _holding = false; _startTime = -1f; Progress = 0f; CompletedThisFrame = false; } public void Rearm() { _armed = true; if (!_holding) { Progress = 0f; } } } public enum DismantleState { Inactive, ActiveIdle, Selected, HoldingConfirm, Validating, Executing } public enum DismantleTransition { Activate, Deactivate, SelectionChanged, BeginHold, CancelHold, HoldComplete, ValidationDone, ExecutionDone, ToolSwitch } public sealed class DismantleStateMachine { public DismantleState State { get; private set; } public bool LastTransitionRequestedExecute { get; private set; } public bool TryTransition(DismantleTransition transition, int queueCount, out DismantleState newState) { LastTransitionRequestedExecute = false; DismantleState dismantleState = (newState = State); if (transition == DismantleTransition.ToolSwitch || transition == DismantleTransition.Deactivate) { State = DismantleState.Inactive; newState = State; return true; } switch (dismantleState) { case DismantleState.Inactive: if (transition == DismantleTransition.Activate) { State = DismantleState.ActiveIdle; newState = State; return true; } break; case DismantleState.ActiveIdle: switch (transition) { case DismantleTransition.SelectionChanged: State = ((queueCount <= 0) ? DismantleState.ActiveIdle : DismantleState.Selected); newState = State; return true; case DismantleTransition.BeginHold: if (queueCount <= 0) { return false; } State = DismantleState.HoldingConfirm; newState = State; return true; } break; case DismantleState.Selected: switch (transition) { case DismantleTransition.SelectionChanged: State = ((queueCount <= 0) ? DismantleState.ActiveIdle : DismantleState.Selected); newState = State; return true; case DismantleTransition.BeginHold: if (queueCount <= 0) { return false; } State = DismantleState.HoldingConfirm; newState = State; return true; } break; case DismantleState.HoldingConfirm: switch (transition) { case DismantleTransition.CancelHold: State = ((queueCount <= 0) ? DismantleState.ActiveIdle : DismantleState.Selected); newState = State; return true; case DismantleTransition.HoldComplete: if (queueCount <= 0) { State = DismantleState.ActiveIdle; newState = State; return true; } State = DismantleState.Validating; newState = State; return true; } break; case DismantleState.Validating: if (transition == DismantleTransition.ValidationDone) { State = DismantleState.Executing; LastTransitionRequestedExecute = true; newState = State; return true; } break; case DismantleState.Executing: if (transition == DismantleTransition.ExecutionDone) { State = ((queueCount <= 0) ? DismantleState.ActiveIdle : DismantleState.Selected); newState = State; return true; } break; } return false; } public void ForceInactive() { State = DismantleState.Inactive; LastTransitionRequestedExecute = false; } } public enum TargetKind { Unsupported, BuildPiece, Environment } public enum EligibilityRejectReason { None, NullTarget, Stale, UnsupportedType, NoPiece, NotRemovable, EnvironmentWithoutFilter, PrefabFilterMismatch, ExtraDeny, SessionMismatch, NoScopePreview } public static class Eligibility { public static bool IsEligible(TargetIdentity target, string prefabFilter, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, out EligibilityRejectReason reason) { return IsEligible(target, OperationMode.MassDelete, prefabFilter, allowEnvironmentWithFilter, extraDeny, extraAllow, out reason); } public static bool IsEligible(TargetIdentity target, OperationMode mode, string prefabFilter, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, out EligibilityRejectReason reason) { if (!PassesDenyAllow(target, extraDeny, extraAllow, out reason)) { return false; } bool flag = !string.IsNullOrEmpty(prefabFilter); bool flag2 = flag && string.Equals(target.PrefabName ?? string.Empty, prefabFilter, StringComparison.OrdinalIgnoreCase); if (mode == OperationMode.MassDelete && flag2 && allowEnvironmentWithFilter) { if (target.Kind == TargetKind.BuildPiece) { return PassesBuildPieceRemovability(target, out reason); } reason = EligibilityRejectReason.None; return true; } if (!PassesHardSafety(target, out reason)) { return false; } if (mode == OperationMode.MassDismantle) { if (target.Kind == TargetKind.Environment) { reason = EligibilityRejectReason.EnvironmentWithoutFilter; return false; } if (target.Kind != TargetKind.BuildPiece) { reason = EligibilityRejectReason.UnsupportedType; return false; } if (flag && !flag2) { reason = EligibilityRejectReason.PrefabFilterMismatch; return false; } return PassesBuildPieceRemovability(target, out reason); } if (flag && !flag2) { reason = EligibilityRejectReason.PrefabFilterMismatch; return false; } if (target.Kind == TargetKind.Environment) { reason = EligibilityRejectReason.EnvironmentWithoutFilter; return false; } if (target.Kind != TargetKind.BuildPiece) { reason = EligibilityRejectReason.UnsupportedType; return false; } return PassesBuildPieceRemovability(target, out reason); } public static bool IsEligibleForCommit(TargetIdentity target, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, out EligibilityRejectReason reason) { return IsEligibleForCommit(target, OperationMode.MassDelete, allowEnvironmentWithFilter, extraDeny, extraAllow, out reason); } public static bool IsEligibleForCommit(TargetIdentity target, OperationMode mode, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, out EligibilityRejectReason reason) { if (!PassesDenyAllow(target, extraDeny, extraAllow, out reason)) { return false; } if (mode == OperationMode.MassDismantle) { if (!PassesHardSafety(target, out reason)) { return false; } if (target.Kind != TargetKind.BuildPiece) { reason = ((target.Kind == TargetKind.Environment) ? EligibilityRejectReason.EnvironmentWithoutFilter : EligibilityRejectReason.UnsupportedType); return false; } return PassesBuildPieceRemovability(target, out reason); } if (target.Kind == TargetKind.Environment || target.Kind == TargetKind.Unsupported) { if (!allowEnvironmentWithFilter) { reason = EligibilityRejectReason.EnvironmentWithoutFilter; return false; } reason = EligibilityRejectReason.None; return true; } if (target.Kind == TargetKind.BuildPiece) { if (!PassesHardSafety(target, out reason)) { return false; } return PassesBuildPieceRemovability(target, out reason); } reason = EligibilityRejectReason.UnsupportedType; return false; } private static bool PassesDenyAllow(TargetIdentity target, ISet<string> extraDeny, ISet<string> extraAllow, out EligibilityRejectReason reason) { reason = EligibilityRejectReason.None; if (target == null) { reason = EligibilityRejectReason.NullTarget; return false; } if (target.IsStale) { reason = EligibilityRejectReason.Stale; return false; } string item = target.PrefabName ?? string.Empty; bool flag = extraDeny?.Contains(item) ?? false; bool flag2 = extraAllow?.Contains(item) ?? false; if (flag && !flag2) { reason = EligibilityRejectReason.ExtraDeny; return false; } return true; } private static bool PassesHardSafety(TargetIdentity target, out EligibilityRejectReason reason) { reason = EligibilityRejectReason.None; if (target.Kind == TargetKind.Unsupported) { reason = EligibilityRejectReason.UnsupportedType; return false; } if (!target.HasScopePreview && target.Kind != TargetKind.Environment) { reason = EligibilityRejectReason.NoScopePreview; return false; } return true; } private static bool PassesBuildPieceRemovability(TargetIdentity target, out EligibilityRejectReason reason) { reason = EligibilityRejectReason.None; if (!target.HasPiece) { reason = EligibilityRejectReason.NoPiece; return false; } if (!target.CanBeRemoved) { reason = EligibilityRejectReason.NotRemovable; return false; } return true; } public static TargetKind Classify(bool hasPiece, bool canBeRemoved, bool isEnvironment, bool hasScopePreview) { if (isEnvironment) { return TargetKind.Environment; } if (hasPiece) { return TargetKind.BuildPiece; } return TargetKind.Unsupported; } public static HashSet<string> ParsePrefabList(string csv) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(csv)) { return hashSet; } string[] array = csv.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length > 0) { hashSet.Add(text2); } } return hashSet; } } public static class IhToolNames { public static bool TryMatch(string label, out OperationMode mode) { mode = OperationMode.MassDismantle; if (string.IsNullOrEmpty(label)) { return false; } if (label.IndexOf("Mass Delete", StringComparison.OrdinalIgnoreCase) >= 0 || label.IndexOf("mode delete", StringComparison.OrdinalIgnoreCase) >= 0) { mode = OperationMode.MassDelete; return true; } if (label.IndexOf("Mass Dismantle", StringComparison.OrdinalIgnoreCase) >= 0 || label.IndexOf("mode dismantle", StringComparison.OrdinalIgnoreCase) >= 0 || (label.IndexOf("Dismantleheim", StringComparison.OrdinalIgnoreCase) >= 0 && label.IndexOf("Delete", StringComparison.OrdinalIgnoreCase) < 0)) { mode = OperationMode.MassDismantle; return true; } return false; } } public interface IRemovalPolicy { OperationMode Mode { get; } DropPolicy PredictedDropPolicy { get; } bool AllowsEnvironment { get; } RemovalPlanEntry PlanEntry(TargetIdentity target, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, bool contentsLossWarning); } public sealed class MassDismantlePolicy : IRemovalPolicy { public OperationMode Mode => OperationMode.MassDismantle; public DropPolicy PredictedDropPolicy => DropPolicy.RefundsViaNative; public bool AllowsEnvironment => false; public RemovalPlanEntry PlanEntry(TargetIdentity target, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, bool contentsLossWarning) { if (!Eligibility.IsEligibleForCommit(target, Mode, allowEnvironmentWithFilter, extraDeny, extraAllow, out var reason)) { return new RemovalPlanEntry(target, Mode, DropPolicy.None, RemovalSkipReason.ModeIneligible, reason.ToString(), contentsLossWarning: false); } return new RemovalPlanEntry(target, Mode, DropPolicy.RefundsViaNative, RemovalSkipReason.None, "native refund path", contentsLossWarning: false); } } public sealed class MassDeletePolicy : IRemovalPolicy { public OperationMode Mode => OperationMode.MassDelete; public DropPolicy PredictedDropPolicy => DropPolicy.NoDrops; public bool AllowsEnvironment => true; public RemovalPlanEntry PlanEntry(TargetIdentity target, bool allowEnvironmentWithFilter, ISet<string> extraDeny, ISet<string> extraAllow, bool contentsLossWarning) { if (!Eligibility.IsEligibleForCommit(target, Mode, allowEnvironmentWithFilter, extraDeny, extraAllow, out var reason)) { return new RemovalPlanEntry(target, Mode, DropPolicy.None, RemovalSkipReason.ModeIneligible, reason.ToString(), contentsLossWarning: false); } return new RemovalPlanEntry(target, Mode, DropPolicy.NoDrops, RemovalSkipReason.None, contentsLossWarning ? "no drops; contents-loss warning" : "no drops", contentsLossWarning); } } public static class RemovalPolicyFactory { public static IRemovalPolicy For(OperationMode mode) { if (mode != OperationMode.MassDelete) { return new MassDismantlePolicy(); } return new MassDeletePolicy(); } } public enum OperationMode { MassDismantle, MassDelete } public enum DropPolicy { None, RefundsViaNative, NoDrops } public static class OperationModeUtil { public static string Banner(OperationMode mode) { if (mode != OperationMode.MassDelete) { return "MASS DISMANTLE — Returns Materials"; } return "MASS DELETE — No Drops"; } public static string ShortName(OperationMode mode) { if (mode != OperationMode.MassDelete) { return "dismantle"; } return "delete"; } public static bool TryParse(string text, out OperationMode mode) { mode = OperationMode.MassDismantle; if (string.IsNullOrWhiteSpace(text)) { return false; } switch (text.Trim().ToLowerInvariant()) { case "dismantle": case "massdismantle": case "mass-dismantle": mode = OperationMode.MassDismantle; return true; case "delete": case "massdelete": case "mass-delete": mode = OperationMode.MassDelete; return true; default: return false; } } } public sealed class PrefabSampler { public string ActiveFilter { get; private set; } public bool HasFilter => !string.IsNullOrEmpty(ActiveFilter); public bool TrySample(string prefabName, out string resultingFilter) { resultingFilter = ActiveFilter; if (string.IsNullOrWhiteSpace(prefabName)) { return false; } string text = prefabName.Trim(); if (string.Equals(ActiveFilter, text, StringComparison.OrdinalIgnoreCase)) { ActiveFilter = null; resultingFilter = null; return true; } ActiveFilter = text; resultingFilter = ActiveFilter; return true; } public void Clear() { ActiveFilter = null; } } public sealed class RemovalPlan { private readonly List<TargetIdentity> _targets; public IReadOnlyList<TargetIdentity> Targets => _targets; public int Count => _targets.Count; private RemovalPlan(IEnumerable<TargetIdentity> targets) { _targets = targets.ToList(); } public static RemovalPlan FromQueue(IEnumerable<TargetIdentity> queued, Func<TargetIdentity, bool> isStillValid, out List<TargetIdentity> skipped) { skipped = new List<TargetIdentity>(); List<TargetIdentity> list = new List<TargetIdentity>(); if (queued == null) { return new RemovalPlan(list); } foreach (TargetIdentity item in queued) { if (item != null) { if (LooksLikeWildcard(item.PrefabName)) { skipped.Add(item); } else if (isStillValid != null && !isStillValid(item)) { skipped.Add(item); } else { list.Add(item); } } } return new RemovalPlan(list); } public static bool LooksLikeWildcard(string prefabOrDescriptor) { if (string.IsNullOrEmpty(prefabOrDescriptor)) { return false; } if (prefabOrDescriptor.IndexOf("id=*", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (prefabOrDescriptor.IndexOf("*", StringComparison.Ordinal) >= 0 && prefabOrDescriptor.IndexOf("remove", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } } public enum RemovalSkipReason { None, Stale, PermissionDenied, ContainerWithContents, Portal, Ward, UnsupportedEnvironment, WildcardRejected, DryRun, UnsafeDelete, ModeIneligible, PendingNetwork } public sealed class RemovalPlanEntry { public TargetIdentity Target { get; } public OperationMode Mode { get; } public DropPolicy DropPolicy { get; } public RemovalSkipReason SkipReason { get; } public string Message { get; } public bool ContentsLossWarning { get; } public bool IsExecutable { get { if (SkipReason != RemovalSkipReason.None) { return SkipReason == RemovalSkipReason.DryRun; } return true; } } public RemovalPlanEntry(TargetIdentity target, OperationMode mode, DropPolicy dropPolicy, RemovalSkipReason skipReason, string message, bool contentsLossWarning) { Target = target; Mode = mode; DropPolicy = dropPolicy; SkipReason = skipReason; Message = message ?? string.Empty; ContentsLossWarning = contentsLossWarning; } } public sealed class RemovalResult { public TargetIdentity Target { get; } public bool Removed { get; } public RemovalSkipReason SkipReason { get; } public string Message { get; } public DropPolicy DropPolicy { get; } public OperationMode Mode { get; } public RemovalResult(TargetIdentity target, bool removed, RemovalSkipReason skipReason, string message, DropPolicy dropPolicy = DropPolicy.None, OperationMode mode = OperationMode.MassDismantle) { Target = target; Removed = removed; SkipReason = skipReason; Message = message ?? string.Empty; DropPolicy = dropPolicy; Mode = mode; } } public sealed class SelectionQueue { private readonly List<TargetIdentity> _entries = new List<TargetIdentity>(); public int Count => _entries.Count; public IReadOnlyList<TargetIdentity> Entries => _entries; public bool Contains(TargetIdentity identity) { if (identity == null) { return false; } for (int i = 0; i < _entries.Count; i++) { if (_entries[i].Equals(identity)) { return true; } } return false; } public bool Toggle(TargetIdentity identity, int maxCount = 0) { if (identity == null) { return false; } for (int i = 0; i < _entries.Count; i++) { if (_entries[i].Equals(identity)) { _entries.RemoveAt(i); return false; } } return TryAdd(identity, maxCount); } public bool TryAdd(TargetIdentity identity, int maxCount = 0) { if (identity == null || Contains(identity)) { return false; } if (maxCount > 0 && _entries.Count >= maxCount) { return false; } _entries.Add(identity); return true; } public bool TryRemove(TargetIdentity identity) { if (identity == null) { return false; } for (int i = 0; i < _entries.Count; i++) { if (_entries[i].Equals(identity)) { _entries.RemoveAt(i); return true; } } return false; } public void Clear() { _entries.Clear(); } public IReadOnlyList<TargetIdentity> Snapshot() { return _entries.ToList(); } } public sealed class TargetIdentity : IEquatable<TargetIdentity> { public long UserId { get; } public uint ObjectId { get; } public long NetworkId => ObjectId; public string WorldSessionKey { get; } public string PrefabName { get; } public bool HasPiece { get; } public bool CanBeRemoved { get; } public bool IsEnvironment { get; } public TargetKind Kind { get; } public bool HasScopePreview { get; } public bool IsStale { get; } public TargetIdentity(long userId, uint objectId, string worldSessionKey, string prefabName, bool hasPiece, bool canBeRemoved, bool isEnvironment, TargetKind kind, bool hasScopePreview, bool isStale = false) { UserId = userId; ObjectId = objectId; WorldSessionKey = worldSessionKey ?? string.Empty; PrefabName = prefabName ?? string.Empty; HasPiece = hasPiece; CanBeRemoved = canBeRemoved; IsEnvironment = isEnvironment; Kind = kind; HasScopePreview = hasScopePreview; IsStale = isStale; } public bool Equals(TargetIdentity other) { if (other == null) { return false; } if (UserId == other.UserId && ObjectId == other.ObjectId) { return string.Equals(WorldSessionKey, other.WorldSessionKey, StringComparison.Ordinal); } return false; } public override bool Equals(object obj) { return Equals(obj as TargetIdentity); } public override int GetHashCode() { int hashCode = UserId.GetHashCode(); hashCode = (hashCode * 397) ^ ObjectId.GetHashCode(); return (hashCode * 397) ^ ((WorldSessionKey != null) ? WorldSessionKey.GetHashCode() : 0); } } public static class YamlToolInstaller { public const string ToolNameDismantle = "Dismantleheim - Mass Dismantle"; public const string ToolNameDelete = "Dismantleheim - Mass Delete"; public const string LegacyToolName = "Dismantleheim"; public const string Marker = "dismantleheim-tool-v10"; public const string ActivateCommandDismantle = "dismantleheim mode dismantle"; public const string ActivateCommandDelete = "dismantleheim mode delete"; public const string LegacyActivateCommand = "dismantleheim activate"; public const string EquipmentKey = "hammer"; public const string OwnedFileName = "infinity_tools_dismantleheim.yaml"; public const string ConflictBackupSuffix = ".dismantleheim-conflict.bak"; public const string ToolName = "Dismantleheim - Mass Dismantle"; public const string ActivateCommand = "dismantleheim mode dismantle"; public static string BuildOwnedDocument() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# dismantleheim-tool-v10 — owned by Dismantleheim; safe to delete on uninstall"); stringBuilder.AppendLine("hammer:"); AppendTool(stringBuilder, "Dismantleheim - Mass Dismantle", "Select built pieces, then hold Mouse3 to reclaim materials (vanilla refunds).", "dismantleheim mode dismantle"); AppendTool(stringBuilder, "Dismantleheim - Mass Delete", "Select objects, then hold Mouse3 to erase without drops. Containers may destroy contents.", "dismantleheim mode delete"); return stringBuilder.ToString(); } private static void AppendTool(StringBuilder sb, string name, string description, string command) { sb.AppendLine("- name: " + name); sb.AppendLine(" description: |-"); sb.AppendLine(" " + description); sb.AppendLine(" Hold Ctrl + wave aim to mass-select. Ctrl+click unselects one. Shift+Mouse3 samples."); sb.AppendLine(" Hold Mouse3 to confirm."); sb.AppendLine(" icon: Hammer"); sb.AppendLine(" instant: true"); sb.AppendLine(" command: " + command); sb.AppendLine(" tabIndex: 0"); } public static bool WriteOwnedDocument(string existingOwnedYaml, out string nextYaml) { string text = existingOwnedYaml ?? string.Empty; if (ShouldPreserveOwnedDocument(text)) { nextYaml = NormalizeNewlines(text).TrimEnd() + Environment.NewLine; return false; } string text2 = NormalizeNewlines(BuildOwnedDocument()).TrimEnd() + "\n"; string a = NormalizeNewlines(text).TrimEnd() + "\n"; nextYaml = text2.Replace("\n", Environment.NewLine); return !string.Equals(a, text2, StringComparison.Ordinal); } public static bool ShouldPreserveOwnedDocument(string yaml) { if (string.IsNullOrWhiteSpace(yaml)) { return false; } string a = NormalizeNewlines(BuildOwnedDocument()).TrimEnd(); string text = NormalizeNewlines(yaml).TrimEnd(); if (string.Equals(a, text, StringComparison.Ordinal)) { return false; } if (IsUpgradeableStockDocument(text)) { return false; } return true; } public static bool IsUpgradeableStockDocument(string yaml) { if (string.IsNullOrWhiteSpace(yaml)) { return false; } if (yaml.IndexOf("dismantleheim-tool", StringComparison.OrdinalIgnoreCase) < 0) { return false; } if (Regex.IsMatch(NormalizeNewlines(yaml), "(?m)^\\s*icon:\\s*(?!Hammer\\s*$).+$")) { return false; } int num = CountNamedToolsInDocument(yaml, "Dismantleheim - Mass Dismantle"); int num2 = CountNamedToolsInDocument(yaml, "Dismantleheim - Mass Delete"); bool flag = CountNamedToolsInDocument(yaml, "Dismantleheim") > 0; bool flag2 = num == 1 && num2 == 1; if (num == 0 && num2 == 0 && !flag) { return false; } if (yaml.IndexOf("dismantleheim-tool-", StringComparison.OrdinalIgnoreCase) >= 0 && yaml.IndexOf("dismantleheim-tool-v10", StringComparison.OrdinalIgnoreCase) < 0) { return true; } return !flag2 || flag; } public static bool WriteOwnedFile(string configRoot, bool preferToolsSubfolder) { if (string.IsNullOrEmpty(configRoot)) { throw new ArgumentException("configRoot required", "configRoot"); } string text = Path.Combine(configRoot, "tools"); bool flag = preferToolsSubfolder && Directory.Exists(text); string text2 = Path.Combine(flag ? text : configRoot, "infinity_tools_dismantleheim.yaml"); string text3 = Path.Combine(flag ? configRoot : text, "infinity_tools_dismantleheim.yaml"); ResolveExistingOwnedContent(text2, text3, out var existing, out var _); bool result = false; WriteOwnedDocument(existing, out var nextYaml); string s = (File.Exists(text2) ? File.ReadAllText(text2, Encoding.UTF8) : string.Empty); if (!File.Exists(text2) || !string.Equals(NormalizeNewlines(s), NormalizeNewlines(nextYaml), StringComparison.Ordinal)) { AtomicWrite(text2, nextYaml); result = true; } if (File.Exists(text3) && !string.Equals(Path.GetFullPath(text3), Path.GetFullPath(text2), StringComparison.OrdinalIgnoreCase)) { string text4 = File.ReadAllText(text3, Encoding.UTF8); string s2 = File.ReadAllText(text2, Encoding.UTF8); if (!string.Equals(NormalizeNewlines(text4), NormalizeNewlines(s2), StringComparison.Ordinal)) { AtomicWrite(text3 + ".dismantleheim-conflict.bak", text4); } File.Delete(text3); result = true; } TryRemoveStaleFromSharedDefault(configRoot); return result; } public static void ResolveExistingOwnedContent(string preferredPath, string alternatePath, out string existing, out string conflictBackupPath) { existing = string.Empty; conflictBackupPath = null; bool flag = File.Exists(preferredPath); bool flag2 = File.Exists(alternatePath) && !string.Equals(Path.GetFullPath(preferredPath), Path.GetFullPath(alternatePath), StringComparison.OrdinalIgnoreCase); if (!flag && !flag2) { return; } if (flag && !flag2) { existing = File.ReadAllText(preferredPath, Encoding.UTF8); return; } if (!flag && flag2) { existing = File.ReadAllText(alternatePath, Encoding.UTF8); return; } string text = File.ReadAllText(preferredPath, Encoding.UTF8); string text2 = File.ReadAllText(alternatePath, Encoding.UTF8); if (string.Equals(NormalizeNewlines(text), NormalizeNewlines(text2), StringComparison.Ordinal)) { existing = text; return; } bool flag3 = ShouldPreserveOwnedDocument(text); if (ShouldPreserveOwnedDocument(text2) && !flag3) { existing = text2; } else { existing = text; } conflictBackupPath = alternatePath + ".dismantleheim-conflict.bak"; } public static int CountNamedToolsInDocument(string yaml, string toolName) { if (string.IsNullOrEmpty(yaml)) { return 0; } int num = 0; Regex regex = new Regex("^\\s*-\\s*name:\\s*(?:\"|')?" + Regex.Escape(toolName) + "(?:\"|')?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline); foreach (Match item in regex.Matches(yaml)) { num++; } return num; } public static bool OwnedEntryHasActivateCommand(string yaml) { if (!OwnedEntryHasCommand(yaml, "Dismantleheim - Mass Dismantle", "dismantleheim mode dismantle")) { return OwnedEntryHasCommand(yaml, "Dismantleheim - Mass Delete", "dismantleheim mode delete"); } return true; } public static bool OwnedEntryHasCommand(string yaml, string toolName, string command) { if (string.IsNullOrEmpty(yaml)) { return false; } string[] array = NormalizeNewlines(yaml).Split('\n'); bool flag = false; Regex regex = new Regex("^\\s*-\\s*name:\\s*(?:\"|')?" + Regex.Escape(toolName) + "(?:\"|')?\\s*$", RegexOptions.IgnoreCase); Regex regex2 = new Regex("^\\s*-\\s*name:\\s*\\S"); string[] array2 = array; foreach (string text in array2) { string text2 = text.TrimEnd('\r'); if (regex.IsMatch(text2)) { flag = true; continue; } if (flag && regex2.IsMatch(text2)) { flag = false; } if (flag && text2.IndexOf("command:", StringComparison.OrdinalIgnoreCase) >= 0 && text2.IndexOf(command, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } public static bool LooksLikeEquipmentDictionary(string yaml) { if (string.IsNullOrEmpty(yaml)) { return false; } return Regex.IsMatch(NormalizeNewlines(yaml), "(?m)^[A-Za-z][A-Za-z0-9_]*:\\s*$", RegexOptions.None); } public static string RemoveNamedToolFromShared(string yaml, string toolName) { if (string.IsNullOrEmpty(yaml)) { return string.Empty; } string[] array = NormalizeNewlines(yaml).Split('\n'); List<string> list = new List<string>(); bool flag = false; Regex regex = new Regex("^\\s*-\\s*name:\\s*(?:\"|')?" + Regex.Escape(toolName) + "(?:\"|')?\\s*$", RegexOptions.IgnoreCase); Regex regex2 = new Regex("^\\s*-\\s*name:\\s*\\S"); Regex regex3 = new Regex("^[A-Za-z][A-Za-z0-9_]*:\\s*$"); for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd('\r'); if (regex.IsMatch(text)) { if (!BlockLooksOwned(array, i)) { list.Add(text); continue; } flag = true; if (list.Count > 0 && list[list.Count - 1].IndexOf("dismantleheim-tool", StringComparison.OrdinalIgnoreCase) >= 0) { list.RemoveAt(list.Count - 1); } continue; } if (flag) { if (!regex2.IsMatch(text) && !regex3.IsMatch(text)) { continue; } flag = false; } list.Add(text); } return string.Join(Environment.NewLine, list).TrimEnd() + Environment.NewLine; } private static bool BlockLooksOwned(string[] lines, int nameLineIndex) { int num = nameLineIndex - 1; while (num >= 0 && num >= nameLineIndex - 3) { if (lines[num].IndexOf("dismantleheim-tool", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } num--; } Regex regex = new Regex("^\\s*-\\s*name:\\s*\\S"); Regex regex2 = new Regex("^[A-Za-z][A-Za-z0-9_]*:\\s*$"); for (int i = nameLineIndex + 1; i < lines.Length; i++) { string text = lines[i].TrimEnd('\r'); if (regex.IsMatch(text) || regex2.IsMatch(text)) { break; } if (text.IndexOf("command:", StringComparison.OrdinalIgnoreCase) >= 0 && (text.IndexOf("dismantleheim mode dismantle", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("dismantleheim mode delete", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("dismantleheim activate", StringComparison.OrdinalIgnoreCase) >= 0)) { return true; } } return false; } private static void TryRemoveStaleFromSharedDefault(string configRoot) { string[] array = new string[3] { "Dismantleheim - Mass Dismantle", "Dismantleheim - Mass Delete", "Dismantleheim" }; string[] array2 = new string[2] { Path.Combine(configRoot, "infinity_tools.yaml"), Path.Combine(configRoot, "tools", "infinity_tools.yaml") }; foreach (string path in array2) { if (!File.Exists(path)) { continue; } string text = File.ReadAllText(path, Encoding.UTF8); string text2 = text; string[] array3 = array; foreach (string toolName in array3) { if (CountNamedToolsInDocument(text2, toolName) > 0) { text2 = RemoveNamedToolFromShared(text2, toolName); } } if (!string.Equals(NormalizeNewlines(text), NormalizeNewlines(text2), StringComparison.Ordinal)) { AtomicWrite(path, text2); } } } private static void AtomicWrite(string path, string contents) { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } string text = path + ".tmp"; File.WriteAllText(text, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); if (File.Exists(path)) { File.Replace(text, path, null); } else { File.Move(text, path); } } private static string NormalizeNewlines(string s) { return (s ?? string.Empty).Replace("\r\n", "\n").Replace('\r', '\n'); } } } namespace Dismantleheim.UI { internal static class ConfirmationRing { private static GUIStyle _bannerStyle; private static GUIStyle _subStyle; private static Texture2D _panelTex; public static void Tick(DismantleSession session) { } public static void DrawGui(DismantleSession session) { //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_0302: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) if (session == null || !session.IsActive) { return; } EnsureStyles(); bool flag = DismantleheimPlugin.ShowActiveMode == null || DismantleheimPlugin.ShowActiveMode.Value; bool flag2 = DismantleheimPlugin.ShowSelectedCount == null || DismantleheimPlugin.ShowSelectedCount.Value; if (flag || flag2) { string text = (flag ? OperationModeUtil.Banner(session.ActiveMode) : string.Empty); string text2 = string.Empty; if (flag2) { text2 = session.Queue.Count + " selected"; if (session.Sampler.HasFilter) { text2 = text2 + " [" + session.Sampler.ActiveFilter + "]"; } if (DismantleheimPlugin.DryRunOnly != null && DismantleheimPlugin.DryRunOnly.Value) { text2 += " (dry-run)"; } } float num = 520f; float num2 = ((flag && flag2) ? 54f : 32f); if (session.HasContentsLossWarning) { num2 += 22f; } Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, 18f, num, num2); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.72f); GUI.DrawTexture(val, (Texture)(object)_panelTex); GUI.color = color; float num3 = ((Rect)(ref val)).y + 6f; if (flag) { _bannerStyle.normal.textColor = ((session.ActiveMode == OperationMode.MassDelete) ? new Color(1f, 0.45f, 0.35f, 1f) : new Color(0.85f, 0.95f, 0.55f, 1f)); GUI.Label(new Rect(((Rect)(ref val)).x, num3, ((Rect)(ref val)).width, 26f), text, _bannerStyle); num3 += 24f; } if (flag2) { _subStyle.normal.textColor = new Color(1f, 0.95f, 0.4f, 1f); GUI.Label(new Rect(((Rect)(ref val)).x, num3, ((Rect)(ref val)).width, 22f), text2, _subStyle); num3 += 20f; } if (session.HasContentsLossWarning) { _subStyle.normal.textColor = new Color(1f, 0.35f, 0.2f, 1f); GUI.Label(new Rect(((Rect)(ref val)).x, num3, ((Rect)(ref val)).width, 22f), "WARNING: queued containers hold items", _subStyle); } } if ((DismantleheimPlugin.ShowRing == null || DismantleheimPlugin.ShowRing.Value) && (session.ConfirmHold.IsHolding || !(session.ConfirmHold.Progress <= 0f))) { float progress = session.ConfirmHold.Progress; Vector2 val2 = Vector2.op_Implicit(Input.mousePosition); val2.y = (float)Screen.height - val2.y; DrawArc(val2, 22f, progress, session.ActiveMode); } } private static void EnsureStyles() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown if ((Object)(object)_panelTex == (Object)null) { _panelTex = Texture2D.whiteTexture; } if (_bannerStyle == null) { _bannerStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)1, fontSize = 18, fontStyle = (FontStyle)1, wordWrap = false }; } if (_subStyle == null) { _subStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)1, fontSize = 14, fontStyle = (FontStyle)1, wordWrap = false }; } } private static void DrawArc(Vector2 center, float radius, float progress, OperationMode mode) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) progress = Mathf.Clamp01(progress); Texture2D whiteTexture = Texture2D.whiteTexture; Color color = default(Color); ((Color)(ref color))..ctor(0f, 0f, 0f, 0.55f); Color color2 = ((mode == OperationMode.MassDelete) ? new Color(1f, 0.4f, 0.25f, 0.95f) : new Color(1f, 0.75f, 0.2f, 0.95f)); for (int i = 0; i < 48; i++) { float a = (float)i / 48f * MathF.PI * 2f - MathF.PI / 2f; float a2 = (float)(i + 1) / 48f * MathF.PI * 2f - MathF.PI / 2f; DrawSegment(center, radius, a, a2, color, whiteTexture); } int num = Mathf.CeilToInt(48f * progress); for (int j = 0; j < num; j++) { float a3 = (float)j / 48f * MathF.PI * 2f - MathF.PI / 2f; float a4 = (float)(j + 1) / 48f * MathF.PI * 2f - MathF.PI / 2f; DrawSegment(center, radius, a3, a4, color2, whiteTexture); } } private static void DrawSegment(Vector2 center, float radius, float a0, float a1, Color color, Texture2D tex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_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_003b: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) Vector2 a2 = center + new Vector2(Mathf.Cos(a0), Mathf.Sin(a0)) * radius; Vector2 b = center + new Vector2(Mathf.Cos(a1), Mathf.Sin(a1)) * radius; DrawLine(a2, b, color, tex, 3f); } private static void DrawLine(Vector2 a, Vector2 b, Color color, Texture2D tex, float width) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) Vector2 val = b - a; float magnitude = ((Vector2)(ref val)).magnitude; if (!(magnitude < 0.01f)) { float num = Mathf.Atan2(val.y, val.x) * 57.29578f; GUI.color = color; Matrix4x4 matrix = GUI.matrix; GUIUtility.RotateAroundPivot(num, a); GUI.DrawTexture(new Rect(a.x, a.y - width * 0.5f, magnitude, width), (Texture)(object)tex); GUI.matrix = matrix; GUI.color = Color.white; } } } internal static class HoverHighlighter { private static readonly Color SelectedColor = new Color(1f, 0.35f, 0.15f, 1f); private static readonly Color HoverColor = new Color(0.35f, 0.85f, 1f, 1f); private static readonly HashSet<int> _activeTintIds = new HashSet<int>(); private static readonly HashSet<int> _frameTintIds = new HashSet<int>(); private static readonly Dictionary<int, GameObject> _tintRoots = new Dictionary<int, GameObject>(); public static void Tick(DismantleSession session) { //IL_0036: 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) if (session == null || !session.IsActive) { ClearAll(); return; } _frameTintIds.Clear(); foreach (TargetIdentity entry in session.Queue.Entries) { Apply(entry, SelectedColor); } TargetIdentity hoverTarget = session.HoverTarget; if (hoverTarget != null && Eligibility.IsEligible(hoverTarget, session.ActiveMode, session.Sampler.ActiveFilter, session.AllowEnvWithFilter, session.ExtraDeny(), session.ExtraAllow(), out var _) && !session.Queue.Contains(hoverTarget)) { Apply(hoverTarget, HoverColor); } if (_activeTintIds.Count > 0) { List<int> list = null; foreach (int activeTintId in _activeTintIds) { if (!_frameTintIds.Contains(activeTintId)) { if (list == null) { list = new List<int>(); } list.Add(activeTintId); } } if (list != null) { foreach (int item in list) { ResetTracked(item); } } } _activeTintIds.Clear(); foreach (int frameTintId in _frameTintIds) { _activeTintIds.Add(frameTintId); } } public static void ClearAll() { if (_activeTintIds.Count == 0 && _tintRoots.Count == 0) { return; } List<int> list = new List<int>(_activeTintIds); foreach (int item in list) { ResetTracked(item); } _activeTintIds.Clear(); _frameTintIds.Clear(); _tintRoots.Clear(); } private static void Apply(TargetIdentity id, Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (id == null) { return; } GameObject val = ExactObjectExecutor.ResolveInstance(id); if ((Object)val == (Object)null) { return; } WearNTear val2 = val.GetComponent<WearNTear>(); if ((Object)val2 == (Object)null) { val2 = val.GetComponentInChildren<WearNTear>(); } if ((Object)val2 != (Object)null) { val2.Highlight(); ApplyMaterialTint(((Component)val2).gameObject, color); try { ((MonoBehaviour)val2).CancelInvoke("ResetHighlight"); ((MonoBehaviour)val2).Invoke("ResetHighlight", 0.35f); return; } catch { return; } } ApplyMaterialTint(val, color); } private static void ApplyMaterialTint(GameObject go, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) if ((Object)go == (Object)null) { return; } try { MaterialMan instance = MaterialMan.instance; if (!((Object)instance == (Object)null)) { instance.SetValue<Color>(go, ShaderProps._EmissionColor, color * 0.55f, false); instance.SetValue<Color>(go, ShaderProps._Color, color, false); int instanceID = ((Object)go).GetInstanceID(); _frameTintIds.Add(instanceID); _tintRoots[instanceID] = go; } } catch { } } private static void ResetTracked(int instanceId) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if (!_tintRoots.TryGetValue(instanceId, out var value)) { _activeTintIds.Remove(instanceId); return; } _tintRoots.Remove(instanceId); _activeTintIds.Remove(instanceId); if ((Object)value == (Object)null) { return; } try { MaterialMan instance = MaterialMan.instance; if (!((Object)instance == (Object)null)) { instance.ResetValue(value, ShaderProps._Color); instance.ResetValue(value, ShaderProps._EmissionColor); } } catch { } } } } namespace Dismantleheim.Selection { internal sealed class DismantleSession { private List<TargetIdentity> _confirmSnapshot; public SelectionQueue Queue { get; } = new SelectionQueue(); public PrefabSampler Sampler { get; } = new PrefabSampler(); public DismantleStateMachine StateMachine { get; } = new DismantleStateMachine(); public ConfirmationHold ConfirmHold { get; } = new ConfirmationHold(); public TargetIdentity HoverTarget { get; set; } public string LastRejectReason { get; set; } public int IgnorePieceChangeFrames { get; set; } public OperationMode ActiveMode { get; private set; } public bool HasContentsLossWarning { get; private set; } public bool IsActive => StateMachine.State != DismantleState.Inactive; public bool AllowEnvWithFilter { get { if (DismantleheimPlugin.AllowEnvironmentWithFilter != null) { return DismantleheimPlugin.AllowEnvironmentWithFilter.Value; } return true; } } public int MaximumTargets { get { if (DismantleheimPlugin.MaximumTargets == null) { return 50; } return DismantleheimPlugin.MaximumTargets.Value; } } public bool TryActivate(string source, out string reject) { return TryActivate(ActiveMode, source, out reject); } public bool TryActivate(OperationMode mode, string source, out string reject) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown reject = null; ActiveMode = mode; if (StateMachine.State != DismantleState.Inactive) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer == (Object)null) { reject = "no-player"; return false; } if (!((Character)localPlayer).InPlaceMode()) { reject = "not-in-place-mode"; ManualLogSource modLogger = DismantleheimPlugin.ModLogger; if (modLogger != null) { modLogger.LogInfo((object)("Dismantleheim activate rejected: " + reject)); } return false; } StateMachine.TryTransition(DismantleTransition.Activate, Queue.Count, out var _); IgnorePieceChangeFrames = 180; ToolIdentityTracker.OnActivated(); ContextualInputRouter.ResetLatches(); DragBoxSelector.Cancel(); RefreshContentsWarning(); Player localPlayer2 = Player.m_localPlayer; bool flag = (Object)localPlayer2 != (Object)null && ((Character)localPlayer2).InPlaceMode(); string text = (((Object)localPlayer2 != (Object)null && ((Humanoid)localPlayer2).RightItem != null) ? (((((Humanoid)localPlayer2).RightItem.m_shared != null) ? ((Humanoid)localPlayer2).RightItem.m_shared.m_name : "?") + "|" + (((Object)(object)((Humanoid)localPlayer2).RightItem.m_dropPrefab != (Object)null) ? ((Object)((Humanoid)localPlayer2).RightItem.m_dropPrefab).name : "?")) : "empty"); ManualLogSource modLogger2 = DismantleheimPlugin.ModLogger; if (modLogger2 != null) { modLogger2.LogInfo((object)("Dismantleheim activate via " + source + " mode=" + OperationModeUtil.ShortName(ActiveMode) + " state=" + StateMachine.State.ToString() + " place=" + flag + " item=" + text + " grace=" + IgnorePieceChangeFrames)); } if ((Object)localPlayer2 != (Object)null) { ((Character)localPlayer2).Message((MessageType)1, OperationModeUtil.Banner(ActiveMode), 0, (Sprite)null, false); } return true; } public void Activate(string source) { TryActivate(source, out var _); } public void SetMode(OperationMode mode, string source) { if (ActiveMode == mode && IsActive) { return; } ConfirmHold.Cancel(); ClearConfirmSnapshot(); bool flag = DismantleheimPlugin.PreserveSelectionOnModeSwitch == null || DismantleheimPlugin.PreserveSelectionOnModeSwitch.Value; OperationMode activeMode = ActiveMode; ActiveMode = mode; if (!IsActive) { TryActivate(mode, source, out var _); return; } if (!flag) { Queue.Clear(); } RefreshContentsWarning(); SyncStateAfterSelectionChange(); ManualLogSource modLogger = DismantleheimPlugin.ModLogger; if (modLogger != null) { modLogger.LogInfo((object)("Dismantleheim mode " + OperationModeUtil.ShortName(activeMode) + " → " + OperationModeUtil.ShortName(mode) + " via " + source + " queue=" + Queue.Count)); } } public void Deactivate(string source) { int count = Queue.Count; DismantleState state = StateMachine.State; ConfirmHold.Cancel(); ConfirmHold.Rearm(); ClearConfirmSnapshot(); if (DismantleheimPlugin.ClearQueueOnToolSwitch == null || DismantleheimPlugin.ClearQueueOnToolSwitch.Value) { Queue.Clear(); } HoverTarget = null; HasContentsLossWarning = false; StateMachine.ForceInactive(); ToolIdentityTracker.OnDeactivated(); ContextualInputRouter.ResetLatches(); HoverHighlighter.ClearAll(); ManualLogSource modLogger = DismantleheimPlugin.ModLogger; if (modLogger != null) { modLogger.LogInfo((object)("Dismantleheim deactivate via " + source + " queue=" + count + " wasState=" + state.ToString() + " mode=" + OperationModeUtil.ShortName(ActiveMode))); } } public void ResetHard(string source) { Queue.Clear(); Sampler.Clear(); ConfirmHold.Cancel(); ConfirmHold.Rearm(); ClearConfirmSnapshot(); HoverTarget = null; HasContentsLossWarning = false; StateMachine.ForceInactive(); ToolIdentityTracker.OnDeactivated(); ContextualInputRouter.ResetLatches(); HoverHighlighter.ClearAll(); ManualLogSource modLogger = DismantleheimPlugin.ModLogger; if (modLogger != null) { modLogger.LogInfo((object)("Dismantleheim hard-reset via " + source)); } } public void ToggleActivate(string source) { if (IsActive) { Deactivate(source); return; } OperationMode defaultMode = DismantleheimPlugin.GetDefaultMode(); TryActivate(defaultMode, source, out var _); } public void SyncStateAfterSelectionChange() { RefreshContentsWarning(); if (IsActive) { StateMachine.TryTransition(DismantleTransition.SelectionChanged, Queue.Count, out var _); } } public void BeginConfirmSnapshot() { _confirmSnapshot = new List<TargetIdentity>(Queue.Snapshot()); } public void ClearConfirmSnapshot() { _confirmSnapshot = null; } public ISet<string> ExtraDeny() { return Eligibility.ParsePrefabList((DismantleheimPlugin.ExtraDenyPrefabs != null) ? DismantleheimPlugin.ExtraDenyPrefabs.Value : string.Empty); } public ISet<string> ExtraAllow() { return Eligibility.ParsePrefabList((DismantleheimPlugin.ExtraAllowPrefabs != null) ? DismantleheimPlugin.ExtraAllowPrefabs.Value : string.Empty); } public void RefreshContentsWarning() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown HasContentsLossWarning = false; if (ActiveMode != OperationMode.MassDelete || (DismantleheimPlugin.WarnWhenDeletingOccupiedContainers != null && !DismantleheimPlugin.WarnWhenDeletingOccupiedContainers.Value)) { return; } foreach (TargetIdentity entry in Queue.Entries) { GameObject val = ExactObjectExecutor.ResolveInstance(entry); if ((Object)val != (Object)null && ContainerContentsInspector.HasStoredItems(val, out var _)) { HasContentsLossWarning = true; break; } } } public void CommitDryOrReal() { DismantleState newState; try { if (!StateMachine.TryTransition(DismantleTransition.HoldComplete, Queue.Count, out newState)) { return; } IReadOnlyList<TargetIdentity> readOnlyList; if (_confirmSnapshot == null) { readOnlyList = Queue.Snapshot(); } else { IReadOnlyList<TargetIdentity> confirmSnapshot = _confirmSnapshot; readOnlyList = confirmSnapshot; } IReadOnlyList<TargetIdentity> queued = readOnlyList; List<TargetIdentity> missing; List<RemovalPlanEntry> list = PreflightBatchValidator.BuildPlan(ActiveMode, queued, AllowEnvWithFilter, ExtraDeny(), ExtraAllow(), out missing); StateMachine.TryTransition(DismantleTransition.ValidationDone, list.Count, out newState); List<RemovalResult> list2 = ExactObjectExecutor.Execute(ActiveMode, list); ExecutionResultReporter.LogAll(list2); string text = ExecutionResultReporter.Summarize(list2, ActiveMode); ManualLogSource modLogger = DismantleheimPlugin.ModLogger; if (modLogger != null) { modLogger.LogInfo((object)text); } if ((Object)(object)Console.instance != (Object)null) { Console.instance.Print("Dismantleheim " + text); } if (DismantleheimPlugin.DryRunOnly == null || !DismantleheimPlugin.DryRunOnly.Value) { foreach (RemovalResult item in list2) { if (item.Removed && item.Target != null && Queue.Contains(item.Target)) { Queue.Toggle(item.Target); } } } RefreshContentsWarning(); } catch (Exception ex) { ManualLogSource modLogger2 = DismantleheimPlugin.ModLogger; if (modLogger2 != null) { modLogger2.LogError((object)("Commit failed: " + ex)); } } finally { ClearConfirmSnapshot(); ConfirmHold.Cancel(); StateMachine.TryTransition(DismantleTransition.ExecutionDone, Queue.Count, out newState); if (StateMachine.State == DismantleState.Executing || StateMachine.State == DismantleState.Validating) { StateMachine.ForceInactive(); TryActivate(ActiveMode, "post-commit", out var _); SyncStateAfterSelectionChange(); } else if (IsActive) { IgnorePieceChangeFrames = Math.Max(IgnorePieceChangeFrames, 45); ToolIdentityTracker.RefreshBaseline("post-commit"); SyncStateAfterSelectionChange(); } ManualLogSource modLogger3 = DismantleheimPlugin.ModLogger; if (modLogger3 != null) { modLogger3.LogInfo((object)("Dismantleheim post-commit state=" + StateMachine.State.ToString() + " active=" + IsActive + " queue=" + Queue.Count + " grace=" + IgnorePieceChangeFrames)); } } } } internal static class DragBoxSelector { private const float CtrlReleaseGraceSeconds = 0.18f; private static bool _ctrlActive; private static bool _paintedAny; private static TargetIdentity _lastPainted; private static TargetIdentity _ctrlClickCandidate; private static float _ctrlReleasedAt = -999f; public static bool IsDragging => _ctrlActive; public static bool BlocksConfirm => _ctrlActive; public static bool ConsumeClickSuppression() { return false; } public static void Cancel() { _ctrlActive = false; _paintedAny = false; _lastPainted = null; _ctrlClickCandidate = null; _ctrlReleasedAt = -999f; } public static void Tick(DismantleSession session) { if (session == null || !session.IsActive) { Cancel(); return; } bool flag = IsCtrlHeld(); if (flag) { _ctrlReleasedAt = -999f; _ctrlActive = true; } else if (_ctrlActive) { if (_ctrlReleasedAt < 0f) { _ctrlReleasedAt = Time.unscaledTime; } if (Time.unscaledTime - _ctrlReleasedAt < 0.18f) { flag = true; } else { _ctrlActive = false; _lastPainted = null; _ctrlClickCandidate = null; _ctrlReleasedAt = -999f; } } if (_ctrlActive && flag) { TickCtrlPaint(session); } } public static void DrawGui() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (_ctrlActive) { GUI.Label(new Rect(16f, 16f, 420f, 22f), "Ctrl: mass-select (wave / drag aim)"); } } private static void TickCtrlPaint(DismantleSession session) { bool down = MouseButtons.GetDown(0); bool up = MouseButtons.GetUp(0); if (down) { _paintedAny = false; _ctrlClickCandidate = ResolveAimTarget(session); if (_ctrlClickCandidate != null && session.Queue.Contains(_ctrlClickCandidate)) { _lastPainted = _ctrlClickCandidate; } else { _lastPainted = null; } } PaintCurrentAim(session, remove: false); if (!up) { return; } if (!_paintedAny && _ctrlClickCandidate != null) { if (session.Queue.TryRemove(_ctrlClickCandidate)) { session.SyncStateAfterSelectionChange(); Log("Unqueued " + _ctrlClickCandidate.PrefabName + " (" + session.Queue.Count + " selected)"); } _lastPainted = _ctrlClickCandidate; } _ctrlClickCandidate = null; } private static TargetIdentity ResolveAimTarget(DismantleSession session) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer != (Object)null && TargetResolver.TryResolveAim(localPlayer, out var identity, out var _)) { session.HoverTarget = identity; return identity; } return session.HoverTarget; } private static void PaintCurrentAim(DismantleSession session, bool remove) { TargetIdentity targetIdentity = ResolveAimTarget(session); if (targetIdentity == null) { _lastPainted = null; } else if (_lastPainted == null || !_lastPainted.Equals(targetIdentity)) { if (ApplyPaint(session, targetIdentity, remove)) { _paintedAny = true; _lastPainted = targetIdentity; } else if (!remove && session.Queue.Contains(targetIdentity)) { _lastPainted = targetIdentity; } else if (remove && !session.Queue.Contains(targetIdentity)) { _lastPainted = targetIdentity; } } } private static bool ApplyPaint(DismantleSession session, TargetIdentity target, bool remove) { if (target == null) { return false; } if (remove) { if (!session.Queue.TryRemove(target)) { return false; } session.SyncStateAfterSelectionChange(); Log("Unqueued " + target.PrefabName + " (" + session.Queue.Count + " selected)"); return true; } if (!Eligibility.IsEligible(target, session.ActiveMode, session.Sampler.ActiveFilter, session.AllowEnvWithFilter, session.ExtraDeny(), session.ExtraAllow(), out var _)) { return false; } if (!session.Queue.TryAdd(target, session.MaximumTargets)) { return false; } session.SyncStateAfterSelectionChange(); Log("Queued " + target.PrefabName + " (" + session.Queue.Count + " selected)"); return true; } private static void Log(string msg) { ManualLogSource modLogger = DismantleheimPlugin.ModLogger; if (modLogger != null) { modLogger.LogInfo((object)("Dismantleheim " + msg)); } } private static bool IsCtrlHeld() { if (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305) && !Input.GetKey((KeyCode)310)) { return Input.GetKey((KeyCode)309); } return true; } } internal static class MouseButtons { public static bool Get(int button) { try { if (ZInput.GetMouseButton(button)) { return true; } } catch { } return Input.GetMouseButton(button); } public static bool GetDown(int button) { try { if (ZInput.GetMouseButtonDown(button)) { return true; } } catch { } return Input.GetMouseButtonDown(button); } public static bool GetUp(int button) { try { if (ZInput.GetMouseButtonUp(button)) { return true; } } catch { } return Input.GetMouseButtonUp(button); } } internal static class TargetResolver { private static readonly FieldInfo RemoveRayMaskField = AccessTools.Field(typeof(Player), "m_removeRayMask"); private static readonly FieldInfo MaxPlaceDistanceField = AccessTools.Field(typeof(Player), "m_maxPlaceDistance"); public static string CurrentWorldSessionKey() { if ((Object)(object)ZNet.instance == (Object)null) { return "local-offline"; } long worldUID = ZNet.instance.GetWorldUID(); long uID = ZNet.GetUID(); return "uid:" + worldUID + "|peer:" + uID; } public static bool TryResolveHover(Player player, out TargetIdentity identity, out string rejectDetail) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown identity = null; rejectDetail = null; if ((Object)player == (Object)null) { rejectDetail = "no-player"; return false; } GameObject val = null; if (((Character)player).InPlaceMode()) { Piece hoveringPiece = player.GetHoveringPiece(); if ((Object)hoveringPiece != (Object)null) { val = ((Component)hoveringPiece).gameObject; } } if ((Object)val == (Object)null) { val = ((Humanoid)player).GetHoverObject(); } if ((Object)val != (Object)null && !Player.IsPlacementGhost(val) && TryResolveObject(val, out identity, out rejectDetail) && identity != null && identity.Kind != TargetKind.Unsupported) { return true; } return TryResolveAim(player, out identity, out rejectDetail); } public static bool TryResolveAim(Player player, out TargetIdentity identity, out string rejectDetail) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_008a: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) identity = null; rejectDetail = null; if ((Object)player == (Object)null) { rejectDetail = "no-player"; return false; } if ((Object)GameCamera.instance == (Object)null) { rejectDetail = "no-camera"; return false; } Transform transform = ((Component)GameCamera.instance).transform; int num = ((RemoveRayMaskField != null) ? ((int)RemoveRayMaskField.GetValue(player)) : 0); float num2 = ((MaxPlaceDistanceField != null) ? ((float)MaxPlaceDistanceField.GetValue(player)) : 5f); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, num)) { rejectDetail = "aim-miss"; return false; } if ((Object)((Character)player).m_eye != (Object)null) { float num3 = Vector3.Distance(((Character)player).m_eye.position, ((RaycastHit)(ref val)).point); if (num3 >= num2) { rejectDetail = "aim-range"; return false; } } GameObject val2 = ResolveRootFromCollider(((RaycastHit)(ref val)).collider); if ((Object)val2 == (Object)null) { rejectDetail = "aim-no-target"; return false; } if (Player.IsPlacementGhost(val2)) { rejectDetail = "placement-ghost"; return false; } return TryResolveObject(val2, out identity, out rejectDetail); } private static GameObject ResolveRootFromCollider(Collider col) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown if ((Object)col == (Object)null) { return null; } ZNetView componentInParent = ((Component)col).GetComponentInParent<ZNetView>(); if ((Object)componentInParent != (Object)null && componentInParent.IsValid()) { return ((Component)componentInParent).gameObject; } Piece componentInParent2 = ((Component)col).GetComponentInParent<Piece>(); if ((Object)componentInParent2 != (Object)null) { return ((Component)componentInParent2).gameObject; } TreeBase componentInParent3 = ((Component)col).GetComponentInParent<TreeBase>(); if ((Object)componentInParent3 != (Object)null) { return ((Component)componentInParent3).gameObject; } TreeLog componentInParent4 = ((Component)col).GetComponentInParent<TreeLog>(); if ((Object)componentInParent4 != (Object)null) { return ((Component)componentInParent4).gameObject; } MineRock componentInParent5 = ((Component)col).GetComponentInParent<MineRock>(); if ((Object)componentInParent5 != (Object)null) { return ((Component)componentInParent5).gameObject; } MineRock5 componentInParent6 = ((Component)col).GetComponentInParent<MineRock5>(); if ((Object)componentInParent6 != (Object)null) { return ((Component)componentInParent6).gameObject; } return null; } public static bool TryResolveObject(GameObject go, out TargetIdentity identity, out string rejectDetail) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) identity = null; rejectDetail = null; if ((Object)go == (Object)null) { rejectDetail = "null"; return false; } ZNetView componentInParent = go.GetComponentInParent<ZNetView>(); if ((Object)componentInParent == (Object)null || !componentInParent.IsValid()) { rejectDetail = "no-znetview"; return false; } GameObject gameObject = ((Component)componentInParent).gameObject; Piece val = gameObject.GetComponent<Piece>(); if ((Object)val == (Object)null) { val = gameObject.GetComponentInChildren<Piece>(); } bool flag = (Object)val != (Object)null; bool canBeRemoved = flag && val.m_canBeRemoved; bool flag2 = IsEnvironmentRoot(gameObject); WearNTear val2 = gameObject.GetComponent<WearNTear>(); if ((Object)val2 == (Object)null) { val2 = gameObject.GetComponentInChildren<WearNTear>(); } bool hasScopePreview = (Object)val2 != (Object)null || flag2; TargetKind kind = Eligibility.Classify(flag, canBeRemoved, flag2, hasScopePreview); if (!flag && !flag2) { kind = TargetKind.Unsupported; } string text = NormalizePrefabName(((Object)gameObject).name ?? string.Empty); if (!flag2 && LooksLikeEnvironmentPrefab(text)) { flag2 = true; hasScopePreview = true; kind = TargetKind.Environment; } string worldSessionKey = CurrentWorldSessionKey(); long userId = 0L; uint objectId = 0u; ZDO zDO = componentInParent.GetZDO(); if (zDO != null) { ZDOID uid = zDO.m_uid; userId = ((ZDOID)(ref uid)).UserID; objectId = ((ZDOID)(ref uid)).ID; } identity = new TargetIdentity(userId, objectId, worldSessionKey, text, flag, canBeRemoved, flag2, kind, hasScopePreview); return true; } public static bool TryRevalidate(TargetIdentity queued, out TargetIdentity live, out string detail) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown live = null; detail = null; if (queued == null) { detail = "null"; return false; } if (!string.Equals(queued.WorldSessionKey, CurrentWorldSessionKey(), StringComparison.Ordinal)) { detail = "session-mismatch"; return false; } GameObject val = ExactObjectExecutor.ResolveInstance(queued); if ((Object)val == (Object)null) { detail = "missing-instance"; return false; } if (!TryResolveObject(val, out live, out detail)) { return false; } if (!string.Equals(live.PrefabName, queued.PrefabName, StringComparison.OrdinalIgnoreCase)) { detail = "prefab-mismatch"; live = null; return false; } if (live.Kind != queued.Kind) { detail = "kind-mismatch"; live = null; return false; } if (!live.HasScopePreview && live.Kind != TargetKind.Environment) { detail = "no-scope-preview"; live = null; return false; } return true; } public static bool IsEnvironmentRoot(GameObject root) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown if ((Object)root == (Object)null) { return false; } if ((Object)root.GetComponentInChildren<TreeBase>(true) != (Object)null) { return true; } if ((Object)root.GetComponentInChildren<TreeLog>(true) != (Object)null) { return true; } if ((Object)root.GetComponentInChildren<MineRock>(true) != (Object)null) { return true; } if ((Object)root.GetComponentInChildren<MineRock5>(true) != (Object)null) { return true; } if ((Object)root.GetComponentInChildren<Destructible>(true) != (Object)null) { return true; } return LooksLikeEnvironmentPrefab(NormalizePrefabName(((Object)root).name ?? string.Empty)); } public static bool LooksLikeEnvironmentPrefab(string prefab) { if (string.IsNullOrEmpty(prefab)) { return false; } if (prefab.StartsWith("prop_", StringComparison.OrdinalIgnoreCase)) { return true; } if (prefab.StartsWith("Rock_", StringComparison.OrdinalIgnoreCase) || prefab.StartsWith("rock_", StringComparison.OrdinalIgnoreCase) || prefab.StartsWith("MineRock", StringComparison.OrdinalIgnoreCase) || prefab.StartsWith("stone_environment", StringComparison.OrdinalIgnoreCase) || prefab.StartsWith("Cliff", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } public static string StripClone(string prefab) { return NormalizePrefabName(prefab); } public static string NormalizePrefabName(string prefab) { if (string.IsNullOrEmpty(prefab)) { return string.Empty; } string text = prefab.Trim(); if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - "(Clone)".Length).TrimEnd(); } int num = text.LastIndexOf('('); int num2 = text.LastIndexOf(')'); if (num > 0 && num2 == text.Length - 1 && num2 > num + 1) { bool flag = true; for (int i = num + 1; i < num2; i++) { if (!char.IsDigit(text[i])) { flag = false; break; } } if (flag) { text = text.Substring(0, num).TrimEnd(); } } return text; } } } namespace Dismantleheim.Removal { internal static class AuthorizedExactDeletionAdapter { public static bool TryDelete(TargetIdentity target, out string error) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown error = string.Empty; GameObject val = ExactObjectExecutor.ResolveInstance(target); if ((Object)val == (Object)null) { error = "instance missing"; return false; } Vector3 position = val.transform.position; if (!PrivateArea.CheckAccess(position, 0f, true, false)) { error = "ward denied"; return false; } if ((Object)val.GetComponent<TeleportWorld>() != (Object)null) { error = "portal unprotected lifecycle"; return false; } if ((Object)val.GetComponent<PrivateArea>() != (Object)null) { error = "ward object"; return false; } Piece component = val.GetComponent<Piece>(); Player localPlayer = Player.m_localPlayer; if ((Object)component != (Object)null) { if (!component.m_canBeRemoved) { error = "m_canBeRemoved=false"; return false; } } else if (target.Kind != TargetKind.Environment && target.Kind != TargetK