Decompiled source of WhoDiedFirst v0.1.1

BepInEx/Plugins/WhoDiedFirst.dll

Decompiled 10 months ago
using System;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using WhoDiedFirst.Helpers;
using WhoDiedFirst.Managers;
using WhoDiedFirst.NetcodePatcher;
using WhoDiedFirst.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WhoDiedFirst")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WhoDiedFirst")]
[assembly: AssemblyTitle("WhoDiedFirst")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 WhoDiedFirst
{
	public static class ConfigSettings
	{
		public static ConfigEntry<bool> isDebug;

		public static ConfigEntry<bool> includeDisconnects;

		public static ConfigEntry<bool> includeAbandoned;

		public static ConfigEntry<bool> addWDFNote;

		public static ConfigEntry<bool> overrideScoreboard;

		public static ConfigEntry<bool> addDCToScoreboard;

		public static ConfigEntry<bool> addDeathPlacementsToScoreboard;

		public static ConfigEntry<int> deathPlacementWindow;

		public static void BindConfigSettings()
		{
			isDebug = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("Overall", "Debug Messages", false, "Debug messages to console.");
			includeDisconnects = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("DeathQualifiers", "includeDisconnects", true, "Should include those who disconnect in deathOrder");
			includeAbandoned = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("DeathQualifiers", "includeAbandoned", true, "Should include those who are abandoned in deathOrder");
			addWDFNote = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("DeathOverrides", "addWDFNote", true, "Adds a note on who died first to the end of round screen.");
			overrideScoreboard = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("DeathOverrides", "overrideScoreboard", true, "Modifies the scoreboard to order each player based on when they died.");
			addDCToScoreboard = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("DeathOverrides", "addDCToScoreboard", true, "Updates the scoreboard with a DC tag when someone DCs.");
			addDeathPlacementsToScoreboard = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<bool>("DeathOverrides", "addDeathPlacementsToScoreboard", true, "Adds death placements alongside when someone dies. This is only for when two people die at the same time.");
			deathPlacementWindow = ((BaseUnityPlugin)MainPlugin.Instance).Config.Bind<int>("DeathOverrides", "deathPlacementWindow", 300, "The window in which a number of people can die at the same time. The lowest value acceptable is 1. I'll probably do an override check because people don't read lmao.");
		}
	}
	[BepInPlugin("lc.zapajax.whodiedfirst", "Who Died First", "0.1.1")]
	public class MainPlugin : BaseUnityPlugin
	{
		private const string GUID = "lc.zapajax.whodiedfirst";

		private const string NAME = "Who Died First";

		private const string VERSION = "0.1.1";

		private readonly Harmony harmony = new Harmony("lc.zapajax.whodiedfirst");

		public static MainPlugin Instance;

		public static LogHandler lh;

		public GameObject netManagerPrefab;

		public static List<SimplePlayer> deathOrder = new List<SimplePlayer>();

		public static string wdfLastRound = "";

		public static string planetName;

		public static bool isOnPlanet = false;

		public void Awake()
		{
			Instance = this;
			lh = new LogHandler(((BaseUnityPlugin)this).Logger);
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			ConfigSettings.BindConfigSettings();
			lh.Log("Finished Binding Config File");
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "netcode-wdf");
			AssetBundle val = AssetBundle.LoadFromFile(text);
			netManagerPrefab = val.LoadAsset<GameObject>("Assets/NetcodeObjs/NetcodeObj-WDF.prefab");
			netManagerPrefab.AddComponent<NetcodeManager>();
			harmony.PatchAll(typeof(ElevatorAnimationEventsPatch));
			harmony.PatchAll(typeof(GameNetworkManagerPatch));
			harmony.PatchAll(typeof(HUDManagerPatch));
			harmony.PatchAll(typeof(PlayerControllerBPatch));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			lh.Log("Finished Loading");
		}
	}
}
namespace WhoDiedFirst.Patches
{
	[HarmonyPatch(typeof(ElevatorAnimationEvents))]
	internal class ElevatorAnimationEventsPatch
	{
		[HarmonyPatch("ElevatorFullyRunning")]
		[HarmonyPrefix]
		private static void UpdateDeathOrderOnAbandoned(ElevatorAnimationEvents __instance)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Invalid comparison between Unknown and I4
			if (!ConfigSettings.includeAbandoned.Value || GameNetworkManager.Instance.localPlayerController.isInElevator || MainPlugin.planetName == "71 Gordion" || (int)GameNetworkManager.Instance.localPlayerController.causeOfDeath != 10)
			{
				return;
			}
			ulong actualClientId = GameNetworkManager.Instance.localPlayerController.actualClientId;
			long timeOfDeath = DateTimeOffset.Now.ToUnixTimeMilliseconds() / ConfigSettings.deathPlacementWindow.Value;
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost || ((NetworkBehaviour)StartOfRound.Instance).IsServer)
			{
				NetcodeManager.Instance.UpdateDeathOrderClientRpc(actualClientId, timeOfDeath);
				return;
			}
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Notifying Server");
			}
			Utilities.addToDeathOrder(actualClientId, timeOfDeath, cache: true);
			NetcodeManager.Instance.UpdateDeathOrderServerRpc(actualClientId, timeOfDeath);
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void AddToPrefabs(ref GameNetworkManager __instance)
		{
			((Component)__instance).GetComponent<NetworkManager>().AddNetworkPrefab(MainPlugin.Instance.netManagerPrefab);
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDManagerPatch
	{
		[HarmonyPatch("UpdateBoxesSpectateUI")]
		[HarmonyPrefix]
		public static bool UpdateBoxesSpectateUIPatcher(HUDManager __instance, ref Dictionary<Animator, PlayerControllerB> ___spectatingPlayerBoxes, ref float ___yOffsetAmount, ref int ___boxesAdded, ref GameObject ___spectatingPlayerBoxPrefab, ref Transform ___SpectateBoxesContainer)
		{
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigSettings.overrideScoreboard.Value)
			{
				return true;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(HUDManager), "FillImageWithSteamProfile", (Type[])null, (Type[])null);
			PlayerControllerB[] array = Utilities.orderPlayerScriptsByDeath(StartOfRound.Instance.allPlayerScripts);
			PlayerControllerB playerScript;
			for (int i = 0; i < array.Length; i++)
			{
				playerScript = array[i];
				string text = Utilities.playerStatus(playerScript);
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log(" -Name: " + playerScript.playerUsername + " - status: " + text);
				}
				if (text != "dead" && text != "disconnected")
				{
					if (ConfigSettings.isDebug.Value)
					{
						MainPlugin.lh.Log(" - Alive");
					}
					continue;
				}
				if (!___spectatingPlayerBoxes.Values.Contains(playerScript))
				{
					if (text == "disconnected" && !ConfigSettings.includeDisconnects.Value)
					{
						continue;
					}
					if (ConfigSettings.isDebug.Value)
					{
						MainPlugin.lh.Log(" - New Spectator");
					}
					GameObject val = Object.Instantiate<GameObject>(___spectatingPlayerBoxPrefab, ___SpectateBoxesContainer, false);
					val.SetActive(true);
					RectTransform component = val.GetComponent<RectTransform>();
					component.anchoredPosition = new Vector2(component.anchoredPosition.x, ___yOffsetAmount);
					___yOffsetAmount -= 70f;
					___boxesAdded++;
					___spectatingPlayerBoxes.Add(val.GetComponent<Animator>(), playerScript);
					int num = Utilities.determineDeathPlacement(Utilities.indexOfIdInDeathOrder(playerScript.actualClientId));
					string text2 = playerScript.playerUsername;
					if (ConfigSettings.addDeathPlacementsToScoreboard.Value)
					{
						text2 = num + ": " + text2;
					}
					bool flag = false;
					if (text == "disconnected" && ConfigSettings.addDCToScoreboard.Value)
					{
						if (ConfigSettings.isDebug.Value)
						{
							MainPlugin.lh.Log(" - is DC'd");
						}
						text2 += " [DC]";
						flag = true;
					}
					((TMP_Text)val.GetComponentInChildren<TextMeshProUGUI>()).text = text2;
					if (!GameNetworkManager.Instance.disableSteam && !flag)
					{
						RawImage component2 = val.GetComponent<RawImage>();
						SteamId val2 = default(SteamId);
						val2.Value = playerScript.playerSteamId;
						if (ConfigSettings.isDebug.Value)
						{
							MainPlugin.lh.Log("playerScript.playerSteamId: " + playerScript.playerSteamId.GetType().ToString() + " - " + playerScript.playerSteamId);
						}
						methodInfo.Invoke(__instance, new object[3] { component2, val2, true });
					}
					continue;
				}
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log(" - Old Spectator");
				}
				Animator key = ___spectatingPlayerBoxes.FirstOrDefault((KeyValuePair<Animator, PlayerControllerB> x) => (Object)(object)x.Value == (Object)(object)playerScript).Key;
				GameObject gameObject = ((Component)key).gameObject;
				int num2 = Utilities.determineDeathPlacement(Utilities.indexOfIdInDeathOrder(playerScript.actualClientId));
				string text3 = playerScript.playerUsername;
				if (ConfigSettings.addDeathPlacementsToScoreboard.Value)
				{
					text3 = num2 + ": " + text3;
				}
				if (text == "disconnected" && ConfigSettings.includeDisconnects.Value && ConfigSettings.addDCToScoreboard.Value)
				{
					if (text3.IndexOf(" [DC]") == -1)
					{
						text3 += " [DC]";
					}
				}
				else if (text == "disconnected" && !ConfigSettings.includeDisconnects.Value)
				{
					if (gameObject.activeSelf)
					{
						for (int j = 0; j < ___spectatingPlayerBoxes.Count; j++)
						{
							RectTransform component3 = ((Component)___spectatingPlayerBoxes.ElementAt(j).Key).gameObject.GetComponent<RectTransform>();
							if (component3.anchoredPosition.y <= -70f * (float)___boxesAdded + 1f)
							{
								component3.anchoredPosition = new Vector2(component3.anchoredPosition.x, component3.anchoredPosition.y + 70f);
							}
						}
						___yOffsetAmount += 70f;
					}
					___spectatingPlayerBoxes.Remove(key);
					Object.Destroy((Object)(object)gameObject);
				}
				((TMP_Text)gameObject.GetComponentInChildren<TextMeshProUGUI>()).text = text3;
				if (!gameObject.activeSelf)
				{
					RectTransform component4 = gameObject.GetComponent<RectTransform>();
					component4.anchoredPosition = new Vector2(component4.anchoredPosition.x, ___yOffsetAmount);
					___boxesAdded++;
					gameObject.SetActive(true);
					___yOffsetAmount -= 70f;
				}
			}
			return false;
		}

		[HarmonyPatch("SubmitChat_performed")]
		[HarmonyPrefix]
		private static bool lookForCmdStr(HUDManager __instance)
		{
			//IL_0155: 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_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: 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_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			__instance.localPlayer = GameNetworkManager.Instance.localPlayerController;
			string text = __instance.chatTextField.text.ToLower();
			MethodInfo methodInfo = AccessTools.Method(typeof(HUDManager), "AddChatMessage", (Type[])null, (Type[])null);
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log(text);
			}
			if (text == "/wdf")
			{
				flag = true;
				string text2 = ((!(MainPlugin.wdfLastRound != "")) ? "No one died last round." : (MainPlugin.wdfLastRound + " died first last round."));
				__instance.lastChatMessage = "";
				methodInfo.Invoke(__instance, new object[2] { text2, "WDF" });
			}
			else if (text == "/status" && ConfigSettings.isDebug.Value)
			{
				flag = true;
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("Planet: " + MainPlugin.planetName + " | IsOnPlanet: " + MainPlugin.isOnPlanet);
				}
			}
			else if (text == "/kill" && ConfigSettings.isDebug.Value)
			{
				flag = true;
				__instance.localPlayer.KillPlayer(default(Vector3), false, (CauseOfDeath)0, 0);
			}
			else if (text == "/ps" && ConfigSettings.isDebug.Value)
			{
				flag = true;
				Utilities.printPlayerScripts();
			}
			else if (text == "/do" && ConfigSettings.isDebug.Value)
			{
				flag = true;
				Utilities.printDeathOrder();
			}
			else if (text == "/lm" && ConfigSettings.isDebug.Value)
			{
				flag = true;
				GameObject val = GameObject.FindGameObjectWithTag("MapPropsContainer");
				GameObject prefabToSpawn = RoundManager.Instance.currentLevel.spawnableMapObjects[0].prefabToSpawn;
				Vector3 position = ((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.position;
				Vector3 forward = ((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.forward;
				position += forward * 3f;
				GameObject val2 = Object.Instantiate<GameObject>(prefabToSpawn, position, Quaternion.identity, val.transform);
				val2.GetComponent<NetworkObject>().Spawn(true);
			}
			else if (text.StartsWith("/spawn ") && ConfigSettings.isDebug.Value)
			{
				flag = true;
				text = text.Substring(7);
				bool flag2 = false;
				string text3 = "";
				SelectableLevel currentLevel = RoundManager.Instance.currentLevel;
				foreach (SpawnableEnemyWithRarity enemy in currentLevel.Enemies)
				{
					if (enemy.enemyType.enemyName.ToLower().Contains(text.ToLower()))
					{
						flag2 = true;
						text3 = enemy.enemyType.enemyName;
						SpawnEnemy(enemy, 1, inside: true);
						MainPlugin.lh.Log("Spawned: " + enemy.enemyType.enemyName);
					}
				}
				if (!flag2)
				{
					foreach (SpawnableEnemyWithRarity outsideEnemy in currentLevel.OutsideEnemies)
					{
						if (outsideEnemy.enemyType.enemyName.ToLower().Contains(text.ToLower()))
						{
							flag2 = true;
							text3 = outsideEnemy.enemyType.enemyName;
							SpawnEnemy(outsideEnemy, 1, inside: false);
							MainPlugin.lh.Log("Spawned: " + outsideEnemy.enemyType.enemyName);
						}
					}
				}
			}
			if (flag)
			{
				__instance.localPlayer.isTypingChat = false;
				__instance.chatTextField.text = "";
				EventSystem.current.SetSelectedGameObject((GameObject)null);
				__instance.PingHUDElement(__instance.Chat, 2f, 1f, 0.2f);
				((Behaviour)__instance.typingIndicator).enabled = false;
				return false;
			}
			return true;
		}

		[HarmonyPatch("AddChatMessage")]
		[HarmonyPostfix]
		private static void ignoreLastCheckMessage(HUDManager __instance)
		{
		}

		private static void SpawnEnemy(SpawnableEnemyWithRarity enemy, int amount, bool inside)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			if (inside)
			{
				RoundManager instance = RoundManager.Instance;
				SelectableLevel currentLevel = RoundManager.Instance.currentLevel;
				instance.SpawnEnemyOnServer(instance.allEnemyVents[Random.Range(0, instance.allEnemyVents.Length)].floorNode.position, instance.allEnemyVents[0].floorNode.eulerAngles.y, currentLevel.Enemies.IndexOf(enemy));
			}
			else
			{
				SelectableLevel currentLevel2 = RoundManager.Instance.currentLevel;
				GameObject val = Object.Instantiate<GameObject>(currentLevel2.OutsideEnemies[currentLevel2.OutsideEnemies.IndexOf(enemy)].enemyType.enemyPrefab, GameObject.FindGameObjectsWithTag("OutsideAINode")[Random.Range(0, GameObject.FindGameObjectsWithTag("OutsideAINode").Length - 1)].transform.position, Quaternion.Euler(Vector3.zero));
				val.gameObject.GetComponentInChildren<NetworkObject>().Spawn(true);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		[HarmonyPatch("KillPlayer")]
		[HarmonyPrefix]
		private static void UpdateDeathOrderOnPlayerDeath(PlayerControllerB __instance)
		{
			if (!((NetworkBehaviour)__instance).IsOwner || __instance.isPlayerDead || !__instance.AllowPlayerDeath() || MainPlugin.planetName == "71 Gordion" || !MainPlugin.isOnPlanet)
			{
				return;
			}
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Attempting Notification");
			}
			long timeOfDeath = DateTimeOffset.Now.ToUnixTimeMilliseconds() / ConfigSettings.deathPlacementWindow.Value;
			if (((NetworkBehaviour)__instance).IsHost || ((NetworkBehaviour)__instance).IsServer)
			{
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("Notifying Client");
				}
				ulong actualClientId = __instance.actualClientId;
				NetcodeManager.Instance.UpdateDeathOrderClientRpc(actualClientId, timeOfDeath);
			}
			else
			{
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("Notifying Server");
				}
				ulong actualClientId2 = __instance.actualClientId;
				Utilities.addToDeathOrder(actualClientId2, timeOfDeath, cache: true);
				NetcodeManager.Instance.UpdateDeathOrderServerRpc(actualClientId2, timeOfDeath);
			}
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Going to the rest of the KillPlayer function");
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void spawnNetManager(StartOfRound __instance)
		{
			if (((NetworkBehaviour)__instance).IsHost)
			{
				GameObject val = Object.Instantiate<GameObject>(MainPlugin.Instance.netManagerPrefab);
				val.GetComponent<NetworkObject>().Spawn(false);
			}
		}

		[HarmonyPatch("OnPlayerDC")]
		[HarmonyPrefix]
		private static void UpdateDeathOrderOnPlayerDC(StartOfRound __instance, ref int playerObjectNumber, ref ulong clientId)
		{
			if (!ConfigSettings.includeDisconnects.Value || !__instance.ClientPlayerList.ContainsKey(clientId) || ((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && clientId == GameNetworkManager.Instance.localPlayerController.actualClientId) || ((NetworkBehaviour)__instance).NetworkManager.ShutdownInProgress || (Object)(object)NetworkManager.Singleton == (Object)null || Utilities.isPlayerInDeathOrder(clientId) || MainPlugin.planetName == "71 Gordion" || !MainPlugin.isOnPlanet)
			{
				return;
			}
			long timeOfDeath = DateTimeOffset.Now.ToUnixTimeMilliseconds() / ConfigSettings.deathPlacementWindow.Value;
			if (((NetworkBehaviour)__instance).IsHost || ((NetworkBehaviour)__instance).IsServer)
			{
				NetcodeManager.Instance.UpdateDeathOrderClientRpc(clientId, timeOfDeath);
				return;
			}
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Notifying Server");
			}
			Utilities.addToDeathOrder(clientId, timeOfDeath, cache: true);
			NetcodeManager.Instance.UpdateDeathOrderServerRpc(clientId, timeOfDeath);
		}

		[HarmonyPatch("ResetStats")]
		[HarmonyPostfix]
		private static void clearDeathList(StartOfRound __instance)
		{
			MainPlugin.isOnPlanet = true;
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Planet Name: " + MainPlugin.planetName);
			}
			if (!(MainPlugin.planetName == "71 Gordion"))
			{
				MainPlugin.deathOrder.Clear();
			}
		}

		[HarmonyPatch("WritePlayerNotes")]
		[HarmonyPostfix]
		private static void addFirstDeathToNotes(StartOfRound __instance, ref EndOfGameStats ___gameStats)
		{
			if (MainPlugin.planetName == "71 Gordion")
			{
				return;
			}
			List<SimplePlayer> deathOrder = MainPlugin.deathOrder;
			if (deathOrder.Count == 0)
			{
				MainPlugin.wdfLastRound = "";
				return;
			}
			List<SimplePlayer> list = new List<SimplePlayer>();
			List<ulong> list2 = new List<ulong>();
			for (int i = 0; i < deathOrder.Count; i++)
			{
				int num = Utilities.determineDeathPlacement(i);
				if (num == 1)
				{
					list.Add(deathOrder[i]);
					list2.Add(deathOrder[i].id);
				}
				if (num > 1)
				{
					break;
				}
			}
			string text = list[0].name;
			if (list.Count == 2)
			{
				text = text + " and " + list[1].name;
			}
			else if (list.Count > 2)
			{
				for (int j = 1; j < list.Count - 1; j++)
				{
					text = text + ", " + list[j].name;
				}
				if (list.Count > 1)
				{
					text = text + ", and " + list[list.Count - 1].name;
				}
			}
			MainPlugin.wdfLastRound = text;
			if (!ConfigSettings.addWDFNote.Value)
			{
				return;
			}
			for (int k = 0; k < __instance.allPlayerScripts.Length; k++)
			{
				string text2 = Utilities.playerStatus(__instance.allPlayerScripts[k]);
				if (list2.Contains(__instance.allPlayerScripts[k].actualClientId) && text2 != "blank" && text2 != "na")
				{
					___gameStats.allPlayerStats[k].playerNotes.Add("Died First");
				}
			}
			for (int l = 0; l < __instance.allPlayerScripts.Length; l++)
			{
				PlayerControllerB val = __instance.allPlayerScripts[l];
				MainPlugin.lh.Log("Player: " + val.playerUsername);
				List<string> playerNotes = ___gameStats.allPlayerStats[l].playerNotes;
				for (int m = 0; m < playerNotes.Count; m++)
				{
					MainPlugin.lh.Log(" - " + playerNotes[m]);
				}
			}
		}

		[HarmonyPatch("ChangeLevel")]
		[HarmonyPostfix]
		private static void savePlanetNameOnChange(StartOfRound __instance)
		{
			MainPlugin.planetName = __instance.currentLevel.PlanetName;
		}

		[HarmonyPatch("EndOfGame")]
		[HarmonyPostfix]
		private static void LeftPlanet()
		{
			MainPlugin.isOnPlanet = true;
		}
	}
}
namespace WhoDiedFirst.Managers
{
	internal class NetcodeManager : NetworkBehaviour
	{
		public static NetcodeManager Instance;

