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 OdinsReach v0.1.0
OdinsReach.dll
Decompiled a day 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.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("OdinsReach")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ce1fe04c1e0d3a2923c660dc5676ceccf87de5a5")] [assembly: AssemblyProduct("OdinsReach")] [assembly: AssemblyTitle("OdinsReach")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace OdinsMissingPatch { internal static class ChestFavorites { [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] [Serves(new Type[] { typeof(QuickStack), typeof(ChestButtons) }, Optional = true)] private static class ShowMarks { private static readonly FieldRef<InventoryElement, Graphic> Amount = AccessTools.FieldRefAccess<InventoryElement, Graphic>("m_amount"); private static Container shownChest; private static uint shownRevision; private static InventoryElement shownFirst; private static bool tinted; private static Color plain; private static bool plainKnown; private static void Prepare() { PanelButtons.Add(ClearButton.Button, PanelButtons.Spot.StackAll, ClearButton.Shows, ClearButton.Refresh); } private static void Postfix(InventoryGui __instance) { //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (PanelButtons.Closing(__instance)) { return; } InventoryGrid containerGrid = __instance.m_containerGrid; if ((Object)(object)containerGrid == (Object)null || !KnowPlain(containerGrid)) { return; } List<InventoryElement> elements = containerGrid.m_elements; Container currentContainer = __instance.m_currentContainer; ZNetView val = (((Object)(object)currentContainer != (Object)null) ? currentContainer.m_nview : null); if (!Used || (Object)(object)val == (Object)null || !val.IsValid() || containerGrid.m_inventory != currentContainer.GetInventory()) { if (tinted) { Reset(elements); } shownChest = null; return; } uint dataRevision = val.GetZDO().DataRevision; InventoryElement val2 = ((elements.Count > 0) ? elements[0] : null); if ((Object)(object)currentContainer == (Object)(object)shownChest && dataRevision == shownRevision && (Object)(object)val2 == (Object)(object)shownFirst) { return; } shownChest = currentContainer; shownRevision = dataRevision; shownFirst = val2; Reset(elements); string text = Marks(currentContainer); if (text.Length == 0) { return; } Inventory inventory = containerGrid.m_inventory; int width = inventory.GetWidth(); foreach (ItemData allItem in inventory.GetAllItems()) { if (Marked(text, allItem.m_shared.m_name)) { InventoryElement element = containerGrid.GetElement(allItem.m_gridPos.x, allItem.m_gridPos.y, width); Graphic val3 = (((Object)(object)element != (Object)null) ? Amount.Invoke(element) : null); if ((Object)(object)val3 != (Object)null) { val3.color = Palette.ChestYellow; tinted = true; } } } } private static bool KnowPlain(InventoryGrid grid) { //IL_004b: 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 (plainKnown) { return true; } InventoryElement val = (((Object)(object)grid.m_elementPrefab != (Object)null) ? grid.m_elementPrefab.GetComponent<InventoryElement>() : null); Graphic val2 = (((Object)(object)val != (Object)null) ? Amount.Invoke(val) : null); if ((Object)(object)val2 == (Object)null) { return false; } plain = val2.color; plainKnown = true; return true; } private static void Reset(List<InventoryElement> elements) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) foreach (InventoryElement element in elements) { Graphic val = (((Object)(object)element != (Object)null) ? Amount.Invoke(element) : null); if ((Object)(object)val != (Object)null) { val.color = plain; } } tinted = false; } } private static class ClearButton { internal static readonly PanelButtons.TextButton Button = new PanelButtons.TextButton("OMP_ClearFavorites", new UnityAction(ClearOpen)); private static string favorites = ""; private static int revision = -1; private static int count; private static string tooltip = ""; internal static bool Shows(InventoryGui gui) { Container currentContainer = gui.m_currentContainer; if ((Object)(object)currentContainer != (Object)null && (Object)(object)gui.m_container != (Object)null && ((Component)gui.m_container).gameObject.activeSelf && Used) { return Marks(currentContainer).Length > 0; } return false; } internal static void Refresh(InventoryGui gui) { Describe(gui.m_currentContainer, Marks(gui.m_currentContainer)); Button.SetLabel((count == 1) ? "$omp_clear_favourite" : "$omp_clear_favourites", count.ToString()); Button.SetTooltip("$omp_favourites_topic", tooltip); } private static void Describe(Container chest, string marks) { if (!(marks == favorites) || revision != Translations.Revision) { favorites = marks; revision = Translations.Revision; count = Names(chest).Count; tooltip = "$omp_favourites_tip_head\n" + ChestFavorites.Describe(chest) + "\n\n$omp_favourites_tip_foot"; } } private static void ClearOpen() { InventoryGui instance = InventoryGui.instance; Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); if (!((Object)(object)val == (Object)null)) { Clear(val); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, "$omp_favourites_cleared", 0, (Sprite)null, false); } } } } private static readonly int FavoritesHash = StringExtensionMethods.GetStableHashCode("OMP_ChestFavorites"); private const char Separator = '\n'; internal static bool Used => Patcher.AnyServedOn(typeof(ShowMarks)); internal static string Marks(Container chest) { ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null); if (!((Object)(object)val != (Object)null) || !val.IsValid()) { return ""; } return val.GetZDO().GetString(FavoritesHash, ""); } internal static bool Marked(string marks, string itemName) { if (string.IsNullOrEmpty(marks) || string.IsNullOrEmpty(itemName)) { return false; } for (int num = marks.IndexOf(itemName, StringComparison.Ordinal); num >= 0; num = marks.IndexOf(itemName, num + 1, StringComparison.Ordinal)) { int num2 = num + itemName.Length; if (num > 0 && num2 < marks.Length && marks[num - 1] == '\n' && marks[num2] == '\n') { return true; } } return false; } internal static bool Accepts(Container chest, string itemName) { return Marked(Marks(chest), itemName); } internal static List<string> Names(Container chest) { List<string> list = new List<string>(); string[] array = Marks(chest).Split(new char[1] { '\n' }); foreach (string text in array) { if (text.Length > 0) { list.Add(text); } } return list; } internal static bool Toggle(Container chest, string itemName) { List<string> list = Names(chest); bool num = !list.Remove(itemName); if (num) { list.Add(itemName); } Write(chest, list); return num; } internal static void Clear(Container chest) { Write(chest, new List<string>()); } internal static string Describe(Container chest) { StringBuilder stringBuilder = new StringBuilder(); foreach (string item in Names(chest)) { if (stringBuilder.Length > 0) { stringBuilder.Append('\n'); } stringBuilder.Append("- ").Append(Localize(item)); } return stringBuilder.ToString(); } internal static string Localize(string itemName) { if (Localization.instance == null) { return itemName; } return Localization.instance.Localize(itemName); } internal static Container OpenChest(Inventory inventory) { InventoryGui instance = InventoryGui.instance; Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); if (!((Object)(object)val != (Object)null) || inventory == null || val.m_inventory != inventory) { return null; } return val; } private static void Write(Container chest, List<string> names) { ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } if (!val.IsOwner()) { val.ClaimOwnership(); } if (!val.IsOwner()) { return; } StringBuilder stringBuilder = new StringBuilder(); foreach (string name in names) { stringBuilder.Append('\n').Append(name); } if (stringBuilder.Length > 0) { stringBuilder.Append('\n'); } val.GetZDO().Set(FavoritesHash, stringBuilder.ToString()); } } internal sealed class ChestGlow : MonoBehaviour { private const float Duration = 7f; private float time; internal static void Flash(Container chest, string text) { //IL_0057: 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_0061: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)chest == (Object)null)) { GameObject val = (((Object)(object)chest.m_rootObjectOverride != (Object)null) ? ((Component)chest.m_rootObjectOverride).gameObject : ((Component)chest).gameObject); ChestGlow chestGlow = val.GetComponent<ChestGlow>(); if ((Object)(object)chestGlow == (Object)null) { chestGlow = val.AddComponent<ChestGlow>(); } chestGlow.time = 0f; if (text != null) { ShowText(((Component)chest).transform.position + Vector3.up, text); } } } private static void ShowText(Vector3 position, string text) { //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_003a: Unknown result type (might be due to invalid IL or missing references) DamageText instance = DamageText.instance; if (!((Object)(object)instance == (Object)null)) { Camera mainCamera = Utils.GetMainCamera(); float num = (((Object)(object)mainCamera != (Object)null) ? Vector3.Distance(((Component)mainCamera).transform.position, position) : 0f); instance.AddInworldText((TextType)7, position, num, text, false); } } private void Update() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) time += Time.deltaTime; MaterialMan instance = MaterialMan.instance; if ((Object)(object)instance == (Object)null || time >= 7f) { Object.Destroy((Object)(object)this); return; } float num = Mathf.Abs(Mathf.Sin(time / 7f * (float)Math.PI * 3f)); instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._EmissionColor, Palette.Gold * (0.6f * num), false); instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._Color, Color.Lerp(Color.white, Palette.Gold, 0.6f * num), false); } private void OnDestroy() { MaterialMan instance = MaterialMan.instance; if ((Object)(object)instance != (Object)null) { instance.ResetValue(((Component)this).gameObject, ShaderProps._EmissionColor); instance.ResetValue(((Component)this).gameObject, ShaderProps._Color); } } } internal static class InventorySorter { internal static bool Sort(Inventory inventory, int fromRow, Func<ItemData, bool> keep) { //IL_003e: 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_0045: 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_0059: 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) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if (inventory == null) { return false; } List<ItemData> allItems = inventory.GetAllItems(); int width = inventory.GetWidth(); int height = inventory.GetHeight(); bool[,] array = new bool[width, height]; List<ItemData> list = new List<ItemData>(); foreach (ItemData item in allItems) { Vector2i gridPos = item.m_gridPos; bool flag = gridPos.x >= 0 && gridPos.x < width && gridPos.y >= 0 && gridPos.y < height; if (flag && gridPos.y >= fromRow && (keep == null || !keep(item))) { list.Add(item); } else if (flag) { array[gridPos.x, gridPos.y] = true; } } if (list.Count == 0) { return false; } List<Vector2i> list2 = new List<Vector2i>(); for (int i = fromRow; i < height; i++) { for (int j = 0; j < width; j++) { if (!array[j, i]) { list2.Add(new Vector2i(j, i)); } } } if (list2.Count < list.Count) { return false; } MaterialOrder.Prepare(); list.Sort(Compare); List<ItemData> list3 = Merge(list, allItems); for (int k = 0; k < list3.Count; k++) { list3[k].m_gridPos = list2[k]; } inventory.Changed(false, false); return true; } private static List<ItemData> Merge(List<ItemData> sorted, List<ItemData> all) { List<ItemData> list = new List<ItemData>(sorted.Count); foreach (ItemData item in sorted) { if (item.m_shared.m_maxStackSize > 1) { foreach (ItemData item2 in list) { if (item.m_stack <= 0) { break; } if (Merges(item2, item)) { int num = Math.Min(item2.m_shared.m_maxStackSize - item2.m_stack, item.m_stack); item2.m_stack += num; item.m_stack -= num; } } } if (item.m_stack > 0) { list.Add(item); } else { all.Remove(item); } } return list; } internal static bool Merges(ItemData stack, ItemData item) { if (stack.m_stack < stack.m_shared.m_maxStackSize) { return SameStack(stack, item); } return false; } private static bool SameStack(ItemData a, ItemData b) { if (a.m_shared.m_name != b.m_shared.m_name || a.m_quality != b.m_quality || a.m_variant != b.m_variant || a.m_worldLevel != b.m_worldLevel || a.m_cheated != b.m_cheated) { return false; } if (Covers(a.m_customData, b.m_customData)) { return Covers(b.m_customData, a.m_customData); } return false; } private static bool Covers(Dictionary<string, string> a, Dictionary<string, string> b) { foreach (KeyValuePair<string, string> item in a) { if (item.Key != "OMP_Favorite" && (!b.TryGetValue(item.Key, out var value) || value != item.Value)) { return false; } } return true; } private static int Compare(ItemData a, ItemData b) { //IL_0006: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 int num = Rank(a.m_shared.m_itemType).CompareTo(Rank(b.m_shared.m_itemType)); if (num != 0) { return num; } if ((int)a.m_shared.m_itemType == 1 && (int)b.m_shared.m_itemType == 1) { num = Portable(a).CompareTo(Portable(b)); if (num != 0) { return num; } num = MaterialOrder.Compare(a, b); if (num != 0) { return num; } } num = string.Compare(DisplayName(a), DisplayName(b), StringComparison.CurrentCultureIgnoreCase); if (num != 0) { return num; } num = b.m_quality.CompareTo(a.m_quality); if (num != 0) { return num; } num = a.m_variant.CompareTo(b.m_variant); if (num == 0) { return b.m_stack.CompareTo(a.m_stack); } return num; } private static int Portable(ItemData item) { return (!item.m_shared.m_teleportable) ? 1 : 0; } private static string DisplayName(ItemData item) { string name = item.m_shared.m_name; Localization instance = Localization.instance; if (instance == null) { return name; } return instance.Localize(name); } private static int Rank(ItemType type) { //IL_0000: 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_0068: Expected I4, but got Unknown switch (type - 1) { case 2: case 3: case 13: case 14: case 19: case 21: return 0; case 4: return 1; case 18: return 2; case 5: return 3; case 6: return 4; case 10: return 5; case 16: return 6; case 11: return 7; case 9: return 8; case 17: return 9; case 23: return 10; case 8: return 11; case 22: return 12; case 1: return 13; case 20: return 14; case 0: return 15; case 12: return 16; case 15: return 17; default: return 18; } } } internal static class MaterialOrder { private struct Place { internal int Family; internal int Depth; } private sealed class Step { internal SharedData Result; internal readonly List<SharedData> Inputs = new List<SharedData>(); internal int Station = -1; internal int Level; } private sealed class Group { internal readonly List<SharedData> Members = new List<SharedData>(); internal int Low = int.MaxValue; internal string Name; internal void Note(SharedData kind, int depth) { Members.Add(kind); string text = Label(kind); if (depth < Low || (depth == Low && string.Compare(text, Name, StringComparison.CurrentCultureIgnoreCase) < 0)) { Low = depth; Name = text; } } } private const int MaxPasses = 32; private static ObjectDB source; private static int sourceRecipes; private static int sourceItems; private static Dictionary<SharedData, Place> places; internal static void Prepare() { ObjectDB instance = ObjectDB.instance; if (!((Object)(object)instance == (Object)null) && (!((Object)(object)instance == (Object)(object)source) || instance.m_recipes.Count != sourceRecipes || instance.m_items.Count != sourceItems)) { source = instance; sourceRecipes = instance.m_recipes.Count; sourceItems = instance.m_items.Count; places = Build(instance); } } internal static int Compare(ItemData a, ItemData b) { Place place = Of(a); Place place2 = Of(b); int num = place.Family.CompareTo(place2.Family); if (num == 0) { return place.Depth.CompareTo(place2.Depth); } return num; } private static Place Of(ItemData item) { if (places != null && item != null && item.m_shared != null && places.TryGetValue(item.m_shared, out var value)) { return value; } return new Place { Family = int.MaxValue, Depth = 0 }; } private static Dictionary<SharedData, Place> Build(ObjectDB db) { List<Piece> allBuildPieces = db.GetAllBuildPieces(true); Dictionary<CraftingStation, int> stations = Stations(allBuildPieces); List<Step> steps = Steps(db, allBuildPieces, stations); int[] pieceDepth = new int[allBuildPieces.Count]; Dictionary<SharedData, int> made = new Dictionary<SharedData, int>(); Settle(allBuildPieces, stations, Producers(steps), pieceDepth, made); Dictionary<SharedData, int> dictionary = Depths(made, Uses(steps, allBuildPieces, made, pieceDepth)); Dictionary<SharedData, SharedData> parents = Families(steps); Dictionary<SharedData, Group> dictionary2 = new Dictionary<SharedData, Group>(); foreach (KeyValuePair<SharedData, int> item in dictionary) { SharedData key = Find(parents, item.Key); if (!dictionary2.TryGetValue(key, out var value)) { value = (dictionary2[key] = new Group()); } value.Note(item.Key, item.Value); } List<Group> list = new List<Group>(dictionary2.Values); list.Sort(CompareGroups); Dictionary<SharedData, Place> dictionary3 = new Dictionary<SharedData, Place>(); for (int i = 0; i < list.Count; i++) { foreach (SharedData member in list[i].Members) { dictionary3[member] = new Place { Family = i, Depth = dictionary[member] }; } } return dictionary3; } private static Dictionary<CraftingStation, int> Stations(List<Piece> pieces) { Dictionary<CraftingStation, int> dictionary = new Dictionary<CraftingStation, int>(); for (int i = 0; i < pieces.Count; i++) { Piece val = pieces[i]; if (!((Object)(object)val == (Object)null)) { CraftingStation component = ((Component)val).GetComponent<CraftingStation>(); if ((Object)(object)component != (Object)null && !dictionary.ContainsKey(component)) { dictionary[component] = i; } } } return dictionary; } private static List<Step> Steps(ObjectDB db, List<Piece> pieces, Dictionary<CraftingStation, int> stations) { List<Step> list = new List<Step>(); foreach (Recipe recipe in db.m_recipes) { if (!((Object)(object)recipe == (Object)null) && recipe.m_enabled && !((Object)(object)recipe.m_item == (Object)null)) { Step step = new Step { Result = recipe.m_item.m_itemData.m_shared, Station = StationPiece(stations, recipe.m_craftingStation), Level = Math.Max(0, recipe.m_minStationLevel - 1) }; Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { Feed(step.Inputs, val?.m_resItem); } Keep(list, step); } } for (int j = 0; j < pieces.Count; j++) { Piece val2 = pieces[j]; if ((Object)(object)val2 == (Object)null) { continue; } Smelter component = ((Component)val2).GetComponent<Smelter>(); if ((Object)(object)component != (Object)null) { foreach (ItemConversion item in component.m_conversion) { if (item != null) { Converted(list, j, item.m_from, item.m_to); } } } CookingStation component2 = ((Component)val2).GetComponent<CookingStation>(); if ((Object)(object)component2 != (Object)null) { foreach (ItemConversion item2 in component2.m_conversion) { if (item2 != null) { Converted(list, j, item2.m_from, item2.m_to); } } } Fermenter component3 = ((Component)val2).GetComponent<Fermenter>(); if (!((Object)(object)component3 != (Object)null)) { continue; } foreach (ItemConversion item3 in component3.m_conversion) { if (item3 != null) { Converted(list, j, item3.m_from, item3.m_to); } } } return list; } private static void Converted(List<Step> steps, int station, ItemDrop from, ItemDrop to) { if (!((Object)(object)to == (Object)null)) { Step step = new Step { Result = to.m_itemData.m_shared, Station = station }; Feed(step.Inputs, from); Keep(steps, step); } } private static void Feed(List<SharedData> inputs, ItemDrop drop) { SharedData val = (((Object)(object)drop == (Object)null) ? null : drop.m_itemData.m_shared); if (val != null && !inputs.Contains(val)) { inputs.Add(val); } } private static void Keep(List<Step> steps, Step step) { if (step.Result != null) { steps.Add(step); } } private static Dictionary<SharedData, List<Step>> Producers(List<Step> steps) { Dictionary<SharedData, List<Step>> dictionary = new Dictionary<SharedData, List<Step>>(); foreach (Step step in steps) { if (!dictionary.TryGetValue(step.Result, out var value)) { value = new List<Step>(); dictionary[step.Result] = value; } value.Add(step); } return dictionary; } private static void Settle(List<Piece> pieces, Dictionary<CraftingStation, int> stations, Dictionary<SharedData, List<Step>> producers, int[] pieceDepth, Dictionary<SharedData, int> made) { bool flag = true; for (int i = 0; i < 32 && flag; i++) { flag = false; for (int j = 0; j < pieces.Count; j++) { Piece val = pieces[j]; if ((Object)(object)val == (Object)null) { continue; } int num = StationDepth(stations, pieceDepth, val.m_craftingStation); Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && (Object)(object)val2.m_resItem != (Object)null) { num = Math.Max(num, Depth(made, val2.m_resItem.m_itemData.m_shared)); } } if (num + 1 > pieceDepth[j]) { pieceDepth[j] = num + 1; flag = true; } } foreach (KeyValuePair<SharedData, List<Step>> producer in producers) { int num2 = int.MaxValue; foreach (Step item in producer.Value) { num2 = Math.Min(num2, StepDepth(item, made, pieceDepth)); } if (num2 != int.MaxValue && num2 > Depth(made, producer.Key)) { made[producer.Key] = num2; flag = true; } } } } private static Dictionary<SharedData, int> Uses(List<Step> steps, List<Piece> pieces, Dictionary<SharedData, int> made, int[] pieceDepth) { Dictionary<SharedData, int> dictionary = new Dictionary<SharedData, int>(); foreach (Step step in steps) { int depth = StepDepth(step, made, pieceDepth); foreach (SharedData input in step.Inputs) { Lower(dictionary, input, depth); } } for (int i = 0; i < pieces.Count; i++) { Piece val = pieces[i]; if ((Object)(object)val == (Object)null) { continue; } Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && (Object)(object)val2.m_resItem != (Object)null) { Lower(dictionary, val2.m_resItem.m_itemData.m_shared, pieceDepth[i]); } } } return dictionary; } private static Dictionary<SharedData, int> Depths(Dictionary<SharedData, int> made, Dictionary<SharedData, int> used) { Dictionary<SharedData, int> dictionary = new Dictionary<SharedData, int>(); foreach (KeyValuePair<SharedData, int> item in used) { if (Material(item.Key)) { dictionary[item.Key] = item.Value; } } foreach (KeyValuePair<SharedData, int> item2 in made) { if (Material(item2.Key) && !dictionary.ContainsKey(item2.Key)) { dictionary[item2.Key] = item2.Value; } } return dictionary; } private static Dictionary<SharedData, SharedData> Families(List<Step> steps) { Dictionary<SharedData, SharedData> dictionary = new Dictionary<SharedData, SharedData>(); foreach (Step step in steps) { if (!Material(step.Result)) { continue; } foreach (SharedData input in step.Inputs) { if (Material(input)) { Union(dictionary, step.Result, input); } } } return dictionary; } private static SharedData Find(Dictionary<SharedData, SharedData> parents, SharedData kind) { if (!parents.TryGetValue(kind, out var value)) { parents[kind] = kind; return kind; } if (value == kind) { return kind; } return parents[kind] = Find(parents, value); } private static void Union(Dictionary<SharedData, SharedData> parents, SharedData a, SharedData b) { SharedData val = Find(parents, a); SharedData val2 = Find(parents, b); if (val != val2) { parents[val2] = val; } } private static int CompareGroups(Group a, Group b) { int num = a.Low.CompareTo(b.Low); if (num == 0) { return string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase); } return num; } private static int StepDepth(Step step, Dictionary<SharedData, int> made, int[] pieceDepth) { int num = ((step.Station >= 0) ? (pieceDepth[step.Station] + step.Level) : step.Level); foreach (SharedData input in step.Inputs) { num = Math.Max(num, Depth(made, input)); } return num + 1; } private static int StationPiece(Dictionary<CraftingStation, int> stations, CraftingStation station) { if (!((Object)(object)station != (Object)null) || !stations.TryGetValue(station, out var value)) { return -1; } return value; } private static int StationDepth(Dictionary<CraftingStation, int> stations, int[] pieceDepth, CraftingStation station) { int num = StationPiece(stations, station); if (num < 0) { return 0; } return pieceDepth[num]; } private static int Depth(Dictionary<SharedData, int> depths, SharedData kind) { if (kind == null || !depths.TryGetValue(kind, out var value)) { return 0; } return value; } private static void Lower(Dictionary<SharedData, int> depths, SharedData kind, int depth) { if (kind != null && (!depths.TryGetValue(kind, out var value) || depth < value)) { depths[kind] = depth; } } private static bool Material(SharedData kind) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if (kind != null) { return (int)kind.m_itemType == 1; } return false; } private static string Label(SharedData kind) { Localization instance = Localization.instance; if (instance == null) { return kind.m_name; } return instance.Localize(kind.m_name); } } internal static class NearbyChests { private sealed class Entry { public Container Container; public Piece Piece; public bool Tombstone; } internal readonly struct Scope : IDisposable { private readonly bool entered; internal Scope(Tweak tweak, Humanoid user) { entered = EnterReach(tweak, user); } public void Dispose() { LeaveReach(entered); } } [HarmonyPatch(typeof(Inventory), "CountItems")] [Serves(new Type[] { typeof(NearbyCrafting), typeof(StationRefill) })] private static class CountChests { private static void Postfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { if (InReach && name != null && IsBackpack(__instance)) { __result += InChests(name, quality, matchWorldLevel); } } } [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] [Serves(new Type[] { typeof(NearbyCrafting), typeof(StationRefill) })] private static class HaveInChests { private static void Postfix(Inventory __instance, string name, bool matchWorldLevel, ref bool __result) { if (!__result && InReach && name != null && IsBackpack(__instance)) { __result = InChests(name, -1, matchWorldLevel) > 0; } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] [Serves(new Type[] { typeof(NearbyCrafting), typeof(StationRefill) })] private static class TakeFromChests { private static void Prefix(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!InReach || name == null || !IsBackpack(__instance)) { return; } int num = Carried(__instance, name, itemQuality, worldLevelBased); if (amount <= num) { return; } int num2 = amount - num; amount = num; foreach (Container item in new List<Container>(Find(((Component)Player.m_localPlayer).transform.position, ReachRange))) { if (num2 <= 0) { break; } Inventory inventory = item.GetInventory(); if (inventory.CountItems(name, itemQuality, worldLevelBased) > 0 && Claim(item)) { int num3 = Mathf.Min(num2, inventory.CountItems(name, itemQuality, worldLevelBased)); if (num3 > 0) { inventory.RemoveItem(name, num3, itemQuality, worldLevelBased); num2 -= num3; } } } counts.Clear(); } } private readonly struct CountKey : IEquatable<CountKey> { private readonly string name; private readonly int quality; private readonly bool matchWorldLevel; public CountKey(string name, int quality, bool matchWorldLevel) { this.name = name; this.quality = quality; this.matchWorldLevel = matchWorldLevel; } public bool Equals(CountKey other) { if (quality == other.quality && matchWorldLevel == other.matchWorldLevel) { return string.Equals(name, other.name, StringComparison.Ordinal); } return false; } public override bool Equals(object obj) { if (obj is CountKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (((name.GetHashCode() * 397) ^ quality) * 397) ^ (matchWorldLevel ? 1 : 0); } } [HarmonyPatch(typeof(Container), "Awake")] [Serves(new Type[] { typeof(QuickStack), typeof(StationRefill), typeof(NearbyCrafting) })] [LoadHook] private static class Register { private static void Postfix(Container __instance) { if (__instance.m_inventory != null) { Registry.Add(new Entry { Container = __instance, Piece = ((Component)__instance).GetComponentInParent<Piece>(), Tombstone = ((Object)(object)((Component)__instance).GetComponent<TombStone>() != (Object)null) }); } } } [HarmonyPatch(typeof(Container), "GetHoverText")] [Serves(new Type[] { typeof(QuickStack), typeof(StationRefill), typeof(NearbyCrafting) }, Optional = true)] private static class HoverText { private static void Prepare() { PanelButtons.Add(NearbyUse, PanelButtons.Spot.TakeAll, ShowsNearbyUse, RefreshNearbyUse); } private static void Postfix(Container __instance, ref string __result) { if (AnyTweakOn && IsExcluded(__instance)) { __result = __result + "\n<color=#a0a0a0>" + Localization.instance.Localize("$omp_nearby_off") + "</color>"; } } } private static readonly int ExcludedHash = StringExtensionMethods.GetStableHashCode("OMP_NoNearbyUse"); private static readonly List<Entry> Registry = new List<Entry>(); private static readonly List<Container> Found = new List<Container>(); private static int reachDepth; private static readonly Dictionary<CountKey, int> counts = new Dictionary<CountKey, int>(); private static int countsFrame = -1; private static readonly PanelButtons.TextButton NearbyUse = new PanelButtons.TextButton("OMP_NearbyUse", new UnityAction(Toggle)); internal static bool AnyTweakOn => Patcher.AnyServedOn(typeof(Register)); private static bool InReach => reachDepth > 0; private static float ReachRange => SharedSettings.ChestRange.Value; internal static List<Container> Find(Vector3 origin) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Find(origin, SharedSettings.ChestRange.Value); } internal static List<Container> Find(Vector3 origin, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) Found.Clear(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return Found; } long playerID = localPlayer.GetPlayerID(); float num = radius * radius; for (int num2 = Registry.Count - 1; num2 >= 0; num2--) { Entry entry = Registry[num2]; if ((Object)(object)entry.Container == (Object)null) { Registry.RemoveAt(num2); } else { Vector3 val = ((Component)entry.Container).transform.position - origin; if (!(((Vector3)(ref val)).sqrMagnitude > num) && IsInReach(entry, playerID)) { Found.Add(entry.Container); } } } Found.Sort(delegate(Container a, Container b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)a).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; val2 = ((Component)b).transform.position - origin; return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude); }); return Found; } private static bool IsInReach(Entry entry, long playerId) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Invalid comparison between Unknown and I4 //IL_00d5: Unknown result type (might be due to invalid IL or missing references) Container container = entry.Container; if (!Eligible(entry) || container.m_inventory == null) { return false; } ZNetView nview = container.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } if (nview.GetZDO().GetBool(ExcludedHash, false)) { return false; } InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_currentContainer == (Object)(object)container)) { if (container.IsInUse() || nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1) { return false; } if ((Object)(object)container.m_wagon != (Object)null && container.m_wagon.InUse()) { return false; } } if ((int)container.m_privacy != 2 && (Object)(object)container.m_piece == (Object)null) { return false; } if (!container.CheckAccess(playerId)) { return false; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false)) { return false; } return true; } internal static bool Claim(Container chest) { if ((Object)(object)chest == (Object)null) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } Entry entry = Registry.Find((Entry e) => (Object)(object)e.Container == (Object)(object)chest); if (entry == null || !IsInReach(entry, localPlayer.GetPlayerID())) { return false; } ZNetView nview = chest.m_nview; chest.Load(); if (!nview.IsOwner()) { nview.ClaimOwnership(); } return nview.IsOwner(); } private static bool Eligible(Container chest) { return Eligible(Registry.Find((Entry e) => (Object)(object)e.Container == (Object)(object)chest)); } private static bool Eligible(Entry entry) { if (entry != null && !entry.Tombstone && (Object)(object)entry.Piece != (Object)null) { return entry.Piece.IsPlacedByPlayer(); } return false; } internal static bool IsExcluded(Container chest) { ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null); if ((Object)(object)val != (Object)null && val.IsValid()) { return val.GetZDO().GetBool(ExcludedHash, false); } return false; } private static void SetExcluded(Container chest, bool excluded) { ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null); if (!((Object)(object)val == (Object)null) && val.IsValid()) { if (!val.IsOwner()) { val.ClaimOwnership(); } if (val.IsOwner()) { val.GetZDO().Set(ExcludedHash, excluded); } } } internal static bool EnterReach(Tweak tweak, Humanoid user) { if (!tweak.On || (Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return false; } reachDepth++; return true; } internal static void LeaveReach(bool entered) { if (entered && reachDepth > 0) { reachDepth--; } } private static bool IsBackpack(Inventory inventory) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return inventory == ((Humanoid)localPlayer).GetInventory(); } return false; } internal static int Carried(Inventory inventory, string name, int quality, bool matchWorldLevel) { int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_shared.m_name == name && (quality < 0 || allItem.m_quality == quality) && (!matchWorldLevel || allItem.m_worldLevel >= Game.m_worldLevel)) { num += allItem.m_stack; } } return num; } private static int InChests(string name, int quality, bool matchWorldLevel) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (Time.frameCount != countsFrame) { counts.Clear(); countsFrame = Time.frameCount; } CountKey key = new CountKey(name, quality, matchWorldLevel); if (counts.TryGetValue(key, out var value)) { return value; } foreach (Container item in Find(((Component)Player.m_localPlayer).transform.position, ReachRange)) { value += item.GetInventory().CountItems(name, quality, matchWorldLevel); } counts[key] = value; return value; } private static bool ShowsNearbyUse(InventoryGui gui) { Container currentContainer = gui.m_currentContainer; if ((Object)(object)currentContainer != (Object)null && (Object)(object)gui.m_container != (Object)null && ((Component)gui.m_container).gameObject.activeSelf && AnyTweakOn) { return Eligible(currentContainer); } return false; } private static void RefreshNearbyUse(InventoryGui gui) { NearbyUse.SetLabel(IsExcluded(gui.m_currentContainer) ? "$omp_nearby_off" : "$omp_nearby_on"); NearbyUse.SetTooltip("$omp_nearby_topic", "$omp_nearby_tip"); } private static void Toggle() { InventoryGui instance = InventoryGui.instance; Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); if ((Object)(object)val != (Object)null) { SetExcluded(val, !IsExcluded(val)); } } } [BepInPlugin("rauschekuh.odinsreach", "Odin's Reach", "0.1.0")] public class OdinsReachPlugin : BaseUnityPlugin { public const string GUID = "rauschekuh.odinsreach"; public const string NAME = "Odin's Reach"; public const string VERSION = "0.1.0"; private static readonly Tweak[] Tweaks = new Tweak[5] { NearbyCrafting.Instance, QuickStack.Instance, StationRefill.Instance, ChestButtons.Instance, InventoryButtons.Instance }; private void Awake() { TweakHost.Start((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config, "rauschekuh.odinsreach", Tweaks, SharedSettings.Bind); } } internal static class PanelButtons { internal enum Column { Inventory, Chest } internal enum Spot { TakeAll, StackAll } private sealed class IconEntry { internal Column Column; internal int Order; internal string Name; internal string Icon; internal string Title; internal Func<string> Tooltip; internal UnityAction OnClick; internal Func<InventoryGui, bool> Visible; internal Button Button; internal UITooltip Tip; } private sealed class TextEntry { internal TextButton Button; internal Spot Spot; internal Func<InventoryGui, bool> Visible; internal Action<InventoryGui> Refresh; } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] [Serves(new Type[] { typeof(ChestButtons), typeof(InventoryButtons) })] private static class LayOut { private static void Postfix(InventoryGui __instance) { Arrange(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] [Serves(new Type[] { typeof(QuickStack), typeof(StationRefill), typeof(NearbyCrafting) }, Optional = true)] private static class LayOutText { private static void Postfix(InventoryGui __instance) { Arrange(__instance); } } [HarmonyPatch(typeof(InventoryGui), "OnDestroy")] [Serves(new Type[] { typeof(ChestButtons), typeof(InventoryButtons) })] private static class ScreenDestroyed { private static void Postfix() { foreach (IconEntry iconButton in iconButtons) { iconButton.Button = null; } foreach (TextEntry textButton in textButtons) { textButton.Button.Forget(); } vanillaHidden = false; } } internal sealed class TextButton { private const float Margin = 16f; private readonly string name; private readonly UnityAction onClick; private Button button; private UITooltip tip; private string label; private string tooltip; private Component labelText; private PropertyInfo labelWidth; internal TextButton(string name, UnityAction onClick) { this.name = name; this.onClick = onClick; } internal bool Show(InventoryGui gui) { if ((Object)(object)button == (Object)null && !Create(gui)) { return false; } ((Component)button).gameObject.SetActive(true); return true; } internal void Hide() { if ((Object)(object)button != (Object)null) { ((Component)button).gameObject.SetActive(false); } } internal void Forget() { button = null; } internal void Place(InventoryGui gui, Button at, bool keepLeft, int slot) { //IL_001c: 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) //IL_003d: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_014e: 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) RectTransform val = ((!((Object)(object)gui.m_takeAllButton != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)gui.m_takeAllButton).transform)); if (!((Object)(object)val == (Object)null)) { Rect rect = val.rect; float height = ((Rect)(ref rect)).height; rect = val.rect; float num = Mathf.Max(((Rect)(ref rect)).width, LabelWidth() + 32f); RectTransform val2 = (RectTransform)((Component)button).transform; val2.sizeDelta = new Vector2(num, height); RectTransform val3 = ((!((Object)(object)at != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)at).transform)); if ((Object)(object)val3 == (Object)null) { RectTransform container = gui.m_container; Pin(val2, new Vector2(ColumnLeft(container) + num * 0.5f, ColumnTop(container) - height * 0.5f - (float)slot * (height + 6f))); return; } val2.anchorMin = val3.anchorMin; val2.anchorMax = val3.anchorMax; val2.pivot = val3.pivot; rect = val3.rect; float num2 = num - ((Rect)(ref rect)).width; val2.anchoredPosition = val3.anchoredPosition + new Vector2(keepLeft ? (num2 * (1f - val3.pivot.x)) : ((0f - num2) * val3.pivot.x), 0f); } } private float LabelWidth() { if ((Object)(object)labelText == (Object)null) { Transform val = ((Component)button).transform.Find("Text"); if ((Object)(object)val == (Object)null) { return 0f; } Component[] components = ((Component)val).GetComponents<Component>(); foreach (Component val2 in components) { PropertyInfo property = ((object)val2).GetType().GetProperty("preferredWidth", typeof(float)); if (property != null && property.CanRead) { labelText = val2; labelWidth = property; break; } } } if (!((Object)(object)labelText != (Object)null)) { return 0f; } return (float)labelWidth.GetValue(labelText, null); } private bool Create(InventoryGui gui) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown Button takeAllButton = gui.m_takeAllButton; if ((Object)(object)takeAllButton == (Object)null) { return false; } GameObject val = Object.Instantiate<GameObject>(((Component)takeAllButton).gameObject, ((Component)takeAllButton).transform.parent); ((Object)val).name = name; button = val.GetComponent<Button>(); if ((Object)(object)button == (Object)null) { Object.Destroy((Object)(object)val); return false; } button.onClick = new ButtonClickedEvent(); ((UnityEvent)button.onClick).AddListener(onClick); val.transform.SetSiblingIndex(((Component)takeAllButton).transform.GetSiblingIndex()); tip = Tooltip(gui, val); label = null; tooltip = null; labelText = null; labelWidth = null; return true; } internal void SetLabel(string text, params string[] words) { if (Localization.instance != null) { text = Localization.instance.Localize(text, words); } if (text == label) { return; } label = text; Component[] componentsInChildren = ((Component)button).GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { PropertyInfo property = ((object)val).GetType().GetProperty("text", typeof(string)); if (property != null && property.CanWrite) { property.SetValue(val, text, null); } } } internal void SetTooltip(string topic, string text) { if (!(text == tooltip) && !((Object)(object)tip == (Object)null)) { tooltip = text; tip.m_topic = topic; tip.m_text = text; } } } private const float Gap = 6f; private static readonly List<IconEntry> iconButtons = new List<IconEntry>(); private static readonly List<TextEntry> textButtons = new List<TextEntry>(); private static bool vanillaHidden; private static int arrangedFrame = -1; internal static void Add(Column column, int order, string name, string icon, string title, string tooltip, UnityAction onClick, Func<InventoryGui, bool> visible) { Add(column, order, name, icon, title, () => tooltip, onClick, visible); } internal static void Add(Column column, int order, string name, string icon, string title, Func<string> tooltip, UnityAction onClick, Func<InventoryGui, bool> visible) { iconButtons.Add(new IconEntry { Column = column, Order = order, Name = name, Icon = icon, Title = title, Tooltip = tooltip, OnClick = onClick, Visible = visible }); iconButtons.Sort((IconEntry a, IconEntry b) => (a.Column == b.Column) ? a.Order.CompareTo(b.Order) : a.Column.CompareTo(b.Column)); } internal static void Add(TextButton button, Spot spot, Func<InventoryGui, bool> visible, Action<InventoryGui> refresh) { if (!textButtons.Exists((TextEntry e) => e.Button == button)) { textButtons.Add(new TextEntry { Button = button, Spot = spot, Visible = visible, Refresh = refresh }); textButtons.Sort((TextEntry a, TextEntry b) => a.Spot.CompareTo(b.Spot)); } } private static float Size(InventoryGui gui) { //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_0032: Unknown result type (might be due to invalid IL or missing references) Button val = (((Object)(object)gui != (Object)null) ? gui.m_takeAllButton : null); if (!((Object)(object)val != (Object)null)) { return 32f; } Rect rect = ((RectTransform)((Component)val).transform).rect; return ((Rect)(ref rect)).height; } private static Button Create(InventoryGui gui, Transform parent, string name, string icon, string title, string tooltip, UnityAction onClick) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Button val = (((Object)(object)gui != (Object)null) ? gui.m_takeAllButton : null); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent); ((Object)val2).name = "OMP_" + name; Button component = val2.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return null; } component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener(onClick); ((Selectable)component).interactable = true; float num = Size(gui); ((RectTransform)val2.transform).sizeDelta = new Vector2(num, num); AddIcon(val2, icon, BlankLabel(val2), num); UITooltip val3 = Tooltip(gui, val2); if ((Object)(object)val3 != (Object)null) { val3.m_topic = title; val3.m_text = tooltip; } val2.SetActive(false); return component; } internal static bool Closing(InventoryGui gui) { Animator val = (((Object)(object)gui != (Object)null) ? gui.m_animator : null); if ((Object)(object)val != (Object)null) { return !val.GetBool("visible"); } return false; } private static void Arrange(InventoryGui gui) { if (Closing(gui) || arrangedFrame == Time.frameCount) { return; } arrangedFrame = Time.frameCount; bool flag = false; foreach (IconEntry iconButton in iconButtons) { bool flag2 = iconButton.Visible(gui) && ((Object)(object)iconButton.Button != (Object)null || Build(gui, iconButton)); if ((Object)(object)iconButton.Button != (Object)null) { ((Component)iconButton.Button).gameObject.SetActive(flag2); } if (flag2 && (Object)(object)iconButton.Tip != (Object)null) { string text = iconButton.Tooltip(); if ((object)iconButton.Tip.m_text != text) { iconButton.Tip.m_text = text; } } flag |= flag2 && iconButton.Column == Column.Chest; } SetVanilla(gui, !flag); int num = LayoutChestColumn(gui); LayoutInventoryColumn(gui); foreach (TextEntry textButton in textButtons) { if (!textButton.Visible(gui) || !textButton.Button.Show(gui)) { textButton.Button.Hide(); continue; } textButton.Refresh(gui); Button val = ((!vanillaHidden) ? null : ((textButton.Spot == Spot.TakeAll) ? gui.m_takeAllButton : gui.m_stackAllButton)); textButton.Button.Place(gui, val, textButton.Spot == Spot.TakeAll, num); if ((Object)(object)val == (Object)null) { num++; } } } private static bool Build(InventoryGui gui, IconEntry entry) { Transform val = (Transform)(object)((entry.Column == Column.Chest) ? gui.m_container : gui.m_player); if ((Object)(object)val == (Object)null) { return false; } entry.Button = Create(gui, val, entry.Name, entry.Icon, entry.Title, entry.Tooltip(), entry.OnClick); if ((Object)(object)entry.Button == (Object)null) { return false; } entry.Tip = ((Component)entry.Button).GetComponent<UITooltip>(); return true; } private static void SetVanilla(InventoryGui gui, bool active) { if (active != !vanillaHidden) { vanillaHidden = !active; if ((Object)(object)gui.m_takeAllButton != (Object)null) { ((Component)gui.m_takeAllButton).gameObject.SetActive(active); } if ((Object)(object)gui.m_stackAllButton != (Object)null) { ((Component)gui.m_stackAllButton).gameObject.SetActive(active); } } } private static void Pin(RectTransform rect, Vector2 center) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.zero; rect.pivot = new Vector2(0.5f, 0.5f); rect.anchoredPosition = center; } private static Vector2 Overhang(RectTransform panel) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Transform obj = ((Transform)panel).Find("Bkg"); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if ((Object)(object)val != (Object)null && val.anchorMin == Vector2.zero && val.anchorMax == Vector2.one) { return Vector2.Max(Vector2.zero, val.sizeDelta * 0.5f); } return new Vector2(10f, 10f); } private static float ColumnLeft(RectTransform panel) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Rect rect = panel.rect; return ((Rect)(ref rect)).width + Overhang(panel).x + 6f; } private static float ColumnTop(RectTransform panel) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Rect rect = panel.rect; return ((Rect)(ref rect)).height + Overhang(panel).y; } private static RectTransform Box(InventoryGui gui, string field, RectTransform panel, string name) { FieldInfo field2 = typeof(InventoryGui).GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Component val = (Component)((field2 != null) ? /*isinst with value type is only supported in some contexts*/: null); RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null && (Object)(object)panel != (Object)null) { Transform obj = ((Transform)panel).Find(name); val2 = (RectTransform)(object)((obj is RectTransform) ? obj : null); } return val2; } private static Rect InPanel(RectTransform panel, RectTransform rect) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0054: 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) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00ba: Unknown result type (might be due to invalid IL or missing references) Rect rect2 = rect.rect; Vector3 val = ((Transform)panel).InverseTransformPoint(((Transform)rect).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect2)).min))); rect2 = rect.rect; Vector3 val2 = ((Transform)panel).InverseTransformPoint(((Transform)rect).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect2)).max))); Vector2 pivot = panel.pivot; rect2 = panel.rect; Vector2 val3 = Vector2.Scale(pivot, ((Rect)(ref rect2)).size); return Rect.MinMaxRect(Mathf.Min(val.x, val2.x) + val3.x, Mathf.Min(val.y, val2.y) + val3.y, Mathf.Max(val.x, val2.x) + val3.x, Mathf.Max(val.y, val2.y) + val3.y); } private static bool Showing(IconEntry entry, Column column) { if (entry.Column == column && (Object)(object)entry.Button != (Object)null) { return ((Component)entry.Button).gameObject.activeSelf; } return false; } private static void LayoutInventoryColumn(InventoryGui gui) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown RectTransform val = (((Object)(object)gui != (Object)null) ? gui.m_player : null); if ((Object)(object)val == (Object)null) { return; } float num = Size(gui); int num2 = 0; foreach (IconEntry iconButton in iconButtons) { if (Showing(iconButton, Column.Inventory)) { num2++; } } if (num2 == 0) { return; } RectTransform val2 = Box(gui, "m_armor", val, "Armor"); RectTransform val3 = Box(gui, "m_weight", val, "Weight"); Rect val4; float num3; if (!((Object)(object)val2 != (Object)null)) { val4 = val.rect; num3 = ((Rect)(ref val4)).height; } else { val4 = InPanel(val, val2); num3 = ((Rect)(ref val4)).yMin; } float num4; if (!((Object)(object)val3 != (Object)null)) { num4 = 0f; } else { val4 = InPanel(val, val3); num4 = ((Rect)(ref val4)).yMax; } float num5 = num4; float num6 = (float)num2 * num + (float)(num2 - 1) * 6f; float num7 = ColumnLeft(val) + num * 0.5f; float num8 = (num3 + num5) * 0.5f + num6 * 0.5f - num * 0.5f; foreach (IconEntry iconButton2 in iconButtons) { if (Showing(iconButton2, Column.Inventory)) { RectTransform val5 = (RectTransform)((Component)iconButton2.Button).transform; val5.sizeDelta = new Vector2(num, num); Pin(val5, new Vector2(num7, num8)); num8 -= num + 6f; } } } private static int LayoutChestColumn(InventoryGui gui) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown RectTransform val = (((Object)(object)gui != (Object)null) ? gui.m_container : null); if ((Object)(object)val == (Object)null) { return 0; } float num = Size(gui); float num2 = ColumnLeft(val) + num * 0.5f; float num3 = ColumnTop(val) - num * 0.5f; int num4 = 0; foreach (IconEntry iconButton in iconButtons) { if (Showing(iconButton, Column.Chest)) { RectTransform val2 = (RectTransform)((Component)iconButton.Button).transform; val2.sizeDelta = new Vector2(num, num); Pin(val2, new Vector2(num2, num3)); num3 -= num + 6f; num4++; } } return num4; } private static Color BlankLabel(GameObject go) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) Color result = Color.white; Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { PropertyInfo property = ((object)val).GetType().GetProperty("text", typeof(string)); if (!(property == null) && property.CanWrite) { Graphic val2 = (Graphic)(object)((val is Graphic) ? val : null); if (val2 != null) { result = val2.color; } property.SetValue(val, "", null); } } return result; } private static void AddIcon(GameObject go, string icon, Color tint, float size) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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) //IL_0092: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("icon", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(go.transform, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; float num = size * 0.2f; val2.offsetMin = new Vector2(num, num); val2.offsetMax = new Vector2(0f - num, 0f - num); Image component = val.GetComponent<Image>(); component.sprite = UiAssets.Icon(icon); ((Graphic)component).color = tint; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; ((Behaviour)component).enabled = (Object)(object)component.sprite != (Object)null; } internal static UITooltip Tooltip(InventoryGui gui, GameObject go) { UITooltip val = go.GetComponent<UITooltip>(); if ((Object)(object)val == (Object)null) { GameObject val2 = UiAssets.TooltipPrefab(gui); if ((Object)(object)val2 == (Object)null) { return null; } val = go.AddComponent<UITooltip>(); val.m_tooltipPrefab = val2; } else if ((Object)(object)val.m_tooltipPrefab == (Object)null) { val.m_tooltipPrefab = UiAssets.TooltipPrefab(gui); } return val; } } internal static class SharedSettings { internal const string Section = "General"; internal static ConfigEntry<float> ChestRange; internal static ConfigEntry<bool> KeepHotbar; internal static void Bind(ConfigFile config) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown ChestRange = config.Bind<float>("General", "ChestRange", 20f, new ConfigDescription("How far from you a chest may stand, in metres, for nearby crafting, quick stack and station refill to use it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); KeepHotbar = config.Bind<bool>("General", "KeepHotbar", true, "Quick stack, Place all, Fill the chest and Sort leave the hotbar row alone. Off lets them move it too."); } internal static bool OnKeptHotbar(ItemData item) { if (KeepHotbar.Value) { return item.m_gridPos.y == 0; } return false; } } internal static class Stash { internal static bool StaysPut(Player player, ItemData item) { if (!item.m_equipped && !((Humanoid)player).IsItemEquiped(item)) { return QuickStack.IsFavorite(item); } return true; } internal static bool MayLeave(Player player, ItemData item) { if (!StaysPut(player, item)) { return !SharedSettings.OnKeptHotbar(item); } return false; } internal static bool Takes(Inventory chest, string marks, string itemName) { if (!chest.ContainsItemByName(itemName)) { return ChestFavorites.Marked(marks, itemName); } return true; } internal static int Move(ItemData item, Inventory from, Inventory to) { if (!to.HaveEmptySlot() && to.FindFreeStackSpace(item.m_shared.m_name, (float)item.m_worldLevel) <= 0) { return 0; } int stack = item.m_stack; if (to.AddItem(item)) { from.RemoveItem(item); return stack; } int num = stack - item.m_stack; if (num > 0) { from.Changed(false, false); } return num; } internal static int TopUp(Inventory target, Inventory source, Func<ItemData, bool> fills = null) { int num = 0; foreach (ItemData item in new List<ItemData>(source.GetAllItems())) { if (item.m_shared.m_maxStackSize <= 1) { continue; } int stack = item.m_stack; foreach (ItemData allItem in target.GetAllItems()) { if (item.m_stack <= 0) { break; } if (InventorySorter.Merges(allItem, item) && (fills == null || fills(allItem))) { int num2 = Mathf.Min(allItem.m_shared.m_maxStackSize - allItem.m_stack, item.m_stack); allItem.m_stack += num2; item.m_stack -= num2; } } if (item.m_stack != stack) { num += stack - item.m_stack; if (item.m_stack <= 0) { source.RemoveItem(item); } } } if (num > 0) { target.Changed(false, false); source.Changed(false, false); } return num; } } internal sealed class ChestButtons : Tweak { [CompilerGenerated] private static class <>O { public static UnityAction <0>__FillInventory; public static Func<InventoryGui, bool> <1>__ChestShown; public static UnityAction <2>__TakeAll; public static UnityAction <3>__PlaceAll; public static UnityAction <4>__FillChest; public static UnityAction <5>__SortChest; } internal static readonly ChestButtons Instance = new ChestButtons(); internal override string Section => "Chest Buttons"; protected override string Summary => "Replaces the chest panel's Take all and Stack all with icon buttons beside the panels: fill your stacks from the chest in the column beside the inventory; take all, place all, fill the chest's stacks from your backpack and sort the chest in a column down the side of the chest."; private ChestButtons() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown Func<string> tooltip = () => QuickStack.Instance.FillInventoryTip(); object obj = <>O.<0>__FillInventory; if (obj == null) { UnityAction val = FillInventory; <>O.<0>__FillInventory = val; obj = (object)val; } PanelButtons.Add(PanelButtons.Column.Inventory, 0, "FillInventory", "fill_inventory", "$omp_fill_inventory", tooltip, (UnityAction)obj, ChestShown); object obj2 = <>O.<2>__TakeAll; if (obj2 == null) { UnityAction val2 = TakeAll; <>O.<2>__TakeAll = val2; obj2 = (object)val2; } PanelButtons.Add(PanelButtons.Column.Chest, 0, "TakeAll", "take_all", "$omp_take_all", "$omp_take_all_tip", (UnityAction)obj2, ChestShown); object obj3 = <>O.<3>__PlaceAll; if (obj3 == null) { UnityAction val3 = PlaceAll; <>O.<3>__PlaceAll = val3; obj3 = (object)val3; } PanelButtons.Add(PanelButtons.Column.Chest, 1, "PlaceAll", "place_all", "$omp_place_all", "$omp_place_all_tip", (UnityAction)obj3, ChestShown); object obj4 = <>O.<4>__FillChest; if (obj4 == null) { UnityAction val4 = FillChest; <>O.<4>__FillChest = val4; obj4 = (object)val4; } PanelButtons.Add(PanelButtons.Column.Chest, 2, "FillChest", "fill_chest", "$omp_fill_chest", "$omp_fill_chest_tip", (UnityAction)obj4, ChestShown); object obj5 = <>O.<5>__SortChest; if (obj5 == null) { UnityAction val5 = SortChest; <>O.<5>__SortChest = val5; obj5 = (object)val5; } PanelButtons.Add(PanelButtons.Column.Chest, 3, "Sort", "sort", "$omp_sort_chest", "$omp_sort_chest_tip", (UnityAction)obj5, ChestShown); } private static bool ChestShown(InventoryGui gui) { RectTransform container = gui.m_container; if (Instance.On && (Object)(object)gui.m_currentContainer != (Object)null && (Object)(object)container != (Object)null) { return ((Component)container).gameObject.activeSelf; } return false; } private static InventoryGui Ready(out Player player, out Container chest) { InventoryGui instance = InventoryGui.instance; player = Player.m_localPlayer; chest = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null || ((Character)player).IsTeleporting() || (Object)(object)chest == (Object)null || !chest.IsOwner()) { return null; } return instance; } private static void TakeAll() { Player player; Container chest; InventoryGui val = Ready(out player, out chest); if ((Object)(object)val != (Object)null) { val.OnTakeAll(); } } private static void FillInventory() { Player player; Container chest; InventoryGui val = Ready(out player, out chest); if (!((Object)(object)val == (Object)null)) { val.SetupDragItem((ItemData)null, (Inventory)null, 1); int moved = Stash.TopUp(((Humanoid)player).GetInventory(), chest.GetInventory()); Report(val, player, moved, "$omp_took", "$omp_took_none"); } } private static void FillChest() { Player player; Container chest; InventoryGui val = Ready(out player, out chest); if (!((Object)(object)val == (Object)null)) { val.SetupDragItem((ItemData)null, (Inventory)null, 1); int moved = MoveToChest(player, chest, onlyExisting: true); Report(val, player, moved, "$omp_stacked_chest", "$omp_stacked_chest_none"); } } private static void PlaceAll() { Player player; Container chest; InventoryGui val = Ready(out player, out chest); if (!((Object)(object)val == (Object)null)) { val.SetupDragItem((ItemData)null, (Inventory)null, 1); int moved = MoveToChest(player, chest, onlyExisting: false); Report(val, player, moved, "$omp_placed", "$omp_placed_none"); } } private static void SortChest() { Player player; Container chest; InventoryGui val = Ready(out player, out chest); if (!((Object)(object)val == (Object)null)) { val.SetupDragItem((ItemData)null, (Inventory)null, 1); InventorySorter.Sort(chest.GetInventory(), 0, null); } } private static void Report(InventoryGui gui, Player player, int moved, string done, string nothing) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (moved > 0) { gui.m_moveItemEffects.Create(((Component)gui).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } ((Character)player).Message((MessageType)2, (moved > 0) ? Localization.instance.Localize(done, new string[1] { moved.ToString() }) : nothing, 0, (Sprite)null, false); } private static int MoveToChest(Player player, Container container, bool onlyExisting) { Inventory inventory = ((Humanoid)player).GetInventory(); Inventory inventory2 = container.GetInventory(); string marks = ChestFavorites.Marks(container); int num = 0; foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (Stash.MayLeave(player, item) && (!onlyExisting || Stash.Takes(inventory2, marks, item.m_shared.m_name))) { num += Stash.Move(item, inventory, inventory2); } } return num; } } internal sealed class InventoryButtons : Tweak { [CompilerGenerated] private static class <>O { public static UnityAction <0>__StackNearby; public static UnityAction <1>__SortInventory; } internal static readonly InventoryButtons Instance = new InventoryButtons(); internal override string Section => "Inventory Buttons"; protected override string Summary => "Two icon buttons beside the inventory panel: stack nearby (quick stacking by click, while Quick Stack is on and no chest is open) and sort."; private InventoryButtons() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown Func<string> tooltip = () => QuickStack.Instance.StackNearbyTip(); object obj = <>O.<0>__StackNearby; if (obj == null) { UnityAction val = StackNearby; <>O.<0>__StackNearby = val; obj = (object)val; } PanelButtons.Add(PanelButtons.Column.Inventory, 10, "StackNearby", "stack_nearby", "$omp_stack_nearby", tooltip, (UnityAction)obj, (InventoryGui gui) => Instance.On && QuickStack.Instance.On && (Object)(object)gui.m_currentContainer == (Object)null); object obj2 = <>O.<1>__SortInventory; if (obj2 == null) { UnityAction val2 = SortInventory; <>O.<1>__SortInventory = val2; obj2 = (object)val2; } PanelButtons.Add(PanelButtons.Column.Inventory, 11, "SortInventory", "sort", "$omp_sort", "$omp_sort_tip", (UnityAction)obj2, (InventoryGui gui) => Instance.On); } private static void StackNearby() { InventoryGui instance = InventoryGui.instance; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)instance == (Object)null) && !((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsTeleporting() && QuickStack.Instance.On) { instance.SetupDragItem((ItemData)null, (Inventory)null, 1); QuickStack.Instance.Stack(localPlayer); } } private static void SortInventory() { InventoryGui instance = InventoryGui.instance; Player player = Player.m_localPlayer; if (!((Object)(object)instance == (Object)null) && !((Object)(object)player == (Object)null) && !((Character)player).IsTeleporting()) { instance.SetupDragItem((ItemData)null, (Inventory)null, 1); InventorySorter.Sort(((Humanoid)player).GetInventory(), SharedSettings.KeepHotbar.Value ? 1 : 0, (ItemData item) => Stash.StaysPut(player, item)); } } } internal sealed class NearbyCrafting : Tweak { [HarmonyPatch(typeof(Player), "HaveRequirementItems")] private static class RecipeScope { private static void Prefix(Player __instance, Recipe piece, out bool __state) { __state = (Object)(object)piece != (Object)null && !piece.m_requireOnlyOneIngredient && Enter(__instance); } private static void Finalizer(bool __state) { Leave(__state); } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] private static class BuildScope { private static void Prefix(Player __instance, out bool __state) { __state = Enter(__instance); } private static void Finalizer(bool __state) { Leave(__state); } } [HarmonyPatch(typeof(Player), "ConsumeResources")] private static class SpendScope { private static void Prefix(Player __instance, out bool __state) { __state = Enter(__instance); } private static void Finalizer(bool __state) { Leave(__state); } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] private static class RowScope { internal struct State { public bool Entered; public int Carried; } private static void Prefix(Requirement req, Player player, bool craft, out State __state) { __state = default(State); if (req != null && !((Object)(object)req.m_resItem == (Object)null) && (!craft || !SelectedRecipeTakesAnyOne())) { __state.Carried = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetInventory().CountItems(req.m_resItem.m_itemData.m_shared.m_name, -1, true) : 0); __state.Entered = Enter(player); } } private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier, bool __result, State __state) { //IL_0149: Unknown result type (might be due to invalid IL or missing references) if (!__state.Entered || !__result || (Object)(object)elementRoot == (Object)null) { return; } string name = req.m_resItem.m_itemData.m_shared.m_name; int num = ((Humanoid)player).GetInventory().CountItems(name, -1, true) - __state.Carried; if (num < 0) { num = 0; } UITooltip component = ((Component)elementRoot).GetComponent<UITooltip>(); if ((Object)(object)component != (Object)null) { Localization instance = Localization.instance; component.m_text = instance.Localize(name) + "\n" + instance.Localize("$omp_carried", new string[1] { __state.Carried.ToString() }) + "\n<color=#ffd64d>" + instance.Localize("$omp_from_chests", new string[1] { num.ToString() }) + "</color>"; } int num2 = req.GetAmount(quality) * craftMultiplier; if (!(craft ? ZoneSystem.instance.GetGlobalKey((GlobalKeys)25) : ZoneSystem.instance.GetGlobalKey((GlobalKeys)24)) && __state.Carried < num2 && __state.Carried + num >= num2) { Transform val = elementRoot.Find("res_amount"); Graphic val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Graphic>() : null); if ((Object)(object)val2 != (Object)null) { val2.color = Palette.ChestYellow; } } } private static void Finalizer(State __state) { Leave(__state.Entered); } private static bool SelectedRecipeTakesAnyOne() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && (Object)(object)((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe != (Object)null) { return ((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe.m_requireOnlyOneIngredient; } return false; } } internal static readonly NearbyCrafting Instance = new NearbyCrafting(); internal override string Section => "Nearby Crafting"; protected override string Summary => "Crafting, upgrading and building take their materials from chests around you (General.ChestRange), without opening them. Only chests placed by a player, and not chests switched off with the Nearby use button in their panel."; private NearbyCrafting() { } private static bool Enter(Player player) { return NearbyChests.EnterReach(Instance, (Humanoid)(object)player); } private static void Leave(bool entered) { NearbyChests.LeaveReach(entered); } } internal sealed class QuickStack : Tweak { [HarmonyPatch(typeof(Player), "Update")] private static class Hotkey { private static void Postfix(Player __instance) { //IL_002c: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) if (Instance.On && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && CanTakeHotkey(__instance) && Hotkeys.Pressed(Instance.hotkey.Value)) { KeyboardShortcut value = Instance.topUpModifier.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && Hotkeys.Held(Instance.topUpModifier.Value)) { Instance.TopUp(__instance); } else { Instance.Stack(__instance); } } } private static bool CanTakeHotkey(Player player) { if (((Character)player).TakeInput()) { return true; } if (InventoryGui.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !UnifiedPopup.IsVisible() && !((Character)player).IsDead()) { return !((Character)player).IsTeleporting(); } return false; } } [HarmonyPatch(typeof(InventoryGrid), "OnLeftDown")] private static class ToggleFavorite { private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || __instance.m_inventory == null || !Hotkeys.Held(Instance.favoriteModifier.Value)) { return true; } bool flag = __instance.m_inventory == ((Humanoid)localPlayer).GetInventory(); if (flag ? (!Instance.On) : (!ChestFavorites.Used)) { return true; } Vector2i buttonPos = __instance.GetButtonPos(((Component)clickHandler).gameObject); ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y); if (itemAt == null) { return true; } if (!flag) { return MarkChest(localPlayer, __instance.m_inventory, itemAt); } SetFavorite(itemAt, !IsFavorite(itemAt)); __instance.m_inventory.Changed(false, false); return false; } private static bool MarkChest(Player player, Inventory inventory, ItemData item) { Container val = ChestFavorites.OpenChest(inventory); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)2, "$omp_favourites_inventory", 0, (Sprite)null, false); return false; } string name = item.m_shared.m_name; bool flag = ChestFavorites.Toggle(val, name); ((Character)player).Message((MessageType)2, Localization.instance.Localize(flag ? "$omp_chest_takes" : "$omp_chest_takes_not", new string[1] { ChestFavorites.Localize(name) }), 0, (Sprite)null, false); return false; } } [HarmonyPatch(typeof(Inventory), "Changed")] private static class ClearOutsideBackpack { private static void Prefix(Inventory __instance) { Player localPlayer = Player.m_localPlayer; if (!Instance.On || (Object)(object)localPlayer == (Object)null || __instance == ((Humanoid)localPlayer).GetInventory()) { return; } foreach (ItemData allItem in __instance.GetAllItems()) { if (IsFavorite(allItem)) { SetFavorite(allItem, favorite: false); } } } } [HarmonyPatch(typeof(ItemDrop), "DropItem")] private static class ClearOnDrop { private static void Postfix(ItemDrop __result) { if (Instance.On && !((Object)(object)__result == (Object)null) && __result.m_itemData != null && IsFavorite(__result.m_itemData)) { SetFavorite(__result.m_itemData, favorite: false); __result.Save(); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class ShowFavorites { private const float Thickness = 3f; private static readonly Dictionary<InventoryElement, GameObject> borders = new Dictionary<InventoryElement, GameObject>(); private static void Postfix(InventoryGrid __instance) { Inventory inventory = __instance.m_inventory; if (inventory == null) { return; } foreach (InventoryElement element2 in __instance.m_elements) { if (borders.TryGetValue(element2, out var value) && (Object)(object)value != (Object)null) { value.SetActive(false); } } if (!Instance.On) { return; } int width = inventory.GetWidth(); foreach (ItemData allItem in inventory.GetAllItems()) { if (IsFavorite(allItem)) { InventoryElement element = __instance.GetElement(allItem.m_gridPos.x, allItem.m_gridPos.y, width); GameObject val = (((Object)(object)element != (Object)null) ? BorderFor(element) : null); if ((Object)(object)val != (Object)null) { val.SetActive(true); } } } } private static GameObject BorderFor(InventoryElement element) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0068: 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) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown if (borders.TryGetValue(element, out var value) && (Object)(object)value != (Object)null) { return value; } Image equiped = element.m_equiped; if ((Object)(object)equiped == (Object)null) { return null; } RectTransform rectTransform = ((Graphic)equiped).rectTransform; value = new GameObject("OMP_Favorite", new Type[1] { typeof(RectTransform) }); value.layer = ((Component)rectTransform).gameObject.layer; RectTransform val = (RectTransform)value.transform; ((Transform)val).SetParent(((Transform)rectTransform).parent, false); val.anchorMin = rectTransform.anchorMin; val.anchorMax = rectTransform.anchorMax; val.pivot = rectTransform.pivot; val.anchoredPosition = rectTransform.anchoredPosition; val.sizeDelta = rectTransform.sizeDelta; ((Transform)val).localScale = ((Transform)rectTransform).localScale; ((Transform)val).localRotation = ((Transform)rectTransform).localRotation; ((Transform)val).SetSiblingIndex(((Transform)rectTransform).GetSiblingIndex() + 1); Bar(val, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, 3f)); Bar(val, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 3f)); Bar(val, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(3f, 0f)); Bar(val, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(3f, 0f)); borders[elemen