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 Pull Toggle v1.0.0
PullToggle.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [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("PullToggle")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PullToggle")] [assembly: AssemblyTitle("PullToggle")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TheShack.PullToggle { [BepInPlugin("theshack.pulltoggle", "Pull Toggle", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [HarmonyPatch] private static class RegisterRpcPatch { private static IEnumerable<MethodBase> TargetMethods() { return Existing(AccessTools.Method(typeof(Container), "Awake", (Type[])null, (Type[])null), AccessTools.Method(typeof(Fireplace), "Awake", (Type[])null, (Type[])null), AccessTools.Method(typeof(Smelter), "Awake", (Type[])null, (Type[])null), AccessTools.Method(typeof(CookingStation), "Awake", (Type[])null, (Type[])null), AccessTools.Method(typeof(ShieldGenerator), "Start", (Type[])null, (Type[])null)); } private static void Postfix(object __instance) { Component val = (Component)((__instance is Component) ? __instance : null); if (val == null) { return; } ZNetView view = ViewOf(val); if ((Object)(object)view == (Object)null || view.GetZDO() == null || registered.TryGetValue(view, out var _)) { return; } registered.Add(view, Registered); view.Register<bool>("TheShack_PullToggle_Set", (Action<long, bool>)delegate(long sender, bool off) { if ((Object)(object)view != (Object)null && view.IsValid() && view.IsOwner()) { view.GetZDO().Set(OffKey, off); } }); } } [HarmonyPatch(typeof(Container), "GetHoverText")] private static class ChestHoverPatch { private static void Postfix(Container __instance, ref string __result) { if (active && !string.IsNullOrEmpty(__result) && IsChest(__instance)) { __result += HoverLine(IsOff((Component)(object)__instance)); } } } [HarmonyPatch] private static class MachineHoverPatch { private static IEnumerable<MethodBase> TargetMethods() { return Existing(AccessTools.Method(typeof(Fireplace), "GetHoverText", (Type[])null, (Type[])null), AccessTools.Method(typeof(CookingStation), "GetHoverText", (Type[])null, (Type[])null), AccessTools.Method(typeof(ShieldGenerator), "GetHoverText", (Type[])null, (Type[])null), AccessTools.Method(typeof(Smelter), "OnHoverAddFuel", (Type[])null, (Type[])null), AccessTools.Method(typeof(Smelter), "OnHoverAddOre", (Type[])null, (Type[])null)); } private static void Postfix(object __instance, ref string __result) { if (!active || string.IsNullOrEmpty(__result)) { return; } Component val = (Component)((__instance is Component) ? __instance : null); if (val != null) { Fireplace val2 = (Fireplace)(object)((val is Fireplace) ? val : null); if (val2 == null || !val2.m_infiniteFuel) { __result += HoverLine(IsOff(val)); } } } } [HarmonyPatch(typeof(InventoryGui), "Update")] private static class ChestButtonPatch { private static void Postfix(InventoryGui __instance) { Container c = currentContainer.Invoke(__instance); bool flag = active && InventoryGui.IsVisible() && IsChest(c); if (!((Object)(object)chestButton == (Object)null) || (flag && CreateChestButton(__instance))) { if (((Component)chestButton).gameObject.activeSelf != flag) { ((Component)chestButton).gameObject.SetActive(flag); } if (flag) { chestButtonText.text = "Pulling: " + (IsOff((Component)(object)c) ? "<color=#FF8A65>OFF</color>" : "<color=#8BE28B>ON</color>"); } } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Predicate<Container> <>9__25_0; public static UnityAction <>9__42_0; internal bool <DropSwitchedOffChests>b__25_0(Container c) { if ((Object)(object)c != (Object)null) { return IsOff((Component)(object)c); } return false; } internal void <CreateChestButton>b__42_0() { Container val = (((Object)(object)InventoryGui.instance == (Object)null) ? null : currentContainer.Invoke(InventoryGui.instance)); if (IsChest(val)) { Toggle((Component)(object)val); } } } public const string PluginGuid = "theshack.pulltoggle"; public const string PluginName = "Pull Toggle"; public const string PluginVersion = "1.0.0"; private const string OttoFuelGuid = "potto007.OttoFuel"; private const string CfcGuid = "aedenthorn.CraftFromContainers"; private const string RpcName = "TheShack_PullToggle_Set"; private static readonly int OffKey = StringExtensionMethods.GetStableHashCode("TheShack_PullOff"); private const string OnText = "<color=#8BE28B>ON</color>"; private const string OffText = "<color=#FF8A65>OFF</color>"; private static ManualLogSource log; private static Plugin instance; private static ConfigEntry<KeyboardShortcut> toggleKey; private static bool active; private static FieldInfo cfcLastPosition; private static readonly FieldRef<InventoryGui, Container> currentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer"); private static readonly Dictionary<Type, FieldInfo> nviewFields = new Dictionary<Type, FieldInfo>(); private static readonly ConditionalWeakTable<ZNetView, object> registered = new ConditionalWeakTable<ZNetView, object>(); private static readonly object Registered = new object(); private static Button chestButton; private static TMP_Text chestButtonText; private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) instance = this; log = ((BaseUnityPlugin)this).Logger; toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Toggle Key", new KeyboardShortcut((KeyCode)105, Array.Empty<KeyCode>()), "Switches resource pulling on or off for the chest or machine you are looking at, or the chest you have open."); Harmony harmony = new Harmony("theshack.pulltoggle"); bool flag = TryPatch("OttoFuel", () => PatchOttoFuel(harmony)); bool flag2 = TryPatch("CraftFromContainers", () => PatchCraftFromContainers(harmony)); active = flag || flag2; if (!active) { log.LogWarning((object)"neither OttoFuel nor CraftFromContainers is hooked; nothing to switch"); return; } try { harmony.PatchAll(typeof(Plugin).Assembly); } catch (Exception ex) { log.LogError((object)("could not apply the key, hover and chest-button hooks: " + ex)); } log.LogInfo((object)string.Format("ready (OttoFuel {0}, CraftFromContainers {1}), key {2}", flag ? "hooked" : "not found", flag2 ? "hooked" : "not found", toggleKey.Value)); } private static IEnumerable<MethodBase> Existing(params MethodBase[] methods) { foreach (MethodBase methodBase in methods) { if (methodBase != null) { yield return methodBase; } } } private static bool TryPatch(string mod, Func<bool> patch) { try { return patch(); } catch (Exception arg) { log.LogWarning((object)$"could not hook {mod}: {arg}"); return false; } } private static bool PatchOttoFuel(Harmony harmony) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown Type type = AccessTools.TypeByName("OttoFuel.TastyUtils"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetNearbyContainers", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null)); if (methodInfo == null) { return false; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "DropSwitchedOffChests", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); (string, string)[] array = new(string, string)[4] { ("OttoFuel.GameClasses.Fireplace_Patches", "RefuelTorch"), ("OttoFuel.GameClasses.Smelters", "RefuelSmelter"), ("OttoFuel.GameClasses.Oven_Patches", "RefuelOven"), ("OttoFuel.GameClasses.Sgenerator_Patches", "RefuelGen") }; for (int i = 0; i < array.Length; i++) { (string, string) tuple = array[i]; string item = tuple.Item1; string item2 = tuple.Item2; Type type2 = AccessTools.TypeByName(item); MethodInfo methodInfo2 = ((type2 == null) ? null : AccessTools.Method(type2, item2, (Type[])null, (Type[])null)); if (methodInfo2 == null) { log.LogWarning((object)("OttoFuel " + item + "." + item2 + " not found; those machines can't be switched off")); } else { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Plugin), "SkipSwitchedOffMachine", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } return true; } private static bool PatchCraftFromContainers(Harmony harmony) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown Type type = AccessTools.TypeByName("CraftFromContainers.BepInExPlugin"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetNearbyContainers", new Type[1] { typeof(Vector3) }, (Type[])null)); if (methodInfo == null) { return false; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "DropSwitchedOffChests", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); cfcLastPosition = AccessTools.Field(type, "lastPosition"); Type type2 = AccessTools.Inner(type, "CookingStation_FindCookableItem_Patch"); MethodInfo methodInfo2 = ((type2 == null) ? null : AccessTools.Method(type2, "Postfix", (Type[])null, (Type[])null)); if (methodInfo2 == null) { log.LogWarning((object)"CraftFromContainers' cooking-station pull not found; cooking stations can't be switched off for it"); } else { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Plugin), "SkipSwitchedOffMachine", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } return true; } private static void DropSwitchedOffChests(List<Container> __result) { __result?.RemoveAll((Container c) => (Object)(object)c != (Object)null && IsOff((Component)(object)c)); } private static bool SkipSwitchedOffMachine(object __0) { Component val = (Component)((__0 is Component) ? __0 : null); if (val != null && (Object)(object)val != (Object)null) { return !IsOff(val); } return true; } private static ZNetView ViewOf(Component c) { Type type = ((object)c).GetType(); if (!nviewFields.TryGetValue(type, out var value)) { value = AccessTools.Field(type, "m_nview"); nviewFields[type] = value; } object? obj = value?.GetValue(c); ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null); if (!((Object)(object)val != (Object)null)) { return c.GetComponentInParent<ZNetView>(); } return val; } private static bool IsOff(Component c) { ZNetView val = ViewOf(c); if ((Object)(object)val != (Object)null && val.IsValid()) { return val.GetZDO().GetBool(OffKey, false); } return false; } private static bool SetOff(Component target, bool off) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) ZNetView val = ViewOf(target); if ((Object)(object)val == (Object)null || !val.IsValid()) { return false; } ZDO zDO = val.GetZDO(); if (val.IsOwner()) { zDO.Set(OffKey, off); } else if (IsOnlinePlayer(zDO.GetOwner())) { val.InvokeRPC("TheShack_PullToggle_Set", new object[1] { off }); } else { val.ClaimOwnership(); zDO.Set(OffKey, off); } cfcLastPosition?.SetValue(null, Vector3.positiveInfinity); return true; } private static bool IsOnlinePlayer(long uid) { //IL_0026: 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_002c: 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_0032: Unknown result type (might be due to invalid IL or missing references) if (uid == 0L || (Object)(object)ZNet.instance == (Object)null) { return false; } foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (((ZDOID)(ref characterID)).UserID == uid) { return true; } } return false; } private static void Toggle(Component target) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (!PrivateArea.CheckAccess(target.transform.position, 0f, true, false)) { ((Character)localPlayer).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false); return; } bool flag = !IsOff(target); if (SetOff(target, flag)) { string text = Localization.instance.Localize(target.GetComponentInParent<Piece>()?.m_name ?? ""); ((Character)localPlayer).Message((MessageType)2, text + ((text.Length > 0) ? ": " : "") + "pulling " + (flag ? "<color=#FF8A65>OFF</color>" : "<color=#8BE28B>ON</color>"), 0, (Sprite)null, false); } } private static bool IsChest(Container c) { if ((Object)(object)c != (Object)null && ((Object)(object)((Component)c).GetComponentInParent<Piece>() != (Object)null || (Object)(object)c.m_wagon != (Object)null)) { return (Object)(object)((Component)c).GetComponentInParent<TombStone>() == (Object)null; } return false; } private static Component MachineAt(GameObject hover) { Smelter componentInParent = hover.GetComponentInParent<Smelter>(); if ((Object)(object)componentInParent != (Object)null) { return (Component)(object)componentInParent; } CookingStation componentInParent2 = hover.GetComponentInParent<CookingStation>(); if ((Object)(object)componentInParent2 != (Object)null) { return (Component)(object)componentInParent2; } ShieldGenerator componentInParent3 = hover.GetComponentInParent<ShieldGenerator>(); if ((Object)(object)componentInParent3 != (Object)null) { return (Component)(object)componentInParent3; } Fireplace componentInParent4 = hover.GetComponentInParent<Fireplace>(); if (!((Object)(object)componentInParent4 != (Object)null) || componentInParent4.m_infiniteFuel) { return null; } return (Component)(object)componentInParent4; } private static Component CurrentTarget() { if (InventoryGui.IsVisible()) { Container val = (((Object)(object)InventoryGui.instance == (Object)null) ? null : currentContainer.Invoke(InventoryGui.instance)); if (!IsChest(val)) { return null; } return (Component)(object)val; } GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); if ((Object)(object)hoverObject == (Object)null) { return null; } Container componentInParent = hoverObject.GetComponentInParent<Container>(); if ((Object)(object)componentInParent != (Object)null) { if (!IsChest(componentInParent)) { return null; } return (Component)(object)componentInParent; } return MachineAt(hoverObject); } private void Update() { //IL_0019: 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) if (!active || (Object)(object)Player.m_localPlayer == (Object)null) { return; } KeyboardShortcut value = toggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !IsTyping()) { Component val = CurrentTarget(); if ((Object)(object)val != (Object)null) { Toggle(val); } } } private static bool IsTyping() { if (((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.IsOpen()) { return true; } GameObject val = (((Object)(object)EventSystem.current == (Object)null) ? null : EventSystem.current.currentSelectedGameObject); if ((Object)(object)val != (Object)null) { return (Object)(object)val.GetComponent<TMP_InputField>() != (Object)null; } return false; } private static string HoverLine(bool off) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return string.Format("\n[<color=yellow><b>{0}</b></color>] Pulling: {1}", toggleKey.Value, off ? "<color=#FF8A65>OFF</color>" : "<color=#8BE28B>ON</color>"); } private static bool CreateChestButton(InventoryGui gui) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0112: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown if ((Object)(object)gui.m_takeAllButton == (Object)null || (Object)(object)gui.m_container == (Object)null) { return false; } GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, (Transform)(object)gui.m_container); ((Object)val).name = "TheShack_PullToggleButton"; UIGamePad[] componentsInChildren = val.GetComponentsInChildren<UIGamePad>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } Localize[] componentsInChildren2 = val.GetComponentsInChildren<Localize>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.Destroy((Object)(object)componentsInChildren2[i]); } chestButton = val.GetComponent<Button>(); chestButtonText = val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)chestButton == (Object)null || (Object)(object)chestButtonText == (Object)null) { Object.Destroy((Object)(object)val); chestButton = null; return false; } chestButton.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = chestButton.onClick; object obj = <>c.<>9__42_0; if (obj == null) { UnityAction val2 = delegate { Container val4 = (((Object)(object)InventoryGui.instance == (Object)null) ? null : currentContainer.Invoke(InventoryGui.instance)); if (IsChest(val4)) { Toggle((Component)(object)val4); } }; <>c.<>9__42_0 = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); RectTransform val3 = (RectTransform)val.transform; val3.anchorMin = new Vector2(1f, 1f); val3.anchorMax = new Vector2(1f, 1f); val3.pivot = new Vector2(1f, 0f); val3.anchoredPosition = new Vector2(0f, 6f); val3.sizeDelta = new Vector2(Mathf.Max(val3.sizeDelta.x, 150f), val3.sizeDelta.y); return true; } } }