Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FuelFromChests v0.2.1
FuelFromChests.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FuelFromChests")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.1.0")] [assembly: AssemblyInformationalVersion("0.2.1")] [assembly: AssemblyProduct("FuelFromChests")] [assembly: AssemblyTitle("FuelFromChests")] [assembly: AssemblyVersion("0.2.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FuelFromChests { internal static class Chests { private static readonly HashSet<Container> All = new HashSet<Container>(); private static readonly FieldRef<Container, ZNetView> ViewField = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview"); private static readonly Func<Container, long, bool> Access = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Container, bool> Load = AccessTools.MethodDelegate<Func<Container, bool>>(AccessTools.Method(typeof(Container), "Load", (Type[])null, (Type[])null), (object)null, true); internal static ZNetView View(Container chest) { return ViewField.Invoke(chest); } internal static void Track(Container chest) { if (!Object.op_Implicit((Object)(object)chest) || !Object.op_Implicit((Object)(object)View(chest)) || !View(chest).IsValid()) { return; } All.RemoveWhere((Container c) => !Object.op_Implicit((Object)(object)c)); All.Add(chest); Ownership.Register(View(chest), delegate(Player player) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (Eligible(chest, player, checkWard: false)) { Vector3 val = ((Component)player).transform.position - ((Component)chest).transform.position; return (double)((Vector3)(ref val)).sqrMagnitude <= Math.Pow(Plugin.Range.Value + player.m_maxInteractDistance + 3f, 2.0); } return false; }); } internal static void Forget(Container chest) { All.Remove(chest); } internal static bool Eligible(Container chest, Player player, bool checkWard = true) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)chest) || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead() || ((Character)player).IsTeleporting()) { return false; } ZNetView val = View(chest); Piece component = ((Component)chest).GetComponent<Piece>(); if (!Object.op_Implicit((Object)(object)val) || !val.IsValid() || !Object.op_Implicit((Object)(object)component) || !component.IsPlacedByPlayer() || Object.op_Implicit((Object)(object)((Component)chest).GetComponent<TombStone>()) || chest.GetInventory() == null || chest.IsInUse() || val.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 0 || (Object.op_Implicit((Object)(object)chest.m_wagon) && chest.m_wagon.InUse()) || val.GetZDO().GetString("seneal.nocraft", "") == "1" || !Access(chest, player.GetPlayerID())) { return false; } if (checkWard && chest.m_checkGuardStone) { return PrivateArea.CheckAccess(((Component)chest).transform.position, 0f, false, false); } return true; } internal static List<Container> Nearby(Station station, Player player) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) All.RemoveWhere((Container c) => !Object.op_Implicit((Object)(object)c)); List<Container> list = new List<Container>(); float num = Plugin.Range.Value * Plugin.Range.Value; foreach (Container item in All) { if (Eligible(item, player)) { Vector3 val = ((Component)item).transform.position - station.Position; if (((Vector3)(ref val)).sqrMagnitude <= num) { list.Add(item); } } } list.Sort(delegate(Container a, Container b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0037: 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_0041: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)a).transform.position - station.Position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; val2 = ((Component)b).transform.position - station.Position; return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude); }); return list; } internal static bool Ready(Container chest, Station station, Player player) { //IL_001d: 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_002d: Unknown result type (might be due to invalid IL or missing references) if (Eligible(chest, player) && View(chest).IsOwner()) { Vector3 val = ((Component)chest).transform.position - station.Position; return ((Vector3)(ref val)).sqrMagnitude <= Plugin.Range.Value * Plugin.Range.Value; } return false; } internal static void Refresh(Container chest) { Load(chest); } } internal sealed class InventoryUnit : IResourceUnit { private static readonly Action<Inventory, bool, bool> Changed = AccessTools.MethodDelegate<Action<Inventory, bool, bool>>(AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null), (object)null, true); private readonly Inventory inventory; private readonly ItemData item; private readonly Func<bool> permitted; private readonly int stack; private readonly int index; private bool attempted; public bool IsDebited { get { if (attempted) { if (stack != 1) { return item.m_stack == stack - 1; } return !inventory.ContainsItem(item); } return false; } } internal InventoryUnit(Inventory source, ItemData resource, Func<bool> canDebit) { inventory = source; item = resource; permitted = canDebit; stack = item.m_stack; index = inventory.GetAllItems().IndexOf(item); } public bool Debit() { if (!permitted() || index < 0 || stack < 1 || item.m_stack != stack || !inventory.ContainsItem(item)) { return false; } attempted = true; return inventory.RemoveItem(item, 1); } public void Refund() { if (IsDebited) { item.m_stack = stack; if (!inventory.ContainsItem(item)) { inventory.GetAllItems().Insert(Math.Min(index, inventory.GetAllItems().Count), item); } attempted = false; Changed(inventory, arg2: false, arg3: false); } } } internal static class HoverHint { internal static string Append(Station station, string original) { //IL_00f7: 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) if (!Object.op_Implicit((Object)(object)Plugin.Instance) || !Plugin.Active.Value || !(station.IsOre ? Plugin.Ore.Value : Plugin.Fuel.Value) || !station.Refillable) { return original; } string text = Plugin.Selected(station); if (text == null) { string text2 = null; foreach (ItemDrop item in station.Inputs()) { if (Transfer.Allowed(((Object)((Component)item).gameObject).name, Plugin.Excluded.Value)) { if (text2 != null) { text2 = null; break; } text2 = ((Object)((Component)item).gameObject).name; } } text = text2; } string text3 = Localization.instance.Localize("$KEY_Use"); return original + "\n<color=#d4b16d>" + Texts.Selected + ": " + station.ResourceName(text) + "</color>\n[<color=yellow><b>" + Texts.Key(Plugin.SelectKey.Value) + " + " + text3 + "</b></color>] " + Texts.ChooseResource + "\n[<color=yellow><b>" + Texts.Key(Plugin.FillKey.Value) + " + " + text3 + "</b></color>] " + Texts.Fill; } } [HarmonyPatch(typeof(Smelter), "OnHoverAddOre")] internal static class SmelterOreHint { private static void Postfix(Smelter __instance, ref string __result) { __result = HoverHint.Append(new Station((Component)(object)__instance, isOre: true), __result); } } [HarmonyPatch(typeof(Smelter), "OnHoverAddFuel")] internal static class SmelterFuelHint { private static void Postfix(Smelter __instance, ref string __result) { __result = HoverHint.Append(new Station((Component)(object)__instance), __result); } } [HarmonyPatch(typeof(CookingStation), "OnHoverFuelSwitch")] internal static class CookingFuelHint { private static void Postfix(CookingStation __instance, ref string __result) { __result = HoverHint.Append(new Station((Component)(object)__instance), __result); } } [HarmonyPatch(typeof(Fireplace), "GetHoverText")] internal static class FireplaceHint { private static void Postfix(Fireplace __instance, ref string __result) { __result = HoverHint.Append(new Station((Component)(object)__instance), __result); } } [HarmonyPatch(typeof(Player), "TakeInput")] internal static class PlayerPickerInput { private static bool Prefix(ref bool __result) { if (!Plugin.BlockInput) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] internal static class ControllerPickerInput { private static bool Prefix(ref bool __result) { if (!Plugin.BlockInput) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] internal static class PickerCursor { private static bool Prefix() { if (!Plugin.BlockInput) { return true; } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); return false; } } [HarmonyPatch(typeof(Menu), "Update")] internal static class PickerEscape { private static bool Prefix() { if (!Plugin.BlockInput || (Object.op_Implicit((Object)(object)Game.instance) && Game.instance.IsShuttingDown())) { return true; } if (!ZInput.GetKeyDown((KeyCode)27, true) && (!ZInput.GetButtonDown("JoyMenu") || (ZInput.GetButton("JoyLTrigger") && ZInput.GetButton("JoyLBumper")) || ZInput.GetButton("JoyAltKeys"))) { return true; } ResourcePicker.Close(); return false; } } [HarmonyPatch(typeof(Chat), "Update")] internal static class PickerChat { private static bool Prefix() { if (Plugin.BlockInput) { return !ZInput.GetButtonDown("Chat"); } return true; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class PickerScroll { private static float FilterScroll(float value) { if (!Plugin.BlockInput) { return value; } return 0f; } [HarmonyAfter(new string[] { "com.jubaroo.smarterhoe" })] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo native = AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", Type.EmptyTypes, (Type[])null); MethodInfo filter = AccessTools.Method(typeof(PickerScroll), "FilterScroll", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { yield return instruction; if (CodeInstructionExtensions.Calls(instruction, native) || IsSmarterHoeReader(instruction)) { yield return new CodeInstruction(OpCodes.Call, (object)filter); } } } private static bool IsSmarterHoeReader(CodeInstruction instruction) { MethodInfo methodInfo = instruction.operand as MethodInfo; if (instruction.opcode == OpCodes.Call && methodInfo != null && methodInfo.IsStatic && methodInfo.DeclaringType?.FullName == "SmarterHoe.Plugin" && methodInfo.Name == "GetCameraScrollWheel" && methodInfo.ReturnType == typeof(float)) { return methodInfo.GetParameters().Length == 0; } return false; } } internal static class Ownership { private sealed class State { internal readonly List<Func<Player, bool>> Permissions = new List<Func<Player, bool>>(); internal Pending Request; internal bool Held; internal float ProtectedUntil; } private sealed class Pending { internal int Token; internal long Owner; internal bool Answered; internal bool Granted; } private sealed class Lease : IDisposable { private State state; internal Lease(State state) { this.state = state; } public void Dispose() { if (state != null) { state.Held = false; state.ProtectedUntil = 0f; state = null; } } } private const string RequestRpc = "FuelFromChests_RequestOwnership_v1"; private const string ReplyRpc = "FuelFromChests_ReplyOwnership_v1"; private const float TimeoutSeconds = 2f; private static readonly ConditionalWeakTable<ZNetView, State> States = new ConditionalWeakTable<ZNetView, State>(); private static int nextToken; internal static void Register(ZNetView view, Func<Player, bool> canGrant) { if (!Valid(view) || canGrant == null) { return; } if (States.TryGetValue(view, out var value)) { if (!value.Permissions.Contains(canGrant)) { value.Permissions.Add(canGrant); } return; } State state = new State(); state.Permissions.Add(canGrant); view.Register<long, int>("FuelFromChests_RequestOwnership_v1", (Action<long, long, int>)delegate(long sender, long playerId, int token) { OnRequest(view, state, sender, playerId, token); }); view.Register<int, bool>("FuelFromChests_ReplyOwnership_v1", (Action<long, int, bool>)delegate(long sender, int token, bool granted) { OnReply(state, sender, token, granted); }); States.Add(view, state); } internal static IEnumerator Acquire(ZNetView view, Player player, Action<bool> completed) { if (!Valid(view) || !States.TryGetValue(view, out var state) || state.Held || state.Request != null || !ValidPlayer(player, ZDOMan.GetSessionID()) || !Allowed(state, player)) { completed?.Invoke(obj: false); yield break; } if (view.IsOwner()) { state.ProtectedUntil = Time.realtimeSinceStartup + 2f; completed?.Invoke(obj: true); yield break; } long owner = view.GetZDO().GetOwner(); if (owner == 0L) { completed?.Invoke(obj: false); yield break; } int num = Interlocked.Increment(ref nextToken); if (num == 0) { num = Interlocked.Increment(ref nextToken); } Pending request = new Pending { Token = num, Owner = owner }; Pending request2 = (state.Request = request); bool acquired = false; float deadline = Time.realtimeSinceStartup + 2f; try { if (SendRequest(view, owner, player.GetPlayerID(), num)) { while (Time.realtimeSinceStartup < deadline && Valid(view)) { if (request2.Answered) { if (!request2.Granted) { break; } if (view.IsOwner()) { acquired = ValidPlayer(player, ZDOMan.GetSessionID()) && Allowed(state, player); break; } } yield return null; } } } finally { if (state.Request == request2) { state.Request = null; } if (acquired) { state.ProtectedUntil = Time.realtimeSinceStartup + 2f; } } completed?.Invoke(acquired); } internal static IDisposable Hold(ZNetView view) { if (!Valid(view) || !view.IsOwner() || !States.TryGetValue(view, out var value) || value.Held || value.Request != null) { throw new InvalidOperationException("Cannot reserve an unowned or busy FuelFromChests view."); } value.Held = true; return new Lease(value); } private static bool Valid(ZNetView view) { if (Object.op_Implicit((Object)(object)view)) { return view.IsValid(); } return false; } private static bool ValidPlayer(Player player, long sender) { if (!Object.op_Implicit((Object)(object)player) || sender == 0L || player.GetPlayerID() == 0L) { return false; } ZNetView component = ((Component)player).GetComponent<ZNetView>(); if (Valid(component)) { return component.GetZDO().GetOwner() == sender; } return false; } private static bool Allowed(State state, Player player) { try { foreach (Func<Player, bool> permission in state.Permissions) { if (!permission(player)) { return false; } } return state.Permissions.Count != 0; } catch { return false; } } private static bool SendRequest(ZNetView view, long owner, long playerId, int token) { try { view.InvokeRPC(owner, "FuelFromChests_RequestOwnership_v1", new object[2] { playerId, token }); return true; } catch { return false; } } private static void OnRequest(ZNetView view, State state, long sender, long playerId, int token) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!Valid(view) || !view.IsOwner() || sender == 0L || token == 0) { return; } bool flag = false; try { Player player = Player.GetPlayer(playerId); if (!state.Held && state.Request == null && Time.realtimeSinceStartup >= state.ProtectedUntil && Object.op_Implicit((Object)(object)player) && player.GetPlayerID() == playerId && ValidPlayer(player, sender) && Allowed(state, player)) { ZDO zDO = view.GetZDO(); ZDOMan.instance.ForceSendZDO(sender, zDO.m_uid); zDO.SetOwner(sender); flag = true; } } catch { flag = false; } try { if (Valid(view)) { view.InvokeRPC(sender, "FuelFromChests_ReplyOwnership_v1", new object[2] { token, flag }); } } catch { } } private static void OnReply(State state, long sender, int token, bool granted) { Pending request = state.Request; if (request != null && !request.Answered && request.Token == token && request.Owner == sender) { request.Granted = granted; request.Answered = true; } } } [BepInPlugin("com.valheim.fuelfromchests", "Fuel From Chests", "0.2.1")] [BepInIncompatibility("aedenthorn.CraftFromContainers")] public sealed class Plugin : BaseUnityPlugin { private sealed class ConfigDisplay { public bool Browsable; } public const string Guid = "com.valheim.fuelfromchests"; public const string Name = "Fuel From Chests"; public const string Version = "0.2.1"; internal static Plugin Instance; internal static ConfigEntry<bool> Active; internal static ConfigEntry<bool> Fuel; internal static ConfigEntry<bool> Ore; internal static ConfigEntry<float> Range; internal static ConfigEntry<string> Excluded; internal static ConfigEntry<KeyCode> FillKey; internal static ConfigEntry<KeyCode> SelectKey; private ConfigEntry<string> savedSelections; private SelectionMemory selections; private Station pickerStation; private float blockInputUntil; private bool pickerWasOpen; private Harmony harmony; private bool busy; private float lastStart; internal static bool BlockInput { get { if (!ResourcePicker.BlocksInput) { if (Object.op_Implicit((Object)(object)Instance)) { return Time.unscaledTime < Instance.blockInputUntil; } return false; } return true; } } internal static bool IsBusy { get { if (Object.op_Implicit((Object)(object)Instance)) { return Instance.busy; } return false; } } private void Awake() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown Instance = this; Active = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable fuel and ore pulling. Crafting and building are not changed."); Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 32f, new ConfigDescription("Chest search radius in metres, measured from the station.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); Fuel = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PullFuel", true, "Pull fuel into fireplaces, smelters and cooking station fuel inputs."); Ore = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PullOre", true, "Pull smelter inputs, including ordinary wood for charcoal kilns."); Excluded = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExcludedPrefabs", "FineWood,RoundLog", "Comma-separated prefab names never selected by this mod. FineWood and RoundLog protect fine/core wood from kilns."); FillKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "FillAllKey", (KeyCode)304, "Hold while interacting to fill available capacity."); SelectKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SelectKey", (KeyCode)308, "Hold while interacting to choose the resource. Mouse or arrow keys + Enter select; Escape cancels."); savedSelections = ((BaseUnityPlugin)this).Config.Bind<string>("Selections", "RememberedResources", "", new ConfigDescription("Saved resource choices by station type and input. Managed by the in-game picker.", (AcceptableValueBase)null, new object[1] { new ConfigDisplay { Browsable = false } })); selections = new SelectionMemory(savedSelections.Value); try { harmony = new Harmony("com.valheim.fuelfromchests"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Fuel From Chests active. Standalone station feeding; no crafting/building hooks or mod dependencies."); } catch (Exception ex) { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ((Behaviour)this).enabled = false; ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } internal static void Report(Exception error) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogError((object)error); } } internal static bool KeyHeld(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if (ZInput.GetKey(key, false)) { return true; } if ((int)key != 308 || !ZInput.GetKey((KeyCode)307, false)) { if ((int)key == 304) { return ZInput.GetKey((KeyCode)303, false); } return false; } return true; } private void Update() { if (ResourcePicker.IsOpen && (!Active.Value || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || pickerStation == null || !pickerStation.Near(Player.m_localPlayer) || InventoryGui.IsVisible() || Menu.IsVisible() || Console.IsVisible() || TextInput.IsVisible() || StoreGui.IsVisible() || (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()))) { ResourcePicker.Close(); } ResourcePicker.Tick(); if (pickerWasOpen && !ResourcePicker.IsOpen) { blockInputUntil = Time.unscaledTime + 0.2f; } pickerWasOpen = ResourcePicker.IsOpen; } private void SaveChoice(Station station, string resource) { selections.Set(station.SelectionKey, resource); savedSelections.Value = selections.Serialize(); } internal static string Selected(Station station) { return Instance?.selections?.Get(station.SelectionKey); } private string ResolveChoice(Station station, Player player) { string text = Selected(station); if (text != null) { return text; } List<PickerOption> options = station.Options(player); List<string> list = new List<string>(); foreach (PickerOption item in options) { list.Add(item.Id); } text = selections.Resolve(station.SelectionKey, list, (string id) => options.Exists((PickerOption option) => option.Id == id && option.Count > 0)); if (text != null) { SaveChoice(station, text); } return text; } private void OpenPicker(Station station, Player player) { List<PickerOption> list = station.Options(player); if (list.Count == 0) { ((Character)player).Message((MessageType)2, Texts.EmptyOptions, 0, (Sprite)null, false); return; } pickerStation = station; ResourcePicker.Show(station.Name, list, Selected(station), delegate(string choice) { blockInputUntil = Time.unscaledTime + 0.2f; if (station.Valid && station.Near(player) && Transfer.Allowed(choice, Excluded.Value)) { SaveChoice(station, choice); } }); pickerWasOpen = ResourcePicker.IsOpen; } internal static void RegisterStation(Component component) { Station station = new Station(component); if (station.Valid) { Ownership.Register(station.View, (Player player) => station.Near(player, checkWard: false)); } } internal static bool Begin(Station station, Humanoid user, ItemData explicitItem = null) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Instance; Player val = (Player)(object)((user is Player) ? user : null); if (!Object.op_Implicit((Object)(object)instance) || !((Behaviour)instance).enabled || (Object)(object)val != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)val)) { return false; } if (instance.busy || BlockInput) { return true; } if (!Active.Value || explicitItem != null || !(station.IsOre ? Ore.Value : Fuel.Value) || !station.Refillable || !station.Near(val)) { return false; } if (KeyHeld(SelectKey.Value)) { instance.OpenPicker(station, val); return true; } if (Time.unscaledTime - instance.lastStart < 0.15f) { return true; } if (station.Space == 0) { return false; } bool bulk = KeyHeld(FillKey.Value); string text = instance.ResolveChoice(station, val); if (text == null) { ((Character)val).Message((MessageType)2, Texts.EmptyOptions, 0, (Sprite)null, false); return true; } instance.busy = true; instance.lastStart = Time.unscaledTime; ((MonoBehaviour)instance).StartCoroutine(instance.Guard(instance.Fill(station, val, bulk, text))); return true; } private IEnumerator Guard(IEnumerator work) { try { while (true) { bool flag = false; object obj = null; try { flag = work.MoveNext(); if (flag) { obj = work.Current; } } catch (Exception error) { Report(error); } if (flag) { yield return obj; continue; } break; } } finally { Plugin plugin = this; (work as IDisposable)?.Dispose(); plugin.busy = false; } } private IEnumerator Fill(Station station, Player player, bool bulk, string selected) { bool owned = false; IEnumerator acquire = Ownership.Acquire(station.View, player, delegate(bool value) { owned = value; }); try { while (acquire.MoveNext()) { yield return acquire.Current; } } finally { IDisposable disposable = acquire as IDisposable; if (disposable != null) { disposable.Dispose(); } } if (!owned || !station.Near(player)) { if (Object.op_Implicit((Object)(object)player)) { ((Character)player).Message((MessageType)2, "Station unavailable. Fuel From Chests must be installed on all peers.", 0, (Sprite)null, false); } yield break; } int added = 0; int wanted = (bulk ? station.Space : Math.Min(1, station.Space)); using (Ownership.Hold(station.View)) { added += Feed(station, player, ((Humanoid)player).GetInventory(), wanted, selected, () => station.Near(player)); float deadline = Time.realtimeSinceStartup + 8f; foreach (Container chest in Chests.Nearby(station, player)) { if (added >= wanted || !station.Valid || !station.View.IsOwner() || !station.Near(player) || station.Space == 0 || Time.realtimeSinceStartup > deadline) { break; } Chests.Refresh(chest); if (station.Find(chest.GetInventory(), selected) == null) { continue; } bool chestOwned = false; { acquire = Ownership.Acquire(Chests.View(chest), player, delegate(bool value) { chestOwned = value; }); try { while (acquire.MoveNext()) { yield return acquire.Current; } } finally { IDisposable disposable2 = acquire as IDisposable; if (disposable2 != null) { disposable2.Dispose(); } } } if (!chestOwned || !station.Near(player) || !station.View.IsOwner() || !Chests.Ready(chest, station, player)) { continue; } using (Ownership.Hold(Chests.View(chest))) { Chests.Refresh(chest); added += Feed(station, player, chest.GetInventory(), wanted - added, selected, () => Chests.Ready(chest, station, player)); } } } if (Object.op_Implicit((Object)(object)player)) { ((Character)player).Message((MessageType)2, (added > 0) ? ("$msg_added " + station.ResourceName(selected) + " × " + added) : Texts.NoneAvailable, 0, (Sprite)null, false); } } private static int Feed(Station station, Player player, Inventory inventory, int budget, string selected, Func<bool> sourceReady) { int i; for (i = 0; i < budget; i++) { if (!Active.Value) { break; } if (!station.Valid) { break; } if (!station.View.IsOwner()) { break; } if (!station.Near(player)) { break; } if (station.Space <= 0) { break; } if (!sourceReady()) { break; } ItemData item = station.Find(inventory, selected); if (item == null || Transfer.One(new InventoryUnit(inventory, item, () => station.View.IsOwner() && station.Near(player) && sourceReady()), () => station.Add(item, player, selected)) != TransferResult.Added) { break; } } return i; } private void OnDestroy() { ((MonoBehaviour)this).StopAllCoroutines(); ResourcePicker.Destroy(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } [HarmonyPatch(typeof(Container), "Awake")] internal static class ChestAwake { private static void Postfix(Container __instance) { Chests.Track(__instance); } } [HarmonyPatch(typeof(Container), "OnDestroyed")] internal static class ChestDestroyed { private static void Postfix(Container __instance) { Chests.Forget(__instance); } } [HarmonyPatch(typeof(Smelter), "Awake")] internal static class SmelterAwake { private static void Postfix(Smelter __instance) { Plugin.RegisterStation((Component)(object)__instance); } } [HarmonyPatch(typeof(Fireplace), "Awake")] internal static class FireplaceAwake { private static void Postfix(Fireplace __instance) { Plugin.RegisterStation((Component)(object)__instance); } } [HarmonyPatch(typeof(CookingStation), "Awake")] internal static class CookingAwake { private static void Postfix(CookingStation __instance) { Plugin.RegisterStation((Component)(object)__instance); } } [HarmonyPatch(typeof(Smelter), "OnAddFuel")] internal static class SmelterFuel { private static bool Prefix(Smelter __instance, Humanoid user, ItemData item, ref bool __result) { if (!Plugin.Begin(new Station((Component)(object)__instance), user, item)) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(Smelter), "OnAddOre")] internal static class SmelterOre { private static bool Prefix(Smelter __instance, Humanoid user, ItemData item, ref bool __result) { if (!Plugin.Begin(new Station((Component)(object)__instance, isOre: true), user, item)) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(CookingStation), "OnAddFuelSwitch")] internal static class CookingFuel { private static bool Prefix(CookingStation __instance, Humanoid user, ItemData item, ref bool __result) { if (!Plugin.Begin(new Station((Component)(object)__instance), user, item)) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(Fireplace), "Interact")] internal static class FireplaceFuel { private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, bool alt, ref bool __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) Station station = new Station((Component)(object)__instance); if (hold && Plugin.IsBusy) { __result = false; return false; } bool flag = Plugin.SelectKey != null && Plugin.KeyHeld(Plugin.SelectKey.Value); if (hold || !station.Valid || (__instance.m_canTurnOff && !alt && !flag && station.Current > 0f) || !Plugin.Begin(station, user)) { return true; } __result = true; return false; } } internal sealed class PickerOption { internal readonly string Id; internal readonly string Label; internal readonly Sprite Icon; internal readonly int Count; internal readonly bool Enabled; internal PickerOption(string id, string label, Sprite icon, int count, bool enabled = true) { Id = id ?? string.Empty; Label = label ?? string.Empty; Icon = icon; Count = Math.Max(0, count); Enabled = enabled; } } internal static class ResourcePicker { private sealed class Row { internal readonly Image Background; internal readonly Outline Outline; internal readonly Image Icon; internal readonly TextMeshProUGUI Label; internal readonly TextMeshProUGUI Count; internal Row(Image background, Outline outline, Image icon, TextMeshProUGUI label, TextMeshProUGUI count) { Background = background; Outline = outline; Icon = icon; Label = label; Count = count; } } private sealed class RowPointer : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, IPointerClickHandler { internal int Index; public void OnPointerEnter(PointerEventData eventData) { Hover(Index, value: true); } public void OnPointerExit(PointerEventData eventData) { Hover(Index, value: false); } public void OnPointerClick(PointerEventData eventData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) Click(Index, eventData.button); } } private sealed class BackdropPointer : MonoBehaviour, IPointerClickHandler, IEventSystemHandler { public void OnPointerClick(PointerEventData eventData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)eventData.button == 0) { Close(); } } } private const float PanelWidth = 440f; private const float PanelPadding = 14f; private const float HeaderHeight = 44f; private const float RowHeight = 44f; private const float RowPitch = 48f; private const float FooterHeight = 26f; private const int MaxVisibleRows = 9; private static readonly Color PanelColor = Rgba(29, 24, 21, 0.92f); private static readonly Color PanelBorder = Rgba(214, 178, 110, 0.32f); private static readonly Color RowColor = Rgba(14, 11, 9, 0.55f); private static readonly Color HoverColor = Rgba(217, 183, 109, 0.07f); private static readonly Color SelectedColor = Rgba(217, 183, 109, 0.14f); private static readonly Color DisabledColor = Rgba(14, 11, 9, 0.28f); private static readonly Color Brass = Rgba(217, 183, 109, 1f); private static readonly Color BrassHalf = Rgba(217, 183, 109, 0.5f); private static readonly Color Parchment = Rgba(239, 229, 211, 1f); private static readonly Color Ash = Rgba(169, 160, 134, 1f); private static readonly List<PickerOption> Options = new List<PickerOption>(); private static readonly List<Row> Rows = new List<Row>(); private static GameObject canvasObject; private static RectTransform panel; private static RectTransform viewport; private static RectTransform content; private static RectTransform canvasBounds; private static ScrollRect scroll; private static TMP_FontAsset bodyFont; private static TMP_FontAsset titleFont; private static Action<string> onSelect; private static int selectedIndex = -1; private static int hoveredIndex = -1; private static float blockUntil; private static bool waitForUseRelease; internal static bool IsOpen { get { if (Object.op_Implicit((Object)(object)canvasObject)) { return canvasObject.activeSelf; } return false; } } internal static bool BlocksInput { get { if (!IsOpen && !waitForUseRelease) { return Time.unscaledTime < blockUntil; } return true; } } internal static void Show(string title, IReadOnlyList<PickerOption> choices, string selected, Action<string> selectedCallback) { Close(); Options.Clear(); if (choices != null) { for (int i = 0; i < choices.Count; i++) { PickerOption pickerOption = choices[i]; if (pickerOption != null) { Options.Add(pickerOption); } } } selectedIndex = FindEnabled(selected); if (selectedIndex < 0) { selectedIndex = FindNextEnabled(-1, 1); } onSelect = selectedCallback; if (Application.isBatchMode || !Object.op_Implicit((Object)(object)Hud.instance) || !Object.op_Implicit((Object)(object)Hud.instance.m_rootObject)) { onSelect = null; return; } try { Build(title ?? string.Empty); ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); RefreshRows(); EnsureSelectedVisible(); } catch (Exception error) { Plugin.Report(error); Destroy(); } } internal static void Close() { if (IsOpen || Object.op_Implicit((Object)(object)canvasObject) || onSelect != null) { if (ZInput.instance != null) { waitForUseRelease |= ZInput.GetButton("Use") || ZInput.GetButton("JoyUse"); ZInput.ResetButtonStatus("Use"); ZInput.ResetButtonStatus("JoyUse"); } blockUntil = Mathf.Max(blockUntil, Time.unscaledTime + 0.2f); } onSelect = null; Options.Clear(); selectedIndex = -1; hoveredIndex = -1; DestroyUi(); } internal static void Tick() { if (waitForUseRelease && !ZInput.GetButton("Use") && !ZInput.GetButton("JoyUse")) { waitForUseRelease = false; } if (!IsOpen) { return; } if (!Object.op_Implicit((Object)(object)panel) || !Object.op_Implicit((Object)(object)viewport) || !Object.op_Implicit((Object)(object)content)) { Close(); return; } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); ClampPanel(); if (ZInput.GetKeyDown((KeyCode)27, false)) { Close(); } else if (ZInput.GetKeyDown((KeyCode)273, false)) { Move(-1); } else if (ZInput.GetKeyDown((KeyCode)274, false)) { Move(1); } else if (ZInput.GetKeyDown((KeyCode)13, false) || ZInput.GetKeyDown((KeyCode)271, false)) { Confirm(); } } internal static void Destroy() { Close(); bodyFont = null; titleFont = null; } private static void Build(string title) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_00cb: 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_015d: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: 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) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0561: Unknown result type (might be due to invalid IL or missing references) Rows.Clear(); ResolveFonts(); canvasObject = new GameObject("FuelFromChests.ResourcePicker", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); ((Object)canvasObject).hideFlags = (HideFlags)61; canvasObject.transform.SetParent(Hud.instance.m_rootObject.transform, false); Stretch(canvasObject.GetComponent<RectTransform>()); Canvas component = canvasObject.GetComponent<Canvas>(); Canvas componentInParent = Hud.instance.m_rootObject.GetComponentInParent<Canvas>(); canvasBounds = (RectTransform)((!Object.op_Implicit((Object)(object)componentInParent)) ? ((object)canvasObject.GetComponent<RectTransform>()) : ((object)(RectTransform)((Component)componentInParent.rootCanvas).transform)); component.renderMode = (RenderMode)0; component.overrideSorting = true; component.sortingOrder = ((!Object.op_Implicit((Object)(object)componentInParent)) ? 1 : (componentInParent.rootCanvas.sortingOrder + 1)); CanvasScaler component2 = canvasObject.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.screenMatchMode = (ScreenMatchMode)0; component2.matchWidthOrHeight = 0.5f; RectTransform obj = Rect(canvasObject.transform, "Blocker"); Stretch(obj); Image obj2 = ((Component)obj).gameObject.AddComponent<Image>(); ((Graphic)obj2).color = Color.clear; ((Graphic)obj2).raycastTarget = true; ((Component)obj).gameObject.AddComponent<BackdropPointer>(); int num = Math.Min(9, Math.Max(1, Options.Count)); float num2 = (float)num * 48f - 4f; float num3 = 58f + num2 + 8f + 26f + 14f; panel = Rect(canvasObject.transform, "Panel"); RectTransform obj3 = panel; RectTransform obj4 = panel; RectTransform obj5 = panel; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); obj5.pivot = val; Vector2 anchorMin = (obj4.anchorMax = val); obj3.anchorMin = anchorMin; panel.anchoredPosition = Vector2.zero; panel.sizeDelta = new Vector2(440f, num3); Image obj6 = ((Component)panel).gameObject.AddComponent<Image>(); ((Graphic)obj6).color = PanelColor; ((Graphic)obj6).raycastTarget = true; AddOutline(((Component)panel).gameObject, PanelBorder, 1f); RectTransform obj7 = Rect((Transform)(object)panel, "InnerBorder"); obj7.anchorMin = Vector2.zero; obj7.anchorMax = Vector2.one; obj7.offsetMin = new Vector2(5f, 5f); obj7.offsetMax = new Vector2(-5f, -5f); Image obj8 = ((Component)obj7).gameObject.AddComponent<Image>(); ((Graphic)obj8).color = Color.clear; ((Graphic)obj8).raycastTarget = false; AddOutline(((Component)obj7).gameObject, Rgba(214, 178, 110, 0.12f), 1f); RectTransform obj9 = TopRect((Transform)(object)panel, "Header", 14f, 14f, 412f, 44f); TextMeshProUGUI obj10 = Text((Transform)(object)obj9, "Title", 22f, Parchment, (TextAlignmentOptions)514, (FontStyles)32, titleFont); ((TMP_Text)obj10).text = title; ((TMP_Text)obj10).margin = new Vector4(32f, 0f, 32f, 0f); AddRule(obj9, "RuleLeft", left: true); AddRule(obj9, "RuleRight", left: false); float num4 = 58f; viewport = TopRect((Transform)(object)panel, "Viewport", 14f, num4, 412f, num2); ((Component)viewport).gameObject.AddComponent<RectMask2D>(); Image obj11 = ((Component)viewport).gameObject.AddComponent<Image>(); ((Graphic)obj11).color = Color.clear; ((Graphic)obj11).raycastTarget = true; content = Rect((Transform)(object)viewport, "Content"); content.anchorMin = new Vector2(0f, 1f); content.anchorMax = new Vector2(1f, 1f); content.pivot = new Vector2(0.5f, 1f); content.anchoredPosition = Vector2.zero; content.sizeDelta = new Vector2(0f, Math.Max(num2, (float)Options.Count * 48f - 4f)); scroll = ((Component)viewport).gameObject.AddComponent<ScrollRect>(); scroll.content = content; scroll.viewport = viewport; scroll.horizontal = false; scroll.vertical = Options.Count > num; scroll.movementType = (MovementType)2; scroll.inertia = true; scroll.decelerationRate = 0.12f; scroll.scrollSensitivity = 28f; if (Options.Count == 0) { BuildEmptyRow(); } else { for (int i = 0; i < Options.Count; i++) { BuildRow(i); } } float y = num4 + num2 + 8f; TextMeshProUGUI obj12 = Text((Transform)(object)TopRect((Transform)(object)panel, "Footer", 14f, y, 412f, 26f), "Hint", 12f, Ash, (TextAlignmentOptions)514, (FontStyles)0); ((TMP_Text)obj12).text = Texts.PickerHelp; ((TMP_Text)obj12).characterSpacing = 0.5f; Canvas.ForceUpdateCanvases(); ClampPanel(); } private static void BuildRow(int index) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) PickerOption pickerOption = Options[index]; RectTransform obj = TopRect((Transform)(object)content, "Option." + index, 0f, (float)index * 48f, 0f, 44f); obj.anchorMin = new Vector2(0f, 1f); obj.anchorMax = new Vector2(1f, 1f); obj.sizeDelta = new Vector2(0f, 44f); Image val = ((Component)obj).gameObject.AddComponent<Image>(); ((Graphic)val).color = RowColor; ((Graphic)val).raycastTarget = true; Outline outline = AddOutline(((Component)obj).gameObject, Rgba(214, 178, 110, 0.14f), 1f); ((Component)obj).gameObject.AddComponent<RowPointer>().Index = index; RectTransform val2 = LeftRect((Transform)(object)obj, "IconSlot", 7f, 5f, 34f, 34f); Image obj2 = ((Component)val2).gameObject.AddComponent<Image>(); ((Graphic)obj2).color = Rgba(64, 51, 40, pickerOption.Enabled ? 0.62f : 0.3f); ((Graphic)obj2).raycastTarget = false; AddOutline(((Component)val2).gameObject, Rgba(214, 178, 110, pickerOption.Enabled ? 0.3f : 0.12f), 1f); Image val3 = null; if (Object.op_Implicit((Object)(object)pickerOption.Icon)) { RectTransform obj3 = Rect((Transform)(object)val2, "Icon"); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.offsetMin = new Vector2(4f, 4f); obj3.offsetMax = new Vector2(-4f, -4f); val3 = ((Component)obj3).gameObject.AddComponent<Image>(); val3.sprite = pickerOption.Icon; val3.preserveAspect = true; ((Graphic)val3).raycastTarget = false; ((Graphic)val3).color = (Color)(pickerOption.Enabled ? Color.white : new Color(1f, 1f, 1f, 0.38f)); } TextMeshProUGUI val4 = Text((Transform)(object)LeftRect((Transform)(object)obj, "Label", 52f, 0f, 270f, 44f), "Text", 17f, pickerOption.Enabled ? Parchment : Ash, (TextAlignmentOptions)4097, (FontStyles)0); ((TMP_Text)val4).text = pickerOption.Label; ((TMP_Text)val4).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val4).overflowMode = (TextOverflowModes)1; TextMeshProUGUI val5 = Text((Transform)(object)RightRect((Transform)(object)obj, "Count", 9f, 0f, 66f, 44f), "Text", 15f, pickerOption.Enabled ? Brass : Ash, (TextAlignmentOptions)4100, (FontStyles)0); ((TMP_Text)val5).text = "x" + pickerOption.Count; Rows.Add(new Row(val, outline, val3, val4, val5)); } private static void BuildEmptyRow() { //IL_002e: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = TopRect((Transform)(object)content, "Empty", 0f, 0f, 0f, 44f); obj.anchorMin = new Vector2(0f, 1f); obj.anchorMax = new Vector2(1f, 1f); obj.sizeDelta = new Vector2(0f, 44f); ((TMP_Text)Text((Transform)(object)obj, "Text", 16f, Ash, (TextAlignmentOptions)514, (FontStyles)2)).text = Texts.EmptyOptions; } private static void Move(int direction) { int num = FindNextEnabled(selectedIndex, direction); if (num >= 0 && num != selectedIndex) { selectedIndex = num; RefreshRows(); EnsureSelectedVisible(); } } private static int FindEnabled(string id) { if (string.IsNullOrEmpty(id)) { return -1; } for (int i = 0; i < Options.Count; i++) { if (Options[i].Enabled && string.Equals(Options[i].Id, id, StringComparison.Ordinal)) { return i; } } return -1; } private static int FindNextEnabled(int from, int direction) { if (Options.Count == 0) { return -1; } int num = from; for (int i = 0; i < Options.Count; i++) { num = (num + direction + Options.Count) % Options.Count; if (Options[num].Enabled) { return num; } } return -1; } private static void Confirm() { if (selectedIndex < 0 || selectedIndex >= Options.Count || !Options[selectedIndex].Enabled) { return; } string id = Options[selectedIndex].Id; Action<string> action = onSelect; Close(); try { action?.Invoke(id); } catch (Exception error) { Plugin.Report(error); } } private static void Hover(int index, bool value) { if (index >= 0 && index < Options.Count && Options[index].Enabled) { hoveredIndex = (value ? index : ((hoveredIndex == index) ? (-1) : hoveredIndex)); RefreshRows(); } } private static void Click(int index, InputButton button) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)button == 0 && index >= 0 && index < Options.Count && Options[index].Enabled) { selectedIndex = index; Confirm(); } } private static void RefreshRows() { //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) //IL_00c3: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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) //IL_00db: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < Rows.Count && i < Options.Count; i++) { PickerOption pickerOption = Options[i]; Row row = Rows[i]; bool flag = i == selectedIndex; bool flag2 = i == hoveredIndex; ((Graphic)row.Background).color = ((!pickerOption.Enabled) ? DisabledColor : (flag ? SelectedColor : (flag2 ? HoverColor : RowColor))); ((Shadow)row.Outline).effectColor = ((!pickerOption.Enabled) ? Rgba(214, 178, 110, 0.08f) : (flag ? BrassHalf : (flag2 ? Rgba(217, 183, 109, 0.2f) : Rgba(214, 178, 110, 0.14f)))); ((Graphic)row.Label).color = (pickerOption.Enabled ? Parchment : Ash); ((Graphic)row.Count).color = (Color)(pickerOption.Enabled ? Brass : new Color(Ash.r, Ash.g, Ash.b, 0.55f)); if (Object.op_Implicit((Object)(object)row.Icon)) { ((Graphic)row.Icon).color = (Color)(pickerOption.Enabled ? Color.white : new Color(1f, 1f, 1f, 0.38f)); } } } private static void EnsureSelectedVisible() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)scroll) && scroll.vertical && selectedIndex >= 0) { Rect rect = viewport.rect; float height = ((Rect)(ref rect)).height; rect = content.rect; float height2 = ((Rect)(ref rect)).height; float num = (float)selectedIndex * 48f; float num2 = num + 44f; float num3 = content.anchoredPosition.y; if (num < num3) { num3 = num; } else if (num2 > num3 + height) { num3 = num2 - height; } content.anchoredPosition = new Vector2(0f, Mathf.Clamp(num3, 0f, Mathf.Max(0f, height2 - height))); } } private static void DestroyUi() { Rows.Clear(); panel = null; viewport = null; content = null; canvasBounds = null; scroll = null; if (Object.op_Implicit((Object)(object)canvasObject)) { canvasObject.SetActive(false); Object.Destroy((Object)(object)canvasObject); } canvasObject = null; } private static RectTransform Rect(Transform parent, string name) { //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) RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }) { hideFlags = (HideFlags)61 }.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); return component; } private static RectTransform TopRect(Transform parent, string name, float x, float y, float width, float height) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) RectTransform obj = Rect(parent, name); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 1f); obj.anchorMax = val; obj.anchorMin = val; obj.pivot = new Vector2(0f, 1f); obj.anchoredPosition = new Vector2(x, 0f - y); obj.sizeDelta = new Vector2(width, height); return obj; } private static RectTransform LeftRect(Transform parent, string name, float x, float y, float width, float height) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) RectTransform obj = Rect(parent, name); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 0.5f); obj.anchorMax = val; obj.anchorMin = val; obj.pivot = new Vector2(0f, 0.5f); obj.anchoredPosition = new Vector2(x, 0f - y); obj.sizeDelta = new Vector2(width, height); return obj; } private static RectTransform RightRect(Transform parent, string name, float x, float y, float width, float height) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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) RectTransform obj = Rect(parent, name); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(1f, 0.5f); obj.anchorMax = val; obj.anchorMin = val; obj.pivot = new Vector2(1f, 0.5f); obj.anchoredPosition = new Vector2(0f - x, 0f - y); obj.sizeDelta = new Vector2(width, height); return obj; } private static void Stretch(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero; } private static TextMeshProUGUI Text(Transform parent, string name, float size, Color color, TextAlignmentOptions alignment, FontStyles style, TMP_FontAsset preferredFont = null) { //IL_0037: 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_0046: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = Rect(parent, name); Stretch(obj); TextMeshProUGUI obj2 = ((Component)obj).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj2).font = (Object.op_Implicit((Object)(object)preferredFont) ? preferredFont : bodyFont); ((TMP_Text)obj2).fontSize = size; ((Graphic)obj2).color = color; ((TMP_Text)obj2).alignment = alignment; ((TMP_Text)obj2).fontStyle = style; ((Graphic)obj2).raycastTarget = false; ((TMP_Text)obj2).richText = false; return obj2; } private static void ResolveFonts() { TMP_FontAsset obj = (Object.op_Implicit((Object)(object)Hud.instance.m_healthText) ? Hud.instance.m_healthText.font : null); if (!Object.op_Implicit((Object)(object)obj)) { throw new InvalidOperationException("Valheim HUD font is unavailable."); } bodyFont = obj; titleFont = obj; TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (Object.op_Implicit((Object)(object)val)) { if (string.Equals(((Object)val).name, "SeneaLUI Forum-Regular.ttf", StringComparison.Ordinal)) { titleFont = val; } else if (string.Equals(((Object)val).name, "SeneaLUI Alegreya-Regular.ttf", StringComparison.Ordinal)) { bodyFont = val; } } } } private static void ClampPanel() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00aa: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)panel) && Object.op_Implicit((Object)(object)canvasBounds) && Object.op_Implicit((Object)(object)canvasObject)) { Rect rect = canvasBounds.rect; float num = Mathf.Max(1f, ((Rect)(ref rect)).width - 32f); float num2 = Mathf.Max(1f, ((Rect)(ref rect)).height - 32f); Vector3 lossyScale = ((Transform)canvasBounds).lossyScale; Vector3 lossyScale2 = canvasObject.transform.lossyScale; float num3 = ((Mathf.Abs(lossyScale.x) > 0.0001f) ? Mathf.Abs(lossyScale2.x / lossyScale.x) : 1f); float num4 = ((Mathf.Abs(lossyScale.y) > 0.0001f) ? Mathf.Abs(lossyScale2.y / lossyScale.y) : 1f); float num5 = Mathf.Min(new float[3] { 1f, num / (440f * num3), num2 / (panel.sizeDelta.y * num4) }); ((Transform)panel).localScale = Vector3.one * Mathf.Max(0.01f, num5); } } private static Outline AddOutline(GameObject target, Color color, float distance) { //IL_0007: 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) Outline obj = target.AddComponent<Outline>(); ((Shadow)obj).effectColor = color; ((Shadow)obj).effectDistance = new Vector2(distance, 0f - distance); ((Shadow)obj).useGraphicAlpha = false; return obj; } private static void AddRule(RectTransform header, string name, bool left) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0079: 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) RectTransform obj = Rect((Transform)(object)header, name); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(left ? 0f : 1f, 0.5f); obj.anchorMax = val; obj.anchorMin = val; obj.pivot = new Vector2(left ? 0f : 1f, 0.5f); obj.anchoredPosition = new Vector2(left ? 0f : 0f, 0f); obj.sizeDelta = new Vector2(46f, 1f); Image obj2 = ((Component)obj).gameObject.AddComponent<Image>(); ((Graphic)obj2).color = BrassHalf; ((Graphic)obj2).raycastTarget = false; } private static Color Rgba(int r, int g, int b, float a) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) return new Color((float)r / 255f, (float)g / 255f, (float)b / 255f, a); } } internal sealed class SelectionMemory { private readonly Dictionary<string, string> choices = new Dictionary<string, string>(StringComparer.Ordinal); internal SelectionMemory(string serialized = "") { string[] array = (serialized ?? "").Split(';'); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0 && num != text.Length - 1 && ValidEscapes(text)) { try { Set(Uri.UnescapeDataString(text.Substring(0, num)), Uri.UnescapeDataString(text.Substring(num + 1))); } catch (UriFormatException) { } } } } private static bool ValidEscapes(string value) { for (int i = 0; i < value.Length; i++) { if (value[i] == '%') { if (i + 2 >= value.Length || !Uri.IsHexDigit(value[i + 1]) || !Uri.IsHexDigit(value[i + 2])) { return false; } i += 2; } } return true; } internal string Get(string stationKey) { if (stationKey == null || !choices.TryGetValue(stationKey, out var value)) { return null; } return value; } internal void Set(string stationKey, string prefab) { if (!string.IsNullOrWhiteSpace(stationKey) && !string.IsNullOrWhiteSpace(prefab) && stationKey.Length <= 256 && prefab.Length <= 128 && (choices.Count < 256 || choices.ContainsKey(stationKey))) { choices[stationKey] = prefab; } } internal string Resolve(string stationKey, IReadOnlyList<string> allowed, Func<string, bool> inStock) { string text = Get(stationKey); if (text != null) { return text; } if (allowed == null || allowed.Count == 0) { return null; } string text2 = allowed[0]; foreach (string item in allowed) { if (inStock(item)) { text2 = item; break; } } Set(stationKey, text2); return text2; } internal string Serialize() { return string.Join(";", from pair in choices.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> pair) => pair.Key, StringComparer.Ordinal) select Uri.EscapeDataString(pair.Key) + "=" + Uri.EscapeDataString(pair.Value)); } } internal sealed class Station { private static readonly Func<Smelter, int> QueueSize = AccessTools.MethodDelegate<Func<Smelter, int>>(AccessTools.Method(typeof(Smelter), "GetQueueSize", (Type[])null, (Type[])null), (object)null, true); private readonly Component component; private readonly bool ore; internal readonly ZNetView View; internal Vector3 Position => component.transform.position; internal string SelectionKey => ((Object)component.gameObject).name.Replace("(Clone)", "").Trim() + (ore ? ":input" : ":fuel"); internal string Name { get { //IL_0029: Unknown result type (might be due to invalid IL or missing references) Localization instance = Localization.instance; Component obj = component; Smelter val = (Smelter)(object)((obj is Smelter) ? obj : null); object obj3; if (val == null) { Component obj2 = component; Fireplace val2 = (Fireplace)(object)((obj2 is Fireplace) ? obj2 : null); obj3 = ((val2 != null) ? val2.m_name : ((CookingStation)component).m_name); } else { obj3 = val.m_name; } return instance.Localize((string)obj3); } } internal bool Valid { get { if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)View)) { return View.IsValid(); } return false; } } internal bool IsOre => ore; internal float Current { get { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown if (!ore) { return View.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); } return QueueSize((Smelter)component); } } private float Maximum { get { //IL_0024: Unknown result type (might be due to invalid IL or missing references) Component obj = component; Smelter val = (Smelter)(object)((obj is Smelter) ? obj : null); if (val == null) { Component obj2 = component; return ((Fireplace)(((obj2 is Fireplace) ? obj2 : null)?)).m_maxFuel ?? ((float)((CookingStation)component).m_maxFuel); } return ore ? val.m_maxOre : val.m_maxFuel; } } internal int Space { get { if (!Valid) { return 0; } return Transfer.Space(Current, Maximum); } } internal bool Refillable { get { if (Valid) { if (!(component is Smelter)) { Component obj = component; Fireplace val = (Fireplace)(object)((obj is Fireplace) ? obj : null); if (val == null || !val.m_canRefill || val.m_infiniteFuel) { Component obj2 = component; return ((CookingStation)(((obj2 is CookingStation) ? obj2 : null)?)).m_useFuel ?? false; } } return true; } return false; } } internal Station(Component target, bool isOre = false) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown component = target; ore = isOre; View = (ZNetView)AccessTools.Field(((object)target).GetType(), "m_nview").GetValue(target); } internal bool Near(Player player, bool checkWard = true) { //IL_0026: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) if (Valid && Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).IsTeleporting()) { Vector3 val = ((Component)player).transform.position - Position; if ((double)((Vector3)(ref val)).sqrMagnitude <= Math.Pow(player.m_maxInteractDistance + 3f, 2.0)) { if (checkWard) { return PrivateArea.CheckAccess(Position, 0f, false, false); } return true; } } return false; } internal IEnumerable<ItemDrop> Inputs() { if (ore) { foreach (ItemConversion item in ((Smelter)component).m_conversion) { if (Object.op_Implicit((Object)(object)item.m_from)) { yield return item.m_from; } } yield break; } Component obj = component; Smelter val = (Smelter)(object)((obj is Smelter) ? obj : null); object obj3; if (val == null) { Component obj2 = component; Fireplace val2 = (Fireplace)(object)((obj2 is Fireplace) ? obj2 : null); obj3 = ((val2 != null) ? val2.m_fuelItem : ((CookingStation)component).m_fuelItem); } else { obj3 = val.m_fuelItem; } ItemDrop val3 = (ItemDrop)obj3; if (Object.op_Implicit((Object)(object)val3)) { yield return val3; } } internal ItemData Find(Inventory inventory, string selectedPrefab) { if (inventory == null) { return null; } foreach (ItemDrop item in Inputs()) { string name = ((Object)((Component)item).gameObject).name; if (name != selectedPrefab || !Transfer.Allowed(name, Plugin.Excluded.Value)) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { if (Object.op_Implicit((Object)(object)allItem.m_dropPrefab) && ((Object)allItem.m_dropPrefab).name == name && allItem.m_stack > 0 && allItem.m_worldLevel >= Game.m_worldLevel && !allItem.m_equipped && !allItem.m_shared.m_questItem) { return allItem; } } } return null; } internal string ResourceName(string prefab) { foreach (ItemDrop item in Inputs()) { if (((Object)((Component)item).gameObject).name == prefab) { return Localization.instance.Localize(item.m_itemData.m_shared.m_name); } } return prefab ?? Texts.ChooseResource; } internal List<PickerOption> Options(Player player) { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); HashSet<Inventory> hashSet = new HashSet<Inventory>(); if (Object.op_Implicit((Object)(object)player) && ((Humanoid)player).GetInventory() != null) { hashSet.Add(((Humanoid)player).GetInventory()); } foreach (Container item in Chests.Nearby(this, player)) { Chests.Refresh(item); hashSet.Add(item.GetInventory()); } foreach (Inventory item2 in hashSet) { foreach (ItemData allItem in item2.GetAllItems()) { if (Object.op_Implicit((Object)(object)allItem.m_dropPrefab) && allItem.m_stack > 0 && allItem.m_worldLevel >= Game.m_worldLevel && !allItem.m_equipped && !allItem.m_shared.m_questItem) { dictionary.TryGetValue(((Object)allItem.m_dropPrefab).name, out var value); dictionary[((Object)allItem.m_dropPrefab).name] = (int)Math.Min(2147483647L, (long)value + (long)allItem.m_stack); } } } List<PickerOption> list = new List<PickerOption>(); HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal); foreach (ItemDrop item3 in Inputs()) { string name = ((Object)((Component)item3).gameObject).name; if (hashSet2.Add(name) && Transfer.Allowed(name, Plugin.Excluded.Value)) { dictionary.TryGetValue(name, out var value2); list.Add(new PickerOption(name, Localization.instance.Localize(item3.m_itemData.m_shared.m_name), item3.m_itemData.GetIcon(), value2)); } } return list; } internal bool Add(ItemData item, Player player, string selectedPrefab) { if (!Refillable || !View.IsOwner() || !Near(player) || Space < 1 || !Object.op_Implicit((Object)(object)item.m_dropPrefab) || ((Object)item.m_dropPrefab).name != selectedPrefab || !Transfer.Allowed(selectedPrefab, Plugin.Excluded.Value)) { return false; } float current = Current; try { if (ore) { View.InvokeRPC("RPC_AddOre", new object[2] { ((Object)item.m_dropPrefab).name, item.m_cheated }); } else { View.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); } } catch (Exception error) { Plugin.Report(error); } if (Valid) { return Current > current; } return false; } } internal static class Texts { private static bool Russian { get { if (Localization.instance != null) { return Localization.instance.GetSelectedLanguage() == "Russian"; } return false; } } internal static string ChooseResource { get { if (!Russian) { return "Choose resource"; } return "Выбрать ресурс"; } } internal static string Fill { get { if (!Russian) { return "Fill"; } return "Заполнить"; } } internal static string Selected { get { if (!Russian) { return "Selected"; } return "Выбрано"; } } internal static string NoneAvailable { get { if (!Russian) { return "Selected resource unavailable in inventory and nearby chests"; } return "Этот ресурс недоступен в инвентаре и ближайших сундуках"; } } internal static string EmptyOptions { get { if (!Russian) { return "No enabled resources for this station"; } return "Нет разрешённых ресурсов для этой печи"; } } internal static string PickerHelp { get { if (!Russian) { return "Up / Down: Select Enter: Choose Esc: Close"; } return "Стрелки: выбор Enter: принять Esc: закрыть"; } } internal unsafe static string Key(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown switch (key - 303) { case 4: case 5: return "Alt"; case 0: case 1: return "Shift"; case 2: case 3: return "Ctrl"; default: return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } } } internal interface IResourceUnit { bool IsDebited { get; } bool Debit(); void Refund(); } internal enum TransferResult { NoResource, Rejected, Added } internal static class Transfer { internal static TransferResult One(IResourceUnit unit, Func<bool> accept) { bool flag = false; try { if (!unit.Debit()) { return TransferResult.NoResource; } flag = accept(); return (!flag) ? TransferResult.Rejected : TransferResult.Added; } finally { if (!flag && unit.IsDebited) { unit.Refund(); } } } internal static int Space(double current, double maximum) { if (double.IsNaN(current) || double.IsInfinity(current) || double.IsNaN(maximum) || double.IsInfinity(maximum) || current < 0.0 || maximum <= current) { return 0; } return (int)Math.Min(1000.0, Math.Floor(maximum - current)); } internal static bool Allowed(string prefab, string excluded) { if (string.IsNullOrEmpty(prefab)) { return false; } string[] array = (excluded ?? "").Split(','); foreach (string text in array) { if (string.Equals(prefab, text.Trim(), StringComparison.OrdinalIgnoreCase)) { return false; } } return true; } } }