using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using UnityEngine;
using YAPYAP;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("YapYapRomajiDisplay")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("YapYapRomajiDisplay")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("232ca5e3-9626-4eca-890a-806072a9a406")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("acpass.romajidisplay", "RomajiDisplay", "1.1.3")]
public class RomajiDisplay : BaseUnityPlugin
{
public void Awake()
{
Harmony.CreateAndPatchAll(typeof(RomajiDisplay).Assembly, (string)null);
((BaseUnityPlugin)this).Logger.LogInfo((object)"RomajiDisplay is enabled.");
}
}
public static class RomajiConfigManager
{
private static Dictionary<string, string> _romajiCache;
private static string ConfigPath => Path.Combine(Paths.ConfigPath, "romaji_mapping.txt");
static RomajiConfigManager()
{
_romajiCache = new Dictionary<string, string>();
LoadConfig();
}
public static void LoadConfig()
{
_romajiCache.Clear();
if (!File.Exists(ConfigPath))
{
bool flag = false;
try
{
string text = Path.Combine(Path.GetDirectoryName(typeof(RomajiDisplay).Assembly.Location), "romaji_mapping.txt");
if (File.Exists(text))
{
File.Copy(text, ConfigPath);
Debug.Log((object)("[RomajiDisplay] 已从插件目录复制配置文件到: " + ConfigPath));
flag = true;
}
}
catch (Exception ex)
{
Debug.LogError((object)("[RomajiDisplay] 复制配置文件出错: " + ex.Message));
}
if (!flag)
{
CreateDefaultConfig();
return;
}
}
try
{
string[] array = File.ReadAllLines(ConfigPath);
foreach (string text2 in array)
{
if (string.IsNullOrWhiteSpace(text2) || text2.Trim().StartsWith("#"))
{
continue;
}
string[] array2 = text2.Split(new char[1] { '=' });
if (array2.Length == 2)
{
string key = array2[0].Trim();
string value = array2[1].Trim();
if (!_romajiCache.ContainsKey(key))
{
_romajiCache.Add(key, value);
}
}
}
Debug.Log((object)$"[RomajiDisplay] 配置文件已加载,共读取 {_romajiCache.Count} 条数据。");
}
catch (Exception ex2)
{
Debug.LogError((object)("[RomajiDisplay] 读取配置文件失败: " + ex2.Message));
}
}
public static string GetValue(string key)
{
if (_romajiCache.TryGetValue(key, out var value))
{
return value;
}
return null;
}
public static string FormatRomaji(string romaji)
{
return "<size=65%><color=#FFD700>" + romaji + "</color></size>";
}
private static void CreateDefaultConfig()
{
try
{
using (StreamWriter streamWriter = File.CreateText(ConfigPath))
{
streamWriter.WriteLine("# 罗马音映射配置文件");
streamWriter.WriteLine("# 按 F9 可以在游戏中重新加载此文件");
streamWriter.WriteLine("# 格式: VoiceCommandKey = 显示文本");
}
Debug.Log((object)("[RomajiDisplay] 已生成默认配置文件: " + ConfigPath));
}
catch (Exception ex)
{
Debug.LogError((object)("[RomajiDisplay] 无法创建默认配置文件: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(VoiceSpell), "Update")]
public class ReloadInputPatch
{
[HarmonyPrefix]
public static void Prefix()
{
if (Input.GetKeyDown((KeyCode)290))
{
RomajiConfigManager.LoadConfig();
Debug.Log((object)"[RomajiDisplay] 用户按下了 F9,正在重新加载配置...");
}
}
}
[HarmonyPatch(typeof(UISelectionWheelOptionElement), "Initialize", new Type[]
{
typeof(IChargeable),
typeof(string),
typeof(Sprite),
typeof(Color),
typeof(Color),
typeof(Material)
})]
public class WheelElementPatch
{
private static Regex _cooldownRegex = new Regex("(\\s<alpha=.*)$");
[HarmonyPrefix]
public static void Prefix(object chargeable, ref string title)
{
if (chargeable == null || string.IsNullOrEmpty(title) || title.Contains("<color=#FFD700>"))
{
return;
}
object obj = ((chargeable is Spell) ? chargeable : null);
string text = ((obj != null) ? ((Spell)obj).VoiceCommandKey : null);
if (string.IsNullOrEmpty(text))
{
return;
}
string value = RomajiConfigManager.GetValue(text);
if (!string.IsNullOrEmpty(value))
{
string text2 = RomajiConfigManager.FormatRomaji(value);
if (_cooldownRegex.IsMatch(title))
{
title = _cooldownRegex.Replace(title, " " + text2 + "$1");
}
else
{
title = title + "\n" + text2;
}
}
}
}
[HarmonyPatch(typeof(ReviveChant), "GetLocalisedVoiceCommandKey", new Type[] { typeof(string) })]
public class ReviveChantPatch
{
[HarmonyPostfix]
public static void Postfix(string __0, ref string __result)
{
string value = RomajiConfigManager.GetValue(__0);
if (!string.IsNullOrEmpty(value))
{
__result = __result + " " + RomajiConfigManager.FormatRomaji(value);
}
}
}
[HarmonyPatch(typeof(ReviveSpell), "GetLocalisedVoiceCommandKey", new Type[] { typeof(string) })]
public class ReviveSpellPatch
{
[HarmonyPostfix]
public static void Postfix(string __0, ref string __result)
{
string value = RomajiConfigManager.GetValue(__0);
if (!string.IsNullOrEmpty(value))
{
__result = __result + " " + RomajiConfigManager.FormatRomaji(value);
}
}
}
[HarmonyPatch(typeof(TradeSpell), "TryGetTradeWord")]
public class TradeSpellPatch
{
[HarmonyPostfix]
public static void Postfix(TradeSpell __instance, ref bool __result, object[] __args)
{
if (__result && __args.Length != 0 && __args[0] is string text)
{
string value = RomajiConfigManager.GetValue("SPELL_ARC_TRADE_2");
if (!string.IsNullOrEmpty(value))
{
__args[0] = text + " " + RomajiConfigManager.FormatRomaji(value);
}
}
}
}
[HarmonyPatch("YAPYAP.XiLanHuaPuzzle, Assembly-CSharp", "UpdateLocalizedWords")]
public class XiLanHuaPuzzlePatch
{
[HarmonyPostfix]
public static void Postfix(object __instance)
{
Traverse obj = Traverse.Create(__instance);
Array array = obj.Field("symbolWords").GetValue() as Array;
GameObject[] array2 = obj.Field("worldSpaceXiLanHuaSigns").GetValue() as GameObject[];
if (array == null)
{
return;
}
for (int i = 0; i < array.Length; i++)
{
object value = array.GetValue(i);
if (value == null)
{
continue;
}
Traverse val = Traverse.Create(value);
string value2 = val.Field("commandKey").GetValue<string>();
string value3 = val.Field("word").GetValue<string>();
if (string.IsNullOrEmpty(value2) || string.IsNullOrEmpty(value3))
{
continue;
}
string value4 = RomajiConfigManager.GetValue(value2);
if (string.IsNullOrEmpty(value4))
{
continue;
}
string text = RomajiConfigManager.FormatRomaji(value4);
if (value3.Contains(text))
{
continue;
}
string value5 = value3 + " " + text;
val.Field("word").SetValue((object)value5);
if (array2 == null || i >= array2.Length || !((Object)(object)array2[i] != (Object)null))
{
continue;
}
GameObject val2 = array2[i];
if ((Object)(object)val2 == (Object)null)
{
continue;
}
Component component = val2.GetComponent("WorldSpaceXiLanHuaSign");
if ((Object)(object)component != (Object)null)
{
object value6 = Traverse.Create((object)component).Field("wordText").GetValue();
if (value6 != null)
{
Traverse.Create(value6).Property("text", (object[])null).SetValue((object)value5);
}
}
}
}
}