Decompiled source of SymbioticGhost v1.5.7

plugins/SymbioticGhost.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 TMPro;
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.5.7.0")]
[assembly: AssemblyInformationalVersion("1.5.7")]
[assembly: AssemblyProduct("SymbioticGhost")]
[assembly: AssemblyTitle("SymbioticGhost")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.7.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> LeashCountdownSeconds;

		internal static ConfigEntry<bool> EnableNames;

		internal static ConfigEntry<float> NameVisibleAngle;

		internal static ConfigEntry<bool> DisplayWhenBlind;

		internal static ConfigEntry<bool> ShowNameDistance;

		internal static ConfigEntry<KeyboardShortcut> NameDisplayToggle;

		internal static ConfigEntry<float> NameDisplayDuration;

		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 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Expected O, but got Unknown
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Expected O, but got Unknown
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Expected O, but got Unknown
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Expected O, but got Unknown
			ToggleKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Free Fly Toggle 自由飞行开关", (KeyCode)284, "EN: Solo — free-fly while passed out. Multiplayer — only after fully dead.\n中文:单人 — 昏迷即可灵魂离体;多人 — 须完全死亡后才能按 F3 离体。");
			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 countdown starts.\n中文:超过与寄宿玩家的该直线距离后开始倒计时。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			LeashCountdownSeconds = config.Bind<float>("3. Symbiosis 共生", "Leash Countdown 寄宿倒计时秒数", 30f, new ConfigDescription("EN: Seconds before free-fly is forced off when out of leash range.\n中文:超出寄宿距离后,多少秒强制退出自由飞行。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			EnableNames = config.Bind<bool>("4. Player Names 队友名字", "Enable Names 启用名字显示", true, "EN: Show teammate names when looking toward them.\n中文:看向队友时显示名字。");
			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中文:在名字下方显示距离。");
			NameDisplayToggle = config.Bind<KeyboardShortcut>("4. Player Names 队友名字", "Name Display Toggle 名字显示开关", new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>()), "EN: Hotkey to toggle name display.\n中文:切换队友名字显示的热键。");
			NameDisplayDuration = config.Bind<float>("4. Player Names 队友名字", "Name Display Duration 名字显示秒数", 0f, new ConfigDescription("EN: Seconds names stay on after toggle; 0 = sticky on/off.\n中文:按下开关后名字保持显示的秒数;0 表示手动开关直至再按。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			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, and show no-LOS pings.\n中文:死亡/昏厥时也可标记,并显示无视线标记。");
			EnableGhostHaul = config.Bind<bool>("7. Ghost Haul 幽灵搬运", "Enable Ghost Haul 启用幽灵搬运", true, "EN: When every player has this mod, ghosts may haul light ground items and use feedable items on teammates.\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: Pick up / drop while spectating as a ghost.\n中文:幽灵状态下提起或放下物品的按键。");
			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: Show markers for passed-out / dead bodies (incl. your own so ghosts can find their corpse).\n中文:显示昏厥/死亡位置指示(含自己的尸体,方便幽灵找回身体)。");
			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>()));
		}
	}
	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>();

		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()
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
				_canvas = null;
			}
			_template = null;
			_instances.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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvas != (Object)null))
			{
				_instances.Clear();
				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();
				}
				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 (!_instances.TryGetValue(character, out var value) || (Object)(object)value == (Object)null)
			{
				if (isDead)
				{
					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();
			float num = Mathf.Max(0f, Configuration.DeadCorpseMarkerMinutes.Value) * 60f;
			_instances.Remove(character);
			if (num <= 0.01f)
			{
				Object.Destroy((Object)(object)instance);
			}
			else
			{
				Object.Destroy((Object)(object)instance, num);
			}
		}
	}
	[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("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 (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;
				HostBond.Instance?.RefillTimer();
				GhostFreeSync.NotifyLocalFreeFlyStarted();
				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);
				HostBond.Instance?.RefillTimer();
				GhostFreeSync.NotifyLocalFreeFlyStopped(obj);
				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);
		}

		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();
		}

		private 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 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 && ModPresence.AllPlayersHaveMod)
				{
					if (!Configuration.EnableGhostBackpack.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 (GhostFeedPatches.GhostCanFeed && TryFindFeedCharacter(out result2))
			{
				result = (IInteractible)(object)result2;
			}
			else if (Configuration.EnableGhostBackpack.Value)
			{
				TryFindBackpackInteractable(out result);
			}
			if (result == null)
			{
				ClearHeldInteract(__instance);
				return false;
			}
			__instance.bestInteractable = result;
			__instance.bestCharacter = result2;
			AccessTools.Method(typeof(Interaction), "DoInteraction", (Type[])null, (Type[])null)?.Invoke(__instance, new object[1] { result });
			__instance.currentHovered = result;
			__instance.bestInteractableName = (((Object)(object)result.GetTransform() != (Object)null) ? ((Object)((Component)result.GetTransform()).gameObject).name : "ghost-interact");
			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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00ce: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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 && val4.IsSecondaryInteractible(localCharacter))
				{
					val2 = val4;
					num = ((RaycastHit)(ref val3)).distance;
				}
			}
			Collider[] array = Physics.OverlapSphere(((Component)instance).transform.position + ((Component)instance).transform.forward * 1f, 1.35f);
			for (int i = 0; i < array.Length; i++)
			{
				CharacterInteractible val5 = (((Object)(object)array[i] != (Object)null) ? ((Component)array[i]).GetComponentInParent<CharacterInteractible>() : null);
				if (!((Object)(object)val5 == (Object)null) && val5.IsSecondaryInteractible(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_0096: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_005e: 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);
			EnsureGhostHeldItemNonSolid(item);
			Vector3 position2 = ((Component)item).transform.position;
			item.Move(position, rotation);
			bool flag = false;
			try
			{
				flag = (Object)(object)((MonoBehaviourPun)item).photonView != (Object)null && ((MonoBehaviourPun)item).photonView.IsMine;
			}
			catch
			{
				flag = character.IsLocal;
			}
			if (flag && Vector3.Distance(position2, position) > 8f)
			{
				try
				{
					item.ForceSyncForFrames(15);
				}
				catch
				{
				}
			}
			return false;
		}

		[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_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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00c0: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00e0: 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_00ea: 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_00ab: 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.refs?.items == (Object)null)
			{
				return false;
			}
			Optionable<byte> currentSelectedSlot = character.refs.items.currentSelectedSlot;
			if (!currentSelectedSlot.IsSome || currentSelectedSlot.Value != 250)
			{
				return false;
			}
			Vector3 ghostFeetPosition = NameAnchor.GetGhostFeetPosition(character);
			Vector3 val = NameAnchor.GetGhostLookForward(character);
			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;
		}

		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(CharacterItems), "DropItemRpc")]
		[HarmonyPrefix]
		private static void DropItemRpcPrefix(CharacterItems __instance, float throwCharge, ref Vector3 spawnPos)
		{
			//IL_0072: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			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 (throwCharge > 0.05f && (Object)(object)character.data.currentItem != (Object)null)
				{
					spawnPos = ((Component)character.data.currentItem).transform.position;
				}
				else
				{
					spawnPos = NameAnchor.GetGhostFeetPosition(character) + Vector3.up * 0.4f;
				}
			}
		}

		private static void ClearHeldInteract(Interaction interaction)
		{
			if (!Character.localCharacter.input.interactIsPressed)
			{
				interaction.readyToInteract = true;
				AccessTools.Method(typeof(Interaction), "CancelHeldInteract", (Type[])null, (Type[])null)?.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_00bf: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			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;
			}
			Collider[] array = Physics.OverlapSphere(((Component)instance).transform.position + ((Component)instance).transform.forward * 1.2f, 1.25f);
			float num2 = 40f;
			IInteractible val2 = null;
			for (int i = 0; i < array.Length; i++)
			{
				if (TryGetBackpackInteractable(array[i], out var interactable))
				{
					Vector3 val3 = interactable.Center() - ((Component)instance).transform.position;
					float num3 = Vector3.Angle(((Component)instance).transform.forward, val3);
					if (num3 < num2 && ((Vector3)(ref val3)).magnitude <= num + 2f)
					{
						num2 = num3;
						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 static class GhostFeedPatches
	{
		internal static bool GhostCanFeed
		{
			get
			{
				if (!Configuration.EnableGhostHaul.Value || !ModPresence.AllPlayersHaveMod)
				{
					return false;
				}
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || !localCharacter.data.fullyPassedOut)
				{
					return false;
				}
				return CanGhostFeedItem(localCharacter.data.currentItem);
			}
		}

		internal static bool IsBlockedGhostFeedItem(Item item)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null)
			{
				return true;
			}
			try
			{
				if (((Enum)item.itemTags).HasFlag((Enum)(object)(ItemTags)512))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool CanGhostFeedItem(Item item)
		{
			if ((Object)(object)item != (Object)null && item.canUseOnFriend)
			{
				return !IsBlockedGhostFeedItem(item);
			}
			return false;
		}

		internal static void SyncGhostLookFromCamera()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0074: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_008a: 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_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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00c6: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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)
			Character localCharacter = Character.localCharacter;
			MainCamera instance = MainCamera.instance;
			if ((Object)(object)localCharacter?.data == (Object)null || !localCharacter.IsLocal || (Object)(object)instance == (Object)null || !localCharacter.data.fullyPassedOut)
			{
				return;
			}
			Vector3 forward = ((Component)instance).transform.forward;
			if (!(((Vector3)(ref forward)).sqrMagnitude < 0.0001f))
			{
				((Vector3)(ref forward)).Normalize();
				localCharacter.data.lookDirection = forward;
				localCharacter.data.lookValues = Vector2.op_Implicit(HelperFunctions.DirectionToLook(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;
				}
			}
		}

		internal static void SampleGhostUseInputs(CharacterInput input)
		{
			if (!((Object)(object)input == (Object)null))
			{
				InputAction action_interact = CharacterInput.action_interact;
				InputAction action_useSecondary = CharacterInput.action_useSecondary;
				InputAction action_usePrimary = CharacterInput.action_usePrimary;
				InputAction action_drop = CharacterInput.action_drop;
				if (action_interact != null)
				{
					input.interactWasPressed = action_interact.WasPressedThisFrame();
					input.interactIsPressed = action_interact.IsPressed();
					input.interactWasReleased = action_interact.WasReleasedThisFrame();
				}
				if (action_useSecondary != null)
				{
					input.useSecondaryWasPressed = action_useSecondary.WasPressedThisFrame();
					input.useSecondaryIsPressed = action_useSecondary.IsPressed();
					input.useSecondaryWasReleased = action_useSecondary.WasReleasedThisFrame();
				}
				if (action_usePrimary != null)
				{
					input.usePrimaryWasPressed = action_usePrimary.WasPressedThisFrame();
					input.usePrimaryIsPressed = action_usePrimary.IsPressed();
					input.usePrimaryWasReleased = action_usePrimary.WasReleasedThisFrame();
				}
				if (action_drop != null)
				{
					input.dropWasPressed = action_drop.WasPressedThisFrame();
					input.dropIsPressed = action_drop.IsPressed();
					input.dropWasReleased = action_drop.WasReleasedThisFrame();
				}
			}
		}

		[HarmonyPatch(typeof(CharacterMovement), "Update")]
		[HarmonyPostfix]
		private static void MovementUpdatePostfix(CharacterMovement __instance)
		{
			Character character = __instance.character;
			if (!((Object)(object)character == (Object)null) && character.IsLocal && !((Object)(object)character.data == (Object)null) && character.data.fullyPassedOut)
			{
				SampleGhostSpectatorInputs(character.input);
				MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
				if (!((Object)(object)instance == (Object)null) && instance.isGodCam && Configuration.EnableGhostHaul.Value && ModPresence.AllPlayersHaveMod)
				{
					SampleGhostUseInputs(character.input);
				}
			}
		}

		internal static void SampleGhostSpectatorInputs(CharacterInput input)
		{
			if (!((Object)(object)input == (Object)null))
			{
				SampleGhostPauseInput(input);
				SampleGhostPingInput(input);
			}
		}

		internal static void SampleGhostPauseInput(CharacterInput input)
		{
			if ((Object)(object)input == (Object)null)
			{
				return;
			}
			try
			{
				InputAction action_pause = CharacterInput.action_pause;
				if (action_pause != null)
				{
					input.pauseWasPressed = action_pause.WasPressedThisFrame();
				}
			}
			catch
			{
			}
		}

		internal static void SampleGhostPingInput(CharacterInput input)
		{
			if ((Object)(object)input == (Object)null || !Configuration.EnableGhostPing.Value)
			{
				return;
			}
			if (GUIManager.InPauseMenu)
			{
				input.pingWasPressed = false;
				return;
			}
			try
			{
				InputAction action_ping = CharacterInput.action_ping;
				if (action_ping != null)
				{
					input.pingWasPressed = action_ping.WasPressedThisFrame();
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(CharacterItems), "DoUsing")]
		[HarmonyPrefix]
		private static bool DoUsingPrefix(CharacterItems __instance)
		{
			Character character = __instance.character;
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.fullyPassedOut)
			{
				return true;
			}
			if (!character.IsLocal)
			{
				return false;
			}
			if (!Configuration.EnableGhostHaul.Value || !ModPresence.AllPlayersHaveMod)
			{
				return false;
			}
			Item currentItem = character.data.currentItem;
			if (!CanGhostFeedItem(currentItem))
			{
				return false;
			}
			SyncGhostLookFromCamera();
			CharacterInput input = character.input;
			if (input.useSecondaryIsPressed && currentItem.CanUseSecondary())
			{
				currentItem.StartUseSecondary();
			}
			if (input.useSecondaryIsPressed && currentItem.CanUseSecondary())
			{
				currentItem.ContinueUseSecondary();
			}
			if (input.useSecondaryWasReleased || (currentItem.isUsingSecondary && !currentItem.CanUseSecondary()))
			{
				currentItem.CancelUseSecondary();
			}
			return false;
		}
	}
	internal sealed class GhostFreeSync : MonoBehaviour, IOnEventCallback, IMatchmakingCallbacks, IInRoomCallbacks
	{
		internal struct RemoteLink
		{
			public Vector3 GhostPosition;

			public Quaternion GhostRotation;

			public int HostViewId;

			public bool Active;

			public float LastUpdateUnscaledTime;
		}

		internal const byte EventCode = 174;

		private const float SendInterval = 0.05f;

		private const float StaleLinkSeconds = 2.5f;

		private static readonly Dictionary<int, RemoteLink> RemoteLinks = new Dictionary<int, RemoteLink>();

		private static GhostFreeSync _instance;

		private static float _nextSendTime;

		private static bool _localFreeActive;

		private static int _localGhostViewId = -1;

		private static float _nextStaleSweep;

		internal static IEnumerable<KeyValuePair<int, RemoteLink>> EnumerateRemoteLinks()
		{
			return RemoteLinks;
		}

		internal static bool TryGetRemoteLink(int ghostViewId, out RemoteLink link)
		{
			return RemoteLinks.TryGetValue(ghostViewId, out link);
		}

		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_GhostFreeSync");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<GhostFreeSync>();
			}
		}

		private void OnEnable()
		{
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		private void OnDisable()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
			ForceSendLocalFreeFlyStopped();
		}

		private void OnApplicationQuit()
		{
			ForceSendLocalFreeFlyStopped();
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextStaleSweep))
			{
				_nextStaleSweep = Time.unscaledTime + 0.5f;
				PurgeStaleRemoteLinks();
			}
		}

		internal static void NotifyLocalFreeFlyStarted()
		{
			//IL_007e: 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_00a2: 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_00a7: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			_localFreeActive = true;
			_nextSendTime = 0f;
			PlayerGhost val = (((Object)(object)Character.localCharacter != (Object)null) ? Character.localCharacter.Ghost : null);
			Character val2 = (((Object)(object)HostBond.Instance != (Object)null) ? HostBond.Instance.Host : null);
			int hostViewId = (((Object)(object)val2 != (Object)null && val2.refs != null && (Object)(object)val2.refs.view != (Object)null) ? val2.refs.view.ViewID : (-1));
			Vector3 localGhostWorldPosition = HostBond.GetLocalGhostWorldPosition();
			Quaternion rotation = (((Object)(object)MainCamera.instance != (Object)null) ? ((Component)MainCamera.instance).transform.rotation : Quaternion.identity);
			if ((Object)(object)val != (Object)null && (Object)(object)val.m_view != (Object)null)
			{
				_localGhostViewId = val.m_view.ViewID;
				SendState(val.m_view.ViewID, active: true, localGhostWorldPosition, rotation, hostViewId, reliable: true);
			}
		}

		internal static void NotifyLocalFreeFlyStopped(Character reattachTarget)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			_localFreeActive = false;
			PlayerGhost val = (((Object)(object)Character.localCharacter != (Object)null) ? Character.localCharacter.Ghost : null);
			int hostViewId = (((Object)(object)reattachTarget != (Object)null && reattachTarget.refs != null && (Object)(object)reattachTarget.refs.view != (Object)null) ? reattachTarget.refs.view.ViewID : (-1));
			if ((Object)(object)val != (Object)null && (Object)(object)val.m_view != (Object)null)
			{
				SendState(val.m_view.ViewID, active: false, ((Component)val).transform.position, ((Component)val).transform.rotation, hostViewId, reliable: true);
				if ((Object)(object)reattachTarget != (Object)null && reattachTarget.refs != null && (Object)(object)reattachTarget.refs.view != (Object)null)
				{
					val.m_view.RPC("RPCA_SetTarget", (RpcTarget)0, new object[1] { reattachTarget.refs.view });
				}
			}
			else if (_localGhostViewId >= 0)
			{
				SendState(_localGhostViewId, active: false, Vector3.zero, Quaternion.identity, hostViewId, reliable: true);
			}
			SnapLocalHeldItemAfterFreeFlyExit();
			if (_localGhostViewId >= 0)
			{
				RemoteLinks.Remove(_localGhostViewId);
				_localGhostViewId = -1;
			}
		}

		private static void ForceSendLocalFreeFlyStopped()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (_localFreeActive || _localGhostViewId >= 0)
			{
				int num = _localGhostViewId;
				PlayerGhost val = (((Object)(object)Character.localCharacter != (Object)null) ? Character.localCharacter.Ghost : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_view != (Object)null)
				{
					num = val.m_view.ViewID;
				}
				_localFreeActive = false;
				if (num >= 0 && PhotonNetwork.InRoom)
				{
					SendState(num, active: false, Vector3.zero, Quaternion.identity, -1, reliable: true);
				}
				_localGhostViewId = -1;
			}
		}

		private static void SnapLocalHeldItemAfterFreeFlyExit()
		{
			//IL_0044: 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)
			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))
				{
					val.Move(position, rotation);
					val.ForceSyncForFrames(20);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Snap held item after free-fly exit failed: " + ex.Message));
			}
		}

		internal static void TickLocalPose(Vector3 cameraPosition, Quaternion cameraRotation)
		{
			//IL_0050: 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_010a: 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)
			if (!_localFreeActive)
			{
				return;
			}
			PlayerGhost val = (((Object)(object)Character.localCharacter != (Object)null) ? Character.localCharacter.Ghost : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.m_view != (Object)null)
			{
				_localGhostViewId = val.m_view.ViewID;
				((Component)val).transform.position = cameraPosition;
				((Component)val).transform.rotation = cameraRotation;
			}
			if (PhotonNetwork.InRoom && !(Time.unscaledTime < _nextSendTime))
			{
				_nextSendTime = Time.unscaledTime + 0.05f;
				Character val2 = (((Object)(object)HostBond.Instance != (Object)null) ? HostBond.Instance.Host : null);
				int hostViewId = (((Object)(object)val2 != (Object)null && val2.refs != null && (Object)(object)val2.refs.view != (Object)null) ? val2.refs.view.ViewID : (-1));
				int num = (((Object)(object)val != (Object)null && (Object)(object)val.m_view != (Object)null) ? val.m_view.ViewID : _localGhostViewId);
				if (num >= 0)
				{
					SendState(num, active: true, cameraPosition, cameraRotation, hostViewId, reliable: false);
				}
			}
		}

		internal static bool TryApplyFreePose(PlayerGhost ghost)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ghost == (Object)null || (Object)(object)ghost.m_view == (Object)null)
			{
				return false;
			}
			int viewID = ghost.m_view.ViewID;
			if (_localFreeActive && (Object)(object)Character.localCharacter != (Object)null && (Object)(object)ghost == (Object)(object)Character.localCharacter.Ghost)
			{
				MainCamera instance = MainCamera.instance;
				if ((Object)(object)instance != (Object)null)
				{
					((Component)ghost).transform.position = ((Component)instance).transform.position;
					((Component)ghost).transform.rotation = ((Component)instance).transform.rotation;
				}
				return true;
			}
			if (RemoteLinks.TryGetValue(viewID, out var value) && value.Active)
			{
				if (Time.unscaledTime - value.LastUpdateUnscaledTime > 2.5f)
				{
					RemoteLinks.Remove(viewID);
					return false;
				}
				((Component)ghost).transform.position = value.GhostPosition;
				((Component)ghost).transform.rotation = value.GhostRotation;
				return true;
			}
			return false;
		}

		private static void SendState(int viewId, bool active, Vector3 position, Quaternion rotation, int hostViewId, bool reliable)
		{
			//IL_0023: 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)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00a7: 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_00ac: 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)
			if (PhotonNetwork.InRoom)
			{
				object[] array = new object[10] { viewId, active, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, hostViewId };
				RaiseEventOptions val = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				};
				SendOptions val2 = (reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable);
				PhotonNetwork.RaiseEvent((byte)174, (object)array, val, val2);
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			//IL_00e0: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code == 174 && photonEvent.CustomData is object[] array && array.Length >= 10 && array[0] is int key)
			{
				object obj = array[1];
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) == 0)
				{
					RemoteLinks.Remove(key);
					return;
				}
				Vector3 ghostPosition = default(Vector3);
				((Vector3)(ref ghostPosition))..ctor(ToFloat(array[2]), ToFloat(array[3]), ToFloat(array[4]));
				Quaternion ghostRotation = default(Quaternion);
				((Quaternion)(ref ghostRotation))..ctor(ToFloat(array[5]), ToFloat(array[6]), ToFloat(array[7]), ToFloat(array[8]));
				int hostViewId = ((array[9] is int num2) ? num2 : (-1));
				RemoteLinks[key] = new RemoteLink
				{
					GhostPosition = ghostPosition,
					GhostRotation = ghostRotation,
					HostViewId = hostViewId,
					Active = true,
					LastUpdateUnscaledTime = Time.unscaledTime
				};
			}
		}

		private static void PurgeStaleRemoteLinks()
		{
			if (RemoteLinks.Count == 0)
			{
				return;
			}
			List<int> list = null;
			float unscaledTime = Time.unscaledTime;
			foreach (KeyValuePair<int, RemoteLink> remoteLink in RemoteLinks)
			{
				bool num = unscaledTime - remoteLink.Value.LastUpdateUnscaledTime > 2.5f;
				bool flag = (Object)(object)PhotonNetwork.GetPhotonView(remoteLink.Key) == (Object)null;
				if (num || flag)
				{
					if (list == null)
					{
						list = new List<int>();
					}
					list.Add(remoteLink.Key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					RemoteLinks.Remove(list[i]);
				}
			}
		}

		private static void RemoveLinksOwnedBy(Player player)
		{
			if (player == null || RemoteLinks.Count == 0)
			{
				return;
			}
			List<int> list = null;
			foreach (KeyValuePair<int, RemoteLink> remoteLink in RemoteLinks)
			{
				PhotonView photonView = PhotonNetwork.GetPhotonView(remoteLink.Key);
				bool num = (Object)(object)photonView != (Object)null && photonView.Owner != null && photonView.Owner.ActorNumber == player.ActorNumber;
				bool flag = (Object)(object)photonView == (Object)null;
				if (num || flag)
				{
					if (list == null)
					{
						list = new List<int>();
					}
					list.Add(remoteLink.Key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					RemoteLinks.Remove(list[i]);
				}
			}
		}

		private static float ToFloat(object value)
		{
			if (!(value is float result))
			{
				if (!(value is double num))
				{
					if (value is int num2)
					{
						return num2;
					}
					return 0f;
				}
				return (float)num;
			}
			return result;
		}

		public void OnFriendListUpdate(List<FriendInfo> friendList)
		{
		}

		public void OnCreatedRoom()
		{
		}

		public void OnCreateRoomFailed(short returnCode, string message)
		{
		}

		public void OnJoinedRoom()
		{
		}

		public void OnJoinRoomFailed(short returnCode, string message)
		{
		}

		public void OnJoinRandomFailed(short returnCode, string message)
		{
		}

		public void OnLeftRoom()
		{
			ForceSendLocalFreeFlyStopped();
			RemoteLinks.Clear();
		}

		public void OnPlayerEnteredRoom(Player newPlayer)
		{
		}

		public void OnPlayerLeftRoom(Player otherPlayer)
		{
			RemoveLinksOwnedBy(otherPlayer);
		}

		public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
		}

		public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
		}

		public void OnMasterClientSwitched(Player newMasterClient)
		{
		}
	}
	[HarmonyPatch(typeof(PlayerGhost), "Update")]
	internal static class PlayerGhostFreeFlyPatch
	{
		private static bool Prefix(PlayerGhost __instance)
		{
			return !GhostFreeSync.TryApplyFreePose(__instance);
		}
	}
	internal sealed class GhostItemHaul : MonoBehaviour
	{
		private static GhostItemHaul _instance;

		private Item _lookTarget;

		private float _lookTargetUntil;

		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_GhostItemHaul");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<GhostItemHaul>();
			}
		}

		private void Update()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (!Configuration.EnableGhostHaul.Value)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && localCharacter.data.fullyPassedOut && ModPresence.AllPlayersHaveMod && Input.GetKeyDown(Configuration.GhostHaulKey.Value) && (!((Object)(object)Interaction.instance != (Object)null) || Interaction.instance.bestInteractable == null))
			{
				if ((Object)(object)localCharacter.data.currentItem != (Object)null)
				{
					DropHeldItem(localCharacter);
				}
				else
				{
					TryPickupLookedItem(localCharacter);
				}
			}
		}

		private void OnGUI()
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_00d6: 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_0216: Unknown result type (might be due to invalid IL or missing references)
			if (!Configuration.EnableGhostHaul.Value)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || !localCharacter.data.fullyPassedOut || !ModPresence.AllPlayersHaveMod)
			{
				return;
			}
			string text = null;
			Item currentItem = localCharacter.data.currentItem;
			if ((Object)(object)currentItem != (Object)null)
			{
				text = (GhostFeedPatches.CanGhostFeedItem(currentItem) ? GameL10n.Pick("Holding " + currentItem.GetName() + " · Aim teammate + secondary to apply (consumed on use)", "手持 " + currentItem.GetName() + " · 瞄准队友按副键使用(用完即消耗,无需放下)") : ((!GhostFeedPatches.IsBlockedGhostFeedItem(currentItem) || !currentItem.canUseOnFriend) ? GameL10n.Pick($"Ghost haul: {currentItem.GetName()} · Press {Configuration.GhostHaulKey.Value} to drop", $"幽灵搬运中:{currentItem.GetName()} · 按 {Configuration.GhostHaulKey.Value} 放下") : GameL10n.Pick($"Ghost haul: {currentItem.GetName()} · Scout amulets cannot be used on teammates as a ghost · Press {Configuration.GhostHaulKey.Value} to drop", $"幽灵搬运中:{currentItem.GetName()} · 童军护身符无法由幽灵对队友使用 · 按 {Configuration.GhostHaulKey.Value} 放下")));
			}
			else
			{
				Item lookItem = GetLookItem();
				if ((Object)(object)lookItem != (Object)null && IsHaulCandidate(lookItem) && IsWithinWeightLimit(lookItem))
				{
					float num = (float)lookItem.CarryWeight * 2.5f;
					string text2 = (GhostFeedPatches.CanGhostFeedItem(lookItem) ? GameL10n.Pick(" (can use on teammate)", "(可对队友使用)") : ((GhostFeedPatches.IsBlockedGhostFeedItem(lookItem) && lookItem.canUseOnFriend) ? GameL10n.Pick(" (amulet: ghost cannot use on teammate)", "(护身符:幽灵不可对队友使用)") : string.Empty));
					text = GameL10n.Pick($"Can haul: {lookItem.GetName()} ({num:0.#}){text2} · Press {Configuration.GhostHaulKey.Value}", $"可幽灵搬运:{lookItem.GetName()}({num:0.#}){text2}· 按 {Configuration.GhostHaulKey.Value} 提起");
				}
			}
			if (!string.IsNullOrEmpty(text))
			{
				DrawBottomHint(text);
			}
		}

		private static void DrawBottomHint(string text)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = new GUIStyle(GUI.skin.box)
			{
				alignment = (TextAnchor)4,
				fontSize = 14
			};
			val.normal.textColor = Color.white;
			float num = 620f;
			GUI.Box(new Rect(((float)Screen.width - num) * 0.5f, (float)Screen.height - 72f, num, 36f), text, val);
		}

		private void TryPickupLookedItem(Character local)
		{
			Item lookItem = GetLookItem();
			if (!((Object)(object)lookItem == (Object)null) && IsHaulCandidate(lookItem))
			{
				if (!IsWithinWeightLimit(lookItem))
				{
					ShowTooHeavyToast(lookItem);
					return;
				}
				if (!local.player.tempFullSlot.IsEmpty() || (Object)(object)local.data.currentItem != (Object)null)
				{
					GhostItemHaulToast.Show("Ghosts can only hold one item", "幽灵同时只能持有一件物品");
					return;
				}
				if (!local.player.HasEmptySlot(lookItem.itemID))
				{
					GhostItemHaulToast.Show("Ghosts can only hold one item", "幽灵同时只能持有一件物品");
					return;
				}
				Plugin.Log.LogInfo((object)$"Ghost haul pickup: {((Object)lookItem).name} (CarryWeight={lookItem.CarryWeight}, UI={(float)lookItem.CarryWeight * 2.5f:0.#}, feedable={lookItem.canUseOnFriend})");
				lookItem.Interact(local);
			}
		}

		private static void DropHeldItem(Character local)
		{
			//IL_0082: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown res