Decompiled source of BasicEnemySync v1.0.1

EnemySyncing.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 BepInEx;
using EnemySyncing.Boss;
using EnemySyncing.Components;
using EnemySyncing.Networking;
using EnemySyncing.Patches;
using GlobalEnums;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using InControl;
using Microsoft.CodeAnalysis;
using SSMP.Api.Client;
using SSMP.Api.Client.Networking;
using SSMP.Api.Server;
using SSMP.Api.Server.Networking;
using SSMP.Math;
using SSMP.Networking.Packet;
using SSMP.Networking.Packet.Data;
using SSMP.Util;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EnemySyncing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+3adc5a0dabcb1c712242ef3fc185501d2728423b")]
[assembly: AssemblyProduct("EnemySyncing")]
[assembly: AssemblyTitle("EnemySyncing")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EnemySyncing
{
	public class ClientAddon : ClientAddon
	{
		public class RemoteCocoonResponder : MonoBehaviour, IHitResponder
		{
			public ushort OwnerPlayerId;

			public HitResponse Hit(HitInstance hitInstance)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				if (!hitInstance.IsHeroDamage)
				{
					return default(HitResponse);
				}
				CocoonDamagePacket packet = new CocoonDamagePacket
				{
					TargetPlayerId = OwnerPlayerId,
					DamageDealt = hitInstance.DamageDealt
				};
				Instance?.SendPacket(EnemySyncPacketId.CocoonDamage, (IPacketData)(object)packet);
				EnemyHitEffectsRegular component = ((Component)this).GetComponent<EnemyHitEffectsRegular>();
				if ((Object)(object)component != (Object)null)
				{
					component.ReceiveHitEffect(hitInstance);
				}
				return default(HitResponse);
			}
		}

		private IClientApi? _clientApi;

		private IClientAddonNetworkSender<EnemySyncPacketId>? _clientSender;

		private ushort _localPlayerId = ushort.MaxValue;

		public ushort SceneOwnerId = ushort.MaxValue;

		public readonly Dictionary<string, Vector3> LastKnownPositions = new Dictionary<string, Vector3>();

		public readonly Dictionary<string, float> LastKnownScales = new Dictionary<string, float>();

		public readonly Dictionary<string, bool> LastKnownActiveStates = new Dictionary<string, bool>();

		public readonly Dictionary<string, ushort> LastKnownControllers = new Dictionary<string, ushort>();

		public readonly Dictionary<string, ushort> LastKnownTargets = new Dictionary<string, ushort>();

		public readonly Dictionary<string, GameObject> PrefabCache = new Dictionary<string, GameObject>();

		public static readonly HashSet<string> FailedPrefabSearches = new HashSet<string>();

		public static readonly HashSet<string> DeadEnemies = new HashSet<string>();

		public static readonly Dictionary<string, HashSet<string>> SceneDeadEnemies = new Dictionary<string, HashSet<string>>();

		public static bool IsApplyingRemoteDeath = false;

		public static bool IsLocalPlayerCocooned = false;

		public static int LocalPlayerCocoonHp = 25;

		public static bool IsSuiciding = false;

		public static Vector3 LocalCocoonSafePosition = Vector3.zero;

		public readonly HashSet<ushort> CocoonedPlayers = new HashSet<ushort>();

		public static int originalHeroLayer = 0;

		public static int originalHeroBoxLayer = 0;

		public static readonly HashSet<Renderer> originalEnabledRenderers = new HashSet<Renderer>();

		private GameObject? localCocoonVisual;

		private static Sprite? _cachedCocoonSprite;

		private static readonly Dictionary<GameObject, List<Renderer>> RemotePlayerOriginalRenderers = new Dictionary<GameObject, List<Renderer>>();

		public static ClientAddon? Instance { get; private set; }

		public IClientApi? Api => _clientApi;

		protected override string Name => "EnemySyncingAddon";

		protected override string Version => "1.0.1";

		public override bool NeedsNetwork => true;

		public override uint ApiVersion => 1u;

		public ushort LocalPlayerId => _localPlayerId;

		public bool IsLocalSceneOwner
		{
			get
			{
				if (SceneOwnerId != _localPlayerId && SceneOwnerId != ushort.MaxValue)
				{
					return GetPlayersInSceneCount() <= 1;
				}
				return true;
			}
		}

		public bool IsSceneOwner => IsLocalSceneOwner;

		public int GetPlayersInSceneCount()
		{
			int num = 1;
			foreach (IClientPlayer item in GetPlayersInScene())
			{
				_ = item;
				num++;
			}
			return num;
		}

		public override void Initialize(IClientApi clientApi)
		{
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			Instance = this;
			_clientApi = clientApi;
			IClientAddonNetworkReceiver<EnemySyncPacketId> networkReceiver = clientApi.NetClient.GetNetworkReceiver<EnemySyncPacketId>((ClientAddon)(object)this, (Func<EnemySyncPacketId, IPacketData>)InstantiatePacket);
			_clientSender = clientApi.NetClient.GetNetworkSender<EnemySyncPacketId>((ClientAddon)(object)this);
			networkReceiver.RegisterPacketHandler<EnemyPositionPacket>(EnemySyncPacketId.EnemyPosition, (GenericClientPacketHandler<EnemyPositionPacket>)HandleEnemyPosition);
			networkReceiver.RegisterPacketHandler<EnemyAnimationPacket>(EnemySyncPacketId.EnemyAnimation, (GenericClientPacketHandler<EnemyAnimationPacket>)HandleEnemyAnimation);
			networkReceiver.RegisterPacketHandler<EnemyTargetPacket>(EnemySyncPacketId.EnemyTarget, (GenericClientPacketHandler<EnemyTargetPacket>)HandleEnemyTarget);
			networkReceiver.RegisterPacketHandler<EnemyTakeDamagePacket>(EnemySyncPacketId.EnemyTakeDamage, (GenericClientPacketHandler<EnemyTakeDamagePacket>)HandleEnemyTakeDamage);
			networkReceiver.RegisterPacketHandler<EnemyHpPacket>(EnemySyncPacketId.EnemyHp, (GenericClientPacketHandler<EnemyHpPacket>)HandleEnemyHp);
			networkReceiver.RegisterPacketHandler<EnemyDiePacket>(EnemySyncPacketId.EnemyDie, (GenericClientPacketHandler<EnemyDiePacket>)HandleEnemyDie);
			networkReceiver.RegisterPacketHandler<SpawnProjectilePacket>(EnemySyncPacketId.SpawnProjectile, (GenericClientPacketHandler<SpawnProjectilePacket>)HandleSpawnProjectile);
			networkReceiver.RegisterPacketHandler<PlayerIdNotifyPacket>(EnemySyncPacketId.PlayerIdNotify, (GenericClientPacketHandler<PlayerIdNotifyPacket>)HandlePlayerIdNotify);
			networkReceiver.RegisterPacketHandler<EnemyFsmStatePacket>(EnemySyncPacketId.EnemyFsmState, (GenericClientPacketHandler<EnemyFsmStatePacket>)HandleEnemyFsmState);
			networkReceiver.RegisterPacketHandler<BossSyncRequestPacket>(EnemySyncPacketId.BossSyncRequest, (GenericClientPacketHandler<BossSyncRequestPacket>)HandleBossSyncRequest);
			networkReceiver.RegisterPacketHandler<PlayerCocoonPacket>(EnemySyncPacketId.PlayerCocoon, (GenericClientPacketHandler<PlayerCocoonPacket>)HandlePlayerCocoon);
			networkReceiver.RegisterPacketHandler<CocoonDamagePacket>(EnemySyncPacketId.CocoonDamage, (GenericClientPacketHandler<CocoonDamagePacket>)HandleCocoonDamage);
			networkReceiver.RegisterPacketHandler<SceneOwnerNotifyPacket>(EnemySyncPacketId.SceneOwnerNotify, (GenericClientPacketHandler<SceneOwnerNotifyPacket>)HandleSceneOwnerNotify);
			networkReceiver.RegisterPacketHandler<VerifyEnemyDieRequestPacket>(EnemySyncPacketId.VerifyEnemyDieRequest, (GenericClientPacketHandler<VerifyEnemyDieRequestPacket>)HandleVerifyEnemyDieRequest);
			clientApi.ClientManager.ConnectEvent += OnClientConnect;
			clientApi.ClientManager.DisconnectEvent += OnClientDisconnect;
			SceneManager.activeSceneChanged += OnSceneChanged;
			GameObject val = new GameObject("EnemySyncManager");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<SyncManager>();
			ApplyHarmonyPatches();
		}

		private void ApplyHarmonyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new Harmony("com.ssmp.enemysyncing").PatchAll(typeof(ClientAddon).Assembly);
				Debug.Log((object)"[EnemySync] Harmony patches applied successfully.");
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[EnemySync] Failed to apply Harmony patches: {arg}");
			}
		}

		public void UnsubscribeFromAllBosses()
		{
			foreach (EnemyAvatar value in EnemyAvatar.ActiveAvatars.Values)
			{
				if ((Object)(object)value != (Object)null && value.isBoss)
				{
					BossSyncRequestPacket packet = new BossSyncRequestPacket
					{
						EnemyName = value.enemyName,
						Subscribe = false
					};
					SendPacket(EnemySyncPacketId.BossSyncRequest, (IPacketData)(object)packet);
					value.isController = false;
					value.controllerId = ushort.MaxValue;
					value.TargetPlayerId = ushort.MaxValue;
				}
			}
		}

		private void OnSceneChanged(Scene current, Scene next)
		{
			UnsubscribeFromAllBosses();
			LastKnownControllers.Clear();
			LastKnownTargets.Clear();
			LastKnownPositions.Clear();
			LastKnownScales.Clear();
			LastKnownActiveStates.Clear();
			EnemyAvatar.ActiveAvatars.Clear();
			DeadEnemies.Clear();
			PrefabCache.Clear();
			FailedPrefabSearches.Clear();
			SceneOwnerId = ushort.MaxValue;
			Debug.Log((object)("[EnemySync] Scene changed to '" + ((Scene)(ref next)).name + "'. Cleared state cache."));
		}

		private void OnClientConnect()
		{
			_localPlayerId = ushort.MaxValue;
			SendPacket(EnemySyncPacketId.RequestPlayerId, (IPacketData)(object)new RequestPlayerIdPacket());
			Debug.Log((object)"[EnemySync] Connected to server. Requested player ID.");
		}

		private void OnClientDisconnect()
		{
			_localPlayerId = ushort.MaxValue;
			CocoonedPlayers.Clear();
			DeadEnemies.Clear();
			PrefabCache.Clear();
			Debug.Log((object)"[EnemySync] Disconnected from server.");
		}

		private void HandlePlayerIdNotify(PlayerIdNotifyPacket packet)
		{
			_localPlayerId = packet.AssignedPlayerId;
			Debug.Log((object)$"[EnemySync] Assigned local player ID: {_localPlayerId}");
		}

		private IPacketData InstantiatePacket(EnemySyncPacketId id)
		{
			return (IPacketData)(id switch
			{
				EnemySyncPacketId.EnemyPosition => new PacketDataCollection<EnemyPositionPacket>(), 
				EnemySyncPacketId.EnemyAnimation => new EnemyAnimationPacket(), 
				EnemySyncPacketId.EnemyTarget => new EnemyTargetPacket(), 
				EnemySyncPacketId.EnemyTakeDamage => new EnemyTakeDamagePacket(), 
				EnemySyncPacketId.EnemyHp => new EnemyHpPacket(), 
				EnemySyncPacketId.EnemyDie => new EnemyDiePacket(), 
				EnemySyncPacketId.SpawnProjectile => new SpawnProjectilePacket(), 
				EnemySyncPacketId.RequestPlayerId => new RequestPlayerIdPacket(), 
				EnemySyncPacketId.PlayerIdNotify => new PlayerIdNotifyPacket(), 
				EnemySyncPacketId.EnemyFsmState => new EnemyFsmStatePacket(), 
				EnemySyncPacketId.BossSyncRequest => new BossSyncRequestPacket(), 
				EnemySyncPacketId.PlayerCocoon => new PlayerCocoonPacket(), 
				EnemySyncPacketId.CocoonDamage => new CocoonDamagePacket(), 
				EnemySyncPacketId.SceneOwnerNotify => new SceneOwnerNotifyPacket(), 
				EnemySyncPacketId.VerifyEnemyDieRequest => new VerifyEnemyDieRequestPacket(), 
				_ => throw new ArgumentException("Unknown packet ID"), 
			});
		}

		private void HandleSceneOwnerNotify(SceneOwnerNotifyPacket packet)
		{
			SceneOwnerId = packet.SceneOwnerId;
			Debug.Log((object)$"[EnemySync] Scene Owner updated: {SceneOwnerId} (isLocalOwner: {IsLocalSceneOwner})");
		}

		private void HandleVerifyEnemyDieRequest(VerifyEnemyDieRequestPacket packet)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!IsLocalSceneOwner || string.IsNullOrEmpty(packet.EnemyName))
			{
				return;
			}
			Debug.Log((object)$"[EnemySync] Scene Owner verifying death request for '{packet.EnemyName}' from player {packet.RequesterPlayerId}");
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if ((Object)(object)enemyAvatar != (Object)null)
			{
				HealthManager component = ((Component)enemyAvatar).GetComponent<HealthManager>();
				if ((Object)(object)component != (Object)null)
				{
					component.hp = 0;
				}
			}
			DeadEnemies.Add(packet.EnemyName);
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (!string.IsNullOrEmpty(name))
			{
				if (!SceneDeadEnemies.TryGetValue(name, out HashSet<string> value))
				{
					value = new HashSet<string>();
					SceneDeadEnemies[name] = value;
				}
				value.Add(packet.EnemyName);
			}
			EnemyDiePacket packet2 = new EnemyDiePacket
			{
				EnemyName = packet.EnemyName,
				AttackDirection = packet.AttackDirection,
				AttackType = packet.AttackType
			};
			SendPacket(EnemySyncPacketId.EnemyDie, (IPacketData)(object)packet2);
		}

		public void SendPacket(EnemySyncPacketId packetId, IPacketData packet)
		{
			if (_clientSender != null && ((ClientAddon)this).ClientApi != null && ((ClientAddon)this).ClientApi.NetClient != null && ((ClientAddon)this).ClientApi.NetClient.IsConnected)
			{
				if (packetId == EnemySyncPacketId.EnemyPosition)
				{
					_clientSender.SendCollectionData<EnemyPositionPacket>(packetId, (EnemyPositionPacket)(object)packet);
				}
				else
				{
					_clientSender.SendSingleData(packetId, packet);
				}
			}
		}

		public IClientPlayer? GetPlayer(ushort id)
		{
			if (((ClientAddon)this).ClientApi == null)
			{
				return null;
			}
			foreach (IClientPlayer player in ((ClientAddon)this).ClientApi.ClientManager.Players)
			{
				if (player.Id == id)
				{
					return player;
				}
			}
			return null;
		}

		public IEnumerable<IClientPlayer> GetPlayersInScene()
		{
			if (((ClientAddon)this).ClientApi == null)
			{
				return Array.Empty<IClientPlayer>();
			}
			List<IClientPlayer> list = new List<IClientPlayer>();
			foreach (IClientPlayer player in ((ClientAddon)this).ClientApi.ClientManager.Players)
			{
				if (player.IsInLocalScene)
				{
					list.Add(player);
				}
			}
			return list;
		}

		public static string GetPrefabNameFromName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return "";
			}
			string text = name.Replace("(Clone)", "").Trim();
			int num = text.IndexOf("_fs_", StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				text = text.Substring(0, num);
			}
			int num2 = text.IndexOf(" (");
			if (num2 >= 0)
			{
				text = text.Substring(0, num2);
			}
			while (text.Length > 0 && (char.IsDigit(text[text.Length - 1]) || char.IsWhiteSpace(text[text.Length - 1])))
			{
				text = text.Substring(0, text.Length - 1);
			}
			return text.Trim();
		}

		public EnemyAvatar? GetActiveBoss()
		{
			return BossSyncManager.GetActiveBoss();
		}

		public GameObject? FindPrefab(string name)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			string prefabNameFromName = GetPrefabNameFromName(name);
			if (string.IsNullOrEmpty(prefabNameFromName))
			{
				return null;
			}
			if (FailedPrefabSearches.Contains(prefabNameFromName))
			{
				return null;
			}
			Scene scene;
			if (PrefabCache.TryGetValue(prefabNameFromName, out GameObject value) && (Object)(object)value != (Object)null)
			{
				scene = value.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					return value;
				}
				EnemyAvatar enemyAvatar = default(EnemyAvatar);
				if (!value.TryGetComponent<EnemyAvatar>(ref enemyAvatar) || !enemyAvatar.isBoss)
				{
					return value;
				}
				PrefabCache.Remove(prefabNameFromName);
			}
			GameObject val = null;
			GameObject val2 = null;
			HealthManager[] array = Resources.FindObjectsOfTypeAll<HealthManager>();
			EnemyAvatar enemyAvatar2 = default(EnemyAvatar);
			foreach (HealthManager val3 in array)
			{
				if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)val3).gameObject;
				string prefabNameFromName2 = GetPrefabNameFromName(((Object)gameObject).name);
				scene = gameObject.scene;
				bool flag = !((Scene)(ref scene)).IsValid();
				if (((Object)gameObject).name == prefabNameFromName || prefabNameFromName2 == prefabNameFromName)
				{
					if (flag)
					{
						val = gameObject;
						break;
					}
					if ((Object)(object)val2 == (Object)null && (!gameObject.TryGetComponent<EnemyAvatar>(ref enemyAvatar2) || !enemyAvatar2.isBoss) && val3.hp <= 100)
					{
						val2 = gameObject;
					}
				}
			}
			GameObject val4 = val ?? val2;
			if ((Object)(object)val4 == (Object)null)
			{
				val = null;
				val2 = null;
				string text = prefabNameFromName.ToLower();
				GameObject[] array2 = Resources.FindObjectsOfTypeAll<GameObject>();
				EnemyAvatar enemyAvatar3 = default(EnemyAvatar);
				foreach (GameObject val5 in array2)
				{
					if ((Object)(object)val5 == (Object)null)
					{
						continue;
					}
					string text2 = ((Object)val5).name.ToLower();
					string text3 = GetPrefabNameFromName(((Object)val5).name).ToLower();
					scene = val5.scene;
					bool flag2 = !((Scene)(ref scene)).IsValid();
					if (((Object)val5).name == prefabNameFromName || text3 == text || text2.Contains(text) || text.Contains(text3))
					{
						if (flag2)
						{
							val = val5;
							break;
						}
						if ((Object)(object)val2 == (Object)null && (!val5.TryGetComponent<EnemyAvatar>(ref enemyAvatar3) || !enemyAvatar3.isBoss))
						{
							val2 = val5;
						}
					}
				}
				val4 = val ?? val2;
			}
			if ((Object)(object)val4 != (Object)null)
			{
				PrefabCache[prefabNameFromName] = val4;
				FailedPrefabSearches.Remove(prefabNameFromName);
			}
			else
			{
				FailedPrefabSearches.Add(prefabNameFromName);
			}
			return val4;
		}

		public EnemyAvatar? FindEnemyAvatar(string name, bool autoSpawn = false, Vector3? spawnPos = null, bool excludeBosses = false)
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			if (EnemyAvatar.ActiveAvatars.TryGetValue(name, out EnemyAvatar value) && (Object)(object)value != (Object)null && (!excludeBosses || !value.isBoss))
			{
				return value;
			}
			string text = BossSyncManager.NormalizePath(name);
			foreach (EnemyAvatar value2 in EnemyAvatar.ActiveAvatars.Values)
			{
				if ((Object)(object)value2 != (Object)null && (Object)(object)((Component)value2).gameObject != (Object)null && (!excludeBosses || !value2.isBoss))
				{
					if (value2.enemyName == name || ((Object)((Component)value2).gameObject).name == name)
					{
						return value2;
					}
					if (!string.IsNullOrEmpty(text) && BossSyncManager.NormalizePath(value2.enemyName) == text)
					{
						return value2;
					}
				}
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).IsValid())
			{
				GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
				foreach (GameObject val in rootGameObjects)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					EnemyAvatar[] componentsInChildren = val.GetComponentsInChildren<EnemyAvatar>(true);
					foreach (EnemyAvatar enemyAvatar in componentsInChildren)
					{
						if ((Object)(object)enemyAvatar != (Object)null && (Object)(object)((Component)enemyAvatar).gameObject != (Object)null && (!excludeBosses || !enemyAvatar.isBoss) && (enemyAvatar.enemyName == name || ((Object)((Component)enemyAvatar).gameObject).name == name || (!string.IsNullOrEmpty(text) && BossSyncManager.NormalizePath(enemyAvatar.enemyName) == text)))
						{
							EnemyAvatar.ActiveAvatars[name] = enemyAvatar;
							return enemyAvatar;
						}
					}
				}
			}
			if (DeadEnemies.Contains(name))
			{
				return null;
			}
			if (autoSpawn)
			{
				if ((Object)(object)HeroController.instance == (Object)null || HeroController.instance.cState.dead)
				{
					return null;
				}
				if (!name.Contains("_fs_"))
				{
					return null;
				}
				string prefabNameFromName = GetPrefabNameFromName(name);
				GameObject val2 = FindPrefab(prefabNameFromName);
				if ((Object)(object)val2 != (Object)null)
				{
					Vector3 val3 = (Vector3)(((??)spawnPos) ?? Vector3.zero);
					GameObject val4 = Object.Instantiate<GameObject>(val2, val3, Quaternion.identity);
					((Object)val4).name = name;
					val4.SetActive(true);
					if ((Object)(object)val4.GetComponent<EnemyHitHandler>() == (Object)null)
					{
						val4.AddComponent<EnemyHitHandler>();
					}
					EnemyAvatar enemyAvatar2 = val4.GetComponent<EnemyAvatar>() ?? val4.AddComponent<EnemyAvatar>();
					enemyAvatar2.enemyName = name;
					enemyAvatar2.targetPosition = val3;
					((Component)enemyAvatar2).transform.position = val3;
					ushort num = ushort.MaxValue;
					if (name.Contains("_fs_"))
					{
						string[] array = name.Split(new string[1] { "_fs_" }, StringSplitOptions.None);
						if (array.Length >= 2)
						{
							string[] array2 = array[1].Split('_');
							if (array2.Length >= 1 && ushort.TryParse(array2[0], out var result))
							{
								num = result;
							}
						}
					}
					if (num != ushort.MaxValue)
					{
						enemyAvatar2.controllerId = num;
						enemyAvatar2.TargetPlayerId = num;
						enemyAvatar2.isController = num == LocalPlayerId;
					}
					enemyAvatar2.ReEnableFSMs();
					EnemyAvatar.ActiveAvatars[name] = enemyAvatar2;
					Debug.Log((object)$"[EnemySync] Auto-spawned missing enemy '{name}' from prefab '{prefabNameFromName}' at {val3} (controller: {enemyAvatar2.controllerId})");
					return enemyAvatar2;
				}
			}
			return null;
		}

		private void HandleBossSyncRequest(BossSyncRequestPacket packet)
		{
			if (string.IsNullOrEmpty(packet.EnemyName) || !packet.Subscribe)
			{
				return;
			}
			if (DeadEnemies.Contains(packet.EnemyName))
			{
				EnemyDiePacket packet2 = new EnemyDiePacket
				{
					EnemyName = packet.EnemyName
				};
				SendPacket(EnemySyncPacketId.EnemyDie, (IPacketData)(object)packet2);
				return;
			}
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if ((Object)(object)enemyAvatar != (Object)null && enemyAvatar.isBoss && enemyAvatar.isController)
			{
				Debug.Log((object)("[EnemySync] Received BossSyncRequest for '" + packet.EnemyName + "'. Sending FSM states."));
				enemyAvatar.SendAllFsmStates();
			}
		}

		public static void EnterCocoonState()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (IsLocalPlayerCocooned)
			{
				return;
			}
			IsLocalPlayerCocooned = true;
			LocalCocoonSafePosition = Vector3.zero;
			LocalPlayerCocoonHp = 25;
			Debug.Log((object)"[EnemySync] Local player entered cocoon state!");
			SetCocoonInputsEnabled(enabled: false);
			originalEnabledRenderers.Clear();
			if ((Object)(object)HeroController.instance != (Object)null)
			{
				HeroController instance = HeroController.instance;
				instance.RelinquishControl();
				instance.acceptingInput = false;
				Rigidbody2D val = default(Rigidbody2D);
				if (((Component)instance).TryGetComponent<Rigidbody2D>(ref val))
				{
					val.bodyType = (RigidbodyType2D)0;
				}
				if (instance.cState != null)
				{
					instance.cState.jumping = false;
					instance.cState.doubleJumping = false;
					instance.cState.dashing = false;
					instance.cState.backDashing = false;
					instance.cState.superDashing = false;
					instance.cState.recoiling = false;
					instance.cState.recoilFrozen = false;
					instance.cState.wallSliding = false;
					instance.cState.touchingWall = false;
				}
				originalHeroLayer = ((Component)instance).gameObject.layer;
				Transform obj = instance.transform.Find("HeroBox");
				GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null);
				if ((Object)(object)val2 != (Object)null)
				{
					originalHeroBoxLayer = val2.layer;
				}
				Renderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren<Renderer>(false);
				foreach (Renderer val3 in componentsInChildren)
				{
					if ((Object)(object)val3 != (Object)null && val3.enabled && ((Object)((Component)val3).gameObject).name != "LocalCocoonVisual")
					{
						originalEnabledRenderers.Add(val3);
					}
				}
			}
			PlayerCocoonPacket packet = new PlayerCocoonPacket
			{
				PlayerId = (Instance?.LocalPlayerId ?? ushort.MaxValue),
				IsCocooned = true
			};
			Instance?.SendPacket(EnemySyncPacketId.PlayerCocoon, (IPacketData)(object)packet);
			Instance?.StartCocoonSettling();
		}

		public static void ExitCocoonState(bool heal)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!IsLocalPlayerCocooned)
			{
				return;
			}
			IsLocalPlayerCocooned = false;
			LocalCocoonSafePosition = Vector3.zero;
			SyncManager? instance = SyncManager.Instance;
			if (instance != null)
			{
				((MonoBehaviour)instance).StopAllCoroutines();
			}
			Debug.Log((object)$"[EnemySync] Local player exited cocoon state (heal={heal})!");
			SetCocoonInputsEnabled(enabled: true);
			if ((Object)(object)HeroController.instance != (Object)null)
			{
				HeroController instance2 = HeroController.instance;
				instance2.acceptingInput = true;
				((Component)instance2).gameObject.layer = ((originalHeroLayer > 0 && originalHeroLayer != 11) ? originalHeroLayer : 9);
				Transform obj = instance2.transform.Find("HeroBox");
				GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
				if ((Object)(object)val != (Object)null)
				{
					val.layer = ((originalHeroBoxLayer > 0 && originalHeroBoxLayer != 11) ? originalHeroBoxLayer : 17);
				}
				if (originalEnabledRenderers.Count > 0)
				{
					foreach (Renderer originalEnabledRenderer in originalEnabledRenderers)
					{
						if ((Object)(object)originalEnabledRenderer != (Object)null && ((Object)((Component)originalEnabledRenderer).gameObject).name != "LocalCocoonVisual")
						{
							originalEnabledRenderer.enabled = true;
						}
					}
				}
				else
				{
					Renderer component = ((Component)instance2).GetComponent<Renderer>();
					if ((Object)(object)component != (Object)null)
					{
						component.enabled = true;
					}
					tk2dSpriteAnimator val2 = ((Component)instance2).GetComponent<tk2dSpriteAnimator>() ?? ((Component)instance2).GetComponentInChildren<tk2dSpriteAnimator>();
					Renderer val3 = default(Renderer);
					if ((Object)(object)val2 != (Object)null && ((Component)val2).TryGetComponent<Renderer>(ref val3))
					{
						val3.enabled = true;
					}
					Transform val4 = instance2.transform.Find("Username");
					if ((Object)(object)val4 != (Object)null)
					{
						Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Renderer>(true);
						foreach (Renderer val5 in componentsInChildren)
						{
							if ((Object)(object)val5 != (Object)null)
							{
								val5.enabled = true;
							}
						}
					}
				}
				originalEnabledRenderers.Clear();
				Rigidbody2D val6 = default(Rigidbody2D);
				if (((Component)instance2).TryGetComponent<Rigidbody2D>(ref val6))
				{
					val6.bodyType = (RigidbodyType2D)0;
				}
				Collider2D component2 = ((Component)instance2).GetComponent<Collider2D>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Behaviour)component2).enabled = true;
				}
				Transform obj2 = instance2.transform.Find("HeroBox");
				Collider2D val7 = ((obj2 != null) ? ((Component)obj2).GetComponent<Collider2D>() : null);
				if ((Object)(object)val7 != (Object)null)
				{
					((Behaviour)val7).enabled = true;
				}
				try
				{
					FieldInfo field = typeof(HeroController).GetField("damageMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						field.SetValue(instance2, 0);
					}
				}
				catch
				{
				}
				instance2.cState.invulnerable = false;
				instance2.cState.hazardDeath = false;
				instance2.cState.hazardRespawning = false;
				instance2.cState.recoiling = false;
				instance2.cState.transitioning = false;
				instance2.cState.onGround = true;
				instance2.RegainControl();
				ResetHeroSpriteFlash();
				if (heal)
				{
					instance2.playerData.health = 1;
					try
					{
						EventRegister.SendEvent("HP CHANGED", (GameObject)null);
						PlayMakerFSM.BroadcastEvent("HP CHANGED");
					}
					catch
					{
					}
				}
			}
			PlayerCocoonPacket packet = new PlayerCocoonPacket
			{
				PlayerId = (Instance?.LocalPlayerId ?? ushort.MaxValue),
				IsCocooned = false
			};
			Instance?.SendPacket(EnemySyncPacketId.PlayerCocoon, (IPacketData)(object)packet);
			Instance?.DestroyLocalCocoonVisual();
		}

		public static void SetCocoonInputsEnabled(bool enabled)
		{
			if ((Object)(object)ManagerSingleton<InputHandler>.Instance == (Object)null || ManagerSingleton<InputHandler>.Instance.inputActions == null)
			{
				return;
			}
			try
			{
				HeroActions inputActions = ManagerSingleton<InputHandler>.Instance.inputActions;
				((OneAxisInputControl)inputActions.Jump).Enabled = enabled;
				((OneAxisInputControl)inputActions.Evade).Enabled = enabled;
				((OneAxisInputControl)inputActions.Dash).Enabled = enabled;
				((OneAxisInputControl)inputActions.SuperDash).Enabled = enabled;
				((OneAxisInputControl)inputActions.Attack).Enabled = enabled;
				((OneAxisInputControl)inputActions.Cast).Enabled = enabled;
				((OneAxisInputControl)inputActions.QuickCast).Enabled = enabled;
				((OneAxisInputControl)inputActions.Taunt).Enabled = enabled;
				((OneAxisInputControl)inputActions.Left).Enabled = enabled;
				((OneAxisInputControl)inputActions.Right).Enabled = enabled;
				((OneAxisInputControl)inputActions.Up).Enabled = enabled;
				((OneAxisInputControl)inputActions.Down).Enabled = enabled;
				((OneAxisInputControl)inputActions.OpenInventory).Enabled = enabled;
				((OneAxisInputControl)inputActions.OpenInventoryMap).Enabled = enabled;
				((OneAxisInputControl)inputActions.OpenInventoryJournal).Enabled = enabled;
				((OneAxisInputControl)inputActions.OpenInventoryTools).Enabled = enabled;
				((OneAxisInputControl)inputActions.OpenInventoryQuests).Enabled = enabled;
				((OneAxisInputControl)inputActions.SwipeInventoryMap).Enabled = enabled;
				((OneAxisInputControl)inputActions.SwipeInventoryJournal).Enabled = enabled;
				((OneAxisInputControl)inputActions.SwipeInventoryTools).Enabled = enabled;
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[EnemySync] Failed to modify input actions state: {arg}");
			}
		}

		public static void ResetHeroSpriteFlash()
		{
			if ((Object)(object)HeroController.instance == (Object)null)
			{
				return;
			}
			try
			{
				SpriteFlash component = ((Component)HeroController.instance).GetComponent<SpriteFlash>();
				if (!((Object)(object)component != (Object)null))
				{
					return;
				}
				MethodInfo method = ((object)component).GetType().GetMethod("CancelFlash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					method.Invoke(component, null);
				}
				else
				{
					MethodInfo method2 = ((object)component).GetType().GetMethod("removeFromList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method2 != null)
					{
						method2.Invoke(component, null);
					}
				}
				((Behaviour)component).enabled = false;
				((Behaviour)component).enabled = true;
			}
			catch
			{
			}
		}

		public static PlayerAction? GetAction(string name)
		{
			if ((Object)(object)ManagerSingleton<InputHandler>.Instance == (Object)null || ManagerSingleton<InputHandler>.Instance.inputActions == null)
			{
				return null;
			}
			HeroActions inputActions = ManagerSingleton<InputHandler>.Instance.inputActions;
			FieldInfo field = ((object)inputActions).GetType().GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
			if (field != null)
			{
				object? value = field.GetValue(inputActions);
				return (PlayerAction?)((value is PlayerAction) ? value : null);
			}
			PropertyInfo property = ((object)inputActions).GetType().GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
			if (property != null)
			{
				object? value2 = property.GetValue(inputActions);
				return (PlayerAction?)((value2 is PlayerAction) ? value2 : null);
			}
			return null;
		}

		public static PlayerAction? GetQuickMapAction()
		{
			return GetAction("quickMap") ?? GetAction("map");
		}

		public unsafe static string GetQuickMapButtonName()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Invalid comparison between Unknown and I4
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Invalid comparison between Unknown and I4
			PlayerAction quickMapAction = GetQuickMapAction();
			if (quickMapAction != null)
			{
				try
				{
					bool flag = (Object)(object)ManagerSingleton<InputHandler>.Instance != (Object)null && (int)ManagerSingleton<InputHandler>.Instance.lastActiveController == 1;
					if (flag)
					{
						InputControlType controllerButtonBinding = KeybindUtil.GetControllerButtonBinding(quickMapAction);
						if ((int)controllerButtonBinding != 0)
						{
							return ((object)(*(InputControlType*)(&controllerButtonBinding))/*cast due to .constrained prefix*/).ToString();
						}
					}
					foreach (BindingSource binding in quickMapAction.Bindings)
					{
						if (!(binding == (BindingSource)null))
						{
							if (flag && (int)binding.BindingSourceType == 1)
							{
								return binding.Name;
							}
							if (!flag && ((int)binding.BindingSourceType == 2 || (int)binding.BindingSourceType == 3))
							{
								return binding.Name;
							}
						}
					}
					foreach (BindingSource binding2 in quickMapAction.Bindings)
					{
						if (binding2 != (BindingSource)null && !string.IsNullOrEmpty(binding2.Name))
						{
							return binding2.Name;
						}
					}
				}
				catch
				{
				}
			}
			return "TAB";
		}

		private void HandlePlayerCocoon(PlayerCocoonPacket packet)
		{
			if (packet.PlayerId == LocalPlayerId)
			{
				return;
			}
			if (packet.IsCocooned)
			{
				CocoonedPlayers.Add(packet.PlayerId);
				IClientPlayer player = GetPlayer(packet.PlayerId);
				if (player != null && (Object)(object)player.PlayerObject != (Object)null)
				{
					SpawnRemoteCocoon(player.PlayerObject, player.Id);
				}
			}
			else
			{
				CocoonedPlayers.Remove(packet.PlayerId);
				IClientPlayer player2 = GetPlayer(packet.PlayerId);
				if (player2 != null && (Object)(object)player2.PlayerObject != (Object)null)
				{
					DestroyRemoteCocoon(player2.PlayerObject);
				}
			}
			if (AreAllPlayersCocooned())
			{
				TriggerNativeDeath();
			}
		}

		private void HandleCocoonDamage(CocoonDamagePacket packet)
		{
			if (packet.TargetPlayerId == LocalPlayerId && IsLocalPlayerCocooned)
			{
				LocalPlayerCocoonHp -= packet.DamageDealt;
				Debug.Log((object)$"[EnemySync] Local cocoon took damage! HP remaining: {LocalPlayerCocoonHp}");
				if (LocalPlayerCocoonHp <= 0)
				{
					ExitCocoonState(heal: true);
				}
			}
		}

		public void StartCocoonSettling()
		{
			SyncManager? instance = SyncManager.Instance;
			if (instance != null)
			{
				((MonoBehaviour)instance).StopAllCoroutines();
			}
			SyncManager? instance2 = SyncManager.Instance;
			if (instance2 != null)
			{
				((MonoBehaviour)instance2).StartCoroutine(SettleCocoonRoutine());
			}
		}

		private IEnumerator SettleCocoonRoutine()
		{
			HeroController hc = HeroController.instance;
			Rigidbody2D val = default(Rigidbody2D);
			if ((Object)(object)hc != (Object)null && ((Component)hc).TryGetComponent<Rigidbody2D>(ref val))
			{
				val.bodyType = (RigidbodyType2D)0;
			}
			int maxAttempts = 10;
			Rigidbody2D val2 = default(Rigidbody2D);
			for (int attempt = 0; attempt < maxAttempts; attempt++)
			{
				yield return (object)new WaitForSeconds(2f);
				if ((Object)(object)hc == (Object)null || !IsLocalPlayerCocooned)
				{
					yield break;
				}
				bool num = hc.cState != null && (hc.cState.hazardDeath || hc.cState.hazardRespawning);
				bool flag = false;
				if (((Component)hc).TryGetComponent<Rigidbody2D>(ref val2))
				{
					Vector2 linearVelocity = val2.linearVelocity;
					if (((Vector2)(ref linearVelocity)).magnitude > 0.05f)
					{
						flag = true;
					}
				}
				bool flag2 = hc.cState != null && hc.cState.onGround;
				if (!num && (!flag || flag2))
				{
					break;
				}
			}
			if (!((Object)(object)hc != (Object)null) || !IsLocalPlayerCocooned)
			{
				yield break;
			}
			Vector3 val3 = hc.transform.position;
			try
			{
				if (hc.playerData != null)
				{
					Vector3 vector = hc.playerData.GetVector3("hazardRespawnLocation");
					if (vector != Vector3.zero && hc.cState != null && (hc.cState.hazardDeath || hc.cState.hazardRespawning))
					{
						val3 = vector;
						hc.transform.position = val3;
					}
				}
			}
			catch
			{
			}
			LocalCocoonSafePosition = val3;
			Rigidbody2D val4 = default(Rigidbody2D);
			if (((Component)hc).TryGetComponent<Rigidbody2D>(ref val4))
			{
				val4.bodyType = (RigidbodyType2D)1;
				val4.linearVelocity = Vector2.zero;
				val4.angularVelocity = 0f;
			}
			ResetHeroSpriteFlash();
			foreach (Renderer originalEnabledRenderer in originalEnabledRenderers)
			{
				if ((Object)(object)originalEnabledRenderer != (Object)null && ((Object)((Component)originalEnabledRenderer).gameObject).name != "LocalCocoonVisual" && !((Object)((Component)originalEnabledRenderer).gameObject).name.Contains("Username") && !((Object)((Component)originalEnabledRenderer).gameObject).name.Contains("Name"))
				{
					originalEnabledRenderer.enabled = false;
				}
			}
			SpawnLocalCocoonVisual();
		}

		public static Sprite? GetCocoonSprite()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: 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_0088: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cachedCocoonSprite != (Object)null)
			{
				return _cachedCocoonSprite;
			}
			try
			{
				Assembly assembly = typeof(ClientAddon).Assembly;
				string text = Array.Find(assembly.GetManifestResourceNames(), (string name) => name.EndsWith("Hornet_death.png"));
				if (text != null)
				{
					using Stream stream = assembly.GetManifestResourceStream(text);
					if (stream != null)
					{
						byte[] array = new byte[stream.Length];
						stream.Read(array, 0, (int)stream.Length);
						Texture2D val = new Texture2D(2, 2);
						ImageConversion.LoadImage(val, array);
						_cachedCocoonSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
						return _cachedCocoonSprite;
					}
				}
			}
			catch
			{
			}
			Texture2D val2 = new Texture2D(32, 48);
			for (int num = 0; num < 48; num++)
			{
				for (int num2 = 0; num2 < 32; num2++)
				{
					float num3 = ((float)num2 - 16f) / 14f;
					float num4 = ((float)num - 24f) / 22f;
					if (num3 * num3 + num4 * num4 <= 1f)
					{
						val2.SetPixel(num2, num, new Color(0.9f, 0.95f, 1f, 0.85f));
					}
					else
					{
						val2.SetPixel(num2, num, Color.clear);
					}
				}
			}
			val2.Apply();
			_cachedCocoonSprite = Sprite.Create(val2, new Rect(0f, 0f, 32f, 48f), new Vector2(0.5f, 0.5f), 100f);
			return _cachedCocoonSprite;
		}

		public void SpawnLocalCocoonVisual()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)localCocoonVisual != (Object)null) && !((Object)(object)HeroController.instance == (Object)null))
			{
				Sprite cocoonSprite = GetCocoonSprite();
				if (!((Object)(object)cocoonSprite == (Object)null))
				{
					localCocoonVisual = new GameObject("LocalCocoonVisual");
					localCocoonVisual.transform.SetParent(HeroController.instance.transform);
					localCocoonVisual.transform.localPosition = new Vector3(0f, 0.5f, -0.05f);
					localCocoonVisual.transform.localScale = new Vector3(1.5f, 1.5f, 1f);
					SpriteRenderer obj = localCocoonVisual.AddComponent<SpriteRenderer>();
					obj.sprite = cocoonSprite;
					((Renderer)obj).sortingOrder = 30;
				}
			}
		}

		public void DestroyLocalCocoonVisual()
		{
			if ((Object)(object)localCocoonVisual != (Object)null)
			{
				Object.Destroy((Object)(object)localCocoonVisual);
				localCocoonVisual = null;
			}
		}

		public void SpawnRemoteCocoon(GameObject remotePlayerGo, ushort ownerId)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			DestroyRemoteCocoon(remotePlayerGo);
			Sprite cocoonSprite = GetCocoonSprite();
			if ((Object)(object)cocoonSprite == (Object)null)
			{
				return;
			}
			List<Renderer> list = new List<Renderer>();
			Renderer[] componentsInChildren = remotePlayerGo.GetComponentsInChildren<Renderer>(false);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && val.enabled && ((Object)((Component)val).gameObject).name != "RemoteCocoonVisual" && !((Object)((Component)val).gameObject).name.Contains("Username") && !((Object)((Component)val).gameObject).name.Contains("Name"))
				{
					list.Add(val);
					val.enabled = false;
				}
			}
			RemotePlayerOriginalRenderers[remotePlayerGo] = list;
			GameObject val2 = new GameObject("RemoteCocoonVisual");
			val2.transform.SetParent(remotePlayerGo.transform);
			val2.transform.localPosition = new Vector3(0f, 0.5f, -0.05f);
			val2.transform.localScale = new Vector3(1.5f, 1.5f, 1f);
			SpriteRenderer obj = val2.AddComponent<SpriteRenderer>();
			obj.sprite = cocoonSprite;
			((Renderer)obj).sortingOrder = 30;
			BoxCollider2D obj2 = val2.AddComponent<BoxCollider2D>();
			obj2.size = new Vector2(1.2f, 2f);
			((Collider2D)obj2).isTrigger = true;
			val2.layer = 11;
			val2.AddComponent<RemoteCocoonResponder>().OwnerPlayerId = ownerId;
		}

		public void DestroyRemoteCocoon(GameObject remotePlayerGo)
		{
			Transform val = remotePlayerGo.transform.Find("RemoteCocoonVisual");
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			if (RemotePlayerOriginalRenderers.TryGetValue(remotePlayerGo, out List<Renderer> value))
			{
				foreach (Renderer item in value)
				{
					if ((Object)(object)item != (Object)null)
					{
						item.enabled = true;
					}
				}
				RemotePlayerOriginalRenderers.Remove(remotePlayerGo);
				return;
			}
			Renderer component = remotePlayerGo.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.enabled = true;
			}
			tk2dSpriteAnimator val2 = remotePlayerGo.GetComponent<tk2dSpriteAnimator>() ?? remotePlayerGo.GetComponentInChildren<tk2dSpriteAnimator>();
			Renderer val3 = default(Renderer);
			if ((Object)(object)val2 != (Object)null && ((Component)val2).TryGetComponent<Renderer>(ref val3))
			{
				val3.enabled = true;
			}
			Transform val4 = remotePlayerGo.transform.Find("Username");
			if (!((Object)(object)val4 != (Object)null))
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					val5.enabled = true;
				}
			}
		}

		public static bool AreAllPlayersCocooned()
		{
			if (Instance == null || !IsLocalPlayerCocooned)
			{
				return false;
			}
			IEnumerable<IClientPlayer> playersInScene = Instance.GetPlayersInScene();
			if (!playersInScene.Any())
			{
				return true;
			}
			foreach (IClientPlayer item in playersInScene)
			{
				if (!Instance.CocoonedPlayers.Contains(item.Id))
				{
					return false;
				}
			}
			return true;
		}

		public static void TriggerNativeDeath()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			if (!((Object)(object)HeroController.instance == (Object)null) && !HeroController.instance.cState.dead)
			{
				Debug.Log((object)"[EnemySync] Triggering native team death.");
				Instance?.UnsubscribeFromAllBosses();
				if (IsLocalPlayerCocooned)
				{
					ExitCocoonState(heal: false);
				}
				IsSuiciding = true;
				HeroController.instance.TakeDamage(new GameObject("AllCocoonedDeath"), (CollisionSide)4, 9999, (HazardType)1, (DamagePropertyFlags)0);
				IsSuiciding = false;
			}
		}

		private void HandleEnemyPosition(EnemyPositionPacket packet)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(packet.Position.X, packet.Position.Y, 0f);
			LastKnownPositions[packet.EnemyName] = val;
			LastKnownScales[packet.EnemyName] = packet.ScaleX;
			LastKnownActiveStates[packet.EnemyName] = packet.Active;
			LastKnownControllers[packet.EnemyName] = packet.ControllerId;
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if (!((Object)(object)enemyAvatar != (Object)null))
			{
				return;
			}
			if (enemyAvatar.isBoss || enemyAvatar.enemyName.Contains("_fs_") || enemyAvatar.IsHazardOrSummonOrProjectile())
			{
				if (!enemyAvatar.isController && (enemyAvatar.controllerId != LocalPlayerId || LocalPlayerId == ushort.MaxValue) && enemyAvatar.controllerId != packet.ControllerId)
				{
					enemyAvatar.SetTargetAndControllerLocal(packet.ControllerId, packet.ControllerId);
				}
			}
			else if (enemyAvatar.controllerId == ushort.MaxValue && packet.ControllerId != ushort.MaxValue)
			{
				enemyAvatar.SetTargetAndControllerLocal(packet.ControllerId, packet.ControllerId);
			}
			else if (enemyAvatar.TargetPlayerId != ushort.MaxValue)
			{
				if (enemyAvatar.controllerId != enemyAvatar.TargetPlayerId)
				{
					enemyAvatar.SetTargetAndControllerLocal(enemyAvatar.TargetPlayerId, enemyAvatar.TargetPlayerId);
				}
			}
			else if (enemyAvatar.isController && LocalPlayerId != ushort.MaxValue && packet.ControllerId != LocalPlayerId)
			{
				float num = (((Object)(object)HeroController.instance != (Object)null) ? Vector3.Distance(((Component)enemyAvatar).transform.position, HeroController.instance.transform.position) : 999f);
				IClientPlayer player = GetPlayer(packet.ControllerId);
				if (((player != null && (Object)(object)player.PlayerObject != (Object)null) ? Vector3.Distance(((Component)enemyAvatar).transform.position, player.PlayerObject.transform.position) : 999f) < num - 5f)
				{
					Debug.Log((object)$"[EnemySync] Yielding FOV position control of '{packet.EnemyName}' to closer player {packet.ControllerId}");
					enemyAvatar.SetTargetAndControllerLocal(ushort.MaxValue, packet.ControllerId);
				}
			}
			else if (!enemyAvatar.isController && enemyAvatar.controllerId != packet.ControllerId)
			{
				enemyAvatar.SetTargetAndControllerLocal(ushort.MaxValue, packet.ControllerId);
			}
			if ((!enemyAvatar.isBoss || ((!((Object)(object)HeroController.instance != (Object)null) || !HeroController.instance.cState.dead) && !(enemyAvatar.spawnDelayTimer > 0f))) && !enemyAvatar.isController)
			{
				enemyAvatar.UpdatePosition(val);
				enemyAvatar.targetScaleX = packet.ScaleX;
				enemyAvatar.targetActive = packet.Active;
				if (((Component)enemyAvatar).gameObject.activeSelf != packet.Active)
				{
					((Component)enemyAvatar).gameObject.SetActive(packet.Active);
				}
				if (!packet.Active && packet.EnemyName.Contains("_fs_"))
				{
					Object.Destroy((Object)(object)((Component)enemyAvatar).gameObject, 0.5f);
				}
			}
		}

		private void HandleEnemyAnimation(EnemyAnimationPacket packet)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if (!((Object)(object)enemyAvatar != (Object)null) || enemyAvatar.isController)
			{
				return;
			}
			if (enemyAvatar.isBoss || enemyAvatar.IsHazardOrSummonOrProjectile())
			{
				if (((Object)(object)HeroController.instance != (Object)null && HeroController.instance.cState.dead) || enemyAvatar.spawnDelayTimer > 0f)
				{
					return;
				}
			}
			else if ((Object)(object)HeroController.instance != (Object)null && Vector2.Distance(Vector2.op_Implicit(HeroController.instance.transform.position), Vector2.op_Implicit(((Component)enemyAvatar).transform.position)) > 35f)
			{
				return;
			}
			tk2dSpriteAnimator val = ((Component)enemyAvatar).GetComponent<tk2dSpriteAnimator>() ?? ((Component)enemyAvatar).GetComponentInChildren<tk2dSpriteAnimator>(true);
			if ((Object)(object)val != (Object)null && (Object)(object)val.Library != (Object)null)
			{
				tk2dSpriteAnimationClip clipByName = val.Library.GetClipByName(packet.ClipName);
				if (clipByName != null)
				{
					val.Play(clipByName);
				}
				else
				{
					val.Play(packet.ClipName);
				}
			}
		}

		private void HandleEnemyTarget(EnemyTargetPacket packet)
		{
			LastKnownControllers[packet.EnemyName] = packet.ControllerId;
			LastKnownTargets[packet.EnemyName] = packet.TargetPlayerId;
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if (!((Object)(object)enemyAvatar != (Object)null))
			{
				return;
			}
			if (enemyAvatar.IsHazardOrSummonOrProjectile() && !enemyAvatar.isBoss)
			{
				enemyAvatar.SetTargetAndControllerLocal(packet.TargetPlayerId, packet.ControllerId);
				return;
			}
			if (enemyAvatar.isBoss && enemyAvatar.isController && enemyAvatar.controllerId == LocalPlayerId && packet.ControllerId != LocalPlayerId)
			{
				ushort num = Math.Min(LocalPlayerId, packet.ControllerId);
				if (LocalPlayerId == num)
				{
					Debug.Log((object)$"[EnemySync] Local player {LocalPlayerId} won boss claim tie-break for '{packet.EnemyName}'. Retaining control.");
					EnemyTargetPacket packet2 = new EnemyTargetPacket
					{
						EnemyName = packet.EnemyName,
						TargetPlayerId = enemyAvatar.TargetPlayerId,
						ControllerId = LocalPlayerId
					};
					SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet2);
				}
				else
				{
					Debug.Log((object)$"[EnemySync] Local player {LocalPlayerId} lost boss claim tie-break for '{packet.EnemyName}' to player {packet.ControllerId}. Yielding control.");
					enemyAvatar.SetTargetAndControllerLocal(packet.TargetPlayerId, packet.ControllerId);
				}
				return;
			}
			if (!enemyAvatar.isBoss && !enemyAvatar.IsHazardOrSummonOrProjectile())
			{
				if (enemyAvatar.TargetPlayerId == LocalPlayerId && LocalPlayerId != ushort.MaxValue && packet.TargetPlayerId != LocalPlayerId && (Object)(object)HeroController.instance != (Object)null && !enemyAvatar.IsPlayerDeadOrCocooned(((Component)HeroController.instance).gameObject))
				{
					if (packet.ControllerId != LocalPlayerId && Time.time - enemyAvatar.lastTargetConfirmTime > 2f)
					{
						enemyAvatar.lastTargetConfirmTime = Time.time;
						EnemyTargetPacket packet3 = new EnemyTargetPacket
						{
							EnemyName = packet.EnemyName,
							TargetPlayerId = LocalPlayerId,
							ControllerId = LocalPlayerId
						};
						SendPacket(EnemySyncPacketId.EnemyTarget, (IPacketData)(object)packet3);
					}
					return;
				}
				if (enemyAvatar.isController && enemyAvatar.controllerId == LocalPlayerId && packet.ControllerId != LocalPlayerId)
				{
					Debug.Log((object)$"[EnemySync] Yielding control of '{packet.EnemyName}' to new controller {packet.ControllerId}");
				}
			}
			enemyAvatar.SetTargetAndControllerLocal(packet.TargetPlayerId, packet.ControllerId);
		}

		private void HandleEnemyFsmState(EnemyFsmStatePacket packet)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(packet.EnemyName) || string.IsNullOrEmpty(packet.FsmName) || DeadEnemies.Contains(packet.EnemyName))
			{
				return;
			}
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if (!((Object)(object)enemyAvatar != (Object)null))
			{
				return;
			}
			if (enemyAvatar.isBoss)
			{
				if ((Object)(object)HeroController.instance != (Object)null && HeroController.instance.cState.dead)
				{
					return;
				}
				enemyAvatar.spawnDelayTimer = 0f;
				enemyAvatar.hasStartedMovingNatively = true;
				if (enemyAvatar.isController)
				{
					return;
				}
			}
			Vector2 value = default(Vector2);
			((Vector2)(ref value))..ctor(packet.Position.X, packet.Position.Y);
			enemyAvatar.SetFsmState(packet.FsmName, packet.StateName, value, packet.ScaleX);
		}

		private void HandleEnemyTakeDamage(EnemyTakeDamagePacket packet)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if (!((Object)(object)enemyAvatar != (Object)null) || (enemyAvatar.isBoss && enemyAvatar.spawnDelayTimer > 0f))
			{
				return;
			}
			GameObject gameObject = ((Component)enemyAvatar).gameObject;
			if (enemyAvatar.isController)
			{
				HealthManager component = gameObject.GetComponent<HealthManager>();
				if (!((Object)(object)component != (Object)null))
				{
					return;
				}
				HitInstance val = new HitInstance
				{
					Source = gameObject,
					DamageDealt = packet.DamageDealt,
					Direction = packet.Direction,
					AttackType = (AttackTypes)packet.AttackType,
					Multiplier = packet.Multiplier,
					MagnitudeMultiplier = packet.MagnitudeMultiplier,
					NailElement = (NailElements)packet.NailElement,
					NonLethal = packet.NonLethal,
					CriticalHit = packet.CriticalHit,
					CanWeakHit = packet.CanWeakHit,
					DamageScalingLevel = packet.DamageScalingLevel,
					SpecialType = (SpecialTypes)packet.SpecialType,
					IsHeroDamage = false
				};
				EnemyHitHandler enemyHitHandler = default(EnemyHitHandler);
				if (gameObject.TryGetComponent<EnemyHitHandler>(ref enemyHitHandler))
				{
					enemyHitHandler.SuppressNextHpSync = true;
				}
				HealthPatches.IsApplyingRemoteDamage = true;
				try
				{
					component.TakeDamage(val);
				}
				catch
				{
				}
				finally
				{
					HealthPatches.IsApplyingRemoteDamage = false;
				}
				EnemyHpPacket packet2 = new EnemyHpPacket
				{
					EnemyName = ((!string.IsNullOrEmpty(enemyAvatar.enemyName)) ? enemyAvatar.enemyName : ((Object)gameObject).name),
					Hp = component.hp
				};
				SendPacket(EnemySyncPacketId.EnemyHp, (IPacketData)(object)packet2);
				return;
			}
			try
			{
				EnemyHitEffectsRegular component2 = gameObject.GetComponent<EnemyHitEffectsRegular>();
				if ((Object)(object)component2 != (Object)null)
				{
					HitInstance val2 = new HitInstance
					{
						Source = gameObject,
						DamageDealt = 0,
						Direction = packet.Direction,
						AttackType = (AttackTypes)packet.AttackType,
						IsHeroDamage = true
					};
					component2.ReceiveHitEffect(val2);
				}
				SpriteFlash val3 = gameObject.GetComponent<SpriteFlash>() ?? gameObject.GetComponentInChildren<SpriteFlash>(true);
				if ((Object)(object)val3 != (Object)null)
				{
					MethodInfo methodInfo = ((object)val3).GetType().GetMethod("flashWhiteQuick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)val3).GetType().GetMethod("flashArmoured", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (methodInfo != null)
					{
						methodInfo.Invoke(val3, null);
					}
					else
					{
						val3.flashInfected();
					}
				}
			}
			catch
			{
			}
		}

		private void HandleEnemyHp(EnemyHpPacket packet)
		{
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if (!((Object)(object)enemyAvatar != (Object)null) || (!enemyAvatar.isBoss && enemyAvatar.isController) || (enemyAvatar.isBoss && enemyAvatar.spawnDelayTimer > 0f))
			{
				return;
			}
			HealthManager component = ((Component)enemyAvatar).GetComponent<HealthManager>();
			if ((Object)(object)component != (Object)null)
			{
				component.hp = packet.Hp;
				if (packet.Hp <= 0)
				{
					HandleEnemyDie(new EnemyDiePacket
					{
						EnemyName = packet.EnemyName
					});
				}
			}
		}

		private void HandleEnemyDie(EnemyDiePacket packet)
		{
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(packet.EnemyName))
			{
				return;
			}
			Debug.Log((object)("[EnemySync] Received Die update for '" + packet.EnemyName + "'"));
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.EnemyName);
			if ((Object)(object)enemyAvatar == (Object)null)
			{
				string text = BossSyncManager.NormalizePath(packet.EnemyName);
				HealthManager[] array = Object.FindObjectsByType<HealthManager>((FindObjectsSortMode)0);
				foreach (HealthManager val in array)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy)
					{
						string fullScenePath = BossSyncManager.GetFullScenePath(((Component)val).transform);
						string text2 = BossSyncManager.NormalizePath(fullScenePath);
						if (((Object)((Component)val).gameObject).name == packet.EnemyName || fullScenePath == packet.EnemyName || (!string.IsNullOrEmpty(text) && text2 == text))
						{
							enemyAvatar = ((Component)val).gameObject.GetComponent<EnemyAvatar>() ?? ((Component)val).gameObject.AddComponent<EnemyAvatar>();
							enemyAvatar.enemyName = packet.EnemyName;
							break;
						}
					}
				}
			}
			if ((Object)(object)enemyAvatar != (Object)null && !((Component)enemyAvatar).gameObject.activeInHierarchy)
			{
				Debug.Log((object)("[EnemySync] Ignored Die update for '" + packet.EnemyName + "' because matching scene object is inactive (dormant / future wave enemy)."));
				return;
			}
			bool num = ((Object)(object)enemyAvatar != (Object)null && (enemyAvatar.isBoss || enemyAvatar.IsHazardOrSummonOrProjectile())) || packet.EnemyName.Contains("_fs_");
			bool flag = packet.EnemyName.StartsWith("scene:") || ((Object)(object)enemyAvatar != (Object)null && (enemyAvatar.enemyName.StartsWith("scene:") || enemyAvatar.enemyName.ToLower().Contains("battle") || enemyAvatar.enemyName.ToLower().Contains("wave")));
			if (!num && !flag)
			{
				DeadEnemies.Add(packet.EnemyName);
				Scene activeScene = SceneManager.GetActiveScene();
				string name = ((Scene)(ref activeScene)).name;
				if (!string.IsNullOrEmpty(name))
				{
					if (!SceneDeadEnemies.TryGetValue(name, out HashSet<string> value))
					{
						value = new HashSet<string>();
						SceneDeadEnemies[name] = value;
					}
					value.Add(packet.EnemyName);
				}
			}
			if (!((Object)(object)enemyAvatar != (Object)null) || enemyAvatar.isController)
			{
				return;
			}
			IsApplyingRemoteDeath = true;
			try
			{
				enemyAvatar.noRespondCounter = -1f;
				enemyAvatar.ReEnableFSMs(restoreLastState: false);
				HealthManager component = ((Component)enemyAvatar).GetComponent<HealthManager>();
				if ((Object)(object)component != (Object)null)
				{
					component.hp = 0;
					float? num2 = ((packet.AttackDirection != 0f) ? new float?(packet.AttackDirection) : ((float?)null));
					AttackTypes val2 = (AttackTypes)((packet.AttackType < 0 || packet.AttackType > 10) ? 1 : packet.AttackType);
					try
					{
						component.Die(num2, val2, (NailElements)0, (GameObject)null, true, 1f, false, false);
					}
					catch (Exception ex)
					{
						Debug.LogWarning((object)("[EnemySync] Exception in remote hm.Die for '" + packet.EnemyName + "': " + ex.Message));
					}
					if (packet.HasCorpseSnapshot)
					{
						Rigidbody2D val3 = ((Component)enemyAvatar).GetComponent<Rigidbody2D>() ?? ((Component)enemyAvatar).GetComponentInChildren<Rigidbody2D>();
						if ((Object)(object)val3 != (Object)null)
						{
							val3.simulated = true;
							val3.bodyType = (RigidbodyType2D)1;
							val3.position = new Vector2(packet.CorpsePosition.X, packet.CorpsePosition.Y);
							val3.rotation = packet.CorpseRotation;
							val3.bodyType = (RigidbodyType2D)0;
							val3.linearVelocity = new Vector2(packet.CorpseVelocity.X, packet.CorpseVelocity.Y);
						}
					}
				}
				else
				{
					((Component)enemyAvatar).gameObject.SetActive(false);
				}
			}
			finally
			{
				IsApplyingRemoteDeath = false;
			}
		}

		private void HandleSpawnProjectile(SpawnProjectilePacket packet)
		{
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0718: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(packet.PrefabName) || string.IsNullOrEmpty(packet.UniqueName) || DeadEnemies.Contains(packet.UniqueName))
			{
				return;
			}
			ushort num = ushort.MaxValue;
			if (packet.UniqueName.Contains("_fs_"))
			{
				string[] array = packet.UniqueName.Split(new string[1] { "_fs_" }, StringSplitOptions.None);
				if (array.Length >= 2)
				{
					string[] array2 = array[1].Split('_');
					if (array2.Length >= 1 && ushort.TryParse(array2[0], out var result))
					{
						num = result;
					}
				}
			}
			EnemyAvatar enemyAvatar = FindEnemyAvatar(packet.UniqueName, autoSpawn: false, null, excludeBosses: true);
			if ((Object)(object)enemyAvatar != (Object)null && !enemyAvatar.isBoss)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(packet.Position.X, packet.Position.Y, ((Component)enemyAvatar).transform.position.z);
				enemyAvatar.targetPosition = val;
				((Component)enemyAvatar).transform.position = val;
				((Component)enemyAvatar).transform.rotation = Quaternion.Euler(new Vector3(packet.Rotation.X, packet.Rotation.Y, packet.Rotation.Z));
				Vector3 localScale = ((Component)enemyAvatar).transform.localScale;
				((Component)enemyAvatar).transform.localScale = new Vector3(packet.ScaleX, localScale.y, localScale.z);
				((Component)enemyAvatar).gameObject.SetActive(true);
				Rigidbody2D val2 = default(Rigidbody2D);
				if (((Component)enemyAvatar).TryGetComponent<Rigidbody2D>(ref val2))
				{
					val2.position = Vector2.op_Implicit(val);
					if (packet.Velocity != (Vector2)null)
					{
						val2.linearVelocity = new Vector2(packet.Velocity.X, packet.Velocity.Y);
					}
				}
				if (string.IsNullOrEmpty(packet.ClipName))
				{
					return;
				}
				tk2dSpriteAnimator val3 = ((Component)enemyAvatar).GetComponent<tk2dSpriteAnimator>() ?? ((Component)enemyAvatar).GetComponentInChildren<tk2dSpriteAnimator>(true);
				if ((Object)(object)val3 != (Object)null)
				{
					tk2dSpriteAnimationClip val4 = (((Object)(object)val3.Library != (Object)null) ? val3.Library.GetClipByName(packet.ClipName) : null);
					if (val4 != null)
					{
						val3.Play(val4);
					}
					else
					{
						val3.Play(packet.ClipName);
					}
				}
				return;
			}
			LastKnownPositions[packet.UniqueName] = new Vector3(packet.Position.X, packet.Position.Y, 0f);
			LastKnownActiveStates[packet.UniqueName] = true;
			if (num != ushort.MaxValue)
			{
				LastKnownControllers[packet.UniqueName] = num;
				LastKnownTargets[packet.UniqueName] = num;
			}
			GameObject val5 = FindPrefab(packet.PrefabName);
			if ((Object)(object)val5 == (Object)null)
			{
				EnemyAvatar enemyAvatar2 = FindEnemyAvatar(packet.PrefabName, autoSpawn: false, null, excludeBosses: true);
				if ((Object)(object)enemyAvatar2 != (Object)null)
				{
					val5 = ((Component)enemyAvatar2).gameObject;
				}
			}
			if (!((Object)(object)val5 != (Object)null))
			{
				return;
			}
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(packet.Position.X, packet.Position.Y, 0f);
			Quaternion val7 = Quaternion.Euler(new Vector3(packet.Rotation.X, packet.Rotation.Y, packet.Rotation.Z));
			GameObject val8;
			try
			{
				val8 = Object.Instantiate<GameObject>(val5, val6, val7);
			}
			catch
			{
				try
				{
					val8 = Object.Instantiate<GameObject>(val5);
					val8.transform.position = val6;
					val8.transform.rotation = val7;
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[EnemySync] Failed to instantiate projectile prefab '" + packet.PrefabName + "': " + ex.Message));
					return;
				}
			}
			((Object)val8).name = packet.UniqueName;
			Vector3 localScale2 = val8.transform.localScale;
			val8.transform.localScale = new Vector3(packet.ScaleX, localScale2.y, localScale2.z);
			val8.SetActive(true);
			Transform[] componentsInChildren = val8.GetComponentsInChildren<Transform>(true);
			foreach (Transform val9 in componentsInChildren)
			{
				if ((Object)(object)val9 != (Object)null)
				{
					((Component)val9).gameObject.SetActive(true);
				}
			}
			Renderer[] componentsInChildren2 = val8.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val10 in componentsInChildren2)
			{
				if ((Object)(object)val10 != (Object)null)
				{
					val10.enabled = true;
				}
			}
			Rigidbody2D component = val8.GetComponent<Rigidbody2D>();
			if ((Object)(object)component != (Object)null)
			{
				if (packet.Velocity != (Vector2)null && (packet.Velocity.X != 0f || packet.Velocity.Y != 0f))
				{
					component.linearVelocity = new Vector2(packet.Velocity.X, packet.Velocity.Y);
				}
				else
				{
					component.bodyType = (RigidbodyType2D)1;
				}
			}
			EnemyAvatar enemyAvatar3 = val8.GetComponent<EnemyAvatar>() ?? val8.AddComponent<EnemyAvatar>();
			enemyAvatar3.enemyName = packet.UniqueName;
			enemyAvatar3.controllerId = num;
			enemyAvatar3.TargetPlayerId = num;
			enemyAvatar3.isController = num != ushort.MaxValue && num == LocalPlayerId;
			enemyAvatar3.isBoss = false;
			enemyAvatar3.targetPosition = val6;
			((Component)enemyAvatar3).transform.position = val6;
			enemyAvatar3.targetActive = true;
			enemyAvatar3.hasStartedMovingNatively = true;
			val8.SetActive(true);
			if (!enemyAvatar3.isController)
			{
				DamageHero[] componentsInChildren3 = val8.GetComponentsInChildren<DamageHero>(true);
				foreach (DamageHero val11 in componentsInChildren3)
				{
					if ((Object)(object)val11 != (Object)null)
					{
						((Behaviour)val11).enabled = false;
					}
				}
				Collider2D[] componentsInChildren4 = val8.GetComponentsInChildren<Collider2D>(true);
				foreach (Collider2D val12 in componentsInChildren4)
				{
					if ((Object)(object)val12 != (Object)null && val12.isTrigger)
					{
						((Behaviour)val12).enabled = false;
					}
				}
			}
			if ((Object)(object)val8.GetComponentInChildren<HealthManager>(true) != (Object)null && (Object)(object)val8.GetComponent<EnemyHitHandler>() == (Object)null)
			{
				val8.AddComponent<EnemyHitHandler>();
			}
			EnemyAvatar.ActiveAvatars[packet.UniqueName] = enemyAvatar3;
			PlayMakerFSM[] componentsInChildren5 = val8.GetComponentsInChildren<PlayMakerFSM>(true);
			foreach (PlayMakerFSM val13 in componentsInChildren5)
			{
				if (!((Object)(object)val13 != (Object)null) || val13.Fsm == null)
				{
					continue;
				}
				if (enemyAvatar3.isController)
				{
					((Behaviour)val13).enabled = true;
					try
					{
						val13.Fsm.Start();
					}
					catch
					{
					}
				}
				else
				{
					((Behaviour)val13).enabled = false;
				}
			}
			if (!string.IsNullOrEmpty(packet.ClipName))
			{
				tk2dSpriteAnimator val14 = val8.GetComponent<tk2dSpriteAnimator>() ?? val8.GetComponentInChildren<tk2dSpriteAnimator>(true);
				if ((Object)(object)val14 != (Object)null)
				{
					tk2dSpriteAnimationClip val15 = (((Object)(object)val14.Library != (Object)null) ? val14.Library.GetClipByName(packet.ClipName) : null);
					if (val15 != null)
					{
						val14.Play(val15);
					}
					else
					{
						val14.Play(packet.ClipName);
					}
				}
			}
			if (enemyAvatar3.isController)
			{
				enemyAvatar3.ReEnableFSMs();
			}
			if (!enemyAvatar3.isController && packet.UniqueName.Contains("_fs_"))
			{
				Object.Destroy((Object)(object)val8, 12f);
			}
			Debug.Log((object)$"[EnemySync] Instantiated summon/projectile '{packet.UniqueName}' from prefab '{packet.PrefabName}' at {val6} (ScaleX: {packet.ScaleX}, Clip: '{packet.ClipName}')");
		}
	}
	[BepInPlugin("bg52.enemysync.ssmp", "BasicEnemySync", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class EnemySyncingPlugin : BaseUnityPlugin
	{
		private void Awake()
		{
			try
			{
				ClientAddon.RegisterAddon((ClientAddon)(object)new ClientAddon());
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[EnemySync] ClientAddon registered successfully.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[EnemySync] ClientAddon registration warning: " + ex.Message));
			}
			try
			{
				ServerAddon.RegisterAddon((ServerAddon)(object)new ServerAddon());
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[EnemySync] ServerAddon registered successfully.");
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[EnemySync] ServerAddon registration warning: " + ex2.Message));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[EnemySync] Plugin loaded. Client and Server addons registered with SSMP.");
		}
	}
	public class ServerAddon : ServerAddon
	{
		private IServerApi? _serverApi;

		private IServerAddonNetworkSender<EnemySyncPacketId>? _serverSender;

		private readonly HashSet<string> _knownBosses = new HashSet<string>();

		private readonly Dictionary<string, HashSet<ushort>> _bossSubscriptions = new Dictionary<string, HashSet<ushort>>();

		private readonly Dictionary<string, ushort> _sceneOwners = new Dictionary<string, ushort>();

		public static ServerAddon? Instance { get; private set; }

		protected override string Name => "EnemySyncingAddon";

		protected override string Version => "1.0.1";

		public override bool NeedsNetwork => true;

		public override uint ApiVersion => 1u;

		public override void Initialize(IServerApi serverApi)
		{
			Instance = this;
			_serverApi = serverApi;
			IServerAddonNetworkReceiver<EnemySyncPacketId> networkReceiver = serverApi.NetServer.GetNetworkReceiver<EnemySyncPacketId>((ServerAddon)(object)this, (Func<EnemySyncPacketId, IPacketData>)InstantiatePacket);
			_serverSender = serverApi.NetServer.GetNetworkSender<EnemySyncPacketId>((ServerAddon)(object)this);
			networkReceiver.RegisterPacketHandler<EnemyPositionPacket>(EnemySyncPacketId.EnemyPosition, (GenericServerPacketHandler<EnemyPositionPacket>)delegate(ushort id, EnemyPositionPacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyPosition, p);
			});
			networkReceiver.RegisterPacketHandler<EnemyAnimationPacket>(EnemySyncPacketId.EnemyAnimation, (GenericServerPacketHandler<EnemyAnimationPacket>)delegate(ushort id, EnemyAnimationPacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyAnimation, p);
			});
			networkReceiver.RegisterPacketHandler<EnemyTargetPacket>(EnemySyncPacketId.EnemyTarget, (GenericServerPacketHandler<EnemyTargetPacket>)delegate(ushort id, EnemyTargetPacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyTarget, p);
			});
			networkReceiver.RegisterPacketHandler<EnemyTakeDamagePacket>(EnemySyncPacketId.EnemyTakeDamage, (GenericServerPacketHandler<EnemyTakeDamagePacket>)delegate(ushort id, EnemyTakeDamagePacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyTakeDamage, p);
			});
			networkReceiver.RegisterPacketHandler<EnemyHpPacket>(EnemySyncPacketId.EnemyHp, (GenericServerPacketHandler<EnemyHpPacket>)delegate(ushort id, EnemyHpPacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyHp, p);
			});
			networkReceiver.RegisterPacketHandler<EnemyDiePacket>(EnemySyncPacketId.EnemyDie, (GenericServerPacketHandler<EnemyDiePacket>)delegate(ushort id, EnemyDiePacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyDie, p);
			});
			networkReceiver.RegisterPacketHandler<SpawnProjectilePacket>(EnemySyncPacketId.SpawnProjectile, (GenericServerPacketHandler<SpawnProjectilePacket>)delegate(ushort id, SpawnProjectilePacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.SpawnProjectile, p);
			});
			networkReceiver.RegisterPacketHandler<EnemyFsmStatePacket>(EnemySyncPacketId.EnemyFsmState, (GenericServerPacketHandler<EnemyFsmStatePacket>)delegate(ushort id, EnemyFsmStatePacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.EnemyFsmState, p);
			});
			networkReceiver.RegisterPacketHandler<RequestPlayerIdPacket>(EnemySyncPacketId.RequestPlayerId, (GenericServerPacketHandler<RequestPlayerIdPacket>)HandleRequestPlayerId);
			networkReceiver.RegisterPacketHandler<BossSyncRequestPacket>(EnemySyncPacketId.BossSyncRequest, (GenericServerPacketHandler<BossSyncRequestPacket>)HandleBossSyncRequest);
			networkReceiver.RegisterPacketHandler<PlayerCocoonPacket>(EnemySyncPacketId.PlayerCocoon, (GenericServerPacketHandler<PlayerCocoonPacket>)delegate(ushort id, PlayerCocoonPacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.PlayerCocoon, p);
			});
			networkReceiver.RegisterPacketHandler<CocoonDamagePacket>(EnemySyncPacketId.CocoonDamage, (GenericServerPacketHandler<CocoonDamagePacket>)delegate(ushort id, CocoonDamagePacket p)
			{
				ForwardToScene(id, EnemySyncPacketId.CocoonDamage, p);
			});
			networkReceiver.RegisterPacketHandler<VerifyEnemyDieRequestPacket>(EnemySyncPacketId.VerifyEnemyDieRequest, (GenericServerPacketHandler<VerifyEnemyDieRequestPacket>)HandleVerifyEnemyDieRequest);
			serverApi.ServerManager.PlayerEnterSceneEvent += OnPlayerEnterScene;
			serverApi.ServerManager.PlayerLeaveSceneEvent += OnPlayerLeaveScene;
		}

		private void OnPlayerEnterScene(IServerPlayer player)
		{
			if (player != null && !string.IsNullOrEmpty(player.CurrentScene))
			{
				UpdateSceneOwner(player.CurrentScene);
			}
		}

		private void OnPlayerLeaveScene(IServerPlayer player)
		{
			if (player != null && !string.IsNullOrEmpty(player.CurrentScene))
			{
				UpdateSceneOwner(player.CurrentScene);
			}
		}

		public ushort GetSceneOwner(string sceneName)
		{
			if (string.IsNullOrEmpty(sceneName) || _serverApi == null)
			{
				return ushort.MaxValue;
			}
			List<IServerPlayer> list = new List<IServerPlayer>();
			foreach (IServerPlayer player in _serverApi.ServerManager.Players)
			{
				if (player.CurrentScene == sceneName)
				{
					list.Add(player);
				}
			}
			if (list.Count == 0)
			{
				_sceneOwners.Remove(sceneName);
				return ushort.MaxValue;
			}
			if (_sceneOwners.TryGetValue(sceneName, out var currentOwner) && list.Exists((IServerPlayer p) => p.Id == currentOwner))
			{
				return currentOwner;
			}
			list.Sort((IServerPlayer a, IServerPlayer b) => a.Id.CompareTo(b.Id));
			ushort id = list[0].Id;
			_sceneOwners[sceneName] = id;
			SceneOwnerNotifyPacket sceneOwnerNotifyPacket = new SceneOwnerNotifyPacket
			{
				SceneOwnerId = id
			};
			ushort[] array = list.ConvertAll((IServerPlayer p) => p.Id).ToArray();
			_serverSender?.SendSingleData(EnemySyncPacketId.SceneOwnerNotify, (IPacketData)(object)sceneOwnerNotifyPacket, array);
			((ServerAddon)this).Logger.Info($"[EnemySync] Assigned player {id} as Scene Owner for '{sceneName}'");
			return id;
		}

		private void UpdateSceneOwner(string sceneName)
		{
			GetSceneOwner(sceneName);
		}

		private void HandleVerifyEnemyDieRequest(ushort senderId, VerifyEnemyDieRequestPacket packet)
		{
			if (_serverApi == null || _serverSender == null)
			{
				return;
			}
			IServerPlayer player = _serverApi.ServerManager.GetPlayer(senderId);
			if (player != null)
			{
				ushort sceneOwner = GetSceneOwner(player.CurrentScene);
				packet.RequesterPlayerId = senderId;
				if (sceneOwner != ushort.MaxValue)
				{
					((ServerAddon)this).Logger.Info($"[EnemySync] Forwarding death verification request for '{packet.EnemyName}' from player {senderId} to Scene Owner {sceneOwner}");
					_serverSender.SendSingleData(EnemySyncPacketId.VerifyEnemyDieRequest, (IPacketData)(object)packet, sceneOwner);
				}
			}
		}

		private void HandleRequestPlayerId(ushort senderId, RequestPlayerIdPacket packet)
		{
			if (_serverSender != null && _serverApi != null)
			{
				PlayerIdNotifyPacket playerIdNotifyPacket = new PlayerIdNotifyPacket
				{
					AssignedPlayerId = senderId
				};
				_serverSender.SendSingleData(EnemySyncPacketId.PlayerIdNotify, (IPacketData)(object)playerIdNotifyPacket, senderId);
				((ServerAddon)this).Logger.Info($"[EnemySync] Sent player ID notification {senderId} to client");
				IServerPlayer player = _serverApi.ServerManager.GetPlayer(senderId);
				if (player != null && !string.IsNullOrEmpty(player.CurrentScene))
				{
					UpdateSceneOwner(player.CurrentScene);
				}
			}
		}

		private void HandleBossSyncRequest(ushort senderId, BossSyncRequestPacket packet)
		{
			if (string.IsNullOrEmpty(packet.EnemyName))
			{
				return;
			}
			lock (_knownBosses)
			{
				_knownBosses.Add(packet.EnemyName);
			}
			lock (_bossSubscriptions)
			{
				HashSet<ushort> value2;
				if (packet.Subscribe)
				{
					if (!_bossSubscriptions.TryGetValue(packet.EnemyName, out HashSet<ushort> value))
					{
						value = new HashSet<ushort>();
						_bossSubscriptions[packet.EnemyName] = value;
					}
					value.Add(senderId);
					((ServerAddon)this).Logger.Info($"[EnemySync] Player {senderId} subscribed to boss sync for '{packet.EnemyName}'");
				}
				else if (_bossSubscriptions.TryGetValue(packet.EnemyName, out value2))
				{
					value2.Remove(senderId);
					((ServerAddon)this).Logger.Info($"[EnemySync] Player {senderId} unsubscribed from boss sync for '{packet.EnemyName}'");
				}
			}
			ForwardToScene(senderId, EnemySyncPacketId.BossSyncRequest, packet);
		}

		private IPacketData InstantiatePacket(EnemySyncPacketId id)
		{
			return (IPacketData)(id switch
			{
				EnemySyncPacketId.EnemyPosition => new PacketDataCollection<EnemyPositionPacket>(), 
				EnemySyncPacketId.EnemyAnimation => new EnemyAnimationPacket(), 
				EnemySyncPacketId.EnemyTarget => new EnemyTargetPacket(), 
				EnemySyncPacketId.EnemyTakeDamage => new EnemyTakeDamagePacket(), 
				EnemySyncPacketId.EnemyHp => new EnemyHpPacket(), 
				EnemySyncPacketId.EnemyDie => new EnemyDiePacket(), 
				EnemySyncPacketId.SpawnProjectile => new SpawnProjectilePacket(), 
				EnemySyncPacketId.RequestPlayerId => new RequestPlayerIdPacket(), 
				EnemySyncPacketId.PlayerIdNotify => new PlayerIdNotifyPacket(), 
				EnemySyncPacketId.EnemyFsmState => new EnemyFsmStatePacket(), 
				EnemySyncPacketId.BossSyncRequest => new BossSyncRequestPacket(), 
				EnemySyncPacketId.PlayerCocoon => new PlayerCocoonPacket(), 
				EnemySyncPacketId.CocoonDamage => new CocoonDamagePacket(), 
				EnemySyncPacketId.SceneOwnerNotify => new SceneOwnerNotifyPacket(), 
				EnemySyncPacketId.VerifyEnemyDieRequest => new VerifyEnemyDieRequestPacket(), 
				_ => throw new ArgumentException("Unknown packet ID"), 
			});
		}

		private void ForwardToScene<TPacketData>(ushort senderId, EnemySyncPacketId packetId, TPacketData packet) where TPacketData : IPacketData, new()
		{
			if (_serverApi == null || _serverSender == null)
			{
				return;
			}
			IServerPlayer player = _serverApi.ServerManager.GetPlayer(senderId);
			if (player == null)
			{
				return;
			}
			string currentScene = player.CurrentScene;
			string text = string.Empty;
			PropertyInfo property = ((object)packet/*cast due to .constrained prefix*/).GetType().GetProperty("EnemyName");
			if (property != null)
			{
				text = (property.GetValue(packet) as string) ?? string.Empty;
			}
			else
			{
				PropertyInfo property2 = ((object)packet/*cast due to .constrained prefix*/).GetType().GetProperty("UniqueName");
				if (property2 != null)
				{
					text = (property2.GetValue(packet) as string) ?? string.Empty;
				}
			}
			bool flag = false;
			if (!string.IsNullOrEmpty(text))
			{
				lock (_knownBosses)
				{
					flag = _knownBosses.Contains(text);
				}
			}
			List<ushort> list = new List<ushort>();
			foreach (IServerPlayer player2 in _serverApi.ServerManager.Players)
			{
				if (player2.Id == senderId || !(player2.CurrentScene == currentScene))
				{
					continue;
				}
				if (flag)
				{
					bool flag2 = false;
					lock (_bossSubscriptions)
					{
						if (_bossSubscriptions.TryGetValue(text, out HashSet<ushort> value))
						{
							flag2 = value.Contains(player2.Id);
						}
					}
					if (!flag2)
					{
						continue;
					}
				}
				list.Add(player2.Id);
			}
			if (list.Count > 0)
			{
				if (packetId == EnemySyncPacketId.EnemyPosition)
				{
					_serverSender.SendCollectionData<TPacketData>(packetId, packet, list.ToArray());
				}
				else
				{
					_serverSender.SendSingleData(packetId, (IPacketData)(object)packet, list.ToArray());
				}
			}
		}
	}
	public class SyncManager : MonoBehaviour
	{
		public static float SuicideHoldTimer = 0f;

		private GameObject? suicideUiGo;

		private Text? cocoonUiText;

		private Text? suicideHintText;

		private static Font? _defaultFont;

		private float hazardScanTimer;

		private float restorationTimer;

		private static readonly Dictionary<Component, Color> OriginalTextColors = new Dictionary<Component, Color>();

		public static SyncManager? Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		public static Font GetDefaultFont()
		{
			if ((Object)(object)_defaultFont != (Object)null)
			{
				return _defaultFont;
			}
			try
			{
				_defaultFont = Font.CreateDynamicFontFromOSFont("Arial", 28);
			}
			catch
			{
			}
			if ((Object)(object)_defaultFont == (Object)null)
			{
				Font[] array = Resources.FindObjectsOfTypeAll<Font>();
				foreach (Font val in array)
				{
					if ((Object)(object)val != (Object)null)
					{
						_defaultFont = val;
						break;
					}
				}
			}
			return _defaultFont ?? Resources.GetBuiltinResource<Font>("Arial.ttf");
		}

		private void Update()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (ClientAddon.Instance == null || ClientAddon.Instance.Api == null || !ClientAddon.Instance.Api.NetClient.IsConnected)
			{
				return;
			}
			if (ClientAddon.IsLocalPlayerCocooned && (Object)(object)HeroController.instance != (Object)null)
			{
				if (ClientAddon.AreAllPlayersCocooned())
				{
					Debug.Log((object)"[EnemySync] All players in scene are cocooned or no survivors left. Triggering team wipe.");
					ClientAddon.TriggerNativeDeath();
					return;
				}
				HeroController instance = HeroController.instance;
				instance.acceptingInput = false;
				if (ClientAddon.LocalCocoonSafePosition != Vector3.zero)
				{
					instance.transform.position = ClientAddon.LocalCocoonSafePosition;
					Rigidbody2D val = default(Rigidbody2D);
					if (((Component)instance).TryGetComponent<Rigidbody2D>(ref val))
					{
						val.bodyType = (RigidbodyType2D)1;
						val.linearVelocity = Vector2.zero;
						val.angularVelocity = 0f;
					}
				}
				if (Input.GetKeyDown((KeyCode)27))
				{
					instance.acceptingInput = true;
				}
			}
			if (ClientAddon.IsLocalPlayerCocooned)
			{
				bool flag = false;
				if (Input.GetKey((KeyCode)9) || Input.GetKey((KeyCode)109) || Input.GetKey((KeyCode)27))
				{
					flag = true;
				}
				if ((Object)(object)ManagerSingleton<InputHandler>.Instance != (Object)null && ManagerSingleton<InputHandler>.Instance.inputActions != null)
				{
					PlayerAction openInventoryMap = ManagerSingleton<InputHandler>.Instance.inputActions.OpenInventoryMap;
					PlayerAction quickMap = ManagerSingleton<InputHandler>.Instance.inputActions.QuickMap;
					if ((openInventoryMap != null && (((OneAxisInputControl)openInventoryMap).WasPressed || ((OneAxisInputControl)openInventoryMap).IsPressed)) || (quickMap != null && (((OneAxisInputControl)quickMap).WasPressed || ((OneAxisInputControl)quickMap).IsPressed)))
					{
						flag = true;
					}
				}
				if (flag)
				{
					SuicideHoldTimer += Time.deltaTime;
					if (SuicideHoldTimer >= 1.5f)
					{
						SuicideHoldTimer = 0f;
						Debug.Log((object)"[EnemySync] Respawn hold threshold met. Triggering suicide respawn.");
						ClientAddon.TriggerNativeDeath();
					}
				}
				else
				{
					SuicideHoldTimer = 0f;
				}
				UpdateSuicideUi();
			}
			else
			{
				SuicideHoldTimer = 0f;
				HideSuicideUi();
			}
			HealthManager[] array = Object.FindObjectsByType<HealthManager>((FindObjectsSortMode)0);
			foreach (HealthManager val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)null && ((Component)val2).gameObject.activeInHierarchy)
				{
					if ((Object)(object)((Component)val2).gameObject.GetComponent<EnemyHitHandler>() == (Object)null)
					{
						((Component)val2).gameObject.AddComponent<EnemyHitHandler>();
					}
					if ((Object)(object)((Component)val2).gameObject.GetComponent<EnemyAvatar>() == (Object)null)
					{
						EnemyAvatar enemyAvatar = ((Component)val2).gameObject.AddComponent<EnemyAvatar>();
						string enemyName = ((((Object)((Component)val2).gameObject).name.Contains("_fs_") || ((Object)((Component)val2).gameObject).name.StartsWith("scene:")) ? ((Object)((Component)val2).gameObject).name : BossSyncManager.GetFullScenePath(((Component)val2).transform));
						enemyAvatar.enemyName = enemyName;
					}
				}
			}
			ScanAndSyncSceneHazards();
			CheckAndRestoreMissingEnemies();
			UpdateBossTargetUsernameTags();
		}

		private void ScanAndSyncSceneHazards()
		{
			//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)
			hazardScanTimer += Time.deltaTime;
			if (hazardScanTimer < 1f)
			{
				return;
			}
			hazardScanTimer = 0f;
			if (ClientAddon.Instance == null || !ClientAddon.Instance.IsSceneOwner)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!((Scene)(ref activeScene)).IsValid())
			{
				return;
			}
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if ((Object)(object)val == (Object)null || !val.activeInHierarchy)
				{
					continue;
				}
				Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
				foreach (Transform val2 in componentsInChildren)
				{
					if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)null)
					{
						continue;
					}
					GameObject gameObject = ((Component)val2).gameObject;
					if ((Object)(object)gameObject.GetComponent<DamageHero>() != (Object)null && !EnemyAvatar.IsBackgroundOrAmbientObject(gameObject) && (!((Object)(object)gameObject.transform.parent != (Object)null) || (!((Object)(object)gameObject.GetComponentInParent<HealthManager>() != (Object)null) && !((Object)(object)((Component)gameObject.transform.parent).GetComponentInParent<EnemyAvatar>() != (Object)null))))
					{
						string text = ((Object)gameObject).name.ToLower();
						if (!text.Contains("hit") && !text.Contains("stab") && !text.Contains("slash") && !text.Contains("attack") && !text.Contains("bite") && !text.Contains("punch") && !text.Contains("range") && !text.Contains("detector") && !text.Contains("trigger") && !text.Contains("alert") && !text.Contains("helper") && !text.Contains("parry") && !text.Contains("patrol") && !text.Contains("turn") && !text.Contains("sight") && (Object)(object)gameObject.GetComponent<EnemyAvatar>() == (Object)null)
						{
							EnemyAvatar enemyAvatar = gameObject.AddComponent<EnemyAvatar>();
							enemyAvatar.enemyName = ((Object)gameObject).name;
							enemyAvatar.controllerId = ClientAddon.Instance.LocalPlayerId;
							enemyAvatar.TargetPlayerId = ClientAddon.Instance.LocalPlayerId;
							enemyAvatar.isController = true;
						}
					}
				}
			}
		}

		private void CheckAndRestoreMissingEnemies()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			restorationTimer += Time.deltaTime;
			if (restorationTimer < 3f)
			{
				return;
			}
			restorationTimer = 0f;
			if (ClientAddon.Instance == null)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			foreach (KeyValuePair<string, Vector3> lastKnownPosition in ClientAddon.Instance.LastKnownPositions)
			{
				string key = lastKnownPosition.Key;
				_ = lastKnownPosition.Value;
				if (key.Contains("_fs_") || ClientAddon.DeadEnemies.Contains(key) || (!string.IsNullOrEmpty(name) && ClientAddon.SceneDeadEnemies.TryGetValue(name, out HashSet<string> value) && value.Contains(key)))
				{
					continue;
				}
				string text = key.ToLower();
				if (!text.Contains("fader") && !text.Contains("fade") && !text.Contains("canvas") && !text.Contains("hud") && !text.Contains("camera"))
				{
					EnemyAvatar enemyAvatar = ClientAddon.Instance.FindEnemyAvatar(key);
					if ((Object)(object)enemyAvatar != (Object)null && (Object)(object)((Component)enemyAvatar).gameObject != (Object)null && !((Component)enemyAvatar).gameObject.activeSelf)
					{
						Debug.Log((object)("[EnemySync] Background routine restored missing enemy '" + key + "'"));
						((Component)enemyAvatar).gameObject.SetActive(true);
						enemyAvatar.ReEnableFSMs();
					}
				}
			}
		}

		private void UpdateBossTargetUsernameTags()
		{
			//IL_062d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0609: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknow