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 OpenKeep v5.2.0
plugins\OpenKeep.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using AreaLoading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BlueprintShelf; using BundlePrefabs; using Charter; using ConfigReload; using EliteCraftingLink; using GUIFramework; using HarmonyLib; using Hotkeys; using ItemCopies; using MapClicks; using Microsoft.CodeAnalysis; using OpenKeep.Batch; using OpenKeep.Blueprints; using OpenKeep.Blueprints.Bench; using OpenKeep.Blueprints.Copy; using OpenKeep.Blueprints.Planner; using OpenKeep.Blueprints.Sites; using OpenKeep.Blueprints.Tab; using OpenKeep.BuildCamera; using OpenKeep.Capacity; using OpenKeep.Carts; using OpenKeep.Core; using OpenKeep.Homestead; using OpenKeep.Mimir; using OpenKeep.Reach; using OpenKeep.Recipes; using OpenKeep.Salvage; using OpenKeep.Shared; using OpenKeep.Signs; using OpenKeep.Stacks; using OpenKeep.Store; using OpenKeep.Tracker; using PatchGuard; using PlateColumn; using Splatform; using SyncedConfig; using TMPro; using Translations; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; using WindowInput; using YamlConfig; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.RepresentationModel; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("OpenKeep")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("OpenKeep: storage and inventory for Valheim")] [assembly: AssemblyFileVersion("5.2.0.0")] [assembly: AssemblyInformationalVersion("5.2.0+41299e456a94991837b85ab4893af7d9fdb6c6b4")] [assembly: AssemblyProduct("OpenKeep")] [assembly: AssemblyTitle("OpenKeep")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.2.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OpenKeep { [HarmonyPatch(typeof(Player), "Update")] public static class PlayerUpdatePatch { [HarmonyPostfix] public static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { CameraToggle.Tick(__instance); TorchKeyPatch.Tick(__instance); ReachKeys.Tick(__instance); DumpKeyPatch.Tick(__instance); } } } [HarmonyPatch(typeof(InventoryGui), "Update")] public static class InventoryUpdatePatch { [HarmonyPostfix] public static void Postfix(InventoryGui __instance) { RecipeInput.Poll(__instance); SalvageHotkey.Tick(__instance); StoreHotkeys.Tick(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] public static class UpdateRecipePatch { [HarmonyPostfix] public static void Postfix(InventoryGui __instance, Player player) { BatchStepper.Refresh(__instance, player); RecipeActions.Refresh(__instance); } } [HarmonyPatch(typeof(Container), "CheckForChanges")] public static class ContainerTickPatch { [HarmonyPrefix] public static void Prefix(Container __instance, out uint __state) { __state = __instance.m_lastRevision; } [HarmonyPostfix] public static void Postfix(Container __instance, uint __state) { SignRefresh.Tick(__instance, force: false); TidySchedule.Tick(__instance, __state); } } [BepInPlugin("milkyteam.openkeep", "OpenKeep", "5.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "milkyteam.openkeep"; public const string PluginName = "OpenKeep"; public const string PluginVersion = "5.2.0"; public static ManualLogSource Log { get; private set; } public static SyncedConfiguration Synced { get; private set; } public static ConfigEntry<bool> LockConfiguration { get; private set; } public static Plugin Instance { get; private set; } private void Awake() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Synced = new SyncedConfiguration((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, "OpenKeep", "5.2.0"); LockConfiguration = Synced.BindLocking("General", "Lock Configuration", defaultValue: true, "[Server Only] Clients cannot change synced settings while connected to a server that has this on."); Harmony harmony = new Harmony("milkyteam.openkeep"); Lang.Install(harmony, Assembly.GetExecutingAssembly(), "OpenKeep", ((BaseUnityPlugin)this).Logger); InitializeModules(); int num = PatchEverything(harmony); StacksModule.HookSpawns(harmony); AreaLoader.Install(harmony, delegate(string text) { Log.LogInfo((object)("OpenKeep: " + text)); }); IconClick.Install(harmony); Synced.Finish(harmony); Log.LogInfo((object)("Loading [OpenKeep 5.2.0]" + ((num > 0) ? $" with {num} failed patches, see above" : ""))); Guard.Install(harmony, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly()); } private static void InitializeModules() { CoreModule.Initialize(Synced); ReachModule.Initialize(Synced); StoreModule.Initialize(Synced); SalvageModule.Initialize(Synced); StacksModule.Initialize(Synced); CapacityModule.Initialize(Synced); CartsModule.Initialize(Synced); SignsModule.Initialize(Synced); HomesteadModule.Initialize(Synced); SharedModule.Initialize(Synced); BatchModule.Initialize(Synced); CameraModule.Initialize(Synced); RecipeListModule.Initialize(Synced); TrackerModule.Initialize(Synced); BlueprintsModule.Initialize(Synced); MimirModule.Initialize(Synced); } private void Start() { EpicLootLink.Register(); } private static int PatchEverything(Harmony harmony) { int num = 0; Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0) { try { harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { num++; Log.LogError((object)("Patch " + type.FullName + " failed to apply: " + ex.Message)); } } } return num; } } } namespace OpenKeep.Tracker { public sealed class CraftWatch { private Recipe recipe; private int quality; private int crafts; private int before; public static CraftWatch Start(InventoryGui gui, Player player) { Recipe craftRecipe = gui.m_craftRecipe; if ((Object)(object)craftRecipe == (Object)null || (Object)(object)player == (Object)null || (Object)(object)craftRecipe.m_item == (Object)null || !TrackerSettings.Enabled.Value) { return null; } int num = ((gui.m_craftUpgradeItem == null) ? 1 : (gui.m_craftUpgradeItem.m_quality + 1)); if (!TrackerList.IsTracked(craftRecipe, num)) { return null; } int num2 = ((gui.m_craftUpgradeItem != null || !gui.m_multiCrafting) ? 1 : gui.m_multiCraftAmount); return new CraftWatch { recipe = craftRecipe, quality = num, crafts = num2, before = Held(player, craftRecipe, num) }; } public void Finish(Player player) { if ((Object)(object)player != (Object)null && Held(player, recipe, quality) > before) { TrackerList.Crafted(recipe, quality, crafts); } } private static int Held(Player player, Recipe recipe, int quality) { return ((Humanoid)player).GetInventory().CountItems(recipe.m_item.m_itemData.m_shared.m_name, quality, false); } } public sealed class TrackedRecipe { public const int MaxAmount = 9999; private const string UpgraderMark = "u"; public string Key { get; } public int Quality { get; } public bool Upgrader { get; } public int Amount { get; set; } public Recipe Recipe => RecipeKeys.Find(Key); public TrackedRecipe(string key, int quality, int amount, bool upgrader) { Key = key; Quality = ((quality < 1) ? 1 : quality); Amount = ((amount < 1) ? 1 : ((amount > 9999) ? 9999 : amount)); Upgrader = upgrader; } public bool Is(string key, int quality, bool upgrader) { if (quality == Quality && upgrader == Upgrader) { return key == Key; } return false; } public override string ToString() { return Key + "|" + Quality + "|" + Amount + (Upgrader ? "|u" : ""); } public static TrackedRecipe Parse(string text) { string[] array = (text ?? "").Split(new char[1] { '|' }); if (array.Length < 3 || array.Length > 4 || array[0].Length == 0) { return null; } if (!int.TryParse(array[1], out var result) || !int.TryParse(array[2], out var result2)) { return null; } return new TrackedRecipe(array[0], result, result2, array.Length == 4 && array[3] == "u"); } } public static class TrackerCounts { public static int Need(Requirement requirement, int quality, int amount) { return requirement.GetAmount(quality) * amount; } public static int Have(Player player, Requirement requirement, int quality) { string name = requirement.m_resItem.m_itemData.m_shared.m_name; int num = ((Humanoid)player).GetInventory().CountItems(name, -1, true); if (!TrackerSettings.CountNearbyChests.Value || !ReachRules.Active(ReachRules.FromQuality(quality))) { return num; } return num + ReachCount.InContainers(name, -1, worldLevel: true); } public static bool Shows(Requirement requirement, TrackedRecipe tracked) { return RecipeNeeds.Counts(requirement, tracked.Quality, tracked.Upgrader); } } public class TrackerDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler { public RectTransform Target; private Vector2 last; public void OnBeginDrag(PointerEventData data) { //IL_001e: 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) if ((Object)(object)Target == (Object)null || !Local(data, out last)) { last = Vector2.zero; } } public void OnDrag(PointerEventData data) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_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_003e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Target == (Object)null) && Local(data, out var point)) { RectTransform target = Target; target.anchoredPosition += point - last; last = point; Clamp(Target); } } public void OnEndDrag(PointerEventData data) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0040: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Target == (Object)null)) { Clamp(Target); Vector2 anchoredPosition = Target.anchoredPosition; TrackerSettings.Position.Value = string.Format(CultureInfo.InvariantCulture, "{0:0},{1:0}", anchoredPosition.x, 0f - anchoredPosition.y); } } private bool Local(PointerEventData data, out Vector2 point) { //IL_000b: 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_0022: Expected O, but got Unknown return RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Transform)Target).parent, data.position, data.pressEventCamera, ref point); } public static void Clamp(RectTransform target) { //IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_004d: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) Rect rect = ((RectTransform)((Transform)target).parent).rect; Rect rect2 = target.rect; Vector2 val = Vector2.Scale(((Rect)(ref rect2)).size, Vector2.op_Implicit(((Transform)target).localScale)); float num = Mathf.Clamp(target.anchoredPosition.x, 0f, Mathf.Max(0f, ((Rect)(ref rect)).width - val.x)); float num2 = Mathf.Clamp(target.anchoredPosition.y, 0f - Mathf.Max(0f, ((Rect)(ref rect)).height - val.y), 0f); target.anchoredPosition = new Vector2(num, num2); } public static bool Saved(out Vector2 position) { //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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) position = Vector2.zero; string[] array = (TrackerSettings.Position.Value ?? "").Split(new char[1] { ',' }); if (array.Length != 2) { return false; } NumberStyles style = NumberStyles.Float; if (!float.TryParse(array[0].Trim(), style, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1].Trim(), style, CultureInfo.InvariantCulture, out var result2)) { return false; } position = new Vector2(result, result2); return true; } } public sealed class TrackerEntry { private const float Gap = 3f; private readonly TrackedRecipe tracked; private readonly Recipe recipe; private readonly List<Requirement> materials = new List<Requirement>(); private readonly List<TMP_Text> labels = new List<TMP_Text>(); private readonly List<TMP_Text> counts = new List<TMP_Text>(); private readonly List<TMP_Text> notes = new List<TMP_Text>(); private readonly List<GameObject> controls = new List<GameObject>(); private TMP_Text name; private TMP_Text amount; private static bool Shift { get { if (!Input.GetKey((KeyCode)304)) { return Input.GetKey((KeyCode)303); } return true; } } private TrackerEntry(TrackedRecipe tracked, Recipe recipe) { this.tracked = tracked; this.recipe = recipe; } public static TrackerEntry Build(Transform parent, TrackedRecipe tracked, Recipe recipe, int index) { TrackerEntry trackerEntry = new TrackerEntry(tracked, recipe); RectTransform val = TrackerUi.Node("OpenKeep_TrackerEntry", parent); TrackerUi.Column(((Component)val).gameObject, 1f); trackerEntry.Header((Transform)(object)val, index); trackerEntry.Notes((Transform)(object)val); Requirement[] resources = recipe.m_resources; foreach (Requirement requirement in resources) { if (TrackerCounts.Shows(requirement, tracked)) { trackerEntry.Material((Transform)(object)val, requirement); } } return trackerEntry; } private void Header(Transform root, int index) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) float size = TrackerStyle.Size; HorizontalLayoutGroup val = TrackerUi.Row(root, "header", 3f); ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Color.clear; ((Component)val).gameObject.AddComponent<TrackerWheel>().Index = index; Control(TrackerUi.TextButton(((Component)val).transform, "remove", "X", size * 0.85f, delegate { TrackerList.Remove(index); })); TrackerUi.Icon(((Component)val).transform, recipe.m_item.m_itemData.GetIcon(), size * 1.6f); name = TrackerUi.Text(((Component)val).transform, "name", size, (TextAlignmentOptions)4097); name.text = TrackerList.DisplayName(recipe, tracked.Quality); TrackerUi.Flexible(name, size * 11f); Amount(((Component)val).transform, index); } private void Amount(Transform row, int index) { float size = TrackerStyle.Size; Control(TrackerUi.TextButton(row, "less", "-", size, delegate { TrackerList.Step(index, -1, Shift); })); amount = TrackerUi.Text(row, "amount", size, (TextAlignmentOptions)514); amount.text = "x" + tracked.Amount; TrackerUi.Short(amount, size * 1.6f); Control(TrackerUi.TextButton(row, "more", "+", size, delegate { TrackerList.Step(index, 1, Shift); })); } private void Control(Button button) { controls.Add(((Component)button).gameObject); } private void Notes(Transform root) { CraftingStation requiredStation = recipe.GetRequiredStation(tracked.Quality); if ((Object)(object)requiredStation != (Object)null) { Note(root, Lang.Format("$ok_tracker_station", Localization.instance.Localize(requiredStation.m_name), recipe.GetRequiredStationLevel(tracked.Quality))); } if (recipe.m_requireOnlyOneIngredient) { Note(root, Lang.Get("$ok_tracker_anyone")); } } private void Note(Transform root, string text) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) TMP_Text val = TrackerUi.Text(root, "note", TrackerStyle.Size * 0.8f, (TextAlignmentOptions)4097); val.text = text; ((Graphic)val).color = TrackerStyle.Dim; notes.Add(val); } private void Material(Transform root, Requirement requirement) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown float size = TrackerStyle.Size; HorizontalLayoutGroup obj = TrackerUi.Row(root, "material", 6f); ((LayoutGroup)obj).padding = new RectOffset(Mathf.RoundToInt(size * 0.4f), 0, 0, 0); TrackerUi.Icon(((Component)obj).transform, requirement.m_resItem.m_itemData.GetIcon(), size * 1.25f); TMP_Text val = TrackerUi.Text(((Component)obj).transform, "name", size * 0.9f, (TextAlignmentOptions)4097); val.text = Localization.instance.Localize(requirement.m_resItem.m_itemData.m_shared.m_name); TrackerUi.Flexible(val, size * 9f); TMP_Text val2 = TrackerUi.Text(((Component)obj).transform, "count", size * 0.9f, (TextAlignmentOptions)4100); TrackerUi.Short(val2, size * 3f); materials.Add(requirement); labels.Add(val); counts.Add(val2); } public void ShowControls(bool open) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject control in controls) { control.SetActive(open); } ((Component)amount).gameObject.SetActive(open || tracked.Amount > 1); float size = TrackerStyle.Size; float num = size * 1.6f + 3f + (open ? (size * 0.85f + 3f) : 0f); foreach (TMP_Text note in notes) { note.margin = new Vector4(num, 0f, 0f, 0f); } } public void Count(Player player) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) bool flag = true; bool flag2 = false; for (int i = 0; i < materials.Count; i++) { int num = TrackerCounts.Have(player, materials[i], tracked.Quality); int num2 = TrackerCounts.Need(materials[i], tracked.Quality, tracked.Amount); bool flag3 = num >= num2; Paint(i, num + "/" + num2, flag3 ? TrackerStyle.Have : TrackerStyle.Missing); flag = flag && flag3; flag2 = flag2 || flag3; } bool flag4 = (recipe.m_requireOnlyOneIngredient ? flag2 : flag); ((Graphic)name).color = (flag4 ? TrackerStyle.Ready : TrackerStyle.Have); } private void Paint(int row, string text, Color colour) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (counts[row].text != text) { counts[row].text = text; } ((Graphic)counts[row]).color = colour; ((Graphic)labels[row]).color = colour; } } public enum TrackerFont { Sans, Serif, Norse } public class TrackerHud : MonoBehaviour { private const float CountSeconds = 0.5f; private TrackerPanel panel; private int builtVersion = -1; private string builtStyle = ""; private string placedAt; private float nextCount; private void Update() { bool flag = TrackerVisibility.Show(); if (panel == null && flag && (Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_rootObject != (Object)null) { panel = TrackerPanel.Create(Hud.instance.m_rootObject.transform); } if (panel == null) { return; } panel.SetVisible(flag); if (!flag) { return; } panel.Interactive(TrackerVisibility.CursorFree); if (builtVersion != TrackerList.Version) { Rebuild(); nextCount = 0f; } Follow(); if (!(Time.unscaledTime < nextCount)) { nextCount = Time.unscaledTime + 0.5f; if (builtStyle != TrackerStyle.Signature) { Rebuild(); } panel.Count(Player.m_localPlayer); } } private void Follow() { string value = TrackerSettings.Position.Value; if (!(value == placedAt)) { placedAt = value; panel.Place(); } } private void Rebuild() { builtVersion = TrackerList.Version; builtStyle = TrackerStyle.Signature; panel.Rebuild(); panel.KeepOnScreen(); } } public static class TrackerList { private const string DataKey = "trackedRecipes"; private static List<TrackedRecipe> entries; private static Player loadedFor; public static int Version { get; private set; } public static List<TrackedRecipe> Entries { get { Player localPlayer = Player.m_localPlayer; if (entries == null || (Object)(object)loadedFor != (Object)(object)localPlayer) { Load(localPlayer); } return entries; } } public static bool IsTracked(Recipe recipe, int quality) { return IndexOf(recipe, quality) >= 0; } public static int IndexOf(Recipe recipe, int quality) { if ((Object)(object)recipe == (Object)null) { return -1; } string key = RecipeKeys.Of(recipe); bool atUpgrader = RecipeNeeds.AtUpgrader; List<TrackedRecipe> list = Entries; for (int i = 0; i < list.Count; i++) { if (list[i].Is(key, quality, atUpgrader)) { return i; } } return -1; } public static void Toggle(Recipe recipe, int quality) { if (TrackerSettings.Enabled.Value && !((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { int num = IndexOf(recipe, quality); if (num >= 0) { Remove(num); return; } if (Entries.Count >= TrackerSettings.MaxTracked.Value) { Messages.Center(Lang.Format("$ok_tracker_full", TrackerSettings.MaxTracked.Value)); return; } Entries.Add(new TrackedRecipe(RecipeKeys.Of(recipe), quality, StartAmount(recipe, quality), RecipeNeeds.AtUpgrader)); Save(); Messages.Center(Lang.Format("$ok_tracker_tracking", DisplayName(recipe, quality))); } } public static void Remove(int index) { if (index >= 0 && index < Entries.Count) { TrackedRecipe trackedRecipe = Entries[index]; Entries.RemoveAt(index); Save(); Recipe recipe = trackedRecipe.Recipe; if ((Object)(object)recipe != (Object)null) { Messages.Center(Lang.Format("$ok_tracker_untracked", DisplayName(recipe, trackedRecipe.Quality))); } } } public static void Step(int index, int direction, bool tens) { if (index >= 0 && index < Entries.Count) { int amount = Entries[index].Amount; int num = ((!tens) ? (amount + direction) : ((direction > 0) ? ((amount / 10 + 1) * 10) : ((amount - 1) / 10 * 10))); Entries[index].Amount = Mathf.Clamp(num, 1, 9999); Save(); } } public static void Crafted(Recipe recipe, int quality, int crafts) { int num = IndexOf(recipe, quality); if (num >= 0 && TrackerSettings.UntrackWhenCrafted.Value) { TrackedRecipe trackedRecipe = Entries[num]; trackedRecipe.Amount -= Mathf.Max(1, crafts); if (trackedRecipe.Amount > 0) { Save(); return; } Entries.RemoveAt(num); Save(); Messages.TopLeft(Lang.Format("$ok_tracker_made", DisplayName(recipe, quality))); } } public static string DisplayName(Recipe recipe, int quality) { string text = Localization.instance.Localize(recipe.m_item.m_itemData.m_shared.m_name); if (quality <= 1) { return text; } return Lang.Format("$ok_tracker_upgrade", text, quality); } private static int StartAmount(Recipe recipe, int quality) { if (quality != 1 || !((Object)(object)BatchAmount.Current == (Object)(object)recipe)) { return 1; } return Mathf.Max(1, BatchAmount.Value); } private static void Load(Player player) { loadedFor = player; entries = (from entry in CharacterData.GetList("trackedRecipes").Select(TrackedRecipe.Parse) where entry != null select entry).ToList(); Version++; } private static void Save() { CharacterData.SetSet("trackedRecipes", Entries.Select((TrackedRecipe entry) => entry.ToString())); Version++; } } public static class TrackerModule { public static void Initialize(SyncedConfiguration synced) { TrackerSettings.Bind(synced); } } public sealed class TrackerPanel { private const int InventoryOrder = 600; private const int AboveInventory = 50; private static readonly Vector2 DefaultPosition = new Vector2(20f, 330f); private readonly RectTransform root; private readonly CanvasGroup group; private readonly Image background; private readonly TMP_Text title; private readonly RectTransform list; private readonly List<TrackerEntry> entries = new List<TrackerEntry>(); private bool? open; private TrackerPanel(RectTransform root) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown this.root = root; group = ((Component)root).gameObject.AddComponent<CanvasGroup>(); background = ((Component)root).gameObject.AddComponent<Image>(); ((Graphic)background).raycastTarget = false; ((LayoutGroup)TrackerUi.Column(((Component)root).gameObject, 2f)).padding = new RectOffset(6, 6, 4, 6); ContentSizeFitter obj = ((Component)root).gameObject.AddComponent<ContentSizeFitter>(); obj.horizontalFit = (FitMode)2; obj.verticalFit = (FitMode)2; title = Title(root); list = TrackerUi.Node("OpenKeep_TrackerList", (Transform)(object)root); TrackerUi.Column(((Component)list).gameObject, 4f); } public static TrackerPanel Create(Transform hudRoot) { //IL_0016: 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_0040: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = TrackerUi.Node("OpenKeep_Tracker", hudRoot); obj.anchorMin = new Vector2(0f, 1f); obj.anchorMax = new Vector2(0f, 1f); obj.pivot = new Vector2(0f, 1f); OwnCanvas(((Component)obj).gameObject, hudRoot); return new TrackerPanel(obj); } private static void OwnCanvas(GameObject go, Transform hudRoot) { Canvas componentInParent = ((Component)hudRoot).GetComponentInParent<Canvas>(); Canvas val = (((Object)(object)InventoryGui.instance != (Object)null) ? ((Component)InventoryGui.instance).GetComponent<Canvas>() : null); Canvas val2 = go.AddComponent<Canvas>(); val2.overrideSorting = true; if ((Object)(object)componentInParent != (Object)null) { val2.sortingLayerID = componentInParent.sortingLayerID; } val2.sortingOrder = (((Object)(object)val != (Object)null) ? val.sortingOrder : 600) + 50; go.AddComponent<GraphicRaycaster>(); } public void SetVisible(bool visible) { if (((Component)root).gameObject.activeSelf != visible) { ((Component)root).gameObject.SetActive(visible); } } public void Interactive(bool free) { if (open == free) { return; } open = free; group.blocksRaycasts = free; foreach (TrackerEntry entry in entries) { entry.ShowControls(free); } KeepOnScreen(); } public void Rebuild() { for (int num = ((Transform)this.list).childCount - 1; num >= 0; num--) { GameObject gameObject = ((Component)((Transform)this.list).GetChild(num)).gameObject; gameObject.SetActive(false); Object.Destroy((Object)(object)gameObject); } entries.Clear(); Style(); List<TrackedRecipe> list = TrackerList.Entries; for (int i = 0; i < list.Count; i++) { Recipe recipe = list[i].Recipe; if (!((Object)(object)recipe == (Object)null)) { TrackerEntry trackerEntry = TrackerEntry.Build((Transform)(object)this.list, list[i], recipe, i); trackerEntry.ShowControls(open == true); entries.Add(trackerEntry); } } } public void Count(Player player) { foreach (TrackerEntry entry in entries) { entry.Count(player); } } private void Style() { //IL_0018: 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_0049: Unknown result type (might be due to invalid IL or missing references) float value = TrackerSettings.Scale.Value; ((Transform)root).localScale = new Vector3(value, value, 1f); Image val = GameBackground(); if ((Object)(object)val != (Object)null) { background.sprite = val.sprite; background.type = val.type; } ((Graphic)background).color = new Color(0f, 0f, 0f, TrackerSettings.BackgroundOpacity.Value); title.font = TrackerStyle.Font; title.fontSize = TrackerStyle.Size * 0.8f; title.text = Lang.Get("$ok_tracker_title"); } private static TMP_Text Title(RectTransform root) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) TMP_Text obj = TrackerUi.Text((Transform)(object)root, "OpenKeep_TrackerTitle", TrackerStyle.Size * 0.8f, (TextAlignmentOptions)4097); ((Graphic)obj).color = TrackerStyle.Dim; ((Graphic)obj).raycastTarget = true; ((Component)obj).gameObject.AddComponent<TrackerDrag>().Target = root; return obj; } public void Place() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Vector2 position; Vector2 val = (TrackerDrag.Saved(out position) ? position : DefaultPosition); root.anchoredPosition = new Vector2(val.x, 0f - val.y); KeepOnScreen(); } public void KeepOnScreen() { LayoutRebuilder.ForceRebuildLayoutImmediate(root); TrackerDrag.Clamp(root); } private static Image GameBackground() { InventoryGui instance = InventoryGui.instance; Transform val = (((Object)(object)instance != (Object)null && (Object)(object)instance.m_recipeDecription != (Object)null) ? instance.m_recipeDecription.transform.parent : null); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent<Image>(); } } [HarmonyPatch] public static class TrackerPatches { [HarmonyPatch(typeof(Hud), "Awake")] [HarmonyPostfix] public static void AfterHudAwake(Hud __instance) { if ((Object)(object)((Component)__instance).GetComponent<TrackerHud>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<TrackerHud>(); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPrefix] [HarmonyPriority(200)] public static void BeforeCrafting(InventoryGui __instance, Player player, out CraftWatch __state) { __state = CraftWatch.Start(__instance, player); } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPostfix] public static void AfterCrafting(Player player, CraftWatch __state) { __state?.Finish(player); } } public static class TrackerSettings { public const string Section = "13. Recipe Tracker"; public static ConfigEntry<bool> Enabled { get; private set; } public static ConfigEntry<int> MaxTracked { get; private set; } public static ConfigEntry<bool> CountNearbyChests { get; private set; } public static ConfigEntry<bool> UntrackWhenCrafted { get; private set; } public static ConfigEntry<bool> HideInCombat { get; private set; } public static ConfigEntry<bool> HideWithMap { get; private set; } public static ConfigEntry<float> Scale { get; private set; } public static ConfigEntry<TrackerFont> Font { get; private set; } public static ConfigEntry<int> FontSize { get; private set; } public static ConfigEntry<string> HaveColour { get; private set; } public static ConfigEntry<string> MissingColour { get; private set; } public static ConfigEntry<string> ReadyColour { get; private set; } public static ConfigEntry<float> BackgroundOpacity { get; private set; } public static ConfigEntry<string> Position { get; private set; } public static void Bind(SyncedConfiguration synced) { Enabled = synced.Bind("13. Recipe Tracker", "Enabled", true, "Track a recipe (right click it in the crafting list, its Track button, or right stick down on a gamepad) to keep it on screen with every material it needs: what you have against what the tracked amount needs. With the inventory open, drag the tracker by its title, change an amount with - and + (Shift: tens) or the mouse wheel, and remove a recipe with the X at its left.", false, null); MaxTracked = synced.Bind("13. Recipe Tracker", "Max Tracked", 6, "The most recipes tracked at once.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 12)); CountNearbyChests = synced.Bind("13. Recipe Tracker", "Count Nearby Chests", true, "Materials in the containers Reach would craft from where you stand count too (only while Reach and its Crafting switch are on). Off: only what you carry.", false, null); UntrackWhenCrafted = synced.Bind("13. Recipe Tracker", "Untrack When Crafted", true, "Crafting a tracked recipe counts its amount down; once that many are made it leaves the tracker. Off: it stays until you remove it.", false, null); HideInCombat = synced.Bind("13. Recipe Tracker", "Hide In Combat", true, "Hidden while a creature is after you, and for 5 seconds after.", false, null); HideWithMap = synced.Bind("13. Recipe Tracker", "Hide With Map", true, "Hidden while the large map is open.", false, null); BindLook(synced); } private static void BindLook(SyncedConfiguration synced) { Scale = synced.Bind("13. Recipe Tracker", "Scale", 1f, "The tracker's size.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 2f)); Font = synced.Bind("13. Recipe Tracker", "Font", TrackerFont.Sans, "The game's typeface to use: Sans (its body text), Serif (its item names) or Norse (its titles).", false, null); FontSize = synced.Bind("13. Recipe Tracker", "Font Size", 16, "The text size; the tracker widens with it.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(10, 28)); HaveColour = synced.Bind("13. Recipe Tracker", "Have Colour", "#FFFFFF", "A material you have enough of (HTML colour).", false, null); MissingColour = synced.Bind("13. Recipe Tracker", "Missing Colour", "#FF6A5A", "A material you are short of (HTML colour).", false, null); ReadyColour = synced.Bind("13. Recipe Tracker", "Ready Colour", "#FFB65C", "A recipe's name once every material is there (HTML colour).", false, null); BackgroundOpacity = synced.Bind("13. Recipe Tracker", "Background Opacity", 0.56f, "The dark background behind the tracker, 0 (none) to 1.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 1f)); Position = synced.Bind("13. Recipe Tracker", "Position", "", "Where the tracker's top left corner sits: x right and y down from the screen's top left, in interface units (20,330 is the default place at the left edge); written when you drag it. A place off the screen is pulled back onto it. Empty: the default place.", false, null); } public static Color Colour(ConfigEntry<string> entry, Color fallback) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (entry == null || !ColorUtility.TryParseHtmlString(entry.Value, ref result)) { return fallback; } return result; } } public static class TrackerStyle { private static readonly string[] FontNames = new string[3] { "Valheim-AveriaSansLibre", "Valheim-AveriaSerifLibre", "Valheim-Norsebold" }; private static readonly TMP_FontAsset[] fonts = (TMP_FontAsset[])(object)new TMP_FontAsset[FontNames.Length]; public static readonly Color Dim = new Color(0.72f, 0.72f, 0.72f, 1f); public static float Size => TrackerSettings.FontSize.Value; public static Color Have => TrackerSettings.Colour(TrackerSettings.HaveColour, Color.white); public static Color Missing => TrackerSettings.Colour(TrackerSettings.MissingColour, new Color(1f, 0.42f, 0.35f)); public static Color Ready => TrackerSettings.Colour(TrackerSettings.ReadyColour, new Color(1f, 0.713f, 0.361f)); public static string Signature => $"{TrackerSettings.Font.Value}|{TrackerSettings.FontSize.Value}|{TrackerSettings.Scale.Value}|{TrackerSettings.BackgroundOpacity.Value}|{(((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.m_recipes.Count : 0)}"; public static TMP_FontAsset Font { get { int num = Mathf.Clamp((int)TrackerSettings.Font.Value, 0, FontNames.Length - 1); if ((Object)(object)fonts[num] == (Object)null) { fonts[num] = Find(FontNames[num]); } if (!((Object)(object)fonts[num] != (Object)null)) { return Fallback(); } return fonts[num]; } } private static TMP_FontAsset Find(string name) { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name == name) { return val; } } return null; } private static TMP_FontAsset Fallback() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_recipeDecription != (Object)null && (Object)(object)instance.m_recipeDecription.font != (Object)null) { return instance.m_recipeDecription.font; } return TMP_Settings.defaultFontAsset; } } public static class TrackerUi { private static readonly Color Hover = new Color(1f, 0.713f, 0.361f, 1f); public static RectTransform Node(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_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: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }) { layer = ((Component)parent).gameObject.layer }; val.transform.SetParent(parent, false); return (RectTransform)val.transform; } public static TMP_Text Text(Transform parent, string name, float size, TextAlignmentOptions align) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.SetActive(false); val.layer = ((Component)parent).gameObject.layer; val.transform.SetParent(parent, false); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = TrackerStyle.Font; val.SetActive(true); ((TMP_Text)val2).fontSize = size; ((TMP_Text)val2).alignment = align; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val2).overflowMode = (TextOverflowModes)1; ((Graphic)val2).raycastTarget = false; ((Graphic)val2).color = Color.white; return (TMP_Text)(object)val2; } public static Image Icon(Transform parent, Sprite sprite, float size) { RectTransform val = Node("icon", parent); Image obj = ((Component)val).gameObject.AddComponent<Image>(); obj.sprite = sprite; obj.preserveAspect = true; ((Graphic)obj).raycastTarget = false; Fixed(((Component)val).gameObject, size, size); return obj; } public static Button TextButton(Transform parent, string name, string label, float size, Action click) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_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_00a5: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown RectTransform val = Node(name, parent); ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Color.clear; Button val2 = ((Component)val).gameObject.AddComponent<Button>(); TMP_Text val3 = Text((Transform)(object)val, "label", size, (TextAlignmentOptions)514); Stretch((RectTransform)val3.transform); val3.overflowMode = (TextOverflowModes)0; val3.text = label; ((Selectable)val2).targetGraphic = (Graphic)(object)val3; ColorBlock colors = ((Selectable)val2).colors; ((ColorBlock)(ref colors)).highlightedColor = Hover; ((ColorBlock)(ref colors)).pressedColor = Hover; ((Selectable)val2).colors = colors; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)val2).navigation = navigation; ((UnityEvent)val2.onClick).AddListener((UnityAction)delegate { Guard.Run("tracker " + name, click); }); Fixed(((Component)val).gameObject, size, size); return val2; } public static HorizontalLayoutGroup Row(Transform parent, string name, float spacing) { HorizontalLayoutGroup obj = ((Component)Node(name, parent)).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((LayoutGroup)obj).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; return obj; } public static VerticalLayoutGroup Column(GameObject go, float spacing) { VerticalLayoutGroup obj = go.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((LayoutGroup)obj).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; return obj; } public static void Fixed(GameObject go, float width, float height) { LayoutElement obj = go.AddComponent<LayoutElement>(); obj.minWidth = width; obj.preferredWidth = width; obj.minHeight = height; obj.preferredHeight = height; } public static void Flexible(TMP_Text text, float most) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) LayoutElement obj = ((Component)text).gameObject.AddComponent<LayoutElement>(); obj.flexibleWidth = 1f; obj.preferredWidth = Mathf.Min(text.GetPreferredValues(text.text).x + 1f, most); obj.minWidth = obj.preferredWidth; } public static void Short(TMP_Text text, float minWidth) { text.overflowMode = (TextOverflowModes)0; ((Component)text).gameObject.AddComponent<LayoutElement>().minWidth = minWidth; } public static void Stretch(RectTransform rect) { //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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero; } } public static class TrackerVisibility { private const float CombatLinger = 5f; private static float lastThreat = -100f; public static bool CursorFree { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)ZCursor.LockState != 1) { return ZCursor.IsVisible; } return false; } } public static bool Show() { Player localPlayer = Player.m_localPlayer; if (!TrackerSettings.Enabled.Value || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { return false; } if (localPlayer.IsTargeted()) { lastThreat = Time.time; } if (TrackerList.Entries.Count == 0) { return false; } if (TrackerSettings.HideWithMap.Value && Minimap.IsOpen()) { return false; } if (TrackerSettings.HideInCombat.Value) { return Time.time - lastThreat >= 5f; } return true; } } public class TrackerWheel : MonoBehaviour, IScrollHandler, IEventSystemHandler { public int Index; public void OnScroll(PointerEventData data) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) float delta = data.scrollDelta.y; if (!Mathf.Approximately(delta, 0f)) { bool tens = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); Guard.Run("tracker wheel", delegate { TrackerList.Step(Index, (delta > 0f) ? 1 : (-1), tens); }); } } } public static class TrackerWords { public const string Track = "$ok_tracker_track"; public const string Untrack = "$ok_tracker_untrack"; public const string Title = "$ok_tracker_title"; public const string Tracking = "$ok_tracker_tracking"; public const string Untracked = "$ok_tracker_untracked"; public const string Full = "$ok_tracker_full"; public const string Made = "$ok_tracker_made"; public const string Upgrade = "$ok_tracker_upgrade"; public const string Station = "$ok_tracker_station"; public const string AnyOne = "$ok_tracker_anyone"; } } namespace OpenKeep.Store { [HarmonyPatch(typeof(InventoryGui), "Show")] public static class AutoSortPatch { [HarmonyPrefix] public static void Prefix(InventoryGui __instance, out bool __state) { __state = InventoryGui.IsVisible(); } [HarmonyPostfix] public static void Postfix(Container container, bool __state) { if (StoreSettings.Enabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null)) { if ((Object)(object)container != (Object)null && StoreSettings.AutoSortContainers.Value) { Sorting.SortContainer(container, quiet: true); } if (!__state && StoreSettings.AutoSortInventory.Value) { Sorting.SortPlayer(Player.m_localPlayer, quiet: true); } } } } internal sealed class ChestBatch { private readonly Container container; private readonly string word; private int pending; private bool finished; public bool Shared { get; } public int Moved { get; private set; } public bool Waiting => pending > 0; public ChestBatch(Container container, string word) { this.container = container; this.word = word; Shared = StoreTargets.IsShared(container); } public void Put(ItemData item, int amount, int credit, Action after = null) { pending++; StackMover.Reserve(item); ChestWriter.Put(container, item, amount, null, delegate(bool ok) { StackMover.Release(item); Reply(ok, credit); after?.Invoke(); }); } public void Take(ItemData item, int amount, int credit) { pending++; ChestWriter.Take(container, item, amount, delegate(bool ok) { Reply(ok, credit); }); } public void Finish() { finished = true; } private void Reply(bool ok, int credit) { pending--; if (ok) { Moved += credit; } if (finished && pending == 0) { Report(); } } private void Report() { if (Moved > 0) { MoveMessages.Center(Lang.Format(word, Moved, StoreTargets.Name(container))); } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] public static class ClickRouting { [HarmonyPrefix] public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 if (!StoreSettings.Enabled.Value || item == null || (Object)(object)__instance.m_dragGo != (Object)null || (Object)(object)grid != (Object)(object)__instance.m_playerGrid) { return true; } if ((int)mod == 3 || !Keys.Held(StoreSettings.RouteModifier)) { return true; } Routing.Route(item); return false; } } public static class Cycling { private const float WheelCooldown = 0.25f; private static float lastWheel; public static void Poll(InventoryGui gui) { if (!((Object)(object)gui.m_currentContainer == (Object)null)) { if (Keys.Pressed(StoreSettings.CyclePreviousKey)) { Cycle(-1); } else if (Keys.Pressed(StoreSettings.CycleNextKey)) { Cycle(1); } else if (StoreSettings.CycleWithWheel.Value) { PollWheel(gui); } } } private static void PollWheel(InventoryGui gui) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) float mouseScrollWheel = ZInput.GetMouseScrollWheel(); if (mouseScrollWheel == 0f || Time.time - lastWheel < 0.25f || Keys.TextInputActive || (Object)(object)gui.m_containerGrid == (Object)null || TooltipScrolls() || GridScrolls(gui.m_containerGrid)) { return; } Transform transform = ((Component)gui.m_containerGrid).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (!((Object)(object)val == (Object)null)) { Rect rect = val.rect; if (((Rect)(ref rect)).Contains(Vector2.op_Implicit(((Transform)val).InverseTransformPoint(ZInput.pointerPosition)))) { lastWheel = Time.time; Cycle((!(mouseScrollWheel > 0f)) ? 1 : (-1)); } } } private static bool GridScrolls(InventoryGrid grid) { Scrollbar scrollbar = grid.m_scrollbar; if ((Object)(object)scrollbar != (Object)null && ((Component)scrollbar).gameObject.activeInHierarchy) { return scrollbar.size < 0.999f; } return false; } private static bool TooltipScrolls() { GameObject tooltip = UITooltip.m_tooltip; Transform val = (((Object)(object)tooltip != (Object)null && tooltip.activeInHierarchy) ? Utils.FindChild(tooltip.transform, "ecf_tooltip_bar", (IterativeSearchType)0) : null); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject.activeInHierarchy; } return false; } public static void Cycle(int direction) { if (!StoreActions.Ready(out var player)) { return; } InventoryGui instance = InventoryGui.instance; Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); if (!((Object)(object)val == (Object)null)) { List<Container> list = Ring(player, instance, val); if (list.Count < 2) { Messages.Center("$ok_store_nocycle"); return; } int num = list.IndexOf(val); Container obj = list[(num + direction + list.Count) % list.Count]; instance.CloseContainer(); obj.Interact((Humanoid)(object)player, false, false); } } private static List<Container> Ring(Player player, InventoryGui gui, Container current) { //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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(StoreSettings.NearbyRange.Value, gui.m_autoCloseDistance); Vector3 origin = ((Component)player).transform.position; List<Container> list = ContainerScan.Nearby(origin, num, ContainerUse.Store); foreach (Container item in ContainerScan.All()) { if (!list.Contains(item) && StoreTargets.Distance(origin, item) <= num && Viewable(item)) { list.Add(item); } } if (!list.Contains(current)) { list.Add(current); } list.Sort((Container a, Container b) => Angle(origin, a).CompareTo(Angle(origin, b))); return list; } private static bool Viewable(Container container) { //IL_0068: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || CoreSettings.SharedChests.Value == SharedMode.Off || container.GetInventory() == null) { return false; } if (!ContainerScan.InUseByAnother(container) || !ContainerRules.IsEnabled(ContainerScan.PrefabName(container)) || !SwitchAllows(container)) { return false; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false)) { return false; } if ((int)container.m_privacy == 0 && (Object)(object)container.m_piece == (Object)null) { return false; } return container.CheckAccess(localPlayer.GetPlayerID()); } private static bool SwitchAllows(Container container) { if (ContainerScan.IsShip(container)) { return CoreSettings.Ships.Value; } if (ContainerScan.IsCart(container)) { return CoreSettings.Carts.Value; } if (ContainerScan.IsPrivateChest(container)) { return CoreSettings.PlayerChests.Value; } return true; } private static float Angle(Vector3 origin, Container container) { //IL_0006: 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_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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)container).transform.position - origin; return Mathf.Atan2(val.z, val.x); } } public static class DumpKeyPatch { public static void Tick(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && StoreSettings.Enabled.Value && !Keys.InventoryOpen && !Menu.IsVisible() && !Console.IsVisible() && !UnifiedPopup.IsVisible() && Keys.Pressed(StoreSettings.DumpKey)) { StoreActions.Dump(); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] public static class FavouriteOverlay { [HarmonyPostfix] public static void Postfix(InventoryGrid __instance, Player player) { Refresh(__instance, (Object)(object)player != (Object)null); } public static void Refresh(InventoryGrid grid, bool playerGrid) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) bool flag = StoreSettings.Enabled.Value && StoreSettings.ShowFavourites.Value; if (GridMarks.Of(grid).Current(grid.m_inventory, grid.m_elements, flag, playerGrid)) { return; } Inventory inventory = grid.m_inventory; foreach (InventoryElement element in grid.m_elements) { SlotMarks slotMarks = ((Component)element).GetComponent<SlotMarks>(); if (!((Object)(object)slotMarks == (Object)null) || (flag && inventory != null)) { if ((Object)(object)slotMarks == (Object)null) { slotMarks = SlotMarks.Attach(element); } ItemData val = ((flag && inventory != null) ? inventory.GetItemAt(element.Position.x, element.Position.y) : null); bool favouriteItem = val != null && Favourites.IsFavouriteItem(val); bool favouriteSlot = flag && playerGrid && Favourites.IsFavouriteSlot(element.Position); bool junk = val != null && Favourites.IsJunk(val); slotMarks.Set(favouriteItem, favouriteSlot, junk); } } } } public static class Favourites { private const string ItemsKey = "favouriteItems"; private const string SlotsKey = "favouriteSlots"; private const string JunkKey = "junk"; private static Player cachedFor; private static HashSet<string> items; private static HashSet<string> slots; private static HashSet<string> junk; private static HashSet<int> slotKeys; private static int revision; public static int Revision { get { CheckPlayer(); return revision; } } public static bool IsFavouriteItem(ItemData item) { if (item != null) { return Set(ref items, "favouriteItems").Contains(Id(item)); } return false; } public static bool IsJunk(ItemData item) { if (item != null) { return Set(ref junk, "junk").Contains(Id(item)); } return false; } public static bool IsFavouriteSlot(Vector2i pos) { //IL_0005: 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) return SlotKeys().Contains(Pack(pos.x, pos.y)); } public static bool ToggleItem(ItemData item) { return Toggle(ref items, "favouriteItems", Id(item)); } public static bool ToggleSlot(Vector2i pos) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) slotKeys = null; return Toggle(ref slots, "favouriteSlots", SlotId(pos)); } public static bool ToggleJunk(ItemData item) { return Toggle(ref junk, "junk", Id(item)); } public static void ToggleItemWithMessage(ItemData item) { Messages.Center(Lang.Format(ToggleItem(item) ? "$ok_store_favourite_on" : "$ok_store_favourite_off", ItemNames.DisplayName(item))); } public static void ToggleSlotWithMessage(Vector2i pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) Messages.Center(Lang.Format(ToggleSlot(pos) ? "$ok_store_slot_on" : "$ok_store_slot_off", pos.x + 1 + "," + (pos.y + 1))); } public static void ToggleJunkWithMessage(ItemData item) { Messages.Center(Lang.Format(ToggleJunk(item) ? "$ok_store_junk_on" : "$ok_store_junk_off", ItemNames.DisplayName(item))); } private static string Id(ItemData item) { return ItemNames.PrefabName(item); } private static string SlotId(Vector2i pos) { return pos.x + ":" + pos.y; } private static int Pack(int x, int y) { return (x << 16) | (y & 0xFFFF); } private static HashSet<int> SlotKeys() { HashSet<string> hashSet = Set(ref slots, "favouriteSlots"); if (slotKeys != null) { return slotKeys; } slotKeys = new HashSet<int>(); foreach (string item in hashSet) { string[] array = item.Split(new char[1] { ':' }); if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2)) { slotKeys.Add(Pack(result, result2)); } } return slotKeys; } private static bool Toggle(ref HashSet<string> set, string key, string id) { if (string.IsNullOrEmpty(id)) { return false; } HashSet<string> hashSet = Set(ref set, key); bool num = !hashSet.Remove(id); if (num) { hashSet.Add(id); } CharacterData.SetSet(key, hashSet); revision++; return num; } private static HashSet<string> Set(ref HashSet<string> set, string key) { CheckPlayer(); return set ?? (set = CharacterData.GetSet(key)); } private static void CheckPlayer() { if (!((Object)(object)cachedFor == (Object)(object)Player.m_localPlayer)) { items = (slots = (junk = null)); slotKeys = null; cachedFor = Player.m_localPlayer; revision++; } } } public static class Finder { private const float DefaultSeconds = 5f; public static void Find(ItemData item) { if (!StoreActions.Ready(out var player) || item == null) { return; } string text = ItemNames.DisplayName(item); float seconds = LinkSeconds(); int num = 0; foreach (Container item2 in StoreTargets.Nearby(player)) { int num2 = item2.GetInventory().CountItems(item.m_shared.m_name, -1, false); if (num2 > 0) { num++; LinkMarker.Create(player, item2, text + " x" + num2, seconds); } } Messages.Center((num > 0) ? Lang.Format("$ok_store_found", text, num) : Lang.Format("$ok_store_notfound", text)); } public static float LinkSeconds() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown ConfigFile val = (((Object)(object)Plugin.Instance != (Object)null) ? ((BaseUnityPlugin)Plugin.Instance).Config : null); ConfigDefinition val2 = new ConfigDefinition("1. Reach", "Link Seconds"); if (val == null || !val.ContainsKey(val2)) { return 5f; } try { return Convert.ToSingle(val[val2].BoxedValue); } catch (Exception) { return 5f; } } } public sealed class GridMarks : MonoBehaviour { private const float MaxAge = 0.25f; private Inventory inventory; private InventoryElement first; private int count = -1; private int change = -1; private int revision = -1; private bool show; private bool playerGrid; private float at = float.MinValue; public static GridMarks Of(InventoryGrid grid) { GridMarks component = ((Component)grid).GetComponent<GridMarks>(); if (!((Object)(object)component != (Object)null)) { return ((Component)grid).gameObject.AddComponent<GridMarks>(); } return component; } public bool Current(Inventory now, List<InventoryElement> elements, bool showing, bool forPlayer) { InventoryElement val = ((elements.Count > 0) ? elements[0] : null); float unscaledTime = Time.unscaledTime; if (now == inventory && (Object)(object)val == (Object)(object)first && elements.Count == count && InventoryChanges.Count == change && Favourites.Revision == revision && showing == show && forPlayer == playerGrid && unscaledTime - at < 0.25f) { return true; } inventory = now; first = val; count = elements.Count; change = InventoryChanges.Count; revision = Favourites.Revision; show = showing; playerGrid = forPlayer; at = unscaledTime; return false; } } [HarmonyPatch(typeof(Container), "CheckForChanges")] public static class GroundPickup { private static readonly Dictionary<Container, float> nextSweep = new Dictionary<Container, float>(); private static readonly List<ItemDrop> drops = new List<ItemDrop>(); private static readonly PruneMark pruneMark = new PruneMark(64); [HarmonyPostfix] public static void Postfix(Container __instance) { Tick(__instance); } public static void Tick(Container container) { if (!StoreSettings.Enabled.Value || !StoreSettings.GroundPickup.Value || (Object)(object)container == (Object)null) { return; } ZNetView nview = container.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner() || container.IsInUse() || !StoreRules.PicksUp(container) || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || !Due(container) || !ContainerScan.IsUsable(container, ContainerUse.Store)) { return; } using (SaveHolds.Hold(container)) { if (Sweep(container) > 0) { ContainerScan.Save(container); } } } private static bool Due(Container container) { float time = Time.time; float num = Mathf.Max(1f, StoreSettings.PickupInterval.Value); if (!nextSweep.TryGetValue(container, out var value)) { if (pruneMark.Due(nextSweep.Count)) { Prune(); } nextSweep[container] = time + num * ((float)(((Object)container).GetInstanceID() & 0xFF) / 256f); return false; } if (time < value) { return false; } nextSweep[container] = time + num; return true; } private static void Prune() { List<Container> list = new List<Container>(); foreach (Container key in nextSweep.Keys) { if ((Object)(object)key == (Object)null) { list.Add(key); } } foreach (Container item in list) { nextSweep.Remove(item); } pruneMark.Pruned(nextSweep.Count); } private static int Sweep(Container container) { //IL_0006: 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_004e: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)container).transform.position; float value = StoreSettings.PickupRange.Value; List<Container> list = null; int num = 0; drops.AddRange(ItemDrop.s_instances); foreach (ItemDrop drop in drops) { if (!((Object)(object)drop == (Object)null) && Eligible(container, drop, position, value)) { list = list ?? PickupOrder.Rivals(container, value); if (PickupOrder.IsFirst(container, drop, list, value)) { num += Take(container, drop); } } } drops.Clear(); return num; } private static bool Eligible(Container container, ItemDrop drop, Vector3 origin, float range) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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_008c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = origin - ((Component)drop).transform.position; if (((Vector3)(ref val)).sqrMagnitude > range * range) { return false; } ZNetView nview = drop.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || drop.m_itemData == null || drop.m_itemData.m_shared == null || drop.IsPiece()) { return false; } if (Age(nview) < (double)StoreSettings.PickupDelay.Value || !Wanted(container, drop.m_itemData)) { return false; } if (CoreSettings.HonourWards.Value) { return PrivateArea.CheckAccess(((Component)drop).transform.position, 0f, false, false); } return true; } private static double Age(ZNetView view) { long num = view.GetZDO().GetLong(ZDOVars.s_spawnTime, 0L); if (num == 0L || (Object)(object)ZNet.instance == (Object)null) { return -1.0; } return (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds; } internal static bool Wanted(Container container, ItemData item) { if (StoreRules.Refuses(container, item)) { return false; } if (StoreRules.Accepts(container, item)) { return true; } if (StoreSettings.PickupOnlyHeldItems.Value) { return container.GetInventory().ContainsItemByName(item.m_shared.m_name); } return true; } private static bool Owned(ItemDrop drop) { ZNetView nview = drop.m_nview; if (nview.IsOwner()) { return true; } if (nview.GetZDO().HasOwner()) { drop.RequestOwn(); return false; } nview.ClaimOwnership(); return nview.IsOwner(); } private static int Take(Container container, ItemDrop drop) { if (!Owned(drop)) { return 0; } drop.Load(); ItemData val = drop.m_itemData.Clone(); int stack = val.m_stack; if (stack <= 0) { return 0; } if (container.GetInventory().AddItem(val)) { ZNetScene.instance.Destroy(((Component)drop).gameObject); return stack; } int num = stack - val.m_stack; if (num > 0) { drop.m_itemData.m_stack = val.m_stack; drop.Save(); } return num; } } public static class HoveredItem { public static bool Find(InventoryGui gui, out InventoryGrid grid, out Vector2i pos) { //IL_0006: 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) grid = null; pos = new Vector2i(-1, -1); if ((Object)(object)gui == (Object)null) { return false; } if (TryGrid(gui.m_playerGrid, out pos)) { grid = gui.m_playerGrid; return true; } if ((Object)(object)gui.m_currentContainer != (Object)null && (Object)(object)gui.m_container != (Object)null && ((Component)gui.m_container).gameObject.activeSelf && TryGrid(gui.m_containerGrid, out pos)) { grid = gui.m_containerGrid; return true; } return false; } public static ItemData Item(InventoryGrid grid, Vector2i pos) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)grid != (Object)null) || grid.m_inventory == null) { return null; } return grid.m_inventory.GetItemAt(pos.x, pos.y); } private static bool TryGrid(InventoryGrid grid, out Vector2i pos) { //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_005e: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) pos = new Vector2i(-1, -1); if ((Object)(object)grid == (Object)null || grid.m_inventory == null || !((Component)grid).gameObject.activeInHierarchy) { return false; } if ((Object)(object)grid.m_uiGroup != (Object)null && grid.m_uiGroup.IsActive && (ZInput.IsExclusiveGamepadActive() || ZInput.IsTouchActive())) { pos = grid.m_selected; if (pos.x >= 0) { return pos.y >= 0; } return false; } InventoryElement hoveredElement = grid.GetHoveredElement(); if ((Object)(object)hoveredElement == (Object)null) { return false; } pos = grid.GetElementPos(hoveredElement); return pos.x >= 0; } } public sealed class LinkMarker : MonoBehaviour { private static readonly Color LinkColour = new Color(0.44f, 0.76f, 1f, 0.9f); private static Material lineMaterial; private LineRenderer line; private TextMeshPro label; private Transform target; private float endTime; public static void Create(Player player, Container container, string text, float seconds) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown GameObject val = new GameObject("OpenKeep_link"); LinkMarker linkMarker = val.AddComponent<LinkMarker>(); linkMarker.target = ((Component)container).transform; linkMarker.endTime = Time.time + Mathf.Max(0.5f, seconds); linkMarker.line = BuildLine(val); linkMarker.label = BuildLabel(val, text); linkMarker.Refresh(); } private void Update() { if (Time.time >= endTime || (Object)(object)target == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); } else { Refresh(); } } private void Refresh() { //IL_000a: 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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0039: 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_004e: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)Player.m_localPlayer).transform.position + Vector3.up; Vector3 val2 = target.position + Vector3.up * 0.5f; line.SetPosition(0, val); line.SetPosition(1, val2); label.transform.position = target.position + Vector3.up * 1.6f; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { label.transform.rotation = Quaternion.LookRotation(label.transform.position - ((Component)main).transform.position); } } private static LineRenderer BuildLine(GameObject go) { //IL_0036: 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) LineRenderer obj = go.AddComponent<LineRenderer>(); obj.useWorldSpace = true; obj.positionCount = 2; obj.startWidth = 0.06f; obj.endWidth = 0.06f; ((Renderer)obj).material = LineMaterial(); obj.startColor = LinkColour; obj.endColor = LinkColour; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; return obj; } private static TextMeshPro BuildLabel(GameObject parent, string text) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0023: 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_0085: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("label"); val.SetActive(false); val.transform.SetParent(parent.transform, false); TextMeshPro val2 = val.AddComponent<TextMeshPro>(); TMP_FontAsset val3 = LabelFont(); if ((Object)(object)val3 != (Object)null) { ((TMP_Text)val2).font = val3; } val.SetActive(true); ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = 3.5f; ((Graphic)val2).color = LinkColour; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val2).rectTransform.sizeDelta = new Vector2(8f, 1.5f); return val2; } private static TMP_FontAsset LabelFont() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_containerName != (Object)null && (Object)(object)instance.m_containerName.font != (Object)null) { return instance.m_containerName.font; } return TMP_Settings.defaultFontAsset; } private static Material LineMaterial() { //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if ((Object)(object)lineMaterial != (Object)null) { return lineMaterial; } lineMaterial = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended") ?? Shader.Find("Standard")) { color = LinkColour }; return lineMaterial; } } public static class MainGrid { private const int GameDefaultRows = 4; public static int FirstRow(Player player, Inventory inventory) { if (!((Object)(object)player != (Object)null) || inventory != ((Humanoid)player).GetInventory()) { return 0; } return 1; } public static int Rows(Player player, Inventory inventory) { int height = inventory.GetHeight(); if ((Object)(object)player == (Object)null || inventory != ((Humanoid)player).GetInventory()) { return height; } int value = StoreSettings.MainInventoryRows.Value; return Math.Min(height, (value > 0) ? value : GameRows(player)); } private static int GameRows(Player player) { if (PackPanelGrid.TryRead(player, out var _, out var mainRows, out var _)) { return mainRows; } string s = default(string); if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result)) { return result; } return 4; } } public static class Movable { public static string Blocker(Player player, Inventory inventory, ItemData item) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (item == null || item.m_shared == null) { return ""; } if (item.m_equipped || ((Object)(object)player != (Object)null && ((Humanoid)player).IsItemEquiped(item))) { return "$ok_store_equipped_kept"; } if (item.m_shared.m_questItem || StackMover.IsPending(item)) { return ""; } if ((Object)(object)player != (Object)null && inventory == ((Humanoid)player).GetInventory() && Favourites.IsFavouriteSlot(item.m_gridPos)) { return "$ok_store_favourite_kept"; } if (Favourites.IsFavouriteItem(item)) { return "$ok_store_favourite_kept"; } return null; } public static bool CanMove(Player player, Inventory inventory, ItemData item) { return Blocker(player, inventory, item) == null; } } internal static class MoveMessages { public static void Center(string text) { if (StoreSettings.MoveMessages.Value) { Messages.Center(text); } } public static void TopLeft(string text) { if (StoreSettings.MoveMessages.Value) { Messages.TopLeft(text); } } } internal sealed class Overflow { private readonly Player player; private readonly ItemData item; private readonly List<Container> line = new List<Container>(); private readonly int chosen; private readonly int fallback = -1; private readonly Action<Overflow> done; private int left; private int next; public List<Container> Took { get; } = new List<Container>(); public bool RefusalSaid { get; private set; } private Overflow(Player player, ItemData item, int amount, Container first, List<Container> rest, Container last, Action<Overflow> done) { this.player = player; this.item = item; this.done = done; left = amount; if ((Object)(object)first != (Object)null) { line.Add(first); } chosen = line.Count; foreach (Container item2 in rest) { if ((Object)(object)item2 != (Object)(object)first && (Object)(object)item2 != (Object)(object)last) { line.Add(item2); } } if ((Object)(object)last != (Object)null && (Object)(object)last != (Object)(object)first) { fallback = line.Count; line.Add(last); } } public static void Send(Player player, ItemData item, int amount, Container first, List<Container> rest, Action<Overflow> done, Container last = null) { new Overflow(player, item, amount, first, rest, last, done).Step(); } private void Step() { Container target = NextTarget(); if ((Object)(object)target == (Object)null) { done?.Invoke(this); return; } int before = Units(); bool shared = StoreTargets.IsShared(target); StackMover.Reserve(item); ChestWriter.Put(target, item, Math.Min(left, before), null, delegate(bool ok) { Answered(target, before, shared, ok); }); } private void Answered(Container target, int before, bool shared, bool ok) { StackMover.Release(item); int num = Math.Max(0, before - Units()); if (num > 0) { left -= num; Took.Add(target); } RefusalSaid = shared && !ok; Step(); } private Container NextTarget() { if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return null; } while (next < line.Count && left > 0 && Units() > 0 && Movable.CanMove(player, ((Humanoid)player).GetInventory(), item)) { Container val = line[next]; bool mustHold = next >= chosen && next != fallback; next++; if (Takes(val, mustHold)) { return val; } } return null; } private bool Takes(Container container, bool mustHold) { if ((Object)(object)container == (Object)null || !StoreTargets.IsTarget(container) || StoreRules.Refuses(container, item) || !container.GetInventory().CanAddItem(item, 1)) { return false; } if (mustHold) { return container.GetInventory().ContainsItemByName(item.m_shared.m_name); } return true; } private int Units() { Inventory val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetInventory() : null); if (val == null || !val.ContainsItem(item)) { return 0; } return item.m_stack; } } [HarmonyPatch(typeof(InventoryGui), "Awake")] public static class PanelButtons { private const float Width = 78f; private const float Height = 26f; private const float Gap = 4f; private const float BelowEdge = -30f; private const string PackPanelStrip = "PackPanel_buttonstrip"; private const float InsideStrip = 2f; private const string Prefix = "OpenKeep_"; private static readonly List<RectTransform> Placed = new List<RectTransform>(); private static bool rowInside; private static float Offset => (StoreSettings.ButtonRowOffset != null) ? StoreSettings.ButtonRowOffset.Value : 0; private static float BottomOf(RectTransform rect) { return ((rowInside && (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)((Transform)rect).parent == (Object)(object)InventoryGui.instance.m_player) ? 2f : (-30f)) + Offset; } public static void Follow(InventoryGui gui) { bool flag = StripShown(gui); if (flag != rowInside) { rowInside = flag; Reposition(); } } private static bool StripShown(InventoryGui gui) { if (!PackPanelLink.Present || (Object)(object)gui == (Object)null || (Object)(object)gui.m_player == (Object)null) { return false; } Transform val = ((Transform)gui.m_player).Find("PackPanel_buttonstrip"); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject.activeSelf; } return false; } [HarmonyPostfix] public static void Postfix(InventoryGui __instance) { Guard.Run("store panel buttons", delegate { Create(__instance); }); } public static void Reposition() { //IL_0041: 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) Placed.RemoveAll((RectTransform rect) => (Object)(object)rect == (Object)null); foreach (RectTransform item in Placed) { item.anchoredPosition = new Vector2(item.anchoredPosition.x, BottomOf(item)); } } public static void Create(InventoryGui gui) { if (!((Object)(object)gui == (Object)null) && !((Object)(object)gui.m_takeAllButton == (Object)null) && !((Object)(object)gui.m_player == (Object)null) && !((Object)(object)gui.m_container == (Object)null)) { bool flag = !PackPanelLink.LaysOutInventory && StoreSettings.TrashOnStatColumn.Value && TrashPlate.TryCreate(gui, delegate { TrashMode.CanClicked(gui); }); float num = -123f - (flag ? 0f : 15f); Add(gui, gui.m_player, "$ok_store_quickstack", num, StoreActions.QuickStack); num += 82f; Add(gui, gui.m_player, "$ok_store_storeall", num, StoreActions.StoreAll); num += 82f; Add(gui, gui.m_player, "$ok_store_topup", num, TopUp.Run); num += 82f; Add(gui, gui.m_player, "$ok_store_sort", num, delegate { Sorting.SortPlayer(Player.m_localPlayer, quiet: false); }); if (!flag) { AddTrash(gui, gui.m_player, num + 39f + 4f + 13f); } Add(gui, gui.m_container, "$ok_store_sort", 0f, Sorting.SortOpenContainer); } } private static void Add(InventoryGui gui, RectTransform panel, string word, float centreX, Action action) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, (Transform)(object)panel); ((Object)val).name = "OpenKeep_" + word.TrimStart(new char[1] { '$' }); val.SetActive(true); Place((RectTransform)val.transform, centreX, new Vector2(78f, 26f)); Button component = val.GetComponent<Button>(); if ((Object)(object)component != (Object)null) { component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { Guard.Run(word, action); }); } SetLabel(val, word); } private static void Place(RectTransform rect, float centreX, Vector2 size) { //IL_000b: 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_0035: 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_0052: 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) rect.anchorMin = new Vector2(0.5f, 0f); rect.anchorMax = new Vector2(0.5f, 0f); rect.pivot = new Vector2(0.5f, 0f); rect.anchoredPosition = new Vector2(centreX, BottomOf(rect)); rect.sizeDelta = size; ((Transform)rect).localScale = Vector3.one; Placed.Add(rect); } private static void SetLabel(GameObject go, string word) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) TMP_Text componentInChildren = go.GetComponentInChildren<TMP_Text>(true); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.text = Lang.Get(word); componentInChildren.enableAutoSizing = true; componentInChildren.fontSizeMax = Mathf.Max(12f, Mathf.Min(componentInChildren.fontSize, 16f)); componentInChildren.fontSizeMin = 9f; componentInChildren.overflowMode = (TextOverflowModes)1; componentInChildren.margin = new Vector4(6f, 1f, 6f, 1f); componentInChildren.textWrappingMode = (TextWrappingModes)0; } } private static void AddTrash(InventoryGui gui, RectTransform panel, float centreX) { //IL_003c: 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_0056: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, (Transform)(object)panel); ((Object)val).name = "OpenKeep_trashcan"; val.SetActive(true); Place((RectTransform)val.transform, centreX, new Vector2(26f, 26f)); TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.SetActive(false); } BinIcon(val.transform); Button component = val.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { Guard.Run("trash can", delegate { TrashMode.CanClicked(gui); }); }); } private static Image BinIcon(Transform button) { //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_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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_005e: 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) GameObject val = new GameObject("icon", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(button, false); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = new Vector2(4f, 4f); val2.offsetMax = new Vector2(-4f, -4f); Image component = val.GetComponent<Image>(); component.sprite = StoreSprites.Bin; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; return component; } } internal static class PickupOrder { private const float HolderLead = 100000f; public static List<Container> Rivals(Container container, float range) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) List<Container> list = ContainerScan.Nearby(((Component)container).transform.position, range * 2f, ContainerUse.Store); list.RemoveAll((Container rival) => (Object)(object)rival == (Object)(object)container || !StoreRules.PicksUp(rival)); return list; } public static bool IsFirst(Container container, ItemDrop drop, List<Container> rivals, float range) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) ItemData itemData = drop.m_itemData; Vector3 position = ((Component)drop).transform.position; float num = Rank(container, itemData, position); float num2 = range * range; foreach (Container rival in rivals) { if (!((Object)(object)rival == (Object)null)) { Vector3 val = ((Component)rival).transform.position - position; if (!(((Vector3)(ref val)).sqrMagnitude > num2) && Rank(rival, itemData, position) < num && TakesNow(rival, itemData)) { return false; } } } return true; } private static float Rank(Container container, ItemData item, Vector3 at) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) return (container.GetInventory().ContainsItemByName(item.m_shared.m_name) ? 0f : 100000f) + Vector3.Distance(((Component)container).transform.position, at); } private static bool TakesNow(Container rival, ItemData item) { if (StoreRules.PicksUp(rival) && !rival.IsInUse() && GroundPickup.Wanted(rival, item)) { return rival.GetInventory().CanAddItem(item, 1); } return false; } } public static class Routing { public static void Route(ItemData item) { if (!StoreActions.Ready(out var player) || Refused(player, item)) { return; } string name = ItemNames.DisplayName(item); List<Container> list = StoreTargets.Nearby(player); list.RemoveAll((Container container) => StoreRules.Refuses(container, item)); Container val = FindTarget(list, item); if ((Object)(object)val == (Object)null) { Messages.Center(Lang.Format("$ok_store_noroute", name)); } else { Overflow.Send(player, item, item.m_stack, val, list, delegate(Overflow sent) { Report(sent, SentWords(sent, name)); }, StoreTargets.OpenTarget); } } public static void StoreOne(ItemData item) { if (!StoreActions.Ready(out var player) || Refused(player, item)) { return; } string name = ItemNames.DisplayName(item); Container openTarget = StoreTargets.OpenTarget; if ((Object)(object)openTarget == (Object)null && StoreTargets.ViewingOnly()) { return; } List<Container> list = StoreTargets.Nearby(player); openTarget = openTarget ?? Holder(list, item); if ((Object)(object)openTarget == (Object)null || StoreRules.Refuses(openTarget, item)) { Messages.Center(Lang.Format("$ok_store_noroute", name)); return; } Overflow.Send(player, item, 1, openTarget, list, delegate(Overflow sent) { Report(sent, Lang.Format("$ok_store_storedone", name)); }); } internal static string SentWords(Overflow sent, string name) { if (sent.Took.Count == 0) { return ""; } string text = StoreTargets.Name(sent.Took[0]); if (sent.Took.Count == 1) {