Decompiled source of GateOfOrethority v1.0.6

GateOfOrethority.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("GateOfOrethority")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GateOfOrethority")]
[assembly: AssemblyTitle("GateOfOrethority")]
[assembly: AssemblyVersion("1.0.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 GateOfOrethority
{
	public static class Commands
	{
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		private static class RegisterCommandsPatch
		{
			[Serializable]
			[CompilerGenerated]
			private sealed class <>c
			{
				public static readonly <>c <>9 = new <>c();

				public static ConsoleEvent <>9__0_0;

				public static ConsoleEvent <>9__0_1;

				public static ConsoleOptionsFetcher <>9__0_2;

				public static ConsoleEvent <>9__0_3;

				public static ConsoleOptionsFetcher <>9__0_4;

				internal void <Postfix>b__0_0(ConsoleEventArgs args)
				{
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null)
					{
						args.Context.AddString("[GateOfOrethority] No local player found.");
						return;
					}
					List<string> list = PersonalKeys(localPlayer).ToList();
					if (list.Count == 0)
					{
						args.Context.AddString("[GateOfOrethority] No personal boss keys set on this character yet.");
						return;
					}
					args.Context.AddString($"[GateOfOrethority] {list.Count} personal key(s) on this character:");
					foreach (string item in list)
					{
						args.Context.AddString("  " + item + " = true");
					}
				}

				internal void <Postfix>b__0_1(ConsoleEventArgs args)
				{
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null)
					{
						args.Context.AddString("[GateOfOrethority] No local player found.");
						return;
					}
					if (args.Length < 2)
					{
						args.Context.AddString("[GateOfOrethority] Usage: gateoforethority_addkey <key>");
						return;
					}
					string text = args[1];
					KeyManager.GrantPersonalKey(localPlayer, text);
					args.Context.AddString("[GateOfOrethority] Granted personal key: " + text);
				}

				internal List<string> <Postfix>b__0_2()
				{
					return KnownConfiguredKeys().ToList();
				}

				internal void <Postfix>b__0_3(ConsoleEventArgs args)
				{
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null)
					{
						args.Context.AddString("[GateOfOrethority] No local player found.");
						return;
					}
					if (args.Length < 2)
					{
						args.Context.AddString("[GateOfOrethority] Usage: gateoforethority_removekey <key>");
						return;
					}
					string text = args[1];
					string key = "GateOfOrethority_" + text;
					if (!localPlayer.m_customData.ContainsKey(key))
					{
						args.Context.AddString("[GateOfOrethority] Key not set: " + text);
						return;
					}
					localPlayer.m_customData.Remove(key);
					args.Context.AddString("[GateOfOrethority] Removed personal key: " + text);
				}

				internal List<string> <Postfix>b__0_4()
				{
					return PersonalKeys(Player.m_localPlayer).ToList();
				}
			}

			private static void Postfix()
			{
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Expected O, but got Unknown
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Expected O, but got Unknown
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Expected O, but got Unknown
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Expected O, but got Unknown
				if (registered)
				{
					return;
				}
				registered = true;
				object obj = <>c.<>9__0_0;
				if (obj == null)
				{
					ConsoleEvent val = delegate(ConsoleEventArgs args)
					{
						Player localPlayer = Player.m_localPlayer;
						if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null)
						{
							args.Context.AddString("[GateOfOrethority] No local player found.");
						}
						else
						{
							List<string> list = PersonalKeys(localPlayer).ToList();
							if (list.Count != 0)
							{
								args.Context.AddString($"[GateOfOrethority] {list.Count} personal key(s) on this character:");
								{
									foreach (string item in list)
									{
										args.Context.AddString("  " + item + " = true");
									}
									return;
								}
							}
							args.Context.AddString("[GateOfOrethority] No personal boss keys set on this character yet.");
						}
					};
					<>c.<>9__0_0 = val;
					obj = (object)val;
				}
				new ConsoleCommand("gateoforethority_keys", "Lists your character's personal GateOfOrethority boss-defeat keys.", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj2 = <>c.<>9__0_1;
				if (obj2 == null)
				{
					ConsoleEvent val2 = delegate(ConsoleEventArgs args)
					{
						Player localPlayer = Player.m_localPlayer;
						if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null)
						{
							args.Context.AddString("[GateOfOrethority] No local player found.");
						}
						else if (args.Length < 2)
						{
							args.Context.AddString("[GateOfOrethority] Usage: gateoforethority_addkey <key>");
						}
						else
						{
							string text = args[1];
							KeyManager.GrantPersonalKey(localPlayer, text);
							args.Context.AddString("[GateOfOrethority] Granted personal key: " + text);
						}
					};
					<>c.<>9__0_1 = val2;
					obj2 = (object)val2;
				}
				object obj3 = <>c.<>9__0_2;
				if (obj3 == null)
				{
					ConsoleOptionsFetcher val3 = () => KnownConfiguredKeys().ToList();
					<>c.<>9__0_2 = val3;
					obj3 = (object)val3;
				}
				new ConsoleCommand("gateoforethority_addkey", "Grants a personal boss-defeat key to your current character. Usage: gateoforethority_addkey <key>", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)obj3, false, false, false);
				object obj4 = <>c.<>9__0_3;
				if (obj4 == null)
				{
					ConsoleEvent val4 = delegate(ConsoleEventArgs args)
					{
						Player localPlayer = Player.m_localPlayer;
						if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null)
						{
							args.Context.AddString("[GateOfOrethority] No local player found.");
						}
						else if (args.Length < 2)
						{
							args.Context.AddString("[GateOfOrethority] Usage: gateoforethority_removekey <key>");
						}
						else
						{
							string text = args[1];
							string key = "GateOfOrethority_" + text;
							if (!localPlayer.m_customData.ContainsKey(key))
							{
								args.Context.AddString("[GateOfOrethority] Key not set: " + text);
							}
							else
							{
								localPlayer.m_customData.Remove(key);
								args.Context.AddString("[GateOfOrethority] Removed personal key: " + text);
							}
						}
					};
					<>c.<>9__0_3 = val4;
					obj4 = (object)val4;
				}
				object obj5 = <>c.<>9__0_4;
				if (obj5 == null)
				{
					ConsoleOptionsFetcher val5 = () => PersonalKeys(Player.m_localPlayer).ToList();
					<>c.<>9__0_4 = val5;
					obj5 = (object)val5;
				}
				new ConsoleCommand("gateoforethority_removekey", "Removes a personal boss-defeat key from your current character. Usage: gateoforethority_removekey <key>", (ConsoleEvent)obj4, false, false, false, false, false, false, (ConsoleOptionsFetcher)obj5, false, false, false);
			}
		}

		private static bool registered;

		private static IEnumerable<string> PersonalKeys(Player player)
		{
			if (player?.m_customData == null)
			{
				return Enumerable.Empty<string>();
			}
			return from k in player.m_customData.Keys
				where k.StartsWith("GateOfOrethority_")
				select k.Substring("GateOfOrethority_".Length);
		}

		private static IEnumerable<string> KnownConfiguredKeys()
		{
			return Plugin.BlockedItems.Values.Select((BlockedItemRule r) => r.RequiredKey).Distinct();
		}
	}
	public static class ConfigSync
	{
		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class RegisterRpcPatch
		{
			private static void Postfix()
			{
				ZRoutedRpc.instance.Register<ZPackage>("GateOfOrethority_ConfigSync", (Action<long, ZPackage>)OnReceiveConfig);
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		private static class SendOnPeerConnectPatch
		{
			private static void Postfix(ZNet __instance, ZRpc rpc)
			{
				if (!__instance.IsServer() || !Plugin.ServerAuthoritative.Value)
				{
					return;
				}
				ZNetPeer val = null;
				foreach (ZNetPeer peer in __instance.GetPeers())
				{
					if (peer.m_rpc == rpc)
					{
						val = peer;
						break;
					}
				}
				if (val != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "GateOfOrethority_ConfigSync", new object[1] { BuildPackage() });
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Shutdown")]
		private static class RestoreOnDisconnectPatch
		{
			private static void Prefix()
			{
				RestoreLocalValues();
			}
		}

		private const string RpcName = "GateOfOrethority_ConfigSync";

		private static readonly Dictionary<string, ConfigEntryBase> Registered = new Dictionary<string, ConfigEntryBase>();

		private static readonly Dictionary<string, object> LocalBackup = new Dictionary<string, object>();

		private static bool serverValuesApplied;

		public static void Register(ConfigEntryBase entry)
		{
			string key = Id(entry);
			if (!Registered.ContainsKey(key))
			{
				Registered[key] = entry;
			}
		}

		private static string Id(ConfigEntryBase entry)
		{
			return entry.Definition.Section + "." + entry.Definition.Key;
		}

		private static ZPackage BuildPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(Registered.Count);
			foreach (KeyValuePair<string, ConfigEntryBase> item in Registered)
			{
				val.Write(item.Key);
				val.Write(TomlTypeConverter.ConvertToString(item.Value.BoxedValue, item.Value.SettingType));
			}
			return val;
		}

		private static void ApplyPackage(ZPackage pkg)
		{
			int num = pkg.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string text = pkg.ReadString();
				string text2 = pkg.ReadString();
				if (!Registered.TryGetValue(text, out var value))
				{
					continue;
				}
				try
				{
					if (!LocalBackup.ContainsKey(text))
					{
						LocalBackup[text] = value.BoxedValue;
					}
					value.BoxedValue = TomlTypeConverter.ConvertToValue(text2, value.SettingType);
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[GateOfOrethority] Could not apply synced config '" + text + "': " + ex.Message));
				}
			}
			serverValuesApplied = true;
			Plugin.RebuildBlockedItems();
		}

		private static void RestoreLocalValues()
		{
			if (!serverValuesApplied)
			{
				return;
			}
			foreach (KeyValuePair<string, object> item in LocalBackup)
			{
				if (Registered.TryGetValue(item.Key, out var value))
				{
					try
					{
						value.BoxedValue = item.Value;
					}
					catch
					{
					}
				}
			}
			LocalBackup.Clear();
			serverValuesApplied = false;
			Plugin.RebuildBlockedItems();
		}

		private static void OnReceiveConfig(long sender, ZPackage pkg)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && pkg != null)
			{
				ApplyPackage(pkg);
			}
		}
	}
	public static class KeyManager
	{
		public static bool WorldHasDefeated(string globalKey)
		{
			if (string.IsNullOrEmpty(globalKey))
			{
				return true;
			}
			return (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey(globalKey);
		}

		public static bool PlayerHasPersonalKey(Player player, string globalKey)
		{
			if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(globalKey))
			{
				return true;
			}
			string key = "GateOfOrethority_" + globalKey;
			string value;
			return player.m_customData != null && player.m_customData.TryGetValue(key, out value) && value == "true";
		}

		public static void GrantPersonalKey(Player player, string globalKey)
		{
			if (!((Object)(object)player == (Object)null) && !string.IsNullOrEmpty(globalKey))
			{
				string key = "GateOfOrethority_" + globalKey;
				if (player.m_customData != null)
				{
					player.m_customData[key] = "true";
				}
			}
		}

		public static bool IsCleared(Player player, string globalKey)
		{
			return WorldHasDefeated(globalKey) && PlayerHasPersonalKey(player, globalKey);
		}

		public static List<BlockedItemRule> GetUnmetRules(Player player, IEnumerable<string> carriedItemNames)
		{
			List<BlockedItemRule> list = new List<BlockedItemRule>();
			foreach (string carriedItemName in carriedItemNames)
			{
				if (Plugin.BlockedItems.TryGetValue(carriedItemName, out var value) && !IsCleared(player, value.RequiredKey))
				{
					list.Add(value);
				}
			}
			return list;
		}
	}
	public static class Messages
	{
		private static readonly Dictionary<string, string> BossMessages = new Dictionary<string, string>
		{
			{ "defeated_eikthyr", "The forest spirits reject this metal - Eikthyr's antlers still guard the old ways." },
			{ "defeated_gdking", "The roots hold tight and the Elder denies your passage" },
			{ "defeated_bonemass", "Iron groans with the weight of decay. Bonemass’s curse clings to its core." },
			{ "defeated_dragon", "The metal remembers the cold breath of Moder. You are not yet worthy." },
			{ "defeated_goblinking", "Black metal hums with scorched defiance. Yagluth’s embers burn too bright to pass." },
			{ "defeated_queen", "The metal clinks with defiance. The Queen’s will must be broken." },
			{ "defeated_fader", "The metal smolders with unspent vengeance. Fader’s dominion endures." },
			{ "defeated_deepnorth_boss", "The frozen north does not yet release its gold to you." }
		};

		public static string ForBossKey(string globalKey)
		{
			if (BossMessages.TryGetValue(globalKey, out var value))
			{
				return value;
			}
			return "An old ward blocks this metal from the portal - a great foe must fall first.";
		}

		public static string Combined(List<BlockedItemRule> unmetRules)
		{
			if (unmetRules.Count == 1)
			{
				BlockedItemRule blockedItemRule = unmetRules[0];
				return (!string.IsNullOrEmpty(blockedItemRule.Message)) ? blockedItemRule.Message : ForBossKey(blockedItemRule.RequiredKey);
			}
			return "The portal rejects your burden - several old wards still hold your items fast.";
		}
	}
	public class BlockedItemRule
	{
		public string ItemId;

		public string RequiredKey;

		public string Message;
	}
	[BepInPlugin("Stayk.valheim.gateoforethority", "Gate of Ore-thority", "1.0.6")]
	public class Plugin : BaseUnityPlugin
	{
		private class ItemConfigEntries
		{
			public string ItemId;

			public ConfigEntry<bool> Enabled;

			public ConfigEntry<string> RequiredKey;

			public ConfigEntry<string> Message;
		}

		public const string PluginGUID = "Stayk.valheim.gateoforethority";

		public const string PluginName = "Gate of Ore-thority";

		public const string PluginVersion = "1.0.6";

		private readonly Harmony harmony = new Harmony("Stayk.valheim.gateoforethority");

		public static ConfigEntry<bool> ModEnabled;

		public static ConfigEntry<bool> ServerAuthoritative;

		public const string PersonalKeyPrefix = "GateOfOrethority_";

		private static readonly List<ItemConfigEntries> ItemConfigs = new List<ItemConfigEntries>();

		public static readonly Dictionary<string, BlockedItemRule> BlockedItems = new Dictionary<string, BlockedItemRule>(StringComparer.OrdinalIgnoreCase);

		private static readonly (string ItemId, string RequiredKey, string Message)[] KnownItems = new(string, string, string)[22]
		{
			("$item_copper", "defeated_gdking", ""),
			("$item_copperore", "defeated_gdking", ""),
			("$item_tin", "defeated_gdking", ""),
			("$item_tinore", "defeated_gdking", ""),
			("$item_bronze", "defeated_gdking", ""),
			("$item_iron", "defeated_bonemass", ""),
			("$item_ironpit", "defeated_bonemass", ""),
			("$item_ironscrap", "defeated_bonemass", ""),
			("$item_ironore", "defeated_bonemass", "Leeches will feed upon the fish that gave this treasure"),
			("$item_dragonegg", "defeated_dragon", "Moder binds her clutch to the mountain realm"),
			("$item_silver", "defeated_dragon", ""),
			("$item_silverore", "defeated_dragon", ""),
			("$item_blackmetalscrap", "defeated_goblinking", ""),
			("$item_blackmetal", "defeated_goblinking", ""),
			("$item_mechanicalspring", "defeated_goblinking", ""),
			("$item_dvergrneedle", "defeated_queen", "The extractor trembles, the Dvergr do not yet recognise your ability"),
			("$item_bronzescrap", "defeated_queen", ""),
			("$item_flametal_old", "defeated_fader", "Fader things you should try the new Flametal"),
			("$item_flametalore_old", "defeated_fader", "Fader says you spawned the wrong ore"),
			("$item_flametalore", "defeated_fader", ""),
			("$item_flametal", "defeated_fader", ""),
			("$item_charredcogwheel", "defeated_fader", "The cogwheel crackles with emerald flame. Fader’s wrath must be extinguished")
		};

		private void Awake()
		{
			BindConfig();
			RebuildBlockedItems();
			harmony.PatchAll();
			foreach (MethodBase patchedMethod in harmony.GetPatchedMethods())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[GateOfOrethority] Harmony reports patched: " + patchedMethod.DeclaringType?.FullName + "." + patchedMethod.Name));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Gate of Ore-thority v1.0.6 loaded.");
		}

		private void BindConfig()
		{
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master on/off switch for the mod.");
			ServerAuthoritative = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ServerAuthoritative", true, "If true, clients joining a server running this mod use the SERVER's config values below, not their own local ones.");
			List<ConfigEntryBase> list = new List<ConfigEntryBase> { (ConfigEntryBase)(object)ModEnabled };
			(string, string, string)[] knownItems = KnownItems;
			for (int i = 0; i < knownItems.Length; i++)
			{
				(string, string, string) tuple = knownItems[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				string item3 = tuple.Item3;
				ItemConfigEntries itemConfigEntries = new ItemConfigEntries
				{
					ItemId = item,
					Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>(item, "Enabled", true, "Whether this item is blocked at all. Set false to remove the rule without deleting it."),
					RequiredKey = ((BaseUnityPlugin)this).Config.Bind<string>(item, "RequiredKey", item2, "The global key that must be defeated (both world-wide AND personally) to carry this item through a portal."),
					Message = ((BaseUnityPlugin)this).Config.Bind<string>(item, "Message", item3, "Shown when this item blocks the portal. Leave blank to fall back to a generic message for that boss.")
				};
				ItemConfigs.Add(itemConfigEntries);
				list.Add((ConfigEntryBase)(object)itemConfigEntries.Enabled);
				list.Add((ConfigEntryBase)(object)itemConfigEntries.RequiredKey);
				list.Add((ConfigEntryBase)(object)itemConfigEntries.Message);
			}
			foreach (ConfigEntryBase item4 in list)
			{
				ConfigSync.Register(item4);
			}
		}

		public static void RebuildBlockedItems()
		{
			BlockedItems.Clear();
			foreach (ItemConfigEntries itemConfig in ItemConfigs)
			{
				if (itemConfig.Enabled.Value)
				{
					string text = itemConfig.RequiredKey.Value?.Trim();
					if (!string.IsNullOrEmpty(text))
					{
						BlockedItems[itemConfig.ItemId] = new BlockedItemRule
						{
							ItemId = itemConfig.ItemId,
							RequiredKey = text,
							Message = (string.IsNullOrWhiteSpace(itemConfig.Message.Value) ? null : itemConfig.Message.Value.Trim())
						};
					}
				}
			}
		}
	}
}
namespace GateOfOrethority.Patches
{
	[HarmonyPatch(typeof(Character), "OnDeath")]
	public static class BossDeathPatch
	{
		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class RegisterGrantKeyRpcPatch
		{
			private static void Postfix()
			{
				ZRoutedRpc.instance.Register<string>("GateOfOrethority_GrantPersonalKey", (Action<long, string>)OnReceiveGrantKey);
			}
		}

