using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("coddingcat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Spam Space while restocking shelves in Shift At Midnight.")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0")] [assembly: AssemblyProduct("SpaceRefillMod")] [assembly: AssemblyTitle("SpaceRefillMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.3.0.0")] [module: UnverifiableCode] [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 SpaceRefillMod { internal static class PluginInfo { internal const string Guid = "com.coddingcat.shiftatm.spacerefill"; internal const string Name = "Space Refill"; internal const string Version = "2.3.0"; } [BepInPlugin("com.coddingcat.shiftatm.spacerefill", "Space Refill", "2.3.0")] public sealed class SpaceRefillPlugin : BasePlugin { private Harmony _harmony; private static ConfigEntry _boostPerPress; private static ConfigEntry _drainPerSecond; internal static ManualLogSource LogSource { get; private set; } internal static float BoostPerPress => Mathf.Clamp(_boostPerPress?.Value ?? 0.12f, 0.01f, 1f); internal static float DrainPerSecond => Mathf.Max(0f, _drainPerSecond?.Value ?? 0.5f); public override void Load() { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown LogSource = ((BasePlugin)this).Log; _boostPerPress = ((BasePlugin)this).Config.Bind("Meter", "BoostPerPress", 0.12f, "Amount added to the meter by each Space press."); _drainPerSecond = ((BasePlugin)this).Config.Bind("Meter", "DrainPerSecond", 0.5f, "Meter power lost per second. Lower values make each press last longer."); bool flag = default(bool); try { if (!ShelfGameAccess.Validate(out var error)) { throw new InvalidOperationException(error); } SpamMeterUi.Create(); _harmony = new Harmony("com.coddingcat.shiftatm.spacerefill"); _harmony.PatchAll(typeof(RestockShelfPatches)); ManualLogSource log = ((BasePlugin)this).Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("Space Refill"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("2.3.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded."); } log.LogInfo(val); ((BasePlugin)this).Log.LogInfo((object)"Interact with a shelf and spam Space. A full meter places one item."); } catch (Exception ex) { SpamMeterUi.Destroy(); ManualLogSource log2 = ((BasePlugin)this).Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(23, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to initialise "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted("Space Refill"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex); } log2.LogError(val2); throw; } } public override bool Unload() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } RefillController.Reset(); SpamMeterUi.Destroy(); LogSource = null; return true; } } internal static class RefillController { private const float PlacementRetryDelay = 0.5f; private const float FailureLogCooldown = 5f; private static RestockShelf _activeShelf; private static float _meterPower; private static float _retryAt; private static float _nextFailureLogAt; internal static void Start(RestockShelf shelf) { if (ShelfGameAccess.IsInteracting(shelf)) { _activeShelf = shelf; _meterPower = 0f; _retryAt = 0f; SpamMeterUi.SetLevel(0f); SpamMeterUi.SetVisible(visible: true); } } internal static void Stop(RestockShelf shelf) { if (IsActiveShelf(shelf)) { Reset(); } } internal static void Tick(RestockShelf shelf) { if (!IsActiveShelf(shelf)) { return; } if (!ShelfGameAccess.IsInteracting(shelf)) { Reset(); return; } if (Input.GetKeyDown((KeyCode)32)) { HandleSpacePress(shelf); } float num = Mathf.Clamp(Time.unscaledDeltaTime, 0f, 0.25f); _meterPower = Mathf.Max(0f, _meterPower - SpaceRefillPlugin.DrainPerSecond * num); SpamMeterUi.SetLevel(_meterPower); } internal static void Reset() { _activeShelf = null; _meterPower = 0f; _retryAt = 0f; SpamMeterUi.SetLevel(0f); SpamMeterUi.SetVisible(visible: false); } private static void HandleSpacePress(RestockShelf shelf) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown _meterPower = Mathf.Clamp01(_meterPower + SpaceRefillPlugin.BoostPerPress); if (_meterPower < 1f || Time.unscaledTime < _retryAt) { return; } string error; PlacementResult placementResult = ShelfGameAccess.TryPlaceNextItem(shelf, out error); if (placementResult == PlacementResult.Success || placementResult == PlacementResult.ShelfEmpty) { _meterPower = 0f; SpamMeterUi.SetLevel(0f); return; } _retryAt = Time.unscaledTime + 0.5f; if (Time.unscaledTime < _nextFailureLogAt) { return; } ManualLogSource logSource = SpaceRefillPlugin.LogSource; if (logSource != null) { bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(37, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not place the next shelf item: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(error); } logSource.LogWarning(val); } _nextFailureLogAt = Time.unscaledTime + 5f; } private static bool IsActiveShelf(RestockShelf shelf) { if ((Object)(object)shelf != (Object)null && (Object)(object)_activeShelf != (Object)null) { return ((Il2CppObjectBase)_activeShelf).Pointer == ((Il2CppObjectBase)shelf).Pointer; } return false; } } internal enum PlacementResult { Success, ShelfEmpty, Failed } internal static class ShelfGameAccess { private const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly PropertyInfo InteractingProperty = typeof(RestockShelf).GetProperty("interacting", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly PropertyInfo ProductsQueueProperty = typeof(ShelfManager).GetProperty("productsQueue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly PropertyInfo LastShelfItemProperty = typeof(ShelfManager).GetProperty("lastShelfItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo CompleteItemMethod = typeof(ShelfManager).GetMethod("CompleteItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static Type _cachedQueueType; private static PropertyInfo _queueCountProperty; private static MethodInfo _queuePeekMethod; internal static bool Validate(out string error) { if (InteractingProperty == null) { error = "RestockShelf.interacting was not found. The game may have been updated."; return false; } if (ProductsQueueProperty == null || LastShelfItemProperty == null || CompleteItemMethod == null) { error = "Required ShelfManager members were not found. The game may have been updated."; return false; } error = null; return true; } internal static bool IsInteracting(RestockShelf shelf) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown if ((Object)(object)shelf == (Object)null) { return false; } try { object value = InteractingProperty.GetValue(shelf); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch (Exception ex) { ManualLogSource logSource = SpaceRefillPlugin.LogSource; if (logSource != null) { bool flag2 = default(bool); BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(41, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not read RestockShelf.interacting: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logSource.LogDebug(val); } return false; } } internal static PlacementResult TryPlaceNextItem(RestockShelf shelf, out string error) { error = null; try { ShelfManager val = ((shelf != null) ? shelf.shelfMan : null); if ((Object)(object)val == (Object)null) { return Fail("the shelf manager is missing", out error); } object value = ProductsQueueProperty.GetValue(val); if (value == null) { return Fail("the product queue is not ready", out error); } if (!TryPrepareQueueAccess(value.GetType(), out error)) { return PlacementResult.Failed; } if (Convert.ToInt32(_queueCountProperty.GetValue(value)) <= 0) { return PlacementResult.ShelfEmpty; } object? obj = _queuePeekMethod.Invoke(value, null); object? obj2 = ((obj is GameObject) ? obj : null); DragItem val2 = ((obj2 != null) ? ((GameObject)obj2).GetComponent() : null); if ((Object)(object)val2 == (Object)null) { return Fail("the next product has no DragItem component", out error); } ShelfItemManager val3 = FindMatchingSlot(val, val2.itemIndex); if ((Object)(object)val3 == (Object)null) { return Fail($"no shelf slot accepts item index {val2.itemIndex}", out error); } LastShelfItemProperty.SetValue(val, val3); CompleteItemMethod.Invoke(val, null); return PlacementResult.Success; } catch (TargetInvocationException ex) { return Fail(ex.InnerException?.Message ?? ex.Message, out error); } catch (Exception ex2) { return Fail(ex2.Message, out error); } } private static bool TryPrepareQueueAccess(Type queueType, out string error) { if (_cachedQueueType == queueType && _queueCountProperty != null && _queuePeekMethod != null) { error = null; return true; } _cachedQueueType = queueType; _queueCountProperty = queueType.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _queuePeekMethod = queueType.GetMethod("Peek", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (_queueCountProperty != null && _queuePeekMethod != null) { error = null; return true; } error = "the product queue API was not found"; return false; } private static ShelfItemManager FindMatchingSlot(ShelfManager manager, int itemIndex) { ShelfItemManager[] array = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)manager.shelfItemManagers); if (array == null) { return null; } foreach (ShelfItemManager val in array) { if ((Object)(object)val != (Object)null && val.itemIndex == itemIndex) { return val; } } return null; } private static PlacementResult Fail(string message, out string error) { error = (string.IsNullOrWhiteSpace(message) ? "unknown game error" : message); return PlacementResult.Failed; } } internal static class SpamMeterUi { private static GameObject _canvasObject; private static RectTransform _fillRect; internal static void Create() { //IL_005e: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_canvasObject != (Object)null)) { _canvasObject = CreateUiObject("SpaceRefill_Canvas"); Object.DontDestroyOnLoad((Object)(object)_canvasObject); Canvas component = _canvasObject.GetComponent(); component.renderMode = (RenderMode)0; component.sortingOrder = 999; CanvasScaler component2 = _canvasObject.GetComponent(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.matchWidthOrHeight = 0.5f; GameObject val = CreateUiObject("SpaceRefill_Background"); val.transform.SetParent(_canvasObject.transform, false); RectTransform component3 = val.GetComponent(); component3.anchorMin = new Vector2(0.92f, 0.5f); component3.anchorMax = new Vector2(0.92f, 0.5f); component3.pivot = new Vector2(0.5f, 0.5f); component3.anchoredPosition = Vector2.zero; component3.sizeDelta = new Vector2(32f, 260f); Image component4 = val.GetComponent(); ((Graphic)component4).color = new Color(0.02f, 0.02f, 0.02f, 0.82f); ((Graphic)component4).raycastTarget = false; GameObject obj = CreateUiObject("SpaceRefill_Fill"); obj.transform.SetParent(val.transform, false); _fillRect = obj.GetComponent(); _fillRect.anchorMin = Vector2.zero; _fillRect.anchorMax = new Vector2(1f, 0f); _fillRect.pivot = new Vector2(0.5f, 0f); _fillRect.offsetMin = Vector2.zero; _fillRect.offsetMax = Vector2.zero; Image component5 = obj.GetComponent(); ((Graphic)component5).color = Color.white; ((Graphic)component5).raycastTarget = false; SetVisible(visible: false); } } internal static void Destroy() { if ((Object)(object)_canvasObject != (Object)null) { Object.Destroy((Object)(object)_canvasObject); } _canvasObject = null; _fillRect = null; } internal static void SetVisible(bool visible) { if ((Object)(object)_canvasObject != (Object)null && _canvasObject.activeSelf != visible) { _canvasObject.SetActive(visible); } } internal static void SetLevel(float amount) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_fillRect == (Object)null)) { Vector2 anchorMax = _fillRect.anchorMax; anchorMax.x = 1f; anchorMax.y = Mathf.Clamp01(amount); _fillRect.anchorMax = anchorMax; } } private static GameObject CreateUiObject(string name) where TComponent : Component { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return new GameObject(name, (Type[])(object)new Type[2] { Il2CppType.Of(), Il2CppType.Of() }); } private static GameObject CreateUiObject(string name) where TFirst : Component where TSecond : Component { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown return new GameObject(name, (Type[])(object)new Type[3] { Il2CppType.Of(), Il2CppType.Of(), Il2CppType.Of() }); } } [HarmonyPatch] internal static class RestockShelfPatches { [HarmonyPatch(typeof(RestockShelf), "Interact")] [HarmonyPostfix] private static void AfterInteract(RestockShelf __instance) { RefillController.Start(__instance); } [HarmonyPatch(typeof(RestockShelf), "StopInteract")] [HarmonyPostfix] private static void AfterStopInteract(RestockShelf __instance) { RefillController.Stop(__instance); } [HarmonyPatch(typeof(RestockShelf), "Update")] [HarmonyPostfix] private static void AfterUpdate(RestockShelf __instance) { RefillController.Tick(__instance); } } }