		private void Awake()
		{
			Instance = this;
		}

		[ServerRpc(RequireOwnership = false)]
		public void UpdateDeathOrderServerRpc(ulong id, long timeOfDeath)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3368827615u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, id);
				BytePacker.WriteValueBitPacked(val2, timeOfDeath);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3368827615u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("Server to Client");
				}
				UpdateDeathOrderClientRpc(id, timeOfDeath);
			}
		}

		[ClientRpc]
		public void UpdateDeathOrderClientRpc(ulong id, long timeOfDeath)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(110921536u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, id);
				BytePacker.WriteValueBitPacked(val2, timeOfDeath);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 110921536u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("Attempt add to Death Order");
				}
				Utilities.addToDeathOrder(id, timeOfDeath);
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_NetcodeManager()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(3368827615u, new RpcReceiveHandler(__rpc_handler_3368827615));
			NetworkManager.__rpc_func_table.Add(110921536u, new RpcReceiveHandler(__rpc_handler_110921536));
		}

		private static void __rpc_handler_3368827615(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong id = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				long timeOfDeath = default(long);
				ByteUnpacker.ReadValueBitPacked(reader, ref timeOfDeath);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((NetcodeManager)(object)target).UpdateDeathOrderServerRpc(id, timeOfDeath);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_110921536(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong id = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				long timeOfDeath = default(long);
				ByteUnpacker.ReadValueBitPacked(reader, ref timeOfDeath);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((NetcodeManager)(object)target).UpdateDeathOrderClientRpc(id, timeOfDeath);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "NetcodeManager";
		}
	}
}
namespace WhoDiedFirst.Helpers
{
	public class LogHandler
	{
		public ManualLogSource mls;

