Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of AutoRestockIL2CPP v1.0.3
Mods\AutoRestockIL2CPP.dll
Decompiled 6 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using AutoRestock; using HarmonyLib; using Il2CppFishNet; using Il2CppFishNet.Object; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Management; using Il2CppScheduleOne.Messaging; using Il2CppScheduleOne.Money; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.NPCs.Behaviour; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.Persistence; using Il2CppScheduleOne.Property; using Il2CppScheduleOne.StationFramework; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.UI; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(AutoRestockMod), "AutoRestock", "1.0.3", "lasersquid", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("AutoRestockIL2CPP")] [assembly: AssemblyConfiguration("IL2CPP")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3+3f17dd375f908f2e61c644e22b595b83b249bf33")] [assembly: AssemblyProduct("AutoRestockIL2CPP")] [assembly: AssemblyTitle("AutoRestockIL2CPP")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 AutoRestock { public class AutoRestockMod : MelonMod { public MelonPreferences_Category melonPrefs; public Harmony harmony = new Harmony("com.lasersquid.autorestock"); public override void OnInitializeMelon() { CreateMelonPreferences(); SetMod(); ((MelonBase)this).LoggerInstance.Msg("Mod initialized."); } private void CreateMelonPreferences() { melonPrefs = MelonPreferences.CreateCategory("AutoRestock"); melonPrefs.SetFilePath("UserData/AutoRestock.cfg", true, false); melonPrefs.CreateEntry<float>("itemDiscount", 0f, "Restock discount", "Discount applied to restock price (0.2 = 20% off)", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("payWithCash", true, "Pay for restock with cash", "True to pay with cash, false to pay with bank account", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("useDebt", false, "Enable debt", "Enable restocking even when zero or negative cash/bank balance", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("enableCauldrons", true, "Enable auto-restock on cauldrons", "Enable auto-restock on cauldrons", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("enableMixingStations", true, "Enable auto-restock on mixing stations", "Enable auto-restock on mixing stations", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("enableChemistryStations", true, "Enable auto-restock on chemistry stations", "Enable auto-restock on chemistry stations", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("enablePackagingStations", true, "Enable auto-restock on packaging stations", "Enable auto-restock on packaging stations", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("enableStorage", true, "Enable auto-restock on storage (shelves and safes)", "Enable auto-restock on storage (shelves and safes)", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("playerRestockStations", true, "Enable auto-restock on stations after player-initiated actions (start cauldron, etc)", "Enable auto-restock on stations after player-initiated actions (start cauldron, etc)", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("verboseLogs", false, "Print to the log for each auto-restock transaction", "Print to the log for each auto-restock transaction", false, false, (ValueValidator)null, (string)null); melonPrefs.CreateEntry<bool>("debugLogs", false, "Print debug logs", "Print debug logs", false, false, (ValueValidator)null, (string)null); melonPrefs.SaveToFile(false); } private List<Type> GetPatchTypes() { return (from t in Assembly.GetExecutingAssembly().GetTypes() where t.Name.EndsWith("Patches") select t).ToList(); } private void SetMod() { foreach (Type patchType in GetPatchTypes()) { MethodInfo method = patchType.GetMethod("SetMod", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); method.Invoke(null, new object[1] { this }); } Utils.SetMod(this); } } public class UnityObjectComparer : IEqualityComparer<Object> { public bool Equals(Object a, Object b) { return a.GetInstanceID() == b.GetInstanceID(); } public int GetHashCode(Object item) { return item.GetInstanceID(); } } public class Sched1PatchesBase { protected static AutoRestockMod Mod; public static void SetMod(AutoRestockMod mod) { Mod = mod; } } public static class Utils { private static AutoRestockMod Mod; public static void SetMod(AutoRestockMod mod) { Mod = mod; } public static void PrintException(Exception e) { Warn("Exception: " + e.GetType().Name + " - " + e.Message); Warn("Source: " + e.Source); Warn(e.StackTrace ?? ""); if (e.InnerException != null) { Warn("Inner exception: " + e.InnerException.GetType().Name + " - " + e.InnerException.Message); Warn("Source: " + e.InnerException.Source); Warn(e.InnerException.StackTrace ?? ""); if (e.InnerException.InnerException != null) { Warn("Inner inner exception: " + e.InnerException.InnerException.GetType().Name + " - " + e.InnerException.InnerException.Message); Warn("Source: " + e.InnerException.InnerException.Source); Warn(e.InnerException.InnerException.StackTrace ?? ""); } } } public static void Log(string message) { ((MelonBase)Mod).LoggerInstance.Msg(message); } public static void Warn(string message) { ((MelonBase)Mod).LoggerInstance.Warning(message); } public static void Debug(string message) { if (Manager.isInitialized && Manager.melonPrefs.GetEntry<bool>("debugLogs").Value) { ((MelonBase)Mod).LoggerInstance.Msg("DEBUG: " + message); } } public static void VerboseLog(string message) { if (Manager.isInitialized && Manager.melonPrefs.GetEntry<bool>("verboseLogs").Value) { ((MelonBase)Mod).LoggerInstance.Msg(message); } } public static object GetField(Type type, string fieldName, object target) { return AccessTools.Property(type, fieldName).GetValue(target); } public static void SetField(Type type, string fieldName, object target, object value) { AccessTools.Property(type, fieldName).SetValue(target, value); } public static object GetProperty(Type type, string fieldName, object target) { return AccessTools.Property(type, fieldName).GetValue(target); } public static void SetProperty(Type type, string fieldName, object target, object value) { AccessTools.Property(type, fieldName).SetValue(target, value); } public static object CallMethod(Type type, string methodName, object target, object[] args) { return AccessTools.Method(type, methodName, (Type[])null, (Type[])null).Invoke(target, args); } public static T CastTo<T>(object o) where T : class { if (!(o is T result)) { return null; } return result; } public static bool Is<T>(object o) { return o is T; } public static T CastTo<T>(Object o) where T : Il2CppObjectBase { return ((Il2CppObjectBase)o).TryCast<T>(); } public static bool Is<T>(Object o) where T : Il2CppObjectBase { return ((Il2CppObjectBase)o).TryCast<T>() != null; } public static UnityAction ToUnityAction(Action action) { return DelegateSupport.ConvertDelegate<UnityAction>((Delegate)action); } public static UnityAction<T> ToUnityAction<T>(Action<T> action) { return DelegateSupport.ConvertDelegate<UnityAction<T>>((Delegate)action); } public static bool IsQualityIngredient(string itemID) { List<string> source = new List<string>(1) { "pseudo" }; return source.Aggregate(seed: false, (bool accum, string name) => accum || itemID.Contains(name)); } public static ItemDefinition GetItemDef(string itemID) { return Registry.GetItem(itemID); } public static StorableItemInstance GetItemInstance(string itemID) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown return new StorableItemInstance(Registry.GetItem(itemID), 1); } public static QualityItemInstance GetItemInstance(string itemID, EQuality quality) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown Dictionary<EQuality, string> dictionary = new Dictionary<EQuality, string> { { (EQuality)4, "heavenly" }, { (EQuality)3, "highquality" }, { (EQuality)2, "" }, { (EQuality)1, "lowquality" }, { (EQuality)0, "trash" } }; if (IsQualityIngredient(itemID)) { string itemID2 = dictionary[quality] + itemID; return new QualityItemInstance(GetItemDef(itemID2), 1, quality); } Warn("itemid " + itemID + " is not a quality ingredient?"); return null; } public static bool IsObjectStorageRack(IItemSlotOwner slotOwner) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) string objName = new Object(((Il2CppObjectBase)slotOwner).Pointer).name; List<string> source = new List<string>(5) { "Safe", "Small Storage Rack", "Medium Storage Rack", "Large Storage Rack", "StorageRack" }; return source.Aggregate(seed: false, (bool accum, string name) => accum || objName.Contains(name)); } public static bool IsObjectBuildableItem(IItemSlotOwner slotOwner) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) string objName = new Object(((Il2CppObjectBase)slotOwner).Pointer).name; List<string> source = new List<string>(6) { "PackagingStation", "PackagingStationMk2", "Cauldron", "ChemistryStation", "MixingStation", "MixingStationMk2" }; return source.Aggregate(seed: false, (bool accum, string name) => accum || objName.Contains(name)); } } public static class Manager { public class Transaction { public string itemID; public int quantity; public float discount; public float unitPrice; public float totalCost; public string property; public bool useCash; public SlotIdentifier slotID; public Transaction(string itemID, int quantity, float discount, float unitPrice, float totalCost, bool useCash, SlotIdentifier slotID) { this.itemID = itemID; this.quantity = quantity; this.discount = discount; this.unitPrice = unitPrice; this.totalCost = totalCost; this.useCash = useCash; this.slotID = slotID; } } public class SlotIdentifier { public List<float> gridLocation; public string type; public int slotIndex; public string property; public SlotIdentifier(string property, Vector2 gridLocation, int slotIndex, string type) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) this.property = property; this.gridLocation = new List<float>(new <>z__ReadOnlyArray<float>(new float[2] { gridLocation.x, gridLocation.y })); this.slotIndex = slotIndex; this.type = type; } [JsonConstructor] public SlotIdentifier(string property, List<float> gridLocation, int slotIndex, string type) { this.property = property; this.gridLocation = gridLocation; this.slotIndex = slotIndex; this.type = type; } } [CompilerGenerated] private sealed class <RestockCoroutine>d__27 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ItemSlot slot; public StorableItemInstance item; public NetworkObject lockOwner; public Transaction transaction; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestockCoroutine>d__27(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; slot.SetIsRemovalLocked(true); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; Utils.VerboseLog($"Restocking {((ItemInstance)item).Name} (${transaction.unitPrice}) x{transaction.quantity} at {transaction.slotID.property}. Total: ${transaction.totalCost}."); if (transaction.quantity > 0) { ((ItemInstance)item).SetQuantity(transaction.quantity - slot.Quantity); slot.AddItem((ItemInstance)(object)item, false); } slot.SetIsRemovalLocked(false); if (transaction.totalCost <= 0f) { Utils.VerboseLog("Total cost of transaction is $0. Get a freebie!"); } else if (melonPrefs.GetEntry<bool>("payWithCash").Value) { moneyManager.ChangeCashBalance(0f - transaction.totalCost, true, false); } else { moneyManager.CreateOnlineTransaction("Restock", (0f - transaction.totalCost) / (float)transaction.quantity, (float)transaction.quantity, ((ItemInstance)item).Definition.Name ?? ""); } AcquireMutex(); coroutines.Remove(transaction); ReleaseMutex(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static Dictionary<ItemSlot, NPC> shelfAccessors; public static MelonPreferences_Category melonPrefs; private static TimeManager timeManager; private static MoneyManager moneyManager; private static SaveManager saveManager; private static string ledgerString; private static string transactionString; private static List<Transaction> ledger; private static Dictionary<Transaction, object> coroutines; private static NPC lockOwner; private static EDay ledgerDay; private static Mutex exclusiveLock; public static bool isInitialized; public static SlotIdentifier SerializeSlot(ItemSlot slot) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) GridItem component; string name; if (Utils.IsObjectBuildableItem(slot.SlotOwner)) { BuildableItem val = new BuildableItem(((Il2CppObjectBase)slot.SlotOwner).Pointer); component = ((Component)val).gameObject.GetComponent<GridItem>(); name = ((Object)val).name; } else { if (!Utils.IsObjectStorageRack(slot.SlotOwner)) { Utils.Warn("Couldn't serialize itemslot!"); return null; } StorageEntity val2 = new StorageEntity(((Il2CppObjectBase)slot.SlotOwner).Pointer); component = (GridItem)(object)((Component)val2).gameObject.GetComponent<PlaceableStorageEntity>(); name = ((Object)val2).name; } string name2 = ((Object)((BuildableItem)component).ParentProperty).name; return new SlotIdentifier(name2, component.OriginCoordinate, (int)Utils.GetProperty(typeof(ItemSlot), "SlotIndex", slot), name); } public static string StringToType(string typeString) { List<string> list = new List<string>(6) { "Cauldron", "ChemistryStation", "MixingStationMk2", "MixingStation", "PackagingStationMk2", "PackagingStation" }; string text = list.Find((string s) => typeString.Contains(s)); if (text != null && text.Length > 0) { return text; } List<string> source = new List<string>(2) { "StorageRack", "Safe" }; if (source.Aggregate(seed: false, (bool accum, string s) => accum || typeString.Contains(s))) { return "StorageEntity"; } return null; } public static ItemSlot DeserializeSlot(SlotIdentifier identifier) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) try { List<Property> source = ((IEnumerable<Property>)Object.FindObjectsOfType<Property>()).ToList(); List<GridItem> list = ((IEnumerable<GridItem>)Object.FindObjectsOfType<GridItem>()).ToList(); Property property = ((IEnumerable<Property>)source).FirstOrDefault((Func<Property, bool>)((Property p) => ((Object)p).name == identifier.property)); List<GridItem> source2 = list.FindAll((GridItem g) => (Object)(object)((BuildableItem)g).ParentProperty == (Object)(object)property); GridItem val = source2.Single((GridItem g) => g.OriginCoordinate == new Vector2(identifier.gridLocation[0], identifier.gridLocation[1])); Component componentByName = ((Component)val).gameObject.GetComponentByName(StringToType(identifier.type)); return new IItemSlotOwner(((Il2CppObjectBase)componentByName).Pointer).ItemSlots[identifier.slotIndex]; } catch (Exception e) { Utils.PrintException(e); } return null; } public static void CompleteTransactions(List<Transaction> transactions) { try { foreach (Transaction transaction in transactions) { ItemSlot val = DeserializeSlot(transaction.slotID); if (val == null) { Utils.Warn("Couldn't deserialize slot!"); continue; } StorableItemInstance itemInstance = Utils.GetItemInstance(transaction.itemID); TryRestocking(val, itemInstance, transaction.quantity); } } catch (Exception e) { Utils.PrintException(e); } } public static void Initialize() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) try { melonPrefs = MelonPreferences.GetCategory("AutoRestock"); timeManager = NetworkSingleton<TimeManager>.Instance; moneyManager = NetworkSingleton<MoneyManager>.Instance; saveManager = Singleton<SaveManager>.Instance; ledgerDay = timeManager.CurrentDay; shelfAccessors = new Dictionary<ItemSlot, NPC>(); coroutines = new Dictionary<Transaction, object>(); lockOwner = ((IEnumerable<NPC>)Object.FindObjectsOfType<NPC>()).FirstOrDefault((Func<NPC, bool>)((NPC npc) => npc.ID == "oscar_holland")); exclusiveLock = new Mutex(); TimeManager obj = timeManager; obj.onDayPass += Action.op_Implicit((Action)OnDayPass); saveManager.onSaveStart.AddListener(Utils.ToUnityAction(OnSaveStart)); ledgerString = GetSaveString() + "_ledger"; transactionString = GetSaveString() + "_inprogress"; if (!melonPrefs.HasEntry(ledgerString)) { melonPrefs.CreateEntry<string>(ledgerString, "[]", "", true); } if (!melonPrefs.HasEntry(transactionString)) { melonPrefs.CreateEntry<string>(transactionString, "[]", "", true); } melonPrefs.LoadFromFile(false); ledger = JsonConvert.DeserializeObject<List<Transaction>>(melonPrefs.GetEntry<string>(ledgerString).Value); isInitialized = true; Utils.Log("AutoRestock manager initialized."); } catch (Exception e) { Utils.PrintException(e); } try { List<Transaction> list = JsonConvert.DeserializeObject<List<Transaction>>(melonPrefs.GetEntry<string>(transactionString).Value); if (list.Count > 0) { Utils.Log($"Completing {list.Count} pending transaction{((list.Count > 1) ? "s" : "")}."); CompleteTransactions(list); } } catch (Exception e2) { Utils.PrintException(e2); } } public static void Stop() { if (isInitialized) { isInitialized = false; ledger.Clear(); StopCoroutines(); lockOwner = null; exclusiveLock.Dispose(); } } public static void StopCoroutines() { if (!isInitialized) { return; } foreach (KeyValuePair<Transaction, object> coroutine in coroutines) { MelonCoroutines.Stop(coroutine.Value); } coroutines.Clear(); } public static void AcquireMutex() { if (isInitialized) { exclusiveLock.WaitOne(); } } public static void ReleaseMutex() { if (isInitialized) { exclusiveLock.ReleaseMutex(); } } public static bool ItemIsRestockable(string itemID) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (isInitialized) { List<string> list = new List<string>(4) { "Agriculture", "Consumable", "Ingredient", "Packaging" }; List<string> list2 = new List<string>(1) { "speedgrow" }; List<string> list3 = new List<string>(3) { "cocaleaf", "cocainebase", "liquidmeth" }; List<string> list4 = new List<string>(5) { "cocaseed", "granddaddypurpleseed", "greencrackseed", "ogkushseed", "sourdieselseed" }; ItemDefinition itemDef = Utils.GetItemDef(itemID); EItemCategory category = itemDef.Category; return (list.Contains(((object)(EItemCategory)(ref category)).ToString()) || list2.Contains(itemDef.ID)) && !list3.Contains(itemDef.ID); } return false; } public static void TryRestocking(ItemSlot slot, StorableItemInstance item, int quantity) { if (isInitialized && InstanceFinder.IsServer) { string iD = ((ItemInstance)item).ID; float num = Mathf.Clamp(melonPrefs.GetEntry<float>("itemDiscount").Value, 0f, 1f); float num2 = ((ItemInstance)item).GetMonetaryValue() * 2f / (float)((ItemInstance)item).Quantity; float num3 = num2 * (float)quantity * (1f - num); bool value = melonPrefs.GetEntry<bool>("payWithCash").Value; bool value2 = melonPrefs.GetEntry<bool>("useDebt").Value; SlotIdentifier slotIdentifier = SerializeSlot(slot); try { if (((ItemInstance)item).StackLimit == 0) { Utils.Debug($"Stacklimit ({((ItemInstance)item).StackLimit}) == 0. Not restocking."); ((ItemInstance)item).RequestClearSlot(); } else if (ItemIsRestockable(((ItemInstance)item).ID)) { float num4 = (value ? moneyManager.cashBalance : moneyManager.onlineBalance); if (num4 < num3 && !value2) { Utils.Log($"Can't afford to restock {quantity}x {iD} (${num3})."); } else if (num4 >= num3) { AcquireMutex(); Transaction transaction = new Transaction(iD, quantity, num, num2, num3, value, slotIdentifier); ledger.Add(transaction); Utils.Debug($"Starting restock coroutine ({iD} x{quantity} at {slotIdentifier.property})."); coroutines[transaction] = MelonCoroutines.Start(RestockCoroutine(slot, item, ((NetworkBehaviour)lockOwner).NetworkObject, transaction)); ReleaseMutex(); } } return; } catch (Exception e) { Utils.PrintException(e); ReleaseMutex(); ((ItemInstance)item).RequestClearSlot(); return; } } Utils.Log("Tried to restock item, but Manager was not initialized!"); } public static bool OwnedByNPC(ItemSlot slot) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) if (isInitialized) { string name = new Object(((Il2CppObjectBase)slot.SlotOwner).Pointer).name; if (name.Contains("Cauldron")) { return (Object)(object)new Cauldron(((Il2CppObjectBase)slot.SlotOwner).Pointer).NPCUserObject != (Object)null; } if (name.Contains("MixingStation") || name.Contains("MixingStationMk2")) { return (Object)(object)new MixingStation(((Il2CppObjectBase)slot.SlotOwner).Pointer).NPCUserObject != (Object)null; } if (name.Contains("PackagingStation") || name.Contains("PackagingStationMk2")) { return (Object)(object)new PackagingStation(((Il2CppObjectBase)slot.SlotOwner).Pointer).NPCUserObject != (Object)null; } if (name.Contains("ChemistryStation")) { return (Object)(object)new ChemistryStation(((Il2CppObjectBase)slot.SlotOwner).Pointer).NPCUserObject != (Object)null; } if (name.Contains("StorageEntity")) { return slot.IsLocked || slot.IsAddLocked || slot.IsRemovalLocked; } return false; } return false; } [IteratorStateMachine(typeof(<RestockCoroutine>d__27))] private static IEnumerator RestockCoroutine(ItemSlot slot, StorableItemInstance item, NetworkObject lockOwner, Transaction transaction) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RestockCoroutine>d__27(0) { slot = slot, item = item, lockOwner = lockOwner, transaction = transaction }; } private static void OnDayPass() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (isInitialized && InstanceFinder.IsServer) { NetworkSingleton<MessagingManager>.Instance.SendMessage(new Message(GetReceipt(), (ESenderType)1, true, -1), true, "oscar_holland"); ledger.Clear(); ledgerDay = timeManager.CurrentDay; } } private static string GetSaveString() { string[] array = Singleton<LoadManager>.Instance.LoadedGameFolderPath.Split('\\'); return array[^2] + "_" + array[^1]; } public static void OnSaveStart() { if (isInitialized && InstanceFinder.IsServer) { string text = GetSaveString() + "_ledger"; if (melonPrefs.HasEntry(text)) { melonPrefs.GetEntry<string>(text).EditedValue = LedgerToJson(); } else { MelonPreferences_Entry val = melonPrefs.CreateEntry<string>(text, "", "", true); val.BoxedEditedValue = LedgerToJson(); } string text2 = GetSaveString() + "_inprogress"; if (melonPrefs.HasEntry(text2)) { melonPrefs.GetEntry<string>(text2).EditedValue = PendingTransactionsToJson(); } else { MelonPreferences_Entry val2 = melonPrefs.CreateEntry<string>(text2, "", "", true); val2.BoxedEditedValue = PendingTransactionsToJson(); } melonPrefs.SaveToFile(false); } } public static List<Transaction> GetPendingTransactions() { return coroutines.Keys.ToList(); } public static string PendingTransactionsToJson() { return JsonConvert.SerializeObject((object)GetPendingTransactions()); } public static float LedgerTotal() { return ledger.Aggregate(0f, (float accum, Transaction transaction) => accum + transaction.totalCost); } public static string LedgerToJson() { return JsonConvert.SerializeObject((object)ledger); } private static string GetReceipt() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (isInitialized) { string text = $"Restock receipt for {ledgerDay}:\n\n"; float num = 0f; if (ledger.Count > 0) { Dictionary<string, Dictionary<string, int>> dictionary = new Dictionary<string, Dictionary<string, int>>(); Dictionary<string, float> dictionary2 = new Dictionary<string, float>(); foreach (Transaction item in ledger) { if (!dictionary.ContainsKey(item.slotID.property)) { dictionary[item.slotID.property] = new Dictionary<string, int>(); } if (!dictionary[item.slotID.property].ContainsKey(item.itemID)) { dictionary[item.slotID.property][item.itemID] = 0; } dictionary[item.slotID.property][item.itemID] += item.quantity; dictionary2[item.itemID] = item.unitPrice; } foreach (string key in dictionary.Keys) { float num2 = 0f; text = text + key + ": \n"; foreach (KeyValuePair<string, int> item2 in dictionary[key]) { string name = Utils.GetItemDef(item2.Key).Name; text += $" {name} x{item2.Value} = ${dictionary2[item2.Key] * (float)item2.Value}\n"; num2 += dictionary2[item2.Key] * (float)item2.Value; } text += "=====================\n"; text += $" Property total: ${num2}\n\n"; num += num2; } } text += "=====================\n"; text += $" Grand total: ${num}\n\n"; return text + "Oscar says thank you for your business! :)"; } return "AutoRestock not initialized!"; } } [HarmonyPatch] public class PersistencePatches : Sched1PatchesBase { [HarmonyPatch(typeof(LoadingScreen), "Close")] [HarmonyPostfix] public static void ClosePostfix(LoadingScreen __instance) { if (InstanceFinder.IsServer && !Manager.isInitialized) { Manager.Initialize(); } } [HarmonyPatch(typeof(LoadManager), "ExitToMenu")] [HarmonyPrefix] public static void ExitToMenuPrefix(LoadManager __instance) { if (InstanceFinder.IsServer && Manager.isInitialized) { Manager.Stop(); } } } [HarmonyPatch] public class CauldronPatches : Sched1PatchesBase { [HarmonyPatch(typeof(Cauldron), "RemoveIngredients")] [HarmonyPrefix] public static bool RemoveIngredientsPrefix(Cauldron __instance) { if (!InstanceFinder.IsServer || !Manager.isInitialized) { return true; } try { if (!Manager.melonPrefs.GetEntry<bool>("enableCauldrons").Value) { return true; } if (__instance.LiquidSlot.ItemInstance.Quantity > 1) { return true; } if (Manager.melonPrefs.GetEntry<bool>("playerRestockStations").Value || (Object)(object)__instance.PlayerUserObject == (Object)null) { StorableItemInstance val = Utils.CastTo<StorableItemInstance>((Object)(object)__instance.LiquidSlot.ItemInstance.GetCopy(1)); Manager.TryRestocking(__instance.LiquidSlot, val, ((ItemInstance)val).StackLimit); } } catch (Exception e) { Utils.Warn(MethodBase.GetCurrentMethod().DeclaringType.Name + ":"); Utils.PrintException(e); } return true; } } [HarmonyPatch] public class MixingStationPatches : Sched1PatchesBase { [HarmonyPatch(typeof(MixingStation), "SendMixingOperation")] [HarmonyPrefix] public static bool SendMixingOperationPrefix(MixingStation __instance, MixOperation operation) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!InstanceFinder.IsServer || !Manager.isInitialized) { return true; } try { if (!Manager.melonPrefs.GetEntry<bool>("enableMixingStations").Value) { return true; } if ((float)(__instance.MixerSlot.Quantity - operation.Quantity) >= ((MixingStationConfiguration)Utils.GetProperty(typeof(MixingStation), "stationConfiguration", __instance)).StartThrehold.GetData().Value) { return true; } if (Manager.melonPrefs.GetEntry<bool>("playerRestockStations").Value || (Object)(object)__instance.PlayerUserObject == (Object)null) { StorableItemInstance itemInstance = Utils.GetItemInstance(operation.IngredientID); Manager.TryRestocking(__instance.MixerSlot, itemInstance, ((ItemInstance)itemInstance).StackLimit); } } catch (Exception e) { Utils.Warn(MethodBase.GetCurrentMethod().DeclaringType.Name + ":"); Utils.PrintException(e); } return true; } } [HarmonyPatch] public class PackagingStationPatches : Sched1PatchesBase { [HarmonyPatch(typeof(PackagingStation), "PackSingleInstance")] [HarmonyPrefix] public static bool PackSingleInstancePrefix(PackagingStation __instance) { if (!InstanceFinder.IsServer || !Manager.isInitialized) { return true; } try { if (!Manager.melonPrefs.GetEntry<bool>("enablePackagingStations").Value) { return true; } if (__instance.PackagingSlot.ItemInstance == null || __instance.PackagingSlot.ItemInstance.Quantity > 1) { return true; } if (Manager.melonPrefs.GetEntry<bool>("playerRestockStations").Value || (Object)(object)__instance.PlayerUserObject == (Object)null) { StorableItemInstance val = Utils.CastTo<StorableItemInstance>((Object)(object)__instance.PackagingSlot.ItemInstance.GetCopy(1)); Manager.TryRestocking(__instance.PackagingSlot, val, ((ItemInstance)val).StackLimit); } } catch (Exception e) { Utils.Warn(MethodBase.GetCurrentMethod().DeclaringType.Name + ":"); Utils.PrintException(e); } return true; } } [HarmonyPatch] public class ChemistryStationPatches : Sched1PatchesBase { private static List<List<T>> Permute<T>(List<T> nums) { List<List<T>> list = new List<List<T>>(); return DoPermute(nums, 0, nums.Count - 1, list); } private static List<List<T>> DoPermute<T>(List<T> nums, int start, int end, List<List<T>> list) { if (start == end) { list.Add(new List<T>(nums)); } else { for (int i = start; i <= end; i++) { Swap(nums, start, i); DoPermute(nums, start + 1, end, list); Swap(nums, start, i); } } return list; } private static void Swap<T>(List<T> list, int index1, int index2) { T value = list[index1]; list[index1] = list[index2]; list[index2] = value; } [HarmonyPatch(typeof(ChemistryStation), "SendCookOperation")] [HarmonyPrefix] public static bool SendCookOperationPrefix(ChemistryStation __instance, ChemistryCookOperation op) { //IL_02af: Unknown result type (might be due to invalid IL or missing references) if (!InstanceFinder.IsServer || !Manager.isInitialized) { return true; } try { if (!Manager.melonPrefs.GetEntry<bool>("enableChemistryStations").Value) { return true; } if (Manager.melonPrefs.GetEntry<bool>("playerRestockStations").Value || (Object)(object)__instance.PlayerUserObject == (Object)null) { List<ItemDefinition> list2 = new List<ItemDefinition>(); Enumerator<IngredientQuantity> enumerator = op.Recipe.Ingredients.GetEnumerator(); while (enumerator.MoveNext()) { IngredientQuantity current = enumerator.Current; bool flag = false; foreach (ItemSlot item in (Il2CppArrayBase<ItemSlot>)(object)__instance.IngredientSlots) { if (item.ItemInstance != null && item.ItemInstance.Definition.Name.Contains(current.Item.Name)) { flag = true; break; } } if (!flag) { list2.Add(current.Item); } } List<List<ItemDefinition>> list3 = new List<List<ItemDefinition>>(); List<List<ItemDefinition>> list4 = new List<List<ItemDefinition>>(); if (list2.Count > 0) { List<ItemSlot> emptySlots = new List<ItemSlot>(); foreach (ItemSlot item2 in (Il2CppArrayBase<ItemSlot>)(object)__instance.IngredientSlots) { if (item2.Quantity == 0) { emptySlots.Add(item2); } } list3 = Permute(list2); list4 = list3.Select(delegate(List<ItemDefinition> mapping) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) bool flag2 = true; for (int i = 0; i < mapping.Count; i++) { ItemInstance val3 = (ItemInstance)((!Utils.IsQualityIngredient(mapping[i].ID)) ? ((object)Utils.GetItemInstance(mapping[i].ID)) : ((object)Utils.GetItemInstance(mapping[i].ID, op.ProductQuality))); if (!emptySlots[i].DoesItemMatchPlayerFilters(val3)) { flag2 = false; break; } } return flag2 ? mapping : null; }).ToList(); list4.RemoveAll((List<ItemDefinition> list) => list == null); if (list4.Count == 0) { Utils.Log("Couldn't restock chemistry station because items do not agree with filters."); } } int num = 0; foreach (ItemSlot item3 in (Il2CppArrayBase<ItemSlot>)(object)__instance.IngredientSlots) { if (item3.ItemInstance == null && list2.Count > 0) { ItemDefinition val = list4[0][num]; if (Utils.IsQualityIngredient(val.ID)) { QualityItemInstance itemInstance = Utils.GetItemInstance(val.ID, op.ProductQuality); Manager.TryRestocking(item3, (StorableItemInstance)(object)itemInstance, ((ItemInstance)itemInstance).StackLimit); } else { StorableItemInstance itemInstance2 = Utils.GetItemInstance(val.ID); Manager.TryRestocking(item3, itemInstance2, ((ItemInstance)itemInstance2).StackLimit); } num++; continue; } int num2 = 0; Enumerator<IngredientQuantity> enumerator5 = op.Recipe.Ingredients.GetEnumerator(); while (enumerator5.MoveNext()) { IngredientQuantity current5 = enumerator5.Current; if (item3.ItemInstance.Definition.Name.Contains(current5.Item.Name)) { num2 = current5.Quantity; break; } } if (num2 > 0 && item3.ItemInstance.Quantity < num2) { StorableItemInstance val2 = Utils.CastTo<StorableItemInstance>((Object)(object)item3.ItemInstance.GetCopy(1)); Manager.TryRestocking(item3, val2, ((ItemInstance)val2).StackLimit); } } } } catch (Exception e) { Utils.Warn(MethodBase.GetCurrentMethod().DeclaringType.Name + ":"); Utils.PrintException(e); } return true; } } [HarmonyPatch] public class StorageEntityPatches : Sched1PatchesBase { [HarmonyPatch(typeof(MoveItemBehaviour), "TakeItem")] [HarmonyPrefix] public static void TakeItemPrefix(MoveItemBehaviour __instance) { if (!InstanceFinder.IsServer || !Manager.isInitialized) { return; } try { if ((int)Utils.CallMethod(typeof(MoveItemBehaviour), "GetAmountToGrab", __instance, Array.Empty<object>()) > 0) { TransitRoute val = Utils.CastTo<TransitRoute>(Utils.GetField(typeof(MoveItemBehaviour), "assignedRoute", __instance)); ItemInstance val2 = Utils.CastTo<ItemInstance>(Utils.GetField(typeof(MoveItemBehaviour), "itemToRetrieveTemplate", __instance)); ItemSlot firstSlotContainingTemplateItem = val.Source.GetFirstSlotContainingTemplateItem(val2, (ESlotType)2); if (firstSlotContainingTemplateItem.SlotOwner != null && Utils.IsObjectStorageRack(firstSlotContainingTemplateItem.SlotOwner) && !Manager.shelfAccessors.TryAdd(firstSlotContainingTemplateItem, ((Behaviour)__instance).Npc)) { Utils.Warn("ItemSlot is already in list of shelfAccessors?"); } } } catch (Exception e) { Utils.PrintException(e); } } [HarmonyPatch(typeof(MoveItemBehaviour), "TakeItem")] [HarmonyPostfix] public static void TakeItemPostfix(MoveItemBehaviour __instance) { if (!InstanceFinder.IsServer || !Manager.isInitialized) { return; } try { TransitRoute val = Utils.CastTo<TransitRoute>(Utils.GetField(typeof(MoveItemBehaviour), "assignedRoute", __instance)); ItemInstance val2 = Utils.CastTo<ItemInstance>(Utils.GetField(typeof(MoveItemBehaviour), "itemToRetrieveTemplate", __instance)); ItemSlot firstSlotContainingTemplateItem = val.Source.GetFirstSlotContainingTemplateItem(val2, (ESlotType)2); if (firstSlotContainingTemplateItem != null) { Manager.shelfAccessors.Remove(firstSlotContainingTemplateItem); } } catch (Exception e) { Utils.PrintException(e); } } [HarmonyPatch(typeof(StorageEntity), "SetStoredInstance")] [HarmonyPrefix] public static void SetStoredInstancePrefix(StorageEntity __instance, int itemSlotIndex, ItemInstance instance) { if (!InstanceFinder.IsServer || !Manager.isInitialized) { return; } try { if (Manager.melonPrefs.GetEntry<bool>("enableStorage").Value && instance == null && IsStorageRack(__instance)) { ItemSlot val = __instance.ItemSlots.ToArray()[itemSlotIndex]; if (val.ItemInstance != null && (!((Object)(object)__instance.CurrentPlayerAccessor != (Object)null) || Manager.shelfAccessors.ContainsKey(val))) { StorableItemInstance val2 = Utils.CastTo<StorableItemInstance>((Object)(object)val.ItemInstance.GetCopy(1)); Manager.TryRestocking(val, val2, ((ItemInstance)val2).StackLimit); } } } catch (Exception e) { Utils.Warn(MethodBase.GetCurrentMethod().DeclaringType.Name + ":"); Utils.PrintException(e); } } private static bool IsStorageRack(StorageEntity item) { if (item.StorageEntityName == "Safe" || item.StorageEntityName == "Large Storage Rack" || item.StorageEntityName == "Medium Storage Rack" || item.StorageEntityName == "Small Storage Rack") { return true; } return false; } } } [CompilerGenerated] internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Length; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Length; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return ((ICollection<T>)_items).Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { ((ICollection<T>)_items).CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return ((IList<T>)_items).IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } }