Decompiled source of ZeroGravityExtraction DroneToOrbItem Fix v1.0.5

ZeroGravityExtraction DroneToOrbItem Fix.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ZeroGravityExtractionDroneToOrbFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ZeroGravityExtractionDroneToOrbFix")]
[assembly: AssemblyTitle("ZeroGravityExtractionDroneToOrbFix")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ZeroGravityExtractionDroneToOrbFix
{
	[BepInPlugin("REPOJP.ZeroGravityExtractionDroneToOrbFix", "ZeroGravityExtraction DroneToOrbItem Fix", "1.0.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class DroneAnchorLatch : MonoBehaviour
		{
			public object Drone;

			public GameObject Anchor;

			public object AnchorPhysObject;

			public float RefreshUntil;

			private bool _savedFlags;

			private object _targetNonValuables;

			private object _targetValuables;

			private object _targetEnemies;

			private object _targetPlayers;

			public void CaptureOriginalTargetFlags(object drone)
			{
				if (!_savedFlags && drone != null)
				{
					_targetNonValuables = GetMember(drone, "targetNonValuables");
					_targetValuables = GetMember(drone, "targetValuables");
					_targetEnemies = GetMember(drone, "targetEnemies");
					_targetPlayers = GetMember(drone, "targetPlayers");
					_savedFlags = true;
				}
			}

			public void ReleaseNow()
			{
				Release();
				Object.Destroy((Object)(object)this);
			}

			private void LateUpdate()
			{
				if (Time.time > RefreshUntil || Drone == null || (Object)(object)Anchor == (Object)null || AnchorPhysObject == null)
				{
					ReleaseNow();
				}
				else if (!IsPoweredZeroGravityDrone(Drone) || !IsDroneInsideAnchorZone((Component)(object)this, Anchor, 3.95f))
				{
					ReleaseNow();
				}
				else
				{
					ApplyDroneLatchTransform(Drone, (Component)(object)this, Anchor, AnchorPhysObject, force: false);
				}
			}

			private void OnDestroy()
			{
				Release();
			}

			private void Release()
			{
				if (Drone != null && AnchorPhysObject != null)
				{
					ClearDroneAnchorTarget(Drone, AnchorPhysObject);
					RestoreOriginalTargetFlags();
				}
				Drone = null;
				Anchor = null;
				AnchorPhysObject = null;
			}

			private void RestoreOriginalTargetFlags()
			{
				if (_savedFlags && Drone != null)
				{
					SetMember(Drone, "targetNonValuables", _targetNonValuables);
					SetMember(Drone, "targetValuables", _targetValuables);
					SetMember(Drone, "targetEnemies", _targetEnemies);
					SetMember(Drone, "targetPlayers", _targetPlayers);
					_savedFlags = false;
				}
			}
		}

		private sealed class Candidate
		{
			public readonly string ItemName;

			public readonly string ResourcePath;

			public readonly GameObject AffectPrefab;

			public readonly int Score;

			public Candidate(string itemName, string resourcePath, GameObject affectPrefab, int score)
			{
				ItemName = itemName;
				ResourcePath = resourcePath;
				AffectPrefab = affectPrefab;
				Score = score;
			}
		}

		public const string PluginGuid = "REPOJP.ZeroGravityExtractionDroneToOrbFix";

		public const string PluginName = "ZeroGravityExtraction DroneToOrbItem Fix";

		public const string PluginVersion = "1.0.5";

		private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();

		private static readonly HashSet<string> MissingTypeCache = new HashSet<string>();

		private static readonly Dictionary<string, object> MemberCache = new Dictionary<string, object>();

		private static readonly Dictionary<string, object> FieldCache = new Dictionary<string, object>();

		private static readonly object MissingMember = new object();

		private static readonly object MissingField = new object();

		private static ManualLogSource Log;

		private static float _nextDebugLog;

		private static MethodInfo _isMultiplayerMethod;

		private Harmony _harmony;

		private bool _patched;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
		}

		private IEnumerator Start()
		{
			yield return null;
			yield return null;
			ApplyPatches();
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}

		private void ApplyPatches()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (!_patched)
			{
				_patched = true;
				_harmony = new Harmony("REPOJP.ZeroGravityExtractionDroneToOrbFix");
				PatchZeroGravityExtraction(_harmony);
				Log.LogInfo((object)"ZeroGravityExtraction DroneToOrbItem Fix v1.0.5 loaded.");
			}
		}

		private static void PatchZeroGravityExtraction(Harmony harmony)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			Type type = FindType("ZeroGravityExtraction.Services.ZeroGravityPadService");
			if (type == null)
			{
				Log.LogError((object)"ZeroGravityPadService type was not found.");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "TryResolveEffect", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(type, "ResetLevelState", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(type, "EnsureAnchor", (Type[])null, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(type, "CollectDroneZoneTargets", (Type[])null, (Type[])null);
			MethodInfo methodInfo5 = AccessTools.Method(type, "IsPadPowered", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "TryResolveEffectPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				Log.LogError((object)"TryResolveEffect method was not found.");
			}
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ResetLevelStatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			if (methodInfo3 != null)
			{
				harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "EnsureAnchorPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			if (methodInfo4 != null)
			{
				harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(Plugin), "CollectDroneZoneTargetsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			if (methodInfo5 != null)
			{
				harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(Plugin), "IsPadPoweredPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			PatchItemDrone(harmony);
		}

		private static void PatchItemDrone(Harmony harmony)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			Type type = FindType("ItemDrone");
			if (!(type == null))
			{
				MethodInfo methodInfo = AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ItemDroneUpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void ItemDroneUpdatePostfix(object __instance)
		{
			object zeroGravityPadServiceInstance = GetZeroGravityPadServiceInstance();
			if (zeroGravityPadServiceInstance != null)
			{
				ConfigureVanillaPlusAnchors(zeroGravityPadServiceInstance);
				List<GameObject> droneAnchors = GetDroneAnchors(zeroGravityPadServiceInstance);
				if (droneAnchors.Count != 0)
				{
					EnforceDroneAnchorLatch(__instance, droneAnchors);
				}
			}
		}

		private static object GetZeroGravityPadServiceInstance()
		{
			object staticMember = GetStaticMember("ZeroGravityExtraction.Services.ZeroGravityPadService", "Instance");
			if (staticMember != null)
			{
				return staticMember;
			}
			return GetStaticMember("ZeroGravityPadService", "Instance");
		}

		private static void ResetLevelStatePostfix(object __instance)
		{
			ResetResolveFailure(__instance);
			SetMember(__instance, "_affectPrefab", null);
			SetMember(__instance, "_orbResourcePath", null);
		}

		private static bool TryResolveEffectPrefix(object __instance, ref bool __result)
		{
			__result = TryResolveEffect(__instance);
			return false;
		}

		private static void EnsureAnchorPostfix(object __instance)
		{
			ConfigureVanillaPlusAnchors(__instance);
		}

		private static void CollectDroneZoneTargetsPrefix(object __instance)
		{
			ConfigureVanillaPlusAnchors(__instance);
			EncourageZeroGravityDronesToAnchors(__instance);
		}

		private static bool IsPadPoweredPrefix(object __instance, object[] __args, ref bool __result)
		{
			__result = false;
			if (__args == null || __args.Length == 0)
			{
				return false;
			}
			object point = __args[0];
			GameObject anchorForPoint = GetAnchorForPoint(__instance, point);
			if ((Object)(object)anchorForPoint == (Object)null)
			{
				return false;
			}
			object componentByName = GetComponentByName(anchorForPoint, "PhysGrabObject");
			if (componentByName == null)
			{
				return false;
			}
			__result = HasPoweredZeroGravityDroneLatchedToAnchor(anchorForPoint, componentByName, 3.25f);
			return false;
		}

		private static void ConfigureVanillaPlusAnchors(object service)
		{
			IEnumerable dictionaryValues = GetDictionaryValues(GetMember(service, "_anchors"));
			if (dictionaryValues == null)
			{
				return;
			}
			foreach (object item in dictionaryValues)
			{
				GameObject val = (GameObject)((item is GameObject) ? item : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				object componentByName = GetComponentByName(val, "PadAnchor");
				if (componentByName != null)
				{
					object member = GetMember(componentByName, "ButtonMode");
					if (member is bool && (bool)member)
					{
						continue;
					}
				}
				ConfigureDroneAnchor(val);
			}
		}

		private static void ConfigureDroneAnchor(GameObject anchor)
		{
			if ((Object)(object)anchor == (Object)null)
			{
				return;
			}
			try
			{
				anchor.tag = "Phys Grab Object";
			}
			catch
			{
			}
			try
			{
				int num = LayerMask.NameToLayer("PhysGrabObject");
				if (num >= 0)
				{
					anchor.layer = num;
				}
			}
			catch
			{
			}
			Collider val = anchor.GetComponent<Collider>();
			if ((Object)(object)val == (Object)null)
			{
				val = (Collider)(object)anchor.AddComponent<SphereCollider>();
			}
			val.enabled = true;
			val.isTrigger = false;
			Rigidbody val2 = anchor.GetComponent<Rigidbody>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = anchor.AddComponent<Rigidbody>();
			}
			val2.useGravity = false;
			val2.isKinematic = true;
			val2.constraints = (RigidbodyConstraints)126;
			object orAddComponentByName = GetOrAddComponentByName(anchor, "PhysGrabObject");
			if (orAddComponentByName != null)
			{
				SetMember(orAddComponentByName, "isNonValuable", true);
				SetMember(orAddComponentByName, "isValuable", false);
				SetMember(orAddComponentByName, "isEnemy", false);
				SetMember(orAddComponentByName, "grabDisable", false);
				SetMember(orAddComponentByName, "disabled", false);
				SetMember(orAddComponentByName, "dead", false);
			}
			GetOrAddComponentByName(anchor, "PhysGrabObjectCollider");
			Renderer component = anchor.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.enabled = false;
			}
		}

		private static void EncourageZeroGravityDronesToAnchors(object service)
		{
			List<GameObject> droneAnchors = GetDroneAnchors(service);
			if (droneAnchors.Count == 0 || !(GetStaticMember("ItemDrone", "activeDrones") is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				EnforceDroneAnchorLatch(item, droneAnchors);
			}
		}

		private static void EnforceDroneAnchorLatch(object drone, List<GameObject> anchors)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (drone == null || anchors == null || anchors.Count == 0)
			{
				return;
			}
			Component val = (Component)((drone is Component) ? drone : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			DroneAnchorLatch component = val.gameObject.GetComponent<DroneAnchorLatch>();
			if (!IsPoweredZeroGravityDrone(drone))
			{
				if ((Object)(object)component != (Object)null)
				{
					component.ReleaseNow();
				}
				else
				{
					ClearAnchorTargetIfNeeded(drone, anchors);
				}
				return;
			}
			GameObject val2 = FindNearestAnchor(val.transform.position, anchors, 3.75f);
			if ((Object)(object)val2 == (Object)null)
			{
				if ((Object)(object)component != (Object)null)
				{
					component.ReleaseNow();
				}
				else
				{
					ClearAnchorTargetIfNeeded(drone, anchors);
				}
				return;
			}
			object componentByName = GetComponentByName(val2, "PhysGrabObject");
			if (componentByName != null)
			{
				AttachDroneLatch(drone, val, val2, componentByName);
			}
		}

		private static List<GameObject> GetDroneAnchors(object service)
		{
			List<GameObject> list = new List<GameObject>();
			IEnumerable dictionaryValues = GetDictionaryValues(GetMember(service, "_anchors"));
			if (dictionaryValues == null)
			{
				return list;
			}
			foreach (object item in dictionaryValues)
			{
				GameObject val = (GameObject)((item is GameObject) ? item : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				object componentByName = GetComponentByName(val, "PadAnchor");
				if (componentByName != null)
				{
					object member = GetMember(componentByName, "ButtonMode");
					if (member is bool && (bool)member)
					{
						continue;
					}
				}
				list.Add(val);
			}
			return list;
		}

		private static GameObject FindNearestAnchor(Vector3 position, List<GameObject> anchors, float maxDistance)
		{
			//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_0027: 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)
			GameObject result = null;
			float num = maxDistance * maxDistance;
			for (int i = 0; i < anchors.Count; i++)
			{
				GameObject val = anchors[i];
				if (!((Object)(object)val == (Object)null))
				{
					Vector3 val2 = val.transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude <= num)
					{
						num = sqrMagnitude;
						result = val;
					}
				}
			}
			return result;
		}

		private static bool IsDroneNearAnchorTarget(Component droneComponent, GameObject anchor, float maxDistance)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)droneComponent == (Object)null || (Object)(object)anchor == (Object)null)
			{
				return false;
			}
			Vector3 val = droneComponent.transform.position - anchor.transform.position;
			return ((Vector3)(ref val)).sqrMagnitude <= maxDistance * maxDistance;
		}

		private static void AttachDroneLatch(object drone, Component droneComponent, GameObject anchor, object anchorPhysObject)
		{
			if (drone != null && !((Object)(object)droneComponent == (Object)null) && !((Object)(object)anchor == (Object)null) && anchorPhysObject != null)
			{
				DroneAnchorLatch droneAnchorLatch = droneComponent.gameObject.GetComponent<DroneAnchorLatch>();
				if ((Object)(object)droneAnchorLatch == (Object)null)
				{
					droneAnchorLatch = droneComponent.gameObject.AddComponent<DroneAnchorLatch>();
				}
				droneAnchorLatch.CaptureOriginalTargetFlags(drone);
				droneAnchorLatch.Drone = drone;
				droneAnchorLatch.Anchor = anchor;
				droneAnchorLatch.AnchorPhysObject = anchorPhysObject;
				droneAnchorLatch.RefreshUntil = Time.time + 0.75f;
				ApplyDroneLatchTransform(drone, droneComponent, anchor, anchorPhysObject, force: false);
			}
		}

		private static void ApplyDroneLatchTransform(object drone, Component droneComponent, GameObject anchor, object anchorPhysObject, bool force)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if (drone == null || (Object)(object)droneComponent == (Object)null || (Object)(object)anchor == (Object)null || anchorPhysObject == null)
			{
				return;
			}
			if (!IsDroneInsideAnchorZone(droneComponent, anchor, 3.95f))
			{
				ClearDroneAnchorTarget(drone, anchorPhysObject);
				return;
			}
			SetMember(drone, "targetNonValuables", true);
			SetMember(drone, "targetValuables", false);
			SetMember(drone, "targetEnemies", false);
			SetMember(drone, "targetPlayers", false);
			SetMember(drone, "magnetTargetPhysGrabObject", anchorPhysObject);
			SetMember(drone, "targetPhysGrabObject", anchorPhysObject);
			SetMember(drone, "currentTargetPhysGrabObject", anchorPhysObject);
			SetMember(drone, "magnetTargetTransform", anchor.transform);
			SetMember(drone, "targetTransform", anchor.transform);
			SetMember(drone, "magnetTargetGameObject", anchor);
			SetMember(drone, "targetGameObject", anchor);
			SetMember(drone, "magnetTargetPosition", anchor.transform.position);
			SetMember(drone, "targetPosition", anchor.transform.position);
			SetMember(drone, "magnetActive", true);
			if (!force && IsDroneGrabbed(droneComponent))
			{
				return;
			}
			Component obj = FindMoveRoot(droneComponent);
			Vector3 position = anchor.transform.position;
			obj.transform.position = position;
			Rigidbody[] componentsInChildren = obj.gameObject.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.velocity = Vector3.zero;
					val.angularVelocity = Vector3.zero;
				}
			}
		}

		private static bool IsDroneInsideAnchorZone(Component droneComponent, GameObject anchor, float maxHorizontalDistance)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)droneComponent == (Object)null || (Object)(object)anchor == (Object)null)
			{
				return false;
			}
			Vector3 val = droneComponent.transform.position - anchor.transform.position;
			if (val.x * val.x + val.z * val.z > maxHorizontalDistance * maxHorizontalDistance)
			{
				return false;
			}
			if (val.y > -2.5f)
			{
				return val.y < 6.5f;
			}
			return false;
		}

		private static Component FindMoveRoot(Component droneComponent)
		{
			if ((Object)(object)droneComponent == (Object)null)
			{
				return null;
			}
			object componentByName = GetComponentByName(droneComponent.gameObject, "PhysGrabObject");
			Component val = (Component)((componentByName is Component) ? componentByName : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			object componentInParentByName = GetComponentInParentByName(droneComponent.gameObject, "PhysGrabObject");
			val = (Component)((componentInParentByName is Component) ? componentInParentByName : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return droneComponent;
		}

		private static bool IsDroneGrabbed(Component droneComponent)
		{
			if ((Object)(object)droneComponent == (Object)null)
			{
				return false;
			}
			object obj = GetComponentByName(droneComponent.gameObject, "PhysGrabObject");
			if (obj == null)
			{
				obj = GetComponentInParentByName(droneComponent.gameObject, "PhysGrabObject");
			}
			if (obj == null)
			{
				return false;
			}
			object member = GetMember(obj, "grabbed");
			if (member is bool)
			{
				return (bool)member;
			}
			return false;
		}

		private static void ClearAnchorTargetIfNeeded(object drone, List<GameObject> anchors)
		{
			if (drone != null && anchors != null)
			{
				object member = GetMember(drone, "magnetTargetPhysGrabObject");
				if (member != null && IsAnchorPhysObject(member, anchors))
				{
					ClearDroneAnchorTarget(drone, member);
				}
			}
		}

		private static void ClearDroneAnchorTarget(object drone, object anchorPhysObject)
		{
			if (drone != null && anchorPhysObject != null && GetMember(drone, "magnetTargetPhysGrabObject") == anchorPhysObject)
			{
				SetMember(drone, "magnetTargetPhysGrabObject", null);
				SetMember(drone, "targetPhysGrabObject", null);
				SetMember(drone, "currentTargetPhysGrabObject", null);
				SetMember(drone, "magnetTargetTransform", null);
				SetMember(drone, "targetTransform", null);
				SetMember(drone, "magnetTargetGameObject", null);
				SetMember(drone, "targetGameObject", null);
				SetMember(drone, "magnetActive", false);
			}
		}

		private static GameObject GetAnchorForPoint(object service, object point)
		{
			if (service == null || point == null)
			{
				return null;
			}
			Object val = (Object)((point is Object) ? point : null);
			if (val == (Object)null)
			{
				return null;
			}
			if (!(GetMember(service, "_anchors") is IDictionary dictionary))
			{
				return null;
			}
			object? obj = dictionary[val.GetInstanceID()];
			return (GameObject)((obj is GameObject) ? obj : null);
		}

		private static bool HasPoweredZeroGravityDroneLatchedToAnchor(GameObject anchor, object anchorPhysObject, float maxDistance)
		{
			if (!(GetStaticMember("ItemDrone", "activeDrones") is IEnumerable enumerable))
			{
				return false;
			}
			foreach (object item in enumerable)
			{
				if (!IsPoweredZeroGravityDrone(item))
				{
					continue;
				}
				object member = GetMember(item, "magnetActive");
				if ((!(member is bool) || (bool)member) && GetMember(item, "magnetTargetPhysGrabObject") == anchorPhysObject)
				{
					Component val = (Component)((item is Component) ? item : null);
					if (!((Object)(object)val != (Object)null) || IsDroneNearAnchorTarget(val, anchor, maxDistance))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool IsPoweredZeroGravityDrone(object drone)
		{
			if (drone == null)
			{
				return false;
			}
			object member = GetMember(drone, "itemActivated");
			if (member is bool && !(bool)member)
			{
				return false;
			}
			Component val = (Component)((drone is Component) ? drone : null);
			if ((Object)(object)val == (Object)null || GetComponentByName(val.gameObject, "ItemDroneZeroGravity") == null)
			{
				return false;
			}
			object componentByName = GetComponentByName(val.gameObject, "ItemBattery");
			if (componentByName != null)
			{
				object member2 = GetMember(componentByName, "batteryLife");
				if (member2 is float && (float)member2 <= 0f)
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsAnchorPhysObject(object physObject, List<GameObject> anchors)
		{
			if (physObject == null)
			{
				return false;
			}
			for (int i = 0; i < anchors.Count; i++)
			{
				object componentByName = GetComponentByName(anchors[i], "PhysGrabObject");
				if (physObject == componentByName)
				{
					return true;
				}
			}
			return false;
		}

		private static object GetOrAddComponentByName(GameObject gameObject, string typeName)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			object componentByName = GetComponentByName(gameObject, typeName);
			if (componentByName != null)
			{
				return componentByName;
			}
			Type type = FindType(typeName);
			if (type == null)
			{
				return null;
			}
			try
			{
				return gameObject.AddComponent(type);
			}
			catch
			{
				return null;
			}
		}

		private static object GetComponentByName(GameObject gameObject, string typeName)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			Type type = FindType(typeName);
			if (type == null)
			{
				return null;
			}
			try
			{
				return gameObject.GetComponent(type);
			}
			catch
			{
				return null;
			}
		}

		private static object GetComponentInParentByName(GameObject gameObject, string typeName)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			Type type = FindType(typeName);
			if (type == null)
			{
				return null;
			}
			try
			{
				return gameObject.GetComponentInParent(type);
			}
			catch
			{
				return null;
			}
		}

		private static bool TryResolveEffect(object service)
		{
			ResetResolveFailure(service);
			object staticMember = GetStaticMember("StatsManager", "instance");
			if (staticMember == null)
			{
				return false;
			}
			IEnumerable dictionaryValues = GetDictionaryValues(GetMember(staticMember, "itemDictionary"));
			if (dictionaryValues == null)
			{
				return false;
			}
			bool flag = IsMultiplayer();
			Candidate candidate = null;
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			foreach (object item in dictionaryValues)
			{
				num++;
				if (item == null)
				{
					continue;
				}
				GameObject prefabFromRef = GetPrefabFromRef(GetMember(item, "prefab"));
				if ((Object)(object)prefabFromRef == (Object)null)
				{
					continue;
				}
				object obj = FindComponentInChildren(prefabFromRef, "ItemStaffZeroGravity");
				if (obj == null)
				{
					continue;
				}
				num2++;
				object member = GetMember(obj, "projectilePrefab");
				string stringMember = GetStringMember(member, "ResourcePath");
				GameObject prefabFromRef2 = GetPrefabFromRef(member);
				if ((Object)(object)prefabFromRef2 == (Object)null)
				{
					continue;
				}
				object obj2 = FindComponentInChildren(prefabFromRef2, "SemiAreaOfEffect");
				if (obj2 == null)
				{
					continue;
				}
				GameObject prefabFromRef3 = GetPrefabFromRef(GetMember(obj2, "semiAffectPrefab"));
				if ((Object)(object)prefabFromRef3 == (Object)null || FindComponentInChildren(prefabFromRef3, "SemiAffectZeroGravity") == null)
				{
					continue;
				}
				num3++;
				if (flag && string.IsNullOrEmpty(stringMember))
				{
					num4++;
					continue;
				}
				string unityName = GetUnityName(item);
				Candidate candidate2 = new Candidate(unityName, stringMember, prefabFromRef3, ScoreCandidate(unityName, stringMember));
				if (candidate == null || candidate2.Score > candidate.Score)
				{
					candidate = candidate2;
				}
			}
			if (candidate != null)
			{
				SetMember(service, "_affectPrefab", candidate.AffectPrefab);
				SetMember(service, "_orbResourcePath", string.IsNullOrEmpty(candidate.ResourcePath) ? null : candidate.ResourcePath);
				ResetResolveFailure(service);
				Log.LogInfo((object)("Resolved zero-gravity effect from '" + candidate.ItemName + "' resourcePath='" + NullText(candidate.ResourcePath) + "'."));
				return true;
			}
			if (Time.realtimeSinceStartup >= _nextDebugLog)
			{
				_nextDebugLog = Time.realtimeSinceStartup + 15f;
				Log.LogDebug((object)("Zero-gravity effect not ready. scanned=" + num + " staff=" + num2 + " effect=" + num3 + " rejectedForMultiplayerPath=" + num4 + "."));
			}
			ResetResolveFailure(service);
			return false;
		}

		private static int ScoreCandidate(string itemName, string resourcePath)
		{
			int num = 0;
			string text = ((itemName ?? string.Empty) + " " + (resourcePath ?? string.Empty)).ToLowerInvariant();
			if (!string.IsNullOrEmpty(resourcePath))
			{
				num += 1000;
			}
			if (text.Contains("staff"))
			{
				num += 100;
			}
			if (text.Contains("orb"))
			{
				num -= 25;
			}
			if (text.Contains("zero") && text.Contains("gravity"))
			{
				num += 10;
			}
			return num;
		}

		private static void ResetResolveFailure(object service)
		{
			if (service != null)
			{
				SetMember(service, "_resolveFailed", false);
				SetMember(service, "_resolveAttempts", 0);
			}
		}

		private static object GetStaticMember(string typeName, string memberName)
		{
			Type type = FindType(typeName);
			if (type == null)
			{
				return null;
			}
			return GetMember(type, memberName);
		}

		private static object GetMember(object target, string memberName)
		{
			if (target == null)
			{
				return null;
			}
			bool num = target is Type;
			Type type = (num ? ((Type)target) : target.GetType());
			object obj = (num ? null : target);
			object cachedMember = GetCachedMember(type, memberName);
			if (cachedMember == MissingMember)
			{
				return null;
			}
			PropertyInfo propertyInfo = cachedMember as PropertyInfo;
			if (propertyInfo != null)
			{
				try
				{
					return propertyInfo.GetValue(obj, null);
				}
				catch
				{
					return null;
				}
			}
			FieldInfo fieldInfo = cachedMember as FieldInfo;
			if (fieldInfo != null)
			{
				try
				{
					return fieldInfo.GetValue(obj);
				}
				catch
				{
					return null;
				}
			}
			return null;
		}

		private static object GetCachedMember(Type type, string memberName)
		{
			string key = type.AssemblyQualifiedName + "|" + memberName;
			if (MemberCache.TryGetValue(key, out var value))
			{
				return value;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			PropertyInfo property = type.GetProperty(memberName, bindingAttr);
			if (property != null)
			{
				MemberCache[key] = property;
				return property;
			}
			FieldInfo field = type.GetField(memberName, bindingAttr);
			if (field != null)
			{
				MemberCache[key] = field;
				return field;
			}
			MemberCache[key] = MissingMember;
			return MissingMember;
		}

		private static void SetMember(object target, string memberName, object value)
		{
			if (target == null)
			{
				return;
			}
			FieldInfo cachedField = GetCachedField(target.GetType(), memberName);
			if (cachedField == null)
			{
				return;
			}
			try
			{
				cachedField.SetValue(target, value);
			}
			catch
			{
			}
		}

		private static FieldInfo GetCachedField(Type type, string memberName)
		{
			string key = type.AssemblyQualifiedName + "|" + memberName;
			if (FieldCache.TryGetValue(key, out var value))
			{
				if (value != MissingField)
				{
					return value as FieldInfo;
				}
				return null;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = type.GetField(memberName, bindingAttr);
			if (field == null)
			{
				FieldCache[key] = MissingField;
				return null;
			}
			FieldCache[key] = field;
			return field;
		}

		private static IEnumerable GetDictionaryValues(object dictionary)
		{
			if (dictionary == null)
			{
				return null;
			}
			if (dictionary is IDictionary dictionary2)
			{
				return dictionary2.Values;
			}
			return GetMember(dictionary, "Values") as IEnumerable;
		}

		private static GameObject GetPrefabFromRef(object prefabRef)
		{
			if (prefabRef == null)
			{
				return null;
			}
			object member = GetMember(prefabRef, "Prefab");
			return (GameObject)((member is GameObject) ? member : null);
		}

		private static string GetStringMember(object target, string memberName)
		{
			return GetMember(target, memberName) as string;
		}

		private static object FindComponentInChildren(GameObject root, string typeName)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Type type = FindType(typeName);
			if (type == null)
			{
				return null;
			}
			try
			{
				return root.GetComponentInChildren(type, true);
			}
			catch
			{
				return null;
			}
		}

		private static Type FindType(string typeName)
		{
			if (TypeCache.TryGetValue(typeName, out var value))
			{
				return value;
			}
			if (MissingTypeCache.Contains(typeName))
			{
				return null;
			}
			Type type = AccessTools.TypeByName(typeName);
			if (type != null)
			{
				TypeCache[typeName] = type;
				return type;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				try
				{
					type = assemblies[i].GetType(typeName, throwOnError: false);
					if (type != null)
					{
						TypeCache[typeName] = type;
						return type;
					}
					Type[] types = assemblies[i].GetTypes();
					for (int j = 0; j < types.Length; j++)
					{
						if (types[j].Name == typeName || types[j].FullName == typeName)
						{
							TypeCache[typeName] = types[j];
							return types[j];
						}
					}
				}
				catch (ReflectionTypeLoadException ex)
				{
					Type[] types2 = ex.Types;
					foreach (Type type2 in types2)
					{
						if (type2 != null && (type2.Name == typeName || type2.FullName == typeName))
						{
							TypeCache[typeName] = type2;
							return type2;
						}
					}
				}
				catch
				{
				}
			}
			MissingTypeCache.Add(typeName);
			return null;
		}

		private static bool IsMultiplayer()
		{
			if (_isMultiplayerMethod == null)
			{
				Type type = FindType("SemiFunc");
				if (type == null)
				{
					return false;
				}
				_isMultiplayerMethod = AccessTools.Method(type, "IsMultiplayer", (Type[])null, (Type[])null);
				if (_isMultiplayerMethod == null)
				{
					return false;
				}
			}
			try
			{
				object obj = _isMultiplayerMethod.Invoke(null, null);
				if (obj is bool)
				{
					return (bool)obj;
				}
			}
			catch
			{
			}
			return false;
		}

		private static string GetUnityName(object obj)
		{
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != (Object)null)
			{
				return val.name;
			}
			return obj.GetType().Name;
		}

		private static string NullText(string text)
		{
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "<empty>";
		}
	}
}