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";
}
}