Decompiled source of SymbioticGhost v1.6.23

plugins\SymbioticGhost.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using SymbioticGhost.Core;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.UI;
using Zorro.ControllerSupport;
using Zorro.Core;
using Zorro.Core.Serizalization;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("youxia173")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.6.23.0")]
[assembly: AssemblyInformationalVersion("1.6.23")]
[assembly: AssemblyProduct("SymbioticGhost")]
[assembly: AssemblyTitle("SymbioticGhost")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.23.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 SymbioticGhost
{
	internal static class Configuration
	{
		internal static ConfigEntry<KeyCode> ToggleKey;

		internal static ConfigEntry<float> MoveSpeed;

		internal static ConfigEntry<float> MoveDamping;

		internal static ConfigEntry<float> LookSensitivityMultiplier;

		internal static ConfigEntry<float> LeashDistance;

		internal static ConfigEntry<float> LeashPoints;

		internal static ConfigEntry<float> FreeFlyHudOffsetX;

		internal static ConfigEntry<float> FreeFlyHudOffsetY;

		internal static ConfigEntry<bool> EnableNames;

		internal static ConfigEntry<float> NameVisibleAngle;

		internal static ConfigEntry<bool> DisplayWhenBlind;

		internal static ConfigEntry<bool> ShowNameDistance;

		internal static ConfigEntry<bool> EnablePingDistance;

		internal static ConfigEntry<float> PingTextDuration;

		internal static ConfigEntry<bool> ShowPingNameShort;

		internal static ConfigEntry<bool> EnableGhostPing;

		internal static ConfigEntry<bool> EnableGhostHaul;

		internal static ConfigEntry<float> MaxGhostHaulDisplayWeight;

		internal static ConfigEntry<KeyCode> GhostHaulKey;

		internal static ConfigEntry<float> GhostHaulRange;

		internal static ConfigEntry<bool> EnableGhostBackpack;

		internal static ConfigEntry<bool> EnableDownedMarkers;

		internal static ConfigEntry<float> DeadCorpseMarkerMinutes;

		internal static ConfigEntry<bool> EnableHostGhostRevive;

		internal static ConfigEntry<float> HostReviveCursePenalty;

		internal static ConfigEntry<float> HostRevivePetrifyPenalty;

		internal static ConfigEntry<float> HostRevivePenaltyDecaySeconds;

		internal static ConfigEntry<float> HostRevivePenaltyDecayAmount;

		internal static ConfigEntry<bool> HostReviveInheritHostState;

		internal static void Initialize(ConfigFile config)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Expected O, but got Unknown
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Expected O, but got Unknown
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Expected O, but got Unknown
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Expected O, but got Unknown
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Expected O, but got Unknown
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Expected O, but got Unknown
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Expected O, but got Unknown
			ToggleKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Free Fly Toggle 自由飞行开关", (KeyCode)284, "EN: Dead — free-fly. Alive — revive ghosts soul-linked to you (picker if several).\n中文:死亡 — 灵魂离体;活着 — 复活挂在自己身上的幽灵(多个时弹出选择)。");
			MoveSpeed = config.Bind<float>("2. Camera 相机", "Move Speed 移动速度", 12f, new ConfigDescription("EN: Free-fly movement force.\n中文:自由飞行移动力度。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			MoveDamping = config.Bind<float>("2. Camera 相机", "Move Damping 移动阻尼", 3f, new ConfigDescription("EN: Velocity settle damping.\n中文:自由飞行速度阻尼。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>()));
			LookSensitivityMultiplier = config.Bind<float>("2. Camera 相机", "Look Sensitivity Multiplier 视角灵敏度倍率", 1f, new ConfigDescription("EN: Multiplies the game Mouse/Controller Sensitivity. 1 = same as living character.\n中文:自由飞行视角 = 游戏设置灵敏度 × 本倍率;1 表示与活着时一致。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), Array.Empty<object>()));
			LeashDistance = config.Bind<float>("3. Symbiosis 共生", "Leash Distance 寄宿距离", 20f, new ConfigDescription("EN: Beyond this distance from the host, free-fly leash points start draining (−4/s).\n中文:超过与寄宿玩家的该直线距离后,寄宿点数开始消耗(−4/s)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			LeashPoints = config.Bind<float>("3. Symbiosis 共生", "Leash Points 寄宿点数", 100f, new ConfigDescription("EN: Max leash points (bar). Drain −4/s out of range; free-fly in-range +1/s; attach spectate +2/s. Decimals OK if you lower this.\n中文:寄宿点数上限(可改)。超距 −4/s;自由飞范围内 +1/s;原版观战 +2/s。改小后可用小数显示。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), Array.Empty<object>()));
			FreeFlyHudOffsetX = config.Bind<float>("3. Symbiosis 共生", "Free Fly Status HUD X 自由飞状态栏X", 1f, new ConfigDescription("EN: Horizontal position of host / leash status HUD (free-fly + attach spectate). 0 = left, 1 = right.\n中文:宿主/寄宿状态栏水平位置(自由飞与原版观战都显示)。0=最左,1=最右。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			FreeFlyHudOffsetY = config.Bind<float>("3. Symbiosis 共生", "Free Fly Status HUD Y 自由飞状态栏Y", 0.06f, new ConfigDescription("EN: Extra vertical lift of status HUD (free-fly and attach spectate share the same base above the hotbar). 0 = base, 1 = higher.\n中文:状态栏额外抬升(自由飞与原版观战共用物品栏上方基准)。0=基准,1=更高。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			EnableNames = config.Bind<bool>("4. Player Names 队友名字", "Enable Names 启用名字显示", true, "EN: Show teammate names when looking at them. Turn OFF to use AlwaysDisplayPlayerName (or similar) instead.\n中文:看向队友时显示名字。关掉后可改用 AlwaysDisplayPlayerName 等同类模组,避免冲突。");
			NameVisibleAngle = config.Bind<float>("4. Player Names 队友名字", "Visible Angle 可见角度", 52f, new ConfigDescription("EN: Cone angle for name visibility.\n中文:名字显示的视角锥角。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 180f), Array.Empty<object>()));
			DisplayWhenBlind = config.Bind<bool>("4. Player Names 队友名字", "Display When Blind 致盲时显示", false, "EN: Force names when the target is blind.\n中文:目标致盲时是否仍显示名字。");
			ShowNameDistance = config.Bind<bool>("4. Player Names 队友名字", "Show Distance 显示距离", true, "EN: Show distance under the player name.\n中文:在名字下方显示距离。");
			EnablePingDistance = config.Bind<bool>("5. Ping Distance 标记距离", "Enable Ping Distance 启用标记距离", true, "EN: Show distance text on pings. Turn OFF to use BetterPingDistance (or similar) instead.\n中文:标记时显示距离。关掉后可改用 BetterPingDistance 等同类模组,避免冲突。");
			PingTextDuration = config.Bind<float>("5. Ping Distance 标记距离", "Ping Text Duration 标记距离秒数", 3f, new ConfigDescription("EN: How long ping distance text stays on screen.\n中文:标记距离文字停留秒数。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f), Array.Empty<object>()));
			ShowPingNameShort = config.Bind<bool>("5. Ping Distance 标记距离", "Show Ping Name Short 标记名缩写", true, "EN: Show a short name after ping distance.\n中文:在标记距离后显示玩家名缩写。");
			EnableGhostPing = config.Bind<bool>("6. Ghost Ping 幽灵标记", "Enable Ghost Ping 启用幽灵标记", true, "EN: Allow pinging while dead / passed out. Turn OFF to use GhostPing (or similar) instead.\n中文:死亡/昏厥时也可标记。关掉后可改用 GhostPing 等同类模组,避免冲突。");
			EnableGhostHaul = config.Bind<bool>("7. Ghost Haul 幽灵搬运", "Enable Ghost Haul 启用幽灵搬运", true, "EN: Ghosts may haul light ground items and use feedable items on teammates (also Book of Bones revive).\n中文:幽灵可提起轻物到临时手持,并对队友使用可喂物品(含骸骨之书复活)。");
			EnableGhostBackpack = config.Bind<bool>("8. Ghost Backpack 幽灵背包", "Enable Ghost Backpack 启用幽灵背包", true, "EN: Ghosts can open ground/worn backpacks to stash or take one held item; wearing and hotbar storage are blocked.\n中文:幽灵可打开地上或他人背上的背包存取(仅临时手持一件);禁止背起,也不会进快捷栏。");
			MaxGhostHaulDisplayWeight = config.Bind<float>("7. Ghost Haul 幽灵搬运", "Max Display Weight 最大界面重量", 2.5f, new ConfigDescription("EN: Max item UI weight (CarryWeight × 2.5). Default 2.5 = rescue claw tier; airplane meal is 5.\n中文:物品界面重量上限(负重槽用的 CarryWeight×2.5)。默认 2.5 为救援爪档;飞机餐为 5。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2.5f, 20f), Array.Empty<object>()));
			GhostHaulKey = config.Bind<KeyCode>("7. Ghost Haul 幽灵搬运", "Haul Key 搬运按键", (KeyCode)101, "EN: Unused legacy. Pickup = Interact (E). Drop = Drop key (Q), same as living.\n中文:已弃用。拾取=交互键 E;放下=丢弃键 Q(与活人一致)。");
			GhostHaulRange = config.Bind<float>("7. Ghost Haul 幽灵搬运", "Haul Range 搬运距离", 4f, new ConfigDescription("EN: How far the ghost can reach to haul an item.\n中文:幽灵可提起物品的最大距离。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 12f), Array.Empty<object>()));
			EnableDownedMarkers = config.Bind<bool>("9. Downed Markers 倒地指示", "Enable Downed Markers 启用倒地指示", true, "EN: Markers for passed-out / dead bodies. Turn OFF to use DownedAwareness (or similar) instead.\n中文:昏厥/死亡位置指示。关掉后可改用 DownedAwareness 等同类模组,避免冲突。");
			DeadCorpseMarkerMinutes = config.Bind<float>("9. Downed Markers 倒地指示", "Dead Corpse Marker Minutes 尸体标记分钟", 6f, new ConfigDescription("EN: How long the corpse marker stays after death (minutes); 0 = hide immediately.\n中文:队友(或自己)死亡后,尸体标记再显示多少分钟;0 = 立刻隐藏。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			EnableHostGhostRevive = config.Bind<bool>("10. Host Revive 宿主复活", "Enable Host Ghost Revive 启用宿主复活幽灵", true, "EN: Living players press F3 to revive ghosts bound to them (Scout Effigy style beside host).\n中文:活人按 F3 复活挂在自己身上的幽灵(童军雕像式,在宿主旁复活)。");
			HostReviveCursePenalty = config.Bind<float>("10. Host Revive 宿主复活", "Curse Penalty 诅咒惩罚", 120f, new ConfigDescription("EN: Starting curse penalty (UI points; vanilla full bar ≈ 100). Decays by Decay Amount every Decay Seconds while bound.\n中文:初始诅咒惩罚(UI 点;原版满条约 100)。绑定宿主期间按「衰减秒数 / 每次降低」削减。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3000f), Array.Empty<object>()));
			HostRevivePetrifyPenalty = config.Bind<float>("10. Host Revive 宿主复活", "Petrify Penalty 石化惩罚", 120f, new ConfigDescription("EN: Starting petrify penalty (UI points; vanilla full bar ≈ 100). Decays by Decay Amount every Decay Seconds while bound.\n中文:初始石化惩罚(UI 点;原版满条约 100)。绑定宿主期间按「衰减秒数 / 每次降低」削减。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3000f), Array.Empty<object>()));
			HostRevivePenaltyDecaySeconds = config.Bind<float>("10. Host Revive 宿主复活", "Penalty Decay Seconds 惩罚衰减秒数", 5f, new ConfigDescription("EN: How many seconds of continuous bind before one decay tick (default 5).\n中文:连续绑定多少秒触发一次惩罚降低(默认 5)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 300f), Array.Empty<object>()));
			HostRevivePenaltyDecayAmount = config.Bind<float>("10. Host Revive 宿主复活", "Penalty Decay Amount 每次降低惩罚", 1f, new ConfigDescription("EN: How many UI penalty points curse and petrify each lose per decay tick (default 1).\n中文:每次衰减时,诅咒与石化各降低多少点(默认 1)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3000f), Array.Empty<object>()));
			HostReviveInheritHostState = config.Bind<bool>("10. Host Revive 宿主复活", "Inherit Host Stamina And Statuses 继承宿主体力与状态", true, "EN: On revive, copy the host's stamina bars and statuses (after host pays the penalty). Off = revived teammate only receives the same curse/petrify penalty — no stamina/status copy.\n中文:复活后复制宿主体力条与状态(宿主先付惩罚)。关闭则队友只承受同等诅咒/石化惩罚,不复制体力与其他状态。");
		}
	}
	internal sealed class DownedMarker : MonoBehaviour
	{
		private Character _character;

		private string _playerName = "";

		private Vector3 _lastPosition;

		private TextMeshProUGUI _distanceText;

		private TextMeshProUGUI _statusText;

		private bool _isDead;

		private bool _hasPosition;

		internal void Bind(Character character)
		{
			_character = character;
			_isDead = false;
			_hasPosition = false;
			_playerName = ResolveName(character);
			CacheTexts();
			if ((Object)(object)_statusText != (Object)null)
			{
				((TMP_Text)_statusText).text = "(@_@;)";
			}
			CapturePositionNow();
		}

		internal void MarkDead()
		{
			_isDead = true;
			_playerName = ResolveName(_character);
			if ((Object)(object)_statusText != (Object)null)
			{
				((TMP_Text)_statusText).text = "(x_x;)";
			}
		}

		internal void CapturePositionNow()
		{
			TryCapturePosition();
		}

		private void Start()
		{
			CacheTexts();
			if ((Object)(object)_statusText != (Object)null && string.IsNullOrEmpty(((TMP_Text)_statusText).text))
			{
				((TMP_Text)_statusText).text = "(@_@;)";
			}
		}

		private void CacheTexts()
		{
			if ((Object)(object)_distanceText == (Object)null)
			{
				Transform val = ((Component)this).transform.Find("DistanceText");
				if ((Object)(object)val != (Object)null)
				{
					_distanceText = ((Component)val).GetComponent<TextMeshProUGUI>();
				}
			}
			if ((Object)(object)_statusText == (Object)null)
			{
				Transform val2 = ((Component)this).transform.Find("StatusText");
				if ((Object)(object)val2 != (Object)null)
				{
					_statusText = ((Component)val2).GetComponent<TextMeshProUGUI>();
				}
			}
		}

		private void LateUpdate()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			CacheTexts();
			Camera val = SpectatorUiCamera.Get();
			if ((Object)(object)val == (Object)null || (Object)(object)_distanceText == (Object)null || (Object)(object)_statusText == (Object)null)
			{
				return;
			}
			if (!_isDead)
			{
				TryCapturePosition();
				if ((Object)(object)_character != (Object)null)
				{
					_playerName = ResolveName(_character);
				}
			}
			if (!_hasPosition)
			{
				return;
			}
			Vector3 position = ((Component)val).transform.position;
			Vector3 val2 = _lastPosition - position;
			Vector3 val3 = val.WorldToScreenPoint(_lastPosition);
			float num = ((((Vector3)(ref val2)).sqrMagnitude > 0.0001f) ? Vector3.Angle(((Component)val).transform.forward, val2) : 180f);
			bool active = val3.z > 0.1f && num < 90f;
			((Component)this).transform.position = val3;
			Color color = (((Object)(object)_character != (Object)null) ? PingDistanceManager.GetReadablePlayerColor(_character) : Color.white);
			((Graphic)_statusText).color = color;
			((Graphic)_distanceText).color = color;
			float num2 = Mathf.Max(1f, Mathf.Round(((Vector3)(ref val2)).magnitude));
			int num3 = 100;
			try
			{
				if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null)
				{
					num3 = 100 - Mathf.CeilToInt(_character.data.deathTimer * 100f);
					num3 = Mathf.Clamp(num3, 0, 100);
				}
			}
			catch
			{
				num3 = 0;
			}
			string arg = (string.IsNullOrEmpty(_playerName) ? GameL10n.Pick("Unknown", "未知") : _playerName);
			string arg2 = (_isDead ? GameL10n.Pick("DEAD", "已死亡") : GameL10n.Pick($"{num3}% to revive", $"{num3}% 待救援"));
			((TMP_Text)_distanceText).text = (_isDead ? GameL10n.Pick($"{arg}'s corpse · {num2}m | {arg2}", $"{arg} 的尸体 · {num2}m | {arg2}") : $"{arg} · {num2}m | {arg2}");
			((Component)_statusText).gameObject.SetActive(active);
			((Component)_distanceText).gameObject.SetActive(active);
		}

		private static string ResolveName(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return "";
			}
			try
			{
				if (!string.IsNullOrEmpty(character.characterName))
				{
					return character.characterName;
				}
			}
			catch
			{
			}
			return ((Object)character).name;
		}

		private void TryCapturePosition()
		{
			//IL_0032: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_character == (Object)null)
			{
				return;
			}
			try
			{
				_lastPosition = _character.TorsoPos();
				_hasPosition = true;
			}
			catch
			{
				try
				{
					_lastPosition = _character.Center;
					_hasPosition = true;
				}
				catch
				{
				}
			}
		}
	}
	internal sealed class DownedMarkerManager
	{
		private TMP_FontAsset _font;

		private Material _fontMaterial;

		private Canvas _canvas;

		private GameObject _template;

		private readonly Dictionary<Character, GameObject> _instances = new Dictionary<Character, GameObject>();

		private readonly Dictionary<Character, GameObject> _corpseMarkers = new Dictionary<Character, GameObject>();

		internal bool IsInitialized
		{
			get
			{
				if ((Object)(object)Plugin.Instance != (Object)null && (Object)(object)_canvas != (Object)null)
				{
					return (Object)(object)_template != (Object)null;
				}
				return false;
			}
		}

		internal void Initialize()
		{
			if (IsInitialized)
			{
				return;
			}
			try
			{
				CreateCanvas();
				CreateTemplate();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("DownedMarkerManager.Initialize failed: " + ex));
			}
		}

		internal void Cleanup()
		{
			DestroyAllCorpseMarkers();
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
				_canvas = null;
			}
			_template = null;
			_instances.Clear();
			_corpseMarkers.Clear();
		}

		private void FindFont()
		{
			TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
			TextMeshProUGUI[] array2 = array;
			foreach (TextMeshProUGUI val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Material materialForRendering = ((Graphic)val).materialForRendering;
					if (((Object)val).name == "Text" && (Object)(object)materialForRendering != (Object)null && ((Object)materialForRendering).name.Contains("DarumaDropOne-Regular SDF"))
					{
						_font = ((TMP_Text)val).font;
						_fontMaterial = materialForRendering;
						return;
					}
				}
			}
			array2 = array;
			foreach (TextMeshProUGUI val2 in array2)
			{
				if (!((Object)(object)((val2 != null) ? ((TMP_Text)val2).font : null) == (Object)null) && (((Object)((TMP_Text)val2).font).name.Contains("Daruma") || ((Object)(object)((Graphic)val2).materialForRendering != (Object)null && ((Object)((Graphic)val2).materialForRendering).name.Contains("Daruma"))))
				{
					_font = ((TMP_Text)val2).font;
					_fontMaterial = ((Graphic)val2).materialForRendering;
					break;
				}
			}
		}

		private void CreateCanvas()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvas != (Object)null))
			{
				_instances.Clear();
				DestroyAllCorpseMarkers();
				GameObject val = GameObject.Find("GAME/GUIManager");
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = new GameObject("Canvas_SymbioticGhostDownedMarkers", new Type[3]
					{
						typeof(Canvas),
						typeof(CanvasScaler),
						typeof(GraphicRaycaster)
					});
					val2.transform.SetParent(val.transform, false);
					_canvas = val2.GetComponent<Canvas>();
					_canvas.renderMode = (RenderMode)0;
					_canvas.sortingOrder = 101;
					CanvasScaler component = val2.GetComponent<CanvasScaler>();
					component.uiScaleMode = (ScaleMode)1;
					component.referenceResolution = new Vector2(1920f, 1080f);
					component.screenMatchMode = (ScreenMatchMode)1;
					val2.layer = LayerMask.NameToLayer("UI");
				}
			}
		}

		private void CreateTemplate()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0091: 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)
			if (!((Object)(object)_template != (Object)null) && !((Object)(object)_canvas == (Object)null))
			{
				_template = new GameObject("DownedMarker", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(DownedMarker)
				});
				_template.transform.SetParent(((Component)_canvas).transform, false);
				TextMeshProUGUI component = AddTmpChild("StatusText", _template.transform, new Vector2(200f, 80f)).GetComponent<TextMeshProUGUI>();
				((TMP_Text)component).fontSize = 35f;
				((TMP_Text)component).outlineWidth = 0f;
				((TMP_Text)component).alignment = (TextAlignmentOptions)258;
				TextMeshProUGUI component2 = AddTmpChild("DistanceText", _template.transform, new Vector2(360f, 70f)).GetComponent<TextMeshProUGUI>();
				((TMP_Text)component2).fontStyle = (FontStyles)1;
				((TMP_Text)component2).alignment = (TextAlignmentOptions)1026;
				_template.SetActive(false);
			}
		}

		private GameObject AddTmpChild(string name, Transform parent, Vector2 size)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			if ((Object)(object)_font == (Object)null)
			{
				FindFont();
			}
			GameObject val = new GameObject(name, new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI),
				typeof(Shadow)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = size;
			TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).font = _font;
			if ((Object)(object)_fontMaterial != (Object)null)
			{
				((TMP_Text)component2).fontMaterial = _fontMaterial;
			}
			((TMP_Text)component2).fontSize = 20f;
			((Graphic)component2).color = Color.white;
			((TMP_Text)component2).outlineWidth = 0.2f;
			((TMP_Text)component2).outlineColor = Color32.op_Implicit(Color.black);
			((TMP_Text)component2).enableAutoSizing = false;
			((TMP_Text)component2).alignment = (TextAlignmentOptions)514;
			((Graphic)component2).raycastTarget = false;
			Shadow component3 = val.GetComponent<Shadow>();
			component3.effectColor = new Color(0f, 0f, 0f, 0.95f);
			component3.effectDistance = new Vector2(2f, -2f);
			return val;
		}

		internal void CreateInstance(Character character)
		{
			if (Configuration.EnableDownedMarkers.Value && !((Object)(object)_canvas == (Object)null) && !((Object)(object)_template == (Object)null) && !((Object)(object)character == (Object)null) && (!_instances.TryGetValue(character, out var value) || !((Object)(object)value != (Object)null)))
			{
				GameObject val = Object.Instantiate<GameObject>(_template, ((Component)_canvas).transform);
				val.GetComponent<DownedMarker>().Bind(character);
				val.SetActive(true);
				_instances[character] = val;
			}
		}

		internal void PrepareForDeath(Character character)
		{
			if (Configuration.EnableDownedMarkers.Value && !((Object)(object)character == (Object)null))
			{
				if ((Object)(object)_canvas == (Object)null || (Object)(object)_template == (Object)null)
				{
					Initialize();
				}
				ClearCorpseMarker(character);
				CreateInstance(character);
				if (_instances.TryGetValue(character, out var value) && (Object)(object)value != (Object)null)
				{
					value.GetComponent<DownedMarker>()?.CapturePositionNow();
				}
			}
		}

		internal void UpdateInstance(Character character, bool isDead = false)
		{
			if ((Object)(object)character == (Object)null)
			{
				return;
			}
			if (!isDead)
			{
				ClearCorpseMarker(character);
			}
			if (!_instances.TryGetValue(character, out var value) || (Object)(object)value == (Object)null)
			{
				if (isDead)
				{
					ClearCorpseMarker(character);
					CreateInstance(character);
					if (_instances.TryGetValue(character, out value) && (Object)(object)value != (Object)null)
					{
						MarkDeadAndScheduleRemoval(character, value);
					}
				}
			}
			else if (isDead)
			{
				MarkDeadAndScheduleRemoval(character, value);
			}
			else
			{
				_instances.Remove(character);
				Object.Destroy((Object)(object)value);
			}
		}

		private void MarkDeadAndScheduleRemoval(Character character, GameObject instance)
		{
			instance.GetComponent<DownedMarker>()?.MarkDead();
			_instances.Remove(character);
			ClearCorpseMarker(character);
			_corpseMarkers[character] = instance;
			float num = Mathf.Max(0f, Configuration.DeadCorpseMarkerMinutes.Value) * 60f;
			if (num <= 0.01f)
			{
				Object.Destroy((Object)(object)instance);
				_corpseMarkers.Remove(character);
			}
			else
			{
				Object.Destroy((Object)(object)instance, num);
			}
		}

		private void ClearCorpseMarker(Character character)
		{
			if (!((Object)(object)character == (Object)null) && _corpseMarkers.TryGetValue(character, out var value))
			{
				_corpseMarkers.Remove(character);
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
		}

		private void DestroyAllCorpseMarkers()
		{
			foreach (KeyValuePair<Character, GameObject> corpseMarker in _corpseMarkers)
			{
				if ((Object)(object)corpseMarker.Value != (Object)null)
				{
					Object.Destroy((Object)(object)corpseMarker.Value);
				}
			}
			_corpseMarkers.Clear();
		}
	}
	[HarmonyPatch(typeof(GUIManager))]
	internal static class DownedMarkerGuiPatches
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix()
		{
			Plugin.DownedMarkers?.Initialize();
		}

		[HarmonyPatch("LateUpdate")]
		[HarmonyPostfix]
		private static void LateUpdatePostfix()
		{
			if (Plugin.DownedMarkers != null && !Plugin.DownedMarkers.IsInitialized)
			{
				Plugin.DownedMarkers.Initialize();
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPostfix]
		private static void OnDestroyPostfix()
		{
			Plugin.DownedMarkers?.Cleanup();
		}
	}
	[HarmonyPatch(typeof(Character))]
	internal static class DownedMarkerCharacterPatches
	{
		[HarmonyPatch("RPCA_PassOut")]
		[HarmonyPostfix]
		private static void PassOutPostfix(Character __instance)
		{
			Plugin.DownedMarkers?.CreateInstance(__instance);
		}

		[HarmonyPatch("RPCA_UnPassOut")]
		[HarmonyPostfix]
		private static void UnPassOutPostfix(Character __instance)
		{
			Plugin.DownedMarkers?.UpdateInstance(__instance);
		}

		[HarmonyPatch("RPCA_ReviveAtPosition")]
		[HarmonyPostfix]
		private static void RevivePostfix(Character __instance)
		{
			Plugin.DownedMarkers?.UpdateInstance(__instance);
		}

		[HarmonyPatch("ReviveCharacter")]
		[HarmonyPostfix]
		private static void ReviveCharacterPostfix(Character __instance)
		{
			Plugin.DownedMarkers?.UpdateInstance(__instance);
		}

		[HarmonyPatch("RPCA_Die")]
		[HarmonyPrefix]
		private static void DiePrefix(Character __instance)
		{
			Plugin.DownedMarkers?.PrepareForDeath(__instance);
		}

		[HarmonyPatch("RPCA_Die")]
		[HarmonyPostfix]
		private static void DiePostfix(Character __instance)
		{
			Plugin.DownedMarkers?.UpdateInstance(__instance, isDead: true);
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPostfix]
		private static void DestroyPostfix(Character __instance)
		{
			Plugin.DownedMarkers?.UpdateInstance(__instance);
		}
	}
	[HarmonyPatch(typeof(GodCam), "Update")]
	internal static class FreeCamPatches
	{
		private static bool Prefix(Transform transform, MainCamera cam)
		{
			FreeSpectatorController instance = FreeSpectatorController.Instance;
			if (instance == null || !instance.IsActive)
			{
				return true;
			}
			instance.UpdateFreeCam(transform, cam);
			return false;
		}
	}
	internal sealed class FreeSpectatorController
	{
		private static readonly FieldInfo IsGodCamField = AccessTools.Field(typeof(MainCameraMovement), "isGodCam");

		private static readonly FieldInfo LookDataField = AccessTools.Field(typeof(GodCam), "lookData");

		private static readonly FieldInfo LookVelField = AccessTools.Field(typeof(GodCam), "lookVel");

		private static readonly FieldInfo VelField = AccessTools.Field(typeof(GodCam), "vel");

		private static readonly MethodInfo SpecCharacterSetter = AccessTools.PropertySetter(typeof(MainCameraMovement), "specCharacter");

		private Vector3 _velocity;

		private Vector2 _lookData;

		private Vector2 _lookVel;

		internal static FreeSpectatorController Instance { get; private set; }

		internal bool IsActive { get; private set; }

		internal FreeSpectatorController()
		{
			Instance = this;
		}

		internal void Update()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			HostBond.Instance?.Tick();
			if (Input.GetKeyDown(Configuration.ToggleKey.Value))
			{
				if (GhostHostRevive.TryHandleLivingToggle())
				{
					return;
				}
				if (IsActive)
				{
					SetActive(active: false);
				}
				else if (CanEnterFreeFly())
				{
					SetActive(active: true);
				}
				else
				{
					TryShowFreeFlyBlockedTip();
				}
			}
			if (IsActive && !CanStayInFreeFly())
			{
				SetActive(active: false);
			}
		}

		internal void SetActive(bool active, bool forcedByLeash = false)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				IsActive = false;
			}
			else if (active == IsActive)
			{
				IsGodCamField?.SetValue(instance, active);
			}
			else if (active)
			{
				HostBond.Instance?.LockHostFromCurrentSpec();
				SyncLookFromCamera(instance);
				_velocity = Vector3.zero;
				_lookVel = Vector2.zero;
				IsActive = true;
				IsGodCamField?.SetValue(instance, true);
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
				GhostFreeSync.NotifyLocalFreeFlyStarted();
				GhostSpectateHud.SetFreeFlyHudHidden(hide: true);
				Plugin.Log.LogInfo((object)"Free-fly enabled.");
			}
			else
			{
				IsActive = false;
				IsGodCamField?.SetValue(instance, false);
				Character obj = (((Object)(object)HostBond.Instance != (Object)null) ? HostBond.Instance.Host : null);
				RestoreSpecTarget(obj);
				GhostFreeSync.NotifyLocalFreeFlyStopped(obj);
				GhostSpectateHud.SetFreeFlyHudHidden(hide: false);
				Plugin.Log.LogInfo((object)(forcedByLeash ? "Free-fly forced off by leash countdown; returned to attach spectate." : "Free-fly disabled; returned to attach spectate."));
			}
		}

		internal void ForceExitByLeash()
		{
			if (IsActive)
			{
				SetActive(active: false, forcedByLeash: true);
			}
		}

		internal void UpdateFreeCam(Transform transform, MainCamera cam)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			if (GUIManager.InPauseMenu)
			{
				_velocity = Vector3.zero;
				_lookVel = Vector2.zero;
				LookDataField?.SetValue(Singleton<MainCameraMovement>.Instance?.godcam, _lookData);
				LookVelField?.SetValue(Singleton<MainCameraMovement>.Instance?.godcam, _lookVel);
				VelField?.SetValue(Singleton<MainCameraMovement>.Instance?.godcam, _velocity);
				return;
			}
			ApplyCharacterMatchedLook(transform);
			SyncCharacterLookFromFreeFly(transform);
			Vector3 zero = Vector3.zero;
			if (Input.GetKey((KeyCode)119))
			{
				zero.z += 1f;
			}
			if (Input.GetKey((KeyCode)115))
			{
				zero.z -= 1f;
			}
			if (Input.GetKey((KeyCode)97))
			{
				zero.x -= 1f;
			}
			if (Input.GetKey((KeyCode)100))
			{
				zero.x += 1f;
			}
			if (Input.GetKey((KeyCode)32))
			{
				zero.y += 1f;
			}
			if (Input.GetKey((KeyCode)306))
			{
				zero.y -= 1f;
			}
			float num = Configuration.MoveSpeed.Value;
			if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
			{
				num *= 3f;
			}
			_velocity += transform.TransformDirection(zero) * num * Time.unscaledDeltaTime;
			_velocity = FRILerp.Lerp(_velocity, Vector3.zero, Configuration.MoveDamping.Value, false);
			transform.position += _velocity * Time.unscaledDeltaTime;
			LookDataField?.SetValue(Singleton<MainCameraMovement>.Instance?.godcam, _lookData);
			LookVelField?.SetValue(Singleton<MainCameraMovement>.Instance?.godcam, _lookVel);
			VelField?.SetValue(Singleton<MainCameraMovement>.Instance?.godcam, _velocity);
			GhostFreeSync.TickLocalPose(transform.position, transform.rotation);
			SnapLocalHeldItemToCamera();
			SoulLinkVisual.RefreshLocalEndpoint();
		}

		private static void SnapLocalHeldItemToCamera()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			Item val = (((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null) ? localCharacter.data.currentItem : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				if (GhostBackpackPatches.TryGetGhostHoldPosePublic(localCharacter, out var position, out var rotation))
				{
					GhostBackpackPatches.EnsureGhostHeldItemVisible(val);
					((Component)val).transform.SetPositionAndRotation(position, rotation);
					if ((Object)(object)val.rig != (Object)null)
					{
						val.rig.interpolation = (RigidbodyInterpolation)0;
						val.rig.isKinematic = true;
						val.rig.detectCollisions = false;
						val.rig.position = position;
						val.rig.rotation = rotation;
						val.rig.linearVelocity = Vector3.zero;
						val.rig.angularVelocity = Vector3.zero;
					}
				}
			}
			catch
			{
			}
		}

		private void ApplyCharacterMatchedLook(Transform transform)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			float num = GetGameLookSensitivity() * Mathf.Max(0.01f, Configuration.LookSensitivityMultiplier.Value);
			Vector2 val = ReadLookInput();
			int invertSign = GetInvertSign(isY: false);
			int invertSign2 = GetInvertSign(isY: true);
			_lookData.x += val.x * num * (float)invertSign;
			_lookData.y += val.y * num * (float)invertSign2;
			_lookData.y = Mathf.Clamp(_lookData.y, -85f, 85f);
			_lookVel = Vector2.zero;
			transform.rotation = Quaternion.LookRotation(HelperFunctions.LookToDirection(new Vector3(_lookData.x, _lookData.y, 0f), Vector3.forward));
		}

		private static Vector2 ReadLookInput()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InputAction action_look = CharacterInput.action_look;
				if (action_look != null)
				{
					return action_look.ReadValue<Vector2>();
				}
			}
			catch
			{
			}
			return new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
		}

		private static float GetGameLookSensitivity()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			try
			{
				SettingsHandler val = (((Object)(object)GameHandler.Instance != (Object)null) ? GameHandler.Instance.SettingsHandler : null);
				if (val == null)
				{
					return 2f;
				}
				bool flag = false;
				try
				{
					flag = (int)InputHandler.GetCurrentUsedInputScheme() == 1;
				}
				catch
				{
					flag = false;
				}
				if (flag)
				{
					ControllerSensitivitySetting setting = val.GetSetting<ControllerSensitivitySetting>();
					if (setting != null)
					{
						return ((FloatSetting)setting).Value;
					}
				}
				else
				{
					MouseSensitivitySetting setting2 = val.GetSetting<MouseSensitivitySetting>();
					if (setting2 != null)
					{
						return ((FloatSetting)setting2).Value;
					}
				}
			}
			catch
			{
			}
			return 2f;
		}

		private static int GetInvertSign(bool isY)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SettingsHandler val = (((Object)(object)GameHandler.Instance != (Object)null) ? GameHandler.Instance.SettingsHandler : null);
				if (val == null)
				{
					return 1;
				}
				if (isY)
				{
					InvertYSetting setting = val.GetSetting<InvertYSetting>();
					if (setting != null)
					{
						return ((int)((EnumSetting<OffOnMode>)(object)setting).Value == 0) ? 1 : (-1);
					}
				}
				else
				{
					InvertXSetting setting2 = val.GetSetting<InvertXSetting>();
					if (setting2 != null)
					{
						return ((int)((EnumSetting<OffOnMode>)(object)setting2).Value == 0) ? 1 : (-1);
					}
				}
			}
			catch
			{
			}
			return 1;
		}

		private void SyncCharacterLookFromFreeFly(Transform camTransform)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter?.data == (Object)null || (Object)(object)camTransform == (Object)null)
			{
				return;
			}
			localCharacter.data.lookValues = _lookData;
			Vector3 forward = camTransform.forward;
			if (!(((Vector3)(ref forward)).sqrMagnitude < 0.0001f))
			{
				((Vector3)(ref forward)).Normalize();
				localCharacter.data.lookDirection = forward;
				Vector3 lookDirection_Flat = HelperFunctions.ZeroY(forward);
				if (((Vector3)(ref lookDirection_Flat)).sqrMagnitude > 0.0001f)
				{
					((Vector3)(ref lookDirection_Flat)).Normalize();
					localCharacter.data.lookDirection_Flat = lookDirection_Flat;
					CharacterData data = localCharacter.data;
					Vector3 val = Vector3.Cross(Vector3.up, forward);
					data.lookDirection_Right = ((Vector3)(ref val)).normalized;
					CharacterData data2 = localCharacter.data;
					val = Vector3.Cross(forward, localCharacter.data.lookDirection_Right);
					data2.lookDirection_Up = ((Vector3)(ref val)).normalized;
				}
			}
		}

		private static bool CanEnterFreeFly()
		{
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || !localCharacter.data.fullyPassedOut)
			{
				return false;
			}
			if (IsSoloPlay())
			{
				return true;
			}
			return localCharacter.data.dead;
		}

		private static bool CanStayInFreeFly()
		{
			return CanEnterFreeFly();
		}

		internal static bool IsSoloPlay()
		{
			try
			{
				if (PhotonNetwork.OfflineMode)
				{
					return true;
				}
				if (!PhotonNetwork.InRoom)
				{
					return true;
				}
				Player[] playerList = PhotonNetwork.PlayerList;
				if (playerList == null || playerList.Length == 0)
				{
					return true;
				}
				int num = 0;
				foreach (Player val in playerList)
				{
					if (val != null && !val.IsInactive)
					{
						num++;
					}
				}
				return num <= 1;
			}
			catch
			{
				return true;
			}
		}

		private static void TryShowFreeFlyBlockedTip()
		{
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter?.data == (Object)null) && localCharacter.data.fullyPassedOut && !IsSoloPlay() && !localCharacter.data.dead)
			{
				GhostItemHaulToast.Show("Multiplayer: free-fly unlocks only after you fully die", "多人模式:昏迷中不能灵魂离体,完全死亡后才能按 F3", 2.8f);
			}
		}

		private void SyncLookFromCamera(MainCameraMovement movement)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)movement).transform;
			_lookData = Vector2.op_Implicit(HelperFunctions.DirectionToLook(transform.forward));
			LookDataField?.SetValue(movement.godcam, _lookData);
			LookVelField?.SetValue(movement.godcam, Vector2.zero);
			VelField?.SetValue(movement.godcam, Vector3.zero);
		}

		private static void RestoreSpecTarget(Character target)
		{
			if ((Object)(object)target == (Object)null || (Object)(object)((Component)target).gameObject == (Object)null || !((Component)target).gameObject.activeInHierarchy)
			{
				return;
			}
			try
			{
				if (!target.data.canBeSpectated)
				{
					return;
				}
			}
			catch
			{
				return;
			}
			SpecCharacterSetter?.Invoke(null, new object[1] { target });
		}
	}
	internal static class GameL10n
	{
		internal static bool UseChinese
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Invalid comparison between Unknown and I4
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				Language cURRENT_LANGUAGE = LocalizedText.CURRENT_LANGUAGE;
				if ((int)cURRENT_LANGUAGE != 9)
				{
					return (int)cURRENT_LANGUAGE == 10;
				}
				return true;
			}
		}

		internal static string Pick(string english, string chinese)
		{
			if (!UseChinese)
			{
				return english;
			}
			return chinese;
		}
	}
	internal static class GhostBackpackPatches
	{
		private const byte TempHoldSlot = 250;

		private static readonly MethodInfo DoInteractionMethod = AccessTools.Method(typeof(Interaction), "DoInteraction", new Type[1] { typeof(IInteractible) }, (Type[])null);

		private static readonly MethodInfo CancelHeldInteractMethod = AccessTools.Method(typeof(Interaction), "CancelHeldInteract", (Type[])null, (Type[])null);

		private static readonly object[] DoInteractionArgs = new object[1];

		private static readonly Collider[] OverlapBuffer = (Collider[])(object)new Collider[48];

		private static readonly Type BugBagType = AccessTools.TypeByName("BugBag");

		private static bool GhostMode
		{
			get
			{
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null)
				{
					return localCharacter.data.fullyPassedOut;
				}
				return false;
			}
		}

		private static bool FeatureEnabled
		{
			get
			{
				if (Configuration.EnableGhostBackpack.Value)
				{
					return GhostMode;
				}
				return false;
			}
		}

		private static bool GhostInteractionEnabled
		{
			get
			{
				if (GhostMode)
				{
					if (!Configuration.EnableGhostBackpack.Value && !Configuration.EnableGhostHaul.Value)
					{
						return GhostFeedPatches.GhostCanFeed;
					}
					return true;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Interaction), "LateUpdate")]
		[HarmonyPrefix]
		private static bool InteractionLateUpdatePrefix(Interaction __instance)
		{
			if (!GhostInteractionEnabled)
			{
				return true;
			}
			GhostFeedPatches.SyncGhostLookFromCamera();
			GhostFeedPatches.SampleGhostUseInputs(Character.localCharacter.input);
			__instance.currentHovered = null;
			__instance.bestInteractable = null;
			__instance.bestCharacter = null;
			IInteractible result = null;
			CharacterInteractible result2 = null;
			if (!Configuration.EnableGhostHaul.Value || !TryFindSkeletonRevive(out result))
			{
				if (GhostFeedPatches.GhostCanFeed && (TryFindFeedCharacter(out result2) || GhostFeedPatches.TryStickSoloSelfFeed(out result2)))
				{
					result = (IInteractible)(object)result2;
				}
				else if ((!Configuration.EnableGhostHaul.Value || !TryFindStuckRemovable(out result)) && (!Configuration.EnableGhostBackpack.Value || !TryFindBackpackInteractable(out result)) && Configuration.EnableGhostHaul.Value)
				{
					TryFindHaulItemInteractable(out result);
				}
			}
			if (result == null)
			{
				ClearHeldInteract(__instance);
				return false;
			}
			__instance.bestInteractable = result;
			__instance.bestCharacter = result2;
			if (DoInteractionMethod != null)
			{
				DoInteractionArgs[0] = result;
				DoInteractionMethod.Invoke(__instance, DoInteractionArgs);
				DoInteractionArgs[0] = null;
			}
			__instance.currentHovered = result;
			__instance.bestInteractableName = (((Object)(object)result.GetTransform() != (Object)null) ? ((Object)((Component)result.GetTransform()).gameObject).name : "ghost-interact");
			return false;
		}

		private static bool TryFindSkeletonRevive(out IInteractible result)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_00af: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			result = null;
			MainCamera instance = MainCamera.instance;
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)instance == (Object)null || (Object)(object)localCharacter == (Object)null || (Object)(object)Interaction.instance == (Object)null || !IsHoldingBookOfBones(localCharacter))
			{
				return false;
			}
			float num = Interaction.instance.distance + 1.5f;
			Ray val = new Ray(((Component)instance).transform.position, ((Component)instance).transform.forward);
			IInteractible val2 = null;
			float num2 = num;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val, ref val3, num2, -1, (QueryTriggerInteraction)2) && TryGetSkeletonRevive(((RaycastHit)(ref val3)).collider, localCharacter, out var interactable))
			{
				val2 = interactable;
				num2 = ((RaycastHit)(ref val3)).distance;
			}
			if (val2 != null && num2 <= Interaction.instance.distance)
			{
				result = val2;
				return true;
			}
			int num3 = Physics.OverlapSphereNonAlloc(((Component)instance).transform.position + ((Component)instance).transform.forward * 1f, 1.75f, OverlapBuffer, -1, (QueryTriggerInteraction)2);
			for (int i = 0; i < num3; i++)
			{
				if (TryGetSkeletonRevive(OverlapBuffer[i], localCharacter, out var interactable2) && !((Object)(object)interactable2.GetTransform() == (Object)null))
				{
					Vector3 val4 = interactable2.Center() - ((Component)instance).transform.position;
					float magnitude = ((Vector3)(ref val4)).magnitude;
					if (!(magnitude >= num2) && !(Vector3.Angle(((Component)instance).transform.forward, val4) > 50f))
					{
						val2 = interactable2;
						num2 = magnitude;
					}
				}
			}
			result = val2;
			return val2 != null;
		}

		private static bool TryGetSkeletonRevive(Collider col, Character local, out IInteractible interactable)
		{
			interactable = null;
			if ((Object)(object)col == (Object)null)
			{
				return false;
			}
			Skelleton componentInParent = ((Component)col).GetComponentInParent<Skelleton>();
			if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsInteractible(local))
			{
				return false;
			}
			interactable = (IInteractible)(object)componentInParent;
			return true;
		}

		internal static bool IsHoldingBookOfBones(Character character)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterData data = character.data;
				obj = ((data != null) ? data.currentItem : null);
			}
			Item val = (Item)obj;
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
			{
				return false;
			}
			bool flag = false;
			try
			{
				flag = ((Component)val).gameObject.CompareTag("BookOfBones") || ((Enum)val.itemTags).HasFlag((Enum)(object)(ItemTags)256);
			}
			catch
			{
				try
				{
					flag = ((Component)val).gameObject.CompareTag("BookOfBones");
				}
				catch
				{
					return false;
				}
			}
			if (!flag)
			{
				return false;
			}
			try
			{
				OptionableIntItemData data2 = val.GetData<OptionableIntItemData>((DataEntryKey)2);
				return data2 != null && data2.Value > 0;
			}
			catch
			{
				return true;
			}
		}

		[HarmonyPatch(typeof(Skelleton), "Interact_CastFinished")]
		[HarmonyPrefix]
		private static void SkeletonReviveCastPrefix(Character interactor)
		{
			GhostBookOfBonesConsume.ConsumeBeforeSkeletonRevive(interactor);
		}

		internal static bool IsBookOfBonesItemPublic(Item item)
		{
			return IsBookOfBonesItem(item);
		}

		private static bool IsBookOfBonesItem(Item item)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null)
			{
				return false;
			}
			try
			{
				if (((Component)item).gameObject.CompareTag("BookOfBones"))
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				return ((Enum)item.itemTags).HasFlag((Enum)(object)(ItemTags)256);
			}
			catch
			{
				return false;
			}
		}

		private static bool TryFindStuckRemovable(out IInteractible result)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			result = null;
			MainCamera instance = MainCamera.instance;
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)instance == (Object)null || (Object)(object)localCharacter == (Object)null || (Object)(object)Interaction.instance == (Object)null)
			{
				return false;
			}
			float num = Interaction.instance.distance + 1.5f;
			Ray val = new Ray(((Component)instance).transform.position, ((Component)instance).transform.forward);
			IInteractible val2 = null;
			float num2 = num;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val, ref val3, num2, -1, (QueryTriggerInteraction)2) && TryGetStuckRemovable(((RaycastHit)(ref val3)).collider, localCharacter, out var interactable))
			{
				val2 = interactable;
				num2 = ((RaycastHit)(ref val3)).distance;
			}
			if (val2 != null && num2 <= Interaction.instance.distance)
			{
				result = val2;
				return true;
			}
			int num3 = Physics.OverlapSphereNonAlloc(((Component)instance).transform.position + ((Component)instance).transform.forward * 1f, 1.35f, OverlapBuffer, -1, (QueryTriggerInteraction)2);
			for (int i = 0; i < num3; i++)
			{
				if (!TryGetStuckRemovable(OverlapBuffer[i], localCharacter, out var interactable2))
				{
					continue;
				}
				Transform transform = interactable2.GetTransform();
				if (!((Object)(object)transform == (Object)null))
				{
					Vector3 val4 = transform.position - ((Component)instance).transform.position;
					float magnitude = ((Vector3)(ref val4)).magnitude;
					if (!(magnitude >= num2) && !(Vector3.Angle(((Component)instance).transform.forward, val4) > 45f))
					{
						val2 = interactable2;
						num2 = magnitude;
					}
				}
			}
			result = val2;
			return val2 != null;
		}

		private static bool TryGetStuckRemovable(Collider col, Character local, out IInteractible interactable)
		{
			interactable = null;
			if ((Object)(object)col == (Object)null)
			{
				return false;
			}
			ThornOnMe componentInParent = ((Component)col).GetComponentInParent<ThornOnMe>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.IsInteractible(local))
			{
				interactable = (IInteractible)(object)componentInParent;
				return true;
			}
			if (BugBagType != null)
			{
				Component componentInParent2 = ((Component)col).GetComponentInParent(BugBagType);
				IInteractible val = (IInteractible)(object)((componentInParent2 is IInteractible) ? componentInParent2 : null);
				if (val != null && val.IsInteractible(local))
				{
					interactable = val;
					return true;
				}
			}
			return false;
		}

		private static bool TryFindHaulItemInteractable(out IInteractible result)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			result = null;
			MainCamera instance = MainCamera.instance;
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)instance == (Object)null || (Object)(object)localCharacter == (Object)null || (Object)(object)Interaction.instance == (Object)null)
			{
				return false;
			}
			if ((Object)(object)localCharacter.data != (Object)null && (Object)(object)localCharacter.data.currentItem != (Object)null)
			{
				return false;
			}
			if ((Object)(object)localCharacter.player != (Object)null && !localCharacter.player.tempFullSlot.IsEmpty())
			{
				return false;
			}
			float num = Interaction.instance.distance + 1.5f;
			Ray val = new Ray(((Component)instance).transform.position, ((Component)instance).transform.forward);
			Item val2 = null;
			float num2 = num;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val, ref val3, num2, -1, (QueryTriggerInteraction)2))
			{
				Item val4 = (((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Item>() : null);
				if (IsGhostHaulInteractable(val4, localCharacter))
				{
					val2 = val4;
					num2 = ((RaycastHit)(ref val3)).distance;
				}
			}
			if ((Object)(object)val2 != (Object)null && num2 <= Interaction.instance.distance)
			{
				result = (IInteractible)(object)val2;
				return true;
			}
			int num3 = Physics.OverlapSphereNonAlloc(((Component)instance).transform.position + ((Component)instance).transform.forward * 1f, 1.35f, OverlapBuffer, -1, (QueryTriggerInteraction)2);
			for (int i = 0; i < num3; i++)
			{
				Item val5 = (((Object)(object)OverlapBuffer[i] != (Object)null) ? ((Component)OverlapBuffer[i]).GetComponentInParent<Item>() : null);
				if (IsGhostHaulInteractable(val5, localCharacter))
				{
					Vector3 val6 = ((Component)val5).transform.position - ((Component)instance).transform.position;
					float magnitude = ((Vector3)(ref val6)).magnitude;
					if (!(magnitude >= num2) && !(Vector3.Angle(((Component)instance).transform.forward, val6) > 40f))
					{
						val2 = val5;
						num2 = magnitude;
					}
				}
			}
			result = (IInteractible)(object)val2;
			return (Object)(object)val2 != (Object)null;
		}

		private static bool IsGhostHaulInteractable(Item item, Character local)
		{
			if ((Object)(object)item == (Object)null || !GhostItemHaul.IsHaulCandidate(item) || !GhostItemHaul.IsWithinWeightLimit(item))
			{
				return false;
			}
			try
			{
				return item.IsInteractible(local);
			}
			catch
			{
				return false;
			}
		}

		private static bool TryFindFeedCharacter(out CharacterInteractible result)
		{
			//IL_0041: 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)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			result = null;
			MainCamera instance = MainCamera.instance;
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)instance == (Object)null || (Object)(object)localCharacter == (Object)null || (Object)(object)Interaction.instance == (Object)null)
			{
				return false;
			}
			float distance = Interaction.instance.distance;
			Ray val = new Ray(((Component)instance).transform.position, ((Component)instance).transform.forward);
			CharacterInteractible val2 = null;
			float num = distance + 1.5f;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val, ref val3, num, -1, (QueryTriggerInteraction)2))
			{
				CharacterInteractible val4 = (((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<CharacterInteractible>() : null);
				if ((Object)(object)val4 != (Object)null && GhostFeedPatches.IsValidGhostFeedTarget(val4, localCharacter))
				{
					val2 = val4;
					num = ((RaycastHit)(ref val3)).distance;
				}
			}
			if ((Object)(object)val2 != (Object)null && num <= distance)
			{
				result = val2;
				return true;
			}
			int num2 = Physics.OverlapSphereNonAlloc(((Component)instance).transform.position + ((Component)instance).transform.forward * 1f, 1.35f, OverlapBuffer, -1, (QueryTriggerInteraction)2);
			for (int i = 0; i < num2; i++)
			{
				CharacterInteractible val5 = (((Object)(object)OverlapBuffer[i] != (Object)null) ? ((Component)OverlapBuffer[i]).GetComponentInParent<CharacterInteractible>() : null);
				if (!((Object)(object)val5 == (Object)null) && GhostFeedPatches.IsValidGhostFeedTarget(val5, localCharacter))
				{
					Vector3 val6 = val5.Center() - ((Component)instance).transform.position;
					float magnitude = ((Vector3)(ref val6)).magnitude;
					if (!(magnitude >= num) && !(Vector3.Angle(((Component)instance).transform.forward, val6) > 40f))
					{
						val2 = val5;
						num = magnitude;
					}
				}
			}
			result = val2;
			return (Object)(object)val2 != (Object)null;
		}

		[HarmonyPatch(typeof(Player), "AddItem")]
		[HarmonyPrefix]
		private static bool AddItemPrefix(Player __instance, ushort itemID, ItemInstanceData instanceData, out ItemSlot slot, ref bool __result)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			slot = null;
			Character character = __instance.character;
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.fullyPassedOut)
			{
				return true;
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				Debug.LogError((object)"Only Master Client can add items!");
				__result = false;
				return false;
			}
			ItemInstanceData val = instanceData;
			if (val == null)
			{
				val = new ItemInstanceData(Guid.NewGuid());
				ItemInstanceDataHandler.AddInstanceData(val);
			}
			Item val2 = default(Item);
			if (!ItemDatabase.TryGetItem(itemID, ref val2))
			{
				__result = false;
				return false;
			}
			if (val2 is Backpack)
			{
				__result = false;
				return false;
			}
			if (!__instance.tempFullSlot.IsEmpty() || character.data.isClimbingAnything)
			{
				__result = false;
				return false;
			}
			__instance.tempFullSlot.SetItem(val2, val);
			slot = __instance.tempFullSlot;
			byte[] array = IBinarySerializable.ToManagedArray<InventorySyncData>(new InventorySyncData(__instance.itemSlots, __instance.backpackSlot, __instance.tempFullSlot));
			__instance.view.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { array, false });
			__result = true;
			return false;
		}

		[HarmonyPatch(typeof(BackpackWheel), "Choose")]
		[HarmonyPrefix]
		private static bool ChoosePrefix(BackpackWheel __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (!GhostMode || !Configuration.EnableGhostBackpack.Value)
			{
				return true;
			}
			if (!__instance.chosenSlice.IsSome)
			{
				return true;
			}
			SliceData value = __instance.chosenSlice.Value;
			if (value.isBackpackWear)
			{
				return true;
			}
			ItemSlot val = ((BackpackReference)(ref __instance.backpack)).GetData().itemSlots[value.slotID];
			if (value.isStashSlice || val == null || val.IsEmpty() || !((Object)(object)Character.localCharacter.data.currentItem == (Object)null))
			{
				if (!value.isStashSlice && val != null && !val.IsEmpty() && (!Character.localCharacter.player.tempFullSlot.IsEmpty() || (Object)(object)Character.localCharacter.data.currentItem != (Object)null))
				{
					GhostItemHaulToast.Show("Ghosts can only hold one item", "幽灵同时只能持有一件物品");
					return false;
				}
				return true;
			}
			if (!Character.localCharacter.player.tempFullSlot.IsEmpty())
			{
				GhostItemHaulToast.Show("Ghosts can only hold one item", "幽灵同时只能持有一件物品");
				return false;
			}
			Item prefab = val.prefab;
			if (!GhostItemHaul.IsWithinWeightLimit(prefab))
			{
				GhostItemHaul.ShowTooHeavyToast(prefab);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Backpack), "Wear")]
		[HarmonyPrefix]
		private static bool WearPrefix(Character interactor)
		{
			if ((Object)(object)interactor != (Object)null && (Object)(object)interactor.data != (Object)null && interactor.data.fullyPassedOut)
			{
				GhostItemHaulToast.Show("Ghosts cannot wear backpacks", "幽灵不能背起背包");
				return false;
			}
			return true;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void WearSliceInteractPostfix(BackpackWheelSlice __instance, ref bool __result)
		{
			if (__result && __instance.isBackpackWear && GhostMode)
			{
				__result = false;
			}
		}

		[HarmonyPatch(typeof(BackpackOnBackVisuals), "IsInteractible")]
		[HarmonyPrefix]
		private static bool WornBackpackInteractiblePrefix(BackpackOnBackVisuals __instance, Character interactor, ref bool __result)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_004a: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!FeatureEnabled || (Object)(object)interactor == (Object)null || !interactor.IsLocal)
			{
				return true;
			}
			MainCamera instance = MainCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				__result = false;
				return false;
			}
			Vector3 val = HelperFunctions.ZeroY(((Component)instance).transform.forward);
			Vector3 val2 = HelperFunctions.ZeroY(((Component)__instance).transform.forward);
			__result = Vector3.Angle(val, val2) < 110f;
			return false;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void CenterPostfix(Character __instance, ref Vector3 __result)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)null) && __instance.IsLocal && !((Object)(object)__instance.data == (Object)null) && __instance.data.fullyPassedOut && __instance.data.usingBackpackWheel)
			{
				__result = NameAnchor.GetViewerPosition();
			}
		}

		[HarmonyPatch(typeof(CharacterItems), "GetItemHoldPos")]
		[HarmonyPostfix]
		private static void HoldPosPostfix(CharacterItems __instance, Item item, bool pushOffTerrain, ref Vector3 __result)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetGhostHoldPose(__instance.character, out var position, out var _))
			{
				__result = position;
			}
		}

		[HarmonyPatch(typeof(CharacterItems), "AttachItem")]
		[HarmonyPrefix]
		private static bool AttachItemPrefix(CharacterItems __instance)
		{
			Character character = __instance.character;
			if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null))
			{
				return !character.data.fullyPassedOut;
			}
			return true;
		}

		[HarmonyPatch(typeof(CharacterItems), "HoldItem")]
		[HarmonyPrefix]
		private static bool HoldItemPrefix(CharacterItems __instance, Item item)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			Character character = __instance.character;
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.fullyPassedOut || (Object)(object)item == (Object)null)
			{
				return true;
			}
			if (!TryGetGhostHoldPose(character, out var position, out var rotation))
			{
				return true;
			}
			DetachGhostHandJoints(character);
			EnsureGhostHeldItemVisible(item);
			EnsureGhostHeldItemNonSolid(item);
			Vector3 position2 = ((Component)item).transform.position;
			bool flag = character.IsLocal && FreeSpectatorController.Instance != null && FreeSpectatorController.Instance.IsActive;
			if (character.IsLocal && !flag)
			{
				HardSnapGhostHeldItem(item, position, rotation);
			}
			else
			{
				SnapGhostHeldItem(item, position, rotation);
			}
			bool flag2 = false;
			try
			{
				flag2 = (Object)(object)((MonoBehaviourPun)item).photonView != (Object)null && ((MonoBehaviourPun)item).photonView.IsMine;
			}
			catch
			{
				flag2 = character.IsLocal;
			}
			if (flag2)
			{
				float num = Vector3.Distance(position2, position);
				if (num > 2f || Time.frameCount % 6 == 0)
				{
					try
					{
						item.ForceSyncForFrames((num > 8f) ? 20 : 8);
					}
					catch
					{
					}
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(PlayerGhost), "Update")]
		[HarmonyPostfix]
		private static void SnapHeldItemAfterGhostUpdate(PlayerGhost __instance)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			Character val = (((Object)(object)__instance != (Object)null) ? __instance.m_owner : null);
			if (!((Object)(object)val == (Object)null) && val.IsLocal && !((Object)(object)val.data == (Object)null) && val.data.fullyPassedOut && (FreeSpectatorController.Instance == null || !FreeSpectatorController.Instance.IsActive))
			{
				Item currentItem = val.data.currentItem;
				if (!((Object)(object)currentItem == (Object)null) && TryGetGhostHoldPose(val, out var position, out var rotation))
				{
					EnsureGhostHeldItemVisible(currentItem);
					EnsureGhostHeldItemNonSolid(currentItem);
					HardSnapGhostHeldItem(currentItem, position, rotation);
				}
			}
		}

		private static void SnapGhostHeldItem(Item item, Vector3 pos, Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				item.Move(pos, rot);
			}
			catch
			{
			}
			HardSnapGhostHeldItem(item, pos, rot);
		}

		private static void HardSnapGhostHeldItem(Item item, Vector3 pos, Quaternion rot)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				((Component)item).transform.SetPositionAndRotation(pos, rot);
				if ((Object)(object)item.rig != (Object)null)
				{
					item.rig.interpolation = (RigidbodyInterpolation)0;
					item.rig.isKinematic = true;
					item.rig.detectCollisions = false;
					item.rig.useGravity = false;
					item.rig.position = pos;
					item.rig.rotation = rot;
					item.rig.linearVelocity = Vector3.zero;
					item.rig.angularVelocity = Vector3.zero;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(CharacterItems), "AddGravity")]
		[HarmonyPrefix]
		private static bool SkipGhostItemGravity(CharacterItems __instance)
		{
			return !IsGhostHolding(__instance);
		}

		[HarmonyPatch(typeof(CharacterItems), "AddMovementForce")]
		[HarmonyPrefix]
		private static bool SkipGhostItemMoveForce(CharacterItems __instance)
		{
			return !IsGhostHolding(__instance);
		}

		[HarmonyPatch(typeof(CharacterItems), "AddDrag")]
		[HarmonyPrefix]
		private static bool SkipGhostItemDrag(CharacterItems __instance)
		{
			return !IsGhostHolding(__instance);
		}

		private static bool IsGhostHolding(CharacterItems items)
		{
			Character val = (((Object)(object)items != (Object)null) ? items.character : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null && val.data.fullyPassedOut)
			{
				return (Object)(object)val.data.currentItem != (Object)null;
			}
			return false;
		}

		private static void EnsureGhostHeldItemNonSolid(Item item)
		{
			//IL_0043: 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)
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			try
			{
				if ((Object)(object)item.rig != (Object)null)
				{
					item.rig.isKinematic = true;
					item.rig.detectCollisions = false;
					item.rig.useGravity = false;
					item.rig.linearVelocity = Vector3.zero;
					item.rig.angularVelocity = Vector3.zero;
				}
			}
			catch
			{
			}
			try
			{
				Collider[] colliders = item.colliders;
				if (colliders == null)
				{
					return;
				}
				for (int i = 0; i < colliders.Length; i++)
				{
					if ((Object)(object)colliders[i] != (Object)null)
					{
						colliders[i].enabled = false;
					}
				}
			}
			catch
			{
			}
		}

		internal static bool TryGetGhostHoldPosePublic(Character character, out Vector3 position, out Quaternion rotation)
		{
			return TryGetGhostHoldPose(character, out position, out rotation);
		}

		private static bool TryGetGhostHoldPose(Character character, out Vector3 position, out Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			rotation = Quaternion.identity;
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.fullyPassedOut)
			{
				return false;
			}
			if ((Object)(object)character.data.currentItem == (Object)null && ((Object)(object)character.refs?.items == (Object)null || !character.refs.items.currentSelectedSlot.IsSome))
			{
				return false;
			}
			if (character.IsLocal && (Object)(object)MainCamera.instance != (Object)null)
			{
				Transform transform = ((Component)MainCamera.instance).transform;
				position = transform.position + transform.forward * 0.85f + transform.right * 0.28f + transform.up * -0.22f;
				rotation = transform.rotation;
				return true;
			}
			PlayerGhost ghost = character.Ghost;
			if ((Object)(object)ghost != (Object)null && (Object)(object)((Component)ghost).gameObject != (Object)null && ((Component)ghost).gameObject.activeInHierarchy)
			{
				Transform transform2 = ((Component)ghost).transform;
				position = transform2.TransformPoint(new Vector3(0.22f, 0.08f, 0.32f));
				Vector3 forward = transform2.forward;
				forward.y = 0f;
				if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
				{
					forward = Vector3.forward;
				}
				rotation = Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up);
				return true;
			}
			Vector3 ghostFeetPosition = NameAnchor.GetGhostFeetPosition(character);
			Vector3 val = character.data.lookDirection;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.forward;
			}
			((Vector3)(ref val)).Normalize();
			position = ghostFeetPosition + val * 0.75f + Vector3.up * 0.45f;
			rotation = Quaternion.LookRotation(val, Vector3.up);
			return true;
		}

		internal static void EnsureGhostHeldItemVisible(Item item)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			Character val = item.holderCharacter;
			if ((Object)(object)val == (Object)null)
			{
				val = (((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data != (Object)null && (Object)(object)Character.localCharacter.data.currentItem == (Object)(object)item) ? Character.localCharacter : null);
			}
			if (GhostHeldVisualProxy.ShouldHideRealHeldMesh(val, item))
			{
				GhostHeldVisualProxy.SetRenderersEnabled(item, enabled: false);
				return;
			}
			try
			{
				if (!((Component)item).gameObject.activeSelf)
				{
					((Component)item).gameObject.SetActive(true);
				}
				GhostHeldVisualProxy.SetRenderersEnabled(item, enabled: true);
				if (item.forceScale)
				{
					((Component)item).transform.localScale = Vector3.one;
				}
			}
			catch
			{
			}
		}

		private static void DetachGhostHandJoints(Character character)
		{
			DestroyHandJoint(character, (BodypartType)7);
			DestroyHandJoint(character, (BodypartType)10);
		}

		private static void DestroyHandJoint(Character character, BodypartType part)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Rigidbody bodypartRig = character.GetBodypartRig(part);
				FixedJoint val = default(FixedJoint);
				if ((Object)(object)bodypartRig != (Object)null && ((Component)bodypartRig).gameObject.TryGetComponent<FixedJoint>(ref val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(Item), "IsInteractible")]
		[HarmonyPostfix]
		private static void GhostProxyNotInteractible(Item __instance, ref bool __result)
		{
			if (!__result || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)((Component)__instance).GetComponent<GhostHeldVisualProxyMarker>() != (Object)null)
			{
				__result = false;
				return;
			}
			try
			{
				if ((Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && GhostHeldVisualProxy.IsProxyView(((MonoBehaviourPun)__instance).photonView.ViewID))
				{
					__result = false;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(Item), "RequestPickup")]
		[HarmonyPrefix]
		private static bool GhostProxyDenyPickup(Item __instance, PhotonView characterView)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			bool flag = (Object)(object)((Component)__instance).GetComponent<GhostHeldVisualProxyMarker>() != (Object)null;
			if (!flag)
			{
				try
				{
					flag = (Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && GhostHeldVisualProxy.IsProxyView(((MonoBehaviourPun)__instance).photonView.ViewID);
				}
				catch
				{
					flag = false;
				}
			}
			if (!flag)
			{
				return true;
			}
			try
			{
				if ((Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && (Object)(object)characterView != (Object)null)
				{
					((MonoBehaviourPun)__instance).photonView.RPC("DenyPickupRPC", characterView.Owner, Array.Empty<object>());
				}
			}
			catch
			{
			}
			return false;
		}

		[HarmonyPatch(typeof(CharacterItems), "DropItemRpc")]
		[HarmonyPrefix]
		private static void DropItemRpcPrefix(CharacterItems __instance, float throwCharge, ref Vector3 spawnPos)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			Character character = __instance.character;
			if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null) && character.data.fullyPassedOut)
			{
				if (character.IsLocal)
				{
					GhostFeedPatches.SyncGhostLookFromCamera();
				}
				if (TryGetGhostHoldPose(character, out var position, out var _))
				{
					spawnPos = position;
				}
				else
				{
					spawnPos = NameAnchor.GetGhostFeetPosition(character) + Vector3.up * 0.4f;
				}
			}
		}

		private static void ClearHeldInteract(Interaction interaction)
		{
			if (!Character.localCharacter.input.interactIsPressed)
			{
				interaction.readyToInteract = true;
				CancelHeldInteractMethod?.Invoke(interaction, null);
			}
		}

		private static bool TryFindBackpackInteractable(out IInteractible result)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			result = null;
			MainCamera instance = MainCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			float num = (((Object)(object)Interaction.instance != (Object)null) ? Interaction.instance.distance : 2.5f);
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Ray(((Component)instance).transform.position, ((Component)instance).transform.forward), ref val, num + 1.5f, -1, (QueryTriggerInteraction)2) && TryGetBackpackInteractable(((RaycastHit)(ref val)).collider, out result))
			{
				return true;
			}
			int num2 = Physics.OverlapSphereNonAlloc(((Component)instance).transform.position + ((Component)instance).transform.forward * 1.2f, 1.25f, OverlapBuffer, -1, (QueryTriggerInteraction)2);
			float num3 = 40f;
			IInteractible val2 = null;
			for (int i = 0; i < num2; i++)
			{
				if (TryGetBackpackInteractable(OverlapBuffer[i], out var interactable))
				{
					Vector3 val3 = interactable.Center() - ((Component)instance).transform.position;
					float num4 = Vector3.Angle(((Component)instance).transform.forward, val3);
					if (num4 < num3 && ((Vector3)(ref val3)).magnitude <= num + 2f)
					{
						num3 = num4;
						val2 = interactable;
					}
				}
			}
			result = val2;
			return val2 != null;
		}

		private static bool TryGetBackpackInteractable(Collider col, out IInteractible interactable)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			interactable = null;
			if ((Object)(object)col == (Object)null)
			{
				return false;
			}
			Backpack componentInParent = ((Component)col).GetComponentInParent<Backpack>();
			if ((Object)(object)componentInParent != (Object)null && (int)((Item)componentInParent).itemState == 0 && ((Item)componentInParent).IsInteractible(Character.localCharacter))
			{
				interactable = (IInteractible)(object)componentInParent;
				return true;
			}
			BackpackOnBackVisuals componentInParent2 = ((Component)col).GetComponentInParent<BackpackOnBackVisuals>();
			if ((Object)(object)componentInParent2 != (Object)null && componentInParent2.IsInteractible(Character.localCharacter))
			{
				interactable = (IInteractible)(object)componentInParent2;
				return true;
			}
			return false;
		}
	}
	internal sealed class GhostBookOfBonesConsume : MonoBehaviour, IOnEventCallback
	{
		internal const byte EventCode = 178;

		private static GhostBookOfBonesConsume _instance;

		private static bool _skipNextReduceUses;

		internal static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("SymbioticGhost_BookOfBonesConsume");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<GhostBookOfBonesConsume>();
			}
		}

		private void OnEnable()
		{
			PhotonNetwo