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 TrueCC Traduction Competences v0.15.0
TrueCC.Traduction.dll
Decompiled 2 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.Configuration; using HarmonyLib; using On.RoR2; using On.RoR2.UI; using R2API.Utils; using Rewired; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.UI; using RoR2.UI.MainMenu; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace TrueCC.Traduction; public struct CreditRect { public float X; public float Y; public float W; public float H; public CreditRect(float x, float y, float w, float h) { X = x; Y = y; W = w; H = h; } public bool Overlaps(CreditRect r, float gap) { if (X < r.X + r.W + gap && X + W + gap > r.X && Y < r.Y + r.H + gap) { return Y + H + gap > r.Y; } return false; } } public static class CreditLayout { public static bool TryFind(float width, float height, IList<CreditRect> occupied, out CreditRect result) { result = default(CreditRect); if (width < 640f || height < 360f) { return false; } float val = Math.Min(width / 1920f, height / 1080f); val = Math.Max(0.7f, val); float num = Math.Min(460f * val, width - 48f); float num2 = 26f * val; float num3 = 20f * val; float[] array = new float[3] { num3, num3 + num2 + 10f * val, num3 + 2f * (num2 + 10f * val) }; foreach (float y in array) { float[] array2 = new float[3] { (width - num) / 2f, width - num3 - num, num3 }; foreach (float x in array2) { CreditRect creditRect = new CreditRect(x, y, num, num2); bool flag = creditRect.Y + creditRect.H < height; foreach (CreditRect item in occupied) { if (creditRect.Overlaps(item, 8f * val)) { flag = false; break; } } if (flag) { result = creditRect; return true; } } } return false; } } public sealed class KizunaTextBridge : IDisposable { private const string PatchId = "com.truecc.traductioncompetences.kizunatext"; private static KizunaTextBridge current; private readonly Dictionary<string, string> tokens = new Dictionary<string, string>(StringComparer.Ordinal); private readonly TranslationEngine engine; private readonly Func<bool> disabled; private readonly Harmony harmony; private FieldInfo englishField; public KizunaTextBridge(TranslationEngine engine, IEnumerable<TranslationEntry> entries, Func<bool> disabled) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown this.engine = engine; this.disabled = disabled; foreach (TranslationEntry entry in entries) { if (entry.externalScope == "KizunaBook") { tokens.Add(entry.source, entry.token); } } harmony = new Harmony("com.truecc.traductioncompetences.kizunatext"); } public bool Attach(Assembly assembly) { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown if (assembly == null || tokens.Count == 0) { return false; } Type type = assembly.GetType("KizunaMod.KizunaBook", throwOnError: false); Type type2 = assembly.GetType("KizunaMod.KizunaBook+Text", throwOnError: false); if (type == null || type2 == null) { return false; } PropertyInfo property = type2.GetProperty("Now", BindingFlags.Instance | BindingFlags.Public); englishField = type2.GetField("en", BindingFlags.Instance | BindingFlags.Public); MethodInfo method = type.GetMethod("Pick", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); if (property == null || property.PropertyType != typeof(string) || property.GetIndexParameters().Length != 0 || property.GetGetMethod() == null || englishField == null || englishField.FieldType != typeof(string) || method == null || method.ReturnType != typeof(string)) { return false; } if (current != null) { throw new InvalidOperationException("Kizuna text bridge already attached"); } try { current = this; harmony.Patch((MethodBase)property.GetGetMethod(), (HarmonyMethod)null, new HarmonyMethod(typeof(KizunaTextBridge), "TextPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(KizunaTextBridge), "PickPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return true; } catch { Dispose(); throw; } } public string Resolve(string english, string original) { if (disabled() || english == null) { return original; } if (!tokens.TryGetValue(english, out var value)) { return original; } string text = engine.Translate(value, english, disabled: false); if (!(text == english)) { return text; } return original; } private static void TextPostfix(object __instance, ref string __result) { KizunaTextBridge kizunaTextBridge = current; if (kizunaTextBridge == null) { return; } try { __result = kizunaTextBridge.Resolve((string)kizunaTextBridge.englishField.GetValue(__instance), __result); } catch { } } private static void PickPostfix(string __1, ref string __result) { KizunaTextBridge kizunaTextBridge = current; if (kizunaTextBridge == null) { return; } try { __result = kizunaTextBridge.Resolve(__1, __result); } catch { } } public void Dispose() { if (current == this) { harmony.UnpatchSelf(); current = null; } } } public sealed class MenuCredit : MonoBehaviour { private TextMeshProUGUI label; private MainMenuController owner; private float nextCheck; private void Update() { if (Time.unscaledTime < nextCheck) { return; } nextCheck = Time.unscaledTime + 0.5f; try { RefreshCredit(); } catch (Exception ex) { if ((Object)(object)label != (Object)null) { ((Component)label).gameObject.SetActive(false); } ((Behaviour)this).enabled = false; Debug.LogWarning((object)("TrueCC : crédit masqué, accueil non reconnu : " + ex.Message)); } } private void RefreshCredit() { //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) MainMenuController instance = MainMenuController.instance; if (!((Object)(object)instance != (Object)null) || !((Behaviour)instance).isActiveAndEnabled || !((Object)(object)instance.currentMenuScreen == (Object)(object)instance.titleMenuScreen) || !Plugin.ShowCredit.Value || Plugin.DisableTranslation.Value) { if ((Object)(object)label != (Object)null) { ((Component)label).gameObject.SetActive(false); } return; } if ((Object)(object)owner != (Object)(object)instance) { if ((Object)(object)label != (Object)null) { Object.Destroy((Object)(object)((Component)label).gameObject); } label = null; owner = instance; } TMP_Text[] componentsInChildren = ((Component)instance).GetComponentsInChildren<TMP_Text>(true); TMP_Text val = null; Canvas val2 = null; TMP_Text[] array = componentsInChildren; foreach (TMP_Text val3 in array) { if (!((Object)(object)val3 == (Object)(object)label) && ((Component)val3).gameObject.activeInHierarchy) { val2 = ((Component)val3).GetComponentInParent<Canvas>(); if ((Object)(object)val2 != (Object)null) { val = val3; break; } } } if ((Object)(object)val == (Object)null) { if ((Object)(object)label != (Object)null) { ((Component)label).gameObject.SetActive(false); } return; } val2 = val2.rootCanvas; Transform transform = ((Component)val2).transform; RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val4 == (Object)null) { return; } Camera val5 = (((int)val2.renderMode == 0) ? null : val2.worldCamera); List<CreditRect> list = new List<CreditRect>(); TMP_Text[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<TMP_Text>(false); foreach (TMP_Text val6 in componentsInChildren2) { if ((Object)(object)val6 != (Object)(object)label && ((Behaviour)val6).isActiveAndEnabled) { Add(list, val6.rectTransform, val5); } } Selectable[] componentsInChildren3 = ((Component)val2).GetComponentsInChildren<Selectable>(false); foreach (Selectable val7 in componentsInChildren3) { if (((Behaviour)val7).isActiveAndEnabled) { Transform transform2 = ((Component)val7).transform; Add(list, (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null), val5); } } if (!CreditLayout.TryFind(Screen.width, Screen.height, list, out var result)) { if ((Object)(object)label != (Object)null) { ((Component)label).gameObject.SetActive(false); } return; } if ((Object)(object)label == (Object)null) { GameObject val8 = new GameObject("TrueCCTranslationCredit", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI) }); val8.transform.SetParent((Transform)(object)val4, false); label = val8.GetComponent<TextMeshProUGUI>(); ((TMP_Text)label).font = val.font; ((TMP_Text)label).text = "Trad' by Charlie and PurpleMOOD"; ((Graphic)label).color = new Color(0.76f, 0.57f, 1f, 1f); ((Graphic)label).raycastTarget = false; ((TMP_Text)label).alignment = (TextAlignmentOptions)514; ((TMP_Text)label).enableWordWrapping = false; ((TMP_Text)label).overflowMode = (TextOverflowModes)1; } float num = Math.Max(0.01f, val2.scaleFactor); RectTransform rectTransform = ((TMP_Text)label).rectTransform; Vector2 anchoredPosition = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(val4, new Vector2(result.X + result.W / 2f, result.Y + result.H / 2f), val5, ref anchoredPosition); Vector2 anchorMin = (rectTransform.anchorMax = val4.pivot); rectTransform.anchorMin = anchorMin; rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.anchoredPosition = anchoredPosition; rectTransform.sizeDelta = new Vector2(result.W / num, result.H / num); ((TMP_Text)label).fontSize = 18f * Math.Max(0.7f, Math.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f)) / num; ((Component)label).gameObject.SetActive(true); } private static void Add(List<CreditRect> result, RectTransform rect, Camera camera) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { Vector3[] array = (Vector3[])(object)new Vector3[4]; rect.GetWorldCorners(array); float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MinValue; float num4 = float.MinValue; Vector3[] array2 = array; foreach (Vector3 val in array2) { Vector2 val2 = RectTransformUtility.WorldToScreenPoint(camera, val); num = Math.Min(num, val2.x); num2 = Math.Min(num2, val2.y); num3 = Math.Max(num3, val2.x); num4 = Math.Max(num4, val2.y); } if (num3 - num > 0f && num4 - num2 > 0f) { result.Add(new CreditRect(num, num2, num3 - num, num4 - num2)); } } } private void OnDestroy() { if ((Object)(object)label != (Object)null) { Object.Destroy((Object)(object)((Component)label).gameObject); } } } internal sealed class MenuInputGuard : IDisposable { private readonly Func<bool> enabled; private readonly Action<string> diagnostic; private readonly Dictionary<MPEventSystem, MenuInputPolicy> states = new Dictionary<MPEventSystem, MenuInputPolicy>(); private readonly MethodInfo change = typeof(MPEventSystem).GetMethod("OnLastActiveControllerChanged", BindingFlags.Instance | BindingFlags.NonPublic); private int samples; internal MenuInputGuard(Func<bool> enabled, Action<string> diagnostic) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown this.enabled = enabled; this.diagnostic = diagnostic; if (change == null) { throw new MissingMethodException(typeof(MPEventSystem).FullName, "OnLastActiveControllerChanged"); } MPEventSystem.OnLastActiveControllerChanged += new hook_OnLastActiveControllerChanged(Changed); MPEventSystem.Update += new hook_Update(Update); MPEventSystem.OnDestroy += new hook_OnDestroy(Destroyed); } private MenuInputPolicy State(MPEventSystem self) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 if (!states.TryGetValue(self, out var value)) { states.Add(self, value = new MenuInputPolicy()); if ((int)self.currentInputSource == 1) { value.ObserveGamepad(); } } return value; } private static bool InMenu(MPEventSystem self) { if (self.cursorOpenerCount <= 0) { return self.cursorOpenerForGamepadCount > 0; } return true; } private static Controller DesktopActivity(Player player) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (player == null || !Application.isFocused) { return null; } ControllerHelper controllers = ReInput.controllers; if (player.controllers.hasMouse && controllers.Mouse != null) { Mouse mouse = controllers.Mouse; if (!((Controller)mouse).GetAnyButtonDown()) { Vector2 screenPositionDelta = mouse.screenPositionDelta; if (!(((Vector2)(ref screenPositionDelta)).sqrMagnitude >= 0.25f) && Input.mouseScrollDelta.y == 0f) { goto IL_005e; } } return (Controller)(object)mouse; } goto IL_005e; IL_005e: if (player.controllers.hasKeyboard && controllers.Keyboard != null && ((Controller)controllers.Keyboard).GetAnyButtonDown()) { return (Controller)(object)controllers.Keyboard; } return null; } private void Changed(orig_OnLastActiveControllerChanged orig, MPEventSystem self, Player player, Controller controller) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 MenuInputPolicy menuInputPolicy = State(self); if (enabled() && InMenu(self) && (int)self.currentInputSource == 1) { menuInputPolicy.ObserveGamepad(); } if (controller == null) { orig.Invoke(self, player, controller); } else if ((int)controller.type == 2) { menuInputPolicy.ObserveGamepad(); orig.Invoke(self, player, controller); } else if ((int)controller.type != 0 && (int)controller.type != 1) { orig.Invoke(self, player, controller); } else if (menuInputPolicy.AllowDesktop(enabled(), InMenu(self), DesktopActivity(player) != null)) { orig.Invoke(self, player, controller); } else if (samples++ < 3) { diagnostic("Menus : priorité manette conservée, notification clavier/souris sans activité."); } } private void Update(orig_Update orig, MPEventSystem self) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Invalid comparison between Unknown and I4 //IL_0098: Unknown result type (might be due to invalid IL or missing references) MenuInputPolicy menuInputPolicy = State(self); bool flag = enabled() && InMenu(self); if (flag && (int)self.currentInputSource == 1) { menuInputPolicy.ObserveGamepad(); } if (menuInputPolicy.GamepadOwns) { Controller val = (flag ? DesktopActivity(self.player) : null); if (!flag || val != null) { menuInputPolicy.Reset(); if (!flag && !enabled() && InMenu(self) && self.player != null) { Controller lastActiveController = self.player.controllers.GetLastActiveController(); if (lastActiveController != null && ((int)lastActiveController.type == 1 || (int)lastActiveController.type == 0)) { val = lastActiveController; } } if (val != null) { change.Invoke(self, new object[2] { self.player, val }); } } } orig.Invoke(self); } private void Destroyed(orig_OnDestroy orig, MPEventSystem self) { states.Remove(self); orig.Invoke(self); } public void Dispose() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown MPEventSystem.OnLastActiveControllerChanged -= new hook_OnLastActiveControllerChanged(Changed); MPEventSystem.Update -= new hook_Update(Update); MPEventSystem.OnDestroy -= new hook_OnDestroy(Destroyed); states.Clear(); } } internal sealed class MenuInputPolicy { internal bool GamepadOwns { get; private set; } internal void ObserveGamepad() { GamepadOwns = true; } internal void Reset() { GamepadOwns = false; } internal bool AllowDesktop(bool enabled, bool inMenu, bool realDesktopActivity) { if (!enabled || !inMenu) { Reset(); return true; } if (!GamepadOwns) { return true; } if (!realDesktopActivity) { return false; } Reset(); return true; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.truecc.traductioncompetences", "TrueCC — Traduction des compétences", "0.15.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.truecc.traductioncompetences"; public const string Name = "TrueCC — Traduction des compétences"; public const string Version = "0.15.0"; internal static ConfigEntry<bool> DisableTranslation; internal static ConfigEntry<bool> ShowCredit; internal static ConfigEntry<bool> StableMenuInput; private TranslationEngine engine; private TranslationEntry[] entries; private KizunaTextBridge kizuna; private MenuInputGuard menuInput; private int translatedSamples; private int unmatchedSamples; private void Awake() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown string text = "configuration"; try { TranslationSettings translationSettings = TranslationSettings.Bind(((BaseUnityPlugin)this).Config); DisableTranslation = translationSettings.Disable; ShowCredit = translationSettings.Credit; StableMenuInput = translationSettings.Menu; text = "données embarquées"; using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("TrueCC.Traduction.entries.json")) { using StreamReader streamReader = new StreamReader(stream); TranslationSet translationSet = JsonUtility.FromJson<TranslationSet>(streamReader.ReadToEnd()); entries = translationSet.entries; engine = new TranslationEngine(entries); } text = "raccord de langue"; Language.GetLocalizedStringByToken += new hook_GetLocalizedStringByToken(Translate); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Initialisation VF interrompue (" + text + ") : " + ex)); engine = null; return; } try { ModSettingsManager.SetModDescription("Descriptions de compétences en français. Noms conservés. Local uniquement / Client-side only. The first checkbox restores original texts.", "com.truecc.traductioncompetences", "TrueCC — Traduction des compétences"); ConfigEntry<bool> disableTranslation = DisableTranslation; CheckBoxConfig val = new CheckBoxConfig(); ((BaseOptionConfig)val).name = "Pour ce feuj de Logan"; ((BaseOptionConfig)val).description = "Désactive la traduction."; ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(disableTranslation, val), "com.truecc.traductioncompetences", "TrueCC — Traduction des compétences"); ConfigEntry<bool> stableMenuInput = StableMenuInput; CheckBoxConfig val2 = new CheckBoxConfig(); ((BaseOptionConfig)val2).name = "Garder la priorité à la manette"; ((BaseOptionConfig)val2).description = "Dans les menus, relâcher la manette ne réactive pas la souris. Un vrai mouvement, clic ou appui clavier reprend la main. Sans effet sur les commandes en partie."; ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(stableMenuInput, val2), "com.truecc.traductioncompetences", "TrueCC — Traduction des compétences"); ConfigEntry<bool> showCredit = ShowCredit; CheckBoxConfig val3 = new CheckBoxConfig(); ((BaseOptionConfig)val3).name = "Crédit à l'accueil"; ((BaseOptionConfig)val3).description = "Affiche le crédit violet à l'accueil."; ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(showCredit, val3), "com.truecc.traductioncompetences", "TrueCC — Traduction des compétences"); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Options VF indisponibles, moteur de traduction toujours actif : " + ex2)); } try { menuInput = new MenuInputGuard(() => StableMenuInput.Value, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogDebug((object)message); }); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Protection de priorité manette dans les menus : " + StableMenuInput.Value)); } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogError((object)("Protection menus indisponible : " + ex3)); } try { ((Component)this).gameObject.AddComponent<MenuCredit>(); } catch (Exception ex4) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Crédit non affiché : " + ex4.Message)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)(engine.Count + " règles de traduction chargées ; aucun changement de gameplay ou de réseau. Désactivation locale=" + DisableTranslation.Value)); } private void Start() { if (engine == null) { return; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!(assembly.GetType("KizunaMod.KizunaBook", throwOnError: false) == null)) { kizuna = new KizunaTextBridge(engine, entries, () => DisableTranslation.Value); if (kizuna.Attach(assembly)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Raccord local des descriptions Kizuna actif."); } break; } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Kizuna conserve ses textes d'origine : " + ex.Message)); if (kizuna != null) { kizuna.Dispose(); } kizuna = null; } } private string Translate(orig_GetLocalizedStringByToken orig, Language language, string token) { string text = orig.Invoke(language, token); if (engine == null) { return text; } try { string text2 = engine.Resolve(token, text, DisableTranslation.Value, () => (Language.english != null && !object.ReferenceEquals(Language.english, language)) ? orig.Invoke(Language.english, token) : null); if (text2 != text && translatedSamples < 3) { translatedSamples++; ((BaseUnityPlugin)this).Logger.LogDebug((object)("VF appliquée : " + token)); } else if (!DisableTranslation.Value && engine.Knows(token) && unmatchedSamples < 3) { unmatchedSamples++; ((BaseUnityPlugin)this).Logger.LogDebug((object)("VF : token connu, texte courant non reconnu ou déjà traduit : " + token)); } return text2; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Texte d'origine conservé pour " + token + " : " + ex.Message)); return text; } } private void OnDestroy() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Language.GetLocalizedStringByToken -= new hook_GetLocalizedStringByToken(Translate); if (kizuna != null) { kizuna.Dispose(); } if (menuInput != null) { menuInput.Dispose(); } } } [Serializable] public sealed class TranslationSet { public TranslationEntry[] entries; } [Serializable] public sealed class TranslationEntry { public string token; public string source; public string french; public string package; public string version; public string externalScope; public bool rawToken; public bool allowTemplate; public bool suffixOnly; } public sealed class TranslationEngine { private sealed class Rule { internal TranslationEntry Entry; internal Regex Pattern; internal string Prefix; private static string LiteralPattern(string text) { return Regex.Escape(text).Replace("\\r\\n", "\\n").Replace("\\n", "(?:\\r\\n|\\n)"); } internal Rule(TranslationEntry entry) { Entry = entry; StringBuilder stringBuilder = new StringBuilder(entry.suffixOnly ? "" : "\\A"); int num = 0; HashSet<string> hashSet = new HashSet<string>(); foreach (Match item in Regex.Matches(entry.source, "\\{(key[0-9]+|input[0-9]+|[0-9]+)\\}")) { stringBuilder.Append(LiteralPattern(entry.source.Substring(num, item.Index - num))); string value = item.Groups[1].Value; if (hashSet.Add(value)) { stringBuilder.Append("(?<n").Append(value).Append('>') .Append(value.StartsWith("key", StringComparison.Ordinal) ? "(?:Not set|[A-Za-z][A-Za-z0-9]{0,63}(?: \\+ [A-Za-z][A-Za-z0-9]{0,63}){0,7})" : (value.StartsWith("input", StringComparison.Ordinal) ? "(?:[A-Za-z0-9]{1,4}|--|K[./*+=-]|[()\\[\\]`\\\\])" : "[-+]?[0-9]+(?:[.,][0-9]+)?(?:[eE][-+]?[0-9]+)?")) .Append(')'); } else { stringBuilder.Append("\\k<n").Append(value).Append('>'); } num = item.Index + item.Length; } stringBuilder.Append(LiteralPattern(entry.source.Substring(num))).Append("\\z"); Match match2 = Regex.Match(entry.source, "\\{(key[0-9]+|input[0-9]+|[0-9]+)\\}"); Prefix = (match2.Success ? entry.source.Substring(0, match2.Index) : entry.source); int num2 = Prefix.IndexOfAny(new char[2] { '\r', '\n' }); if (num2 >= 0) { Prefix = Prefix.Substring(0, num2); } if (entry.suffixOnly) { Prefix = ""; } Pattern = new Regex(stringBuilder.ToString(), RegexOptions.CultureInvariant, TimeSpan.FromMilliseconds(20.0)); } internal string Translate(Match m) { return Regex.Replace(Entry.french, "\\{(key[0-9]+|input[0-9]+|[0-9]+)\\}", (Match x) => m.Groups["n" + x.Groups[1].Value].Value); } } private const string PlaceholderPattern = "\\{(key[0-9]+|input[0-9]+|[0-9]+)\\}"; private const string ShortcutPattern = "(?:Not set|[A-Za-z][A-Za-z0-9]{0,63}(?: \\+ [A-Za-z][A-Za-z0-9]{0,63}){0,7})"; private const string InputPattern = "(?:[A-Za-z0-9]{1,4}|--|K[./*+=-]|[()\\[\\]`\\\\])"; private readonly Dictionary<string, List<Rule>> rules = new Dictionary<string, List<Rule>>(StringComparer.Ordinal); private readonly List<Rule> rawRules = new List<Rule>(); private readonly Dictionary<string, string> cache = new Dictionary<string, string>(StringComparer.Ordinal); public int Count { get; private set; } public TranslationEngine(IEnumerable<TranslationEntry> entries) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (TranslationEntry entry in entries) { if (entry == null || string.IsNullOrEmpty(entry.token) || string.IsNullOrEmpty(entry.source) || string.IsNullOrEmpty(entry.french)) { throw new ArgumentException("Entrée de traduction incomplète."); } if (entry.allowTemplate && entry.rawToken) { throw new ArgumentException("Un modèle de formatage exige un token nommé."); } if (entry.suffixOnly && (entry.rawToken || entry.allowTemplate || !string.IsNullOrEmpty(entry.externalScope) || !entry.source.StartsWith("\n<color=#d299ff>SCEPTER: ", StringComparison.Ordinal))) { throw new ArgumentException("Suffixe réservé à une amélioration Scepter nommée et exacte."); } if (!hashSet.Add(entry.token + "\n" + entry.source)) { throw new ArgumentException("Traduction dupliquée : " + entry.token); } if (!Placeholders(entry.source).SetEquals(Placeholders(entry.french))) { throw new ArgumentException("Valeurs dynamiques différentes : " + entry.token); } if (entry.rawToken) { rawRules.Add(new Rule(entry)); Count++; continue; } if (!rules.TryGetValue(entry.token, out var value)) { value = new List<Rule>(); rules.Add(entry.token, value); } value.Add(new Rule(entry)); Count++; } } private static HashSet<string> Placeholders(string text) { HashSet<string> hashSet = new HashSet<string>(); foreach (Match item in Regex.Matches(text, "\\{(key[0-9]+|input[0-9]+|[0-9]+)\\}")) { hashSet.Add(item.Groups[1].Value); } return hashSet; } public bool Knows(string token) { if (token != null) { return rules.ContainsKey(token); } return false; } public string Resolve(string token, string original, bool disabled, Func<string> english) { string text = Translate(token, original, disabled); if (disabled || text != original || !Knows(token) || english == null) { return text; } try { string text2 = english(); if (text2 == null || text2 == original) { return original; } string text3 = Translate(token, text2, disabled: false); return (text3 == text2) ? original : text3; } catch { return original; } } public string Translate(string token, string original, bool disabled) { if (disabled || token == null || original == null) { return original; } lock (cache) { if (original.Length > 16384) { return original; } if (!rules.TryGetValue(token, out var value)) { if (token != original || rawRules.Count == 0) { return original; } value = rawRules; } string key = token + "\0" + original; if (cache.TryGetValue(key, out var value2)) { return value2; } value2 = original; foreach (Rule item in value) { try { if (original.StartsWith(item.Prefix, StringComparison.Ordinal)) { if (item.Entry.allowTemplate && string.Equals(original, item.Entry.source, StringComparison.Ordinal)) { value2 = item.Entry.french; break; } Match match = item.Pattern.Match(original); if (match.Success) { value2 = (item.Entry.suffixOnly ? original.Substring(0, match.Index) : "") + item.Translate(match); break; } } } catch (RegexMatchTimeoutException) { return original; } } if (cache.Count >= 512) { cache.Clear(); } cache[key] = value2; return value2; } } } internal sealed class TranslationSettings { internal const string Section = "Translation"; internal const string DisableKey = "DisableTranslation"; internal const string CreditKey = "ShowMenuCredit"; internal const string MenuKey = "StableMenuInput"; internal const string DisableTitle = "Pour ce feuj de Logan"; internal const string DisableDescription = "Désactive la traduction."; internal ConfigEntry<bool> Disable; internal ConfigEntry<bool> Credit; internal ConfigEntry<bool> Menu; internal static TranslationSettings Bind(ConfigFile config) { bool result = false; try { if (File.Exists(config.ConfigFilePath)) { string input = File.ReadAllText(config.ConfigFilePath); Match match = Regex.Match(input, "(?m)^Pour Logan\\s*=\\s*(true|false)\\s*$", RegexOptions.IgnoreCase); if (match.Success) { bool.TryParse(match.Groups[1].Value, out result); } } } catch (IOException) { } catch (UnauthorizedAccessException) { } TranslationSettings translationSettings = new TranslationSettings(); translationSettings.Disable = config.Bind<bool>("Translation", "DisableTranslation", result, "Désactive la traduction."); translationSettings.Menu = config.Bind<bool>("Translation", "StableMenuInput", true, "Conserve la priorité manette dans les menus jusqu’à un vrai mouvement, clic ou appui clavier. Indépendant de la traduction."); translationSettings.Credit = config.Bind<bool>("Translation", "ShowMenuCredit", true, "Affiche le crédit violet à l'accueil quand un emplacement libre est disponible."); return translationSettings; } }