using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Mirror; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] [HarmonyPatch(typeof(WarehouseButton), "CmdRequestPress", new Type[] { typeof(NetworkConnectionToClient) })] public static class WarehouseButton_CmdRequestPress_Patch { public static bool BypassConfirmation; [HarmonyPrefix] public static bool Prefix(WarehouseButton __instance, NetworkConnectionToClient conn) { if (BypassConfirmation) { return true; } ButtonRerollShop component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } if (!NetworkClient.active) { return true; } if (SafeShopPlugin.EnableCooldown.Value && SafeShopUI.IsOnCooldown(component)) { return false; } if (SafeShopPlugin.EnableConfirmation.Value) { SafeShopUI.RequestConfirmation(component); return false; } return true; } } [HarmonyPatch(typeof(ButtonRerollShop), "OnUpdatePresentation")] public static class ButtonRerollShop_OnUpdatePresentation_Patch { private static FieldInfo _costTextField; private static PropertyInfo _textProp; [HarmonyPostfix] public static void Postfix(ButtonRerollShop __instance) { if (!SafeShopPlugin.EnableCooldown.Value || !SafeShopPlugin.ShowCountdown.Value) { return; } float cooldownRemaining = SafeShopUI.GetCooldownRemaining(__instance); if (cooldownRemaining <= 0f) { return; } FloaterUI floaterUI = SafeShopUI.GetFloaterUI(__instance); if ((Object)(object)floaterUI == (Object)null) { return; } if (_costTextField == null) { _costTextField = AccessTools.Field(typeof(ShopInfoFloaterUI), "costText"); } if (_costTextField == null) { return; } object component = ((Component)floaterUI).GetComponent(typeof(ShopInfoFloaterUI)); if (component == null) { return; } object value = _costTextField.GetValue(component); if (value != null) { if (_textProp == null) { _textProp = value.GetType().GetProperty("text"); } if (!(_textProp == null)) { int num = Mathf.CeilToInt(cooldownRemaining); _textProp.SetValue(value, "Available in\n" + num + "s", null); } } } } [BepInPlugin("strazer.safeshop", "Strazer's SafeShop", "1.0.0")] public class SafeShopPlugin : BaseUnityPlugin { public const string GUID = "strazer.safeshop"; public const string NAME = "Strazer's SafeShop"; public const string VERSION = "1.0.0"; public static ConfigEntry EnableConfirmation; public static ConfigEntry EnableCooldown; public static ConfigEntry CooldownSeconds; public static ConfigEntry ShowCountdown; public static ConfigEntry PopupTitle; public static ConfigEntry PopupMessage; public static SafeShopPlugin Instance { get; private set; } private void Awake() { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown Instance = this; EnableConfirmation = ((BaseUnityPlugin)this).Config.Bind("General", "EnableConfirmation", true, "Show a confirmation popup before rerolling the shop."); EnableCooldown = ((BaseUnityPlugin)this).Config.Bind("General", "EnableCooldown", false, "Apply a cooldown after each reroll."); CooldownSeconds = ((BaseUnityPlugin)this).Config.Bind("General", "CooldownSeconds", 30, "Cooldown duration in seconds."); ShowCountdown = ((BaseUnityPlugin)this).Config.Bind("General", "ShowCountdown", true, "Show the countdown on the in-world button floater."); PopupTitle = ((BaseUnityPlugin)this).Config.Bind("General", "PopupTitle", "Reroll Shop?", "Title text for the confirmation popup."); PopupMessage = ((BaseUnityPlugin)this).Config.Bind("General", "PopupMessage", "Spend {0} to reroll the shop?", "Message text for the confirmation popup. {0} is replaced with the cost."); SafeShopUI.Initialize(); Harmony val = new Harmony("strazer.safeshop"); val.PatchAll(); GameObject val2 = new GameObject("SafeShop_UI"); Object.DontDestroyOnLoad((Object)(object)val2); ((Object)val2).hideFlags = (HideFlags)61; val2.AddComponent(); Debug.Log((object)"[SafeShop] Loaded"); } } public class SafeShopUI : MonoBehaviour, IInputController { private const float WindowWidth = 420f; private const float WindowHeight = 240f; private const float ButtonHeight = 44f; private const float ButtonWidth = 140f; private const float ButtonSpacing = 24f; private const float OverlayAlpha = 0.4f; private const float AnimDuration = 0.18f; private const int PopupWindowId = 1396786757; private static readonly Dictionary Cooldowns = new Dictionary(); private static ButtonRerollShop _pendingButton; private static bool _popupVisible; private static SafeShopUI _instance; private static FieldInfo _floaterUIField; private static FieldInfo _costForRerollField; private static FieldInfo _syncTimesRerolledField; private static FieldInfo _rerollCostIncrementField; private static FieldInfo _costTextField; private static FieldInfo _pressedField; private static FieldInfo _receivedResponseField; private static MethodInfo _cmdRequestPressMethod; private Rect _windowRect; private int _cost; private float _openTime; private bool _savedCursorVisible; private CursorLockMode _savedCursorLockMode; private bool _cursorSaved; private bool _controllerRegistered; private GUIStyle _windowStyle; private GUIStyle _titleStyle; private GUIStyle _messageStyle; private GUIStyle _costLabelStyle; private GUIStyle _costValueStyle; private GUIStyle _confirmButtonStyle; private GUIStyle _cancelButtonStyle; private GUIStyle _separatorStyle; private bool _stylesReady; public static void Initialize() { _floaterUIField = AccessTools.Field(typeof(ButtonRerollShop), "_floaterUI"); _costForRerollField = AccessTools.Field(typeof(ButtonRerollShop), "costForReroll"); _syncTimesRerolledField = AccessTools.Field(typeof(ButtonRerollShop), "_syncTimesRerolled"); _rerollCostIncrementField = AccessTools.Field(typeof(ButtonRerollShop), "rerollCostIncrement"); _costTextField = AccessTools.Field(typeof(ShopInfoFloaterUI), "costText"); _pressedField = AccessTools.Field(typeof(WarehouseButton), "_pressed"); _receivedResponseField = AccessTools.Field(typeof(WarehouseButton), "_receivedResponse"); _cmdRequestPressMethod = AccessTools.Method(typeof(WarehouseButton), "CmdRequestPress", new Type[1] { typeof(NetworkConnectionToClient) }, (Type[])null); } public static FloaterUI GetFloaterUI(ButtonRerollShop button) { if (_floaterUIField == null) { return null; } object? value = _floaterUIField.GetValue(button); return (FloaterUI)((value is FloaterUI) ? value : null); } private static int GetRerollCost(ButtonRerollShop button) { int num = 0; int num2 = 0; int num3 = 0; if (_costForRerollField != null) { num = (int)_costForRerollField.GetValue(button); } if (_syncTimesRerolledField != null) { num2 = (int)_syncTimesRerolledField.GetValue(button); } if (_rerollCostIncrementField != null) { num3 = (int)_rerollCostIncrementField.GetValue(button); } return num + num2 * num3; } private void Awake() { _instance = this; } private void Update() { TickCooldowns(); if (_popupVisible) { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } } private void TickCooldowns() { if (Cooldowns.Count == 0) { return; } float unscaledTime = Time.unscaledTime; List list = null; foreach (KeyValuePair cooldown in Cooldowns) { if (unscaledTime >= cooldown.Value) { if (list == null) { list = new List(); } list.Add(cooldown.Key); } } if (list == null) { return; } foreach (ButtonRerollShop item in list) { RestoreButton(item); Cooldowns.Remove(item); } Debug.Log((object)"[SafeShop] Cooldown ended"); } private void OnGUI() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if (_popupVisible) { EnsureStyles(); HandleKeyboardInput(); HandleControllerInput(); float num = Mathf.Clamp01((Time.unscaledTime - _openTime) / 0.18f); float progress = 1f - (1f - num) * (1f - num); DrawOverlay(progress); _windowRect = new Rect(((float)Screen.width - 420f) * 0.5f, ((float)Screen.height - 240f) * 0.5f, 420f, 240f); GUI.backgroundColor = Color.clear; _windowRect = GUI.Window(1396786757, _windowRect, new WindowFunction(DrawWindowContents), SafeShopPlugin.PopupTitle.Value, _windowStyle); } } private void DrawOverlay(float progress) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.4f * progress); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } private void DrawWindowContents(int id) { GUILayout.Space(4f); GUILayout.Label(SafeShopPlugin.PopupTitle.Value, _titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Space(6f); string text = string.Format(SafeShopPlugin.PopupMessage.Value, "$" + _cost); GUILayout.Label(text, _messageStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Space(10f); GUILayout.Label("", _separatorStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f); GUILayout.Label("Cost", _costLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Label("$" + _cost, _costValueStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Space(4f); GUILayout.Label("", _separatorStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f); DrawButtons(); } private void DrawButtons() { GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.FlexibleSpace(); if (GUILayout.Button("Confirm", _confirmButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(140f), GUILayout.Height(44f) })) { ConfirmReroll(); } GUILayout.Space(24f); if (GUILayout.Button("Cancel", _cancelButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(140f), GUILayout.Height(44f) })) { CancelReroll(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } private void HandleKeyboardInput() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 Event current = Event.current; if ((int)current.type == 4) { if ((int)current.keyCode == 27) { CancelReroll(); current.Use(); } else if ((int)current.keyCode == 13 || (int)current.keyCode == 271 || (int)current.keyCode == 32) { ConfirmReroll(); current.Use(); } } } private void HandleControllerInput() { if (Input.GetKeyDown((KeyCode)330) || Input.GetKeyDown((KeyCode)350) || Input.GetKeyDown((KeyCode)370) || Input.GetKeyDown((KeyCode)390)) { ConfirmReroll(); } if (Input.GetKeyDown((KeyCode)331) || Input.GetKeyDown((KeyCode)351) || Input.GetKeyDown((KeyCode)371) || Input.GetKeyDown((KeyCode)391)) { CancelReroll(); } } public void OnInputControlGained() { } public void OnInputControlLost() { } private void EnsureStyles() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00d1: 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_00f3: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Expected O, but got Unknown //IL_0283: Unknown result type (might be due to invalid IL or missing references) if (!_stylesReady) { _stylesReady = true; _windowStyle = new GUIStyle(GUI.skin.window); Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, new Color(0.12f, 0.12f, 0.14f, 0.97f)); val.Apply(); _windowStyle.normal.background = val; _windowStyle.padding = new RectOffset(16, 16, 8, 16); _windowStyle.border = new RectOffset(8, 8, 8, 8); GUIStyle val2 = new GUIStyle(GUI.skin.label); val2.fontSize = 22; val2.fontStyle = (FontStyle)1; val2.alignment = (TextAnchor)1; val2.normal.textColor = Color.white; _titleStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label); val3.fontSize = 16; val3.alignment = (TextAnchor)1; val3.normal.textColor = new Color(0.85f, 0.85f, 0.85f); val3.wordWrap = true; _messageStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.label); val4.fontSize = 14; val4.alignment = (TextAnchor)1; val4.normal.textColor = new Color(0.7f, 0.7f, 0.7f); _costLabelStyle = val4; GUIStyle val5 = new GUIStyle(GUI.skin.label); val5.fontSize = 22; val5.fontStyle = (FontStyle)1; val5.alignment = (TextAnchor)1; val5.normal.textColor = new Color(0.3f, 0.95f, 0.35f); _costValueStyle = val5; GUIStyle val6 = new GUIStyle(GUI.skin.button); val6.fontSize = 16; val6.fontStyle = (FontStyle)1; val6.alignment = (TextAnchor)4; val6.fixedHeight = 44f; _confirmButtonStyle = val6; GUIStyle val7 = new GUIStyle(GUI.skin.button); val7.fontSize = 16; val7.fontStyle = (FontStyle)1; val7.alignment = (TextAnchor)4; val7.fixedHeight = 44f; _cancelButtonStyle = val7; _separatorStyle = new GUIStyle(); Texture2D val8 = new Texture2D(1, 1); val8.SetPixel(0, 0, new Color(0.35f, 0.35f, 0.4f, 0.8f)); val8.Apply(); _separatorStyle.normal.background = val8; } } public static void RequestConfirmation(ButtonRerollShop button) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (_popupVisible || (Object)(object)_pendingButton != (Object)null) { return; } _pendingButton = button; if (!((Object)(object)_instance == (Object)null)) { _instance._cost = GetRerollCost(button); _instance._openTime = Time.unscaledTime; _instance._savedCursorVisible = Cursor.visible; _instance._savedCursorLockMode = Cursor.lockState; _instance._cursorSaved = true; Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; _popupVisible = true; if (!_instance._controllerRegistered) { AggroInputManager.PushController((IInputController)(object)_instance); _instance._controllerRegistered = true; } Debug.Log((object)"[SafeShop] Popup opened"); } } private void ConfirmReroll() { ClosePopup(); ButtonRerollShop pendingButton = _pendingButton; _pendingButton = null; if (!((Object)(object)pendingButton == (Object)null) && !(_cmdRequestPressMethod == null)) { Debug.Log((object)"[SafeShop] Player confirmed"); WarehouseButton_CmdRequestPress_Patch.BypassConfirmation = true; WarehouseButton component = ((Component)pendingButton).GetComponent(); if ((Object)(object)component != (Object)null) { MethodInfo cmdRequestPressMethod = _cmdRequestPressMethod; object[] parameters = new object[1]; cmdRequestPressMethod.Invoke(component, parameters); } WarehouseButton_CmdRequestPress_Patch.BypassConfirmation = false; if (SafeShopPlugin.EnableCooldown.Value) { StartCooldown(pendingButton); } } } private void CancelReroll() { if ((Object)(object)_pendingButton != (Object)null) { ResetButtonState(_pendingButton); } ClosePopup(); _pendingButton = null; Debug.Log((object)"[SafeShop] Player cancelled"); } private void ClosePopup() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) _popupVisible = false; if (_controllerRegistered) { AggroInputManager.RemoveController((IInputController)(object)this); _controllerRegistered = false; } if (_cursorSaved) { Cursor.visible = _savedCursorVisible; Cursor.lockState = _savedCursorLockMode; _cursorSaved = false; } } private static void ResetButtonState(ButtonRerollShop button) { WarehouseButton component = ((Component)button).GetComponent(); if (!((Object)(object)component == (Object)null)) { if (_pressedField != null) { _pressedField.SetValue(component, false); } if (_receivedResponseField != null) { _receivedResponseField.SetValue(component, true); } } } private void OnDisable() { ForceClose(); } private void OnDestroy() { ForceClose(); } private void ForceClose() { if (_popupVisible) { if ((Object)(object)_pendingButton != (Object)null) { ResetButtonState(_pendingButton); } ClosePopup(); _pendingButton = null; } } public static bool IsOnCooldown(ButtonRerollShop button) { if (!Cooldowns.TryGetValue(button, out var value)) { return false; } return Time.unscaledTime < value; } public static float GetCooldownRemaining(ButtonRerollShop button) { if (!Cooldowns.TryGetValue(button, out var value)) { return -1f; } return value - Time.unscaledTime; } private static void StartCooldown(ButtonRerollShop button) { float value = Time.unscaledTime + (float)SafeShopPlugin.CooldownSeconds.Value; Cooldowns[button] = value; Debug.Log((object)"[SafeShop] Cooldown started"); } private static void RestoreButton(ButtonRerollShop button) { FloaterUI floaterUI = GetFloaterUI(button); if ((Object)(object)floaterUI == (Object)null || _costTextField == null) { return; } object component = ((Component)floaterUI).GetComponent(typeof(ShopInfoFloaterUI)); if (component == null) { return; } object value = _costTextField.GetValue(component); if (value != null) { PropertyInfo property = value.GetType().GetProperty("text"); if (property != null) { property.SetValue(value, "", null); } } } }