Decompiled source of TradeForRevive v1.0.0

TradeForRevive.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 TradeForReviveMod
{
	[BepInPlugin("REPOJP.TradeForRevive", "TradeForRevive", "1.0.0")]
	public sealed class TradeForRevivePlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "REPOJP.TradeForRevive";

		public const string PluginName = "TradeForRevive";

		public const string PluginVersion = "1.0.0";

		internal static TradeForRevivePlugin Instance;

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			try
			{
				Instance = this;
				Log = ((BaseUnityPlugin)this).Logger;
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				GameObject val = new GameObject("TradeForReviveManager");
				val.transform.parent = null;
				((Object)val).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)val);
				val.AddComponent<TradeForReviveManager>();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"TradeForRevive 1.0.0 loaded");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Awake failed\n" + ex));
			}
		}
	}
	internal sealed class TradeForReviveManager : MonoBehaviour
	{
		private sealed class HoldState
		{
			public int ItemKey;

			public float StartTime;
		}

		private sealed class TradeCandidate
		{
			public PlayerDeathHead DeathHead;

			public PlayerAvatar PlayerAvatar;

			public PhysGrabObject PhysGrabObject;

			public ItemAttributes ItemAttributes;

			public string SourceLabel;

			public int TargetHp;

			public float DistanceSqr;
		}

		private struct ReviveValueResult
		{
			public bool Valid;

			public int TargetHp;

			public string SourceLabel;
		}

		[CompilerGenerated]
		private sealed class <ExecuteTradeReviveRoutine>d__32 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TradeCandidate candidate;

			public int headViewId;

			public TradeForReviveManager <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ExecuteTradeReviveRoutine>d__32(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!<>4__this.CanExecuteTrade(candidate))
					{
						<>4__this.runningHeadIds.Remove(headViewId);
						return false;
					}
					<>4__this.ForceReleaseAllGrabbers(candidate.PhysGrabObject);
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!<>4__this.CanExecuteTrade(candidate))
					{
						<>4__this.runningHeadIds.Remove(headViewId);
						return false;
					}
					<>4__this.ExecuteTradeCore(candidate);
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>4__this.FinalizeReviveHealth(candidate, headViewId);
					<>4__this.runningHeadIds.Remove(headViewId);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static ConfigEntry<bool> configEnableMod;

		private static ConfigEntry<float> configDetectRadius;

		private static ConfigEntry<float> configTouchHoldSeconds;

		private static ConfigEntry<float> configScanInterval;

		private static ConfigEntry<float> configHeadCooldown;

		private static ConfigEntry<bool> configRequirePurchasedItem;

		private static ConfigEntry<bool> configAllowBatteryItems;

		private static ConfigEntry<bool> configAllowHealthPacks;

		private static ConfigEntry<bool> configAllowZeroBatteryRevive;

		private static ConfigEntry<bool> configConsumeItem;

		private static ConfigEntry<bool> configDestroyWithEffects;

		private static ConfigEntry<bool> configDebugLog;

		private static readonly FieldInfo FieldPlayerDeathHeadTriggered = typeof(PlayerDeathHead).GetField("triggered", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldPlayerDeathHeadInExtractionPoint = typeof(PlayerDeathHead).GetField("inExtractionPoint", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldPlayerAvatarIsDisabled = typeof(PlayerAvatar).GetField("isDisabled", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldPlayerHealthHealth = typeof(PlayerHealth).GetField("health", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldPlayerHealthMaxHealth = typeof(PlayerHealth).GetField("maxHealth", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldItemAttributesInstanceName = typeof(ItemAttributes).GetField("instanceName", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldPhysGrabObjectImpactDetector = typeof(PhysGrabObject).GetField("impactDetector", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo FieldPlayerDeathHeadPhysGrabObject = typeof(PlayerDeathHead).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.NonPublic);

		private readonly Dictionary<int, float> headCooldownUntil = new Dictionary<int, float>();

		private readonly HashSet<int> runningHeadIds = new HashSet<int>();

		private readonly Dictionary<int, HoldState> holdStates = new Dictionary<int, HoldState>();

		private float scanTimer;

		private void Awake()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			try
			{
				if (configEnableMod == null)
				{
					ConfigFile config = ((BaseUnityPlugin)TradeForRevivePlugin.Instance).Config;
					configEnableMod = config.Bind<bool>("General", "EnableMod", true, "Enable revive trading system.蘇生トレード機能の有効化");
					configDetectRadius = config.Bind<float>("General", "DetectRadius", 0.55f, new ConfigDescription("Detection radius around a death head for trade items.デスヘッド周囲で引き換えアイテムを検知する半径", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
					configTouchHoldSeconds = config.Bind<float>("General", "TouchHoldSeconds", 2f, new ConfigDescription("Required continuous contact time before revive trade activates.蘇生トレードが発動するまでに必要な連続接触時間 秒", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
					configScanInterval = config.Bind<float>("General", "ScanInterval", 0.05f, new ConfigDescription("Scan interval in seconds.検知処理の実行間隔 秒", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
					configHeadCooldown = config.Bind<float>("General", "HeadCooldown", 0.75f, new ConfigDescription("Cooldown per death head after a successful trade.蘇生成功後の同一デスヘッド再判定クールダウン 秒", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
					configRequirePurchasedItem = config.Bind<bool>("General", "RequirePurchasedItem", true, "Only allow purchased items to be traded.購入済みアイテムのみ引き換え対象にする");
					configAllowBatteryItems = config.Bind<bool>("General", "AllowBatteryItems", true, "Allow battery powered items as revive payment.バッテリー付きアイテムを蘇生素材として許可する");
					configAllowHealthPacks = config.Bind<bool>("General", "AllowHealthPacks", true, "Allow health packs as revive payment.ヘルスパックを蘇生素材として許可する");
					configAllowZeroBatteryRevive = config.Bind<bool>("General", "AllowZeroBatteryRevive", true, "Allow battery items with zero charge to revive with 1 HP.残量0のバッテリーでもHP1で蘇生を許可する");
					configConsumeItem = config.Bind<bool>("General", "ConsumeItem", true, "Consume the traded item on success.蘇生成功時にアイテムを消費する");
					configDestroyWithEffects = config.Bind<bool>("General", "DestroyWithEffects", false, "Destroy consumed item with normal break effects.消費アイテムを通常破壊演出ありで消す");
					configDebugLog = config.Bind<bool>("Debug", "DebugLog", false, "Enable verbose debug logging.詳細デバッグログの有効化");
				}
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("Manager Awake failed\n" + ex));
			}
		}

		private void Update()
		{
			try
			{
				if (configEnableMod == null || !configEnableMod.Value || !SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsLevel())
				{
					return;
				}
				scanTimer -= Time.deltaTime;
				if (scanTimer > 0f)
				{
					return;
				}
				scanTimer = configScanInterval.Value;
				if (!((Object)(object)GameDirector.instance == (Object)null) && GameDirector.instance.PlayerList != null)
				{
					for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++)
					{
						PlayerAvatar player = GameDirector.instance.PlayerList[i];
						TryProcessPlayerDeathHead(player);
					}
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("Update failed\n" + ex));
			}
		}

		private void TryProcessPlayerDeathHead(PlayerAvatar player)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)player.playerDeathHead == (Object)null || (Object)(object)player.playerHealth == (Object)null || !GetPlayerIsDisabled(player))
			{
				return;
			}
			PlayerDeathHead playerDeathHead = player.playerDeathHead;
			PhysGrabObject deathHeadPhysGrabObject = GetDeathHeadPhysGrabObject(playerDeathHead);
			if (!IsDeathHeadTriggered(playerDeathHead) || (Object)(object)deathHeadPhysGrabObject == (Object)null)
			{
				return;
			}
			PhotonView component = ((Component)playerDeathHead).GetComponent<PhotonView>();
			int num = (((Object)(object)component != (Object)null) ? component.ViewID : ((Object)playerDeathHead).GetInstanceID());
			if (runningHeadIds.Contains(num) || (headCooldownUntil.TryGetValue(num, out var value) && Time.time < value))
			{
				return;
			}
			Collider[] array = Physics.OverlapSphere(deathHeadPhysGrabObject.centerPoint, configDetectRadius.Value, -1, (QueryTriggerInteraction)2);
			if (array == null || array.Length == 0)
			{
				return;
			}
			TradeCandidate tradeCandidate = null;
			for (int i = 0; i < array.Length; i++)
			{
				TradeCandidate tradeCandidate2 = BuildCandidateFromCollider(array[i], playerDeathHead);
				if (tradeCandidate2 != null && (tradeCandidate == null || tradeCandidate2.DistanceSqr < tradeCandidate.DistanceSqr))
				{
					tradeCandidate = tradeCandidate2;
				}
			}
			if (tradeCandidate == null)
			{
				ClearHoldState(num);
			}
			else if (UpdateHoldStateAndCheckReady(num, tradeCandidate))
			{
				runningHeadIds.Add(num);
				ClearHoldState(num);
				((MonoBehaviour)this).StartCoroutine(ExecuteTradeReviveRoutine(tradeCandidate, num));
			}
		}

		private TradeCandidate BuildCandidateFromCollider(Collider hitCollider, PlayerDeathHead deathHead)
		{
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hitCollider == (Object)null)
			{
				return null;
			}
			PlayerDeathHead componentInParent = ((Component)hitCollider).GetComponentInParent<PlayerDeathHead>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return null;
			}
			PhysGrabObject componentInParent2 = ((Component)hitCollider).GetComponentInParent<PhysGrabObject>();
			if ((Object)(object)componentInParent2 == (Object)null)
			{
				return null;
			}
			PhysGrabObject deathHeadPhysGrabObject = GetDeathHeadPhysGrabObject(deathHead);
			if ((Object)(object)componentInParent2 == (Object)(object)deathHeadPhysGrabObject)
			{
				return null;
			}
			ItemAttributes val = ((Component)componentInParent2).GetComponent<ItemAttributes>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)componentInParent2).GetComponentInParent<ItemAttributes>();
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val.item == (Object)null)
			{
				return null;
			}
			if (!IsTradeItemCurrentlyHeld(componentInParent2))
			{
				return null;
			}
			if (configRequirePurchasedItem.Value && !IsPurchasedTradeItem(val))
			{
				return null;
			}
			int playerMaxHealth = GetPlayerMaxHealth(deathHead.playerAvatar);
			ReviveValueResult reviveValue = GetReviveValue(val, componentInParent2, playerMaxHealth);
			if (!reviveValue.Valid)
			{
				return null;
			}
			if ((Object)(object)deathHeadPhysGrabObject == (Object)null)
			{
				return null;
			}
			TradeCandidate tradeCandidate = new TradeCandidate();
			tradeCandidate.DeathHead = deathHead;
			tradeCandidate.PlayerAvatar = deathHead.playerAvatar;
			tradeCandidate.PhysGrabObject = componentInParent2;
			tradeCandidate.ItemAttributes = val;
			tradeCandidate.SourceLabel = reviveValue.SourceLabel;
			tradeCandidate.TargetHp = Mathf.Clamp(reviveValue.TargetHp, 1, playerMaxHealth);
			Vector3 val2 = componentInParent2.centerPoint - deathHeadPhysGrabObject.centerPoint;
			tradeCandidate.DistanceSqr = ((Vector3)(ref val2)).sqrMagnitude;
			return tradeCandidate;
		}

		private bool UpdateHoldStateAndCheckReady(int headViewId, TradeCandidate candidate)
		{
			if (candidate == null || (Object)(object)candidate.PhysGrabObject == (Object)null)
			{
				ClearHoldState(headViewId);
				return false;
			}
			int tradeItemKey = GetTradeItemKey(candidate.PhysGrabObject, candidate.ItemAttributes);
			float time = Time.time;
			if (!holdStates.TryGetValue(headViewId, out var value))
			{
				value = new HoldState();
				value.ItemKey = tradeItemKey;
				value.StartTime = time;
				holdStates[headViewId] = value;
				return false;
			}
			if (value.ItemKey != tradeItemKey)
			{
				value.ItemKey = tradeItemKey;
				value.StartTime = time;
				holdStates[headViewId] = value;
				return false;
			}
			if (time - value.StartTime < configTouchHoldSeconds.Value)
			{
				return false;
			}
			return true;
		}

		private void ClearHoldState(int headViewId)
		{
			if (holdStates.ContainsKey(headViewId))
			{
				holdStates.Remove(headViewId);
			}
		}

		private int GetTradeItemKey(PhysGrabObject physGrabObject, ItemAttributes itemAttributes)
		{
			if ((Object)(object)physGrabObject != (Object)null)
			{
				PhotonView component = ((Component)physGrabObject).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					return component.ViewID;
				}
			}
			if ((Object)(object)itemAttributes != (Object)null)
			{
				string instanceName = GetInstanceName(itemAttributes);
				if (!string.IsNullOrEmpty(instanceName))
				{
					return instanceName.GetHashCode();
				}
			}
			if ((Object)(object)physGrabObject != (Object)null)
			{
				return ((Object)physGrabObject).GetInstanceID();
			}
			return 0;
		}

		private ReviveValueResult GetReviveValue(ItemAttributes itemAttributes, PhysGrabObject physGrabObject, int playerMaxHealth)
		{
			ReviveValueResult result = default(ReviveValueResult);
			result.Valid = false;
			result.TargetHp = 0;
			result.SourceLabel = string.Empty;
			if (configAllowHealthPacks.Value)
			{
				ItemHealthPack val = ((Component)physGrabObject).GetComponent<ItemHealthPack>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)physGrabObject).GetComponentInParent<ItemHealthPack>();
				}
				if ((Object)(object)val != (Object)null)
				{
					result.Valid = true;
					result.TargetHp = Mathf.Clamp(val.healAmount, 1, playerMaxHealth);
					result.SourceLabel = GetDisplayItemName(itemAttributes);
					return result;
				}
			}
			if (configAllowBatteryItems.Value)
			{
				ItemBattery val2 = ((Component)physGrabObject).GetComponent<ItemBattery>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)physGrabObject).GetComponentInParent<ItemBattery>();
				}
				if ((Object)(object)val2 != (Object)null)
				{
					string instanceName = GetInstanceName(itemAttributes);
					float batteryPercent = GetBatteryPercent(val2, instanceName);
					int targetHp;
					if (batteryPercent <= 0f)
					{
						if (!configAllowZeroBatteryRevive.Value)
						{
							return result;
						}
						targetHp = 1;
					}
					else
					{
						targetHp = Mathf.Max(1, Mathf.FloorToInt((float)playerMaxHealth * batteryPercent));
					}
					result.Valid = true;
					result.TargetHp = targetHp;
					result.SourceLabel = GetDisplayItemName(itemAttributes);
					return result;
				}
			}
			return result;
		}

		[IteratorStateMachine(typeof(<ExecuteTradeReviveRoutine>d__32))]
		private IEnumerator ExecuteTradeReviveRoutine(TradeCandidate candidate, int headViewId)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ExecuteTradeReviveRoutine>d__32(0)
			{
				<>4__this = this,
				candidate = candidate,
				headViewId = headViewId
			};
		}

		private bool CanExecuteTrade(TradeCandidate candidate)
		{
			try
			{
				if (candidate == null)
				{
					return false;
				}
				if ((Object)(object)candidate.DeathHead == (Object)null || (Object)(object)candidate.PlayerAvatar == (Object)null || (Object)(object)candidate.PlayerAvatar.playerHealth == (Object)null)
				{
					return false;
				}
				if ((Object)(object)candidate.PhysGrabObject == (Object)null || (Object)(object)candidate.ItemAttributes == (Object)null || (Object)(object)candidate.ItemAttributes.item == (Object)null)
				{
					return false;
				}
				if (!GetPlayerIsDisabled(candidate.PlayerAvatar))
				{
					return false;
				}
				if (!IsDeathHeadTriggered(candidate.DeathHead))
				{
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("CanExecuteTrade failed\n" + ex));
				return false;
			}
		}

		private void ExecuteTradeCore(TradeCandidate candidate)
		{
			try
			{
				if (configConsumeItem.Value)
				{
					ConsumePurchasedItem(candidate.ItemAttributes);
					RemoveFromShoppingList(candidate.ItemAttributes);
					DestroyTradeItem(candidate.PhysGrabObject);
				}
				SetDeathHeadInExtractionPoint(candidate.DeathHead, value: true);
				candidate.DeathHead.Revive();
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("ExecuteTradeCore failed\n" + ex));
			}
		}

		private void FinalizeReviveHealth(TradeCandidate candidate, int headViewId)
		{
			try
			{
				if (candidate != null && !((Object)(object)candidate.PlayerAvatar == (Object)null) && !((Object)(object)candidate.PlayerAvatar.playerHealth == (Object)null) && !GetPlayerIsDisabled(candidate.PlayerAvatar))
				{
					int playerCurrentHealth = GetPlayerCurrentHealth(candidate.PlayerAvatar);
					int playerMaxHealth = GetPlayerMaxHealth(candidate.PlayerAvatar);
					int num = Mathf.Clamp(candidate.TargetHp, 1, playerMaxHealth);
					int num2 = num - playerCurrentHealth;
					if (num2 > 0)
					{
						candidate.PlayerAvatar.playerHealth.HealOther(num2, true);
					}
					headCooldownUntil[headViewId] = Time.time + configHeadCooldown.Value;
					if (configDebugLog.Value)
					{
						TradeForRevivePlugin.Log.LogInfo((object)("Revived " + GetPlayerName(candidate.PlayerAvatar) + " with " + num + " HP by " + candidate.SourceLabel));
					}
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("FinalizeReviveHealth failed\n" + ex));
			}
		}

		private bool IsTradeItemCurrentlyHeld(PhysGrabObject physGrabObject)
		{
			try
			{
				if ((Object)(object)physGrabObject == (Object)null)
				{
					return false;
				}
				if (physGrabObject.playerGrabbing != null && physGrabObject.playerGrabbing.Count > 0)
				{
					return true;
				}
				if (physGrabObject.grabbed || physGrabObject.grabbedLocal)
				{
					return true;
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("IsTradeItemCurrentlyHeld failed" + ex));
			}
			return false;
		}

		private void ForceReleaseAllGrabbers(PhysGrabObject physGrabObject)
		{
			try
			{
				if ((Object)(object)physGrabObject == (Object)null)
				{
					return;
				}
				List<PhysGrabber> list = new List<PhysGrabber>(physGrabObject.playerGrabbing);
				PhotonView component = ((Component)physGrabObject).GetComponent<PhotonView>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				for (int i = 0; i < list.Count; i++)
				{
					PhysGrabber val = list[i];
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val.photonView == (Object)null))
					{
						val.photonView.RPC("ReleaseObjectRPC", (RpcTarget)0, new object[3] { false, 0.1f, component.ViewID });
					}
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("ForceReleaseAllGrabbers failed\n" + ex));
			}
		}

		private void ConsumePurchasedItem(ItemAttributes itemAttributes)
		{
			try
			{
				if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null || (Object)(object)StatsManager.instance == (Object)null)
				{
					return;
				}
				string instanceName = GetInstanceName(itemAttributes);
				if (!string.IsNullOrEmpty(instanceName) && StatsManager.instance.item.ContainsKey(instanceName))
				{
					StatsManager.instance.ItemRemove(instanceName);
				}
				else
				{
					int num = 0;
					if (StatsManager.instance.itemsPurchased.ContainsKey(((Object)itemAttributes.item).name))
					{
						num = StatsManager.instance.itemsPurchased[((Object)itemAttributes.item).name];
					}
					StatsManager.instance.SetItemPurchase(itemAttributes.item, Mathf.Max(0, num - 1));
				}
				if ((Object)(object)ItemManager.instance != (Object)null)
				{
					ItemManager.instance.purchasedItems.Remove(itemAttributes.item);
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("ConsumePurchasedItem failed\n" + ex));
			}
		}

		private void RemoveFromShoppingList(ItemAttributes itemAttributes)
		{
			try
			{
				if ((Object)(object)itemAttributes != (Object)null && (Object)(object)ShopManager.instance != (Object)null)
				{
					ShopManager.instance.ShoppingListItemRemove(itemAttributes);
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("RemoveFromShoppingList failed\n" + ex));
			}
		}

		private void DestroyTradeItem(PhysGrabObject physGrabObject)
		{
			try
			{
				if (!((Object)(object)physGrabObject == (Object)null))
				{
					PhysGrabObjectImpactDetector val = GetImpactDetector(physGrabObject);
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)physGrabObject).GetComponent<PhysGrabObjectImpactDetector>();
					}
					if (!((Object)(object)val == (Object)null))
					{
						val.DestroyObject(configDestroyWithEffects.Value);
					}
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("DestroyTradeItem failed\n" + ex));
			}
		}

		private float GetBatteryPercent(ItemBattery itemBattery, string instanceName)
		{
			try
			{
				if ((Object)(object)StatsManager.instance != (Object)null && !string.IsNullOrEmpty(instanceName) && StatsManager.instance.itemStatBattery.ContainsKey(instanceName))
				{
					int batteryLevel = StatsManager.instance.GetBatteryLevel(instanceName);
					return Mathf.Clamp01((float)batteryLevel / 100f);
				}
				if ((Object)(object)itemBattery != (Object)null)
				{
					return Mathf.Clamp01(itemBattery.batteryLife / 100f);
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetBatteryPercent failed\n" + ex));
			}
			return 0f;
		}

		private bool IsPurchasedTradeItem(ItemAttributes itemAttributes)
		{
			try
			{
				if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null || (Object)(object)StatsManager.instance == (Object)null)
				{
					return false;
				}
				string instanceName = GetInstanceName(itemAttributes);
				if (!string.IsNullOrEmpty(instanceName) && StatsManager.instance.item.ContainsKey(instanceName))
				{
					return true;
				}
				if (StatsManager.instance.itemsPurchased.ContainsKey(((Object)itemAttributes.item).name))
				{
					return StatsManager.instance.itemsPurchased[((Object)itemAttributes.item).name] > 0;
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("IsPurchasedTradeItem failed\n" + ex));
			}
			return false;
		}

		private bool IsDeathHeadTriggered(PlayerDeathHead deathHead)
		{
			try
			{
				if ((Object)(object)deathHead == (Object)null || FieldPlayerDeathHeadTriggered == null)
				{
					return false;
				}
				object value = FieldPlayerDeathHeadTriggered.GetValue(deathHead);
				return value is bool && (bool)value;
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("IsDeathHeadTriggered failed\n" + ex));
				return false;
			}
		}

		private void SetDeathHeadInExtractionPoint(PlayerDeathHead deathHead, bool value)
		{
			try
			{
				if ((Object)(object)deathHead != (Object)null && FieldPlayerDeathHeadInExtractionPoint != null)
				{
					FieldPlayerDeathHeadInExtractionPoint.SetValue(deathHead, value);
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("SetDeathHeadInExtractionPoint failed\n" + ex));
			}
		}

		private bool GetPlayerIsDisabled(PlayerAvatar playerAvatar)
		{
			try
			{
				if ((Object)(object)playerAvatar == (Object)null || FieldPlayerAvatarIsDisabled == null)
				{
					return false;
				}
				object value = FieldPlayerAvatarIsDisabled.GetValue(playerAvatar);
				return value is bool && (bool)value;
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetPlayerIsDisabled failed\n" + ex));
				return false;
			}
		}

		private int GetPlayerCurrentHealth(PlayerAvatar playerAvatar)
		{
			try
			{
				if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.playerHealth == (Object)null || FieldPlayerHealthHealth == null)
				{
					return 1;
				}
				object value = FieldPlayerHealthHealth.GetValue(playerAvatar.playerHealth);
				if (value is int)
				{
					return (int)value;
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetPlayerCurrentHealth failed\n" + ex));
			}
			return 1;
		}

		private int GetPlayerMaxHealth(PlayerAvatar playerAvatar)
		{
			try
			{
				if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.playerHealth == (Object)null || FieldPlayerHealthMaxHealth == null)
				{
					return 100;
				}
				object value = FieldPlayerHealthMaxHealth.GetValue(playerAvatar.playerHealth);
				if (value is int)
				{
					return Mathf.Max(1, (int)value);
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetPlayerMaxHealth failed\n" + ex));
			}
			return 100;
		}

		private string GetPlayerName(PlayerAvatar playerAvatar)
		{
			try
			{
				if ((Object)(object)playerAvatar == (Object)null)
				{
					return "Unknown";
				}
				return ((Object)playerAvatar).name;
			}
			catch
			{
				return "Unknown";
			}
		}

		private string GetDisplayItemName(ItemAttributes itemAttributes)
		{
			try
			{
				if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null)
				{
					return "Unknown Item";
				}
				return itemAttributes.item.itemName;
			}
			catch
			{
				return "Unknown Item";
			}
		}

		private string GetInstanceName(ItemAttributes itemAttributes)
		{
			try
			{
				if ((Object)(object)itemAttributes == (Object)null || FieldItemAttributesInstanceName == null)
				{
					return string.Empty;
				}
				object value = FieldItemAttributesInstanceName.GetValue(itemAttributes);
				if (value is string)
				{
					return (string)value;
				}
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetInstanceName failed\n" + ex));
			}
			return string.Empty;
		}

		private PhysGrabObject GetDeathHeadPhysGrabObject(PlayerDeathHead deathHead)
		{
			try
			{
				if ((Object)(object)deathHead == (Object)null || FieldPlayerDeathHeadPhysGrabObject == null)
				{
					return null;
				}
				object? value = FieldPlayerDeathHeadPhysGrabObject.GetValue(deathHead);
				return (PhysGrabObject)((value is PhysGrabObject) ? value : null);
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetDeathHeadPhysGrabObject failed\n" + ex));
				return null;
			}
		}

		private PhysGrabObjectImpactDetector GetImpactDetector(PhysGrabObject physGrabObject)
		{
			try
			{
				if ((Object)(object)physGrabObject == (Object)null || FieldPhysGrabObjectImpactDetector == null)
				{
					return null;
				}
				object? value = FieldPhysGrabObjectImpactDetector.GetValue(physGrabObject);
				return (PhysGrabObjectImpactDetector)((value is PhysGrabObjectImpactDetector) ? value : null);
			}
			catch (Exception ex)
			{
				TradeForRevivePlugin.Log.LogError((object)("GetImpactDetector failed\n" + ex));
				return null;
			}
		}
	}
}