using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("GooderRecycling")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Main Street Gaming")] [assembly: AssemblyProduct("GooderRecycling")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] namespace GooderRecycling; [BepInPlugin("MainStreetGaming.GooderRecycling", "GooderRecycling", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class GooderRecycling : BaseUnityPlugin { public const string PluginGUID = "MainStreetGaming.GooderRecycling"; public const string PluginName = "GooderRecycling"; public const string PluginVersion = "1.0.1"; public static ConfigEntry _enableDebug; public static ConfigEntry recycleHotKey; public static ConfigEntry returnUnknownRes; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private void Awake() { string[] array = new string[10] { "In the game of life, you either adapt or you install {0}. Choose wisely.", "Hold your breath, gamers! {0} is here to either fix everything or create chaos – we're not sure which yet.", "Just when you thought things couldn't get crazier, along comes {0} to prove you wrong.", "We're not saying {0} is the answer to all your problems, but it's definitely the answer to some of them.", "They say curiosity killed the cat, but in our case, it just installed {0}.", "Someone fetch the confetti cannon! {0} has arrived, and we're throwing a virtual party!", "We're not saying {0} is the key to happiness, but it's a pretty good start!", "Welcome to the age of enlightenment, where {0} has replaced logic and reason.", "Breaking news: {0} just took a wrong turn and ended up here. Let the chaos begin!", "Buckle up, buttercups! {0} just strolled in, and it's ready to rewrite the rules." }; int num = new Random().Next(array.Length); Logger.LogInfo((object)string.Format(array[num], "GooderRecycling")); CreateConfigValues(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } private void CreateConfigValues() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; _enableDebug = ((BaseUnityPlugin)this).Config.Bind("Client config", "Enable Debug", false, new ConfigDescription("Enable Debug Mode?", (AcceptableValueBase)null, Array.Empty())); recycleHotKey = ((BaseUnityPlugin)this).Config.Bind("Client config", "Recycle Hotkey", (KeyCode)127, new ConfigDescription("Hotkey to recylce items.", (AcceptableValueBase)null, Array.Empty())); returnUnknownRes = ((BaseUnityPlugin)this).Config.Bind("Server config", "Return Unknown Resources", true, new ConfigDescription("Return resources for unknown recipe?", (AcceptableValueBase)null, new object[1] { val })); } public static void DebugLog(string data) { if (_enableDebug.Value) { Logger.LogInfo((object)("GooderRecycling: " + data)); } } } [HarmonyPatch(typeof(InventoryGui), "UpdateItemDrag")] public static class UpdateItemDrag_Patch { private static void Postfix(InventoryGui __instance, ItemData ___m_dragItem, Inventory ___m_dragInventory, int ___m_dragAmount, ref GameObject ___m_dragGo) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetKeyDown(GooderRecycling.recycleHotKey.Value) || ___m_dragItem == null || !___m_dragInventory.ContainsItem(___m_dragItem)) { return; } GooderRecycling.DebugLog($"Initiating Recycling Process for {___m_dragAmount}/{___m_dragItem.m_stack} {((Object)___m_dragItem.m_dropPrefab).name}"); Recipe recipe = ObjectDB.instance.GetRecipe(___m_dragItem); if ((Object)(object)recipe != (Object)null && (GooderRecycling.returnUnknownRes.Value || Player.m_localPlayer.IsRecipeKnown(___m_dragItem.m_shared.m_name))) { List list = recipe.m_resources.ToList(); if (0 == 0 && ___m_dragAmount / recipe.m_amount > 0) { for (int i = 0; i < ___m_dragAmount / recipe.m_amount; i++) { foreach (Requirement requirement in list) { Func predicate = delegate(GameObject item) { if ((Object)(object)item == (Object)null) { return false; } ItemDrop component3 = item.GetComponent(); return !((Object)(object)component3 == (Object)null) && component3.m_itemData != null && component3.m_itemData.m_shared != null && component3.m_itemData.m_shared.m_name == requirement.m_resItem.m_itemData.m_shared.m_name; }; for (int num = ___m_dragItem.m_quality; num > 0; num--) { GameObject val = ObjectDB.instance.m_items.FirstOrDefault(predicate); if ((Object)(object)val == (Object)null) { GooderRecycling.DebugLog("Could not find matching item for recycled resource: " + requirement.m_resItem.m_itemData.m_shared.m_name); } else { ItemDrop component = val.GetComponent(); if ((Object)(object)component == (Object)null || component.m_itemData == null) { GooderRecycling.DebugLog("Matching item has invalid ItemData: " + requirement.m_resItem.m_itemData.m_shared.m_name); } else { ItemData val2 = component.m_itemData.Clone(); val2.m_quality = requirement.m_resItem.m_itemData.m_quality; val2.m_variant = requirement.m_resItem.m_itemData.m_variant; int num2 = ((num > 1 || !requirement.m_upgraderResource) ? requirement.GetAmount(num) : 0); while (num2 > 0) { int num3 = Mathf.Min(requirement.m_resItem.m_itemData.m_shared.m_maxStackSize, num2); num2 -= num3; ItemData recycledItemData = val2.Clone(); recycledItemData.m_stack = num3; Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); while (recycledItemData.m_stack > 0) { bool flag = false; ItemData val3 = ((IEnumerable)inventory.GetAllItems()).FirstOrDefault((Func)((ItemData item) => item.IsSameType(recycledItemData) && item.m_stack < item.m_shared.m_maxStackSize)); if (val3 != null) { Vector2i gridPos = val3.m_gridPos; int stack = recycledItemData.m_stack; inventory.AddItem(recycledItemData, recycledItemData.m_stack, gridPos.x, gridPos.y, false); flag = recycledItemData.m_stack < stack; } if (!flag) { for (int num4 = 0; num4 < inventory.GetHeight(); num4++) { if (flag) { break; } for (int num5 = 0; num5 < inventory.GetWidth(); num5++) { if (inventory.GetItemAt(num5, num4) == null) { int stack2 = recycledItemData.m_stack; inventory.AddItem(recycledItemData, recycledItemData.m_stack, num5, num4, false); flag = recycledItemData.m_stack < stack2; if (flag) { break; } } } } } if (!flag) { Transform transform; ItemDrop component2 = Object.Instantiate(val, (transform = ((Component)Player.m_localPlayer).transform).position + transform.forward + transform.up, transform.rotation).GetComponent(); component2.m_itemData = recycledItemData; component2.m_itemData.m_dropPrefab = val; component2.m_itemData.m_stack = recycledItemData.m_stack; component2.Save(); recycledItemData.m_stack = 0; } } } } } } } } if (IsEquippedWeapon(___m_dragItem)) { GooderRecycling.DebugLog("Item is equipped. Unequipping..."); UnequipWeapon(___m_dragItem); } ___m_dragInventory.RemoveItem(___m_dragItem, ___m_dragAmount); } } Object.Destroy((Object)(object)___m_dragGo); ___m_dragGo = null; __instance.UpdateCraftingPanel(false); } private static bool IsEquippedWeapon(ItemData itemData) { string itemName = itemData.m_shared.m_name; return ((Humanoid)Player.m_localPlayer).GetInventory().GetEquippedItems().Any((ItemData equippedItem) => equippedItem.m_shared.m_name == itemName); } private static void UnequipWeapon(ItemData itemData) { ((Humanoid)Player.m_localPlayer).RemoveEquipAction(itemData); ((Humanoid)Player.m_localPlayer).UnequipItem(itemData, false); } }