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 OdinsMissingPatch v0.3.0
OdinsMissingPatch.dll
Decompiled 12 hours 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.Globalization; 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 Splatform; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using Valheim.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("OdinsMissingPatch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+e04ed725ff3bf8678203c36bea55678c46ebfa14")] [assembly: AssemblyProduct("OdinsMissingPatch")] [assembly: AssemblyTitle("OdinsMissingPatch")] [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 { private static readonly int FavoritesHash = StringExtensionMethods.GetStableHashCode("OMP_ChestFavorites"); private const char Separator = '\n'; internal static bool Used { get { if (!QuickStack.Instance.On) { return ChestButtons.Instance.On; } return true; } } 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 static readonly Color Gold = new Color(1f, 0.78f, 0.25f); 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, Gold * (0.6f * num), false); instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._Color, Color.Lerp(Color.white, 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 Hotkeys { internal static bool Pressed(KeyboardShortcut shortcut) { //IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false)) { return false; } return ModifiersHeld(shortcut); } internal static bool Held(KeyboardShortcut shortcut) { //IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey, false)) { return false; } return ModifiersHeld(shortcut); } private static bool ModifiersHeld(KeyboardShortcut shortcut) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } } 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) { int maxStackSize = item.m_shared.m_maxStackSize; if (maxStackSize > 1) { foreach (ItemData item2 in list) { if (item.m_stack <= 0) { break; } if (item2.m_stack < maxStackSize && SameStack(item2, item)) { int num = Math.Min(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; } 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 (a.m_customData.Count != b.m_customData.Count) { return false; } foreach (KeyValuePair<string, string> customDatum in a.m_customData) { if (!b.m_customData.TryGetValue(customDatum.Key, out var value) || value != customDatum.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; } [HarmonyPatch(typeof(Inventory), "CountItems")] 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) })] 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) })] 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")] 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")] private static class HoverText { private static void Postfix(Container __instance, ref string __result) { if (AnyTweakOn && IsExcluded(__instance)) { __result += "\n<color=#a0a0a0>Nearby use: off</color>"; } } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] private static class PanelButton { private static readonly TextButton NearbyUse = new TextButton("OMP_NearbyUse", new UnityAction(Toggle)); private static readonly TextButton ClearFavorites = new TextButton("OMP_ClearFavorites", new UnityAction(ClearFavorited)); private static string favorites = ""; private static int revision = -1; private static int favoritesCount; private static string favoritesTooltip = ""; private static void Postfix(InventoryGui __instance) { if (PanelButtons.Closing(__instance)) { return; } Container currentContainer = __instance.m_currentContainer; bool num = (Object)(object)currentContainer != (Object)null && ((Component)__instance.m_container).gameObject.activeSelf; int num2 = 0; if (num && AnyTweakOn && Eligible(currentContainer) && NearbyUse.Show(__instance)) { NearbyUse.SetLabel(IsExcluded(currentContainer) ? "$omp_nearby_off" : "$omp_nearby_on"); NearbyUse.SetTooltip("$omp_nearby_topic", "$omp_nearby_tip"); Button val = (ChestButtons.HidesVanilla ? __instance.m_takeAllButton : null); NearbyUse.Place(__instance, val, keepLeft: true, num2); if ((Object)(object)val == (Object)null) { num2++; } } else { NearbyUse.Hide(); } string text = (num ? ChestFavorites.Marks(currentContainer) : ""); if (ChestFavorites.Used && text.Length > 0 && ClearFavorites.Show(__instance)) { Describe(currentContainer, text); ClearFavorites.SetLabel((favoritesCount == 1) ? "$omp_clear_favourite" : "$omp_clear_favourites", favoritesCount.ToString()); ClearFavorites.SetTooltip("$omp_favourites_topic", favoritesTooltip); Button at = (ChestButtons.HidesVanilla ? __instance.m_stackAllButton : null); ClearFavorites.Place(__instance, at, keepLeft: false, num2); } else { ClearFavorites.Hide(); } } private static void Describe(Container chest, string marks) { if (!(marks == favorites) || revision != Translations.Revision) { favorites = marks; revision = Translations.Revision; favoritesCount = ChestFavorites.Names(chest).Count; favoritesTooltip = "$omp_favourites_tip_head\n" + ChestFavorites.Describe(chest) + "\n\n$omp_favourites_tip_foot"; } } private static Container Open() { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.m_currentContainer; } private static void Toggle() { Container val = Open(); if ((Object)(object)val != (Object)null) { SetExcluded(val, !IsExcluded(val)); } } private static void ClearFavorited() { Container val = Open(); if (!((Object)(object)val == (Object)null)) { ChestFavorites.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 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 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; PanelButtons.Pin(val2, new Vector2(PanelButtons.ColumnLeft(container) + num * 0.5f, PanelButtons.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 = PanelButtons.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 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 readonly List<float> Reaches = new List<float>(); private static readonly Dictionary<CountKey, int> counts = new Dictionary<CountKey, int>(); private static int countsFrame = -1; internal static bool AnyTweakOn { get { if (!NearbyCrafting.Instance.On && !QuickStack.Instance.On && !NearbyFuel.Instance.On) { return AddAll.Instance.On; } return true; } } private static bool InReach => Reaches.Count > 0; private static float ReachRange => Reaches[Reaches.Count - 1]; 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 void EnterReach(float range) { Reaches.Add(range); } internal static void LeaveReach() { if (Reaches.Count > 0) { Reaches.RemoveAt(Reaches.Count - 1); } } 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; } } [BepInPlugin("rauschekuh.odinsmissingpatch", "Odin's Missing Patch", "0.3.0")] public class OdinsMissingPatchPlugin : BaseUnityPlugin { public const string GUID = "rauschekuh.odinsmissingpatch"; public const string NAME = "Odin's Missing Patch"; public const string VERSION = "0.3.0"; private static readonly Tweak[] Tweaks = new Tweak[25] { StationRange.Instance, ComfortRange.Instance, EndlessFuel.Instance, MistClearRange.Instance, CombatStamina.Instance, InstantComfort.Instance, FiresideHealing.Instance, FastPortals.Instance, KeepGearOnDeath.Instance, AreaRepair.Instance, NearbyCrafting.Instance, QuickStack.Instance, NearbyFuel.Instance, AddAll.Instance, AutoRepair.Instance, ChestButtons.Instance, InventoryButtons.Instance, PowerPicker.Instance, EquipWhileRunning.Instance, AutoShield.Instance, PocketUpgrades.Instance, SharedMapTable.Instance, AutoPins.Instance, PinLooks.Instance, DeathPins.Instance }; private void Awake() { Tweak[] tweaks = Tweaks; for (int i = 0; i < tweaks.Length; i++) { tweaks[i].Setup(((BaseUnityPlugin)this).Config); } Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "rauschekuh.odinsmissingpatch"); string text = string.Join(", ", (from t in Tweaks where t.On select t.Section).ToArray()); ((BaseUnityPlugin)this).Logger.LogInfo((object)((text.Length > 0) ? ("tweaks on: " + text) : "every tweak is switched off")); } } internal static class PanelButtons { internal const float Gap = 6f; private static readonly Dictionary<string, Sprite> icons = new Dictionary<string, Sprite>(); private static readonly List<KeyValuePair<int, Button>> column = new List<KeyValuePair<int, Button>>(); private static MethodInfo loadImage; internal 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; } internal 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; } internal 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); } internal 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; } internal 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); } internal static void Enlist(Button button, int order) { column.Add(new KeyValuePair<int, Button>(order, button)); column.Sort((KeyValuePair<int, Button> a, KeyValuePair<int, Button> b) => a.Key.CompareTo(b.Key)); } internal static void LayoutInventoryColumn(InventoryGui gui) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: 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 (KeyValuePair<int, Button> item in column) { if ((Object)(object)item.Value != (Object)null && ((Component)item.Value).gameObject.activeSelf) { 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 (KeyValuePair<int, Button> item2 in column) { if (!((Object)(object)item2.Value == (Object)null) && ((Component)item2.Value).gameObject.activeSelf) { RectTransform val5 = (RectTransform)((Component)item2.Value).transform; val5.sizeDelta = new Vector2(num, num); Pin(val5, new Vector2(num7, num8)); num8 -= num + 6f; } } } internal static void LayoutChestColumn(InventoryGui gui, IList<Button> buttons) { //IL_0066: 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_006e: 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_0084: Expected O, but got Unknown RectTransform val = (((Object)(object)gui != (Object)null) ? gui.m_container : null); if ((Object)(object)val == (Object)null) { return; } float num = Size(gui); float num2 = ColumnLeft(val) + num * 0.5f; float num3 = ColumnTop(val) - num * 0.5f; foreach (Button button in buttons) { if (!((Object)(object)button == (Object)null)) { RectTransform val2 = (RectTransform)((Component)button).transform; val2.sizeDelta = new Vector2(num, num); Pin(val2, new Vector2(num2, num3)); num3 -= num + 6f; } } } internal static Sprite Icon(string name) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_007d: 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) if (icons.TryGetValue(name, out var value)) { return value; } value = null; try { string text = Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "icons"), name + ".png"); if (File.Exists(text)) { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (LoadPng(val, File.ReadAllBytes(text))) { ((Texture)val).filterMode = (FilterMode)1; value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } } else { Debug.LogWarning((object)("[OdinsMissingPatch] icon missing: " + text)); } } catch (Exception ex) { Debug.LogWarning((object)("[OdinsMissingPatch] could not load icon " + name + ": " + ex.Message)); } icons[name] = value; return value; } private static bool LoadPng(Texture2D texture, byte[] png) { if (loadImage == null) { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); loadImage = ((type != null) ? type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }) : null); if (loadImage == null) { Debug.LogWarning((object)"[OdinsMissingPatch] ImageConversion.LoadImage not found; icons stay blank"); return false; } } return (bool)loadImage.Invoke(null, new object[2] { texture, png }); } 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 = 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 = 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 = TooltipPrefab(gui); } return val; } private static GameObject TooltipPrefab(InventoryGui gui) { InventoryGrid playerGrid = gui.m_playerGrid; GameObject val = (((Object)(object)playerGrid != (Object)null) ? playerGrid.m_elementPrefab : null); InventoryElement val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<InventoryElement>() : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_tooltip != (Object)null && (Object)(object)val2.m_tooltip.m_tooltipPrefab != (Object)null) { return val2.m_tooltip.m_tooltipPrefab; } UITooltip[] componentsInChildren = ((Component)gui).GetComponentsInChildren<UITooltip>(true); foreach (UITooltip val3 in componentsInChildren) { if ((Object)(object)val3.m_tooltipPrefab != (Object)null) { return val3.m_tooltipPrefab; } } return null; } } internal static class Translations { [HarmonyPatch(typeof(Localization), "SetupLanguage")] private static class Load { private static void Postfix(Localization __instance, string language) { if (__instance == null || !Read() || !Reader()) { return; } object obj = null; try { obj = textAsset.Invoke(new object[1] { csv }); loadCsv.Invoke(__instance, new object[2] { obj, Has(language) ? language : "English" }); Revision++; } catch (Exception ex) { Debug.LogWarning((object)("[OdinsMissingPatch] could not load translations.csv: " + ex.Message)); } finally { Object val = (Object)((obj is Object) ? obj : null); if (val != (Object)null) { Object.Destroy(val); } } } } private const string FileName = "translations.csv"; private const string Fallback = "English"; private static string csv; private static string[] languages; private static ConstructorInfo textAsset; private static MethodInfo loadCsv; private static bool looked; internal static int Revision { get; private set; } private static bool Read() { if (languages != null) { return csv != null; } languages = new string[0]; try { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "translations.csv"); if (!File.Exists(text)) { Debug.LogWarning((object)("[OdinsMissingPatch] translations.csv missing: " + text)); return false; } csv = File.ReadAllText(text); using (StringReader stringReader = new StringReader(csv)) { string text2 = stringReader.ReadLine(); languages = ((text2 != null) ? text2.Split(new char[1] { ',' }) : new string[0]); } for (int i = 0; i < languages.Length; i++) { languages[i] = languages[i].Trim().Trim(new char[1] { '"' }); } } catch (Exception ex) { csv = null; Debug.LogWarning((object)("[OdinsMissingPatch] could not read translations.csv: " + ex.Message)); } return csv != null; } private static bool Has(string language) { string[] array = languages; for (int i = 0; i < array.Length; i++) { if (array[i] == language) { return true; } } return false; } private static bool Reader() { if (looked) { if (loadCsv != null) { return textAsset != null; } return false; } looked = true; Type type = Type.GetType("UnityEngine.TextAsset, UnityEngine.CoreModule"); if (type != null) { textAsset = type.GetConstructor(new Type[1] { typeof(string) }); loadCsv = typeof(Localization).GetMethod("LoadCSV", new Type[2] { type, typeof(string) }); } if (loadCsv == null || textAsset == null) { Debug.LogWarning((object)"[OdinsMissingPatch] Localization.LoadCSV not found; the mod's words stay untranslated"); return false; } return true; } } internal abstract class Tweak { private const float MinMultiplier = 0.1f; private const float MaxMultiplier = 20f; private ConfigEntry<bool> enabled; internal abstract string Section { get; } protected abstract string Summary { get; } internal bool On { get { if (enabled != null) { return enabled.Value; } return false; } } protected abstract void Bind(ConfigFile config); internal void Setup(ConfigFile config) { enabled = config.Bind<bool>(Section, "Enabled", true, Summary); Bind(config); } protected ConfigEntry<float> BindMultiplier(ConfigFile config, string key, float value, string description) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown return config.Bind<float>(Section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>())); } protected void OnSettingChanged(ConfigFile config, Action handler) { config.SettingChanged += delegate(object sender, SettingChangedEventArgs args) { if (args.ChangedSetting.Definition.Section == Section) { handler(); } }; } } internal sealed class AddAll : Tweak { private struct Batch { public string Name; public string Prefab; public bool Cheated; public int Count; } private readonly struct Reach : IDisposable { private readonly bool entered; internal Reach(Humanoid user) { entered = Instance.On && (Object)(object)user != (Object)null && (Object)(object)user == (Object)(object)Player.m_localPlayer; if (entered) { NearbyChests.EnterReach(Instance.range.Value); } } public void Dispose() { if (entered) { NearbyChests.LeaveReach(); } } } [HarmonyPatch(typeof(Fireplace), "Interact")] private static class FireUse { private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, bool alt) { if (!Wants(user, hold, alt)) { return true; } PlanFire(__instance, user); if (LeaveToGame(user, Plan)) { return true; } int num = Total(Plan); ZNetView nview = __instance.m_nview; if (!nview.HasOwner()) { nview.ClaimOwnership(); } Take(user, Plan[0].Name, num); nview.InvokeRPC("RPC_AddFuelAmount", new object[1] { (float)num }); Report(user, Plan); return false; } } [HarmonyPatch(typeof(Switch), "Interact")] private static class SwitchUse { private static bool Prefix(Switch __instance, Humanoid character, bool hold, bool alt) { if (!Wants(character, hold, alt)) { return true; } Smelter componentInParent = ((Component)__instance).GetComponentInParent<Smelter>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.m_nview != (Object)null && componentInParent.m_nview.IsValid()) { if ((Object)(object)__instance == (Object)(object)componentInParent.m_addWoodSwitch) { return !AddSmelterFuel(componentInParent, character); } if ((Object)(object)__instance == (Object)(object)componentInParent.m_addOreSwitch) { return !AddSmelterOre(componentInParent, character); } return true; } CookingStation componentInParent2 = ((Component)__instance).GetComponentInParent<CookingStation>(); if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent2.m_nview != (Object)null && componentInParent2.m_nview.IsValid()) { if ((Object)(object)__instance == (Object)(object)componentInParent2.m_addFuelSwitch) { return !AddOvenFuel(componentInParent2, character); } if ((Object)(object)__instance == (Object)(object)componentInParent2.m_addFoodSwitch) { return !AddFood(componentInParent2, character); } return true; } ShieldGenerator componentInParent3 = ((Component)__instance).GetComponentInParent<ShieldGenerator>(); if ((Object)(object)componentInParent3 != (Object)null && (Object)(object)componentInParent3.m_nview != (Object)null && componentInParent3.m_nview.IsValid() && (Object)(object)__instance == (Object)(object)componentInParent3.m_addFuelSwitch) { return !AddShieldFuel(componentInParent3, character); } return true; } } [HarmonyPatch(typeof(CookingStation), "Interact")] private static class StationUse { private static bool Prefix(CookingStation __instance, Humanoid user, bool hold, bool alt) { if (!Wants(user, hold, alt) || (Object)(object)__instance.m_addFoodSwitch != (Object)null || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return true; } return !AddFood(__instance, user); } } [HarmonyPatch(typeof(Turret), "Interact")] private static class BallistaUse { private static bool Prefix(Turret __instance, Humanoid character, bool hold, bool alt) { if (!Wants(character, hold, alt)) { return true; } PlanAmmo(__instance, character); if (LeaveToGame(character, Plan)) { return true; } int num = Total(Plan); Batch batch = Plan[0]; Take(character, batch.Name, num); for (int i = 0; i < num; i++) { Game.instance.IncrementPlayerStat((PlayerStatType)78, 1f, false); __instance.m_nview.InvokeRPC("RPC_AddAmmo", new object[1] { batch.Prefab }); } Report(character, Plan); return false; } } [HarmonyPatch(typeof(Fireplace), "GetHoverText")] private static class FireHover { private static void Postfix(Fireplace __instance, ref string __result) { if (Hovering && !string.IsNullOrEmpty(__result)) { PlanFire(__instance, (Humanoid)(object)Player.m_localPlayer); __result += HoverLine(Plan); } } } [HarmonyPatch(typeof(Switch), "GetHoverText")] private static class SwitchHover { private static void Postfix(Switch __instance, ref string __result) { if (!Hovering || string.IsNullOrEmpty(__result)) { return; } Player localPlayer = Player.m_localPlayer; Smelter componentInParent = ((Component)__instance).GetComponentInParent<Smelter>(); if ((Object)(object)componentInParent != (Object)null) { if ((Object)(object)componentInParent.m_nview == (Object)null || !componentInParent.m_nview.IsValid()) { return; } if ((Object)(object)__instance == (Object)(object)componentInParent.m_addWoodSwitch) { PlanSmelterFuel(componentInParent, (Humanoid)(object)localPlayer); } else { if (!((Object)(object)__instance == (Object)(object)componentInParent.m_addOreSwitch)) { return; } PlanSmelterOre(componentInParent, (Humanoid)(object)localPlayer); } __result += HoverLine(Plan); return; } CookingStation componentInParent2 = ((Component)__instance).GetComponentInParent<CookingStation>(); if ((Object)(object)componentInParent2 != (Object)null) { if ((Object)(object)componentInParent2.m_nview == (Object)null || !componentInParent2.m_nview.IsValid()) { return; } if ((Object)(object)__instance == (Object)(object)componentInParent2.m_addFuelSwitch) { PlanOvenFuel(componentInParent2, (Humanoid)(object)localPlayer); } else { if (!((Object)(object)__instance == (Object)(object)componentInParent2.m_addFoodSwitch)) { return; } PlanFood(componentInParent2, (Humanoid)(object)localPlayer); } __result += HoverLine(Plan); } else { ShieldGenerator componentInParent3 = ((Component)__instance).GetComponentInParent<ShieldGenerator>(); if ((Object)(object)componentInParent3 != (Object)null && (Object)(object)componentInParent3.m_nview != (Object)null && componentInParent3.m_nview.IsValid() && (Object)(object)__instance == (Object)(object)componentInParent3.m_addFuelSwitch) { PlanShieldFuel(componentInParent3, (Humanoid)(object)localPlayer); __result += HoverLine(Plan); } } } } [HarmonyPatch(typeof(CookingStation), "GetHoverText")] private static class StationHover { private static void Postfix(CookingStation __instance, ref string __result) { if (Hovering && !string.IsNullOrEmpty(__result) && !((Object)(object)__instance.m_addFoodSwitch != (Object)null) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid()) { PlanFood(__instance, (Humanoid)(object)Player.m_localPlayer); __result += HoverLine(Plan); } } } [HarmonyPatch(typeof(Turret), "GetHoverText")] private static class BallistaHover { private static void Postfix(Turret __instance, ref string __result) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (Hovering && !string.IsNullOrEmpty(__result) && __instance.m_targetEnemies && PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false)) { PlanAmmo(__instance, (Humanoid)(object)Player.m_localPlayer); __result += HoverLine(Plan); } } } internal static readonly AddAll Instance = new AddAll(); private ConfigEntry<float> range; private static readonly List<Batch> Plan = new List<Batch>(); private static readonly StringBuilder Text = new StringBuilder(); internal override string Section => "Add All"; protected override string Summary => "Shift + Use on a fire, smelter, oven, cooking station, shield generator or ballista adds everything that fits, instead of one item: out of your backpack first and then out of the chests around you."; private static bool Hovering { get { if (Instance.On) { return (Object)(object)Player.m_localPlayer != (Object)null; } return false; } } private AddAll() { } protected override void Bind(ConfigFile config) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown range = config.Bind<float>(Section, "Range", 20f, new ConfigDescription("How far from you a chest may stand, in metres, for a Shift + Use to reach what it holds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); } private static bool Wants(Humanoid user, bool hold, bool alt) { if (Instance.On && alt && !hold && (Object)(object)user != (Object)null) { return (Object)(object)user == (Object)(object)Player.m_localPlayer; } return false; } private static int Count(Humanoid user, string name) { using (new Reach(user)) { return user.GetInventory().CountItems(name, -1, true); } } private static void Take(Humanoid user, string name, int amount) { using (new Reach(user)) { user.GetInventory().RemoveItem(name, amount, -1, true); } } private static ItemData Sample(Humanoid user, string name) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) ItemData item = user.GetInventory().GetItem(name, -1, false); if (item != null || !Instance.On || (Object)(object)Player.m_localPlayer == (Object)null) { return item; } foreach (Container item2 in NearbyChests.Find(((Component)Player.m_localPlayer).transform.position, Instance.range.Value)) { item = item2.GetInventory().GetItem(name, -1, false); if (item != null) { return item; } } return null; } private static ItemData Ammo(Turret turret, Humanoid user) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) ItemData val = turret.FindAmmoItem(user.GetInventory(), true); if (val != null || !Instance.On || (Object)(object)Player.m_localPlayer == (Object)null) { return val; } foreach (Container item in NearbyChests.Find(((Component)Player.m_localPlayer).transform.position, Instance.range.Value)) { val = turret.FindAmmoItem(item.GetInventory(), true); if (val != null) { return val; } } return null; } private static bool LeaveToGame(Humanoid user, List<Batch> plan) { return Total(plan) switch { 1 => NearbyChests.Carried(user.GetInventory(), plan[0].Name, -1, matchWorldLevel: true) > 0, 0 => true, _ => false, }; } private static int FuelRoom(float fuel, int maxFuel) { if (fuel > (float)(maxFuel - 1)) { return 0; } return Mathf.FloorToInt((float)(maxFuel - 1) - fuel) + 1; } private static int Total(List<Batch> plan) { int num = 0; foreach (Batch item in plan) { num += item.Count; } return num; } private static string Describe(List<Batch> plan) { Text.Length = 0; foreach (Batch item in plan) { if (Text.Length > 0) { Text.Append(", "); } Text.Append(item.Count).Append(' ').Append(item.Name); } return Text.ToString(); } private static string HoverLine(List<Batch> plan) { if (Total(plan) <= 0) { return ""; } string text = ((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "$KEY_AltKeys" : "$KEY_AltPlace"); string text2 = Localization.instance.Localize(Describe(plan)); return Localization.instance.Localize("\n[<color=yellow><b>" + text + " + $KEY_Use</b></color>] $omp_add_all", new string[1] { text2 }); } private static void Report(Humanoid user, List<Batch> plan) { ((Character)user).Message((MessageType)2, "$msg_added " + Describe(plan), 0, (Sprite)null, false); } private static void PlanFire(Fireplace fire, Humanoid user) { Plan.Clear(); ZNetView nview = fire.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && fire.m_canRefill && !fire.m_infiniteFuel && !((Object)(object)fire.m_fuelItem == (Object)null)) { int num = (int)fire.m_maxFuel - Mathf.CeilToInt(nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f)); string name = fire.m_fuelItem.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, Count(user, name)); if (num2 > 0) { Plan.Add(new Batch { Name = name, Count = num2 }); } } } private static void PlanSmelterFuel(Smelter smelter, Humanoid user) { Plan.Clear(); if (!((Object)(object)smelter.m_fuelItem == (Object)null)) { int num = FuelRoom(smelter.GetFuel(), smelter.m_maxFuel); string name = smelter.m_fuelItem.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, Count(user, name)); if (num2 > 0) { Plan.Add(new Batch { Name = name, Count = num2 }); } } } private static void PlanSmelterOre(Smelter smelter, Humanoid user) { Plan.Clear(); int num = smelter.m_maxOre - smelter.GetQueueSize(); using (new Reach(user)) { Inventory inventory = user.GetInventory(); foreach (ItemConversion item in smelter.m_conversion) { if (num <= 0) { break; } if (!((Object)(object)item.m_from == (Object)null)) { string name = item.m_from.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, inventory.CountItems(name, -1, true)); if (num2 > 0) { ItemData val = Sample(user, name); Plan.Add(new Batch { Name = name, Prefab = ((Object)((Component)item.m_from).gameObject).name, Cheated = (val?.m_cheated ?? false), Count = num2 }); num -= num2; } } } } } private static void PlanOvenFuel(CookingStation station, Humanoid user) { Plan.Clear(); if (station.m_useFuel && !((Object)(object)station.m_fuelItem == (Object)null)) { int num = FuelRoom(station.GetFuel(), station.m_maxFuel); string name = station.m_fuelItem.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, Count(user, name)); if (num2 > 0) { Plan.Add(new Batch { Name = name, Count = num2 }); } } } private static void PlanFood(CookingStation station, Humanoid user) { Plan.Clear(); ZNetView nview = station.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || station.HaveDoneItem() || (station.m_requireFire && !station.IsFireLit())) { return; } int num = 0; for (int i = 0; i < station.m_slots.Length; i++) { if (nview.GetZDO().GetString("slot" + i, "") == "") { num++; } } using (new Reach(user)) { Inventory inventory = user.GetInventory(); foreach (ItemConversion item in station.m_conversion) { if (num <= 0) { break; } if (!((Object)(object)item.m_from == (Object)null)) { string name = item.m_from.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, inventory.CountItems(name, -1, true)); if (num2 > 0) { ItemData val = Sample(user, name); Plan.Add(new Batch { Name = name, Prefab = ((Object)((Component)item.m_from).gameObject).name, Cheated = (val?.m_cheated ?? false), Count = num2 }); num -= num2; } } } } } private static void PlanShieldFuel(ShieldGenerator generator, Humanoid user) { Plan.Clear(); int num = FuelRoom(generator.GetFuel(), generator.m_maxFuel); foreach (ItemDrop fuelItem in generator.m_fuelItems) { if (num <= 0) { break; } if (!((Object)(object)fuelItem == (Object)null)) { string name = fuelItem.m_itemData.m_shared.m_name; int num2 = Mathf.Min(num, Count(user, name)); if (num2 > 0) { Plan.Add(new Batch { Name = name, Count = num2 }); num -= num2; } } } } private static void PlanAmmo(Turret turret, Humanoid user) { Plan.Clear(); ZNetView nview = turret.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || turret.m_maxAmmo <= 0) { return; } int num = turret.m_maxAmmo - turret.GetAmmo(); ItemData val = Ammo(turret, user); if (num > 0 && val != null && !((Object)(object)val.m_dropPrefab == (Object)null)) { string name = val.m_shared.m_name; int num2 = Mathf.Min(num, Count(user, name)); if (num2 > 0) { Plan.Add(new Batch { Name = name, Prefab = ((Object)val.m_dropPrefab).name, Count = num2 }); } } } private static bool AddSmelterFuel(Smelter smelter, Humanoid user) { PlanSmelterFuel(smelter, user); if (LeaveToGame(user, Plan)) { return false; } int num = Total(Plan); Take(user, Plan[0].Name, num); for (int i = 0; i < num; i++) { smelter.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } Report(user, Plan); return true; } private static bool AddSmelterOre(Smelter smelter, Humanoid user) { PlanSmelterOre(smelter, user); if (LeaveToGame(user, Plan)) { return false; } foreach (Batch item in Plan) { Take(user, item.Name, item.Count); for (int i = 0; i < item.Count; i++) { smelter.m_nview.InvokeRPC("RPC_AddOre", new object[2] { item.Prefab, item.Cheated }); } } smelter.m_addedOreTime = Time.time; if (smelter.m_addOreAnimationDuration > 0f) { smelter.SetAnimation(true); } Report(user, Plan); return true; } private static bool AddOvenFuel(CookingStation station, Humanoid user) { PlanOvenFuel(station, user); if (LeaveToGame(user, Plan)) { return false; } int num = Total(Plan); Take(user, Plan[0].Name, num); for (int i = 0; i < num; i++) { station.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } Report(user, Plan); return true; } private static bool AddFood(CookingStation station, Humanoid user) { //IL_007f: 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) PlanFood(station, user); if (LeaveToGame(user, Plan)) { return false; } ZNetView nview = station.m_nview; if (!nview.HasOwner()) { nview.ClaimOwnership(); } foreach (Batch item in Plan) { Take(user, item.Name, item.Count); for (int i = 0; i < item.Count; i++) { nview.InvokeRPC("RPC_AddItem", new object[2] { item.Prefab, item.Cheated }); if ((int)station.m_skill != 0) { ((Character)Player.m_localPlayer).RaiseSkill(station.m_skill, 0.4f); } } } Report(user, Plan); return true; } private static bool AddShieldFuel(ShieldGenerator generator, Humanoid user) { PlanShieldFuel(generator, user); if (LeaveToGame(user, Plan)) { return false; } foreach (Batch item in Plan) { Take(user, item.Name, item.Count); for (int i = 0; i < item.Count; i++) { generator.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } } Report(user, Plan); return true; } } internal sealed class AreaRepair : Tweak { [HarmonyPatch(typeof(Player), "Repair")] private static class RepairEverythingAround { private static void Postfix(Player __instance, ItemData toolItem) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_004a: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) if (!Instance.On || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || toolItem == null || toolItem.m_shared == null || !((Character)__instance).InPlaceMode()) { return; } KeyCode value = Instance.singleRepairKey.Value; if ((int)value != 0 && ZInput.GetKey(value, false)) { return; } bool placementCostDisabled = __instance.PlacementCostDisabled; bool stationFree = placementCostDisabled || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)27)); float buildStamina = __instance.GetBuildStamina(); float attackEitr = toolItem.m_shared.m_attack.m_attackEitr; float num = (toolItem.m_shared.m_useDurability ? (toolItem.m_shared.m_useDurabilityDrain * Game.m_durabilityRate) : 0f); if (!placementCostDisabled && !CanPayFor(__instance, toolItem, buildStamina, attackEitr, num)) { return; } Piece hoveringPiece = __instance.GetHoveringPiece(); Vector3 centre = (((Object)(object)hoveringPiece != (Object)null) ? ((Component)hoveringPiece).transform.position : ((Component)__instance).transform.position); int num2 = 0; List<KeyValuePair<Piece, float>> list = PiecesInRadius(centre, Instance.radius.Value); for (int i = 0; i < list.Count; i++) { Piece key = list[i].Key; WearNTear component = ((Component)key).GetComponent<WearNTear>(); if (!((Object)(object)component == (Object)null) && CanRepair(__instance, key, stationFree) && component.Repair()) { num2++; if (!placementCostDisabled) { ((Character)__instance).UseStamina(buildStamina); ((Character)__instance).UseEitr(attackEitr); toolItem.m_durability -= num; } if (key.m_placeEffect != null) { key.m_placeEffect.Create(((Component)key).transform.position, ((Component)key).transform.rotation, (Transform)null, 1f, -1, ((Character)__instance).GetZDOID()); } if (!placementCostDisabled && !CanPayFor(__instance, toolItem, buildStamina, attackEitr, num)) { break; } } } StationsInRange.Clear(); Nearby.Clear(); if (num2 > 0) { __instance.FaceLookDirection(); ((Character)__instance).m_zanim.SetTrigger(toolItem.m_shared.m_attack.m_attackAnimation); ((Character)__instance).Message((MessageType)1, Localization.instance.Localize("$msg_repaired", new string[1] { num2.ToString() }), 0, (Sprite)null, false); } } private static bool CanPayFor(Player player, ItemData toolItem, float stamina, float eitr, float wear) { if (((Character)player).HaveStamina(stamina) && (eitr <= 0f || ((Character)player).HaveEitr(eitr))) { return toolItem.m_durability >= wear; } return false; } } internal static readonly AreaRepair Instance = new AreaRepair(); private ConfigEntry<float> radius; private ConfigEntry<KeyCode> singleRepairKey; private static readonly Dictionary<string, bool> StationsInRange = new Dictionary<string, bool>(); private static readonly List<KeyValuePair<Piece, float>> Nearby = new List<KeyValuePair<Piece, float>>(); internal override string Section => "Area Repair"; protected override string Summary => "One swing of the hammer repairs every damaged piece around the one you aim at, instead of that one piece alone."; private AreaRepair() { } protected override void Bind(ConfigFile config) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown radius = config.Bind<float>(Section, "Radius", 10f, new ConfigDescription("Metres around the piece you aim at that one swing reaches. Everything inside it is repaired closest first, so a short swing mends what is nearest.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 64f), Array.Empty<object>())); singleRepairKey = config.Bind<KeyCode>(Section, "SingleRepairKey", (KeyCode)308, "Hold this while you swing to repair only the piece you aim at, the way the game does. None to always repair the area."); } private static List<KeyValuePair<Piece, float>> PiecesInRadius(Vector3 centre, float radius) { //IL_003a: 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) Nearby.Clear(); foreach (Piece s_allPiece in Piece.s_allPieces) { if (!((Object)(object)s_allPiece == (Object)null) && ((Component)s_allPiece).gameObject.layer != Piece.s_ghostLayer) { float num = Vector3.Distance(centre, ((Component)s_allPiece).transform.position); if (num <= radius) { Nearby.Add(new KeyValuePair<Piece, float>(s_allPiece, num)); } } } Nearby.Sort((KeyValuePair<Piece, float> a, KeyValuePair<Piece, float> b) => a.Value.CompareTo(b.Value)); return Nearby; } private static bool CanRepair(Player player, Piece piece, bool stationFree) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!stationFree && (Object)(object)piece.m_craftingStation != (Object)null) { string name = piece.m_craftingStation.m_name; if (!StationsInRange.TryGetValue(name, out var value)) { value = Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(name, ((Component)player).transform.position)); StationsInRange[name] = value; } if (!value) { return false; } } return PrivateArea.CheckAccess(((Component)piece).transform.position, 0f, true, false); } } internal sealed class AutoPins : Tweak { private sealed class Site { public string PrefabName; public bool GameIcon; public Teleport Entrance; public PlaceKind Kind; public string KindName; } internal enum PlaceKind { None, Treasure, Generated, Tar } internal enum MinedOut { Tick, Remove, Keep } [HarmonyPatch(typeof(Player), "Update")] private static class Sweep { private static void Postfix(Player __instance) { //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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!Instance.On || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || Time.time < nextSweep) { return; } nextSweep = Time.time + 3f; Minimap instance = Minimap.instance; Vector3 position = ((Component)__instance).transform.position; if (!((Object)(object)instance == (Object)null) && !Character.InInterior(position)) { if (Instance.dungeons.Value || Instance.places.Value) { Instance.SweepLocations(position); } if (Instance.minedOut.Value != MinedOut.Keep) { Instance.SweepMinedOut(instance, position); } } } } [HarmonyPatch(typeof(MineRock5), "Damage")] private static class StrikeMineRock5 { private static void Postfix(MineRock5 __instance, HitData hit) {