using System;
using System.Diagnostics;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using TMProOld;
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("RomanNumerals")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8cb4a3ea608b6acf87be2e515504329a1770dd71")]
[assembly: AssemblyProduct("RomanNumerals")]
[assembly: AssemblyTitle("RomanNumerals")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dpinela/RomanNumerals")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[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 BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace RomanNumerals
{
[BepInPlugin("io.github.dpinela.romannumerals", "RomanNumerals", "1.0.0")]
public class RomanNumeralsPlugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(SaveSlotButton), "Awake")]
private static class SaveButtonPatch
{
private static void Postfix(SaveSlotButton __instance)
{
Text component = ((Component)__instance.slotNumberText).GetComponent<Text>();
component.resizeTextForBestFit = true;
component.text = component.text;
}
}
private Settings? settings;
private Hook? textHook;
private Hook? otherTextHook;
private NativeDetour? textDetour;
private static Action<TextMesh, string?>? origTMSetText;
private static readonly Regex numberPattern = new Regex("(?<!<#)\\b\\d+");
private static RomanNumeralsPlugin? Instance = null;
private static readonly string[] hundreds = new string[10] { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" };
private static readonly string[] tens = new string[10] { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" };
private static readonly string[] ones = new string[10] { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };
public const string Id = "io.github.dpinela.romannumerals";
private static bool Enabled => (Instance?.settings?.ModEnabled).GetValueOrDefault();
public static string Name => "RomanNumerals";
public static string Version => "1.0.0";
private void Awake()
{
Instance = this;
settings = new Settings(((BaseUnityPlugin)this).Config);
if (settings.ModEnabled)
{
Hook();
}
settings.ModToggled += delegate
{
if (settings.ModEnabled)
{
Hook();
}
else
{
Unhook();
}
};
}
private void Hook()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
if (textHook == null)
{
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;
MethodInfo method = typeof(TextMeshPro).GetMethod("set_text", bindingAttr);
textHook = new Hook((MethodBase)method, (Delegate)new Action<Action<TextMeshPro, string>, TextMeshPro, string>(ReplaceText));
method = typeof(Text).GetMethod("set_text", bindingAttr);
otherTextHook = new Hook((MethodBase)method, (Delegate)new Action<Action<Text, string>, Text, string>(ReplaceTextUEUI));
method = typeof(TextMesh).GetMethod("set_text", bindingAttr);
textDetour = new NativeDetour((MethodBase)method, (MethodBase)typeof(RomanNumeralsPlugin).GetMethod("ReplaceTextUE", BindingFlags.Static | BindingFlags.NonPublic));
origTMSetText = textDetour.GenerateTrampoline<Action<TextMesh, string>>();
new Harmony("io.github.dpinela.romannumerals").PatchAll();
}
}
public void Unhook()
{
if (textHook != null)
{
textHook.Dispose();
textHook = null;
otherTextHook.Dispose();
otherTextHook = null;
textDetour.Dispose();
textDetour = null;
origTMSetText = null;
}
}
private void ReplaceText(Action<TextMeshPro, string?> orig, TextMeshPro self, string? origText)
{
orig(self, Romanify(origText));
}
private void ReplaceTextUEUI(Action<Text, string?> orig, Text self, string? origText)
{
orig(self, Romanify(origText));
}
private static void ReplaceTextUE(TextMesh self, string? text)
{
origTMSetText(self, Romanify(text));
}
private static string? Romanify(string? text)
{
if (text == null)
{
return null;
}
return numberPattern.Replace(text, (Match m) => RomanifyNumber(m.Value));
}
private static string RomanifyNumber(string val)
{
if (!int.TryParse(val, out var result))
{
return val;
}
return RomanifyNumber(result);
}
private static string RomanifyNumber(int x)
{
if (x == 0)
{
return "N";
}
if (x < 4000)
{
return RomanifySmallNumber(x);
}
return "(" + RomanifySmallNumber(x / 1000) + ")" + RomanifySmallNumber(x % 1000);
}
private static string RomanifySmallNumber(int x)
{
string text = new string('M', x / 1000);
x %= 1000;
string text2 = text + hundreds[x / 100];
x %= 100;
string text3 = text2 + tens[x / 10];
x %= 10;
return text3 + ones[x];
}
}
internal class Settings
{
private ConfigEntry<bool> _modEnabled;
public bool ModEnabled => _modEnabled.Value;
public event Action ModToggled = delegate
{
};
public Settings(ConfigFile config)
{
_modEnabled = config.Bind<bool>("", "Mod Enabled", true, "Turn all numbers into Roman numerals");
_modEnabled.SettingChanged += delegate
{
this.ModToggled?.Invoke();
};
}
}
}