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 LookingGlass Chinese Patch v1.1.1
BepInEx/plugins/LookingGlassZhCN/LookingGlassZhCN.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using HarmonyLib; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace LookingGlassZhCN; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("local.lookingglass.zhcn.settings", "LookingGlass Chinese Patch", "1.1.0")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "local.lookingglass.zhcn.settings"; private Harmony harmony; private void Start() { //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown try { if (!Chainloader.PluginInfos.TryGetValue("com.rune580.riskofoptions", out var value)) { throw new InvalidOperationException("Risk Of Options was not loaded."); } Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = assembly.GetType("RiskOfOptions.Lib.LanguageApi", throwOnError: true); FieldInfo field = type.GetField("LanguageEntries", BindingFlags.Static | BindingFlags.NonPublic); if (field == null) { throw new MissingFieldException(type.FullName, "LanguageEntries"); } if (!(field.GetValue(null) is IDictionary<string, string> entries)) { throw new InvalidOperationException("Unexpected language registry type."); } int num = MenuTranslation.Apply(entries); ((BaseUnityPlugin)this).Logger.LogInfo((object)("LookingGlass ESC settings translated: " + num + " entries.")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not translate the settings menu: " + ex)); } try { if (!Chainloader.PluginInfos.TryGetValue("droppod.lookingglass", out var value2)) { throw new InvalidOperationException("LookingGlass was not loaded."); } Type type2 = ((object)value2.Instance).GetType().Assembly.GetType("LookingGlass.StatsDisplay.StatsDisplayClass", throwOnError: true); MethodInfo method = type2.GetMethod("CalculateStuff", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (method == null || method.ReturnType != typeof(void)) { throw new MissingMethodException(type2.FullName, "CalculateStuff(string)"); } harmony = new Harmony("local.lookingglass.zhcn.settings"); harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(Plugin).GetMethod("TranslateStats", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LookingGlass main/Tab stats translation enabled. Original configuration is unchanged."); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not translate the stats display: " + ex2)); } } private static void TranslateStats(ref string __0) { __0 = StatsTranslation.Translate(__0); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } } public static class MenuTranslation { private const string LookingGlassPrefix = "RISK_OF_OPTIONS.DROPPOD.LOOKINGGLASS."; private static readonly Dictionary<string, string> Translations = LoadTranslations(); private static Dictionary<string, string> LoadTranslations() { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); using Stream stream = typeof(MenuTranslation).Assembly.GetManifestResourceStream("LookingGlassZhCN.translations.tsv"); if (stream == null) { throw new InvalidOperationException("Missing translation resource."); } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); string text; while ((text = streamReader.ReadLine()) != null) { int num = text.IndexOf('\t'); if (num <= 0) { throw new InvalidDataException("Invalid translation row."); } dictionary.Add(Unescape(text.Substring(0, num)), Unescape(text.Substring(num + 1))); } return dictionary; } private static string Unescape(string value) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < value.Length; i++) { char c = value[i]; if (c != '\\') { stringBuilder.Append(c); continue; } if (++i >= value.Length) { throw new InvalidDataException("Invalid escape."); } switch (value[i]) { case '\\': stringBuilder.Append('\\'); break; case 'n': stringBuilder.Append('\n'); break; case 'r': stringBuilder.Append('\r'); break; case 't': stringBuilder.Append('\t'); break; default: throw new InvalidDataException("Unknown escape."); } } return stringBuilder.ToString(); } public static string Translate(string token, string text) { if (token == null || !token.StartsWith("RISK_OF_OPTIONS.DROPPOD.LOOKINGGLASS.", StringComparison.OrdinalIgnoreCase)) { return text; } if (token.EndsWith(".ITEM.SET", StringComparison.OrdinalIgnoreCase)) { return "保留当前设置"; } if (token.EndsWith(".ITEM.LOOKINGGLASS", StringComparison.OrdinalIgnoreCase)) { return "LookingGlass 默认"; } if (Translations.TryGetValue(text, out var value)) { return value; } if (text != null && text.StartsWith("Position of detached Stats Display.\n[Default: ", StringComparison.Ordinal)) { return "独立属性面板的位置。\n[默认:" + text.Substring("Position of detached Stats Display.\n[Default: ".Length); } return text; } public static int Apply(IDictionary<string, string> entries) { List<string> list = new List<string>(entries.Keys); int num = 0; foreach (string item in list) { string text = entries[item]; string text2 = Translate(item, text); if (!string.Equals(text, text2, StringComparison.Ordinal)) { entries[item] = text2; num++; } } if (!entries.ContainsKey("RISK_OF_OPTIONS_MOD_OPTIONS_HEADER_BUTTON_TEXT") || entries["RISK_OF_OPTIONS_MOD_OPTIONS_HEADER_BUTTON_TEXT"] != "模组选项") { entries["RISK_OF_OPTIONS_MOD_OPTIONS_HEADER_BUTTON_TEXT"] = "模组选项"; num++; } return num; } } public static class StatsTranslation { private static readonly Dictionary<string, string> Labels = new Dictionary<string, string>(StringComparer.Ordinal) { { "Stats", "属性" }, { "Damage", "伤害" }, { "Attack Speed", "攻击速度" }, { "Crit Chance", "暴击率" }, { "Crit Stats", "暴击率 / 暴击倍率" }, { "Bleed Chance", "流血几率" }, { "Regen", "生命恢复" }, { "Armor", "护甲 / 减伤" }, { "Speed", "移动速度" }, { "Jumps", "可用跳跃" }, { "Kills", "击杀" }, { "Total Kills", "总击杀" }, { "DPS", "每秒伤害" }, { "Combo", "连击伤害" }, { "Max Combo", "最高连击伤害" }, { "Combo Timer", "连击剩余时间" }, { "Mountain Shrines", "山之神龛" }, { "Portals", "传送门" }, { "Portal", "传送门" }, { "Luck", "幸运" }, { "Max Hp", "最大生命值" }, { "Ehp", "有效生命值" }, { "Ping", "延迟" }, { "Curse", "诅咒" }, { "Gold", "黄金" }, { "Shop", "商店" }, { "Celestial", "天界" }, { "Void", "虚空" } }; private static readonly Regex Protected = new Regex("(<[^>]*>|\\[[^\\]\\r\\n]*\\])"); private static readonly Regex LineLabel = new Regex("(?m)(^|[\\r\\n])([ \\t]*)(Stats|Damage|Attack Speed|Crit Chance|Crit Stats|Bleed Chance|Regen|Armor|Speed|Jumps|Kills|Total Kills|DPS|Combo|Max Combo|Combo Timer|Mountain Shrines|Portals|Portal|Luck|Max Hp|Ehp|Ping|Curse)(?=[ \\t]*[::])"); private static readonly Regex Title = new Regex("(?m)(^|[\\r\\n])([ \\t]*)Stats([ \\t]*)(?=$|[\\r\\n])"); private static readonly Regex PortalLabel = new Regex("(?<![\\p{L}\\p{N}_])(Gold|Shop|Celestial|Void)(?=[ \\t]*[::])"); public static string Translate(string text) { if (string.IsNullOrEmpty(text)) { return text; } string[] array = Protected.Split(text); StringBuilder stringBuilder = new StringBuilder(text.Length); for (int i = 0; i < array.Length; i++) { if ((i & 1) != 0) { stringBuilder.Append(array[i]); continue; } string input = LineLabel.Replace(array[i], (Match m) => m.Groups[1].Value + m.Groups[2].Value + Labels[m.Groups[3].Value]); input = Title.Replace(input, "$1$2属性$3"); input = PortalLabel.Replace(input, (Match m) => Labels[m.Value]); stringBuilder.Append(input); } string text2 = stringBuilder.ToString(); if (!string.Equals(text, text2, StringComparison.Ordinal)) { return text2; } return text; } }