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 CraftFromChestOptimized v1.0.0
despr0grammer.CraftFromChestOptimized.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.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 despr0grammer.CraftFromChestOptimized { internal static class ChestRegistry { private sealed class Entry { internal int Id; internal Container Container; internal Transform Transform; internal Transform Root; internal ZNetView NetView; internal Collider[] Colliders; } private struct Candidate { internal Container Container; internal float SqrDistance; } internal const float Radius = 20f; private static readonly List<Entry> Entries = new List<Entry>(64); private static readonly HashSet<int> Known = new HashSet<int>(); private static readonly List<Candidate> Scratch = new List<Candidate>(32); private static readonly Comparison<Candidate> ByDistance = (Candidate a, Candidate b) => a.SqrDistance.CompareTo(b.SqrDistance); private static int _pieceLayer = -2; private static int PieceLayer { get { if (_pieceLayer == -2) { _pieceLayer = LayerMask.NameToLayer("piece"); } return _pieceLayer; } } internal static void Register(Container container) { if (!((Object)(object)container == (Object)null) && Known.Add(((Object)container).GetInstanceID())) { Entries.Add(Build(container)); } } internal static void SeedFromScene() { Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { Register(array[i]); } } internal static void Prune() { for (int num = Entries.Count - 1; num >= 0; num--) { if ((Object)(object)Entries[num].Container == (Object)null) { RemoveAt(num); } } } internal static void Find(Vector3 center, long playerId, List<Container> result) { //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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) result.Clear(); Scratch.Clear(); float num = 400f; for (int num2 = Entries.Count - 1; num2 >= 0; num2--) { Entry entry = Entries[num2]; if ((Object)(object)entry.Container == (Object)null) { RemoveAt(num2); continue; } Vector3 val = entry.Transform.position - center; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude > num) { val = entry.Root.position - center; if (((Vector3)(ref val)).sqrMagnitude > num) { continue; } } if (IsUsable(entry, playerId)) { Scratch.Add(new Candidate { Container = entry.Container, SqrDistance = sqrMagnitude }); } } Scratch.Sort(ByDistance); for (int i = 0; i < Scratch.Count; i++) { result.Add(Scratch[i].Container); } } private static bool IsUsable(Entry entry, long playerId) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)entry.NetView == (Object)null || !entry.NetView.IsValid()) { return false; } Container container = entry.Container; if (container.GetInventory() == null) { return false; } if (!HasLiveCollider(entry)) { return false; } if (!GameAccess.CheckAccess(container, playerId)) { return false; } if (container.m_checkGuardStone) { return PrivateArea.CheckAccess(entry.Transform.position, 0f, false, false); } return true; } private static bool HasLiveCollider(Entry entry) { Collider[] colliders = entry.Colliders; foreach (Collider val in colliders) { if ((Object)(object)val != (Object)null && val.enabled && ((Component)val).gameObject.activeInHierarchy) { return true; } } return false; } private static void RemoveAt(int index) { Known.Remove(Entries[index].Id); int index2 = Entries.Count - 1; Entries[index] = Entries[index2]; Entries.RemoveAt(index2); } private static Entry Build(Container container) { ZNetView val = ((Component)container).GetComponent<ZNetView>(); if ((Object)(object)val == (Object)null) { val = ((Component)container).GetComponentInParent<ZNetView>(); } List<Collider> list = new List<Collider>(); int pieceLayer = PieceLayer; CollectResolved(container, ((Component)container).GetComponentsInChildren<Collider>(true), pieceLayer, list); Transform parent = ((Component)container).transform.parent; while ((Object)(object)parent != (Object)null) { CollectResolved(container, ((Component)parent).GetComponents<Collider>(), pieceLayer, list); parent = parent.parent; } Incinerator componentInParent = ((Component)container).GetComponentInParent<Incinerator>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.m_container == (Object)(object)container) { Collider[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren) { if (((Component)val2).gameObject.layer == pieceLayer && !list.Contains(val2)) { list.Add(val2); } } } return new Entry { Id = ((Object)container).GetInstanceID(), Container = container, Transform = ((Component)container).transform, Root = ((Component)container).transform.root, NetView = val, Colliders = list.ToArray() }; } private static void CollectResolved(Container owner, Collider[] candidates, int layer, List<Collider> into) { foreach (Collider val in candidates) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.layer == layer && !into.Contains(val)) { Container val2 = ((Component)val).GetComponentInParent<Container>(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).GetComponentInChildren<Container>(); } if ((Object)(object)val2 == (Object)(object)owner) { into.Add(val); } } } } } internal static class ChestScope { private readonly struct CountKey : IEquatable<CountKey> { private readonly string _name; private readonly int _quality; internal CountKey(string name, int quality) { _name = name; _quality = quality; } public bool Equals(CountKey other) { if (_quality == other._quality) { return _name == other._name; } return false; } public override bool Equals(object obj) { if (obj is CountKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (_name.GetHashCode() * 397) ^ _quality; } } private static int _depth; private static bool _bypass; private static Player _player; private static Inventory _playerInventory; private static readonly List<Container> Chests = new List<Container>(32); private static readonly List<Container> NoChests = new List<Container>(0); private static int _chestsFrame = -1; private static readonly Dictionary<CountKey, int> Counts = new Dictionary<CountKey, int>(); private static int _countsFrame = -1; private static int _countsVersion; private static int _version; internal static bool Enabled { get; private set; } = true; internal static bool Active { get { if (_depth > 0) { return !_bypass; } return false; } } internal static void SetEnabled(bool enabled) { Enabled = enabled; _chestsFrame = -1; _countsFrame = -1; Chests.Clear(); Counts.Clear(); } internal static bool Enter(Player player) { if (!Enabled || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return false; } if (_depth == 0) { _player = player; _playerInventory = ((Humanoid)player).GetInventory(); } _depth++; return true; } internal static void Exit(bool entered) { if (entered && _depth > 0) { _depth--; if (_depth == 0) { _player = null; _playerInventory = null; } } } internal static void EndFrameCheck() { if (_depth != 0 || _bypass) { Plugin.Log.LogWarning((object)"Craft scope was left open; resetting it."); _depth = 0; _bypass = false; _player = null; _playerInventory = null; } } internal static int CountInChests(string name, int quality = -1) { List<Container> list = NearbyChests(); if (list.Count == 0) { return 0; } if (name == null) { return Sum(list, null, quality); } int frameCount = Time.frameCount; if (_countsFrame != frameCount || _countsVersion != _version) { Counts.Clear(); _countsFrame = frameCount; _countsVersion = _version; } CountKey key = new CountKey(name, quality); if (!Counts.TryGetValue(key, out var value)) { value = Sum(list, name, quality); Counts[key] = value; } return value; } internal static void AddChestCount(Inventory inventory, string name, int quality, ref int result) { if (Active && inventory == _playerInventory) { result += CountInChests(name, quality); } } internal static bool TryRemoveFromChests(Inventory inventory, string name, int amount, int itemQuality, bool worldLevelBased) { if (!Active || inventory == null || inventory != _playerInventory || amount <= 0) { return false; } _bypass = true; try { int num = Mathf.Min(inventory.CountItems(name, itemQuality, worldLevelBased), amount); if (num > 0) { inventory.RemoveItem(name, num, itemQuality, worldLevelBased); } int num2 = amount - num; if (num2 > 0) { TakeFromChests(name, num2, itemQuality); } } finally { _bypass = false; _version++; } return true; } private static List<Container> NearbyChests() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) Player player = _player; if ((Object)(object)player == (Object)null) { return NoChests; } int frameCount = Time.frameCount; if (_chestsFrame != frameCount) { _chestsFrame = frameCount; ChestRegistry.Find(((Component)player).transform.position, player.GetPlayerID(), Chests); } return Chests; } private static int Sum(List<Container> chests, string name, int quality) { int num = 0; for (int i = 0; i < chests.Count; i++) { Inventory inventory = chests[i].GetInventory(); if (inventory != null) { num += inventory.CountItems(name, quality, true); } } return num; } private static void TakeFromChests(string name, int amount, int quality) { List<Container> list = NearbyChests(); int num = amount; for (int i = 0; i < list.Count; i++) { if (num <= 0) { break; } Container val = list[i]; Inventory inventory = val.GetInventory(); if (inventory != null) { int num2 = inventory.CountItems(name, quality, true); if (num2 > 0) { int num3 = Mathf.Min(num2, num); inventory.RemoveItem(name, num3, quality, true); GameAccess.Save(val); num -= num3; } } } } } internal static class GameAccess { private static readonly Func<Container, long, bool> CheckAccessImpl = Bind<Func<Container, long, bool>>(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }); private static readonly Action<Container> SaveImpl = Bind<Action<Container>>(typeof(Container), "Save", Array.Empty<Type>()); private static readonly Action<InventoryGui, bool> UpdateCraftingPanelImpl = Bind<Action<InventoryGui, bool>>(typeof(InventoryGui), "UpdateCraftingPanel", new Type[1] { typeof(bool) }); internal static bool Ready { get { if (CheckAccessImpl != null) { return SaveImpl != null; } return false; } } internal static bool CheckAccess(Container container, long playerId) { if (CheckAccessImpl == null) { return false; } try { return CheckAccessImpl(container, playerId); } catch (Exception) { return false; } } internal static void Save(Container container) { SaveImpl?.Invoke(container); } internal static void RefreshCraftingPanel(InventoryGui gui) { if ((Object)(object)gui == (Object)null || UpdateCraftingPanelImpl == null) { return; } try { UpdateCraftingPanelImpl(gui, arg2: false); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not refresh the crafting panel: " + ex.Message)); } } private static T Bind<T>(Type owner, string name, params Type[] args) where T : class { MethodInfo methodInfo = AccessTools.Method(owner, name, args, (Type[])null); if (!(methodInfo == null)) { return (T)(object)Delegate.CreateDelegate(typeof(T), methodInfo); } return null; } } [HarmonyPatch(typeof(Container), "Awake")] internal static class ContainerAwakePatch { private static bool _reported; private static void Postfix(Container __instance) { try { ChestRegistry.Register(__instance); } catch (Exception arg) { if (!_reported) { _reported = true; Plugin.Log.LogError((object)$"Could not register a container: {arg}"); } } } } [HarmonyPatch(typeof(Player), "HaveRequirementItems")] internal static class HaveRequirementItemsPatch { private static void Prefix(Player __instance, out bool __state) { __state = ChestScope.Enter(__instance); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] internal static class HaveRequirementsPiecePatch { private static void Prefix(Player __instance, out bool __state) { __state = ChestScope.Enter(__instance); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Recipe), typeof(bool), typeof(int), typeof(int) })] internal static class HaveRequirementsRecipePatch { private static void Prefix(Player __instance, out bool __state) { __state = ChestScope.Enter(__instance); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(Player), "ConsumeResources")] internal static class ConsumeResourcesPatch { private static void Prefix(Player __instance, out bool __state) { __state = ChestScope.Enter(__instance); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(Player), "GetFirstRequiredItem")] internal static class GetFirstRequiredItemPatch { private static void Prefix(Player __instance, out bool __state) { __state = ChestScope.Enter(__instance); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] internal static class DoCraftingPatch { private static void Prefix(Player player, out bool __state) { __state = ChestScope.Enter(player); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] internal static class SetupRequirementPatch { private static void Prefix(Player player, out bool __state) { __state = ChestScope.Enter(player); } private static void Finalizer(bool __state) { ChestScope.Exit(__state); } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] internal static class RequirementLabelPatch { private const int MaxCachedLabels = 1024; private static readonly Dictionary<long, string> Labels = new Dictionary<long, string>(); private static bool _reported; private static void Postfix(Transform elementRoot, Requirement req, int quality, int craftMultiplier) { if (!ChestScope.Active) { return; } try { AppendChestAvailability(elementRoot, req, quality, craftMultiplier); } catch (Exception arg) { if (!_reported) { _reported = true; Plugin.Log.LogError((object)$"Could not update a requirement label: {arg}"); } } } private static void AppendChestAvailability(Transform elementRoot, Requirement req, int quality, int craftMultiplier) { string text = req?.m_resItem?.m_itemData?.m_shared?.m_name; if (string.IsNullOrEmpty(text) || (Object)(object)elementRoot == (Object)null) { return; } int num = req.GetAmount(quality) * craftMultiplier; if (num > 0) { Transform val = elementRoot.Find("res_amount"); TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null); if (!((Object)(object)val2 == (Object)null)) { val2.text = Label(num, ChestScope.CountInChests(text)); } } } private static string Label(int need, int inChests) { long key = ((long)need << 32) | (uint)inChests; if (!Labels.TryGetValue(key, out var value)) { if (Labels.Count >= 1024) { Labels.Clear(); } value = $"{need} ({inChests})"; Labels[key] = value; } return value; } } [HarmonyPatch(typeof(Inventory), "CountItems")] internal static class CountItemsPatch { private static void Postfix(Inventory __instance, string name, int quality, ref int __result) { ChestScope.AddChestCount(__instance, name, quality, ref __result); } } [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] internal static class HaveItemPatch { private static void Postfix(Inventory __instance, string name, ref bool __result) { if (!__result && ChestScope.Active) { int result = 0; ChestScope.AddChestCount(__instance, name, -1, ref result); if (result > 0) { __result = true; } } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] internal static class RemoveItemPatch { private static bool Prefix(Inventory __instance, string name, int amount, int itemQuality, bool worldLevelBased) { return !ChestScope.TryRemoveFromChests(__instance, name, amount, itemQuality, worldLevelBased); } } [BepInPlugin("com.despr0grammer.craftfromchestoptimized", "CraftFromChestOptimized", "1.0.0")] [BepInIncompatibility("com.teflonted.valheim.craftfromchests")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.despr0grammer.craftfromchestoptimized"; public const string PluginName = "CraftFromChestOptimized"; public const string PluginVersion = "1.0.0"; private const string OriginalGuid = "com.teflonted.valheim.craftfromchests"; private const float PruneInterval = 30f; internal static ManualLogSource Log; private ConfigEntry<KeyboardShortcut> _toggleKey; private Harmony _harmony; private float _nextPrune; private static readonly Type[] CorePatches = new Type[11] { typeof(ContainerAwakePatch), typeof(HaveRequirementItemsPatch), typeof(HaveRequirementsPiecePatch), typeof(HaveRequirementsRecipePatch), typeof(ConsumeResourcesPatch), typeof(GetFirstRequiredItemPatch), typeof(DoCraftingPatch), typeof(SetupRequirementPatch), typeof(CountItemsPatch), typeof(HaveItemPatch), typeof(RemoveItemPatch) }; private static readonly Type[] OptionalPatches = new Type[1] { typeof(RequirementLabelPatch) }; private void Awake() { //IL_0026: 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_0068: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; _toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Key that turns crafting from nearby chests on/off while playing."); if (!GameAccess.Ready) { ((BaseUnityPlugin)this).Logger.LogError((object)"Valheim internals changed (Container.CheckAccess/Save not found); mod disabled."); Disable(); return; } _harmony = new Harmony("com.despr0grammer.craftfromchestoptimized"); if (!ApplyPatches()) { Disable(); return; } ChestRegistry.SeedFromScene(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded ({2} toggles it)", "CraftFromChestOptimized", "1.0.0", _toggleKey.Value)); } private bool ApplyPatches() { Type[] corePatches = CorePatches; foreach (Type type in corePatches) { try { _harmony.PatchAll(type); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Required patch " + type.Name + " failed, mod disabled: " + ex.Message)); _harmony.UnpatchSelf(); return false; } } corePatches = OptionalPatches; foreach (Type type2 in corePatches) { try { _harmony.PatchAll(type2); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Optional patch " + type2.Name + " failed: " + ex2.Message)); } } return true; } private void Disable() { ChestScope.SetEnabled(enabled: false); ((Behaviour)this).enabled = false; } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) ChestScope.EndFrameCheck(); KeyboardShortcut value = _toggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && CanToggle()) { Toggle(); } if (Time.unscaledTime >= _nextPrune) { _nextPrune = Time.unscaledTime + 30f; ChestRegistry.Prune(); } } private static bool CanToggle() { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible()) { return !TextInput.IsVisible(); } return false; } private void Toggle() { bool flag = !ChestScope.Enabled; ChestScope.SetEnabled(flag); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Craft from chests: " + (flag ? "ON" : "OFF"))); ((Character)Player.m_localPlayer).Message((MessageType)1, StatusText(flag), 0, (Sprite)null, false); if (InventoryGui.IsVisible()) { GameAccess.RefreshCraftingPanel(InventoryGui.instance); } } private static string StatusText(bool on) { if (Localization.instance != null && Localization.instance.GetSelectedLanguage() == "Spanish") { if (!on) { return "Craftear desde cofres: DESACTIVADO"; } return "Craftear desde cofres: ACTIVADO"; } if (!on) { return "Craft from chests: OFF"; } return "Craft from chests: ON"; } } }