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 SlotAnchor v0.1.2
BepInEx/plugins/SlotAnchor/SlotAnchor.dll
Decompiled 17 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; 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("SlotAnchor")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2")] [assembly: AssemblyProduct("SlotAnchor")] [assembly: AssemblyTitle("SlotAnchor")] [assembly: AssemblyVersion("0.1.2.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 SlotAnchor { public static class Instrumentation { public static IEnumerable<CodeInstruction> ListReads(IEnumerable<CodeInstruction> src, FieldInfo field, MethodInfo getAll, MethodInfo replacement) { int count = 0; foreach (CodeInstruction item in src) { if ((item.opcode == OpCodes.Ldfld && object.Equals(item.operand, field)) || CodeInstructionExtensions.Calls(item, getAll)) { item.opcode = OpCodes.Call; item.operand = replacement; count++; } yield return item; } if (count == 0) { throw new InvalidOperationException("Inventory list pattern missing"); } } public static IEnumerable<CodeInstruction> EmptySlots(IEnumerable<CodeInstruction> src, MethodInfo getAt, MethodInfo replacement) { int count = 0; foreach (CodeInstruction item in src) { if (CodeInstructionExtensions.Calls(item, getAt)) { item.opcode = OpCodes.Call; item.operand = replacement; count++; } yield return item; } if (count != 2) { throw new InvalidOperationException("FindEmptySlot changed; expected 2 probes, got " + count); } } } public static class MethodLookup { public static MethodInfo Exact(Type type, string name, params string[] parameters) { MethodInfo[] array = (from m in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == name && (from p in m.GetParameters() select p.ParameterType.FullName).SequenceEqual<string>(parameters) select m).ToArray(); if (array.Length != 1) { throw new MissingMethodException(type.FullName, name + "(" + string.Join(",", parameters) + "): expected one match, found " + array.Length); } return array[0]; } public static MethodInfo[] InventoryLoadMethods(Type inventory) { return new MethodInfo[2] { Exact(inventory, "Load", "ZPackage"), Exact(inventory, "Load", "ZPackage", "System.Boolean") }; } } internal static class Overlay { private static Type imageType; private static Sprite lockSprite; private static bool failed; private static readonly Color Cyan = new Color(0.25f, 0.85f, 0.95f, 0.8f); private static Component Image(string name, Transform parent, Vector2 min, Vector2 max, Vector2 offsetMin, Vector2 offsetMax, Color color) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(parent, false); val2.anchorMin = min; val2.anchorMax = max; val2.offsetMin = offsetMin; val2.offsetMax = offsetMax; Component obj = val.AddComponent(imageType); Set(obj, "color", color); Set(obj, "raycastTarget", false); return obj; } private static void Set(object obj, string p, object v) { obj.GetType().GetProperty(p).SetValue(obj, v, null); } private static void Init() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_00b6: Unknown result type (might be due to invalid IL or missing references) imageType = Type.GetType("UnityEngine.UI.Image, UnityEngine.UI", throwOnError: true); Texture2D val = new Texture2D(16, 20, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)0; for (int i = 0; i < 20; i++) { for (int j = 0; j < 16; j++) { bool flag = j >= 2 && j <= 13 && i >= 1 && i <= 11; bool flag2 = i >= 11 && i <= 18 && j >= 4 && j <= 11 && (j <= 5 || j >= 10 || i >= 17); bool flag3 = j >= 7 && j <= 8 && i >= 4 && i <= 8; val.SetPixel(j, i, (Color)(((flag || flag2) && !flag3) ? new Color(1f, 0.8f, 0.25f, 1f) : Color.clear)); } } val.Apply(); lockSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 20f), new Vector2(0.5f, 0.5f)); } public static void Draw(InventoryGrid grid) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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_0131: 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_0148: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: 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_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) if (failed) { return; } try { Inventory inventory = grid.GetInventory(); if (inventory == null) { return; } if (imageType == null) { Init(); } RuleBook ruleBook = Plugin.Rules(inventory); IList list = (IList)Plugin.Field(grid, "m_elements"); for (int i = 0; i < list.Count; i++) { Component val = (Component)list[i]; object pos = Plugin.Call(grid, "GetElementPos", val); int num = Plugin.X(pos); int num2 = Plugin.Y(pos); string value; bool num3 = ruleBook.Slots.TryGetValue(RuleBook.Key(num, num2), out value); Transform val2 = val.transform.Find("SlotAnchorOverlay"); if (!num3) { if (Object.op_Implicit((Object)(object)val2)) { ((Component)val2).gameObject.SetActive(false); } continue; } if (!Object.op_Implicit((Object)(object)val2)) { RectTransform val3 = (RectTransform)new GameObject("SlotAnchorOverlay", new Type[1] { typeof(RectTransform) }).transform; ((Transform)val3).SetParent(val.transform, false); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = new Vector2(2f, 2f); val3.offsetMax = new Vector2(-2f, -2f); val2 = (Transform)val3; Image("Ghost", val2, Vector2.zero, Vector2.one, new Vector2(6f, 6f), new Vector2(-6f, -6f), new Color(1f, 1f, 1f, 0.25f)); Image("Top", val2, new Vector2(0f, 1f), Vector2.one, new Vector2(0f, -2f), Vector2.zero, Cyan); Image("Bottom", val2, Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 2f), Cyan); Image("Left", val2, Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(2f, 0f), Cyan); Image("Right", val2, new Vector2(1f, 0f), Vector2.one, new Vector2(-2f, 0f), Vector2.zero, Cyan); Set(Image("Lock", val2, new Vector2(1f, 1f), Vector2.one, new Vector2(-17f, -21f), new Vector2(-1f, -1f), Color.white), "sprite", lockSprite); } ((Component)val2).gameObject.SetActive(true); val2.SetAsLastSibling(); Transform val4 = val2.Find("Ghost"); bool flag = inventory.GetItemAt(num, num2) == null; ((Component)val4).gameObject.SetActive(flag); if (flag && Object.op_Implicit((Object)(object)ObjectDB.instance)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(value); ItemDrop val5 = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null); Set(((Component)val4).GetComponent(imageType), "sprite", Object.op_Implicit((Object)(object)val5) ? val5.m_itemData.GetIcon() : null); ((Component)val4).gameObject.SetActive((Object)(object)val5 != (Object)null); } } } catch (Exception ex) { failed = true; Debug.LogError((object)("Slot Anchor overlay failed: " + ex)); } } } [BepInPlugin("cz.misaweb.valheim.slotanchor", "Slot Anchor", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("com.Azura.slotlock")] public sealed class Plugin : BaseUnityPlugin { private sealed class Cache { public string Raw; public RuleBook Book; } public const string Id = "cz.misaweb.valheim.slotanchor"; public const string QssId = "goldenrevolver.quick_stack_store"; internal static Plugin Self; internal static bool Ready; internal static int Manual; internal static int Loading; private ConfigEntry<KeyboardShortcut> hotkey; private Harmony harmony; internal static readonly FieldInfo ItemsField = AccessTools.Field(typeof(Inventory), "m_inventory"); private static readonly FieldInfo PosField = AccessTools.Field(typeof(ItemData), "m_gridPos"); private static readonly ConditionalWeakTable<Inventory, Container> Owners = new ConditionalWeakTable<Inventory, Container>(); private static readonly ConditionalWeakTable<Inventory, Cache> CacheTable = new ConditionalWeakTable<Inventory, Cache>(); internal const string DataKey = "cz.misaweb.valheim.slotanchor.rules.v1"; internal static readonly ItemData ReservedMarker = new ItemData(); private void Awake() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Self = this; hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1. Controls", "Lock key", new KeyboardShortcut((KeyCode)106, Array.Empty<KeyCode>()), "Zamknout/odemknout policko pod mysi. Pouze v otevrenem inventari. Zamek chrani pred automatickymi operacemi; rucni presuny jsou povolene."); } private void Start() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0096: 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) harmony = new Harmony("cz.misaweb.valheim.slotanchor"); try { PluginInfo info; bool num = Chainloader.PluginInfos.TryGetValue("goldenrevolver.quick_stack_store", out info); bool flag = StartupPlan.Install(num, num ? info.Metadata.Version.ToString() : null, InstallCore, delegate { InstallQss(((object)info.Instance).GetType().Assembly); }); Ready = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Slot Anchor 0.1.2 READY. " + (flag ? "Quick Stack 1.4.16 integration installed." : "Standalone mode; Quick Stack is not installed.") + " Key: " + ((object)hotkey.Value/*cast due to .constrained prefix*/).ToString())); } catch (Exception ex) { Ready = false; harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("Slot Anchor DISABLED; no locks are active: " + ex)); } } private void OnDestroy() { Ready = false; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } internal static object Field(object o, string n) { return AccessTools.Field(o.GetType(), n).GetValue(o); } internal static object Call(object o, string n, params object[] a) { MethodInfo? methodInfo = AccessTools.GetDeclaredMethods(o.GetType()).FirstOrDefault((MethodInfo x) => x.Name == n && x.GetParameters().Length == a.Length && x.GetParameters().Select((ParameterInfo p, int i) => a[i] == null || p.ParameterType.IsInstanceOfType(a[i])).All((bool result) => result)); if (methodInfo == null) { throw new MissingMethodException(o.GetType().FullName, n + " with compatible arguments"); } return methodInfo.Invoke(o, a); } internal static int X(object pos) { return (int)Field(pos, "x"); } internal static int Y(object pos) { return (int)Field(pos, "y"); } internal static object Pos(ItemData item) { return PosField.GetValue(item); } internal static string Identity(ItemData item) { if (!Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return item.m_shared.m_name; } return ((Object)item.m_dropPrefab).name; } internal static List<ItemData> Items(Inventory inv) { return (List<ItemData>)ItemsField.GetValue(inv); } internal static void Register(Container c) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Inventory val = (Inventory)Field(c, "m_inventory"); if (val != null) { Owners.Remove(val); Owners.Add(val, c); } } private static object Zdo(Container c) { object obj = Field(c, "m_nview"); if (obj != null) { return Call(obj, "GetZDO"); } return null; } internal static string ReadRaw(Inventory inv) { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && inv == ((Humanoid)localPlayer).GetInventory()) { if (!((Dictionary<string, string>)Field(localPlayer, "m_customData")).TryGetValue("cz.misaweb.valheim.slotanchor.rules.v1", out var value)) { return ""; } return value; } if (Owners.TryGetValue(inv, out var value2) && Object.op_Implicit((Object)(object)value2)) { object obj = Zdo(value2); if (obj != null) { return (string)Call(obj, "GetString", "cz.misaweb.valheim.slotanchor.rules.v1", ""); } } return ""; } internal static RuleBook Rules(Inventory inv) { if (inv == null) { return new RuleBook(); } string text = ReadRaw(inv); Cache value = CacheTable.GetValue(inv, (Inventory _) => new Cache()); if (value.Book == null || value.Raw != text) { value.Book = RuleBook.Decode(text); value.Raw = text; } return value.Book; } private static bool Save(Inventory inv, RuleBook rules) { string text = rules.Encode(); Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && inv == ((Humanoid)localPlayer).GetInventory()) { ((Dictionary<string, string>)Field(localPlayer, "m_customData"))["cz.misaweb.valheim.slotanchor.rules.v1"] = text; return true; } if (!Owners.TryGetValue(inv, out var value) || !Object.op_Implicit((Object)(object)value)) { return false; } object obj = Field(value, "m_nview"); if (obj == null || !(bool)Call(obj, "IsOwner")) { Message("Truhla ještě není připravená. Zkus J znovu."); return false; } object obj2 = Zdo(value); if (obj2 == null) { return false; } Call(obj2, "Set", "cz.misaweb.valheim.slotanchor.rules.v1", text); return true; } internal static bool Locked(Inventory inv, ItemData item) { object pos = Pos(item); return Rules(inv).Locked(X(pos), Y(pos)); } internal static List<ItemData> UnlockedItems(Inventory inv) { List<ItemData> list = Items(inv); if (!Ready || Loading > 0) { return list; } RuleBook rules = Rules(inv); if (rules.Slots.Count == 0) { return list; } return list.Where(delegate(ItemData i) { object pos = Pos(i); return !rules.Locked(X(pos), Y(pos)); }).ToList(); } internal static List<ItemData> StackCandidates(Inventory inv) { if (Manual <= 0) { return UnlockedItems(inv); } return Items(inv); } internal static ItemData EmptyProbe(Inventory inv, int x, int y) { ItemData itemAt = inv.GetItemAt(x, y); if (itemAt == null && Ready && Loading == 0 && Rules(inv).Locked(x, y)) { return ReservedMarker; } return itemAt; } internal static void Message(string text) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } private void Update() { //IL_002e: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown if (!Ready || !Object.op_Implicit((Object)(object)InventoryGui.instance) || !InventoryGui.IsVisible() || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } try { KeyboardShortcut value = hotkey.Value; if (!((KeyboardShortcut)(ref value)).IsDown() || TextInputActive()) { return; } InventoryGui instance = InventoryGui.instance; if (Field(instance, "m_dragItem") != null) { return; } Container val = (Container)Field(instance, "m_currentContainer"); if (Object.op_Implicit((Object)(object)val)) { Register(val); } InventoryGrid[] array = (InventoryGrid[])(object)new InventoryGrid[2] { instance.m_playerGrid, (InventoryGrid)Field(instance, "m_containerGrid") }; foreach (InventoryGrid val2 in array) { if (!Object.op_Implicit((Object)(object)val2) || !((Component)val2).gameObject.activeInHierarchy) { continue; } object obj = Call(val2, "GetHoveredElement"); if (obj == null) { continue; } object pos = Call(val2, "GetElementPos", obj); int num = X(pos); int num2 = Y(pos); if (num < 0 || num2 < 0) { break; } Inventory inventory = val2.GetInventory(); if (inventory == null) { break; } RuleBook ruleBook = RuleBook.Decode(ReadRaw(inventory)); string key = RuleBook.Key(num, num2); bool flag = ruleBook.Slots.Remove(key); if (!flag) { ItemData itemAt = inventory.GetItemAt(num, num2); if (itemAt == null) { Message("Nejdřív vlož do políčka předmět."); break; } ruleBook.Slots[key] = Identity(itemAt); } if (Save(inventory, ruleBook)) { Message(flag ? "Políčko odemčeno" : "Políčko uzamčeno — pouze ruční přesuny"); } break; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Lock input failed: " + ex)); } } private static bool TextInputActive() { if (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) { return true; } object obj = Type.GetType("UnityEngine.GUIUtility, UnityEngine.IMGUIModule")?.GetProperty("keyboardControl")?.GetValue(null, null); if (obj is int && (int)obj != 0) { return true; } foreach (PluginInfo value in Chainloader.PluginInfos.Values) { BaseUnityPlugin instance = value.Instance; if (Object.op_Implicit((Object)(object)instance)) { PropertyInfo propertyInfo = AccessTools.Property(((object)instance).GetType(), "DisplayingWindow"); if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool) && (bool)propertyInfo.GetValue(instance, null)) { return true; } } } Type type = AccessTools.TypeByName("UnityEngine.EventSystems.EventSystem"); object obj2 = type?.GetProperty("current")?.GetValue(null, null); GameObject val = (GameObject)((obj2 == null) ? null : /*isinst with value type is only supported in some contexts*/); if (Object.op_Implicit((Object)(object)val) && (Object.op_Implicit((Object)(object)val.GetComponent("TMP_InputField")) || Object.op_Implicit((Object)(object)val.GetComponent("InputField")))) { return true; } string[] array = new string[4] { "Chat", "Console", "TextInput", "Menu" }; for (int i = 0; i < array.Length; i++) { Type type2 = AccessTools.TypeByName(array[i]); MethodInfo methodInfo = ((type2 == null) ? null : AccessTools.Method(type2, "IsVisible", Type.EmptyTypes, (Type[])null)); if (methodInfo != null && methodInfo.IsStatic && methodInfo.ReturnType == typeof(bool) && (bool)methodInfo.Invoke(null, null)) { return true; } } return false; } private void Patch(MethodBase target, string pre = null, string post = null, string trans = null, string fin = null) { if (target == null) { throw new MissingMethodException("Required patch target missing"); } harmony.Patch(target, H(pre), H(post), H(trans), H(fin), (HarmonyMethod)null); static HarmonyMethod H(string n) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (n != null) { return new HarmonyMethod(typeof(Patches), n, (Type[])null); } return null; } } private void InstallCore() { Patch(AccessTools.Method(typeof(Container), "Awake", (Type[])null, (Type[])null), null, "ContainerAwake"); MethodInfo[] array = MethodLookup.InventoryLoadMethods(typeof(Inventory)); foreach (MethodInfo target in array) { Patch(target, "LoadEnter", null, null, "LoadExit"); } Patch(AccessTools.Method(typeof(Inventory), "FindEmptySlot", (Type[])null, (Type[])null), null, null, "EmptySlots"); Patch(AccessTools.Method(typeof(Inventory), "FindFreeStackItem", (Type[])null, (Type[])null), null, null, "StackReads"); Patch(AccessTools.Method(typeof(Inventory), "FindFreeStackSpace", (Type[])null, (Type[])null), null, null, "StackReads"); Patch(AccessTools.Method(typeof(Inventory), "AddItem", new Type[5] { typeof(ItemData), typeof(int), typeof(int), typeof(int), typeof(bool) }, (Type[])null), "AddAt"); Type fieldType = PosField.FieldType; Patch(AccessTools.Method(typeof(Inventory), "AddItem", new Type[2] { typeof(ItemData), fieldType }, (Type[])null), "AddPos"); Patch(AccessTools.Method(typeof(InventoryGrid), "DropItem", (Type[])null, (Type[])null), "Drop"); string[] array2 = new string[4] { "OnSelectedItem", "OnRightClickItem", "OnDropOutside", "OnReleasedItem" }; foreach (string text in array2) { Patch(AccessTools.Method(typeof(InventoryGui), text, (Type[])null, (Type[])null), "ManualEnter", null, null, "ManualExit"); } Patch(AccessTools.Method(typeof(Container), "RPC_TakeAllResponse", (Type[])null, (Type[])null), "AutoEnter", null, null, "AutoExit"); Patch(AccessTools.Method(typeof(Inventory), "MoveAll", (Type[])null, (Type[])null), null, null, "MoveAllReads"); Patch(AccessTools.Method(typeof(Inventory), "StackAll", (Type[])null, (Type[])null), null, null, "FilterReads"); Patch(AccessTools.Method(typeof(InventoryGrid), "UpdateGui", (Type[])null, (Type[])null), null, "Draw"); } private void InstallQss(Assembly a) { string[] array = new string[6] { "SortModule.SortInternal", "QuickStackModule.DoQuickStack", "RestockModule.DoRestock", "RestockModule.RestockFromThisContainer", "StoreTakeAllModule.MoveAllItemsInOrder", "TrashModule.QuickTrash" }; foreach (string text in array) { string[] array2 = text.Split('.'); MethodInfo target = AccessTools.Method(a.GetType("QuickStackStore." + array2[0], throwOnError: true), array2[1], (Type[])null, (Type[])null); Patch(target, (text == "SortModule.SortInternal") ? "ValidateSort" : null, null, "FilterReads"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Protected QSS " + text)); } Patch(AccessTools.Method(a.GetType("QuickStackStore.SortModule", throwOnError: true), "GetAllowedSlots", (Type[])null, (Type[])null), null, "AllowedSlots"); } } internal static class Patches { private static int auto; public static void ContainerAwake(Container __instance) { Plugin.Register(__instance); } public static void ManualEnter(out int __state) { __state = Plugin.Manual; Plugin.Manual++; } public static void ManualExit(int __state) { Plugin.Manual = __state; } public static void LoadEnter(out int __state) { __state = Plugin.Loading; Plugin.Loading++; } public static void LoadExit(int __state) { Plugin.Loading = __state; } public static void AutoEnter(out int __state) { __state = auto; auto++; } public static void AutoExit(int __state) { auto = __state; } public static List<ItemData> MoveAllItems(Inventory inv) { if (auto <= 0) { return Plugin.Items(inv); } return Plugin.UnlockedItems(inv); } private static IEnumerable<CodeInstruction> ReplaceReads(IEnumerable<CodeInstruction> src, string method, Type type) { return Instrumentation.ListReads(src, Plugin.ItemsField, AccessTools.Method(typeof(Inventory), "GetAllItems", Type.EmptyTypes, (Type[])null), AccessTools.Method(type, method, (Type[])null, (Type[])null)); } public static IEnumerable<CodeInstruction> FilterReads(IEnumerable<CodeInstruction> src) { return ReplaceReads(src, "UnlockedItems", typeof(Plugin)); } public static IEnumerable<CodeInstruction> StackReads(IEnumerable<CodeInstruction> src) { return ReplaceReads(src, "StackCandidates", typeof(Plugin)); } public static IEnumerable<CodeInstruction> MoveAllReads(IEnumerable<CodeInstruction> src) { return ReplaceReads(src, "MoveAllItems", typeof(Patches)); } public static IEnumerable<CodeInstruction> EmptySlots(IEnumerable<CodeInstruction> src) { return Instrumentation.EmptySlots(src, AccessTools.Method(typeof(Inventory), "GetItemAt", (Type[])null, (Type[])null), AccessTools.Method(typeof(Plugin), "EmptyProbe", (Type[])null, (Type[])null)); } public static bool ValidateSort(object[] __args) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown if (!Plugin.Ready) { return true; } Inventory val = (Inventory)__args[0]; HashSet<string> hashSet = new HashSet<string>(); foreach (ItemData item in Plugin.Items(val)) { object pos = Plugin.Pos(item); int num = Plugin.X(pos); int num2 = Plugin.Y(pos); if (num < 0 || num2 < 0 || num >= val.GetWidth() || num2 >= val.GetHeight() || !hashSet.Add(RuleBook.Key(num, num2))) { Plugin.Message("Třídění zastaveno: inventář obsahuje neplatné nebo překrývající se pozice."); return false; } } return true; } public static void AllowedSlots(object[] __args, object __result, MethodBase __originalMethod) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if (!Plugin.Ready) { return; } Inventory val = (Inventory)__args[0]; IList list = (IList)__result; HashSet<string> hashSet = new HashSet<string>(Plugin.Rules(val).Slots.Keys); if (__args[2] != null) { MethodInfo methodInfo = AccessTools.Method(__originalMethod.DeclaringType, "ShouldSortItem", (Type[])null, (Type[])null); foreach (ItemData item in Plugin.Items(val)) { if (!(bool)methodInfo.Invoke(null, new object[5] { item, __args[2], val.GetHeight(), val.GetWidth(), __args[1] })) { object pos = Plugin.Pos(item); hashSet.Add(RuleBook.Key(Plugin.X(pos), Plugin.Y(pos))); } } } for (int num = list.Count - 1; num >= 0; num--) { if (hashSet.Contains(RuleBook.Key(Plugin.X(list[num]), Plugin.Y(list[num])))) { list.RemoveAt(num); } } } private static bool MayAdd(Inventory inv, ItemData item, int x, int y) { if (!Plugin.Ready || Plugin.Loading > 0) { return true; } RuleBook ruleBook = Plugin.Rules(inv); if (!ruleBook.Locked(x, y)) { return true; } if (Plugin.Manual > 0) { return ruleBook.Accepts(x, y, Plugin.Identity(item)); } return false; } public static bool AddAt(Inventory __instance, object[] __args, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (MayAdd(__instance, (ItemData)__args[0], (int)__args[2], (int)__args[3])) { return true; } __result = false; return false; } public static bool AddPos(Inventory __instance, object[] __args, ref bool __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (MayAdd(__instance, (ItemData)__args[0], Plugin.X(__args[1]), Plugin.Y(__args[1]))) { return true; } __result = false; return false; } public static bool Drop(InventoryGrid __instance, object[] __args, ref bool __result) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (!Plugin.Ready) { return true; } Inventory inv = (Inventory)__args[0]; ItemData item = (ItemData)__args[1]; object pos = __args[3]; Inventory inventory = __instance.GetInventory(); ItemData itemAt = inventory.GetItemAt(Plugin.X(pos), Plugin.Y(pos)); object pos2 = Plugin.Pos(item); if (!Plugin.Rules(inventory).Accepts(Plugin.X(pos), Plugin.Y(pos), Plugin.Identity(item)) || (itemAt != null && Plugin.Identity(itemAt) != Plugin.Identity(item) && !Plugin.Rules(inv).Accepts(Plugin.X(pos2), Plugin.Y(pos2), Plugin.Identity(itemAt)))) { __result = false; Plugin.Message("Políčko je rezervované pro jiný předmět. Odemkni ho klávesou J."); return false; } return true; } public static void Draw(InventoryGrid __instance) { if (Plugin.Ready) { Overlay.Draw(__instance); } } } public sealed class RuleBook { public readonly Dictionary<string, string> Slots = new Dictionary<string, string>(); public static string Key(int x, int y) { return x.ToString(CultureInfo.InvariantCulture) + "," + y.ToString(CultureInfo.InvariantCulture); } public bool Locked(int x, int y) { return Slots.ContainsKey(Key(x, y)); } public bool Accepts(int x, int y, string item) { if (Slots.TryGetValue(Key(x, y), out var value)) { return value == item; } return true; } public string Encode() { List<string> list = new List<string>(); foreach (KeyValuePair<string, string> slot in Slots) { list.Add(slot.Key + ":" + Convert.ToBase64String(Encoding.UTF8.GetBytes(slot.Value))); } list.Sort(StringComparer.Ordinal); return "1|" + string.Join(";", list); } public static RuleBook Decode(string text) { RuleBook ruleBook = new RuleBook(); if (string.IsNullOrEmpty(text)) { return ruleBook; } if (!text.StartsWith("1|")) { throw new FormatException("Unknown slot rules version"); } string[] array = text.Substring(2).Split(';'); foreach (string text2 in array) { if (text2.Length != 0) { int num = text2.IndexOf(':'); if (num < 1) { throw new FormatException("Invalid rule"); } string[] array2 = text2.Substring(0, num).Split(','); if (array2.Length != 2 || !int.TryParse(array2[0], out var result) || !int.TryParse(array2[1], out var result2) || result < 0 || result2 < 0) { throw new FormatException("Invalid slot"); } string text3 = Encoding.UTF8.GetString(Convert.FromBase64String(text2.Substring(num + 1))); if (text3.Length == 0) { throw new FormatException("Empty item"); } ruleBook.Slots.Add(Key(result, result2), text3); } } return ruleBook; } } public static class StartupPlan { public const string SupportedQuickStack = "1.4.16"; public static bool Install(bool hasQuickStack, string version, Action installCore, Action installQuickStack) { if (hasQuickStack && version != "1.4.16") { throw new NotSupportedException("Quick Stack " + version + " is installed; supported version is 1.4.16. Use that version or disable Quick Stack to run Slot Anchor standalone."); } installCore(); if (hasQuickStack) { installQuickStack(); } return hasQuickStack; } } }