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 BepInEx.Logging; using BunkbedRevive.Configuration; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; [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: AssemblyCompany("BunkbedRevive")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BunkbedRevive")] [assembly: AssemblyTitle("BunkbedRevive")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BunkbedRevive { public class BunkbedController : MonoBehaviour { private static InteractTrigger interactTrigger; private static Sprite defaultIcon; private static Sprite disabledIcon; public static BunkbedController Instance; public static int GetReviveCost() { return ModConfig.ReviveCost.Value; } public static bool HasDeadPlayers() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return false; } return StartOfRound.Instance.connectedPlayersAmount + 1 - StartOfRound.Instance.livingPlayers > 0; } private static void CreateTrigger() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_004f: 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_006a: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown GameObject val = new GameObject("ReviveBed", new Type[2] { typeof(BoxCollider), typeof(InteractTrigger) }); val.transform.SetParent(((Component)Instance).transform); val.transform.localPosition = Vector3.zero; val.layer = LayerMask.NameToLayer("InteractableObject"); val.tag = "InteractTrigger"; BoxCollider component = val.GetComponent(); component.center = Vector3.zero; component.size = new Vector3(2.5f, 3f, 1f); ((Collider)component).enabled = true; interactTrigger = val.GetComponent(); interactTrigger.twoHandedItemAllowed = true; interactTrigger.interactable = true; interactTrigger.holdInteraction = false; interactTrigger.timeToHold = 0.4f; interactTrigger.cooldownTime = 0.25f; interactTrigger.timeToHoldSpeedMultiplier = 1f; int reviveCost = GetReviveCost(); interactTrigger.hoverTip = "Revive for " + ((reviveCost <= 0) ? "free" : (reviveCost + " credits")) + " : [E]"; interactTrigger.hoverIcon = defaultIcon; interactTrigger.disabledHoverIcon = disabledIcon; interactTrigger.disabledHoverTip = "No dead players"; interactTrigger.onCancelAnimation = new InteractEvent(); interactTrigger.holdingInteractEvent = new InteractEventFloat(); interactTrigger.onInteractEarly = new InteractEvent(); interactTrigger.onInteract = new InteractEvent(); interactTrigger.onStopInteract = new InteractEvent(); ((UnityEvent)(object)interactTrigger.onInteract).AddListener((UnityAction)delegate { OnInteract(); }); ((UnityEvent)(object)interactTrigger.onStopInteract).AddListener((UnityAction)delegate { OnStopInteract(); }); } private static void GetIcons() { StartMatchLever val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { defaultIcon = val.triggerScript.hoverIcon; disabledIcon = val.triggerScript.disabledHoverIcon; } } private static RagdollGrabbableObject GetHeldBody() { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (!localPlayerController.isHoldingObject || (Object)(object)localPlayerController.currentlyHeldObjectServer == (Object)null) { return null; } GrabbableObject currentlyHeldObjectServer = localPlayerController.currentlyHeldObjectServer; RagdollGrabbableObject val = (RagdollGrabbableObject)(object)((currentlyHeldObjectServer is RagdollGrabbableObject) ? currentlyHeldObjectServer : null); if (val != null) { return val; } return null; } private void Awake() { Instance = this; GetIcons(); CreateTrigger(); } private void Update() { if (!((Object)(object)StartOfRound.Instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)) { bool flag = HasDeadPlayers(); RagdollGrabbableObject heldBody = GetHeldBody(); interactTrigger.interactable = flag && (Object)(object)heldBody != (Object)null; if ((Object)(object)heldBody != (Object)null) { string text = (((Object)(object)heldBody.ragdoll != (Object)null) ? heldBody.ragdoll.playerScript.playerUsername : "Player"); int reviveCost = GetReviveCost(); interactTrigger.hoverTip = "Revive " + text + " for " + ((reviveCost <= 0) ? "free" : (reviveCost + " credits")) + " : [E]"; } } } public static void OnInteract() { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; RagdollGrabbableObject heldBody = GetHeldBody(); if ((Object)(object)heldBody == (Object)null) { return; } int reviveCost = GetReviveCost(); Terminal val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null && val.groupCredits < reviveCost) { BunkbedRevivePlugin.Log.LogMessage((object)"Not enough credits for revive"); interactTrigger.StopInteraction(); return; } if ((Object)(object)val != (Object)null) { val.groupCredits -= reviveCost; val.SyncGroupCreditsServerRpc(val.groupCredits, val.numberOfItemsInDropship); } BunkbedNetworking.RevivePlayerServerRpc(heldBody.bodyID); if ((Object)(object)localPlayerController != (Object)null) { localPlayerController.DespawnHeldObject(); } string text = (((Object)(object)heldBody.ragdoll != (Object)null) ? heldBody.ragdoll.playerScript.playerUsername : "Player"); BunkbedRevivePlugin.Log.LogMessage((object)(text + " has been revived")); } private static void OnStopInteract() { int reviveCost = GetReviveCost(); interactTrigger.hoverTip = "Revive for " + ((reviveCost <= 0) ? "free" : (reviveCost + " credits")) + " : [E]"; } public static void RevivePlayer(int playerId) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if ((Object)(object)val == (Object)null) { return; } bool isPlayerDead = val.isPlayerDead; val.ResetPlayerBloodObjects(isPlayerDead); if (isPlayerDead) { val.isPlayerDead = false; val.isPlayerControlled = true; val.isInElevator = true; val.isInHangarShipRoom = true; val.isInsideFactory = false; val.health = 100; val.criticallyInjured = false; val.bleedingHeavily = false; val.setPositionOfDeadPlayer = false; val.deadBody = null; val.isClimbingLadder = false; val.clampLooking = false; val.inVehicleAnimation = false; val.disableMoveInput = false; val.disableLookInput = false; val.disableInteract = false; val.ResetZAndXRotation(); ((Collider)val.thisController).enabled = true; StartOfRound.Instance.SetPlayerObjectExtrapolate(false); Vector3 position = StartOfRound.Instance.playerSpawnPositions[playerId].position; val.TeleportPlayer(position, false, 0f, false, true); if ((Object)(object)val.playerBodyAnimator != (Object)null) { val.playerBodyAnimator.SetBool("Limp", false); } } StartOfRound instance = StartOfRound.Instance; instance.livingPlayers++; StartOfRound.Instance.allPlayersDead = false; ((Renderer)val.thisPlayerModel).enabled = true; ((Renderer)val.thisPlayerModelLOD1).enabled = true; ((Renderer)val.thisPlayerModelLOD2).enabled = true; if ((Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController) { val.health = 100; val.hasBegunSpectating = false; val.hinderedMultiplier = 1f; val.isMovementHindered = 0; val.sourcesCausingSinking = 0; val.criticallyInjured = false; val.bleedingHeavily = false; val.isSinking = false; val.isUnderwater = false; val.sinkingValue = 0f; val.statusEffectAudio.Stop(); val.DisableJetpackControlsLocally(); HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false); HUDManager.Instance.RemoveSpectateUI(); HUDManager.Instance.gameOverAnimator.SetTrigger("revive"); HUDManager.Instance.HideHUD(false); HUDManager.Instance.UpdateHealthUI(100, false); val.spectatedPlayerScript = null; ((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false; StartOfRound.Instance.SetSpectateCameraToGameOverMode(false, val); TimeOfDay.Instance.DisableAllWeather(false); StartOfRound.Instance.UpdatePlayerVoiceEffects(); val.reverbPreset = StartOfRound.Instance.shipReverb; SoundManager.Instance.earsRingingTimer = 0f; SoundManager.Instance.playerVoicePitchTargets[playerId] = 1f; SoundManager.Instance.SetPlayerPitch(1f, playerId); } } } public static class BunkbedNetworking { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__HandleReviveRequest; public static HandleNamedMessageDelegate <1>__HandleReviveBroadcast; } private const string ReviveServerMsg = "BunkbedRevive.ReviveServer"; private const string ReviveClientMsg = "BunkbedRevive.ReviveClient"; public static void Init() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__HandleReviveRequest; if (obj == null) { HandleNamedMessageDelegate val = HandleReviveRequest; <>O.<0>__HandleReviveRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("BunkbedRevive.ReviveServer", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__HandleReviveBroadcast; if (obj2 == null) { HandleNamedMessageDelegate val2 = HandleReviveBroadcast; <>O.<1>__HandleReviveBroadcast = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("BunkbedRevive.ReviveClient", (HandleNamedMessageDelegate)obj2); BunkbedRevivePlugin.Log.LogInfo((object)"BunkbedRevive networking initialized"); } public static void Cleanup() { if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.CustomMessagingManager != null) { NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("BunkbedRevive.ReviveServer"); NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("BunkbedRevive.ReviveClient"); } } public static void RevivePlayerServerRpc(int playerId) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { BroadcastRevive(playerId); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValue(ref playerId, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("BunkbedRevive.ReviveServer", 0uL, val, (NetworkDelivery)2); } private static void HandleReviveRequest(ulong clientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValue(ref playerId, default(ForPrimitives)); BroadcastRevive(playerId); } private static void BroadcastRevive(int playerId) { //IL_0045: 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_0065: Unknown result type (might be due to invalid IL or missing references) BunkbedController.RevivePlayer(playerId); PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController != (Object)null && localPlayerController.isHoldingObject && localPlayerController.currentlyHeldObjectServer is RagdollGrabbableObject) { localPlayerController.DespawnHeldObject(); } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValue(ref playerId, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("BunkbedRevive.ReviveClient", (IReadOnlyList)GetClientIds(), val, (NetworkDelivery)2); } private static List GetClientIds() { List list = new List(); if (NetworkManager.Singleton.ConnectedClientsList != null) { foreach (NetworkClient connectedClients in NetworkManager.Singleton.ConnectedClientsList) { list.Add(connectedClients.ClientId); } } return list; } private static void HandleReviveBroadcast(ulong clientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValue(ref playerId, default(ForPrimitives)); BunkbedController.RevivePlayer(playerId); } } [BepInPlugin("com.user.BunkbedRevive", "BunkbedRevive", "1.0.1")] public sealed class BunkbedRevivePlugin : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("com.user.BunkbedRevive"); public static BunkbedRevivePlugin Instance; public static ManualLogSource Log { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Init(); harmony.PatchAll(); Log.LogInfo((object)"BunkbedRevive v1.0.1 loaded!"); } } } namespace BunkbedRevive.Patches { [HarmonyPatch(typeof(RagdollGrabbableObject))] public class RagdollGrabbableObjectPatch { [HarmonyPatch("Start")] [HarmonyPrefix] private static void StartPatch(RagdollGrabbableObject __instance) { ((GrabbableObject)__instance).itemProperties.weight = ModConfig.BodyWeight.Value; } } [HarmonyPatch(typeof(StartOfRound))] public class StartOfRoundPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch(StartOfRound __instance) { BunkbedNetworking.Init(); int bunkBedId = __instance.unlockablesList.unlockables.FindIndex((UnlockableItem un) => un.unlockableName.IndexOf("bunkbeds", StringComparison.CurrentCultureIgnoreCase) >= 0); if (bunkBedId >= 0) { PlaceableShipObject val = ((IEnumerable)Object.FindObjectsOfType()).FirstOrDefault((Func)((PlaceableShipObject pc) => pc.unlockableID == bunkBedId)); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject.GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); BunkbedRevivePlugin.Log.LogInfo((object)"BunkbedController added to bunk beds"); } } } [HarmonyPatch("openingDoorsSequence")] [HarmonyPrefix] private static void openingDoorsSequencePatch() { BunkbedController.Instance = null; } [HarmonyPatch("EndOfGame")] [HarmonyPrefix] private static void EndOfGamePatch() { BunkbedNetworking.Cleanup(); BunkbedController.Instance = null; } } } namespace BunkbedRevive.Configuration { public static class ModConfig { public static ConfigEntry ReviveCost; public static ConfigEntry BodyWeight; public static void Init() { ConfigFile config = ((BaseUnityPlugin)BunkbedRevivePlugin.Instance).Config; ReviveCost = config.Bind("Revive", "Cost", 25, "Number of credits to revive a dead player at the bunk beds"); BodyWeight = config.Bind("Revive", "Body Weight", 1.1f, "Weight of dead bodies when carried"); } } }