Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ShipLootTotal v1.1.2
ShipLootTotal.dll
Decompiled 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ShipLootTotal")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ShipLootTotal")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("03969134-fca5-435b-9dc6-2366b8fb8b9b")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace ShipLootTotal; [BepInPlugin("DaanSmoki.LethalCompany.ShipLootTotal", "Ship Loot Total", "1.1.2")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "DaanSmoki.LethalCompany.ShipLootTotal"; public const string PluginName = "Ship Loot Total"; public const string PluginVersion = "1.1.2"; internal static ManualLogSource Log; internal static Harmony Harmony; internal static float _lastScanPostfixAt = -999f; internal static bool SuppressNextHudSfx = false; internal static bool SuppressHudSfxActive = false; internal static ConfigEntry<float> PopupDuration; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Harmony = new Harmony("DaanSmoki.LethalCompany.ShipLootTotal"); PopupDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PopupDuration", 3f, "How long (in seconds) the popup stays visible after scanning."); Harmony.PatchAll(); ScrapValueSyncPatcher.Apply(Harmony); Log.LogInfo((object)"Ship Loot Total 1.1.2 loaded."); } } [HarmonyPatch(typeof(HUDManager))] public static class Patch_HUD_PingScan { [HarmonyPostfix] [HarmonyPatch("PingScan_performed")] public static void Postfix(CallbackContext context) { try { if (!((CallbackContext)(ref context)).performed || Time.time - Plugin._lastScanPostfixAt < 0.25f) { return; } Plugin._lastScanPostfixAt = Time.time; object localPlayerController = Utils.GetLocalPlayerController(); if (localPlayerController != null && Utils.IsPlayerInShip(localPlayerController)) { Utils.InvalidateGrabbablesCache(); int num = Utils.SumShipScrapValues(); HUDHelper.ShowStable("Total in Ship: " + num); if (Plugin.Log != null) { Plugin.Log.LogInfo((object)("ShipLootTotal: PingScan -> total=" + num)); } } } catch (Exception ex) { if (Plugin.Log != null) { Plugin.Log.LogError((object)ex); } } } } [HarmonyPatch] public static class Patch_HUD_Display_SilentGate { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; Type type = AccessTools.TypeByName("HUDManager"); if (type == null) { return false; } MethodInfo methodInfo = AccessTools.Method(type, "DisplayGlobalNotification", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo != null) { <>2__current = methodInfo; <>1__state = 1; return true; } break; } case 1: <>1__state = -1; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } private static void Prefix() { Plugin.SuppressHudSfxActive = Plugin.SuppressNextHudSfx; Plugin.SuppressNextHudSfx = false; } private static void Postfix() { Plugin.SuppressHudSfxActive = false; } } internal static class HUDHelper { private static Type _hudType; private static object _hudInstance; private static MethodInfo _miDisplayGlobal; public static void ShowStable(string bodyText) { try { object hUDManager = GetHUDManager(); if (hUDManager == null) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)"HUDHelper: HUDManager.Instance not found."); } return; } Plugin.SuppressNextHudSfx = true; HudHideHelper.PrepareForShow(hUDManager); if (_miDisplayGlobal == null || _miDisplayGlobal.DeclaringType == null) { _miDisplayGlobal = hUDManager.GetType().GetMethod("DisplayGlobalNotification", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); } if (_miDisplayGlobal != null) { _miDisplayGlobal.Invoke(hUDManager, new object[1] { bodyText }); HudHideHelper.HideAfterSeconds((Plugin.PopupDuration != null) ? Plugin.PopupDuration.Value : 3f); if (Plugin.Log != null) { Plugin.Log.LogInfo((object)"HUDHelper: Used DisplayGlobalNotification(string) [silent]."); } } else if (Plugin.Log != null) { Plugin.Log.LogWarning((object)"HUDHelper: DisplayGlobalNotification(string) not found."); } } catch (Exception ex) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)("HUDHelper.ShowStable failed: " + ex.GetType().Name + ": " + ex.Message)); } } } internal static object GetHUDManager() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown if (_hudType == null) { _hudType = AccessTools.TypeByName("HUDManager"); if (_hudType == null) { return null; } } PropertyInfo propertyInfo = _hudType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? _hudType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((propertyInfo != null) ? propertyInfo.GetValue(null) : null); bool flag = _hudInstance is Object && (Object)_hudInstance == (Object)null; bool flag2 = obj is Object && (Object)obj == (Object)null; if (_hudInstance == null || flag || (!flag2 && _hudInstance != obj)) { _hudInstance = obj; HudAudioLocator.Reset(); } return _hudInstance; } } internal static class HudHideHelper { [CompilerGenerated] private sealed class <HideCoroutine>d__5 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float seconds; public object hud; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HideCoroutine>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(seconds); <>1__state = 1; return true; case 1: <>1__state = -1; try { FieldInfo field = hud.GetType().GetField("globalNotificationCoroutine", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(hud); Coroutine val = (Coroutine)((value is Coroutine) ? value : null); object obj = hud; MonoBehaviour val2 = (MonoBehaviour)((obj is MonoBehaviour) ? obj : null); if (val != null && (Object)(object)val2 != (Object)null) { val2.StopCoroutine(val); field.SetValue(hud, null); } } EnsureCachedParts(hud); if ((Object)(object)_tmp != (Object)null) { ((TMP_Text)_tmp).text = string.Empty; } if ((Object)(object)_panelGO != (Object)null) { CanvasGroup obj2 = _panelGO.GetComponent<CanvasGroup>() ?? _panelGO.AddComponent<CanvasGroup>(); obj2.alpha = 0f; obj2.interactable = false; obj2.blocksRaycasts = false; } } catch (Exception ex) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)("HudHideHelper: hide failed: " + ex.Message)); } } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static Coroutine _hideRoutine; private static GameObject _panelGO; private static TextMeshProUGUI _tmp; public static void PrepareForShow(object hud) { try { EnsureCachedParts(hud); if ((Object)(object)_panelGO != (Object)null) { if (!_panelGO.activeSelf) { _panelGO.SetActive(true); } CanvasGroup obj = _panelGO.GetComponent<CanvasGroup>() ?? _panelGO.AddComponent<CanvasGroup>(); obj.alpha = 1f; obj.interactable = false; obj.blocksRaycasts = false; } if ((Object)(object)_tmp != (Object)null) { PropertyInfo property = ((object)_tmp).GetType().GetProperty("alpha"); if (property != null) { property.SetValue(_tmp, 1f); } } } catch { } } public static void HideAfterSeconds(float seconds) { object hUDManager = HUDHelper.GetHUDManager(); if (hUDManager == null) { return; } MonoBehaviour val = (MonoBehaviour)((hUDManager is MonoBehaviour) ? hUDManager : null); if (!((Object)(object)val == (Object)null)) { if (_hideRoutine != null) { val.StopCoroutine(_hideRoutine); } _hideRoutine = val.StartCoroutine(HideCoroutine(hUDManager, seconds)); } } [IteratorStateMachine(typeof(<HideCoroutine>d__5))] private static IEnumerator HideCoroutine(object hud, float seconds) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HideCoroutine>d__5(0) { hud = hud, seconds = seconds }; } private static void EnsureCachedParts(object hud) { if ((Object)(object)_panelGO != (Object)null && (Object)(object)_tmp != (Object)null) { return; } if (_panelGO != null && (Object)(object)_panelGO == (Object)null) { _panelGO = null; } if (_tmp != null && (Object)(object)_tmp == (Object)null) { _tmp = null; } if ((Object)(object)_panelGO != (Object)null && (Object)(object)_tmp != (Object)null) { return; } Type type = hud.GetType(); if ((Object)(object)_tmp == (Object)null) { FieldInfo field = type.GetField("globalNotificationText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _tmp = (TextMeshProUGUI)((field != null) ? /*isinst with value type is only supported in some contexts*/: null); } if (!((Object)(object)_panelGO == (Object)null)) { return; } FieldInfo field2 = type.GetField("globalNotificationBackground", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((field2 != null) ? field2.GetValue(hud) : null); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val != (Object)null) { _panelGO = val; } else { Component val2 = (Component)((obj is Component) ? obj : null); if ((Object)(object)val2 != (Object)null) { _panelGO = val2.gameObject; } } if ((Object)(object)_panelGO == (Object)null && (Object)(object)_tmp != (Object)null && (Object)(object)((TMP_Text)_tmp).transform != (Object)null) { Transform parent = ((TMP_Text)_tmp).transform.parent; if ((Object)(object)parent != (Object)null) { _panelGO = ((Component)parent).gameObject; } } } } internal static class HudAudioLocator { private static AudioSource _cached; private static Type _hudType; private static object _hudInstance; public static void Reset() { _cached = null; _hudType = null; _hudInstance = null; } public static AudioSource GetHudAudio() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown if (_cached != null && (Object)(object)_cached == (Object)null) { _cached = null; } if ((Object)(object)_cached != (Object)null) { return _cached; } if (_hudType == null) { _hudType = AccessTools.TypeByName("HUDManager"); } if (_hudType == null) { return null; } PropertyInfo propertyInfo = _hudType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? _hudType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((propertyInfo != null) ? propertyInfo.GetValue(null) : null); bool flag = _hudInstance is Object && (Object)_hudInstance == (Object)null; bool flag2 = obj is Object && (Object)obj == (Object)null; if (_hudInstance == null || flag || (!flag2 && _hudInstance != obj)) { _hudInstance = obj; _cached = null; } if (_hudInstance == null) { return null; } FieldInfo fieldInfo = _hudType.GetField("UIAudio", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? _hudType.GetField("uiAudio", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { object? value = fieldInfo.GetValue(_hudInstance); _cached = (AudioSource)((value is AudioSource) ? value : null); } if ((Object)(object)_cached == (Object)null) { PropertyInfo propertyInfo2 = _hudType.GetProperty("UIAudio", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? _hudType.GetProperty("uiAudio", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo2 != null) { object? value2 = propertyInfo2.GetValue(_hudInstance); _cached = (AudioSource)((value2 is AudioSource) ? value2 : null); } } if ((Object)(object)_cached == (Object)null) { object hudInstance = _hudInstance; Component val = (Component)((hudInstance is Component) ? hudInstance : null); if ((Object)(object)val != (Object)null) { _cached = val.GetComponentInChildren<AudioSource>(true); } } return _cached; } } [HarmonyPatch(typeof(AudioSource), "PlayOneShot", new Type[] { typeof(AudioClip) })] public static class Patch_AudioSource_PlayOneShot_1 { private static bool Prefix(AudioSource __instance) { if (!Plugin.SuppressHudSfxActive) { return true; } AudioSource hudAudio = HudAudioLocator.GetHudAudio(); if ((Object)(object)hudAudio != (Object)null && (Object)(object)__instance == (Object)(object)hudAudio) { return false; } return true; } } [HarmonyPatch(typeof(AudioSource), "PlayOneShot", new Type[] { typeof(AudioClip), typeof(float) })] public static class Patch_AudioSource_PlayOneShot_2 { private static bool Prefix(AudioSource __instance) { if (!Plugin.SuppressHudSfxActive) { return true; } AudioSource hudAudio = HudAudioLocator.GetHudAudio(); if ((Object)(object)hudAudio != (Object)null && (Object)(object)__instance == (Object)(object)hudAudio) { return false; } return true; } } [HarmonyPatch(typeof(HUDManager), "Awake")] public static class Patch_HUD_Awake_ResetAudioLocator { private static void Postfix() { HudAudioLocator.Reset(); } } internal static class Utils { private static Type _grabType; private static FieldInfo _fi_itemProps; private static FieldInfo _fi_scrapValue; private static FieldInfo _fi_isInShipRoom; private static FieldInfo _fi_isInElevator; private static FieldInfo _fi_ip_isScrap; private static FieldInfo _fi_ip_scrapValue; private static FieldInfo _fi_isHeld; private static FieldInfo _fi_isPocketed; private static FieldInfo _fi_playerHeldBy; private static Type _sorType; private static Type _gnmType; private static Type _pcbType; private static PropertyInfo _pi_SOR_Instance; private static FieldInfo _fi_SOR_localPlayerController; private static PropertyInfo _pi_SOR_localPlayerController; private static PropertyInfo _pi_GNM_Instance; private static FieldInfo _fi_GNM_localPlayerController; private static PropertyInfo _pi_GNM_localPlayerController; private static FieldInfo _fi_PCB_isInHangar; private static FieldInfo _fi_PCB_isInShip; private static FieldInfo _fi_PCB_isLocal; private static FieldInfo _fi_PCB_isOwner; private static Object[] _grabbablesCache = (Object[])(object)new Object[0]; private static float _lastCacheAt = -999f; private const float CacheWindowSeconds = 2f; private static Bounds _shipBounds; private static float _shipBoundsLastBuild = -999f; private const float ShipBoundsRebuildSeconds = 3f; private const float ShipBoundsPadding = 8f; private static readonly string[] _shipNameNeedles = new string[2] { "ship", "hangar" }; private const int ParentHeuristicMaxDepth = 24; public static object GetLocalPlayerController() { if (_sorType == null) { _sorType = AccessTools.TypeByName("StartOfRound"); if (_sorType != null) { _pi_SOR_Instance = _sorType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _fi_SOR_localPlayerController = _sorType.GetField("localPlayerController", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _pi_SOR_localPlayerController = _sorType.GetProperty("localPlayerController", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } if (_sorType != null && _pi_SOR_Instance != null) { object value = _pi_SOR_Instance.GetValue(null); if (value != null) { object obj = ((_fi_SOR_localPlayerController != null) ? _fi_SOR_localPlayerController.GetValue(value) : null); if (obj == null && _pi_SOR_localPlayerController != null) { obj = _pi_SOR_localPlayerController.GetValue(value); } if (obj != null) { return obj; } } } if (_gnmType == null) { _gnmType = AccessTools.TypeByName("GameNetworkManager"); if (_gnmType != null) { _pi_GNM_Instance = _gnmType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _fi_GNM_localPlayerController = _gnmType.GetField("localPlayerController", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _pi_GNM_localPlayerController = _gnmType.GetProperty("localPlayerController", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } if (_gnmType != null && _pi_GNM_Instance != null) { object value2 = _pi_GNM_Instance.GetValue(null); if (value2 != null) { object obj2 = ((_fi_GNM_localPlayerController != null) ? _fi_GNM_localPlayerController.GetValue(value2) : null); if (obj2 == null && _pi_GNM_localPlayerController != null) { obj2 = _pi_GNM_localPlayerController.GetValue(value2); } if (obj2 != null) { return obj2; } } } return null; } public static bool IsPlayerInShip(object playerControllerB) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) if (playerControllerB == null) { return false; } if (_pcbType == null) { _pcbType = playerControllerB.GetType(); _fi_PCB_isInHangar = _pcbType.GetField("isInHangarShipRoom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_PCB_isInShip = _pcbType.GetField("isInShipRoom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_PCB_isLocal = _pcbType.GetField("isLocalPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_PCB_isOwner = _pcbType.GetField("IsOwner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } bool? flag = ((_fi_PCB_isLocal != null) ? ((bool?)_fi_PCB_isLocal.GetValue(playerControllerB)) : null); if (flag.HasValue && !flag.Value) { return false; } bool? flag2 = ((_fi_PCB_isOwner != null) ? ((bool?)_fi_PCB_isOwner.GetValue(playerControllerB)) : null); if (flag2.HasValue && !flag2.Value) { return false; } bool? flag3 = ((_fi_PCB_isInHangar != null) ? ((bool?)_fi_PCB_isInHangar.GetValue(playerControllerB)) : null); if (flag3.HasValue && flag3.Value) { return true; } bool? flag4 = ((_fi_PCB_isInShip != null) ? ((bool?)_fi_PCB_isInShip.GetValue(playerControllerB)) : null); if (flag4.HasValue) { return flag4.Value; } Bounds shipBounds = GetShipBounds(); Transform val = null; Component val2 = (Component)((playerControllerB is Component) ? playerControllerB : null); if ((Object)(object)val2 != (Object)null) { val = val2.transform; } else { PropertyInfo property = _pcbType.GetProperty("transform"); if (property != null) { object? value = property.GetValue(playerControllerB, null); val = (Transform)((value is Transform) ? value : null); } } if ((Object)(object)val != (Object)null && ((Bounds)(ref shipBounds)).size != Vector3.zero) { return ((Bounds)(ref shipBounds)).Contains(val.position); } return false; } private static Transform GetShipRootTransform() { if (_sorType == null) { return null; } object obj = ((_pi_SOR_Instance != null) ? _pi_SOR_Instance.GetValue(null) : null); if (obj == null) { return null; } FieldInfo field = _sorType.GetField("shipRoom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(obj); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null) { return val.transform; } } FieldInfo field2 = _sorType.GetField("hangarShip", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { object? value2 = field2.GetValue(obj); GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null); if ((Object)(object)val2 != (Object)null) { return val2.transform; } } FieldInfo field3 = _sorType.GetField("shipFloor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field3 != null) { object? value3 = field3.GetValue(obj); GameObject val3 = (GameObject)((value3 is GameObject) ? value3 : null); if ((Object)(object)val3 != (Object)null) { return val3.transform; } } return null; } private static Bounds GetShipBounds() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (Time.time - _shipBoundsLastBuild <= 3f && ((Bounds)(ref _shipBounds)).size != Vector3.zero) { return _shipBounds; } _shipBoundsLastBuild = Time.time; _shipBounds = default(Bounds); Transform shipRootTransform = GetShipRootTransform(); if ((Object)(object)shipRootTransform == (Object)null) { return _shipBounds; } Collider[] componentsInChildren = ((Component)shipRootTransform).GetComponentsInChildren<Collider>(true); if (componentsInChildren != null && componentsInChildren.Length != 0) { _shipBounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref _shipBounds)).Encapsulate(componentsInChildren[i].bounds); } ((Bounds)(ref _shipBounds)).Expand(8f); } if (((Bounds)(ref _shipBounds)).size == Vector3.zero) { if (Plugin.Log != null) { Plugin.Log.LogInfo((object)"[ShipLootTotal] Ship bounds empty, scheduling delayed rebuild."); } new GameObject("ShipBoundsRebuilder").AddComponent<ShipBoundsRebuilder>(); } return _shipBounds; } private static Object[] GetGrabbables() { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) if (_grabType == null) { _grabType = AccessTools.TypeByName("GrabbableObject"); if (_grabType != null) { _fi_itemProps = _grabType.GetField("itemProperties", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_scrapValue = _grabType.GetField("scrapValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_isInShipRoom = _grabType.GetField("isInShipRoom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_isInElevator = _grabType.GetField("isInElevator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_isHeld = _grabType.GetField("isHeld", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_isPocketed = _grabType.GetField("isPocketed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fi_playerHeldBy = _grabType.GetField("playerHeldBy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } if (_grabType == null) { return (Object[])(object)new Object[0]; } if (Time.time - _lastCacheAt > 2f || _grabbablesCache == null) { _lastCacheAt = Time.time; Object[] array = Object.FindObjectsOfType(_grabType); if (array == null || array.Length == 0) { Object[] array2 = Resources.FindObjectsOfTypeAll(_grabType); if (array2 != null && array2.Length != 0) { List<Object> list = new List<Object>(array2.Length); for (int i = 0; i < array2.Length; i++) { Object obj = array2[i]; Component val = (Component)(object)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null)) { Scene scene = val.gameObject.scene; if (((Scene)(ref scene)).IsValid()) { list.Add(array2[i]); } } } array = list.ToArray(); } } _grabbablesCache = (Object[])((array != null) ? ((Array)array) : ((Array)new Object[0])); } return _grabbablesCache; } public static int SumShipScrapValues() { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) Object[] grabbables = GetGrabbables(); if (grabbables == null || grabbables.Length == 0) { return 0; } if (_fi_ip_isScrap == null || _fi_ip_scrapValue == null) { Object val = null; for (int i = 0; i < grabbables.Length; i++) { if (grabbables[i] != (Object)null) { val = grabbables[i]; break; } } if (val != (Object)null && _fi_itemProps != null) { object value = _fi_itemProps.GetValue(val); if (value != null) { Type type = value.GetType(); if (_fi_ip_isScrap == null) { _fi_ip_isScrap = type.GetField("isScrap", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (_fi_ip_scrapValue == null) { _fi_ip_scrapValue = type.GetField("scrapValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } } } int num = 0; Bounds shipBounds = GetShipBounds(); Transform shipRootTransform = GetShipRootTransform(); foreach (Object val2 in grabbables) { if (val2 == (Object)null) { continue; } Transform val3 = ((((val2 is Component) ? val2 : null) != (Object)null) ? ((Component)val2).transform : null); bool flag = false; int num2 = 0; if (!(_fi_itemProps != null)) { continue; } object value2 = _fi_itemProps.GetValue(val2); if (value2 != null && _fi_ip_isScrap != null) { object value3 = _fi_ip_isScrap.GetValue(value2); if (value3 is bool && (bool)value3) { flag = true; } } if (!flag) { continue; } if (_fi_ip_scrapValue != null) { object value4 = _fi_ip_scrapValue.GetValue(value2); if (value4 is int) { num2 = Math.Max(num2, (int)value4); } } if (_fi_scrapValue != null) { object value5 = _fi_scrapValue.GetValue(val2); if (value5 is int) { num2 = Math.Max(num2, (int)value5); } } if (num2 <= 0) { continue; } if (_fi_isHeld != null) { object value6 = _fi_isHeld.GetValue(val2); if (value6 is bool && (bool)value6) { continue; } } if (_fi_isPocketed != null) { object value7 = _fi_isPocketed.GetValue(val2); if (value7 is bool && (bool)value7) { continue; } } bool flag2 = false; if (_fi_isInShipRoom != null) { object value8 = _fi_isInShipRoom.GetValue(val2); if (value8 is bool && (bool)value8) { flag2 = true; } } if (!flag2 && _fi_isInElevator != null) { object value9 = _fi_isInElevator.GetValue(val2); if (value9 is bool && (bool)value9) { flag2 = true; } } if (!flag2 && (Object)(object)val3 != (Object)null) { int num3 = 0; Transform val4 = val3; while ((Object)(object)val4 != (Object)null && num3 < 24) { string name = ((Object)val4).name; if (!string.IsNullOrEmpty(name)) { string text = name.ToLowerInvariant(); for (int k = 0; k < _shipNameNeedles.Length; k++) { if (text.IndexOf(_shipNameNeedles[k], StringComparison.Ordinal) >= 0) { flag2 = true; break; } } if (flag2) { break; } } val4 = val4.parent; num3++; } } if (!flag2 && (Object)(object)val3 != (Object)null && ((Bounds)(ref shipBounds)).size != Vector3.zero && ((Bounds)(ref shipBounds)).Contains(val3.position)) { flag2 = true; } if (!flag2 && (Object)(object)shipRootTransform != (Object)null && (Object)(object)val3 != (Object)null) { Vector3 position = val3.position; Vector3 position2 = shipRootTransform.position; position.y = position2.y; if (Vector3.Distance(position, position2) < 30f) { flag2 = true; } } if (flag2) { num += num2; } } if (Plugin.Log != null) { ManualLogSource log = Plugin.Log; string[] obj = new string[6] { "[DEBUG] Total=", num.ToString(), ", Objects=", grabbables.Length.ToString(), ", Bounds=", null }; Bounds shipBounds2 = GetShipBounds(); Vector3 size = ((Bounds)(ref shipBounds2)).size; obj[5] = ((object)(Vector3)(ref size)).ToString(); log.LogInfo((object)string.Concat(obj)); } return num; } public static void InvalidateGrabbablesCache() { _grabbablesCache = (Object[])(object)new Object[0]; _lastCacheAt = -999f; } } internal static class ScrapValueSyncPatcher { public static void Apply(Harmony harmony) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown Type type = AccessTools.TypeByName("GrabbableObject"); if (type == null) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)"ScrapValueSyncPatcher: GrabbableObject type not found."); } return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo[] methods = type.GetMethods(bindingAttr); string[] array = new string[5] { "ClientRpc", "SetScrap", "SyncScrap", "UpdateScrap", "ScrapValue" }; int num = 0; foreach (MethodInfo methodInfo in methods) { string text = methodInfo.Name.ToLowerInvariant(); if (text.IndexOf("scrap", StringComparison.Ordinal) < 0) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 0 || parameters[0].ParameterType != typeof(int)) { continue; } bool flag = false; for (int j = 0; j < array.Length; j++) { if (text.IndexOf(array[j].ToLowerInvariant(), StringComparison.Ordinal) >= 0) { flag = true; break; } } if (!flag) { continue; } try { HarmonyMethod val = new HarmonyMethod(typeof(ScrapValueSyncPatcher).GetMethod("ScrapValuePostfix", BindingFlags.Static | BindingFlags.NonPublic)); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch (Exception ex) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)("ScrapValueSyncPatcher: failed to patch " + methodInfo.Name + " : " + ex.Message)); } } } if (Plugin.Log != null) { Plugin.Log.LogInfo((object)("ScrapValueSyncPatcher: patched " + num + " scrap sync method(s).")); } } private static void ScrapValuePostfix(object __instance, object[] __args) { try { if (__instance == null || __args == null || __args.Length == 0) { return; } object obj = __args[0]; if (obj is int) { int num = (int)obj; FieldInfo field = __instance.GetType().GetField("scrapValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(__instance, num); Utils.InvalidateGrabbablesCache(); } } } catch { } } } public class ShipBoundsRebuilder : MonoBehaviour { [CompilerGenerated] private sealed class <Start>d__0 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ShipBoundsRebuilder <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Start>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; ShipBoundsRebuilder shipBoundsRebuilder = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; case 1: { <>1__state = -1; Utils.InvalidateGrabbablesCache(); object obj = typeof(Utils).GetMethod("GetShipBounds", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null); if (Plugin.Log != null) { Plugin.Log.LogInfo((object)("[ShipLootTotal] Delayed ship bounds rebuilt: " + obj)); } Object.Destroy((Object)(object)((Component)shipBoundsRebuilder).gameObject); return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<Start>d__0))] private IEnumerator Start() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Start>d__0(0) { <>4__this = this }; } } [HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsClientRpc")] public static class Patch_SOR_AfterHeldSync { private static void Postfix() { Plugin._lastScanPostfixAt = -999f; } }