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 WorkshopWorker v1.0.2
BepInEx/plugins/WorkshopWorker/WorkshopWorker.dll
Decompiled an hour ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; 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("Daxtillion")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Valheim quality-of-life improvements for storage, crafting, production and repairs.")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("Workshop Worker")] [assembly: AssemblyTitle("WorkshopWorker")] [assembly: AssemblyVersion("1.0.2.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 WorkshopWorker { internal static class AccessPolicy { internal static bool Busy(bool owner, bool localUse, bool replicatedUse, bool exactOpen, bool wagon) { if (!wagon) { if (!owner) { return replicatedUse; } if (localUse) { return !exactOpen; } return false; } return true; } } internal sealed class OpenTicket { internal readonly long Peer; internal readonly float Started; internal bool Answered; internal bool Granted; internal int Frame; internal OpenTicket(long peer, float started) { Peer = peer; Started = started; } internal bool Accept(long peer, bool granted, int frame) { if (Answered || peer != Peer) { return false; } Answered = true; Granted = granted; Frame = frame; return true; } internal bool Settled(bool owner, int frame) { if (Answered && Granted && owner) { return frame > Frame + 1; } return false; } } internal static class BackpackLayout { internal static InventoryElement[] Elements(InventoryGrid grid) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown RectTransform rect = (RectTransform)((Component)grid).transform; int height; bool knownHeight = ExtraSlotsBridge.TryBackpackHeight(out height); int width = ((Humanoid)Player.m_localPlayer).GetInventory().GetWidth(); return GameApi.Get<List<InventoryElement>>(grid, "m_elements").Where(delegate(InventoryElement e) { //IL_001c: 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_003d: 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_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) //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_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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)e) && ((Component)e).gameObject.activeInHierarchy && e.Position.x >= 0 && e.Position.x < width && e.Position.y >= 0) { if (!knownHeight) { Rect rect2 = rect.rect; RectTransform obj = rect; RectTransform elementRectTransform = e.GetElementRectTransform(); Rect rect3 = e.GetElementRectTransform().rect; return ((Rect)(ref rect2)).Contains(((Transform)obj).InverseTransformPoint(((Transform)elementRectTransform).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect3)).center)))); } return e.Position.y < height; } return false; }).ToArray(); } } internal static class ChestAccess { private static readonly Dictionary<Container, OpenTicket> tickets = new Dictionary<Container, OpenTicket>(); private static readonly Dictionary<Container, float> rejected = new Dictionary<Container, float>(); internal static Container Open { get { if (!Object.op_Implicit((Object)(object)InventoryGui.instance)) { return null; } return GameApi.Get<Container>(InventoryGui.instance, "m_currentContainer"); } } internal static bool Dragging { get { if (Object.op_Implicit((Object)(object)InventoryGui.instance)) { return GameApi.Get<ItemData>(InventoryGui.instance, "m_dragItem") != null; } return false; } } internal static bool Allowed(Container c) { //IL_003d: 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) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)c) || !Object.op_Implicit((Object)(object)localPlayer) || !((Character)localPlayer).IsOwner() || ((Character)localPlayer).IsDead() || !((Behaviour)c).isActiveAndEnabled || c.GetInventory() == null || !GameApi.Nearby((Component)(object)c, ((Component)localPlayer).transform.position)) { return false; } ZNetView val = GameApi.View((Component)(object)c); if (Object.op_Implicit((Object)(object)val) && val.IsValid() && (bool)GameApi.Call(c, "CheckAccess", localPlayer.GetPlayerID())) { return PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false); } return false; } internal static IEnumerable<Container> Near(Vector3 center) { //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 Plugin.Chests.Where((Container c) => Object.op_Implicit((Object)(object)c) && GameApi.Nearby((Component)(object)c, center) && Allowed(c)).OrderBy(delegate(Container c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)c).transform.position - center; return ((Vector3)(ref val)).sqrMagnitude; }); } internal static bool Editable(Container c) { if (Allowed(c) && (Object)(object)Open == (Object)(object)c && c.IsInUse() && GameApi.Owned((Component)(object)c)) { return !Dragging; } return false; } internal static bool Ready(Container c) { if (!Allowed(c)) { return false; } ZNetView val = GameApi.View((Component)(object)c); bool flag = val.IsOwner(); if (AccessPolicy.Busy(flag, c.IsInUse(), val.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 0, (Object)(object)Open == (Object)(object)c, Object.op_Implicit((Object)(object)c.m_wagon) && c.m_wagon.InUse())) { return false; } if (tickets.TryGetValue(c, out var value)) { if (!value.Settled(flag, Time.frameCount)) { return false; } if (!c.IsInUse()) { GameApi.Call(c, "Load"); } tickets.Remove(c); } if (flag) { if (!c.IsInUse()) { GameApi.Call(c, "Load"); } return !GameApi.Get<bool>(c, "m_loading"); } if (rejected.TryGetValue(c, out var value2) && Time.unscaledTime < value2) { return false; } if (tickets.Values.Count((OpenTicket t) => !t.Answered) >= 8 || val.GetZDO().GetOwner() == 0L) { return false; } tickets[c] = new OpenTicket(val.GetZDO().GetOwner(), Time.unscaledTime); val.InvokeRPC("RPC_RequestOpen", new object[1] { Player.m_localPlayer.GetPlayerID() }); return false; } internal static bool Reply(Container c, long peer, bool granted) { if (!tickets.TryGetValue(c, out var value)) { return true; } value.Accept(peer, granted, Time.frameCount); if (value.Answered && !value.Granted) { tickets.Remove(c); rejected[c] = Time.unscaledTime + 2f; } return false; } internal static bool Manual(Container c) { if (tickets.TryGetValue(c, out var value)) { if (!value.Answered) { Plugin.Say("Waiting for this chest's owner. Try again shortly."); return false; } tickets.Remove(c); } rejected.Remove(c); return true; } internal static void Tick() { Container[] array = tickets.Keys.ToArray(); foreach (Container val in array) { if (!Object.op_Implicit((Object)(object)val)) { tickets.Remove(val); continue; } OpenTicket openTicket = tickets[val]; if (openTicket.Settled(GameApi.Owned((Component)(object)val), Time.frameCount)) { Ready(val); } if (!openTicket.Answered && Time.unscaledTime - openTicket.Started > 8f) { openTicket.Answered = true; openTicket.Granted = false; } } } internal static string State(Container c) { if (!Allowed(c)) { return "access or range"; } if (tickets.TryGetValue(c, out var value)) { if (!value.Answered) { return "awaiting owner reply"; } if (!value.Granted) { return "request declined/timed out; open chest once"; } return "ownership packet pending"; } if (c.IsInUse() && (Object)(object)Open != (Object)(object)c) { return "another open session"; } if (!GameApi.Owned((Component)(object)c)) { return "remote owner"; } return "local owner"; } } [HarmonyPatch(typeof(Container), "RPC_OpenResponse")] internal static class BackgroundChestReply { private static bool Prefix(Container __instance, long uid, bool granted) { return ChestAccess.Reply(__instance, uid, granted); } } [HarmonyPatch(typeof(Container), "Interact")] internal static class ManualChestOpen { private static bool Prefix(Container __instance, ref bool __result) { if (ChestAccess.Manual(__instance)) { return true; } __result = false; return false; } } internal static class ChestPresentation { internal static string FaceName(int face) { return (new string[4] { "Back", "Right", "Front", "Left" })[(face % 4 + 4) % 4]; } internal static string Memory(bool enabled, IEnumerable<string> contents) { return "Remember: " + (enabled ? "On" : "Off") + " (" + contents.Where((string s) => !string.IsNullOrEmpty(s)).Distinct().Count() + ")"; } } internal static class ChestUi { private static GameObject toolbar; private static GameObject panel; private static GameObject playerSort; private static Container selected; private static ChestSettings draft; private static TMP_InputField label; private static TMP_InputField priority; private static TMP_InputField search; private static GameObject searchBar; private static Player searchPlayer; private static readonly Vector3[] searchCorners = (Vector3[])(object)new Vector3[4]; private static RectTransform inventoryBackground; private static RectTransform shiftedContainer; private static Vector2 backgroundBase; private static Vector2 backgroundApplied; private static Vector2 containerBase; private static Vector2 containerApplied; private static bool backgroundAdjusted; private static bool containerAdjusted; private static TMP_Text rememberText; private static TMP_Text faceText; private static readonly TextEntryState textEntry = new TextEntryState(); internal static bool Editing { get { if (Object.op_Implicit((Object)(object)panel)) { return panel.activeSelf; } return false; } } private static bool Typing { get { if (!Editing || ((!Object.op_Implicit((Object)(object)label) || !label.isFocused) && (!Object.op_Implicit((Object)(object)priority) || !priority.isFocused))) { if (InventoryGui.IsVisible() && Object.op_Implicit((Object)(object)search)) { return search.isFocused; } return false; } return true; } } internal static bool BlockGameplayInput => textEntry.Blocks(Typing, Time.frameCount); internal static TMP_FontAsset Font { get { if (!Object.op_Implicit((Object)(object)InventoryGui.instance) || !Object.op_Implicit((Object)(object)InventoryGui.instance.m_playerName.font)) { return TMP_Settings.defaultFontAsset; } return InventoryGui.instance.m_playerName.font; } } private static RectTransform Rect(Transform parent, string name, float x, float y, float w, float h) { //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_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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.SetActive(false); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(parent, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 1f); val2.anchorMax = val3; val2.anchorMin = val3; val2.pivot = new Vector2(0f, 1f); val2.anchoredPosition = new Vector2(x, 0f - y); val2.sizeDelta = new Vector2(w, h); return val2; } private static TMP_Text Text(Transform parent, string text, float x, float y, float w, float h, int size = 18) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Rect(parent, "Text", x, y, w, h); TextMeshProUGUI obj = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj).font = Font; ((TMP_Text)obj).fontSize = size; ((TMP_Text)obj).text = text; ((Graphic)obj).color = new Color(1f, 0.92f, 0.75f); ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).alignment = (TextAlignmentOptions)4097; ((Component)val).gameObject.SetActive(true); return (TMP_Text)(object)obj; } private static Button Button(Transform parent, string name, float x, float y, float w, Action action) { //IL_0040: 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: Expected O, but got Unknown RectTransform val = Rect(parent, name, x, y, w, 34f); Image val2 = ((Component)val).gameObject.AddComponent<Image>(); ((Graphic)val2).color = new Color(0.22f, 0.18f, 0.13f, 0.98f); Button val3 = ((Component)val).gameObject.AddComponent<Button>(); ((Selectable)val3).targetGraphic = (Graphic)(object)val2; TMP_Text val4 = Text((Transform)(object)val, name, 8f, 0f, w - 16f, 34f); val4.alignment = (TextAlignmentOptions)514; UiSkin.Button(val3, val4); ((Graphic)val2).raycastTarget = true; ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { try { action(); } catch (Exception ex) { Plugin.Log(ex.ToString()); Plugin.Say("Operation failed; see client log."); } }); ((Component)val).gameObject.SetActive(true); return val3; } private static TMP_InputField InputBox(Transform parent, string text, float y, float x = 170f, float width = 265f) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0082: 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_00ac: 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_010b: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Rect(parent, "Input", x, y, width, 34f); ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0.07f, 0.07f, 0.07f, 0.98f); RectTransform val2 = Rect((Transform)(object)val, "Text Area", 8f, 0f, width - 16f, 34f); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.pivot = new Vector2(0.5f, 0.5f); val2.offsetMin = new Vector2(8f, 0f); val2.offsetMax = new Vector2(-8f, 0f); ((Component)val2).gameObject.AddComponent<RectMask2D>(); ((Component)val2).gameObject.SetActive(true); TMP_Text val3 = Text((Transform)(object)val2, "", 0f, 0f, width - 16f, 34f); ((Graphic)val3).color = Color.white; val3.richText = false; val3.rectTransform.anchorMin = Vector2.zero; val3.rectTransform.anchorMax = Vector2.one; val3.rectTransform.pivot = new Vector2(0.5f, 0.5f); RectTransform rectTransform = val3.rectTransform; Vector2 offsetMin = (val3.rectTransform.offsetMax = Vector2.zero); rectTransform.offsetMin = offsetMin; val3.alignment = (TextAlignmentOptions)513; val3.textWrappingMode = (TextWrappingModes)0; TMP_InputField obj = ((Component)val).gameObject.AddComponent<TMP_InputField>(); obj.textViewport = val2; obj.textComponent = val3; obj.lineType = (LineType)0; ((UnityEvent<string>)(object)obj.onSelect).AddListener((UnityAction<string>)delegate { textEntry.FocusChanged(Time.frameCount); }); ((UnityEvent<string>)(object)obj.onDeselect).AddListener((UnityAction<string>)delegate { textEntry.FocusChanged(Time.frameCount); }); ((UnityEvent<string>)(object)obj.onEndEdit).AddListener((UnityAction<string>)delegate { textEntry.FocusChanged(Time.frameCount); }); obj.characterLimit = 96; obj.text = text; ((Component)val).gameObject.SetActive(true); return obj; } internal static void Tick() { //IL_009a: 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_00b1: 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_01fa: 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_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } if ((Object)(object)searchPlayer != (Object)(object)Player.m_localPlayer) { searchPlayer = Player.m_localPlayer; StorageSearch.Query = ""; StorageSearch.Clear(); if (Object.op_Implicit((Object)(object)search)) { search.SetTextWithoutNotify(""); } } Vector2 val = default(Vector2); if (!Object.op_Implicit((Object)(object)searchBar)) { RectTransform obj = Rect((Transform)(object)instance.m_player, "WorkshopWorkerStorageSearch", 12f, 0f, 420f, 38f); ((Vector2)(ref val))..ctor(0f, 0f); obj.anchorMax = val; obj.anchorMin = val; obj.anchoredPosition = new Vector2(12f, -8f); searchBar = ((Component)obj).gameObject; Text((Transform)(object)obj, "Find in Storage", 0f, 0f, 110f, 34f, 16).textWrappingMode = (TextWrappingModes)0; search = InputBox((Transform)(object)obj, "", 0f, 120f, 240f); ((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate(string value) { StorageSearch.Query = value; }); Button((Transform)(object)obj, "Clear", 368f, 0f, 65f, delegate { search.text = ""; StorageSearch.Clear(); }); } searchBar.SetActive(InventoryGui.IsVisible()); if (Object.op_Implicit((Object)(object)search) && search.isFocused && Input.GetKeyDown((KeyCode)27)) { search.DeactivateInputField(false); } if (!Object.op_Implicit((Object)(object)toolbar)) { RectTransform obj2 = Rect((Transform)(object)instance.m_container, "WorkshopWorkerTools", 0f, 0f, 310f, 38f); ((Vector2)(ref val))..ctor(0f, 0f); obj2.anchorMax = val; obj2.anchorMin = val; obj2.anchoredPosition = new Vector2(12f, -6f); toolbar = ((Component)obj2).gameObject; Button((Transform)(object)obj2, "Chest Rules", 0f, 0f, 190f, Open); Button((Transform)(object)obj2, "Sort", 198f, 0f, 90f, delegate { Storage.Sort(ChestAccess.Open); }); } toolbar.SetActive(InventoryGui.IsVisible() && Object.op_Implicit((Object)(object)ChestAccess.Open)); if (!Object.op_Implicit((Object)(object)playerSort) && Object.op_Implicit((Object)(object)instance.m_weight)) { Image val2 = ((IEnumerable<Image>)((Component)instance.m_weight.transform.parent).GetComponentsInChildren<Image>(true)).FirstOrDefault((Func<Image, bool>)((Image i) => Object.op_Implicit((Object)(object)i.sprite) && ((Object)i).name.IndexOf("weight", StringComparison.OrdinalIgnoreCase) >= 0)); Button obj3 = Button((Transform)(object)(Object.op_Implicit((Object)(object)val2) ? ((Graphic)val2).rectTransform : instance.m_weight.rectTransform), "Sort", 0f, 0f, 90f, Storage.SortPlayer); RectTransform val3 = (RectTransform)((Component)obj3).transform; ((Vector2)(ref val))..ctor(0.5f, 0f); val3.anchorMax = val; val3.anchorMin = val; val3.pivot = new Vector2(0.5f, 1f); val3.anchoredPosition = new Vector2(0f, -8f); playerSort = ((Component)obj3).gameObject; } if (Object.op_Implicit((Object)(object)playerSort)) { playerSort.SetActive(InventoryGui.IsVisible()); } if (Editing && (!InventoryGui.IsVisible() || (Object)(object)ChestAccess.Open != (Object)(object)selected || Input.GetKeyDown((KeyCode)27))) { Close(); } } private static void RestoreSearchLayout() { //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_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_002e: 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) if (backgroundAdjusted && Object.op_Implicit((Object)(object)inventoryBackground) && inventoryBackground.offsetMin == backgroundApplied) { inventoryBackground.offsetMin = backgroundBase; } if (containerAdjusted && Object.op_Implicit((Object)(object)shiftedContainer) && shiftedContainer.anchoredPosition == containerApplied) { shiftedContainer.anchoredPosition = containerBase; } backgroundAdjusted = (containerAdjusted = false); } internal static void PositionSearch() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: 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_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0200: 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_00d9: 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_00e4: 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_0288: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: 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_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) RestoreSearchLayout(); InventoryGui instance = InventoryGui.instance; if (!Object.op_Implicit((Object)(object)searchBar) || !Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !InventoryGui.IsVisible()) { return; } Transform obj = ((Transform)instance.m_player).Find("Bkg"); inventoryBackground = (RectTransform)(object)((obj is RectTransform) ? obj : null); Rect rect = instance.m_player.rect; float num = ((Rect)(ref rect)).yMin; if (Object.op_Implicit((Object)(object)inventoryBackground)) { inventoryBackground.GetWorldCorners(searchCorners); num = Mathf.Min(num, ((Transform)instance.m_player).InverseTransformPoint(searchCorners[0]).y); } InventoryElement[] array = BackpackLayout.Elements(instance.m_playerGrid); for (int i = 0; i < array.Length; i++) { array[i].GetElementRectTransform().GetWorldCorners(searchCorners); Vector3[] array2 = searchCorners; foreach (Vector3 val in array2) { num = Mathf.Min(num, ((Transform)instance.m_player).InverseTransformPoint(val).y); } } float num2 = num - 0f - 34f - 12f; RectTransform val2 = (RectTransform)searchBar.transform; float num3 = num; rect = instance.m_player.rect; val2.anchoredPosition = new Vector2(12f, num3 - ((Rect)(ref rect)).yMin - 0f); if (Object.op_Implicit((Object)(object)inventoryBackground)) { inventoryBackground.GetWorldCorners(searchCorners); Transform parent = ((Transform)inventoryBackground).parent; float y = parent.InverseTransformPoint(searchCorners[0]).y; float y2 = parent.InverseTransformPoint(((Transform)instance.m_player).TransformPoint(new Vector3(0f, num2, 0f))).y; backgroundBase = inventoryBackground.offsetMin; backgroundApplied = backgroundBase + new Vector2(0f, Mathf.Min(0f, y2 - y)); inventoryBackground.offsetMin = backgroundApplied; backgroundAdjusted = true; } if (Object.op_Implicit((Object)(object)instance.m_container) && ((Component)instance.m_container).gameObject.activeInHierarchy) { shiftedContainer = instance.m_container; Transform obj2 = ((Transform)shiftedContainer).Find("Bkg"); RectTransform val3 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null); (Object.op_Implicit((Object)(object)val3) ? val3 : shiftedContainer).GetWorldCorners(searchCorners); Transform parent2 = ((Transform)shiftedContainer).parent; float y3 = parent2.InverseTransformPoint(searchCorners[1]).y; float y4 = parent2.InverseTransformPoint(((Transform)instance.m_player).TransformPoint(new Vector3(0f, num2 - 10f, 0f))).y; containerBase = shiftedContainer.anchoredPosition; containerApplied = containerBase + new Vector2(0f, Mathf.Min(0f, y4 - y3)); shiftedContainer.anchoredPosition = containerApplied; containerAdjusted = true; } } private static void Open() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_02c1: Unknown result type (might be due to invalid IL or missing references) selected = ChestAccess.Open; if (!ChestAccess.Editable(selected)) { Plugin.Say("Chest access changed. Reopen the chest."); Plugin.Log("Rules editor: " + ChestAccess.State(selected)); return; } if (Object.op_Implicit((Object)(object)panel)) { Object.Destroy((Object)(object)panel); } draft = ChestSettings.Read(selected); draft.Learn(selected); RectTransform val = Rect(((Component)((Component)InventoryGui.instance).GetComponentInParent<Canvas>()).transform, "WorkshopWorkerRules", 0f, 0f, 460f, 372f); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); val.pivot = val2; Vector2 anchorMin = (val.anchorMax = val2); val.anchorMin = anchorMin; val.anchoredPosition = Vector2.zero; ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0.09f, 0.085f, 0.075f, 0.99f); panel = ((Component)val).gameObject; Text((Transform)(object)val, "Workshop Worker · Chest rules", 20f, 12f, 420f, 40f, 23); Text((Transform)(object)val, "Label", 20f, 76f, 65f, 34f); label = InputBox((Transform)(object)val, draft.label, 76f, 95f, 340f); (string, string)[] array = new(string, string)[7] { ("White", "#FFFFFF"), ("Red", "#FF6565"), ("Orange", "#FFAA44"), ("Yellow", "#FFEE66"), ("Green", "#77DD77"), ("Blue", "#66BBFF"), ("Purple", "#CC99FF") }; Color color = default(Color); for (int i = 0; i < array.Length; i++) { (string, string) choice = array[i]; TMP_Text componentInChildren = ((Component)Button((Transform)(object)val, choice.Item1, 20 + i * 60, 120f, 56f, delegate { //IL_0032: Unknown result type (might be due to invalid IL or missing references) draft.color = choice.Item2; Color color3 = default(Color); ColorUtility.TryParseHtmlString(choice.Item2, ref color3); ((Graphic)label.textComponent).color = color3; })).GetComponentInChildren<TMP_Text>(); ColorUtility.TryParseHtmlString(choice.Item2, ref color); ((Graphic)componentInChildren).color = color; componentInChildren.fontSizeMax = 14f; componentInChildren.fontSizeMin = 10f; } Color color2 = default(Color); if (ColorUtility.TryParseHtmlString(draft.color, ref color2)) { ((Graphic)label.textComponent).color = color2; } Text((Transform)(object)val, "Priority (0 first)", 20f, 170f, 145f, 34f); priority = InputBox((Transform)(object)val, draft.priority.ToString(), 170f); faceText = ((Component)Button((Transform)(object)val, "", 20f, 218f, 200f, delegate { draft.face = (draft.face + 1) % 4; UpdateButtons(); })).GetComponentInChildren<TMP_Text>(); rememberText = ((Component)Button((Transform)(object)val, "", 235f, 218f, 200f, delegate { draft.remember = !draft.remember; draft.Learn(selected); UpdateButtons(); })).GetComponentInChildren<TMP_Text>(); Button((Transform)(object)val, "Remember current contents", 20f, 264f, 265f, delegate { draft.remember = true; draft.Learn(selected); UpdateButtons(); }); Button((Transform)(object)val, "Forget types", 295f, 264f, 140f, delegate { draft.contents.Clear(); draft.remember = false; UpdateButtons(); }); Button((Transform)(object)val, "Save", 235f, 322f, 95f, Save); Button((Transform)(object)val, "Cancel", 340f, 322f, 95f, Close); UpdateButtons(); ((Component)val).gameObject.SetActive(true); } private static void UpdateButtons() { faceText.text = "Label: " + ChestPresentation.FaceName(draft.face); rememberText.text = ChestPresentation.Memory(draft.remember, draft.contents); } private static void Save() { if (!ChestAccess.Editable(selected)) { Plugin.Say("Chest access changed; settings were not saved."); return; } if (!int.TryParse(priority.text, out var result) || result < 0 || result > 9) { Plugin.Say("Use a priority from 0 to 9."); return; } draft.label = label.text.Trim(); draft.priority = result; draft.Learn(selected); draft.Save(selected); Close(); RefreshLabels(); } private static void Close() { if (Typing) { textEntry.FocusChanged(Time.frameCount); } if (Object.op_Implicit((Object)(object)panel)) { Object.Destroy((Object)(object)panel); } panel = null; selected = null; } internal static void Dispose() { Close(); if (Object.op_Implicit((Object)(object)toolbar)) { Object.Destroy((Object)(object)toolbar); } if (Object.op_Implicit((Object)(object)playerSort)) { Object.Destroy((Object)(object)playerSort); } if (Object.op_Implicit((Object)(object)searchBar)) { Object.Destroy((Object)(object)searchBar); } RestoreSearchLayout(); StorageSearchDim.Dispose(); StorageSearch.Query = ""; StorageSearch.Clear(); } internal static void RefreshLabels() { SurfaceLabels.Refresh(); } } [HarmonyPatch(typeof(Container), "Save")] internal static class RememberChestContents { private static void Postfix(Container __instance) { if (!GameApi.Owned((Component)(object)__instance)) { return; } ChestSettings chestSettings = ChestSettings.Read(__instance); if (chestSettings.remember) { int count = chestSettings.contents.Count; chestSettings.Learn(__instance); if (count != chestSettings.contents.Count) { chestSettings.Save(__instance); } } } } internal static class Crafting { internal static int QueryDepth; internal static int SpendDepth; internal static Container[] Held; internal static bool PlayerInventory(Inventory inv) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return inv == ((Humanoid)Player.m_localPlayer).GetInventory(); } return false; } internal static IEnumerable<Container> Sources() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) return (Held ?? ChestAccess.Near(((Component)Player.m_localPlayer).transform.position).ToArray()).Where(ChestAccess.Ready); } internal static bool Match(ItemData i, string name, int quality, bool world) { if (i.m_shared.m_name == name && (quality < 0 || i.m_quality == quality)) { if (world) { return i.m_worldLevel >= Game.m_worldLevel; } return true; } return false; } internal static int Count(string name, int quality, bool world) { return Sources().Sum((Container c) => (from i in c.GetInventory().GetAllItems() where Match(i, name, quality, world) select i).Sum((ItemData i) => i.m_stack)); } internal static ItemData Find(string name, int quality, bool prefab) { return Sources().SelectMany((Container c) => c.GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => (prefab ? Storage.ItemId(i) : i.m_shared.m_name) == name && (quality < 0 || quality == i.m_quality) && i.m_worldLevel >= Game.m_worldLevel)); } internal static Container Source(ItemData item) { return Sources().FirstOrDefault((Func<Container, bool>)((Container c) => c.GetInventory().GetAllItems().Contains(item))); } internal static void BeginSpend() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (SpendDepth++ == 0) { Held = ChestAccess.Near(((Component)Player.m_localPlayer).transform.position).Where(ChestAccess.Ready).ToArray(); } } internal static void EndSpend() { if (--SpendDepth == 0) { Held = null; } } } [HarmonyPatch] internal static class RecipeQueries { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Player), "HaveRequirements", new Type[4] { typeof(Recipe), typeof(bool), typeof(int), typeof(int) }, (Type[])null); yield return AccessTools.Method(typeof(Player), "HaveRequirements", new Type[2] { typeof(Piece), typeof(RequirementMode) }, (Type[])null); yield return AccessTools.Method(typeof(Player), "GetFirstRequiredItem", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(InventoryGui), "SetupRequirement", (Type[])null, (Type[])null); } private static void Prefix(out bool __state) { __state = Plugin.Craft.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer); if (__state) { Crafting.QueryDepth++; } } private static Exception Finalizer(Exception __exception, bool __state) { if (__state) { Crafting.QueryDepth--; } return __exception; } } [HarmonyPatch(typeof(Inventory), "CountItems")] internal static class NearbyCounts { private static void Postfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { if (Crafting.QueryDepth > 0 && name != null && Crafting.PlayerInventory(__instance)) { __result += Crafting.Count(name, quality, matchWorldLevel); } } } [HarmonyPatch(typeof(Inventory), "GetItem", new Type[] { typeof(string), typeof(int), typeof(bool) })] internal static class NearbyItem { private static void Postfix(Inventory __instance, string name, int quality, bool isPrefabName, ref ItemData __result) { if (__result == null && Crafting.QueryDepth > 0 && Crafting.PlayerInventory(__instance)) { __result = Crafting.Find(name, quality, isPrefabName); } } } [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] internal static class NearbyHaveItem { private static void Postfix(Inventory __instance, string name, bool matchWorldLevel, ref bool __result) { if (!__result && Crafting.QueryDepth > 0 && Crafting.PlayerInventory(__instance)) { __result = Crafting.Count(name, -1, matchWorldLevel) > 0; } } } [HarmonyPatch] internal static class RecipeSpend { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(InventoryGui), "DoCrafting", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Player), "ConsumeResources", (Type[])null, (Type[])null); } private static void Prefix(out bool __state) { __state = Plugin.Craft.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer); if (__state) { Crafting.BeginSpend(); } } private static Exception Finalizer(Exception __exception, bool __state) { if (__state) { Crafting.EndSpend(); } return __exception; } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] internal static class ConsumeNearbyByName { private static bool Prefix(Inventory __instance, string name, int amount, int itemQuality, bool worldLevelBased) { if (Crafting.SpendDepth == 0 || !Crafting.PlayerInventory(__instance)) { return true; } (Inventory inv, ItemData item)[] array = ((IEnumerable<Inventory>)(object)new Inventory[1] { __instance }).Concat(from c in Crafting.Sources() select c.GetInventory()).ToArray().SelectMany((Inventory inv) => from i in inv.GetAllItems() where Crafting.Match(i, name, itemQuality, worldLevelBased) select (inv: inv, item: i)) .ToArray(); if (array.Sum(((Inventory inv, ItemData item) p) => p.item.m_stack) < amount) { throw new InvalidOperationException("Crafting source changed before ingredient consumption."); } (Inventory, ItemData)[] array2 = array; for (int num = 0; num < array2.Length; num++) { (Inventory, ItemData) tuple = array2[num]; int num2 = Math.Min(amount, tuple.Item2.m_stack); if (num2 <= 0) { break; } tuple.Item1.RemoveItem(tuple.Item2, num2); amount -= num2; } return false; } } [HarmonyPatch] internal static class ManualMachineScope { private static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[2] { "OnAddOre", "OnAddFuel" }; foreach (string text in array) { yield return AccessTools.Method(typeof(Smelter), text, (Type[])null, (Type[])null); } array = new string[3] { "OnInteract", "OnUseItem", "OnAddFuelSwitch" }; foreach (string text2 in array) { yield return AccessTools.Method(typeof(CookingStation), text2, (Type[])null, (Type[])null); } array = new string[2] { "Interact", "UseItem" }; foreach (string m in array) { yield return AccessTools.Method(typeof(Fermenter), m, (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Fireplace), m, (Type[])null, (Type[])null); } } private static void Prefix(Component __instance, out bool __state) { //IL_0024: 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) __state = Plugin.Craft.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer) && GameApi.Nearby(__instance, ((Component)Player.m_localPlayer).transform.position) && PrivateArea.CheckAccess(__instance.transform.position, 0f, false, false); if (__state) { Crafting.BeginSpend(); Crafting.QueryDepth++; } } private static Exception Finalizer(Exception __exception, bool __state) { if (__state) { Crafting.QueryDepth--; Crafting.EndSpend(); } return __exception; } } [HarmonyPatch(typeof(Inventory), "RemoveOneItem")] internal static class ConsumeNearbyOne { private static bool Prefix(Inventory __instance, ItemData item, ref bool __result) { if (Crafting.SpendDepth == 0 || !Crafting.PlayerInventory(__instance) || __instance.ContainsItem(item)) { return true; } Container val = Crafting.Source(item); __result = Object.op_Implicit((Object)(object)val) && val.GetInventory().RemoveOneItem(item); return false; } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData), typeof(int) })] internal static class ConsumeNearbyStack { private static bool Prefix(Inventory __instance, ItemData item, int amount, ref bool __result) { if (Crafting.SpendDepth == 0 || !Crafting.PlayerInventory(__instance) || __instance.ContainsItem(item)) { return true; } Container val = Crafting.Source(item); __result = Object.op_Implicit((Object)(object)val) && val.GetInventory().RemoveItem(item, amount); return false; } } [HarmonyPatch] internal static class MachineIngredientPreview { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Smelter), "OnHoverAddOre", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Smelter), "OnHoverAddFuel", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(CookingStation), "GetHoverText", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(CookingStation), "OnHoverFuelSwitch", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Fermenter), "GetHoverText", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Fireplace), "GetHoverText", (Type[])null, (Type[])null); } private static void Postfix(Component __instance, MethodBase __originalMethod, ref string __result) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Craft.Value || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } IEnumerable<string> enumerable = (from i in Production.Ingredients(__instance, __originalMethod.Name.IndexOf("Fuel", StringComparison.OrdinalIgnoreCase) >= 0 || __instance is Fireplace) select i.m_itemData.m_shared.m_name).Distinct(); Container[] source = ChestAccess.Near(__instance.transform.position).Where(ChestAccess.Ready).ToArray(); foreach (string name in enumerable) { int num = source.Sum((Container c) => c.GetInventory().CountItems(name, -1, true)); if (num > 0) { __result = __result + "\n" + Localization.instance.Localize(name) + ": " + num + " in nearby storage"; } } } } internal static class ExtraSlotsBridge { private static MethodInfo backpackHeight; private static bool heightResolved; internal static bool TryBackpackHeight(out int height) { height = 0; try { if (!heightResolved) { heightResolved = true; backpackHeight = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ExtraSlots")?.GetType("ExtraSlots.API")?.GetMethod("GetInventoryHeightPlayer", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null); } if (backpackHeight == null) { return false; } height = (int)backpackHeight.Invoke(null, null); return height > 0; } catch { return false; } } internal static bool ReducedSlots(IEnumerable<Vector2i> visible, out Vector2i[] slots, out Func<Vector2i, bool> special) { slots = Array.Empty<Vector2i>(); special = null; try { Assembly? assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ExtraSlots"); Type type = assembly?.GetType("ExtraSlots.API"); Type type2 = assembly?.GetType("ExtraSlots.LightenedSlots"); MethodInfo methodInfo = type?.GetMethod("IsGridPositionASlot", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Vector2i) }, null); MethodInfo methodInfo2 = type2?.GetMethod("IsRowAffected", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(int) }, null); PropertyInfo propertyInfo = type2?.GetProperty("WeightFactor", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null || methodInfo2 == null || propertyInfo == null || (float)propertyInfo.GetValue(null) >= 1f) { return false; } Func<Vector2i, bool> check = (Func<Vector2i, bool>)Delegate.CreateDelegate(typeof(Func<Vector2i, bool>), methodInfo); Func<int, bool> reduced = (Func<int, bool>)Delegate.CreateDelegate(typeof(Func<int, bool>), methodInfo2); slots = visible.Where((Vector2i p) => p.y > 0 && !check(p) && reduced(p.y)).ToArray(); special = check; return slots.Length != 0; } catch (Exception ex) { Plugin.Log("ExtraSlots weight-row detection unavailable: " + ex.Message); return false; } } } internal static class InventorySort { internal static int HeavySlots(Inventory inventory, Func<ItemData, bool> keep, IEnumerable<Vector2i> preferred, Func<ItemData, float> weight, Func<ItemData, string> name) { //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) ItemData[] array = (from i in inventory.GetAllItems() where !keep(i) select i).ToArray(); HashSet<Vector2i> blocked = new HashSet<Vector2i>(from i in inventory.GetAllItems().Where(keep) select i.m_gridPos); Vector2i[] array2 = (from p in preferred.Where((Vector2i p) => !blocked.Contains(p)).Distinct() orderby p.y descending, p.x select p).Take(array.Length).ToArray(); ItemData[] array3 = array.OrderByDescending(weight).ThenBy<ItemData, string>(name, StringComparer.CurrentCultureIgnoreCase).Take(array2.Length) .ToArray(); Vector2i[] array4 = (from p in array.Select((ItemData i) => i.m_gridPos).Except(array2) orderby p.y, p.x select p).ToArray(); ItemData[] array5 = array.Except(array3).OrderBy<ItemData, string>(name, StringComparer.CurrentCultureIgnoreCase).ThenByDescending((ItemData i) => i.m_quality) .ThenByDescending((ItemData i) => i.m_stack) .ToArray(); for (int num = 0; num < array3.Length; num++) { array3[num].m_gridPos = array2[num]; } for (int num2 = 0; num2 < array5.Length; num2++) { array5[num2].m_gridPos = array4[num2]; } return array.Length; } internal static int Occupied(Inventory inventory, Func<ItemData, bool> keep, Func<ItemData, string> name) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) ItemData[] source = (from i in inventory.GetAllItems() where !keep(i) select i).ToArray(); Vector2i[] array = (from i in source select i.m_gridPos into p orderby p.y, p.x select p).ToArray(); ItemData[] array2 = source.OrderBy<ItemData, string>(name, StringComparer.CurrentCultureIgnoreCase).ThenByDescending((ItemData i) => i.m_quality).ThenByDescending((ItemData i) => i.m_stack) .ToArray(); for (int num = 0; num < array2.Length; num++) { array2[num].m_gridPos = array[num]; } return array2.Length; } } internal static class LiveObjectPool { internal static T Get<T>(List<T> items, int index, Func<T, bool> alive, Func<T> create) where T : class { while (items.Count <= index) { items.Add(null); } if (!alive(items[index])) { items[index] = create(); } return items[index]; } } [BepInPlugin("local.WorkshopWorker", "Workshop Worker", "1.0.2")] public sealed class Plugin : BaseUnityPlugin { internal static Plugin Self; internal static ConfigEntry<float> Range; internal static ConfigEntry<bool> Hotbar; internal static ConfigEntry<bool> Craft; internal static ConfigEntry<bool> Automate; internal static ConfigEntry<KeyboardShortcut> StackKey; internal static ConfigEntry<KeyboardShortcut> ReserveKey; internal static ConfigEntry<KeyboardShortcut> InputKey; internal static ConfigEntry<KeyboardShortcut> OutputKey; internal static ConfigEntry<KeyCode> ClearKey; internal static ConfigEntry<bool> ShowVfx; internal static ConfigEntry<bool> UniformLabelSize; internal static ConfigEntry<bool> SortHeavyToReducedRows; internal static ConfigEntry<float> SearchGlowIntensity; internal static ConfigEntry<KeyboardShortcut> VfxKey; internal static ConfigEntry<KeyboardShortcut> RepairKey; private Harmony patches; private float scanAt; private float workAt; internal static Container[] Chests = Array.Empty<Container>(); internal static Component[] Machines = Array.Empty<Component>(); private void Awake() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0293: 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_02b7: Expected O, but got Unknown if (Application.isBatchMode) { ((Behaviour)this).enabled = false; return; } Self = this; Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RangeMeters", 75f, new ConfigDescription("Nearby loaded storage range shared by all features.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); Hotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("Storage", "ProtectHotbar", true, "Exclude the first inventory row from quick stack."); SearchGlowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Find in Storage", "HighlightIntensity", 0.85f, new ConfigDescription("Blue glow strength on matching chests. Increase if hard to see; decrease if too bright. 0 keeps only the blue tint. Default is 0.85.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); SortHeavyToReducedRows = ((BaseUnityPlugin)this).Config.Bind<bool>("Inventory", "SortHeaviestStacksToWeightReducedRows", false, "Player Sort button: place the heaviest eligible stacks in ExtraSlots' active weight-reduced inventory rows, including empty slots. Protects hotbar, equipped, quest, reserved and special slots. Requires ExtraSlots with weight reduction enabled; otherwise normal sorting is used. False keeps alphabetical sorting."); UniformLabelSize = ((BaseUnityPlugin)this).Config.Bind<bool>("Chest Labels", "UseUniformTextSize", true, "Use the smallest fitted font size among currently loaded chest labels for every chest label. True: consistent text size. False: each label sizes itself independently. Recalculated as chests load or labels change; wrapping stays enabled."); Craft = ((BaseUnityPlugin)this).Config.Bind<bool>("Crafting", "Enabled", true, "Use accessible nearby chests for recipes and manual machine inputs."); Automate = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "Enabled", true, "Operate linked vanilla machines while this client owns and loads them."); StackKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "QuickStack", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Stack unprotected inventory items into matching nearby storage."); ReserveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "ReserveSlot", new KeyboardShortcut((KeyCode)325, (KeyCode[])(object)new KeyCode[2] { (KeyCode)308, (KeyCode)304 }), "Toggle protection on the hovered player inventory slot, including an empty slot."); InputKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "LinkInputOrFuel", new KeyboardShortcut((KeyCode)323, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Select the machine input or fuel control, then a chest within 30 seconds."); OutputKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "LinkOutput", new KeyboardShortcut((KeyCode)324, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Select a machine, then a chest within 30 seconds."); ClearKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "RemoveLinkModifier", (KeyCode)304, "Hold along with a link gesture to remove the selected chest binding."); ShowVfx = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "ShowLinkVfx", true, "Show connection lines and the selected control highlight. Automation is unaffected."); VfxKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "ToggleLinkVfx", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggle production connection visuals and save the setting."); RepairKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "RepairAll", new KeyboardShortcut((KeyCode)59, Array.Empty<KeyCode>()), "Repair loaded building pieces within 100 metres, respecting wards."); patches = new Harmony("local.WorkshopWorker"); patches.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Workshop Worker 1.0.2 by Daxtillion loaded; client only."); } private void Update() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !((Character)Player.m_localPlayer).IsOwner()) { StorageSearch.Clear(); return; } try { if (Time.unscaledTime >= scanAt) { scanAt = Time.unscaledTime + 2f; Chests = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); Machines = Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0).Cast<Component>().Concat((IEnumerable<Component>)(object)Object.FindObjectsByType<CookingStation>((FindObjectsSortMode)0)) .Concat((IEnumerable<Component>)(object)Object.FindObjectsByType<Fermenter>((FindObjectsSortMode)0)) .Concat((IEnumerable<Component>)(object)Object.FindObjectsByType<Fireplace>((FindObjectsSortMode)0)) .ToArray(); ChestUi.RefreshLabels(); } ChestAccess.Tick(); KeyboardShortcut value; if (!ChestUi.BlockGameplayInput) { value = RepairKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && (bool)GameApi.Call(Player.m_localPlayer, "TakeInput")) { Repairs.Begin(); } } Repairs.Tick(); Reservations.Tick(); ChestUi.Tick(); StorageSearch.Tick(); if (!ChestUi.BlockGameplayInput && !ChestUi.Editing && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus())) { value = StackKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Storage.Begin(); } } Storage.Tick(); Production.Gestures(); if (!ChestUi.BlockGameplayInput && !ChestUi.Editing && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus())) { value = VfxKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ShowVfx.Value = !ShowVfx.Value; ((BaseUnityPlugin)this).Config.Save(); Say("Connection visuals " + (ShowVfx.Value ? "on." : "off.")); } } if (!(Time.unscaledTime >= workAt)) { return; } workAt = Time.unscaledTime + 1f; if (Craft.Value && (InventoryGui.IsVisible() || Object.op_Implicit((Object)(object)Production.HoverMachine()))) { foreach (Container item in ChestAccess.Near(((Component)Player.m_localPlayer).transform.position)) { ChestAccess.Ready(item); } } if (Automate.Value) { Production.Tick(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } private void LateUpdate() { ChestUi.PositionSearch(); StorageSearchDim.Update(); } private void OnDestroy() { Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } ChestUi.Dispose(); Production.Dispose(); Self = null; } internal static void Say(string text) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Workshop Worker: " + text, 0, (Sprite)null, false); } } internal static void Log(string text) { Plugin self = Self; if (self != null) { ((BaseUnityPlugin)self).Logger.LogWarning((object)text); } } internal static void LogInfo(string text) { Plugin self = Self; if (self != null) { ((BaseUnityPlugin)self).Logger.LogInfo((object)text); } } } internal static class GameApi { internal static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; internal static T Get<T>(object obj, string name) { return (T)obj.GetType().GetField(name, Fields).GetValue(obj); } internal static object Call(object obj, string name, params object[] args) { return AccessTools.Method(obj.GetType(), name, (Type[])null, (Type[])null).Invoke(obj, args); } internal static ZNetView View(Component obj) { Container val = (Container)(object)((obj is Container) ? obj : null); if (val == null || !Object.op_Implicit((Object)(object)val.m_rootObjectOverride)) { if (!Object.op_Implicit((Object)(object)obj)) { return null; } return obj.GetComponent<ZNetView>(); } return val.m_rootObjectOverride; } internal static bool Owned(Component obj) { ZNetView val = View(obj); if (Object.op_Implicit((Object)(object)val) && val.IsValid()) { return val.IsOwner(); } return false; } internal static void Changed(Inventory inventory) { Call(inventory, "Changed", false, false); } internal static bool Nearby(Component obj, Vector3 center) { //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) //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) if (Object.op_Implicit((Object)(object)obj)) { Vector3 val = obj.transform.position - center; return ((Vector3)(ref val)).sqrMagnitude <= Plugin.Range.Value * Plugin.Range.Value; } return false; } } internal static class Production { private const string Key = "WorkshopWorker.links.v2"; private const string IdentityKey = "WorkshopWorker.endpoint.v1"; private static string savedJson; private static string savedWorld; private static readonly Dictionary<LinkEndpoint, Component> resolved = new Dictionary<LinkEndpoint, Component>(); private static Component selection; private static Component completedMachine; private static float lingerUntil; private static string role; private static bool removing; private static float expires; private static LinkBook book = new LinkBook(); private static Player savedPlayer; private static readonly List<LineRenderer> lines = new List<LineRenderer>(); private static Material lineMaterial; internal static bool LinkHeld { get { //IL_000c: 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) if (!InventoryGui.IsVisible()) { if (!LinkModifier(Plugin.InputKey.Value)) { return LinkModifier(Plugin.OutputKey.Value); } return true; } return false; } } private static LinkEndpoint Snapshot(Component c) { //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_006b: 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_0083: Unknown result type (might be due to invalid IL or missing references) ZNetView obj = GameApi.View(c); ZDO val = ((obj != null) ? obj.GetZDO() : null); if (val == null || !Object.op_Implicit((Object)(object)ZNet.instance)) { return null; } Vector3 position = val.GetPosition(); return new LinkEndpoint { world = ZNet.instance.GetWorldUID().ToString(), guid = val.GetString("WorkshopWorker.endpoint.v1", ""), prefab = val.GetPrefab(), x = position.x, y = position.y, z = position.z }; } private static LinkEndpoint Capture(Component c) { LinkEndpoint linkEndpoint = Snapshot(c); if (linkEndpoint == null) { return null; } Promote(linkEndpoint, c); resolved[linkEndpoint] = c; return linkEndpoint; } private static bool Promote(LinkEndpoint endpoint, Component c) { ZNetView obj = GameApi.View(c); ZDO val = ((obj != null) ? obj.GetZDO() : null); if (val == null || !string.IsNullOrEmpty(endpoint.guid)) { return false; } string text = val.GetString("WorkshopWorker.endpoint.v1", ""); if (string.IsNullOrEmpty(text) && GameApi.Owned(c)) { text = Guid.NewGuid().ToString("N"); val.Set("WorkshopWorker.endpoint.v1", text); } if (string.IsNullOrEmpty(text)) { return false; } endpoint.guid = text; return true; } private static bool Matches(LinkEndpoint endpoint, Component c) { if (endpoint == null || !Object.op_Implicit((Object)(object)c) || endpoint.world != savedWorld) { return false; } if (resolved.TryGetValue(endpoint, out var value) && Object.op_Implicit((Object)(object)value)) { if ((Object)(object)value != (Object)(object)c) { return false; } } else { if (!endpoint.Matches(Snapshot(c))) { return false; } resolved[endpoint] = c; } if (Promote(endpoint, c)) { Save(); } return true; } private static void Save() { if (Object.op_Implicit((Object)(object)savedPlayer)) { savedJson = ProductionLinkCodec.Serialize(book); savedPlayer.m_customData["WorkshopWorker.links.v2"] = savedJson; } } private static void Load() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)ZNet.instance)) { return; } localPlayer.m_customData.TryGetValue("WorkshopWorker.links.v2", out var value); string text = ZNet.instance.GetWorldUID().ToString(); if (!((Object)(object)savedPlayer == (Object)(object)localPlayer) || !(savedWorld == text) || !(savedJson == value)) { savedPlayer = localPlayer; savedWorld = text; savedJson = value; selection = null; completedMachine = null; resolved.Clear(); ClearVisuals(); try { book = (string.IsNullOrEmpty(value) ? new LinkBook() : ProductionLinkCodec.Deserialize(value)); } catch (Exception ex) { Plugin.Log("Could not read production links: " + ex.Message); book = new LinkBook(); } if (book == null) { book = new LinkBook(); } LinkBook linkBook = book; if (linkBook.links == null) { linkBook.links = new List<MachineLink>(); } book.links.RemoveAll((MachineLink l) => l == null || l.machine == null || l.chest == null); Plugin.LogInfo("Loaded " + book.links.Count + " production links from character save."); } } private static MachineLink[] MachineLinks(Component machine) { Load(); return book.links.Where((MachineLink l) => Matches(l.machine, machine)).ToArray(); } internal static string Summary(Component machine) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return ""; } Smelter val = (Smelter)(object)((machine is Smelter) ? machine : null); int num; if (val == null || !Object.op_Implicit((Object)(object)val.m_fuelItem) || val.m_maxFuel <= 0) { CookingStation val2 = (CookingStation)(object)((machine is CookingStation) ? machine : null); if (val2 == null || !val2.m_useFuel || !Object.op_Implicit((Object)(object)val2.m_fuelItem)) { Fireplace val3 = (Fireplace)(object)((machine is Fireplace) ? machine : null); num = ((val3 != null && val3.m_canRefill && !val3.m_infiniteFuel && Object.op_Implicit((Object)(object)val3.m_fuelItem)) ? 1 : 0); goto IL_007c; } } num = 1; goto IL_007c; IL_007c: bool fuel = (byte)num != 0; return ProductionLinkSummary.Format(MachineLinks(machine), !(machine is Fireplace), fuel, !(machine is Fireplace)); } internal static Component HoverMachine() { Player localPlayer = Player.m_localPlayer; GameObject val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetHoverObject() : null); if (!Object.op_Implicit((Object)(object)val)) { return null; } return (Component)(val.GetComponentInParent<Smelter>() ?? val.GetComponentInParent<CookingStation>() ?? ((object)val.GetComponentInParent<Fermenter>()) ?? ((object)val.GetComponentInParent<Fireplace>())); } private static bool Down(KeyboardShortcut key) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(((KeyboardShortcut)(ref key)).MainKey)) { return ((KeyboardShortcut)(ref key)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } private static bool LinkModifier(KeyboardShortcut key) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!((KeyboardShortcut)(ref key)).Modifiers.Any()) { if (Object.op_Implicit((Object)(object)HoverMachine()) || Object.op_Implicit((Object)(object)selection)) { return Input.GetKey(((KeyboardShortcut)(ref key)).MainKey); } return false; } return ((KeyboardShortcut)(ref key)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } internal static void Gestures() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) if (ChestUi.BlockGameplayInput) { return; } Load(); if (Object.op_Implicit((Object)(object)selection) && Time.unscaledTime > expires) { selection = null; Plugin.Say("Link selection expired."); } if (Object.op_Implicit((Object)(object)completedMachine) && Time.unscaledTime >= lingerUntil) { completedMachine = null; } bool flag; Component val; int num2; if (!InventoryGui.IsVisible() && !Chat.instance.HasFocus()) { flag = Down(Plugin.OutputKey.Value); bool flag2 = Down(Plugin.InputKey.Value); if (flag || flag2) { GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject(); Container chest = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<Container>() : null); if (Object.op_Implicit((Object)(object)selection) && Object.op_Implicit((Object)(object)chest)) { if (role == "Output" != flag) { Plugin.Say("Use the gesture matching the selected role."); return; } if (!ChestAccess.Allowed(chest) || !GameApi.Nearby((Component)(object)chest, selection.transform.position)) { Plugin.Say("Chest is out of range or access is denied."); } else { LinkEndpoint linkEndpoint = Capture(selection); LinkEndpoint linkEndpoint2 = Capture((Component)(object)chest); if (linkEndpoint == null || linkEndpoint2 == null) { return; } book.links.RemoveAll((MachineLink l) => Matches(l.machine, selection) && Matches(l.chest, (Component)(object)chest) && l.role == role); int num; if (!removing) { num = (Input.GetKey(Plugin.ClearKey.Value) ? 1 : 0); if (num == 0) { book.links.Add(new MachineLink { machine = linkEndpoint, chest = linkEndpoint2, role = role }); } } else { num = 1; } Save(); completedMachine = selection; lingerUntil = Time.unscaledTime + 5f; selection = null; Plugin.Say(((num != 0) ? "Removed " : "Added ") + role + " chest."); } } else { val = HoverMachine(); if (Object.op_Implicit((Object)(object)val) && PrivateArea.CheckAccess(val.transform.position, 0f, false, false)) { Switch componentInParent = hoverObject.GetComponentInParent<Switch>(); if (!(val is Fireplace)) { Smelter val2 = (Smelter)(object)((val is Smelter) ? val : null); if (val2 == null || !Object.op_Implicit((Object)(object)componentInParent) || !((Object)(object)componentInParent == (Object)(object)val2.m_addWoodSwitch)) { CookingStation val3 = (CookingStation)(object)((val is CookingStation) ? val : null); num2 = ((val3 != null && Object.op_Implicit((Object)(object)componentInParent) && (Object)(object)componentInParent == (Object)(object)val3.m_addFuelSwitch) ? 1 : 0); goto IL_029a; } } num2 = 1; goto IL_029a; } } } } goto IL_0313; IL_0313: Component val4 = HoverMachine(); Draw((!Plugin.ShowVfx.Value) ? null : (Object.op_Implicit((Object)(object)val4) ? val4 : (Object.op_Implicit((Object)(object)selection) ? selection : completedMachine))); return; IL_029a: bool flag3 = (byte)num2 != 0; selection = val; completedMachine = null; role = (flag ? "Output" : (flag3 ? "Fuel" : "Input")); removing = Input.GetKey(Plugin.ClearKey.Value); expires = Time.unscaledTime + 30f; Plugin.Say((removing ? "Remove " : "Link ") + role + ": use the same gesture on a chest within 30 seconds."); goto IL_0313; } internal static IEnumerable<Container> Linked(Component machine, string kind) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) MachineLink[] links = (from l in MachineLinks(machine) where l.role == kind select l).ToArray(); return from c in ChestAccess.Near(machine.transform.position) where links.Any((MachineLink l) => Matches(l.chest, (Component)(object)c)) select c; } internal static IEnumerable<ItemDrop> Ingredients(Component m, bool fuel) { Smelter val = (Smelter)(object)((m is Smelter) ? m : null); if (val != null) { if (!fuel) { return from i in val.m_conversion select i.m_from into i where Object.op_Implicit((Object)(object)i) select i; } return ((IEnumerable<ItemDrop>)(object)new ItemDrop[1] { val.m_fuelItem }).Where((ItemDrop i) => Object.op_Implicit((Object)(object)i)); } CookingStation val2 = (CookingStation)(object)((m is CookingStation) ? m : null); if (val2 != null) { if (!fuel) { return from i in val2.m_conversion select i.m_from into i where Object.op_Implicit((Object)(object)i) select i; } return ((IEnumerable<ItemDrop>)(object)new ItemDrop[1] { val2.m_fuelItem }).Where((ItemDrop i) => Object.op_Implicit((Object)(object)i)); } Fermenter val3 = (Fermenter)(object)((m is Fermenter) ? m : null); if (val3 != null) { return from i in val3.m_conversion select i.m_from into i where Object.op_Implicit((Object)(object)i) select i; } Fireplace val4 = (Fireplace)(object)((m is Fireplace) ? m : null); if (val4 != null) { return ((IEnumerable<ItemDrop>)(object)new ItemDrop[1] { val4.m_fuelItem }).Where((ItemDrop i) => Object.op_Implicit((Object)(object)i)); } return Array.Empty<ItemDrop>(); } private static void Feed(Component machine, string kind, Func<bool> room, string rpc, Func<ItemData, object[]> args) { if (!room()) { return; } HashSet<string> allowed = new HashSet<string>(from i in Ingredients(machine, kind == "Fuel") select ((Object)i).name); foreach (Container item in Linked(machine, kind)) { if (ChestAccess.Ready(item)) { ItemData val = ((IEnumerable<ItemData>)item.GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => allowed.Contains(Storage.ItemId(i)) && i.m_worldLevel >= Game.m_worldLevel)); if (val != null && GameApi.Owned(machine) && room()) { GameApi.Call(machine, rpc, args(val)); item.GetInventory().RemoveItem(val, 1); break; } } } } internal static void Tick() { //IL_0051: 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_0418: Unknown result type (might be due to invalid IL or missing references) Load(); Component[] machines = Plugin.Machines; Smelter s = default(Smelter); CookingStation c = default(CookingStation); Fermenter f = default(Fermenter); Fireplace firePlace = default(Fireplace); foreach (Component m in machines) { if (!Object.op_Implicit((Object)(object)m) || !GameApi.Owned(m) || !GameApi.Nearby(m, ((Component)Player.m_localPlayer).transform.position) || !PrivateArea.CheckAccess(m.transform.position, 0f, false, false)) { continue; } foreach (Container item in Linked(m, "Output")) { ChestAccess.Ready(item); } ref Smelter reference = ref s; Component obj = m; reference = (Smelter)(object)((obj is Smelter) ? obj : null); if (s != null) { Feed((Component)(object)s, "Input", () => (int)GameApi.Call(s, "GetQueueSize") < s.m_maxOre, "RPC_AddOre", (ItemData val2) => new object[3] { ZNet.GetUID(), Storage.ItemId(val2), val2.m_cheated }); if (Object.op_Implicit((Object)(object)s.m_fuelItem) && s.m_maxFuel > 0) { Feed((Component)(object)s, "Fuel", () => (float)GameApi.Call(s, "GetFuel") <= (float)s.m_maxFuel - 1f, "RPC_AddFuel", (ItemData val2) => new object[1] { ZNet.GetUID() }); } int num = (int)GameApi.Call(s, "GetProcessedQueueSize"); string ore = GameApi.View((Component)(object)s).GetZDO().GetString(ZDOVars.s_spawnOre, ""); ItemDrop prefab = ((IEnumerable<ItemConversion>)s.m_conversion).FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion x) => !Object.op_Implicit((Object)(object)x.m_from) || ((Object)x.m_from).name == ore))?.m_to; if (num > 0 && OutputRoom((Component)(object)s, prefab, num)) { GameApi.Call(s, "RPC_EmptyProcessed", ZNet.GetUID()); } continue; } ref CookingStation reference2 = ref c; Component obj2 = m; reference2 = (CookingStation)(object)((obj2 is CookingStation) ? obj2 : null); if (c != null) { if (!c.m_requireFire || (bool)GameApi.Call(c, "IsFireLit")) { Feed((Component)(object)c, "Input", () => (int)GameApi.Call(c, "GetFreeSlot") >= 0, "RPC_AddItem", (ItemData val2) => new object[3] { ZNet.GetUID(), Storage.ItemId(val2), val2.m_cheated }); } if (c.m_useFuel && Object.op_Implicit((Object)(object)c.m_fuelItem)) { Feed((Component)(object)c, "Fuel", () => (float)GameApi.Call(c, "GetFuel") <= (float)c.m_maxFuel - 1f, "RPC_AddFuel", (ItemData val2) => new object[1] { ZNet.GetUID() }); } for (int num2 = 0; num2 < c.m_slots.Length; num2++) { object[] array = new object[5] { num2, null, 0f, null, false }; GameApi.Call(c, "GetSlot", array); string text = (string)array[1]; if (!string.IsNullOrEmpty(text) && (bool)GameApi.Call(c, "IsItemDone", text)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); ItemDrop prefab2 = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (OutputRoom((Component)(object)c, prefab2, 1, (bool)array[4])) { GameApi.Call(c, "RPC_RemoveDoneItem", ZNet.GetUID(), ((Component)Player.m_localPlayer).transform.position, 1); } break; } } continue; } ref Fermenter reference3 = ref f; Component obj3 = m; reference3 = (Fermenter)(object)((obj3 is Fermenter) ? obj3 : null); if (f != null) { GameApi.Call(f, "UpdateCover", 0f, true); if (GameApi.Get<bool>(f, "m_hasRoof") && !GameApi.Get<bool>(f, "m_exposed")) { Feed((Component)(object)f, "Input", () => (int)GameApi.Call(f, "GetContent") == 0, "RPC_AddItem", (ItemData val2) => new object[3] { ZNet.GetUID(), StringExtensionMethods.GetStableHashCode(Storage.ItemId(val2)), val2.m_cheated }); } if (GameApi.Call(f, "GetStatus").ToString() == "Ready") { int content = (int)GameApi.Call(f, "GetContent"); ItemConversion val = ((IEnumerable<ItemConversion>)f.m_conversion).FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion x) => StringExtensionMethods.GetStableHashCode(((Object)x.m_from).name) == content)); if (val != null && OutputRoom((Component)(object)f, val.m_to, val.m_producedItems)) { GameApi.Call(f, "RPC_Tap", ZNet.GetUID()); } } continue; } ref Fireplace reference4 = ref firePlace; Component obj4 = m; reference4 = (Fireplace)(object)((obj4 is Fireplace) ? obj4 : null); if (firePlace != null && Object.op_Implicit((Object)(object)firePlace.m_fuelItem) && !firePlace.m_infiniteFuel && firePlace.m_canRefill) { Feed(m, "Fuel", () => GameApi.View(m).GetZDO().GetFloat(ZDOVars.s_fuel, 0f) <= firePlace.m_maxFuel - 1f, "RPC_AddFuel", (ItemData val2) => new object[1] { ZNet.GetUID() }); } } } private static bool OutputRoom(Component machine, ItemDrop prefab, int amount, bool cheated = false) { if (!Object.op_Implicit((Object)(object)prefab)) { return false; } ItemData item = prefab.m_itemData.Clone(); item.m_dropPrefab = ((Component)prefab).gameObject; item.m_worldLevel = (byte)Game.m_worldLevel; ZDO zDO = GameApi.View(machine).GetZDO(); item.m_cheated = (cheated || zDO.GetBool(ZDOVars.s_cheatedQueued, false) || zDO.GetBool(ZDOVars.s_cheated, false)) && !PlayerProfile.s_bypassCheatChecks; CookingStation val = (CookingStation)(object)((machine is CookingStation) ? machine : null); if (val != null) { if (val.m_spawnFullDurability) { item.m_durability = item.m_shared.m_maxDurability; } if (val.m_recordCrafter) { item.m_crafterID = Player.m_localPlayer.GetPlayerID(); item.m_crafterName = Player.m_localPlayer.GetPlayerName(); } } return Linked(machine, "Output").Where(ChestAccess.Ready).Sum((Container c) => Transfer.Capacity(c.GetInventory(), item)) >= amount; } internal static void Deposit(Component machine, ItemDrop drop) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)machine) || !Object.op_Implicit((Object)(object)drop) || !GameApi.Owned(machine) || !GameApi.Owned((Component)(object)drop) || !Plugin.Automate.Value || !PrivateArea.CheckAccess(machine.transform.position, 0f, false, false)) { return; } Container[] array = Linked(machine, "Output").Where(ChestAccess.Ready).ToArray(); if (array.Sum((Container c) => Transfer.Capacity(c.GetInventory(), drop.m_itemData)) < drop.m_itemData.m_stack) { return; } Inventory val = new Inventory("Workshop Worker output", (Sprite)null, 1, 1); val.GetAllItems().Add(drop.m_itemData); try { Container[] array2 = array; foreach (Container val2 in array2) { if (!ChestAccess.Ready(val2)) { break; } Transfer.Move(val, val2.GetInventory(), drop.m_itemData, drop.m_itemData.m_stack); if (drop.m_itemData.m_stack == 0) { break; } } } finally { if (drop.m_itemData.m_stack == 0) { ZNetScene.instance.Destroy(((Component)drop).gameObject); } else { GameApi.Call(drop, "Save"); } } } private static void Draw(Component m) { //IL_010b: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) int num = 0; if (Object.op_Implicit((Object)(object)m)) { string[] array = new string[3] { "Input", "Fuel", "Output" }; foreach (string text in array) { foreach (Container item in Linked(m, text)) { Line(num++, m.transform.position + Vector3.up, ((Component)item).transform.position + Vector3.up * 0.5f, (Color)((text == "Input") ? Color.cyan : ((text == "Fuel") ? new Color(1f, 0.5f, 0f) : Color.green))); } } if ((Object)(object)selection == (Object)(object)m) { Vector3 val = m.transform.position + Vector3.up; Smelter val2 = (Smelter)(object)((m is Smelter) ? m : null); if (val2 != null) { Switch obj = ((role == "Fuel") ? val2.m_addWoodSwitch : val2.m_addOreSwitch); val = ((obj != null) ? ((Component)obj).transform.position : val); } CookingStation val3 = (CookingStation)(object)((m is CookingStation) ? m : null); if (val3 != null) { Switch obj2 = ((role == "Fuel") ? val3.m_addFuelSwitch : val3.m_addFoodSwitch); val = ((obj2 != null) ? ((Component)obj2).transform.position : val); } for (int j = 0; j < 16; j++) { Line(num++, val + new Vector3(Mathf.Cos((float)j * MathF.PI / 8f), 0.1f, Mathf.Sin((float)j * MathF.PI / 8f)) * 0.22f, val + new Vector3(Mathf.Cos((float)(j + 1) * MathF.PI / 8f), 0.1f, Mathf.Sin((float)(j + 1) * MathF.PI / 8f)) * 0.22f, Color.yellow); } } } for (int k = num; k < lines.Count; k++) { if (Object.op_Implicit((Object)(object)lines[k])) { ((Component)lines[k]).gameObject.SetActive(false); } } } private static void Line(int index, Vector3 start, Vector3 end, Color tint) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)lineMaterial)) { lineMaterial = new Material(Shader.Find("Sprites/Default")); } LineRenderer obj = LiveObjectPool.Get(lines, index, (LineRenderer line) => Object.op_Implicit((Object)(object)line), delegate { //IL_0005: Unknown result type (might be due to invalid IL or missing references) LineRenderer obj2 = new GameObject("WorkshopWorkerLink").AddComponent<LineRenderer>(); obj2.positionCount = 2; obj2.useWorldSpace = true; float startWidth = (obj2.endWidth = 0.035f); obj2.startWidth = startWidth; return obj2; }); ((Renderer)obj).sharedMaterial = lineMaterial; ((Component)obj).gameObject.SetActive(true); Color startColor = (obj.endColor = tint); obj.startColor = startColor; obj.SetPosition(0, start); obj.SetPosition(1, end); } private static void ClearVisuals() { foreach (LineRenderer line in lines) { if (Object.op_Implicit((Object)(object)line)) { Object.Destroy((Object)(object)((Component)line).gameObject); } } lines.Clear(); if (Object.op_Implicit((Object)(object)lineMaterial)) { Object.Destroy((Object)(object)lineMaterial); } lineMaterial = null; } internal static void Dispose() { ClearVisuals(); resolved.Clear(); selection = null; completedMachine = null; savedPlayer = null; savedJson = null; savedWorld = null; book = new LinkBook(); } } internal sealed class OutputCapture { internal static OutputCapture Current; internal Component machine; internal OutputCapture previous; internal readonly List<ItemDrop> drops = new List<ItemDrop>(); } [HarmonyPatch] internal static class ProductionHoverLinks { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Switch), "GetHoverText", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(CookingStation), "GetHoverText", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Fermenter), "GetHoverText", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Fireplace), "GetHoverText", (Type[])null, (Type[])null); } private static void Postfix(Component __instance, ref string __result) { Component val = (Component)((__instance is Switch) ? (__instance.GetComponentInParent<Smelter>() ?? __instance.GetComponentInParent<CookingStation>() ?? ((object)__instance.GetComponentInParent<Fermenter>()) ?? ((object)__instance.GetComponentInParent<Fireplace>())) : __instance); if (Object.op_Implicit((Object)(object)val)) { string text = Production.Summary(val); if (text.Length > 0 && !(__result ?? "").Contains(text)) { __result = __result + "\n" + text; } } } } [HarmonyPatch] internal static class NativeOutput { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Smelter), "Spawn", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(CookingStation), "SpawnItem", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Fermenter), "DelayedTap", (Type[])null, (Type[])null); } private static void Prefix(Component __instance, out OutputCapture __state) { __state = new OutputCapture { machine = __instance, previous = OutputCapture.Current }; OutputCapture.Current = __state; } private static Exception Finalizer(Exception __exception, OutputCapture __state) { OutputCapture.Current = __state.previous; if (__exception == null) { foreach (ItemDrop drop in __state.drops) { try { Production.Deposit(__state.machine, drop); } catch (Exception ex) { Plugin.Log("Output routing failed: " + ex); } } } return __exception; } } [HarmonyPatch(typeof(ItemDrop), "OnCreateNew", new Type[] { typeof(ItemDrop), typeof(bool) })] internal static class CaptureCreatedDrop { private static void Postfix(ItemDrop __0) { if (Object.op_Implicit((Object)(object)__0)) { OutputCapture.Current?.drops.Add(__0); } } } [HarmonyPatch(typeof(Player), "PlayerAttackInput")] internal static class LinkAttackGuard { private static void Prefix(Player __instance, ref bool ___m_attack, ref bool ___m_attackHold, ref bool ___m_secondaryAttack, ref bool ___m_secondaryAttackHold, ref float ___m_queuedAttackTimer, ref float ___m_queuedSecondAttackTimer) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Production.LinkHeld) { ___m_attack = (___m_attackHold = (___m_secondaryAttack = (___m_secondaryAttackHold = false))); ___m_queuedAttackTimer = (___m_queuedSecondAttackTimer = 0f); } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class LinkControlsGuard { [HarmonyPriority(0)] private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Production.LinkHeld) { attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (block = (blockHold = false))))); } } } [DataContract] internal sealed class LinkEndpoint { [DataMember(IsRequired = true)] public string world; [DataMember] public string guid; [DataMember(IsRequired = true)] public int prefab; [DataMember(IsRequired = true)] public float x; [DataMember(IsRequired = true)] public float y; [DataMember(IsRequired = true)] public float z; internal string Identity { get { if (string.IsNullOrEmpty(guid)) { return FormattableString.Invariant($"{prefab}:{x:R}:{y:R}:{z:R}"); } return guid; } } internal bool Matches(LinkEndpoint other) { if (other == null || world != other.world || prefab != other.prefab) { return false; } if (!string.IsNullOrEmpty(guid)) { return guid == other.guid; } if (Math.Abs(x - other.x) < 0.01f && Math.Abs(y - other.y) < 0.01f) { return Math.Abs(z - other.z) < 0.01f; } return false; } } [DataContract] internal sealed class MachineLink { [DataMember(IsRequired = true)] public LinkEndpoint machine; [DataMember(IsRequired = true)] public LinkEndpoint chest; [DataMember(IsRequired = true)] public string role; } [DataContract] internal sealed class LinkBook { [DataMember(IsRequired = true)] public List<MachineLink> links = new List<MachineLink>(); } internal static class ProductionLinkCodec { internal static string Serialize(LinkBook book) { using MemoryStream memoryStream = new MemoryStream(); new DataContractJsonSerializer(typeof(LinkBook)).WriteObject(memoryStream, book); string text = Encoding.UTF8.GetString(memoryStream.ToArray()); if (Deserialize(text).links.Count != book.links.Count) { throw new SerializationException("Production link serialization lost records."); } return text; } internal static LinkBook Deserialize(string json) { using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)); LinkBook linkBook = (LinkBook)new DataContractJsonSerializer(typeof(LinkBook)).ReadObject(stream); if (linkBook?.links == null || linkBook.links.Any((MachineLink l) => l?.machine == null || l.chest == null || string.IsNullOrEmpty(l.machine.world) || string.IsNullOrEmpty(l.chest.world) || (!(l.role == "Input") && !(l.role == "Fuel") && !(l.role == "Output")))) { throw new SerializationException("Invalid production link records."); } return linkBook; } } internal static class ProductionLinkSummary { internal static string Format(IEnumerable<MachineLink> links, bool input, bool fuel, bool output) { List<string> list = new List<string>(); string[] array = new string[3] { "Input", "Fuel", "Output" }; foreach (string role in array) { if ((role == "Input") ? input : ((role == "Fuel") ? fuel : output)) { int num = (from l in links where l.role == role && l.chest != null select l.chest.Identity).Distinct().Count(); if (num > 0) { list.Add(role + ": " + num); } } } return string.Join(" ", list); } } internal static class Repairs { private static readonly Queue<WearNTear> pending = new Queue<WearNTear>(); private static Player actor; private static Vector3 center; private static int requested; internal static void Begin() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) actor = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)actor) || ((Character)actor).IsDead()) { return; } center = ((Component)actor).transform.position; requested = 0; pending.Clear(); foreach (WearNTear item in Object.FindObjectsByType<WearNTear>((FindObjectsSortMode)0).Where(delegate(WearNTear w) { //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_001d: 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) if (Object.op_Implicit((Object)(object)((Component)w).GetComponent<Piece>())) { Vector3 val = ((Component)w).transform.position - center; return ((Vector3)(ref val)).sqrMagnitude <= 10000f; } return false; })) { pending.Enqueue(item); } if (pending.Count == 0) { Plugin.Say("No loaded structures within 100 m."); } } internal static void