using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [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("UltimateReviveMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("UltimateReviveMod")] [assembly: AssemblyTitle("UltimateReviveMod")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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 RevivePlayer { [BepInPlugin("com.yuniverse.reviveplayer", "Revive Player", "1.1.0")] public class Plugin : BaseUnityPlugin { public static Plugin Instance; public static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ConfigManager.Init(((BaseUnityPlugin)this).Config); harmony = new Harmony("com.yuniverse.reviveplayer"); harmony.PatchAll(); Log.LogInfo((object)"RevivePlayer 模組已成功載入!(修正多人連線血量同步問題)"); } } public static class ConfigManager { public static ConfigEntry HpPercentCost; public static ConfigEntry TargetReviveHp; public static ConfigEntry ReviveKey; public static void Init(ConfigFile config) { HpPercentCost = config.Bind("General", "HP Percent Cost", 0.1f, "施救者需要消耗自己當前血量的百分比 (0.10 = 10%)"); TargetReviveHp = config.Bind("General", "Target Revive HP", 100, "隊友復活後的血量 (預設 100 為滿血)"); ReviveKey = config.Bind("Controls", "Revive Key", "H", "執行復活的按鍵"); } } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] public static class PlayerControllerPatch { public static PlayerDeathHead GrabbedHead; public static PlayerAvatar GrabbedAvatar; public static bool IsGrabbing; private static void Postfix(PlayerController __instance) { IsGrabbing = false; GrabbedHead = null; GrabbedAvatar = null; if ((Object)(object)__instance != (Object)null && __instance.physGrabActive && (Object)(object)__instance.physGrabObject != (Object)null) { PlayerDeathHead component = __instance.physGrabObject.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.playerAvatar != (Object)null) { GrabbedHead = component; GrabbedAvatar = component.playerAvatar; IsGrabbing = true; } } } } [HarmonyPatch(typeof(PhysGrabCart), "Update")] public static class PhysGrabCartPatch { private static void Postfix() { //IL_0149: 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) if (SemiFunc.RunIsShop() || !PlayerControllerPatch.IsGrabbing) { return; } PlayerAvatar grabbedAvatar = PlayerControllerPatch.GrabbedAvatar; if ((Object)(object)grabbedAvatar == (Object)null) { return; } PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null) { return; } PlayerHealth playerHealth = instance.playerAvatarScript.playerHealth; if ((Object)(object)playerHealth != (Object)null) { int healthInternal = Helpers.GetHealthInternal(playerHealth); float num = Mathf.Clamp01(ConfigManager.HpPercentCost.Value); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)healthInternal * num)); string value = ConfigManager.ReviveKey.Value; if (healthInternal <= num2) { ItemInfoExtraUI.instance.ItemInfoText($"血量不足以施展復活 (需要 {num2} HP)", new Color(1f, 0.2f, 0.2f)); return; } string name = ((Object)grabbedAvatar).name; ItemInfoExtraUI.instance.ItemInfoText($"按下 [{value}] 復活 {name} (-{num2} HP / {Mathf.RoundToInt(num * 100f)}%)", new Color(0.2f, 1f, 0.2f)); } } } [HarmonyPatch(typeof(PlayerController), "Awake")] public static class InjectPatch { private static void Postfix(PlayerController __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } public class ReviveManager : MonoBehaviourPun { private void Update() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown if (!Input.GetKeyDown(Helpers.ParseKey(ConfigManager.ReviveKey.Value)) || !PlayerControllerPatch.IsGrabbing) { return; } PlayerAvatar grabbedAvatar = PlayerControllerPatch.GrabbedAvatar; if ((Object)(object)grabbedAvatar == (Object)null || (Object)(object)grabbedAvatar.photonView == (Object)null) { return; } PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null) { return; } PlayerHealth playerHealth = instance.playerAvatarScript.playerHealth; if ((Object)(object)playerHealth == (Object)null) { return; } int healthInternal = Helpers.GetHealthInternal(playerHealth); float num = Mathf.Clamp01(ConfigManager.HpPercentCost.Value); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)healthInternal * num)); if (healthInternal > num2) { PhotonView val = PhotonView.Get((Component)this); if ((Object)(object)val != (Object)null) { int viewID = grabbedAvatar.photonView.ViewID; Plugin.Log.LogInfo((object)$"[連線要求] 正在向伺服器申請復活 {((Object)grabbedAvatar).name} (ID: {viewID}),扣除自身 {num2} HP"); val.RPC("HostRevive", (RpcTarget)2, new object[1] { viewID }); playerHealth.Hurt(num2, true, -1, false); } } } [PunRPC] private void HostRevive(int viewID) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if (!PhotonNetwork.IsMasterClient) { return; } Plugin.Log.LogInfo((object)$"[伺服器端] 房主收到復活請求,正在處理 ViewID: {viewID}"); PhotonView val = PhotonView.Find(viewID); if (!((Object)(object)val != (Object)null)) { return; } PlayerAvatar component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.Revive(false); int value = ConfigManager.TargetReviveHp.Value; PhotonView val2 = PhotonView.Get((Component)this); if ((Object)(object)val2 != (Object)null) { val2.RPC("SyncHealth", (RpcTarget)0, new object[2] { viewID, value }); } } } [PunRPC] private void SyncHealth(int viewID, int targetHp) { PhotonView val = PhotonView.Find(viewID); if (!((Object)(object)val != (Object)null)) { return; } PlayerHealth component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { Traverse.Create((object)component).Field("health").SetValue((object)targetHp); if (val.IsMine) { Traverse.Create((object)component).Method("UpdateHealthUI", Array.Empty()).GetValue(); } Plugin.Log.LogInfo((object)$"[連線同步] 玩家 (ViewID: {viewID}) 的血量已強制同步為: {targetHp}"); } } } public static class Helpers { public static KeyCode ParseKey(string key) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(key)) { return (KeyCode)104; } try { return (KeyCode)Enum.Parse(typeof(KeyCode), key.ToUpperInvariant(), ignoreCase: true); } catch { return (KeyCode)104; } } public static int GetHealthInternal(PlayerHealth health) { return Traverse.Create((object)health).Field("health").GetValue(); } } }