Decompiled source of RepoUtilityDrones v0.1.1

BepInEx/plugins/RepoUtilityDrones/RepoUtilityDrones.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Photon.Pun;
using REPOLib.Modules;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("RepoUtilityDrones")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("RepoUtilityDrones")]
[assembly: AssemblyTitle("RepoUtilityDrones")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Matsu.RepoUtilityDrones
{
	[HarmonyPatch(typeof(ShopManager), "GetAllItemsFromStatsManager")]
	internal static class ShopCatalogReady
	{
		private static void Prefix()
		{
			DroneAssets.TryRegister();
		}
	}
	[HarmonyPatch(typeof(ItemManager), "GetPurchasedItems")]
	internal static class OwnedCatalogReady
	{
		private static void Prefix()
		{
			DroneAssets.TryRegister();
		}
	}
	public static class DroneAssets
	{
		public const string LinkAName = "Item Utility Link A";

		public const string LinkBName = "Item Utility Link B";

		public static readonly Dictionary<DroneKind, Item> Registered = new Dictionary<DroneKind, Item>();

		private static Transform? holder;

		public static bool Ready => Registered.Count == 4;

		public static string Status { get; private set; } = "Waiting for native catalog";

		public static bool TryRegister()
		{
			//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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			if (Ready)
			{
				return true;
			}
			Item[] source = Items.AllItems.Where((Item i) => (Object)(object)i != (Object)null && (Object)(object)((PrefabRef<GameObject>)(object)i.prefab)?.Prefab != (Object)null && (Object)(object)((PrefabRef<GameObject>)(object)i.prefab).Prefab.GetComponent<ItemDrone>() != (Object)null).ToArray();
			Item val = ((IEnumerable<Item>)source).FirstOrDefault((Func<Item, bool>)((Item i) => (Object)(object)((PrefabRef<GameObject>)(object)i.prefab).Prefab.GetComponent<ItemDroneZeroGravity>() != (Object)null)) ?? source.FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				Status = "Native drone unavailable; catalog count=" + Items.AllItems.Count;
				return false;
			}
			if ((Object)(object)holder == (Object)null)
			{
				GameObject val2 = new GameObject("Utility Drone dormant templates");
				val2.SetActive(false);
				Object.DontDestroyOnLoad((Object)val2);
				holder = val2.transform;
			}
			foreach (DroneKind value in Enum.GetValues(typeof(DroneKind)))
			{
				if (!Registered.ContainsKey(value))
				{
					Register(val, value);
				}
			}
			Status = "Ready: native template " + ((Object)val).name;
			return Ready;
		}

		public static Color Color(DroneKind kind)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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)
			return (Color)(kind switch
			{
				DroneKind.Silencer => new Color(0.2f, 0.95f, 0.55f), 
				DroneKind.GhostValue => new Color(0.65f, 0.45f, 1f), 
				_ => new Color(1f, 0.65f, 0.12f), 
			});
		}

		private static void Register(Item source, DroneKind kind)
		{
			//IL_011e: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)source.prefab).Prefab, holder, false);
			val.SetActive(true);
			((Object)val).name = kind switch
			{
				DroneKind.LinkB => "Item Utility Link B", 
				DroneKind.LinkA => "Item Utility Link A", 
				_ => "Item Utility " + kind, 
			};
			Item val2 = Object.Instantiate<Item>(source);
			((Object)val2).name = ((Object)val).name;
			val2.itemName = kind switch
			{
				DroneKind.GhostValue => "Ghost Drone", 
				DroneKind.LinkB => "Link Drone B", 
				DroneKind.LinkA => "Link Drone Set (A + B)", 
				_ => "Silencer Drone", 
			};
			val2.itemNameLocalized = null;
			val2.description = (DroneRules.Link(kind) ? "A + B kit: attach to two carts or valuables to limit separation. Both halves are delivered after checkout. Turn either off to release." : ((kind == DroneKind.GhostValue) ? "Players can pass through this valuable while it is attached. Floors, walls, carts, grabbing and actual value stay normal. Also holds its extraction until switched off." : "Quiet this player's voice and body sounds, or this valuable, item, weapon or enemy's own sounds. Nearby enemies hear less of that noise. Does not deafen the target or change damage."));
			val2.value = Object.Instantiate<Value>(source.value);
			val2.value.valueMin = (val2.value.valueMax = (DroneRules.Link(kind) ? 4500 : ((kind == DroneKind.GhostValue) ? 2500 : 3500)));
			val2.colorPreset = Object.Instantiate<ColorPresets>(source.colorPreset);
			val2.colorPreset.colorMain = Color(kind);
			val2.colorPreset.colorLight = Color(kind);
			val2.colorPreset.colorDark = Color(kind) * 0.6f;
			val2.maxAmount = 24;
			val2.maxAmountInShop = ((kind != DroneKind.LinkB) ? 3 : 0);
			val2.minPlayerCount = 1;
			val2.disabled = false;
			val2.maxPurchase = false;
			val2.physicalItem = true;
			val2.itemSecretShopType = (itemSecretShopType)0;
			ItemAttributes component = val.GetComponent<ItemAttributes>();
			component.item = val2;
			MonoBehaviour[] components = val.GetComponents<MonoBehaviour>();
			foreach (MonoBehaviour val3 in components)
			{
				if ((!(val3 is ItemDrone) && ((object)val3).GetType().Name.StartsWith("ItemDrone", StringComparison.Ordinal)) || val3 is ITargetingCondition)
				{
					Object.DestroyImmediate((Object)(object)val3);
				}
			}
			ItemDrone component2 = val.GetComponent<ItemDrone>();
			component2.targetPlayers = (component2.targetEnemies = kind == DroneKind.Silencer);
			component2.targetValuables = true;
			component2.targetNonValuables = DroneRules.Link(kind) || kind == DroneKind.Silencer;
			component2.batteryDrainPreset = Object.Instantiate<BatteryDrainPresets>(component2.batteryDrainPreset);
			component2.batteryDrainPreset.batteryDrainRate = (DroneRules.Link(kind) ? 0.12f : 0.15f);
			Texture2D val4 = (Texture2D)(object)(component2.droneIcon = (Texture)(object)DroneVisuals.Icon(kind));
			component.icon = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f), 128f);
			val.AddComponent<UtilityDrone>().Kind = kind;
			PrefabRef prefab = Items.RegisterItem(component) ?? throw new InvalidOperationException("Cannot register " + ((Object)val).name);
			val2.prefab = prefab;
			Registered.Add(kind, val2);
			Plugin.Log.LogInfo((object)("Registered " + val2.itemName + "; shop stock=" + val2.maxAmountInShop));
		}
	}
	[DefaultExecutionOrder(10000)]
	public sealed class DroneDirector : MonoBehaviour
	{
		private readonly Dictionary<int, LinkConstraint> links = new Dictionary<int, LinkConstraint>();

		private readonly Dictionary<int, DroneState> remote = new Dictionary<int, DroneState>();

		private readonly Dictionary<int, LinkAnchorState> remoteAnchors = new Dictionary<int, LinkAnchorState>();

		private float nextCatalog;

		private float nextBind;

		private float nextRequest;

		private float remoteUntil;

		private bool wasHost;

		private int seq;

		private int acceptedActor;

		private double acceptedTime = -1.0;

		private string epoch = Guid.NewGuid().ToString("N");

		private string acceptedEpoch = "";

		public static DroneDirector? Instance { get; private set; }

		public float MaximumDistance { get; private set; } = 3.5f;

		public float NoiseFactor { get; private set; } = 0.08f;

		public IReadOnlyDictionary<int, LinkConstraint> Links => links;

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.AddComponent<SilencerFrameRestore>();
			Plugin.Log.LogInfo((object)"Utility Drone native-scene director created.");
		}

		public void SceneChanged()
		{
			foreach (LinkConstraint value in links.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					value.ReleaseJoint();
					((Component)value).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
			links.Clear();
			remote.Clear();
			remoteAnchors.Clear();
			GhostExtraction.Clear();
			GhostPhase.Clear();
			SilencerSources.Clear();
			epoch = Guid.NewGuid().ToString("N");
			seq = 0;
			acceptedTime = -1.0;
			acceptedActor = 0;
			acceptedEpoch = "";
			nextBind = (nextRequest = 0f);
			foreach (UtilityDrone item in UtilityDrone.Active)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.PairToken = 0;
				}
			}
		}

		private void Update()
		{
			if (!DroneAssets.Ready && Time.unscaledTime >= nextCatalog)
			{
				nextCatalog = Time.unscaledTime + 0.5f;
				try
				{
					DroneAssets.TryRegister();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Drone registration failed: " + ex));
					nextCatalog += 10f;
				}
			}
			bool host = NativeAccess.Host;
			if (host != wasHost)
			{
				foreach (LinkConstraint value2 in links.Values)
				{
					if ((Object)(object)value2 != (Object)null)
					{
						value2.ReleaseJoint();
					}
				}
				if (host)
				{
					epoch = Guid.NewGuid().ToString("N");
					seq = 0;
				}
				wasHost = host;
			}
			if (Time.unscaledTime < nextBind)
			{
				return;
			}
			nextBind = Time.unscaledTime + 0.2f;
			if (host)
			{
				MaximumDistance = DroneRules.Distance(Plugin.LinkDistance.Value);
				NoiseFactor = DroneRules.Noise(Plugin.SilencerFactor.Value);
				foreach (UtilityDrone item in UtilityDrone.Active)
				{
					if ((Object)(object)item != (Object)null)
					{
						PairStore.Bind(item);
					}
				}
				RefreshLinks();
				GhostExtraction.Refresh();
				Broadcast();
				return;
			}
			if (Time.unscaledTime > remoteUntil)
			{
				remote.Clear();
				remoteAnchors.Clear();
				foreach (UtilityDrone item2 in UtilityDrone.Active)
				{
					if ((Object)(object)item2 != (Object)null)
					{
						item2.PairToken = 0;
					}
				}
			}
			foreach (UtilityDrone item3 in UtilityDrone.Active)
			{
				if ((Object)(object)item3 != (Object)null && remote.TryGetValue(item3.Id, out DroneState value) && value.Kind == item3.Kind)
				{
					item3.PairToken = value.Token;
					NativeAccess.Present(item3, value);
				}
			}
			RefreshLinks();
			GhostExtraction.Refresh();
			if (Time.unscaledTime >= nextRequest)
			{
				nextRequest = Time.unscaledTime + 3f;
				DroneNetwork.RequestSnapshot();
			}
		}

		private void FixedUpdate()
		{
			GhostPhase.Refresh();
		}

		private void LateUpdate()
		{
			SilencerSources.ApplyFrame();
		}

		public void Release(UtilityDrone source)
		{
			foreach (LinkConstraint value in links.Values)
			{
				if ((Object)(object)value != (Object)null && ((Object)(object)value.A == (Object)(object)source || (Object)(object)value.B == (Object)(object)source))
				{
					value.ReleaseJoint();
				}
			}
			GhostExtraction.Refresh();
			SilencerSources.ReleaseInactive();
		}

		private void RefreshLinks()
		{
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, UtilityDrone> dictionary = new Dictionary<int, UtilityDrone>();
			Dictionary<int, UtilityDrone> dictionary2 = new Dictionary<int, UtilityDrone>();
			foreach (UtilityDrone item in UtilityDrone.Active)
			{
				if ((Object)(object)item != (Object)null && item.PairToken > 0 && DroneRules.Link(item.Kind))
				{
					Dictionary<int, UtilityDrone> dictionary3 = ((item.Kind == DroneKind.LinkA) ? dictionary : dictionary2);
					if (!dictionary3.ContainsKey(item.PairToken))
					{
						dictionary3.Add(item.PairToken, item);
					}
				}
			}
			int[] array = links.Keys.ToArray();
			foreach (int key in array)
			{
				if (!dictionary.ContainsKey(key) || !dictionary2.ContainsKey(key) || (Object)(object)links[key].A != (Object)(object)dictionary[key] || (Object)(object)links[key].B != (Object)(object)dictionary2[key])
				{
					LinkConstraint linkConstraint = links[key];
					linkConstraint.ReleaseJoint();
					((Component)linkConstraint).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)linkConstraint).gameObject);
					links.Remove(key);
				}
			}
			foreach (KeyValuePair<int, UtilityDrone> item2 in dictionary)
			{
				if (dictionary2.TryGetValue(item2.Key, out var value) && !links.ContainsKey(item2.Key))
				{
					GameObject val = new GameObject("Link Drone pair " + item2.Key);
					val.transform.SetParent(((Component)this).transform, false);
					LinkConstraint linkConstraint2 = val.AddComponent<LinkConstraint>();
					linkConstraint2.A = item2.Value;
					linkConstraint2.B = value;
					links.Add(item2.Key, linkConstraint2);
				}
			}
			if (NativeAccess.Host)
			{
				return;
			}
			foreach (KeyValuePair<int, LinkConstraint> link in links)
			{
				link.Value.ReceiveAnchors(remoteAnchors.TryGetValue(link.Key, out LinkAnchorState value2) ? value2 : null);
			}
		}

		public bool HasEffect(Component? target, DroneKind kind)
		{
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			if (NativeAccess.Host)
			{
				foreach (UtilityDrone item in UtilityDrone.Active)
				{
					if ((Object)(object)item != (Object)null && item.Kind == kind && item.Attached && ((kind == DroneKind.Silencer) ? SilencerTargets.Same(item.AttachedObject, target) : ((Object)(object)item.Target == (Object)(object)target)))
					{
						return true;
					}
				}
			}
			else if (Time.unscaledTime <= remoteUntil)
			{
				foreach (DroneState binding in remote.Values)
				{
					if (binding.Kind == kind && binding.Attached && ((kind == DroneKind.Silencer) ? SilencerTargets.Same(NativeAccess.SnapshotTarget(binding), target) : (binding.Target == NativeAccess.Id(target))) && UtilityDrone.Active.Any((UtilityDrone d) => (Object)(object)d != (Object)null && d.Id == binding.Drone && ((Behaviour)d).isActiveAndEnabled))
					{
						return true;
					}
				}
			}
			return false;
		}

		public PhysGrabObject? EffectTarget(UtilityDrone drone)
		{
			if (!NativeAccess.Host)
			{
				if (!(Time.unscaledTime <= remoteUntil) || !remote.TryGetValue(drone.Id, out DroneState value) || value.Kind != drone.Kind || !value.Attached)
				{
					return null;
				}
				return NativeAccess.Physics(value.Target);
			}
			if (!drone.Attached)
			{
				return null;
			}
			return drone.Target;
		}

		public Component? SilencerTarget(UtilityDrone drone)
		{
			if (drone.Kind == DroneKind.Silencer)
			{
				if (!NativeAccess.Host)
				{
					if (!(Time.unscaledTime <= remoteUntil) || !remote.TryGetValue(drone.Id, out DroneState value) || value.Kind != DroneKind.Silencer || !value.Attached)
					{
						return null;
					}
					return NativeAccess.SnapshotTarget(value);
				}
				if (!drone.Attached)
				{
					return null;
				}
				return drone.AttachedObject;
			}
			return null;
		}

		public void Broadcast()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected I4, but got Unknown
			//IL_01ba: 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_01d4: Unknown result type (might be due to invalid IL or missing references)
			if (!NativeAccess.Host || !NativeAccess.Multiplayer)
			{
				return;
			}
			DroneSnapshot obj = new DroneSnapshot
			{
				Epoch = epoch
			};
			Scene activeScene = SceneManager.GetActiveScene();
			obj.Scene = ((Scene)(ref activeScene)).name;
			obj.Sequence = ++seq;
			obj.Time = PhotonNetwork.Time;
			obj.MaxDistance = MaximumDistance;
			obj.Noise = NoiseFactor;
			obj.Pairs = ((PairStore.Data != null) ? new Dictionary<string, int>(PairStore.Data) : new Dictionary<string, int>());
			DroneSnapshot droneSnapshot = obj;
			foreach (UtilityDrone item in UtilityDrone.Active)
			{
				if ((Object)(object)item != (Object)null && item.Id > 0)
				{
					Vector3 val = NativeAccess.SnapshotHit(item);
					droneSnapshot.Drones.Add(new DroneState
					{
						Drone = item.Id,
						Kind = item.Kind,
						Token = item.PairToken,
						Target = ((item.Attached && (Object)(object)item.AttachedObject != (Object)null) ? NativeAccess.Id(item.AttachedObject) : 0),
						Attached = item.Attached,
						TargetType = ((item.AttachedObject is PlayerAvatar) ? DroneTargetType.Player : DroneTargetType.Physics),
						Collider = ((item.Attached && (Object)(object)item.PlayerTarget == (Object)null) ? NativeAccess.TargetCollider(item.Drone) : (-1)),
						State = (int)item.Drone.currentState,
						Powered = item.Powered,
						Battery = Mathf.Clamp(item.Battery.batteryLife, 0f, 100f),
						X = val.x,
						Y = val.y,
						Z = val.z
					});
				}
			}
			foreach (LinkConstraint value in links.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					LinkAnchorState linkAnchorState = value.Snapshot();
					if (linkAnchorState != null)
					{
						droneSnapshot.Links.Add(linkAnchorState);
					}
				}
			}
			DroneNetwork.Broadcast(droneSnapshot);
		}

		public bool Receive(DroneSnapshot snapshot, int actor)
		{
			//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)
			if (DroneNetwork.Valid(snapshot, PhotonNetwork.Time))
			{
				string scene = snapshot.Scene;
				Scene activeScene = SceneManager.GetActiveScene();
				if (!(scene != ((Scene)(ref activeScene)).name) && (actor != acceptedActor || (!(snapshot.Time < acceptedTime) && (!(snapshot.Epoch == acceptedEpoch) || snapshot.Sequence > seq))))
				{
					acceptedActor = actor;
					acceptedEpoch = snapshot.Epoch;
					acceptedTime = snapshot.Time;
					seq = snapshot.Sequence;
					MaximumDistance = snapshot.MaxDistance;
					NoiseFactor = snapshot.Noise;
					remoteUntil = Time.unscaledTime + 2f;
					remote.Clear();
					foreach (DroneState drone in snapshot.Drones)
					{
						remote[drone.Drone] = drone;
					}
					remoteAnchors.Clear();
					foreach (LinkAnchorState link in snapshot.Links)
					{
						remoteAnchors[link.Token] = link;
					}
					foreach (UtilityDrone item in UtilityDrone.Active)
					{
						if ((Object)(object)item != (Object)null)
						{
							item.PairToken = ((remote.TryGetValue(item.Id, out DroneState value) && value.Kind == item.Kind) ? value.Token : 0);
						}
					}
					Dictionary<string, int> data = PairStore.Data;
					if (data != null)
					{
						data.Clear();
						foreach (KeyValuePair<string, int> pair in snapshot.Pairs)
						{
							data.Add(pair.Key, pair.Value);
						}
					}
					return true;
				}
			}
			return false;
		}

		private void OnDestroy()
		{
			SceneChanged();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	public static class DroneNetwork
	{
		private static NetworkedEvent request;

		private static NetworkedEvent state;

		public static void Initialize()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			request = new NetworkedEvent("com.matsu.repoutilitydrones.sync.v1", (Action<EventData>)ReceiveRequest);
			state = new NetworkedEvent("com.matsu.repoutilitydrones.state.v1", (Action<EventData>)ReceiveState);
		}

		public static void RequestSnapshot()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (NativeAccess.Multiplayer && !NativeAccess.Host)
			{
				request.RaiseEvent((object)new object[1] { "com.matsu.repoutilitydrones" }, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable);
			}
		}

		private static void ReceiveRequest(EventData evt)
		{
			if (NativeAccess.Host && NativeAccess.Multiplayer && evt.CustomData is object[] array && array.Length == 1 && array[0] is string text && text == "com.matsu.repoutilitydrones" && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.Players.ContainsKey(evt.Sender))
			{
				DroneDirector.Instance?.Broadcast();
			}
		}

		public static void Broadcast(DroneSnapshot snapshot)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			state.RaiseEvent((object)new object[2]
			{
				"com.matsu.repoutilitydrones",
				JsonConvert.SerializeObject((object)snapshot)
			}, NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
		}

		private static void ReceiveState(EventData evt)
		{
			if (!NativeAccess.Multiplayer || NativeAccess.Host || PhotonNetwork.MasterClient == null || evt.Sender != PhotonNetwork.MasterClient.ActorNumber || !(evt.CustomData is object[] array) || array.Length != 2 || !(array[0] is string text) || text != "com.matsu.repoutilitydrones" || !(array[1] is string { Length: <=32768 } text2))
			{
				return;
			}
			try
			{
				DroneSnapshot droneSnapshot = JsonConvert.DeserializeObject<DroneSnapshot>(text2);
				if (droneSnapshot != null)
				{
					DroneDirector.Instance?.Receive(droneSnapshot, evt.Sender);
				}
			}
			catch (JsonException)
			{
				Plugin.Log.LogWarning((object)"Rejected malformed drone snapshot.");
			}
		}

		public static bool Valid(DroneSnapshot s, double now)
		{
			return DroneProtocol.Valid(s, now);
		}
	}
	public enum DroneTargetType
	{
		Physics,
		Player
	}
	public sealed class DroneState
	{
		public int Drone;

		public int Target;

		public int Token;

		public int Collider = -1;

		public int State;

		public DroneKind Kind;

		public bool Attached;

		public bool Powered;

		public DroneTargetType TargetType;

		public float X;

		public float Y;

		public float Z;

		public float Battery;
	}
	public sealed class LinkAnchorState
	{
		public int Token;

		public int TargetA;

		public int TargetB;

		public float Ax;

		public float Ay;

		public float Az;

		public float Bx;

		public float By;

		public float Bz;
	}
	public sealed class DroneSnapshot
	{
		public string Epoch = "";

		public string Scene = "";

		public int Sequence;

		public double Time;

		public float MaxDistance;

		public float Noise;

		public List<DroneState> Drones = new List<DroneState>();

		public Dictionary<string, int> Pairs = new Dictionary<string, int>();

		public List<LinkAnchorState> Links = new List<LinkAnchorState>();
	}
	public static class DroneProtocol
	{
		public static bool Valid(DroneSnapshot s, double now)
		{
			if (s == null || s.Epoch == null || s.Epoch.Length != 32 || !Guid.TryParseExact(s.Epoch, "N", out var _) || s.Scene == null || s.Scene.Length > 80 || s.Sequence <= 0 || !DroneRules.SnapshotTime(s.Time, now) || !DroneRules.Finite(s.MaxDistance) || s.MaxDistance < 1f || s.MaxDistance > 12f || !DroneRules.Finite(s.Noise) || s.Noise < 0.01f || s.Noise > 0.35f || s.Drones == null || s.Drones.Count > 256 || s.Pairs == null || s.Pairs.Count > 512 || s.Links == null || s.Links.Count > 128)
			{
				return false;
			}
			HashSet<int> hashSet = new HashSet<int>();
			foreach (DroneState drone in s.Drones)
			{
				if (drone == null || drone.Drone <= 0 || drone.Target < 0 || !hashSet.Add(drone.Drone) || drone.Token < 0 || drone.Kind < DroneKind.LinkA || drone.Kind > DroneKind.Silencer || drone.TargetType < DroneTargetType.Physics || drone.TargetType > DroneTargetType.Player || (drone.TargetType == DroneTargetType.Player && drone.Kind != DroneKind.Silencer) || (drone.Attached && (drone.Target == 0 || !drone.Powered || ((drone.TargetType == DroneTargetType.Player) ? (drone.Collider != -1) : (drone.Collider < 0)) || drone.Battery <= 0f || (drone.State != 2 && drone.State != 3))) || (!DroneRules.Link(drone.Kind) && drone.Token != 0) || drone.State < 0 || drone.State > 4 || drone.Collider < -1 || !Coordinate(drone.X) || !Coordinate(drone.Y) || !Coordinate(drone.Z) || !DroneRules.Finite(drone.Battery) || drone.Battery < 0f || drone.Battery > 100f)
				{
					return false;
				}
			}
			foreach (KeyValuePair<string, int> pair in s.Pairs)
			{
				if (pair.Value <= 0 || pair.Key == null || pair.Key.Length > 100)
				{
					return false;
				}
				if (pair.Key == "__next")
				{
					continue;
				}
				if (DroneRules.NativeName(pair.Key))
				{
					if (!int.TryParse(pair.Key.Substring(pair.Key.LastIndexOf('/') + 1), out var result2) || result2 <= 0)
					{
						return false;
					}
					continue;
				}
				if (pair.Key.StartsWith("pendingA/", StringComparison.Ordinal) || pair.Key.StartsWith("pendingB/", StringComparison.Ordinal))
				{
					if (!int.TryParse(pair.Key.Substring(9), out var result3) || result3 <= 0)
					{
						return false;
					}
					continue;
				}
				return false;
			}
			HashSet<int> hashSet2 = new HashSet<int>();
			foreach (LinkAnchorState link in s.Links)
			{
				if (link == null || link.Token <= 0 || !hashSet2.Add(link.Token) || link.TargetA <= 0 || link.TargetB <= 0 || link.TargetA == link.TargetB || !Coordinate(link.Ax) || !Coordinate(link.Ay) || !Coordinate(link.Az) || !Coordinate(link.Bx) || !Coordinate(link.By) || !Coordinate(link.Bz))
				{
					return false;
				}
			}
			return true;
		}

		private static bool Coordinate(float n)
		{
			if (DroneRules.Finite(n))
			{
				return Math.Abs(n) < 1000f;
			}
			return false;
		}
	}
	public enum DroneKind
	{
		LinkA,
		LinkB,
		GhostValue,
		Silencer
	}
	public static class DroneRules
	{
		public const string LinkAName = "Item Utility Link A";

		public const string LinkBName = "Item Utility Link B";

		public static bool Finite(float n)
		{
			if (!float.IsNaN(n))
			{
				return !float.IsInfinity(n);
			}
			return false;
		}

		public static bool Finite(double n)
		{
			if (!double.IsNaN(n))
			{
				return !double.IsInfinity(n);
			}
			return false;
		}

		public static float Distance(float n)
		{
			if (!Finite(n))
			{
				return 3.5f;
			}
			return Math.Max(1f, Math.Min(12f, n));
		}

		public static float Noise(float n)
		{
			if (!Finite(n))
			{
				return 0.08f;
			}
			return Math.Max(0.01f, Math.Min(0.35f, n));
		}

		public static bool Link(DroneKind k)
		{
			if (k != DroneKind.LinkA)
			{
				return k == DroneKind.LinkB;
			}
			return true;
		}

		public static bool SnapshotTime(double time, double now)
		{
			if (Finite(time) && Finite(now) && time <= now + 1.0)
			{
				return now - time < 3.0;
			}
			return false;
		}

		public static bool NativeName(string name)
		{
			if (name != null && name.Length < 100)
			{
				if (!name.StartsWith("Item Utility Link A/", StringComparison.Ordinal))
				{
					return name.StartsWith("Item Utility Link B/", StringComparison.Ordinal);
				}
				return true;
			}
			return false;
		}

		public static int NextToken(Dictionary<string, int> store)
		{
			int value;
			int num = (store.TryGetValue("__next", out value) ? value : 0);
			if (num < 0 || num == int.MaxValue)
			{
				throw new InvalidOperationException("Invalid pair sequence");
			}
			return store["__next"] = num + 1;
		}

		public static int AssignPending(Dictionary<string, int> store, string name, bool a)
		{
			if (!NativeName(name))
			{
				return 0;
			}
			if (store.TryGetValue(name, out var value) && value > 0)
			{
				return value;
			}
			string text = (a ? "pendingA/" : "pendingB/");
			int num = int.MaxValue;
			string text2 = null;
			foreach (KeyValuePair<string, int> item in store)
			{
				if (item.Key.StartsWith(text, StringComparison.Ordinal) && int.TryParse(item.Key.Substring(text.Length), out var result) && result > 0 && result < num)
				{
					num = result;
					text2 = item.Key;
				}
			}
			if (text2 == null)
			{
				return 0;
			}
			store.Remove(text2);
			store[name] = num;
			return num;
		}
	}
	public static class DroneVisuals
	{
		private static Material? lineMaterial;

		public static Texture2D Icon(DroneKind kind)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0060: 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_008a: 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_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[16384];
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num = ((float)j - 63.5f) / 64f;
					float num2 = ((float)i - 63.5f) / 64f;
					bool flag2;
					if (DroneRules.Link(kind))
					{
						Vector2 val2 = new Vector2(num + 0.25f, num2);
						bool num3 = Mathf.Abs(((Vector2)(ref val2)).magnitude - 0.26f) < 0.06f;
						val2 = new Vector2(num - 0.25f, num2);
						bool flag = Mathf.Abs(((Vector2)(ref val2)).magnitude - 0.26f) < 0.06f;
						flag2 = num3 || flag || (Mathf.Abs(num2) < 0.04f && Mathf.Abs(num) < 0.25f) || (Mathf.Abs(num2 + 0.62f) < 0.04f && ((kind == DroneKind.LinkA) ? (Mathf.Abs(num) < 0.13f) : (Mathf.Abs(Mathf.Abs(num) - 0.16f) < 0.08f)));
					}
					else
					{
						flag2 = ((kind != DroneKind.GhostValue) ? ((num > -0.55f && num < -0.12f && Mathf.Abs(num2) < 0.16f) || (num > -0.14f && num < 0.17f && Mathf.Abs(num2) < num + 0.35f) || (Mathf.Abs(num2 - num) < 0.07f && Mathf.Abs(num) < 0.6f)) : ((Mathf.Abs(num) + Mathf.Abs(num2) < 0.62f && Mathf.Abs(num) + Mathf.Abs(num2) > 0.49f) || (Mathf.Abs(num + num2) < 0.055f && Mathf.Abs(num) < 0.52f)));
					}
					array[i * 128 + j] = (flag2 ? DroneAssets.Color(kind) : Color.clear);
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			((Object)val).name = "Utility " + kind.ToString() + " icon";
			return val;
		}

		public static LineRenderer Tether(Transform parent)
		{
			//IL_0053: 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_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_004e: Expected O, but got Unknown
			if ((Object)(object)lineMaterial == (Object)null)
			{
				Shader obj = Shader.Find("Sprites/Default") ?? Shader.Find("Hidden/Internal-Colored");
				if ((Object)(object)obj == (Object)null)
				{
					throw new InvalidOperationException("No supported world-line shader");
				}
				lineMaterial = new Material(obj)
				{
					name = "Utility Drone tether material"
				};
			}
			GameObject val = new GameObject("Link Drone physical tether");
			val.transform.SetParent(parent, false);
			LineRenderer obj2 = val.AddComponent<LineRenderer>();
			((Renderer)obj2).sharedMaterial = lineMaterial;
			obj2.positionCount = 9;
			obj2.useWorldSpace = true;
			float startWidth = (obj2.endWidth = 0.035f);
			obj2.startWidth = startWidth;
			((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj2).receiveShadows = false;
			return obj2;
		}

		public static Color PairColor(int token)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return Color.HSVToRGB((float)token * 0.618034f % 1f, 0.65f, 1f);
		}
	}
	public static class GhostExtraction
	{
		private static readonly FieldRef<RoundDirector, int> CurrentHaul = AccessTools.FieldRefAccess<RoundDirector, int>("currentHaul");

		private static readonly FieldRef<RoundDirector, int> MaximumHaul = AccessTools.FieldRefAccess<RoundDirector, int>("currentHaulMax");

		private static readonly FieldRef<ValuableObject, float> Value = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueCurrent");

		private static readonly FieldRef<ValuableObject, float> OriginalValue = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueOriginal");

		private static readonly HashSet<GameObject> held = new HashSet<GameObject>();

		private static readonly List<GameObject> remove = new List<GameObject>();

		public static int SuppressedCount => held.Count;

		private static bool Ghost(GameObject go)
		{
			if ((Object)(object)go != (Object)null && go.activeInHierarchy && (Object)(object)go.GetComponent<ValuableObject>() != (Object)null && (Object)(object)DroneDirector.Instance != (Object)null)
			{
				return DroneDirector.Instance.HasEffect((Component?)(object)go.GetComponent<PhysGrabObject>(), DroneKind.GhostValue);
			}
			return false;
		}

		public static void Refresh()
		{
			if ((Object)(object)RoundDirector.instance == (Object)null || SemiFunc.RunIsShop())
			{
				held.Clear();
				return;
			}
			List<GameObject> dollarHaulList = RoundDirector.instance.dollarHaulList;
			bool flag = false;
			remove.Clear();
			foreach (GameObject item in held)
			{
				if ((Object)(object)item == (Object)null || !item.activeInHierarchy)
				{
					remove.Add(item);
				}
				else
				{
					if (Ghost(item))
					{
						continue;
					}
					RoomVolumeCheck component = item.GetComponent<RoomVolumeCheck>();
					if ((Object)(object)component != (Object)null)
					{
						component.CheckSet();
						if (NativeAccess.InExtractor.Invoke(component) && !dollarHaulList.Contains(item))
						{
							dollarHaulList.Add(item);
							flag = true;
						}
					}
					remove.Add(item);
				}
			}
			foreach (GameObject item2 in remove)
			{
				held.Remove(item2);
			}
			for (int num = dollarHaulList.Count - 1; num >= 0; num--)
			{
				if (Ghost(dollarHaulList[num]))
				{
					held.Add(dollarHaulList[num]);
					dollarHaulList.RemoveAt(num);
					flag = true;
				}
			}
			if (!flag || !NativeAccess.Host)
			{
				return;
			}
			int num2 = 0;
			int num3 = 0;
			foreach (GameObject item3 in dollarHaulList)
			{
				if ((Object)(object)item3 != (Object)null)
				{
					ValuableObject component2 = item3.GetComponent<ValuableObject>();
					if (component2 != null)
					{
						num2 += (int)Value.Invoke(component2);
						num3 += (int)OriginalValue.Invoke(component2);
					}
				}
			}
			foreach (ItemValuableBox valuableBoxHaul in RoundDirector.instance.valuableBoxHaulList)
			{
				if ((Object)(object)valuableBoxHaul != (Object)null)
				{
					num2 += (int)valuableBoxHaul.CurrentValue;
				}
			}
			CurrentHaul.Invoke(RoundDirector.instance) = num2;
			MaximumHaul.Invoke(RoundDirector.instance) = num3;
		}

		public static void Clear()
		{
			held.Clear();
			remove.Clear();
		}
	}
	[HarmonyPatch]
	internal static class GhostBeforeCountOrSuction
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(RoundDirector), "Update", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(RoundDirector), "HaulCheck", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ExtractionPoint), "HaulInternalStatsUpdate", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ExtractionPoint), "DestroyTheFirstPhysObjectsInHaulList", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ExtractionPoint), "DestroyAllPhysObjectsInHaulList", (Type[])null, (Type[])null);
		}

		private static void Prefix()
		{
			GhostExtraction.Refresh();
		}
	}
	public static class GhostPhase
	{
		private sealed class Pair
		{
			public Collider Cargo;

			public Collider Player;

			public PhysGrabObject Target;

			public bool Local;
		}

		private static readonly FieldRef<PlayerAvatar, PlayerTumble> Tumble = AccessTools.FieldRefAccess<PlayerAvatar, PlayerTumble>("tumble");

		private static readonly Dictionary<long, Pair> owned = new Dictionary<long, Pair>();

		private static readonly HashSet<long> desired = new HashSet<long>();

		private static readonly Dictionary<Collider, bool> players = new Dictionary<Collider, bool>();

		private static readonly List<long> remove = new List<long>();

		private static float nextScan;

		public static int OwnedCollisionPairs => owned.Count;

		private static long Key(Collider cargo, Collider player)
		{
			return (long)(((ulong)(uint)((Object)cargo).GetInstanceID() << 32) | (uint)((Object)player).GetInstanceID());
		}

		private static void AddPlayers(Component? root, bool local)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && val.enabled && ((Component)val).gameObject.activeInHierarchy && !val.isTrigger)
				{
					players[val] = (players.TryGetValue(val, out var value) ? (value || local) : local);
				}
			}
		}

		public static void Refresh(bool immediate = false)
		{
			if (!immediate && Time.unscaledTime < nextScan)
			{
				return;
			}
			nextScan = Time.unscaledTime + 0.1f;
			players.Clear();
			desired.Clear();
			if ((Object)(object)GameDirector.instance != (Object)null)
			{
				foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
				{
					if ((Object)(object)player != (Object)null)
					{
						bool local = !NativeAccess.Multiplayer || ((Object)(object)player.photonView != (Object)null && player.photonView.IsMine);
						AddPlayers((Component?)(object)player, local);
						AddPlayers((Component?)(object)Tumble.Invoke(player), local);
						AddPlayers((Component?)(object)player.playerPhysPusher, local);
					}
				}
			}
			AddPlayers((Component?)(object)PlayerController.instance, local: true);
			DroneDirector instance = DroneDirector.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				foreach (UtilityDrone item in UtilityDrone.Active)
				{
					if ((Object)(object)item == (Object)null || item.Kind != DroneKind.GhostValue)
					{
						continue;
					}
					PhysGrabObject val = instance.EffectTarget(item);
					if ((Object)(object)val == (Object)null || !instance.HasEffect((Component?)(object)val, DroneKind.GhostValue))
					{
						continue;
					}
					Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true);
					foreach (Collider val2 in componentsInChildren)
					{
						if ((Object)(object)val2 == (Object)null || !val2.enabled || val2.isTrigger || !((Component)val2).gameObject.activeInHierarchy || (Object)(object)val2.attachedRigidbody != (Object)(object)val.rb)
						{
							continue;
						}
						foreach (KeyValuePair<Collider, bool> player2 in players)
						{
							long num = Key(val2, player2.Key);
							desired.Add(num);
							if (owned.TryGetValue(num, out Pair value))
							{
								value.Local = player2.Value;
								if (!Physics.GetIgnoreCollision(val2, player2.Key))
								{
									Physics.IgnoreCollision(val2, player2.Key, true);
								}
							}
							else if (!Physics.GetIgnoreCollision(val2, player2.Key))
							{
								Physics.IgnoreCollision(val2, player2.Key, true);
								owned.Add(num, new Pair
								{
									Cargo = val2,
									Player = player2.Key,
									Target = val,
									Local = player2.Value
								});
							}
						}
					}
				}
			}
			remove.Clear();
			foreach (KeyValuePair<long, Pair> item2 in owned)
			{
				Pair value2 = item2.Value;
				if (!desired.Contains(item2.Key))
				{
					if (!Alive(value2.Cargo) || !Alive(value2.Player))
					{
						remove.Add(item2.Key);
					}
					else if (!Overlapping(value2.Player, value2.Cargo))
					{
						Physics.IgnoreCollision(value2.Cargo, value2.Player, false);
						remove.Add(item2.Key);
					}
				}
			}
			foreach (long item3 in remove)
			{
				owned.Remove(item3);
			}
		}

		private static bool Alive(Collider c)
		{
			if ((Object)(object)c != (Object)null && c.enabled)
			{
				return ((Component)c).gameObject.activeInHierarchy;
			}
			return false;
		}

		private static bool Overlapping(Collider player, Collider cargo)
		{
			//IL_0001: 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_000a: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = player.bounds;
			if (!((Bounds)(ref bounds)).Intersects(cargo.bounds))
			{
				return false;
			}
			if (!(player is CapsuleCollider) && !(player is BoxCollider) && !(player is SphereCollider))
			{
				MeshCollider val = (MeshCollider)(object)((player is MeshCollider) ? player : null);
				if (val == null || !val.convex)
				{
					return true;
				}
			}
			Vector3 val2 = default(Vector3);
			float num = default(float);
			return Physics.ComputePenetration(player, ((Component)player).transform.position, ((Component)player).transform.rotation, cargo, ((Component)cargo).transform.position, ((Component)cargo).transform.rotation, ref val2, ref num);
		}

		public static bool IgnoreLocalGround(Collider c)
		{
			PhysGrabObject target = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponentInParent<PhysGrabObject>() : null);
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			DroneDirector? instance = DroneDirector.Instance;
			if (instance != null && instance.HasEffect((Component?)(object)target, DroneKind.GhostValue))
			{
				return true;
			}
			return owned.Values.Any((Pair pair) => pair.Local && (Object)(object)pair.Target == (Object)(object)target && Alive(pair.Player));
		}

		public static Collider[] GroundOverlap(Vector3 position, float radius, int mask, QueryTriggerInteraction query)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return (from c in Physics.OverlapSphere(position, radius, mask, query)
				where !IgnoreLocalGround(c)
				select c).ToArray();
		}

		public static void Clear()
		{
			foreach (Pair value in owned.Values)
			{
				if (Alive(value.Cargo) && Alive(value.Player))
				{
					Physics.IgnoreCollision(value.Cargo, value.Player, false);
				}
			}
			owned.Clear();
			desired.Clear();
			players.Clear();
			remove.Clear();
			nextScan = 0f;
		}
	}
	[HarmonyPatch]
	internal static class GhostGrounding
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(PlayerCollisionGrounded), "ColliderCheck", (Type[])null, (Type[])null));
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo original = AccessTools.Method(typeof(Physics), "OverlapSphere", new Type[4]
			{
				typeof(Vector3),
				typeof(float),
				typeof(int),
				typeof(QueryTriggerInteraction)
			}, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(GhostPhase), "GroundOverlap", (Type[])null, (Type[])null);
			int matches = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, original))
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = replacement;
					matches++;
				}
				yield return instruction;
			}
			if (matches != 1)
			{
				throw new InvalidOperationException("Native grounding changed; expected one overlap call, found " + matches);
			}
		}
	}
	public sealed class LinkConstraint : MonoBehaviour
	{
		public UtilityDrone A;

		public UtilityDrone B;

		private PhysGrabObject? targetA;

		private PhysGrabObject? targetB;

		private LineRenderer line;

		private float limit;

		private Vector3 localA;

		private Vector3 localB;

		private Rigidbody? solverA;

		private Rigidbody? solverB;

		public ConfigurableJoint? Joint { get; private set; }

		public bool AnchorsBound { get; private set; }

		public Vector3 WorldA
		{
			get
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				if (!AnchorsBound || !((Object)(object)targetA != (Object)null))
				{
					return A.Anchor;
				}
				return ((Component)targetA).transform.TransformPoint(localA);
			}
		}

		public Vector3 WorldB
		{
			get
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				if (!AnchorsBound || !((Object)(object)targetB != (Object)null))
				{
					return B.Anchor;
				}
				return ((Component)targetB).transform.TransformPoint(localB);
			}
		}

		public bool Valid
		{
			get
			{
				if ((Object)(object)A != (Object)null && (Object)(object)B != (Object)null && A.Attached && B.Attached && A.PairToken > 0 && A.PairToken == B.PairToken)
				{
					return (Object)(object)A.Target != (Object)(object)B.Target;
				}
				return false;
			}
		}

		private void Awake()
		{
			line = DroneVisuals.Tether(((Component)this).transform);
		}

		private void FixedUpdate()
		{
			//IL_00e8: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			if (!Valid)
			{
				ReleaseJoint();
				((Renderer)line).enabled = false;
				return;
			}
			if (!NativeAccess.Host)
			{
				if ((Object)(object)Joint != (Object)null)
				{
					ReleaseJoint();
				}
				return;
			}
			float num = DroneDirector.Instance?.MaximumDistance ?? 3.5f;
			if ((Object)(object)Joint != (Object)null && ((Object)(object)targetA != (Object)(object)A.Target || (Object)(object)targetB != (Object)(object)B.Target || Mathf.Abs(num - limit) > 0.001f))
			{
				ReleaseJoint();
			}
			if ((Object)(object)Joint == (Object)null && (Object)(object)A.Target != (Object)null && (Object)(object)B.Target != (Object)null && NativeAccess.Finite(A.Anchor) && NativeAccess.Finite(B.Anchor) && Vector3.Distance(A.Anchor, B.Anchor) <= num)
			{
				targetA = A.Target;
				targetB = B.Target;
				limit = num;
				localA = ((Component)targetA.rb).transform.InverseTransformPoint(A.Anchor);
				localB = ((Component)targetB.rb).transform.InverseTransformPoint(B.Anchor);
				AnchorsBound = true;
				solverA = targetA.rb;
				solverB = targetB.rb;
				LinkSolver.Acquire(solverA);
				LinkSolver.Acquire(solverB);
				Joint = ((Component)targetA).gameObject.AddComponent<ConfigurableJoint>();
				((Joint)Joint).connectedBody = targetB.rb;
				((Joint)Joint).autoConfigureConnectedAnchor = false;
				((Joint)Joint).anchor = localA;
				((Joint)Joint).connectedAnchor = localB;
				ConfigurableJoint? joint = Joint;
				ConfigurableJoint? joint2 = Joint;
				ConfigurableJoint? joint3 = Joint;
				ConfigurableJointMotion val = (ConfigurableJointMotion)1;
				joint3.zMotion = (ConfigurableJointMotion)1;
				ConfigurableJointMotion xMotion = (joint2.yMotion = val);
				joint.xMotion = xMotion;
				ConfigurableJoint? joint4 = Joint;
				ConfigurableJoint? joint5 = Joint;
				ConfigurableJoint? joint6 = Joint;
				val = (ConfigurableJointMotion)2;
				joint6.angularZMotion = (ConfigurableJointMotion)2;
				xMotion = (joint5.angularYMotion = val);
				joint4.angularXMotion = xMotion;
				ConfigurableJoint? joint7 = Joint;
				SoftJointLimit linearLimit = default(SoftJointLimit);
				((SoftJointLimit)(ref linearLimit)).limit = limit;
				((SoftJointLimit)(ref linearLimit)).contactDistance = 0.15f;
				joint7.linearLimit = linearLimit;
				((Joint)Joint).enableCollision = true;
				((Joint)Joint).enablePreprocessing = false;
				Joint.projectionMode = (JointProjectionMode)0;
				targetA.rb.WakeUp();
				targetB.rb.WakeUp();
			}
			if ((Object)(object)Joint != (Object)null && (Object)(object)targetA != (Object)null && (Object)(object)targetB != (Object)null)
			{
				ApplyTension(targetA.rb, targetB.rb);
			}
		}

		private void ApplyTension(Rigidbody a, Rigidbody b)
		{
			//IL_0001: 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_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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0050: 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_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_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 worldA = WorldA;
			Vector3 worldB = WorldB;
			Vector3 val = worldB - worldA;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float fixedDeltaTime = Time.fixedDeltaTime;
			if (magnitude < 0.001f || fixedDeltaTime <= 0f || !NativeAccess.Finite(val))
			{
				return;
			}
			Vector3 val2 = val / magnitude;
			float num = Vector3.Dot(b.GetPointVelocity(worldB) - a.GetPointVelocity(worldA), val2);
			float num2 = Mathf.Max(0f, limit - magnitude) / fixedDeltaTime;
			float num3 = Mathf.Max(0f, magnitude - limit) * 0.35f / fixedDeltaTime;
			float num4 = num - num2 + num3;
			if (num4 <= 0f || magnitude + num * fixedDeltaTime < limit - 0.04f)
			{
				return;
			}
			float num5 = (a.isKinematic ? 0f : (1f / Mathf.Max(a.mass, 0.0001f))) + (b.isKinematic ? 0f : (1f / Mathf.Max(b.mass, 0.0001f)));
			if (num5 <= 1E-06f || !DroneRules.Finite(num5))
			{
				return;
			}
			float num6 = num4 / num5;
			if (DroneRules.Finite(num6))
			{
				if (!a.isKinematic)
				{
					a.AddForce(val2 * num6, (ForceMode)1);
				}
				if (!b.isKinematic)
				{
					b.AddForce(-val2 * num6, (ForceMode)1);
				}
			}
		}

		private void LateUpdate()
		{
			//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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			((Renderer)line).enabled = Valid;
			if (!Valid)
			{
				return;
			}
			Vector3 worldA = WorldA;
			Vector3 worldB = WorldB;
			if (!NativeAccess.Finite(worldA) || !NativeAccess.Finite(worldB))
			{
				((Renderer)line).enabled = false;
				return;
			}
			float num = Vector3.Distance(worldA, worldB);
			float num2 = DroneDirector.Instance?.MaximumDistance ?? 3.5f;
			float num3 = Mathf.Clamp(num2 - num, 0f, 1f) * 0.3f;
			for (int i = 0; i < 9; i++)
			{
				float num4 = (float)i / 8f;
				line.SetPosition(i, Vector3.Lerp(worldA, worldB, num4) - Vector3.up * Mathf.Sin(num4 * (float)Math.PI) * num3);
			}
			Color val = (Color)((num > num2 + 0.05f) ? new Color(1f, 0.2f, 0.1f) : DroneVisuals.PairColor(A.PairToken));
			LineRenderer obj = line;
			Color startColor = (line.endColor = val);
			obj.startColor = startColor;
		}

		public void ReleaseJoint()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Joint != (Object)null)
			{
				ConfigurableJoint? joint = Joint;
				ConfigurableJoint? joint2 = Joint;
				ConfigurableJoint? joint3 = Joint;
				ConfigurableJointMotion val = (ConfigurableJointMotion)2;
				joint3.zMotion = (ConfigurableJointMotion)2;
				ConfigurableJointMotion xMotion = (joint2.yMotion = val);
				joint.xMotion = xMotion;
				((Joint)Joint).connectedBody = null;
				Object.Destroy((Object)(object)Joint);
				Joint = null;
			}
			LinkSolver.Release(solverA);
			LinkSolver.Release(solverB);
			solverA = (solverB = null);
			targetA = (targetB = null);
			AnchorsBound = false;
		}

		public LinkAnchorState? Snapshot()
		{
			if (!((Object)(object)Joint != (Object)null) || !((Object)(object)targetA != (Object)null) || !((Object)(object)targetB != (Object)null))
			{
				return null;
			}
			return new LinkAnchorState
			{
				Token = A.PairToken,
				TargetA = NativeAccess.Id((Component)(object)targetA),
				TargetB = NativeAccess.Id((Component)(object)targetB),
				Ax = localA.x,
				Ay = localA.y,
				Az = localA.z,
				Bx = localB.x,
				By = localB.y,
				Bz = localB.z
			};
		}

		public void ReceiveAnchors(LinkAnchorState? state)
		{
			//IL_00a4: 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_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)
			if (NativeAccess.Host || state == null || (Object)(object)A.Target == (Object)null || (Object)(object)B.Target == (Object)null || NativeAccess.Id((Component)(object)A.Target) != state.TargetA || NativeAccess.Id((Component)(object)B.Target) != state.TargetB)
			{
				if (!NativeAccess.Host)
				{
					AnchorsBound = false;
				}
			}
			else
			{
				targetA = A.Target;
				targetB = B.Target;
				localA = new Vector3(state.Ax, state.Ay, state.Az);
				localB = new Vector3(state.Bx, state.By, state.Bz);
				AnchorsBound = true;
			}
		}

		private void OnDisable()
		{
			ReleaseJoint();
			if ((Object)(object)line != (Object)null)
			{
				((Renderer)line).enabled = false;
			}
		}
	}
	internal static class LinkSolver
	{
		private sealed class Lease
		{
			public int Count;

			public int Original;

			public int Velocity;

			public int Applied;

			public int AppliedVelocity;
		}

		private static readonly Dictionary<Rigidbody, Lease> leases = new Dictionary<Rigidbody, Lease>();

		public static void Acquire(Rigidbody body)
		{
			if (leases.TryGetValue(body, out Lease value))
			{
				value.Count++;
				return;
			}
			Lease lease = new Lease
			{
				Count = 1,
				Original = body.solverIterations,
				Velocity = body.solverVelocityIterations,
				Applied = Mathf.Max(body.solverIterations, 24),
				AppliedVelocity = Mathf.Max(body.solverVelocityIterations, 8)
			};
			leases.Add(body, lease);
			body.solverIterations = lease.Applied;
			body.solverVelocityIterations = lease.AppliedVelocity;
		}

		public static void Release(Rigidbody? body)
		{
			if (body == null || !leases.TryGetValue(body, out Lease value) || --value.Count > 0)
			{
				return;
			}
			leases.Remove(body);
			if ((Object)(object)body != (Object)null)
			{
				if (body.solverIterations == value.Applied)
				{
					body.solverIterations = value.Original;
				}
				if (body.solverVelocityIterations == value.AppliedVelocity)
				{
					body.solverVelocityIterations = value.Velocity;
				}
			}
		}
	}
	public static class NativeAccess
	{
		internal static readonly FieldRef<ItemDrone, bool> Activated = AccessTools.FieldRefAccess<ItemDrone, bool>("itemActivated");

		internal static readonly FieldRef<ItemDrone, bool> Magnet = AccessTools.FieldRefAccess<ItemDrone, bool>("magnetActive");

		internal static readonly FieldRef<ItemDrone, PhysGrabObject> Target = AccessTools.FieldRefAccess<ItemDrone, PhysGrabObject>("magnetTargetPhysGrabObject");

		internal static readonly FieldRef<ItemDrone, Transform> MagnetTransform = AccessTools.FieldRefAccess<ItemDrone, Transform>("magnetTarget");

		internal static readonly FieldRef<ItemDrone, Vector3> HitLocal = AccessTools.FieldRefAccess<ItemDrone, Vector3>("rayHitPosition");

		internal static readonly FieldRef<ItemDrone, Transform> DroneTransform = AccessTools.FieldRefAccess<ItemDrone, Transform>("droneTransform");

		private static readonly FieldRef<ItemDrone, PlayerAvatar> Player = AccessTools.FieldRefAccess<ItemDrone, PlayerAvatar>("playerAvatarTarget");

		internal static readonly FieldRef<PhysGrabObjectCollider, int> ColliderId = AccessTools.FieldRefAccess<PhysGrabObjectCollider, int>("colliderID");

		private static readonly MethodInfo SetNativeState = AccessTools.Method(typeof(ItemDrone), "StateSetRPC", (Type[])null, (Type[])null);

		private static readonly MethodInfo SetNativeTarget = AccessTools.Method(typeof(ItemDrone), "NewRayHitPointLogic", (Type[])null, (Type[])null);

		private static readonly MethodInfo SetNativeMagnet = AccessTools.Method(typeof(ItemDrone), "MagnetActiveToggleLogic", (Type[])null, (Type[])null);

		internal static readonly FieldRef<ItemAttributes, string> InstanceName = AccessTools.FieldRefAccess<ItemAttributes, string>("instanceName");

		internal static readonly FieldRef<StatsManager, SortedDictionary<string, Dictionary<string, int>>> Dictionaries = AccessTools.FieldRefAccess<StatsManager, SortedDictionary<string, Dictionary<string, int>>>("dictionaryOfDictionaries");

		internal static readonly FieldRef<StatsManager, Dictionary<string, int>> OwnedItems = AccessTools.FieldRefAccess<StatsManager, Dictionary<string, int>>("item");

		internal static readonly FieldRef<RoomVolumeCheck, bool> InExtractor = AccessTools.FieldRefAccess<RoomVolumeCheck, bool>("inExtractionPoint");

		internal static readonly FieldRef<PlayerAvatar, bool> PlayerDisabled = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isDisabled");

		private static readonly FieldRef<PlayerAvatar, bool> PlayerTumbling = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isTumbling");

		private static readonly FieldRef<PlayerAvatar, PlayerTumble> PlayerBody = AccessTools.FieldRefAccess<PlayerAvatar, PlayerTumble>("tumble");

		internal static readonly FieldRef<EnemyParent, bool> EnemySpawned = AccessTools.FieldRefAccess<EnemyParent, bool>("Spawned");

		internal static readonly FieldRef<RunManager, List<PlayerVoiceChat>> VoiceChats = AccessTools.FieldRefAccess<RunManager, List<PlayerVoiceChat>>("voiceChats");

		public static bool Host
		{
			get
			{
				if ((Object)(object)GameManager.instance != (Object)null)
				{
					return SemiFunc.IsMasterClientOrSingleplayer();
				}
				return false;
			}
		}

		public static bool Multiplayer
		{
			get
			{
				if ((Object)(object)GameManager.instance != (Object)null)
				{
					return SemiFunc.IsMultiplayer();
				}
				return false;
			}
		}

		public static int Id(Component component)
		{
			if (!Multiplayer)
			{
				return ((Object)component).GetInstanceID();
			}
			PhotonView component2 = component.GetComponent<PhotonView>();
			if (component2 == null)
			{
				return 0;
			}
			return component2.ViewID;
		}

		public static PhysGrabObject? Physics(int id)
		{
			if (!Multiplayer || id <= 0)
			{
				return null;
			}
			PhotonView obj = PhotonView.Find(id);
			if (obj == null)
			{
				return null;
			}
			return ((Component)obj).GetComponent<PhysGrabObject>();
		}

		public static PlayerAvatar? PlayerTarget(ItemDrone drone)
		{
			if (!((Object)(object)Player.Invoke(drone) != (Object)null))
			{
				if (!((Object)(object)drone.playerTumbleTarget != (Object)null))
				{
					return null;
				}
				return drone.playerTumbleTarget.playerAvatar;
			}
			return Player.Invoke(drone);
		}

		public static Component? SnapshotTarget(DroneState state)
		{
			if (state.TargetType != DroneTargetType.Player)
			{
				return (Component?)(object)Physics(state.Target);
			}
			PhotonView obj = PhotonView.Find(state.Target);
			if (obj == null)
			{
				return null;
			}
			return (Component?)(object)((Component)obj).GetComponent<PlayerAvatar>();
		}

		public static bool Finite(Vector3 value)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (DroneRules.Finite(value.x) && DroneRules.Finite(value.y))
			{
				return DroneRules.Finite(value.z);
			}
			return false;
		}

		public static Vector3 SnapshotHit(UtilityDrone drone)
		{
			//IL_002c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar playerTarget = drone.PlayerTarget;
			if (playerTarget == null)
			{
				return HitLocal.Invoke(drone.Drone);
			}
			return playerTarget.PlayerVisionTarget.VisionTransform.InverseTransformPoint(drone.Anchor);
		}

		private static bool Tumbling(PlayerAvatar player)
		{
			if (PlayerTumbling.Invoke(player))
			{
				return (Object)(object)PlayerBody.Invoke(player) != (Object)null;
			}
			return false;
		}

		public static int TargetCollider(ItemDrone drone)
		{
			Transform obj = MagnetTransform.Invoke(drone);
			PhysGrabObjectCollider val = ((obj != null) ? ((Component)obj).GetComponent<PhysGrabObjectCollider>() : null);
			if (val == null)
			{
				return -1;
			}
			return ColliderId.Invoke(val);
		}

		internal static bool Present(UtilityDrone utility, DroneState state)
		{
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Invalid comparison between Unknown and I4
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			ItemDrone drone = utility.Drone;
			if ((Object)(object)drone == (Object)null || (Object)(object)DroneTransform.Invoke(drone) == (Object)null || PhotonNetwork.MasterClient == null)
			{
				return false;
			}
			Component val = (state.Attached ? SnapshotTarget(state) : null);
			PlayerAvatar val2 = (PlayerAvatar)(object)((val is PlayerAvatar) ? val : null);
			object obj;
			if (val2 != null)
			{
				obj = (Tumbling(val2) ? ((Component)PlayerBody.Invoke(val2)).transform : val2.PlayerVisionTarget.VisionTransform);
			}
			else
			{
				PhysGrabObject val3 = (PhysGrabObject)(object)((val is PhysGrabObject) ? val : null);
				obj = ((val3 != null) ? val3.FindColliderFromID(state.Collider) : null);
			}
			Transform val4 = (Transform)obj;
			if (state.Attached && ((Object)(object)val == (Object)null || (Object)(object)val4 == (Object)null || !utility.CustomTargetingCondition(val.gameObject)))
			{
				return false;
			}
			utility.Battery.batteryLife = state.Battery;
			((Component)utility).GetComponent<ItemToggle>().toggleState = state.Powered;
			Activated.Invoke(drone) = state.Powered;
			if (state.Attached && (Object)(object)val != (Object)null && (Object)(object)val4 != (Object)null)
			{
				Vector3 val5 = default(Vector3);
				((Vector3)(ref val5))..ctor(state.X, state.Y, state.Z);
				PlayerAvatar val6 = (PlayerAvatar)(object)((val is PlayerAvatar) ? val : null);
				Vector3 val7 = ((val6 != null) ? val6.PlayerVisionTarget.VisionTransform.TransformPoint(val5) : val4.TransformPoint(val5));
				if ((Object)(object)utility.AttachedObject != (Object)(object)val || (Object)(object)MagnetTransform.Invoke(drone) != (Object)(object)val4 || Vector3.Distance(utility.Anchor, val7) > 0.025f)
				{
					MethodInfo setNativeTarget = SetNativeTarget;
					object[] obj2 = new object[4] { val7, state.Target, state.Collider, null };
					object obj3;
					if (state.TargetType != DroneTargetType.Player)
					{
						obj3 = val.transform;
					}
					else
					{
						PlayerAvatar val8 = (PlayerAvatar)(object)((val is PlayerAvatar) ? val : null);
						obj3 = ((val8 != null && Tumbling(val8)) ? val4 : null);
					}
					obj2[3] = obj3;
					setNativeTarget.Invoke(drone, obj2);
				}
			}
			if (Magnet.Invoke(drone) != state.Attached)
			{
				SetNativeMagnet.Invoke(drone, new object[1] { state.Attached });
			}
			if ((int)drone.currentState != state.State)
			{
				SetNativeState.Invoke(drone, new object[2]
				{
					state.State,
					(object)new PhotonMessageInfo(PhotonNetwork.MasterClient, PhotonNetwork.ServerTimestamp, ((Component)utility).GetComponent<PhotonView>())
				});
			}
			return true;
		}
	}
	public static class PairStore
	{
		public const string Key = "com.matsu.repoutilitydrones.linkPairs.v1";

		public static Dictionary<string, int>? Data
		{
			get
			{
				if ((Object)(object)StatsManager.instance == (Object)null)
				{
					return null;
				}
				SortedDictionary<string, Dictionary<string, int>> sortedDictionary = NativeAccess.Dictionaries.Invoke(StatsManager.instance);
				if (!sortedDictionary.TryGetValue("com.matsu.repoutilitydrones.linkPairs.v1", out var value))
				{
					value = new Dictionary<string, int>();
					sortedDictionary.Add("com.matsu.repoutilitydrones.linkPairs.v1", value);
				}
				return value;
			}
		}

		public static void AwardPartner(StatsManager stats)
		{
			Dictionary<string, int>? obj = Data ?? throw new InvalidOperationException("Stats not ready");
			int num = DroneRules.NextToken(obj);
			obj.Add("pendingA/" + num, 1);
			obj.Add("pendingB/" + num, 1);
			stats.ItemPurchase("Item Utility Link B");
		}

		public static void Bind(UtilityDrone drone)
		{
			if (NativeAccess.Host && DroneRules.Link(drone.Kind) && !SemiFunc.RunIsShop() && !string.IsNullOrEmpty(drone.InstanceName))
			{
				Dictionary<string, int> data = Data;
				if (data != null)
				{
					drone.PairToken = DroneRules.AssignPending(data, drone.InstanceName, drone.Kind == DroneKind.LinkA);
				}
			}
		}

		public static void Remove(string name)
		{
			if (NativeAccess.Host && DroneRules.NativeName(name))
			{
				Data?.Remove(name);
			}
		}

		public static void ClearForLoad()
		{
			Data?.Clear();
			DroneDirector.Instance?.SceneChanged();
		}
	}
	[HarmonyPatch(typeof(StatsManager), "Start")]
	internal static class PairDictionaryInit
	{
		private static void Postfix()
		{
			_ = PairStore.Data;
		}
	}
	[HarmonyPatch(typeof(StatsManager), "LoadGame")]
	internal static class PairLoad
	{
		private static void Prefix()
		{
			PairStore.ClearForLoad();
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemPurchase")]
	internal static class LinkKitPurchase
	{
		private static void Postfix(StatsManager __instance, string itemName)
		{
			if (itemName == "Item Utility Link A" && NativeAccess.Host && DroneAssets.Ready)
			{
				PairStore.AwardPartner(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemRemove")]
	internal static class PairLost
	{
		private static void Postfix(string instanceName)
		{
			PairStore.Remove(instanceName);
		}
	}
	[BepInPlugin("com.matsu.repoutilitydrones", "Repo Utility Drones", "0.1.1")]
	[BepInDependency("REPOLib", "4.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.matsu.repoutilitydrones";

		public const string Version = "0.1.1";

		internal static ManualLogSource Log;

		public static ConfigEntry<float> LinkDistance;

		public static ConfigEntry<float> SilencerFactor;

		private Harmony? patches;

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			LinkDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Link", "MaximumDistance", 3.5f, "Host setting: maximum distance in metres between target attachment points (1-12). No target teleporting.");
			SilencerFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Silencer", "NoiseMultiplier", 0.08f, "Host setting: attached valuable/item/weapon/player/enemy emitted audio, in-game voice and investigation radius multiplier (0.01-0.35). Does not deafen the target or change damage, mass, price or durability.");
			patches = new Harmony("com.matsu.repoutilitydrones");
			patches.PatchAll(typeof(Plugin).Assembly);
			DroneNetwork.Initialize();
			SceneManager.sceneLoaded += Loaded;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Utility Drones loaded; three drone kits, no screen-text overlay.");
		}

		private static void Loaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0012: 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_001d: Expected O, but got Unknown
			if ((Object)(object)DroneDirector.Instance == (Object)null)
			{
				GameObject val = new GameObject("Utility Drone Director");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<DroneDirector>();
			}
			DroneDirector.Instance.SceneChanged();
		}

		private void OnDestroy()
		{
			Log.LogInfo((object)"Utility Drone loader component destroyed; application-lifetime hooks retained.");
		}
	}
	public static class SilencerAudioScope
	{
		public readonly struct State
		{
			public readonly float Factor;

			public readonly Component? Emitter;

			public State(float previous, Component? owner)
			{
				Factor = previous;
				Emitter = owner;
			}
		}

		[ThreadStatic]
		private static float factor;

		[ThreadStatic]
		private static Component? emitter;

		public static float Factor
		{
			get
			{
				if (!(factor > 0f))
				{
					return 1f;
				}
				return factor;
			}
		}

		public static Component? Emitter => emitter;

		public static State Capture()
		{
			return new State(factor, emitter);
		}

		public static float Enter(float next)
		{
			float result = factor;
			factor = Math.Min(Factor, DroneRules.Noise(next));
			return result;
		}

		public static void Restore(float previous)
		{
			factor = previous;
		}

		public static State EnterEmitter(Component? source)
		{
			State result = new State(factor, emitter);
			Component val = SilencerTargets.Root(source);
			if ((Object)(object)val != (Object)null)
			{
				factor = (((Object)(object)val == (Object)(object)emitter) ? Math.Min(Factor, SilencerTargets.Factor(val)) : SilencerTargets.Factor(val));
				emitter = val;
			}
			return result;
		}

		public static void Restore(State state)
		{
			factor = state.Factor;
			emitter = state.Emitter;
		}
	}
	[HarmonyPatch]
	internal static class SilencerEmitterScope
	{
		private static readonly Dictionary<Type, FieldInfo?> capturedOwners = new Dictionary<Type, FieldInfo>();

		public static int TargetCount { get; private set; }

		private static bool SourceType(Type type)
		{
			if (typeof(Trap).IsAssignableFrom(type))
			{
				return true;
			}
			return new string[6] { "Enemy", "Item", "Player", "Valuable", "PhysGrab", "Musical" }.Any((string prefix) => type.Name.StartsWith(prefix, StringComparison.Ordinal));
		}

		private static Type? OwnerType(Type type)
		{
			if (typeof(MonoBehaviour).IsAssignableFrom(type))
			{
				return type;
			}
			if (!type.IsNested || !(type.DeclaringType != null) || !typeof(MonoBehaviour).IsAssignableFrom(type.DeclaringType) || !type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any((FieldInfo f) => f.Name == "<>4__this"))
			{
				return null;
			}
			return type.DeclaringType;
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			HashSet<MethodBase> hashSet = new HashSet<MethodBase>();
			Stopwatch stopwatch = Stopwatch.StartNew();
			foreach (Type item in typeof(ItemDrone).Assembly.GetTypes().Where(delegate(Type t)
			{
				Type type = OwnerType(t);
				return (object)type != null && SourceType(type);
			}))
			{
				MethodInfo[] methods = item.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && methodInfo.GetMethodBody() != null && (from i in PatchProcessor.GetOriginalInstructions((MethodBase)methodInfo, (ILGenerator)null)
						where i.opcode == OpCodes.Call || i.opcode == OpCodes.Callvirt
						select i.operand as MethodInfo).Any((MethodInfo m) => m != null && ((m.DeclaringType == typeof(Sound) && (m.Name == "Play" || m.Name == "PlayLoop")) || (m.DeclaringType == typeof(EnemyDirector) && m.Name == "SetInvestigate") || (m.DeclaringType == typeof(SemiFunc) && m.Name == "EnemyInvestigate") || (m.DeclaringType == typeof(Materials) && m.Name == "Impulse"))))
					{
						hashSet.Add(methodInfo);
					}
				}
			}
			TargetCount = hashSet.Count;
			Plugin.Log.LogInfo((object)("Silencer emitting-call scan: " + TargetCount + " native methods in " + stopwatch.ElapsedMilliseconds + " ms (startup only)."));
			return hashSet;
		}

		private static void Prefix(object __instance, out SilencerAudioScope.State __state)
		{
			Component val = (Component)((__instance is Component) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				Type type = __instance.GetType();
				if (!capturedOwners.TryGetValue(type, out FieldInfo value))
				{
					value = (capturedOwners[type] = AccessTools.Field(type, "<>4__this"));
				}
				object? obj = value?.GetValue(__instance);
				val = (Component)((obj is Component) ? obj : null);
			}
			__state = SilencerAudioScope.EnterEmitter(val);
		}

		private static Exception? Finalizer(Exception? __exception, SilencerAudioScope.State __state)
		{
			SilencerAudioScope.Restore(__state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(EnemyDirector), "SetInvestigate")]
	internal static class SilencerHearing
	{
		private static void Prefix(ref float __1)
		{
			__1 *= SilencerAudioScope.Factor;
		}
	}
	[HarmonyPatch(typeof(Sound), "Play", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(float),
		typeof(float),
		typeof(float)
	})]
	internal static class SilencerOneShot
	{
		private static void Prefix(Sound __instance, ref float volumeMultiplier)
		{
			if ((Object)(object)__instance.Source != (Object)null)
			{
				SilencerSources.Bind(__instance.Source, SilencerAudioScope.Emitter ?? SilencerTargets.Root((Component?)(object)__instance.Source));
			}
			else
			{
				volumeMultiplier *= SilencerAudioScope.Factor;
			}
		}
	}
	[HarmonyPatch(typeof(Sound), "PlayLoop")]
	internal static class SilencerLoop
	{
		private static void Prefix(Sound __instance)
		{
			SilencerSources.Bind(__instance.Source, SilencerAudioScope.Emitter ?? SilencerTargets.Root((Component?)(object)__instance.Source));
		}
	}
	[HarmonyPatch]
	internal static class SilencerFollowTarget
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(Sound).GetMethods()
				where m.Name == "Play" && m.GetParameters().Length != 0 && m.GetParameters()[0].ParameterType == typeof(Transform)
				select m;
		}

		private static void Prefix(Transform? __0, out SilencerAudioScope.State __state)
		{
			__state = (((Object)(object)SilencerAudioScope.Emitter == (Object)null) ? SilencerAudioScope.EnterEmitter((Component?)(object)__0) : SilencerAudioScope.Capture());
		}

		private static Exception? Finalizer(Exception? __exception, SilencerAudioScope.State __state)
		{
			SilencerAudioScope.Restore(__state);
			return __exception;
		}
	}
	public static class SilencerSources
	{
		private sealed class Lease
		{
			public AudioSource Source;

			public Component Owner;

			public float Original;

			public float Applied;

			public bool HasApplied;
		}

		private static readonly Dictionary<AudioSource, Lease> leases = new Dictionary<AudioSource, Lease>();

		private static readonly Dictionary<Type, FieldInfo[]> soundFields = new Dictionary<Type, FieldInfo[]>();

		private static readonly FieldRef<PlayerVoiceChat, PlayerAvatar> VoicePlayer = AccessTools.FieldRefAccess<PlayerVoiceChat, PlayerAvatar>("playerAvatar");

		private static float nextScan;

		public static int OwnedSources => leases.Count;

		public static void Bind(AudioSource? source, Component? owner)
		{
			Component val = SilencerTargets.Root(owner);
			if (!((Object)(object)source == (Object)null) && !((Object)(object)val == (Object)null) && !(SilencerTargets.Factor(val) >= 1f))
			{
				if (leases.TryGetValue(source, out Lease value))
				{
					value.Owner = val;
					return;
				}
				leases.Add(source, new Lease
				{
					Source = source,
					Owner = val
				});
			}
		}

		private static void Restore(Lease lease)
		{
			if ((Object)(object)lease.Source != (Object)null && lease.HasApplied && Mathf.Abs(lease.Source.volume - lease.Applied) < 1E-05f)
			{
				lease.Source.volume = lease.Original;
			}
			lease.HasApplied = false;
		}

		public static void BeginFrame()
		{
			foreach (Lease value in leases.Values)
			{
				Restore(value);
			}
		}

		public static void ReleaseInactive()
		{
			KeyValuePair<AudioSource, Lease>[] array = leases.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<AudioSource, Lease> keyValuePair = array[i];
				if ((Object)(object)keyValuePair.Key == (Object)null || (Object)(object)keyValuePair.Value.Owner == (Object)null || SilencerTargets.Factor(keyValuePair.Value.Owner) >= 1f)
				{
					Restore(keyValuePair.Value);
					leases.Remove(keyValuePair.Key);
				}
			}
		}

		public static void ApplyFrame()
		{
			ReleaseInactive();
			if (Time.unscaledTime >= nextScan)
			{
				nextScan = Time.unscaledTime + 0.2f;
				Scan();
			}
			foreach (Lease value in leases.Values)
			{
				if (!((Object)(object)value.Source == (Object)null) && ((Behaviour)value.Source).enabled && ((Component)value.Source).gameObject.activeInHierarchy)
				{
					Restore(value);
					value.Original = value.Source.volume;
					value.Applied = value.Original * SilencerTargets.Factor(value.Owner);
					value.Source.volume = value.Applied;
					value.HasApplied = true;
				}
			}
		}

		private static void Scan()
		{
			if ((Object)(object)DroneDirector.Instance == (Object)null)
			{
				return;
			}
			HashSet<Component> hashSet = new HashSet<Component>();
			foreach (UtilityDrone item in UtilityDrone.Active)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Component val = SilencerTargets.Root(DroneDirector.Instance.SilencerTarget(item));
				if ((Object)(object)val == (Object)null || !hashSet.Add(val))
				{
					continue;
				}
				AudioSource[] componentsInChildren = val.GetComponentsInChildren<AudioSource>();
				foreach (AudioSource val2 in componentsInChildren)
				{
					if (SilencerTargets.Same((Component?)(object)val2, val))
					{
						Bind(val2, val);
					}
				}
				MonoBehaviour[] componentsInChildren2 = val.GetComponentsInChildren<MonoBehaviour>();
				foreach (MonoBehaviour val3 in componentsInChildren2)
				{
					if ((Object)(object)val3 == (Object)null || !SilencerTargets.Same((Component?)(object)val3, val))
					{
						continue;
					}
					if (!soundFields.TryGetValue(((object)val3).GetType(), out FieldInfo[] value))
					{
						List<FieldInfo> list = new List<FieldInfo>();
						Type type = ((object)val3).GetType();
						while (type != null && type != typeof(MonoBehaviour))
						{
							list.AddRange(from f in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
								where f.FieldType == typeof(Sound) || f.FieldType == typeof(Sound[]) || f.FieldType == typeof(List<Sound>)
								select f);
							type = type.BaseType;
						}
						value = (soundFields[((object)val3).GetType()] = list.ToArray());
					}
					FieldInfo[] array2 = value;
					for (int num = 0; num < array2.Length; num++)
					{
						object value2 = array2[num].GetValue(val3);
						Sound val4 = (Sound)((value2 is Sound) ? value2 : null);
						if (val4 != null)
						{
							Bind(val4.Source, val);
						}
						else
						{
							if (!(value2 is IEnumerable<Sound> enumerable))
							{
								continue;
							}
							foreach (Sound item2 in enumerable)
							{
								if (item2 != null)
								{
									Bind(item2.Source, val);
								}
							}
						}
					}
				}
				PlayerAvatar val5 = (PlayerAvatar)(object)((val is PlayerAvatar) ? val : null);
				if (val5 == null || !((Object)(object)RunManager.instance != (Object)null))
				{
					continue;
				}
				foreach (PlayerVoiceChat item3 in NativeAccess.VoiceChats.Invoke(RunManager.instance))
				{
					if ((Object)(object)item3 != (Object)null && (Object)(object)VoicePlayer.Invoke(item3) == (Object)(object)val5)
					{
						componentsInChildren = ((Component)item3).GetComponentsInChildren<AudioSource>();
						for (int i = 0; i < componentsInChildren.Length; i++)
						{
							Bind(componentsInChildren[i], (Component?)(object)val5);
						}
					}
				}
			}
		}

		public static void Clear()
		{
			foreach (Lease value in leases.Values)
			{
				Restore(value);
			}
			leases.Clear();
			nextScan = 0f;
		}
	}
	[DefaultExecutionOrder(-10000)]
	public sealed class SilencerFrameRestore : MonoBehaviour
	{
		private void Update()
		{
			SilencerSources.BeginFrame();
		}

		private void OnDestroy()
		{
			SilencerSources.Clear();
		}
	}
	public static class SilencerTargets
	{
		private static readonly FieldRef<PlayerVoiceChat, PlayerAvatar> VoicePlayer = AccessTools.FieldRefAccess<PlayerVoiceChat, PlayerAvatar>("playerAvatar");

		public static Component? Root(Component? source)
		{
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			PlayerVoiceChat val = (PlayerVoiceChat)(object)((source is PlayerVoiceChat) ? source : null);
			if (val != null)
			{
				return (Component?)(object)VoicePlayer.Invoke(val);
			}
			PlayerVoiceChat componentInParent = source.GetComponentInParent<PlayerVoiceChat>(true);
			if ((Object)(object)componentInParent != (Object)null)
			{
				return (Component?)(object)VoicePlayer.Invoke(componentInParent);
			}
			PlayerController val2 = (PlayerController)(object)((source is PlayerController) ? source : null);
			if (val2 != null)
			{
				return (Component?)(object)val2.playerAvatarScript;
			}
			PhysGrabObject componentInParent2 = source.GetComponentInParent<PhysGrabObject>(true);
			if ((Object)(object)componentInParent2 != (Object)null && ((Object)(object)((Component)componentInParent2).GetComponent<ItemAttributes>() != (Object)null || (Object)(object)((Component)componentInParent2).GetComponent<ValuableObject>() != (Object)null))
			{
				return (Component?)(object)componentInParent2;
			}
			PlayerTumble componentInParent3 = source.GetComponentInParent<PlayerTumble>(true);
			if ((Object)(object)componentInParent3 != (Object)null)
			{
				return (Component?)(object)componentInParent3.playerAvatar;
			}
			PlayerAvatar componentInParent4 = source.GetComponentInParent<PlayerAvatar>(true);
			if ((Object)(object)componentInParent4 != (Object)null)
			{
				return (Component?)(object)componentInParent4;
			}
			PlayerController componentInParent5 = source.GetComponentInParent<PlayerController>(true);
			if ((Object)(object)componentInParent5 != (Object)null)
			{
				return (Component?)(object)componentInParent5.playerAvatarScript;
			}
			EnemyParent componentInParent6 = source.GetComponentInParent<EnemyParent>(true);
			if (!((Object)(object)componentInParent6 != (Object)null))
			{
				return (Component?)(object)componentInParent2;
			}
			return (Component?)(object)componentInParent6;
		}

		public static bool Same(Component? a, Component? b)
		{
			Component val = Root(a);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)val == (Object)(object)Root(b);
			}
			return false;
		}

		public static float Factor(Component? source)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)DroneDirector.Instance == (Object)null)
			{
				return 1f;
			}
			if (!DroneDirector.Instance.HasEffect(source, DroneKind.Silencer))
			{
				return 1f;
			}
			return DroneDirector.Instance.NoiseFactor;
		}
	}
	public sealed class UtilityDrone : MonoBehaviour, ITargetingCondition
	{
		public static readonly List<UtilityDrone> Active = new List<UtilityDrone>();

		public DroneKind Kind;

		private ItemEquippable equipment;

		private ItemAttributes attributes;

		private ItemToggle toggle;

		public int PairToken { get; internal set; }

		public ItemDrone Drone { get; private set; }

		public ItemBattery Battery { get; private set; }

		public PhysGrabObject Physics { get; private set; }

		public int Id => NativeAccess.Id((Component)(object)this);

		public string InstanceName
		{
			get
			{
				if (!((Object)(object)attributes != (Object)null))
				{
					return "";
				}
				return NativeAccess.InstanceName.Invoke(attributes) ?? "";
			}
		}

		public bool Powered
		{
			get
			{
				if ((Object)(object)Drone != (Object)null && ((Behaviour)this).isActiveAndEnabled && (Object)(object)toggle != (Object)null && toggle.toggleState && NativeAccess.Activated.Invoke(Drone) && (Object)(object)Battery != (Object)null && Battery.batteryLife > 0f && (Object)(object)equipment != (Object)null && !equipment.IsEquipped())
				{
					return !SemiFunc.RunIsShop();
				}
				return false;
			}
		}

		public bool Attached
		{
			get
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Invalid comparison between Unknown and I4
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Invalid comparison between Unknown and I4
				if (Powered && ((int)Drone.currentState == 3 || (int)Drone.currentState == 2) && NativeAccess.Magnet.Invoke(Drone) && (Object)(object)AttachedObject != (Object)null && AttachedObject.gameObject.activeInHierarchy)
				{
					return CustomTargetingCondition(AttachedObject.gameObject);
				}
				return false;
			}
		}

		public PhysGrabObject? Target
		{
			get
			{
				if (!((Object)(object)Drone != (Object)null))
				{
					return null;
				}
				return NativeAccess.Target.Invoke(Drone);
			}
		}

		public PlayerAvatar? PlayerTarget
		{
			get
			{
				if (!((Object)(object)Drone != (Object)null))
				{
					return null;
				}
				return NativeAccess.PlayerTarget(Drone);
			}
		}

		public Component? AttachedObject
		{
			get
			{
				if (Kind != DroneKind.Silencer || !((Object)(object)PlayerTarget != (Object)null))
				{
					return (Component?)(object)Target;
				}
				return (Component?)(object)PlayerTarget;
			}
		}

		public Vector3 Anchor
		{
			get
			{
				//IL_004c: 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_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)Drone != (Object)null) || !((Object)(object)NativeAccess.MagnetTransform.Invoke(Drone) != (Object)null))
				{
					if (!((Object)(object)Target != (Object)null))
					{
						return ((Component)this).transform.position;
					}
					return ((Component)Target).transform.position;
				}
				return NativeAccess.MagnetTransform.Invoke(Drone).TransformPoint(NativeAccess.HitLocal.Invoke(Drone));
			}
		}

		private void Awake()
		{
			Drone = ((Component)this).GetComponent<ItemDrone>();
			Battery = ((Component)this).GetComponent<ItemBattery>();
			Physics = ((Component)this).GetComponent<PhysGrabObject>();
			equipment = ((Component)this).GetComponent<ItemEquippable>();
			attributes = ((Component)this).GetComponent<ItemAttributes>();
			toggle = ((Component)this).GetComponent<ItemToggle>();
		}

		private void OnEnable()
		{
			if (!Active.Contains(this))
			{
				Active.Add(this);
			}
		}

		private void OnDisable()
		{
			Active.Remove(this);
			DroneDirector.Instance?.Release(this);
		}

		public bool CustomTargetingCondition(GameObject target)
		{
			if ((Object)(object)target == (Object)null || (Object)(object)target == (Object)(object)((Component)this).gameObject)
			{
				return false;
			}
			if (Kind == DroneKind.Silencer)
			{
				PlayerAvatar val = target.GetComponent<PlayerAvatar>() ?? target.GetComponentInParent<PlayerTumble>()?.playerAvatar;
				if ((Object)(object)val != (Object)null)
				{
					return !NativeAccess.PlayerDisabled.Invoke(val);
				}
				EnemyParent componentInParent = target.GetComponentInParent<EnemyParent>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					if (NativeAccess.EnemySpawned.Invoke(componentInParent))
					{
						return (Object)(object)target.GetComponent<PhysGrabObject>() != (Object)null;
					}
					return false;
				}
				if ((Object)(object)target.GetComponent<Rigidbody>() != (Object)null)
				{
					return (Object)(object)target.GetComponent<PhysGrabObject>() != (Object)null;
				}
				return false;
			}
			if ((Object)(object)target.GetComponent<Rigidbody>() == (Object)null || (Object)(object)target.GetComponent<PhysGrabObject>() == (Object)null)
			{
				return false;
			}
			if ((Object)(object)target.GetComponentInParent<EnemyParent>() != (Object)null || (Object)(object)target.GetComponentInParent<PlayerAvatar>() != (Object)null || ((Object)(object)target.GetComponent<ItemAttributes>() != (Object)null && (Object)(object)target.GetComponent<PhysGrabCart>() == (Object)null))
			{
				return false;
			}
			if (!((Object)(object)target.GetComponent<ValuableObject>() != (Object)null))
			{
				if (DroneRules.Link(Kind))
				{
					return (Object)(object)target.GetComponent<PhysGrabCart>() != (Object)null;
				}
				return false;
			}
			return true;
		}

		private void Update()
		{
			if (NativeAccess.Host && Powered)
			{
				Physics.OverrideZeroGravity(0.1f);
				Physics.OverrideDrag(1f, 0.1f);
				Physics.OverrideAngularDrag(10f, 0.1f);
			}
		}
	}
}