Decompiled source of ObeliskRU v0.1.0

ObeliskRU.dll

Decompiled 7 hours ago
using 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;
		}
	}
}