Decompiled source of OscarsInventoryTweaksMono v1.2.0

Mods/OscarsInventoryTweaks.Mono.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Fxcpds;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using OscarsInventoryTweaks;
using ScheduleOne;
using ScheduleOne.Core.Items.Framework;
using ScheduleOne.NPCs;
using ScheduleOne.NPCs.CharacterClasses;
using ScheduleOne.PlayerScripts;
using ScheduleOne.UI.Shop;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonInfo(typeof(Mod), "Oscar's Inventory Tweaks", "1.2.0", "Foxcapades", null)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("OscarsInventoryTweaks")]
[assembly: AssemblyConfiguration("Mono")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7d32857f571070ba18933c47e913d0f34ddd7d5d")]
[assembly: AssemblyProduct("OscarsInventoryTweaks")]
[assembly: AssemblyTitle("OscarsInventoryTweaks")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Fxcpds
{
	public abstract class FxMod : MelonMod
	{
		protected const string SCENE_NAME_MAIN = "Main";

		private static FxMod? instance;

		public static FxMod Instance => instance;

		protected string Scene { get; private set; } = "";


		public bool InMainScene { get; private set; }

		protected virtual string? configPath { get; }

		public string? ConfigPath => (configPath == null) ? null : Path.Combine(MelonEnvironment.UserDataDirectory, configPath);

		public override void OnEarlyInitializeMelon()
		{
			instance = this;
		}

		public override void OnInitializeMelon()
		{
			Player.onPlayerSpawned = (Action<Player>)Delegate.Combine(Player.onPlayerSpawned, new Action<Player>(onPlayerSpawned));
		}

		public override void OnSceneWasLoaded(int _, string sceneName)
		{
			Scene = sceneName;
			if (sceneName == "Main")
			{
				InMainScene = true;
				onMainLoaded();
			}
		}

		public override void OnSceneWasInitialized(int _, string sceneName)
		{
			if (sceneName == "Main")
			{
				onMainInitialized();
			}
		}

		public override void OnSceneWasUnloaded(int _, string sceneName)
		{
			if (Scene == sceneName)
			{
				Scene = "";
			}
			if (sceneName == "Main")
			{
				InMainScene = false;
				onMainUnloaded();
			}
		}

		public sealed override void OnPreferencesSaved(string filepath)
		{
			if (configPath != null && filepath.EndsWith(configPath))
			{
				((MelonBase)this).LoggerInstance.Debug("calling onModPreferencesSaved()");
				onModPreferencesSaved();
			}
		}

		public override void OnPreferencesLoaded(string filepath)
		{
			if (configPath != null && filepath.EndsWith(configPath))
			{
				((MelonBase)this).LoggerInstance.Debug("calling onModPreferencesLoaded()");
				onModPreferencesSaved();
			}
		}

		protected virtual void onModPreferencesSaved()
		{
		}

		protected virtual void onModPreferencesLoaded()
		{
		}

		private void onPlayerSpawned(Player player)
		{
			if (player.IsLocalPlayer)
			{
				((MelonBase)this).LoggerInstance.Debug("local player loaded");
				onLocalPlayerLoaded(player);
			}
			onPlayerLoaded(player);
		}

		protected virtual void onPlayerLoaded(Player player)
		{
		}

		protected virtual void onLocalPlayerLoaded(Player player)
		{
		}

		protected virtual void onMainLoaded()
		{
		}

		protected virtual void onMainInitialized()
		{
		}

		protected virtual void onMainUnloaded()
		{
		}
	}
	internal static class DebugTools
	{
		public static void Debug(this Instance logger, string message)
		{
		}

		public static void Debug(this Instance logger, string message, object? a1)
		{
		}
	}
	public static class Interop
	{
		public static T? cast<T>(Object? obj) where T : Object
		{
			return (obj == (Object)null) ? default(T) : ((T)(object)obj);
		}
	}
	public static class NPC
	{
		public const string Oscar = "oscar_holland";

		public const string Dan = "dan_samwell";

		public const string Hank = "hank_stevenson";

		public static T? Get<T>(string id) where T : NPC
		{
			return Interop.cast<T>((Object?)(object)NPCManager.GetNPC(id));
		}
	}
}
namespace OscarsInventoryTweaks
{
	internal readonly struct Category
	{
		public static readonly Category Additives = new Category("Additives", "extralonglifesoil");

		public static readonly Category Storage = new Category("Storage", "bed");

		public static readonly Category Equipment = new Category("Growing", "soilpourer");

		public static readonly Category[] allCategories = new Category[3] { Additives, Storage, Equipment };

		public readonly string name;

		public readonly string appearsAfter;

		private Category(string name, string appearsAfter)
		{
			this.name = name;
			this.appearsAfter = appearsAfter;
		}

		public override bool Equals(object? obj)
		{
			return obj != null && (obj as Category?)?.name == name;
		}

		public override int GetHashCode()
		{
			return name.GetHashCode();
		}

		public static bool operator ==(Category a, Category b)
		{
			return a.name == b.name;
		}

		public static bool operator !=(Category a, Category b)
		{
			return a.name != b.name;
		}
	}
	internal readonly struct Item
	{
		public static readonly Item Fertilizer = new Item("fertilizer", Category.Additives);

		public static readonly Item PGR = new Item("pgr", Category.Additives);

		public static readonly Item SpeedGrow = new Item("speedgrow", Category.Additives);

		public static readonly Item Locker = new Item("locker", Category.Storage);

		public static readonly Item SmallStorageCloset = new Item("smallstoragecloset", Category.Storage);

		public static readonly Item MediumStorageCloset = new Item("mediumstoragecloset", Category.Storage);

		public static readonly Item LargeStorageCloset = new Item("largestoragecloset", Category.Storage);

		public static readonly Item HugeStorageCloset = new Item("hugestoragecloset", Category.Storage);

		public static readonly Item SmallStorageRack = new Item("smallstoragerack", Category.Storage);

		public static readonly Item MediumStorageRack = new Item("mediumstoragerack", Category.Storage);

		public static readonly Item LargeStorageRack = new Item("largestoragerack", Category.Storage);

		public static readonly Item BigSprinkler = new Item("bigsprinkler", Category.Equipment);

		public static readonly Item AirConditioner = new Item("acunit", Category.Equipment);

		public static readonly Item[] allItems = new Item[13]
		{
			Fertilizer, PGR, SpeedGrow, Locker, BigSprinkler, AirConditioner, SmallStorageCloset, MediumStorageCloset, LargeStorageCloset, HugeStorageCloset,
			SmallStorageRack, MediumStorageRack, LargeStorageRack
		};

		public readonly string id;

		public readonly Category category;

		public static int itemCount => allItems.Length;

		private Item(string id, Category category)
		{
			this.id = id;
			this.category = category;
		}
	}
	public class Mod : FxMod
	{
		public const string MOD_ID = "Oscar's Inventory Tweaks";

		private static readonly ShopListing[] targetItemListings = (ShopListing[])(object)new ShopListing[Item.itemCount];

		private static Preferences? preferences;

		protected override string configPath => "OscarsInventoryTweaks.cfg";

		public override void OnInitializeMelon()
		{
			preferences = new Preferences(base.ConfigPath);
			base.OnInitializeMelon();
		}

		protected override void onModPreferencesSaved()
		{
			if (base.InMainScene)
			{
				updateShopListings();
			}
		}

		protected override void onLocalPlayerLoaded(Player _)
		{
			init();
			updateShopListings();
		}

		private static void init()
		{
			((MelonBase)FxMod.Instance).LoggerInstance.Debug("initializing");
			ShopInterface shopInterface = NPC.Get<Dan>("dan_samwell").ShopInterface;
			for (int i = 0; i < Item.itemCount; i++)
			{
				targetItemListings[i] = shopInterface.GetListing(Item.allItems[i].id);
				((MelonBase)FxMod.Instance).LoggerInstance.Debug("grabbed {0} listing from dan", ((BaseItemDefinition)targetItemListings[i].Item).ID);
			}
		}

		private static void moveItem<T>(List<T> items, int from, int to)
		{
			T item = items[from];
			items.RemoveAt(from);
			items.Insert(to, item);
		}

		private static Dictionary<string, ShopListing?> buildListings()
		{
			Dictionary<string, ShopListing> dictionary = new Dictionary<string, ShopListing>(Item.itemCount);
			(Item, bool)[] items = preferences.getItems();
			for (int i = 0; i < items.Length; i++)
			{
				var (item, flag) = items[i];
				dictionary[item.id] = (flag ? targetItemListings[i] : null);
			}
			return dictionary;
		}

		private static void pruneDisabledListings(ShopInterface oscar, Dictionary<string, ShopListing?> newListings, List<ListingUI> uiListings, UIPanel listingPanel)
		{
			foreach (var (text2, val2) in newListings)
			{
				if (val2 != null)
				{
					continue;
				}
				ShopListing listing = oscar.GetListing(text2);
				if (listing == null)
				{
					continue;
				}
				((MelonBase)FxMod.Instance).LoggerInstance.Debug("removing {0} from Oscar's inventory", text2);
				oscar.Listings.Remove(listing);
				ListingUI val3 = null;
				for (int i = 0; i < uiListings.Count; i++)
				{
					if (((BaseItemDefinition)uiListings[i].Listing.Item).ID == text2)
					{
						val3 = uiListings[i];
						uiListings.RemoveAt(i);
						break;
					}
				}
				if (!((Object)(object)val3 == (Object)null))
				{
					listingPanel.RemoveSelectable(((Component)val3).GetComponent<UISelectable>(), true);
					Object.Destroy((Object)(object)((Component)val3).gameObject);
				}
			}
		}

		private static void injectNewListings(ShopInterface oscar, Dictionary<string, ShopListing?> newListings, List<ListingUI> uiListings)
		{
			MethodInfo method = typeof(ShopInterface).GetMethod("CreateListingUI", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(ShopListing) }, null);
			object[] array = new object[1];
			foreach (ShopListing listing in oscar.Listings)
			{
				newListings.Remove(((BaseItemDefinition)listing.Item).ID);
			}
			for (int num = Item.allItems.Length - 1; num >= 0; num--)
			{
				Item item = Item.allItems[num];
				if (newListings.TryGetValue(item.id, out ShopListing value) && value != null)
				{
					oscar.Listings.Add(Utils.copyListing(targetItemListings[num], oscar));
					array[0] = value;
					method.Invoke(oscar, array);
					int num2 = findInsertPosition(uiListings, item.category.appearsAfter);
					if (num2 > -1)
					{
						moveItem(uiListings, uiListings.Count - 1, num2);
					}
				}
			}
		}

		private static int findInsertPosition(List<ListingUI> list, string target)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if (((BaseItemDefinition)list[i].Listing.Item).ID == target)
				{
					return i + 1;
				}
			}
			return -1;
		}

		private static void updateShopListings()
		{
			ShopInterface val = NPC.Get<Oscar>("oscar_holland")?.ShopInterface;
			if ((Object)(object)val == (Object)null)
			{
				((MelonBase)FxMod.Instance).LoggerInstance.Debug("oscar was null");
				return;
			}
			List<ListingUI> list = val.ListingUIItems();
			if (list == null)
			{
				((MelonBase)FxMod.Instance).LoggerInstance.Debug("uiListings was null");
				return;
			}
			UIPanel val2 = val.ListingPanel();
			if ((Object)(object)val2 == (Object)null)
			{
				((MelonBase)FxMod.Instance).LoggerInstance.Debug("uiPanel was null");
				return;
			}
			Dictionary<string, ShopListing> newListings = buildListings();
			pruneDisabledListings(val, newListings, list, val2);
			injectNewListings(val, newListings, list);
		}
	}
	internal sealed class Preferences
	{
		private readonly MelonPreferences_Entry<bool> sellFertilizer;

		private readonly MelonPreferences_Entry<bool> sellPGR;

		private readonly MelonPreferences_Entry<bool> sellSpeedGrow;

		private readonly MelonPreferences_Entry<bool> sellBigSprinkler;

		private readonly MelonPreferences_Entry<bool> sellLocker;

		private readonly MelonPreferences_Entry<bool> sellShelves;

		private readonly MelonPreferences_Entry<bool> sellClosets;

		private readonly MelonPreferences_Entry<bool> sellAirCon;

		public bool SellFertilizer => sellFertilizer.Value;

		public bool SellPgr => sellPGR.Value;

		public bool SellSpeedGrow => sellSpeedGrow.Value;

		public bool SellBigSprinkler => sellBigSprinkler.Value;

		public bool SellLocker => sellLocker.Value;

		public bool SellShelves => sellShelves.Value;

		public bool SellClosets => sellClosets.Value;

		public bool SellAirCon => sellAirCon.Value;

		public Preferences(string configPath)
		{
			MelonPreferences_Category val = MelonPreferences.CreateCategory("Oscar's Inventory Tweaks - Additives", "Growth Additives");
			val.SetFilePath(configPath);
			sellFertilizer = val.CreateEntry<bool>("sellFertilizer", true, "Sell Fertilizer", (string)null, false, false, (ValueValidator)null, (string)null);
			sellPGR = val.CreateEntry<bool>("sellPGR", true, "Sell PGR", (string)null, false, false, (ValueValidator)null, (string)null);
			sellSpeedGrow = val.CreateEntry<bool>("sellSpeedGrow", true, "Sell Speed Grow", (string)null, false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Category val2 = MelonPreferences.CreateCategory("Oscar's Inventory Tweaks - Growing", "Equipment");
			val2.SetFilePath(configPath);
			sellBigSprinkler = val2.CreateEntry<bool>("sellBigSprinkler", true, "Sell Big Sprinkler", (string)null, false, false, (ValueValidator)null, (string)null);
			sellAirCon = val2.CreateEntry<bool>("sellAirConditioner", true, "Sell AC Unit", (string)null, false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Category val3 = MelonPreferences.CreateCategory("Oscar's Inventory Tweaks - Storage", "Storage");
			val3.SetFilePath(configPath);
			sellLocker = val3.CreateEntry<bool>("sellLocker", true, "Sell Locker", (string)null, false, false, (ValueValidator)null, (string)null);
			sellShelves = val3.CreateEntry<bool>("sellShelves", true, "Sell Shelves", (string)null, false, false, (ValueValidator)null, (string)null);
			sellClosets = val3.CreateEntry<bool>("sellClosets", true, "Sell Closets", (string)null, false, false, (ValueValidator)null, (string)null);
		}
	}
	internal static class Utils
	{
		public static (Item, bool)[] getItems(this Preferences prefs)
		{
			return new(Item, bool)[13]
			{
				(Item.Fertilizer, prefs.SellFertilizer),
				(Item.PGR, prefs.SellPgr),
				(Item.SpeedGrow, prefs.SellSpeedGrow),
				(Item.Locker, prefs.SellLocker),
				(Item.BigSprinkler, prefs.SellBigSprinkler),
				(Item.AirConditioner, prefs.SellAirCon),
				(Item.SmallStorageCloset, prefs.SellClosets),
				(Item.MediumStorageCloset, prefs.SellClosets),
				(Item.LargeStorageCloset, prefs.SellClosets),
				(Item.HugeStorageCloset, prefs.SellClosets),
				(Item.SmallStorageRack, prefs.SellShelves),
				(Item.MediumStorageRack, prefs.SellShelves),
				(Item.LargeStorageRack, prefs.SellShelves)
			};
		}

		public static List<ListingUI>? ListingUIItems(this ShopInterface shop)
		{
			FieldInfo field = typeof(ShopInterface).GetField("listingUI", BindingFlags.Instance | BindingFlags.NonPublic);
			((MelonBase)FxMod.Instance).LoggerInstance.Debug("reflectively got field {0}", field);
			return (List<ListingUI>)field.GetValue(shop);
		}

		public static UIPanel? ListingPanel(this ShopInterface shop)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			FieldInfo field = typeof(ShopInterface).GetField("listingPanel", BindingFlags.Instance | BindingFlags.NonPublic);
			((MelonBase)FxMod.Instance).LoggerInstance.Debug("reflectively got field {0}", field);
			return (UIPanel)field.GetValue(shop);
		}

		public static ShopListing copyListing(ShopListing old, ShopInterface shop)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00c7: Expected O, but got Unknown
			ShopListing val = new ShopListing
			{
				name = old.name,
				Item = old.Item,
				LimitedStock = old.LimitedStock,
				DefaultStock = old.DefaultStock,
				RestockRate = old.RestockRate,
				TieStockToNumberVariable = old.TieStockToNumberVariable,
				StockVariableName = old.StockVariableName,
				TrackPurchases = old.TrackPurchases,
				PurchasedQuantityVariableName = old.PurchasedQuantityVariableName,
				EnforceMinimumGameCreationVersion = old.EnforceMinimumGameCreationVersion,
				MinimumGameCreationVersion = old.MinimumGameCreationVersion,
				CanBeDelivered = old.CanBeDelivered,
				UseIconTint = old.UseIconTint,
				IconTint = old.IconTint,
				ConditionalVisibility = old.ConditionalVisibility,
				ConditionalVisibilityVariableName = old.ConditionalVisibilityVariableName
			};
			val.Initialize(shop);
			val.SetStock(old.CurrentStock, true);
			return val;
		}
	}
}