Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of AutomaticReup v0.2.0
Mods/AutomatedReup.dll
Decompiled a week agousing System; 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 AutomatedReUp; using FishNet; using FishNet.Connection; using FishNet.Object; using MelonLoader; using Microsoft.CodeAnalysis; using ScheduleOne.DevUtilities; using ScheduleOne.Economy; using ScheduleOne.ItemFramework; using ScheduleOne.NPCs; using ScheduleOne.Product; using ScheduleOne.UI; 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(ReUpMod), "Automated Re-Up", "1.1.0", "You", null)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AutomatedReup")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5b8bfea65b08fe9810ef21cd116fad8f5be354cf")] [assembly: AssemblyProduct("AutomatedReup")] [assembly: AssemblyTitle("AutomatedReup")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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 AutomatedReUp { public sealed class ReUpMod : MelonMod { private const KeyCode OPEN_STASH_KEY = 291; private const int REUP_WHEN_BELOW_UNITS = 200; private const int REUP_TARGET_UNITS = 600; private const float CHECK_INTERVAL_SECONDS = 2f; private const int STASH_SLOT_COUNT = 24; private ReUpStashContainer _stash; private float _nextCheckTime; private bool _stashUiOpen; private UnityAction _onStorageClosedAction; public override void OnInitializeMelon() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown _onStorageClosedAction = new UnityAction(OnAnyStorageMenuClosed); _nextCheckTime = 0f; MelonLogger.Msg("[ReUp] Loaded. Press F10 to open stash."); } public override void OnUpdate() { if (Input.GetKeyDown((KeyCode)291)) { ToggleStashUI(); } if (Time.unscaledTime >= _nextCheckTime) { _nextCheckTime = Time.unscaledTime + 2f; TryAutoReUp(); } } private void ToggleStashUI() { StorageMenu instance = Singleton<StorageMenu>.Instance; if ((Object)(object)instance == (Object)null) { MelonLogger.Warning("[ReUp] StorageMenu is not available yet."); return; } EnsureStashExists(); instance.Open((IItemSlotOwner)(object)_stash, "Automated Re-Up Stash", "Place PACKAGED product here. Dealers will be topped up automatically."); _stashUiOpen = true; instance.onClosed.RemoveListener(_onStorageClosedAction); instance.onClosed.AddListener(_onStorageClosedAction); } private void OnAnyStorageMenuClosed() { _stashUiOpen = false; StorageMenu instance = Singleton<StorageMenu>.Instance; if ((Object)(object)instance != (Object)null) { instance.onClosed.RemoveListener(_onStorageClosedAction); } } private void EnsureStashExists() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_stash != (Object)null)) { GameObject val = new GameObject("AutomatedReUp_StashContainer"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); _stash = val.AddComponent<ReUpStashContainer>(); _stash.Initialize(24); MelonLogger.Msg($"[ReUp] Stash created with {24} slots."); } } private void TryAutoReUp() { if (_stashUiOpen || !InstanceFinder.IsServer || (Object)(object)_stash == (Object)null || _stash.GetTotalPackagedUnits() <= 0) { return; } List<Dealer> list = Dealer.AllPlayerDealers?.ToList(); if (list == null || list.Count == 0) { return; } foreach (Dealer item in list) { if ((Object)(object)item == (Object)null || !item.IsRecruited) { continue; } int packagedProductAmount = item.GetPackagedProductAmount(); if (packagedProductAmount >= 200) { continue; } int num = 600; int num2 = num - packagedProductAmount; if (num2 > 0) { int num3 = TransferPackagedUnitsFromStashToDealer(item, num2); if (num3 > 0) { MelonLogger.Msg($"[ReUp] Topped up {((NPC)item).fullName}: +{num3} units (was {packagedProductAmount}, target {num})."); } } } } private int TransferPackagedUnitsFromStashToDealer(Dealer dealer, int neededUnits) { if ((Object)(object)_stash == (Object)null || (Object)(object)dealer == (Object)null || neededUnits <= 0) { return 0; } int num = 0; for (int i = 0; i < _stash.ItemSlots.Count; i++) { if (neededUnits <= 0) { break; } ItemSlot val = _stash.ItemSlots[i]; if (val == null || val.ItemInstance == null || val.Quantity <= 0) { continue; } ItemInstance itemInstance = val.ItemInstance; ProductItemInstance val2 = (ProductItemInstance)(object)((itemInstance is ProductItemInstance) ? itemInstance : null); if (val2 == null || (Object)(object)val2.AppliedPackaging == (Object)null) { continue; } int amount = val2.Amount; if (amount <= 0) { continue; } while (val.ItemInstance != null && val.Quantity > 0 && neededUnits > 0) { ItemInstance itemInstance2 = val.ItemInstance; ProductItemInstance val3 = (ProductItemInstance)(object)((itemInstance2 is ProductItemInstance) ? itemInstance2 : null); if (val3 == null || (Object)(object)val3.AppliedPackaging == (Object)null) { break; } amount = val3.Amount; if (amount <= 0) { break; } ItemInstance copy = ((ItemInstance)val3).GetCopy(1); ProductItemInstance val4 = (ProductItemInstance)(object)((copy is ProductItemInstance) ? copy : null); if (val4 == null) { break; } int quantity = ((ItemInstance)val4).Quantity; dealer.AddItemToInventory((ItemInstance)(object)val4); if (((ItemInstance)val4).Quantity >= quantity) { return num; } val.ChangeQuantity(-1, true); num += amount; neededUnits -= amount; } } return num; } } public sealed class ReUpStashContainer : MonoBehaviour, IItemSlotOwner { private bool _initialized; public List<ItemSlot> ItemSlots { get; set; } = new List<ItemSlot>(); public void Initialize(int slotCount) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown if (!_initialized) { _initialized = true; ItemSlots.Clear(); ItemSlots.Capacity = Mathf.Max(ItemSlots.Capacity, slotCount); for (int i = 0; i < slotCount; i++) { ItemSlot val = new ItemSlot(); val.SetSlotOwner((IItemSlotOwner)(object)this); } } } public int GetTotalPackagedUnits() { int num = 0; foreach (ItemSlot itemSlot in ItemSlots) { ItemInstance obj = ((itemSlot != null) ? itemSlot.ItemInstance : null); ProductItemInstance val = (ProductItemInstance)(object)((obj is ProductItemInstance) ? obj : null); if (val != null && (Object)(object)val.AppliedPackaging != (Object)null) { num += itemSlot.Quantity * val.Amount; } } return num; } public void SetStoredInstance(NetworkConnection conn, int itemSlotIndex, ItemInstance instance) { if (IsValidIndex(itemSlotIndex)) { ItemSlot val = ItemSlots[itemSlotIndex]; if (instance == null || instance.Quantity <= 0) { val.ClearStoredInstance(true); } else { val.SetStoredItem(instance, true); } } } public void SetItemSlotQuantity(int itemSlotIndex, int quantity) { if (!IsValidIndex(itemSlotIndex)) { return; } ItemSlot val = ItemSlots[itemSlotIndex]; if (val.ItemInstance != null) { if (quantity <= 0) { val.ClearStoredInstance(true); } else { val.SetQuantity(quantity, true); } } } public void SetSlotLocked(NetworkConnection conn, int itemSlotIndex, bool locked, NetworkObject lockOwner, string lockReason) { if (IsValidIndex(itemSlotIndex)) { ItemSlot val = ItemSlots[itemSlotIndex]; if (locked) { val.ApplyLock(lockOwner, lockReason, true); } else { val.RemoveLock(true); } } } public void SetSlotFilter(NetworkConnection conn, int itemSlotIndex, SlotFilter filter) { if (IsValidIndex(itemSlotIndex)) { ItemSlots[itemSlotIndex].SetPlayerFilter(filter, true); } } private bool IsValidIndex(int idx) { return idx >= 0 && idx < ItemSlots.Count; } } }