		private const float ProximityRadius = 50f;

		private const string GrantKeyRpcName = "GateOfOrethority_GrantPersonalKey";

		private static void OnReceiveGrantKey(long sender, string globalKey)
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				KeyManager.GrantPersonalKey(Player.m_localPlayer, globalKey);
			}
		}

		[HarmonyPrefix]
		public static void Prefix(Character __instance)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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)
			if (!Plugin.ModEnabled.Value || (Object)(object)__instance == (Object)null || !__instance.m_boss)
			{
				return;
			}
			string text = ResolveGlobalKeyForBoss(__instance);
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				ZoneSystem.instance.SetGlobalKey(text);
			}
			Vector3 position = ((Component)__instance).transform.position;
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer == (Object)null)
				{
					continue;
				}
				float num = Vector3.Distance(((Component)allPlayer).transform.position, position);
				if (num > 50f)
				{
					continue;
				}
				if ((Object)(object)allPlayer == (Object)(object)Player.m_localPlayer)
				{
					KeyManager.GrantPersonalKey(allPlayer, text);
					continue;
				}
				ZNetPeer val = FindPeerForPlayer(allPlayer);
				if (val != null && ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "GateOfOrethority_GrantPersonalKey", new object[1] { text });
				}
			}
		}

		private static ZNetPeer FindPeerForPlayer(Player player)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return null;
			}
			ZDOID zDOID = ((Character)player).GetZDOID();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer.m_characterID == zDOID)
				{
					return peer;
				}
			}
			return null;
		}

		private static string ResolveGlobalKeyForBoss(Character boss)
		{
			return ((Object)boss).name.Replace("(Clone)", "") switch
			{
				"Eikthyr" => "defeated_eikthyr", 
				"gd_king" => "defeated_gdking", 
				"Bonemass" => "defeated_bonemass", 
				"Dragon" => "defeated_dragon", 
				"GoblinKing" => "defeated_goblinking", 
				"SeekerQueen" => "defeated_queen", 
				"Fader" => "defeated_fader", 
				"DeepNorthBoss" => "defeated_deepnorth_boss", 
				_ => null, 
			};
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
	public static class PortalPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(TeleportWorld __instance, Player player)
		{
			Debug.Log((object)("[GateOfOrethority] Teleport prefix called for player=" + ((player != null) ? player.GetPlayerName() : null)));
			if (!Plugin.ModEnabled.Value)
			{
				return true;
			}
			if ((Object)(object)player == (Object)null)
			{
				return true;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return true;
			}
			List<string> list = (from n in inventory.GetAllItems().Select(delegate(ItemData item)
				{
					object result;
					if (item.m_shared == null)
					{
						GameObject dropPrefab = item.m_dropPrefab;
						result = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "";
					}
					else
					{
						result = item.m_shared.m_name;
					}
					return (string)result;
				})
				where !string.IsNullOrEmpty(n)
				select n).ToList();
			List<BlockedItemRule> unmetRules = KeyManager.GetUnmetRules(player, list);
			Debug.Log((object)("[GateOfOrethority] carried item names: " + string.Join(", ", list)));
			Debug.Log((object)("[GateOfOrethority] unmet item rules: " + string.Join(", ", unmetRules.Select((BlockedItemRule r) => r.ItemId))));
			if (unmetRules.Count == 0)
			{
				return true;
			}
			((Character)player).Message((MessageType)2, Messages.Combined(unmetRules), 0, (Sprite)null, false);
			return false;
		}
	}
}