using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon.Movement; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("coru")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Translates alien language text in upgrade names and descriptions to readable English. Adds an in-game toggle via Sparroh's mod config menu.")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0.0")] [assembly: AssemblyProduct("TranslatorMod")] [assembly: AssemblyTitle("TranslatorMod")] [assembly: AssemblyVersion("1.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } [MycoMod(/*Could not decode attribute arguments.*/)] [BepInPlugin("coruscnium.translator", "Translator", "1.3.0.0")] [BepInProcess("Mycopunk.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class TranslatorModPlugin : BaseUnityPlugin { public const string PluginGUID = "coruscnium.translator"; public const string PluginName = "Translator"; public const string PluginVersion = "1.3.0.0"; internal static ManualLogSource Logger; private static ConfigEntry _enableTranslation; private static volatile bool _enabled = true; private static FileSystemWatcher _configWatcher; private static volatile bool _pendingReload; private static bool _lastRefreshedState = true; internal static bool Enabled => _enabled; private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; _enableTranslation = ((BaseUnityPlugin)this).Config.Bind("General", "EnableTranslation", true, "When ON, shows Mycopunk's alien-language text as readable English. Turn OFF to keep the in-game Hashetty look. Toggle it live from Sparroh's mod config menu (default F10)."); _enabled = _enableTranslation.Value; _lastRefreshedState = _enabled; try { _configWatcher = new FileSystemWatcher(Paths.ConfigPath, "coruscnium.translator.cfg") { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), EnableRaisingEvents = true }; _configWatcher.Changed += OnConfigFileChanged; _configWatcher.Created += OnConfigFileChanged; _configWatcher.Renamed += OnConfigFileChanged; } catch (Exception ex) { Logger.LogWarning((object)("Could not start config watcher; the menu toggle will still apply after reopening affected UI. (" + ex.Message + ")")); } Harmony.CreateAndPatchAll(typeof(FontLookupPatch), (string)null); Harmony.CreateAndPatchAll(typeof(UpgradeNamePatch), (string)null); Harmony.CreateAndPatchAll(typeof(UpgradeDescriptionPatch), (string)null); Harmony.CreateAndPatchAll(typeof(UpgradeStatListPatch), (string)null); Harmony.CreateAndPatchAll(typeof(PlayerStackPatch), (string)null); Harmony.CreateAndPatchAll(typeof(ChatMessagePatch), (string)null); Harmony.CreateAndPatchAll(typeof(AddPropertyPatch), (string)null); Harmony.CreateAndPatchAll(typeof(TextBlockGetTextPatch), (string)null); Harmony.CreateAndPatchAll(typeof(TextBlockGetStringPatch), (string)null); Harmony.CreateAndPatchAll(typeof(TextBlockGetStringIndexPatch), (string)null); Harmony.CreateAndPatchAll(typeof(TextValueApplyToPatch), (string)null); Logger.LogInfo((object)("Translator v1.3.0.0 loaded (translation " + (_enabled ? "ON" : "OFF") + ")")); } private void Update() { if (_pendingReload) { _pendingReload = false; try { ((BaseUnityPlugin)this).Config.Reload(); bool value = _enableTranslation.Value; if (value != _enabled) { _enabled = value; Logger.LogInfo((object)("Translation " + (value ? "ON" : "OFF") + " (config reloaded)")); } } catch (Exception ex) { Logger.LogWarning((object)("Config reload failed: " + ex.Message)); } } if (_lastRefreshedState != _enabled) { _lastRefreshedState = _enabled; FontRedirect.RefreshVisibleText(); } } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { _pendingReload = true; } private void OnDestroy() { if (_configWatcher != null) { _configWatcher.EnableRaisingEvents = false; _configWatcher.Changed -= OnConfigFileChanged; _configWatcher.Created -= OnConfigFileChanged; _configWatcher.Renamed -= OnConfigFileChanged; _configWatcher.Dispose(); _configWatcher = null; } } internal static string Strip(string s) { if (!_enabled || string.IsNullOrEmpty(s)) { return s; } if (s.IndexOf("", StringComparison.Ordinal) < 0) { return s; } return s.Replace("", "").Replace("", ""); } } internal static class FontRedirect { internal const int HHash = 72; private static TMP_FontAsset _readable; internal static TMP_FontAsset Readable { get { if ((Object)(object)_readable != (Object)null) { return _readable; } Global instance = Global.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.NormalFont != (Object)null && ((Object)instance.NormalFont).name != "H") { return _readable = instance.NormalFont; } TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset; if ((Object)(object)defaultFontAsset != (Object)null && ((Object)defaultFontAsset).name != "H") { return _readable = defaultFontAsset; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name != "H") { _readable = val; break; } } return _readable; } } internal static void RefreshVisibleText() { try { TMP_Text[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled) { try { val.ForceMeshUpdate(false, true); } catch { } } } } catch { } } } [HarmonyPatch(typeof(MaterialReferenceManager), "TryGetFontAsset")] internal static class FontLookupPatch { [HarmonyPostfix] private static void Postfix(int hashCode, ref TMP_FontAsset fontAsset, ref bool __result) { if (TranslatorModPlugin.Enabled && hashCode == 72) { TMP_FontAsset readable = FontRedirect.Readable; if ((Object)(object)readable != (Object)null) { fontAsset = readable; __result = true; } } } } [HarmonyPatch(typeof(Upgrade), "get_Name")] internal static class UpgradeNamePatch { [HarmonyPostfix] private static void Postfix(ref string __result) { __result = TranslatorModPlugin.Strip(__result); } } [HarmonyPatch(typeof(Upgrade), "get_Description")] internal static class UpgradeDescriptionPatch { [HarmonyPostfix] private static void Postfix(ref string __result) { __result = TranslatorModPlugin.Strip(__result); } } [HarmonyPatch(typeof(Upgrade), "GetStatList")] internal static class UpgradeStatListPatch { [HarmonyPostfix] private static void Postfix(ref string __result) { __result = TranslatorModPlugin.Strip(__result); } } [HarmonyPatch(typeof(PlayerLook), "AddTextChatMessage")] internal static class ChatMessagePatch { [HarmonyPrefix] private static void Prefix(ref string message) { message = TranslatorModPlugin.Strip(message); } } [HarmonyPatch(typeof(UpgradeProperty), "AddProperty")] internal static class AddPropertyPatch { [HarmonyPostfix] private static void Postfix(ref string properties) { properties = TranslatorModPlugin.Strip(properties); } } [HarmonyPatch(typeof(TextBlock), "GetText")] internal static class TextBlockGetTextPatch { [HarmonyPostfix] private static void Postfix(ref string __result) { __result = TranslatorModPlugin.Strip(__result); } } [HarmonyPatch(typeof(TextBlocks), "GetString", new Type[] { typeof(string) })] internal static class TextBlockGetStringPatch { [HarmonyPostfix] private static void Postfix(ref string __result) { __result = TranslatorModPlugin.Strip(__result); } } [HarmonyPatch(typeof(TextBlocks), "GetString", new Type[] { typeof(string), typeof(int) })] internal static class TextBlockGetStringIndexPatch { [HarmonyPostfix] private static void Postfix(ref string __result) { __result = TranslatorModPlugin.Strip(__result); } } [HarmonyPatch(typeof(TextValue), "ApplyTo")] internal static class TextValueApplyToPatch { [HarmonyPostfix] private static void Postfix(TextMeshProUGUI text) { if (!((Object)(object)text == (Object)null)) { string text2 = TranslatorModPlugin.Strip(((TMP_Text)text).text); if ((object)text2 != ((TMP_Text)text).text) { ((TMP_Text)text).text = text2; } } } } [HarmonyPatch(typeof(Player), "UpdateStackDisplay")] internal static class PlayerStackPatch { [HarmonyPrefix] private static void Prefix(object id, ref string name, Sprite icon, Color color, int stacks, bool updateName, float timeoutDuration) { name = TranslatorModPlugin.Strip(name); } }