Decompiled source of KZT Currency v1.2.1

kztCurrency.dll

Decompiled a week ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
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("kossnikita")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+f62ca6acd693a1a39864d73f984689ce94e252a9")]
[assembly: AssemblyProduct("kztCurrency")]
[assembly: AssemblyTitle("kztCurrency")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.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 kztCurrency
{
	public static class CurrencyFormatter
	{
		private static class RegexCache
		{
			public static readonly Regex GroupingChars = new Regex("[ \\u00A0\\.,]", RegexOptions.Compiled);

			public static readonly Regex GroupingCharsExtended = new Regex("[ \\u00A0\\u202F,\\u2009]", RegexOptions.Compiled);

			public static readonly Regex NonDigits = new Regex("[^0-9-]", RegexOptions.Compiled);
		}

		private const string Nbsp = "\u00a0";

		public static readonly string NBSP = "\u00a0";

		private static readonly NumberFormatInfo NbspNumberFormat = new NumberFormatInfo
		{
			NumberGroupSeparator = "\u00a0",
			NumberDecimalSeparator = ".",
			NumberGroupSizes = new int[1] { 3 }
		};

		private static readonly ConcurrentDictionary<string, string> LastLoggedOutputs = new ConcurrentDictionary<string, string>();

		private static string ApplyTemplate(string template, string formattedValue)
		{
			if (string.IsNullOrEmpty(template))
			{
				return formattedValue;
			}
			return template.Replace("{value}", formattedValue);
		}

		private static void LogFormatCall(string methodName, string input, string output)
		{
			try
			{
				string text = output ?? string.Empty;
				if (!LastLoggedOutputs.TryGetValue(methodName, out var value) || !(value == text))
				{
					LastLoggedOutputs[methodName] = text;
				}
			}
			catch (Exception ex)
			{
				try
				{
					Plugin.Logger.LogWarning((object)("[Formatting] " + methodName + " logging failed: " + ex.Message));
				}
				catch
				{
				}
			}
		}

		public static string FormatPlayerUI(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_PlayerUI ?? new Plugin.TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (RegexCache.GroupingChars.IsMatch(value ?? "") ? Math.Max(0L, value2) : (Math.Max(0L, value2) * 1000)).ToString("N0", NbspNumberFormat);
				return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_PlayerUI ?? templateInfo.Template) : templateInfo.Template, text);
			}
			string text2 = FormatNumber(value);
			return ApplyTemplate((text2 == "0") ? (Plugin.TemplateZero_PlayerUI ?? templateInfo.Template) : templateInfo.Template, text2);
		}

		public static string FormatPlayerUICurrency(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_PlayerUI ?? new Plugin.TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false);
			bool flag = !string.IsNullOrEmpty(value) && value.Contains('.');
			bool flag2 = RegexCache.GroupingCharsExtended.IsMatch(value ?? "");
			if (templateInfo.MultiplyBy1000 && (flag || flag2))
			{
				if (long.TryParse(RegexCache.NonDigits.Replace(value ?? "", ""), out var result))
				{
					string text = Math.Max(0L, result).ToString("N0", NbspNumberFormat);
					return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_PlayerUI ?? templateInfo.Template) : templateInfo.Template, text);
				}
				string text2 = (value ?? string.Empty).Replace('.', '\u00a0');
				return ApplyTemplate((text2 == "0") ? (Plugin.TemplateZero_PlayerUI ?? templateInfo.Template) : templateInfo.Template, text2);
			}
			string text3 = FormatNumber(value);
			return ApplyTemplate((text3 == "0") ? (Plugin.TemplateZero_PlayerUI ?? templateInfo.Template) : templateInfo.Template, text3);
		}

		public static string FormatShopCost(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_ItemCost ?? new Plugin.TemplateInfo("{value}K\u00a0KZT", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (RegexCache.GroupingChars.IsMatch(value ?? "") ? Math.Max(0L, value2) : (Math.Max(0L, value2) * 1000)).ToString("N0", NbspNumberFormat);
				return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_ItemCost ?? templateInfo.Template) : templateInfo.Template, text);
			}
			string text2 = FormatNumber(value);
			return ApplyTemplate((text2 == "0") ? (Plugin.TemplateZero_ItemCost ?? templateInfo.Template) : templateInfo.Template, text2);
		}

		public static string FormatItemCost(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_ItemCost ?? new Plugin.TemplateInfo("{value}K\u00a0KZT", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (RegexCache.GroupingChars.IsMatch(value ?? "") ? Math.Max(0L, value2) : (Math.Max(0L, value2) * 1000)).ToString("N0", NbspNumberFormat);
				return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_ItemCost ?? templateInfo.Template) : templateInfo.Template, text);
			}
			string text2 = FormatNumber(value);
			return ApplyTemplate((text2 == "0") ? (Plugin.TemplateZero_ItemCost ?? templateInfo.Template) : templateInfo.Template, text2);
		}

		public static string FormatItemCost(int thousands)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_ItemCost ?? new Plugin.TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000)
			{
				int num = thousands * 1000;
				return templateInfo.Template.Replace("{value}", num.ToString("N0", NbspNumberFormat));
			}
			return ((thousands == 0) ? (Plugin.TemplateZero_ItemCost ?? templateInfo.Template) : templateInfo.Template).Replace("{value}", thousands.ToString());
		}

		public static string FormatItemValue(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_ItemCost ?? new Plugin.TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (RegexCache.GroupingChars.IsMatch(value ?? "") ? Math.Max(0L, value2) : (Math.Max(0L, value2) * 1000)).ToString("N0", NbspNumberFormat);
				string text2 = ApplyTemplate((text == "0") ? (Plugin.TemplateZero_ItemPickup ?? templateInfo.Template) : templateInfo.Template, text);
				LogFormatCall("FormatItemValue(string)", value, text2);
				return text2;
			}
			string text3 = FormatNumber(value);
			string text4 = ApplyTemplate((text3 == "0") ? (Plugin.TemplateZero_ItemPickup ?? templateInfo.Template) : templateInfo.Template, text3);
			LogFormatCall("FormatItemValue(string)", value, text4);
			return text4;
		}

		public static string FormatItemValue(int units)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_ItemCost ?? new Plugin.TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false);
			if (units < 1000)
			{
				string text = units + "\u00a0₸";
				LogFormatCall("FormatItemValue(int)", units.ToString(), text);
				return text;
			}
			if (templateInfo.MultiplyBy1000)
			{
				string text2 = templateInfo.Template.Replace("{value}", units.ToString("N0", NbspNumberFormat));
				LogFormatCall("FormatItemValue(int)", units.ToString(), text2);
				return text2;
			}
			int num = units / 1000;
			string text3 = templateInfo.Template.Replace("{value}", num.ToString());
			LogFormatCall("FormatItemValue(int)", units.ToString(), text3);
			return text3;
		}

		public static string FormatBlackbox(long units)
		{
			string text = Math.Max(0L, units).ToString("N0", NbspNumberFormat) + "\u00a0₸";
			LogFormatCall("FormatBlackbox", units.ToString(), text);
			return text;
		}

		public static string FormatBlackboxDigits(long units)
		{
			return Math.Max(0L, units).ToString("N0", NbspNumberFormat);
		}

		public static string FormatShoppingListDigits(long units)
		{
			string text = Math.Max(0L, units).ToString("N0", NbspNumberFormat);
			LogFormatCall("FormatShoppingListDigits", units.ToString(), text);
			return text;
		}

		public static string FormatShoppingListUI(long units)
		{
			string text = Math.Max(0L, units).ToString("N0", NbspNumberFormat) + "\u00a0₸";
			LogFormatCall("FormatShoppingListUI", units.ToString(), text);
			return text;
		}

		public static string FormatHaulUI(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_HaulUI ?? new Plugin.TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (Math.Max(0L, value2) * 1000).ToString("N0", NbspNumberFormat);
				return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_HaulUI ?? templateInfo.Template) : templateInfo.Template, text);
			}
			string text2 = FormatNumber(value);
			return ApplyTemplate((text2 == "0") ? (Plugin.TemplateZero_HaulUI ?? templateInfo.Template) : templateInfo.Template, text2);
		}

		public static string FormatHaulUI(int units)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_HaulUI ?? new Plugin.TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false);
			string text = Math.Max(0, units).ToString("N0", NbspNumberFormat);
			return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_HaulUI ?? templateInfo.Template) : templateInfo.Template, text);
		}

		public static string FormatHaul(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_Haul ?? new Plugin.TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (Math.Max(0L, value2) * 1000).ToString("N0", NbspNumberFormat);
				string text2 = ApplyTemplate((text == "0") ? (Plugin.TemplateZero_Haul ?? templateInfo.Template) : templateInfo.Template, text);
				LogFormatCall("FormatHaul(string)", value, text2);
				return text2;
			}
			string text3 = FormatNumber(value);
			string text4 = ApplyTemplate((text3 == "0") ? (Plugin.TemplateZero_Haul ?? templateInfo.Template) : templateInfo.Template, text3);
			LogFormatCall("FormatHaul(string)", value, text4);
			return text4;
		}

		public static string FormatHaul(int units)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_Haul ?? new Plugin.TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false);
			int num = Math.Max(0, units);
			string text2;
			if (templateInfo.MultiplyBy1000)
			{
				string text = num.ToString("N0", NbspNumberFormat);
				text2 = ApplyTemplate((text == "0") ? (Plugin.TemplateZero_Haul ?? templateInfo.Template) : templateInfo.Template, text);
			}
			else if (num < 1000)
			{
				string text3 = num.ToString();
				text2 = ApplyTemplate((text3 == "0") ? (Plugin.TemplateZero_Haul ?? templateInfo.Template) : templateInfo.Template, text3);
			}
			else
			{
				double num2 = (double)num / 1000.0;
				string text4 = ((Math.Abs(num2 - Math.Truncate(num2)) < 0.001) ? ((int)Math.Truncate(num2)).ToString() : num2.ToString("0.#", CultureInfo.InvariantCulture));
				text2 = ApplyTemplate((text4 == "0") ? (Plugin.TemplateZero_Haul ?? templateInfo.Template) : templateInfo.Template, text4);
			}
			LogFormatCall("FormatHaul(int)", units.ToString(), text2);
			return text2;
		}

		public static string FormatCart(string value)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_Cart ?? new Plugin.TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false);
			if (templateInfo.MultiplyBy1000 && TryParseDigitsToLong(value, out var value2))
			{
				string text = (RegexCache.GroupingChars.IsMatch(value ?? "") ? Math.Max(0L, value2) : (Math.Max(0L, value2) * 1000)).ToString("N0", NbspNumberFormat);
				return ApplyTemplate((text == "0") ? (Plugin.TemplateZero_Cart ?? templateInfo.Template) : templateInfo.Template, text);
			}
			string text2 = FormatNumber(value);
			return ApplyTemplate((text2 == "0") ? (Plugin.TemplateZero_Cart ?? templateInfo.Template) : templateInfo.Template, text2);
		}

		public static string FormatCart(int units)
		{
			Plugin.TemplateInfo templateInfo = Plugin.Template_Cart ?? new Plugin.TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false);
			int num = Math.Max(0, units);
			string text2;
			if (templateInfo.MultiplyBy1000)
			{
				string text = num.ToString("N0", NbspNumberFormat);
				text2 = ApplyTemplate((text == "0") ? (Plugin.TemplateZero_Cart ?? templateInfo.Template) : templateInfo.Template, text);
			}
			else if (num < 1000)
			{
				string formattedValue = num.ToString();
				text2 = ApplyTemplate(Plugin.TemplateZero_Cart ?? "{value}\u00a0тг", formattedValue);
			}
			else
			{
				double num2 = (double)num / 1000.0;
				string text3 = ((Math.Abs(num2 - Math.Truncate(num2)) < 0.001) ? ((int)Math.Truncate(num2)).ToString() : num2.ToString("0.#", CultureInfo.InvariantCulture));
				text2 = ApplyTemplate((text3 == "0") ? (Plugin.TemplateZero_Cart ?? templateInfo.Template) : templateInfo.Template, text3);
			}
			LogFormatCall("FormatCart(int)", units.ToString(), text2);
			return text2;
		}

		private static bool TryParseDigitsToLong(string raw, out long value)
		{
			value = 0L;
			if (string.IsNullOrWhiteSpace(raw))
			{
				return false;
			}
			string text = RegexCache.NonDigits.Replace(raw, "");
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			return long.TryParse(text, out value);
		}

		private static string FormatNumber(string raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return raw ?? string.Empty;
			}
			string text = raw.Trim();
			text = text.Replace("\u00a0", "");
			text = text.Replace(" ", "");
			if (long.TryParse(text, NumberStyles.Integer, NbspNumberFormat, out var result))
			{
				return result.ToString("N0", NbspNumberFormat);
			}
			if (decimal.TryParse(text, NumberStyles.Number, NbspNumberFormat, out var result2))
			{
				return result2.ToString("N2", NbspNumberFormat).TrimEnd('0').TrimEnd('.');
			}
			return raw;
		}
	}
	[HarmonyPatch(typeof(HaulUI), "Update")]
	public class HaulUIPatch
	{
		private static string _lastOriginalText;

		private static string _lastProcessedText;

		[HarmonyPostfix]
		public static void UpdatePostfix(HaulUI __instance, TextMeshProUGUI ___Text)
		{
			if ((Object)(object)___Text == (Object)null)
			{
				return;
			}
			string text = ((TMP_Text)___Text).text;
			if (string.IsNullOrEmpty(text) || text == _lastProcessedText)
			{
				return;
			}
			try
			{
				int units = (((Object)(object)RoundDirector.instance != (Object)null) ? RoundDirector.instance.currentHaul : 0);
				int units2 = (((Object)(object)RoundDirector.instance != (Object)null) ? RoundDirector.instance.extractionHaulGoal : 0);
				string text2 = CurrencyFormatter.FormatHaulUI(units);
				string text3 = CurrencyFormatter.FormatHaulUI(units2);
				string text4 = "<size=30>" + text2 + "<color=#616161> <size=45>/</size> </color><u>" + text3 + "</u>";
				_lastOriginalText = text;
				_lastProcessedText = text4;
				((TMP_Text)___Text).text = text4;
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch]
	public static class BlackboxInitWatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameObject), "AddComponent", new Type[] { typeof(Type) })]
		private static void AddComponent_Postfix(GameObject __instance, Type componentType, Component __result)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			try
			{
				if (componentType == null)
				{
					return;
				}
				string text = componentType.FullName ?? string.Empty;
				if (!((componentType.Name ?? string.Empty) == "Blackbox") && !text.EndsWith(".Blackbox") && !(text == "Blackbox"))
				{
					return;
				}
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"[BlackboxInitWatcher] Detected Blackbox component added — applying runtime patches.");
				}
				try
				{
					if (BlackboxPatches.TryPatchNow(new Harmony("kztCurrency.blackbox")))
					{
						ManualLogSource logger2 = Plugin.Logger;
						if (logger2 != null)
						{
							logger2.LogInfo((object)"[BlackboxInitWatcher] Blackbox patches applied successfully on AddComponent");
						}
					}
					else
					{
						ManualLogSource logger3 = Plugin.Logger;
						if (logger3 != null)
						{
							logger3.LogDebug((object)"[BlackboxInitWatcher] Blackbox patches not applied (may already be patched or types not found)");
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource logger4 = Plugin.Logger;
					if (logger4 != null)
					{
						logger4.LogWarning((object)$"[BlackboxInitWatcher] Failed to apply Blackbox patches: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				ManualLogSource logger5 = Plugin.Logger;
				if (logger5 != null)
				{
					logger5.LogWarning((object)$"[BlackboxInitWatcher] unexpected error: {arg2}");
				}
			}
		}
	}
	public static class BlackboxPatches
	{
		private static readonly Regex DollarNumberRegex = new Regex("\\$(?:<[^>]+>)*\\s*([0-9][0-9\\.,\\u00A0\\s]*)", RegexOptions.Compiled);

		internal static string Preview(string s, int max = 120)
		{
			if (s == null)
			{
				return "<null>";
			}
			if (s.Length > max)
			{
				return s.Substring(0, max) + "...";
			}
			return s;
		}

		internal static string ReplaceDollarNumbers(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return input;
			}
			int replaced = 0;
			return DollarNumberRegex.Replace(input, delegate(Match m)
			{
				string value = m.Groups[1].Value;
				string text = Regex.Replace(value, "[^0-9]", "");
				if (string.IsNullOrEmpty(text))
				{
					return m.Value;
				}
				if (!long.TryParse(text, out var result))
				{
					return m.Value;
				}
				string text2 = CurrencyFormatter.FormatBlackbox((int)Math.Min(result, 2147483647L));
				string value2 = m.Groups[0].Value;
				int num = value2.IndexOf(value, StringComparison.Ordinal);
				if (num < 0)
				{
					replaced++;
					ManualLogSource logger = Plugin.Logger;
					if (logger != null)
					{
						logger.LogDebug((object)("[BlackboxPatches] Unexpected match structure, replacing whole '" + value2 + "' with '" + text2 + "'"));
					}
					return text2;
				}
				string text3 = value2.Substring(0, num);
				string text4 = string.Concat(str2: value2.Substring(num + value.Length), str0: text3.Replace("$", ""), str1: text2);
				replaced++;
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("[BlackboxPatches] Replaced '" + value2 + "' -> '" + text4 + "' in preview: '" + Preview(input) + "'"));
				}
				return text4;
			});
		}

		public static bool TryPatchNow(Harmony harmony)
		{
			int num = 0;
			try
			{
				Type[] array = new Type[3]
				{
					typeof(Blackbox_getPostRunStatString_Patch),
					typeof(ValuableEventTracker_getStatsByPlayerValueLost_Patch),
					typeof(ValuableEventTracker_getDetailedStatsByValueLost_Patch)
				};
				foreach (Type type in array)
				{
					try
					{
						List<MethodInfo> list = harmony.CreateClassProcessor(type).Patch();
						if (list != null && list.Count > 0)
						{
							num++;
							ManualLogSource logger = Plugin.Logger;
							if (logger != null)
							{
								logger.LogDebug((object)("[BlackboxPatches] Applied patch: " + type.Name));
							}
						}
					}
					catch (Exception ex)
					{
						ManualLogSource logger2 = Plugin.Logger;
						if (logger2 != null)
						{
							logger2.LogDebug((object)("[BlackboxPatches] Could not apply " + type.Name + ": " + ex.Message));
						}
					}
				}
				if (num > 0)
				{
					ManualLogSource logger3 = Plugin.Logger;
					if (logger3 != null)
					{
						logger3.LogInfo((object)$"[BlackboxPatches] Successfully applied {num} patch(es)");
					}
					return true;
				}
			}
			catch (Exception arg)
			{
				ManualLogSource logger4 = Plugin.Logger;
				if (logger4 != null)
				{
					logger4.LogWarning((object)$"[BlackboxPatches] TryPatchNow failed: {arg}");
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal class Blackbox_getPostRunStatString_Patch
	{
		private static bool Prepare()
		{
			bool flag = AccessTools.TypeByName("Blackbox") != null;
			ManualLogSource logger = Plugin.Logger;
			if (logger != null)
			{
				logger.LogDebug((object)$"[BlackboxPatches] Prepare Blackbox.getPostRunStatString: {flag}");
			}
			return flag;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method("Blackbox:getPostRunStatString", (Type[])null, (Type[])null);
		}

		private static void Postfix(ref string __result)
		{
			__result = BlackboxPatches.ReplaceDollarNumbers(__result);
		}
	}
	[HarmonyPatch]
	internal class ValuableEventTracker_getStatsByPlayerValueLost_Patch
	{
		private static bool Prepare()
		{
			bool flag = AccessTools.TypeByName("ValuableEventTracker") != null;
			ManualLogSource logger = Plugin.Logger;
			if (logger != null)
			{
				logger.LogDebug((object)$"[BlackboxPatches] Prepare ValuableEventTracker.getStatsByPlayerValueLost: {flag}");
			}
			return flag;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method("ValuableEventTracker:getStatsByPlayerValueLost", (Type[])null, (Type[])null);
		}

		private static void Postfix(ref string __result)
		{
			__result = BlackboxPatches.ReplaceDollarNumbers(__result);
		}
	}
	[HarmonyPatch]
	internal class ValuableEventTracker_getDetailedStatsByValueLost_Patch
	{
		private static bool Prepare()
		{
			bool flag = AccessTools.TypeByName("ValuableEventTracker") != null;
			ManualLogSource logger = Plugin.Logger;
			if (logger != null)
			{
				logger.LogDebug((object)$"[BlackboxPatches] Prepare ValuableEventTracker.getDetailedStatsByValueLost: {flag}");
			}
			return flag;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method("ValuableEventTracker:getDetailedStatsByValueLost", (Type[])null, (Type[])null);
		}

		private static void Postfix(ref Dictionary<string, string> __result)
		{
			if (__result == null)
			{
				return;
			}
			foreach (string item in new List<string>(__result.Keys))
			{
				string text = BlackboxPatches.Preview(__result[item]);
				__result[item] = BlackboxPatches.ReplaceDollarNumbers(__result[item]);
				string text2 = BlackboxPatches.Preview(__result[item]);
				if (text != text2)
				{
					ManualLogSource logger = Plugin.Logger;
					if (logger != null)
					{
						logger.LogDebug((object)("[BlackboxPatches] Replaced in key '" + item + "': '" + text + "' -> '" + text2 + "'"));
					}
				}
			}
		}
	}
	internal static class CurrencyUIHelper
	{
		public static int ParseThousandsToBase(string valueInThousands)
		{
			if (int.TryParse(Regex.Replace(valueInThousands ?? "", "[^0-9]", ""), out var result))
			{
				return result * 1000;
			}
			return 0;
		}
	}
	[HarmonyPatch(typeof(CurrencyUI), "Update")]
	public class CurrencyUIPatch
	{
		private static TMP_FontAsset _cachedTengeFont;

		[HarmonyPostfix]
		public static void UpdatePostfix(CurrencyUI __instance, TextMeshProUGUI ___Text, ref float ___showTimer, ref int ___currentHaulValue)
		{
			if (!(___showTimer > 0f) || !((Object)(object)___Text != (Object)null))
			{
				return;
			}
			string text = ((TMP_Text)___Text).text;
			if (text.StartsWith("$") && text.EndsWith("K"))
			{
				int units = CurrencyUIHelper.ParseThousandsToBase(text.Substring(1, text.Length - 2));
				if (_cachedTengeFont == null)
				{
					_cachedTengeFont = TengeSymbolSupport.GetTengeFallbackFont();
				}
				if ((Object)(object)_cachedTengeFont != (Object)null && (Object)(object)((TMP_Text)___Text).font != (Object)(object)_cachedTengeFont)
				{
					TengeSymbolSupport.SetPrimaryFont((TMP_Text)(object)___Text);
				}
				string text2 = CurrencyFormatter.FormatHaul(units);
				((TMP_Text)___Text).text = text2;
			}
		}
	}
	[HarmonyPatch(typeof(CurrencyUI), "FetchCurrency")]
	public class CurrencyUIFetchCurrencyPatch
	{
		[HarmonyPostfix]
		public static void FetchCurrencyPostfix(CurrencyUI __instance, TextMeshProUGUI ___Text)
		{
			if ((Object)(object)___Text != (Object)null)
			{
				string text = ((TMP_Text)___Text).text;
				if (text.StartsWith("$") && text.EndsWith("K"))
				{
					int units = CurrencyUIHelper.ParseThousandsToBase(text.Substring(1, text.Length - 2));
					TengeSymbolSupport.EnsureFallbackFont((TMP_Text)(object)___Text);
					((TMP_Text)___Text).text = CurrencyFormatter.FormatHaul(units);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint))]
	internal class ExtractionPointPatch
	{
		private static readonly Regex TagRemoval = new Regex("<.*?>", RegexOptions.Compiled);

		[HarmonyPatch("SetHaulText")]
		[HarmonyPostfix]
		private static void SetHaulTextPostfix(ExtractionPoint __instance, int ___haulCurrent, bool ___isShop)
		{
			if ((Object)(object)__instance.haulGoalScreen == (Object)null)
			{
				return;
			}
			string text = ((TMP_Text)__instance.haulGoalScreen).text;
			if (string.IsNullOrEmpty(text) || text.Contains("₸") || text.Contains("тг") || text.Contains("KZT"))
			{
				return;
			}
			string text2 = TagRemoval.Replace(text, "");
			if (text2.Contains("$"))
			{
				if (text.Contains("TAX"))
				{
					string text3 = text.Replace("$", "₸");
					((TMP_Text)__instance.haulGoalScreen).text = text3;
					return;
				}
				int num = ((!___isShop) ? ___haulCurrent : (__instance.haulGoal - ___haulCurrent));
				bool flag = text2.TrimStart().StartsWith("-");
				string text4 = CurrencyFormatter.FormatHaul(Math.Abs(num));
				string text5 = ((!(num < 0 || flag)) ? text4 : ("<color=#bd4300>-" + text4 + "</color>"));
				((TMP_Text)__instance.haulGoalScreen).text = text5;
			}
		}

		[HarmonyPatch("StateSuccess")]
		[HarmonyPostfix]
		private static void StateSuccessPostfix(ExtractionPoint __instance, int ___haulCurrent, bool ___isShop)
		{
			if ((Object)(object)__instance.haulGoalScreen == (Object)null)
			{
				return;
			}
			string text = ((TMP_Text)__instance.haulGoalScreen).text;
			if (!string.IsNullOrEmpty(text) && text.Contains("$") && !text.Contains("₸") && !text.Contains("тг") && !text.Contains("KZT"))
			{
				if (text.Contains("TAX"))
				{
					string text2 = text.Replace("$", "₸");
					((TMP_Text)__instance.haulGoalScreen).text = text2;
					return;
				}
				int units = Math.Max(0, __instance.haulGoal - ___haulCurrent);
				TagRemoval.Replace(text, "").TrimStart().StartsWith("-");
				string text3 = CurrencyFormatter.FormatHaul(units);
				((TMP_Text)__instance.haulGoalScreen).text = text3;
			}
		}

		[HarmonyPatch("StateSurplus")]
		[HarmonyPostfix]
		private static void StateSurplusPostfix(ExtractionPoint __instance)
		{
			if ((Object)(object)__instance.haulGoalScreen == (Object)null)
			{
				return;
			}
			string text = ((TMP_Text)__instance.haulGoalScreen).text;
			if (string.IsNullOrEmpty(text) || !text.Contains("$") || text.Contains("₸") || text.Contains("тг") || text.Contains("KZT"))
			{
				return;
			}
			string text2 = TagRemoval.Replace(text, "");
			if (text.Contains("TAX"))
			{
				string text3 = text.Replace("$", "₸");
				((TMP_Text)__instance.haulGoalScreen).text = text3;
				return;
			}
			bool flag = text2.TrimStart().StartsWith("+");
			bool flag2 = text2.TrimStart().StartsWith("-");
			if (!int.TryParse(text2.Replace("+", "").Replace("-", "").Replace("$", "")
				.Replace(".", "")
				.Replace(" ", "")
				.Replace(",", ""), out var result))
			{
				string text4 = text.Replace("$", "₸");
				((TMP_Text)__instance.haulGoalScreen).text = text4;
				return;
			}
			if (flag2 && result > 0)
			{
				result = -result;
			}
			string text5 = CurrencyFormatter.FormatHaul(Math.Abs(result));
			string text6 = ((result < 0 || flag2) ? ("<color=#bd4300>-" + text5 + "</color>") : ((!flag) ? text5 : ("+" + text5)));
			((TMP_Text)__instance.haulGoalScreen).text = text6;
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "SetHaulText")]
	internal class PhysGrabCartHaulTextPatch
	{
		[HarmonyPostfix]
		private static void SetHaulTextPostfix(PhysGrabCart __instance, int ___haulCurrent)
		{
			try
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.displayText == (Object)null))
				{
					TengeSymbolSupport.EnsureFallbackFont((TMP_Text)(object)__instance.displayText);
					string text = CurrencyFormatter.FormatCart(___haulCurrent);
					((TMP_Text)__instance.displayText).text = text;
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[PhysGrabCart] Exception in SetHaulTextPostfix: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ShopCostUI), "Update")]
	public class ShopCostUIPatch
	{
		private static TMP_FontAsset _cachedTengeFont;

		[HarmonyPostfix]
		public static void UpdatePostfix(ShopCostUI __instance, TextMeshProUGUI ___Text)
		{
			if ((Object)(object)___Text != (Object)null && !string.IsNullOrEmpty(((TMP_Text)___Text).text))
			{
				string text = ((TMP_Text)___Text).text;
				if (text.StartsWith("-$") && text.EndsWith("K"))
				{
					string value = text.Substring(2, text.Length - 3);
					((TMP_Text)___Text).text = "-" + CurrencyFormatter.FormatShopCost(value);
				}
				else if (text.StartsWith("+$") && text.EndsWith("K"))
				{
					string value2 = text.Substring(2, text.Length - 3);
					((TMP_Text)___Text).text = "+" + CurrencyFormatter.FormatShopCost(value2);
				}
				if (_cachedTengeFont == null)
				{
					_cachedTengeFont = TengeSymbolSupport.GetTengeFallbackFont();
				}
				if ((Object)(object)_cachedTengeFont != (Object)null && (Object)(object)((TMP_Text)___Text).font != (Object)(object)_cachedTengeFont)
				{
					TengeSymbolSupport.SetPrimaryFont((TMP_Text)(object)___Text);
				}
			}
		}
	}
	[HarmonyPatch]
	public static class ShoppingListInitWatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameObject), "AddComponent", new Type[] { typeof(Type) })]
		private static void AddComponent_Postfix(GameObject __instance, Type componentType, Component __result)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			try
			{
				if (componentType == null)
				{
					return;
				}
				string text = componentType.FullName ?? string.Empty;
				if (!((componentType.Name ?? string.Empty) == "ShoppingListHUD") && !text.EndsWith(".ShoppingListHUD") && !(text == "ShoppingListHUD"))
				{
					return;
				}
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"[ShoppingListInitWatcher] Detected ShoppingListHUD component added — applying runtime patches.");
				}
				try
				{
					if (ShoppingListPatches.TryPatchNow(new Harmony("kztCurrency.shoppinglist")))
					{
						ManualLogSource logger2 = Plugin.Logger;
						if (logger2 != null)
						{
							logger2.LogInfo((object)"[ShoppingListInitWatcher] ShoppingList patches applied successfully on AddComponent");
						}
					}
					else
					{
						ManualLogSource logger3 = Plugin.Logger;
						if (logger3 != null)
						{
							logger3.LogDebug((object)"[ShoppingListInitWatcher] ShoppingList patches not applied (may already be patched or types not found)");
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource logger4 = Plugin.Logger;
					if (logger4 != null)
					{
						logger4.LogWarning((object)$"[ShoppingListInitWatcher] Failed to apply ShoppingList patches: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				ManualLogSource logger5 = Plugin.Logger;
				if (logger5 != null)
				{
					logger5.LogWarning((object)$"[ShoppingListInitWatcher] unexpected error: {arg2}");
				}
			}
		}
	}
	public static class ShoppingListPatches
	{
		private static readonly Regex s_colorWrapped = new Regex("\\$<(?<tag>color=[^>]+)>(?<num>[0-9\\u00A0\\s\\.,]+)</color>", RegexOptions.Compiled);

		private static readonly Regex s_simpleDollar = new Regex("\\$([0-9\\u00A0\\s\\.,]+)", RegexOptions.Compiled);

		internal static FieldInfo s_statsInstanceField;

		internal static FieldInfo s_textField;

		internal static FieldInfo s_textNumbersField;

		internal static FieldInfo s_upgradesHeaderField;

		internal static readonly ConcurrentDictionary<Type, PropertyInfo> s_textPropCache = new ConcurrentDictionary<Type, PropertyInfo>();

		internal static string Preview(string s, int max = 120)
		{
			if (s == null)
			{
				return "<null>";
			}
			if (s.Length > max)
			{
				return s.Substring(0, max) + "...";
			}
			return s;
		}

		internal static string ReplaceDollarNumbers(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return input;
			}
			int replaced = 0;
			if (!input.Contains("$"))
			{
				return input;
			}
			string text = s_colorWrapped.Replace(input, delegate(Match m)
			{
				string value = m.Groups["tag"].Value;
				if (!long.TryParse(Regex.Replace(m.Groups["num"].Value, "[^0-9]", ""), out var result2))
				{
					return m.Value;
				}
				string text2 = CurrencyFormatter.FormatShoppingListDigits(result2);
				replaced++;
				return "<" + value + ">" + text2 + "</color>" + CurrencyFormatter.NBSP + "₸";
			});
			if (replaced == 0)
			{
				text = s_simpleDollar.Replace(text, delegate(Match m)
				{
					if (!long.TryParse(Regex.Replace(m.Groups[1].Value, "[^0-9]", ""), out var result))
					{
						return m.Value;
					}
					replaced++;
					return CurrencyFormatter.FormatShoppingListUI(result);
				});
			}
			if (replaced > 0)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)$"[ShoppingListPatches] Replaced {replaced} dollar-formatted value(s)");
				}
			}
			return text;
		}

		public static bool TryPatchNow(Harmony harmony)
		{
			try
			{
				List<MethodInfo> list = harmony.CreateClassProcessor(typeof(ShoppingListHUDPatches_SetUITexts_Patch)).Patch();
				if (list != null && list.Count > 0)
				{
					ManualLogSource logger = Plugin.Logger;
					if (logger != null)
					{
						logger.LogInfo((object)"[ShoppingListPatches] Successfully applied patch");
					}
					return true;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("[ShoppingListPatches] TryPatchNow failed: " + ex.Message));
				}
			}
			return false;
		}

		internal static void UpdateUITexts()
		{
			try
			{
				try
				{
					if (s_statsInstanceField == null)
					{
						Type type = AccessTools.TypeByName("StatsUI");
						if (type != null)
						{
							s_statsInstanceField = AccessTools.Field(type, "instance");
							s_textField = AccessTools.Field(type, "Text");
							s_textNumbersField = AccessTools.Field(type, "textNumbers");
							s_upgradesHeaderField = AccessTools.Field(type, "upgradesHeader");
						}
					}
					object obj = s_statsInstanceField?.GetValue(null);
					if (obj == null)
					{
						return;
					}
					object obj2 = s_textField?.GetValue(obj);
					object obj3 = s_textNumbersField?.GetValue(obj);
					object obj4 = s_upgradesHeaderField?.GetValue(obj);
					if (obj2 != null)
					{
						Type type2 = obj2.GetType();
						PropertyInfo orAdd = s_textPropCache.GetOrAdd(type2, (Type tt) => tt.GetProperty("text"));
						if (orAdd != null)
						{
							string text = orAdd.GetValue(obj2) as string;
							if (!string.IsNullOrEmpty(text) && text.Contains("$"))
							{
								string text2 = ReplaceDollarNumbers(text);
								if (text2 != text)
								{
									orAdd.SetValue(obj2, text2);
									ManualLogSource logger = Plugin.Logger;
									if (logger != null)
									{
										logger.LogDebug((object)"[ShoppingListPatches] Updated TMP_Text.Text");
									}
								}
							}
						}
					}
					if (obj3 != null)
					{
						Type type3 = obj3.GetType();
						PropertyInfo orAdd2 = s_textPropCache.GetOrAdd(type3, (Type tt) => tt.GetProperty("text"));
						if (orAdd2 != null)
						{
							string text3 = orAdd2.GetValue(obj3) as string;
							if (!string.IsNullOrEmpty(text3) && text3.Contains("$"))
							{
								string text4 = ReplaceDollarNumbers(text3);
								if (text4 != text3)
								{
									orAdd2.SetValue(obj3, text4);
									ManualLogSource logger2 = Plugin.Logger;
									if (logger2 != null)
									{
										logger2.LogDebug((object)"[ShoppingListPatches] Updated TMP_Text.textNumbers");
									}
								}
							}
						}
					}
					if (obj4 == null)
					{
						return;
					}
					Type type4 = obj4.GetType();
					PropertyInfo orAdd3 = s_textPropCache.GetOrAdd(type4, (Type tt) => tt.GetProperty("text"));
					if (!(orAdd3 != null))
					{
						return;
					}
					string text5 = orAdd3.GetValue(obj4) as string;
					if (string.IsNullOrEmpty(text5) || !text5.Contains("$"))
					{
						return;
					}
					string text6 = ReplaceDollarNumbers(text5);
					if (text6 != text5)
					{
						orAdd3.SetValue(obj4, text6);
						ManualLogSource logger3 = Plugin.Logger;
						if (logger3 != null)
						{
							logger3.LogDebug((object)"[ShoppingListPatches] Updated TMP_Text.upgradesHeader");
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource logger4 = Plugin.Logger;
					if (logger4 != null)
					{
						logger4.LogWarning((object)$"[ShoppingListPatches] Postfix_SetUITexts inner error: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				ManualLogSource logger5 = Plugin.Logger;
				if (logger5 != null)
				{
					logger5.LogWarning((object)$"[ShoppingListPatches] Postfix_SetUITexts error: {arg2}");
				}
			}
		}
	}
	[HarmonyPatch]
	internal class ShoppingListHUDPatches_SetUITexts_Patch
	{
		private static bool Prepare()
		{
			bool flag = AccessTools.TypeByName("ShoppingListHUDPatches") != null;
			ManualLogSource logger = Plugin.Logger;
			if (logger != null)
			{
				logger.LogDebug((object)$"[ShoppingListPatches] Prepare ShoppingListHUDPatches.SetUITexts: {flag}");
			}
			return flag;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method("ShoppingListHUDPatches:SetUITexts", (Type[])null, (Type[])null);
		}

		private static void Postfix()
		{
			ShoppingListPatches.UpdateUITexts();
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class TMPTextAutoFontPatch
	{
		[HarmonyPrefix]
		private static void Prefix(TMP_Text __instance, ref string value)
		{
			if (!((Object)(object)__instance == (Object)null) && !string.IsNullOrEmpty(value) && ContainsCyrillicOrTenge(value))
			{
				TMP_FontAsset tengeFallbackFont = TengeSymbolSupport.GetTengeFallbackFont();
				if (!((Object)(object)tengeFallbackFont == (Object)null) && !((Object)(object)__instance.font == (Object)(object)tengeFallbackFont))
				{
					TengeSymbolSupport.SetPrimaryFont(__instance);
				}
			}
		}

		private static bool ContainsCyrillicOrTenge(string s)
		{
			foreach (char c in s)
			{
				if ((c >= 'Ѐ' && c <= 'ӿ') || c == '₸')
				{
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(WorldSpaceUIValueLost), "Start")]
	public static class WorldSpaceUIValueLostPatch
	{
		[HarmonyPostfix]
		public static void StartPostfix(WorldSpaceUIValueLost __instance, TextMeshProUGUI ___text, int ___value)
		{
			if ((Object)(object)___text == (Object)null)
			{
				return;
			}
			TengeSymbolSupport.SetPrimaryFont((TMP_Text)(object)___text);
			try
			{
				((TMP_Text)___text).text = "-" + CurrencyFormatter.FormatItemValue(___value);
			}
			catch
			{
				((TMP_Text)___text).text = "-$" + SemiFunc.DollarGetString(___value);
			}
		}
	}
	[HarmonyPatch(typeof(WorldSpaceUIValue), "Show")]
	public class WorldSpaceUIValuePatch
	{
		[HarmonyPostfix]
		public static void ShowPostfix(WorldSpaceUIValue __instance, PhysGrabObject _grabObject, int _value, bool _cost, TextMeshProUGUI ___text, PhysGrabObject ___currentPhysGrabObject)
		{
			if ((!((Object)(object)___currentPhysGrabObject != (Object)null) || !((Object)(object)___currentPhysGrabObject != (Object)(object)_grabObject)) && !((Object)(object)___text == (Object)null) && !string.IsNullOrEmpty(((TMP_Text)___text).text))
			{
				_ = ((TMP_Text)___text).text;
				TengeSymbolSupport.SetPrimaryFont((TMP_Text)(object)___text);
				if (_cost)
				{
					((TMP_Text)___text).text = "-" + CurrencyFormatter.FormatItemCost(_value);
				}
				else
				{
					((TMP_Text)___text).text = CurrencyFormatter.FormatItemValue(_value);
				}
			}
		}
	}
	[BepInPlugin("kztCurrency", "kztCurrency", "1.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal class TemplateInfo
		{
			public string Template { get; set; }

			public bool MultiplyBy1000 { get; set; }

			public TemplateInfo(string template, bool multiplyBy1000)
			{
				Template = template;
				MultiplyBy1000 = multiplyBy1000;
			}
		}

		internal static ManualLogSource Logger;

		private static readonly Regex ZeroSuffixPattern = new Regex("\\{value\\}(?:[Kkк]|[\\u00A0 ]?тыс\\.?)", RegexOptions.Compiled);

		private static readonly Dictionary<string, TemplateInfo> ExampleToTemplate_PlayerUI = new Dictionary<string, TemplateInfo>
		{
			{
				"100K тг",
				new TemplateInfo("{value}K\u00a0тг", multiplyBy1000: false)
			},
			{
				"100K ₸",
				new TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false)
			},
			{
				"100K KZT",
				new TemplateInfo("{value}K\u00a0KZT", multiplyBy1000: false)
			},
			{
				"100к тг",
				new TemplateInfo("{value}к\u00a0тг", multiplyBy1000: false)
			},
			{
				"100к ₸",
				new TemplateInfo("{value}к\u00a0₸", multiplyBy1000: false)
			},
			{
				"100к KZT",
				new TemplateInfo("{value}к\u00a0KZT", multiplyBy1000: false)
			},
			{
				"100 тыс. тг",
				new TemplateInfo("{value}\u00a0тыс.\u00a0тг", multiplyBy1000: false)
			},
			{
				"100 000 тг",
				new TemplateInfo("{value}\u00a0тг", multiplyBy1000: true)
			},
			{
				"100 000 ₸",
				new TemplateInfo("{value}\u00a0₸", multiplyBy1000: true)
			},
			{
				"100 000 KZT",
				new TemplateInfo("{value}\u00a0KZT", multiplyBy1000: true)
			}
		};

		private static readonly Dictionary<string, TemplateInfo> ExampleToTemplate_ItemCost = new Dictionary<string, TemplateInfo>
		{
			{
				"100K тг",
				new TemplateInfo("{value}K\u00a0тг", multiplyBy1000: false)
			},
			{
				"100K ₸",
				new TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false)
			},
			{
				"100K KZT",
				new TemplateInfo("{value}K\u00a0KZT", multiplyBy1000: false)
			},
			{
				"100 тыс. тг",
				new TemplateInfo("{value}\u00a0тыс.\u00a0тг", multiplyBy1000: false)
			},
			{
				"100 тыс. ₸",
				new TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false)
			},
			{
				"100 тыс. KZT",
				new TemplateInfo("{value}\u00a0тыс.\u00a0KZT", multiplyBy1000: false)
			},
			{
				"100 000 тг",
				new TemplateInfo("{value}\u00a0тг", multiplyBy1000: true)
			},
			{
				"100 000 ₸",
				new TemplateInfo("{value}\u00a0₸", multiplyBy1000: true)
			},
			{
				"100 000 KZT",
				new TemplateInfo("{value}\u00a0KZT", multiplyBy1000: true)
			}
		};

		private static readonly Dictionary<string, TemplateInfo> ExampleToTemplate_HaulUI = new Dictionary<string, TemplateInfo>
		{
			{
				"100K тг",
				new TemplateInfo("{value}K\u00a0<color=#558B2F>тг</color>", multiplyBy1000: false)
			},
			{
				"100K ₸",
				new TemplateInfo("{value}K\u00a0<color=#558B2F>₸</color>", multiplyBy1000: false)
			},
			{
				"100K KZT",
				new TemplateInfo("{value}K\u00a0<color=#558B2F>KZT</color>", multiplyBy1000: false)
			},
			{
				"100к тг",
				new TemplateInfo("{value}к\u00a0<color=#558B2F>тг</color>", multiplyBy1000: false)
			},
			{
				"100к ₸",
				new TemplateInfo("{value}к\u00a0<color=#558B2F>₸</color>", multiplyBy1000: false)
			},
			{
				"100к KZT",
				new TemplateInfo("{value}к\u00a0<color=#558B2F>KZT</color>", multiplyBy1000: false)
			},
			{
				"100 000 тг",
				new TemplateInfo("{value}\u00a0<color=#558B2F>тг</color>", multiplyBy1000: true)
			},
			{
				"100 000 ₸",
				new TemplateInfo("{value}\u00a0<color=#558B2F>₸</color>", multiplyBy1000: true)
			},
			{
				"100 000 KZT",
				new TemplateInfo("{value}\u00a0<color=#558B2F>KZT</color>", multiplyBy1000: true)
			}
		};

		private static readonly Dictionary<string, TemplateInfo> ExampleToTemplate_Haul = new Dictionary<string, TemplateInfo>
		{
			{
				"100K тг",
				new TemplateInfo("{value}K\u00a0тг", multiplyBy1000: false)
			},
			{
				"100K ₸",
				new TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false)
			},
			{
				"100K KZT",
				new TemplateInfo("{value}K\u00a0KZT", multiplyBy1000: false)
			},
			{
				"100к тг",
				new TemplateInfo("{value}к\u00a0тг", multiplyBy1000: false)
			},
			{
				"100к ₸",
				new TemplateInfo("{value}к\u00a0₸", multiplyBy1000: false)
			},
			{
				"100 000 тг",
				new TemplateInfo("{value}\u00a0тг", multiplyBy1000: true)
			},
			{
				"100 000 ₸",
				new TemplateInfo("{value}\u00a0₸", multiplyBy1000: true)
			},
			{
				"100 000 KZT",
				new TemplateInfo("{value}\u00a0KZT", multiplyBy1000: true)
			}
		};

		private static readonly Dictionary<string, TemplateInfo> ExampleToTemplate_Cart = new Dictionary<string, TemplateInfo>
		{
			{
				"100 тыс. тг",
				new TemplateInfo("{value}\u00a0тыс.\u00a0тг", multiplyBy1000: false)
			},
			{
				"100 тыс. ₸",
				new TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false)
			},
			{
				"100 тыс. KZT",
				new TemplateInfo("{value}\u00a0тыс.\u00a0KZT", multiplyBy1000: false)
			},
			{
				"100 тг",
				new TemplateInfo("{value}\u00a0тг", multiplyBy1000: false)
			},
			{
				"100 000 тг",
				new TemplateInfo("{value}\u00a0тг", multiplyBy1000: true)
			},
			{
				"100 000 ₸",
				new TemplateInfo("{value}\u00a0₸", multiplyBy1000: true)
			},
			{
				"100 000 KZT",
				new TemplateInfo("{value}\u00a0KZT", multiplyBy1000: true)
			}
		};

		internal static ConfigEntry<string> Format_PlayerUI;

		internal static ConfigEntry<string> Format_ItemCost;

		internal static ConfigEntry<string> Format_ItemPickup;

		internal static ConfigEntry<string> Format_ExtractionPointUI;

		internal static ConfigEntry<string> Format_ExtractionPoint;

		internal static ConfigEntry<string> Format_Cart;

		internal static TemplateInfo Template_PlayerUI;

		internal static TemplateInfo Template_ItemCost;

		internal static TemplateInfo Template_HaulUI;

		internal static TemplateInfo Template_Haul;

		internal static TemplateInfo Template_Cart;

		internal static string TemplateZero_PlayerUI;

		internal static string TemplateZero_ItemCost;

		internal static string TemplateZero_ItemPickup;

		internal static string TemplateZero_HaulUI;

		internal static string TemplateZero_Haul;

		internal static string TemplateZero_Cart;

		private static string MakeZeroFriendlyTemplate(string template)
		{
			if (string.IsNullOrEmpty(template))
			{
				return template;
			}
			return ZeroSuffixPattern.Replace(template, "{value}");
		}

		private static TemplateInfo ConvertExampleToTemplateInfo(string example, Dictionary<string, TemplateInfo> mapping, string mappingName = "Unknown")
		{
			if (mapping.TryGetValue(example, out var value))
			{
				return value;
			}
			Logger.LogWarning((object)("[Formatting] No mapping found for example '" + example + "' in " + mappingName + " mapper. Using fallback with MultiplyBy1000=false."));
			return new TemplateInfo(example, multiplyBy1000: false);
		}

		internal static TemplateInfo GetFormatTemplateInfo(ConfigEntry<string> configEntry, TemplateInfo defaultTemplateInfo, Dictionary<string, TemplateInfo> mapping, string mappingName = "Unknown")
		{
			if (configEntry == null || configEntry.Value == null)
			{
				return defaultTemplateInfo;
			}
			return ConvertExampleToTemplateInfo(configEntry.Value, mapping, mappingName);
		}

		internal static void RefreshTemplates(string reason)
		{
			try
			{
				string arg = Format_PlayerUI?.Value;
				string arg2 = Format_ItemCost?.Value;
				string arg3 = Format_ItemPickup?.Value;
				string arg4 = Format_ExtractionPointUI?.Value;
				string arg5 = Format_Cart?.Value;
				Template_PlayerUI = GetFormatTemplateInfo(Format_PlayerUI, new TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false), ExampleToTemplate_PlayerUI, "PlayerUI");
				Template_ItemCost = GetFormatTemplateInfo(Format_ItemCost, new TemplateInfo("{value}K\u00a0KZT", multiplyBy1000: false), ExampleToTemplate_ItemCost, "ItemCost");
				Template_HaulUI = GetFormatTemplateInfo(Format_ExtractionPointUI, new TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false), ExampleToTemplate_HaulUI, "HaulUI");
				Template_Haul = GetFormatTemplateInfo(Format_ExtractionPoint, new TemplateInfo("{value}K\u00a0₸", multiplyBy1000: false), ExampleToTemplate_Haul, "Haul");
				Template_Cart = GetFormatTemplateInfo(Format_Cart, new TemplateInfo("{value}\u00a0тыс.\u00a0₸", multiplyBy1000: false), ExampleToTemplate_Cart, "Cart");
				TemplateZero_PlayerUI = MakeZeroFriendlyTemplate(Template_PlayerUI.Template);
				TemplateZero_ItemCost = MakeZeroFriendlyTemplate(Template_ItemCost.Template);
				TemplateZero_ItemPickup = MakeZeroFriendlyTemplate(Template_ItemCost.Template);
				TemplateZero_HaulUI = MakeZeroFriendlyTemplate(Template_HaulUI.Template);
				TemplateZero_Haul = MakeZeroFriendlyTemplate(Template_Haul.Template);
				TemplateZero_Cart = MakeZeroFriendlyTemplate(Template_Cart.Template);
				Logger.LogInfo((object)("[Formatting] Refreshed templates (" + reason + ")"));
				Logger.LogInfo((object)$"  PlayerUI:   raw='{arg}' => tpl='{Template_PlayerUI.Template}' x1000={Template_PlayerUI.MultiplyBy1000}");
				Logger.LogInfo((object)$"  ItemCost:     raw='{arg2}' => tpl='{Template_ItemCost.Template}' x1000={Template_ItemCost.MultiplyBy1000}");
				Logger.LogInfo((object)$"  ItemPickup: raw='{arg3}' => tpl='{Template_ItemCost.Template}' x1000={Template_ItemCost.MultiplyBy1000}");
				Logger.LogInfo((object)$"  Haul:     raw='{arg4}' => tpl='{Template_Haul.Template}' x1000={Template_Haul.MultiplyBy1000}");
				Logger.LogInfo((object)$"  HaulUI:     raw='{arg4}' => tpl='{Template_HaulUI.Template}' x1000={Template_HaulUI.MultiplyBy1000}");
				Logger.LogInfo((object)$"  Cart: raw='{arg5}' => tpl='{Template_Cart.Template}' x1000={Template_Cart.MultiplyBy1000}");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[Formatting] Failed to log templates: " + ex.Message));
			}
		}

		private void Awake()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			Format_PlayerUI = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "PlayerUI", "100 000 ₸", new ConfigDescription("Player UI currency format.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[9] { "100K тг", "100K ₸", "100K KZT", "100к тг", "100к ₸", "100 тыс. тг", "100 000 тг", "100 000 ₸", "100 000 KZT" }), Array.Empty<object>()));
			Format_ItemCost = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "ItemCost", "100K ₸", new ConfigDescription("Shop/cart UI currency format.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "100K тг", "100K ₸", "100K KZT", "100 000 тг", "100 000 ₸", "100 000 KZT" }), Array.Empty<object>()));
			Format_ItemPickup = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "ItemPickup", "100 000 ₸", new ConfigDescription("Item pickup/value UI currency format. For values >= 1000: uses thousands format; for < 1000: shows units.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "100 тыс. тг", "100 тыс. ₸", "100 тыс. KZT", "100 000 тг", "100 000 ₸" }), Array.Empty<object>()));
			Format_ExtractionPointUI = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "HaulUI", "100 000 ₸", new ConfigDescription("Extraction point UI currency format.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[9] { "100K тг", "100K ₸", "100K KZT", "100к тг", "100к ₸", "100к KZT", "100 000 тг", "100 000 ₸", "100 000 KZT" }), Array.Empty<object>()));
			Format_ExtractionPoint = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "ExtractionPoint", "100 000 ₸", new ConfigDescription("Extraction point (plain) currency format used by extraction point screens.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[8] { "100K тг", "100K ₸", "100K KZT", "100к тг", "100к ₸", "100 000 тг", "100 000 ₸", "100 000 KZT" }), Array.Empty<object>()));
			Format_Cart = ((BaseUnityPlugin)this).Config.Bind<string>("Formatting", "Cart", "100 тыс. тг", new ConfigDescription("Cart haul currency format.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "100 тыс. тг", "100 тыс. ₸", "100 тыс. KZT", "100 000 тг", "100 000 ₸", "100 000 KZT" }), Array.Empty<object>()));
			TengeSymbolSupport.Initialize();
			RefreshTemplates("startup");
			((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs args)
			{
				RefreshTemplates("configChanged: " + args.ChangedSetting.Definition.Key);
			};
			new Harmony("kztCurrency").PatchAll();
			Logger.LogInfo((object)"Plugin loaded!");
		}
	}
	public static class TengeSymbolSupport
	{
		private const string BUNDLE_FILE_NAME = "teko-cyrillic-tenge.bundle";

		private static TMP_FontAsset tengeFallbackFont;

		private static bool initialized;

		public static void Initialize()
		{
			if (!initialized)
			{
				LoadFontAsset();
				if ((Object)(object)tengeFallbackFont == (Object)null)
				{
					Plugin.Logger.LogError((object)"Failed to load Tenge font asset");
					return;
				}
				AddFallbackToDefaultFont();
				InjectFallbackIntoAllFonts();
				initialized = true;
				Plugin.Logger.LogInfo((object)"Tenge symbol (₸) support initialized");
			}
		}

		private static void LoadFontAsset()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string r) => r.EndsWith("teko-cyrillic-tenge.bundle", StringComparison.OrdinalIgnoreCase));
			if (text == null)
			{
				throw new Exception("Embedded resource ending with 'teko-cyrillic-tenge.bundle' not found");
			}
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				throw new Exception("Failed to open resource stream: " + text);
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			AssetBundle obj = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)obj == (Object)null)
			{
				throw new Exception("Failed to load AssetBundle from memory");
			}
			TMP_FontAsset[] array2 = obj.LoadAllAssets<TMP_FontAsset>();
			if (array2 == null || array2.Length == 0)
			{
				throw new Exception("No TMP_FontAsset found in bundle");
			}
			tengeFallbackFont = array2[0];
			EnsureFontMaterial();
		}

		private static void EnsureFontMaterial()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			if ((Object)(object)((TMP_Asset)tengeFallbackFont).material != (Object)null)
			{
				return;
			}
			Shader val = Shader.Find("TextMeshPro/Distance Field") ?? Shader.Find("TextMeshPro/Mobile/Distance Field");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"TMP shader not found");
				return;
			}
			Material val2 = new Material(val)
			{
				name = "TengeFont_Material"
			};
			if ((Object)(object)tengeFallbackFont.atlasTexture != (Object)null)
			{
				val2.mainTexture = (Texture)(object)tengeFallbackFont.atlasTexture;
			}
			((TMP_Asset)tengeFallbackFont).material = val2;
		}

		private static void AddFallbackToDefaultFont()
		{
			List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets;
			if (fallbackFontAssets != null && !fallbackFontAssets.Contains(tengeFallbackFont))
			{
				fallbackFontAssets.Insert(0, tengeFallbackFont);
			}
			TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset;
			if (!((Object)(object)defaultFontAsset == (Object)null))
			{
				List<TMP_FontAsset> list2 = (defaultFontAsset.fallbackFontAssetTable = defaultFontAsset.fallbackFontAssetTable ?? new List<TMP_FontAsset>());
				if (!list2.Contains(tengeFallbackFont))
				{
					list2.Insert(0, tengeFallbackFont);
				}
			}
		}

		private static void InjectFallbackIntoAllFonts()
		{
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			foreach (TMP_FontAsset val in array)
			{
				if (!((Object)(object)val == (Object)null) && val != tengeFallbackFont)
				{
					List<TMP_FontAsset> list2 = (val.fallbackFontAssetTable = val.fallbackFontAssetTable ?? new List<TMP_FontAsset>());
					if (!list2.Contains(tengeFallbackFont))
					{
						list2.Insert(0, tengeFallbackFont);
					}
				}
			}
		}

		public static void EnsureFallbackFont(TMP_Text textComponent)
		{
			if ((Object)(object)textComponent == (Object)null || (Object)(object)tengeFallbackFont == (Object)null)
			{
				return;
			}
			TMP_FontAsset font = textComponent.font;
			if (!((Object)(object)font == (Object)null))
			{
				List<TMP_FontAsset> list2 = (font.fallbackFontAssetTable = font.fallbackFontAssetTable ?? new List<TMP_FontAsset>());
				if (!list2.Contains(tengeFallbackFont))
				{
					list2.Add(tengeFallbackFont);
				}
			}
		}

		public static void SetPrimaryFont(TMP_Text textComponent)
		{
			if (!((Object)(object)textComponent == (Object)null) && !((Object)(object)tengeFallbackFont == (Object)null) && textComponent.font != tengeFallbackFont)
			{
				textComponent.font = tengeFallbackFont;
				if ((Object)(object)((TMP_Asset)tengeFallbackFont).material != (Object)null)
				{
					textComponent.fontSharedMaterial = ((TMP_Asset)tengeFallbackFont).material;
					textComponent.fontMaterial = ((TMP_Asset)tengeFallbackFont).material;
				}
				((Graphic)textComponent).SetAllDirty();
			}
		}

		public static TMP_FontAsset GetTengeFallbackFont()
		{
			return tengeFallbackFont;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "kztCurrency";

		public const string PLUGIN_NAME = "kztCurrency";

		public const string PLUGIN_VERSION = "1.2.1";
	}
}