Decompiled source of BasicEnemySyncAddonsFix v1.0.0

BasicEnemySyncAddonsFix.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using EnemySyncing;
using EnemySyncing.Components;
using EnemySyncing.Networking;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SSMP.Api.Client;
using SSMP.Networking.Packet;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("BasicEnemySyncAddonsFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+49e203745195cbd03e05fecab7a99e952bd37484")]
[assembly: AssemblyProduct("BasicEnemySyncAddonsFix")]
[assembly: AssemblyTitle("BasicEnemySyncAddonsFix")]
[assembly: AssemblyVersion("1.0.0.0")]
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;
		}
	}
}
namespace BasicEnemySyncAddonsFix
{
	[BepInPlugin("riggola.basicenemysync.addonsfix", "BasicEnemySync Addons Fix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "riggola.basicenemysync.addonsfix";

		public const string PluginName = "BasicEnemySync Addons Fix";

		public const string PluginVersion = "1.0.0";

		private Harmony? _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("riggola.basicenemysync.addonsfix");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((Component)this).gameObject.AddComponent<SyncGuard>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BasicEnemySync Addons Fix loaded. Brief protection will run after a cocoon revive.");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class ReviveGrace
	{
		private static long _untilTimestamp;

		private static readonly long GraceTicks = (long)((double)Stopwatch.Frequency * 1.5);

		internal static bool IsActive => Stopwatch.GetTimestamp() < Interlocked.Read(in _untilTimestamp);

		internal static void Arm()
		{
			Interlocked.Exchange(ref _untilTimestamp, Stopwatch.GetTimestamp() + GraceTicks);
		}
	}
	[HarmonyPatch]
	internal static class CocoonExitPatch
	{
		private static MethodBase? TargetMethod()
		{
			Type type = AccessTools.TypeByName("EnemySyncing.ClientAddon");
			if (!(type == null))
			{
				return AccessTools.Method(type, "ExitCocoonState", new Type[1] { typeof(bool) }, (Type[])null);
			}
			return null;
		}

		private static void Postfix(bool heal)
		{
			if (heal)
			{
				ReviveGrace.Arm();
			}
			SyncGuard.QueueCocoonState(cocooned: false);
		}
	}
	[HarmonyPatch]
	internal static class HeroTakeDamagePatch
	{
		private static MethodBase? TargetMethod()
		{
			Type type = AccessTools.TypeByName("HeroController");
			if (!(type == null))
			{
				return AccessTools.Method(type, "TakeDamage", (Type[])null, (Type[])null);
			}
			return null;
		}

		private static bool Prefix()
		{
			if (!ReviveGrace.IsActive)
			{
				if (ClientAddon.IsLocalPlayerCocooned)
				{
					return ClientAddon.IsSuiciding;
				}
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class PlayerTakeHealthPatch
	{
		private static MethodBase? TargetMethod()
		{
			Type type = AccessTools.TypeByName("PlayerData");
			if (!(type == null))
			{
				return AccessTools.Method(type, "TakeHealth", new Type[3]
				{
					typeof(int),
					typeof(bool),
					typeof(bool)
				}, (Type[])null);
			}
			return null;
		}

		private static bool Prefix()
		{
			return !ReviveGrace.IsActive;
		}
	}
	internal sealed class SyncGuard : MonoBehaviour
	{
		private struct RockState
		{
			public Vector3 Position;

			public bool Moved;

			public float Still;
		}

		private float _nextCocoonBroadcast;

		private float _nextEnemyBroadcast;

		private float _nextRockScan;

		private static float _clearCocoonUntil;

		private readonly Dictionary<int, RockState> _rocks = new Dictionary<int, RockState>();

		internal static void QueueCocoonState(bool cocooned)
		{
			if (!cocooned)
			{
				_clearCocoonUntil = Time.unscaledTime + 4f;
			}
		}

		private void Update()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//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_0135: Expected O, but got Unknown
			ClientAddon instance = ClientAddon.Instance;
			if (instance == null)
			{
				return;
			}
			if (Time.unscaledTime >= _nextCocoonBroadcast)
			{
				_nextCocoonBroadcast = Time.unscaledTime + 0.75f;
				if (instance.LocalPlayerId != ushort.MaxValue && (ClientAddon.IsLocalPlayerCocooned || Time.unscaledTime < _clearCocoonUntil))
				{
					instance.SendPacket((EnemySyncPacketId)12, (IPacketData)new PlayerCocoonPacket
					{
						PlayerId = instance.LocalPlayerId,
						IsCocooned = ClientAddon.IsLocalPlayerCocooned
					});
				}
				foreach (ushort cocoonedPlayer in instance.CocoonedPlayers)
				{
					IClientPlayer player = instance.GetPlayer(cocoonedPlayer);
					if ((Object)(object)((player != null) ? player.PlayerObject : null) != (Object)null && (Object)(object)player.PlayerObject.transform.Find("RemoteCocoonVisual") == (Object)null)
					{
						instance.SpawnRemoteCocoon(player.PlayerObject, cocoonedPlayer);
					}
				}
			}
			if (Time.unscaledTime >= _nextEnemyBroadcast)
			{
				_nextEnemyBroadcast = Time.unscaledTime + 8f;
				if (instance.IsLocalSceneOwner)
				{
					foreach (string deadEnemy in ClientAddon.DeadEnemies)
					{
						instance.SendPacket((EnemySyncPacketId)5, (IPacketData)new EnemyDiePacket
						{
							EnemyName = deadEnemy
						});
					}
				}
			}
			if (Time.unscaledTime >= _nextRockScan)
			{
				_nextRockScan = Time.unscaledTime + 0.1f;
				ScanRocks();
			}
		}

		private void ScanRocks()
		{
			//IL_00ee: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			foreach (EnemyAvatar value2 in EnemyAvatar.ActiveAvatars.Values)
			{
				if ((Object)(object)value2 == (Object)null || !((Component)value2).gameObject.activeInHierarchy)
				{
					continue;
				}
				string text = (value2.enemyName ?? ((Object)((Component)value2).gameObject).name).ToLowerInvariant();
				if (!text.Contains("rock") && !text.Contains("boulder") && !text.Contains("rubble") && !text.Contains("debris") && !text.Contains("stalactite"))
				{
					continue;
				}
				Rigidbody2D val = ((Component)value2).GetComponent<Rigidbody2D>() ?? ((Component)value2).GetComponentInChildren<Rigidbody2D>();
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)value2).GetInstanceID();
				if (!_rocks.TryGetValue(instanceID, out var value))
				{
					value = new RockState
					{
						Position = ((Component)value2).transform.position
					};
				}
				int num;
				if (!(Vector3.Distance(value.Position, ((Component)value2).transform.position) > 0.03f))
				{
					Vector2 linearVelocity = val.linearVelocity;
					num = ((((Vector2)(ref linearVelocity)).magnitude > 0.3f) ? 1 : 0);
				}
				else
				{
					num = 1;
				}
				bool flag = (byte)num != 0;
				value.Moved |= flag;
				value.Still = (flag ? 0f : (value.Still + 0.1f));
				value.Position = ((Component)value2).transform.position;
				_rocks[instanceID] = value;
				if (value.Moved && !(value.Still < 0.4f))
				{
					DamageHero[] componentsInChildren = ((Component)value2).GetComponentsInChildren<DamageHero>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						((Behaviour)componentsInChildren[i]).enabled = false;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(ClientAddon), "EnterCocoonState")]
	internal static class ImmediateCocoonPatch
	{
		private static void Postfix()
		{
			if (!ClientAddon.IsLocalPlayerCocooned || ClientAddon.Instance == null)
			{
				return;
			}
			ClientAddon.Instance.SpawnLocalCocoonVisual();
			if ((Object)(object)HeroController.instance == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)HeroController.instance).GetComponentsInChildren<Renderer>(false);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name != "LocalCocoonVisual" && !((Object)((Component)val).gameObject).name.Contains("Username"))
				{
					val.enabled = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ClientAddon), "HandlePlayerCocoon")]
	internal static class RemoteCocoonPatch
	{
		private static bool Prefix(ClientAddon __instance, PlayerCocoonPacket packet)
		{
			if (packet.PlayerId == __instance.LocalPlayerId)
			{
				return false;
			}
			IClientPlayer player = __instance.GetPlayer(packet.PlayerId);
			if (packet.IsCocooned && __instance.CocoonedPlayers.Contains(packet.PlayerId) && (Object)(object)((player != null) ? player.PlayerObject : null) != (Object)null && (Object)(object)player.PlayerObject.transform.Find("RemoteCocoonVisual") != (Object)null)
			{
				return false;
			}
			if (!packet.IsCocooned && !__instance.CocoonedPlayers.Contains(packet.PlayerId))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ClientAddon), "HandleVerifyEnemyDieRequest")]
	internal static class VerifiedDeathPatch
	{
		private static void Postfix(ClientAddon __instance, VerifyEnemyDieRequestPacket packet)
		{
			if (__instance.IsLocalSceneOwner && !string.IsNullOrEmpty(packet.EnemyName))
			{
				EnemyAvatar val = __instance.FindEnemyAvatar(packet.EnemyName, false, (Vector3?)null, false);
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ClientAddon), "HandleEnemyPosition")]
	internal static class DeadEnemyPositionPatch
	{
		private static bool Prefix(EnemyPositionPacket packet)
		{
			return !ClientAddon.DeadEnemies.Contains(packet.EnemyName);
		}
	}
	[HarmonyPatch(typeof(ClientAddon), "HandleEnemyDie")]
	internal static class DeadEnemyPacketPatch
	{
		private static void Postfix(ClientAddon __instance, EnemyDiePacket packet)
		{
			if (!string.IsNullOrEmpty(packet.EnemyName) && ClientAddon.DeadEnemies.Contains(packet.EnemyName))
			{
				EnemyAvatar val = __instance.FindEnemyAvatar(packet.EnemyName, false, (Vector3?)null, false);
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf && !val.isBoss)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SyncManager), "CheckAndRestoreMissingEnemies")]
	internal static class RestoreGuardPatch
	{
		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(HealthManager), "Die", new Type[]
	{
		typeof(float?),
		typeof(AttackTypes),
		typeof(NailElements),
		typeof(GameObject),
		typeof(bool),
		typeof(float),
		typeof(bool),
		typeof(bool)
	})]
	internal static class LocalDeathRecordPatch
	{
		private static void Postfix(HealthManager __instance)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			ClientAddon instance = ClientAddon.Instance;
			if (instance == null || !instance.IsLocalSceneOwner || ClientAddon.IsApplyingRemoteDeath || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			EnemyAvatar component = ((Component)__instance).GetComponent<EnemyAvatar>();
			if ((Object)(object)component == (Object)null || component.isBoss || component.IsHazardOrSummonOrProjectile())
			{
				return;
			}
			string enemyName = component.enemyName;
			if (!string.IsNullOrEmpty(enemyName) && !enemyName.Contains("_fs_"))
			{
				ClientAddon.DeadEnemies.Add(enemyName);
				Scene activeScene = SceneManager.GetActiveScene();
				string name = ((Scene)(ref activeScene)).name;
				if (!ClientAddon.SceneDeadEnemies.TryGetValue(name, out var value))
				{
					value = (ClientAddon.SceneDeadEnemies[name] = new HashSet<string>());
				}
				value.Add(enemyName);
			}
		}
	}
}