Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of WhoDiedFirst v0.1.1
BepInEx/Plugins/WhoDiedFirst.dll
Decompiled 2 years agousing 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 { } }