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 CraftFromChests v1.0.1
CraftFromChests.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("CraftFromChests")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CraftFromChests")] [assembly: AssemblyTitle("CraftFromChests")] [assembly: AssemblyVersion("1.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 CraftFromChests { [BepInPlugin("GamerOff02.craftfromchests", "Craft From Chests", "1.0.1")] public class Plugin : BaseUnityPlugin { public const string GUID = "GamerOff02.craftfromchests"; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> DebugLog; internal static ConfigEntry<float> Radius; internal static ManualLogSource Log; private void Awake() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Включить мод"); Radius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Radius", 20f, "Радиус (в метрах) вокруг игрока, в котором ищутся сундуки"); DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", false, "Писать в лог, сколько сундуков найдено (для диагностики)"); Harmony val = new Harmony("GamerOff02.craftfromchests"); Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0) { try { val.CreateClassProcessor(type).Patch(); Log.LogInfo((object)("Patched: " + type.Name)); } catch (Exception ex) { Log.LogError((object)("FAILED patch " + type.Name + ": " + ex.Message)); } } } Log.LogInfo((object)"Craft From Chests loaded"); } } internal static class Chests { private static readonly MethodInfo SaveMethod = AccessTools.Method(typeof(Container), "Save", (Type[])null, (Type[])null); private static readonly MethodInfo CheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); private static readonly FieldInfo AllContainersField = typeof(Container).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((FieldInfo f) => f.FieldType == typeof(List<Container>)); public static int CraftDepth; public static bool Suppress; private static List<Container> _cache = new List<Container>(); private static float _cacheTime = -10f; private static float _lastLog = -10f; private static bool _accessErrorLogged; public static bool InCraftContext { get { if (CraftDepth > 0) { return !Suppress; } return false; } } public static List<Container> Nearby() { //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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Plugin.Enabled.Value || (Object)(object)localPlayer == (Object)null) { return new List<Container>(); } if (Time.time - _cacheTime < 0.5f) { return _cache; } _cacheTime = Time.time; List<Container> list = ((AllContainersField != null) ? (AllContainersField.GetValue(null) as List<Container>) : null); if (list == null || list.Count == 0) { list = Object.FindObjectsOfType<Container>().ToList(); } List<Container> list2 = new List<Container>(); int num = 0; float value = Plugin.Radius.Value; Vector3 position = ((Component)localPlayer).transform.position; long playerID = localPlayer.GetPlayerID(); foreach (Container item in list) { if ((Object)(object)item == (Object)null || item.GetInventory() == null) { continue; } ZNetView component = ((Component)item).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && !(Vector3.Distance(((Component)item).transform.position, position) > value)) { num++; if (HasAccess(item, playerID)) { list2.Add(item); } } } if (Plugin.DebugLog.Value && Time.time - _lastLog > 5f) { _lastLog = Time.time; Plugin.Log.LogInfo((object)$"Containers: total={list.Count}, in radius={num}, accessible={list2.Count}"); } _cache = list2; return list2; } private static bool HasAccess(Container c, long playerId) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) try { if (CheckAccessMethod != null && !(bool)CheckAccessMethod.Invoke(c, new object[1] { playerId })) { return false; } if (!PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false)) { return false; } return true; } catch (Exception ex) { if (!_accessErrorLogged) { _accessErrorLogged = true; Plugin.Log.LogWarning((object)("Access check failed: " + ex.Message)); } return false; } } public static int RawCount(Inventory inv, string name, int quality = -1) { bool suppress = Suppress; Suppress = true; try { return inv.CountItems(name, quality, true); } finally { Suppress = suppress; } } public static int Count(string name, int quality = -1) { int num = 0; foreach (Container item in Nearby()) { num += RawCount(item.GetInventory(), name, quality); } return num; } public static int Remove(string name, int amount, int quality = -1) { int num = amount; foreach (Container item in Nearby()) { if (num <= 0) { break; } Inventory inventory = item.GetInventory(); int num2 = RawCount(inventory, name, quality); if (num2 > 0) { int num3 = Math.Min(num2, num); ZNetView component = ((Component)item).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { component.ClaimOwnership(); } inventory.RemoveItem(name, num3, quality, true); if (SaveMethod != null) { SaveMethod.Invoke(item, null); } num -= num3; } } _cacheTime = -10f; return amount - num; } public static bool Enough(Player player, Requirement[] reqs, int quality, int multiplier) { Inventory inventory = ((Humanoid)player).GetInventory(); foreach (Requirement val in reqs) { if ((Object)(object)val.m_resItem == (Object)null) { continue; } int num = val.GetAmount(quality) * multiplier; if (num > 0) { string name = val.m_resItem.m_itemData.m_shared.m_name; if (RawCount(inventory, name) + Count(name) < num) { return false; } } } return true; } public static bool IsPlayerInventory(Inventory inv) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return inv == ((Humanoid)localPlayer).GetInventory(); } return false; } } [HarmonyPatch] internal static class CraftContext_Patch { private static readonly string[] InventoryGuiNames = new string[4] { "UpdateRecipe", "SetRecipe", "UpdateRecipeList", "SetupRequirement" }; private static readonly string[] HudNames = new string[4] { "UpdateBuild", "UpdatePieceBuildStatus", "SetupPieceInfo", "UpdatePieceList" }; private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(InventoryGui))) { if (InventoryGuiNames.Contains(declaredMethod.Name)) { yield return declaredMethod; } } foreach (MethodInfo declaredMethod2 in AccessTools.GetDeclaredMethods(typeof(Hud))) { if (HudNames.Contains(declaredMethod2.Name)) { yield return declaredMethod2; } } } [HarmonyPriority(800)] private static void Prefix() { Chests.CraftDepth++; } [HarmonyPriority(0)] private static void Finalizer() { if (Chests.CraftDepth > 0) { Chests.CraftDepth--; } } } [HarmonyPatch(typeof(Inventory), "CountItems")] internal static class CountItems_Patch { [HarmonyPriority(0)] private static void Postfix(Inventory __instance, ref int __result, object[] __args) { if (Chests.InCraftContext && Chests.IsPlayerInventory(__instance) && __args[0] is string name) { int quality = ((__args.Length > 1 && __args[1] is int) ? ((int)__args[1]) : (-1)); __result += Chests.Count(name, quality); } } } [HarmonyPatch(typeof(Inventory), "HaveItem")] internal static class HaveItem_Patch { [HarmonyPriority(0)] private static void Postfix(Inventory __instance, ref bool __result, object[] __args) { if (!__result && Chests.InCraftContext && Chests.IsPlayerInventory(__instance) && __args[0] is string name && Chests.Count(name) > 0) { __result = true; } } } [HarmonyPatch(typeof(Player), "HaveRequirementItems")] internal static class HaveRequirementItems_Patch { [HarmonyPriority(0)] private static void Postfix(Player __instance, ref bool __result, object[] __args) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } try { Recipe val = (Recipe)__args[0]; int quality = (int)__args[2]; int multiplier = ((__args.Length <= 3 || !(__args[3] is int)) ? 1 : ((int)__args[3])); if (Chests.Enough(__instance, val.m_resources, quality, multiplier)) { __result = true; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("HaveRequirementItems: " + ex.Message)); } } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] internal static class HaveRequirementsPiece_Patch { [HarmonyPriority(0)] private static void Postfix(Player __instance, ref bool __result, Piece piece, RequirementMode mode) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (__result || (int)mode != 0 || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } try { if ((!((Object)(object)piece.m_craftingStation != (Object)null) || Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position))) && (string.IsNullOrEmpty(piece.m_dlc) || DLCMan.instance.IsDLCInstalled(piece.m_dlc)) && Chests.Enough(__instance, piece.m_resources, 1, 1)) { __result = true; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("HaveRequirements(Piece): " + ex.Message)); } } } [HarmonyPatch(typeof(Player), "ConsumeResources")] internal static class ConsumeResources_Patch { [HarmonyPriority(800)] private static void Prefix(Player __instance, object[] __args) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } try { Requirement[] obj = (Requirement[])__args[0]; int num = (int)__args[1]; int quality = ((__args.Length > 2 && __args[2] is int) ? ((int)__args[2]) : (-1)); int num2 = ((__args.Length <= 3 || !(__args[3] is int)) ? 1 : ((int)__args[3])); Inventory inventory = ((Humanoid)__instance).GetInventory(); Requirement[] array = obj; foreach (Requirement val in array) { if ((Object)(object)val.m_resItem == (Object)null) { continue; } int num3 = val.GetAmount(num) * num2; if (num3 <= 0) { continue; } string name = val.m_resItem.m_itemData.m_shared.m_name; int num4 = num3 - Chests.RawCount(inventory, name, quality); if (num4 > 0) { int num5 = Chests.Remove(name, num4, quality); if (Plugin.DebugLog.Value) { Plugin.Log.LogInfo((object)$"Took {num5}/{num4} x {name} from chests"); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("ConsumeResources: " + ex.Message)); } } } }