Decompiled source of StrazersSafeShop v1.0.0

StrazersSafeShop.dll

Decompiled a day ago
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<ButtonRerollShop>();
		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<bool> EnableConfirmation;

	public static ConfigEntry<bool> EnableCooldown;

	public static ConfigEntry<int> CooldownSeconds;

	public static ConfigEntry<bool> ShowCountdown;

	public static ConfigEntry<string> PopupTitle;

	public static ConfigEntry<string> 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<bool>("General", "EnableConfirmation", true, "Show a confirmation popup before rerolling the shop.");
		EnableCooldown = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableCooldown", false, "Apply a cooldown after each reroll.");
		CooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "CooldownSeconds", 30, "Cooldown duration in seconds.");
		ShowCountdown = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowCountdown", true, "Show the countdown on the in-world button floater.");
		PopupTitle = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PopupTitle", "Reroll Shop?", "Title text for the confirmation popup.");
		PopupMessage = ((BaseUnityPlugin)this).Config.Bind<string>("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<SafeShopUI>();
		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<ButtonRerollShop, float> Cooldowns = new Dictionary<ButtonRerollShop, float>();

	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<ButtonRerollShop> list = null;
		foreach (KeyValuePair<ButtonRerollShop, float> cooldown in Cooldowns)
		{
			if (unscaledTime >= cooldown.Value)
			{
				if (list == null)
				{
					list = new List<ButtonRerollShop>();
				}
				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<WarehouseButton>();
			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<WarehouseButton>();
		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);
			}
		}
	}
}