Decompiled source of MultiBossSpawner v1.0.12

MultiBossSpawner.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Zeitsurfer.MultiBoss.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Zeitsurfer.MultiBoss
{
	[BepInPlugin("com.zeitsurfer.multiboss", "MultiBoss", "1.0.12")]
	public class MultiBossPlugin : BaseUnityPlugin
	{
		internal static MultiBossPlugin Instance;

		private Harmony _harmony;

		internal static ConfigEntry<float> PlayerRadius;

		internal static ConfigEntry<float> PlayersPerBoss;

		internal static ConfigEntry<int> MaxExtraBosses;

		internal static ConfigEntry<string> BossPrefabNamesCsv;

		internal static ConfigEntry<bool> EndFightOnAnyPlayerDeath;

		internal static readonly HashSet<GameObject> ActiveBosses = new HashSet<GameObject>();

		internal static readonly HashSet<int> SpawnProcessedIDs = new HashSet<int>();

		internal static readonly HashSet<Vector3> RecentSpawnCenters = new HashSet<Vector3>();

		internal static readonly Dictionary<Vector3, HashSet<long>> FightParticipantsByCenter = new Dictionary<Vector3, HashSet<long>>();

		internal static readonly Dictionary<long, Vector3> PlayerParticipationCenters = new Dictionary<long, Vector3>();

		internal static float RecentCenterMergeRadius = 40f;

		private static bool _networkSpawnWarningShown;

		private void Awake()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			Instance = this;
			PlayerRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "PlayerRadius", 40f, "Radius um den Boss, in dem Spieler gezählt werden.");
			PlayersPerBoss = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "PlayersPerBoss", 2f, "Spieler pro Boss-Gruppe: floor(spieler / n).");
			MaxExtraBosses = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "MaxExtraBosses", 4, "Maximal zusätzliche Bosse (oberhalb des ersten, also insgesamt bis 1+X).");
			BossPrefabNamesCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BossPrefabs", "Eikthyr,TheElder,Bonemass,Dragon,Moder,GoblinKing,Yagluth,SeekerQueen,TheQueen", "CSV der Boss-Prefab-Namen (Teiltreffer erlaubt).");
			EndFightOnAnyPlayerDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Fight", "EndFightOnAnyPlayerDeath", true, "Beende Bosskampf, wenn irgendein Spieler stirbt.");
			_harmony = new Harmony("com.zeitsurfer.multiboss");
			_harmony.PatchAll(typeof(MultiBossPlugin));
			_harmony.PatchAll(typeof(CharacterBossSpawnPatches));
			_harmony.PatchAll(typeof(CharacterBossCleanup));
			_harmony.PatchAll(typeof(PlayerDeathPatches));
			_harmony.PatchAll(typeof(ConsoleCommands));
			if (ZRoutedRpc.instance != null)
			{
				try
				{
					ZRoutedRpc.instance.Register<long, string>("MB_PlayerDied", (Action<long, long, string>)RPC_PlayerDied);
				}
				catch
				{
				}
				try
				{
					ZRoutedRpc.instance.Register("MB_DespawnAll", (Action<long>)RPC_DespawnAll);
				}
				catch
				{
				}
				try
				{
					ZRoutedRpc.instance.Register<string>("MB_ShowParticipantDeath", (Action<long, string>)RPC_ShowParticipantDeath);
				}
				catch
				{
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[MultiBoss] 1.0.12 geladen. Server-authoritativ (Dedicated + Host/Singleplayer).");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static bool IsServerDedicated()
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				return ZNet.instance.IsDedicated();
			}
			return false;
		}

		internal static List<Player> GetPlayersInRadius(Vector3 center, float radius)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			List<Player> list = new List<Player>();
			Player.GetPlayersInRange(center, radius, list);
			return list;
		}

		internal static bool NameMatches(string prefabOrObjectName, string csv)
		{
			if (string.IsNullOrWhiteSpace(prefabOrObjectName))
			{
				return false;
			}
			string i = prefabOrObjectName.Trim().ToLowerInvariant();
			return (from s in csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select s.Trim().ToLowerInvariant()).Any((string token) => i.Contains(token));
		}

		internal static Vector3 FindOrMergeCenter(Vector3 center)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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)
			foreach (Vector3 item in RecentSpawnCenters.ToList())
			{
				if (Vector3.Distance(item, center) <= RecentCenterMergeRadius)
				{
					return item;
				}
			}
			RecentSpawnCenters.Add(center);
			return center;
		}

		internal static void RegisterFightParticipants(Vector3 center)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || FightParticipantsByCenter.ContainsKey(center))
			{
				return;
			}
			HashSet<long> hashSet = new HashSet<long>();
			foreach (Player item in GetPlayersInRadius(center, PlayerRadius.Value))
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					long playerID = item.GetPlayerID();
					if (playerID != 0L)
					{
						hashSet.Add(playerID);
						PlayerParticipationCenters[playerID] = center;
					}
				}
			}
			FightParticipantsByCenter[center] = hashSet;
		}

		internal static bool HandleParticipantDeath(long playerId, string playerName)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return false;
			}
			if (!PlayerParticipationCenters.TryGetValue(playerId, out var value))
			{
				return false;
			}
			if (!FightParticipantsByCenter.TryGetValue(value, out var value2) || value2.Count == 0)
			{
				return false;
			}
			string text = "Schildbruder " + playerName + " ist gefallen – die Bosse ziehen sich knurrend in den Nebel zurück!";
			long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0);
			foreach (long item in value2.ToList())
			{
				if (item != 0L)
				{
					if (num != 0L && item == num)
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
					}
					else if (ZRoutedRpc.instance != null)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(item, "MB_ShowParticipantDeath", new object[1] { text });
					}
				}
			}
			foreach (long item2 in value2)
			{
				PlayerParticipationCenters.Remove(item2);
			}
			FightParticipantsByCenter.Remove(value);
			return true;
		}

		internal static void RegisterBoss(GameObject go)
		{
			if (Object.op_Implicit((Object)(object)go))
			{
				ActiveBosses.Add(go);
			}
		}

		internal static bool MarkSpawnProcessed(Component c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return false;
			}
			int instanceID = ((Object)c.gameObject).GetInstanceID();
			if (SpawnProcessedIDs.Contains(instanceID))
			{
				return false;
			}
			SpawnProcessedIDs.Add(instanceID);
			return true;
		}

		private void EndAllBossesDelayed()
		{
			EndAllBossFights("Delay");
		}

		internal static void EndAllBossFights(string reason = "")
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return;
			}
			foreach (GameObject item in ActiveBosses.ToList())
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					ZNetView component = item.GetComponent<ZNetView>();
					if (Object.op_Implicit((Object)(object)component) && component.IsValid() && (Object)(object)ZNetScene.instance != (Object)null)
					{
						ZNetScene.instance.Destroy(item);
					}
					else
					{
						Object.Destroy((Object)(object)item);
					}
				}
			}
			ActiveBosses.Clear();
			RecentSpawnCenters.Clear();
			FightParticipantsByCenter.Clear();
			PlayerParticipationCenters.Clear();
			if (!string.IsNullOrEmpty(reason))
			{
				Debug.Log((object)("[MultiBoss] Bosskampf beendet: " + reason));
			}
		}

		private void RPC_PlayerDied(long sender, long playerId, string playerName)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && EndFightOnAnyPlayerDeath.Value && HandleParticipantDeath(playerId, playerName))
			{
				((MonoBehaviour)this).Invoke("EndAllBossesDelayed", 0.1f);
			}
		}

		private void RPC_DespawnAll(long sender)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				((MonoBehaviour)this).Invoke("EndAllBossesDelayed", 0.05f);
			}
		}

		private void RPC_ShowParticipantDeath(long sender, string message)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, message, 0, (Sprite)null);
			}
		}

		internal static void TrySpawnExtraBossesNear(Vector3 center, Character original = null)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return;
			}
			int num = Mathf.Max(GetPlayersInRadius(center, PlayerRadius.Value).Count, 1);
			int num2 = Mathf.Clamp(Mathf.FloorToInt((float)num / PlayersPerBoss.Value), 1, 1 + MaxExtraBosses.Value);
			int num3 = ActiveBosses.Count((GameObject go) => Object.op_Implicit((Object)(object)go) && Vector3.Distance(go.transform.position, center) <= PlayerRadius.Value * 1.2f);
			int num4 = Mathf.Max(0, num2 - num3);
			if (num4 <= 0)
			{
				Debug.Log((object)$"[MultiBoss] Spieler:{num} → SollGesamt:{num2}, Existierend:{num3}, Neu:0 @ {center}");
				return;
			}
			if (!Object.op_Implicit((Object)(object)original))
			{
				GameObject val = ((IEnumerable<GameObject>)ActiveBosses).FirstOrDefault((Func<GameObject, bool>)((GameObject go) => Object.op_Implicit((Object)(object)go) && Vector3.Distance(go.transform.position, center) <= PlayerRadius.Value * 1.2f));
				if (Object.op_Implicit((Object)(object)val))
				{
					original = val.GetComponent<Character>();
				}
			}
			if (!Object.op_Implicit((Object)(object)original))
			{
				return;
			}
			string prefabName = Utils.GetPrefabName(((Component)original).gameObject);
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				Debug.LogWarning((object)("[MultiBoss] Prefab '" + prefabName + "' nicht gefunden."));
				return;
			}
			float num5 = 8f;
			for (int i = 0; i < num4; i++)
			{
				float num6 = 360f / (float)Mathf.Max(num4, 1) * (float)i * ((float)Math.PI / 180f);
				Vector3 position = center + new Vector3(Mathf.Cos(num6), 0f, Mathf.Sin(num6)) * num5;
				GameObject val2 = SpawnBossPrefab(prefab, position, Quaternion.identity);
				if (Object.op_Implicit((Object)(object)val2))
				{
					ActiveBosses.Add(val2);
				}
			}
			Debug.Log((object)$"[MultiBoss] Spieler:{num} → SollGesamt:{num2}, Existierend:{num3}, Neu:{num4} @ {center}");
		}

		internal static GameObject SpawnBossPrefab(GameObject prefab, Vector3 position, Quaternion rotation)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null && ZDOMan.instance != null)
			{
				try
				{
					string prefabName = Utils.GetPrefabName(prefab);
					int stableHashCode = StringExtensionMethods.GetStableHashCode(prefabName);
					GameObject val = TrySpawnWithNetwork(prefab, prefabName, stableHashCode, position, rotation);
					if (Object.op_Implicit((Object)(object)val))
					{
						return val;
					}
				}
				catch (Exception ex)
				{
					if (!_networkSpawnWarningShown)
					{
						Debug.LogWarning((object)("[MultiBoss] Netzwerk-Spawn fehlgeschlagen, fallback auf lokale Instanziierung. Fehler: " + ex.Message));
						_networkSpawnWarningShown = true;
					}
				}
			}
			return Object.Instantiate<GameObject>(prefab, position, rotation);
		}

		private static GameObject TrySpawnWithNetwork(GameObject prefab, string prefabName, int prefabHash, Vector3 position, Quaternion rotation)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = CreateNewZDOCompat(position, prefabHash);
			if (val == null)
			{
				return null;
			}
			val.SetRotation(rotation);
			val.SetPrefab(prefabHash);
			val.SetPosition(position);
			MethodInfo[] methods = typeof(ZNetScene).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "CreateObject")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				bool flag = true;
				for (int j = 0; j < parameters.Length; j++)
				{
					Type parameterType = parameters[j].ParameterType;
					if (parameterType == typeof(ZDO))
					{
						array[j] = val;
						continue;
					}
					if (parameterType == typeof(int))
					{
						array[j] = prefabHash;
						continue;
					}
					if (parameterType == typeof(bool))
					{
						array[j] = true;
						continue;
					}
					if (parameterType == typeof(GameObject))
					{
						array[j] = prefab;
						continue;
					}
					if (parameterType == typeof(Vector3))
					{
						array[j] = position;
						continue;
					}
					if (parameterType == typeof(Quaternion))
					{
						array[j] = rotation;
						continue;
					}
					if (parameterType == typeof(string))
					{
						array[j] = prefabName;
						continue;
					}
					flag = false;
					break;
				}
				if (!flag)
				{
					continue;
				}
				try
				{
					object? obj = methodInfo.Invoke(ZNetScene.instance, array);
					GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
					if (val2 != null && Object.op_Implicit((Object)(object)val2))
					{
						return val2;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static ZDO CreateNewZDOCompat(Vector3 position, int prefabHash)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan instance = ZDOMan.instance;
			if (instance == null)
			{
				return null;
			}
			MethodInfo[] methods = ((object)instance).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "CreateNewZDO" || methodInfo.ReturnType != typeof(ZDO))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				try
				{
					if (parameters.Length == 2 && parameters[0].ParameterType == typeof(Vector3) && parameters[1].ParameterType == typeof(int))
					{
						object? obj = methodInfo.Invoke(instance, new object[2] { position, prefabHash });
						return (ZDO)((obj is ZDO) ? obj : null);
					}
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Vector3))
					{
						object? obj2 = methodInfo.Invoke(instance, new object[1] { position });
						return (ZDO)((obj2 is ZDO) ? obj2 : null);
					}
				}
				catch
				{
				}
			}
			return null;
		}

		internal static Character[] FindAllBossCharacters()
		{
			return (from ch in Object.FindObjectsByType<Character>((FindObjectsInactive)0, (FindObjectsSortMode)0)
				where NameMatches(Utils.GetPrefabName(((Component)ch).gameObject), BossPrefabNamesCsv.Value)
				select ch).ToArray();
		}
	}
	internal static class PluginInfo
	{
		internal const string GUID = "com.zeitsurfer.multiboss";

		internal const string NAME = "MultiBoss";

		internal const string VERSION = "1.0.12";
	}
}
namespace Zeitsurfer.MultiBoss.Patches
{
	[HarmonyPatch(typeof(Character))]
	public static class CharacterBossCleanup
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnDestroy")]
		private static void Character_OnDestroy_Postfix(Character __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance))
			{
				GameObject gameObject = ((Component)__instance).gameObject;
				if (MultiBossPlugin.ActiveBosses.Contains(gameObject))
				{
					MultiBossPlugin.ActiveBosses.Remove(gameObject);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character))]
	public static class CharacterBossSpawnPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Character_Awake_Postfix(Character __instance)
		{
			TryHandleBossSpawn(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Character_Start_Postfix(Character __instance)
		{
			TryHandleBossSpawn(__instance);
		}

		private static void TryHandleBossSpawn(Character ch)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ch) || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return;
			}
			ZNetView component = ((Component)ch).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid())
			{
				GameObject gameObject = ((Component)ch).gameObject;
				if (MultiBossPlugin.NameMatches(Utils.GetPrefabName(gameObject), MultiBossPlugin.BossPrefabNamesCsv.Value) && MultiBossPlugin.MarkSpawnProcessed((Component)(object)ch))
				{
					MultiBossPlugin.RegisterBoss(gameObject);
					Vector3 center = MultiBossPlugin.FindOrMergeCenter(((Component)ch).transform.position);
					MultiBossPlugin.TrySpawnExtraBossesNear(center, ch);
					MultiBossPlugin.RegisterFightParticipants(center);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	public static class ConsoleCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			public static ConsoleEvent <>9__0_1;

			internal void <Terminal_InitTerminal_Postfix>b__0_0(ConsoleEventArgs args)
			{
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: 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_0153: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)ZNet.instance))
				{
					Debug.Log((object)"[MultiBoss] [MultiBoss] no ZNet");
				}
				else if (ZNet.instance.IsServer())
				{
					if (MultiBossPlugin.ActiveBosses.Count == 0)
					{
						Debug.Log((object)"[MultiBoss] [MultiBoss] no active boss in memory");
						return;
					}
					Player localPlayer = Player.m_localPlayer;
					Vector3 val = (Object.op_Implicit((Object)(object)localPlayer) ? ((Component)localPlayer).transform.position : Vector3.zero);
					Vector3 val2 = val;
					float num = 1E+09f;
					foreach (GameObject activeBoss in MultiBossPlugin.ActiveBosses)
					{
						if (Object.op_Implicit((Object)(object)activeBoss))
						{
							float num2 = Vector3.Distance(activeBoss.transform.position, val);
							if (num2 < num)
							{
								num = num2;
								val2 = activeBoss.transform.position;
							}
						}
					}
					Character val3 = null;
					foreach (GameObject activeBoss2 in MultiBossPlugin.ActiveBosses)
					{
						if (Object.op_Implicit((Object)(object)activeBoss2) && Vector3.Distance(activeBoss2.transform.position, val2) <= MultiBossPlugin.PlayerRadius.Value * 1.2f)
						{
							val3 = activeBoss2.GetComponent<Character>();
							if (Object.op_Implicit((Object)(object)val3))
							{
								break;
							}
						}
					}
					if (Object.op_Implicit((Object)(object)val3))
					{
						MultiBossPlugin.TrySpawnExtraBossesNear(val2, val3);
						Vector3 val4 = val2;
						Debug.Log((object)("[MultiBoss] [MultiBoss] mb_test: spawned near center " + ((object)(Vector3)(ref val4)).ToString()));
					}
					else
					{
						Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test: no original found");
					}
				}
				else
				{
					Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test only on server/host");
				}
			}

			internal void <Terminal_InitTerminal_Postfix>b__0_1(ConsoleEventArgs args)
			{
				if (!Object.op_Implicit((Object)(object)ZNet.instance))
				{
					Debug.Log((object)"[MultiBoss] [MultiBoss] no ZNet");
					return;
				}
				if (ZNet.instance.IsServer())
				{
					((MonoBehaviour)MultiBossPlugin.Instance).Invoke("EndAllBossesDelayed", 0.1f);
					Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test2: requested despawn (server)");
					return;
				}
				ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
				if (serverPeer != null && ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "MB_DespawnAll", Array.Empty<object>());
					Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test2: requested despawn (client->server)");
				}
				else
				{
					Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test2: no server peer");
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("InitTerminal")]
		private static void Terminal_InitTerminal_Postfix(Terminal __instance)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate
				{
					//IL_0058: Unknown result type (might be due to invalid IL or missing references)
					//IL_004b: Unknown result type (might be due to invalid IL or missing references)
					//IL_005d: Unknown result type (might be due to invalid IL or missing references)
					//IL_005e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0092: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
					//IL_0145: 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_0153: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)ZNet.instance))
					{
						Debug.Log((object)"[MultiBoss] [MultiBoss] no ZNet");
					}
					else if (ZNet.instance.IsServer())
					{
						if (MultiBossPlugin.ActiveBosses.Count == 0)
						{
							Debug.Log((object)"[MultiBoss] [MultiBoss] no active boss in memory");
						}
						else
						{
							Player localPlayer = Player.m_localPlayer;
							Vector3 val3 = (Object.op_Implicit((Object)(object)localPlayer) ? ((Component)localPlayer).transform.position : Vector3.zero);
							Vector3 val4 = val3;
							float num = 1E+09f;
							foreach (GameObject activeBoss in MultiBossPlugin.ActiveBosses)
							{
								if (Object.op_Implicit((Object)(object)activeBoss))
								{
									float num2 = Vector3.Distance(activeBoss.transform.position, val3);
									if (num2 < num)
									{
										num = num2;
										val4 = activeBoss.transform.position;
									}
								}
							}
							Character val5 = null;
							foreach (GameObject activeBoss2 in MultiBossPlugin.ActiveBosses)
							{
								if (Object.op_Implicit((Object)(object)activeBoss2) && Vector3.Distance(activeBoss2.transform.position, val4) <= MultiBossPlugin.PlayerRadius.Value * 1.2f)
								{
									val5 = activeBoss2.GetComponent<Character>();
									if (Object.op_Implicit((Object)(object)val5))
									{
										break;
									}
								}
							}
							if (Object.op_Implicit((Object)(object)val5))
							{
								MultiBossPlugin.TrySpawnExtraBossesNear(val4, val5);
								Vector3 val6 = val4;
								Debug.Log((object)("[MultiBoss] [MultiBoss] mb_test: spawned near center " + ((object)(Vector3)(ref val6)).ToString()));
							}
							else
							{
								Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test: no original found");
							}
						}
					}
					else
					{
						Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test only on server/host");
					}
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("mb_test", "Spawn extra bosses near nearest active boss center (server/host only).", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj2 = <>c.<>9__0_1;
			if (obj2 == null)
			{
				ConsoleEvent val2 = delegate
				{
					if (!Object.op_Implicit((Object)(object)ZNet.instance))
					{
						Debug.Log((object)"[MultiBoss] [MultiBoss] no ZNet");
					}
					else if (ZNet.instance.IsServer())
					{
						((MonoBehaviour)MultiBossPlugin.Instance).Invoke("EndAllBossesDelayed", 0.1f);
						Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test2: requested despawn (server)");
					}
					else
					{
						ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
						if (serverPeer != null && ZRoutedRpc.instance != null)
						{
							ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "MB_DespawnAll", Array.Empty<object>());
							Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test2: requested despawn (client->server)");
						}
						else
						{
							Debug.Log((object)"[MultiBoss] [MultiBoss] mb_test2: no server peer");
						}
					}
				};
				<>c.<>9__0_1 = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("mb_test2", "Despawn all active bosses (server authoritative).", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	[HarmonyPatch(typeof(Player))]
	public static class PlayerDeathPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnDeath")]
		private static void Player_OnDeath_Postfix(Player __instance)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !MultiBossPlugin.EndFightOnAnyPlayerDeath.Value)
			{
				return;
			}
			long playerID = __instance.GetPlayerID();
			string playerName = __instance.GetPlayerName();
			if (ZNet.instance.IsServer())
			{
				if (MultiBossPlugin.HandleParticipantDeath(playerID, playerName))
				{
					((MonoBehaviour)MultiBossPlugin.Instance).Invoke("EndAllBossesDelayed", 0.1f);
				}
				return;
			}
			ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
			if (serverPeer != null && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "MB_PlayerDied", new object[2] { playerID, playerName });
			}
		}
	}
}