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 ObeliskRU v0.1.0
ObeliskRU.dll
Decompiled 7 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 ObeliskRU { [BepInPlugin("obelisk.ru.localization", "ObeliskRU", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ObeliskRUPlugin : BaseUnityPlugin { private static readonly HashSet<string> AddedLocalizationWordKeys = new HashSet<string>(StringComparer.Ordinal); private const string BlacksmithingGuid = "org.bepinex.plugins.blacksmithing"; private const string CreatureLevelControlGuid = "org.bepinex.plugins.creaturelevelcontrol"; private const string CookingGuid = "org.bepinex.plugins.cooking"; private const string FarmingGuid = "org.bepinex.plugins.farming"; private const string InventorySlotsGuid = "sighsorry.InventorySlots"; private const string ImpactfulSkillsGuid = "MidnightsFX.ImpactfulSkills"; private const string CartographySkillGuid = "advize.CartographySkill"; private const string ValheimClockGuid = "com.orfox.valheimclock"; private const string MoreWorldLocationsAioGuid = "warpalicious.More_World_Locations_AIO"; private const string BalrondAmazingNatureGuid = "balrond.astafaraios.BalrondAmazingNature"; private const string BalrondArsenalRebornGuid = "balrond.astafaraios.ZBalrondArsenalReborn"; private const string BalrondConstructionsGuid = "balrond.astafaraios.BalrondConstructions"; private const string BalrondDualMasteryGuid = "balrond.astafaraios.BalrondDualMastery"; private const string BalrondFurnitureRebornGuid = "balrond.astafaraios.BalrondFurnitureReborn"; private const string BalrondLightkeeperGuid = "balrond.astafaraios.BalrondLightkeeper"; private const string BalrondMonsterMayhemGuid = "balrond.astafaraios.BalrondMonsterMayhem"; private const string BetterArcheryGuid = "ishid4.mods.betterarchery"; private const string OdinHorseGuid = "Raelaziel.OdinHorse"; private const string ValheimArmoryGuid = "MidnightsFX.ValheimArmory"; private const string ValheimGlidersGuid = "Yggdrah.ValheimGliders"; private const string XPortalGuid = "yay.spikehimself.xportal"; private const string CraftyCartsGuid = "Azumatt.CraftyCarts"; private const string CulinaryHorizonsGuid = "Insanity.Culinary_Horizons"; private const string EternalLegendsGuid = "Dreanegade.Eternal_Legends"; private const string HunterLegacyGuid = "Dreanegade.Hunter_Legacy"; private const string MagicSupremacyGuid = "Dreanegade.Magic_Supremacy"; private void Awake() { ApplyBlacksmithingLocalization(); ApplyValheimLocalizationWords(); ApplyCreatureLevelAndLootControlLocalization(); ApplyInventorySlotsSlotLabels(); ApplyCartographySkillTranspiler(); ApplyValheimClockTranspilers(); ApplyBalrondAmazingNatureLocalization(); ApplyBalrondArsenalRebornLocalization(); ApplyBalrondConstructionsLocalization(); ApplyBalrondDualMasteryLocalization(); ApplyBalrondFurnitureRebornLocalization(); ApplyBalrondLightkeeperLocalization(); ApplyBalrondMonsterMayhemLocalization(); ApplyBetterArcheryTranspilers(); ApplyOdinHorseTranspilers(); ApplyXPortalTranspilers(); ApplyMoreWorldLocationsTranspilers(); ApplyPieceManagerCategoryNormalizers(); } private void Start() { ApplyValheimLocalizationWords(); ApplyImpactfulSkillsLocalization(); ApplyValheimArmoryLocalization(); ApplyBalrondAmazingNatureLocalizationWords(); ApplyBalrondArsenalRebornLocalizationWords(); ApplyBalrondConstructionsLocalizationWords(); ApplyBalrondDualMasteryLocalizationWords(); ApplyBalrondDualMasterySkillLocalization(); ApplyBalrondFurnitureRebornLocalizationWords(); ApplyBalrondLightkeeperLocalizationWords(); ApplyBalrondMonsterMayhemLocalizationWords(); ApplyBetterArcheryLocalizationWords(); ApplyValheimGlidersLocalizationWords(); ApplyXPortalLocalizationWords(); ApplyCraftyCartsLocalizationWords(); ApplyMoreWorldLocationsLocalization(); ApplyMoreWorldLocationsTutorials(); } private void ApplyBlacksmithingLocalization() { if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.blacksmithing", out var value)) { return; } if (!((((object)value.Instance).GetType().Assembly.GetType("SkillManager.Skill")?.GetField("skillByName", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) is IDictionary dictionary) || !dictionary.Contains("Blacksmithing")) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Blacksmithing found, but SkillManager data was not available. Block skipped."); return; } object obj = dictionary["Blacksmithing"]; if (obj == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Blacksmithing skill entry was empty. Block skipped."); return; } ApplySkillLocalization(obj, "Name", "Кузнечное дело"); ApplySkillLocalization(obj, "Description", "Повышает прочность созданных доспехов и оружия."); } private void ApplyValheimLocalizationWords() { bool flag = false; if (Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.cooking")) { flag |= AddLocalizationWordVariants(new string[2] { "skill_cooking", "skill_Cooking" }, "Готовка"); flag |= AddLocalizationWordVariants(new string[2] { "skilldesc_cooking", "skilldesc_Cooking" }, "Повышает пользу приготовленной еды: здоровье, выносливость, эйтр и восстановление здоровья."); } if (Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.farming")) { flag |= AddLocalizationWordVariants(new string[2] { "skill_farming", "skill_Farming" }, "Земледелие"); flag |= AddLocalizationWordVariants(new string[2] { "skilldesc_farming", "skilldesc_Farming" }, "Ускоряет рост посевов, повышает урожайность и снижает расход выносливости при посадке и сборе."); } if (flag) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Smoothbrain skill localization words registered."); } } private bool AddLocalizationWordVariants(IEnumerable<string> keys, string russianText) { Type type = Type.GetType("Localization, Assembly-CSharp"); object obj = type?.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? type?.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); MethodInfo methodInfo = type?.GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); if (obj == null || methodInfo == null) { return false; } foreach (string key in keys) { methodInfo.Invoke(obj, new object[2] { key, russianText }); } return true; } private void ApplyBalrondAmazingNatureLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.BalrondAmazingNature", "BalrondNature.BalrondTranslator", "BalrondAmazingNature"); } private void ApplyBalrondAmazingNatureLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.BalrondAmazingNature", "BalrondAmazingNature"); } private void ApplyBalrondArsenalRebornLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.ZBalrondArsenalReborn", "BalrondArsenalReborn.BalrondTranslator", "BalrondArsenalReborn"); } private void ApplyBalrondArsenalRebornLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.ZBalrondArsenalReborn", "BalrondArsenalReborn"); } private void ApplyBalrondConstructionsLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.BalrondConstructions", "BalrondConstructions.BalrondTranslator", "BalrondConstructions"); } private void ApplyBalrondConstructionsLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.BalrondConstructions", "BalrondConstructions"); } private void ApplyBalrondDualMasteryLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.BalrondDualMastery", "BalrondDualWield.BalrondTranslator", "BalrondDualMastery"); } private void ApplyBalrondDualMasteryLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.BalrondDualMastery", "BalrondDualMastery"); } private void ApplyBalrondDualMasterySkillLocalization() { if (Chainloader.PluginInfos.TryGetValue("balrond.astafaraios.BalrondDualMastery", out var value) && (((object)value.Instance).GetType().Assembly.GetType("BalrondDualWield.DualWieldSkills")?.GetField("SkillsById", BindingFlags.Static | BindingFlags.NonPublic))?.GetValue(null) is IDictionary dictionary && dictionary.Contains(874298)) { object obj = dictionary[874298]; if (obj != null) { Type type = obj.GetType(); type.GetField("SkillName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, "Парное оружие"); object obj2 = type.GetField("SkillDef", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj); obj2?.GetType().GetField("m_description", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj2, "Повышает эффективность атак второй рукой при использовании двух одноручных видов оружия."); AddLocalizationWords(new Dictionary<string, string> { ["skill_874298"] = "Парное оружие", ["tag_dualwield_bal"] = "Парное оружие", ["tag_dualwield_bal_tooltip"] = "Повышает эффективность атак второй рукой при использовании двух одноручных видов оружия." }); } } } private void ApplyBalrondFurnitureRebornLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.BalrondFurnitureReborn", "BalrondFurnitureReborn.BalrondTranslator", "BalrondFurnitureReborn"); } private void ApplyBalrondFurnitureRebornLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.BalrondFurnitureReborn", "BalrondFurnitureReborn"); } private void ApplyBalrondLightkeeperLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.BalrondLightkeeper", "LightController.BalrondTranslator", "BalrondLightkeeper"); } private void ApplyBalrondLightkeeperLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.BalrondLightkeeper", "BalrondLightkeeper"); } private void ApplyBalrondMonsterMayhemLocalization() { ApplyBalrondJsonLocalization("balrond.astafaraios.BalrondMonsterMayhem", "BalrondExtendedAnimals.BalrondTranslator", "BalrondMonsterMayhem"); } private void ApplyBalrondMonsterMayhemLocalizationWords() { ApplyBalrondJsonLocalizationWords("balrond.astafaraios.BalrondMonsterMayhem", "BalrondMonsterMayhem"); } private void ApplyBetterArcheryLocalizationWords() { if (Chainloader.PluginInfos.ContainsKey("ishid4.mods.betterarchery")) { string path = Path.Combine(GetPluginDirectory(), "BetterArchery", "ishid4_translations.json"); if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"BetterArchery Russian localization file was not found. Block skipped."); return; } Dictionary<string, string> dictionary = LoadFlatJsonDictionary(path); AddLocalizationWords(dictionary); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"BetterArchery Russian localization words registered: {dictionary.Count}."); } } private void ApplyBalrondJsonLocalizationWords(string pluginGuid, string folderName) { if (Chainloader.PluginInfos.ContainsKey(pluginGuid)) { string path = Path.Combine(GetPluginDirectory(), folderName, "Russian.json"); if (File.Exists(path)) { Dictionary<string, string> words = LoadFlatJsonDictionary(path); AddLocalizationWords(words); } } } private void ApplyValheimGlidersLocalizationWords() { if (Chainloader.PluginInfos.ContainsKey("Yggdrah.ValheimGliders")) { string path = Path.Combine(GetPluginDirectory(), "ValheimGliders", "Russian.json"); if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"ValheimGliders Russian localization file was not found. Block skipped."); return; } Dictionary<string, string> dictionary = LoadFlatJsonDictionary(path); AddLocalizationWords(dictionary); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"ValheimGliders Russian localization words registered: {dictionary.Count}."); } } private void ApplyXPortalLocalizationWords() { if (Chainloader.PluginInfos.ContainsKey("yay.spikehimself.xportal")) { string path = Path.Combine(GetPluginDirectory(), "XPortal", "Russian.json"); if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"XPortal Russian localization file was not found. Block skipped."); return; } Dictionary<string, string> dictionary = LoadFlatJsonDictionary(path); AddLocalizationWords(dictionary); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"XPortal Russian localization words registered: {dictionary.Count}."); } } private void ApplyCraftyCartsLocalizationWords() { if (Chainloader.PluginInfos.TryGetValue("Azumatt.CraftyCarts", out var value)) { Dictionary<string, string> words = new Dictionary<string, string>(StringComparer.Ordinal) { ["msg_cartupgraded"] = "$1 улучшена", ["msg_cantupgrade"] = "$1 нельзя улучшить", ["msg_maxlevel"] = "$1 уже максимального уровня", ["piece_upgradecart"] = "Улучшение телеги", ["piece_upgradecart_description"] = "Улучшает телегу до более высокого уровня.", ["piecemanager_cat_craftycarts"] = "Телеги-мастерские" }; AddLocalizationWords(words); int num = ApplyPieceManagerLocalizeKeyTranslations(((object)value.Instance).GetType().Assembly, words); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"CraftyCarts Russian localization words registered. LocalizeKeys updated: {num}."); } } private static int ApplyPieceManagerLocalizeKeyTranslations(Assembly assembly, Dictionary<string, string> words) { Type? type = assembly.GetType("PieceManager.LocalizeKey"); FieldInfo fieldInfo = type?.GetField("keys", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo methodInfo = type?.GetMethod("Russian", BindingFlags.Instance | BindingFlags.Public); FieldInfo fieldInfo2 = type?.GetField("Key", BindingFlags.Instance | BindingFlags.Public); if (!(fieldInfo?.GetValue(null) is IEnumerable enumerable) || methodInfo == null || fieldInfo2 == null) { return 0; } int num = 0; foreach (object item in enumerable) { if (fieldInfo2.GetValue(item) is string key && words.TryGetValue(key, out string value)) { methodInfo.Invoke(item, new object[1] { value }); num++; } } return num; } private void ApplyBalrondJsonLocalization(string pluginGuid, string translatorTypeName, string folderName) { if (Chainloader.PluginInfos.TryGetValue(pluginGuid, out var value)) { string path = Path.Combine(GetPluginDirectory(), folderName, "Russian.json"); if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(folderName + " Russian localization file was not found. Block skipped.")); return; } if (!((((object)value.Instance).GetType().Assembly.GetType(translatorTypeName)?.GetField("translations", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) is IDictionary dictionary)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(folderName + " translator dictionary was not recognized. Block skipped.")); return; } Dictionary<string, string> dictionary2 = (Dictionary<string, string>)(dictionary["Russian"] = LoadFlatJsonDictionary(path)); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"{folderName} Russian localization registered: {dictionary2.Count} words."); } } private static Dictionary<string, string> LoadFlatJsonDictionary(string path) { return ParseFlatJsonDictionary(File.ReadAllText(path)); } private static Dictionary<string, string> ParseFlatJsonDictionary(string json) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); int index = 0; SkipJsonWhitespace(json, ref index); ExpectJsonChar(json, ref index, '{'); while (true) { SkipJsonWhitespace(json, ref index); if (TryReadJsonChar(json, ref index, '}')) { break; } string key = ReadJsonString(json, ref index); SkipJsonWhitespace(json, ref index); ExpectJsonChar(json, ref index, ':'); SkipJsonWhitespace(json, ref index); string value = ReadJsonString(json, ref index); dictionary[key] = value; SkipJsonWhitespace(json, ref index); if (!TryReadJsonChar(json, ref index, ',')) { ExpectJsonChar(json, ref index, '}'); break; } } return dictionary; } private static void SkipJsonWhitespace(string json, ref int index) { while (index < json.Length && char.IsWhiteSpace(json[index])) { index++; } } private static bool TryReadJsonChar(string json, ref int index, char expected) { if (index < json.Length && json[index] == expected) { index++; return true; } return false; } private static void ExpectJsonChar(string json, ref int index, char expected) { if (!TryReadJsonChar(json, ref index, expected)) { throw new FormatException($"Expected JSON character '{expected}' at position {index}."); } } private static string ReadJsonString(string json, ref int index) { ExpectJsonChar(json, ref index, '"'); StringBuilder stringBuilder = new StringBuilder(); while (index < json.Length) { char c = json[index++]; switch (c) { case '"': return stringBuilder.ToString(); default: stringBuilder.Append(c); break; case '\\': { if (index >= json.Length) { throw new FormatException("Unexpected end of JSON escape sequence."); } char c2 = json[index++]; switch (c2) { case '"': case '/': case '\\': stringBuilder.Append(c2); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'n': stringBuilder.Append('\n'); break; case 'r': stringBuilder.Append('\r'); break; case 't': stringBuilder.Append('\t'); break; case 'u': { if (index + 4 > json.Length) { throw new FormatException("Unexpected end of JSON unicode escape sequence."); } string value = json.Substring(index, 4); stringBuilder.Append((char)Convert.ToInt32(value, 16)); index += 4; break; } default: throw new FormatException($"Unsupported JSON escape sequence '\\{c2}' at position {index - 1}."); } break; } } } throw new FormatException("Unterminated JSON string."); } private void AddLocalizationWords(Dictionary<string, string> words) { Type type = Type.GetType("Localization, Assembly-CSharp"); object obj = type?.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? type?.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); if (obj == null) { return; } if ((type?.GetField("m_translations", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj) is IDictionary dictionary) { { foreach (KeyValuePair<string, string> word in words) { dictionary[word.Key] = word.Value; AddedLocalizationWordKeys.Add(word.Key); } return; } } MethodInfo methodInfo = type?.GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); if (methodInfo == null) { return; } foreach (KeyValuePair<string, string> word2 in words) { if (AddedLocalizationWordKeys.Add(word2.Key)) { methodInfo.Invoke(obj, new object[2] { word2.Key, word2.Value }); } } } private void ApplyBetterArcheryTranspilers() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown if (!Chainloader.PluginInfos.TryGetValue("ishid4.mods.betterarchery", out var value)) { return; } MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("TranspileBetterArcheryStrings", BindingFlags.Static | BindingFlags.NonPublic); if (method == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"BetterArchery transpiler was not available. Hardcoded string block skipped."); return; } string[] obj = new string[4] { "BetterArchery.ModifyOnSpawned", "BetterArchery.Character_OnDamaged_Patch", "BetterArchery.Humanoid_OnDamaged_Patch", "BetterArchery.TerminalAwake_Patch" }; Harmony harmony = new Harmony("obelisk.ru.localization.betterarchery"); int num = 0; string[] array = obj; foreach (string name in array) { Type type = ((object)value.Instance).GetType().Assembly.GetType(name); if (!(type == null)) { num += PatchBetterArcheryTypeStrings(type, harmony, method); Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type2 in nestedTypes) { num += PatchBetterArcheryTypeStrings(type2, harmony, method); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"BetterArchery hardcoded string transpilers applied: {num} methods."); } private static int PatchBetterArcheryTypeStrings(Type type, Harmony harmony, MethodInfo transpiler) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown int num = 0; MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && methodInfo.GetMethodBody() != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(transpiler), (HarmonyMethod)null, (HarmonyMethod)null); num++; } } return num; } private static IEnumerable<CodeInstruction> TranspileBetterArcheryStrings(IEnumerable<CodeInstruction> instructions) { Dictionary<string, string> replacements = new Dictionary<string, string>(StringComparer.Ordinal) { ["Thank you for using this mod! Don't forget to change configurations to get your own taste!"] = "Спасибо за использование BetterArchery. Настройте мод под свой стиль игры в конфигурации.", ["Welcome to BetterArchery"] = "Добро пожаловать в BetterArchery", ["<size=25>Sneak attack for {0}X ({1}) damage!</size>"] = "<size=25>Скрытая атака: {0}x ({1}) урона!</size>", ["Syntax: ba [action]"] = "Синтаксис: ba [действие]", ["Better Archery Reloaded."] = "BetterArchery перезагружен." }; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldstr && instruction.operand is string key && replacements.TryGetValue(key, out string value)) { instruction.operand = value; } yield return instruction; } } private void ApplyOdinHorseTranspilers() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown if (!Chainloader.PluginInfos.TryGetValue("Raelaziel.OdinHorse", out var value)) { return; } MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("TranspileOdinHorseStrings", BindingFlags.Static | BindingFlags.NonPublic); if (method == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"OdinHorse transpiler was not available. Hardcoded string block skipped."); return; } Type type = ((object)value.Instance).GetType().Assembly.GetType("OdinHorse.OdinHorse"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"OdinHorse type was not recognized. Hardcoded string block skipped."); return; } Harmony harmony = new Harmony("obelisk.ru.localization.odinhorse"); int num = 0; Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type2 in nestedTypes) { string name = type2.Name; if (name.IndexOf("AddTextForRemovalOfArmorTameableGetHoverTextPatch", StringComparison.Ordinal) >= 0 || name.IndexOf("SaddlebagHoverTextPatch", StringComparison.Ordinal) >= 0) { num += PatchDeclaredMethods(type2, harmony, method); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"OdinHorse hardcoded string transpilers applied: {num} methods."); } private static int PatchDeclaredMethods(Type type, Harmony harmony, MethodInfo transpiler) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown int num = 0; MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && methodInfo.GetMethodBody() != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(transpiler), (HarmonyMethod)null, (HarmonyMethod)null); num++; } } return num; } private static IEnumerable<CodeInstruction> TranspileOdinHorseStrings(IEnumerable<CodeInstruction> instructions) { Dictionary<string, string> replacements = new Dictionary<string, string>(StringComparer.Ordinal) { ["Remove Armor"] = "Снять броню", ["Wait Here"] = "Ждать здесь", ["Resume"] = "Следовать", ["Open Saddlebags"] = "Открыть седельные сумки" }; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldstr && instruction.operand is string key && replacements.TryGetValue(key, out string value)) { instruction.operand = value; } yield return instruction; } } private void ApplyPieceManagerCategoryNormalizers() { ApplyPieceManagerCategoryNormalizer("Azumatt.CraftyCarts", "CraftyCarts"); ApplyPieceManagerCategoryNormalizer("Insanity.Culinary_Horizons", "Culinary Horizons"); ApplyPieceManagerCategoryNormalizer("Dreanegade.Eternal_Legends", "Eternal Legends"); ApplyPieceManagerCategoryNormalizer("Dreanegade.Hunter_Legacy", "Hunter Legacy"); ApplyPieceManagerCategoryNormalizer("Dreanegade.Magic_Supremacy", "Magic Supremacy"); } private void ApplyPieceManagerCategoryNormalizer(string pluginGuid, string logName) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown if (Chainloader.PluginInfos.TryGetValue(pluginGuid, out var value)) { Assembly assembly = ((object)value.Instance).GetType().Assembly; MethodInfo methodInfo = assembly.GetType("PieceManager.PiecePrefabManager")?.GetMethod("GetCategory", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("NormalizePieceManagerCategoryArgument", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo == null || method == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(logName + " PieceManager category method was not recognized. Category block skipped.")); return; } new Harmony("obelisk.ru.localization.categories." + pluginGuid).Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); int num = RewriteRegisteredBuildPieceCategoryCustoms(assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"{logName} build categories normalized. Registered pieces updated: {num}."); } } private static void NormalizePieceManagerCategoryArgument(ref string name) { name = NormalizePieceManagerCategoryName(name); } private static int RewriteRegisteredBuildPieceCategoryCustoms(Assembly assembly) { Type? type = assembly.GetType("PieceManager.BuildPiece"); FieldInfo fieldInfo = type?.GetField("registeredPieces", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo fieldInfo2 = type?.GetField("Category", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(fieldInfo?.GetValue(null) is IEnumerable enumerable) || fieldInfo2 == null) { return 0; } int num = 0; foreach (object item in enumerable) { object value = fieldInfo2.GetValue(item); FieldInfo fieldInfo3 = value?.GetType().GetField("custom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo3?.GetValue(value) is string text) { string text2 = NormalizePieceManagerCategoryName(text); if (!(text2 == text)) { fieldInfo3.SetValue(value, text2); num++; } } } return num; } private static string NormalizePieceManagerCategoryName(string name) { return name switch { "Crafty Carts" => "Телеги-мастерские", "Distant Origins" => "Древние истоки", "Distant Origins Decor" => "Декор древних истоков", "Culinary Horizons" => "Кулинарные горизонты", _ => name, }; } private void ApplyXPortalTranspilers() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown if (Chainloader.PluginInfos.TryGetValue("yay.spikehimself.xportal", out var value)) { Assembly assembly = ((object)value.Instance).GetType().Assembly; MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("TranspileXPortalStrings", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo methodInfo = assembly.GetType("XPortal.XPortal")?.GetMethod("OnPrePortalHover", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo methodInfo2 = assembly.GetType("XPortal.Patches.TeleportWorld_GetHoverText")?.GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (method == null || methodInfo == null || methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"XPortal methods were not recognized. Hardcoded string block skipped."); return; } Harmony val = new Harmony("obelisk.ru.localization.xportal"); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"XPortal hardcoded string transpilers applied."); } } private static IEnumerable<CodeInstruction> TranspileXPortalStrings(IEnumerable<CodeInstruction> instructions) { Dictionary<string, string> replacements = new Dictionary<string, string>(StringComparer.Ordinal) { ["Fetching portal info..."] = "Получение сведений о портале...", ["This portal doesn't actually appear to exist. Heimdallr sees you..."] = "Похоже, этого портала на самом деле не существует. Хеймдалль видит тебя..." }; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldstr && instruction.operand is string key && replacements.TryGetValue(key, out string value)) { instruction.operand = value; } yield return instruction; } } private void ApplyImpactfulSkillsLocalization() { ApplyJotunnJsonLocalization("MidnightsFX.ImpactfulSkills", "ImpactfulSkills", "ImpactfulSkills"); } private void ApplyValheimArmoryLocalization() { ApplyJotunnJsonLocalization("MidnightsFX.ValheimArmory", "ValheimArmory", "ValheimArmory"); } private void ApplyJotunnJsonLocalization(string pluginGuid, string folderName, string logName) { if (Chainloader.PluginInfos.ContainsKey(pluginGuid)) { string path = Path.Combine(GetPluginDirectory(), folderName, "Russian.json"); if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(logName + " Russian localization file was not found. Block skipped.")); return; } Dictionary<string, string> dictionary = LoadFlatJsonDictionary(path); AddLocalizationWords(dictionary); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"{logName} Russian localization words registered: {dictionary.Count}."); } } private void ApplyValheimClockTranspilers() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown if (Chainloader.PluginInfos.TryGetValue("com.orfox.valheimclock", out var value)) { Type? type = ((object)value.Instance).GetType().Assembly.GetType("ClockMod.MinimapPatches"); MethodInfo methodInfo = type?.GetMethod("Update_Postfix", BindingFlags.Static | BindingFlags.Public); MethodInfo methodInfo2 = type?.GetMethod("TranslateWeather", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("TranspileValheimClockDay", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method2 = typeof(ObeliskRUPlugin).GetMethod("TranspileValheimClockWeather", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo == null || methodInfo2 == null || method == null || method2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"ValheimClock methods were not recognized. Clock block skipped."); return; } Harmony val = new Harmony("obelisk.ru.localization.valheimclock"); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"ValheimClock Russian clock transpilers applied."); } } private static IEnumerable<CodeInstruction> TranspileValheimClockDay(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldstr && instruction.operand as string == "<size={0}>Day {1}{2}{3}</size>{4}") { instruction.operand = "<size={0}>День {1}{2}{3}</size>{4}"; } yield return instruction; } } private static IEnumerable<CodeInstruction> TranspileValheimClockWeather(IEnumerable<CodeInstruction> instructions) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal) { ["Clear Skies"] = "Ясно", ["Light Rain"] = "Лёгкий дождь", ["Raining"] = "Дождь", ["Thunderstorm"] = "Гроза", ["Snowing"] = "Снег", ["Warm Snow"] = "Тёплый снег", ["Warm Snowstorm"] = "Тёплая метель", ["Blizzard"] = "Метель", ["Ash Rain"] = "Пепельный дождь", ["Ash Clear"] = "Ясно в Пепельных землях", ["Cinder Rain"] = "Дождь из углей", ["Meteor Shower"] = "Метеоритный дождь", ["Ashlands Fog"] = "Туман Пепельных земель", ["Ashlands Storm"] = "Буря Пепельных земель", ["Ashlands Seastorm"] = "Морская буря Пепельных земель", ["Mistlands Dark"] = "Тьма Туманных земель", ["Mislands Clear"] = "Ясно в Туманных землях", ["Mistlands Rain"] = "Дождь в Туманных землях", ["Mistlands Thunder"] = "Гроза в Туманных землях", ["Twilight Clear"] = "Сумеречное ясное небо", ["Twilight Snow"] = "Сумеречный снег", ["Twilight Snowstorm"] = "Сумеречная метель", ["Black Forest Fog"] = "Туман Чёрного леса", ["Swamp Rain"] = "Болотный дождь", ["Freezing"] = "Мороз", ["Sunken Crypt"] = "Затопленный склеп", ["Crypt"] = "Склеп", ["Crypt Hildir"] = "Склеп Хильдир", ["Infected Mine"] = "Заражённая шахта", ["Night Frost"] = "Ночной мороз", ["Queen's Jam"] = "Морок Королевы", ["Eikthyr's Thunderstorm"] = "Гроза Эйктюра", ["The Elder's Haze"] = "Мгла Древнего", ["Bonemass' Downpour"] = "Ливень Массы Костей", ["Moder's Vortex"] = "Вихрь Моудер", ["Yagluth's Magic Blizzard"] = "Магическая метель Яглута", ["Plains Fog"] = "Туман равнин", ["Ocean Fog"] = "Морской туман", ["Fog"] = "Туман" }; List<CodeInstruction> list = instructions.ToList(); for (int i = 0; i < list.Count - 1; i++) { if (!(list[i].opcode != OpCodes.Ldstr) && !(list[i + 1].opcode != OpCodes.Ret) && list[i].operand is string key && dictionary.TryGetValue(key, out var value)) { list[i].operand = value; } } return list; } private void ApplyCartographySkillTranspiler() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (Chainloader.PluginInfos.TryGetValue("advize.CartographySkill", out var value)) { MethodInfo methodInfo = ((object)value.Instance).GetType().Assembly.GetType("Advize_CartographySkill.CartographySkill")?.GetMethod("UpdateLocalization", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("TranspileCartographySkillLocalization", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo == null || method == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"CartographySkill localization method was not recognized. Cartography block skipped."); return; } new Harmony("obelisk.ru.localization.cartographyskill").Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"CartographySkill Russian localization transpiler applied."); } } private static IEnumerable<CodeInstruction> TranspileCartographySkillLocalization(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo && methodInfo.DeclaringType?.FullName == "Advize_CartographySkill.ModConfig") { if (methodInfo.Name == "get_SkillDescription") { yield return new CodeInstruction(OpCodes.Pop, (object)null); yield return new CodeInstruction(OpCodes.Ldstr, (object)"Увеличивает радиус разведки карты."); continue; } if (methodInfo.Name == "get_SkillName") { yield return new CodeInstruction(OpCodes.Pop, (object)null); yield return new CodeInstruction(OpCodes.Ldstr, (object)"Картография"); continue; } } yield return instruction; } } private void ApplyMoreWorldLocationsTranspilers() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown Assembly loadedOrLoadPluginAssembly = GetLoadedOrLoadPluginAssembly("warpalicious.More_World_Locations_AIO", "More_World_Locations_AIO", "More_World_Locations_AIO.dll"); if (!(loadedOrLoadPluginAssembly == null)) { Type type = loadedOrLoadPluginAssembly.GetType("More_World_Locations_AIO.PortInit"); Type? type2 = loadedOrLoadPluginAssembly.GetType("More_World_Locations_AIO.MWLLocalizations"); MethodInfo methodInfo = type?.GetMethod("SetupManifests", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo methodInfo2 = type2?.GetMethod("Load", BindingFlags.Static | BindingFlags.Public); MethodInfo method = typeof(ObeliskRUPlugin).GetMethod("TranspileMoreWorldLocationsManifests", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method2 = typeof(ObeliskRUPlugin).GetMethod("TranspileMoreWorldLocationsLocalizationLoad", BindingFlags.Static | BindingFlags.NonPublic); if (type == null || methodInfo == null || methodInfo2 == null || method == null || method2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"More World Locations AIO localization methods were not recognized. MWL block skipped."); return; } Harmony val = new Harmony("obelisk.ru.localization.moreworldlocations"); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null); int num = PatchMoreWorldLocationsManifestCreationMethods(type, val, method); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"More World Locations AIO transpilers applied. Manifest methods patched: {num}."); } } private static int PatchMoreWorldLocationsManifestCreationMethods(Type portInitType, Harmony harmony, MethodInfo manifestTranspiler) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown int num = 0; Type[] nestedTypes = portInitType.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < nestedTypes.Length; i++) { MethodInfo[] methods = nestedTypes[i].GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && methodInfo.Name.IndexOf("SetupManifests", StringComparison.Ordinal) >= 0) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(manifestTranspiler), (HarmonyMethod)null, (HarmonyMethod)null); num++; } } } return num; } private static Assembly? GetLoadedOrLoadPluginAssembly(string pluginGuid, string assemblyName, string dllName) { Assembly loadedPluginAssembly = GetLoadedPluginAssembly(pluginGuid, assemblyName); if (loadedPluginAssembly != null) { return loadedPluginAssembly; } try { string text = Directory.GetFiles(Paths.PluginPath, dllName, SearchOption.AllDirectories).FirstOrDefault((string file) => file.IndexOf("More_World_Locations_AIO", StringComparison.OrdinalIgnoreCase) >= 0); return (text == null) ? null : Assembly.LoadFrom(text); } catch { return null; } } private static Assembly? GetLoadedPluginAssembly(string pluginGuid, string assemblyName) { if (Chainloader.PluginInfos.TryGetValue(pluginGuid, out var value) && (Object)(object)value.Instance != (Object)null) { return ((object)value.Instance).GetType().Assembly; } return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => string.Equals(assembly.GetName().Name, assemblyName, StringComparison.Ordinal)); } private static IEnumerable<CodeInstruction> TranspileMoreWorldLocationsManifests(IEnumerable<CodeInstruction> instructions) { Dictionary<string, string> manifests = new Dictionary<string, string>(StringComparer.Ordinal) { ["Wooden Shipment"] = "Грузовой деревянный сундук", ["Barrel Shipment"] = "Грузовая бочка", ["Fine Shipment"] = "Грузовой добротный сундук", ["Fuling Shipment"] = "Грузовой сундук фулингов", ["Dvergr Shipment"] = "Грузовой сундук двергров" }; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldstr && instruction.operand is string key && manifests.TryGetValue(key, out string value)) { instruction.operand = value; } yield return instruction; } } private static IEnumerable<CodeInstruction> TranspileMoreWorldLocationsLocalizationLoad(IEnumerable<CodeInstruction> instructions) { MethodInfo addRussianLocalization = typeof(ObeliskRUPlugin).GetMethod("AddMoreWorldLocationsRussianLocalization", BindingFlags.Static | BindingFlags.NonPublic); bool inserted = false; foreach (CodeInstruction instruction in instructions) { yield return instruction; if (!inserted && !(addRussianLocalization == null) && !(instruction.opcode != OpCodes.Callvirt) && instruction.operand is MethodInfo { Name: "AddYamlFile" }) { yield return new CodeInstruction(OpCodes.Call, (object)addRussianLocalization); inserted = true; } } } private static void AddMoreWorldLocationsRussianLocalization() { string directoryName = Path.GetDirectoryName(typeof(ObeliskRUPlugin).Assembly.Location); if (directoryName == null) { return; } string path = Path.Combine(directoryName, "More_World_Locations_AIO", "warpalicious.More_World_Locations_Localization.Russian.yml"); if (!File.Exists(path)) { Console.WriteLine("[ObeliskRU] More World Locations AIO Russian localization file was not found. Block skipped."); return; } Type? type = Type.GetType("Jotunn.Managers.LocalizationManager, Jotunn"); object obj = type?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object obj2 = type?.GetMethod("GetLocalization", BindingFlags.Instance | BindingFlags.Public)?.Invoke(obj, null); MethodInfo methodInfo = obj2?.GetType().GetMethod("AddYamlFile", new Type[2] { typeof(string), typeof(string) }); if (methodInfo == null) { Console.WriteLine("[ObeliskRU] Jotunn localization API was not available. More World Locations AIO block skipped."); return; } string text = File.ReadAllText(path); methodInfo.Invoke(obj2, new object[2] { "Russian", text }); Console.WriteLine("[ObeliskRU] More World Locations AIO Russian localization loaded."); } private void ApplyMoreWorldLocationsLocalization() { if (Chainloader.PluginInfos.ContainsKey("warpalicious.More_World_Locations_AIO") || !AppDomain.CurrentDomain.GetAssemblies().All((Assembly assembly) => assembly.GetName().Name != "More_World_Locations_AIO")) { AddMoreWorldLocationsRussianLocalization(); } } private void ApplySkillLocalization(object skill, string fieldName, string russianText) { object obj = skill.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(skill); MethodInfo methodInfo = obj?.GetType().GetMethod("Russian", BindingFlags.Instance | BindingFlags.Public); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not register Blacksmithing " + fieldName + " localization. Block skipped.")); return; } methodInfo.Invoke(obj, new object[1] { russianText }); } private void ApplyCreatureLevelAndLootControlLocalization() { if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.creaturelevelcontrol", out var value)) { return; } string path = Path.Combine(GetPluginDirectory(), "CreatureLevelAndLootControl", "Russian.yml"); if (!File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Creature Level and Loot Control localization file was not found. Block skipped."); return; } Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = assembly.GetType("CreatureLevelControl.LocalizationWrapper"); Type type2 = assembly.GetType("YamlDotNet.Serialization.DeserializerBuilder"); if (type == null || type2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Creature Level and Loot Control localization types were not available. Block skipped."); return; } object obj = Activator.CreateInstance(type2, nonPublic: true); object obj2 = type2.GetMethod("Build", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(obj, null); MethodInfo methodInfo = obj2?.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo method) { if (method.Name != "Deserialize" || method.IsGenericMethod) { return false; } ParameterInfo[] parameters = method.GetParameters(); return parameters.Length == 2 && parameters[0].ParameterType == typeof(TextReader) && parameters[1].ParameterType == typeof(Type); }); FieldInfo field = type.GetField("instance", BindingFlags.Static | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("language", BindingFlags.Instance | BindingFlags.NonPublic); if (methodInfo == null || field == null || field2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Creature Level and Loot Control localization internals were not available. Block skipped."); return; } using StreamReader streamReader = new StreamReader(path); object obj3 = methodInfo.Invoke(obj2, new object[2] { streamReader, type }); if (obj3 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Creature Level and Loot Control localization file could not be read. Block skipped."); return; } field2.SetValue(obj3, "Russian"); field.SetValue(null, obj3); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Creature Level and Loot Control Russian localization loaded."); } private void ApplyInventorySlotsSlotLabels() { if (!Chainloader.PluginInfos.TryGetValue("sighsorry.InventorySlots", out var value)) { return; } Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = assembly.GetType("InventorySlots.InventorySlotsPlugin"); Type type2 = assembly.GetType("InventorySlots.SlotDefinition"); Type type3 = assembly.GetType("InventorySlots.SlotKind"); if (!((type?.GetProperty("SlotDefinitions", BindingFlags.Static | BindingFlags.NonPublic))?.GetValue(null) is IList list) || type2 == null || type3 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"InventorySlots slot definitions were not available. Slot label block skipped."); return; } FieldInfo field = type2.GetField("_accepts", BindingFlags.Instance | BindingFlags.NonPublic); PropertyInfo property = type2.GetProperty("Id", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property2 = type2.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property3 = type2.GetProperty("Kind", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property4 = type2.GetProperty("QuickSlotIndex", BindingFlags.Instance | BindingFlags.Public); if (field == null || property == null || property2 == null || property3 == null || property4 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"InventorySlots slot definition shape was not recognized. Slot label block skipped."); return; } ConstructorInfo constructor = type2.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[5] { typeof(string), typeof(string), type3, field.FieldType, typeof(int) }, null); if (constructor == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"InventorySlots slot definition constructor was not available. Slot label block skipped."); return; } Dictionary<string, (string, string)> dictionary = new Dictionary<string, (string, string)>(StringComparer.OrdinalIgnoreCase) { ["helmet"] = ("Helmet", "Шлем"), ["chest"] = ("Chest", "Нагрудник"), ["legs"] = ("Legs", "Поножи"), ["cape"] = ("Cape", "Плащ"), ["utility"] = ("Utility", "Аксессуар"), ["trinket"] = ("Trinket", "Талисман"), ["circlet"] = ("Circlet", "Венец"), ["wishbone"] = ("Wishbone", "Дужка"), ["demister"] = ("Demister", "Висп"), ["jewelcrafting.necklace"] = ("Necklace", "Ожерелье"), ["jewelcrafting.ring"] = ("Ring", "Кольцо"), ["smoothbrainbackpacks.backpack"] = ("Backpack", "Рюкзак"), ["adventurebackpacks.backpack"] = ("Backpack", "Рюкзак"), ["rustybags.bag"] = ("Bag", "Сумка"), ["rustybags.quiver"] = ("Quiver", "Колчан"), ["magicsupremacy.belt"] = ("MagicBelt", "Магический пояс") }; int num = 0; for (int i = 0; i < list.Count; i++) { object obj = list[i]; if (obj == null) { continue; } string text = property.GetValue(obj) as string; string text2 = property2.GetValue(obj) as string; if (text != null && text2 != null && dictionary.TryGetValue(text, out var value2) && string.Equals(text2, value2.Item1, StringComparison.OrdinalIgnoreCase)) { object value3 = property3.GetValue(obj); object value4 = field.GetValue(obj); object value5 = property4.GetValue(obj); if (value3 != null && value4 != null && value5 != null) { list[i] = constructor.Invoke(new object[5] { text, value2.Item2, value3, value4, value5 }); num++; } } } if (num > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"InventorySlots Russian slot labels applied: {num}."); } } private void ApplyMoreWorldLocationsTutorials() { Assembly loadedPluginAssembly = GetLoadedPluginAssembly("warpalicious.More_World_Locations_AIO", "More_World_Locations_AIO"); if (loadedPluginAssembly == null) { return; } Type? type = loadedPluginAssembly.GetType("More_World_Locations_AIO.tutorials.PortTutorial"); FieldInfo fieldInfo = type?.GetField("tutorials", BindingFlags.Static | BindingFlags.NonPublic); ConstructorInfo constructorInfo = type?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(List<string>) }, null); if (!(fieldInfo?.GetValue(null) is IList list) || constructorInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"More World Locations AIO tutorial data was not available. Tutorial block skipped."); return; } string path = Path.Combine(GetPluginDirectory(), "More_World_Locations_AIO", "Tutorials"); (string, string)[] array = new(string, string)[6] { ("Введение", "introduction.md"), ("Порт", "port.md"), ("Накладная", "manifest.md"), ("Отправка", "shipment.md"), ("Доставка", "delivery.md"), ("Телепорт", "teleport.md") }; (string, string)[] array2 = array; for (int i = 0; i < array2.Length; i++) { string item = array2[i].Item2; if (!File.Exists(Path.Combine(path, item))) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"More World Locations AIO tutorial file was not found. Tutorial block skipped."); return; } } list.Clear(); array2 = array; for (int i = 0; i < array2.Length; i++) { (string, string) tuple = array2[i]; string item2 = tuple.Item1; string item3 = tuple.Item2; string path2 = Path.Combine(path, item3); constructorInfo.Invoke(new object[2] { item2, new List<string>(File.ReadAllLines(path2)) }); } } private string GetPluginDirectory() { return Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath; } } }