using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExtraPotions.Kindle.Config; using ExtraPotions.Kindle.Recipes; using ExtraPotions.Kindle.Repair; using ExtraPotions.Kindle.Runtime.Salvage; using ExtraPotions.Kindle.Salvage; using ExtraPotions.Meadworks.Contracts; using ExtraPotions.Meadworks.Crucible; using ExtraPotions.Meadworks.Crucible.UI; using HarmonyLib; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Serialization; [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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ExtraPotions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")] [assembly: AssemblyFileVersion("0.1.25.0")] [assembly: AssemblyInformationalVersion("0.1.25")] [assembly: AssemblyProduct("Kindle")] [assembly: AssemblyTitle("Kindle")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.25.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 ExtraPotions.Kindle.Runtime { public static class BatchAmount { private static Recipe recipe; public static int Value { get; private set; } = 1; public static Recipe Current => recipe; internal static void Reset() { recipe = null; Value = 1; } public static bool Applies(InventoryGui gui, Player player) { if (!KindleBatch.Active || SalvageTabCapability.Active || !KindleBatch.Config.Get(Batch.Enabled) || (Object)(object)gui == (Object)null || (Object)(object)player == (Object)null || !gui.InCraftTab()) { return false; } CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); if (!((Object)(object)currentCraftingStation == (Object)null)) { return !currentCraftingStation.m_upgrader; } return true; } public static void Follow(Player player, Recipe selected) { if ((Object)(object)selected != (Object)(object)recipe) { recipe = selected; Value = 1; } if ((Object)(object)recipe != (Object)null && Value > 1 && !CanMake(player, recipe, Value)) { Value = Limit(player, recipe); } } public static bool CanStepUp(Player player) { if ((Object)(object)recipe != (Object)null) { return CanMake(player, recipe, Value + 1); } return false; } public static int NextCraft(InventoryGui gui, Player player) { if (Applies(gui, player)) { return Value; } if (!ZInput.GetButton("AltPlace") && !ZInput.GetButton("JoyLStick") && !gui.m_touchMultiCrafting) { return 1; } return gui.m_multiCraftAmount; } public static void Set(int typed) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)recipe == (Object)null)) { Value = Mathf.Clamp(typed, 1, Limit(localPlayer, recipe)); } } public static bool CanMake(Player player, Recipe made, int amount) { if (amount <= 1) { return true; } if (amount > KindleBatch.Config.Get(Batch.MaxAmount)) { return false; } return BatchCheck.HaveAndFit(player, made, amount); } public static int Limit(Player player, Recipe made) { int num = 1; int num2 = KindleBatch.Config.Get(Batch.MaxAmount); while (num < num2) { int num3 = (num + num2 + 1) / 2; if (CanMake(player, made, num3)) { num = num3; } else { num2 = num3 - 1; } } return num; } } internal static class BatchCheck { private const float MaxAge = 0.25f; private static readonly Dictionary answers = new Dictionary(); private static Recipe forRecipe; private static CraftingStation forStation; private static Player forPlayer; private static int forChange = -1; private static float since = float.MinValue; public static bool HaveAndFit(Player player, Recipe made, int amount) { Expire(player, made); if (answers.TryGetValue(amount, out var value)) { return value; } value = Ask(player, made, amount); answers[amount] = value; return value; } private static bool Ask(Player player, Recipe made, int amount) { if (!player.NoCostCheat() && (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25)) && !player.HaveRequirements(made, false, 1, amount)) { return false; } return ((Humanoid)player).GetInventory().CanAddItem(((Component)made.m_item).gameObject, made.m_amount * amount); } private static void Expire(Player player, Recipe made) { CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); float unscaledTime = Time.unscaledTime; if (!((Object)(object)made == (Object)(object)forRecipe) || !((Object)(object)currentCraftingStation == (Object)(object)forStation) || !((Object)(object)player == (Object)(object)forPlayer) || KindleBatch.InventoryChanges != forChange || !(unscaledTime - since < 0.25f)) { answers.Clear(); forRecipe = made; forStation = currentCraftingStation; forPlayer = player; forChange = KindleBatch.InventoryChanges; since = unscaledTime; } } } public static class BatchDrive { private static int gameAmount = 5; private static bool driving; private static int started; public static void Remember(InventoryGui gui) { gameAmount = gui.m_multiCraftAmount; driving = false; started = 0; } public static void Drive(InventoryGui gui, int amount) { gui.m_multiCraftAmount = amount; gui.m_touchMultiCrafting = amount > 1; driving = true; } public static void Release(InventoryGui gui) { if (driving) { driving = false; gui.m_multiCraftAmount = gameAmount; gui.m_touchMultiCrafting = false; } } public static void Started(InventoryGui gui, int amount) { started = amount; gui.m_multiCrafting = amount > 1; } public static void Forget() { started = 0; } public static void Restore(InventoryGui gui) { if (started > 0) { gui.m_multiCraftAmount = started; gui.m_multiCrafting = started > 1; } } } public static class CraftSpeed { private static float craft = 2f; private static float multi = 6f; private static float upgrader = 8f; private static float perLevel = 1f; public static void Remember(InventoryGui gui) { craft = gui.m_craftDuration; multi = gui.m_multiCraftDuration; upgrader = gui.m_upgraderDuration; perLevel = gui.m_upgraderDurationPerLevel; } public static void Apply(InventoryGui gui) { float craftSpeed = KindleBatch.Config.CraftSpeed; bool instantCrafting = KindleBatch.Config.InstantCrafting; gui.m_craftDuration = KindleCheats.CraftDuration(craft, craftSpeed, instantCrafting); gui.m_multiCraftDuration = KindleCheats.CraftDuration(multi, craftSpeed, instantCrafting); gui.m_upgraderDuration = KindleCheats.CraftDuration(upgrader, craftSpeed, instantCrafting); gui.m_upgraderDurationPerLevel = KindleCheats.CraftDuration(perLevel, craftSpeed, instantCrafting); } internal static void ApplySafe(InventoryGui gui) { gui.m_craftDuration = craft; gui.m_multiCraftDuration = multi; gui.m_upgraderDuration = upgrader; gui.m_upgraderDurationPerLevel = perLevel; } } public static class KindleBatch { internal static KindleConfig Config; internal static int InventoryChanges; private static MeadworksLog log; private static Harmony patches; private static InventoryGui owner; private static KitStepper stepper; private static RectTransform craft; private static Vector2 originalMin; private static Vector2 originalMax; private static float trim; private static bool laidOut; private const float CaptionPadding = 12f; private const float MinRowHeight = 30f; public static bool Active { get { if (Config != null && Plugin.GameplayAvailable && Plugin.AllowsUi && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return Object.op_Implicit((Object)(object)ZNet.instance); } return false; } } public static int Amount => BatchAmount.Value; public static bool Shown { get { if (stepper != null) { return stepper.Shown; } return false; } } public static int NextCraft(InventoryGui gui, Player player) { if (!Object.op_Implicit((Object)(object)gui) || !Object.op_Implicit((Object)(object)player)) { return 1; } return BatchAmount.NextCraft(gui, player); } public static void Initialize(KindleConfig config, MeadworksLog logger) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Shutdown(); Config = config; log = logger; patches = new Harmony("com.meadworks.kindle.batch"); patches.CreateClassProcessor(typeof(KindleBatchPatches)).Patch(); if (Object.op_Implicit((Object)(object)InventoryGui.instance)) { Remember(InventoryGui.instance); } } internal static void Guard(Action action) { try { action(); } catch (Exception ex) { MeadworksLog obj = log; if (obj != null) { obj.Warning("Batch crafting: " + ex.GetType().Name + ": " + ex.Message); } } } internal static void Remember(InventoryGui gui) { ClearUi(); owner = gui; BatchDrive.Remember(gui); CraftSpeed.Remember(gui); BatchAmount.Reset(); } internal static void BeforeRecipe(InventoryGui gui, Player player) { if ((Object)(object)owner != (Object)(object)gui) { Remember(gui); } if (!Active) { BatchDrive.Release(gui); CraftSpeed.ApplySafe(gui); return; } CraftSpeed.Apply(gui); if (!BatchAmount.Applies(gui, player)) { BatchDrive.Release(gui); return; } BatchAmount.Follow(player, ((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe); BatchDrive.Drive(gui, BatchAmount.Value); } internal static void Refresh(InventoryGui gui, Player player) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown if (!Active) { RestoreCraft(); return; } if ((Object)(object)owner != (Object)(object)gui) { Remember(gui); } if (stepper == null && Object.op_Implicit((Object)(object)gui.m_craftButton)) { craft = (RectTransform)((Component)gui.m_craftButton).transform; originalMin = craft.offsetMin; originalMax = craft.offsetMax; Rect rect = craft.rect; float height = ((Rect)(ref rect)).height; float num = RowHeight(craft, height); trim = (height - num) * 0.5f; stepper = KitStepper.Create((RectTransform)((Transform)craft).parent, "Kindle_batch", Vector2.zero, num, 1, 9999); if (stepper == null) { return; } stepper.Changed += BatchAmount.Set; } bool num2 = BatchAmount.Applies(gui, player) && gui.m_craftTimer < 0f; Show(num2); if (!num2 || stepper == null) { return; } bool flag = Object.op_Implicit((Object)(object)((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe); int num3 = ((!flag) ? 1 : BatchAmount.Limit(player, ((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe)); stepper.Follow(num3); stepper.Set(BatchAmount.Value); ((Selectable)stepper.Less).interactable = flag && BatchAmount.Value > 1; ((Selectable)stepper.More).interactable = flag && BatchAmount.CanStepUp(player); stepper.Field.SetUsable(flag); stepper.PadSteps = ZInput.IsGamepadActive() && gui.m_activeGroup == 3; if (flag) { TMP_Text componentInChildren = ((Component)gui.m_craftButton).GetComponentInChildren(true); if (componentInChildren != null) { componentInChildren.text = Localization.instance.Localize("$inventory_craftbutton"); } } } private static float RowHeight(RectTransform button, float native) { TMP_Text componentInChildren = ((Component)button).GetComponentInChildren(true); float num = (((Object)(object)componentInChildren == (Object)null) ? 0f : componentInChildren.fontSize); float num2 = Mathf.Max(30f, num + 12f); if (!(native > 0f)) { return num2; } return Mathf.Min(num2, native); } private static void Show(bool show) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (stepper != null && Object.op_Implicit((Object)(object)craft)) { float num = (show ? (stepper.Root.sizeDelta.x + 6f) : 0f); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(originalMin.x + num, originalMin.y + trim); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(originalMax.x, originalMax.y - trim); if (craft.offsetMin != val) { craft.offsetMin = val; } if (craft.offsetMax != val2) { craft.offsetMax = val2; } laidOut = true; RectTransform root = stepper.Root; Vector2 anchorMin = (root.anchorMax = craft.anchorMin); root.anchorMin = anchorMin; root.pivot = new Vector2(0f, 0f); root.anchoredPosition = new Vector2(originalMin.x, originalMin.y + trim); float x = root.sizeDelta.x; Rect rect = craft.rect; root.sizeDelta = new Vector2(x, ((Rect)(ref rect)).height); stepper.Show(show); } } private static void RestoreCraft() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (laidOut && Object.op_Implicit((Object)(object)craft)) { craft.offsetMin = originalMin; craft.offsetMax = originalMax; } laidOut = false; KitStepper obj = stepper; if (obj != null) { obj.Show(false); } } public static void Tick() { if (!Active) { RestoreCraft(); } else if ((Object)(object)owner != (Object)(object)InventoryGui.instance && Object.op_Implicit((Object)(object)InventoryGui.instance)) { Guard(delegate { Remember(InventoryGui.instance); }); } } private static void ClearUi() { RestoreCraft(); KitStepper obj = stepper; if (obj != null) { obj.Destroy(); } stepper = null; craft = null; trim = 0f; } public static void Shutdown() { if (Object.op_Implicit((Object)(object)owner)) { BatchDrive.Release(owner); CraftSpeed.ApplySafe(owner); } ClearUi(); owner = null; BatchDrive.Forget(); BatchAmount.Reset(); Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; Config = null; log = null; } } [HarmonyPatch] internal static class KindleBatchPatches { [HarmonyPatch(typeof(InventoryGui), "Awake")] [HarmonyPostfix] private static void Awake(InventoryGui __instance) { KindleBatch.Guard(delegate { KindleBatch.Remember(__instance); }); } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] [HarmonyPrefix] private static void BeforeRecipe(InventoryGui __instance, Player player) { KindleBatch.Guard(delegate { KindleBatch.BeforeRecipe(__instance, player); }); } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] [HarmonyPostfix] private static void AfterRecipe(InventoryGui __instance, Player player) { KindleBatch.Guard(delegate { KindleBatch.Refresh(__instance, player); }); } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] [HarmonyPrefix] private static void BeforePressed(InventoryGui __instance, out int __state) { __state = 0; BatchDrive.Forget(); if (KindleBatch.Active && !(__instance.m_craftTimer >= 0f) && BatchAmount.Applies(__instance, Player.m_localPlayer)) { BatchAmount.Follow(Player.m_localPlayer, ((RecipeDataPair)(ref __instance.m_selectedRecipe)).Recipe); BatchDrive.Drive(__instance, BatchAmount.Value); __state = BatchAmount.Value; } } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] [HarmonyPostfix] private static void AfterPressed(InventoryGui __instance, int __state) { if (__state > 0 && __instance.m_craftTimer >= 0f) { BatchDrive.Started(__instance, __state); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPrefix] [HarmonyPriority(800)] private static void BeforeCraft(InventoryGui __instance) { BatchDrive.Restore(__instance); } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyFinalizer] private static void AfterCraft() { BatchDrive.Forget(); } [HarmonyPatch(typeof(Inventory), "Changed")] [HarmonyPrefix] private static void Changed() { KindleBatch.InventoryChanges++; } } public static class KindleCarts { [HarmonyPatch(typeof(Vagon), "Awake")] private static class AwakePatch { [HarmonyPostfix] private static void Postfix(Vagon __instance) { Apply(__instance); } } [HarmonyPatch(typeof(Vagon), "Interact")] private static class InteractPatch { [HarmonyPrefix] private static bool Prefix(Vagon __instance, Humanoid character, bool hold, bool alt, ref bool __result) { if (hold || !alt || !Enabled) { return true; } Apply(__instance); CraftingStation component = ((Component)__instance).GetComponent(); if (!IsCart(component)) { return true; } if (!settings.TryUseCheat((KindleSetting)(object)Cart.CartWorkbench)) { return true; } __result = component.Interact(character, false, false); return false; } } [HarmonyPatch(typeof(Vagon), "GetHoverText")] private static class HoverPatch { [HarmonyPostfix] private static void Postfix(Vagon __instance, ref string __result) { if (Enabled && IsCart(((Component)__instance).GetComponent())) { __result = __result + Localization.instance.Localize("\n[$KEY_AltPlace + $KEY_Use] ") + KindleText.Text("cartcraft"); } } } [HarmonyPatch(typeof(CraftingStation), "GetLevel")] private static class LevelPatch { [HarmonyPostfix] private static void Postfix(CraftingStation __instance, ref int __result) { if (Enabled && IsCart(__instance)) { __result += Math.Max(1, settings.Get(Cart.CartStationLevel)) - 1; } } } private static readonly HashSet added = new HashSet(); private static KindleConfig? settings; private static MeadworksLog? log; private static Harmony? patches; private static float nextScan; private static bool previousEnabled; private static float previousRange; internal static bool Enabled { get { if (Plugin.Ready && settings != null) { return settings.Get(Cart.CartWorkbench); } return false; } } public static void Initialize(KindleConfig config, MeadworksLog logger) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown Shutdown(); settings = config; log = logger; nextScan = 0f; settings.Changed += OnSettingsChanged; patches = new Harmony("com.meadworks.kindle.carts"); Type[] array = new Type[4] { typeof(AwakePatch), typeof(InteractPatch), typeof(HoverPatch), typeof(LevelPatch) }; foreach (Type type in array) { patches.CreateClassProcessor(type).Patch(); } } private static void OnSettingsChanged(object sender, EventArgs args) { try { foreach (Vagon item in new List(Vagon.m_instances)) { Apply(item); } } catch (Exception ex) { MeadworksLog? obj = log; if (obj != null) { obj.Warning("Cart station refresh refused: " + ex.GetType().Name); } } } public static void Tick() { if (settings == null) { return; } bool enabled = Enabled; float num = settings.Get(Cart.CartStationRange); if (enabled == previousEnabled && num == previousRange && Time.unscaledTime < nextScan) { return; } previousEnabled = enabled; previousRange = num; nextScan = Time.unscaledTime + 0.5f; foreach (Vagon item in new List(Vagon.m_instances)) { Apply(item); } added.RemoveWhere((CraftingStation station) => (Object)(object)station == (Object)null); } public static void Shutdown() { Harmony? obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; if (settings != null) { settings.Changed -= OnSettingsChanged; } foreach (CraftingStation item in added) { if (Object.op_Implicit((Object)(object)item)) { Object.Destroy((Object)(object)item); } } added.Clear(); settings = null; log = null; previousEnabled = false; previousRange = 0f; nextScan = 0f; } internal static bool IsCart(CraftingStation station) { if (Object.op_Implicit((Object)(object)station)) { return added.Contains(station); } return false; } internal static void Apply(Vagon cart) { if (settings == null || !Object.op_Implicit((Object)(object)cart) || !Object.op_Implicit((Object)(object)cart.m_nview) || cart.m_nview.GetZDO() == null) { return; } CraftingStation component = ((Component)cart).GetComponent(); if (!Enabled) { if (IsCart(component)) { added.Remove(component); Object.Destroy((Object)(object)component); } return; } if (Object.op_Implicit((Object)(object)component)) { if (IsCart(component)) { component.m_rangeBuild = settings.Get(Cart.CartStationRange); } return; } GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab("piece_workbench") : null); CraftingStation val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponentInChildren(true) : null); if (!Object.op_Implicit((Object)(object)val2)) { MeadworksLog? obj = log; if (obj != null) { obj.Warning("The workbench prefab has no crafting station; carts stay plain carts."); } } else { component = ((Component)cart).gameObject.AddComponent(); Copy(val2, component, ((Component)cart).transform); added.Add(component); } } private static void Copy(CraftingStation from, CraftingStation to, Transform cart) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) to.m_name = from.m_name; to.m_icon = from.m_icon; to.m_discoverRange = from.m_discoverRange; to.m_rangeBuild = settings.Get(Cart.CartStationRange); to.m_extraRangePerLevel = from.m_extraRangePerLevel; to.m_craftRequireRoof = false; to.m_craftRequireFire = false; to.m_roofCheckPoint = cart; to.m_connectionPoint = null; to.m_showBasicRecipies = from.m_showBasicRecipies; to.m_useDistance = Mathf.Max(from.m_useDistance, 4f); to.m_craftingSkill = from.m_craftingSkill; to.m_hoverOffset = from.m_hoverOffset; to.m_hasCraftTab = from.m_hasCraftTab; to.m_canRepair = from.m_canRepair; to.m_upgrader = false; to.m_craftItemEffects = from.m_craftItemEffects; to.m_craftItemDoneEffects = from.m_craftItemDoneEffects; to.m_repairItemDoneEffects = from.m_repairItemDoneEffects; to.m_craftItemDoneFailEffects = from.m_craftItemDoneFailEffects; } } public static class KindleStationReach { [HarmonyPatch(typeof(CraftingStation), "InUseDistance")] private static class DistancePatch { [HarmonyPostfix] private static void Postfix(CraftingStation __instance, Humanoid human, ref bool __result) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (__result || !Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)human) || (Object)(object)human != (Object)(object)Player.m_localPlayer) { return; } try { float multiplier = Multiplier; if (multiplier > 1f) { __result = Vector3.Distance(((Component)human).transform.position, ((Component)__instance).transform.position) < __instance.m_useDistance * multiplier; } } catch (Exception ex) { KindleSalvage.Warn("Station use distance: " + ex.GetType().Name + ": " + ex.Message); } } } private static KindleConfig? settings; private static Harmony? patches; private static float Multiplier { get { if (settings == null || !Plugin.GameplayAvailable) { return 1f; } return settings.Get(Stations.UseDistance); } } public static void Initialize(KindleConfig config) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Shutdown(); settings = config; patches = new Harmony("com.meadworks.kindle.stationreach"); patches.CreateClassProcessor(typeof(DistancePatch)).Patch(); } public static void Shutdown() { Harmony? obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; settings = null; } } public static class KindleVirtualStation { [HarmonyPatch(typeof(Player), "SetCraftingStation")] private static class RememberPatch { [HarmonyPostfix] private static void Postfix(Player __instance, CraftingStation station) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)station) && !((Object)(object)station == (Object)(object)active) && !KindleCarts.IsCart(station)) { ZNetView componentInParent = ((Component)station).GetComponentInParent(); ZDO val = ((Object.op_Implicit((Object)(object)componentInParent) && componentInParent.IsValid()) ? componentInParent.GetZDO() : null); if (val != null) { remembered = val.m_uid; } } } catch (Exception ex) { KindleSalvage.Warn("Virtual Workbench: " + ex.GetType().Name + ": " + ex.Message); } } } [HarmonyPatch(typeof(CraftingStation), "InUseDistance")] private static class DistancePatch { [HarmonyPrefix] private static bool Prefix(CraftingStation __instance, Humanoid human, ref bool __result) { if ((Object)(object)active == (Object)null || (Object)(object)__instance != (Object)(object)active || (Object)(object)human != (Object)(object)Player.m_localPlayer || !Enabled) { return true; } __result = true; return false; } } private static KindleConfig? settings; private static Harmony? patches; private static ZDOID remembered = ZDOID.None; private static CraftingStation? active; internal static bool Enabled { get { if (Plugin.GameplayAvailable && settings != null) { return settings.Get(VirtualWorkbench.Enabled); } return false; } } public static void Initialize(KindleConfig config) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Shutdown(); settings = config; patches = new Harmony("com.meadworks.kindle.virtualstation"); patches.CreateClassProcessor(typeof(RememberPatch)).Patch(); patches.CreateClassProcessor(typeof(DistancePatch)).Patch(); } public static void Shutdown() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Release(close: true); Harmony? obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; settings = null; remembered = ZDOID.None; } public static void Tick() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (settings == null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)active != (Object)null) { if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)localPlayer.GetCurrentCraftingStation() != (Object)(object)active) { active = null; } else if (!Enabled) { Release(close: true); } } if (!Object.op_Implicit((Object)(object)localPlayer) || InventoryGui.IsVisible() || !MeadworksInput.Allows((InputContext)0)) { return; } KeyboardShortcut val = settings.Shortcut(VirtualWorkbench.Key); if (((KeyboardShortcut)(ref val)).IsDown()) { if (!Enabled) { ((Character)localPlayer).Message((MessageType)2, KindleText.Text("virtualoff"), 0, (Sprite)null, false); } else { Open(localPlayer); } } } private static void Open(Player player) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!((Character)player).IsDead() && !((Character)player).IsTeleporting() && !((Character)player).InCutscene() && !((Character)player).InPlaceMode()) { CraftingStation val = Find(remembered); if (!Object.op_Implicit((Object)(object)val)) { ((Character)player).Message((MessageType)2, KindleText.Text("virtualnone"), 0, (Sprite)null, false); } else if (val.CheckUsable(player, true)) { active = val; player.SetCraftingStation(val); InventoryGui.instance.Show((Container)null, 3); } } } private static CraftingStation? Find(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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) if (id == ZDOID.None || (Object)(object)ZNetScene.instance == (Object)null) { return null; } GameObject val = ZNetScene.instance.FindInstance(id); if (!Object.op_Implicit((Object)(object)val)) { return null; } return val.GetComponentInChildren(); } private static void Release(bool close) { Player localPlayer = Player.m_localPlayer; if (close && Object.op_Implicit((Object)(object)active) && Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)localPlayer.GetCurrentCraftingStation() == (Object)(object)active) { localPlayer.SetCraftingStation((CraftingStation)null); if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible()) { InventoryGui.instance.Hide(); } } active = null; } } public sealed class KindleConfig { public const string LockedValuesKey = "Locked Player Values"; private const string Product = "com.meadworks.kindle"; private const float RefreshSeconds = 0.5f; private static readonly HashSet Shortcuts = BuildShortcuts(); private readonly ConfigFile file; private readonly Dictionary entries = new Dictionary(); private readonly Dictionary settingsByEntry = new Dictionary(); private readonly ConfigurationManagerAttributes nearbyTag = new ConfigurationManagerAttributes(); private float nextRefresh; public PadButton? GamepadSortButton { get { //IL_002a: 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) KindleSetting gamepadSortButton = RecipeList.GamepadSortButton; string text = Get(gamepadSortButton); if (text.Length == 0) { return null; } PadButton value = default(PadButton); if (GamepadMap.TryParse(text, ref value)) { return value; } if (!GamepadMap.TryParse(gamepadSortButton.Default, ref value)) { return null; } return value; } } public float CraftSpeed => Get(Batch.CraftSpeed); public bool InstantCrafting => Get(Batch.InstantCrafting); public bool CartWorkbench => Get(Cart.CartWorkbench); public LockList Locks => LockList.Empty; public event EventHandler? Changed; private static HashSet BuildShortcuts() { _ = KindleSettings.All; return new HashSet { (KindleSetting)(object)RecipeList.SearchKey, (KindleSetting)(object)RecipeList.FavouriteRecipeKey, (KindleSetting)(object)Salvage.SalvageKey, (KindleSetting)(object)VirtualWorkbench.Key }; } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { this.Changed?.Invoke(this, EventArgs.Empty); } private KindleConfig(ConfigFile file, MeadworksLog log) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown KindleConfig kindleConfig = this; this.file = file; bool saveOnConfigSet = file.SaveOnConfigSet; file.SaveOnConfigSet = false; try { foreach (KindleSetting item in KindleSettings.All) { BindSetting(item); } ConfigDescription description = entries[(KindleSetting)(object)Tracker.CountNearbyChests].Description; typeof(ConfigDescription).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(description, description.Tags.Concat(new object[1] { nearbyTag }).ToArray()); ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { Browsable = false, ReadOnly = true }; ConfigFileExtensions.BindConfig(file, "Server", "Locked Player Values", "", "Retained compatibility carrier. Client-local settings always use their own values.", true, (int?)null, (AcceptableValueBase)null, (Action)null, val); MeadworksConfig.EnsureSchema(file, 1, (IReadOnlyList)(object)new MigrationStep[1] { new MigrationStep(0, 1, (Action)delegate { kindleConfig.MigrateDefaults(log); }) }); } finally { file.SaveOnConfigSet = saveOnConfigSet; } file.Save(); file.SettingChanged += OnSettingChanged; } public static KindleConfig Bind(ConfigFile file, MeadworksLog log) { //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) if (file == null) { throw new ArgumentNullException("file"); } if (log == null) { throw new ArgumentNullException("log"); } KindleConfig kindleConfig = new KindleConfig(file, log); foreach (KeyValuePair item in kindleConfig.entries.Where>((KeyValuePair p) => (int)p.Key.Scope > 0)) { MeadworksBlockedOptions.Track("com.meadworks.kindle", item.Value, Map(item.Key.Scope), true); } kindleConfig.Refresh(); log.Verbose("Configuration bound: " + Count((SettingScope)0) + " Local, " + Count((SettingScope)1) + " ServerAuthoritative, " + Count((SettingScope)2) + " Cheat."); return kindleConfig; } public static ConfigScope Map(SettingScope scope) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown return (ConfigScope)((int)scope switch { 0 => 0, 1 => 1, 2 => 2, _ => throw new ArgumentException("Unknown scope.", "scope"), }); } public ConfigEntryBase Entry(KindleSetting setting) { if (!entries.TryGetValue(setting ?? throw new ArgumentNullException("setting"), out ConfigEntryBase value)) { throw new ArgumentException("Not a Kindle setting.", "setting"); } return value; } public T Get(KindleSetting setting) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 if (Shortcuts.Contains((KindleSetting)(object)setting)) { throw new ArgumentException(((KindleSetting)setting).Id + " is a keyboard shortcut; use Shortcut.", "setting"); } ConfigEntry val = (ConfigEntry)(object)Entry((KindleSetting)(object)setting); SettingScope scope = ((KindleSetting)setting).Scope; if ((int)scope != 1) { if ((int)scope == 2) { return KindleCheats.Effective(setting, CheatLocked(), val.Value); } return setting.Normalize(val.Value); } return setting.Normalize(MeadworksConfig.Effective(val, "com.meadworks.kindle", (ConfigScope)1, setting.Default, true)); } public KeyboardShortcut Shortcut(KindleSetting setting) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!Shortcuts.Contains((KindleSetting)(object)setting)) { throw new ArgumentException(((KindleSetting)setting).Id + " is not a keyboard shortcut.", "setting"); } return ((ConfigEntry)(object)Entry((KindleSetting)(object)setting)).Value; } public bool IsLocked(KindleSetting setting) { return false; } public bool TryUseCheat(KindleSetting cheat, string? label = null) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if (cheat == null || (int)cheat.Scope != 2) { throw new ArgumentException("Expected a Kindle cheat.", "cheat"); } return MeadworksBlockedOptions.TryUse("com.meadworks.kindle", cheat.Id, (ConfigScope)2, label, true); } public bool TryChange(KindleSetting setting, string? label = null) { //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_0065: Unknown result type (might be due to invalid IL or missing references) if (setting == null) { throw new ArgumentNullException("setting"); } if ((object)setting == Tracker.CountNearbyChests && !KindleTracker.NearbyAvailable) { if ((Object)(object)MessageHud.instance != (Object)null && MeadworksHeadless.AllowsUi) { MessageHud.instance.ShowMessage((MessageType)2, KindleText.Text("needs_burrow"), 0, (Sprite)null, false, true); } return false; } if ((int)setting.Scope != 0) { return MeadworksBlockedOptions.TryEdit("com.meadworks.kindle", setting.Id, Map(setting.Scope), label, true); } return true; } public void Tick(float now) { if (!(now < nextRefresh)) { nextRefresh = now + 0.5f; Refresh(); } } public void Shutdown() { file.SettingChanged -= OnSettingChanged; this.Changed = null; foreach (ConfigEntryBase item in entries.Values.Where((ConfigEntryBase e) => (int)settingsByEntry[e].Scope > 0)) { MeadworksBlockedOptions.Untrack(item); } } private void Refresh() { nearbyTag.ReadOnly = (KindleTracker.NearbyAvailable ? ((bool?)null) : new bool?(true)); } private void MigrateDefaults(MeadworksLog log) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (KeyValuePair, string> change in KindleDefaultsMigration.Changes) { ConfigEntryBase val = entries[(KindleSetting)(object)change.Key]; object obj; if (!(val is ConfigEntry val2)) { obj = val.BoxedValue as string; } else { KeyboardShortcut value = val2.Value; obj = ((KeyboardShortcut)(ref value)).Serialize(); } string text = (string)obj; string text2 = KindleDefaultsMigration.Migrate(change.Key, text); if (text2 != null) { val.BoxedValue = ((val is ConfigEntry) ? ((object)KeyboardShortcut.Deserialize(text2)) : text2); list.Add(((KindleSetting)change.Key).Id); } } if (list.Count > 0) { log.Info("Moved unchanged old input defaults to the new defaults: " + string.Join(", ", list) + ". Customized values were kept."); } } private static bool CheatLocked() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 return (int)MeadworksAuthority.Decide("com.meadworks.kindle", (ConfigScope)2, true).Source == 2; } private void BindSetting(KindleSetting setting) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) ConfigEntryBase val; if ((object)setting == Server.LockedPlayerSettings) { val = (ConfigEntryBase)(object)MeadworksConfig.BindHidden(file, setting.Section, setting.Key, (string)setting.DefaultValue, setting.Description, (ConfigScope)1, (AcceptableValueBase)null); } else if (Shortcuts.Contains(setting)) { val = (ConfigEntryBase)(object)MeadworksConfig.Bind(file, setting.Section, setting.Key, KeyboardShortcut.Deserialize((string)setting.DefaultValue), Describe(setting, null), Map(setting.Scope)); } else if (!(setting is KindleSetting setting2)) { if (!(setting is KindleSetting val2)) { if (!(setting is KindleSetting val3)) { if (!(setting is KindleSetting setting3)) { if (!(setting is KindleSetting setting4)) { if (!(setting is KindleSetting setting5)) { if (!(setting is KindleSetting setting6)) { throw new NotSupportedException(setting.Id + ": unsupported value type " + setting.ValueType.Name + "."); } val = (ConfigEntryBase)(object)Bind(setting6, null); } else { val = (ConfigEntryBase)(object)Bind(setting5, null); } } else { val = (ConfigEntryBase)(object)Bind(setting4, null); } } else { val = (ConfigEntryBase)(object)Bind(setting3, null); } } else { val = (ConfigEntryBase)(object)Bind(val3, (AcceptableValueBase?)(object)new AcceptableValueRange((float)((KindleSetting)val3).Minimum, (float)((KindleSetting)val3).Maximum)); } } else { val = (ConfigEntryBase)(object)Bind(val2, (AcceptableValueBase?)(object)new AcceptableValueRange((int)((KindleSetting)val2).Minimum, (int)((KindleSetting)val2).Maximum)); } } else { val = (ConfigEntryBase)(object)Bind(setting2, null); } entries.Add(setting, val); settingsByEntry.Add(val, setting); } private ConfigDescription Describe(KindleSetting setting, AcceptableValueBase? acceptable, string? text = null) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown ConfigDependency val = null; if ((object)setting == Tracker.MaxTracked || (object)setting == Tracker.CountNearbyChests || (object)setting == Tracker.HideInCombat || (object)setting == Tracker.HideWithMap || (object)setting == Tracker.Font || (object)setting == Tracker.FontSize || (object)setting == Tracker.HaveColour || (object)setting == Tracker.MissingColour || (object)setting == Tracker.ReadyColour || (object)setting == Tracker.BackgroundOpacity) { val = new ConfigDependency((Func)(() => Get(Tracker.Enabled)), (Func)(() => "Requires " + ((KindleSetting)Tracker.Enabled).Section + ": " + ((KindleSetting)Tracker.Enabled).Key + "."), (Func)null); } if ((object)setting == RecipeList.FavouritesFirst || (object)setting == RecipeList.FavouriteRecipeKey) { val = new ConfigDependency((Func)(() => Get(RecipeList.Favourites)), (Func)(() => "Requires " + ((KindleSetting)RecipeList.Favourites).Section + ": " + ((KindleSetting)RecipeList.Favourites).Key + "."), (Func)null); } if ((object)setting == RecipeList.SearchKey) { val = new ConfigDependency((Func)(() => Get(RecipeList.Search)), (Func)(() => "Requires " + ((KindleSetting)RecipeList.Search).Section + ": " + ((KindleSetting)RecipeList.Search).Key + "."), (Func)null); } if ((object)setting == RecipeList.GamepadSortButton) { val = new ConfigDependency((Func)(() => Get(RecipeList.GamepadControls)), (Func)(() => "Requires " + ((KindleSetting)RecipeList.GamepadControls).Section + ": " + ((KindleSetting)RecipeList.GamepadControls).Key + "."), (Func)null); } if ((object)setting == Batch.MaxAmount) { val = new ConfigDependency((Func)(() => Get(Batch.Enabled)), (Func)(() => "Requires " + ((KindleSetting)Batch.Enabled).Section + ": " + ((KindleSetting)Batch.Enabled).Key + "."), (Func)null); } if ((object)setting == VirtualWorkbench.Key) { val = new ConfigDependency((Func)(() => Get(VirtualWorkbench.Enabled)), (Func)(() => "Requires " + ((KindleSetting)VirtualWorkbench.Enabled).Section + ": " + ((KindleSetting)VirtualWorkbench.Enabled).Key + "."), (Func)null); } if ((object)setting == Salvage.SalvageKey) { val = new ConfigDependency((Func)(() => Get(Salvage.Enabled)), (Func)(() => "Requires " + ((KindleSetting)Salvage.Enabled).Section + ": " + ((KindleSetting)Salvage.Enabled).Key + "."), (Func)null); } return new ConfigDescription(text ?? setting.Description, acceptable, (val == null) ? Array.Empty() : new object[1] { val }); } private ConfigEntry Bind(KindleSetting setting, AcceptableValueBase? acceptable) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //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) if ((int)((KindleSetting)setting).Scope != 2) { return MeadworksConfig.Bind(file, ((KindleSetting)setting).Section, ((KindleSetting)setting).Key, setting.Default, Describe((KindleSetting)(object)setting, acceptable), Map(((KindleSetting)setting).Scope)); } return MeadworksConfig.BindCheat(file, ((KindleSetting)setting).Section, ((KindleSetting)setting).Key, setting.Safe, ((KindleSetting)setting).Description, acceptable); } private static int Count(SettingScope scope) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return KindleSettings.All.Count((KindleSetting s) => s.Scope == scope); } } internal static class InscribeDetails { private static Tuple, Func, Func[]>> Resolve() { if (!Plugin.IsReady) { return null; } Tuple, Func, Func[]>> result = default(Tuple, Func, Func[]>>); if (!Plugin.Services.Capabilities.TryResolve, Func, Func[]>>>("meadworks.items.decoration", ItemDecorationContract.ContractVersion, ref result)) { return null; } return result; } internal static string Name(ItemData item, string fallback) { try { string text = Resolve()?.Item1(item); return string.IsNullOrEmpty(text) ? fallback : text; } catch (Exception) { return fallback; } } internal static string Lines(ItemData item) { try { Tuple[] array = Resolve()?.Item3(item); if (array == null) { return ""; } HashSet hashSet = new HashSet(StringComparer.Ordinal); List list = new List(); Tuple[] array2 = array; foreach (Tuple tuple in array2) { if (list.Count == 128) { break; } if (tuple != null && tuple.Item1 != null && tuple.Item1.StartsWith("inscribe.", StringComparison.Ordinal) && hashSet.Add(tuple.Item1) && !float.IsNaN(tuple.Item3) && !float.IsInfinity(tuple.Item3) && !string.IsNullOrEmpty(tuple.Item6)) { list.Add(tuple.Item6); } } return string.Join("\n", list); } catch (Exception) { return ""; } } } public sealed class KindleImportValue { public string SourceId { get; } public string TargetId { get; } public string SourceValue { get; } public string Value { get; } public string CurrentValue { get; } internal KindleImportValue(string source, string target, string original, string value, string current) { SourceId = source; TargetId = target; SourceValue = original; Value = value; CurrentValue = current; } } public sealed class KindleImportPreview { internal KindleReferenceImport Owner { get; } internal IReadOnlyDictionary Sources { get; } internal IReadOnlyList PrepareErrors { get; } internal long Generation { get; } public ConversionPreview Preview { get; } public IReadOnlyList Values { get; } public IReadOnlyList Errors { get; } public IReadOnlyList Skipped { get; } public IReadOnlyList Normalizations { get; } public IReadOnlyList Conflicts => Preview.Conflicts; public IReadOnlyList BindingConflicts => Preview.BindingConflicts; public string SourceSha256 { get; } public string TargetSha256 { get; } internal KindleImportPreview(KindleReferenceImport owner, ConversionPreview plan, IEnumerable values, IEnumerable errors, IEnumerable prepareErrors, IEnumerable skipped, IEnumerable normalizations, IReadOnlyDictionary sources, string sourceHash, string targetHash, long generation) { Owner = owner; Preview = plan; Values = Array.AsReadOnly(values.ToArray()); Errors = Array.AsReadOnly(errors.ToArray()); PrepareErrors = Array.AsReadOnly(prepareErrors.ToArray()); Skipped = Array.AsReadOnly(skipped.ToArray()); Normalizations = Array.AsReadOnly(normalizations.ToArray()); Sources = new ReadOnlyDictionary(sources.ToDictionary, string, string>((KeyValuePair p) => p.Key, (KeyValuePair p) => p.Value, StringComparer.OrdinalIgnoreCase)); SourceSha256 = sourceHash; TargetSha256 = targetHash; Generation = generation; } public override string ToString() { List list = new List { KindleText.Text("import_review") }; list.AddRange(Values.Select((KindleImportValue v) => v.SourceId + " → " + v.TargetId + ": " + v.CurrentValue + " → " + v.Value + " (source: " + v.SourceValue + ")")); list.AddRange(Normalizations.Select((string v) => "Normalized: " + v)); list.AddRange(Skipped.Select((string v) => "Skipped: " + v)); list.AddRange(Errors.Select((string v) => "Invalid: " + v)); list.AddRange(Conflicts.Select((ConversionConflict c) => "Choice required: " + c.TargetId + " = " + string.Join(" or ", c.Choices.Select((ConversionValue v) => v.SourceId)))); list.AddRange(BindingConflicts.Select((ConversionConflict c) => "Shortcut collision: " + c.TargetId + "; replace binding:=")); list.AddRange(from p in Sources where !p.Key.EndsWith(".cfg", StringComparison.OrdinalIgnoreCase) select "Salvage file: " + Path.GetFileName(p.Key) + " → " + Path.GetFileName(p.Key).Replace("OpenKeep.", "Kindle.")); list.Add("Overrides: binding:=; conflicts: =."); list.Add("Source SHA256: " + SourceSha256); list.Add("Target SHA256: " + TargetSha256); return string.Join("\n", list); } } public sealed class KindleImportResult { public int Written { get; } public bool BackedUp { get; } public string SourceSha256 { get; } public string TargetSha256 { get; } public IReadOnlyList Backups { get; } public IReadOnlyList Messages { get; } internal KindleImportResult(ConversionResult result, string sourceHash, string targetHash, IEnumerable backups, IEnumerable messages) { Written = result.Written; BackedUp = result.BackedUp; SourceSha256 = sourceHash; TargetSha256 = targetHash; Backups = Array.AsReadOnly(backups.ToArray()); Messages = Array.AsReadOnly(messages.ToArray()); } public override string ToString() { return string.Join("\n", new string[1] { "Applied " + Written + " settings; config backup " + (BackedUp ? "created" : "no config changes") }.Concat(Messages).Concat(Backups.Select((string p) => "Backup: " + p)).Concat(new string[2] { "Source SHA256: " + SourceSha256, "Target SHA256: " + TargetSha256 })); } } internal static class KindleAlmanac { internal const int MaxBytes = 1048576; internal static string ReadText(string path) { using FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); if (fileStream.Length > 1048576) { throw new InvalidDataException("Registered text exceeds 1 MiB."); } using StreamReader streamReader = new StreamReader(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), detectEncodingFromByteOrderMarks: true); return streamReader.ReadToEnd(); } internal static string Hash(string text) { using SHA256 sHA = SHA256.Create(); return Hex(sHA.ComputeHash(Encoding.UTF8.GetBytes(text))); } internal static string FileHash(string path) { if (!File.Exists(path)) { return "missing"; } using FileStream inputStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); using SHA256 sHA = SHA256.Create(); return Hex(sHA.ComputeHash(inputStream)); } private static string Hex(byte[] bytes) { return string.Concat(bytes.Select((byte b) => b.ToString("X2", CultureInfo.InvariantCulture))); } internal static string SetHash(IEnumerable> files) { StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair item in files.OrderBy, string>((KeyValuePair p) => p.Key, StringComparer.Ordinal)) { stringBuilder.Append(item.Key.Length).Append(':').Append(item.Key) .Append(item.Value.Length) .Append(':') .Append(item.Value); } return Hash(stringBuilder.ToString()); } internal static IEnumerable> Ordered(IEnumerable> files) { return files.OrderBy, int>((KeyValuePair p) => (!Path.GetFileName(p.Key).Equals("Kindle.Salvage.yml", StringComparison.OrdinalIgnoreCase)) ? 1 : 0).ThenBy, string>((KeyValuePair p) => Path.GetFileName(p.Key), StringComparer.OrdinalIgnoreCase); } internal static void Authority() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if (!Plugin.IsReady || !Plugin.Ready) { throw new InvalidOperationException("Kindle configuration owner is unavailable."); } AuthorityDecision val = MeadworksAuthority.Decide("com.meadworks.kindle", (ConfigScope)1, true); if ((int)Plugin.Session.Role == 3 || !val.Allowed || val.RequiresServerAmendment) { throw new InvalidOperationException("Apply this import on the authority machine; this client cannot replace server-controlled configuration."); } } internal static string Temporary(string path, string text) { if (Encoding.UTF8.GetByteCount(text) > 1048576) { throw new InvalidDataException("Registered text exceeds 1 MiB."); } string text2 = path + ".import-" + Guid.NewGuid().ToString("N") + ".tmp"; try { using (FileStream fileStream = new FileStream(text2, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { using (StreamWriter streamWriter = new StreamWriter(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), 1024, leaveOpen: true)) { streamWriter.Write(text); streamWriter.Flush(); } fileStream.Flush(flushToDisk: true); } return text2; } catch { if (File.Exists(text2)) { File.Delete(text2); } throw; } } internal static string Backup(string path) { return path + ".import-" + DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture) + "-" + Guid.NewGuid().ToString("N") + ".bak"; } } public sealed class KindleReferenceImport : IDisposable { private sealed class ImportTarget : IValidatedConversionTarget, IConversionTarget { private readonly KindleReferenceImport owner; private readonly KindleImportPreview preview; private readonly IConversionTarget target; internal readonly List Backups = new List(); private bool backupRequested; private bool written; public int SchemaVersion => target.SchemaVersion; internal ImportTarget(KindleReferenceImport owner, KindleImportPreview preview) { this.owner = owner; this.preview = preview; target = MeadworksConversion.Target(owner.config); } private ConfigEntryBase[] Entries(IReadOnlyDictionary values) { List list = new List(); ConfigEntryMetadata val2 = default(ConfigEntryMetadata); foreach (KeyValuePair value in values) { KindleSetting setting = ((IEnumerable)KindleSettings.All).SingleOrDefault((Func)((KindleSetting s) => s.Id == value.Key)) ?? throw new ArgumentException("Unknown Kindle import target: " + value.Key); ConfigEntryBase val = owner.settingsEntry(setting); if (!MeadworksConfig.TryGetMetadata(val, ref val2) || val2.ProductId != "com.meadworks.kindle" || !val2.Decision.Allowed || val2.Decision.RequiresServerAmendment || owner.settings.IsLocked(setting)) { throw new InvalidOperationException("An import target is now locked: " + value.Key); } object obj = (val.SettingType.IsInstanceOfType(value.Value) ? value.Value : TomlTypeConverter.ConvertToValue(Convert.ToString(value.Value, CultureInfo.InvariantCulture), val.SettingType)); if (val.Description.AcceptableValues != null && !val.Description.AcceptableValues.IsValid(obj)) { throw new ArgumentException("Invalid Kindle import target value: " + value.Key); } list.Add(val); } return list.Distinct().ToArray(); } public void Validate(IReadOnlyDictionary values) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (written) { throw new InvalidOperationException("This Kindle configuration import has already been applied."); } owner.Admission(preview); ((IValidatedConversionTarget)target).Validate(values); Entries(values); } public void Backup() { owner.Admission(preview); if (!File.Exists(owner.config.ConfigFilePath)) { throw new InvalidOperationException("Save Kindle configuration before importing; a target backup is required."); } backupRequested = true; } private void VerifiedBackup() { string configFilePath = owner.config.ConfigFilePath; string directoryName = Path.GetDirectoryName(configFilePath); string searchPattern = Path.GetFileName(configFilePath) + ".import-*.bak"; string[] files = Directory.GetFiles(directoryName, searchPattern); string text = KindleAlmanac.FileHash(configFilePath); target.Backup(); string[] array = Directory.GetFiles(directoryName, searchPattern).Except(files, StringComparer.OrdinalIgnoreCase).ToArray(); if (array.Length != 1 || KindleAlmanac.FileHash(array[0]) != text) { throw new IOException("The exact target backup could not be verified."); } Backups.Add(array[0]); } public void WriteAtomic(IReadOnlyDictionary values) { Validate(values); if (!backupRequested) { throw new InvalidOperationException("Kindle import requires a backup."); } ConfigEntryBase[] array = Entries(values); if (array.Length == 0) { return; } try { if (!MeadworksConfig.AmendBatch("com.meadworks.kindle", (IReadOnlyList)array, (Action)delegate { owner.Admission(preview); Entries(values); VerifiedBackup(); target.WriteAtomic(values); written = true; }, "Kindle import").Applied || !written) { throw new InvalidOperationException("Current authority or synchronization refused the Kindle import before writing."); } } catch (Exception innerException) when (written) { throw new IOException("Kindle settings were saved locally, but synchronization did not complete. Salvage files and the import marker were not updated; review synchronization before continuing.", innerException); } } } private readonly ConfigFile config; private readonly ConfigEntry marker; private readonly ConfigEntry apply; private readonly ConfigEntry preview; private readonly ConfigEntry choices; private readonly Dictionary mappings = new Dictionary(StringComparer.Ordinal); private readonly ConfigConverter converter; private readonly MeadworksLog log; private readonly KindleConfig settings; private readonly int thread = Thread.CurrentThread.ManagedThreadId; private IDisposable registration; private bool disposed; private Player lastPlayer; private bool offered; public string ReportPath => Path.Combine(Paths.ConfigPath, "Meadworks", "kindle", "import-report.txt"); public string SourcePath => Path.Combine(Paths.ConfigPath, "milkyteam.openkeep.cfg"); public KindleReferenceImport(ConfigFile config, KindleConfig settings, MeadworksLog log) { //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Expected O, but got Unknown this.config = config; this.log = log; this.settings = settings; marker = MeadworksConfig.BindHidden(config, "Import", "Imported Sources", "", "Managed by Kindle.", (ConfigScope)0, (AcceptableValueBase)null); preview = MeadworksConfig.Bind(config, "Import", "Preview OpenKeep", false, "Write a preview report without changing any source or target settings. Resets after running.", (ConfigScope)0, (AcceptableValueBase)null); apply = MeadworksConfig.Bind(config, "Import", "Apply OpenKeep", false, "Apply the previewed reference settings with a target backup. Source files remain intact. Resets after running.", (ConfigScope)0, (AcceptableValueBase)null); choices = MeadworksConfig.Bind(config, "Import", "Binding Overrides", "", "Replacement shortcuts as Section.Key=value, separated by semicolons, for collisions shown by Preview.", (ConfigScope)0, (AcceptableValueBase)null); foreach (KindleSetting item in KindleSettings.All) { string text = ((item.Section == "Recipe List") ? "12. Recipe List" : ((item.Section == "Batch Crafting") ? "10. Batch Crafting" : ((item.Section == "Recipe Tracker") ? "13. Recipe Tracker" : ((item.Section == "Salvage") ? "3. Salvage" : ((item.Section == "Cart Workbench") ? "6. Carts" : ""))))); if (text.Length != 0 && (object)item != RecipeList.FavouriteRecipeKey && (object)item != RecipeList.IgnoreAccents && (object)item != RecipeList.SortButton && (object)item != RecipeList.GamepadSortButton) { mappings.Add("OpenKeep." + text + "." + item.Key, item); } } mappings.Add("OpenKeep.2. Stow.Favourite Item Key", (KindleSetting)(object)RecipeList.FavouriteRecipeKey); IEnumerable enumerable = mappings.Select, ConversionRule>((KeyValuePair pair) => new ConversionRule(pair.Key, pair.Value.Id, IsShortcut(pair.Value) ? "KeyboardShortcut" : pair.Value.ValueType.Name, string.Join(",", pair.Value.Choices), false, IsShortcut(pair.Value))); converter = new ConfigConverter(new ConversionMapping(1, "OpenKeep", 0, enumerable)); registration = MeadworksConversion.Register(new ConversionRegistration("kindle.openkeep", "com.meadworks.kindle", "milkyteam.openkeep", "OpenKeep", (Func)(() => !disposed && (File.Exists(SourcePath) || Directory.GetFiles(Paths.ConfigPath, "OpenKeep.Salvage*.yml").Length != 0)), (Func)(() => Preview()), (Func, bool, object>)delegate(object document, IReadOnlyDictionary resolutions, bool backup) { if (!backup) { throw new InvalidOperationException("Kindle import requires a backup."); } Dictionary dictionary = new Dictionary(StringComparer.Ordinal); Dictionary dictionary2 = new Dictionary(StringComparer.Ordinal); foreach (KeyValuePair resolution in resolutions) { if (resolution.Key.StartsWith("binding:", StringComparison.Ordinal)) { dictionary2.Add(resolution.Key.Substring(8), resolution.Value); } else if (KindleSettings.All.Any((KindleSetting s) => s.Id == resolution.Key && IsShortcut(s)) && !mappings.ContainsKey(resolution.Value)) { dictionary2.Add(resolution.Key, resolution.Value); } else { dictionary.Add(resolution.Key, resolution.Value); } } return Apply((document as KindleImportPreview) ?? throw new ArgumentException("Wrong Kindle import preview."), dictionary, dictionary2); })); } private void Check() { if (disposed || Thread.CurrentThread.ManagedThreadId != thread) { throw new InvalidOperationException("Kindle imports require their live owning thread."); } } public void Dispose() { if (!disposed) { disposed = true; registration?.Dispose(); registration = null; } } private static bool IsShortcut(KindleSetting setting) { if ((object)setting != RecipeList.SearchKey && (object)setting != RecipeList.FavouriteRecipeKey) { return (object)setting == Salvage.SalvageKey; } return true; } public static bool DeclareAndYield() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown if (!Plugin.Services.StepAside.Declared("com.meadworks.kindle").Any()) { List list = new List(); if (Chainloader.PluginInfos.TryGetValue("milkyteam.openkeep", out var value) && value.Metadata.Version >= new Version(2, 0)) { list.Add(new SourceMod(value.Metadata.GUID, "OpenKeep")); } foreach (PluginInfo info in Chainloader.PluginInfos.Values) { if ((info.Metadata.GUID == "com.ab5olutezer0.valheim.craftingsearch" || string.Equals(info.Metadata.Name, "Crafting Search", StringComparison.OrdinalIgnoreCase) || string.Equals(((object)info.Instance)?.GetType().Assembly.GetName().Name, "CraftingSearch", StringComparison.OrdinalIgnoreCase)) && !list.Any((SourceMod s) => s.Guid == info.Metadata.GUID)) { list.Add(new SourceMod(info.Metadata.GUID, "Crafting Search")); } } MeadworksStepAside.Declare("com.meadworks.kindle", "Kindle", (IEnumerable)list); } return MeadworksStepAside.ShouldYield("com.meadworks.kindle"); } public void Tick(bool active) { if (!offered) { offered = true; if (marker.Value.Length == 0 && File.Exists(Path.Combine(Paths.ConfigPath, "milkyteam.openkeep.cfg"))) { Run(write: false); } } if (preview.Value || apply.Value) { Run(apply.Value); } if (!active) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)localPlayer == (Object)(object)lastPlayer) { return; } lastPlayer = localPlayer; (string, string)[] array = new(string, string)[3] { ("favouriteRecipes", "favoriteRecipes"), ("favouriteRecipesOnly", "favoriteRecipesOnly"), ("trackedRecipes", "trackedRecipes") }; for (int i = 0; i < array.Length; i++) { var (text, text2) = array[i]; if (!localPlayer.m_customData.ContainsKey("Kindle." + text2) && localPlayer.m_customData.TryGetValue("OpenKeep." + text, out var value)) { localPlayer.m_customData["Kindle." + text2] = value; } } string text3 = default(string); if (!localPlayer.TryGetUniqueKeyValue("kindle_sort_desc", ref text3) && !localPlayer.m_customData.ContainsKey("Kindle.importedCraftingSearch") && localPlayer.TryGetUniqueKeyValue("craftingsearch_desc", ref text3)) { localPlayer.AddUniqueKeyValue("kindle_sort_desc", "1"); localPlayer.m_customData["Kindle.importedCraftingSearch"] = "1"; } } public KindleImportPreview Preview() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Invalid comparison between Unknown and I4 //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Invalid comparison between Unknown and I4 //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) Check(); string hash; Dictionary dictionary = ReadSources(out hash); if (dictionary.Count == 0) { throw new InvalidOperationException("No OpenKeep settings or salvage files were found to import."); } IReadOnlyList> readOnlyList2; if (!dictionary.TryGetValue(SourcePath, out var value)) { IReadOnlyList> readOnlyList = Array.Empty>(); readOnlyList2 = readOnlyList; } else { readOnlyList2 = CfgText.Read(value, "OpenKeep"); } IReadOnlyList> raw = readOnlyList2; List> list = new List>(); List list2 = new List(); List list3 = new List(); List list4 = new List(); foreach (KeyValuePair item in raw) { if (!mappings.TryGetValue(item.Key, out KindleSetting value2)) { list3.Add(item.Key + ": no Kindle mapping"); continue; } if ((object)value2 == RecipeList.FavouriteRecipeKey && item.Value == "F") { list3.Add(item.Key + ": default reference F binding retained as Kindle's configured binding"); continue; } AuthorityDecision val = MeadworksAuthority.Decide("com.meadworks.kindle", KindleConfig.Map(value2.Scope), true); if (settings.IsLocked(value2) || (int)val.Source == 1 || (int)val.Source == 2) { list3.Add(item.Key + ": target is locked or server-provided"); continue; } try { Type valueType = value2.ValueType; object result; object obj = (IsShortcut(value2) ? ((object)KeyboardShortcut.Deserialize(item.Value)) : ((!valueType.IsEnum) ? TomlTypeConverter.ConvertToValue(item.Value, valueType) : (Enum.TryParse(valueType, item.Value, ignoreCase: true, out result) ? result : value2.DefaultValue))); object obj2 = (IsShortcut(value2) ? obj : value2.NormalizeBoxed(obj)); object obj3; if (!IsShortcut(value2)) { obj3 = Convert.ToString(obj2, CultureInfo.InvariantCulture) ?? ""; } else { KeyboardShortcut val2 = (KeyboardShortcut)obj2; obj3 = ((KeyboardShortcut)(ref val2)).Serialize(); } string text = (string)obj3; if (text != item.Value) { list4.Add(item.Key + ": " + item.Value + " -> " + text + " (normalized)"); } list.Add(new KeyValuePair(item.Key, text)); } catch (Exception ex) { list2.Add(item.Key + ": " + ex.GetBaseException().Message); } } ConversionPreview val3 = converter.Preview((IEnumerable>)list); list2.AddRange(val3.Errors); Dictionary dictionary2 = ReadTargetYaml(); foreach (KeyValuePair item2 in dictionary.Where((KeyValuePair p) => p.Key != SourcePath)) { dictionary2[Destination(item2.Key)] = ImportedText(item2.Key, item2.Value); } if (dictionary2.Count != 0) { SalvageModel salvageModel = new SalvageModel(); salvageModel.LoadAll(KindleAlmanac.Ordered(dictionary2)); list2.AddRange(salvageModel.Errors); } string[] prepareErrors = list2.ToArray(); try { ValidateFinalBindings(val3, ReadOverrides()); } catch (Exception ex2) { list2.Add(ex2.GetBaseException().Message); } IEnumerable values = val3.Values.Select((ConversionValue v) => new KindleImportValue(v.SourceId, v.TargetId, raw.First>((KeyValuePair p) => p.Key == v.SourceId).Value, Convert.ToString(v.Value, CultureInfo.InvariantCulture) ?? "", config[config.Keys.Single((ConfigDefinition k) => k.Section + "." + k.Key == v.TargetId)].GetSerializedValue())); return new KindleImportPreview(this, val3, values, list2, prepareErrors, list3, list4, dictionary, hash, TargetHash(), Plugin.Session.Generation); } private Dictionary ReadOverrides() { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); string[] array = choices.Value.Split(';'); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { dictionary[text.Substring(0, num).Trim()] = text.Substring(num + 1).Trim(); } } return dictionary; } private Dictionary ReadSources(out string hash) { List list = Directory.GetFiles(Paths.ConfigPath, "OpenKeep.Salvage*.yml").OrderBy((string p) => p, StringComparer.Ordinal).ToList(); if (File.Exists(SourcePath)) { list.Insert(0, SourcePath); } Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); Dictionary dictionary2 = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (string item in list) { string text = KindleAlmanac.FileHash(item); string value = KindleAlmanac.ReadText(item); if (KindleAlmanac.FileHash(item) != text) { throw new InvalidOperationException("Source changed while preparing the import."); } dictionary.Add(item, value); dictionary2.Add(item, text); } hash = KindleAlmanac.SetHash(dictionary2); return dictionary; } private Dictionary ReadTargetYaml() { return Directory.GetFiles(Paths.ConfigPath, "Kindle.Salvage*.yml").ToDictionary((string p) => p, (string p) => KindleAlmanac.ReadText(p), StringComparer.OrdinalIgnoreCase); } private static string Destination(string source) { return Path.Combine(Paths.ConfigPath, Path.GetFileName(source).Replace("OpenKeep.", "Kindle.")); } private static string ImportedText(string path, string text) { return "# Imported from " + Path.GetFileName(path) + "; source preserved.\n" + text; } private string TargetHash() { List> list = (from k in config.Keys.OrderBy((ConfigDefinition k) => k.Section, StringComparer.Ordinal).ThenBy((ConfigDefinition k) => k.Key, StringComparer.Ordinal) select new KeyValuePair(k.Section.Length + ":" + k.Section + k.Key.Length + ":" + k.Key, TomlTypeConverter.ConvertToString(config[k].BoxedValue, config[k].SettingType))).ToList(); list.Add(new KeyValuePair("config-bytes", KindleAlmanac.FileHash(config.ConfigFilePath))); list.Add(new KeyValuePair("yaml-set", KindleAlmanac.SetHash(ReadTargetYaml()))); return KindleAlmanac.SetHash(list); } private void Admission(KindleImportPreview document, bool target = true) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) Check(); if (document == null || document.Owner != this) { throw new ArgumentException("Preview belongs to another Kindle importer."); } KindleAlmanac.Authority(); if (Plugin.Session.Generation != document.Generation) { throw new InvalidOperationException("Session changed; preview again."); } ReadSources(out string hash); if (hash != document.SourceSha256) { throw new InvalidOperationException("Source files changed; preview again."); } if (target && TargetHash() != document.TargetSha256) { throw new InvalidOperationException("Target configuration or salvage files changed; preview again."); } foreach (ConversionValue value in document.Preview.Values) { KindleSetting val = KindleSettings.All.Single((KindleSetting s) => s.Id == value.TargetId); AuthorityDecision val2 = MeadworksAuthority.Decide("com.meadworks.kindle", KindleConfig.Map(val.Scope), true); if (settings.IsLocked(val) || !val2.Allowed || val2.RequiresServerAmendment) { throw new InvalidOperationException("An import target is now locked: " + value.TargetId); } } } public KindleImportResult Apply(KindleImportPreview document, IReadOnlyDictionary sourceChoices, IReadOnlyDictionary bindingOverrides = null) { Admission(document); if (document.PrepareErrors.Count != 0) { throw new ArgumentException(string.Join("; ", document.PrepareErrors)); } if (bindingOverrides == null) { bindingOverrides = new Dictionary(); } ValidateFinalBindings(document.Preview, bindingOverrides); ImportTarget importTarget = new ImportTarget(this, document); ConversionResult val = converter.Apply(document.Preview, (IConversionTarget)(object)importTarget, sourceChoices, bindingOverrides); List list = new List(); List list2 = importTarget.Backups.ToList(); try { CopyYaml(document, list, list2); Admission(document, target: false); } catch (Exception ex) { throw new InvalidOperationException("Configuration committed " + val.Written + " settings before YAML/source verification stopped: " + ex.GetBaseException().Message + ". Backups: " + string.Join(", ", list2), ex); } marker.Value = "OpenKeep"; return new KindleImportResult(val, document.SourceSha256, TargetHash(), list2, list); } private void Run(bool write) { List list = new List { "Kindle OpenKeep import: " + (write ? "apply" : "preview") }; try { KindleImportPreview kindleImportPreview = Preview(); list.AddRange(kindleImportPreview.Normalizations); list.AddRange(kindleImportPreview.Values.Select((KindleImportValue v) => v.SourceId + " -> " + v.TargetId + " = " + v.Value)); list.AddRange(kindleImportPreview.Errors); list.AddRange(kindleImportPreview.Skipped); list.AddRange(kindleImportPreview.BindingConflicts.Select((ConversionConflict c) => "Shortcut collision: " + c.TargetId + " (set Binding Overrides)")); list.Add("Source SHA256: " + kindleImportPreview.SourceSha256 + "; target SHA256: " + kindleImportPreview.TargetSha256); if (write) { KindleImportResult kindleImportResult = Apply(kindleImportPreview, new Dictionary(), ReadOverrides()); list.AddRange(kindleImportResult.Messages); list.Add("Applied " + kindleImportResult.Written + " settings; target backup: " + kindleImportResult.BackedUp); } else { list.Add("Preview only; no settings changed."); } } catch (Exception ex) { list.Add("Import stopped: " + ex.GetType().Name + ": " + ex.Message); } finally { ConfigEntry obj = preview; bool value = (apply.Value = false); obj.Value = value; Directory.CreateDirectory(Path.GetDirectoryName(ReportPath)); File.WriteAllLines(ReportPath, list); log.Info(list[list.Count - 1] + " Report: " + ReportPath); } } private void ValidateFinalBindings(ConversionPreview plan, IReadOnlyDictionary overrides) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); foreach (KindleSetting item in KindleSettings.All.Where(IsShortcut)) { dictionary[item.Id] = settingsEntry(item).GetSerializedValue(); } foreach (ConversionValue value in plan.Values) { if (dictionary.ContainsKey(value.TargetId)) { dictionary[value.TargetId] = Convert.ToString(value.Value, CultureInfo.InvariantCulture) ?? ""; } } foreach (KeyValuePair @override in overrides) { if (dictionary.ContainsKey(@override.Key)) { dictionary[@override.Key] = @override.Value; } } Dictionary dictionary2 = new Dictionary(StringComparer.Ordinal); HotkeyChord val = default(HotkeyChord); foreach (KeyValuePair item2 in dictionary) { if (!HotkeyChord.TryParse(item2.Value, ref val)) { throw new ArgumentException("Unknown shortcut: " + item2.Key); } if (!val.IsNone) { dictionary2[item2.Key] = string.Join(" + ", new string[1] { val.Main }.Concat(val.Modifiers.OrderBy((string m) => m, StringComparer.Ordinal))); } } IGrouping>[] array = (from @group in dictionary2.GroupBy, string>((KeyValuePair pair) => pair.Value, StringComparer.OrdinalIgnoreCase) where @group.Count() > 1 select @group).ToArray(); if (array.Length == 0) { return; } throw new ArgumentException("Final shortcut collision: " + string.Join("; ", array.Select((IGrouping> group) => group.Key + " -> " + string.Join(", ", group.Select((KeyValuePair pair) => pair.Key))))); } private ConfigEntryBase settingsEntry(KindleSetting setting) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown return config[new ConfigDefinition(setting.Section, setting.Key)]; } private void CopyYaml(KindleImportPreview document, List report, List backups) { string text = TargetHash(); foreach (KeyValuePair item in document.Sources.Where>((KeyValuePair p) => p.Key != SourcePath)) { Admission(document, target: false); if (TargetHash() != text) { throw new InvalidOperationException("Target changed during YAML import."); } string text2 = Destination(item.Key); string text3 = ImportedText(item.Key, item.Value); string text4 = (File.Exists(text2) ? KindleAlmanac.ReadText(text2) : null); string text5 = KindleAlmanac.Temporary(text2, text3); string text6 = null; try { Admission(document, target: false); if (TargetHash() != text) { throw new InvalidOperationException("Target changed at YAML publication."); } if (text4 != null) { text6 = KindleAlmanac.Backup(text2); File.Replace(text5, text2, text6); backups.Add(text6); } else { File.Move(text5, text2); } if (KindleAlmanac.ReadText(text2) != text3) { throw new IOException("Imported YAML verification failed; backup: " + text6); } text = TargetHash(); report.Add("Copied " + Path.GetFileName(text2) + ((text6 != null) ? " (existing target backed up)" : " (new target; no previous bytes)")); } finally { if (File.Exists(text5)) { File.Delete(text5); } } } } } internal sealed class KindleSyncReceipt { private ZNet network; private ZRpc server; private string epoch = ""; private long world; internal long CurrentGeneration { get { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 if (!Plugin.IsReady || (Object)(object)network == (Object)null || server == null || !server.IsConnected() || network != ZNet.instance || network.IsServer() || server != network.GetServerRPC()) { return -1L; } SessionSnapshot session = Plugin.Session; if ((int)session.Role != 3 || !session.AuthorityReady || session.WorldId == 0L || string.IsNullOrEmpty(session.SessionId)) { return -1L; } if (epoch.Length == 0) { epoch = session.SessionId; world = session.WorldId; } if (!(epoch == session.SessionId) || world != session.WorldId) { return -1L; } return session.Generation; } } internal void Observe() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 network = ZNet.instance; server = (((Object)(object)network != (Object)null && !network.IsServer()) ? network.GetServerRPC() : null); epoch = ""; world = 0L; if (server != null && server.IsConnected() && Plugin.IsReady) { SessionSnapshot session = Plugin.Session; if ((int)session.Role == 3 && !string.IsNullOrEmpty(session.SessionId)) { epoch = session.SessionId; world = session.WorldId; } } } } public static class KindleText { private static MeadworksTranslations catalog; public static long Revision { get { MeadworksTranslations obj = catalog; if (obj == null) { return -1L; } return obj.Translations.Revision; } } public static void Initialize(BepInPlugin metadata, ManualLogSource log) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); Assembly assembly = typeof(KindleText).Assembly; foreach (string item in MeadworksLanguages.Supported) { using Stream stream = assembly.GetManifestResourceStream("Kindle.localization." + item + ".json"); if (stream != null) { using StreamReader streamReader = new StreamReader(stream); dictionary.Add(item, streamReader.ReadToEnd()); } } catalog = MeadworksTranslations.Register(metadata, new ProductTranslations("kindle", (IReadOnlyDictionary)dictionary), (string)null, log); } public static void Notice(string text, bool top = false) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (!((Object)(object)MessageHud.instance == (Object)null)) { ProductRegistration source = Plugin.Source; if (source != null && source.IsActive && CrucibleUiPlugin.Active) { KitNotices.Show(source, new KitNotice(text, (KitNoticeKind)(!top), "", 0, (Sprite)null, true, false, true)); } else { MessageHud.instance.ShowMessage((MessageType)(top ? 1 : 2), text, 0, (Sprite)null, false, true); } } } public static string Text(string key) { MeadworksTranslations obj = catalog; return ((obj != null) ? obj.Text(key) : null) ?? key; } public static string Format(string key, params object[] arguments) { MeadworksTranslations obj = catalog; return ((obj != null) ? obj.Format(key, arguments) : null) ?? key; } public static string Token(string key) { return "$meadworks_kindle_" + key; } public static void Tick() { MeadworksTranslations obj = catalog; if (obj != null) { obj.Update(); } } public static void Shutdown() { MeadworksTranslations obj = catalog; if (obj != null) { obj.Dispose(); } catalog = null; } } public static class SalvageStackCapability { public const string CanId = "meadworks.crafting.salvage_can"; public const string ItemId = "meadworks.crafting.salvage_item"; public static readonly Version ContractVersion = new Version(1, 0); public static readonly Func Can = delegate(object item) { ItemData val = (ItemData)((item is ItemData) ? item : null); return val != null && SalvageActions.CanSalvage(val); }; public static readonly Func Salvage = delegate(object player, object item) { Player val = (Player)((player is Player) ? player : null); if (val != null) { ItemData val2 = (ItemData)((item is ItemData) ? item : null); if (val2 != null) { return SalvageActions.Salvage(val, val2); } } return false; }; public static void Register(ProductRegistration registration) { if (registration == null) { throw new ArgumentNullException("registration"); } registration.AddCapability>("meadworks.crafting.salvage_can", ContractVersion, Can); registration.AddCapability>("meadworks.crafting.salvage_item", ContractVersion, Salvage); } } public static class SalvageTabCapability { public const string Id = "meadworks.crafting.salvage_tab"; public static readonly Version ContractVersion = new Version(1, 0); public static readonly Func Provider = () => Active; public static bool Active { get; internal set; } public static void Register(ProductRegistration registration) { if (registration == null) { throw new ArgumentNullException("registration"); } registration.AddCapability>("meadworks.crafting.salvage_tab", ContractVersion, Provider); } } [BepInPlugin("com.meadworks.kindle", "Kindle", "0.1.25")] [BepInDependency("com.meadworks.crucible", "0.3.32")] [BepInDependency("com.meadworks.crucible.ui", "0.3.21")] [BepInDependency("com.jotunn.jotunn", "2.30.2")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.meadworks.kindle"; public const string Name = "Kindle"; public const string Version = "0.1.25"; public const string Family = "Forge"; private ProductRegistration? registration; private MeadworksLog? log; private KindleReferenceImport? referenceImport; private bool started; private long noticedSession = -1L; internal static ProductRegistration? Source { get; private set; } public static bool Ready { get; private set; } public static bool SteppedAside { get; private set; } public static bool GameplayAvailable { get { ConfigBlockReason val = default(ConfigBlockReason); if (Ready && !SteppedAside) { return MeadworksAuthority.ProductActive("com.meadworks.kindle", ref val); } return false; } } public static bool AllowsUi { get; private set; } public static KindleConfig? Settings { get; private set; } private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown log = MeadworksLog.For(((BaseUnityPlugin)this).Logger, "Kindle"); try { if (!Plugin.IsReady) { throw new InvalidOperationException("Required Crucible is not ready"); } registration = Plugin.Services.Register(new ProductMetadata("com.meadworks.kindle", "Kindle", new Version("0.1.25"), new Version(0, 1), new Version(0, 1), (MultiplayerPolicy)1, "Forge")); Source = registration; AllowsUi = MeadworksHeadless.AllowsUi; Settings = KindleConfig.Bind(((BaseUnityPlugin)this).Config, log); KindleText.Initialize(((BaseUnityPlugin)this).Info.Metadata, ((BaseUnityPlugin)this).Logger); referenceImport = new KindleReferenceImport(((BaseUnityPlugin)this).Config, Settings, log); SalvageTabCapability.Register(registration); SalvageStackCapability.Register(registration); Ready = true; log.Info(AllowsUi ? "Kindle registered; crafting modules start after plugin discovery." : "Kindle registered on a headless process; no UI is created."); } catch (Exception ex) { Shutdown(); log.Error((object)("Kindle initialization rejected: " + ex)); } } private void Start() { if (!Ready || Settings == null || registration == null || log == null) { return; } try { SteppedAside = KindleReferenceImport.DeclareAndYield(); KindleSalvage.Initialize(((BaseUnityPlugin)this).Config, registration, delegate(string message) { log.Warning(message); }); if (!SteppedAside && AllowsUi) { KindleRecipes.Initialize(Settings, log); KindleBatch.Initialize(Settings, log); KindleTracker.Initialize(Settings, log); KindleCarts.Initialize(Settings, log); KindleVirtualStation.Initialize(Settings); KindleStationReach.Initialize(Settings); KindleRepair.Initialize(); KindleRecipes.ToggleTracking = KindleTracker.Toggle; KindleRecipes.IsTracked = KindleTracker.IsTracked; Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(Relabel)); } started = true; } catch (Exception ex) { log.Error((object)("Kindle modules rejected: " + ex.GetType().Name + ": " + ex.Message)); Shutdown(); } } private void Update() { if (!Ready) { return; } Settings?.Tick(Time.unscaledTime); KindleText.Tick(); if (!started) { return; } referenceImport?.Tick(GameplayAvailable); if (SteppedAside && AllowsUi && InventoryGui.IsVisible() && (Object)(object)MessageHud.instance != (Object)null && noticedSession != Plugin.Session.Generation) { noticedSession = Plugin.Session.Generation; IReadOnlyList present = MeadworksStepAside.Decide("com.meadworks.kindle").Present; MessageHud.instance.ShowMessage((MessageType)2, KindleText.Format("step_aside", string.Join(", ", present.Select((SourceMod source) => source.Name))), 0, (Sprite)null, false, true); } KindleSalvage.Tick(); if (GameplayAvailable && AllowsUi) { KindleRecipes.Tick(); KindleBatch.Tick(); KindleTracker.Tick(); KindleCarts.Tick(); KindleVirtualStation.Tick(); } } private void Relabel() { if (!GameplayAvailable || !AllowsUi) { return; } try { KindleSalvage.Tick(); KindleRecipes.Relabel(); KindleTracker.Relabel(); } catch (Exception ex) { MeadworksLog? obj = log; if (obj != null) { obj.Warning("Kindle language refresh: " + ex.GetType().Name + ": " + ex.Message); } } } private void OnDestroy() { Shutdown(); } private void Shutdown() { Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(Relabel)); Ready = false; started = false; noticedSession = -1L; Action[] array = new Action[9] { KindleRepair.Shutdown, KindleRecipes.Shutdown, KindleBatch.Shutdown, KindleTracker.Shutdown, KindleCarts.Shutdown, KindleVirtualStation.Shutdown, KindleStationReach.Shutdown, KindleSalvage.Shutdown, KindleText.Shutdown }; foreach (Action action in array) { try { action(); } catch (Exception ex) { MeadworksLog? obj = log; if (obj != null) { obj.Warning("Kindle teardown: " + ex.GetType().Name); } } } referenceImport?.Dispose(); referenceImport = null; Settings?.Shutdown(); Settings = null; Source = null; ProductRegistration? obj2 = registration; if (obj2 != null) { obj2.Dispose(); } registration = null; SteppedAside = false; } } public static class KindleRecipes { [CompilerGenerated] private static class <>O { public static PopupButtonCallback <0>__Pop; public static EventHandler <1>__Changed; public static Func <2>__Facts; } private static readonly string[] categoryIcons = new string[8] { "ArrowWood", "SwordIron", "Bow", "HelmetBronze", "ShieldWood", "Hammer", "CookedMeat", "Wood" }; private static readonly Color categoryDim = new Color(0.5f, 0.5f, 0.5f, 0.75f); private static readonly KitListShrink categoryShrink = new KitListShrink(); private static readonly List categoryButtons = new List(); private static RectTransform categoryRow; private static RecipeCategory picked = (RecipeCategory)0; private static bool steady; private static bool steadySearch; private static bool steadyCategories; private static Vector2 steadyPosition; private static Vector2 steadySize; private static TrackLabelState shownTrack; private static GameObject hoveredRow; private static Recipe hoveredRecipe; private static KitIconButton favouriteButton; private static Button trackButton; private static RectTransform style; private static Sprite starSprite; private static Color starColour = new Color(1f, 0.713f, 0.361f, 1f); private static float nextStar; private static readonly HashSet latched = new HashSet(); private static KindleConfig config; private static MeadworksLog log; private static Harmony patches; private static InventoryGui owner; private static Player cachedFor; private static FavouriteRecipes favourites = FavouriteRecipes.Parse((string)null, (string)null); private static readonly RecipeKeyIndex index = new RecipeKeyIndex((Func)Key, (Func)((Recipe r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)r.m_item))); private static KitSearchRow search; private static KitTileList tiles; private static KitLatch latch = new KitLatch(); private static RecipeQuery query = RecipeQuery.All; private static string queryText = ""; private static bool rebuilding; private static readonly Dictionary searchButtons = new Dictionary(); private static Recipe keyRecipe; private static string keyText = ""; private static readonly string[] viewKeys = new string[5] { "recipe_view_list", "recipe_view_compact", "recipe_view_small", "recipe_view_medium", "recipe_view_large" }; private static readonly KitGlyph[] sortGlyphs; private static readonly string[] sortKeys; private static SearchButtonsState shownSearch; public static RecipeCategory PickedCategories { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)categoryRow) || !((Component)categoryRow).gameObject.activeSelf) { return (RecipeCategory)0; } return picked; } } private static Recipe Hovered { get { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)hoveredRow) || !hoveredRow.activeInHierarchy || !RectTransformUtility.RectangleContainsScreenPoint((RectTransform)hoveredRow.transform, Vector2.op_Implicit(ZInput.pointerPosition))) { return null; } return hoveredRecipe; } } public static Action ToggleTracking { get; set; } public static Func IsTracked { get; set; } public static bool Active { get { if (config != null && Plugin.GameplayAvailable && Plugin.AllowsUi && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return Object.op_Implicit((Object)(object)ZNet.instance); } return false; } } public static RecipeQuery Query { get { if (search == null || !search.Shown) { return RecipeQuery.All; } return query; } } public static bool Upgrader { get { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Player.m_localPlayer.GetCurrentCraftingStation())) { return Player.m_localPlayer.GetCurrentCraftingStation().m_upgrader; } return false; } } private static RecipeSort Sort { get { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; string text = default(string); localPlayer.TryGetUniqueKeyValue("sortcraft", ref text); string text2 = default(string); return RecipeSorts.FromStored(text, localPlayer.TryGetUniqueKeyValue("kindle_sort_desc", ref text2)); } } private static RecipeCategory CategoryOf(ItemData item) { //IL_0013: 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_0019: 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_007d: Expected I4, but got Unknown SharedData val = item?.m_shared; if (val == null) { return (RecipeCategory)0; } ItemType itemType = val.m_itemType; switch (itemType - 1) { case 1: if (!(val.m_food > 0f) && !(val.m_foodStamina > 0f) && !(val.m_foodEitr > 0f) && !(val.m_foodRegen > 0f)) { return (RecipeCategory)0; } return (RecipeCategory)64; case 0: return (RecipeCategory)128; case 3: return (RecipeCategory)4; case 5: case 6: case 10: case 16: case 17: return (RecipeCategory)8; case 8: case 22: return (RecipeCategory)1; case 4: return (RecipeCategory)16; case 18: return (RecipeCategory)32; default: if (item.IsWeapon()) { return (RecipeCategory)2; } return (RecipeCategory)0; } } private static void BuildCategories() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)categoryRow) || search == null || !Object.op_Implicit((Object)(object)search.List)) { return; } RectTransform list = search.List; GameObject val = new GameObject("Kindle_recipe_categories", new Type[1] { typeof(RectTransform) }); val.layer = ((Component)list).gameObject.layer; categoryRow = (RectTransform)val.transform; ((Transform)categoryRow).SetParent(((Transform)list).parent, false); ((Transform)categoryRow).SetSiblingIndex(((Transform)search.Row).GetSiblingIndex() + 1); RectTransform obj = categoryRow; RectTransform obj2 = categoryRow; RectTransform obj3 = categoryRow; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 1f); obj3.pivot = val2; Vector2 anchorMin = (obj2.anchorMax = val2); obj.anchorMin = anchorMin; for (int i = 0; i < RecipeCategories.All.Count; i++) { RecipeCategory category = RecipeCategories.All[i]; string text = ((object)Unsafe.As(ref category)/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(); KitIconButton val4 = KitIconButton.Create(categoryRow, "Kindle_recipe_category_" + text, (KitGlyph)0, Vector2.zero, 26f, (Action)delegate { Guard(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PickCategory(category); }); }); if (val4 != null) { GameObject val5 = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(categoryIcons[i]) : null); ItemDrop val6 = (Object.op_Implicit((Object)(object)val5) ? val5.GetComponent() : null); if (Object.op_Implicit((Object)(object)val6)) { val4.SetSprite(val6.m_itemData.GetIcon(), false); } val4.Tooltip(KindleText.Text("recipe_cat_" + text), KindleText.Text("recipe_cat_tip")); categoryButtons.Add(val4); } } val.SetActive(false); } private static void PickCategory(RecipeCategory category) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (Active) { picked = RecipeCategories.Toggle(picked, category); InventoryGui instance = InventoryGui.instance; ScrollRect val = ((Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_recipeListRoot)) ? ((Component)instance.m_recipeListRoot).GetComponentInParent() : null); if (Object.op_Implicit((Object)(object)val)) { val.verticalNormalizedPosition = 1f; } RefreshCategories(); Rebuild(); } } private static void TickRows(InventoryGui gui, bool showSearch) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) RectTransform list = search.List; bool flag = config.Get(RecipeList.Categories) && !CustomTabSelected(gui); if (flag) { BuildCategories(); } bool flag2 = (Object.op_Implicit((Object)(object)categoryRow) ? (((Component)categoryRow).gameObject.activeSelf == flag) : (!flag)); if (steady && Object.op_Implicit((Object)(object)list) && list.anchoredPosition == steadyPosition && list.sizeDelta == steadySize && showSearch == steadySearch && flag == steadyCategories && search.Shown == showSearch && flag2) { if (flag && Object.op_Implicit((Object)(object)categoryRow)) { LayoutCategories(); RefreshCategories(); } return; } ShrinkForCategories(gui, list, on: false); search.Tick(showSearch); if (Object.op_Implicit((Object)(object)categoryRow)) { if (((Component)categoryRow).gameObject.activeSelf != flag) { ((Component)categoryRow).gameObject.SetActive(flag); } ShrinkForCategories(gui, list, flag); if (flag) { LayoutCategories(); RefreshCategories(); } } steady = Object.op_Implicit((Object)(object)list); if (steady) { steadyPosition = list.anchoredPosition; steadySize = list.sizeDelta; steadySearch = showSearch; steadyCategories = flag; } } private static void ShrinkForCategories(InventoryGui gui, RectTransform list, bool on) { //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) //IL_0029: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)list) || (!on && !categoryShrink.Shrunk)) { return; } KitShrinkResult val = categoryShrink.Apply(KitUnity.Vector(list.anchoredPosition), KitUnity.Vector(list.sizeDelta), on, 34f, 30f); if (Object.op_Implicit((Object)(object)categoryRow)) { categoryRow.anchoredPosition = KitUnity.Vector(((KitShrinkResult)(ref val)).RowPosition); categoryRow.sizeDelta = KitUnity.Vector(((KitShrinkResult)(ref val)).RowSize); } if (((KitShrinkResult)(ref val)).Write) { list.anchoredPosition = KitUnity.Vector(((KitShrinkResult)(ref val)).ListPosition); list.sizeDelta = KitUnity.Vector(((KitShrinkResult)(ref val)).ListSize); if (Object.op_Implicit((Object)(object)gui)) { gui.m_recipeListBaseSize = list.sizeDelta.y; } } } private static void LayoutCategories() { //IL_0014: 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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) int count = categoryButtons.Count; if (count != 0) { float x = categoryRow.sizeDelta.x; float num = Mathf.Floor(Mathf.Min(26f, (x - 2f * (float)(count - 1)) / (float)count)); float num2 = ((count > 1) ? ((x - num * (float)count) / (float)(count - 1)) : 0f); for (int i = 0; i < count; i++) { RectTransform val = (RectTransform)((Component)categoryButtons[i].Button).transform; val.sizeDelta = new Vector2(num, num); val.anchoredPosition = new Vector2(Mathf.Round((float)i * (num + num2)), (0f - (30f - num)) / 2f); } } } private static void RefreshCategories() { //IL_0010: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < categoryButtons.Count && i < RecipeCategories.All.Count; i++) { KitIconButton val = categoryButtons[i]; bool flag = RecipeCategories.IsPicked(picked, RecipeCategories.All[i]); if (val.On != flag) { val.SetOn(flag); } if (Object.op_Implicit((Object)(object)val.Glyph)) { ((Graphic)val.Glyph).color = (((int)picked == 0 || flag) ? Color.white : categoryDim); } } } private static void HideRows() { if (search != null) { steady = false; ShrinkForCategories(owner, search.List, on: false); if (Object.op_Implicit((Object)(object)categoryRow) && ((Component)categoryRow).gameObject.activeSelf) { ((Component)categoryRow).gameObject.SetActive(false); } search.Tick(false); } } private static void DetachCategories() { steady = false; if (search != null) { ShrinkForCategories(owner, search.List, on: false); } categoryShrink.Reset(); categoryButtons.Clear(); if (Object.op_Implicit((Object)(object)categoryRow)) { KitUnity.Retire(((Component)categoryRow).gameObject); } categoryRow = null; } private static void Star() { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)starSprite) && !(Time.unscaledTime < nextStar)) { nextStar = Time.unscaledTime + 2f; BuildUi val = (Object.op_Implicit((Object)(object)Hud.instance) ? Hud.instance.m_buildUi : null); BuildUiPieceButton val2 = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.m_pieceButtonPrefab)) ? val.m_pieceButtonPrefab.GetComponent() : null); Image val3 = (Object.op_Implicit((Object)(object)val2) ? val2.m_favoriteStar : null); if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val3.sprite)) { starSprite = val3.sprite; starColour = ((Graphic)val3).color; } } } private static void Decorate(InventoryGui gui) { //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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) hoveredRow = null; Star(); foreach (RecipeDataPair availableRecipe in gui.m_availableRecipes) { RecipeDataPair current = availableRecipe; GameObject row = ((RecipeDataPair)(ref current)).InterfaceElement; Recipe recipe = ((RecipeDataPair)(ref current)).Recipe; if (!Object.op_Implicit((Object)(object)row) || !Object.op_Implicit((Object)(object)recipe)) { continue; } UIInputHandler obj = row.GetComponent() ?? row.AddComponent(); int quality = Quality(((RecipeDataPair)(ref current)).ItemData); obj.m_onMiddleClick = delegate { Guard(delegate { ToggleFavourite(recipe); }); }; obj.m_onRightClick = delegate { Guard(delegate { Track(gui, recipe, quality); }); }; obj.m_onPointerEnter = (Action)Delegate.Combine(obj.m_onPointerEnter, (Action)delegate { hoveredRow = row; hoveredRecipe = recipe; }); obj.m_onPointerExit = (Action)Delegate.Combine(obj.m_onPointerExit, (Action)delegate { if ((Object)(object)hoveredRow == (Object)(object)row) { hoveredRow = null; } }); RectTransform val = (RectTransform)row.transform; tiles.Mark(val, Favourite(recipe), starSprite, (Color?)starColour); tiles.Greyed(val, !((RecipeDataPair)(ref current)).CanCraft); if (!RecipeViews.IsGrid(config.Get(RecipeList.RecipeView))) { continue; } KitTileList obj2 = tiles; object obj3 = recipe.m_item?.m_itemData?.m_shared?.m_name; if (obj3 == null) { ItemDrop item = recipe.m_item; if (item == null) { obj3 = null; } else { GameObject gameObject = ((Component)item).gameObject; obj3 = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj3 == null) { obj3 = ((Object)recipe).name; } } obj2.Tooltip(val, Localize((string)obj3), (recipe.m_amount > 1) ? ("x" + recipe.m_amount) : ""); } } private static void ToggleFavourite(Recipe recipe) { if (!Active || !Object.op_Implicit((Object)(object)recipe) || !config.Get(RecipeList.Favourites)) { return; } ReadFavourites(); bool num = favourites.Toggle(Key(recipe)); WriteFavourites(); string key = (num ? "recipe_favorite_on" : "recipe_favorite_off"); object[] array = new object[1]; object obj = recipe.m_item?.m_itemData?.m_shared?.m_name; if (obj == null) { ItemDrop item = recipe.m_item; if (item == null) { obj = null; } else { GameObject gameObject = ((Component)item).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = ((Object)recipe).name; } } array[0] = Localize((string)obj); KindleText.Notice(KindleText.Format(key, array)); } private static void Only(KitClickKind kind) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Invalid comparison between Unknown and I4 //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Invalid comparison between Unknown and I4 //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown if (!Active || !config.Get(RecipeList.Favourites)) { return; } ReadFavourites(); if ((int)kind == 1) { if (favourites.Count == 0) { Message("recipe_none"); } else { if (!UnifiedPopup.IsAvailable()) { return; } Player captured = Player.m_localPlayer; Action clear = delegate { Guard(delegate { if (Active && !((Object)(object)Player.m_localPlayer != (Object)(object)captured)) { ReadFavourites(); favourites.Clear(); WriteFavourites(); Message("recipe_cleared"); } }); }; string text = KindleText.Text("recipe_only_topic"); string text2 = KindleText.Format("recipe_clear_ask", favourites.Count); if (Plugin.Source == null || KitDialogs.Confirm(Plugin.Source, text, text2, clear, (Action)null, true) == null) { PopupButtonCallback val = delegate { UnifiedPopup.Pop(); clear(); }; object obj = <>O.<0>__Pop; if (obj == null) { PopupButtonCallback val2 = UnifiedPopup.Pop; <>O.<0>__Pop = val2; obj = (object)val2; } UnifiedPopup.Push((PopupBase)new YesNoPopup(text, text2, val, (PopupButtonCallback)obj, true, false)); } } } else { OnlyToggle val3 = favourites.ToggleOnly(); if ((int)val3 != 2) { WriteFavourites(); } Message(((int)val3 == 0) ? "recipe_only_on" : (((int)val3 == 1) ? "recipe_only_off" : "recipe_none")); } } private static void Message(string key) { KindleText.Notice(KindleText.Text(key)); } private static void Track(InventoryGui gui, Recipe recipe, int quality) { if (Active && Object.op_Implicit((Object)(object)recipe) && config.Get(Tracker.Enabled)) { int arg = ((!gui.InCraftTab() || !((Object)(object)Selected(gui) == (Object)(object)recipe)) ? 1 : KindleBatch.NextCraft(gui, Player.m_localPlayer)); ToggleTracking?.Invoke(recipe, quality, arg, Upgrader); } } private static void RefreshActions(InventoryGui gui) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Expected O, but got Unknown //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)gui.m_variantButton)) { HideActions(); return; } style = (RectTransform)((Component)gui.m_variantButton).transform; Rect rect; if (favouriteButton == null || !Object.op_Implicit((Object)(object)favouriteButton.Button)) { RectTransform val = (RectTransform)((Transform)style).parent; Vector2 zero = Vector2.zero; rect = style.rect; favouriteButton = KitIconButton.Create(val, "Kindle_favourite", (KitGlyph)10, zero, ((Rect)(ref rect)).height, (Action)delegate { Guard(delegate { ToggleFavourite(Selected(gui)); }); }); RectTransform val2 = (RectTransform)((Transform)style).parent; string text = KindleText.Text("tracker_track"); Action obj = delegate { Guard(delegate { Track(gui, Selected(gui), Quality(((RecipeDataPair)(ref gui.m_selectedRecipe)).ItemData)); }); }; Vector2 zero2 = Vector2.zero; rect = style.rect; trackButton = KitButton.Create(val2, "Kindle_track", text, obj, zero2, new Vector2(80f, ((Rect)(ref rect)).height)); if (favouriteButton != null) { favouriteButton.Tooltip(KindleText.Text("recipe_favorite_topic"), KindleText.Text("recipe_favorite_tip")); } } Recipe val3 = Selected(gui); int num; int num2; if (Object.op_Implicit((Object)(object)val3)) { num = ((!CustomTabSelected(gui)) ? 1 : 0); if (num != 0 && config.Get(Tracker.Enabled)) { num2 = ((ToggleTracking != null) ? 1 : 0); goto IL_015d; } } else { num = 0; } num2 = 0; goto IL_015d; IL_015d: bool flag = (byte)num2 != 0; bool flag2 = num != 0 && config.Get(RecipeList.Favourites); if (Object.op_Implicit((Object)(object)trackButton)) { ((Component)trackButton).gameObject.SetActive(flag); } if (favouriteButton != null && Object.op_Implicit((Object)(object)favouriteButton.Button)) { ((Component)favouriteButton.Button).gameObject.SetActive(flag2); } if (num == 0) { return; } float x = style.anchoredPosition.x; rect = style.rect; float num3 = x - ((Rect)(ref rect)).width * style.pivot.x; if (((Component)style).gameObject.activeSelf) { float num4 = num3; rect = style.rect; num3 = num4 + (((Rect)(ref rect)).width + 6f); } if (flag && Object.op_Implicit((Object)(object)trackButton)) { bool flag3 = IsTracked?.Invoke(val3, Quality(((RecipeDataPair)(ref gui.m_selectedRecipe)).ItemData), Upgrader) ?? false; TrackLabelState val4 = default(TrackLabelState); ((TrackLabelState)(ref val4))..ctor((object)trackButton, flag3, KindleText.Revision); if (!((TrackLabelState)(ref val4)).Equals(shownTrack)) { shownTrack = val4; string text2 = KindleText.Text(flag3 ? "tracker_untrack" : "tracker_track"); TMP_Text componentInChildren = ((Component)trackButton).GetComponentInChildren(true); if (componentInChildren != null) { componentInChildren.text = text2; } KitTooltip.Set(((Component)trackButton).gameObject, text2, text2); } num3 = PlaceAction((RectTransform)((Component)trackButton).transform, num3); } if (flag2 && favouriteButton != null) { Star(); favouriteButton.SetSprite(starSprite, true); favouriteButton.SetOn(Favourite(val3)); PlaceAction((RectTransform)((Component)favouriteButton.Button).transform, num3); } } private static float PlaceAction(RectTransform rect, float x) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = style.anchorMin; rect.anchorMax = style.anchorMax; Rect rect2 = rect.rect; rect.anchoredPosition = new Vector2(x + ((Rect)(ref rect2)).width * rect.pivot.x, style.anchoredPosition.y); rect2 = rect.rect; return x + ((Rect)(ref rect2)).width + 6f; } private static void HideActions() { if (Object.op_Implicit((Object)(object)trackButton)) { ((Component)trackButton).gameObject.SetActive(false); } if (favouriteButton != null && Object.op_Implicit((Object)(object)favouriteButton.Button)) { ((Component)favouriteButton.Button).gameObject.SetActive(false); } } private static void ClearActions() { if (Object.op_Implicit((Object)(object)trackButton)) { Object.Destroy((Object)(object)((Component)trackButton).gameObject); } if (favouriteButton != null && Object.op_Implicit((Object)(object)favouriteButton.Button)) { Object.Destroy((Object)(object)((Component)favouriteButton.Button).gameObject); } trackButton = null; favouriteButton = null; style = null; starSprite = null; nextStar = 0f; latched.Clear(); } private static void InputTick() { //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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (CustomTabSelected(InventoryGui.instance) || KitTextField.Typing) { return; } KeyboardShortcut val = config.Shortcut(RecipeList.SearchKey); if (((KeyboardShortcut)(ref val)).IsDown()) { KitSearchRow obj = search; if (obj != null) { obj.Focus(); } } if (Object.op_Implicit((Object)(object)Hovered)) { val = config.Shortcut(RecipeList.FavouriteRecipeKey); if (((KeyboardShortcut)(ref val)).IsDown()) { ToggleFavourite(Hovered); } } } private static bool Once(string button) { if (!ZInput.GetButton(button)) { latched.Remove(button); return false; } if (ZInput.GetButtonDown(button)) { return latched.Add(button); } return false; } internal static bool Gamepad(InventoryGui gui) { if (!Active || CustomTabSelected(gui)) { return true; } if (KitTextField.Typing) { return false; } bool runGame = true; Guard(delegate { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) if (config.Get(RecipeList.GamepadControls)) { if (Once("JoyRStickUp")) { KitSearchRow obj = search; if (obj != null) { obj.Focus(); } } if (Once("JoyRStickDown")) { Track(gui, Selected(gui), Quality(((RecipeDataPair)(ref gui.m_selectedRecipe)).ItemData)); } if (Once("JoyRStickLeft")) { ToggleFavourite(Selected(gui)); } if (Once("JoyRStickRight")) { Only((KitClickKind)0); } PadButton? gamepadSortButton = config.GamepadSortButton; if (gamepadSortButton.HasValue && Once(GamepadMap.ZInputName(gamepadSortButton.Value))) { CycleSort(); } } if (tiles != null && tiles.Columns > 1) { runGame = false; int num = 0; int num2 = 0; if (ZInput.GetButtonDown("JoyLStickDown") || ZInput.GetButtonDown("JoyDPadDown")) { num2 = 1; } else if (ZInput.GetButtonDown("JoyLStickUp") || ZInput.GetButtonDown("JoyDPadUp")) { num2 = -1; } else if (ZInput.GetButtonDown("JoyLStickRight") || (!KindleBatch.Shown && ZInput.GetButtonDown("JoyDPadRight"))) { num = 1; } else if (ZInput.GetButtonDown("JoyLStickLeft") || (!KindleBatch.Shown && ZInput.GetButtonDown("JoyDPadLeft"))) { num = -1; } int selectedRecipeIndex = gui.GetSelectedRecipeIndex(false); if (selectedRecipeIndex >= 0 && gui.m_availableRecipes.Count != 0 && (num != 0 || num2 != 0)) { GridCell val = tiles.Navigator((Func)null).Move(new GridCell(selectedRecipeIndex % tiles.Columns, selectedRecipeIndex / tiles.Columns), new GridCell(num, num2)); gui.SetRecipe(((GridCell)(ref val)).Y * tiles.Columns + ((GridCell)(ref val)).X, true); } } }); return runGame; } public static Recipe Selected(InventoryGui gui) { if (!Object.op_Implicit((Object)(object)gui)) { return null; } return ((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe; } private static bool CustomTabSelected(InventoryGui gui) { if (Object.op_Implicit((Object)(object)gui) && Object.op_Implicit((Object)(object)gui.m_tabCraft)) { Transform parent = ((Component)gui.m_tabCraft).transform.parent; return KitTabs.HasSelected((RectTransform)(object)((parent is RectTransform) ? parent : null)); } return false; } public static int Quality(ItemData item) { if (item != null) { return item.m_quality + 1; } return 1; } public static string Key(Recipe recipe) { if (!Object.op_Implicit((Object)(object)recipe) || !Object.op_Implicit((Object)(object)recipe.m_item)) { return ""; } if (recipe == keyRecipe) { return keyText; } keyText = RecipeKeys.Of(((Object)recipe).name, ((Object)((Component)recipe.m_item).gameObject).name); keyRecipe = recipe; return keyText; } public static Recipe Find(string key) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { return null; } return index.Find((object)ObjectDB.instance, (IReadOnlyList)ObjectDB.instance.m_recipes, key); } public static void Initialize(KindleConfig settings, MeadworksLog logger) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown Shutdown(); config = settings; log = logger; config.Changed += Changed; patches = new Harmony("com.meadworks.kindle.recipes"); patches.CreateClassProcessor(typeof(KindleRecipePatches)).Patch(); patches.CreateClassProcessor(typeof(TypingStill)).Patch(); } private static void Changed(object sender, EventArgs args) { Guard(delegate { //IL_0005: Unknown result type (might be due to invalid IL or missing references) shownSearch = default(SearchButtonsState); DetachCategories(); KitSearchRow obj = search; if (obj != null) { obj.Detach(); } search = null; searchButtons.Clear(); query = RecipeQuery.Parse(queryText, config.Get(RecipeList.IgnoreAccents)); Rebuild(); }); } internal static void Guard(Action action) { try { action(); } catch (Exception ex) { MeadworksLog obj = log; if (obj != null) { obj.Warning("Recipe list: " + ex.GetType().Name + ": " + ex.Message); } } } private static void Bind(InventoryGui gui) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)owner == (Object)(object)gui)) { ClearUi(); owner = gui; queryText = ""; query = RecipeQuery.All; latch = new KitLatch(); picked = (RecipeCategory)0; } } private static void ReadFavourites() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)cachedFor == (Object)(object)localPlayer)) { cachedFor = localPlayer; localPlayer.m_customData.TryGetValue("Kindle.favoriteRecipes", out var value); localPlayer.m_customData.TryGetValue("Kindle.favoriteRecipesOnly", out var value2); favourites = FavouriteRecipes.Parse(value, value2); } } private static void WriteFavourites() { Dictionary customData = Player.m_localPlayer.m_customData; Write(customData, "Kindle.favoriteRecipes", favourites.SerializeSet()); Write(customData, "Kindle.favoriteRecipesOnly", favourites.SerializeOnly()); Rebuild(); } private static void Write(Dictionary data, string key, string value) { if (value == null) { data.Remove(key); } else { data[key] = value; } } private static bool Favourite(Recipe recipe) { if (config.Get(RecipeList.Favourites)) { return favourites.Contains(Key(recipe)); } return false; } private static void CycleSort() { CycleSort((KitClickKind)0); } private static void CycleSort(KitClickKind kind) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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) if (Active) { (string, bool) tuple = RecipeSorts.ToStored(((int)kind == 1) ? RecipeSorts.Previous(Sort) : RecipeSorts.Next(Sort)); Player localPlayer = Player.m_localPlayer; localPlayer.RemoveUniqueKeyValue("sortcraft"); localPlayer.RemoveUniqueKeyValue("kindle_sort_desc"); if (tuple.Item1 != null) { localPlayer.AddUniqueKeyValue("sortcraft", tuple.Item1); } if (tuple.Item2) { localPlayer.AddUniqueKeyValue("kindle_sort_desc", "1"); } Rebuild(); } } public static void Rebuild() { if (!Active || rebuilding || !Object.op_Implicit((Object)(object)InventoryGui.instance) || !InventoryGui.IsVisible()) { return; } Guard(delegate { rebuilding = true; try { InventoryGui.instance.UpdateCraftingPanel(false); } finally { rebuilding = false; } }); } private static RecipeFacts Facts(RecipeDataPair pair) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown Recipe recipe = ((RecipeDataPair)(ref pair)).Recipe; if (!Object.op_Implicit((Object)(object)recipe) || !Object.op_Implicit((Object)(object)recipe.m_item)) { return null; } RecipeMaterial[] array = recipe.m_resources.Where((Requirement r) => Object.op_Implicit((Object)(object)r.m_resItem)).Select((Func)((Requirement r) => new RecipeMaterial(Localize(r.m_resItem.m_itemData?.m_shared?.m_name ?? ((Object)((Component)r.m_resItem).gameObject).name), ((Object)((Component)r.m_resItem).gameObject).name, r.GetAmount(Quality(((RecipeDataPair)(ref pair)).ItemData)), r.m_upgraderResource))).ToArray(); string text = Localize(recipe.m_item.m_itemData?.m_shared?.m_name ?? ((Object)((Component)recipe.m_item).gameObject).name); return new RecipeFacts(Key(recipe), text, ((Object)((Component)recipe.m_item).gameObject).name, (IReadOnlyList)array, ((RecipeDataPair)(ref pair)).CanCraft, recipe.m_listSortWeight, ((RecipeDataPair)(ref pair)).ItemData?.m_quality ?? 0, CategoryOf(recipe.m_item.m_itemData)); } private static string Localize(string text) { if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } internal static void Apply(InventoryGui gui) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (!Active || CustomTabSelected(gui)) { return; } Prepare(gui); ReadFavourites(); RecipePipeline.Apply((IList)gui.m_availableRecipes, (Func)Facts, new RecipeListState(Query, favourites, Sort, config.Get(RecipeList.Favourites), config.Get(RecipeList.FavouritesFirst), Upgrader, (CultureInfo)null, PickedCategories), (Action)delegate(RecipeDataPair pair) { if (Object.op_Implicit((Object)(object)((RecipeDataPair)(ref pair)).InterfaceElement)) { Object.Destroy((Object)(object)((RecipeDataPair)(ref pair)).InterfaceElement); } }); KitTileList obj = tiles; if (obj != null) { obj.Forget(); } tiles = KitTileList.For(gui.m_recipeListRoot, gui.m_recipeListSpace, gui.m_recipeListBaseSize, (KitTileParts)null); if (tiles != null) { tiles.View = (KitTileView)config.Get(RecipeList.RecipeView); tiles.Arrange((IList)gui.m_availableRecipes.Where((RecipeDataPair p) => Object.op_Implicit((Object)(object)((RecipeDataPair)(ref p)).InterfaceElement)).Select((Func)((RecipeDataPair p) => (RectTransform)((RecipeDataPair)(ref p)).InterfaceElement.transform)).ToList()); Decorate(gui); } } internal static void Prepare(InventoryGui gui) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_018b: Expected O, but got Unknown if (!Active) { return; } Bind(gui); ReadFavourites(); KitTabs.RestoreEmptyRecipeCaption(gui, (Object)(object)((RecipeDataPair)(ref gui.m_selectedRecipe)).Recipe != (Object)null); if (search == null && !latch.Failed) { Transform val = (Object.op_Implicit((Object)(object)gui.m_recipeListRoot) ? ((Transform)gui.m_recipeListRoot).parent : null); object obj = (object)(Object.op_Implicit((Object)(object)val) ? /*isinst with value type is only supported in some contexts*/: null); List list = new List { new KitSearchButton { Id = "view", Glyph = (KitGlyph)0, Click = delegate(KitClickKind kind) { //IL_0006: 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) Guard(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) CycleView(kind); }); } } }; if (config.Get(RecipeList.Favourites)) { list.Add(new KitSearchButton { Id = "only", Glyph = (KitGlyph)10, Click = delegate(KitClickKind kind) { //IL_0006: 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) Guard(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Only(kind); }); } }); } if (config.Get(RecipeList.SortButton)) { list.Add(new KitSearchButton { Id = "sort", Glyph = (KitGlyph)9, Click = delegate(KitClickKind kind) { //IL_0006: 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) Guard(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) CycleSort(kind); }); } }); } search = KitSearchRow.Attach((RectTransform)obj, "Kindle_recipe_search", (IList)list, latch, KindleText.Text("recipe_search")); if (search != null) { search.ListWritten += delegate(Vector2 size) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) gui.m_recipeListBaseSize = size.y; }; search.Field.ReportChat = true; search.Field.Text = queryText; search.Field.Changed += delegate(string text) { queryText = text; query = RecipeQuery.Parse(text, config.Get(RecipeList.IgnoreAccents)); ScrollRect componentInParent = ((Component)gui.m_recipeListRoot).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { componentInParent.verticalNormalizedPosition = 1f; } Rebuild(); }; for (int num = 0; num < search.Buttons.Count; num++) { searchButtons[list[num].Id] = search.Buttons[num]; } KitTooltip.Set(((Component)search.Field.Rect).gameObject, KindleText.Text("recipe_search_topic"), KindleText.Text("recipe_search_tip")); } } if (search != null) { search.ClearOnClose = config.Get(RecipeList.ClearSearchOnClose); TickRows(gui, config.Get(RecipeList.Search) && !CustomTabSelected(gui)); RefreshSearch(); } } private static void CycleView(KitClickKind kind) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_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 (Active && config.TryChange((KindleSetting)(object)RecipeList.RecipeView)) { RecipeView val = config.Get(RecipeList.RecipeView); config.Entry((KindleSetting)(object)RecipeList.RecipeView).BoxedValue = (((int)kind == 1) ? RecipeViews.Previous(val) : RecipeViews.Next(val)); } } private static void RefreshSearch() { //IL_001c: 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_003f: Expected I4, but got Unknown //IL_003f: Expected I4, but got Unknown //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_004f: Unknown result type (might be due to invalid IL or missing references) SearchButtonsState val = default(SearchButtonsState); ((SearchButtonsState)(ref val))..ctor((object)search, favourites.OnlyFavourites(true), (int)config.Get(RecipeList.RecipeView), config.IsLocked((KindleSetting)(object)RecipeList.RecipeView), (int)Sort, KindleText.Revision); if (!((SearchButtonsState)(ref val)).Equals(shownSearch)) { shownSearch = val; if (searchButtons.TryGetValue("only", out KitIconButton value)) { value.SetOn(((SearchButtonsState)(ref val)).Only); value.Tooltip(KindleText.Text("recipe_only_topic"), KindleText.Text("recipe_only_tip")); } if (searchButtons.TryGetValue("view", out KitIconButton value2)) { value2.SetGlyph((KitGlyph)((SearchButtonsState)(ref val)).View); value2.Tooltip(KindleText.Text(viewKeys[((SearchButtonsState)(ref val)).View]), KindleText.Text("recipe_view_tip")); value2.SetUsable(!((SearchButtonsState)(ref val)).ViewLocked); } if (searchButtons.TryGetValue("sort", out KitIconButton value3)) { value3.SetGlyph(sortGlyphs[((SearchButtonsState)(ref val)).Sort]); value3.Tooltip(KindleText.Format("sort_topic", KindleText.Text(sortKeys[((SearchButtonsState)(ref val)).Sort])), KindleText.Text("sort_tip")); } } } internal static void Closed() { KitSearchRow obj = search; if (obj != null) { obj.Closed(); } if (config != null && config.Get(RecipeList.ClearSearchOnClose)) { queryText = ""; query = RecipeQuery.All; } } public static void Tick() { if (!Active) { HideRows(); HideActions(); } else if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible()) { Guard(delegate { Prepare(InventoryGui.instance); RefreshActions(InventoryGui.instance); InputTick(); }); } } internal static void Relabel() { if (!Active) { return; } ClearUi(); InventoryGui gui = InventoryGui.instance; if (Object.op_Implicit((Object)(object)gui) && InventoryGui.IsVisible() && !CustomTabSelected(gui)) { Guard(delegate { gui.UpdateCraftingPanel(false); RefreshActions(gui); gui.UpdateRecipe(Player.m_localPlayer, 0f); }); } } private static void ClearUi() { //IL_0005: 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) shownSearch = default(SearchButtonsState); shownTrack = default(TrackLabelState); DetachCategories(); KitSearchRow obj = search; if (obj != null) { obj.Detach(); } search = null; KitTileList obj2 = tiles; if (obj2 != null) { obj2.Forget(); } tiles = null; searchButtons.Clear(); ClearActions(); hoveredRow = null; } public static void Shutdown() { if (config != null) { config.Changed -= Changed; } Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; ClearUi(); if (Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && InventoryGui.IsVisible() && !CustomTabSelected(owner)) { Guard(delegate { owner.UpdateCraftingPanel(false); }); } owner = null; cachedFor = null; config = null; log = null; query = RecipeQuery.All; queryText = ""; } static KindleRecipes() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown KitGlyph[] array = new KitGlyph[5]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); sortGlyphs = (KitGlyph[])(object)array; sortKeys = new string[5] { "sort_default", "sort_az", "sort_za", "sort_type", "sort_weight" }; } } [HarmonyPatch] internal static class KindleRecipePatches { [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] [HarmonyPrefix] [HarmonyPriority(800)] private static void Prepare(InventoryGui __instance) { KindleRecipes.Guard(delegate { KindleRecipes.Prepare(__instance); }); } [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] [HarmonyPostfix] private static void Prepared(InventoryGui __instance) { KindleRecipes.Guard(delegate { KindleRecipes.Prepare(__instance); }); } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] [HarmonyPostfix] private static void Listed(InventoryGui __instance) { KindleRecipes.Guard(delegate { KindleRecipes.Apply(__instance); }); } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeGamepadInput")] [HarmonyPrefix] private static bool Pad(InventoryGui __instance) { return KindleRecipes.Gamepad(__instance); } [HarmonyPatch(typeof(InventoryGui), "Hide")] [HarmonyPostfix] private static void Closed() { KindleRecipes.Guard(KindleRecipes.Closed); } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] internal static class TypingStill { [HarmonyPostfix] private static void Postfix(ref bool __result) { if (__result && KitTextField.AnyFocused) { __result = false; } } } public static class KindleRepair { private static readonly List worn = new List(); private static Harmony patches; private static float nextCount; private static int repairable; private static GameObject tipOwner; private static int tipShown; private static string tipLanguage; private static long tipRevision = -1L; private static bool Active { get { if (Plugin.GameplayAvailable && Plugin.AllowsUi) { return Object.op_Implicit((Object)(object)Player.m_localPlayer); } return false; } } public static void Initialize() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown Shutdown(); patches = new Harmony("com.meadworks.kindle.repair"); patches.CreateClassProcessor(typeof(KindleRepairPatches)).Patch(); } public static void Shutdown() { Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; nextCount = 0f; tipOwner = null; } internal static void Guard(Action action) { try { action(); } catch (Exception ex) { KindleSalvage.Warn("Repair all: " + ex.GetType().Name + ": " + ex.Message); } } public static List Repairable(Player player) { //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) List list = new List(); if (!Object.op_Implicit((Object)(object)player)) { return list; } CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); bool flag = player.NoCostCheat(); if (!Object.op_Implicit((Object)(object)currentCraftingStation) && !flag) { return list; } if (Object.op_Implicit((Object)(object)currentCraftingStation) && !currentCraftingStation.CheckUsable(player, false)) { return list; } worn.Clear(); ((Humanoid)player).GetInventory().GetWornItems(worn); foreach (ItemData item in worn) { RepairFacts val = Facts(item, currentCraftingStation, flag); if (RepairRule.Qualifies(ref val)) { list.Add(item); } } return list; } public static RepairFacts Facts(ItemData item, CraftingStation station, bool noCost) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) Recipe val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetRecipe(item) : null); return new RepairFacts { CanBeRepaired = item.m_shared.m_canBeReparied, NoCost = noCost, Station = (Object.op_Implicit((Object)(object)station) ? station.m_name : null), StationLevel = (Object.op_Implicit((Object)(object)station) ? station.GetLevel(true) : 0), HasRecipe = Object.op_Implicit((Object)(object)val), CraftingStation = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.m_craftingStation)) ? val.m_craftingStation.m_name : null), RepairStation = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.m_repairStation)) ? val.m_repairStation.m_name : null), MinStationLevel = (Object.op_Implicit((Object)(object)val) ? val.m_minStationLevel : 0), ItemWorldLevel = item.m_worldLevel, GameWorldLevel = Game.m_worldLevel }; } internal static bool Pressed(InventoryGui gui) { //IL_0090: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return true; } Player localPlayer = Player.m_localPlayer; CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); List list = Repairable(localPlayer); foreach (ItemData item in list) { ((Character)localPlayer).RaiseSkill((SkillType)107, 1f - item.m_durability / item.GetMaxDurability()); item.m_durability = item.GetMaxDurability(); } if (list.Count > 0 && Object.op_Implicit((Object)(object)currentCraftingStation)) { currentCraftingStation.m_repairItemDoneEffects.Create(((Component)currentCraftingStation).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } ((Character)localPlayer).Message((MessageType)2, (list.Count == 0) ? KindleText.Text("repair_all_none") : ((list.Count == 1) ? KindleText.Text("repair_all_done_one") : KindleText.Format("repair_all_done", list.Count)), 0, (Sprite)null, false); if (gui.m_uiGroups != null && gui.m_uiGroups.Length > 3) { gui.SetActiveGroup(gui.m_uiGroups[3], true); } nextCount = 0f; gui.UpdateRepair(); gui.UpdateCraftingPanel(false); return false; } internal static void StationOpened(CraftingStation station, Humanoid user, bool repeat, bool opened, bool ranOriginal) { if (!opened || !ranOriginal || repeat || !Active || !Object.op_Implicit((Object)(object)station) || !station.m_canRepair) { return; } KindleConfig? settings = Plugin.Settings; if (settings == null || !settings.Get(Repair.OnStationOpen) || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return; } Player val = (Player)(object)((user is Player) ? user : null); if (val != null && !((Character)val).IsDead() && !((Character)val).InCutscene() && !((Character)val).IsTeleporting()) { ZNetView component = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner() && !((Object)(object)val.GetCurrentCraftingStation() != (Object)(object)station) && station.InUseDistance((Humanoid)(object)val) && station.CheckUsable(val, false) && Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible() && Repairable(val).Count != 0) { Pressed(InventoryGui.instance); } } } internal static bool BeforeRepair(InventoryGui gui) { if (!Active || !Object.op_Implicit((Object)(object)gui.m_repairButton)) { return true; } Player localPlayer = Player.m_localPlayer; CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); if ((Object.op_Implicit((Object)(object)currentCraftingStation) ? currentCraftingStation.m_canRepair : localPlayer.NoCostCheat()) || !Object.op_Implicit((Object)(object)gui.m_crafting) || !((Component)gui.m_crafting).gameObject.activeInHierarchy) { return true; } if (Object.op_Implicit((Object)(object)gui.m_repairPanel)) { ((Component)gui.m_repairPanel).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)gui.m_repairPanelSelection)) { ((Component)gui.m_repairPanelSelection).gameObject.SetActive(false); } return false; } internal static void AfterRepair(InventoryGui gui) { if (!Active || !Object.op_Implicit((Object)(object)gui.m_repairButton)) { return; } Player localPlayer = Player.m_localPlayer; if (Time.unscaledTime >= nextCount) { nextCount = Time.unscaledTime + 0.25f; repairable = Repairable(localPlayer).Count; } Button repairButton = gui.m_repairButton; CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); bool flag = localPlayer.NoCostCheat(); bool flag2 = (Object.op_Implicit((Object)(object)currentCraftingStation) ? currentCraftingStation.m_canRepair : flag); bool flag3 = Object.op_Implicit((Object)(object)gui.m_crafting) && ((Component)gui.m_crafting).gameObject.activeInHierarchy; if (!flag2 && flag3 && !((Component)repairButton).gameObject.activeSelf) { ((Component)repairButton).gameObject.SetActive(true); } if (((Component)repairButton).gameObject.activeSelf) { bool active = (((Selectable)repairButton).interactable = flag2 && repairable > 0); if (Object.op_Implicit((Object)(object)gui.m_repairButtonGlow)) { ((Component)gui.m_repairButtonGlow).gameObject.SetActive(active); } int num = (flag2 ? repairable : (-1)); string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English"); long revision = KindleText.Revision; if ((Object)(object)tipOwner != (Object)(object)((Component)repairButton).gameObject || num != tipShown || text != tipLanguage || revision != tipRevision) { string text2 = ((!flag2) ? KindleText.Text("station_needed") : ((repairable == 0) ? KindleText.Text("repair_all_tip_none") : ((repairable == 1) ? KindleText.Text("repair_all_tip_one") : KindleText.Format("repair_all_tip", repairable)))); KitTooltip.Set(((Component)repairButton).gameObject, KindleText.Text("repair_all"), text2); tipOwner = ((Component)repairButton).gameObject; tipShown = num; tipLanguage = text; tipRevision = revision; } } Back(gui); } private static void Back(InventoryGui gui) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) Transform repairPanel = gui.m_repairPanel; RectTransform val = (RectTransform)(object)((repairPanel is RectTransform) ? repairPanel : null); RectTransform val2 = (RectTransform)((Component)gui.m_repairButton).transform; if (!Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy || !((Component)val2).gameObject.activeInHierarchy) { return; } Transform parent = ((Transform)val).parent; RectTransform val3 = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (val3 == null) { return; } Rect rect = val2.rect; if (((Rect)(ref rect)).width < 1f) { return; } rect = val2.rect; if (!(((Rect)(ref rect)).height < 1f)) { rect = val2.rect; float width = ((Rect)(ref rect)).width; rect = val2.rect; ValueTuple valueTuple = StationStack.Backing(width, ((Rect)(ref rect)).height); float item = valueTuple.Item1; float item2 = valueTuple.Item2; rect = val.rect; if (Mathf.Abs(((Rect)(ref rect)).width - item) > 0.01f) { val.SetSizeWithCurrentAnchors((Axis)0, item); } rect = val.rect; if (Mathf.Abs(((Rect)(ref rect)).height - item2) > 0.01f) { val.SetSizeWithCurrentAnchors((Axis)1, item2); } rect = val2.rect; Vector3 val4 = ((Transform)val3).InverseTransformPoint(((Transform)val2).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))); rect = val.rect; Vector2 val5 = Vector2.op_Implicit(val4 - ((Transform)val3).InverseTransformPoint(((Transform)val).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)))); if (((Vector2)(ref val5)).sqrMagnitude > 0.0001f) { val.anchoredPosition += val5; } } } } [HarmonyPatch] internal static class KindleRepairPatches { [HarmonyPatch(typeof(CraftingStation), "Interact")] [HarmonyPrefix] private static void Opening(CraftingStation __instance, Humanoid user, bool repeat, out bool __state) { __state = !repeat && Object.op_Implicit((Object)(object)user) && (Object)(object)user == (Object)(object)Player.m_localPlayer && ((Object)(object)Player.m_localPlayer.GetCurrentCraftingStation() != (Object)(object)__instance || !InventoryGui.IsVisible()); } [HarmonyPatch(typeof(CraftingStation), "Interact")] [HarmonyPostfix] private static void Opened(CraftingStation __instance, Humanoid user, bool repeat, bool __state, bool __runOriginal) { KindleRepair.Guard(delegate { KindleRepair.StationOpened(__instance, user, repeat, __state, __runOriginal); }); } [HarmonyPatch(typeof(InventoryGui), "OnRepairPressed")] [HarmonyPrefix] private static bool Pressed(InventoryGui __instance) { bool run = true; KindleRepair.Guard(delegate { run = KindleRepair.Pressed(__instance); }); return run; } [HarmonyPatch(typeof(InventoryGui), "UpdateRepair")] [HarmonyPrefix] private static bool Repairing(InventoryGui __instance) { try { return KindleRepair.BeforeRepair(__instance); } catch (Exception ex) { KindleSalvage.Warn("Repair all: " + ex.GetType().Name + ": " + ex.Message); return true; } } [HarmonyPatch(typeof(InventoryGui), "UpdateRepair")] [HarmonyPostfix] private static void Updated(InventoryGui __instance) { try { KindleRepair.AfterRepair(__instance); } catch (Exception ex) { KindleSalvage.Warn("Repair all: " + ex.GetType().Name + ": " + ex.Message); } } } public static class KindleSalvage { private readonly struct DrawKey : IEquatable { private readonly ItemData item; private readonly CraftingStation station; private readonly int stack; private readonly int quality; private readonly int changes; private readonly int second; private readonly int generation; public DrawKey(ItemData item, CraftingStation station, int stack, int quality, int changes, int second, int generation) { this.item = item; this.station = station; this.stack = stack; this.quality = quality; this.changes = changes; this.second = second; this.generation = generation; } public bool Equals(DrawKey other) { if (item == other.item && station == other.station && stack == other.stack && quality == other.quality && changes == other.changes && second == other.second) { return generation == other.generation; } return false; } public override bool Equals(object obj) { if (obj is DrawKey other) { return Equals(other); } return false; } public override int GetHashCode() { return HashCode.Combine(stack, quality, changes, second, generation); } } private static bool initialized; private static bool wasActive; private static InventoryGui gui; private static KitGameTab tab; private static KitTileList layout; private static readonly List> rows = new List>(); private static ItemData selected; private static int selectedIndex; private static Action warning; private static Harmony patches; private static bool configurationDirty; private static DrawKey drawn; private static readonly Color BlockedName = new Color(0.6f, 0.6f, 0.6f, 1f); private static int drawGeneration = 1; private static readonly HashSet warned = new HashSet(); private static readonly Dictionary chestOf = new Dictionary(); private const string ChestColour = "#6fc3ff"; private static int favouriteStamp; private static float nextFavouriteCheck; private static int chestStamp; private static float nextChestCheck; public static bool Ready { get { if (initialized && Plugin.GameplayAvailable && Plugin.AllowsUi && SalvageYaml.Ready && Plugin.IsReady && Plugin.Session.WorldId != 0L && (Object)(object)ZNet.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && !((Character)Player.m_localPlayer).IsDead()) { return !((Character)Player.m_localPlayer).IsTeleporting(); } return false; } } public static bool Active { get { if (Ready && SalvageSettings.Enabled.Value && tab != null) { return tab.Selected; } return false; } } public static ItemData Selected => selected; public static IReadOnlyDictionary Files => SalvageYaml.Files; public static void Initialize(ConfigFile config, ProductRegistration registration, Action warn = null) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown Shutdown(); warning = warn; initialized = true; SalvageYaml.Initialize(config, registration); if (Plugin.Settings != null) { Plugin.Settings.Changed += Changed; } if (Plugin.AllowsUi && !Plugin.SteppedAside) { patches = new Harmony("com.meadworks.kindle.salvage"); patches.CreateClassProcessor(typeof(SalvageGuiPatches)).Patch(); } } internal static void Warn(string text) { if (warned.Add(text)) { if (warning != null) { warning(text); } else { Debug.LogWarning((object)("Kindle: " + text)); } } } internal static void Guard(Action action) { try { action(); } catch (Exception ex) { Warn("Salvage UI: " + ex.GetType().Name); } } internal static bool Guard(Func action) { try { return action(); } catch (Exception ex) { Warn("Salvage UI: " + ex.GetType().Name); Deselect(); return true; } } private static void Changed(object sender, EventArgs args) { configurationDirty = true; drawGeneration++; } public static void Reload() { SalvageYaml.Reload(); } private static bool FavouritesChanged() { float unscaledTime = Time.unscaledTime; if (wasActive && unscaledTime < nextFavouriteCheck) { return false; } nextFavouriteCheck = unscaledTime + 0.25f; int num = SalvageInterop.FavouritesStamp(); bool result = wasActive && num != favouriteStamp; favouriteStamp = num; return result; } private static bool ChestsChanged() { float unscaledTime = Time.unscaledTime; if (wasActive && unscaledTime < nextChestCheck) { return false; } nextChestCheck = unscaledTime + 0.5f; int num = SalvageChests.Stamp(); bool result = wasActive && num != chestStamp; chestStamp = num; return result; } public static void Tick() { if (!initialized) { return; } SalvageChests.Tick(); SalvageYaml.Tick(); if (!Plugin.AllowsUi || Plugin.SteppedAside) { return; } Ensure(InventoryGui.instance); if (tab == null || !Object.op_Implicit((Object)(object)tab.Button)) { SalvageTabCapability.Active = false; return; } tab.Refresh(); bool flag = Ready && SalvageSettings.Enabled.Value; ((Component)tab.Button).gameObject.SetActive(flag); TMP_Text componentInChildren = ((Component)tab.Button).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = SalvageWords.Salvage; } if (!flag && tab.Selected) { Leave(); } SalvageTabCapability.Active = Active && InventoryGui.IsVisible(); bool flag2 = SalvageTabCapability.Active && FavouritesChanged(); bool flag3 = SalvageTabCapability.Active && ChestsChanged(); if (SalvageTabCapability.Active && (!wasActive || configurationDirty || flag2 || flag3)) { configurationDirty = false; drawGeneration++; Rebuild(); } wasActive = SalvageTabCapability.Active; } public static void Ensure(InventoryGui instance) { if (initialized && Plugin.AllowsUi && !Plugin.SteppedAside && !((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_tabUpgrade == (Object)null) && (!((Object)(object)gui == (Object)(object)instance) || tab == null || !((Object)(object)tab.Button != (Object)null))) { Clear(); KitTileList obj = layout; if (obj != null) { obj.Forget(); } KitGameTab obj2 = tab; if (obj2 != null) { obj2.Dispose(); } gui = instance; selected = null; selectedIndex = 0; wasActive = false; Transform parent = ((Component)instance.m_tabUpgrade).transform.parent; tab = KitTabs.Append((RectTransform)(object)((parent is RectTransform) ? parent : null), instance.m_tabUpgrade, "Kindle_SalvageTab", SalvageWords.Salvage, (Action)delegate { Select(instance); }); layout = KitTileList.For(instance.m_recipeListRoot, instance.m_recipeListSpace, instance.m_recipeListBaseSize, (KitTileParts)null); } } private static void Select(InventoryGui instance) { if (!Ready || !SalvageSettings.Enabled.Value || (Object)(object)instance != (Object)(object)gui || instance.m_craftTimer >= 0f) { KitGameTab obj = tab; if (obj != null) { obj.Select(false); } return; } instance.OnTabCraftPressed(); tab.Select(true); SalvageTabCapability.Active = true; if (instance.m_uiGroups != null && instance.m_uiGroups.Length > 3) { instance.SetActiveGroup(instance.m_uiGroups[3], true); } ((Selectable)instance.m_tabCraft).interactable = true; ((Selectable)instance.m_tabUpgrade).interactable = true; instance.UpdateCraftingPanel(false); } public static bool AnySalvageable(Player player) { if (Ready && SalvageSettings.Enabled.Value && (Object)(object)player != (Object)null) { return ((Humanoid)player).GetInventory().GetAllItems().Any((ItemData item) => SalvageInterop.ListedCell(player, item) && SalvageActions.CanSalvage(item)); } return false; } public static void Open(InventoryGui instance, ItemData item) { Ensure(instance); if (tab != null && !((Object)(object)instance != (Object)(object)gui)) { if (item != null) { selected = item; } Select(instance); } } public static void Deselect() { KitGameTab obj = tab; if (obj != null) { obj.Select(false); } SalvageTabCapability.Active = false; wasActive = false; Clear(); drawGeneration++; } private static void Leave() { Deselect(); if ((Object)(object)gui != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { gui.OnTabCraftPressed(); } } public static bool BeforeCraftingPanel(InventoryGui instance, bool focusView) { Ensure(instance); if (!Active) { SalvageTabCapability.Active = false; return true; } SalvageTabCapability.Active = true; Player localPlayer = Player.m_localPlayer; CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); bool flag = localPlayer.NoCostCheat() || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)25)); ((Component)instance.m_tabCraft).gameObject.SetActive((Object)(object)currentCraftingStation == (Object)null || currentCraftingStation.m_hasCraftTab); ((Component)instance.m_tabUpgrade).gameObject.SetActive((Object)(object)currentCraftingStation != (Object)null || flag); ((Selectable)instance.m_tabCraft).interactable = true; ((Selectable)instance.m_tabUpgrade).interactable = true; Rebuild(focusView); return false; } public static void Rebuild() { if (Active && (Object)(object)gui != (Object)null) { Rebuild(center: false); } } private static void Rebuild(bool center) { //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_0067: Unknown result type (might be due to invalid IL or missing references) foreach (RecipeDataPair availableRecipe in gui.m_availableRecipes) { RecipeDataPair current = availableRecipe; if ((Object)(object)((RecipeDataPair)(ref current)).InterfaceElement != (Object)null) { Object.Destroy((Object)(object)((RecipeDataPair)(ref current)).InterfaceElement); } } gui.m_availableRecipes.Clear(); gui.m_selectedRecipe = default(RecipeDataPair); Clear(); foreach (ItemData item in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItemsInGridOrder()) { if (SalvageInterop.ListedCell(Player.m_localPlayer, item)) { AddRow(item, SalvageActions.WhyNot(item), null); } } foreach (KeyValuePair item2 in SalvageChests.Items()) { if (!chestOf.ContainsKey(item2.Value)) { AddRow(item2.Value, SalvageRules.Blocker(Player.m_localPlayer, item2.Value, item2.Key.GetInventory()), item2.Key); } } if (layout != null) { layout.View = (KitTileView)0; layout.Arrange((IList)rows.Select, RectTransform>(delegate(KeyValuePair r) { Transform transform = r.Value.transform; return (RectTransform)(object)((transform is RectTransform) ? transform : null); }).ToList()); } int num = rows.FindIndex((KeyValuePair r) => r.Key == selected); Choose((num >= 0) ? num : Mathf.Clamp(selectedIndex, 0, rows.Count - 1), center); } private static void AddRow(ItemData item, string blocked, Container chest) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Expected O, but got Unknown if (item?.m_shared == null || (blocked != null && (blocked == SalvageWords.Off || blocked == SalvageWords.Cannot || blocked == SalvageWords.NoRecipe))) { return; } GameObject val = Object.Instantiate(gui.m_recipeElementPrefab, (Transform)(object)gui.m_recipeListRoot); ((Object)val).name = "Kindle_SalvageRow"; val.SetActive(true); Transform obj = val.transform.Find("icon"); Image val2 = ((obj != null) ? ((Component)obj).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { val2.sprite = item.GetIcon(); ((Graphic)val2).color = Color.white; SalvageRarity.Apply(((Component)val2).gameObject, item); } Transform obj2 = val.transform.Find("name"); TMP_Text val3 = ((obj2 != null) ? ((Component)obj2).GetComponent() : null); if ((Object)(object)val3 != (Object)null) { val3.text = ItemNames.DisplayName(item) + ((item.m_stack > 1) ? (" ×" + item.m_stack) : "") + ChestLabel(chest); ((Graphic)val3).color = ((blocked == null) ? Color.white : BlockedName); } Transform obj3 = val.transform.Find("QualityLevel"); TMP_Text val4 = ((obj3 != null) ? ((Component)obj3).GetComponent() : null); if ((Object)(object)val4 != (Object)null) { ((Component)val4).gameObject.SetActive(item?.m_shared != null && item.m_shared.m_maxQuality > 1); val4.text = item.m_quality.ToString(); } Transform obj4 = val.transform.Find("Durability"); GuiBar val5 = ((obj4 != null) ? ((Component)obj4).GetComponent() : null); if ((Object)(object)val5 != (Object)null) { bool flag = item?.m_shared != null && item.m_shared.m_useDurability && item.m_durability < item.GetMaxDurability(); ((Component)val5).gameObject.SetActive(flag); if (flag) { val5.SetValue(item.GetDurabilityPercentage()); } } Button component = val.GetComponent