Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Sims Translation v1.0.1
SimTranslation.dll
Decompiled 8 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Omniscye")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SimTranslation")] [assembly: AssemblyTitle("SimTranslation")] [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 SimTranslation { [BepInPlugin("Omniscye.SimTranslation", "SimTranslation", "1.0")] public class SimTranslation : BaseUnityPlugin { internal static SimTranslation Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { } } } namespace Empress.Simlishizer { [BepInPlugin("empress.repo.simlishizer", "Simlishizer", "1.1.1")] public class Simlishizer : BaseUnityPlugin { internal class SimlishState : MonoBehaviour { public string lastIn; public string lastOut; } internal static class Core { private static readonly Regex TagRx = new Regex("<[^>]*>", RegexOptions.Compiled); private static readonly Regex WordRx = new Regex("\\b[\\p{L}][\\p{L}\\p{Mn}\\p{Pd}']*\\b", RegexOptions.Compiled); private static readonly Regex SimlishHintRx = new Regex("\\b(sul\\s?sul|dag\\s?dag|nooboo|voo?hoo|yibs|whippna|glooby|frabbit)\\b", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Dictionary<string, string> VowelSubs = new Dictionary<string, string> { { "ea", "ee" }, { "ee", "ii" }, { "oo", "uu" }, { "ou", "oo" }, { "ai", "ay" }, { "au", "oo" }, { "oi", "oy" }, { "ie", "ee" }, { "ei", "ee" } }; private static readonly Dictionary<string, string> Common = new Dictionary<string, string> { { "play", "plumbob" }, { "start", "sul sul" }, { "exit", "dag dag" }, { "confirm", "voohoo" }, { "ok", "okie-dokie" }, { "yes", "yibs" }, { "no", "naybo" }, { "pause", "glooby" }, { "resume", "frabbit" }, { "loading", "whippna choba" }, { "settings", "zowie" }, { "options", "zowie" }, { "warning", "zo hungwah" }, { "error", "hoo baa" }, { "player", "sim" }, { "you", "duh" }, { "health", "nooboo" }, { "ammo", "zizzle" }, { "score", "zooba" } }; private static readonly (string Key, string Value)[] ConsonantSubs = new(string, string)[5] { ("th", "d"), ("ch", "sh"), ("ph", "f"), ("ck", "k"), ("qu", "kw") }; private static readonly string[] SimlishParticles = new string[6] { " sul!", " dag dag!", " nooboo!", " yibs!", " zowie!", " voohoo!" }; public static string StripTags(string s) { return TagRx.Replace(s ?? string.Empty, ""); } private static bool LooksSimlish(string s) { return SimlishHintRx.IsMatch(s); } public static SimlishState GetStateFor(Component comp) { GameObject gameObject = comp.gameObject; SimlishState simlishState = gameObject.GetComponent<SimlishState>(); if (!Object.op_Implicit((Object)(object)simlishState)) { simlishState = gameObject.AddComponent<SimlishState>(); } return simlishState; } public static string ToSimlishIfNeeded(Component comp, string raw, bool treatAsTMP) { if (!Enabled.Value) { return raw; } if ((Object)(object)comp == (Object)null) { return raw; } if (ProcessTMPOnly.Value && !treatAsTMP) { return raw; } SimlishState stateFor = GetStateFor(comp); if (stateFor.lastIn == raw) { return stateFor.lastOut ?? raw; } string text = StripTags(raw); if (text.Length < MinLength.Value) { stateFor.lastIn = raw; stateFor.lastOut = raw; return raw; } try { if (!string.IsNullOrEmpty(ExclusionsRegex.Value) && Regex.IsMatch(text, ExclusionsRegex.Value)) { stateFor.lastIn = raw; stateFor.lastOut = raw; return raw; } if (SkipIfLooksSimlish.Value && LooksSimlish(text)) { stateFor.lastIn = raw; stateFor.lastOut = raw; return raw; } string text2 = (RespectRichTags.Value ? MapPreservingTags(raw) : MapPlain(text)); stateFor.lastIn = raw; stateFor.lastOut = text2; return text2; } catch (Exception arg) { Log.LogWarning((object)$"Simlish transform failed: {arg}"); stateFor.lastIn = raw; stateFor.lastOut = raw; return raw; } } private static string MapPreservingTags(string s) { StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (Match item in TagRx.Matches(s)) { if (item.Index > num) { stringBuilder.Append(MapPlain(s.Substring(num, item.Index - num))); } stringBuilder.Append(item.Value); num = item.Index + item.Length; } if (num < s.Length) { stringBuilder.Append(MapPlain(s.Substring(num))); } return stringBuilder.ToString(); } private static string MapPlain(string s) { bool addFlavor = AddFlavorParticles.Value; int flavorEvery = Math.Max(FlavorEveryNWords.Value, 2); int wordCount = 0; return WordRx.Replace(s, delegate(Match match) { string value = match.Value; wordCount++; string text = MapWordToSimlish(value); if (addFlavor && wordCount % flavorEvery == 0) { text += SimlishParticles[Random.Range(0, SimlishParticles.Length)]; } return text; }); } private static string MapWordToSimlish(string word) { if (string.IsNullOrEmpty(word)) { return word; } string text = word; string text2 = ""; string text3 = ""; Match match = Regex.Match(text, "^[\\p{Pd}']+"); if (match.Success) { text2 = match.Value; text = text.Substring(text2.Length); } Match match2 = Regex.Match(text, "[\\p{Pd}']+$"); if (match2.Success) { text3 = match2.Value; text = text.Substring(0, text.Length - match2.Length); } if (text.Length == 0) { return word; } bool flag = text.ToUpperInvariant() == text; bool flag2 = char.IsUpper(text[0]) && (text.Length == 1 || text.Substring(1).ToLowerInvariant() == text.Substring(1)); text = ((!Common.TryGetValue(text.ToLowerInvariant(), out string value)) ? Phonetic(text) : value); if (flag) { text = text.ToUpperInvariant(); } else if (flag2 && text.Length > 0) { text = char.ToUpperInvariant(text[0]) + text.Substring(1); } return text2 + text + text3; } private static string Phonetic(string s) { string text = s.ToLowerInvariant(); foreach (KeyValuePair<string, string> vowelSub in VowelSubs) { text = text.Replace(vowelSub.Key, vowelSub.Value); } (string, string)[] consonantSubs = ConsonantSubs; for (int i = 0; i < consonantSubs.Length; i++) { (string, string) tuple = consonantSubs[i]; text = Regex.Replace(text, tuple.Item1, tuple.Item2); } text = Regex.Replace(text, "([bcdfghjklmnpqrstvwxyz])(?=[bcdfghjklmnpqrstvwxyz])", "$1a"); text = Regex.Replace(text, "([aeiou])([bcdfghjklmnpqrstvwxyz])\\b", (Match m) => m.Groups[1].Value + m.Groups[2].Value + "a"); StringBuilder stringBuilder = new StringBuilder(text.Length + 8); for (int j = 0; j < text.Length; j++) { char c = text[j]; stringBuilder.Append(c); if (IsVowel(c) && j + 1 < text.Length && IsConsonant(text[j + 1])) { if ((j & 3) == 1) { stringBuilder.Append("oo"); } else if ((j & 3) == 2) { stringBuilder.Append("ah"); } } } string input = stringBuilder.ToString(); input = Regex.Replace(input, "([aeiou])\\1{2,}", "$1$1"); input = Regex.Replace(input, "([a]{2,})", "a"); return Regex.Replace(input, "([o]{3,})", "oo"); } private static bool IsVowel(char c) { return "aeiou".IndexOf(c) >= 0; } private static bool IsConsonant(char c) { return c >= 'a' && c <= 'z' && !IsVowel(c); } } internal static class Patches { public static class TMPText_set_text { public static void Prefix(TMP_Text __instance, ref string value) { if (value != null) { value = Core.ToSimlishIfNeeded((Component)(object)__instance, value, treatAsTMP: true); } } } [HarmonyPatch(typeof(TMP_Text))] public static class TMPText_SetText_StringLike { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private List<MethodInfo>.Enumerator <>s__1; private MethodInfo <m>5__2; private ParameterInfo[] <ps>5__3; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = default(List<MethodInfo>.Enumerator); <m>5__2 = null; <ps>5__3 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; goto IL_00db; } <>1__state = -1; <>s__1 = AccessTools.GetDeclaredMethods(typeof(TMP_Text)).GetEnumerator(); <>1__state = -3; goto IL_00ea; IL_00db: <ps>5__3 = null; <m>5__2 = null; goto IL_00ea; IL_00ea: do { if (<>s__1.MoveNext()) { <m>5__2 = <>s__1.Current; continue; } <>m__Finally1(); <>s__1 = default(List<MethodInfo>.Enumerator); return false; } while (<m>5__2.Name != "SetText"); <ps>5__3 = <m>5__2.GetParameters(); if (<ps>5__3.Length >= 1 && <ps>5__3[0].ParameterType == typeof(string)) { <>2__current = <m>5__2; <>1__state = 1; return true; } goto IL_00db; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } private static void Prefix(TMP_Text __instance, ref string __0) { if (__0 != null) { __0 = Core.ToSimlishIfNeeded((Component)(object)__instance, __0, treatAsTMP: true); } } } [HarmonyPatch(typeof(TMP_Text))] public static class TMPText_SetText_SBLike { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private List<MethodInfo>.Enumerator <>s__1; private MethodInfo <m>5__2; private ParameterInfo[] <ps>5__3; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = default(List<MethodInfo>.Enumerator); <m>5__2 = null; <ps>5__3 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; goto IL_00db; } <>1__state = -1; <>s__1 = AccessTools.GetDeclaredMethods(typeof(TMP_Text)).GetEnumerator(); <>1__state = -3; goto IL_00ea; IL_00db: <ps>5__3 = null; <m>5__2 = null; goto IL_00ea; IL_00ea: do { if (<>s__1.MoveNext()) { <m>5__2 = <>s__1.Current; continue; } <>m__Finally1(); <>s__1 = default(List<MethodInfo>.Enumerator); return false; } while (<m>5__2.Name != "SetText"); <ps>5__3 = <m>5__2.GetParameters(); if (<ps>5__3.Length >= 1 && <ps>5__3[0].ParameterType == typeof(StringBuilder)) { <>2__current = <m>5__2; <>1__state = 1; return true; } goto IL_00db; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } private static void Prefix(TMP_Text __instance, StringBuilder __0) { if (__0 != null) { string value = Core.ToSimlishIfNeeded((Component)(object)__instance, __0.ToString(), treatAsTMP: true); __0.Length = 0; __0.Append(value); } } } public static class LegacyText_set_text { public static void Prefix(Text __instance, ref string value) { if (value != null) { value = Core.ToSimlishIfNeeded((Component)(object)__instance, value, treatAsTMP: false); } } } } public const string PluginGuid = "empress.repo.simlishizer"; public const string PluginName = "Simlishizer"; public const string PluginVersion = "1.1.1"; internal static ManualLogSource Log; internal static Harmony Harmony; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<int> MinLength; internal static ConfigEntry<string> ExclusionsRegex; internal static ConfigEntry<bool> ProcessTMPOnly; internal static ConfigEntry<bool> RespectRichTags; internal static ConfigEntry<bool> AddFlavorParticles; internal static ConfigEntry<int> FlavorEveryNWords; internal static ConfigEntry<bool> SkipIfLooksSimlish; internal static ConfigEntry<bool> PatchLegacyUGUIText; private void Awake() { //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master on/off."); MinLength = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MinLength", 3, "Minimum raw segment length to process."); ExclusionsRegex = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExclusionsRegex", "^\\s*$", "Regex tested against tag-stripped text; matching text is skipped."); ProcessTMPOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "ProcessTMPOnly", true, "Only process TMPro components (recommended)."); RespectRichTags = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "RespectRichTags", true, "Keep <...> segments intact."); AddFlavorParticles = ((BaseUnityPlugin)this).Config.Bind<bool>("Style", "AddFlavorParticles", true, "Occasionally insert small Simlish particles."); FlavorEveryNWords = ((BaseUnityPlugin)this).Config.Bind<int>("Style", "FlavorEveryNWords", 8, "Insert a particle roughly every N words."); SkipIfLooksSimlish = ((BaseUnityPlugin)this).Config.Bind<bool>("Style", "SkipIfLooksSimlish", true, "Avoid double-processing if text already looks Simlish."); PatchLegacyUGUIText = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "PatchLegacyUGUIText", true, "Also patch UnityEngine.UI.Text.text setter."); Harmony = new Harmony("empress.repo.simlishizer"); TryPatch(typeof(TMP_Text).GetProperty("text")?.GetSetMethod(nonPublic: true), typeof(Patches.TMPText_set_text)); Harmony.CreateClassProcessor(typeof(Patches.TMPText_SetText_StringLike)).Patch(); Harmony.CreateClassProcessor(typeof(Patches.TMPText_SetText_SBLike)).Patch(); if (PatchLegacyUGUIText.Value) { TryPatch(typeof(Text).GetProperty("text")?.GetSetMethod(nonPublic: true), typeof(Patches.LegacyText_set_text)); } Log.LogInfo((object)("Simlishizer 1.1.1 loaded. TMP text + SetText patched; LegacyText " + (PatchLegacyUGUIText.Value ? "ON" : "OFF") + ".")); } private void OnDestroy() { try { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } } private static void TryPatch(MethodBase target, Type patchType) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (target == null) { Log.LogWarning((object)("Target missing for " + patchType.Name + ", skipping.")); return; } object obj = Harmony; obj = target; obj = (object)((!(AccessTools.Method(patchType, "Prefix", (Type[])null, (Type[])null) != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(patchType, "Prefix", (Type[])null)); obj = (object)((!(AccessTools.Method(patchType, "Postfix", (Type[])null, (Type[])null) != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(patchType, "Postfix", (Type[])null)); ((Harmony)obj).Patch((MethodBase)obj, (HarmonyMethod)obj, (HarmonyMethod)obj, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogDebug((object)("Patched: " + target.DeclaringType?.FullName + "." + target.Name)); } } }