Decompiled source of FortecaClanWarfare v420.0.66

plugins/FehuKingdoms/FortecaClanWarfare.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FortecaClanWarfare.Core;
using FortecaClanWarfare.Data;
using FortecaClanWarfare.Network;
using FortecaClanWarfare.Patches;
using FortecaClanWarfare.UI;
using FortecaClanWarfare.Utils;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("forteca")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Clan-based territory warfare mod for Valheim")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0")]
[assembly: AssemblyProduct("FortecaClanWarfare")]
[assembly: AssemblyTitle("FortecaClanWarfare")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[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 FortecaClanWarfare
{
	[BepInPlugin("com.forteca.clanwarfare", "Forteca Clan Warfare", "0.2.0")]
	[BepInProcess("valheim.exe")]
	[BepInProcess("valheim_server.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.forteca.clanwarfare";

		public const string PluginName = "Forteca Clan Warfare";

		public const string PluginVersion = "0.2.0";

		private Harmony _harmony;

		private GameObject _managerObj;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Invalid comparison between Unknown and I4
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ClanConfig.Initialize(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.forteca.clanwarfare");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			TargetPortalFehuAdapter.Initialize(_harmony);
			((MonoBehaviour)this).InvokeRepeating("RetryTargetPortalAdapter", 2f, 2f);
			_managerObj = new GameObject("FortecaClanWarfare");
			Object.DontDestroyOnLoad((Object)_managerObj);
			_managerObj.AddComponent<WarfareManager>();
			_managerObj.AddComponent<WarfareRPC>();
			if ((int)SystemInfo.graphicsDeviceType != 4)
			{
				_managerObj.AddComponent<GridManager>();
				_managerObj.AddComponent<WarfareHUD>();
				_managerObj.AddComponent<ClanSelectionUI>();
				_managerObj.AddComponent<ClanNameTagRenderer>();
				_managerObj.AddComponent<MapGridOverlay>();
				_managerObj.AddComponent<TabMenuButtonRenderer>();
			}
			Log.LogMessage((object)"");
			Log.LogMessage((object)"  ============================================");
			Log.LogMessage((object)"       FORTECA CLAN WARFARE");
			Log.LogMessage((object)"       Developed by Freyja and Black Viking");
			Log.LogMessage((object)"       https://tinyurl.com/DiscordFreyja");
			Log.LogMessage((object)"  ============================================");
			Log.LogMessage((object)"");
		}

		private void OnDestroy()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			((MonoBehaviour)this).CancelInvoke("RetryTargetPortalAdapter");
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)_managerObj != (Object)null)
			{
				Object.Destroy((Object)_managerObj);
			}
		}

		private void RetryTargetPortalAdapter()
		{
			TargetPortalFehuAdapter.RefreshIfNeeded();
			if (TargetPortalFehuAdapter.AdapterEnabled)
			{
				((MonoBehaviour)this).CancelInvoke("RetryTargetPortalAdapter");
			}
		}
	}
	[HarmonyPatch]
	public static class TargetPortalDebugCommands
	{
		[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;

			internal void <RegisterCommands>b__0_0(ConsoleEventArgs args)
			{
				args.Context.AddString(TargetPortalFehuAdapter.DebugSetCurrentPortalClanMode());
			}

			internal void <RegisterCommands>b__0_1(ConsoleEventArgs args)
			{
				args.Context.AddString(TargetPortalFehuAdapter.DebugNearPortal());
			}
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		[HarmonyPostfix]
		public static void RegisterCommands()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					args.Context.AddString(TargetPortalFehuAdapter.DebugSetCurrentPortalClanMode());
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("fcw_portal_clan", "Set the nearby TargetPortal portal to FCW Clan mode for the current clan.", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj2 = <>c.<>9__0_1;
			if (obj2 == null)
			{
				ConsoleEvent val2 = delegate(ConsoleEventArgs args)
				{
					args.Context.AddString(TargetPortalFehuAdapter.DebugNearPortal());
				};
				<>c.<>9__0_1 = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("fcw_portal_debug_near", "Print FCW TargetPortal permission and ownership data for the nearby portal.", (ConsoleEvent)obj2, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	public static class TargetPortalFehuAdapter
	{
		private sealed class PortalAccessData
		{
			public string AccessType = "None";

			public int ClanId;

			public ClanRank RequiredRank;

			public long FreebornId;

			public long OwnerPlayerId;

			public string ClanName = "";

			public string ClanTag = "";

			public string FreebornName = "";

			public string OwnerName = "";
		}

		private const string TargetPortalGuid = "org.bepinex.plugins.targetportal";

		private const string TargetPortalModeKey = "Target Portal PortalMode";

		private const string TargetPortalModeKeyAlt = "TargetPortal PortalMode";

		private const string TargetPortalOwnerIdKey = "Target Portal PortalOwnerId";

		private const string TargetPortalOwnerIdKeyAlt = "TargetPortal PortalOwnerId";

		private const string TargetPortalOwnerNameKey = "Target Portal PortalOwnerName";

		private const string TargetPortalOwnerNameKeyAlt = "TargetPortal PortalOwnerName";

		private const string FcwTargetPortalModeKey = "FCW_TargetPortalMode";

		private const string FcwTargetPortalClanIdKey = "FCW_TargetPortalClanId";

		private const string FcwTargetPortalClanNameKey = "FCW_TargetPortalClanName";

		private const string FcwTargetPortalClanTagKey = "FCW_TargetPortalClanTag";

		private const string FcwTargetPortalOwnerPlayerIdKey = "FCW_TargetPortalOwnerPlayerId";

		private const string FcwTargetPortalOwnerNameKey = "FCW_TargetPortalOwnerName";

		private const string FcwTargetPortalCreatorIdKey = "FCW_TargetPortalCreatorId";

		private const string FcwTargetPortalCreatorSteamIdKey = "FCW_TargetPortalCreatorSteamId";

		private const string FcwTargetPortalCreatorPlayerIdKey = "FCW_TargetPortalCreatorPlayerId";

		private const string FcwTargetPortalCreatorNameKey = "FCW_TargetPortalCreatorName";

		private const string TargetPortalProtectionOwnerIdKey = "TargetPortalProtection OwnerId";

		private const int PortalModePublic = 0;

		private const int PortalModePrivate = 1;

		private const int PortalModeGroup = 2;

		private const int PortalModeAdmin = 3;

		private const int PortalModeGuildCarrier = 4;

		private static readonly string[] BoolHookNames = new string[4] { "HandlePortalClick", "CanUsePortal", "CanTeleport", "FilterPortals" };

		private static readonly string[] PortalListHookNames = new string[7] { "FilterPortals", "FetchPortals", "GetPortals", "AddPortalPins", "FillFavorites", "RefereshPortalPins", "HandlePortalClick" };

		private static readonly HashSet<string> Logged = new HashSet<string>();

		private static readonly Dictionary<ZDOID, int> PreviousPortalModes = new Dictionary<ZDOID, int>();

		private static readonly HashSet<ZDOID> MigratedClanCarriers = new HashSet<ZDOID>();

		private static bool _initialized;

		private static bool _enabled;

		private static bool _targetPortalFound;

		private static Harmony _harmony;

		private static float _nextDetectionTime;

		private static int _lastPatchedCount;

		private static float _nextRetryLogTime;

		private static bool _dumpedToggleDetails;

		public static bool TargetPortalFound
		{
			get
			{
				RefreshIfNeeded();
				return _targetPortalFound;
			}
		}

		public static bool AdapterEnabled
		{
			get
			{
				RefreshIfNeeded();
				return _enabled;
			}
		}

		public static void Initialize(Harmony harmony)
		{
			_harmony = harmony;
			if (!_initialized)
			{
				_initialized = true;
				TryEnableAdapter(logMissing: true);
			}
		}

		public static void RefreshIfNeeded()
		{
			if (!_enabled)
			{
				float time = Time.time;
				if (!(time > 0f) || !(time < _nextDetectionTime))
				{
					_nextDetectionTime = time + 3f;
					TryEnableAdapter(logMissing: false);
				}
			}
		}

		private static bool ShouldLogRetry(bool force)
		{
			if (force)
			{
				_nextRetryLogTime = Time.time + 3f;
				return true;
			}
			if (Time.time >= _nextRetryLogTime)
			{
				_nextRetryLogTime = Time.time + 10f;
				return true;
			}
			return false;
		}

		private static void TryEnableAdapter(bool logMissing)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00a0: Expected O, but got Unknown
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Expected O, but got Unknown
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_0472: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ab: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			Assembly assembly = FindTargetPortalAssembly();
			if (assembly == null)
			{
				_targetPortalFound = false;
				_enabled = false;
				_lastPatchedCount = 0;
				if (ShouldLogRetry(logMissing))
				{
					Plugin.Log.LogInfo((object)"[FCW TargetPortal] TargetPortal not loaded yet, retrying...");
				}
				return;
			}
			_targetPortalFound = true;
			if (_enabled || _harmony == null)
			{
				return;
			}
			int num = 0;
			foreach (MethodInfo item in FindHookMethods(assembly))
			{
				try
				{
					_harmony.Patch((MethodBase)item, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalBoolAccessPrefix", (Type[])null), new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalBoolAccessPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched:" + item.DeclaringType?.FullName + "." + item.Name, "[FCW TargetPortal] Patched real TargetPortal method: " + item.DeclaringType?.FullName + "." + item.Name);
				}
				catch (Exception ex)
				{
					LogOnce("patchfail:" + item.Name, "[FCW TargetPortal] Patch failed for " + item.Name + ": " + ex.Message);
				}
			}
			num += PatchTargetPortalMapAccess(assembly);
			foreach (MethodInfo item2 in FindPortalListMethods(assembly))
			{
				try
				{
					HarmonyMethod val = ((!HasMutablePortalListArg(item2)) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalPortalListPrefix", (Type[])null));
					HarmonyMethod val2 = null;
					if (item2.ReturnType == typeof(List<ZDO>))
					{
						val2 = new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalPortalListPostfix", (Type[])null);
					}
					else if (item2.ReturnType == typeof(IEnumerable<ZDO>))
					{
						val2 = new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalPortalEnumerablePostfix", (Type[])null);
					}
					if (val != null || val2 != null)
					{
						_harmony.Patch((MethodBase)item2, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
						LogOnce("patched-list:" + item2.DeclaringType?.FullName + "." + item2.Name, "[FCW TargetPortal] Patched real TargetPortal method: " + item2.DeclaringType?.FullName + "." + item2.Name);
					}
				}
				catch (Exception ex2)
				{
					LogOnce("patchlistfail:" + item2.DeclaringType?.FullName + "." + item2.Name, "[FCW TargetPortal] Portal list patch failed for " + item2.DeclaringType?.FullName + "." + item2.Name + ": " + ex2.Message);
				}
			}
			foreach (MethodInfo item3 in FindToggleModeMethods(assembly))
			{
				try
				{
					_harmony.Patch((MethodBase)item3, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalToggleModePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-toggle:" + item3.DeclaringType?.FullName + "." + item3.Name, "[FCW TargetPortal] Patched real TargetPortal method: " + item3.DeclaringType?.FullName + "." + item3.Name);
				}
				catch (Exception ex3)
				{
					LogOnce("patchtogglefail:" + item3.DeclaringType?.FullName + "." + item3.Name, "[FCW TargetPortal] Mode toggle patch failed for " + item3.DeclaringType?.FullName + "." + item3.Name + ": " + ex3.Message);
				}
			}
			foreach (MethodInfo item4 in FindHoverTextMethods(assembly))
			{
				try
				{
					_harmony.Patch((MethodBase)item4, (HarmonyMethod)null, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalHoverTextPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-hover:" + item4.DeclaringType?.FullName + "." + item4.Name, "[FCW TargetPortal] Patched real TargetPortal method: " + item4.DeclaringType?.FullName + "." + item4.Name);
				}
				catch (Exception ex4)
				{
					LogOnce("patchhoverfail:" + item4.DeclaringType?.FullName + "." + item4.Name, "[FCW TargetPortal] Hover patch failed for " + item4.DeclaringType?.FullName + "." + item4.Name + ": " + ex4.Message);
				}
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(TeleportWorld), "GetHoverText", Type.EmptyTypes, (Type[])null);
				if (methodInfo != null)
				{
					HarmonyMethod val3 = new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalFinalHoverPostfix", (Type[])null)
					{
						priority = 0
					};
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-final-hover", "[FCW TargetPortal] Patched final TeleportWorld.GetHoverText display path after TargetPortal.");
				}
			}
			catch (Exception ex5)
			{
				LogOnce("patch-final-hover-fail", "[FCW TargetPortal] Final hover display patch failed: " + ex5.Message);
			}
			num = (_lastPatchedCount = num + PatchPortalProtectionMethods());
			if (num <= 0)
			{
				LogOnce("nohooks", "[FCW TargetPortal] TargetPortal found, but no safe boolean access hook was found. Adapter backend disabled.");
				return;
			}
			_enabled = true;
			LogOnce("enabled", "[FCW TargetPortal] Fehu portal adapter enabled. Assembly=" + assembly.GetName().Name + " hooks=" + num);
		}

		private static int PatchPortalProtectionMethods()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			int num = 0;
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(WearNTear), "Damage", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalDamagePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-portal-damage", "[FCW TargetPortal] Patched local portal damage protection path.");
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(WearNTear), "ApplyDamage", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					_harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalDamagePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-portal-apply-damage", "[FCW TargetPortal] Patched portal ApplyDamage protection path.");
				}
				MethodInfo methodInfo3 = AccessTools.Method(typeof(WearNTear), "RPC_Damage", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					_harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalRpcDamagePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-portal-rpc-damage", "[FCW TargetPortal] Patched server portal RPC_Damage protection path.");
				}
				MethodInfo methodInfo4 = AccessTools.Method(typeof(WearNTear), "Remove", (Type[])null, (Type[])null);
				if (methodInfo4 != null)
				{
					_harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalRemovePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-portal-remove", "[FCW TargetPortal] Patched portal remove protection path.");
				}
				MethodInfo methodInfo5 = AccessTools.Method(typeof(WearNTear), "RPC_Remove", (Type[])null, (Type[])null);
				if (methodInfo5 != null)
				{
					_harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalRpcRemovePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-portal-rpc-remove", "[FCW TargetPortal] Patched portal RPC_Remove protection path.");
				}
			}
			catch (Exception ex)
			{
				LogOnce("patch-portal-protection-fail", "[FCW TargetPortal] Portal damage/remove protection patch failed: " + ex.Message);
			}
			try
			{
				MethodInfo methodInfo6 = AccessTools.Method(typeof(ZDOMan), "GetPortals", (Type[])null, (Type[])null);
				if (methodInfo6 != null)
				{
					HarmonyMethod val = new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalPortalListPostfix", (Type[])null)
					{
						priority = 0
					};
					_harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-zdoman-portals", "[FCW TargetPortal] Patched ZDOMan.GetPortals for FCW Clan visibility filtering.");
				}
			}
			catch (Exception ex2)
			{
				LogOnce("patch-zdoman-portals-fail", "[FCW TargetPortal] Portal list visibility patch failed: " + ex2.Message);
			}
			return num;
		}

		private static int PatchTargetPortalMapAccess(Assembly assembly)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0080: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			int num = 0;
			try
			{
				Type? type = assembly.GetType("TargetPortal.Map", throwOnError: false);
				MethodInfo methodInfo = AccessTools.Method(type, "AddPortalPins", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalMapAddPortalPinsPrefix", (Type[])null)
					{
						priority = 800
					}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalMapAddPortalPinsPostfix", (Type[])null)
					{
						priority = 0
					}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-map-add-pins", "[FCW TargetPortal] Patched TargetPortal.Map.AddPortalPins after native visibility filtering.");
				}
				MethodInfo methodInfo2 = AccessTools.Method(type, "HandlePortalClick", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					_harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(TargetPortalFehuAdapter), "TargetPortalMapHandlePortalClickPrefix", (Type[])null)
					{
						priority = 800
					}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
					LogOnce("patched-map-handle-click", "[FCW TargetPortal] Patched TargetPortal.Map.HandlePortalClick destination access check.");
				}
			}
			catch (Exception ex)
			{
				LogOnce("patch-map-access-fail:" + ex.GetType().Name, "[FCW TargetPortal] Map visibility/access patch failed: " + ex.Message);
			}
			return num;
		}

		public static void TargetPortalMapAddPortalPinsPrefix()
		{
			if (_enabled && IsLocalPortalMapClient())
			{
				LogMapStage("raw", GetKnownTargetPortalPortals(), null, "before native TargetPortal filtering");
			}
		}

		public unsafe static void TargetPortalMapAddPortalPinsPostfix()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_enabled || (Object)(object)ZNet.instance == (Object)null || !IsLocalPortalMapClient() || ZDOMan.instance == null || (Object)(object)Minimap.instance == (Object)null)
				{
					return;
				}
				Type type = FindTargetPortalAssembly()?.GetType("TargetPortal.Map", throwOnError: false);
				object obj = AccessTools.Field(type, "activePins")?.GetValue(null);
				if (obj == null)
				{
					return;
				}
				LogMapStage("afterNative", null, obj, "after TargetPortal native Group/Guild gate");
				LogMapStage("afterGuild", null, obj, "native Group/Guild gate shares AddPortalPins collection");
				HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
				foreach (object item in EnumerateDictionaryEntries(obj))
				{
					object dictionaryEntryValue = GetDictionaryEntryValue(item);
					ZDO val = (ZDO)((dictionaryEntryValue is ZDO) ? dictionaryEntryValue : null);
					if (val != null)
					{
						hashSet.Add(val.m_uid);
					}
				}
				foreach (ZDO receivedZdo in GetReceivedZdos())
				{
					if (!IsFcwVisibilityOverridePortal(receivedZdo) || hashSet.Contains(receivedZdo.m_uid))
					{
						continue;
					}
					if (!CanCurrentPlayerSeePortal(receivedZdo, out var access, out var reason))
					{
						LogPortalDecision("LIST", receivedZdo, allowed: false, reason + " finalAdded=false");
						LogClanPortalTrace(receivedZdo, access, finalVisible: false, "afterFCWRestore", reason);
						continue;
					}
					object obj2 = AddTargetPortalMapPin(receivedZdo, type);
					if (obj2 != null)
					{
						AddDictionaryEntry(obj, obj2, receivedZdo);
						hashSet.Add(receivedZdo.m_uid);
						LogPortalDecision("LIST", receivedZdo, allowed: true, reason + " finalAdded=true");
						ManualLogSource log = Plugin.Log;
						string[] obj3 = new string[6] { "[FCW TargetPortal] Restored allowed ", access.AccessType, " portal pin portal=", null, null, null };
						ZDOID uid = receivedZdo.m_uid;
						obj3[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
						obj3[4] = " reason=";
						obj3[5] = reason;
						log.LogInfo((object)string.Concat(obj3));
					}
					else
					{
						LogPortalDecision("LIST", receivedZdo, allowed: true, reason + " finalAdded=false");
					}
				}
				LogMapStage("afterFCWRestore", null, obj, "after FCW Clan/private restoration");
				LogMapStage("finalUI", null, obj, "TargetPortal.Map.activePins plus Minimap pin registry");
				foreach (ZDO item2 in from portal in GetReceivedZdos()
					where portal != null && string.Equals(portal.GetString("FCW_TargetPortalMode", ""), "Clan", StringComparison.OrdinalIgnoreCase)
					select portal)
				{
					bool finalVisible = obj != null && ContainsPortal(obj, item2.m_uid) && IsInMinimapPinRegistry(obj, item2.m_uid);
					CanCurrentPlayerSeePortal(item2, out var access2, out var reason2);
					LogClanPortalTrace(item2, access2, finalVisible, "finalUI", reason2);
				}
			}
			catch (Exception ex)
			{
				LogOnce("map-add-pins-postfix:" + ex.GetType().Name, "[FCW TargetPortal] Map pin restore failed: " + ex.Message);
			}
		}

		public static bool TargetPortalMapHandlePortalClickPrefix(object[] __args, ref bool __result)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			try
			{
				Delegate obj = __args?.OfType<Delegate>().FirstOrDefault();
				if ((object)obj == null)
				{
					return true;
				}
				object[] array = new object[2];
				object obj2 = obj.DynamicInvoke(array);
				if (obj2 is bool && (bool)obj2)
				{
					object obj3 = array[1];
					ZDO val = (ZDO)((obj3 is ZDO) ? obj3 : null);
					if (val != null)
					{
						Player localPlayer = Player.m_localPlayer;
						long playerId = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0);
						PlayerClanInfo player = WarfareManager.Instance?.Data?.GetPlayer(playerId);
						string reason;
						bool flag = HasPortalAccess(val, playerId, player, out reason);
						LogPortalDecision("USE", val, flag, reason);
						if (flag)
						{
							return true;
						}
						WarfareHUD.ShowLeftNotification("Portal access denied: " + reason + ".");
						__result = false;
						return false;
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				LogOnce("map-handle-click-prefix:" + ex.GetType().Name, "[FCW TargetPortal] Destination access check failed: " + ex.Message);
				return true;
			}
		}

		public static string AdapterStatusText()
		{
			RefreshIfNeeded();
			if (!_targetPortalFound)
			{
				return "<color=#ff6666>TargetPortal not detected yet</color>";
			}
			if (_enabled)
			{
				return "<color=#88ff88>Active</color>";
			}
			if (_lastPatchedCount <= 0)
			{
				return "<color=#ffd24a>Detected / backend only</color>";
			}
			return "<color=#ffd24a>Detected / hook pending</color>";
		}

		public static bool TargetPortalBoolAccessPrefix(object __instance, object[] __args, MethodBase __originalMethod, ref bool __result)
		{
			if (!_enabled)
			{
				return true;
			}
			try
			{
				PortalAccessData portalAccessData = GetPortalAccessData(__instance, __args);
				if (portalAccessData.AccessType == "None")
				{
					return true;
				}
				bool flag = FehuAllowsPortalAccess(portalAccessData);
				LogPortalAccessCheck("TargetPortal." + (__originalMethod?.Name ?? "unknown"), portalAccessData, flag, flag ? "matching clan/admin" : "clan mismatch/freeborn/no clan");
				if (!flag)
				{
					WarfareHUD.ShowLeftNotification("Portal access denied: " + DenialLabel(portalAccessData.AccessType) + ".");
				}
				__result = flag;
				return false;
			}
			catch (Exception ex)
			{
				LogOnce("access-prefix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Fehu pre-access check failed: " + ex.Message);
				return true;
			}
		}

		public static void TargetPortalModeChangePrefix(object __instance, object[] __args, MethodBase __originalMethod)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ZDO val = FindPortalZdo(__instance, __args);
				if (val != null)
				{
					PreviousPortalModes[val.m_uid] = ReadTargetPortalModeValue(val);
				}
			}
			catch (Exception ex)
			{
				LogOnce("modechange-prefix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Mode-change prefix failed: " + ex.Message);
			}
		}

		public static void TargetPortalModeChangePostfix(object __instance, object[] __args, MethodBase __originalMethod)
		{
			try
			{
				ZDO val = FindPortalZdo(__instance, __args);
				if (val != null)
				{
					int num = ReadTargetPortalModeValue(val);
					if (ReadPortalAccessData(val, __instance, __args).AccessType == "Clan" && num != 4)
					{
						DeactivateClanModeForCycle(val);
						LogPortalCycle("Clan", fcwClan: true, ModeName(num));
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce("modechange-postfix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Mode-change postfix failed: " + ex.Message);
			}
		}

		public static void TargetPortalBoolAccessPostfix(object __instance, object[] __args, MethodBase __originalMethod, ref bool __result)
		{
			if (!_enabled)
			{
				return;
			}
			try
			{
				PortalAccessData portalAccessData = GetPortalAccessData(__instance, __args);
				if (!(portalAccessData.AccessType == "None"))
				{
					bool flag = FehuAllowsPortalAccess(portalAccessData);
					LogPortalAccessCheck("TargetPortal." + (__originalMethod?.Name ?? "unknown") + ".post", portalAccessData, flag, flag ? "matching clan/admin" : "clan mismatch/freeborn/no clan");
					if (!flag)
					{
						__result = false;
					}
					else
					{
						__result = true;
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce("access-ex:" + ex.GetType().Name, "[FCW TargetPortal] Fehu access check failed: " + ex.Message);
			}
		}

		public static bool TargetPortalDamagePrefix(WearNTear __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			long playerId = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0);
			return !ShouldBlockPortalAction(__instance, playerId, showMessage: true, serverAuthoritative: false);
		}

		public static bool TargetPortalRpcDamagePrefix(WearNTear __instance, long sender, HitData hit)
		{
			long playerId = ResolvePortalActorId(sender, hit);
			return !ShouldBlockPortalAction(__instance, playerId, showMessage: false, serverAuthoritative: true);
		}

		public static bool TargetPortalRemovePrefix(WearNTear __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			long playerId = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0);
			return !ShouldBlockPortalAction(__instance, playerId, showMessage: true, serverAuthoritative: false);
		}

		public static bool TargetPortalRpcRemovePrefix(WearNTear __instance, long sender)
		{
			long playerId = ResolvePortalActorId(sender, null);
			return !ShouldBlockPortalAction(__instance, playerId, showMessage: false, serverAuthoritative: true);
		}

		private static long ResolvePortalActorId(long sender, HitData hit)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Character obj = ((hit != null) ? hit.GetAttacker() : null);
				Player val = (Player)(object)((obj is Player) ? obj : null);
				if ((Object)val != (Object)null)
				{
					return val.GetPlayerID();
				}
				Player[] array = Object.FindObjectsOfType<Player>();
				foreach (Player val2 in array)
				{
					ZDO val3 = TryGetZdo(val2);
					if (val3 != null && GetZdoUserId(val3) == sender)
					{
						return val2.GetPlayerID();
					}
				}
				ZNet instance = ZNet.instance;
				ZNetPeer val4 = ((instance != null) ? instance.GetPeer(sender) : null);
				ZDO obj2 = ((val4 != null && ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(val4.m_characterID) : null);
				long num = ((obj2 != null) ? obj2.GetLong(ZDOVars.s_playerID, 0L) : 0);
				if (num != 0L)
				{
					return num;
				}
			}
			catch
			{
			}
			return 0L;
		}

		private static long GetZdoUserId(ZDO zdo)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object obj = zdo?.m_uid;
				if (obj == null)
				{
					return 0L;
				}
				FieldInfo fieldInfo = obj.GetType().GetField("userID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? obj.GetType().GetField("m_userID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				return (fieldInfo != null) ? Convert.ToInt64(fieldInfo.GetValue(obj)) : 0;
			}
			catch
			{
				return 0L;
			}
		}

		private unsafe static bool ShouldBlockPortalAction(WearNTear wear, long playerId, bool showMessage, bool serverAuthoritative)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			try
			{
				if ((Object)wear == (Object)null)
				{
					return false;
				}
				TeleportWorld component = ((Component)wear).GetComponent<TeleportWorld>();
				ZDO val = TryGetZdo(component);
				if ((Object)component == (Object)null || val == null || !IsTargetPortalPortal(val))
				{
					return false;
				}
				Player localPlayer = Player.m_localPlayer;
				if (playerId == 0L)
				{
					ManualLogSource log = Plugin.Log;
					string obj = (serverAuthoritative ? "server" : "client");
					ZDOID uid = val.m_uid;
					log.LogWarning((object)("[FCW TargetPortal] Blocked unresolved " + obj + " portal action portal=" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString()));
					return true;
				}
				SyncOwnerMetadata(val, localPlayer, playerId);
				PlayerClanInfo player = WarfareManager.Instance?.Data?.GetPlayer(playerId);
				if (HasPortalDestroyAccess(val, playerId, player, out var reason))
				{
					LogPortalDecision("DESTROY", val, allowed: true, reason);
					return false;
				}
				if (showMessage && (Object)localPlayer != (Object)null && localPlayer.GetPlayerID() == playerId)
				{
					WarfareHUD.ShowLeftNotification("You do not have permission for this portal.");
				}
				LogPortalDecision("DESTROY", val, allowed: false, reason);
				return true;
			}
			catch (Exception ex)
			{
				LogOnce("portal-action-prefix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Portal damage/remove permission check failed: " + ex.Message);
				return false;
			}
		}

		public static void TargetPortalPortalListPrefix(object[] __args, MethodBase __originalMethod)
		{
			if (!_enabled || __args == null)
			{
				return;
			}
			for (int i = 0; i < __args.Length; i++)
			{
				if (__args[i] is IList<ZDO> portals)
				{
					FilterPortalListInPlace(portals, "TargetPortal." + (__originalMethod?.Name ?? "unknown") + ".args");
				}
			}
		}

		public static void TargetPortalPortalListPostfix(MethodBase __originalMethod, ref List<ZDO> __result)
		{
			if (_enabled && __result != null)
			{
				RestoreAllowedClanPortals(__result, "TargetPortal." + (__originalMethod?.Name ?? "unknown") + ".restore");
				FilterPortalListInPlace(__result, "TargetPortal." + (__originalMethod?.Name ?? "unknown") + ".result");
			}
		}

		public static void TargetPortalPortalEnumerablePostfix(MethodBase __originalMethod, ref IEnumerable<ZDO> __result)
		{
			if (_enabled && __result != null)
			{
				List<ZDO> list = __result.ToList();
				FilterPortalListInPlace(list, "TargetPortal." + (__originalMethod?.Name ?? "unknown") + ".result");
				__result = list;
			}
		}

		public unsafe static bool TargetPortalToggleModePrefix(object __instance, object[] __args, MethodBase __originalMethod, ref bool __result)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((__args != null && __args.OfType<bool>().Any((bool value) => value)) || !IsShiftDown())
				{
					TryInitializePortalCreator(__instance, __args);
					return true;
				}
				DumpToggleDetailsOnce(__instance, __args, __originalMethod);
				TeleportWorld val = FindTeleportWorldArg(__args);
				ZDO val2 = TryGetZdo(val) ?? FindPortalZdo(__instance, __args);
				if ((Object)val == (Object)null || val2 == null)
				{
					return true;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)localPlayer == (Object)null)
				{
					return true;
				}
				long playerID = localPlayer.GetPlayerID();
				PlayerClanInfo playerClanInfo = WarfareManager.Instance?.Data?.GetPlayer(playerID);
				Clan clan = ((playerClanInfo == null || playerClanInfo.ClanId == 0) ? null : WarfareManager.Instance?.Data?.GetClan(playerClanInfo.ClanId));
				EnsurePortalCreatorMetadata(val2, localPlayer, playerID);
				if (!CanChangeTargetPortalMode(val2, playerID, playerClanInfo, out var reason))
				{
					ManualLogSource log = Plugin.Log;
					string[] obj = new string[8]
					{
						"[FCW TargetPortal] Toggle denied player=",
						playerID.ToString(),
						"/",
						localPlayer.GetPlayerName(),
						" portal=",
						null,
						null,
						null
					};
					ZDOID uid = val2.m_uid;
					obj[5] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
					obj[6] = " reason=";
					obj[7] = reason;
					log.LogWarning((object)string.Concat(obj));
					WarfareHUD.ShowLeftNotification("You do not have permission to change this portal.");
					__result = false;
					return false;
				}
				List<string> list = BuildPortalCycle(val2, playerClanInfo, clan, playerID);
				PortalAccessData portalAccessData = ReadPortalAccessData(val2, val, null);
				string oldMode = ((portalAccessData.AccessType == "Clan") ? "Clan" : ModeName(ReadTargetPortalModeValue(val2)));
				int num = list.FindIndex((string mode) => string.Equals(mode, oldMode, StringComparison.OrdinalIgnoreCase));
				if (num < 0)
				{
					num = 0;
					oldMode = list[0];
				}
				string text = list[(num + 1) % list.Count];
				Plugin.Log.LogInfo((object)("[FCW PortalModes] CYCLE old=" + oldMode + " next=" + text + " index=" + num + " list=" + string.Join(" -> ", list.ToArray())));
				if (string.Equals(text, "Clan", StringComparison.OrdinalIgnoreCase))
				{
					SetFehuClanSnapshot(val2, playerClanInfo, clan, localPlayer);
					WarfareHUD.ShowLeftNotification("Portal mode: Clan - " + clan.Name + " [" + clan.Tag + "]");
				}
				else
				{
					DeactivateClanModeForCycle(val2);
					SetNormalTargetPortalMode(val2, ModeValue(text), playerID, localPlayer);
				}
				LogPortalModeChanged(oldMode, text, string.Equals(text, "Clan", StringComparison.OrdinalIgnoreCase) ? playerClanInfo.ClanId : 0, string.Equals(text, "Clan", StringComparison.OrdinalIgnoreCase) ? clan.Name : "");
				__result = false;
				return false;
			}
			catch (Exception ex)
			{
				LogOnce("toggle-prefix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Clan mode toggle failed: " + ex.Message);
				return true;
			}
		}

		public static void TargetPortalToggleModePostfix(object __instance, object[] __args, MethodBase __originalMethod)
		{
			try
			{
				ZDO val = FindPortalZdo(__instance, __args);
				if (val == null)
				{
					val = TryGetZdo(FindCurrentPortal());
				}
				if (val != null)
				{
					int num = ReadTargetPortalModeValue(val);
					if (num != 4 && ReadPortalAccessData(val, __instance, __args).AccessType == "Clan")
					{
						DeactivateClanModeForCycle(val);
						LogPortalCycle("Clan", fcwClan: true, ModeName(num));
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce("toggle-postfix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Clan mode toggle postfix failed: " + ex.Message);
			}
		}

		public static void TargetPortalTracePrefix(object __instance, object[] __args, MethodBase __originalMethod)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			try
			{
				ZDO val = FindPortalZdo(__instance, __args) ?? TryGetZdo(FindCurrentPortal());
				Player localPlayer = Player.m_localPlayer;
				long num = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0);
				PlayerClanInfo playerClanInfo = ((num == 0L) ? null : WarfareManager.Instance?.Data?.GetPlayer(num));
				Clan clan = ((playerClanInfo == null || playerClanInfo.ClanId == 0) ? null : WarfareManager.Instance?.Data?.GetClan(playerClanInfo.ClanId));
				Plugin.Log.LogInfo((object)("FCW TargetPortal TRACE: method=" + (__originalMethod?.DeclaringType?.FullName ?? "unknown") + "." + (__originalMethod?.Name ?? "unknown") + " currentMode=" + ReadTargetPortalMode(val, "") + " ownerName=" + ((val != null) ? val.GetString("Target Portal PortalOwnerName", "") : null) + " clanId=" + (playerClanInfo?.ClanId ?? 0) + " clanName=" + clan?.Name));
			}
			catch (Exception ex)
			{
				LogOnce("trace-ex:" + ex.GetType().Name, "[FCW TargetPortal] Trace failed: " + ex.Message);
			}
		}

		private static void DumpToggleDetailsOnce(object instance, object[] args, MethodBase method)
		{
			if (_dumpedToggleDetails)
			{
				return;
			}
			_dumpedToggleDetails = true;
			try
			{
				Plugin.Log.LogInfo((object)("FCW TargetPortal TOGGLE INSPECT: method=" + (method?.DeclaringType?.FullName ?? "unknown") + "." + (method?.Name ?? "unknown")));
				ParameterInfo[] array = method?.GetParameters() ?? Array.Empty<ParameterInfo>();
				for (int i = 0; i < array.Length; i++)
				{
					object value = ((args != null && i < args.Length) ? args[i] : null);
					Plugin.Log.LogInfo((object)("FCW TargetPortal TOGGLE PARAM: name=" + array[i].Name + " type=" + array[i].ParameterType.FullName + " value=" + FormatDebugValue(value)));
				}
				if (instance == null)
				{
					Plugin.Log.LogInfo((object)"FCW TargetPortal TOGGLE INSTANCE: null");
					return;
				}
				Type type = instance.GetType();
				Plugin.Log.LogInfo((object)("FCW TargetPortal TOGGLE INSTANCE: type=" + type.FullName));
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					object obj = null;
					try
					{
						obj = fieldInfo.GetValue(fieldInfo.IsStatic ? null : instance);
					}
					catch (Exception ex)
					{
						obj = "<error " + ex.GetType().Name + ">";
					}
					Plugin.Log.LogInfo((object)("FCW TargetPortal TOGGLE FIELD: " + fieldInfo.Name + " type=" + fieldInfo.FieldType.FullName + " value=" + FormatDebugValue(obj)));
				}
				PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (propertyInfo.GetIndexParameters().Length == 0)
					{
						object obj2 = null;
						try
						{
							MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true);
							obj2 = ((!(getMethod == null)) ? propertyInfo.GetValue(getMethod.IsStatic ? null : instance, null) : "<no getter>");
						}
						catch (Exception ex2)
						{
							obj2 = "<error " + ex2.GetType().Name + ">";
						}
						Plugin.Log.LogInfo((object)("FCW TargetPortal TOGGLE PROPERTY: " + propertyInfo.Name + " type=" + propertyInfo.PropertyType.FullName + " value=" + FormatDebugValue(obj2)));
					}
				}
			}
			catch (Exception ex3)
			{
				Plugin.Log.LogInfo((object)("[FCW TargetPortal] Toggle inspect failed: " + ex3.Message));
			}
		}

		private unsafe static string FormatDebugValue(object value)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (value == null)
			{
				return "null";
			}
			try
			{
				ZDO val = (ZDO)((value is ZDO) ? value : null);
				if (val != null)
				{
					ZDOID uid = val.m_uid;
					return "ZDO " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
				}
				if (value is ZDOID val2)
				{
					ZDOID uid = val2;
					return "ZDOID " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
				}
				Component val3 = (Component)((value is Component) ? value : null);
				if (val3 != null)
				{
					return ((object)val3).GetType().FullName + " name=" + ((Object)val3).name;
				}
				return value.ToString();
			}
			catch
			{
				return "<unprintable>";
			}
		}

		public static void TargetPortalHoverTextPostfix(object __instance, object[] __args, MethodBase __originalMethod, ref string __result)
		{
			try
			{
				ZDO val = FindPortalZdo(__instance, __args) ?? TryGetZdo(FindCurrentPortal());
				PortalAccessData portalAccessData = ReadPortalAccessData(val, __instance, __args);
				string text = __result ?? "";
				if (!(portalAccessData.AccessType != "Clan"))
				{
					LogOnce("hover-raw:" + (((object)Unsafe.As<ZDOID, ZDOID>(ref val?.m_uid)/*cast due to .constrained prefix*/).ToString() ?? "unknown"), "[FCW TargetPortal] Hover raw=" + text);
					string text2 = ReplaceClanHoverMode(text, ClanLabel(portalAccessData));
					if (!string.Equals(text, text2, StringComparison.Ordinal))
					{
						__result = text2;
						LogOnce("hover-replaced:" + (((object)Unsafe.As<ZDOID, ZDOID>(ref val?.m_uid)/*cast due to .constrained prefix*/).ToString() ?? "unknown"), "[FCW TargetPortal] Hover replaced=" + text2);
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce("hover-postfix-ex:" + ex.GetType().Name, "[FCW TargetPortal] Hover rewrite failed: " + ex.Message);
			}
		}

		public static void TargetPortalFinalHoverPostfix(TeleportWorld __instance, ref string __result)
		{
			try
			{
				ZDO val = TryGetZdo(__instance);
				PortalAccessData portalAccessData = ReadPortalAccessData(val, __instance, null);
				if (!(portalAccessData.AccessType != "Clan"))
				{
					string obj = __result ?? "";
					string text = ReplaceClanHoverMode(obj, ClanLabel(portalAccessData));
					if (!string.Equals(obj, text, StringComparison.Ordinal))
					{
						__result = text;
						LogOnce("final-hover-replaced:" + (((object)Unsafe.As<ZDOID, ZDOID>(ref val?.m_uid)/*cast due to .constrained prefix*/).ToString() ?? "unknown"), "[FCW TargetPortal] Final hover replaced=" + text);
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce("final-hover-ex:" + ex.GetType().Name, "[FCW TargetPortal] Final hover display failed: " + ex.Message);
			}
		}

		private static string ReplaceClanHoverMode(string text, string clanName)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text ?? "";
			}
			string text2 = "Clan: " + clanName;
			int num = text.IndexOf("Portal Tag:", StringComparison.OrdinalIgnoreCase);
			int num2 = ((num >= 0) ? text.IndexOf('[', num) : text.IndexOf('['));
			int num3 = ((num2 >= 0) ? text.IndexOf(']', num2) : (-1));
			if (num2 >= 0 && num3 > num2)
			{
				return text.Substring(0, num2 + 1) + text2 + text.Substring(num3);
			}
			return RewriteClanHoverLabel(text, clanName);
		}

		private static string RewriteClanHoverLabel(string text, string clanName)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text ?? "";
			}
			string[] array = text.Replace("\r\n", "\n").Split(new char[1] { '\n' });
			bool flag = false;
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i];
				if (TryExtractClanOwnerName(text2, out var clanName2))
				{
					string text3 = "Clan: " + ((!string.IsNullOrWhiteSpace(clanName2)) ? clanName2 : clanName);
					int num = text2.IndexOf("(Owner: Clan:", StringComparison.OrdinalIgnoreCase);
					int num2 = text2.LastIndexOf('[', num);
					int num3 = ((num >= 0) ? text2.IndexOf(']', num) : (-1));
					if (num2 >= 0 && num3 > num2)
					{
						array[i] = text2.Substring(0, num2 + 1) + text3 + text2.Substring(num3);
					}
					else
					{
						array[i] = text3;
					}
					flag = true;
				}
			}
			if (!flag)
			{
				return text;
			}
			string text4 = string.Join("\n", array);
			if (!text.Contains("\r\n"))
			{
				return text4;
			}
			return text4.Replace("\n", "\r\n");
		}

		private static bool TryExtractClanOwnerName(string line, out string clanName)
		{
			clanName = "";
			if (string.IsNullOrEmpty(line))
			{
				return false;
			}
			string text = "(Owner: Clan:";
			int num = line.IndexOf(text, StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return false;
			}
			int num2 = num + text.Length;
			int num3 = line.IndexOf(')', num2);
			if (num3 < 0)
			{
				num3 = line.Length;
			}
			clanName = line.Substring(num2, num3 - num2).Trim().TrimEnd(new char[1] { ']' });
			return true;
		}

		public static void UpdateFallbackHotkey()
		{
		}

		public unsafe static string DebugSetCurrentPortalClanMode()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			RefreshIfNeeded();
			TeleportWorld obj = FindCurrentPortal();
			ZDO val = TryGetZdo(obj);
			if ((Object)obj == (Object)null || val == null)
			{
				return "No nearby portal found.";
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)localPlayer == (Object)null)
			{
				return "No local player.";
			}
			long playerID = localPlayer.GetPlayerID();
			PlayerClanInfo playerClanInfo = WarfareManager.Instance?.Data?.GetPlayer(playerID);
			Clan clan = ((playerClanInfo == null || playerClanInfo.ClanId == 0) ? null : WarfareManager.Instance?.Data?.GetClan(playerClanInfo.ClanId));
			if (playerClanInfo == null || playerClanInfo.ClanId == 0 || clan == null)
			{
				return "You must be in a clan to set Clan portal mode.";
			}
			SetFehuClanSnapshot(val, playerClanInfo, clan, localPlayer);
			string[] obj2 = new string[6]
			{
				"FCW TargetPortal: DEBUG COMMAND set Clan mode clanId=",
				playerClanInfo.ClanId.ToString(),
				" clanName=",
				clan.Name,
				" zdo=",
				null
			};
			ZDOID uid = val.m_uid;
			obj2[5] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
			string text = string.Concat(obj2);
			Plugin.Log.LogInfo((object)text);
			WarfareHUD.ShowLeftNotification("Portal mode set to Clan: " + clan.Name);
			return text;
		}

		public unsafe static string DebugNearPortal()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			RefreshIfNeeded();
			TeleportWorld val = FindCurrentPortal();
			ZDO val2 = TryGetZdo(val);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)val == (Object)null || val2 == null)
			{
				return "FCW Portal Debug: no nearby portal found.";
			}
			if ((Object)localPlayer == (Object)null)
			{
				return "FCW Portal Debug: no local player.";
			}
			long playerID = localPlayer.GetPlayerID();
			long playerSteamId = GetPlayerSteamId(localPlayer, playerID);
			PlayerClanInfo playerClanInfo = WarfareManager.Instance?.Data?.GetPlayer(playerID);
			PortalAccessData portalAccessData = ReadPortalAccessData(val2, val, null);
			string reason;
			bool flag = HasPortalAccess(val2, playerID, playerClanInfo, out reason);
			PortalAccessData access;
			string reason2;
			bool flag2 = CanCurrentPlayerSeePortal(val2, out access, out reason2);
			string reason3;
			bool flag3 = HasPortalManagementAccess(val2, playerID, playerClanInfo, out reason3);
			string reason4;
			bool flag4 = HasPortalDestroyAccess(val2, playerID, playerClanInfo, out reason4);
			string[] array = new string[48];
			array[0] = "FCW Portal Debug\nPortal:\n- ZDO id=";
			ZDOID uid = val2.m_uid;
			array[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
			array[2] = "\n- native TargetPortal mode=";
			array[3] = ModeName(ReadTargetPortalModeValue(val2));
			array[4] = "\n- FCW mode=";
			array[5] = val2.GetString("FCW_TargetPortalMode", "");
			array[6] = "\n- displayed mode=";
			array[7] = ((portalAccessData.AccessType == "Clan") ? ("Clan: " + ClanLabel(portalAccessData)) : ModeName(ReadTargetPortalModeValue(val2)));
			array[8] = "\n- nativeOwnerId=";
			array[9] = ReadStoredTargetPortalOwnerId(val2).ToString();
			array[10] = "\n- nativeOwnerName=";
			array[11] = ReadPortalOwnerName(val2, "");
			array[12] = "\n- creatorOldId=";
			array[13] = val2.GetLong("FCW_TargetPortalCreatorId", 0L).ToString();
			array[14] = "\n- creatorName=";
			array[15] = val2.GetString("FCW_TargetPortalCreatorName", "");
			array[16] = "\n- assignedClanId=";
			array[17] = portalAccessData.ClanId.ToString();
			array[18] = "\n- assignedClanName=";
			array[19] = portalAccessData.ClanName;
			array[20] = "\n- assignedClanTag=";
			array[21] = portalAccessData.ClanTag;
			array[22] = "\nPlayer:\n- playerName=";
			array[23] = localPlayer.GetPlayerName();
			array[24] = "\n- playerId=";
			array[25] = playerID.ToString();
			array[26] = "\n- playerSteam=";
			array[27] = playerSteamId.ToString();
			array[28] = "\n- playerClanId=";
			array[29] = (playerClanInfo?.ClanId ?? 0).ToString();
			array[30] = "\n- isAdmin=";
			array[31] = IsAdminAccess(playerID).ToString().ToLowerInvariant();
			array[32] = "\nResults:\n- HasUseAccess=";
			array[33] = flag.ToString().ToLowerInvariant();
			array[34] = " reason=";
			array[35] = reason;
			array[36] = "\n- HasListAccess=";
			array[37] = flag2.ToString().ToLowerInvariant();
			array[38] = " reason=";
			array[39] = reason2;
			array[40] = "\n- HasChangeAccess=";
			array[41] = flag3.ToString().ToLowerInvariant();
			array[42] = " reason=";
			array[43] = reason3;
			array[44] = "\n- HasDestroyAccess=";
			array[45] = flag4.ToString().ToLowerInvariant();
			array[46] = " reason=";
			array[47] = reason4;
			string text = string.Concat(array);
			Plugin.Log.LogInfo((object)("[FCW TargetPortal] " + text));
			return text;
		}

		private static Assembly FindTargetPortalAssembly()
		{
			try
			{
				if (Chainloader.PluginInfos != null && Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.targetportal", out var value))
				{
					Assembly assembly = ((value == null) ? null : ((object)value.Instance)?.GetType().Assembly);
					if (IsRealTargetPortalAssembly(assembly))
					{
						LogTargetPortalPluginFound(value, assembly, "guid");
						return assembly;
					}
					LogInvalidTargetPortalAssembly("guid", assembly);
				}
				foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
				{
					string text = pluginInfo.Key ?? "";
					PluginInfo value2 = pluginInfo.Value;
					object obj;
					if (value2 == null)
					{
						obj = null;
					}
					else
					{
						BepInPlugin metadata = value2.Metadata;
						obj = ((metadata != null) ? metadata.Name : null);
					}
					if (obj == null)
					{
						obj = "";
					}
					string text2 = (string)obj;
					if (string.Equals(text2, "TargetPortal", StringComparison.OrdinalIgnoreCase) || text.IndexOf("targetportal", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("targetportal", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("target portal", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						PluginInfo value3 = pluginInfo.Value;
						Assembly assembly2 = ((value3 == null) ? null : ((object)value3.Instance)?.GetType().Assembly);
						if (IsRealTargetPortalAssembly(assembly2))
						{
							LogTargetPortalPluginFound(pluginInfo.Value, assembly2, "plugin:" + text);
							return assembly2;
						}
						LogInvalidTargetPortalAssembly("plugin:" + text, assembly2);
					}
				}
			}
			catch
			{
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly3 in assemblies)
			{
				string text3 = assembly3.GetName().Name ?? "";
				if (IsRealTargetPortalAssembly(assembly3))
				{
					LogOnce("found-name", "[FCW TargetPortal] TargetPortal found by assembly name: " + text3);
					return assembly3;
				}
			}
			return null;
		}

		private static bool IsRealTargetPortalAssembly(Assembly assembly)
		{
			if (assembly == null)
			{
				return false;
			}
			string text = assembly.GetName().Name ?? "";
			if (string.Equals(text, "FortecaClanWarfare", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "FortecaClanWarfare.Core", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "FortecaClanWarfare.UI", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (!string.Equals(text, "TargetPortal", StringComparison.OrdinalIgnoreCase))
			{
				return text.StartsWith("TargetPortal", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static void LogTargetPortalPluginFound(PluginInfo info, Assembly assembly, string source)
		{
			object obj;
			if (info == null)
			{
				obj = null;
			}
			else
			{
				BepInPlugin metadata = info.Metadata;
				obj = ((metadata != null) ? metadata.Name : null);
			}
			if (obj == null)
			{
				obj = assembly?.GetName().Name ?? "TargetPortal";
			}
			string text = (string)obj;
			object obj2;
			if (info == null)
			{
				obj2 = null;
			}
			else
			{
				BepInPlugin metadata2 = info.Metadata;
				obj2 = ((metadata2 == null) ? null : metadata2.Version?.ToString());
			}
			if (obj2 == null)
			{
				obj2 = assembly?.GetName().Version?.ToString() ?? "";
			}
			string text2 = (string)obj2;
			LogOnce("real-targetportal:" + source, "[FCW TargetPortal] Real TargetPortal plugin found: " + text + (string.IsNullOrEmpty(text2) ? "" : (" " + text2)));
		}

		private static void LogInvalidTargetPortalAssembly(string source, Assembly assembly)
		{
			string text = assembly?.GetName().Name ?? "null";
			LogOnce("invalid-targetportal:" + source + ":" + text, "[FCW TargetPortal] Ignored non-TargetPortal assembly from " + source + ": " + text);
		}

		private static IEnumerable<MethodInfo> FindHookMethods(Assembly assembly)
		{
			foreach (Type type in SafeGetTypes(assembly))
			{
				MethodInfo[] methods;
				try
				{
					methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array = methods;
				foreach (MethodInfo method in array)
				{
					if (!(method.ReturnType != typeof(bool)) && (!string.Equals(type.FullName, "TargetPortal.Map", StringComparison.Ordinal) || !string.Equals(method.Name, "HandlePortalClick", StringComparison.Ordinal)) && BoolHookNames.Any((string n) => string.Equals(method.Name, n, StringComparison.OrdinalIgnoreCase)))
					{
						yield return method;
					}
				}
			}
		}

		private static IEnumerable<MethodInfo> FindPortalListMethods(Assembly assembly)
		{
			foreach (Type item in SafeGetTypes(assembly))
			{
				MethodInfo[] methods;
				try
				{
					methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array = methods;
				foreach (MethodInfo method in array)
				{
					if (PortalListHookNames.Any((string n) => string.Equals(method.Name, n, StringComparison.OrdinalIgnoreCase)) && (HasMutablePortalListArg(method) || method.ReturnType == typeof(List<ZDO>) || method.ReturnType == typeof(IEnumerable<ZDO>)))
					{
						yield return method;
					}
				}
			}
		}

		private static IEnumerable<MethodInfo> FindToggleModeMethods(Assembly assembly)
		{
			foreach (Type item in SafeGetTypes(assembly))
			{
				if ((item.FullName ?? "").IndexOf("TogglePortalMode", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				MethodInfo[] methods;
				try
				{
					methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					if (string.Equals(methodInfo.Name, "Prefix", StringComparison.OrdinalIgnoreCase))
					{
						yield return methodInfo;
					}
				}
			}
		}

		private static IEnumerable<MethodInfo> FindModeChangeMethods(Assembly assembly)
		{
			foreach (Type item in SafeGetTypes(assembly))
			{
				if ((item.FullName ?? "").IndexOf("TargetPortal", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				MethodInfo[] methods;
				try
				{
					methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					if (string.Equals(methodInfo.Name, "SetPortalMode", StringComparison.OrdinalIgnoreCase) || string.Equals(methodInfo.Name, "OnPortalModeChange", StringComparison.OrdinalIgnoreCase))
					{
						yield return methodInfo;
					}
				}
			}
		}

		private static IEnumerable<MethodInfo> FindHoverTextMethods(Assembly assembly)
		{
			foreach (Type item in SafeGetTypes(assembly))
			{
				if ((item.FullName ?? "").IndexOf("TargetPortal", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				MethodInfo[] methods;
				try
				{
					methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					if (!(methodInfo.ReturnType == typeof(string)))
					{
						continue;
					}
					if (!string.Equals(methodInfo.Name, "GetHoverText", StringComparison.OrdinalIgnoreCase) && !string.Equals(methodInfo.Name, "SquashPortalMode", StringComparison.OrdinalIgnoreCase) && methodInfo.Name.IndexOf("Hover", StringComparison.OrdinalIgnoreCase) < 0)
					{
						Type? declaringType = methodInfo.DeclaringType;
						if ((object)declaringType == null || !(declaringType.FullName?.IndexOf("OverrideHoverText", StringComparison.OrdinalIgnoreCase) >= 0))
						{
							continue;
						}
					}
					yield return methodInfo;
				}
			}
		}

		private static IEnumerable<MethodInfo> FindTraceMethods(Assembly assembly)
		{
			string[] names = new string[8] { "TogglePortalMode", "SetPortalMode", "OnPortalModeChange", "SetInitialPortalMode", "UpdatePortalMode", "UpdatePortalText", "Interact", "GetHoverText" };
			foreach (Type item in SafeGetTypes(assembly))
			{
				if ((item.FullName ?? "").IndexOf("TargetPortal", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				MethodInfo[] methods;
				try
				{
					methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					string methodName = methodInfo.Name ?? "";
					string declaring = methodInfo.DeclaringType?.FullName ?? "";
					if (names.Any((string n) => string.Equals(methodName, n, StringComparison.OrdinalIgnoreCase) || declaring.IndexOf(n, StringComparison.OrdinalIgnoreCase) >= 0) || methodName.IndexOf("PortalMode", StringComparison.OrdinalIgnoreCase) >= 0 || methodName.IndexOf("PortalText", StringComparison.OrdinalIgnoreCase) >= 0 || methodName.IndexOf("Hover", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						yield return methodInfo;
					}
				}
			}
		}

		private static bool HasMutablePortalListArg(MethodInfo method)
		{
			ParameterInfo[] parameters = method.GetParameters();
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				if (parameterType == typeof(List<ZDO>) || parameterType == typeof(IList<ZDO>))
				{
					return true;
				}
			}
			return false;
		}

		private static TeleportWorld FindTeleportWorldArg(object[] args)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			if (args == null)
			{
				return null;
			}
			foreach (object obj in args)
			{
				TeleportWorld val = (TeleportWorld)((obj is TeleportWorld) ? obj : null);
				if (val != null)
				{
					return val;
				}
			}
			foreach (object obj2 in args)
			{
				Component val2 = (Component)((obj2 is Component) ? obj2 : null);
				if (val2 != null)
				{
					TeleportWorld component = val2.GetComponent<TeleportWorld>();
					if ((Object)component != (Object)null)
					{
						return component;
					}
				}
			}
			return FindCurrentPortal();
		}

		private static IEnumerable<Type> SafeGetTypes(Assembly assembly)
		{
			try
			{
				return assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.Where((Type t) => t != null);
			}
			catch
			{
				return Array.Empty<Type>();
			}
		}

		public static TeleportWorld FindCurrentPortal(float maxDistance = 6f)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)localPlayer == (Object)null)
			{
				return null;
			}
			TeleportWorld[] array = Object.FindObjectsOfType<TeleportWorld>();
			TeleportWorld result = null;
			float num = maxDistance;
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = Vector3.Distance(((Component)array[i]).transform.position, ((Component)localPlayer).transform.position);
				if (num2 < num)
				{
					num = num2;
					result = array[i];
				}
			}
			return result;
		}

		public static string GetPortalRestrictionText(TeleportWorld portal)
		{
			return FormatRestriction(ReadPortalAccessData(TryGetZdo(portal), portal, null));
		}

		public static string RewriteHoverText(TeleportWorld portal, string original)
		{
			PortalAccessData portalAccessData = ReadPortalAccessData(TryGetZdo(portal), portal, null);
			string text = original ?? "";
			if (portalAccessData.AccessType != "Clan")
			{
				return text;
			}
			return ReplaceClanHoverMode(text, ClanLabel(portalAccessData));
		}

		public static bool IsFehuClansMode(TeleportWorld portal)
		{
			return ReadPortalAccessData(TryGetZdo(portal), portal, null).AccessType == "Clan";
		}

		public static bool TryHandleModeToggle(TeleportWorld portal)
		{
			return false;
		}

		private static bool IsFehuCarrierMode(string currentTpMode, string hover)
		{
			return ModeMatches(currentTpMode, hover, "Admin");
		}

		private static bool ModeMatches(string currentTpMode, string hover, string mode)
		{
			if (string.Equals(currentTpMode, mode, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return (hover ?? "").IndexOf("[" + mode, StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static string ReadTargetPortalMode(ZDO zdo, string hover)
		{
			if (zdo != null)
			{
				string text = ModeName(ReadTargetPortalModeValue(zdo));
				if (!string.Equals(text, "Unknown", StringComparison.OrdinalIgnoreCase))
				{
					return text;
				}
			}
			string text2 = hover ?? "";
			int num = text2.IndexOf('[');
			int num2 = ((num >= 0) ? text2.IndexOf(']', num) : (-1));
			if (num >= 0 && num2 > num)
			{
				string text3 = text2.Substring(num + 1, num2 - num - 1);
				string[] array = new string[5] { "Public", "Private", "Group", "Admin", "Guild" };
				foreach (string text4 in array)
				{
					if (text3.StartsWith(text4, StringComparison.OrdinalIgnoreCase))
					{
						return text4;
					}
				}
			}
			return "Unknown";
		}

		private static int ReadTargetPortalModeValue(ZDO zdo)
		{
			if (zdo == null)
			{
				return -1;
			}
			int num = zdo.GetInt("Target Portal PortalMode", -1);
			if (num < 0)
			{
				num = zdo.GetInt("TargetPortal PortalMode", -1);
			}
			return num;
		}

		private static string ModeName(int mode)
		{
			return mode switch
			{
				0 => "Public", 
				1 => "Private", 
				2 => "Group", 
				3 => "Admin", 
				4 => "Guild", 
				_ => "Unknown", 
			};
		}

		private static List<string> BuildPortalCycle(ZDO zdo, PlayerClanInfo player, Clan clan, long playerId)
		{
			List<string> list = new List<string>();
			Plugin.Log.LogInfo((object)"[FCW PortalModes] REBUILD START");
			list.Add("Public");
			Plugin.Log.LogInfo((object)"[FCW PortalModes] Public add=true reason=always");
			list.Add("Private");
			Plugin.Log.LogInfo((object)"[FCW PortalModes] Private add=true reason=always");
			bool flag = HasGroupsIntegration();
			string text = (flag ? ReadPortalOwnerName(zdo, "Groups") : "");
			Plugin.Log.LogInfo((object)("[FCW PortalModes] Group add=" + flag.ToString().ToLowerInvariant() + " reason=" + (flag ? "Groups integration active" : "Groups integration unavailable") + " groupName=" + text));
			if (flag)
			{
				list.Add("Group");
			}
			bool flag2 = player != null && player.ClanId != 0 && clan != null;
			Plugin.Log.LogInfo((object)("[FCW PortalModes] Clan add=" + flag2.ToString().ToLowerInvariant() + " reason=" + (flag2 ? "current FCW clan resolved" : "no current FCW clan") + " clanId=" + (player?.ClanId ?? 0) + " clanName=" + clan?.Name + " clanTag=" + clan?.Tag));
			if (flag2)
			{
				list.Add("Clan");
			}
			bool flag3 = IsAdminAccess(playerId);
			Plugin.Log.LogInfo((object)("[FCW PortalModes] Admin add=" + flag3.ToString().ToLowerInvariant() + " reason=" + (flag3 ? "FCW admin access" : "not an admin")));
			if (flag3)
			{
				list.Add("Admin");
			}
			Plugin.Log.LogInfo((object)"[FCW PortalModes] Guild add=false reason=reserved for FCW Clan mode guildName=");
			Plugin.Log.LogInfo((object)("[FCW PortalModes] FINAL LIST=" + string.Join(" -> ", list.ToArray())));
			return list;
		}

		private static int ModeValue(string mode)
		{
			return mode switch
			{
				"Public" => 0, 
				"Private" => 1, 
				"Group" => 2, 
				"Admin" => 3, 
				"Guild" => 4, 
				_ => 0, 
			};
		}

		private static string ReadPortalOwnerName(ZDO zdo, string fallback)
		{
			if (zdo == null)
			{
				return fallback;
			}
			string text = zdo.GetString("Target Portal PortalOwnerName", "");
			if (string.IsNullOrWhiteSpace(text))
			{
				text = zdo.GetString("TargetPortal PortalOwnerName", "");
			}
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return fallback;
		}

		private static void LogModeToggle(ZDO zdo, string currentTpMode, string currentFcwMode, string nextMode, PlayerClanInfo player, Clan clan)
		{
			string text = "";
			if (zdo != null)
			{
				text = zdo.GetString("Target Portal PortalOwnerName", "");
				if (string.IsNullOrWhiteSpace(text))
				{
					text = zdo.GetString("TargetPortal PortalOwnerName", "");
				}
				if (string.IsNullOrWhiteSpace(text))
				{
					text = zdo.GetString("ownerName", "");
				}
			}
			string text2 = ((clan != null) ? (clan.Name + " [" + clan.Tag + "]") : ((player != null && player.ClanId != 0) ? ("ClanId " + player.ClanId) : "None"));
			Plugin.Log.LogInfo((object)("[FCW TargetPortal]\ncurrent TP mode = " + currentTpMode + "\ncurrent FCW mode = " + currentFcwMode + "\nnext mode = " + nextMode + "\nportal zdo = " + ((zdo != null) ? ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString() : "null") + "\nowner = " + text + "\nclan = " + text2));
		}

		private static void LogPortalCycle(string currentMode, bool fcwClan, string nextMode)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			PlayerClanInfo playerClanInfo = ((!((Object)localPlayer != (Object)null)) ? null : WarfareManager.Instance?.Data?.GetPlayer(localPlayer.GetPlayerID()));
			Clan clan = ((playerClanInfo == null || playerClanInfo.ClanId == 0) ? null : WarfareManager.Instance?.Data?.GetClan(playerClanInfo.ClanId));
			string text = ((clan != null) ? (clan.Name + " [" + clan.Tag + "]") : "none");
			Plugin.Log.LogInfo((object)("[FCW TargetPortal] Cycle current=" + currentMode + " fcwClan=" + fcwClan.ToString().ToLowerInvariant() + " playerClan=" + (playerClanInfo?.ClanId ?? 0) + "/" + text + " next=" + nextMode));
			if (fcwClan && !string.Equals(nextMode, "Clan", StringComparison.OrdinalIgnoreCase))
			{
				Plugin.Log.LogInfo((object)("[FCW TargetPortal] Exit Clan mode next=" + nextMode));
			}
		}

		private static bool IsShiftDown()
		{
			if (!Input.GetKey((KeyCode)304))
			{
				return Input.GetKey((KeyCode)303);
			}
			return true;
		}

		private static bool HasGroupsIntegration()
		{
			return Chainloader.PluginInfos.Keys.Any((string guid) => guid.IndexOf("groups", StringComparison.OrdinalIgnoreCase) >= 0);
		}

		private static bool HasGuildsIntegration()
		{
			return Chainloader.PluginInfos.Keys.Any((string guid) => guid.IndexOf("guilds", StringComparison.OrdinalIgnoreCase) >= 0);
		}

		private static void SetNormalTargetPortalMode(ZDO zdo, int mode, long playerId, Player player)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			EnsurePortalCreatorMetadata(zdo, player, playerId);
			string text = (((Object)player != (Object)null) ? player.GetPlayerName() : "");
			zdo.Set("Target Portal PortalMode", mode);
			zdo.Set("TargetPortal PortalMode", mode);
			zdo.Set("Target Portal PortalOwnerId", playerId.ToString());
			zdo.Set("TargetPortal PortalOwnerId", playerId.ToString());
			zdo.Set("Target Portal PortalOwnerName", text);
			zdo.Set("TargetPortal PortalOwnerName", text);
		}

		private static void LogPortalModeChanged(string oldMode, string newMode, int clanId, string clanName)
		{
			Plugin.Log.LogInfo((object)("[FCW TargetPortal] Mode changed old=" + oldMode + " new=" + newMode + " clanId=" + clanId + " clanName=" + clanName));
		}

		private static void ClearFehuMode(ZDO zdo)
		{
			zdo.Set("FCW_TargetPortalMode", "");
			zdo.Set("FCW_TargetPortalClanId", 0);
			zdo.Set("FCW_TargetPortalClanName", "");
			zdo.Set("FCW_TargetPortalClanTag", "");
			zdo.Set("FCW_TargetPortalOwnerPlayerId", 0L);
			zdo.Set("FCW_TargetPortalOwnerName", "");
			zdo.Set("FCW_PortalClanRank", "");
			zdo.Set("FCW_PortalClanRankValue", 0);
			zdo.Set("FCW_PortalFreebornId", 0L);
			zdo.Set("FCW_PortalFreebornName", "");
		}

		private static void DeactivateClanModeForCycle(ZDO zdo)
		{
			ClearFehuMode(zdo);
		}

		private static void ClearTargetPortalClanOwner(ZDO zdo)
		{
			zdo.Set("Target Portal PortalOwnerId", "");
			zdo.Set("TargetPortal PortalOwnerId", "");
			zdo.Set("Target Portal PortalOwnerName", "");
			zdo.Set("TargetPortal PortalOwnerName", "");
		}

		private static void SetFehuClanSnapshot(ZDO zdo, PlayerClanInfo player, Clan clan, Player localPlayer)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			EnsurePortalCreatorMetadata(zdo, localPlayer, player.PlayerId);
			string text = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : (player.PlayerName ?? ""));
			if (!IsSameClanSnapshot(zdo, player, clan, text))
			{
				zdo.Set("Target Portal PortalMode", 4);
				zdo.Set("TargetPortal PortalMode", 4);
				zdo.Set("Target Portal PortalOwnerId", player.PlayerId.ToString());
				zdo.Set("TargetPortal PortalOwnerId", player.PlayerId.ToString());
				zdo.Set("Target Portal PortalOwnerName", "Clan: " + clan.Name);
				zdo.Set("TargetPortal PortalOwnerName", "Clan: " + clan.Name);
				zdo.Set("FCW_TargetPortalMode", "Clan");
				zdo.Set("FCW_TargetPortalClanId", player.ClanId);
				zdo.Set("FCW_TargetPortalClanTag", clan.Tag ?? "");
				zdo.Set("FCW_TargetPortalClanName", clan.Name ?? "");
				zdo.Set("FCW_TargetPortalOwnerPlayerId", player.PlayerId);
				zdo.Set("FCW_TargetPortalOwnerName", text ?? "");
				zdo.Set("FCW_PortalClanRank", "");
				zdo.Set("FCW_PortalClanRankValue", 0);
				zdo.Set("FCW_PortalFreebornId", 0L);
			}
		}

		private static bool IsSameClanSnapshot(ZDO zdo, PlayerClanInfo player, Clan clan, string ownerName)
		{
			if (string.Equals(zdo.GetString("FCW_TargetPortalMode", ""), "Clan", StringComparison.OrdinalIgnoreCase) && ReadTargetPortalModeValue(zdo) == 4 && zdo.GetInt("FCW_TargetPortalClanId", 0) == player.ClanId && string.Equals(zdo.GetString("FCW_TargetPortalClanName", ""), clan.Name ?? "", StringComparison.Ordinal) && zdo.GetLong("FCW_TargetPortalOwnerPlayerId", 0L) == player.PlayerId)
			{
				return string.Equals(zdo.GetString("FCW_TargetPortalOwnerName", ""), ownerName ?? "", StringComparison.Ordinal);
			}
			return false;
		}

		public static string SetPortalRestriction(TeleportWorld portal, string accessType, PlayerClanInfo player, Clan clan, ClanRank requiredRank = ClanRank.Member)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			if ((Object)portal == (Object)null)
			{
				return "<color=red>No portal selected.</color>";
			}
			Player localPlayer = Player.m_localPlayer;
			ZDO val = TryGetZdo(portal);
			if ((Object)localPlayer == (Object)null || val == null || player == null)
			{
				return "<color=red>Portal data not available.</color>";
			}
			long playerID = localPlayer.GetPlayerID();
			if (!CanEditPortal(val, playerID))
			{
				return "<color=red>Only portal owner or admin can change Fehu portal access.</color>";
			}
			string text = NormalizeAccessType(accessType);
			switch (text)
			{
			case "None":
				ClearFehuMode(val);
				return "<color=green>Fehu portal access set to None.</color>";
			case "Clan":
			case "ClanRank":
				if (player.ClanId == 0 || clan == null)
				{
					return "<color=red>You must be in a clan to set clan portal access.</color>";
				}
				break;
			}
			if (text == "Clan" || text == "ClanRank")
			{
				SetFehuClanSnapshot(val, player, clan, localPlayer);
				val.Set("FCW_PortalClanRank", requiredRank.ToString());
				val.Set("FCW_PortalClanRankValue", (int)requiredRank);
			}
			return "<color=green>Fehu portal access set to " + FormatRestriction(ReadPortalAccessData(val, portal, null)) + ".</color>";
		}

		private static bool CanEditPortal(ZDO zdo, long playerId)
		{
			Player localPlayer = Player.m_localPlayer;
			EnsurePortalCreatorMetadata(zdo, localPlayer, playerId);
			PlayerClanInfo player = WarfareManager.Instance?.Data?.GetPlayer(playerId);
			string reason;
			return CanChangeTargetPortalMode(zdo, playerId, player, out reason);
		}

		private static void TryInitializePortalCreator(object instance, object[] args)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			try
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)localPlayer == (Object)null))
				{
					EnsurePortalCreatorMetadata(FindPortalZdo(instance, args) ?? TryGetZdo(FindTeleportWorldArg(args)), localPlayer, localPlayer.GetPlayerID());
				}
			}
			catch (Exception ex)
			{
				LogOnce("creator-init-ex:" + ex.GetType().Name, "[FCW TargetPortal] Creator initialization failed: " + ex.Message);
			}
		}

		private static void EnsurePortalCreatorMetadata(ZDO zdo, Player localPlayer, long playerId)
		{
			SyncOwnerMetadata(zdo, localPlayer, playerId);
		}

		private unsafe static void SyncOwnerMetadata(ZDO zdo, Player localPlayer, long playerId)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null)
			{
				return;
			}
			long playerSteamId = GetPlayerSteamId(localPlayer, playerId);
			string playerName = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : "");
			long num = ReadStoredTargetPortalOwnerId(zdo);
			if (num != 0L)
			{
				zdo.Set("TargetPortalProtection OwnerId", num.ToString());
			}
			long num2 = zdo.GetLong("FCW_TargetPortalCreatorId", 0L);
			string reason;
			if (num2 != 0L)
			{
				if (IsSamePortalOwner(localPlayer, zdo, playerId, playerSteamId, out reason))
				{
					NormalizeOwnerMetadata(zdo, playerSteamId, playerId, playerName);
				}
				return;
			}
			num2 = ReadStoredTargetPortalOwnerId(zdo);
			string text = ReadPortalOwnerName(zdo, "");
			string text2 = "TargetPortal owner";
			if (num2 == 0L && IsAdminAccess(playerId))
			{
				num2 = playerId;
				text = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : "");
				text2 = "admin repair";
			}
			if (num2 != 0L)
			{
				zdo.Set("FCW_TargetPortalCreatorId", num2);
				zdo.Set("FCW_TargetPortalCreatorName", text ?? "");
				if (IsSamePortalOwner(localPlayer, zdo, playerId, playerSteamId, out reason))
				{
					NormalizeOwnerMetadata(zdo, playerSteamId, playerId, playerName);
				}
				ManualLogSource log = Plugin.Log;
				string[] obj = new string[8] { "[FCW TargetPortal] Synced owner metadata portal=", null, null, null, null, null, null, null };
				ZDOID uid = zdo.m_uid;
				obj[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
				obj[2] = " owner=";
				obj[3] = num2.ToString();
				obj[4] = "/";
				obj[5] = text;
				obj[6] = " source=";
				obj[7] = text2;
				log.LogInfo((object)string.Concat(obj));
			}
		}

		private static bool IsTargetPortalPortal(ZDO zdo)
		{
			if (zdo != null)
			{
				if (ReadTargetPortalModeValue(zdo) < 0 && ReadStoredTargetPortalOwnerId(zdo) == 0L)
				{
					return !string.IsNullOrEmpty(zdo.GetString("FCW_TargetPortalMode", ""));
				}
				return true;
			}
			return false;
		}

		private static bool IsFcwVisibilityOverridePortal(ZDO zdo)
		{
			if (zdo == null)
			{
				return false;
			}
			if (string.Equals(zdo.GetString("FCW_TargetPortalMode", ""), "Clan", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (ReadTargetPortalModeValue(zdo) != 1)
			{
				return false;
			}
			if (ReadStoredTargetPortalOwnerId(zdo) == 0L && string.IsNullOrWhiteSpace(ReadPortalOwnerName(zdo, "")))
			{
				return zdo.GetLong("FCW_TargetPortalCreatorId", 0L) != 0;
			}
			return true;
		}

		private static object AddTargetPortalMapPin(ZDO portal, Type mapType)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object obj = AccessTools.Field(mapType?.Assembly.GetType("TargetPortal.AddMinimapPortalIcon", throwOnError: false), "pinType")?.GetValue(null);
				MethodInfo methodInfo = typeof(Minimap).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo method) => method.Name == "AddPin" && method.GetParameters().Length == 7 && method.ReturnType != typeof(void));
				if (methodInfo == null || obj == null)
				{
					return null;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				for (int num = 0; num < parameters.Length; num++)
				{
					Type parameterType = parameters[num].ParameterType;
					if (num == 0 && parameterType == typeof(Vector3))
					{
						array[num] = GetPortalPosition(portal);
					}
					else if (num == 1 && parameterType.IsEnum)
					{
						array[num] = Enum.ToObject(parameterType, Convert.ToInt32(obj));
					}
					else if (parameterType == typeof(string))
					{
						array[num] = portal.GetString("tag", "");
					}
					else if (parameterType == typeof(bool))
					{
						array[num] = false;
					}
					else if (parameterType == typeof(long))
					{
						array[num] = 0L;
					}
					else if (parameters[num].HasDefaultValue)
					{
						array[num] = parameters[num].DefaultValue;
					}
					else
					{
						array[num] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null);
					}
				}
				return methodInfo.Invoke(Minimap.instance, array);
			}
			catch (Exception ex)
			{
				LogOnce("add-fcw-map-pin:" + ex.GetType().Name, "[FCW TargetPortal] Could not add restored map pin: " + ex.Message);
				return null;
			}
		}

		private static IEnumerable<object> EnumerateDictionaryEntries(object dictionary)
		{
			if (!(dictionary is IEnumerable enumerable))
			{
				yield break;
			}
			foreach (object item in enumerable)
			{
				yield return item;
			}
		}

		private static object GetDictionaryEntryValue(object entry)
		{
			return entry?.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public)?.GetValue(entry, null);
		}

		private static void AddDictionaryEntry(object dictionary, object key, object value)
		{
			MethodInfo? obj = dictionary?.GetType().GetMethod("Add", BindingFlags.Instance | BindingFlags.Public);
			if (obj == null)
			{
				throw new InvalidOperationException("TargetPortal active pin dictionary does not expose Add.");
			}
			obj.Invoke(dictionary, new object[2] { key, value });
		}

		private static IEnumerable<ZDO> GetReceivedZdos()
		{
			object dictionary = AccessTools.Field(typeof(ZDOMan), "m_objectsByID")?.GetValue(ZDOMan.instance);
			foreach (object item in EnumerateDictionaryEntries(dictionary))
			{
				object dictionaryEntryValue = GetDictionaryEntryValue(item);
				ZDO val = (ZDO)((dictionaryEntryValue is ZDO) ? dictionaryEntryValue : null);
				if (val != null)
				{
					yield return val;
				}
			}
		}

		private static bool IsLocalPortalMapClient()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			return (Object)Player.m_localPlayer != (Object)null;
		}

		private static IEnumerable<ZDO> GetKnownTargetPortalPortals()
		{
			if (!(AccessTools.Field(FindTargetPortalAssembly()?.GetType("TargetPortal.TargetPortal", throwOnError: false), "knownPortals")?.GetValue(null) is IEnumerable enumerable))
			{
				yield break;
			}
			foreach (object item in enumerable)
			{
				ZDO val = (ZDO)((item is ZDO) ? item : null);
				if (val != null)
				{
					yield return val;
				}
			}
		}

		private static bool ContainsPortal(object activePins, ZDOID portalId)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return EnumerateDictionaryEntries(activePins).Any(delegate(object entry)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				object dictionaryEntryValue = GetDictionaryEntryValue(entry);
				ZDO val = (ZDO)((dictionaryEntryValue is ZDO) ? dictionaryEntryValue : null);
				return val != null && val.m_uid == portalId;
			});
		}

		private static bool IsInMinimapPinRegistry(object activePins, ZDOID portalId)
		{
			//IL_0035: 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)
			object targetPin = null;
			foreach (object item in EnumerateDictionaryEntries(activePins))
			{
				object dictionaryEntryValue = GetDictionaryEntryValue(item);
				ZDO val = (ZDO)((dictionaryEntryValue is ZDO) ? dictionaryEntryValue : null);
				if (val != null && val.m_uid == portalId)
				{
					targetPin = item.GetType().GetProperty("Key", BindingFlags.Instance | BindingFlags.Public)?.GetValue(item, null);
					break;
				}
			}
			if (targetPin == null)
			{
				return false;
			}
			if (AccessTools.Field(typeof(Minimap), "m_pins")?.GetValue(Minimap.instance) is IEnumerable source)
			{
				return source.Cast<object>().Any((object pin) => pin == targetPin);
			}
			return false;
		}

		private static void LogMapStage(string stage, IEnumerable<ZDO> rawPortals, object activePins, string source)
		{
			List<ZDO> list = (rawPortals ?? EnumerateDictionaryEntries(activePins).Select(GetDictionaryEntryValue).OfType<ZDO>()).Where((ZDO portal) => portal != null).ToList();
			bool flag = list.Any((ZDO portal) => string.Equals(portal.GetString("FCW_TargetPortalMode", ""), "Clan", StringComparison.OrdinalIgnoreCase));
			Plugin.Log.LogInfo((object)("[FCW TargetPortal] LIST STAGE " + stage + " count=" + list.Count + " containsClanPortal=" + flag.ToString().ToLowerInvariant() + " source=" + source));
		}

		private unsafe static void LogClanPortalTrace(ZDO portal, PortalAccessData access, bool finalVisible, string addedStage, string reason)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			long playerId = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0);
			int valueOrDefault = (WarfareManager.Instance?.Data?.GetPlayer(playerId)?.ClanId).GetValueOrDefault();
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[16]
			{
				"[FCW TargetPortal] CLAN PORTAL TRACE id=", null, null, null, null, null, null, null, null, null,
				null, null, null, null, null, null
			};
			ZDOID uid = portal.m_uid;
			obj[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
			obj[2] = " tag=";
			obj[3] = portal.GetString("tag", "");
			obj[4] = " assignedClanId=";
			obj[5] = (access?.ClanId ?? 0).ToString();
			obj[6] = " playerClanId=";
			obj[7] = valueOrDefault.ToString();
			obj[8] = " allowed=";
			obj[9] = (CanCurrentPlayerSeePortal(portal, out var _, out var _) ? "true" : "false");
			obj[10] = " addedStage=";
			obj[11] = addedStage;
			obj[12] = " finalVisible=";
			obj[13] = finalVisible.ToString().ToLowerInvariant();
			obj[14] = " reason=";
			obj[15] = reason;
			log.LogInfo((object)string.Concat(obj));
		}

		private static Vector3 GetPortalPosition(ZDO portal)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(ZDO), "GetPosition", (Type[])null, (Type[])null);
				if (methodInfo != null && methodInfo.Invoke(portal, null) is Vector3 result)
				{
					return result;
				}
				if (AccessTools.Field(typeof(ZDO), "m_position")?.GetValue(portal) is Vector3 result2)
				{
					return result2;
				}
			}
			catch
			{
			}
			return Vector3.zero;
		}

		private static void LogPortalDecision(string action, ZDO zdo, bool allowed, string reason)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			long playerId = (((Object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0);
			PlayerClanInfo playerClanInfo = WarfareManager.Instance?.Data?.GetPlayer(playerId);
			PortalAccessData portalAccessData = ReadPortalAccessData(zdo, null, null);
			string text = ((portalAccessData.AccessType == "Clan") ? "Clan" : ModeName(ReadTargetPortalModeValue(zdo)));
			Plugin.Log.LogInfo((object)("[FCW TargetPortal] " + action + " CHECK mode=" + text + " fcwMode=" + ((zdo != null) ? zdo.GetString("FCW_TargetPortalMode", "") : null) + " player=" + ((localPlayer != null) ? localPlayer.GetPlayerName() : null) + " playerClanId=" + (playerClanInfo?.ClanId ?? 0) + " assignedClanId=" + (portalAccessData?.ClanId ?? 0) + " owner=" + ReadPortalOwnerName(zdo, "") + " allowed=" + allowed.ToString().ToLowerInvariant() + " reason=" + reason));
		}

		private static bool IsPortalOwner(ZDO zdo, long playerId)
		{
			Player player = FindPlayerById(playerId);
			string reason;
			return IsSamePortalOwner(player, zdo, playerId, GetPlayerSteamId(player, playerId), out reason);
		}

		private static bool IsSamePortalOwner(Player player, ZDO zdo, long playerId, long playerSteamId, out string reason)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			reason = "owner metadata missing";
			if (zdo == null || playerId == 0L)
			{
				return false;
			}
			if (IsAdminAccess(playerId))
			{
				reason = "admin bypass";
				return true;
			}
			string text = (((Object)player != (Object)null) ? player.GetPlayerName() : "");
			long num = zdo.GetLong("FCW_TargetPortalCreatorSteamId", 0L);
			long num2 = zdo.GetLong("FCW_TargetPortalCreatorPlayerId", 0L);
			long num3 = zdo.GetLong("FCW_TargetPortalCreatorId", 0L);
			long num4 = ReadStoredTargetPortalOwnerId(zdo);
			string text2 = zdo.GetString("FCW_TargetPortalCreatorName", "");
			string text3 = ReadPortalOwnerName(zdo, "");
			if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(text3) && string.Equals(text3, text, StringComparison.Ordinal))
			{
				reason = "owner name match";
				return true;
			}
			if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(text2) && string.Equals(text2, text, StringComparison.Ordinal))
			{
				reason = "creator name match";
				return true;
			}
			if ((num != 0L && num == playerSteamId) || (num2 != 0L && num2 == playerId))
			{
				reason = "stored owner identity";
				return true;
			}
			if (num3 != 0L && (num3 == playerSteamId || num3 == playerId))
			{
				reason = "legacy creator identity";
				return true;
			}
			if (num4 != 0L && (num4 == playerSteamId || num4 == playerId))
			{
				reason = "native owner identity";
				return true;
			}
			reason = "portal owner only";
			return false;
		}

		private unsafe static void NormalizeOwnerMetadata(ZDO zdo, long steamId, long playerId, string playerName)
		{
			//IL_008c: 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)
			if (zdo != null)
			{
				bool flag = false;
				if (steamId != 0L && zdo.GetLong("FCW_TargetPortalCreatorSteamId", 0L) == 0L)
				{
					zdo.Set("FCW_TargetPortalCreatorSteamId", steamId);
					flag = true;
				}
				if (playerId != 0L && zdo.GetLong("FCW_TargetPortalCreatorPlayerId", 0L) == 0L)
				{
					zdo.Set("FCW_TargetPortalCreatorPlayerId", playerId);
					flag = true;
				}
				if (!string.IsNullOrWhiteSpace(playerName) && string.IsNullOrWhiteSpace(zdo.GetString("FCW_TargetPortalCreatorName", "")))
				{
					zdo.Set("FCW_TargetPortalCreatorName", playerName);
					flag = true;
				}
				if (flag)
				{
					ManualLogSource log = Plugin.Log;
					string[] obj = new string[8] { "[FCW TargetPortal] Owner metadata normalized portal=", null, null, null, null, null, null, null };
					ZDOID uid = zdo.m_uid;
					obj[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
					obj[2] = " steam=";
					obj[3] = steamId.ToString();
					obj[4] = " playerId=";
					obj[5] = playerId.ToString();
					obj[6] = " name=";
					obj[7] = playerName;
					log.LogInfo((object)string.Concat(obj));
				}
			}
		}

		private static Player FindPlayerById(long playerId)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			if ((Object)localPlayer != (Object)null && localPlayer.GetPlayerID() == playerId)
			{
				return localPlayer;
			}
			try
			{
				return ((IEnumerable<Player>)Object.FindObjectsOfType<Player>()).FirstOrDefault((Func<Player, bool>)((Player candidate) => (Object)candidate != (Object)null && candidate.GetPlayerID() == playerId));
			}
			catch
			{
				return null;
			}
		}

		private static long GetPlayerSteamId(Player player, long playerId)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			try
			{
				if ((Object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer)
				{
					return ZNet.GetUID();
				}
			}
			catch
			{
			}
			return 0L;
		}

		private static bool LooksLikeSteamId(long value)
		{
			return value >= 10000000000000000L;
		}

		private static bool IsOwnerOrAdmin(ZDO zdo, long playerId)
		{
			if (!IsAdminAccess(playerId))
			{
				return IsPortalOwner(zdo, playerId);
			}
			return true;
		}

		private unsafe static bool HasPortalAccess(ZDO zdo, long playerId, PlayerClanInfo player, out string reason)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (m