using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using OPJosMod.ReviveCompany.CustomRpc;
using OPJosMod.ReviveCompany.Patches;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OPJosMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OPJosMod")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("70095872-b952-4e27-bbc4-3d70d0238f39")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace OPJosMod.ReviveCompany
{
public static class ConfigVariables
{
public static float reviveTime;
public static bool reviveTeleportedBodies;
public static Key ReviveButton;
public static bool CanPickUpBodies;
public static float DeadPlayerWeight;
public static int ReviveToHealth;
public static bool LimitedRevives;
public static float RevivesPerLevelMultiplier;
public static int HardAmountOfLives;
public static int ExtraHealthLostPerRevive;
public static bool InfiniteReviveTime;
public static int TimeUnitlCantBeRevived;
}
public static class GeneralUtil
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
public static Vector3 StringToVector3(string str)
{
//IL_0046: 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_004f: Unknown result type (might be due to invalid IL or missing references)
string[] array = str.Trim('(', ')').Split(new char[1] { ',' });
float num = float.Parse(array[0]);
float num2 = float.Parse(array[1]);
float num3 = float.Parse(array[2]);
return new Vector3(num, num2, num3);
}
public static RagdollGrabbableObject GetClosestDeadBody(Vector3 position)
{
//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)
RagdollGrabbableObject result = null;
float num = float.MaxValue;
RagdollGrabbableObject[] array = Object.FindObjectsOfType<RagdollGrabbableObject>();
RagdollGrabbableObject[] array2 = array;
foreach (RagdollGrabbableObject val in array2)
{
float num2 = Vector3.Distance(((Component)val).transform.position, position);
if (num2 < num)
{
result = val;
num = num2;
}
}
return result;
}
public static PlayerControllerB GetClosestAlivePlayer(Vector3 position)
{
//IL_0040: 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)
PlayerControllerB result = null;
float num = float.MaxValue;
PlayerControllerB[] allPlayerScripts = RoundManager.Instance.playersManager.allPlayerScripts;
PlayerControllerB[] array = allPlayerScripts;
foreach (PlayerControllerB val in array)
{
if (!val.isPlayerDead)
{
float num2 = Vector3.Distance(((Component)val).transform.position, position);
if (num2 < num)
{
result = val;
num = num2;
}
}
}
return result;
}
public static string simplifyObjectNames(string ogName)
{
string text = ogName;
int num = text.IndexOf("(");
if (num != -1)
{
text = text.Substring(0, num).Trim();
}
return text;
}
public static void RevivePlayer(int playerId)
{
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
//IL_03c3: Expected O, but got Unknown
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
//IL_02ac: Expected O, but got Unknown
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
//IL_03e7: Expected O, but got Unknown
//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0404: Expected O, but got Unknown
//IL_053f: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_042e: Expected O, but got Unknown
//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
//IL_05d6: Expected O, but got Unknown
//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
//IL_05b5: Expected O, but got Unknown
//IL_060f: Unknown result type (might be due to invalid IL or missing references)
//IL_0619: Expected O, but got Unknown
if (playerId >= RoundManager.Instance.playersManager.allPlayerScripts.Length || playerId < 0)
{
Debug.Log((object)$"ReiveCompanyERROR: error when trying to revive player {playerId} as it is outside the range of the allPlayerScripts array");
return;
}
PlayerControllerB val = RoundManager.Instance.playersManager.allPlayerScripts[playerId];
if ((Object)(object)val != (Object)null && !val.isPlayerDead)
{
Debug.Log((object)$"ReiveCompanyERROR: error when trying to revive player {playerId} player is already alive! do nothing more");
return;
}
Vector3 val2 = val.serverPlayerPosition;
if ((Object)(object)val.deadBody != (Object)null && (Object)(object)((Component)val.deadBody).transform != (Object)null)
{
_ = ((Component)val.deadBody).transform.position;
if (true)
{
val2 = ((Component)val.deadBody).transform.position;
PlayerControllerB closestAlivePlayer = GetClosestAlivePlayer(((Component)val.deadBody).transform.position);
if ((Object)(object)closestAlivePlayer != (Object)null && Vector3.Distance(val2, ((Component)closestAlivePlayer).transform.position) > 7f)
{
val2 = ((Component)closestAlivePlayer).transform.position;
}
}
}
bool isInsideFactory = false;
PlayerControllerB closestAlivePlayer2 = GetClosestAlivePlayer(((Component)val.deadBody).transform.position);
if ((Object)(object)closestAlivePlayer2 != (Object)null)
{
isInsideFactory = closestAlivePlayer2.isInsideFactory;
}
StartOfRound instance = StartOfRound.Instance;
instance.livingPlayers++;
StartOfRound.Instance.allPlayersDead = false;
StartOfRound.Instance.UpdatePlayerVoiceEffects();
GlobalVariables.RemainingRevives--;
if (GlobalVariables.RemainingRevives < 100)
{
HUDManager.Instance.DisplayTip(val.playerUsername + " was revived", $"{GlobalVariables.RemainingRevives} revives remain!", false, false, "LC_Tip1");
}
int num = (int)val.playerClientId;
val.ResetPlayerBloodObjects(val.isPlayerDead);
val.isClimbingLadder = false;
val.ResetZAndXRotation();
((Collider)val.thisController).enabled = true;
val.health = ConfigVariables.ReviveToHealth;
val.disableLookInput = false;
if (val.isPlayerDead)
{
val.isPlayerDead = false;
val.isPlayerControlled = true;
val.isInElevator = true;
val.isInHangarShipRoom = true;
val.isInsideFactory = isInsideFactory;
val.TeleportPlayer(val2, false, 0f, false, true);
val.setPositionOfDeadPlayer = false;
val.DisablePlayerModel(StartOfRound.Instance.allPlayerObjects[num], true, true);
((Behaviour)val.helmetLight).enabled = false;
val.Crouch(false);
val.criticallyInjured = false;
if ((Object)val.playerBodyAnimator != (Object)null)
{
val.playerBodyAnimator.SetBool("Limp", false);
}
val.bleedingHeavily = false;
val.activatingItem = false;
val.twoHanded = false;
val.inSpecialInteractAnimation = false;
val.disableSyncInAnimation = false;
val.inAnimationWithEnemy = null;
val.holdingWalkieTalkie = false;
val.speakingToWalkieTalkie = false;
val.isSinking = false;
val.isUnderwater = false;
val.sinkingValue = 0f;
val.statusEffectAudio.Stop();
val.DisableJetpackControlsLocally();
val.health = ConfigVariables.ReviveToHealth;
val.mapRadarDotAnimator.SetBool("dead", false);
val.hasBegunSpectating = false;
val.hinderedMultiplier = 1f;
val.isMovementHindered = 0;
val.sourcesCausingSinking = 0;
val.reverbPreset = StartOfRound.Instance.shipReverb;
}
SoundManager.Instance.earsRingingTimer = 0f;
val.voiceMuffledByEnemy = false;
SoundManager.Instance.playerVoicePitchTargets[num] = 1f;
SoundManager.Instance.SetPlayerPitch(1f, num);
if ((Object)val.currentVoiceChatIngameSettings == (Object)null)
{
StartOfRound.Instance.RefreshPlayerVoicePlaybackObjects();
}
if ((Object)val.currentVoiceChatIngameSettings != (Object)null)
{
if ((Object)val.currentVoiceChatIngameSettings.voiceAudio == (Object)null)
{
val.currentVoiceChatIngameSettings.InitializeComponents();
}
if ((Object)val.currentVoiceChatIngameSettings.voiceAudio == (Object)null)
{
return;
}
((Component)val.currentVoiceChatIngameSettings.voiceAudio).GetComponent<OccludeAudio>().overridingLowPass = false;
}
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
if (localPlayerController.playerClientId == val.playerClientId)
{
GlobalVariables.AmountOfTimesRevived++;
int num2 = ConfigVariables.ReviveToHealth - GlobalVariables.AmountOfTimesRevived * ConfigVariables.ExtraHealthLostPerRevive;
localPlayerController.bleedingHeavily = false;
localPlayerController.criticallyInjured = false;
localPlayerController.playerBodyAnimator.SetBool("Limp", false);
localPlayerController.health = num2;
localPlayerController.spectatedPlayerScript = null;
((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false;
StartOfRound.Instance.SetSpectateCameraToGameOverMode(false, localPlayerController);
StartOfRound.Instance.SetPlayerObjectExtrapolate(false);
HUDManager.Instance.UpdateHealthUI(num2, true);
HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false);
HUDManager.Instance.RemoveSpectateUI();
HUDManager.Instance.gameOverAnimator.SetTrigger("revive");
}
RagdollGrabbableObject closestDeadBody = GetClosestDeadBody(((Component)val).transform.position);
if ((Object)(object)closestDeadBody != (Object)null)
{
if (!((GrabbableObject)closestDeadBody).isHeld)
{
if (((NetworkBehaviour)StartOfRound.Instance).IsServer)
{
if (((NetworkBehaviour)closestDeadBody).NetworkObject.IsSpawned)
{
((NetworkBehaviour)closestDeadBody).NetworkObject.Despawn(true);
}
else
{
Object.Destroy((Object)((Component)closestDeadBody).gameObject);
}
}
}
else if (((GrabbableObject)closestDeadBody).isHeld && (Object)((GrabbableObject)closestDeadBody).playerHeldBy != (Object)null)
{
((GrabbableObject)closestDeadBody).playerHeldBy.DropAllHeldItems(true, false);
}
if ((Object)(object)closestDeadBody.ragdoll != (Object)null)
{
Object.Destroy((Object)((Component)closestDeadBody.ragdoll).gameObject);
}
}
if (localPlayerController.isPlayerDead)
{
HUDManager.Instance.UpdateBoxesSpectateUI();
}
}
public static void ResetAllPlayerInfos()
{
GlobalVariables.PlayerInfos.Clear();
PlayerControllerB[] allPlayerScripts = RoundManager.Instance.playersManager.allPlayerScripts;
foreach (PlayerControllerB val in allPlayerScripts)
{
GlobalVariables.PlayerInfos.Add(new PlayerInfo
{
PlayerId = (int)val.playerClientId
});
}
}
public static bool HasPlayerTeleported(int playerClientId)
{
int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
if (num != -1)
{
return GlobalVariables.PlayerInfos[num].HasBeenTeleported;
}
return false;
}
public static void SetPlayerAsTeleported(int playerClientId)
{
int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
if (num != -1)
{
GlobalVariables.PlayerInfos[num].HasBeenTeleported = true;
}
}
public static void SetPlayerDiedAt(int playerClientId)
{
int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
if (num != -1)
{
GlobalVariables.PlayerInfos[num].TimeDiedAt = Time.time;
}
}
public static float GetPlayersDiedAtTime(int playerClientId)
{
int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
if (num != -1)
{
return GlobalVariables.PlayerInfos[num].TimeDiedAt;
}
return Time.time;
}
}
public static class GlobalVariables
{
public static bool ModActivated = false;
public static List<PlayerInfo> PlayerInfos = new List<PlayerInfo>();
public static int RemainingRevives = int.MaxValue;
public static int AmountOfTimesRevived = 0;
}
public class PlayerInfo
{
public int PlayerId { get; set; }
public bool HasBeenTeleported { get; set; }
public float TimeDiedAt { get; set; }
}
[BepInPlugin("OpJosMod.ReviveCompany", "ReviveCompany", "1.4.0")]
public class OpJosMod : BaseUnityPlugin
{
private const string modGUID = "OpJosMod.ReviveCompany";
private const string modName = "ReviveCompany";
private const string modVersion = "1.4.0";
private readonly Harmony harmony = new Harmony("OpJosMod.ReviveCompany");
private static OpJosMod Instance;
internal ManualLogSource mls;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
mls = Logger.CreateLogSource("OpJosMod.ReviveCompany");
setupConfig();
PatchesForRPC.SetLogSource(mls);
RpcMessageHandler.SetLogSource(mls);
CompleteRecievedTasks.SetLogSource(mls);
ResponseHandler.SetLogSource(mls);
PlayerControllerBPatch.SetLogSource(mls);
ShipTeleporterPatch.SetLogSource(mls);
StartOfRoundPatch.SetLogSource(mls);
RagdollGrabbableObjectPatch.SetLogSource(mls);
GeneralUtil.SetLogSource(mls);
harmony.PatchAll();
}
private void setupConfig()
{
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<float> val = ((BaseUnityPlugin)this).Config.Bind<float>("Revive Time", "ReviveTime", 5f, "How long it takes to revive someone");
ConfigEntry<Key> val2 = ((BaseUnityPlugin)this).Config.Bind<Key>("ReviveButton", "ReviveButton", (Key)32, "Button Used to Revive Players");
ConfigEntry<bool> val3 = ((BaseUnityPlugin)this).Config.Bind<bool>("Can Pick Up Bodies", "CanPickUpBodies", true, "Toggle if you can pick up bodies.");
ConfigEntry<float> val4 = ((BaseUnityPlugin)this).Config.Bind<float>("Dead Body Weight Multiplier", "DeadBodyWeight", 3.25f, "How heavy are the dead players.");
ConfigEntry<bool> val5 = ((BaseUnityPlugin)this).Config.Bind<bool>("Can Revive Teleported Bodies", "CanReviveTeleportedBodies", false, "Toggle for if you are able to revive dead players you teleport back to the ship");
ConfigEntry<int> val6 = ((BaseUnityPlugin)this).Config.Bind<int>("Health you revive with.", "HealthYouReviveWith", 25, "How much health you revive with.");
ConfigEntry<int> val7 = ((BaseUnityPlugin)this).Config.Bind<int>("Extra Health Lost Per Revive", "ExtraHealthLostPerRevive", 5, "If player is revived more than once per level, revive with this much less HP each time");
ConfigEntry<bool> val8 = ((BaseUnityPlugin)this).Config.Bind<bool>("Limit amount of revives", "LimitAmountOfRevives", true, "do you want to have limited revives?");
ConfigEntry<float> val9 = ((BaseUnityPlugin)this).Config.Bind<float>("Revives Per Level Multiplier", "RevivesPerLevelMultiplier", 1.25f, "How many revives you get per level, mulitplied by players in game. ex) value set to 2 and have 4 players then you get 8 revives.");
ConfigEntry<int> val10 = ((BaseUnityPlugin)this).Config.Bind<int>("Set Amount of Revives", "SetAmountOfRevives", 0, "Set amount of revives per level. If not at 0 This will override the revive amount being set by the (Revives Per Level Multiplier) setting");
ConfigEntry<bool> val11 = ((BaseUnityPlugin)this).Config.Bind<bool>("Infinite Revive Time", "InfiniteReviveTime", false, "Can you alwasy revive someone no longer how long they have been dead?");
ConfigEntry<int> val12 = ((BaseUnityPlugin)this).Config.Bind<int>("Time Until Cant Be Revived", "TimeUntilCantBeRevived", 120, "How long someone can be dead for and still be revived in seconds");
ConfigVariables.reviveTime = val.Value;
ConfigVariables.ReviveButton = val2.Value;
ConfigVariables.CanPickUpBodies = val3.Value;
ConfigVariables.DeadPlayerWeight = val4.Value;
ConfigVariables.reviveTeleportedBodies = val5.Value;
ConfigVariables.ReviveToHealth = val6.Value;
ConfigVariables.LimitedRevives = val8.Value;
ConfigVariables.RevivesPerLevelMultiplier = val9.Value;
ConfigVariables.HardAmountOfLives = val10.Value;
ConfigVariables.ExtraHealthLostPerRevive = val7.Value;
ConfigVariables.InfiniteReviveTime = val11.Value;
ConfigVariables.TimeUnitlCantBeRevived = val12.Value;
}
}
}
namespace OPJosMod.ReviveCompany.Utils
{
public class ReflectionUtils
{
public static void InvokeMethod(object obj, string methodName, object[] parameters)
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
method.Invoke(obj, parameters);
}
public static void InvokeMethod(object obj, Type forceType, string methodName, object[] parameters)
{
MethodInfo method = forceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
method.Invoke(obj, parameters);
}
public static void SetPropertyValue(object obj, string propertyName, object value)
{
Type type = obj.GetType();
PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
property.SetValue(obj, value);
}
public static T InvokeMethod<T>(object obj, string methodName, object[] parameters)
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return (T)method.Invoke(obj, parameters);
}
public static T GetFieldValue<T>(object obj, string fieldName)
{
Type type = obj.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return (T)field.GetValue(obj);
}
public static void SetFieldValue(object obj, string fieldName, object value)
{
Type type = obj.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
field.SetValue(obj, value);
}
}
}
namespace OPJosMod.ReviveCompany.Patches
{
[HarmonyPatch(typeof(RagdollGrabbableObject))]
internal class RagdollGrabbableObjectPatch
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
[HarmonyPatch("Start")]
[HarmonyPrefix]
private static void patchStart(RagdollGrabbableObject __instance)
{
if (GlobalVariables.ModActivated)
{
((GrabbableObject)__instance).itemProperties.weight = ConfigVariables.DeadPlayerWeight;
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal class StartOfRoundPatch
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
[HarmonyPatch("EndOfGame")]
[HarmonyPrefix]
private static void patchEndOfGame()
{
if (GlobalVariables.ModActivated)
{
mls.LogMessage((object)"reset bodies teleported list");
GeneralUtil.ResetAllPlayerInfos();
}
}
[HarmonyPatch("openingDoorsSequence")]
[HarmonyPrefix]
private static void patchOpeningDoorsSequence()
{
if (GlobalVariables.ModActivated)
{
mls.LogMessage((object)"round starting, reseting allowed revive count");
GeneralUtil.ResetAllPlayerInfos();
setStartingRevives();
}
}
private static void setStartingRevives()
{
int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => x.isPlayerControlled).Count();
GlobalVariables.AmountOfTimesRevived = 0;
if (ConfigVariables.LimitedRevives)
{
if (ConfigVariables.HardAmountOfLives != 0)
{
GlobalVariables.RemainingRevives = ConfigVariables.HardAmountOfLives;
}
else
{
GlobalVariables.RemainingRevives = Mathf.RoundToInt((float)num * ConfigVariables.RevivesPerLevelMultiplier);
}
}
else
{
GlobalVariables.RemainingRevives = int.MaxValue;
}
}
}
[HarmonyPatch(typeof(ShipTeleporter))]
internal class ShipTeleporterPatch
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
[HarmonyPatch("beamUpPlayer")]
[HarmonyPrefix]
private static void patchbeamUpPlayer()
{
if (GlobalVariables.ModActivated)
{
PlayerControllerB targetedPlayer = StartOfRound.Instance.mapScreen.targetedPlayer;
if (!((Object)(object)targetedPlayer == (Object)null) && !((Object)(object)targetedPlayer.redirectToEnemy != (Object)null) && !((Object)(object)targetedPlayer.deadBody == (Object)null) && targetedPlayer.isPlayerDead)
{
GeneralUtil.SetPlayerAsTeleported((int)targetedPlayer.playerClientId);
}
}
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerBPatch
{
private static ManualLogSource mls;
private static int interactableObjectsMask = 832;
private static float StartedReviveAt = Time.time;
private static bool StartedRevive = false;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
[HarmonyPatch("Interact_performed")]
[HarmonyPrefix]
private static bool interact_performedPatch(PlayerControllerB __instance)
{
if (!GlobalVariables.ModActivated)
{
return true;
}
if (ConfigVariables.CanPickUpBodies)
{
return true;
}
if (((NetworkBehaviour)__instance).IsOwner && !__instance.isPlayerDead && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject) && !canUse(__instance))
{
return false;
}
return true;
}
[HarmonyPatch("KillPlayerClientRpc")]
[HarmonyPrefix]
private static void killPlayerClientRpcPatch(PlayerControllerB __instance, ref int playerId)
{
if (GlobalVariables.ModActivated)
{
GeneralUtil.SetPlayerDiedAt(playerId);
}
}
[HarmonyPatch("SetHoverTipAndCurrentInteractTrigger")]
[HarmonyPostfix]
private static void setHoverTipAndCurrentInteractTriggerPatch(PlayerControllerB __instance)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
if (!GlobalVariables.ModActivated)
{
return;
}
if (!canUse(__instance) && ((TMP_Text)__instance.cursorTip).text != "")
{
if (((ButtonControl)Keyboard.current[ConfigVariables.ReviveButton]).isPressed)
{
if (!StartedRevive)
{
StartedRevive = true;
StartedReviveAt = Time.time;
}
else if (Time.time - StartedReviveAt > ConfigVariables.reviveTime)
{
RagdollGrabbableObject closestDeadBody = GeneralUtil.GetClosestDeadBody(((Component)__instance).transform.position);
if (!canRevive(closestDeadBody))
{
((TMP_Text)__instance.cursorTip).text = "[Can't Revive Player!]";
return;
}
StartedRevive = false;
RpcMessage message = new RpcMessage(MessageTasks.RevivePlayer, closestDeadBody.ragdoll.playerScript.playerClientId.ToString(), (int)__instance.playerClientId, MessageCodes.Request);
RpcMessageHandler.SendRpcMessage(message);
ResponseHandler.SentMessageNeedResponses(message);
GeneralUtil.RevivePlayer((int)closestDeadBody.ragdoll.playerScript.playerClientId);
RpcMessage message2 = new RpcMessage(MessageTasks.TurnOffGhostMode, closestDeadBody.ragdoll.playerScript.playerClientId.ToString(), (int)__instance.playerClientId, MessageCodes.Request);
RpcMessageHandler.SendRpcMessage(message2);
}
((TMP_Text)__instance.cursorTip).text = $"[Reviving! {(int)Mathf.Round(Time.time - StartedReviveAt)}/{ConfigVariables.reviveTime}s]";
return;
}
if (ConfigVariables.InfiniteReviveTime)
{
((TMP_Text)__instance.cursorTip).text = $"[Hold {ConfigVariables.ReviveButton} to revive!]";
}
else
{
RagdollGrabbableObject closestDeadBody2 = GeneralUtil.GetClosestDeadBody(((Component)__instance).transform.position);
double num = Math.Round((float)ConfigVariables.TimeUnitlCantBeRevived - (Time.time - GeneralUtil.GetPlayersDiedAtTime((int)closestDeadBody2.ragdoll.playerScript.playerClientId)));
if (num > 0.0)
{
((TMP_Text)__instance.cursorTip).text = $"[Hold {ConfigVariables.ReviveButton} to revive!] {num}s Left!";
}
else
{
((TMP_Text)__instance.cursorTip).text = "0 Time Left!";
}
}
StartedRevive = false;
}
else
{
StartedRevive = false;
}
}
private static bool canUse(PlayerControllerB __instance)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
Ray val = default(Ray);
((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward);
RaycastHit val2 = default(RaycastHit);
Physics.Raycast(val, ref val2, __instance.grabDistance, interactableObjectsMask);
Collider collider = ((RaycastHit)(ref val2)).collider;
GrabbableObject val3 = ((collider != null) ? ((Component)collider).GetComponent<GrabbableObject>() : null);
if ((Object)(object)val3 != (Object)null)
{
string text = GeneralUtil.simplifyObjectNames(((Object)val3).name);
if (text == "RagdollGrabbableObject")
{
return false;
}
}
return true;
}
private static bool canRevive(RagdollGrabbableObject revivingBody)
{
if (GlobalVariables.RemainingRevives <= 0)
{
return false;
}
if ((Object)(object)revivingBody != (Object)null && (Object)(object)revivingBody.ragdoll != (Object)null && (Object)(object)revivingBody.ragdoll.playerScript != (Object)null && GameNetworkManager.Instance.localPlayerController.playerClientId == revivingBody.ragdoll.playerScript.playerClientId)
{
return false;
}
int playerClientId = (int)revivingBody.ragdoll.playerScript.playerClientId;
if (GeneralUtil.HasPlayerTeleported(playerClientId) && !ConfigVariables.reviveTeleportedBodies)
{
return false;
}
mls.LogInfo((object)(Time.time + " | " + GeneralUtil.GetPlayersDiedAtTime(playerClientId)));
if (Time.time - GeneralUtil.GetPlayersDiedAtTime(playerClientId) > (float)ConfigVariables.TimeUnitlCantBeRevived && !ConfigVariables.InfiniteReviveTime)
{
return false;
}
return true;
}
}
}
namespace OPJosMod.ReviveCompany.CustomRpc
{
public static class ResponseHandler
{
private static ManualLogSource mls;
private static float LastSendTime;
private static RpcMessage ResendMessageMessage;
private static bool StartWaitForResend;
private static int TotalResponses;
private static int TotalSentMessages;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
public static void RecievedResponse(MessageTasks messageTask)
{
if (messageTask == MessageTasks.RevivePlayer && !((Object)(object)StartOfRound.Instance == (Object)null) && StartOfRound.Instance.allPlayerScripts != null)
{
TotalResponses++;
}
}
public static void SentMessageNeedResponses(RpcMessage message)
{
LastSendTime = Time.time;
ResendMessageMessage = message;
StartWaitForResend = true;
TotalResponses = 0;
TotalSentMessages = 0;
}
public static void CalculateIfShouldResend()
{
if (ResendMessageMessage == null || ResendMessageMessage.Task != MessageTasks.RevivePlayer || !StartWaitForResend || !(Time.time - LastSendTime > 2f))
{
return;
}
if (TotalSentMessages > 4)
{
mls.LogError((object)"No longer retrying message send as it has already sent 5 extra times.");
LastSendTime = 0f;
StartWaitForResend = false;
TotalResponses = 0;
TotalSentMessages = 0;
return;
}
int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => !x.playerUsername.Contains("Player")).ToList().Count();
mls.LogMessage((object)$"TotalResponses:{TotalResponses}, playerCount:{num}");
if (TotalResponses > num - 2 || num - 2 < 0)
{
LastSendTime = 0f;
StartWaitForResend = false;
TotalResponses = 0;
TotalSentMessages = 0;
}
else
{
mls.LogMessage((object)"resending revive message as dont have enough responses");
TotalSentMessages++;
LastSendTime = Time.time;
RpcMessageHandler.SendRpcMessage(ResendMessageMessage);
ResendMessageMessage.Task = MessageTasks.TurnOffGhostMode;
RpcMessageHandler.SendRpcMessage(ResendMessageMessage);
ResendMessageMessage.Task = MessageTasks.RevivePlayer;
}
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerBPatchResponseHandler
{
[HarmonyPatch("Update")]
[HarmonyPostfix]
private static void patchUpdate(PlayerControllerB __instance)
{
if (GlobalVariables.ModActivated && ((NetworkBehaviour)__instance).IsOwner)
{
ResponseHandler.CalculateIfShouldResend();
}
}
}
public static class CompleteRecievedTasks
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
public static void ModActivated(string modName)
{
if (mls.SourceName == modName)
{
mls.LogMessage((object)"Mod Activated");
GlobalVariables.ModActivated = true;
}
}
public static void RevivePlayer(string playerIdString)
{
if (int.TryParse(playerIdString, out var result))
{
GeneralUtil.RevivePlayer(result);
}
else
{
mls.LogError((object)("Error: Invalid player ID '" + playerIdString + "' did not revive"));
}
}
}
public static class PatchesForRPC
{
public static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
}
[HarmonyPatch(typeof(HUDManager))]
internal static class HUDManagerPatchForRPC
{
private static float lastRecievedAt = Time.time;
private static string lastRecievedMessage = null;
private static float messageWaitTime = 0.5f;
[HarmonyPatch("AddPlayerChatMessageClientRpc")]
[HarmonyPrefix]
private static void addPlayerChatMessageClientRpcPatch(ref string chatMessage, ref int playerId)
{
string text = MessageCodeUtil.returnMessageNoSeperators(chatMessage);
if (MessageCodeUtil.stringContainsMessageCode(chatMessage) && (Time.time - lastRecievedAt > messageWaitTime || text != lastRecievedMessage) && playerId != (int)GameNetworkManager.Instance.localPlayerController.playerClientId)
{
lastRecievedAt = Time.time;
lastRecievedMessage = text;
RpcMessageHandler.ReceiveRpcMessage(chatMessage, playerId);
}
}
[HarmonyPatch("AddChatMessage")]
[HarmonyPrefix]
private static bool addChatMessagePatch(ref string chatMessage)
{
if (MessageCodeUtil.stringContainsMessageCode(chatMessage))
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal static class StartOfRoundPatchForRPC
{
[HarmonyPatch("OnClientConnect")]
[HarmonyPostfix]
private static void patchOnClientConnect(StartOfRound __instance)
{
((MonoBehaviour)__instance).StartCoroutine(activateModForOthers(__instance));
}
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void patchStart(StartOfRound __instance)
{
if (((NetworkBehaviour)__instance).IsHost)
{
GlobalVariables.ModActivated = true;
}
}
[HarmonyPatch("OnLocalDisconnect")]
[HarmonyPostfix]
private static void patchOnLocalDisconnect(StartOfRound __instance)
{
GlobalVariables.ModActivated = false;
}
private static IEnumerator activateModForOthers(StartOfRound __instance)
{
yield return (object)new WaitForSeconds(3f);
if (((NetworkBehaviour)__instance).IsHost)
{
GlobalVariables.ModActivated = true;
RpcMessage rpcMessage = new RpcMessage(MessageTasks.ModActivated, PatchesForRPC.mls.SourceName, (int)__instance.localPlayerController.playerClientId, MessageCodes.Request);
RpcMessageHandler.SendRpcMessage(rpcMessage);
}
}
}
public enum MessageCodes
{
Request,
Response
}
public static class MessageCodeUtil
{
public static string GetCode(MessageCodes code)
{
return code switch
{
MessageCodes.Request => ":rpcRequest:",
MessageCodes.Response => ":rpcResponse:",
_ => ":Error:",
};
}
public static bool stringContainsMessageCode(string givenString)
{
if (string.IsNullOrEmpty(givenString))
{
return false;
}
return givenString.Contains(GetCode(MessageCodes.Request)) || givenString.Contains(GetCode(MessageCodes.Response));
}
public static string returnMessageWithoutCode(string message)
{
if (stringContainsMessageCode(message))
{
message = message.Replace(GetCode(MessageCodes.Request), string.Empty);
message = message.Replace(GetCode(MessageCodes.Response), string.Empty);
}
return message;
}
public static string returnMessageNoSeperators(string message)
{
if (stringContainsMessageCode(message))
{
return new string(message.Where((char c) => c != ':').ToArray());
}
return message;
}
}
public enum MessageTasks
{
ModActivated,
RevivePlayer,
TurnOffGhostMode,
ErrorNoTask
}
public static class MessageTaskUtil
{
public static string GetCode(MessageTasks code)
{
return code switch
{
MessageTasks.ModActivated => ":ModActivated:",
MessageTasks.RevivePlayer => ":RevivePlayer:",
MessageTasks.TurnOffGhostMode => ":TurnOffGhostMode:",
MessageTasks.ErrorNoTask => ":Error:",
_ => ":Error:",
};
}
public static string getMessageWithoutTask(string message)
{
foreach (MessageTasks value in Enum.GetValues(typeof(MessageTasks)))
{
string code2 = GetCode(value);
message = message.Replace(code2, "");
}
return message.Trim();
}
public static MessageTasks getMessageTask(string givenString)
{
if (givenString.Contains(GetCode(MessageTasks.ModActivated)))
{
return MessageTasks.ModActivated;
}
if (givenString.Contains(GetCode(MessageTasks.RevivePlayer)))
{
return MessageTasks.RevivePlayer;
}
if (givenString.Contains(GetCode(MessageTasks.TurnOffGhostMode)))
{
return MessageTasks.TurnOffGhostMode;
}
return MessageTasks.ErrorNoTask;
}
}
public class RpcMessage
{
public MessageTasks Task { get; set; }
public string Message { get; set; }
public int FromUser { get; set; }
public MessageCodes MessageCode { get; set; }
public RpcMessage(MessageTasks task, string message, int user, MessageCodes code)
{
Task = task;
Message = message;
FromUser = user;
MessageCode = code;
}
public string getMessageWithCode()
{
return MessageCodeUtil.GetCode(MessageCode) + MessageTaskUtil.GetCode(Task) + Message;
}
}
public static class RpcMessageHandler
{
private static ManualLogSource mls;
private static RpcMessage lastSentMessage = null;
private static float lastSentTime = Time.time;
private static float messageWaitTime = 0.5f;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
public static void SendRpcMessage(RpcMessage message)
{
if (Time.time - lastSentTime > messageWaitTime || lastSentMessage != message)
{
mls.LogMessage((object)$"Sending rpc message: {message.getMessageWithCode()}, user:{message.FromUser}");
lastSentTime = Time.time;
lastSentMessage = message;
HUDManager instance = HUDManager.Instance;
if ((Object)(object)instance != (Object)null)
{
MethodInfo method = typeof(HUDManager).GetMethod("AddPlayerChatMessageServerRpc", BindingFlags.Instance | BindingFlags.NonPublic);
if (method != null)
{
object[] parameters = new object[2]
{
message.getMessageWithCode(),
message.FromUser
};
method.Invoke(instance, parameters);
}
else
{
mls.LogError((object)"AddPlayerChatMessageServerRpc method not found in HUDManager class.");
}
}
else
{
mls.LogError((object)"HUDManager.Instance is null.");
}
}
else
{
mls.LogError((object)("didnt' send message as it was too soon and was the same message as last message " + message.getMessageWithCode()));
}
}
public static void ReceiveRpcMessage(string message, int user)
{
mls.LogMessage((object)$"recieved message: {message}, user:{user}");
if (user != (int)StartOfRound.Instance.localPlayerController.playerClientId)
{
string text = MessageCodeUtil.returnMessageWithoutCode(message);
if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Request)))
{
MessageTasks messageTask = MessageTaskUtil.getMessageTask(text);
string messageWithoutTask = MessageTaskUtil.getMessageWithoutTask(text);
SendRpcResponse(messageTask, messageWithoutTask);
handleTask(messageTask, messageWithoutTask);
}
else if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Response)))
{
ResponseHandler.RecievedResponse(MessageTaskUtil.getMessageTask(text));
}
}
}
public static void SendRpcResponse(MessageTasks task, string message)
{
try
{
RpcMessage message2 = new RpcMessage(task, message, (int)StartOfRound.Instance.localPlayerController.playerClientId, MessageCodes.Response);
SendRpcMessage(message2);
}
catch (Exception arg)
{
mls.LogError((object)$"failed to send response message: {arg}");
}
}
private static void handleTask(MessageTasks task, string message)
{
try
{
switch (task)
{
case MessageTasks.ModActivated:
CompleteRecievedTasks.ModActivated(message);
break;
case MessageTasks.RevivePlayer:
CompleteRecievedTasks.RevivePlayer(message);
break;
case MessageTasks.ErrorNoTask:
mls.LogError((object)"got an error task");
break;
case MessageTasks.TurnOffGhostMode:
break;
}
}
catch (Exception arg)
{
mls.LogError((object)$"failed handlign rpc task: {arg}, task:{task}, message:{message}");
}
}
}
}