		public LogHandler(ManualLogSource mls)
		{
			this.mls = mls;
		}

		public void Log(string msg)
		{
			long num = DateTimeOffset.Now.ToUnixTimeMilliseconds();
			mls.LogInfo((object)(msg + " || " + num));
		}

		public void LogError(string msg)
		{
			long num = DateTimeOffset.Now.ToUnixTimeMilliseconds();
			mls.LogError((object)(msg + " || " + num));
		}

		public void LogWarning(string msg)
		{
			long num = DateTimeOffset.Now.ToUnixTimeMilliseconds();
			mls.LogWarning((object)(msg + " || " + num));
		}
	}
	public class SimplePlayer
	{
		public ulong id { get; set; }

		public string name { get; set; }

		public long timeOfDeath { get; set; }

		public PlayerControllerB playerScript { get; set; }

		public bool isCached { get; set; }

		public SimplePlayer(ulong id, string name, long timeOfDeath, PlayerControllerB playerScript, bool isCached = false)
		{
			this.id = id;
			this.name = name;
			this.timeOfDeath = timeOfDeath;
			this.playerScript = playerScript;
			this.isCached = isCached;
		}
	}
	public class Utilities
	{
		public static int indexOfPlayerScript(ulong id, PlayerControllerB[] playerScripts)
		{
			for (int i = 0; i < playerScripts.Length; i++)
			{
				if (playerScripts[i].actualClientId == id)
				{
					return i;
				}
			}
			return -1;
		}

