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 TypeCache = new Dictionary(); private static readonly HashSet MissingTypeCache = new HashSet(); private static readonly Dictionary MemberCache = new Dictionary(); private static readonly Dictionary FieldCache = new Dictionary(); 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 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(); if ((Object)(object)val == (Object)null) { val = (Collider)(object)anchor.AddComponent(); } val.enabled = true; val.isTrigger = false; Rigidbody val2 = anchor.GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = anchor.AddComponent(); } 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(); if ((Object)(object)component != (Object)null) { component.enabled = false; } } private static void EncourageZeroGravityDronesToAnchors(object service) { List 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 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(); 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 GetDroneAnchors(object service) { List list = new List(); 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 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(); if ((Object)(object)droneAnchorLatch == (Object)null) { droneAnchorLatch = droneComponent.gameObject.AddComponent(); } 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(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 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 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 ""; } } }