Decompiled source of GiveCorrectChange v1.0.0

GiveCorrectChange.dll

Decompiled 12 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("GiveCorrectChange")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GiveCorrectChange")]
[assembly: AssemblyTitle("GiveCorrectChange")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 GiveCorrectChange
{
	[BepInPlugin("com.acesgaminguk.givecorrectchange", "GiveCorrectChange", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static Harmony Harmony;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<ChangeMode> Mode;

		internal static ConfigEntry<KeyboardShortcut> ManualHotkey;

		internal static ConfigEntry<float> PanelX;

		internal static ConfigEntry<float> PanelY;

		internal static Data_Container? ActiveCashRegister;

		internal static bool ManualChangePrepared;

		internal static float ManualPreparedAt;

		private Rect _panelRect;

		private bool _panelPositionLoaded;

		private GUIStyle? _windowStyle;

		private GUIStyle? _titleStyle;

		private GUIStyle? _smallStyle;

		private GUIStyle? _buttonStyle;

		private GUIStyle? _dangerButtonStyle;

		private void Awake()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("# General #", "Enabled", true, "Enable Give Correct Change.");
			Mode = ((BaseUnityPlugin)this).Config.Bind<ChangeMode>("# General #", "Mode", ChangeMode.ManualFill, "ManualFill shows a status panel and uses the hotkey. AutoFill prepares the exact change automatically. AutoComplete immediately completes cash transactions.");
			ManualHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("# Controls #", "ManualHotkey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Hotkey used in ManualFill mode to prepare the correct change. Rebind this in the config or BepInEx ConfigurationManager.");
			PanelX = ((BaseUnityPlugin)this).Config.Bind<float>("# UI #", "PanelX", -1f, "ManualFill panel X position. -1 uses default centered position.");
			PanelY = ((BaseUnityPlugin)this).Config.Bind<float>("# UI #", "PanelY", -1f, "ManualFill panel Y position. -1 uses default lower-screen position.");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)string.Format("{0} v{1} Initializing...", "Give Correct Change", ((BaseUnityPlugin)this).Info.Metadata.Version));
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Author: AcesGamingUK");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"GitHub: https://github.com/AcesGamingUK/Give-Correct-Change");
			((BaseUnityPlugin)this).Logger.LogMessage((object)("ManualFill hotkey: " + ((object)ManualHotkey.Value/*cast due to .constrained prefix*/).ToString()));
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Give Correct Change Initialized successfully!");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			Harmony = new Harmony("com.acesgaminguk.givecorrectchange");
			Harmony.PatchAll();
		}

		private void Update()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled.Value && Mode.Value == ChangeMode.ManualFill && !((Object)(object)ActiveCashRegister == (Object)null))
			{
				KeyboardShortcut value = ManualHotkey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					CorrectChangeHelper.PrepareCorrectChange(ActiveCashRegister, hideManualPrompt: false);
				}
			}
		}

		private void OnGUI()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Invalid comparison between Unknown and I4
			if (Enabled.Value && Mode.Value == ChangeMode.ManualFill && !((Object)(object)ActiveCashRegister == (Object)null))
			{
				EnsureStyles();
				EnsurePanelPosition();
				_panelRect = GUI.Window(920041, _panelRect, new WindowFunction(DrawManualPanel), GUIContent.none, _windowStyle);
				if ((int)Event.current.type == 1)
				{
					SavePanelPosition();
				}
			}
		}

		private void DrawManualPanel(int windowId)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			float moneyToReturn = CorrectChangeHelper.GetMoneyToReturn(ActiveCashRegister);
			string text = (Object.op_Implicit((Object)(object)ProductListing.Instance) ? ProductListing.Instance.ConvertFloatToTextPrice(moneyToReturn) : ("$" + moneyToReturn.ToString("0.00")));
			GUI.Label(new Rect(16f, 10f, ((Rect)(ref _panelRect)).width - 32f, 24f), "Give Correct Change", _titleStyle);
			GUI.Label(new Rect(16f, 42f, ((Rect)(ref _panelRect)).width - 32f, 24f), "Change due: " + text, _smallStyle);
			string text2 = (ManualChangePrepared ? "✓ Change Prepared" : ("Press [" + ((object)ManualHotkey.Value/*cast due to .constrained prefix*/).ToString() + "] to prepare change"));
			GUI.Label(new Rect(16f, 72f, ((Rect)(ref _panelRect)).width - 32f, 30f), text2, _buttonStyle);
			GUI.Label(new Rect(16f, 113f, ((Rect)(ref _panelRect)).width - 32f, 22f), ManualChangePrepared ? "Click the cash pile on the counter" : "Cash checkout only", _smallStyle);
			GUI.Label(new Rect(16f, 140f, ((Rect)(ref _panelRect)).width - 32f, 20f), "Mode: ManualFill", _smallStyle);
			GUI.Label(new Rect(16f, 162f, ((Rect)(ref _panelRect)).width - 32f, 18f), "Hotkey active during checkout", _smallStyle);
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _panelRect)).width, 34f));
		}

		private void EnsurePanelPosition()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (!_panelPositionLoaded)
			{
				float num = 300f;
				float num2 = 186f;
				float num3 = ((float)Screen.width - num) / 2f;
				float num4 = (float)Screen.height - 245f;
				float num5 = ((PanelX.Value < 0f) ? num3 : PanelX.Value);
				float num6 = ((PanelY.Value < 0f) ? num4 : PanelY.Value);
				num5 = Mathf.Clamp(num5, 0f, Mathf.Max(0f, (float)Screen.width - num));
				num6 = Mathf.Clamp(num6, 0f, Mathf.Max(0f, (float)Screen.height - num2));
				_panelRect = new Rect(num5, num6, num, num2);
				_panelPositionLoaded = true;
			}
		}

		private void SavePanelPosition()
		{
			if (_panelPositionLoaded)
			{
				float num = Mathf.Round(((Rect)(ref _panelRect)).x);
				float num2 = Mathf.Round(((Rect)(ref _panelRect)).y);
				if (Mathf.Abs(PanelX.Value - num) > 0.5f)
				{
					PanelX.Value = num;
				}
				if (Mathf.Abs(PanelY.Value - num2) > 0.5f)
				{
					PanelY.Value = num2;
				}
			}
		}

		private void EnsureStyles()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Expected O, but got Unknown
			if (_windowStyle == null)
			{
				Texture2D background = MakeTexture(new Color(0.04f, 0.04f, 0.04f, 0.92f));
				Texture2D background2 = MakeTexture(new Color(0.13f, 0.38f, 0.2f, 0.95f));
				Texture2D background3 = MakeTexture(new Color(0.18f, 0.5f, 0.28f, 0.95f));
				Texture2D background4 = MakeTexture(new Color(0.22f, 0.16f, 0.1f, 0.95f));
				Texture2D background5 = MakeTexture(new Color(0.34f, 0.24f, 0.14f, 0.95f));
				GUIStyle val = new GUIStyle(GUI.skin.window)
				{
					padding = new RectOffset(0, 0, 0, 0),
					border = new RectOffset(8, 8, 8, 8)
				};
				val.normal.background = background;
				_windowStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 17,
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = new Color(1f, 0.72f, 0.22f, 1f);
				_titleStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 13
				};
				val3.normal.textColor = Color.white;
				_smallStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.button)
				{
					alignment = (TextAnchor)4,
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				val4.normal.background = background2;
				val4.normal.textColor = Color.white;
				val4.hover.background = background3;
				val4.hover.textColor = Color.white;
				val4.active.background = background3;
				val4.active.textColor = Color.white;
				_buttonStyle = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.button)
				{
					alignment = (TextAnchor)4,
					fontSize = 12
				};
				val5.normal.background = background4;
				val5.normal.textColor = Color.white;
				val5.hover.background = background5;
				val5.hover.textColor = Color.white;
				val5.active.background = background5;
				val5.active.textColor = Color.white;
				_dangerButtonStyle = val5;
			}
		}

		private static Texture2D MakeTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private void OnDestroy()
		{
			Harmony harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public enum ChangeMode
	{
		ManualFill,
		AutoFill,
		AutoComplete
	}
	internal static class CorrectChangeHelper
	{
		private static readonly FieldInfo MoneyToReturnField = AccessTools.Field(typeof(Data_Container), "moneyToReturn");

		private static readonly FieldInfo CurrentAmountToReturnField = AccessTools.Field(typeof(Data_Container), "currentAmountToReturn");

		private static readonly FieldInfo AllowMoneyReturnField = AccessTools.Field(typeof(Data_Container), "allowMoneyReturn");

		internal static bool FieldsReady()
		{
			if (MoneyToReturnField != null && CurrentAmountToReturnField != null && AllowMoneyReturnField != null)
			{
				return true;
			}
			Plugin.Log.LogError((object)"Could not find one or more checkout fields. Game update may have changed Data_Container.");
			return false;
		}

		internal static float GetMoneyToReturn(Data_Container container)
		{
			if (!FieldsReady())
			{
				return 0f;
			}
			return Mathf.Round((float)MoneyToReturnField.GetValue(container) * 100f) / 100f;
		}

		internal static void PrepareCorrectChange(Data_Container container, bool hideManualPrompt)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Plugin.Enabled.Value || !FieldsReady())
				{
					return;
				}
				float moneyToReturn = GetMoneyToReturn(container);
				if (moneyToReturn < 0f)
				{
					return;
				}
				CurrentAmountToReturnField.SetValue(container, moneyToReturn);
				AllowMoneyReturnField.SetValue(container, true);
				Transform val = ((Component)container).transform.Find("CashRegisterCanvas/Container/CurrentAmount");
				if (Object.op_Implicit((Object)(object)val))
				{
					TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>();
					if (Object.op_Implicit((Object)(object)component))
					{
						((TMP_Text)component).text = ProductListing.Instance.ConvertFloatToTextPrice(moneyToReturn);
						((Graphic)component).color = Color.green;
					}
				}
				Transform val2 = ((Component)container).transform.Find("CashRegister/MoneyGivenBack");
				if (Object.op_Implicit((Object)(object)val2))
				{
					((Component)val2).gameObject.SetActive(true);
				}
				if ((Object)(object)Plugin.ActiveCashRegister == (Object)(object)container)
				{
					Plugin.ManualChangePrepared = true;
					Plugin.ManualPreparedAt = Time.realtimeSinceStartup;
				}
				if (hideManualPrompt && (Object)(object)Plugin.ActiveCashRegister == (Object)(object)container)
				{
					Plugin.ActiveCashRegister = null;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to prepare correct change: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(Data_Container), "UserCode_RpcHidePaymentMethod__Int32__Int32")]
	internal static class DataContainer_RpcHidePaymentMethod_Patch
	{
		private static void Postfix(Data_Container __instance, int index, int amountGiven)
		{
			if (!Plugin.Enabled.Value || index != 0)
			{
				return;
			}
			try
			{
				if (CorrectChangeHelper.FieldsReady() && !(CorrectChangeHelper.GetMoneyToReturn(__instance) < 0f))
				{
					if (Plugin.Mode.Value == ChangeMode.AutoComplete)
					{
						Plugin.ActiveCashRegister = null;
						Plugin.ManualChangePrepared = false;
						__instance.CmdReceivePayment(0f);
					}
					else if (Plugin.Mode.Value == ChangeMode.AutoFill)
					{
						Plugin.ActiveCashRegister = null;
						Plugin.ManualChangePrepared = false;
						CorrectChangeHelper.PrepareCorrectChange(__instance, hideManualPrompt: true);
					}
					else
					{
						Plugin.ManualChangePrepared = false;
						Plugin.ManualPreparedAt = 0f;
						Plugin.ActiveCashRegister = __instance;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to set up manual correct change: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(Data_Container), "UserCode_CmdReceivePayment__Single")]
	internal static class DataContainer_CmdReceivePayment_Patch
	{
		private static void Prefix(Data_Container __instance, ref float returnDifference)
		{
			if (!Plugin.Enabled.Value)
			{
				return;
			}
			try
			{
				if (Plugin.Mode.Value == ChangeMode.AutoFill || Plugin.Mode.Value == ChangeMode.ManualFill)
				{
					float moneyToReturn = CorrectChangeHelper.GetMoneyToReturn(__instance);
					if (Mathf.Abs(__instance.currentAmountToReturn - moneyToReturn) <= 0.011f)
					{
						returnDifference = 0f;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to normalize return difference: " + ex));
			}
		}

		private static void Postfix(Data_Container __instance)
		{
			if ((Object)(object)Plugin.ActiveCashRegister == (Object)(object)__instance)
			{
				Plugin.ActiveCashRegister = null;
				Plugin.ManualChangePrepared = false;
				Plugin.ManualPreparedAt = 0f;
			}
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "com.acesgaminguk.givecorrectchange";

		public const string Name = "GiveCorrectChange";

		public const string DisplayName = "Give Correct Change";

		public const string Version = "1.0.0";

		public const string Author = "AcesGamingUK";

		public const string Website = "https://github.com/AcesGamingUK/Give-Correct-Change";
	}
}