		public static void addToDeathOrder(ulong id, long timeOfDeath, bool cache = false)
		{
			if (MainPlugin.planetName == "71 Gordion" || !MainPlugin.isOnPlanet)
			{
				return;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			int num = indexOfPlayerScript(id, allPlayerScripts);
			if (num < 0)
			{
				printPlayerScripts();
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.LogError("Something is wrong with the id. It returned: " + num + " - id: " + id);
				}
				return;
			}
			PlayerControllerB val = allPlayerScripts[num];
			SimplePlayer item = new SimplePlayer(id, val.playerUsername, timeOfDeath, val, cache);
			if (!isPlayerInDeathOrder(id))
			{
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("Add to Death Order");
				}
				int num2;
				for (num2 = MainPlugin.deathOrder.Count - 1; num2 >= 0; num2--)
				{
					SimplePlayer simplePlayer = MainPlugin.deathOrder[num2];
					if (simplePlayer.timeOfDeath <= timeOfDeath)
					{
						break;
					}
				}
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log("On Insertion - idx: " + num2 + " - cahced: " + cache);
				}
				MainPlugin.deathOrder.Insert(num2 + 1, item);
			}
			else if (GameNetworkManager.Instance.localPlayerController.actualClientId == id && !cache)
			{
				for (int i = 0; i < MainPlugin.deathOrder.Count; i++)
				{
					if (MainPlugin.deathOrder[i].id == id)
					{
						MainPlugin.deathOrder[i].isCached = false;
					}
				}
			}
			printDeathOrder();
		}

		public static int indexOfIdInDeathOrder(ulong id)
		{
			List<SimplePlayer> deathOrder = MainPlugin.deathOrder;
			for (int i = 0; i < deathOrder.Count; i++)
			{
				SimplePlayer simplePlayer = deathOrder[i];
				if (simplePlayer.id == id)
				{
					return i;
				}
			}
			return -1;
		}

		public static int determineDeathPlacement(int idx)
		{
			List<SimplePlayer> deathOrder = MainPlugin.deathOrder;
			int num = 0;
			long num2 = 0L;
			for (int i = 0; i <= idx; i++)
			{
				SimplePlayer simplePlayer = deathOrder[i];
				if (num2 == 0L || num2 != simplePlayer.timeOfDeath)
				{
					num2 = simplePlayer.timeOfDeath;
					num++;
				}
			}
			if (num == 0)
			{
				num = -1;
			}
			return num;
		}

		public static void printDeathOrder()
		{
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Printing Death Order");
			}
			for (int i = 0; i < MainPlugin.deathOrder.Count; i++)
			{
				SimplePlayer simplePlayer = MainPlugin.deathOrder[i];
				string text = "-Player: " + simplePlayer.name;
				text = text + " -id: " + simplePlayer.id;
				text = text + " -tod: " + simplePlayer.timeOfDeath;
				if ((Object)(object)simplePlayer.playerScript != (Object)null)
				{
					text = text + " -status: " + playerStatus(simplePlayer.playerScript);
				}
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log(text);
				}
			}
		}

		public static void printPlayerScripts()
		{
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Printing Player Scripts");
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			for (int i = 0; i < allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = allPlayerScripts[i];
				string text = "";
				text = text + " -idx: " + i;
				text = text + " -name: " + val.playerUsername;
				text = text + " -id: " + val.actualClientId;
				text = text + " -pId: " + val.playerClientId;
				text = text + " -status: " + playerStatus(val);
				if (ConfigSettings.isDebug.Value)
				{
					MainPlugin.lh.Log(text);
				}
			}
		}

		public static PlayerControllerB[] orderPlayerScriptsByDeath(PlayerControllerB[] playerScripts)
		{
			PlayerControllerB[] array = (PlayerControllerB[])(object)new PlayerControllerB[playerScripts.Length];
			PlayerControllerB[] array2 = (PlayerControllerB[])playerScripts.Clone();
			List<SimplePlayer> deathOrder = MainPlugin.deathOrder;
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Start of Ordering");
			}
			int i;
			for (i = 0; i < deathOrder.Count; i++)
			{
				SimplePlayer simplePlayer = deathOrder[i];
				int num = indexOfPlayerScript(simplePlayer.id, playerScripts);
				array[i] = playerScripts[num];
				array2[num] = null;
			}
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("Midpoint of Ordering");
			}
			for (int j = 0; j < playerScripts.Length; j++)
			{
				if (!((Object)(object)array2[j] == (Object)null))
				{
					array[i] = array2[j];
					i++;
				}
			}
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log("End of Ordering");
			}
			return array;
		}

		public static string playerStatus(PlayerControllerB playerScript)
		{
			if (playerScript.disconnectedMidGame)
			{
				return "disconnected";
			}
			if (playerScript.isPlayerDead && !playerScript.isPlayerControlled)
			{
				return "dead";
			}
			if (!playerScript.isPlayerDead && playerScript.isPlayerControlled)
			{
				return "living";
			}
			if (!playerScript.isPlayerDead && !playerScript.isPlayerControlled)
			{
				return "blank";
			}
			return "na";
		}

		public static void printInfo(PlayerControllerB playerScript)
		{
			if (ConfigSettings.isDebug.Value)
			{
				MainPlugin.lh.Log(playerScript.playerUsername + " Status: " + playerStatus(playerScript));
			}
		}

		public static bool isPlayerInDeathOrder(ulong id)
		{
			List<SimplePlayer> deathOrder = MainPlugin.deathOrder;
			for (int i = 0; i < deathOrder.Count; i++)
			{
				if (deathOrder[i].id == id)
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace WhoDiedFirst.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}