Decompiled source of PotalMapLocalization v0.1.0

PotalMapLocalization.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using LocalizationShared;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("lnx")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © lnx")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("PotalMapLocalization")]
[assembly: AssemblyTitle("PotalMapLocalization")]
[assembly: AssemblyMetadata("Author", "lnx")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 LocalizationShared
{
	internal sealed class TranslationConfig : IDisposable
	{
		private readonly ConfigFile config;

		private readonly Action<string> warning;

		private readonly Dictionary<string, ConfigEntry<string>> entries = new Dictionary<string, ConfigEntry<string>>(StringComparer.Ordinal);

		private readonly Dictionary<string, string> defaults;

		private readonly Dictionary<string, string> aliases = new Dictionary<string, string>(StringComparer.Ordinal);

		private readonly Dictionary<string, string> lastValues = new Dictionary<string, string>(StringComparer.Ordinal);

		private readonly Dictionary<string, string> resolved = new Dictionary<string, string>(StringComparer.Ordinal);

		private DateTime nextCheck;

		private DateTime observedWrite;

		private DateTime loadedWrite;

		private long observedLength;

		private long loadedLength;

		private int changed;

		internal TranslationConfig(ConfigFile config, TranslationDefinition[] definitions, Action<string> warning, Func<string, string> gameLocalize = null)
		{
			this.config = config;
			defaults = new Dictionary<string, string>(StringComparer.Ordinal);
			this.warning = warning;
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				HashSet<ConfigDefinition> hashSet = new HashSet<ConfigDefinition>();
				Dictionary<string, string> dictionary = MigrateLegacySection(config, hashSet);
				Dictionary<string, string> dictionary2 = MigrateDuplicates(config, definitions);
				foreach (TranslationDefinition translationDefinition in definitions)
				{
					string text = translationDefinition.Default;
					if (translationDefinition.GameKey != null && gameLocalize != null)
					{
						string text2 = gameLocalize(translationDefinition.GameKey);
						if (!string.IsNullOrEmpty(text2) && text2 != translationDefinition.GameKey && !text2.StartsWith("[", StringComparison.Ordinal))
						{
							text = text2;
						}
					}
					defaults.Add(translationDefinition.Id, text);
					string text3 = "Исходный текст: " + translationDefinition.Source;
					ConfigEntry<string> val = config.Bind<string>(translationDefinition.Section, translationDefinition.Key, text, text3);
					if (!hashSet.Contains(((ConfigEntryBase)val).Definition) && dictionary.TryGetValue(KeyFor(translationDefinition.Source), out var value))
					{
						string text4 = TomlTypeConverter.ConvertToValue<string>(value);
						if (text4 != translationDefinition.LegacyDefault)
						{
							val.Value = text4;
						}
					}
					entries.Add(translationDefinition.Id, val);
					if (translationDefinition.AliasSource == null)
					{
						continue;
					}
					aliases.Add(translationDefinition.AliasSource, translationDefinition.Id);
					if (!dictionary2.TryGetValue(translationDefinition.Id, out var value2))
					{
						dictionary.TryGetValue(KeyFor(translationDefinition.AliasSource), out value2);
					}
					if (value2 != null && val.Value == text)
					{
						string text5 = TomlTypeConverter.ConvertToValue<string>(value2);
						if (text5 != translationDefinition.LegacyDefault)
						{
							val.Value = text5;
						}
					}
				}
				config.Save();
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
			FileInfo fileInfo = new FileInfo(config.ConfigFilePath);
			loadedWrite = (observedWrite = fileInfo.LastWriteTimeUtc);
			loadedLength = (observedLength = fileInfo.Length);
			config.SettingChanged += OnSettingChanged;
			config.ConfigReloaded += OnReloaded;
		}

		private static Dictionary<string, string> MigrateDuplicates(ConfigFile config, TranslationDefinition[] definitions)
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			Dictionary<ConfigDefinition, TranslationDefinition> dictionary2 = definitions.Where((TranslationDefinition d) => d.AliasKey != null).ToDictionary((Func<TranslationDefinition, ConfigDefinition>)((TranslationDefinition d) => new ConfigDefinition(d.Section, d.AliasKey)));
			if (dictionary2.Count == 0 || !File.Exists(config.ConfigFilePath))
			{
				return dictionary;
			}
			List<string> list = new List<string>();
			string text = "";
			string[] array = File.ReadAllLines(config.ConfigFilePath);
			foreach (string text2 in array)
			{
				string text3 = text2.Trim();
				if (text3.StartsWith("[", StringComparison.Ordinal) && text3.EndsWith("]", StringComparison.Ordinal))
				{
					text = text3.Substring(1, text3.Length - 2);
				}
				int num2 = text3.IndexOf('=');
				if (text.Length != 0 && num2 > 0 && !text3.StartsWith("#", StringComparison.Ordinal) && !text3.StartsWith("[", StringComparison.Ordinal) && dictionary2.TryGetValue(new ConfigDefinition(text, text3.Substring(0, num2).Trim()), out var value))
				{
					dictionary[value.Id] = text3.Substring(num2 + 1).Trim();
				}
				else
				{
					list.Add(text2);
				}
			}
			if (dictionary.Count != 0)
			{
				string text4 = config.ConfigFilePath + ".v1.2.bak";
				int num3 = 1;
				while (File.Exists(text4))
				{
					text4 = config.ConfigFilePath + ".v1.2.bak." + num3;
					num3++;
				}
				File.Copy(config.ConfigFilePath, text4);
				File.WriteAllLines(config.ConfigFilePath, list, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				config.Reload();
			}
			return dictionary;
		}

		private static Dictionary<string, string> MigrateLegacySection(ConfigFile config, HashSet<ConfigDefinition> existing)
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			if (!File.Exists(config.ConfigFilePath))
			{
				return dictionary;
			}
			List<string> list = new List<string>();
			string text = "";
			bool flag = false;
			string[] array = File.ReadAllLines(config.ConfigFilePath);
			foreach (string text2 in array)
			{
				string text3 = text2.Trim();
				if (text3.StartsWith("[", StringComparison.Ordinal) && text3.EndsWith("]", StringComparison.Ordinal))
				{
					text = text3.Substring(1, text3.Length - 2);
				}
				bool flag2 = text == "Translations";
				flag = flag || flag2;
				if (!flag2)
				{
					list.Add(text2);
				}
				int num = text3.IndexOf('=');
				if (num > 0 && !text3.StartsWith("#", StringComparison.Ordinal) && !text3.StartsWith("[", StringComparison.Ordinal))
				{
					string text4 = text3.Substring(0, num).Trim();
					if (flag2)
					{
						dictionary[text4] = text3.Substring(num + 1).Trim();
					}
					else if (text.Length != 0)
					{
						existing.Add(new ConfigDefinition(text, text4));
					}
				}
			}
			if (flag)
			{
				string text5 = config.ConfigFilePath + ".v1.1.bak";
				int num2 = 1;
				while (File.Exists(text5))
				{
					text5 = config.ConfigFilePath + ".v1.1.bak." + num2;
					num2++;
				}
				File.Copy(config.ConfigFilePath, text5);
				File.WriteAllLines(config.ConfigFilePath, list, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				config.Reload();
			}
			return dictionary;
		}

		internal static string KeyFor(string source)
		{
			string text = Regex.Replace(source, "[^\\p{L}\\p{Nd}]+", "_").Trim('_');
			if (text.Length > 48)
			{
				text = text.Substring(0, 48);
			}
			using SHA256 sHA = SHA256.Create();
			string text2 = BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(source))).Replace("-", "").Substring(0, 12);
			return ((text.Length == 0) ? "Text" : text) + "_" + text2;
		}

		internal string Get(string source)
		{
			if (aliases.TryGetValue(source, out var value))
			{
				source = value;
			}
			if (!entries.TryGetValue(source, out var value2))
			{
				return source;
			}
			string text = value2.Value ?? "";
			if (lastValues.TryGetValue(source, out var value3) && value3 == text)
			{
				return resolved[source];
			}
			lastValues[source] = text;
			if (!ValidFormat(source, text))
			{
				warning("Invalid translation template [" + ((ConfigEntryBase)value2).Definition.Key + "]; using the built-in text. Preserve its placeholders.");
				text = defaults[source];
			}
			resolved[source] = text;
			return text;
		}

		private static bool ValidFormat(string source, string value)
		{
			if (!source.Contains("{0}"))
			{
				return true;
			}
			object[] array = ((!source.Contains("{1}")) ? new object[1] { "__LOC_ARG_0__" } : new object[2] { "__LOC_ARG_0__", "__LOC_ARG_1__" });
			try
			{
				string formatted = string.Format(CultureInfo.InvariantCulture, value, array);
				return array.All((object argument) => formatted.Contains((string)argument));
			}
			catch (FormatException)
			{
				return false;
			}
		}

		internal bool Poll()
		{
			if (DateTime.UtcNow >= nextCheck)
			{
				nextCheck = DateTime.UtcNow.AddSeconds(1.0);
				try
				{
					FileInfo fileInfo = new FileInfo(config.ConfigFilePath);
					if (fileInfo.Exists)
					{
						if (fileInfo.LastWriteTimeUtc != observedWrite || fileInfo.Length != observedLength)
						{
							observedWrite = fileInfo.LastWriteTimeUtc;
							observedLength = fileInfo.Length;
						}
						else if (observedWrite != loadedWrite || observedLength != loadedLength)
						{
							bool saveOnConfigSet = config.SaveOnConfigSet;
							config.SaveOnConfigSet = false;
							try
							{
								config.Reload();
							}
							finally
							{
								config.SaveOnConfigSet = saveOnConfigSet;
							}
							loadedWrite = observedWrite;
							loadedLength = observedLength;
						}
					}
				}
				catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
				{
					warning("Cannot reload translation config: " + ex.Message);
				}
			}
			return Interlocked.Exchange(ref changed, 0) != 0;
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs args)
		{
			Interlocked.Exchange(ref changed, 1);
		}

		private void OnReloaded(object sender, EventArgs args)
		{
			Interlocked.Exchange(ref changed, 1);
		}

		public void Dispose()
		{
			config.SettingChanged -= OnSettingChanged;
			config.ConfigReloaded -= OnReloaded;
		}
	}
	internal sealed class TranslationDefinition
	{
		internal readonly string Id;

		internal readonly string Source;

		internal readonly string Section;

		internal readonly string Key;

		internal readonly string Default;

		internal readonly string LegacyDefault;

		internal readonly string GameKey;

		internal readonly string AliasSource;

		internal readonly string AliasKey;

		internal TranslationDefinition(string id, string source, string section, string key, string defaultValue, string legacyDefault, string gameKey = null, string aliasSource = null, string aliasKey = null)
		{
			Id = id;
			Source = source;
			Section = section;
			Key = key;
			Default = defaultValue;
			LegacyDefault = legacyDefault;
			GameKey = gameKey;
			AliasSource = aliasSource;
			AliasKey = aliasKey;
		}
	}
}
namespace PotalMapLocalization
{
	[BepInPlugin("lordn.potalmap.localization", "PotalMap Localization", "0.1.0")]
	[BepInDependency("com.korcaptain.potalmap", "0.1.83")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "lordn.potalmap.localization";

		public const string OriginalGuid = "com.korcaptain.potalmap";

		private Harmony harmony;

		private bool initialized;

		private static FieldInfo panelField;

		private static MethodInfo refreshList;

		internal static readonly Dictionary<string, string[]> LiteralPatches = new Dictionary<string, string[]>
		{
			{
				"PortalHoverHints.Postfix",
				new string[2] { "Cycle mode", "모드 변경" }
			},
			{
				"PortalFuel.TryConsume",
				new string[1] { "Not enough {0} ({1} required)." }
			},
			{
				"PortalTagValidation.OnSetText",
				new string[4] { "Portal name already in use: \"", "\" — please choose a different name.", "이미 사용 중인 포탈 이름입니다: \"", "\" — 다른 이름을 입력해주세요." }
			},
			{
				"PortalTeleporter.TryTeleport",
				new string[1] { "이 포탈은 이용 권한이 없습니다." }
			}
		};

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			harmony = new Harmony("lordn.potalmap.localization");
			try
			{
				Translations.Initialize(((BaseUnityPlugin)this).Config, delegate(string message)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)message);
				});
				StonePortals.Bind(((BaseUnityPlugin)this).Config);
				PluginInfo val = Chainloader.PluginInfos["com.korcaptain.potalmap"];
				Assembly assembly = ((object)val.Instance).GetType().Assembly;
				Type type = assembly.GetType("PortalMap.PortalBrowserPanel", throwOnError: true);
				panelField = AccessTools.Field(type, "_panel");
				refreshList = AccessTools.Method(type, "RefreshPortalList", Type.EmptyTypes, (Type[])null);
				if (panelField == null || refreshList == null)
				{
					throw new MissingMemberException("Portal browser API changed.");
				}
				foreach (KeyValuePair<string, string[]> literalPatch in LiteralPatches)
				{
					string[] array = literalPatch.Key.Split('.');
					MethodInfo methodInfo = AccessTools.Method(assembly.GetType("PortalMap." + array[0], throwOnError: true), array[1], (Type[])null, (Type[])null);
					if (methodInfo == null)
					{
						throw new MissingMethodException(literalPatch.Key);
					}
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "TranslateLiterals", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				}
				Postfix(AccessTools.Method(type, "GroupLabel", (Type[])null, (Type[])null), "TranslateResult");
				Postfix(AccessTools.Method(assembly.GetType("PortalMap.PortalHoverHints", throwOnError: true), "ModeLabel", (Type[])null, (Type[])null), "TranslateResult");
				harmony.Patch((MethodBase)AccessTools.Method(type, "AddHeader", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "TranslateLabel", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)AccessTools.Method(type, "AddSectionHeader", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "TranslateLabel", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Postfix(AccessTools.Method(typeof(Localization), "SetLanguage", new Type[1] { typeof(string) }, (Type[])null), "LanguageChanged");
				StonePortals.Install(harmony, assembly);
				StonePortals.ApplySetting();
				initialized = true;
				LanguageChanged();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Russian localization loaded for PotalMap " + val.Metadata.Version));
			}
			catch (Exception ex)
			{
				Translations.Config?.Dispose();
				Translations.Config = null;
				harmony.UnpatchSelf();
				StonePortals.Dispose();
				initialized = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("Localization disabled: " + ex));
			}
		}

		private void Update()
		{
			if (initialized && Translations.Config != null && Translations.Config.Poll())
			{
				StonePortals.ApplySetting();
				LanguageChanged();
			}
		}

		private void Postfix(MethodBase target, string method)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (target == null)
			{
				throw new MissingMethodException(method);
			}
			harmony.Patch(target, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), method, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static IEnumerable<CodeInstruction> TranslateLiterals(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			string[] array = LiteralPatches[__originalMethod.DeclaringType.Name + "." + __originalMethod.Name];
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (list.Count((CodeInstruction val) => val.opcode == OpCodes.Ldstr && object.Equals(val.operand, text)) != 1)
				{
					throw new InvalidOperationException("Unsupported PotalMap IL in " + __originalMethod.Name + ": " + text);
				}
			}
			MethodInfo method = typeof(Translations).GetMethod("Translate", BindingFlags.Static | BindingFlags.NonPublic);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			foreach (CodeInstruction item in list)
			{
				list2.Add(item);
				if (item.opcode == OpCodes.Ldstr && array.Contains(item.operand as string))
				{
					list2.Add(new CodeInstruction(OpCodes.Call, (object)method));
				}
			}
			return list2;
		}

		private static void TranslateResult(ref string __result)
		{
			__result = Translations.Translate(__result);
		}

		private static void TranslateLabel(ref string __1)
		{
			__1 = Translations.Translate(__1);
		}

		private static void LanguageChanged()
		{
			object? obj = panelField?.GetValue(null);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				Transform obj2 = val.transform.Find("Header");
				Text val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<Text>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.text = Translations.Translate("Potal_Map");
				}
				refreshList.Invoke(null, null);
			}
		}

		private void OnDestroy()
		{
			Translations.Config?.Dispose();
			Translations.Config = null;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			StonePortals.Dispose();
			if (!initialized)
			{
				return;
			}
			object? value = panelField.GetValue(null);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (!((Object)(object)val == (Object)null))
			{
				Transform obj2 = val.transform.Find("Header");
				Text val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<Text>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.text = "Potal_Map";
				}
				refreshList.Invoke(null, null);
			}
		}
	}
	internal static class StonePortals
	{
		private static ConfigEntry<bool> enabled;

		private static bool applied;

		private static int stoneHash;

		private static FieldInfo triggerPortal;

		private static Func<bool> sessionActive;

		private static Action syncPins;

		private static Action<TeleportWorld> portalAwake;

		private static TeleportWorld sourcePortal;

		private static Player sourcePlayer;

		private static bool Enabled
		{
			get
			{
				if (enabled != null)
				{
					return enabled.Value;
				}
				return false;
			}
		}

		internal static void Bind(ConfigFile config)
		{
			enabled = config.Bind<bool>("4 - Stone portals", "Enable stone portals", false, "Use PotalMap for stone portals and allow all carried items when departing from a stone portal. Каменные порталы используют PotalMap и позволяют переносить любые предметы при отправлении через них.");
		}

		internal static void Install(Harmony harmony, Assembly original)
		{
			Type type = original.GetType("PortalMap.PortalMapGeneralConfig", throwOnError: true);
			Type type2 = original.GetType("PortalMap.PortalMapSession", throwOnError: true);
			Type type3 = original.GetType("PortalMap.MapInteraction", throwOnError: true);
			Type type4 = original.GetType("PortalMap.PortalTracking", throwOnError: true);
			stoneHash = (int)(AccessTools.Field(type, "PortalStoneHash") ?? throw new MissingFieldException(type.FullName, "PortalStoneHash")).GetValue(null);
			triggerPortal = AccessTools.Field(typeof(TeleportWorldTrigger), "m_teleportWorld") ?? throw new MissingFieldException(typeof(TeleportWorldTrigger).FullName, "m_teleportWorld");
			sessionActive = (Func<bool>)Required(type2, "get_Active", Type.EmptyTypes).CreateDelegate(typeof(Func<bool>));
			syncPins = (Action)Required(type4, "SyncAllPins", Type.EmptyTypes).CreateDelegate(typeof(Action));
			portalAwake = (Action<TeleportWorld>)Required(type4, "OnPortalAwake", typeof(TeleportWorld)).CreateDelegate(typeof(Action<TeleportWorld>));
			harmony.Patch((MethodBase)Required(type, "IsEligiblePortal", typeof(GameObject)), (HarmonyMethod)null, Patch("EligibleObject"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)Required(type, "IsEligiblePortal", typeof(ZDO)), (HarmonyMethod)null, Patch("EligibleZdo"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)(AccessTools.Method(type3, "OpenMapOnPortalEnter", (Type[])null, (Type[])null) ?? throw new MissingMethodException(type3.FullName, "OpenMapOnPortalEnter")), (HarmonyMethod)null, Patch("PortalEntered"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)Required(type2, "MarkSession", typeof(MapMode)), (HarmonyMethod)null, Patch("SessionChanged"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)Required(type4, "OnGameStart", Type.EmptyTypes), (HarmonyMethod)null, Patch("ClearSource"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)Required(original.GetType("PortalMap.PortalTeleporter", throwOnError: true), "TryTeleport", typeof(ZDOID)), (HarmonyMethod)null, (HarmonyMethod)null, Patch("ReplaceInventoryCheck"), (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static MethodInfo Required(Type type, string name, params Type[] parameters)
		{
			return AccessTools.Method(type, name, parameters, (Type[])null) ?? throw new MissingMethodException(type.FullName, name);
		}

		private static HarmonyMethod Patch(string name)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return new HarmonyMethod(typeof(StonePortals), name, (Type[])null);
		}

		private static bool IsStone(GameObject portal)
		{
			if ((Object)(object)portal != (Object)null)
			{
				return Utils.GetPrefabName(portal) == "portal_stone";
			}
			return false;
		}

		private static void EligibleObject(GameObject __0, ref bool __result)
		{
			if (Enabled && IsStone(__0))
			{
				__result = true;
			}
		}

		private static void EligibleZdo(ZDO __0, ref bool __result)
		{
			if (Enabled && __0 != null && __0.GetPrefab() == stoneHash)
			{
				__result = true;
			}
		}

		private static void PortalEntered(TeleportWorldTrigger __0, bool __result)
		{
			if (!__result)
			{
				ClearSource();
				object? value = triggerPortal.GetValue(__0);
				TeleportWorld val = (TeleportWorld)((value is TeleportWorld) ? value : null);
				if (Enabled && (Object)(object)val != (Object)null && IsStone(((Component)val).gameObject) && sessionActive())
				{
					sourcePortal = val;
					sourcePlayer = Player.m_localPlayer;
				}
			}
		}

		private static void SessionChanged()
		{
			if (!sessionActive())
			{
				ClearSource();
			}
		}

		private static void ClearSource()
		{
			sourcePortal = null;
			sourcePlayer = null;
		}

		private static bool CanCarryItems(Humanoid player, bool originalAllowAllItems)
		{
			if (Enabled && (Object)(object)sourcePortal != (Object)null && (Object)(object)sourcePlayer != (Object)null && (Object)(object)player == (Object)(object)sourcePlayer && (Object)(object)sourcePlayer == (Object)(object)Player.m_localPlayer && sessionActive())
			{
				return true;
			}
			return player.IsTeleportable(originalAllowAllItems);
		}

		private static IEnumerable<CodeInstruction> ReplaceInventoryCheck(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo check = typeof(Humanoid).GetMethod("IsTeleportable", new Type[1] { typeof(bool) });
			List<CodeInstruction> list2 = list.Where((CodeInstruction i) => (i.opcode == OpCodes.Callvirt || i.opcode == OpCodes.Call) && object.Equals(i.operand, check)).ToList();
			if (check == null || list2.Count != 1)
			{
				throw new InvalidOperationException("Unsupported PotalMap inventory check: expected exactly one Humanoid.IsTeleportable call.");
			}
			list2[0].opcode = OpCodes.Call;
			list2[0].operand = typeof(StonePortals).GetMethod("CanCarryItems", BindingFlags.Static | BindingFlags.NonPublic);
			return list;
		}

		internal static void ApplySetting()
		{
			if (applied == Enabled)
			{
				return;
			}
			applied = Enabled;
			if (!applied && (Object)(object)sourcePortal != (Object)null && sessionActive() && (Object)(object)Minimap.instance != (Object)null)
			{
				Minimap.instance.SetMapMode((MapMode)1);
			}
			ClearSource();
			if ((Object)(object)Minimap.instance == (Object)null || ZDOMan.instance == null)
			{
				return;
			}
			if (applied)
			{
				TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
				foreach (TeleportWorld val in array)
				{
					if (IsStone(((Component)val).gameObject))
					{
						portalAwake(val);
					}
				}
			}
			syncPins();
		}

		internal static void Dispose()
		{
			enabled = null;
			if (sessionActive != null)
			{
				ApplySetting();
			}
			ClearSource();
			sessionActive = null;
			syncPins = null;
			portalAwake = null;
			triggerPortal = null;
			applied = false;
		}
	}
	internal static class Translations
	{
		internal static TranslationConfig Config;

		internal static readonly TranslationDefinition[] Definitions = new TranslationDefinition[13]
		{
			new TranslationDefinition("Potal_Map", "Potal_Map", "1 - Interface", "Panel title", "Порталы", "Порталы"),
			new TranslationDefinition("즐겨찾기", "즐겨찾기", "1 - Interface", "Favorites", "Избранное", "Избранное"),
			new TranslationDefinition("Public", "Public", "2 - Access modes", "Public hint", "Общий", "Общий"),
			new TranslationDefinition("Private", "Private", "2 - Access modes", "Private hint", "Личный", "Личный"),
			new TranslationDefinition("Guild", "Guild", "2 - Access modes", "Guild hint", "Гильдия", "Гильдия"),
			new TranslationDefinition("공개", "공개", "2 - Access modes", "Public category", "Общие", "Общие"),
			new TranslationDefinition("개인", "개인", "2 - Access modes", "Private category", "Личные", "Личные"),
			new TranslationDefinition("길드", "길드", "2 - Access modes", "Guild category", "Гильдия", "Гильдия"),
			new TranslationDefinition("Cycle mode", "Cycle mode", "2 - Access modes", "Cycle mode hint", "Сменить режим", "Сменить режим", null, "모드 변경", "Cycle mode hint - Korean source"),
			new TranslationDefinition("Not enough {0} ({1} required).", "Not enough {0} ({1} required).", "3 - Messages", "Not enough fuel", "Недостаточно: {0} (требуется {1}).", "Недостаточно: {0} (требуется {1})."),
			new TranslationDefinition("Portal name already in use: \"", "Portal name already in use: \"", "3 - Messages", "Duplicate name - beginning", "Имя портала уже занято: \"", "Имя портала уже занято: \"", null, "이미 사용 중인 포탈 이름입니다: \"", "Duplicate name - beginning - Korean source"),
			new TranslationDefinition("\" — please choose a different name.", "\" — please choose a different name.", "3 - Messages", "Duplicate name - ending", "\" — выберите другое имя.", "\" — выберите другое имя.", null, "\" — 다른 이름을 입력해주세요.", "Duplicate name - ending - Korean source"),
			new TranslationDefinition("이 포탈은 이용 권한이 없습니다.", "이 포탈은 이용 권한이 없습니다.", "3 - Messages", "Access denied", "У вас нет доступа к этому порталу.", "У вас нет доступа к этому порталу.")
		};

		internal static readonly Dictionary<string, string> Text = Definitions.ToDictionary<TranslationDefinition, string, string>((TranslationDefinition entry) => entry.Id, (TranslationDefinition entry) => entry.Default, StringComparer.Ordinal);

		internal static readonly Dictionary<string, string> Aliases = Definitions.Where((TranslationDefinition entry) => entry.AliasSource != null).ToDictionary<TranslationDefinition, string, string>((TranslationDefinition entry) => entry.AliasSource, (TranslationDefinition entry) => entry.Id, StringComparer.Ordinal);

		internal static bool Russian
		{
			get
			{
				if (Localization.instance != null)
				{
					return string.Equals(Localization.instance.GetSelectedLanguage(), "Russian", StringComparison.OrdinalIgnoreCase);
				}
				return false;
			}
		}

		internal static void Initialize(ConfigFile config, Action<string> warning)
		{
			Config = new TranslationConfig(config, Definitions, warning);
		}

		internal static string Translate(string value)
		{
			if (value == null || !Russian)
			{
				return value;
			}
			if (Aliases.TryGetValue(value, out var value2))
			{
				value = value2;
			}
			if (!Text.TryGetValue(value, out var value3))
			{
				return value;
			}
			if (Config != null)
			{
				return Config.Get(value);
			}
			return value3;
		}
	}
}